diff --git a/compiler.c b/compiler.c index d8a110a..d79d650 100644 --- a/compiler.c +++ b/compiler.c @@ -1,9 +1,10 @@ #include "compiler.h" #include "common.h" #include "emit.h" +#include "lexer.h" -Emitter emitter; -Parser parser; +Emitter emitter = {0}; +Parser parser = {0}; Arena *arena; /**************************************************** @@ -141,7 +142,7 @@ binary() emitter.emit_eq(); break; case TOKEN_GT: - emitter.emit_ge(); + emitter.emit_gt(); break; case TOKEN_GTE: emitter.emit_ge(); @@ -164,6 +165,24 @@ binary() case TOKEN_SLASH: emitter.emit_div(); break; + case TOKEN_OPERATOR_AND: + emitter.emit_and(); + break; + case TOKEN_OPERATOR_OR: + emitter.emit_or(); + break; + case TOKEN_OPERATOR_XOR: + emitter.emit_xor(); + break; + case TOKEN_OPERATOR_MOD: + emitter.emit_mod(); + break; + case TOKEN_SLL: + emitter.emit_sll(); + break; + case TOKEN_SRL: + emitter.emit_srl(); + break; default: return; } @@ -204,7 +223,7 @@ variable() } parser.current_type = sym->type; - emitter.emit_variable(sym); + emitter.emit_variable(sym, parser.depth); } static void @@ -233,7 +252,7 @@ cast_type() emitter.error("Not castable to this type", 26, parser.previous.line); } - break; + break; } case TOKEN_TYPE_NAT:{ switch(st) { @@ -313,77 +332,77 @@ variable_declaration() switch(tt) { case TOKEN_TYPE_INT: { - size = emitter.emit_int_type(parser.current.start, parser.current.length); + size = emitter.emit_int_type(parser.current.start, parser.current.length, parser.depth); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_INT, size); parser.current_type = SYMBOL_INT; break; } case TOKEN_TYPE_NAT: { - size = emitter.emit_nat_type(parser.current.start, parser.current.length); + size = emitter.emit_nat_type(parser.current.start, parser.current.length, parser.depth); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_NAT, size); parser.current_type = SYMBOL_NAT; break; } case TOKEN_TYPE_REAL: { - size = emitter.emit_real_type(parser.current.start, parser.current.length); + size = emitter.emit_real_type(parser.current.start, parser.current.length, parser.depth); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_REAL, size); parser.current_type = SYMBOL_REAL; break; } case TOKEN_TYPE_STR: { - size = emitter.emit_str_type(parser.current.start, parser.current.length); + size = emitter.emit_str_type(parser.current.start, parser.current.length, parser.depth); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_STR, size); parser.current_type = SYMBOL_STR; break; } case TOKEN_TYPE_BOOL: { - size = emitter.emit_bool_type(parser.current.start, parser.current.length); + size = emitter.emit_bool_type(parser.current.start, parser.current.length, parser.depth); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_BOOL, size); parser.current_type = SYMBOL_BOOL; break; } case TOKEN_TYPE_BYTE: { - size = emitter.emit_byte_type(parser.current.start, parser.current.length); + size = emitter.emit_byte_type(parser.current.start, parser.current.length, parser.depth); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_U8, size); parser.current_type = SYMBOL_BYTE; break; } case TOKEN_TYPE_U8: { - size = emitter.emit_u8_type(parser.current.start, parser.current.length); + size = emitter.emit_u8_type(parser.current.start, parser.current.length, parser.depth); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_U8, size); parser.current_type = SYMBOL_U8; break; } case TOKEN_TYPE_I8: { - size = emitter.emit_i8_type(parser.current.start, parser.current.length); + size = emitter.emit_i8_type(parser.current.start, parser.current.length, parser.depth); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_I8, size); parser.current_type = SYMBOL_I8; break; } case TOKEN_TYPE_U16: { - size = emitter.emit_u16_type(parser.current.start, parser.current.length); + size = emitter.emit_u16_type(parser.current.start, parser.current.length, parser.depth); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_U16, size); parser.current_type = SYMBOL_U16; break; } case TOKEN_TYPE_I16: { - size = emitter.emit_i16_type(parser.current.start, parser.current.length); + size = emitter.emit_i16_type(parser.current.start, parser.current.length, parser.depth); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_I16, size); parser.current_type = SYMBOL_I16; break; } default: { - /* probably a variable */ + /* probably a plex */ break; } } @@ -393,7 +412,7 @@ variable_declaration() if(match(TOKEN_EQ)) { emitter.emit_set_value(); expression(); - emitter.emit_constant(var.start, var.length); + emitter.emit_constant(var.start, var.length, parser.depth); } consume(TOKEN_SEMICOLON); @@ -425,6 +444,35 @@ print_statement() emitter.emit_print(); } +static void +putchar_statement() +{ + expression(); + consume(TOKEN_SEMICOLON); + emitter.emit_end_statement(); + emitter.emit_putchar(); +} + +static void +getchar_statement() +{ + expression(); + consume(TOKEN_SEMICOLON); + emitter.emit_end_statement(); + emitter.emit_putchar(); +} + +static void +if_statement() +{ + consume(TOKEN_LPAREN); + expression(); + consume(TOKEN_RPAREN); + emitter.emit_jump(); + statement(); + emitter.emit_patch_jump(); +} + static void block() { @@ -440,8 +488,14 @@ statement() scope_push(); block(); scope_pop(); + } else if(match(TOKEN_KEYWORD_IF)) { + if_statement(); } else if(match(TOKEN_KEYWORD_PRINT)) { - print_statement(); + print_statement(); + } else if(match(TOKEN_KEYWORD_PUTCHAR)) { + putchar_statement(); + } else if(match(TOKEN_KEYWORD_GETCHAR)) { + getchar_statement(); } else { expression(); } @@ -521,7 +575,6 @@ ParseRule rules[] = { /* 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}, @@ -532,10 +585,12 @@ ParseRule rules[] = { /* 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_KEYWORD_PUTCHAR */ {nil, nil, PREC_NONE}, + /* TOKEN_KEYWORD_GETCHAR */ {nil, nil, PREC_NONE}, + /* TOKEN_OPERATOR_AND */ {nil, binary, PREC_NONE}, + /* TOKEN_OPERATOR_OR */ {nil, binary, PREC_NONE}, + /* TOKEN_OPERATOR_XOR */ {nil, binary, PREC_NONE}, + /* TOKEN_OPERATOR_MOD */ {nil, binary, PREC_NONE}, /* TOKEN_BANG */ {unary, nil, PREC_NONE}, /* TOKEN_BANG_EQ */ {nil, binary, PREC_EQUALITY}, /* TOKEN_EQ */ {nil, nil, PREC_NONE}, @@ -567,7 +622,10 @@ ParseRule rules[] = { /* 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}}; + /* TOKEN_ARROW_RIGHT */ {nil, nil, PREC_NONE}, + /* TOKEN_SLL */ {nil, binary, PREC_NONE}, + /* TOKEN_SRL */ {nil, binary, PREC_NONE}, + /*TOKEN_KEYWORD_PRINT*/{nil, binary, PREC_NONE} }; static void parse_precedence(Precedence precedence) diff --git a/compiler.h b/compiler.h index 0735a59..17c3b56 100644 --- a/compiler.h +++ b/compiler.h @@ -42,6 +42,7 @@ struct parser_s { Token current; Token previous; SymbolType current_type; + u32 depth; }; bool compile(Arena *a, Emitter e, char *source); diff --git a/emit.h b/emit.h index a033924..46d4d76 100644 --- a/emit.h +++ b/emit.h @@ -8,7 +8,9 @@ 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 i32 (*TypeVariableEmit)(const char *str, i32 length, bool local); +typedef void (*ConstEmit)(const char *str, i32 length, bool local); +typedef void (*VarEmit)(Symbol *sym, bool local); typedef struct emitter_s Emitter; struct emitter_s { @@ -54,12 +56,14 @@ struct emitter_s { VoidArgEmit emit_trait; VoidArgEmit emit_const; VoidArgEmit emit_print; + VoidArgEmit emit_putchar; + VoidArgEmit emit_getchar; VoidArgEmit emit_neg; VoidArgEmit emit_not; VoidArgEmit emit_open_paren; VoidArgEmit emit_close_paren; - StrArgEmit emit_constant; - SymbolEmit emit_variable; + ConstEmit emit_constant; + VarEmit emit_variable; VoidArgEmit emit_write; VoidArgEmit emit_read; VoidArgEmit emit_open; @@ -87,6 +91,14 @@ struct emitter_s { VoidArgEmit emit_cast_str_to_int; VoidArgEmit emit_cast_str_to_nat; VoidArgEmit emit_cast_str_to_real; + VoidArgEmit emit_sll; + VoidArgEmit emit_srl; + VoidArgEmit emit_xor; + VoidArgEmit emit_mod; + VoidArgEmit emit_and; + VoidArgEmit emit_or; + VoidArgEmit emit_jump; + VoidArgEmit emit_patch_jump; }; Emitter rer_emitter(); diff --git a/emit/rer/emit.c b/emit/rer/emit.c index f9f2fbb..90aa63f 100644 --- a/emit/rer/emit.c +++ b/emit/rer/emit.c @@ -2,6 +2,25 @@ #include #include +#define RER_OP_2 (1 << 5) +#define RER_OP_R (1 << 6) +#define RER_OP_K (1 << 7) + +enum rer_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 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, + + LIT = 0x80, JCI = 0x20, JMI = 0x40, JSI = 0x60, +}; + void rer_emit_error(const char *str, i32 length, i32 line) { @@ -18,87 +37,106 @@ rer_mem(u32 a) void rer_prolog() { + printf("|100\n"); } void rer_epilogue() { - + printf("\n\n@str/ ( str* -- )\n\ + LDAk DUP ?{ POP POP2 JMP2r }\n\ + #18 DEO\n\ + INC2 !/\n"); } void rer_emit_add() { + printf("ADD2 "); } void rer_emit_sub() { + printf("SUB2 "); } void rer_emit_mul() { + printf("MUL2 "); } void rer_emit_div() { + printf("DIV2 "); } void rer_emit_lt() { + printf("LTH2 "); } void rer_emit_le() { + printf("ROT SWP LTH ?{ LTH #00 EQU JMPr } GTH JMPr "); } void rer_emit_gt() { + printf("GTH2 "); } void rer_emit_ge() { + printf("ROT SWP GTH ?{ GTH #00 EQU JMPr } LTH JMPr "); } void rer_emit_ne() { + printf("NEQ2 "); } void rer_emit_eq() { + printf("EQU2 "); } void rer_emit_false() { + printf("#0000 "); } void rer_emit_true() { + printf("#0001 "); } void rer_emit_nil() { + printf("#0000 "); } void rer_emit_neg() { + printf("#0000 SUB2 "); } void rer_emit_not() { + printf("#FFFF EOR2 "); } void @@ -107,93 +145,133 @@ rer_emit_void() } i32 -rer_emit_bool_type(const char *str, i32 length) +rer_emit_bool_type(const char *str, i32 length, bool local) { - USED(str);USED(length); + if(local) + printf("!{ &%.*s $1 } ", length, str); + else + printf("!{ @%.*s $1 } ", length, str); + return 1; } i32 -rer_emit_byte_type(const char *str, i32 length) +rer_emit_byte_type(const char *str, i32 length, bool local) { - USED(str);USED(length); + if(local) + printf("!{ &%.*s $1 } ", length, str); + else + printf("!{ @%.*s $1 } ", length, str); return 1; } i32 -rer_emit_int_type(const char *str, i32 length) +rer_emit_int_type(const char *str, i32 length, bool local) { - USED(str);USED(length); + if(local) + printf("!{ &%.*s $2 } ", length, str); + else + printf("!{ @%.*s $2 } ", length, str); return 2; } i32 -rer_emit_nat_type(const char *str, i32 length) +rer_emit_nat_type(const char *str, i32 length, bool local) { - USED(str);USED(length); + if(local) + printf("!{ &%.*s $2 } ", length, str); + else + printf("!{ @%.*s $2 } ", length, str); return 2; } i32 -rer_emit_real_type(const char *str, i32 length) +rer_emit_real_type(const char *str, i32 length, bool local) { - USED(str);USED(length); + if(local) + printf("!{ &%.*s $2 } ", length, str); + else + printf("!{ @%.*s $2 } ", length, str); return 2; } i32 -rer_emit_str_type(const char *str, i32 length) +rer_emit_str_type(const char *str, i32 length, bool local) { - USED(str);USED(length); + if(local) + printf("!{ &%.*s $2 } ", length, str); + else + printf("!{ @%.*s $2 } ", length, str); return 2; } i32 -rer_emit_u8_type(const char *str, i32 length) +rer_emit_u8_type(const char *str, i32 length, bool local) { - USED(str);USED(length); + if(local) + printf("!{ &%.*s $1 } ", length, str); + else + printf("!{ @%.*s $1 } ", length, str); return 1; } i32 -rer_emit_i8_type(const char *str, i32 length) +rer_emit_i8_type(const char *str, i32 length, bool local) { - USED(str);USED(length); + if(local) + printf("!{ &%.*s $1 } ", length, str); + else + printf("!{ @%.*s $1 } ", length, str); return 1; } i32 -rer_emit_i16_type(const char *str, i32 length) +rer_emit_i16_type(const char *str, i32 length, bool local) { - USED(str);USED(length); + if(local) + printf("!{ &%.*s $2 } ", length, str); + else + printf("!{ @%.*s $2 } ", length, str); return 2; } i32 -rer_emit_u16_type(const char *str, i32 length) +rer_emit_u16_type(const char *str, i32 length, bool local) { - USED(str);USED(length); + if(local) + printf("!{ &%.*s $2 } ", length, str); + else + printf("!{ @%.*s $2 } ", length, str); return 2; } i32 -rer_emit_i32_type(const char *str, i32 length) +rer_emit_i32_type(const char *str, i32 length, bool local) { - USED(str);USED(length); + if(local) + printf("!{ &%.*s $4 } ", length, str); + else + printf("!{ @%.*s $4 } ", length, str); return 4; } i32 -rer_emit_u32_type(const char *str, i32 length) +rer_emit_u32_type(const char *str, i32 length, bool local) { - USED(str);USED(length); + if(local) + printf("!{ &%.*s $4 } ", length, str); + else + printf("!{ @%.*s $4 } ", length, str); return 4; } i32 -rer_emit_f32_type(const char *str, i32 length) +rer_emit_f32_type(const char *str, i32 length, bool local) { - USED(str);USED(length); + if(local) + printf("!{ &%.*s $4 } ", length, str); + else + printf("!{ @%.*s $4 } ", length, str); return 4; } @@ -232,13 +310,23 @@ rer_emit_byte(const char *str, i32 length) void rer_emit_str(const char *str, i32 length) { - printf("\"%.*s ", length, str); + /* set a pointer to the string literal and then jump over it */ + printf(";{ #0002 ADD2 } !{ "); + + for (i32 i = 1; i < length - 1 ; i++) { + printf("#%02x ", str[i]); + } + + printf("#00 } "); } void -rer_emit_constant(const char *str, i32 length) +rer_emit_constant(const char *str, i32 length, bool local) { - printf(";%.*s STA2 ", length, str); + if(local) + printf(",/%.*s STR2 ", length, str); + else + printf(";%.*s STA2 ", length, str); } void @@ -272,9 +360,15 @@ rer_emit_const() } void -rer_emit_print() +rer_emit_putchar() { - printf("print "); + printf("#18 DEO "); +} + +void +rer_emit_getchar() +{ + printf("#12 DEI "); } void @@ -288,9 +382,12 @@ rer_emit_close_paren() } void -rer_emit_variable(Symbol *sym) +rer_emit_variable(Symbol *sym, bool local) { - printf(";%.*s LDA2 ", sym->name_length, sym->name); + if(local) + printf(",/%.*s LDR2 ", sym->name_length, sym->name); + else + printf(";%.*s LDA2 ", sym->name_length, sym->name); } void @@ -426,6 +523,60 @@ rer_emit_cast_str_to_real() { } +void +rer_emit_sll() +{ + printf("#40 SFT SFT "); +} + +void +rer_emit_srl() +{ + printf("SFT "); +} + +void +rer_emit_xor() +{ + printf("EOR2 "); +} + +void +rer_emit_mod() +{ + printf("DIV2k MUL2 SUB2 "); +} +void +rer_emit_or() +{ + printf("ORA2 "); +} + +void +rer_emit_and() +{ + printf("AND2 "); +} + +void +rer_emit_print() +{ + printf("str/ "); +} + + +void +rer_emit_jump() +{ + printf("?{ "); +} + +void +rer_emit_patch_jump() +{ + printf("} "); +} + Emitter rer_emitter() { @@ -472,6 +623,8 @@ rer_emitter() rer_emit_trait, rer_emit_const, rer_emit_print, + rer_emit_putchar, + rer_emit_getchar, rer_emit_neg, rer_emit_not, rer_emit_open_paren, @@ -505,5 +658,13 @@ rer_emitter() rer_emit_cast_str_to_int, rer_emit_cast_str_to_nat, rer_emit_cast_str_to_real, + rer_emit_sll, + rer_emit_srl, + rer_emit_xor, + rer_emit_mod, + rer_emit_and, + rer_emit_or, + rer_emit_jump, + rer_emit_patch_jump, }; } diff --git a/emit/uxn/emit.c b/emit/uxn/emit.c index 71d4d6d..2ef3a93 100644 --- a/emit/uxn/emit.c +++ b/emit/uxn/emit.c @@ -7,60 +7,20 @@ #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, }; -/* -https://rosettacode.org/wiki/Bitwise_operations#Uxntal - -%not { #ff EOR } -%and { AND } -%or { ORA } -%xor { EOR } -%shl { #40 SFT SFT } -%shr { SFT } -%rol { #40 SFT #00 ROT ROT SFT2 ORA } -%ror { SWP #00 ROT SFT2 ORA } -*/ - void uxn_emit_error(const char *str, i32 length, i32 line) { @@ -77,21 +37,16 @@ uxn_mem(u32 a) void uxn_prolog() { - printf("|100 @main ( -> )\n"); + printf("|100\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"); + printf("BRK\n\n@str/ ( str* -- )\n\ + LDAk DUP ?{ POP POP2 JMP2r }\n\ + #18 DEO\n\ + INC2 !/\n"); } void @@ -181,7 +136,7 @@ uxn_emit_neg() void uxn_emit_not() { - printf("#FFFF EOR2 "); + printf("#ffff EOR2 "); } void @@ -190,93 +145,133 @@ uxn_emit_void() } i32 -uxn_emit_bool_type(const char *str, i32 length) +uxn_emit_bool_type(const char *str, i32 length, bool local) { - printf("!{ @%.*s $1 } ", length, str); + if(local) + printf("!{ &%.*s $2 } ", length, str); + else + printf("!{ @%.*s $2 } ", length, str); + + return 2; +} + +i32 +uxn_emit_byte_type(const char *str, i32 length, bool local) +{ + if(local) + printf("!{ &%.*s $1 } ", length, str); + else + printf("!{ @%.*s $1 } ", length, str); return 1; } i32 -uxn_emit_byte_type(const char *str, i32 length) +uxn_emit_int_type(const char *str, i32 length, bool local) { - printf("!{ @%.*s $1 } ", length, str); + if(local) + printf("!{ &%.*s $2 } ", length, str); + else + printf("!{ @%.*s $2 } ", length, str); + return 2; +} + +i32 +uxn_emit_nat_type(const char *str, i32 length, bool local) +{ + if(local) + printf("!{ &%.*s $2 } ", length, str); + else + printf("!{ @%.*s $2 } ", length, str); + return 2; +} + +i32 +uxn_emit_real_type(const char *str, i32 length, bool local) +{ + if(local) + printf("!{ &%.*s $2 } ", length, str); + else + printf("!{ @%.*s $2 } ", length, str); + return 2; +} + +i32 +uxn_emit_str_type(const char *str, i32 length, bool local) +{ + if(local) + printf("!{ &%.*s $2 } ", length, str); + else + printf("!{ @%.*s $2 } ", length, str); + return 2; +} + +i32 +uxn_emit_u8_type(const char *str, i32 length, bool local) +{ + if(local) + printf("!{ &%.*s $1 } ", length, str); + else + printf("!{ @%.*s $1 } ", length, str); return 1; } i32 -uxn_emit_int_type(const char *str, i32 length) +uxn_emit_i8_type(const char *str, i32 length, bool local) { - printf("!{ @%.*s $2 } ", length, str); - return 2; -} - -i32 -uxn_emit_nat_type(const char *str, i32 length) -{ - printf("!{ @%.*s $2 } ", length, str); - return 2; -} - -i32 -uxn_emit_real_type(const char *str, i32 length) -{ - printf("!{ @%.*s $2 } ", length, str); - return 2; -} - -i32 -uxn_emit_str_type(const char *str, i32 length) -{ - printf("!{ @%.*s $2 } ", length, str); - return 2; -} - -i32 -uxn_emit_u8_type(const char *str, i32 length) -{ - printf("!{ @%.*s $1 } ", length, str); + if(local) + printf("!{ &%.*s $1 } ", length, str); + else + printf("!{ @%.*s $1 } ", length, str); return 1; } i32 -uxn_emit_i8_type(const char *str, i32 length) +uxn_emit_i16_type(const char *str, i32 length, bool local) { - printf("!{ @%.*s $1 } ", length, str); - return 1; -} - -i32 -uxn_emit_i16_type(const char *str, i32 length) -{ - printf("!{ @%.*s $2 } ", length, str); + if(local) + printf("!{ &%.*s $2 } ", length, str); + else + printf("!{ @%.*s $2 } ", length, str); return 2; } i32 -uxn_emit_u16_type(const char *str, i32 length) +uxn_emit_u16_type(const char *str, i32 length, bool local) { - printf("!{ @%.*s $2 } ", length, str); + if(local) + printf("!{ &%.*s $2 } ", length, str); + else + printf("!{ @%.*s $2 } ", length, str); return 2; } i32 -uxn_emit_i32_type(const char *str, i32 length) +uxn_emit_i32_type(const char *str, i32 length, bool local) { - printf("!{ @%.*s $4 } ", length, str); + if(local) + printf("!{ &%.*s $4 } ", length, str); + else + printf("!{ @%.*s $4 } ", length, str); return 4; } i32 -uxn_emit_u32_type(const char *str, i32 length) +uxn_emit_u32_type(const char *str, i32 length, bool local) { - printf("!{ @%.*s $4 } ", length, str); + if(local) + printf("!{ &%.*s $4 } ", length, str); + else + printf("!{ @%.*s $4 } ", length, str); return 4; } i32 -uxn_emit_f32_type(const char *str, i32 length) +uxn_emit_f32_type(const char *str, i32 length, bool local) { - printf("!{ @%.*s $4 } ", length, str); + if(local) + printf("!{ &%.*s $4 } ", length, str); + else + printf("!{ @%.*s $4 } ", length, str); return 4; } @@ -315,13 +310,23 @@ uxn_emit_byte(const char *str, i32 length) void uxn_emit_str(const char *str, i32 length) { - printf("\"%.*s ", length, str); + /* set a pointer to the string literal and then jump over it */ + printf(";{ #0002 ADD2 } !{ "); + + for (i32 i = 1; i < length - 1 ; i++) { + printf("#%02x ", str[i]); + } + + printf("#00 } "); } void -uxn_emit_constant(const char *str, i32 length) +uxn_emit_constant(const char *str, i32 length, bool local) { - printf(";%.*s STA2 ", length, str); + if(local) + printf(",/%.*s STR2 ", length, str); + else + printf(";%.*s STA2 ", length, str); } void @@ -355,9 +360,15 @@ uxn_emit_const() } void -uxn_emit_print() +uxn_emit_putchar() { - printf("print "); + printf("#18 DEO "); +} + +void +uxn_emit_getchar() +{ + printf("#12 DEI "); } void @@ -371,9 +382,12 @@ uxn_emit_close_paren() } void -uxn_emit_variable(Symbol *sym) +uxn_emit_variable(Symbol *sym, bool local) { - printf(";%.*s LDA2 ", sym->name_length, sym->name); + if(local) + printf(",/%.*s LDR2 ", sym->name_length, sym->name); + else + printf(";%.*s LDA2 ", sym->name_length, sym->name); } void @@ -509,6 +523,60 @@ uxn_emit_cast_str_to_real() { } +void +uxn_emit_sll() +{ + printf("#40 SFT SFT "); +} + +void +uxn_emit_srl() +{ + printf("SFT "); +} + +void +uxn_emit_xor() +{ + printf("EOR2 "); +} + +void +uxn_emit_mod() +{ + printf("DIV2k MUL2 SUB2 "); +} +void +uxn_emit_or() +{ + printf("ORA2 "); +} + +void +uxn_emit_and() +{ + printf("AND2 "); +} + +void +uxn_emit_print() +{ + printf("str/ "); +} + + +void +uxn_emit_jump() +{ + printf("?{ "); +} + +void +uxn_emit_patch_jump() +{ + printf("} "); +} + Emitter uxn_emitter() { @@ -555,6 +623,8 @@ uxn_emitter() uxn_emit_trait, uxn_emit_const, uxn_emit_print, + uxn_emit_putchar, + uxn_emit_getchar, uxn_emit_neg, uxn_emit_not, uxn_emit_open_paren, @@ -588,5 +658,13 @@ uxn_emitter() uxn_emit_cast_str_to_int, uxn_emit_cast_str_to_nat, uxn_emit_cast_str_to_real, + uxn_emit_sll, + uxn_emit_srl, + uxn_emit_xor, + uxn_emit_mod, + uxn_emit_and, + uxn_emit_or, + uxn_emit_jump, + uxn_emit_patch_jump, }; } diff --git a/lexer.c b/lexer.c index 34aa8b0..4078b9c 100644 --- a/lexer.c +++ b/lexer.c @@ -233,8 +233,10 @@ identifierType() return check_keyword(2, 1, "r", TOKEN_TYPE_PTR); case 'l': return check_keyword(2, 2, "ex", TOKEN_KEYWORD_PLEX); + case 'u': + return check_keyword(2, 5, "tchar", TOKEN_KEYWORD_PUTCHAR); case 'r': - return check_keyword(2, 3, "int", TOKEN_KEYWORD_PRINT); + return check_keyword(2, 3, "int", TOKEN_KEYWORD_PRINT); } } break; @@ -321,13 +323,17 @@ identifierType() } break; case 'g': - return check_keyword(1, 5, "lobal", TOKEN_KEYWORD_GLOBAL); + return check_keyword(1, 6, "etchar", TOKEN_KEYWORD_GETCHAR); case 'l': return check_keyword(1, 3, "oop", TOKEN_KEYWORD_LOOP); case 'd': return check_keyword(1, 1, "o", TOKEN_KEYWORD_DO); case 'v': return check_keyword(1, 3, "oid", TOKEN_TYPE_VOID); + case 'x': + return check_keyword(1, 2, "or", TOKEN_OPERATOR_XOR); + case 'm': + return check_keyword(1, 2, "od", TOKEN_OPERATOR_MOD); } return TOKEN_IDENTIFIER; @@ -426,9 +432,9 @@ next_token() case '=': return make_token(match('=') ? TOKEN_EQ_EQ : TOKEN_EQ); case '<': - return make_token(match('=') ? TOKEN_LTE : TOKEN_LT); + return make_token(match('=') ? TOKEN_LTE : match('<') ? TOKEN_SLL : TOKEN_LT); case '>': - return make_token(match('=') ? TOKEN_GTE : TOKEN_GT); + return make_token(match('=') ? TOKEN_GTE : match('>') ? TOKEN_SRL : TOKEN_GT); case '"': return string(); } @@ -504,10 +510,8 @@ token_type_to_string(TokenType type) return "KEYWORD_TRUE"; case TOKEN_KEYWORD_FALSE: return "KEYWORD_FALSE"; - case TOKEN_KEYWORD_GLOBAL: - return "KEYWORD_GLOBAL"; - case TOKEN_OPERATOR_NOT: - return "OPERATOR_NOT"; + case TOKEN_KEYWORD_GETCHAR: + return "KEYWORD_GETCHAR"; case TOKEN_OPERATOR_AND: return "OPERATOR_AND"; case TOKEN_OPERATOR_OR: diff --git a/lexer.h b/lexer.h index a3953c3..2a654ef 100644 --- a/lexer.h +++ b/lexer.h @@ -36,7 +36,6 @@ typedef enum { TOKEN_KEYWORD_USE, TOKEN_KEYWORD_INIT, TOKEN_KEYWORD_THIS, - TOKEN_KEYWORD_GLOBAL, TOKEN_KEYWORD_OPEN, TOKEN_KEYWORD_READ, TOKEN_KEYWORD_WRITE, @@ -47,10 +46,12 @@ typedef enum { TOKEN_KEYWORD_NIL, TOKEN_KEYWORD_TRUE, TOKEN_KEYWORD_FALSE, - TOKEN_KEYWORD_PRINT, - TOKEN_OPERATOR_NOT, + TOKEN_KEYWORD_PUTCHAR, + TOKEN_KEYWORD_GETCHAR, TOKEN_OPERATOR_AND, TOKEN_OPERATOR_OR, + TOKEN_OPERATOR_XOR, + TOKEN_OPERATOR_MOD, TOKEN_BANG, TOKEN_BANG_EQ, TOKEN_EQ, @@ -82,7 +83,10 @@ typedef enum { TOKEN_RBRACE, TOKEN_LBRACKET, TOKEN_RBRACKET, - TOKEN_ARROW_RIGHT + TOKEN_ARROW_RIGHT, + TOKEN_SLL, + TOKEN_SRL, + TOKEN_KEYWORD_PRINT } TokenType; typedef struct token_s Token; diff --git a/test/global.ul b/test/global.ul index e05fde6..446eb55 100755 --- a/test/global.ul +++ b/test/global.ul @@ -1,6 +1,3 @@ int i = 122; int j = 32; - -//function main() { - print((i - j) as str); -//} +putchar((i - j)); diff --git a/test/local.ul b/test/local.ul index 20386b5..2d112b6 100755 --- a/test/local.ul +++ b/test/local.ul @@ -2,5 +2,5 @@ function main() { int i = 122; int j = 32; - print((i - j)); // prints ascii `Z` + putchar((i - j)); // prints ascii `Z` }