diff --git a/arch/linux/main.c b/arch/linux/main.c index 448cf3c..f803db3 100644 --- a/arch/linux/main.c +++ b/arch/linux/main.c @@ -1,4 +1,4 @@ -#include "../../parser.h" +#include "../../compiler.h" #include #include @@ -45,7 +45,7 @@ readFile(const char *path) void print_help() { - printf("Usage: undar [options] file...\nOptions:\n\t-emit={c|u}\tEmitter " + printf("Usage: undar [options] file...\nOptions:\n\t-emit={c99|uxn}\tEmitter " "output, currently C source and Uxn binary.\n\n"); } @@ -65,9 +65,9 @@ main(int argc, char **argv) } Emitter e; - if(seq(argv[1], "-emit=c")) { + if(seq(argv[1], "-emit=c99")) { e = c_emitter(); - } else if(seq(argv[1], "-emit=u")) { + } else if(seq(argv[1], "-emit=uxn")) { e = uxn_emitter(); } else { printf("unknown emitter type\n"); diff --git a/build b/build index 958a7d2..3d1e49e 100755 --- a/build +++ b/build @@ -74,17 +74,15 @@ VM_BUILD_FLAGS="$BUILD_FLAGS -std=c89 -ffreestanding -nostdlib -fno-builtin" ${CC} -c libc.c -o $BUILD_DIR/libc.o $VM_BUILD_FLAGS ${CC} -c list.c -o $BUILD_DIR/list.o $VM_BUILD_FLAGS ${CC} -c lexer.c -o $BUILD_DIR/lexer.o $VM_BUILD_FLAGS -${CC} -c parser.c -o $BUILD_DIR/parser.o $VM_BUILD_FLAGS - -#BUILD_CMD="$CC -o $BUILD_DIR/undar $SRC_DIR/main.c libc.c list.c lexer.c parser.c -I$GEN_DIR $BUILD_FLAGS" +${CC} -c compiler.c -o $BUILD_DIR/compiler.o $VM_BUILD_FLAGS # Set up the final build command case $ARCH in "linux") - BUILD_CMD="$CC -o $BUILD_DIR/undar $SRC_DIR/main.c emit/c/emit.c emit/uxn/emit.c $LINK_FLAGS $BUILD_DIR/libc.o $BUILD_DIR/list.o $BUILD_DIR/lexer.o $BUILD_DIR/parser.o $BUILD_FLAGS $LINK_FLAGS" + BUILD_CMD="$CC -o $BUILD_DIR/undar $SRC_DIR/main.c emit/c/emit.c emit/uxn/emit.c $LINK_FLAGS $BUILD_DIR/libc.o $BUILD_DIR/list.o $BUILD_DIR/lexer.o $BUILD_DIR/compiler.o $BUILD_FLAGS $LINK_FLAGS" ;; "web") - BUILD_CMD="$CC $SRC_DIR/main.c emit/c/emit.c emit/uxn/emit.c $BUILD_DIR/libc.o $BUILD_DIR/list.o $BUILD_DIR/lexer.o $BUILD_DIR/parser.o -o $BUILD_DIR/undar.html $BUILD_FLAGS $LINK_FLAGS" + BUILD_CMD="$CC $SRC_DIR/main.c emit/c/emit.c emit/uxn/emit.c $BUILD_DIR/libc.o $BUILD_DIR/list.o $BUILD_DIR/lexer.o $BUILD_DIR/compiler.o -o $BUILD_DIR/undar.html $BUILD_FLAGS $LINK_FLAGS" ;; esac diff --git a/parser.c b/compiler.c similarity index 57% rename from parser.c rename to compiler.c index 8d1dd23..1a1eb2d 100644 --- a/parser.c +++ b/compiler.c @@ -1,4 +1,4 @@ -#include "parser.h" +#include "compiler.h" #include "emit.h" Emitter emitter; @@ -196,77 +196,91 @@ expression() parse_precedence(PREC_ASSIGNMENT); } -static void variable() { - Symbol *sym = scope_get_symbol(parser.current_scope, parser.previous.start, parser.previous.length); +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.error(parser.previous.start, parser.previous.length, + parser.previous.line); } emitter.emit_variable(sym); } +static void +cast_type() +{ +} + static void variable_declaration() { i32 size = 0; TokenType tt = parser.previous.type; - Token var = parser.current; + 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); + 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); + 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); + 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); - */ + size = emitter.emit_str_type(parser.current.start, parser.current.length); + 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); + 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); + 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); + 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); + 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); + 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); + scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_I16, + size); break; } default: { @@ -375,86 +389,85 @@ unary() } ParseRule rules[] = { - /* 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 */ - /* 6 */ {string, NULL, PREC_NONE}, /* TOKEN_LITERAL_STR */ - /* 7 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_I8 */ - /* 8 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_I16 */ - /* 9 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_INT */ - /*10 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_U8 */ - /*11 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_U16 */ - /*12 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_NAT */ - /*13 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_REAL */ - /*14 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_STR */ - /*15 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_BOOL */ - /*16 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_BYTE */ - /*17 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_VOID */ - /*18 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_PTR */ - /*19 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_PLEX */ - /*20 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_FN */ - /*21 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_CONST */ - /*22 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_IF */ - /*23 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_IS */ - /*24 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_AS */ - /*25 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_ELSE */ - /*26 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_WHILE */ - /*27 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_FOR */ - /*28 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_RETURN */ - /*29 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_USE */ - /*30 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_INIT */ - /*31 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_THIS */ - /*32 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_GLOBAL */ - /*33 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_OPEN */ - /*34 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_READ */ - /*35 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_WRITE */ - /*36 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_STAT */ - /*37 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_CLOSE */ - /*38 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_LOOP */ - /*39 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_DO */ - /*40 */ {literal, NULL, PREC_NONE}, /* TOKEN_KEYWORD_NIL */ - /*41 */ {literal, NULL, PREC_NONE}, /* TOKEN_KEYWORD_TRUE */ - /*42 */ {literal, NULL, PREC_NONE}, /* TOKEN_KEYWORD_FALSE */ - /*43 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_PRINT */ - /*44 */ {NULL, NULL, PREC_NONE}, /* TOKEN_OPERATOR_NOT */ - /*45 */ {NULL, NULL, PREC_NONE}, /* TOKEN_OPERATOR_AND */ - /*46 */ {NULL, NULL, PREC_NONE}, /* TOKEN_OPERATOR_OR */ - /*47 */ {unary, NULL, PREC_NONE}, /* TOKEN_BANG */ - /*48 */ {NULL, binary, PREC_EQUALITY}, /* TOKEN_BANG_EQ */ - /*49 */ {NULL, NULL, PREC_NONE}, /* TOKEN_EQ */ - /*50 */ {NULL, binary, PREC_EQUALITY}, /* TOKEN_EQ_EQ */ - /*51 */ {NULL, NULL, PREC_NONE}, /* TOKEN_AND */ - /*52 */ {NULL, NULL, PREC_NONE}, /* TOKEN_AND_AND */ - /*53 */ {NULL, NULL, PREC_NONE}, /* TOKEN_PIPE */ - /*54 */ {NULL, NULL, PREC_NONE}, /* TOKEN_PIPE_PIPE */ - /*55 */ {NULL, NULL, PREC_NONE}, /* TOKEN_QUESTION */ - /*56 */ {NULL, NULL, PREC_NONE}, /* TOKEN_QUESTION_DOT */ - /*57 */ {NULL, binary, PREC_TERM}, /* TOKEN_PLUS */ - /*58 */ {unary, binary, PREC_TERM}, /* TOKEN_MINUS */ - /*59 */ {NULL, binary, PREC_FACTOR}, /* TOKEN_STAR */ - /*60 */ {NULL, binary, PREC_FACTOR}, /* TOKEN_SLASH */ - /*61 */ {NULL, NULL, PREC_NONE}, /* TOKEN_MESH */ - /*62 */ {NULL, NULL, PREC_NONE}, /* TOKEN_BIG_MONEY */ - /*63 */ {NULL, binary, PREC_COMPARISON}, /* TOKEN_GT */ - /*64 */ {NULL, binary, PREC_COMPARISON}, /* TOKEN_LT */ - /*65 */ {NULL, binary, PREC_COMPARISON}, /* TOKEN_GTE */ - /*66 */ {NULL, binary, PREC_COMPARISON}, /* TOKEN_LTE */ - /*67 */ {NULL, NULL, PREC_NONE}, /* TOKEN_DOT */ - /*68 */ {NULL, NULL, PREC_NONE}, /* TOKEN_COMMA */ - /*69 */ {NULL, NULL, PREC_NONE}, /* TOKEN_COLON */ - /*70 */ {NULL, NULL, PREC_NONE}, /* TOKEN_CARET */ - /*71 */ {NULL, NULL, PREC_NONE}, /* TOKEN_SEMICOLON */ - /*72 */ {grouping, NULL, PREC_NONE}, /* TOKEN_LPAREN */ - /*73 */ {NULL, NULL, PREC_NONE}, /* TOKEN_RPAREN */ - /*74 */ {NULL, NULL, PREC_NONE}, /* TOKEN_LBRACE */ - /*75 */ {NULL, NULL, PREC_NONE}, /* TOKEN_RBRACE */ - /*76 */ {NULL, NULL, PREC_NONE}, /* TOKEN_LBRACKET */ - /*77 */ {NULL, NULL, PREC_NONE}, /* TOKEN_RBRACKET */ - /*78 */ {NULL, NULL, PREC_NONE} /* TOKEN_ARROW_RIGHT */ -}; + /* TOKEN_ERROR */ {nil, nil, PREC_NONE}, + /* TOKEN_EOF */ {nil, nil, PREC_NONE}, + /* TOKEN_IDENTIFIER */ {variable, nil, PREC_NONE}, + /* TOKEN_LITERAL_INT */ {number, nil, PREC_NONE}, + /* TOKEN_LITERAL_NAT */ {number, nil, PREC_NONE}, + /* TOKEN_LITERAL_REAL */ {number, nil, PREC_NONE}, + /* TOKEN_LITERAL_STR */ {string, nil, PREC_NONE}, + /* TOKEN_TYPE_I8 */ {nil, nil, PREC_NONE}, + /* TOKEN_TYPE_I16 */ {nil, nil, PREC_NONE}, + /* TOKEN_TYPE_INT */ {nil, nil, PREC_NONE}, + /* TOKEN_TYPE_U8 */ {nil, nil, PREC_NONE}, + /* TOKEN_TYPE_U16 */ {nil, nil, PREC_NONE}, + /* TOKEN_TYPE_NAT */ {nil, nil, PREC_NONE}, + /* TOKEN_TYPE_REAL */ {nil, nil, PREC_NONE}, + /* TOKEN_TYPE_STR */ {nil, nil, PREC_NONE}, + /* TOKEN_TYPE_BOOL */ {nil, nil, PREC_NONE}, + /* TOKEN_TYPE_BYTE */ {nil, nil, PREC_NONE}, + /* TOKEN_TYPE_VOID */ {nil, nil, PREC_NONE}, + /* TOKEN_TYPE_PTR */ {nil, nil, PREC_NONE}, + /* TOKEN_KEYWORD_PLEX */ {nil, nil, PREC_NONE}, + /* TOKEN_KEYWORD_FN */ {nil, nil, PREC_NONE}, + /* TOKEN_KEYWORD_CONST */ {nil, nil, PREC_NONE}, + /* TOKEN_KEYWORD_IF */ {nil, nil, PREC_NONE}, + /* TOKEN_KEYWORD_IS */ {nil, nil, PREC_NONE}, + /* TOKEN_KEYWORD_AS */ {nil, cast_type, PREC_NONE}, + /* TOKEN_KEYWORD_ELSE */ {nil, nil, PREC_NONE}, + /* TOKEN_KEYWORD_WHILE */ {nil, nil, PREC_NONE}, + /* TOKEN_KEYWORD_FOR */ {nil, nil, PREC_NONE}, + /* TOKEN_KEYWORD_RETURN */ {nil, nil, PREC_NONE}, + /* TOKEN_KEYWORD_USE */ {nil, nil, PREC_NONE}, + /* TOKEN_KEYWORD_INIT */ {nil, nil, PREC_NONE}, + /* TOKEN_KEYWORD_THIS */ {nil, nil, PREC_NONE}, + /* TOKEN_KEYWORD_GLOBAL */ {nil, nil, PREC_NONE}, + /* TOKEN_KEYWORD_OPEN */ {nil, nil, PREC_NONE}, + /* TOKEN_KEYWORD_READ */ {nil, nil, PREC_NONE}, + /* TOKEN_KEYWORD_WRITE */ {nil, nil, PREC_NONE}, + /* TOKEN_KEYWORD_STAT */ {nil, nil, PREC_NONE}, + /* TOKEN_KEYWORD_CLOSE */ {nil, nil, PREC_NONE}, + /* TOKEN_KEYWORD_LOOP */ {nil, nil, PREC_NONE}, + /* TOKEN_KEYWORD_DO */ {nil, nil, PREC_NONE}, + /* TOKEN_KEYWORD_NIL */ {literal, nil, PREC_NONE}, + /* TOKEN_KEYWORD_TRUE */ {literal, nil, PREC_NONE}, + /* TOKEN_KEYWORD_FALSE */ {literal, nil, PREC_NONE}, + /* TOKEN_KEYWORD_PRINT */ {nil, nil, PREC_NONE}, + /* TOKEN_OPERATOR_NOT */ {nil, nil, PREC_NONE}, + /* TOKEN_OPERATOR_AND */ {nil, nil, PREC_NONE}, + /* TOKEN_OPERATOR_OR */ {nil, nil, PREC_NONE}, + /* TOKEN_BANG */ {unary, nil, PREC_NONE}, + /* TOKEN_BANG_EQ */ {nil, binary, PREC_EQUALITY}, + /* TOKEN_EQ */ {nil, nil, PREC_NONE}, + /* TOKEN_EQ_EQ */ {nil, binary, PREC_EQUALITY}, + /* TOKEN_AND */ {nil, nil, PREC_NONE}, + /* TOKEN_AND_AND */ {nil, nil, PREC_NONE}, + /* TOKEN_PIPE */ {nil, nil, PREC_NONE}, + /* TOKEN_PIPE_PIPE */ {nil, nil, PREC_NONE}, + /* TOKEN_QUESTION */ {nil, nil, PREC_NONE}, + /* TOKEN_QUESTION_DOT */ {nil, nil, PREC_NONE}, + /* TOKEN_PLUS */ {nil, binary, PREC_TERM}, + /* TOKEN_MINUS */ {unary, binary, PREC_TERM}, + /* TOKEN_STAR */ {nil, binary, PREC_FACTOR}, + /* TOKEN_SLASH */ {nil, binary, PREC_FACTOR}, + /* TOKEN_MESH */ {nil, nil, PREC_NONE}, + /* TOKEN_BIG_MONEY */ {nil, nil, PREC_NONE}, + /* TOKEN_GT */ {nil, binary, PREC_COMPARISON}, + /* TOKEN_LT */ {nil, binary, PREC_COMPARISON}, + /* TOKEN_GTE */ {nil, binary, PREC_COMPARISON}, + /* TOKEN_LTE */ {nil, binary, PREC_COMPARISON}, + /* TOKEN_DOT */ {nil, nil, PREC_NONE}, + /* TOKEN_COMMA */ {nil, nil, PREC_NONE}, + /* TOKEN_COLON */ {nil, nil, PREC_NONE}, + /* TOKEN_CARET */ {nil, nil, PREC_NONE}, + /* TOKEN_SEMICOLON */ {nil, nil, PREC_NONE}, + /* TOKEN_LPAREN */ {grouping, nil, PREC_NONE}, + /* TOKEN_RPAREN */ {nil, nil, PREC_NONE}, + /* TOKEN_LBRACE */ {nil, nil, PREC_NONE}, + /* TOKEN_RBRACE */ {nil, nil, PREC_NONE}, + /* TOKEN_LBRACKET */ {nil, nil, PREC_NONE}, + /* TOKEN_RBRACKET */ {nil, nil, PREC_NONE}, + /* TOKEN_ARROW_RIGHT */ {nil, nil, PREC_NONE}}; static void parse_precedence(Precedence precedence) @@ -464,7 +477,7 @@ parse_precedence(Precedence precedence) advance(); prefixRule = get_rule(parser.previous.type)->prefix; - if(prefixRule == NULL) return; + if(prefixRule == nil) return; prefixRule(); diff --git a/parser.h b/compiler.h similarity index 100% rename from parser.h rename to compiler.h diff --git a/emit.h b/emit.h index 0425697..4155eaf 100644 --- a/emit.h +++ b/emit.h @@ -73,6 +73,11 @@ struct emitter_s { VoidArgEmit emit_close_paren; StrArgEmit emit_constant; SymbolEmit emit_variable; + VoidArgEmit emit_write; + VoidArgEmit emit_read; + VoidArgEmit emit_open; + VoidArgEmit emit_close; + VoidArgEmit emit_stat; }; Emitter c_emitter(); diff --git a/emit/c/emit.c b/emit/c/emit.c deleted file mode 100644 index d1b5fff..0000000 --- a/emit/c/emit.c +++ /dev/null @@ -1,353 +0,0 @@ -#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() -{ -} - -void -c_epilogue() -{ -} - -void -c_emit_add() -{ - printf("+ "); -} - -void -c_emit_sub() -{ - printf("- "); -} - -void -c_emit_mul() -{ - printf("* "); -} - -void -c_emit_div() -{ - printf("/ "); -} - -void -c_emit_lt() -{ - printf("< "); -} - -void -c_emit_le() -{ - printf("<= "); -} - -void -c_emit_gt() -{ - printf("> "); -} - -void -c_emit_ge() -{ - printf(">= "); -} - -void -c_emit_ne() -{ - printf("!= "); -} - -void -c_emit_eq() -{ - printf("== "); -} - -void -c_emit_false() -{ - printf("false "); -} - -void -c_emit_true() -{ - printf("true "); -} - -void -c_emit_nil() -{ - printf("NULL "); -} - -void -c_emit_neg() -{ - printf("-"); -} - -void -c_emit_not() -{ - printf("!"); -} - -void -c_emit_void() -{ -} - -i32 -c_emit_bool_type(const char *str, i32 length) -{ - printf("%.*s ", length, str); - return 1; -} - -i32 -c_emit_byte_type(const char *str, i32 length) -{ - printf("%.*s ", length, str); - return 1; -} - -i32 -c_emit_int_type(const char *str, i32 length) -{ - printf("%.*s ", length, str); - return 2; -} - -i32 -c_emit_nat_type(const char *str, i32 length) -{ - printf("%.*s ", length, str); - return 2; -} - -i32 -c_emit_real_type(const char *str, i32 length) -{ - printf("%.*s ", length, str); - return 2; -} - -i32 -c_emit_str_type(const char *str, i32 length) -{ - printf("%.*s ", length, str); - return 2; -} - -i32 -c_emit_u8_type(const char *str, i32 length) -{ - printf("%.*s ", length, str); - return 1; -} - -i32 -c_emit_i8_type(const char *str, i32 length) -{ - printf("%.*s ", length, str); - return 1; -} - -i32 -c_emit_i16_type(const char *str, i32 length) -{ - printf("%.*s ", length, str); - return 2; -} - -i32 -c_emit_u16_type(const char *str, i32 length) -{ - printf("%.*s ", length, str); - return 2; -} - -i32 -c_emit_i32_type(const char *str, i32 length) -{ - printf("%.*s ", length, str); - return 4; -} - -i32 -c_emit_u32_type(const char *str, i32 length) -{ - printf("%.*s ", length, str); - return 4; -} - -i32 -c_emit_f32_type(const char *str, i32 length) -{ - printf("%.*s ", length, str); - return 4; -} - -void -c_emit_int(const char *str, i32 length) -{ - printf("%.*s ", length, str); -} - -void -c_emit_nat(const char *str, i32 length) -{ - printf("%.*s ", length, str); -} - -void -c_emit_real(const char *str, i32 length) -{ - printf("%.*s ", length, str); -} - -void -c_emit_byte(const char *str, i32 length) -{ - printf("%.*s ", length, str); -} - -void -c_emit_str(const char *str, i32 length) -{ - printf("%.*s ", length, str); -} - -void -c_emit_array() -{ -} - -void -c_emit_function() -{ -} - -void -c_emit_plex() -{ -} - -void -c_emit_method() -{ -} - -void -c_emit_trait() -{ -} - -void -c_emit_const() -{ -} - -void -c_emit_print() -{ - printf("putchar"); -} - -void -c_emit_open_paren() -{ - printf("("); -} - -void -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, - c_emit_sub, - c_emit_mul, - c_emit_div, - c_emit_lt, - c_emit_le, - c_emit_gt, - c_emit_ge, - c_emit_ne, - c_emit_eq, - c_emit_false, - c_emit_true, - c_emit_nil, - c_emit_void, - c_emit_int, - c_emit_nat, - c_emit_real, - c_emit_byte, - c_emit_str, - c_emit_bool_type, - c_emit_byte_type, - c_emit_int_type, - c_emit_nat_type, - c_emit_real_type, - c_emit_str_type, - c_emit_u8_type, - c_emit_i8_type, - c_emit_i16_type, - c_emit_u16_type, - c_emit_i32_type, - c_emit_u32_type, - c_emit_f32_type, - c_emit_array, - c_emit_function, - c_emit_plex, - c_emit_method, - c_emit_trait, - c_emit_const, - c_emit_print, - c_emit_neg, - c_emit_not, - c_emit_open_paren, - c_emit_close_paren, - c_emit_constant, - c_emit_variable, - }; -} diff --git a/emit/c99/emit.c b/emit/c99/emit.c new file mode 100644 index 0000000..77ed4a6 --- /dev/null +++ b/emit/c99/emit.c @@ -0,0 +1,384 @@ +#include "../../emit.h" +#include +#include + +void +c99_emit_error(const char *str, i32 length, i32 line) +{ + printf("Error at line: %d (%.*s)\n ", line, length, str); + exit(1); +} + +void +c99_prolog() +{ +} + +void +c99_epilogue() +{ +} + +void +c99_emit_add() +{ + printf("+ "); +} + +void +c99_emit_sub() +{ + printf("- "); +} + +void +c99_emit_mul() +{ + printf("* "); +} + +void +c99_emit_div() +{ + printf("/ "); +} + +void +c99_emit_lt() +{ + printf("< "); +} + +void +c99_emit_le() +{ + printf("<= "); +} + +void +c99_emit_gt() +{ + printf("> "); +} + +void +c99_emit_ge() +{ + printf(">= "); +} + +void +c99_emit_ne() +{ + printf("!= "); +} + +void +c99_emit_eq() +{ + printf("== "); +} + +void +c99_emit_false() +{ + printf("false "); +} + +void +c99_emit_true() +{ + printf("true "); +} + +void +c99_emit_nil() +{ + printf("nil "); +} + +void +c99_emit_neg() +{ + printf("-"); +} + +void +c99_emit_not() +{ + printf("!"); +} + +void +c99_emit_void() +{ +} + +i32 +c99_emit_bool_type(const char *str, i32 length) +{ + printf("%.*s ", length, str); + return 1; +} + +i32 +c99_emit_byte_type(const char *str, i32 length) +{ + printf("%.*s ", length, str); + return 1; +} + +i32 +c99_emit_int_type(const char *str, i32 length) +{ + printf("%.*s ", length, str); + return 2; +} + +i32 +c99_emit_nat_type(const char *str, i32 length) +{ + printf("%.*s ", length, str); + return 2; +} + +i32 +c99_emit_real_type(const char *str, i32 length) +{ + printf("%.*s ", length, str); + return 2; +} + +i32 +c99_emit_str_type(const char *str, i32 length) +{ + printf("%.*s ", length, str); + return 2; +} + +i32 +c99_emit_u8_type(const char *str, i32 length) +{ + printf("%.*s ", length, str); + return 1; +} + +i32 +c99_emit_i8_type(const char *str, i32 length) +{ + printf("%.*s ", length, str); + return 1; +} + +i32 +c99_emit_i16_type(const char *str, i32 length) +{ + printf("%.*s ", length, str); + return 2; +} + +i32 +c99_emit_u16_type(const char *str, i32 length) +{ + printf("%.*s ", length, str); + return 2; +} + +i32 +c99_emit_i32_type(const char *str, i32 length) +{ + printf("%.*s ", length, str); + return 4; +} + +i32 +c99_emit_u32_type(const char *str, i32 length) +{ + printf("%.*s ", length, str); + return 4; +} + +i32 +c99_emit_f32_type(const char *str, i32 length) +{ + printf("%.*s ", length, str); + return 4; +} + +void +c99_emit_int(const char *str, i32 length) +{ + printf("%.*s ", length, str); +} + +void +c99_emit_nat(const char *str, i32 length) +{ + printf("%.*s ", length, str); +} + +void +c99_emit_real(const char *str, i32 length) +{ + printf("%.*s ", length, str); +} + +void +c99_emit_byte(const char *str, i32 length) +{ + printf("%.*s ", length, str); +} + +void +c99_emit_str(const char *str, i32 length) +{ + printf("%.*s ", length, str); +} + +void +c99_emit_array() +{ +} + +void +c99_emit_function() +{ +} + +void +c99_emit_plex() +{ +} + +void +c99_emit_method() +{ +} + +void +c99_emit_trait() +{ +} + +void +c99_emit_const() +{ +} + +void +c99_emit_print() +{ + printf("printf"); +} + +void +c99_emit_open_paren() +{ + printf("("); +} + +void +c99_emit_close_paren() +{ + printf(")"); +} + +void +c99_emit_constant(const char *str, i32 length) +{ + USED(str); + USED(length); +} + +void +c99_emit_variable(Symbol *sym) +{ + USED(sym); +} + +void +c99_emit_write() +{ +} + +void +c99_emit_read() +{ +} + +void +c99_emit_open() +{ +} + +void +c99_emit_close() +{ +} + +void +c99_emit_stat() +{ +} + +Emitter +c99_emitter() +{ + return (Emitter){ + INFIX, + TEXT, + c99_emit_error, + c99_prolog, + c99_epilogue, + c99_emit_add, + c99_emit_sub, + c99_emit_mul, + c99_emit_div, + c99_emit_lt, + c99_emit_le, + c99_emit_gt, + c99_emit_ge, + c99_emit_ne, + c99_emit_eq, + c99_emit_false, + c99_emit_true, + c99_emit_nil, + c99_emit_void, + c99_emit_int, + c99_emit_nat, + c99_emit_real, + c99_emit_byte, + c99_emit_str, + c99_emit_bool_type, + c99_emit_byte_type, + c99_emit_int_type, + c99_emit_nat_type, + c99_emit_real_type, + c99_emit_str_type, + c99_emit_u8_type, + c99_emit_i8_type, + c99_emit_i16_type, + c99_emit_u16_type, + c99_emit_i32_type, + c99_emit_u32_type, + c99_emit_f32_type, + c99_emit_array, + c99_emit_function, + c99_emit_plex, + c99_emit_method, + c99_emit_trait, + c99_emit_const, + c99_emit_print, + c99_emit_neg, + c99_emit_not, + c99_emit_open_paren, + c99_emit_close_paren, + c99_emit_constant, + c99_emit_variable, + c99_emit_write, + c99_emit_read, + c99_emit_open, + c99_emit_close, + c99_emit_stat, + }; +} diff --git a/emit/c99/libundar.c b/emit/c99/libundar.c new file mode 100644 index 0000000..21ed0ac --- /dev/null +++ b/emit/c99/libundar.c @@ -0,0 +1,511 @@ +#if defined(__has_include) +#if __has_include() +#define HAVE_STDINT 1 +#endif +#if __has_include() +#define HAVE_STDBOOL 1 +#endif +#if __has_include() +#define HAVE_STDDEF 1 +#endif +#endif + +#ifdef HAVE_STDINT +#include +typedef uint8_t u8; +typedef int8_t i8; +typedef uint16_t u16; +typedef int16_t i16; +typedef uint32_t u32; +typedef int32_t i32; +typedef int32_t r32; +typedef float f32; +#else +typedef unsigned char u8; +typedef signed char i8; +typedef unsigned short u16; +typedef signed short i16; +typedef unsigned int u32; +typedef signed int i32; +typedef signed int r32; +typedef float f32; +#endif + +#ifdef HAVE_STDBOOL +#include +#else +#define true 1 +#define false 0 +typedef u8 bool; +#endif + +#ifdef HAVE_STDDEF +#include +#define nil NULL +#else +#define nil ((void *)0) +#endif + +#define I8_MIN -128 +#define I8_MAX 127 +#define U8_MAX 255 + +#define I16_MIN -32768 +#define I16_MAX 32767 +#define U16_MAX 65535 + +#define I32_MIN -2147483648 +#define I32_MAX 2147483647 +#define U32_MAX 4294967295 + +#define FIXED_CONST 65536.0f + +#define AS_INT(v) ((i32)(v)) +#define AS_NAT(v) ((u32)(v)) +#define AS_REAL(v) ((r32)(v)) +#define FLOAT_TO_REAL(v) (((r32)(v)) * FIXED_CONST) +#define REAL_TO_FLOAT(v) (((f32)(v)) / FIXED_CONST) + +#define USED(x) ((void)(x)) + +#define MAX_LEN_REAL32 12 +#define MAX_LEN_INT32 11 +const char radix_set[11] = "0123456789"; + +typedef struct arena_s Arena; +struct arena_s { + u8 *tape; + u32 count; + u32 capacity; +}; + +typedef struct node_s Node; +struct node_s { + struct node_s *next; +}; + +typedef struct list_s List; +struct list_s { + Node *head; + Node *tail; + u32 count; +}; + +typedef bool (*compare_fn)(void *data, void *target); +typedef void (*list_iter_fn)(void *data); + +void +mcpy(void *to, void *from, u32 length) +{ + u8 *src, *dest; + if(to == nil || from == nil) return; + + src = (u8 *)from; + dest = (u8 *)to; + + while(length-- > 0) *(dest++) = *(src++); + return; +} + +i32 +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 && from[i] != '\0'; i++) to[i] = from[i]; + to[i] = '\0'; + return 0; +} + +bool +seq(const char *s1, const char *s2) +{ + if(s1 == nil && s2 == nil) return true; + if(s1 == nil || s2 == nil) return false; + + while(*s1 && *s2) { + if(*s1 != *s2) return false; + s1++; + s2++; + } + + return (*s1 == '\0' && *s2 == '\0'); +} + +bool +sleq(const char *s1, const char *s2, u32 length) +{ + u32 i; + if(s1 == nil && s2 == nil) return true; + if(s1 == nil || s2 == nil) return false; + + i = 0; + while(i < length && *s1 && *s2) { + if(*s1 != *s2) return false; + s1++; + s2++; + i++; + } + if(i == length) return true; + return (*s1 == '\0' && *s2 == '\0'); +} + +u32 +slen(const char *str) +{ + u32 i; + if(str == nil) return 0; + for(i = 0; str[i] != '\0'; i++); + return i; +} + +u32 +snlen(const char *str, u32 max_len) +{ + u32 i; + if(str == nil) return 0; + for(i = 0; i < max_len && str[i] != '\0'; i++); + return i; +} + +void * +aalloc(Arena *arena, u32 size) +{ + u32 pos; + if(arena == nil) return nil; + if(arena->count + size > arena->capacity) return nil; + + pos = arena->count; + arena->count += size; + return (void *)&arena->tape[pos]; +} + +void * +areturn(Arena *arena, u32 checkpoint, const void *src, u32 size) +{ + void *dest; + if(arena == nil || src == nil) return nil; + + dest = (void *)&arena->tape[checkpoint]; + if(src == dest) return dest; + + mcpy(dest, (void *)src, size); + arena->count = checkpoint + size; + + return dest; +} + +#define ARENA_RETURN(arena, ckpt, src_ptr, type) \ + return (type *)areturn((arena), (ckpt), (src_ptr), sizeof(type)) + +#define ARENA_RETURN_ARRAY(arena, ckpt, src_ptr, type, count) \ + return (type *)areturn((arena), (ckpt), (src_ptr), sizeof(type) * (count)) + +r32 +int_to_real(i32 i) +{ + return i << 16; +} +i32 +real_to_int(r32 f) +{ + return f >> 16; +} +r32 +float_to_real(f32 f) +{ + return FLOAT_TO_REAL(f); +} +f32 +real_tor32oat(r32 f) +{ + return REAL_TO_FLOAT(f); +} +r32 +real_add(r32 a, r32 b) +{ + return a + b; +} +r32 +real_sub(r32 a, r32 b) +{ + return a - b; +} +r32 +real_mul(r32 a, r32 b) +{ + + r32 src1_whole = (r32)a >> 16; + r32 src2_whole = (r32)b >> 16; + + r32 src1_decimal = (r32)a & 16; + r32 src2_decimal = (r32)b & 16; + + r32 result = 0; + result += (src1_whole * src2_whole) << 16; + result += (src1_whole * src2_decimal); + result += (src1_decimal * src2_whole); + result += ((src1_decimal * src2_decimal) >> 16) & 16; + + return result; +} + +r32 +real_div(r32 a, r32 b) +{ + r32 result; + + r32 src1_val = (r32)a; + r32 src2_val = (r32)b; + u32 src2_reciprocal = 1; + + src2_reciprocal <<= 31; + src2_reciprocal = (u32)(src2_reciprocal / src2_val); + result = src1_val * src2_reciprocal; + result <<= 1; + + return result; +} + +r32 +real_eq(r32 a, r32 b) +{ + return a == b; +} +r32 +real_ne(r32 a, r32 b) +{ + return a != b; +} +r32 +real_lt(r32 a, r32 b) +{ + return a < b; +} +r32 +real_le(r32 a, r32 b) +{ + return a <= b; +} +r32 +real_gt(r32 a, r32 b) +{ + return a > b; +} +r32 +real_ge(r32 a, r32 b) +{ + return a >= b; +} +r32 +real_neg(r32 f) +{ + return -f; +} +r32 +real_abs(r32 f) +{ + return (f < 0) ? -f : f; +} + +char * +ascpy(Arena *arena, const char *start, u32 length) +{ + char *str; + if(!start) return nil; + str = (char *)aalloc(arena, length + 1); + if(!str) return nil; + scpy(str, start, length); + return str; +} + +void * +amcpy(Arena *arena, void *from, u32 length) +{ + void *ptr; + if(!from) return nil; + ptr = aalloc(arena, length); + if(!ptr) return nil; + mcpy(ptr, from, length); + return ptr; +} + +void +int_to_string(i32 v, char *str) +{ + char buffer[MAX_LEN_INT32]; + i32 n; + u32 i = MAX_LEN_INT32; + bool neg; + n = v; + neg = n < 0; + + if(neg) n = -n; + + do { + buffer[--i] = radix_set[n % 10]; + n /= 10; + } while(n > 0); + if(neg) buffer[--i] = '-'; + /* Ensure at least one digit is written for 0 */ + if(v == 0) buffer[--i] = '0'; + + scpy(str, buffer + i, MAX_LEN_INT32 - i); +} + +void +nat_to_string(u32 v, char *str) +{ + char buffer[MAX_LEN_INT32]; + u32 n; + u32 i = MAX_LEN_INT32; + n = v; + + do { + buffer[--i] = radix_set[n % 10]; + n /= 10; + } while(n > 0); + /* Ensure at least one digit is written for 0 */ + if(v == 0) buffer[--i] = '0'; + + scpy(str, buffer + i, MAX_LEN_INT32 - i); +} + +void +real_to_string(r32 q, char *str) +{ + char buffer[MAX_LEN_REAL32]; + bool neg; + i32 int_part; + u32 frac_part; + u32 i = MAX_LEN_REAL32; + + if(q < 0) q = -q; + + int_part = q >> 16; + frac_part = q & 0xFFFF; + + do { + buffer[--i] = radix_set[frac_part % 10]; + frac_part /= 10; + } while(frac_part > 0); + + buffer[--i] = '.'; + + neg = int_part < 0; + + if(neg) int_part = -int_part; + + do { + buffer[--i] = radix_set[int_part % 10]; + int_part /= 10; + } while(int_part > 0); + + if(neg) buffer[--i] = '-'; + + scpy(str, buffer + i, MAX_LEN_REAL32 - i); +} + +List * +new_list(Arena *arena) +{ + List *l = aalloc(arena, sizeof(List)); + if (!l) return nil; + + l->head = nil; + l->tail = nil; + l->count = 0; + + return l; +} + +void * +node_value(Node *n) +{ + return (void *)((u8 *)n + sizeof(Node)); +} + +void * +list_push(Arena *arena, List *list, void *data, u32 data_size) +{ + void *dest; + void *ptr = aalloc(arena, sizeof(Node) + data_size); + Node *node = (Node *)ptr; + + if (!node) return nil; + + node->next = nil; + + if (!list->head) { + list->head = list->tail = node; + } else { + list->tail->next = node; + list->tail = node; + } + + list->count++; + + dest = node_value(node); + if (data && data_size > 0) { + mcpy(dest, data, data_size); + } + + return dest; +} + +void +list_foreach(List *list, list_iter_fn func) +{ + Node *curr; + if (!list || !func) return; + + curr = list->head; + while (curr) { + func(node_value(curr)); + curr = curr->next; + } +} + +void * +list_get(List *list, u32 index) +{ + u32 i; + Node *curr; + if (!list || index >= list->count) return nil; + + curr = list->head; + for (i = 0; i < index; i++) { + curr = curr->next; + } + + return node_value(curr); +} + +void +list_set(List *list, u32 index, void *data, u32 size) +{ + void *target = list_get(list, index); + if (target) { + mcpy(target, data, size); + } +} + +void * +list_find(List *list, compare_fn compare, void *target) +{ + Node *curr; + void *data; + + if (!list || !compare) return nil; + + curr = list->head; + while (curr) { + data = node_value(curr); + if (compare(data, target)) { + return data; + } + curr = curr->next; + } + return nil; +} diff --git a/emit/uxn/emit.c b/emit/uxn/emit.c index ea38a34..5a5707c 100644 --- a/emit/uxn/emit.c +++ b/emit/uxn/emit.c @@ -71,13 +71,21 @@ uxn_emit_error(const char *str, i32 length, i32 line) void uxn_prolog() { - /* essentially the "main" function */ - printf("|100 @on-reset ( -> )\n"); + printf("|100 @main ( -> )\n"); } void uxn_epilogue() { + /* https://wiki.xxiivv.com/etc/lib.math.tal.txt */ + + printf("\n@nat-to-str ( -- ) \n\ + &>wp \n\ + LDAk DUP ?{ POP POP2 JMP2r } \n\ + #18 DEO \n\ + INC2 !&>wp\n\n"); + printf("@num-to-string $12\n"); + printf("@heap\n"); } void @@ -175,9 +183,6 @@ uxn_emit_void() { } -/* @global $size */ -/* &local $size */ - i32 uxn_emit_bool_type(const char *str, i32 length) { @@ -346,13 +351,14 @@ uxn_emit_const() void uxn_emit_print() { - printf("#18 DEO "); + printf("print "); } void uxn_emit_open_paren() { } + void uxn_emit_close_paren() { @@ -363,6 +369,31 @@ uxn_emit_variable(Symbol *sym) { printf(";%.*s LDA2 ", sym->name_length, sym->name); } +void +uxn_emit_write() +{ +} + +void +uxn_emit_read() +{ +} + +void +uxn_emit_open() +{ +} + +void +uxn_emit_close() +{ +} + +void +uxn_emit_stat() +{ +} + Emitter uxn_emitter() { @@ -417,5 +448,10 @@ uxn_emitter() uxn_emit_close_paren, uxn_emit_constant, uxn_emit_variable, + uxn_emit_write, + uxn_emit_read, + uxn_emit_open, + uxn_emit_close, + uxn_emit_stat, }; } diff --git a/test/for.ul b/test/for.ul index 61496b9..3e74023 100755 --- a/test/for.ul +++ b/test/for.ul @@ -1,6 +1,6 @@ nat i = 0; -for (nat x in 10) { +for (nat x in [0..10]) { print(x as str); } diff --git a/test/global.ul b/test/global.ul index c2ed6af..8eaf0db 100755 --- a/test/global.ul +++ b/test/global.ul @@ -1,4 +1,4 @@ int i = 122; int j = 32; -print((i - j)); // prints ascii `Z` +print((i - j) as str); diff --git a/test/hello.ul b/test/hello.ul index dd150bd..4c0b5b9 100755 --- a/test/hello.ul +++ b/test/hello.ul @@ -1 +1,2 @@ -print("nuqneH 'u'?"); +str msg = "nuqneH 'u'?"; +print(msg); diff --git a/test/str.ul b/test/str.ul new file mode 100755 index 0000000..efa4a2a --- /dev/null +++ b/test/str.ul @@ -0,0 +1,8 @@ +str msg = " damage inflicted!\n" +int AT = 14; +int accuracy = 150; + +int dmg = ((AT * accuracy) / 20) - 3; + +print(dmg as str); +print(msg); \ No newline at end of file