diff --git a/arch/linux/main.c b/arch/linux/main.c index fe6c0ce..448cf3c 100644 --- a/arch/linux/main.c +++ b/arch/linux/main.c @@ -3,74 +3,83 @@ #include #define EMBED_FILE(name) \ - void emit_##name(const char *filename) \ - { \ - FILE *f = fopen(filename, "wb"); \ - if(f) { \ - fwrite(name, 1, name##_len, f); \ - fclose(f); \ - } \ + void emit_##name(const char *filename) \ + { \ + FILE *f = fopen(filename, "wb"); \ + if(f) { \ + fwrite(name, 1, name##_len, f); \ + fclose(f); \ + } \ } -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); - } +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); + } - fseek(file, 0L, SEEK_END); - size_t fileSize = ftell(file); - rewind(file); + fseek(file, 0L, SEEK_END); + size_t fileSize = ftell(file); + rewind(file); - 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) { - fprintf(stderr, "Could not read file \"%s\".\n", path); - exit(74); - } + 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) { + fprintf(stderr, "Could not read file \"%s\".\n", path); + exit(74); + } - buffer[bytesRead] = '\0'; + buffer[bytesRead] = '\0'; - fclose(file); - return buffer; + fclose(file); + 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"))) { - print_help(); - return EXIT_SUCCESS; - } + if(argc > 1 && (seq(argv[1], "--help") || seq(argv[1], "-h"))) { + print_help(); + return EXIT_SUCCESS; + } if(argc != 3) { - print_help(); - return EXIT_FAILURE; - } + print_help(); + return EXIT_FAILURE; + } - Emitter e; - if (seq(argv[1], "-emit=c")) { - e = c_emitter(); - } else if (seq(argv[1], "-emit=u")) { - e = uxn_emitter(); - } else { - printf("unknown emitter type\n"); - return EXIT_FAILURE; - } + Emitter e; + if(seq(argv[1], "-emit=c")) { + e = c_emitter(); + } 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); - free(source); - printf("\n"); + char *source = readFile(argv[2]); + compile(&a, e, source); + free(source); + printf("\n"); return EXIT_SUCCESS; } diff --git a/common.h b/common.h new file mode 100644 index 0000000..e48daa9 --- /dev/null +++ b/common.h @@ -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 \ No newline at end of file diff --git a/emit.h b/emit.h index f600d86..0425697 100644 --- a/emit.h +++ b/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,9 +71,11 @@ struct emitter_s { VoidArgEmit emit_not; VoidArgEmit emit_open_paren; VoidArgEmit emit_close_paren; + StrArgEmit emit_constant; + SymbolEmit emit_variable; }; Emitter c_emitter(); Emitter uxn_emitter(); -#endif \ No newline at end of file +#endif diff --git a/emit/c/emit.c b/emit/c/emit.c index ad1bb64..d1b5fff 100644 --- a/emit/c/emit.c +++ b/emit/c/emit.c @@ -1,5 +1,13 @@ #include "../../emit.h" #include +#include + +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, }; } diff --git a/emit/uxn/emit.c b/emit/uxn/emit.c index a24ddfa..ea38a34 100644 --- a/emit/uxn/emit.c +++ b/emit/uxn/emit.c @@ -7,18 +7,45 @@ #define UXN_OP_K (1 << 7) 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, + /* 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, /* 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, }; -} \ No newline at end of file +} diff --git a/libc.c b/libc.c index 9108e65..d86bcef 100644 --- a/libc.c +++ b/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; } diff --git a/parser.c b/parser.c index 44de44c..8d1dd23 100644 --- a/parser.c +++ b/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) { - parse_precedence((Precedence)(rule->precedence + 1)); - } + 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) { - parse_precedence((Precedence)(rule->precedence + 1)); - } + if(emitter.notation == INFIX) + parse_precedence((Precedence)(rule->precedence + 1)); } static void @@ -185,59 +196,139 @@ 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 - */ - } + /** + * maybe a Plex? + * lookup plex defs + * if not then + */ - statement(); + if(is_type()) + variable_declaration(); + else + statement(); } -static void print_statement() { - if (emitter.notation == INFIX) { - emitter.emit_print(); - } - expression(); - consume(TOKEN_SEMICOLON); - if (emitter.notation == POSTFIX) { - 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(); +} + +static void +block() +{ + while(!check(TOKEN_RBRACE) && !check(TOKEN_EOF)) declaration(); + + consume(TOKEN_RBRACE); } static void statement() { - if(match(TOKEN_KEYWORD_PRINT)) { - print_statement(); - } else { + if(match(TOKEN_LBRACE)) { + scope_push(); + block(); + scope_pop(); + } else if(match(TOKEN_KEYWORD_PRINT)) { + print_statement(); + } else { expression(); - } + } } static void @@ -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) { - emitter = e; + arena = a; + emitter = e; init_lexer(source); advance(); + scope_push(); emitter.prolog(); diff --git a/parser.h b/parser.h index 2ceb573..6012fad 100644 --- a/parser.h +++ b/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 diff --git a/test/vars.ul b/test/vars.ul new file mode 100755 index 0000000..c2ed6af --- /dev/null +++ b/test/vars.ul @@ -0,0 +1,4 @@ +int i = 122; +int j = 32; + +print((i - j)); // prints ascii `Z`