diff --git a/Makefile b/Makefile index 108bfcd..20d823d 100644 --- a/Makefile +++ b/Makefile @@ -91,14 +91,14 @@ ifeq ($(BUILD_MODE), release) PLATFORM_SOURCE := $(ARCH_DIR)/main.c \ $(ARCH_DIR)/devices.c\ $(SRC_DIR)/tools/lexer.c \ - $(SRC_DIR)/tools/assembler/assembler.c - # $(SRC_DIR)/tools/compiler/compiler.c + $(SRC_DIR)/tools/assembler/assembler.c \ + $(SRC_DIR)/tools/compiler/compiler.c else PLATFORM_SOURCE := $(ARCH_DIR)/main.c \ $(ARCH_DIR)/devices.c \ $(SRC_DIR)/tools/lexer.c \ - $(SRC_DIR)/tools/assembler/assembler.c - # $(SRC_DIR)/tools/compiler/compiler.c + $(SRC_DIR)/tools/assembler/assembler.c \ + $(SRC_DIR)/tools/compiler/compiler.c endif # --- OBJECT FILES --- diff --git a/src/arch/linux/main.c b/src/arch/linux/main.c index a8e310f..9769b0b 100644 --- a/src/arch/linux/main.c +++ b/src/arch/linux/main.c @@ -1,4 +1,4 @@ -//#include "../../tools/compiler/compiler.h" +#include "../../tools/compiler/compiler.h" #include "../../tools/assembler/assembler.h" #include "../../vm/vm.h" #include "devices.h" diff --git a/src/tools/compiler/compiler.c b/src/tools/compiler/compiler.c index 8b350fd..b9ff6a5 100644 --- a/src/tools/compiler/compiler.c +++ b/src/tools/compiler/compiler.c @@ -11,6 +11,24 @@ #include #include +typedef struct { + Token current; + Token previous; +} Parser; + +Parser parser; + +static void advance() { + parser.previous = parser.current; + + for (;;) { + parser.current = next_token(); + if (parser.current.type != TOKEN_ERROR) break; + + printf("ERROR at line %d: %.*s\n", parser.current.line, parser.current.length, parser.current.start); + exit(1); + } +} void emit_op(VM *vm, u8 byte) { #ifdef DEBUG_PRINT @@ -33,6 +51,22 @@ void emit_u32(VM *vm, u32 value) { write_u32(vm, code, vm->cp, value); } +bool is_type() { + TokenType tt = parser.previous.type; + return tt == TOKEN_TYPE_PTR || tt == TOKEN_TYPE_I8 || + tt == TOKEN_TYPE_I16 || tt == TOKEN_TYPE_INT || + tt == TOKEN_TYPE_U8 || tt == TOKEN_TYPE_U16 || + tt == TOKEN_TYPE_NAT || tt == TOKEN_TYPE_REAL || + tt == TOKEN_TYPE_STR || tt == TOKEN_TYPE_BOOL; +} + +bool is_branch() { + TokenType tt = parser.previous.type; + return tt == TOKEN_KEYWORD_LOOP || tt == TOKEN_KEYWORD_IF || + tt == TOKEN_KEYWORD_ELSE || tt == TOKEN_KEYWORD_DO || + tt == TOKEN_KEYWORD_FOR; +} + Symbol *symbol_table_lookup(ScopeTable *table, const char *name, u32 length, i32 scope_ref) { SymbolTable st = table->scopes[scope_ref]; @@ -104,46 +138,47 @@ u32 get_ref(ScopeTable *st, const char *name, u32 length) { u32 get_ptr(Token token, ScopeTable *st) { if (token.type == TOKEN_IDENTIFIER) { - return get_ref(st, token.start, token.length); + return get_ref(st, parser.previous.start, parser.previous.length); } if (token.type == TOKEN_LITERAL_INT) { - return atoi(token.start); + return atoi(parser.previous.start); } if (token.type == TOKEN_LITERAL_NAT) { char *endptr; - u32 out = (u32)strtoul(token.start, &endptr, 10); - if (endptr == token.start || *endptr != '\0') { + u32 out = (u32)strtoul(parser.previous.start, &endptr, 10); + if (endptr == parser.previous.start || *endptr != '\0') { fprintf(stderr, "Invalid decimal literal at line %d: %.*s\n", token.line, - token.length, token.start); + parser.previous.length, parser.previous.start); exit(1); } return out; } fprintf(stderr, "Error: Not a pointer or symbol at line %d: %.*s\n", - token.line, token.length, token.start); + token.line, parser.previous.length, parser.previous.start); exit(1); } u32 get_reg(Token token, ScopeTable *st) { if (token.type == TOKEN_IDENTIFIER) { - return get_ref(st, token.start, token.length); + return get_ref(st, parser.previous.start, parser.previous.length); } fprintf(stderr, "Error: Not a symbol at line %d: %.*s\n", - token.line, token.length, token.start); + token.line, parser.previous.length, parser.previous.start); exit(1); } -Token next_token_is(TokenType type) { - Token token = next_token(); - if (token.type != type) { - printf("ERROR at line %d: %.*s\n", token.line, token.length, token.start); - exit(1); +static void next_token_is(TokenType type) { + if (parser.current.type == type) { + advance(); + return; } - return token; + + printf("Unexpected token at line %d: %.*s\n", parser.current.line, parser.current.length, parser.current.start); + exit(1); } /** @@ -158,10 +193,10 @@ bool parse_const(VM *vm, ScopeTable *st) { /** * Global . */ -bool define_global(VM *vm, ScopeTable *st, Token token_type) { +bool define_global(VM *vm, ScopeTable *st) { Symbol s; - switch (token_type.type) { + switch (parser.previous.type) { case TOKEN_TYPE_BOOL: s.type = BOOL; s.size = 1; @@ -203,14 +238,14 @@ bool define_global(VM *vm, ScopeTable *st, Token token_type) { return false; } - Token name = next_token_is(TOKEN_IDENTIFIER); - if (name.length > MAX_SYMBOL_NAME_LENGTH) { + next_token_is(TOKEN_IDENTIFIER); + if (parser.previous.length > MAX_SYMBOL_NAME_LENGTH) { return false; } - memcpy(s.name, name.start, name.length); - s.name_length = name.length; - s.name[name.length] = '\0'; + memcpy(s.name, parser.previous.start, parser.previous.length); + s.name_length = parser.previous.length; + s.name[parser.previous.length] = '\0'; u32 addr = vm->mp; s.ref = addr; @@ -218,8 +253,8 @@ bool define_global(VM *vm, ScopeTable *st, Token token_type) { next_token_is(TOKEN_EQ); - Token value = next_token(); - switch (value.type) { + advance(); + switch (parser.previous.type) { case TOKEN_KEYWORD_TRUE: { u32 addr = vm->mp; write_u8(vm, memory, addr, 1); @@ -237,7 +272,7 @@ bool define_global(VM *vm, ScopeTable *st, Token token_type) { break; } case TOKEN_LITERAL_INT: { - i32 out = atoi(value.start); + i32 out = atoi(parser.previous.start); u32 addr = vm->mp; write_u32(vm, memory, addr, out); @@ -248,9 +283,9 @@ bool define_global(VM *vm, ScopeTable *st, Token token_type) { } case TOKEN_LITERAL_NAT: { char *endptr; - u32 out = (u32)strtoul(value.start, &endptr, 10); - if (endptr == value.start || *endptr != '\0') { - fprintf(stderr, "Invalid decimal literal: %s\n", value.start); + u32 out = (u32)strtoul(parser.previous.start, &endptr, 10); + if (endptr == parser.previous.start || *endptr != '\0') { + fprintf(stderr, "Invalid decimal literal: %s\n", parser.previous.start); exit(1); } @@ -262,7 +297,7 @@ bool define_global(VM *vm, ScopeTable *st, Token token_type) { break; } case TOKEN_LITERAL_REAL: { - r32 out = float_to_real(atof(value.start)); + r32 out = float_to_real(atof(parser.previous.start)); u32 addr = vm->mp; write_u32(vm, memory, addr, out); @@ -272,16 +307,16 @@ bool define_global(VM *vm, ScopeTable *st, Token token_type) { break; } case TOKEN_LITERAL_STR: { - const char *src = value.start; + const char *src = parser.previous.start; i32 len = 0; i32 i = 0; - while (i < value.length) { + while (i < parser.previous.length) { char c = src[i++]; if (c == '"') { continue; } - if (c == '\\' && i < value.length) { + if (c == '\\' && i < parser.previous.length) { switch (src[i++]) { case 'n': c = '\n'; @@ -326,10 +361,10 @@ bool define_global(VM *vm, ScopeTable *st, Token token_type) { /** * Var . */ -void define_var(ScopeTable *st, Token regType) { +void define_var(ScopeTable *st) { Symbol s; s.scope = VAR; - switch (regType.type) { + switch (parser.previous.type) { case TOKEN_KEYWORD_PLEX: { s.type = PLEX; s.size = 4; /* not really this type, pointer alias which is 4 */ @@ -381,30 +416,24 @@ void define_var(ScopeTable *st, Token regType) { break; } default: - printf("ERROR at line %d: %.*s\n", regType.line, regType.length, - regType.start); + printf("Unknown type ERROR at line %d: %.*s\n", parser.previous.line, parser.previous.length, + parser.previous.start); exit(1); } - Token name = next_token_is(TOKEN_IDENTIFIER); - if (name.length > MAX_SYMBOL_NAME_LENGTH) { - printf("VARIABLE NAME TOO LONG at line %d: %.*s\n", regType.line, - regType.length, regType.start); + next_token_is(TOKEN_IDENTIFIER); + if (parser.previous.length > MAX_SYMBOL_NAME_LENGTH) { + printf("VARIABLE NAME TOO LONG at line %d: %.*s\n", parser.previous.line, + parser.previous.length, parser.previous.start); exit(1); } - memcpy(s.name, name.start, name.length); - s.name[name.length] = '\0'; - s.name_length = name.length; + memcpy(s.name, parser.previous.start, parser.previous.length); + s.name[parser.previous.length] = '\0'; + s.name_length = parser.previous.length; - Token next = next_token(); - if (next.type == TOKEN_SEMICOLON) { - s.ref = st->current_reg++; - } else { - printf("Unexpected token ERROR at line %d: %.*s\n", regType.line, regType.length, - regType.start); - exit(1); - } + // Token next = next_token(); + s.ref = st->current_reg++; symbol_table_add(st, s); } @@ -430,15 +459,15 @@ void define_function(VM *vm, ScopeTable *st) { st->last_used_registers[st->reg_count++] = st->current_reg; st->current_reg = 0; - Token name = next_token_is(TOKEN_IDENTIFIER); - if (name.length > MAX_SYMBOL_NAME_LENGTH) { - printf("FUNCITON NAME TOO LONG at line %d: %.*s\n", name.line, name.length, - name.start); + next_token_is(TOKEN_IDENTIFIER); + if (parser.previous.length > MAX_SYMBOL_NAME_LENGTH) { + printf("FUNCITON NAME TOO LONG at line %d: %.*s\n", parser.previous.line, parser.previous.length, + parser.previous.start); exit(1); } - memcpy(s.name, name.start, name.length); - s.name[name.length] = '\0'; - s.name_length = name.length; + memcpy(s.name, parser.previous.start, parser.previous.length); + s.name[parser.previous.length] = '\0'; + s.name_length = parser.previous.length; next_token_is(TOKEN_LPAREN); @@ -448,22 +477,29 @@ void define_function(VM *vm, ScopeTable *st) { st->scopes[st->count].parent = st->scope_ref; st->scope_ref = (i32)st->count; - Token next = next_token(); - while (next.type != TOKEN_RPAREN) { - define_var(st, next); - next = next_token(); - if (next.type == TOKEN_COMMA) { - next = next_token(); + advance(); + while (parser.previous.type != TOKEN_RPAREN) { + define_var(st); + advance(); + if (parser.previous.type == TOKEN_COMMA) { + advance(); continue; - } else if (next.type == TOKEN_RPAREN) { + } else if (parser.previous.type == TOKEN_RPAREN) { break; } else { - printf("ERROR at line %d: %.*s\n", next.line, next.length, next.start); + printf("Unknown argument type ERROR at line %d: %.*s\n", parser.previous.line, parser.previous.length, parser.previous.start); exit(1); } } s.ref = vm->cp; + advance(); + if (parser.current.type == TOKEN_RBRACE) { + s.return_type = TOKEN_TYPE_VOID; + } else { + s.return_type = parser.current.type; + } + st->scope_ref = temp; // need to add to the parents scope symbol_table_add(st, s); st->scope_ref = (i32)st->count; @@ -480,142 +516,231 @@ void define_branch(VM *vm, ScopeTable *st) { s.scope = LOCAL; s.type = VOID; - Token name = next_token_is(TOKEN_IDENTIFIER); - if (name.length > MAX_SYMBOL_NAME_LENGTH) { - printf("BRANCH NAME TOO LONG at line %d: %.*s\n", name.line, name.length, - name.start); + next_token_is(TOKEN_IDENTIFIER); + if (parser.previous.length > MAX_SYMBOL_NAME_LENGTH) { + printf("BRANCH NAME TOO LONG at line %d: %.*s\n", parser.previous.line, + parser.previous.length, + parser.previous.start); exit(1); } - memcpy(s.name, name.start, name.length); - s.name_length = name.length; - s.name[name.length] = '\0'; + memcpy(s.name, parser.previous.start, parser.previous.length); + s.name_length = parser.previous.length; + s.name[parser.previous.length] = '\0'; s.ref = vm->cp; symbol_table_add(st, s); } -int get_instruction_byte_size(const char *opname) { +void advance_op(VM *vm, ScopeTable *st, char *op_name); +void parse_exit(VM *vm, ScopeTable *st, char *op_name); +void parse_call(VM *vm, ScopeTable *st, char *op_name); +void parse_syscall(VM *vm, ScopeTable *st, char *op_name); +void emit_exit(VM *vm, ScopeTable *st, char *op_name); +void emit_call(VM *vm, ScopeTable *st, char *op_name); +void emit_syscall(VM *vm, ScopeTable *st, char *op_name); +void emit_reg_reg(VM *vm, ScopeTable *st, char *op_name); - if (strcmp(opname, "return") == 0) { - return 2; - } +OpDef operations[] = { + [OP_EXIT] = {5, parse_exit, emit_exit, "exit"}, + [OP_CALL] = {-1, parse_call, emit_call, "call"}, + [OP_RETURN] = {3, nil, nil, "return"}, + [OP_SYSCALL] = {-1, parse_syscall, emit_syscall, "syscall"}, + [OP_LOAD_IMM] = {6, advance_op, nil, "load_immediate"}, + [OP_LOAD_IND_8] = {3, advance_op, nil, "load_indirect_8" }, + [OP_LOAD_IND_16] = {3, advance_op, nil, "load_indirect_16"}, + [OP_LOAD_IND_32] = {3, advance_op, nil, "load_indirect_32"}, + [OP_LOAD_ABS_8] = {6, advance_op, nil, "load_absolute_8" }, + [OP_LOAD_ABS_16] = {6, advance_op, nil, "load_absolute_16"}, + [OP_LOAD_ABS_32] = {6, advance_op, nil, "load_absolute_32"}, + [OP_LOAD_OFF_8] = {7, advance_op, nil, "load_offset_8"}, + [OP_LOAD_OFF_16] = {7, advance_op, nil, "load_offset_16"}, + [OP_LOAD_OFF_32] = {7, advance_op, nil, "load_offset_32"}, + [OP_STORE_ABS_8] = {6, advance_op, nil, "store_absolute_8" }, + [OP_STORE_ABS_16] = {6, advance_op, nil, "store_absolute_16"}, + [OP_STORE_ABS_32] = {6, advance_op, nil, "store_absolute_32"}, + [OP_STORE_IND_8] = {3, advance_op, nil, "store_indirect_8" }, + [OP_STORE_IND_16] = {3, advance_op, nil, "store_indirect_16"}, + [OP_STORE_IND_32] = {3, advance_op, nil, "store_indirect_32"}, + [OP_STORE_OFF_8] = {7, advance_op, nil, "store_offset_8"}, + [OP_STORE_OFF_16] = {7, advance_op, nil, "store_offset_16"}, + [OP_STORE_OFF_32] = {7, advance_op, nil, "store_offset_32"}, + [OP_MALLOC] = {3, advance_op, emit_reg_reg, "malloc"}, + [OP_MEMSET_8] = {3, advance_op, nil, "memset_8" }, + [OP_MEMSET_16] = {3, advance_op, nil, "memset_16"}, + [OP_MEMSET_32] = {3, advance_op, nil, "memset_32"}, + [OP_REG_MOV] = {3, advance_op, emit_reg_reg, "register_move"}, + [OP_ADD_INT] = {4, advance_op, nil, "add_int"}, + [OP_SUB_INT] = {4, advance_op, nil, "sub_int"}, + [OP_MUL_INT] = {4, advance_op, nil, "mul_int"}, + [OP_DIV_INT] = {4, advance_op, nil, "div_int"}, + [OP_ABS_INT] = {3, advance_op, emit_reg_reg, "abs_int"}, + [OP_NEG_INT] = {3, advance_op, emit_reg_reg, "neg_int"}, + [OP_ADD_NAT] = {4, advance_op, nil, "add_nat"}, + [OP_SUB_NAT] = {4, advance_op, nil, "sub_nat"}, + [OP_MUL_NAT] = {4, advance_op, nil, "mul_nat"}, + [OP_DIV_NAT] = {4, advance_op, nil, "div_nat"}, + [OP_ABS_NAT] = {3, advance_op, emit_reg_reg, "abs_nat"}, + [OP_NEG_NAT] = {3, advance_op, emit_reg_reg, "neg_nat"}, + [OP_ADD_REAL] = {4, advance_op, nil, "add_real"}, + [OP_SUB_REAL] = {4, advance_op, nil, "sub_real"}, + [OP_MUL_REAL] = {4, advance_op, nil, "mul_real"}, + [OP_DIV_REAL] = {4, advance_op, nil, "div_real"}, + [OP_ABS_REAL] = {3, advance_op, emit_reg_reg, "abs_real"}, + [OP_NEG_REAL] = {3, advance_op, emit_reg_reg, "neg_real"}, + [OP_INT_TO_REAL] = {3, advance_op, emit_reg_reg, "int_to_real"}, + [OP_INT_TO_NAT] = {3, advance_op, emit_reg_reg, "int_to_nat"}, + [OP_NAT_TO_REAL] = {3, advance_op, emit_reg_reg, "nat_to_real"}, + [OP_NAT_TO_INT] = {3, advance_op, emit_reg_reg, "nat_to_int"}, + [OP_REAL_TO_INT] = {3, advance_op, emit_reg_reg, "real_to_int"}, + [OP_REAL_TO_NAT] = {3, advance_op, emit_reg_reg, "real_to_nat"}, + [OP_BIT_SHIFT_LEFT] = {4, advance_op, nil, "bit_shift_left" }, + [OP_BIT_SHIFT_RIGHT] = {4, advance_op, nil, "bit_shift_right" }, + [OP_BIT_SHIFT_R_EXT] = {4, advance_op, nil, "bit_shift_r_ext" }, + [OP_BAND] = {4, advance_op, nil, "bit_and" }, + [OP_BOR] = {4, advance_op, nil, "bit_or" }, + [OP_BXOR] = {4, advance_op, nil, "bit_xor" }, + [OP_JMP] = {5, advance_op, nil, "jump"}, + [OP_JMPF] = {5, advance_op, nil, "jump_if_flag"}, + [OP_JEQ_INT] = {7, advance_op, nil, "jump_eq_int"}, + [OP_JNEQ_INT] = {7, advance_op, nil, "jump_neq_int"}, + [OP_JGT_INT] = {7, advance_op, nil, "jump_gt_int"}, + [OP_JLT_INT] = {7, advance_op, nil, "jump_lt_int"}, + [OP_JLE_INT] = {7, advance_op, nil, "jump_le_int"}, + [OP_JGE_INT] = {7, advance_op, nil, "jump_ge_int"}, + [OP_JEQ_NAT] = {7, advance_op, nil, "jump_eq_nat"}, + [OP_JNEQ_NAT] = {7, advance_op, nil, "jump_neq_nat"}, + [OP_JGT_NAT] = {7, advance_op, nil, "jump_gt_nat"}, + [OP_JLT_NAT] = {7, advance_op, nil, "jump_lt_nat"}, + [OP_JLE_NAT] = {7, advance_op, nil, "jump_le_nat"}, + [OP_JGE_NAT] = {7, advance_op, nil, "jump_ge_nat"}, + [OP_JEQ_REAL] = {7, advance_op, nil, "jump_eq_real"}, + [OP_JNEQ_REAL] = {7, advance_op, nil, "jump_neq_real"}, + [OP_JGE_REAL] = {7, advance_op, nil, "jump_gt_real"}, + [OP_JGT_REAL] = {7, advance_op, nil, "jump_lt_real"}, + [OP_JLT_REAL] = {7, advance_op, nil, "jump_le_real"}, + [OP_JLE_REAL] = {7, advance_op, nil, "jump_ge_real"}, + [OP_STRLEN] = {3, advance_op, emit_reg_reg, "string_length"}, + [OP_STREQ] = {0, advance_op, nil, "string_eq"}, + [OP_STRCAT] = {0, advance_op, nil, "string_concat"}, + [OP_STR_GET_CHAR] = {0, advance_op, nil, "string_get_char"}, + [OP_STR_FIND_CHAR] = {0, advance_op, nil, "string_find_char"}, + [OP_STR_SLICE] = {0, advance_op, nil, "string_slice"}, + [OP_INT_TO_STRING] = {3, advance_op, emit_reg_reg, "int_to_string"}, + [OP_NAT_TO_STRING] = {3, advance_op, emit_reg_reg, "nat_to_string"}, + [OP_REAL_TO_STRING] = {3, advance_op, emit_reg_reg, "real_to_string" }, + [OP_STRING_TO_INT] = {0, advance_op, nil, "string_to_int"}, + [OP_STRING_TO_NAT] = {0, advance_op, nil, "string_to_nat"}, + [OP_STRING_TO_REAL] = {0, advance_op, nil, "string_to_real"}, +}; - if (strcmp(opname, "neg_int") == 0 || - strcmp(opname, "abs_int") == 0 || - strcmp(opname, "neg_nat") == 0 || - strcmp(opname, "abs_nat") == 0 || - strcmp(opname, "neg_real") == 0 || - strcmp(opname, "abs_real") == 0 || - strcmp(opname, "int_to_string") == 0 || - strcmp(opname, "load_indirect_8") == 0 || - strcmp(opname, "nat_to_string") == 0 || - strcmp(opname, "load_indirect_16") == 0 || - strcmp(opname, "real_to_string") == 0 || - strcmp(opname, "load_indirect_32") == 0 || - strcmp(opname, "int_to_real") == 0 || - strcmp(opname, "store_indirect_8") == 0 || - strcmp(opname, "nat_to_real") == 0 || - strcmp(opname, "store_indirect_16") == 0 || - strcmp(opname, "real_to_int") == 0 || - strcmp(opname, "store_indirect_32") == 0 || - strcmp(opname, "real_to_nat") == 0 || strcmp(opname, "nat_to_int") == 0 || - strcmp(opname, "int_to_nat") == 0 || - strcmp(opname, "string_length") == 0 || strcmp(opname, "memset") == 0 || - strcmp(opname, "memset") == 0 || strcmp(opname, "memset_8") == 0 || - strcmp(opname, "memset_16") == 0 || - strcmp(opname, "register_move") == 0 || strcmp(opname, "malloc") == 0) { - return 3; - } - - if (strcmp(opname, "add_int") == 0 || strcmp(opname, "sub_int") == 0 || - strcmp(opname, "mul_int") == 0 || strcmp(opname, "div_int") == 0 || - strcmp(opname, "add_nat") == 0 || strcmp(opname, "sub_nat") == 0 || - strcmp(opname, "mul_nat") == 0 || strcmp(opname, "div_nat") == 0 || - strcmp(opname, "add_real") == 0 || strcmp(opname, "sub_real") == 0 || - strcmp(opname, "bit_shift_left") == 0 || - strcmp(opname, "bit_shift_right") == 0 || - strcmp(opname, "bit_shift_r_ext") == 0 || - strcmp(opname, "bit_and") == 0 || strcmp(opname, "bit_or") == 0 || - strcmp(opname, "bit_xor") == 0 || strcmp(opname, "mul_real") == 0 || - strcmp(opname, "div_real") == 0) { - return 4; - } - - if (strcmp(opname, "halt") == 0 || strcmp(opname, "jump_if_flag") == 0 || - strcmp(opname, "jump") == 0) { - return 5; - } - - if (strcmp(opname, "load_absolute_32") == 0 || - strcmp(opname, "load_immediate") == 0 || - strcmp(opname, "load_address") == 0 || - strcmp(opname, "load_absolute_16") == 0 || - strcmp(opname, "load_absolute_8") == 0 || - strcmp(opname, "store_absolute_32") == 0 || - strcmp(opname, "store_absolute_8") == 0 || - strcmp(opname, "store_absolute_16") == 0) { - return 6; - } - - if (strcmp(opname, "jump_eq_int") == 0 || - strcmp(opname, "jump_neq_int") == 0 || - strcmp(opname, "jump_gt_int") == 0 || - strcmp(opname, "jump_lt_int") == 0 || - strcmp(opname, "jump_le_int") == 0 || - strcmp(opname, "jump_ge_int") == 0 || - strcmp(opname, "jump_eq_nat") == 0 || - strcmp(opname, "jump_neq_nat") == 0 || - strcmp(opname, "jump_gt_nat") == 0 || - strcmp(opname, "jump_lt_nat") == 0 || - strcmp(opname, "jump_le_nat") == 0 || - strcmp(opname, "jump_ge_nat") == 0 || - strcmp(opname, "jump_eq_real") == 0 || - strcmp(opname, "jump_neq_real") == 0 || - strcmp(opname, "jump_gt_real") == 0 || - strcmp(opname, "jump_lt_real") == 0 || - strcmp(opname, "jump_le_real") == 0 || - strcmp(opname, "jump_ge_real") == 0 || - strcmp(opname, "store_offset_8") == 0 || - strcmp(opname, "store_offset_16") == 0 || - strcmp(opname, "store_offset_32") == 0 || - strcmp(opname, "load_offset_8") == 0 || - strcmp(opname, "load_offset_16") == 0 || - strcmp(opname, "load_offset_32") == 0) { - return 7; +i32 get_instruction_byte_size(const char *opname) { + /* we could speed this up with a hash map, but this is fine for now */ + for (i32 i = 0; i < OP_MAX_OPCODE; i++) { + OpDef op = operations[i]; + if (strcmp(opname, op.to_str) == 0) { + return op.instruction_byte_size; + } } fprintf(stderr, "Unknown opcode for sizing: %s\n", opname); exit(-1); } -#define FAKE_OP(op) \ - } else if (strleq(token.start, op, token.length)) { \ - do { \ - while (token.type != TOKEN_SEMICOLON) { \ - token = next_token(); \ - } \ - /*printf("code[%d]=%s\n %d + %d = %d\n", vm->cp, op, \ - * get_instruction_byte_size(op), vm->cp, vm->cp + \ - * get_instruction_byte_size(op)); */ \ - vm->cp += get_instruction_byte_size(op); \ - } while (0); +Opcode get_opcode(char *op_name) { + for (i32 i = 0; i < OP_MAX_OPCODE; i++) { + OpDef op = operations[i]; + if (strcmp(op_name, op.to_str) == 0) { + return ((Opcode)(i)); + } + } + return OP_MAX_OPCODE; +} + +void advance_op(VM *vm, ScopeTable *st, char *op_name) { + USED(st); + while (parser.previous.type != TOKEN_SEMICOLON) { + advance(); + } + vm->cp += get_instruction_byte_size(op_name); +} + +void parse_exit(VM *vm, ScopeTable *st, char *op_name) { + USED(op_name); + USED(st); + vm->cp++; + + advance(); + vm->cp += 4; + +#ifdef DEBUG_PRINT + printf("code[%d] = exit\n", vm->cp); +#endif + + next_token_is(TOKEN_SEMICOLON); +} + +void parse_call(VM *vm, ScopeTable *st, char *op_name) { + USED(op_name); + vm->cp++; + + next_token_is(TOKEN_IDENTIFIER); + vm->cp += 4; + + vm->cp++; + next_token_is(TOKEN_LPAREN); + advance(); + while (parser.previous.type != TOKEN_RPAREN) { + get_reg(parser.previous, st); + vm->cp++; + advance(); + } + + advance(); + if (parser.previous.type == TOKEN_SEMICOLON) { + vm->cp++; + } else { + advance(); + get_reg(parser.previous, st); + vm->cp++; + } +#ifdef DEBUG_PRINT + printf("code[%d] = call\n", vm->cp); +#endif +} + +void parse_syscall(VM *vm, ScopeTable *st, char *op_name) { + USED(op_name); + vm->cp++; + + advance(); + vm->cp += 4; + + advance(); + while (parser.previous.type != TOKEN_SEMICOLON) { + get_reg(parser.previous, st); + vm->cp++; + advance(); + } +#ifdef DEBUG_PRINT + printf("code[%d] = syscall\n", vm->cp); +#endif +} /** * Build the symbol table and calculate the types/size/offsets of all values. */ void build_symbol_table(VM *vm, char *source, ScopeTable *st) { - Token token; init_lexer(source); do { - token = next_token(); - if (token.type == TOKEN_ERROR) { - printf("ERROR at line %d: %.*s\n", token.line, token.length, token.start); + advance(); + if (parser.previous.type == TOKEN_ERROR) { + printf("Generic ERROR during symbol table pass at line %d: %.*s\n", parser.previous.line, parser.previous.length, parser.previous.start); exit(1); } - if (token.type != TOKEN_EOF) { + if (parser.previous.type != TOKEN_EOF) { - if (token.type == TOKEN_LBRACE) { + if (parser.previous.type == TOKEN_LBRACE) { st->count++; st->scopes[st->count].parent = st->scope_ref; st->scope_ref = (i32)st->count; @@ -623,7 +748,7 @@ void build_symbol_table(VM *vm, char *source, ScopeTable *st) { continue; } - if (token.type == TOKEN_RBRACE) { + if (parser.previous.type == TOKEN_RBRACE) { i32 current_scope = st->scope_ref; i32 parent = st->scopes[current_scope].parent; if (parent < 0) parent = 0; @@ -632,38 +757,32 @@ void build_symbol_table(VM *vm, char *source, ScopeTable *st) { continue; } - if (token.type == TOKEN_KEYWORD_FN) { + if (parser.previous.type == TOKEN_KEYWORD_FN) { define_function(vm, st); continue; } - if (token.type == TOKEN_KEYWORD_PLEX) { + if (parser.previous.type == TOKEN_KEYWORD_PLEX) { define_plex(vm, st); continue; } - if (token.type == TOKEN_TYPE_PTR || token.type == TOKEN_TYPE_I8 || - token.type == TOKEN_TYPE_I16 || token.type == TOKEN_TYPE_INT || - token.type == TOKEN_TYPE_U8 || token.type == TOKEN_TYPE_U16 || - token.type == TOKEN_TYPE_NAT || token.type == TOKEN_TYPE_REAL || - token.type == TOKEN_TYPE_STR || token.type == TOKEN_TYPE_BOOL) { + if (is_type()) { if (st->depth > 0) { - define_var(st, token); + define_var(st); next_token_is(TOKEN_SEMICOLON); } else { - define_global(vm, st, token); + define_global(vm, st); } continue; } - if (token.type == TOKEN_KEYWORD_LOOP || token.type == TOKEN_KEYWORD_IF || - token.type == TOKEN_KEYWORD_ELSE || token.type == TOKEN_KEYWORD_DO || - token.type == TOKEN_KEYWORD_FOR) { + if (is_branch()) { define_branch(vm, st); continue; } - if (token.type == TOKEN_KEYWORD_RETURN) { + if (parser.previous.type == TOKEN_KEYWORD_RETURN) { vm->cp++; Token next = next_token(); @@ -675,190 +794,71 @@ void build_symbol_table(VM *vm, char *source, ScopeTable *st) { get_reg(next, st); vm->cp++; + + next = next_token(); + if (next.type == TOKEN_SEMICOLON) { + /* assume it is not a heap value */ + vm->cp++; + continue; + } + + vm->cp++; next_token_is(TOKEN_SEMICOLON); continue; } #ifdef DEBUG_PRINT - printf("-- %.*s --\n", token.length, token.start); + printf("-- %.*s --\n", parser.previous.length, parser.previous.start); #endif - if (token.type == TOKEN_IDENTIFIER) { - /* check to see if it is an opcode first */ - if (strleq(token.start, "exit", token.length)) { + if (parser.previous.type == TOKEN_IDENTIFIER) { - vm->cp++; - - next_token(); - vm->cp += 4; - -#ifdef DEBUG_PRINT - printf("code[%d] = exit\n", vm->cp); -#endif - - next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "call", token.length)) { - - vm->cp++; - - next_token_is(TOKEN_IDENTIFIER); - vm->cp += 4; - - vm->cp++; - Token next = next_token_is(TOKEN_LPAREN); - next = next_token(); - while (next.type != TOKEN_RPAREN) { - get_reg(next, st); - vm->cp++; - next = next_token(); + for (i32 i = 0; i < OP_MAX_OPCODE; i++) { + OpDef op = operations[i]; + if (strleq(parser.previous.start, op.to_str, parser.previous.length)) { + op.parse_symbol(vm, st, op.to_str); } + } - next = next_token(); - if (next.type == TOKEN_SEMICOLON) { - vm->cp++; - } else { - next = next_token(); - get_reg(next, st); - vm->cp++; - } -#ifdef DEBUG_PRINT - printf("code[%d] = call\n", vm->cp); -#endif - continue; - } else if (strleq(token.start, "syscall", token.length)) { + /* special because we are reusing load_immediate */ + if (strleq(parser.previous.start, "load_address", parser.previous.length)) { + while (parser.previous.type != TOKEN_SEMICOLON) { + advance(); + } - vm->cp++; - - Token next = next_token(); - vm->cp += 4; - - next = next_token(); - while (next.type != TOKEN_SEMICOLON) { - get_reg(next, st); - vm->cp++; - next = next_token(); - } -#ifdef DEBUG_PRINT - printf("code[%d] = syscall\n", vm->cp); -#endif - continue; - FAKE_OP("load_immediate") - FAKE_OP("load_address") - FAKE_OP("malloc") - FAKE_OP("memset_8") - FAKE_OP("memset_16") - FAKE_OP("memset_32") - FAKE_OP("load_offset_8") - FAKE_OP("load_offset_16") - FAKE_OP("load_offset_32") - FAKE_OP("load_indirect_8") - FAKE_OP("load_indirect_16") - FAKE_OP("load_indirect_32") - FAKE_OP("load_absolute_8") - FAKE_OP("load_absolute_16") - FAKE_OP("load_absolute_32") - FAKE_OP("store_absolute_8") - FAKE_OP("store_absolute_16") - FAKE_OP("store_absolute_32") - FAKE_OP("store_indirect_8") - FAKE_OP("store_indirect_16") - FAKE_OP("store_indirect_32") - FAKE_OP("store_offset_8") - FAKE_OP("store_offset_16") - FAKE_OP("store_offset_32") - FAKE_OP("register_move") - FAKE_OP("add_int") - FAKE_OP("sub_int") - FAKE_OP("mul_int") - FAKE_OP("div_int") - FAKE_OP("abs_int") - FAKE_OP("neg_int") - FAKE_OP("add_nat") - FAKE_OP("sub_nat") - FAKE_OP("mul_nat") - FAKE_OP("div_nat") - FAKE_OP("abs_nat") - FAKE_OP("neg_nat") - FAKE_OP("add_real") - FAKE_OP("sub_real") - FAKE_OP("mul_real") - FAKE_OP("div_real") - FAKE_OP("abs_real") - FAKE_OP("neg_real") - FAKE_OP("int_to_real") - FAKE_OP("nat_to_real") - FAKE_OP("real_to_int") - FAKE_OP("real_to_nat") - FAKE_OP("bit_shift_left") - FAKE_OP("bit_shift_right") - FAKE_OP("bit_shift_r_ext") - FAKE_OP("bit_and") - FAKE_OP("bit_or") - FAKE_OP("bit_xor") - FAKE_OP("jump") - FAKE_OP("jump_if_flag") - FAKE_OP("jump_eq_int") - FAKE_OP("jump_neq_int") - FAKE_OP("jump_gt_int") - FAKE_OP("jump_lt_int") - FAKE_OP("jump_le_int") - FAKE_OP("jump_ge_int") - FAKE_OP("jump_eq_nat") - FAKE_OP("jump_neq_nat") - FAKE_OP("jump_gt_nat") - FAKE_OP("jump_lt_nat") - FAKE_OP("jump_le_nat") - FAKE_OP("jump_ge_nat") - FAKE_OP("jump_eq_real") - FAKE_OP("jump_neq_real") - FAKE_OP("jump_ge_real") - FAKE_OP("jump_gt_real") - FAKE_OP("jump_lt_real") - FAKE_OP("jump_le_real") - FAKE_OP("string_length") - FAKE_OP("int_to_string") - FAKE_OP("nat_to_string") - FAKE_OP("real_to_string") - FAKE_OP("string_eq") - FAKE_OP("string_concat") - FAKE_OP("string_get_char") - FAKE_OP("string_find_char") - FAKE_OP("string_slice") - FAKE_OP("string_to_int") - FAKE_OP("string_to_nat") - FAKE_OP("string_to_real") + vm->cp += 6; } else { /* some other identifier */ - printf("Unknown id at line %d: %.*s\n", token.line, token.length, - token.start); + printf("Unknown id at line %d: %.*s\n", parser.previous.line, + parser.previous.length, + parser.previous.start); exit(1); } } } - } while (token.type != TOKEN_EOF); + } while (parser.previous.type != TOKEN_EOF); } /** * 2nd pass, emit the bytecode */ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { - Token token; init_lexer(source); do { - token = next_token(); - if (token.type == TOKEN_ERROR) { - printf("ERROR at line %d: %.*s\n", token.line, token.length, token.start); + advance(); + if (parser.previous.type == TOKEN_ERROR) { + printf("Generic ERROR during bytecode emit at line %d: %.*s\n", parser.previous.line, parser.previous.length, parser.previous.start); break; } - if (token.type != TOKEN_EOF) { + if (parser.previous.type != TOKEN_EOF) { - if (token.type == TOKEN_LBRACE) { + if (parser.previous.type == TOKEN_LBRACE) { st->count++; st->scopes[st->count].parent = st->scope_ref; st->scope_ref = (i32)st->count; continue; } - if (token.type == TOKEN_RBRACE) { + if (parser.previous.type == TOKEN_RBRACE) { i32 current_scope = st->scope_ref; i32 parent = st->scopes[current_scope].parent; if (parent < 0) parent = 0; @@ -866,169 +866,75 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { continue; } - if (token.type == TOKEN_KEYWORD_FN) { + if (parser.previous.type == TOKEN_KEYWORD_FN) { /* ignore, already processed */ - Token next = next_token(); - while (next.type != TOKEN_RPAREN) { - next = next_token(); + advance(); + while (parser.previous.type != TOKEN_RPAREN) { + advance(); } continue; } - if (token.type == TOKEN_TYPE_PTR || token.type == TOKEN_TYPE_I8 || - token.type == TOKEN_TYPE_I16 || token.type == TOKEN_TYPE_INT || - token.type == TOKEN_TYPE_U8 || token.type == TOKEN_TYPE_U16 || - token.type == TOKEN_TYPE_NAT || token.type == TOKEN_TYPE_REAL || - token.type == TOKEN_TYPE_STR) { + if (is_type()) { if (st->depth > 0) { /* ignore, local already processed */ - next_token(); /* type */ - next_token(); /* var */ - next_token(); /* reg */ - next_token(); /* ; */ + advance(); /* type */ + advance(); /* var */ + advance(); /* reg */ + advance(); /* ; */ } else { /* ignore, global already processed */ - next_token(); /* type */ - next_token(); /* var */ - next_token(); /* eq */ - next_token(); /* value */ - next_token(); /* ; */ + advance(); /* type */ + advance(); /* var */ + advance(); /* eq */ + advance(); /* value */ + advance(); /* ; */ } continue; } - if (token.type == TOKEN_KEYWORD_LOOP || token.type == TOKEN_KEYWORD_IF || - token.type == TOKEN_KEYWORD_ELSE || token.type == TOKEN_KEYWORD_DO || - token.type == TOKEN_KEYWORD_FOR) { + if (is_branch()) { /* ignore, already processed */ - next_token(); /* id */ + advance(); /* id */ } - if (token.type == TOKEN_KEYWORD_RETURN) { - emit_op(vm, OP_RETURN); + if (parser.previous.type == TOKEN_KEYWORD_RETURN) { vm->cp++; - Token next = next_token(); - if (next.type == TOKEN_SEMICOLON) { + advance(); + if (parser.previous.type == TOKEN_SEMICOLON) { /* put 0xFF as return register */ - emit_byte(vm, 0xFF); vm->cp++; continue; } - u32 reg = get_reg(next, st); - emit_byte(vm, reg); + get_reg(parser.previous, st); vm->cp++; + + advance(); + if (parser.previous.type == TOKEN_SEMICOLON) { + /* assume it is not a heap value */ + vm->cp++; + continue; + } + + vm->cp++; next_token_is(TOKEN_SEMICOLON); continue; } #ifdef DEBUG_PRINT - printf("-- %.*s --\n", token.length, token.start); + printf("-- %.*s --\n", parser.previous.length, parser.previous.start); #endif - if (token.type == TOKEN_IDENTIFIER) { + if (parser.previous.type == TOKEN_IDENTIFIER) { /* check to see if it is an opcode first */ - if (strleq(token.start, "exit", token.length)) { - - emit_op(vm, OP_EXIT); - vm->cp++; - - Token next = next_token(); - u32 ptr = get_ptr(next, st); - emit_u32(vm, ptr); - vm->cp += 4; - - next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "call", token.length)) { - - emit_op(vm, OP_CALL); - vm->cp++; - - Token id = next_token_is(TOKEN_IDENTIFIER); - u32 ptr = get_ptr(id, st); - emit_u32(vm, ptr); - vm->cp += 4; - - u8 arg_count = 0; - u32 arg_pos = vm->cp++; - Token next = next_token_is(TOKEN_LPAREN); - next = next_token(); - while (next.type != TOKEN_RPAREN) { - u8 arg = get_reg(next, st); - emit_byte(vm, arg); - vm->cp++; - arg_count++; - next = next_token(); - } - - vm->code[arg_pos] = arg_count; - -#ifdef DEBUG_PRINT - printf("^code[%d] = %d\n", arg_pos, arg_count); -#endif - - next = next_token(); - if (next.type == TOKEN_SEMICOLON) { - emit_byte(vm, 255); - vm->cp++; - } else { - next = next_token(); - u8 arg = get_reg(next, st); - emit_byte(vm, arg); - vm->cp++; - } - - continue; - } else if (strleq(token.start, "syscall", token.length)) { - - emit_op(vm, OP_SYSCALL); - vm->cp++; - - Token next = next_token(); - - u32 syscall_id = 0; - const char *syscall_name = next.start; - if (strleq(syscall_name, "EXIT", next.length)) - syscall_id = SYSCALL_EXIT; - else if (strleq(syscall_name, "OPEN", next.length)) - syscall_id = SYSCALL_DEVICE_OPEN; - else if (strleq(syscall_name, "READ", next.length)) - syscall_id = SYSCALL_DEVICE_READ; - else if (strleq(syscall_name, "WRITE", next.length)) - syscall_id = SYSCALL_DEVICE_WRITE; - else if (strleq(syscall_name, "CLOSE", next.length)) - syscall_id = SYSCALL_DEVICE_CLOSE; - else if (strleq(syscall_name, "IOCTL", next.length)) - syscall_id = SYSCALL_DEVICE_IOCTL; - else if (strleq(syscall_name, "REFRESH", next.length)) - syscall_id = SYSCALL_DEVICE_REFRESH; - - emit_u32(vm, syscall_id); - vm->cp += 4; - - next = next_token(); - while (next.type != TOKEN_SEMICOLON && - next.type != TOKEN_ARROW_RIGHT) { - u8 arg = get_reg(next, st); - emit_byte(vm, arg); - vm->cp++; - next = next_token(); - } - - if (next.type == TOKEN_ARROW_RIGHT) { - next = next_token(); - u8 arg = get_reg(next, st); - emit_byte(vm, arg); - vm->cp++; - } - - } else if (strleq(token.start, "load_immediate", token.length)) { + if (strleq(parser.previous.start, "load_immediate", parser.previous.length)) { emit_op(vm, OP_LOAD_IMM); vm->cp++; - Token value = next_token(); - switch (value.type) { + advance(); + switch (parser.previous.type) { case TOKEN_KEYWORD_TRUE: { emit_u32(vm, 1); break; @@ -1038,29 +944,29 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { break; } case TOKEN_LITERAL_INT: { - i32 out = atoi(value.start); + i32 out = atoi(parser.previous.start); emit_u32(vm, out); break; } case TOKEN_LITERAL_NAT: { char *endptr; - u32 out = (u32)strtoul(value.start, &endptr, 10); - if (endptr == value.start || *endptr != '\0') { - fprintf(stderr, "Invalid 'real' number: '%.*s'\n", token.length, - token.start); + u32 out = (u32)strtoul(parser.previous.start, &endptr, 10); + if (endptr == parser.previous.start || *endptr != '\0') { + fprintf(stderr, "Invalid 'real' number: '%.*s'\n", parser.previous.length, + parser.previous.start); exit(1); } emit_u32(vm, out); break; } case TOKEN_LITERAL_REAL: { - r32 out = float_to_real(atof(value.start)); + r32 out = float_to_real(atof(parser.previous.start)); emit_u32(vm, out); break; } default: { - fprintf(stderr, "Unknown immediate: '%.*s'\n", token.length, - token.start); + fprintf(stderr, "Unknown immediate: '%.*s'\n", parser.previous.length, + parser.previous.start); exit(1); } } @@ -1069,43 +975,31 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { next_token_is(TOKEN_ARROW_RIGHT); - Token reg = next_token(); - u8 arg = get_reg(reg, st); + advance(); + u8 arg = get_reg(parser.previous, st); emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "load_address", token.length)) { + } else if (strleq(parser.previous.start, "load_address", parser.previous.length)) { emit_op(vm, OP_LOAD_IMM); vm->cp++; - Token id = next_token(); - u32 ptr = get_ptr(id, st); + advance(); + u32 ptr = get_ptr(parser.previous, st); emit_u32(vm, ptr); vm->cp += 4; next_token_is(TOKEN_ARROW_RIGHT); - Token reg = next_token(); - u8 arg = get_reg(reg, st); + advance(); + u8 arg = get_reg(parser.previous, st); emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "malloc", token.length)) { - emit_op(vm, OP_MALLOC); - vm->cp++; - Token reg = next_token(); - u8 arg = get_reg(reg, st); - emit_byte(vm, arg); - vm->cp++; - next_token_is(TOKEN_ARROW_RIGHT); - reg = next_token(); - arg = get_reg(reg, st); - emit_byte(vm, arg); - vm->cp++; - next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "memset_8", token.length)) { + + } else if (strleq(parser.previous.start, "memset_8", parser.previous.length)) { emit_op(vm, OP_MEMSET_8); vm->cp++; @@ -1127,7 +1021,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "memset_16", token.length)) { + } else if (strleq(parser.previous.start, "memset_16", parser.previous.length)) { emit_op(vm, OP_MEMSET_16); vm->cp++; @@ -1149,7 +1043,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "memset_32", token.length)) { + } else if (strleq(parser.previous.start, "memset_32", parser.previous.length)) { emit_op(vm, OP_MEMSET_32); vm->cp++; @@ -1171,7 +1065,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "load_offset_8", token.length)) { + } else if (strleq(parser.previous.start, "load_offset_8", parser.previous.length)) { emit_op(vm, OP_LOAD_OFF_8); vm->cp++; @@ -1193,7 +1087,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "load_offset_16", token.length)) { + } else if (strleq(parser.previous.start, "load_offset_16", parser.previous.length)) { emit_op(vm, OP_LOAD_OFF_16); vm->cp++; @@ -1215,7 +1109,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "load_offset_32", token.length)) { + } else if (strleq(parser.previous.start, "load_offset_32", parser.previous.length)) { emit_op(vm, OP_LOAD_OFF_32); vm->cp++; @@ -1237,7 +1131,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "load_indirect_8", token.length)) { + } else if (strleq(parser.previous.start, "load_indirect_8", parser.previous.length)) { emit_op(vm, OP_LOAD_IND_8); vm->cp++; @@ -1254,7 +1148,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "load_indirect_16", token.length)) { + } else if (strleq(parser.previous.start, "load_indirect_16", parser.previous.length)) { emit_op(vm, OP_LOAD_IND_16); vm->cp++; @@ -1271,7 +1165,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "load_indirect_32", token.length)) { + } else if (strleq(parser.previous.start, "load_indirect_32", parser.previous.length)) { emit_op(vm, OP_LOAD_IND_32); vm->cp++; @@ -1288,7 +1182,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "load_absolute_8", token.length)) { + } else if (strleq(parser.previous.start, "load_absolute_8", parser.previous.length)) { emit_op(vm, OP_LOAD_ABS_8); vm->cp++; @@ -1305,7 +1199,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "load_absolute_16", token.length)) { + } else if (strleq(parser.previous.start, "load_absolute_16", parser.previous.length)) { emit_op(vm, OP_LOAD_ABS_16); vm->cp++; @@ -1322,7 +1216,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "load_absolute_32", token.length)) { + } else if (strleq(parser.previous.start, "load_absolute_32", parser.previous.length)) { emit_op(vm, OP_LOAD_ABS_32); vm->cp++; @@ -1339,7 +1233,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "store_absolute_8", token.length)) { + } else if (strleq(parser.previous.start, "store_absolute_8", parser.previous.length)) { emit_op(vm, OP_STORE_ABS_8); vm->cp++; @@ -1356,7 +1250,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { vm->cp += 4; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "store_absolute_16", token.length)) { + } else if (strleq(parser.previous.start, "store_absolute_16", parser.previous.length)) { emit_op(vm, OP_STORE_ABS_16); vm->cp++; @@ -1373,7 +1267,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { vm->cp += 4; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "store_absolute_32", token.length)) { + } else if (strleq(parser.previous.start, "store_absolute_32", parser.previous.length)) { emit_op(vm, OP_STORE_ABS_32); vm->cp++; @@ -1390,7 +1284,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { vm->cp += 4; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "store_indirect_8", token.length)) { + } else if (strleq(parser.previous.start, "store_indirect_8", parser.previous.length)) { emit_op(vm, OP_STORE_IND_8); vm->cp++; @@ -1407,7 +1301,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "store_indirect_16", token.length)) { + } else if (strleq(parser.previous.start, "store_indirect_16", parser.previous.length)) { emit_op(vm, OP_STORE_IND_16); vm->cp++; @@ -1424,7 +1318,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "store_indirect_32", token.length)) { + } else if (strleq(parser.previous.start, "store_indirect_32", parser.previous.length)) { emit_op(vm, OP_STORE_IND_32); vm->cp++; @@ -1441,7 +1335,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "store_offset_8", token.length)) { + } else if (strleq(parser.previous.start, "store_offset_8", parser.previous.length)) { emit_op(vm, OP_STORE_OFF_8); vm->cp++; @@ -1463,7 +1357,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "store_offset_16", token.length)) { + } else if (strleq(parser.previous.start, "store_offset_16", parser.previous.length)) { emit_op(vm, OP_STORE_OFF_16); vm->cp++; @@ -1485,7 +1379,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "store_offset_32", token.length)) { + } else if (strleq(parser.previous.start, "store_offset_32", parser.previous.length)) { emit_op(vm, OP_STORE_OFF_32); vm->cp++; @@ -1507,20 +1401,8 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "register_move", token.length)) { - emit_op(vm, OP_REG_MOV); - vm->cp++; - Token reg = next_token(); - u8 arg = get_reg(reg, st); - emit_byte(vm, arg); - vm->cp++; - next_token_is(TOKEN_ARROW_RIGHT); - reg = next_token(); - arg = get_reg(reg, st); - emit_byte(vm, arg); - vm->cp++; - next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "add_int", token.length)) { + + } else if (strleq(parser.previous.start, "add_int", parser.previous.length)) { emit_op(vm, OP_ADD_INT); vm->cp++; Token reg = next_token(); @@ -1537,7 +1419,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "sub_int", token.length)) { + } else if (strleq(parser.previous.start, "sub_int", parser.previous.length)) { emit_op(vm, OP_SUB_INT); vm->cp++; Token reg = next_token(); @@ -1554,7 +1436,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "mul_int", token.length)) { + } else if (strleq(parser.previous.start, "mul_int", parser.previous.length)) { emit_op(vm, OP_MUL_INT); vm->cp++; Token reg = next_token(); @@ -1571,7 +1453,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "div_int", token.length)) { + } else if (strleq(parser.previous.start, "div_int", parser.previous.length)) { emit_op(vm, OP_DIV_INT); vm->cp++; Token reg = next_token(); @@ -1588,33 +1470,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "abs_int", token.length)) { - emit_op(vm, OP_ABS_INT); - vm->cp++; - Token reg = next_token(); - u8 arg = get_reg(reg, st); - emit_byte(vm, arg); - vm->cp++; - next_token_is(TOKEN_ARROW_RIGHT); - reg = next_token(); - arg = get_reg(reg, st); - emit_byte(vm, arg); - vm->cp++; - next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "neg_int", token.length)) { - emit_op(vm, OP_NEG_INT); - vm->cp++; - Token reg = next_token(); - u8 arg = get_reg(reg, st); - emit_byte(vm, arg); - vm->cp++; - next_token_is(TOKEN_ARROW_RIGHT); - reg = next_token(); - arg = get_reg(reg, st); - emit_byte(vm, arg); - vm->cp++; - next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "add_nat", token.length)) { + } else if (strleq(parser.previous.start, "add_nat", parser.previous.length)) { emit_op(vm, OP_ADD_NAT); vm->cp++; Token reg = next_token(); @@ -1631,7 +1487,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "sub_nat", token.length)) { + } else if (strleq(parser.previous.start, "sub_nat", parser.previous.length)) { emit_op(vm, OP_SUB_NAT); vm->cp++; Token reg = next_token(); @@ -1648,7 +1504,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "mul_nat", token.length)) { + } else if (strleq(parser.previous.start, "mul_nat", parser.previous.length)) { emit_op(vm, OP_MUL_NAT); vm->cp++; Token reg = next_token(); @@ -1665,7 +1521,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "div_nat", token.length)) { + } else if (strleq(parser.previous.start, "div_nat", parser.previous.length)) { emit_op(vm, OP_DIV_NAT); vm->cp++; Token reg = next_token(); @@ -1682,33 +1538,8 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "abs_nat", token.length)) { - emit_op(vm, OP_ABS_NAT); - vm->cp++; - Token reg = next_token(); - u8 arg = get_reg(reg, st); - emit_byte(vm, arg); - vm->cp++; - next_token_is(TOKEN_ARROW_RIGHT); - reg = next_token(); - arg = get_reg(reg, st); - emit_byte(vm, arg); - vm->cp++; - next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "neg_nat", token.length)) { - emit_op(vm, OP_NEG_NAT); - vm->cp++; - Token reg = next_token(); - u8 arg = get_reg(reg, st); - emit_byte(vm, arg); - vm->cp++; - next_token_is(TOKEN_ARROW_RIGHT); - reg = next_token(); - arg = get_reg(reg, st); - emit_byte(vm, arg); - vm->cp++; - next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "add_real", token.length)) { + + } else if (strleq(parser.previous.start, "add_real", parser.previous.length)) { emit_op(vm, OP_ADD_REAL); vm->cp++; Token reg = next_token(); @@ -1726,7 +1557,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { vm->cp++; next_token_is(TOKEN_SEMICOLON); ; - } else if (strleq(token.start, "sub_real", token.length)) { + } else if (strleq(parser.previous.start, "sub_real", parser.previous.length)) { emit_op(vm, OP_SUB_REAL); vm->cp++; Token reg = next_token(); @@ -1743,7 +1574,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "mul_real", token.length)) { + } else if (strleq(parser.previous.start, "mul_real", parser.previous.length)) { emit_op(vm, OP_MUL_REAL); vm->cp++; Token reg = next_token(); @@ -1760,7 +1591,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "div_real", token.length)) { + } else if (strleq(parser.previous.start, "div_real", parser.previous.length)) { emit_op(vm, OP_DIV_REAL); vm->cp++; Token reg = next_token(); @@ -1777,85 +1608,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "abs_real", token.length)) { - emit_op(vm, OP_ABS_REAL); - vm->cp++; - Token reg = next_token(); - u8 arg = get_reg(reg, st); - emit_byte(vm, arg); - vm->cp++; - next_token_is(TOKEN_ARROW_RIGHT); - reg = next_token(); - arg = get_reg(reg, st); - emit_byte(vm, arg); - vm->cp++; - next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "neg_real", token.length)) { - emit_op(vm, OP_NEG_REAL); - vm->cp++; - Token reg = next_token(); - u8 arg = get_reg(reg, st); - emit_byte(vm, arg); - vm->cp++; - next_token_is(TOKEN_ARROW_RIGHT); - reg = next_token(); - arg = get_reg(reg, st); - emit_byte(vm, arg); - vm->cp++; - next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "int_to_real", token.length)) { - emit_op(vm, OP_INT_TO_REAL); - vm->cp++; - Token reg = next_token(); - u8 arg = get_reg(reg, st); - emit_byte(vm, arg); - vm->cp++; - next_token_is(TOKEN_ARROW_RIGHT); - reg = next_token(); - arg = get_reg(reg, st); - emit_byte(vm, arg); - vm->cp++; - next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "nat_to_real", token.length)) { - emit_op(vm, OP_NAT_TO_REAL); - vm->cp++; - Token reg = next_token(); - u8 arg = get_reg(reg, st); - emit_byte(vm, arg); - vm->cp++; - next_token_is(TOKEN_ARROW_RIGHT); - reg = next_token(); - arg = get_reg(reg, st); - emit_byte(vm, arg); - vm->cp++; - next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "real_to_int", token.length)) { - emit_op(vm, OP_REAL_TO_INT); - vm->cp++; - Token reg = next_token(); - u8 arg = get_reg(reg, st); - emit_byte(vm, arg); - vm->cp++; - next_token_is(TOKEN_ARROW_RIGHT); - reg = next_token(); - arg = get_reg(reg, st); - emit_byte(vm, arg); - vm->cp++; - next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "real_to_nat", token.length)) { - emit_op(vm, OP_REAL_TO_NAT); - vm->cp++; - Token reg = next_token(); - u8 arg = get_reg(reg, st); - emit_byte(vm, arg); - vm->cp++; - next_token_is(TOKEN_ARROW_RIGHT); - reg = next_token(); - arg = get_reg(reg, st); - emit_byte(vm, arg); - vm->cp++; - next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "bit_shift_left", token.length)) { + } else if (strleq(parser.previous.start, "bit_shift_left", parser.previous.length)) { emit_op(vm, OP_BIT_SHIFT_LEFT); vm->cp++; Token reg = next_token(); @@ -1872,7 +1625,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "bit_shift_right", token.length)) { + } else if (strleq(parser.previous.start, "bit_shift_right", parser.previous.length)) { emit_op(vm, OP_BIT_SHIFT_RIGHT); vm->cp++; Token reg = next_token(); @@ -1889,7 +1642,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "bit_shift_r_ext", token.length)) { + } else if (strleq(parser.previous.start, "bit_shift_r_ext", parser.previous.length)) { emit_op(vm, OP_BIT_SHIFT_R_EXT); vm->cp++; Token reg = next_token(); @@ -1906,7 +1659,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "bit_and", token.length)) { + } else if (strleq(parser.previous.start, "bit_and", parser.previous.length)) { emit_op(vm, OP_BAND); vm->cp++; Token reg = next_token(); @@ -1923,7 +1676,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "bit_or", token.length)) { + } else if (strleq(parser.previous.start, "bit_or", parser.previous.length)) { emit_op(vm, OP_BOR); vm->cp++; Token reg = next_token(); @@ -1940,7 +1693,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "bit_xor", token.length)) { + } else if (strleq(parser.previous.start, "bit_xor", parser.previous.length)) { emit_op(vm, OP_BXOR); vm->cp++; Token reg = next_token(); @@ -1957,7 +1710,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "jump", token.length)) { + } else if (strleq(parser.previous.start, "jump", parser.previous.length)) { emit_op(vm, OP_JMP); vm->cp++; @@ -1967,7 +1720,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { vm->cp += 4; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "jump_if_flag", token.length)) { + } else if (strleq(parser.previous.start, "jump_if_flag", parser.previous.length)) { emit_op(vm, OP_JMPF); vm->cp++; @@ -1977,7 +1730,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { vm->cp += 4; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "jump_eq_int", token.length)) { + } else if (strleq(parser.previous.start, "jump_eq_int", parser.previous.length)) { emit_op(vm, OP_JEQ_INT); vm->cp++; Token id = next_token(); @@ -1993,7 +1746,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "jump_neq_int", token.length)) { + } else if (strleq(parser.previous.start, "jump_neq_int", parser.previous.length)) { emit_op(vm, OP_JNEQ_INT); vm->cp++; Token id = next_token(); @@ -2009,7 +1762,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "jump_gt_int", token.length)) { + } else if (strleq(parser.previous.start, "jump_gt_int", parser.previous.length)) { emit_op(vm, OP_JGT_INT); vm->cp++; Token id = next_token(); @@ -2025,7 +1778,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "jump_lt_int", token.length)) { + } else if (strleq(parser.previous.start, "jump_lt_int", parser.previous.length)) { emit_op(vm, OP_JLT_INT); vm->cp++; Token id = next_token(); @@ -2041,7 +1794,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "jump_le_int", token.length)) { + } else if (strleq(parser.previous.start, "jump_le_int", parser.previous.length)) { emit_op(vm, OP_JLE_INT); vm->cp++; Token id = next_token(); @@ -2057,7 +1810,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "jump_ge_int", token.length)) { + } else if (strleq(parser.previous.start, "jump_ge_int", parser.previous.length)) { emit_op(vm, OP_JGE_INT); vm->cp++; Token id = next_token(); @@ -2073,7 +1826,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "jump_eq_nat", token.length)) { + } else if (strleq(parser.previous.start, "jump_eq_nat", parser.previous.length)) { emit_op(vm, OP_JEQ_NAT); vm->cp++; Token id = next_token(); @@ -2089,7 +1842,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "jump_neq_nat", token.length)) { + } else if (strleq(parser.previous.start, "jump_neq_nat", parser.previous.length)) { emit_op(vm, OP_JNEQ_NAT); vm->cp++; Token id = next_token(); @@ -2105,7 +1858,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "jump_gt_nat", token.length)) { + } else if (strleq(parser.previous.start, "jump_gt_nat", parser.previous.length)) { emit_op(vm, OP_JGT_NAT); vm->cp++; Token id = next_token(); @@ -2121,7 +1874,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "jump_lt_nat", token.length)) { + } else if (strleq(parser.previous.start, "jump_lt_nat", parser.previous.length)) { emit_op(vm, OP_JLT_NAT); vm->cp++; Token id = next_token(); @@ -2137,7 +1890,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "jump_le_nat", token.length)) { + } else if (strleq(parser.previous.start, "jump_le_nat", parser.previous.length)) { emit_op(vm, OP_JLE_NAT); vm->cp++; Token id = next_token(); @@ -2153,7 +1906,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "jump_ge_nat", token.length)) { + } else if (strleq(parser.previous.start, "jump_ge_nat", parser.previous.length)) { emit_op(vm, OP_JGE_NAT); vm->cp++; Token id = next_token(); @@ -2169,7 +1922,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "jump_eq_real", token.length)) { + } else if (strleq(parser.previous.start, "jump_eq_real", parser.previous.length)) { emit_op(vm, OP_JEQ_REAL); vm->cp++; Token id = next_token(); @@ -2185,7 +1938,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "jump_neq_real", token.length)) { + } else if (strleq(parser.previous.start, "jump_neq_real", parser.previous.length)) { emit_op(vm, OP_JNEQ_REAL); vm->cp++; Token id = next_token(); @@ -2201,7 +1954,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "jump_ge_real", token.length)) { + } else if (strleq(parser.previous.start, "jump_ge_real", parser.previous.length)) { emit_op(vm, OP_JGE_REAL); vm->cp++; Token id = next_token(); @@ -2217,7 +1970,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "jump_gt_real", token.length)) { + } else if (strleq(parser.previous.start, "jump_gt_real", parser.previous.length)) { emit_op(vm, OP_JGT_REAL); vm->cp++; Token id = next_token(); @@ -2233,7 +1986,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "jump_lt_real", token.length)) { + } else if (strleq(parser.previous.start, "jump_lt_real", parser.previous.length)) { emit_op(vm, OP_JLT_REAL); vm->cp++; Token id = next_token(); @@ -2249,7 +2002,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "jump_le_real", token.length)) { + } else if (strleq(parser.previous.start, "jump_le_real", parser.previous.length)) { emit_op(vm, OP_JLE_REAL); vm->cp++; Token id = next_token(); @@ -2265,20 +2018,8 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "string_length", token.length)) { - emit_op(vm, OP_STRLEN); - vm->cp++; - Token reg = next_token(); - u8 arg = get_reg(reg, st); - emit_byte(vm, arg); - vm->cp++; - next_token_is(TOKEN_ARROW_RIGHT); - reg = next_token(); - arg = get_reg(reg, st); - emit_byte(vm, arg); - vm->cp++; - next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "int_to_string", token.length)) { + + } else if (strleq(parser.previous.start, "int_to_string", parser.previous.length)) { emit_op(vm, OP_INT_TO_STRING); vm->cp++; Token reg = next_token(); @@ -2291,7 +2032,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "nat_to_string", token.length)) { + } else if (strleq(parser.previous.start, "nat_to_string", parser.previous.length)) { emit_op(vm, OP_NAT_TO_STRING); vm->cp++; Token reg = next_token(); @@ -2304,7 +2045,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { emit_byte(vm, arg); vm->cp++; next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "real_to_string", token.length)) { + } else if (strleq(parser.previous.start, "real_to_string", parser.previous.length)) { emit_op(vm, OP_REAL_TO_STRING); vm->cp++; Token reg = next_token(); @@ -2318,23 +2059,136 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { vm->cp++; next_token_is(TOKEN_SEMICOLON); ; - } else if (strleq(token.start, "string_eq", token.length)) { - } else if (strleq(token.start, "string_concat", token.length)) { - } else if (strleq(token.start, "string_get_char", token.length)) { - } else if (strleq(token.start, "string_find_char", token.length)) { - } else if (strleq(token.start, "string_slice", token.length)) { - } else if (strleq(token.start, "string_to_int", token.length)) { - } else if (strleq(token.start, "string_to_nat", token.length)) { - } else if (strleq(token.start, "string_to_real", token.length)) { + } else if (strleq(parser.previous.start, "string_eq", parser.previous.length)) { + } else if (strleq(parser.previous.start, "string_concat", parser.previous.length)) { + } else if (strleq(parser.previous.start, "string_get_char", parser.previous.length)) { + } else if (strleq(parser.previous.start, "string_find_char", parser.previous.length)) { + } else if (strleq(parser.previous.start, "string_slice", parser.previous.length)) { + } else if (strleq(parser.previous.start, "string_to_int", parser.previous.length)) { + } else if (strleq(parser.previous.start, "string_to_nat", parser.previous.length)) { + } else if (strleq(parser.previous.start, "string_to_real", parser.previous.length)) { } else { /* some other identifier */ - printf("Unknown id at line %d: %.*s\n", token.line, token.length, - token.start); + printf("Unknown id at line %d: %.*s\n", parser.previous.line, parser.previous.length, + parser.previous.start); exit(1); } } } - } while (token.type != TOKEN_EOF); + } while (parser.previous.type != TOKEN_EOF); +} + +void emit_reg_reg(VM *vm, ScopeTable *st, char *op_name) { + Opcode op = get_opcode(op_name); + emit_op(vm, op); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); +} + +void emit_exit(VM *vm, ScopeTable *st, char *op_name) { + USED(op_name); + emit_op(vm, OP_EXIT); + vm->cp++; + + advance(); + u32 ptr = get_ptr(parser.previous, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_SEMICOLON); +} + +void emit_call(VM *vm, ScopeTable *st, char *op_name) { + USED(op_name); + emit_op(vm, OP_CALL); + vm->cp++; + + next_token_is(TOKEN_IDENTIFIER); + u32 ptr = get_ptr(parser.previous, st); + emit_u32(vm, ptr); + vm->cp += 4; + + u8 arg_count = 0; + u32 arg_pos = vm->cp++; + next_token_is(TOKEN_LPAREN); + advance(); + while (parser.previous.type != TOKEN_RPAREN) { + u8 arg = get_reg(parser.previous, st); + emit_byte(vm, arg); + vm->cp++; + arg_count++; + advance(); + } + + vm->code[arg_pos] = arg_count; + +#ifdef DEBUG_PRINT + printf("^code[%d] = %d\n", arg_pos, arg_count); +#endif + + advance(); + if (parser.previous.type == TOKEN_SEMICOLON) { + emit_byte(vm, 255); + vm->cp++; + } else { + advance(); + u8 arg = get_reg(parser.previous, st); + emit_byte(vm, arg); + vm->cp++; + } +} + +void emit_syscall(VM *vm, ScopeTable *st, char *op_name) { + USED(op_name); + emit_op(vm, OP_SYSCALL); + vm->cp++; + + advance(); + + u32 syscall_id = 0; + const char *syscall_name = parser.previous.start; + if (strleq(syscall_name, "EXIT", parser.previous.length)) + syscall_id = SYSCALL_EXIT; + else if (strleq(syscall_name, "OPEN", parser.previous.length)) + syscall_id = SYSCALL_DEVICE_OPEN; + else if (strleq(syscall_name, "READ", parser.previous.length)) + syscall_id = SYSCALL_DEVICE_READ; + else if (strleq(syscall_name, "WRITE", parser.previous.length)) + syscall_id = SYSCALL_DEVICE_WRITE; + else if (strleq(syscall_name, "CLOSE", parser.previous.length)) + syscall_id = SYSCALL_DEVICE_CLOSE; + else if (strleq(syscall_name, "IOCTL", parser.previous.length)) + syscall_id = SYSCALL_DEVICE_IOCTL; + else if (strleq(syscall_name, "REFRESH", parser.previous.length)) + syscall_id = SYSCALL_DEVICE_REFRESH; + + emit_u32(vm, syscall_id); + vm->cp += 4; + + advance(); + while (parser.previous.type != TOKEN_SEMICOLON && + parser.previous.type != TOKEN_ARROW_RIGHT) { + u8 arg = get_reg(parser.previous, st); + emit_byte(vm, arg); + vm->cp++; + advance(); + } + + if (parser.previous.type == TOKEN_ARROW_RIGHT) { + advance(); + u8 arg = get_reg(parser.previous, st); + emit_byte(vm, arg); + vm->cp++; + } } /** diff --git a/src/tools/compiler/compiler.h b/src/tools/compiler/compiler.h index 4600bdd..2e9296e 100644 --- a/src/tools/compiler/compiler.h +++ b/src/tools/compiler/compiler.h @@ -5,6 +5,14 @@ #include "../../vm/common.h" #include "../../vm/opcodes.h" +typedef struct op_def_s OpDef; +struct op_def_s { + i32 instruction_byte_size; + void (*parse_symbol)(VM *vm, ScopeTable *st, char *op_name); + void (*emit_symbol)(VM *vm, ScopeTable *st, char *op_name); + char *to_str; +}; + bool compile(VM *vm, ScopeTable *st, char *source); extern bool table_realloc(ScopeTable *table);/* implement this in arch/ not here */