Add global variables
This commit is contained in:
parent
11158ba4f9
commit
9d7fdbb622
|
|
@ -12,9 +12,11 @@
|
|||
} \
|
||||
}
|
||||
|
||||
static char* readFile(const char* path) {
|
||||
FILE* file = fopen(path, "rb");
|
||||
if (file == NULL) {
|
||||
static char *
|
||||
readFile(const char *path)
|
||||
{
|
||||
FILE *file = fopen(path, "rb");
|
||||
if(file == NULL) {
|
||||
fprintf(stderr, "Could not open file \"%s\".\n", path);
|
||||
exit(74);
|
||||
}
|
||||
|
|
@ -23,13 +25,13 @@ static char* readFile(const char* path) {
|
|||
size_t fileSize = ftell(file);
|
||||
rewind(file);
|
||||
|
||||
char* buffer = (char*)malloc(fileSize + 1);
|
||||
if (buffer == NULL) {
|
||||
char *buffer = (char *)malloc(fileSize + 1);
|
||||
if(buffer == NULL) {
|
||||
fprintf(stderr, "Not enough memory to read \"%s\".\n", path);
|
||||
exit(74);
|
||||
}
|
||||
size_t bytesRead = fread(buffer, sizeof(char), fileSize, file);
|
||||
if (bytesRead < fileSize) {
|
||||
if(bytesRead < fileSize) {
|
||||
fprintf(stderr, "Could not read file \"%s\".\n", path);
|
||||
exit(74);
|
||||
}
|
||||
|
|
@ -40,14 +42,19 @@ static char* readFile(const char* path) {
|
|||
return buffer;
|
||||
}
|
||||
|
||||
void print_help() {
|
||||
printf("Usage: undar [options] file...\nOptions:\n\t-emit={c|u}\tEmitter output, currently C source and Uxn binary.\n\n");
|
||||
void
|
||||
print_help()
|
||||
{
|
||||
printf("Usage: undar [options] file...\nOptions:\n\t-emit={c|u}\tEmitter "
|
||||
"output, currently C source and Uxn binary.\n\n");
|
||||
}
|
||||
|
||||
#define MEM_SIZE 68000
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
if (argc > 1 && (seq(argv[1], "--help") || seq(argv[1], "-h"))) {
|
||||
if(argc > 1 && (seq(argv[1], "--help") || seq(argv[1], "-h"))) {
|
||||
print_help();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -58,17 +65,19 @@ main(int argc, char **argv)
|
|||
}
|
||||
|
||||
Emitter e;
|
||||
if (seq(argv[1], "-emit=c")) {
|
||||
if(seq(argv[1], "-emit=c")) {
|
||||
e = c_emitter();
|
||||
} else if (seq(argv[1], "-emit=u")) {
|
||||
} else if(seq(argv[1], "-emit=u")) {
|
||||
e = uxn_emitter();
|
||||
} else {
|
||||
printf("unknown emitter type\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
u8 tape[MEM_SIZE];
|
||||
Arena a = {tape, 0, MEM_SIZE};
|
||||
|
||||
char* source = readFile(argv[2]);
|
||||
compile(e, source);
|
||||
char *source = readFile(argv[2]);
|
||||
compile(&a, e, source);
|
||||
free(source);
|
||||
printf("\n");
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
#ifndef UNDAR_COMMON_H
|
||||
#define UNDAR_COMMON_H
|
||||
|
||||
#include "libc.h"
|
||||
#include "list.h"
|
||||
|
||||
typedef enum symbol_type_e {
|
||||
SYMBOL_VOID,
|
||||
SYMBOL_BOOL,
|
||||
SYMBOL_BYTE,
|
||||
SYMBOL_INT,
|
||||
SYMBOL_NAT,
|
||||
SYMBOL_REAL,
|
||||
SYMBOL_STR,
|
||||
SYMBOL_U8,
|
||||
SYMBOL_I8,
|
||||
SYMBOL_I16,
|
||||
SYMBOL_U16,
|
||||
SYMBOL_I32,
|
||||
SYMBOL_U32,
|
||||
SYMBOL_F32,
|
||||
SYMBOL_ARRAY,
|
||||
SYMBOL_FUNCTION,
|
||||
SYMBOL_PLEX,
|
||||
SYMBOL_METHOD,
|
||||
SYMBOL_TRAIT,
|
||||
SYMBOL_CONST
|
||||
} SymbolType;
|
||||
|
||||
typedef struct symbol_s Symbol;
|
||||
|
||||
#define MAX_SYMBOL_NAME_LENGTH 64
|
||||
struct symbol_s {
|
||||
char name[MAX_SYMBOL_NAME_LENGTH]; /* ptr to name */
|
||||
u8 name_length; /* length of the name, max 64 */
|
||||
SymbolType type; /* the type for this symbol */
|
||||
SymbolType secondary_type; /* return type for functions/methods, or const if type/plex */
|
||||
u32 ref; /* either constant value or pointer to other thing */
|
||||
u32 size; /* either size of the plex or length of the array/list/etc. */
|
||||
List *args; /* function params or plex constructor args */
|
||||
List *fields; /* either plex variable fields, or method signatures */
|
||||
};
|
||||
|
||||
#endif
|
||||
33
emit.h
33
emit.h
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef UNDAR_EMIT_H
|
||||
#define UNDAR_EMIT_H
|
||||
|
||||
#include "common.h"
|
||||
#include "libc.h"
|
||||
|
||||
typedef enum notation_type_e {
|
||||
|
|
@ -14,13 +15,17 @@ typedef enum output_type_e {
|
|||
TEXT
|
||||
} OutputType;
|
||||
|
||||
typedef void (*SymbolEmit)(Symbol *sym);
|
||||
typedef void (*ErrorMsg)(const char *str, i32 length, i32 line);
|
||||
typedef void (*VoidArgEmit)();
|
||||
typedef void (*StrArgEmit)(const char *str, i32 length);
|
||||
typedef i32 (*TypeVariableEmit)(const char *str, i32 length);
|
||||
|
||||
typedef struct emitter_s Emitter;
|
||||
struct emitter_s {
|
||||
NotationType notation;
|
||||
OutputType output;
|
||||
ErrorMsg error;
|
||||
VoidArgEmit prolog;
|
||||
VoidArgEmit epilogue;
|
||||
VoidArgEmit emit_add;
|
||||
|
|
@ -42,19 +47,19 @@ struct emitter_s {
|
|||
StrArgEmit emit_real;
|
||||
StrArgEmit emit_byte;
|
||||
StrArgEmit emit_str;
|
||||
VoidArgEmit emit_bool_type;
|
||||
VoidArgEmit emit_byte_type;
|
||||
VoidArgEmit emit_int_type;
|
||||
VoidArgEmit emit_nat_type;
|
||||
VoidArgEmit emit_real_type;
|
||||
VoidArgEmit emit_str_type;
|
||||
VoidArgEmit emit_u8_type;
|
||||
VoidArgEmit emit_i8_type;
|
||||
VoidArgEmit emit_i16_type;
|
||||
VoidArgEmit emit_u16_type;
|
||||
VoidArgEmit emit_i32_type;
|
||||
VoidArgEmit emit_u32_type;
|
||||
VoidArgEmit emit_f32_type;
|
||||
TypeVariableEmit emit_bool_type;
|
||||
TypeVariableEmit emit_byte_type;
|
||||
TypeVariableEmit emit_int_type;
|
||||
TypeVariableEmit emit_nat_type;
|
||||
TypeVariableEmit emit_real_type;
|
||||
TypeVariableEmit emit_str_type;
|
||||
TypeVariableEmit emit_u8_type;
|
||||
TypeVariableEmit emit_i8_type;
|
||||
TypeVariableEmit emit_i16_type;
|
||||
TypeVariableEmit emit_u16_type;
|
||||
TypeVariableEmit emit_i32_type;
|
||||
TypeVariableEmit emit_u32_type;
|
||||
TypeVariableEmit emit_f32_type;
|
||||
VoidArgEmit emit_array;
|
||||
VoidArgEmit emit_function;
|
||||
VoidArgEmit emit_plex;
|
||||
|
|
@ -66,6 +71,8 @@ struct emitter_s {
|
|||
VoidArgEmit emit_not;
|
||||
VoidArgEmit emit_open_paren;
|
||||
VoidArgEmit emit_close_paren;
|
||||
StrArgEmit emit_constant;
|
||||
SymbolEmit emit_variable;
|
||||
};
|
||||
|
||||
Emitter c_emitter();
|
||||
|
|
|
|||
101
emit/c/emit.c
101
emit/c/emit.c
|
|
@ -1,5 +1,13 @@
|
|||
#include "../../emit.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void
|
||||
c_emit_error(const char *str, i32 length, i32 line)
|
||||
{
|
||||
printf("Error at line: %d > %.*s\n ", line, length, str);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
c_prolog()
|
||||
|
|
@ -106,69 +114,95 @@ c_emit_void()
|
|||
{
|
||||
}
|
||||
|
||||
void
|
||||
c_emit_bool_type()
|
||||
i32
|
||||
c_emit_bool_type(const char *str, i32 length)
|
||||
{
|
||||
printf("%.*s ", length, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
c_emit_byte_type()
|
||||
i32
|
||||
c_emit_byte_type(const char *str, i32 length)
|
||||
{
|
||||
printf("%.*s ", length, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
c_emit_int_type()
|
||||
i32
|
||||
c_emit_int_type(const char *str, i32 length)
|
||||
{
|
||||
printf("%.*s ", length, str);
|
||||
return 2;
|
||||
}
|
||||
|
||||
void
|
||||
c_emit_nat_type()
|
||||
i32
|
||||
c_emit_nat_type(const char *str, i32 length)
|
||||
{
|
||||
printf("%.*s ", length, str);
|
||||
return 2;
|
||||
}
|
||||
|
||||
void
|
||||
c_emit_real_type()
|
||||
i32
|
||||
c_emit_real_type(const char *str, i32 length)
|
||||
{
|
||||
printf("%.*s ", length, str);
|
||||
return 2;
|
||||
}
|
||||
|
||||
void
|
||||
c_emit_str_type()
|
||||
i32
|
||||
c_emit_str_type(const char *str, i32 length)
|
||||
{
|
||||
printf("%.*s ", length, str);
|
||||
return 2;
|
||||
}
|
||||
|
||||
void
|
||||
c_emit_u8_type()
|
||||
i32
|
||||
c_emit_u8_type(const char *str, i32 length)
|
||||
{
|
||||
printf("%.*s ", length, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
c_emit_i8_type()
|
||||
i32
|
||||
c_emit_i8_type(const char *str, i32 length)
|
||||
{
|
||||
printf("%.*s ", length, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
c_emit_i16_type()
|
||||
i32
|
||||
c_emit_i16_type(const char *str, i32 length)
|
||||
{
|
||||
printf("%.*s ", length, str);
|
||||
return 2;
|
||||
}
|
||||
|
||||
void
|
||||
c_emit_u16_type()
|
||||
i32
|
||||
c_emit_u16_type(const char *str, i32 length)
|
||||
{
|
||||
printf("%.*s ", length, str);
|
||||
return 2;
|
||||
}
|
||||
|
||||
void
|
||||
c_emit_i32_type()
|
||||
i32
|
||||
c_emit_i32_type(const char *str, i32 length)
|
||||
{
|
||||
printf("%.*s ", length, str);
|
||||
return 4;
|
||||
}
|
||||
|
||||
void
|
||||
c_emit_u32_type()
|
||||
i32
|
||||
c_emit_u32_type(const char *str, i32 length)
|
||||
{
|
||||
printf("%.*s ", length, str);
|
||||
return 4;
|
||||
}
|
||||
|
||||
void
|
||||
c_emit_f32_type()
|
||||
i32
|
||||
c_emit_f32_type(const char *str, i32 length)
|
||||
{
|
||||
printf("%.*s ", length, str);
|
||||
return 4;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -249,12 +283,25 @@ c_emit_close_paren()
|
|||
printf(")");
|
||||
}
|
||||
|
||||
void
|
||||
c_emit_constant(const char *str, i32 length)
|
||||
{
|
||||
USED(str);
|
||||
USED(length);
|
||||
}
|
||||
|
||||
void
|
||||
c_emit_variable(Symbol *sym) {
|
||||
USED(sym);
|
||||
}
|
||||
|
||||
Emitter
|
||||
c_emitter()
|
||||
{
|
||||
return (Emitter){
|
||||
INFIX,
|
||||
TEXT,
|
||||
c_emit_error,
|
||||
c_prolog,
|
||||
c_epilogue,
|
||||
c_emit_add,
|
||||
|
|
@ -300,5 +347,7 @@ c_emitter()
|
|||
c_emit_not,
|
||||
c_emit_open_paren,
|
||||
c_emit_close_paren,
|
||||
c_emit_constant,
|
||||
c_emit_variable,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
151
emit/uxn/emit.c
151
emit/uxn/emit.c
|
|
@ -8,17 +8,44 @@
|
|||
|
||||
enum uxn_opcode {
|
||||
/* Stack I */ /* Logic */ /* Memory I */ /* Arithmetic*/
|
||||
BRK = 0x00, EQU = 0x08, LDZ = 0x10, ADD = 0x18,
|
||||
INC = 0x01, NEQ = 0x09, STZ = 0x11, SUB = 0x19,
|
||||
POP = 0x02, GTH = 0x0A, LDR = 0x12, MUL = 0x1A,
|
||||
NIP = 0x03, LTH = 0x0B, STR = 0x13, DIV = 0x1B,
|
||||
BRK = 0x00,
|
||||
EQU = 0x08,
|
||||
LDZ = 0x10,
|
||||
ADD = 0x18,
|
||||
INC = 0x01,
|
||||
NEQ = 0x09,
|
||||
STZ = 0x11,
|
||||
SUB = 0x19,
|
||||
POP = 0x02,
|
||||
GTH = 0x0A,
|
||||
LDR = 0x12,
|
||||
MUL = 0x1A,
|
||||
NIP = 0x03,
|
||||
LTH = 0x0B,
|
||||
STR = 0x13,
|
||||
DIV = 0x1B,
|
||||
/* Stack II */ /* Stash */ /* Memory II */ /* Bitwise */
|
||||
SWP = 0x04, JMP = 0x0C, LDA = 0x14, AND = 0x1C,
|
||||
ROT = 0x05, JCN = 0x0D, STA = 0x15, ORA = 0x1D,
|
||||
DUP = 0x06, JSR = 0x0E, DEI = 0x16, EOR = 0x1E,
|
||||
OVR = 0x07, STH = 0x0F, DEO = 0x17, SFT = 0x1F,
|
||||
SWP = 0x04,
|
||||
JMP = 0x0C,
|
||||
LDA = 0x14,
|
||||
AND = 0x1C,
|
||||
ROT = 0x05,
|
||||
JCN = 0x0D,
|
||||
STA = 0x15,
|
||||
ORA = 0x1D,
|
||||
DUP = 0x06,
|
||||
JSR = 0x0E,
|
||||
DEI = 0x16,
|
||||
EOR = 0x1E,
|
||||
OVR = 0x07,
|
||||
STH = 0x0F,
|
||||
DEO = 0x17,
|
||||
SFT = 0x1F,
|
||||
|
||||
LIT = 0x80, JCI = 0x20, JMI = 0x40, JSI = 0x60,
|
||||
LIT = 0x80,
|
||||
JCI = 0x20,
|
||||
JMI = 0x40,
|
||||
JSI = 0x60,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -34,16 +61,23 @@ https://rosettacode.org/wiki/Bitwise_operations#Uxntal
|
|||
%ror { SWP #00 ROT SFT2 ORA }
|
||||
*/
|
||||
|
||||
void
|
||||
uxn_emit_error(const char *str, i32 length, i32 line)
|
||||
{
|
||||
printf("Error at line: %d > %.*s\n ", line, length, str);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
uxn_prolog()
|
||||
{
|
||||
|
||||
/* essentially the "main" function */
|
||||
printf("|100 @on-reset ( -> )\n");
|
||||
}
|
||||
|
||||
void
|
||||
uxn_epilogue()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -141,69 +175,98 @@ uxn_emit_void()
|
|||
{
|
||||
}
|
||||
|
||||
void
|
||||
uxn_emit_bool_type()
|
||||
/* @global $size */
|
||||
/* &local $size */
|
||||
|
||||
i32
|
||||
uxn_emit_bool_type(const char *str, i32 length)
|
||||
{
|
||||
printf("!{ @%.*s $1 } ", length, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
uxn_emit_byte_type()
|
||||
i32
|
||||
uxn_emit_byte_type(const char *str, i32 length)
|
||||
{
|
||||
printf("!{ @%.*s $1 } ", length, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
uxn_emit_int_type()
|
||||
i32
|
||||
uxn_emit_int_type(const char *str, i32 length)
|
||||
{
|
||||
printf("!{ @%.*s $2 } ", length, str);
|
||||
return 2;
|
||||
}
|
||||
|
||||
void
|
||||
uxn_emit_nat_type()
|
||||
i32
|
||||
uxn_emit_nat_type(const char *str, i32 length)
|
||||
{
|
||||
printf("!{ @%.*s $2 } ", length, str);
|
||||
return 2;
|
||||
}
|
||||
|
||||
void
|
||||
uxn_emit_real_type()
|
||||
i32
|
||||
uxn_emit_real_type(const char *str, i32 length)
|
||||
{
|
||||
printf("!{ @%.*s $2 } ", length, str);
|
||||
return 2;
|
||||
}
|
||||
|
||||
void
|
||||
uxn_emit_str_type()
|
||||
i32
|
||||
uxn_emit_str_type(const char *str, i32 length)
|
||||
{
|
||||
printf("!{ @%.*s $2 } ", length, str);
|
||||
return 2;
|
||||
}
|
||||
|
||||
void
|
||||
uxn_emit_u8_type()
|
||||
i32
|
||||
uxn_emit_u8_type(const char *str, i32 length)
|
||||
{
|
||||
printf("!{ @%.*s $1 } ", length, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
uxn_emit_i8_type()
|
||||
i32
|
||||
uxn_emit_i8_type(const char *str, i32 length)
|
||||
{
|
||||
printf("!{ @%.*s $1 } ", length, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
uxn_emit_i16_type()
|
||||
i32
|
||||
uxn_emit_i16_type(const char *str, i32 length)
|
||||
{
|
||||
printf("!{ @%.*s $2 } ", length, str);
|
||||
return 2;
|
||||
}
|
||||
|
||||
void
|
||||
uxn_emit_u16_type()
|
||||
i32
|
||||
uxn_emit_u16_type(const char *str, i32 length)
|
||||
{
|
||||
printf("!{ @%.*s $2 } ", length, str);
|
||||
return 2;
|
||||
}
|
||||
|
||||
void
|
||||
uxn_emit_i32_type()
|
||||
i32
|
||||
uxn_emit_i32_type(const char *str, i32 length)
|
||||
{
|
||||
printf("!{ @%.*s $4 } ", length, str);
|
||||
return 4;
|
||||
}
|
||||
|
||||
void
|
||||
uxn_emit_u32_type()
|
||||
i32
|
||||
uxn_emit_u32_type(const char *str, i32 length)
|
||||
{
|
||||
printf("!{ @%.*s $4 } ", length, str);
|
||||
return 4;
|
||||
}
|
||||
|
||||
void
|
||||
uxn_emit_f32_type()
|
||||
i32
|
||||
uxn_emit_f32_type(const char *str, i32 length)
|
||||
{
|
||||
printf("!{ @%.*s $4 } ", length, str);
|
||||
return 4;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -244,6 +307,12 @@ uxn_emit_str(const char *str, i32 length)
|
|||
printf("\"%.*s ", length, str);
|
||||
}
|
||||
|
||||
void
|
||||
uxn_emit_constant(const char *str, i32 length)
|
||||
{
|
||||
printf(";%.*s STA2 ", length, str);
|
||||
}
|
||||
|
||||
void
|
||||
uxn_emit_array()
|
||||
{
|
||||
|
|
@ -283,12 +352,15 @@ uxn_emit_print()
|
|||
void
|
||||
uxn_emit_open_paren()
|
||||
{
|
||||
|
||||
}
|
||||
void
|
||||
uxn_emit_close_paren()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
uxn_emit_variable(Symbol *sym) {
|
||||
printf(";%.*s LDA2 ", sym->name_length, sym->name);
|
||||
}
|
||||
|
||||
Emitter
|
||||
|
|
@ -297,6 +369,7 @@ uxn_emitter()
|
|||
return (Emitter){
|
||||
POSTFIX,
|
||||
BINARY,
|
||||
uxn_emit_error,
|
||||
uxn_prolog,
|
||||
uxn_epilogue,
|
||||
uxn_emit_add,
|
||||
|
|
@ -342,5 +415,7 @@ uxn_emitter()
|
|||
uxn_emit_not,
|
||||
uxn_emit_open_paren,
|
||||
uxn_emit_close_paren,
|
||||
uxn_emit_constant,
|
||||
uxn_emit_variable,
|
||||
};
|
||||
}
|
||||
2
libc.c
2
libc.c
|
|
@ -19,7 +19,7 @@ scpy(char *to, const char *from, u32 length)
|
|||
u32 i;
|
||||
if(to == nil || from == nil) return -1;
|
||||
if(length == 0) return 0;
|
||||
for(i = 0; i < length - 1 && from[i] != '\0'; i++) to[i] = from[i];
|
||||
for(i = 0; i < length && from[i] != '\0'; i++) to[i] = from[i];
|
||||
to[i] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
195
parser.c
195
parser.c
|
|
@ -3,13 +3,14 @@
|
|||
|
||||
Emitter emitter;
|
||||
Parser parser;
|
||||
Arena *arena;
|
||||
|
||||
/****************************************************
|
||||
* Scope
|
||||
***************************************************/
|
||||
|
||||
void
|
||||
scope_push(Arena *arena)
|
||||
scope_push()
|
||||
{
|
||||
Scope *child = aalloc(arena, sizeof(Scope));
|
||||
child->symbols = new_list(arena);
|
||||
|
|
@ -41,20 +42,19 @@ scope_get_symbol(Scope *scope, const char *name, u32 name_length)
|
|||
}
|
||||
|
||||
Symbol *
|
||||
scope_add_symbol(Arena *arena, const char *name, u32 name_length,
|
||||
SymbolType type, u32 size)
|
||||
scope_add_symbol(const char *name, u32 name_length, SymbolType type, u32 size)
|
||||
{
|
||||
Symbol *sym = scope_get_symbol(parser.current_scope, name, name_length);
|
||||
if(sym != nil) return sym;
|
||||
|
||||
sym = aalloc(arena, sizeof(Symbol));
|
||||
scpy(sym->name, name, slen(name));
|
||||
sym->name_length = slen(name);
|
||||
scpy(sym->name, name, name_length);
|
||||
sym->name_length = name_length;
|
||||
sym->type = type;
|
||||
sym->secondary_type = VOID;
|
||||
sym->secondary_type = SYMBOL_VOID;
|
||||
sym->size = size;
|
||||
sym->ref = 0;
|
||||
if(type == PLEX || type == METHOD || type == TRAIT) {
|
||||
if(type == SYMBOL_PLEX || type == SYMBOL_METHOD || type == SYMBOL_TRAIT) {
|
||||
sym->args = new_list(arena);
|
||||
sym->fields = new_list(arena);
|
||||
}
|
||||
|
|
@ -64,6 +64,19 @@ scope_add_symbol(Arena *arena, const char *name, u32 name_length,
|
|||
return sym;
|
||||
}
|
||||
|
||||
bool
|
||||
is_global()
|
||||
{
|
||||
return parser.current_scope != nil && parser.current_scope->parent == nil;
|
||||
}
|
||||
|
||||
bool
|
||||
is_type()
|
||||
{
|
||||
return parser.previous.type >= TOKEN_TYPE_I8 &&
|
||||
parser.previous.type <= TOKEN_TYPE_PTR;
|
||||
}
|
||||
|
||||
/****************************************************
|
||||
* Parser
|
||||
***************************************************/
|
||||
|
|
@ -117,9 +130,8 @@ binary()
|
|||
TokenType operatorType = parser.previous.type;
|
||||
ParseRule *rule = get_rule(operatorType);
|
||||
|
||||
if (emitter.notation == POSTFIX) {
|
||||
if(emitter.notation == POSTFIX)
|
||||
parse_precedence((Precedence)(rule->precedence + 1));
|
||||
}
|
||||
|
||||
switch(operatorType) {
|
||||
case TOKEN_BANG_EQ:
|
||||
|
|
@ -156,9 +168,8 @@ binary()
|
|||
return;
|
||||
}
|
||||
|
||||
if (emitter.notation == INFIX) {
|
||||
if(emitter.notation == INFIX)
|
||||
parse_precedence((Precedence)(rule->precedence + 1));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -185,55 +196,135 @@ expression()
|
|||
parse_precedence(PREC_ASSIGNMENT);
|
||||
}
|
||||
|
||||
static void variable() {
|
||||
Symbol *sym = scope_get_symbol(parser.current_scope, parser.previous.start, parser.previous.length);
|
||||
if(sym == nil) {
|
||||
emitter.error(parser.previous.start, parser.previous.length, parser.previous.line);
|
||||
}
|
||||
|
||||
emitter.emit_variable(sym);
|
||||
}
|
||||
|
||||
static void
|
||||
variable_declaration()
|
||||
{
|
||||
|
||||
i32 size = 0;
|
||||
TokenType tt = parser.previous.type;
|
||||
Token var = parser.current;
|
||||
|
||||
switch(tt) {
|
||||
case TOKEN_TYPE_INT: {
|
||||
size = emitter.emit_int_type(parser.current.start, parser.current.length);
|
||||
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_INT, size);
|
||||
break;
|
||||
}
|
||||
case TOKEN_TYPE_NAT: {
|
||||
size = emitter.emit_nat_type(parser.current.start, parser.current.length);
|
||||
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_NAT, size);
|
||||
break;
|
||||
}
|
||||
case TOKEN_TYPE_REAL: {
|
||||
size = emitter.emit_real_type(parser.current.start, parser.current.length);
|
||||
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_REAL, size);
|
||||
break;
|
||||
}
|
||||
case TOKEN_TYPE_STR: {
|
||||
/* FIXME: this is wrong, we need to store the size of the string, not just
|
||||
* the pointer */
|
||||
/* size = emitter.emit_str_type(parser.current.start, parser.current.length,
|
||||
*/
|
||||
/* is_global()); */
|
||||
/* scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_STR, size);
|
||||
*/
|
||||
break;
|
||||
}
|
||||
case TOKEN_TYPE_BOOL: {
|
||||
size = emitter.emit_bool_type(parser.current.start, parser.current.length);
|
||||
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_BOOL, size);
|
||||
break;
|
||||
}
|
||||
case TOKEN_TYPE_BYTE: {
|
||||
size = emitter.emit_byte_type(parser.current.start, parser.current.length);
|
||||
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_U8, size);
|
||||
break;
|
||||
}
|
||||
case TOKEN_TYPE_U8: {
|
||||
size = emitter.emit_u8_type(parser.current.start, parser.current.length);
|
||||
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_U8, size);
|
||||
break;
|
||||
}
|
||||
case TOKEN_TYPE_I8: {
|
||||
size = emitter.emit_i8_type(parser.current.start, parser.current.length);
|
||||
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_I8, size);
|
||||
break;
|
||||
}
|
||||
case TOKEN_TYPE_U16: {
|
||||
size = emitter.emit_u16_type(parser.current.start, parser.current.length);
|
||||
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_U16, size);
|
||||
break;
|
||||
}
|
||||
case TOKEN_TYPE_I16: {
|
||||
size = emitter.emit_i16_type(parser.current.start, parser.current.length);
|
||||
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_I16, size);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
/* probably a variable */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
advance();
|
||||
|
||||
if(match(TOKEN_EQ)) {
|
||||
expression();
|
||||
emitter.emit_constant(var.start, var.length);
|
||||
}
|
||||
|
||||
consume(TOKEN_SEMICOLON);
|
||||
}
|
||||
|
||||
static void
|
||||
declaration()
|
||||
{
|
||||
if(match(TOKEN_TYPE_INT)) {
|
||||
emitter.emit_int_type();
|
||||
} else if(match(TOKEN_TYPE_NAT)) {
|
||||
emitter.emit_nat_type();
|
||||
} else if(match(TOKEN_TYPE_REAL)) {
|
||||
emitter.emit_real_type();
|
||||
} else if(match(TOKEN_TYPE_STR)) {
|
||||
emitter.emit_str_type();
|
||||
} else if(match(TOKEN_TYPE_BOOL)) {
|
||||
emitter.emit_bool_type();
|
||||
} else if(match(TOKEN_TYPE_BYTE)) {
|
||||
emitter.emit_byte_type();
|
||||
} else if(match(TOKEN_TYPE_U8)) {
|
||||
emitter.emit_u8_type();
|
||||
} else if(match(TOKEN_TYPE_I8)) {
|
||||
emitter.emit_i8_type();
|
||||
} else if(match(TOKEN_TYPE_U16)) {
|
||||
emitter.emit_u16_type();
|
||||
} else if(match(TOKEN_TYPE_I16)) {
|
||||
emitter.emit_i16_type();
|
||||
} else if(match(TOKEN_IDENTIFIER)) {
|
||||
/**
|
||||
* maybe a Plex?
|
||||
* lookup plex defs
|
||||
* if not then
|
||||
*/
|
||||
}
|
||||
|
||||
if(is_type())
|
||||
variable_declaration();
|
||||
else
|
||||
statement();
|
||||
}
|
||||
|
||||
static void print_statement() {
|
||||
if (emitter.notation == INFIX) {
|
||||
emitter.emit_print();
|
||||
}
|
||||
static void
|
||||
print_statement()
|
||||
{
|
||||
if(emitter.notation == INFIX) emitter.emit_print();
|
||||
expression();
|
||||
consume(TOKEN_SEMICOLON);
|
||||
if (emitter.notation == POSTFIX) {
|
||||
emitter.emit_print();
|
||||
}
|
||||
if(emitter.notation == POSTFIX) emitter.emit_print();
|
||||
}
|
||||
|
||||
static void
|
||||
block()
|
||||
{
|
||||
while(!check(TOKEN_RBRACE) && !check(TOKEN_EOF)) declaration();
|
||||
|
||||
consume(TOKEN_RBRACE);
|
||||
}
|
||||
|
||||
static void
|
||||
statement()
|
||||
{
|
||||
if(match(TOKEN_KEYWORD_PRINT)) {
|
||||
if(match(TOKEN_LBRACE)) {
|
||||
scope_push();
|
||||
block();
|
||||
scope_pop();
|
||||
} else if(match(TOKEN_KEYWORD_PRINT)) {
|
||||
print_statement();
|
||||
} else {
|
||||
expression();
|
||||
|
|
@ -267,9 +358,7 @@ static void
|
|||
unary()
|
||||
{
|
||||
TokenType operatorType = parser.previous.type;
|
||||
if (emitter.notation == POSTFIX) {
|
||||
parse_precedence(PREC_UNARY);
|
||||
}
|
||||
if(emitter.notation == POSTFIX) parse_precedence(PREC_UNARY);
|
||||
|
||||
switch(operatorType) {
|
||||
case TOKEN_MINUS:
|
||||
|
|
@ -282,15 +371,13 @@ unary()
|
|||
return;
|
||||
}
|
||||
|
||||
if (emitter.notation == INFIX) {
|
||||
parse_precedence(PREC_UNARY);
|
||||
}
|
||||
if(emitter.notation == INFIX) parse_precedence(PREC_UNARY);
|
||||
}
|
||||
|
||||
ParseRule rules[] = {
|
||||
/* 0 */ {NULL, NULL, PREC_NONE},
|
||||
/* 1 */ {NULL, NULL, PREC_NONE},
|
||||
/* 2 */ {NULL, NULL, PREC_NONE},
|
||||
/* 0 */ {NULL, NULL, PREC_NONE}, /* TOKEN_ERROR */
|
||||
/* 1 */ {NULL, NULL, PREC_NONE}, /* TOKEN_EOF */
|
||||
/* 2 */ {variable, NULL, PREC_NONE}, /* TOKEN_IDENTIFIER */
|
||||
/* 3 */ {number, NULL, PREC_NONE}, /* TOKEN_LITERAL_INT */
|
||||
/* 4 */ {number, NULL, PREC_NONE}, /* TOKEN_LITERAL_NAT */
|
||||
/* 5 */ {number, NULL, PREC_NONE}, /* TOKEN_LITERAL_REAL */
|
||||
|
|
@ -377,9 +464,7 @@ parse_precedence(Precedence precedence)
|
|||
|
||||
advance();
|
||||
prefixRule = get_rule(parser.previous.type)->prefix;
|
||||
if(prefixRule == NULL) {
|
||||
return;
|
||||
}
|
||||
if(prefixRule == NULL) return;
|
||||
|
||||
prefixRule();
|
||||
|
||||
|
|
@ -397,11 +482,13 @@ get_rule(TokenType type)
|
|||
}
|
||||
|
||||
bool
|
||||
compile(Emitter e, char *source)
|
||||
compile(Arena *a, Emitter e, char *source)
|
||||
{
|
||||
arena = a;
|
||||
emitter = e;
|
||||
init_lexer(source);
|
||||
advance();
|
||||
scope_push();
|
||||
|
||||
emitter.prolog();
|
||||
|
||||
|
|
|
|||
41
parser.h
41
parser.h
|
|
@ -1,51 +1,14 @@
|
|||
#ifndef UNDAR_PARSER_H
|
||||
#define UNDAR_PARSER_H
|
||||
|
||||
#include "libc.h"
|
||||
#include "list.h"
|
||||
#include "common.h"
|
||||
#include "lexer.h"
|
||||
#include "emit.h"
|
||||
|
||||
typedef enum symbol_type_e {
|
||||
VOID,
|
||||
BOOL,
|
||||
BYTE,
|
||||
INT,
|
||||
NAT,
|
||||
REAL,
|
||||
STR,
|
||||
U8,
|
||||
I8,
|
||||
I16,
|
||||
U16,
|
||||
I32,
|
||||
U32,
|
||||
F32,
|
||||
ARRAY,
|
||||
FUNCTION,
|
||||
PLEX,
|
||||
METHOD,
|
||||
TRAIT,
|
||||
CONST
|
||||
} SymbolType;
|
||||
|
||||
typedef struct symbol_s Symbol;
|
||||
typedef struct scope_s Scope;
|
||||
typedef struct parser_s Parser;
|
||||
typedef struct parse_rule_s ParseRule;
|
||||
|
||||
#define MAX_SYMBOL_NAME_LENGTH 64
|
||||
struct symbol_s {
|
||||
char name[MAX_SYMBOL_NAME_LENGTH]; /* ptr to name */
|
||||
u8 name_length; /* length of the name, max 64 */
|
||||
SymbolType type; /* the type for this symbol */
|
||||
SymbolType secondary_type; /* return type for functions/methods, or const if type/plex */
|
||||
u32 ref; /* either constant value or pointer to other thing */
|
||||
u32 size; /* either size of the plex or length of the array/list/etc. */
|
||||
List *args; /* function params or plex constructor args */
|
||||
List *fields; /* either plex variable fields, or method signatures */
|
||||
};
|
||||
|
||||
struct scope_s {
|
||||
Scope *parent; /* pointer to this scopes parent to "bubble up"*/
|
||||
List *symbols; /* list of symbols that live in this scope */
|
||||
|
|
@ -79,6 +42,6 @@ struct parser_s {
|
|||
Token previous;
|
||||
};
|
||||
|
||||
bool compile(Emitter e, char *source);
|
||||
bool compile(Arena *a, Emitter e, char *source);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
int i = 122;
|
||||
int j = 32;
|
||||
|
||||
print((i - j)); // prints ascii `Z`
|
||||
Loading…
Reference in New Issue