diff --git a/src/arch/emscripten/main.c b/src/arch/emscripten/main.c index 1a98d0e..8067a09 100644 --- a/src/arch/emscripten/main.c +++ b/src/arch/emscripten/main.c @@ -66,7 +66,6 @@ void mainloop() { mouse_data.btn4 = 0; break; - // Touch events (map to mouse_data as left-click equivalent) case SDL_FINGERMOTION: case SDL_FINGERDOWN: case SDL_FINGERUP: { @@ -77,8 +76,6 @@ void mainloop() { mouse_data.x = (int)x; mouse_data.y = (int)y; - // Only treat the first finger as mouse input (ignore multi-touch beyond 1 - // finger) if (event.tfinger.fingerId == 0) { if (event.type == SDL_FINGERDOWN || event.type == SDL_FINGERMOTION) { mouse_data.btn1 = 1; @@ -91,9 +88,8 @@ void mainloop() { } } - // Run VM for a fixed number of cycles or a time slice int cycles_this_frame = 0; - int max_cycles_per_frame = 2000; // Adjust this value + int max_cycles_per_frame = 2000; while (cycles_this_frame < max_cycles_per_frame) { if (!step_vm(&vm)) { emscripten_cancel_main_loop(); @@ -102,13 +98,12 @@ void mainloop() { cycles_this_frame++; } - // Render only if the screen buffer was updated AND at a reasonable rate if (screen_data.update) { if (screen_data.renderer && screen_data.texture) { SDL_RenderCopy(screen_data.renderer, screen_data.texture, NULL, NULL); SDL_RenderPresent(screen_data.renderer); } - screen_data.update = false; // Reset flag after rendering + screen_data.update = false; } } @@ -119,7 +114,6 @@ bool loadVM(const char *filename, VM *vm) { return false; } - // Read VM state if (fread(&vm->pc, sizeof(u32), 1, file) != 1 || fread(&vm->cp, sizeof(u32), 1, file) != 1 || fread(&vm->fp, sizeof(u32), 1, file) != 1 || @@ -132,14 +126,12 @@ bool loadVM(const char *filename, VM *vm) { return false; } - // Read code section if (fread(vm->code, 1, vm->cp, file) != vm->cp) { printf("Failed to read code section\n"); fclose(file); return false; } - // Read memory section if (fread(vm->memory, 1, vm->mp, file) != vm->mp) { printf("Failed to read memory section\n"); fclose(file); @@ -187,7 +179,6 @@ int main(int argc, char **argv) { vm_register_device(&vm, "/dev/term/0", "terminal", &console_data, &console_device_ops, 4); - // Set up main loop emscripten_set_main_loop(mainloop, 0, 1); return 0; } \ No newline at end of file diff --git a/src/tools/assembler/assembler.c b/src/tools/assembler/assembler.c index d69c183..00ed047 100644 --- a/src/tools/assembler/assembler.c +++ b/src/tools/assembler/assembler.c @@ -11,127 +11,127 @@ #include #include +/* FIXME: technically this is not allowed in C89 find another way */ const char *opcode_to_string(Opcode op) { - static const char *names[] = { - [OP_EXIT] = "exit", - [OP_JMP] = "jump", - [OP_JMPF] = "jump_if_flag", - [OP_CALL] = "call", - [OP_RETURN] = "return", + static const char *names[] = {[OP_EXIT] = "exit", + [OP_JMP] = "jump", + [OP_JMPF] = "jump_if_flag", + [OP_CALL] = "call", + [OP_RETURN] = "return", - [OP_LOAD_IMM] = "load_immediate", + [OP_LOAD_IMM] = "load_immediate", - /* Register_indirect loads */ - [OP_LOAD_IND_8] = "load_indirect_8", - [OP_LOAD_IND_16] = "load_indirect_16", - [OP_LOAD_IND_32] = "load_indirect_32", + /* Register_indirect loads */ + [OP_LOAD_IND_8] = "load_indirect_8", + [OP_LOAD_IND_16] = "load_indirect_16", + [OP_LOAD_IND_32] = "load_indirect_32", - /* Absolute address loads */ - [OP_LOAD_ABS_8] = "load_absolute_8", - [OP_LOAD_ABS_16] = "load_absolute_16", - [OP_LOAD_ABS_32] = "load_absolute_32", + /* Absolute address loads */ + [OP_LOAD_ABS_8] = "load_absolute_8", + [OP_LOAD_ABS_16] = "load_absolute_16", + [OP_LOAD_ABS_32] = "load_absolute_32", - /* Base+offset loads */ - [OP_LOAD_OFF_8] = "load_offset_8", - [OP_LOAD_OFF_16] = "load_offset_16", - [OP_LOAD_OFF_32] = "load_offset_32", + /* Base+offset loads */ + [OP_LOAD_OFF_8] = "load_offset_8", + [OP_LOAD_OFF_16] = "load_offset_16", + [OP_LOAD_OFF_32] = "load_offset_32", - /* Absolute address stores */ - [OP_STORE_ABS_8] = "store_absolute_8", - [OP_STORE_ABS_16] = "store_absolute_16", - [OP_STORE_ABS_32] = "store_absolute_32", + /* Absolute address stores */ + [OP_STORE_ABS_8] = "store_absolute_8", + [OP_STORE_ABS_16] = "store_absolute_16", + [OP_STORE_ABS_32] = "store_absolute_32", - /* Register_indirect stores */ - [OP_STORE_IND_8] = "store_indirect_8", - [OP_STORE_IND_16] = "store_indirect_16", - [OP_STORE_IND_32] = "store_indirect_32", + /* Register_indirect stores */ + [OP_STORE_IND_8] = "store_indirect_8", + [OP_STORE_IND_16] = "store_indirect_16", + [OP_STORE_IND_32] = "store_indirect_32", - /* Base+offset stores */ - [OP_STORE_OFF_8] = "store_offset_8", - [OP_STORE_OFF_16] = "store_offset_16", - [OP_STORE_OFF_32] = "store_offset_32", + /* Base+offset stores */ + [OP_STORE_OFF_8] = "store_offset_8", + [OP_STORE_OFF_16] = "store_offset_16", + [OP_STORE_OFF_32] = "store_offset_32", - /* Memory operations */ - [OP_MALLOC] = "malloc", - [OP_MEMSET_8] = "memset_8", - [OP_MEMSET_16] = "memset_16", - [OP_MEMSET_32] = "memset_32", + /* Memory operations */ + [OP_MALLOC] = "malloc", + [OP_MEMSET_8] = "memset_8", + [OP_MEMSET_16] = "memset_16", + [OP_MEMSET_32] = "memset_32", - /* Register operations */ - [OP_REG_MOV] = "register_move", - [OP_SYSCALL] = "syscall", + /* Register operations */ + [OP_REG_MOV] = "register_move", + [OP_SYSCALL] = "syscall", - /* Bit operations */ - [OP_BIT_SHIFT_LEFT] = "bit_shift_left", - [OP_BIT_SHIFT_RIGHT] = "bit_shift_right", - [OP_BIT_SHIFT_R_EXT] = "bit_shift_re", - [OP_BAND] = "bit_and", - [OP_BOR] = "bit_or", - [OP_BXOR] = "bit_xor", + /* Bit operations */ + [OP_BIT_SHIFT_LEFT] = "bit_shift_left", + [OP_BIT_SHIFT_RIGHT] = "bit_shift_right", + [OP_BIT_SHIFT_R_EXT] = "bit_shift_re", + [OP_BAND] = "bit_and", + [OP_BOR] = "bit_or", + [OP_BXOR] = "bit_xor", - /* Integer arithmetic */ - [OP_ADD_INT] = "add_int", - [OP_SUB_INT] = "sub_int", - [OP_MUL_INT] = "mul_int", - [OP_DIV_INT] = "div_int", + /* Integer arithmetic */ + [OP_ADD_INT] = "add_int", + [OP_SUB_INT] = "sub_int", + [OP_MUL_INT] = "mul_int", + [OP_DIV_INT] = "div_int", - /* Natural number arithmetic */ - [OP_ADD_NAT] = "add_nat", - [OP_SUB_NAT] = "sub_nat", - [OP_MUL_NAT] = "mul_nat", - [OP_DIV_NAT] = "div_nat", + /* Natural number arithmetic */ + [OP_ADD_NAT] = "add_nat", + [OP_SUB_NAT] = "sub_nat", + [OP_MUL_NAT] = "mul_nat", + [OP_DIV_NAT] = "div_nat", - /* Floating point operations */ - [OP_ADD_REAL] = "add_real", - [OP_SUB_REAL] = "sub_real", - [OP_MUL_REAL] = "mul_real", - [OP_DIV_REAL] = "div_real", + /* Floating point operations */ + [OP_ADD_REAL] = "add_real", + [OP_SUB_REAL] = "sub_real", + [OP_MUL_REAL] = "mul_real", + [OP_DIV_REAL] = "div_real", - /* Type conversions */ - [OP_INT_TO_REAL] = "int_to_real", - [OP_NAT_TO_REAL] = "nat_to_real", - [OP_REAL_TO_INT] = "real_to_int", - [OP_REAL_TO_NAT] = "real_to_nat", + /* Type conversions */ + [OP_INT_TO_REAL] = "int_to_real", + [OP_NAT_TO_REAL] = "nat_to_real", + [OP_REAL_TO_INT] = "real_to_int", + [OP_REAL_TO_NAT] = "real_to_nat", - /* Integer comparisons */ - [OP_JEQ_INT] = "jump_eq_int", - [OP_JNEQ_INT] = "jump_neq_int", - [OP_JGT_INT] = "jump_gt_int", - [OP_JLT_INT] = "jump_lt_int", - [OP_JLE_INT] = "jump_le_int", - [OP_JGE_INT] = "jump_ge_int", + /* Integer comparisons */ + [OP_JEQ_INT] = "jump_eq_int", + [OP_JNEQ_INT] = "jump_neq_int", + [OP_JGT_INT] = "jump_gt_int", + [OP_JLT_INT] = "jump_lt_int", + [OP_JLE_INT] = "jump_le_int", + [OP_JGE_INT] = "jump_ge_int", - /* Natural number comparisons */ - [OP_JEQ_NAT] = "jump_eq_nat", - [OP_JNEQ_NAT] = "jump_neq_nat", - [OP_JGT_NAT] = "jump_gt_nat", - [OP_JLT_NAT] = "jump_lt_nat", - [OP_JLE_NAT] = "jump_le_nat", - [OP_JGE_NAT] = "jump_ge_nat", + /* Natural number comparisons */ + [OP_JEQ_NAT] = "jump_eq_nat", + [OP_JNEQ_NAT] = "jump_neq_nat", + [OP_JGT_NAT] = "jump_gt_nat", + [OP_JLT_NAT] = "jump_lt_nat", + [OP_JLE_NAT] = "jump_le_nat", + [OP_JGE_NAT] = "jump_ge_nat", - /* Floating point comparisons */ - [OP_JEQ_REAL] = "jump_eq_real", - [OP_JNEQ_REAL] = "jump_neq_real", - [OP_JGE_REAL] = "jump_ge_real", - [OP_JGT_REAL] = "jump_gt_real", - [OP_JLT_REAL] = "jump_lt_real", - [OP_JLE_REAL] = "jump_le_real", + /* Floating point comparisons */ + [OP_JEQ_REAL] = "jump_eq_real", + [OP_JNEQ_REAL] = "jump_neq_real", + [OP_JGE_REAL] = "jump_ge_real", + [OP_JGT_REAL] = "jump_gt_real", + [OP_JLT_REAL] = "jump_lt_real", + [OP_JLE_REAL] = "jump_le_real", - /* String operations */ - [OP_STRLEN] = "string_length", - [OP_STREQ] = "string_eq", - [OP_STRCAT] = "string_concat", - [OP_STR_GET_CHAR] = "string_get_char", - [OP_STR_FIND_CHAR] = "string_find_char", - [OP_STR_SLICE] = "string_slice", + /* String operations */ + [OP_STRLEN] = "string_length", + [OP_STREQ] = "string_eq", + [OP_STRCAT] = "string_concat", + [OP_STR_GET_CHAR] = "string_get_char", + [OP_STR_FIND_CHAR] = "string_find_char", + [OP_STR_SLICE] = "string_slice", - /* String conversions */ - [OP_INT_TO_STRING] = "int_to_string", - [OP_NAT_TO_STRING] = "nat_to_string", - [OP_REAL_TO_STRING] = "real_to_string", - [OP_STRING_TO_INT] = "string_to_int", - [OP_STRING_TO_NAT] = "string_to_nat", - [OP_STRING_TO_REAL] = "string_to_real"}; + /* String conversions */ + [OP_INT_TO_STRING] = "int_to_string", + [OP_NAT_TO_STRING] = "nat_to_string", + [OP_REAL_TO_STRING] = "real_to_string", + [OP_STRING_TO_INT] = "string_to_int", + [OP_STRING_TO_NAT] = "string_to_nat", + [OP_STRING_TO_REAL] = "string_to_real"}; if (op < 0 || op >= (int)(sizeof(names) / sizeof(names[0]))) { return ""; @@ -141,7 +141,6 @@ const char *opcode_to_string(Opcode op) { return name ? name : ""; } - void emit_op(VM *vm, u8 byte) { #ifdef DEBUG_PRINT printf("code[%d] = %s\n", vm->cp, opcode_to_string(byte)); @@ -152,7 +151,7 @@ void emit_op(VM *vm, u8 byte) { void emit_byte(VM *vm, u8 byte) { #ifdef DEBUG_PRINT printf("code[%d] = %d\n", vm->cp, byte); -#endif +#endif vm->code[vm->cp] = byte; } @@ -186,9 +185,11 @@ u32 symbol_table_add(SymbolTable *table, Symbol s) { } if (!resize_or_check_size(table)) { - fprintf(stderr, - "Error: Symbol table is out of memory! This is likely because you built this in static mode." - "if you built using malloc, that means your computer is out of memory. Close a few tabs in your web browser and try again." + fprintf(stderr, + "Error: Symbol table is out of memory! This is likely because you " + "built the assembler in static mode, increase the static size." + "if you built using malloc, that means your computer is out of " + "memory. Close a few tabs in your web browser and try again." "Count was %d, while capacity was %d\n", table->count, table->capacity); exit(1); @@ -212,7 +213,8 @@ u32 symbol_table_add(SymbolTable *table, Symbol s) { u32 get_ref(SymbolTable *st, const char *name, u32 length) { Symbol *sym = symbol_table_lookup(st, name, length); if (!sym) { - fprintf(stderr, "Error: Undefined Symbol '%.*s'\n", length, name); + fprintf(stderr, "Error: Assembler has no idea what Symbol '%.*s' means.\n", + length, name); exit(1); return 0; } @@ -232,15 +234,15 @@ u32 get_ptr(Token token, SymbolTable *st) { char *endptr; u32 out = (u32)strtoul(token.start, &endptr, 10); if (endptr == token.start || *endptr != '\0') { - fprintf(stderr, "Invalid decimal literal: '%.*s'\n", token.length, - token.start); + fprintf(stderr, "Invalid decimal literal at line %d: %.*s\n", token.line, + token.length, token.start); exit(1); } return out; } - fprintf(stderr, "Error: Not a pointer or symbol '%.*s'\n", token.length, - token.start); + fprintf(stderr, "Error: Not a pointer or symbol at line %d: %.*s\n", + token.line, token.length, token.start); exit(1); } @@ -254,8 +256,8 @@ u32 get_reg(Token token, SymbolTable *st) { return atoi(token.start); } - fprintf(stderr, "Error: Not a register or symbol '%.*s'\n", token.length, - token.start); + fprintf(stderr, "Error: Not a register or symbol at line %d: %.*s\n", + token.line, token.length, token.start); exit(1); } @@ -439,16 +441,16 @@ bool define_global(VM *vm, SymbolTable *st) { case '\\': case '"': case '\'': - break; // Keep as-is + break; default: - i--; // Rewind for unknown escapes + i--; /* Rewind for unknown escapes */ } } write_u8(vm, memory, addr + 4 + len, c); len++; } - u32 size = len + 5; // 4 (len) + dst_len + 1 (null) + u32 size = len + 5; /* 4 (len) + dst_len + 1 (null) */ s.size = size; vm->mp += size; @@ -610,9 +612,8 @@ void define_branch(VM *vm, SymbolTable *st) { int get_instruction_byte_size(const char *opname) { - // Return (1 + 1) if (strcmp(opname, "return") == 0) { - return 2; // 1 byte opcode + 1 byte return register + return 2; } if (strcmp(opname, "neg_int") == 0 || strcmp(opname, "abs_int") == 0 || @@ -632,14 +633,13 @@ int get_instruction_byte_size(const char *opname) { 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, "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; } - // Register_register_register opcodes (4 bytes: 1 + 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 || @@ -654,13 +654,11 @@ int get_instruction_byte_size(const char *opname) { return 4; } - // (5 bytes: 1 + 4) if (strcmp(opname, "halt") == 0 || strcmp(opname, "jump_if_flag") == 0 || strcmp(opname, "jump") == 0) { return 5; } - // Load, Load_immediate (6 bytes: 1 + 1 + 4) if (strcmp(opname, "load_absolute_32") == 0 || strcmp(opname, "load_immediate") == 0 || strcmp(opname, "load_address") == 0 || @@ -672,7 +670,6 @@ int get_instruction_byte_size(const char *opname) { return 6; } - // jump compare (7 bytes: 1 + 4 + 1 + 1) if (strcmp(opname, "jump_eq_int") == 0 || strcmp(opname, "jump_neq_int") == 0 || strcmp(opname, "jump_gt_int") == 0 || @@ -704,15 +701,17 @@ int get_instruction_byte_size(const char *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); +#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); /** * Build the symbol table and calculate the types/size/offsets of all values. @@ -771,11 +770,11 @@ void build_symbol_table(VM *vm, char *source, SymbolTable *st) { continue; } - #ifdef DEBUG_PRINT - printf("-- %.*s --\n", token.length, token.start); - #endif +#ifdef DEBUG_PRINT + printf("-- %.*s --\n", token.length, token.start); +#endif if (token.type == TOKEN_IDENTIFIER) { - // check to see if it is an opcode first + /* check to see if it is an opcode first */ if (strleq(token.start, "exit", token.length)) { vm->cp++; @@ -783,9 +782,9 @@ void build_symbol_table(VM *vm, char *source, SymbolTable *st) { next_token(); vm->cp += 4; - #ifdef DEBUG_PRINT - printf("code[%d] = exit\n", vm->cp); - #endif +#ifdef DEBUG_PRINT + printf("code[%d] = exit\n", vm->cp); +#endif next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "call", token.length)) { @@ -799,9 +798,9 @@ void build_symbol_table(VM *vm, char *source, SymbolTable *st) { Token next = next_token_is(TOKEN_LPAREN); next = next_token(); while (next.type != TOKEN_RPAREN) { - get_reg(next, st); - vm->cp++; - next = next_token(); + get_reg(next, st); + vm->cp++; + next = next_token(); } next = next_token(); @@ -812,9 +811,9 @@ void build_symbol_table(VM *vm, char *source, SymbolTable *st) { get_reg(next, st); vm->cp++; } - #ifdef DEBUG_PRINT - printf("code[%d] = call\n", vm->cp); - #endif +#ifdef DEBUG_PRINT + printf("code[%d] = call\n", vm->cp); +#endif continue; } else if (strleq(token.start, "syscall", token.length)) { @@ -829,97 +828,97 @@ void build_symbol_table(VM *vm, char *source, SymbolTable *st) { vm->cp++; next = next_token(); } - #ifdef DEBUG_PRINT - printf("code[%d] = syscall\n", vm->cp); - #endif +#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") + 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") } else { - // some other identifier + /* some other identifier */ printf("Unknown id at line %d: %.*s\n", token.line, token.length, token.start); exit(1); @@ -944,17 +943,17 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) { if (token.type != TOKEN_EOF) { if (token.type == TOKEN_KEYWORD_GLOBAL) { - // ignore, already processed - next_token(); // type - next_token(); // var - next_token(); // eq - next_token(); // value - next_token(); // ; + /* ignore, already processed */ + next_token(); /* type */ + next_token(); /* var */ + next_token(); /* eq */ + next_token(); /* value */ + next_token(); /* ; */ continue; } if (token.type == TOKEN_KEYWORD_FN) { - // ignore, already processed + /* ignore, already processed */ Token next = next_token(); while (next.type != TOKEN_RPAREN) { next = next_token(); @@ -967,19 +966,19 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) { 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) { - // ignore, already processed - next_token(); // type - next_token(); // var - next_token(); // reg - next_token(); // ; + /* ignore, already processed */ + next_token(); /* type */ + next_token(); /* var */ + next_token(); /* reg */ + next_token(); /* ; */ 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) { - // ignore, already processed - next_token(); // id + /* ignore, already processed */ + next_token(); /* id */ } if (token.type == TOKEN_KEYWORD_RETURN) { @@ -1001,11 +1000,11 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) { continue; } - #ifdef DEBUG_PRINT - printf("-- %.*s --\n", token.length, token.start); - #endif +#ifdef DEBUG_PRINT + printf("-- %.*s --\n", token.length, token.start); +#endif if (token.type == TOKEN_IDENTIFIER) { - // check to see if it is an opcode first + /* check to see if it is an opcode first */ if (strleq(token.start, "exit", token.length)) { emit_op(vm, OP_EXIT); @@ -1032,19 +1031,19 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) { 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(); + 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 + +#ifdef DEBUG_PRINT printf("^code[%d] = %d\n", arg_pos, arg_count); - #endif - +#endif + next = next_token(); if (next.type == TOKEN_SEMICOLON) { emit_byte(vm, 255); @@ -1085,8 +1084,9 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) { vm->cp += 4; next = next_token(); - while (next.type != TOKEN_SEMICOLON && next.type != TOKEN_ARROW_RIGHT) { - u8 arg =get_reg(next, st); + 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(); @@ -1241,7 +1241,7 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) { vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); - + reg = next_token(); arg = get_reg(reg, st); emit_byte(vm, arg); @@ -2404,7 +2404,7 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) { } else if (strleq(token.start, "string_to_nat", token.length)) { } else if (strleq(token.start, "string_to_real", token.length)) { } else { - // some other identifier + /* some other identifier */ printf("Unknown id at line %d: %.*s\n", token.line, token.length, token.start); exit(1); diff --git a/src/tools/compiler/compiler.c b/src/tools/compiler/compiler.c index 889c277..056219e 100644 --- a/src/tools/compiler/compiler.c +++ b/src/tools/compiler/compiler.c @@ -1,5 +1,7 @@ +#include "lexer.h" #include "compiler.h" #include "../../vm/common.h" +#include "../../vm/opcodes.h" #include "../../vm/libc.h" #include #include @@ -178,101 +180,6 @@ ValueType *plex_get_field_by_name(PlexTable *plex_table, return plex_get_field(plex_table, fields_table, plex_index, (u32)field_index); } -Symbol *global(VM *vm) { - Symbol s; - ValueType t; - - s.ref.global = vm->mp; - - Token token_type = next_token(); - Token array_or_eq = next_token(); - if (array_or_eq.type == TOKEN_LBRACKET) { - Token rb = next_token(); - if (rb.type != TOKEN_RBRACKET) - return nil; - - Token eq = next_token(); - if (eq.type != TOKEN_EQ) - return nil; - - t.type = ARRAY; - ValueType array_type; - - switch (token_type.type) { - case TOKEN_TYPE_I8: - array_type.type = I8; - break; - case TOKEN_TYPE_I16: - array_type.type = I16; - break; - case TOKEN_TYPE_INT: - array_type.type = I32; - break; - case TOKEN_TYPE_U8: - array_type.type = U8; - break; - case TOKEN_TYPE_U16: - array_type.type = U16; - break; - case TOKEN_TYPE_NAT: - array_type.type = U32; - break; - case TOKEN_TYPE_REAL: - array_type.type = F32; - break; - case TOKEN_TYPE_STR: - array_type.type = STR; - break; - case TOKEN_IDENTIFIER: - break; - default: - return nil; - } - - } else { - // its not an array, so should be = - if (array_or_eq.type != TOKEN_EQ) - return nil; - - switch (token_type.type) { - case TOKEN_TYPE_I8: - t.type = I8; - break; - case TOKEN_TYPE_I16: - t.type = I16; - break; - case TOKEN_TYPE_INT: - t.type = I32; - break; - case TOKEN_TYPE_U8: - t.type = U8; - break; - case TOKEN_TYPE_U16: - t.type = U16; - break; - case TOKEN_TYPE_NAT: - t.type = U32; - break; - case TOKEN_TYPE_REAL: - t.type = F32; - break; - case TOKEN_TYPE_STR: - t.type = STR; - break; - case TOKEN_IDENTIFIER: - break; - default: - return nil; - } - } - - s.type = t; - - Token value = next_token(); - - return nil; -} - typedef struct { Token current; Token previous; @@ -420,18 +327,18 @@ void number(Compiler *c, VM *vm) { c->last = Symbol{ .type=parser.previous.type }; switch (parser.previous.type) { - case TOKEN_INT_LITERAL: { + case TOKEN_LITERAL_INT: { char *endptr; i32 value = (i32)strtol(parser.previous.start, &endptr, 10); emit_u32(vm, value); return; } - case TOKEN_UINT_LITERAL: { + case TOKEN_LITERAL_NAT: { long value = atol(parser.previous.start); emit_u32(vm, value); return; } - case TOKEN_FLOAT_LITERAL: { + case TOKEN_LITERAL_REAL: { float value = atof(parser.previous.start); fixed_t fvalue = float_to_fixed(value); emit_u32(vm, fvalue); @@ -454,10 +361,10 @@ static void unary(Compiler *c, VM *vm) { switch (operatorType) { case TOKEN_MINUS: { switch (c->last.type) { - case TOKEN_UINT_LITERAL: - emit_opcode(vm, OP_NEG_UINT); - case TOKEN_FLOAT_LITERAL: - emit_opcode(vm, OP_NEG_FLOAT); + case TOKEN_LITERAL_NAT: + emit_opcode(vm, OP_NEG_NAT); + case TOKEN_LITERAL_REAL: + emit_opcode(vm, OP_NEG_REAL); default: emit_opcode(vm, OP_NEG_INT); } @@ -472,7 +379,7 @@ static void unary(Compiler *c, VM *vm) { } static void emitHalt(Compiler *c, VM *vm) { - emit_opcode(vm, OP_HALT); + emit_opcode(vm, OP_EXIT); advance(); number(c, vm); } diff --git a/src/tools/compiler/compiler.h b/src/tools/compiler/compiler.h index 778a5e3..59e420b 100644 --- a/src/tools/compiler/compiler.h +++ b/src/tools/compiler/compiler.h @@ -3,7 +3,6 @@ #import "../../vm/common.h" -typedef enum { GLOBAL, LOCAL } ScopeType; typedef enum { VOID, BOOL, @@ -33,6 +32,8 @@ typedef struct symbol_s Symbol; typedef struct symbol_tab_s SymbolTable; typedef struct names_tab_s NamesTable; typedef struct plex_fields_tab_s PlexFieldsTable; +typedef struct scope_s Scope; +typedef struct scope_tab_s ScopeTable; struct value_type_s { SymbolType type; @@ -65,7 +66,6 @@ struct array_def_s { struct symbol_s { u32 name; ValueType type; - ScopeType scope; union { u32 local; // register u32 global; // address @@ -103,14 +103,20 @@ struct names_tab_s { u32 capacity; }; -/** - * FIXME: - * Symbols need to be inside a scope so we can have duplicates - */ struct symbol_tab_s { Symbol *symbols; u32 count; u32 capacity; }; +struct scope_s { + SymbolTable table; +}; + +struct scope_tab_s { + Scope *scopes; + u32 count; + u32 capacity; +}; + #endif diff --git a/src/tools/compiler/lexer.c b/src/tools/compiler/parser.c similarity index 100% rename from src/tools/compiler/lexer.c rename to src/tools/compiler/parser.c diff --git a/src/tools/compiler/lexer.h b/src/tools/compiler/parser.h similarity index 100% rename from src/tools/compiler/lexer.h rename to src/tools/compiler/parser.h diff --git a/src/vm/fixed.c b/src/vm/fixed.c index bbbdbc2..f75aae0 100644 --- a/src/vm/fixed.c +++ b/src/vm/fixed.c @@ -1,8 +1,5 @@ -/* fixed.c - Q16.16 Fixed-Point Math Implementation */ - #include "fixed.h" -/* Conversion functions */ fixed_t int_to_fixed(i32 i) { return i << 16; } i32 fixed_to_int(fixed_t f) { return f >> 16; } @@ -16,38 +13,32 @@ fixed_t fixed_add(fixed_t a, fixed_t b) { return a + b; } fixed_t fixed_sub(fixed_t a, fixed_t b) { return a - b; } fixed_t fixed_mul(fixed_t a, fixed_t b) { - /* Extract high and low parts */ i32 a_hi = a >> 16; u32 a_lo = (u32)a & 0xFFFFU; i32 b_hi = b >> 16; u32 b_lo = (u32)b & 0xFFFFU; - /* Compute partial products */ - i32 p0 = (i32)(a_lo * b_lo) >> 16; /* Low * Low */ - i32 p1 = a_hi * (i32)b_lo; /* High * Low */ - i32 p2 = (i32)a_lo * b_hi; /* Low * High */ - i32 p3 = (a_hi * b_hi) << 16; /* High * High */ + i32 p0 = (i32)(a_lo * b_lo) >> 16; + i32 p1 = a_hi * (i32)b_lo; + i32 p2 = (i32)a_lo * b_hi; + i32 p3 = (a_hi * b_hi) << 16; - /* Combine results */ return p0 + p1 + p2 + p3; } fixed_t fixed_div(fixed_t a, fixed_t b) { - int negative; + i32 negative; u32 ua, ub, quotient, remainder; - int i; + i32 i; if (b == 0) - return 0; /* Handle division by zero */ + return 0; - /* Determine sign */ negative = ((a < 0) ^ (b < 0)); - /* Work with absolute values */ ua = (a < 0) ? -a : a; ub = (b < 0) ? -b : b; - /* Perform division using long division in base 2^16 */ quotient = 0; remainder = 0; @@ -71,111 +62,18 @@ fixed_t fixed_div(fixed_t a, fixed_t b) { return negative ? -(i32)quotient : (i32)quotient; } -int fixed_eq(fixed_t a, fixed_t b) { return a == b; } +i32 fixed_eq(fixed_t a, fixed_t b) { return a == b; } -int fixed_ne(fixed_t a, fixed_t b) { return a != b; } +i32 fixed_ne(fixed_t a, fixed_t b) { return a != b; } -int fixed_lt(fixed_t a, fixed_t b) { return a < b; } +i32 fixed_lt(fixed_t a, fixed_t b) { return a < b; } -int fixed_le(fixed_t a, fixed_t b) { return a <= b; } +i32 fixed_le(fixed_t a, fixed_t b) { return a <= b; } -int fixed_gt(fixed_t a, fixed_t b) { return a > b; } +i32 fixed_gt(fixed_t a, fixed_t b) { return a > b; } -int fixed_ge(fixed_t a, fixed_t b) { return a >= b; } +i32 fixed_ge(fixed_t a, fixed_t b) { return a >= b; } -/* Unary operations */ fixed_t fixed_neg(fixed_t f) { return -f; } fixed_t fixed_abs(fixed_t f) { return (f < 0) ? -f : f; } - -/* Square root using Newton-Raphson method */ -fixed_t fixed_sqrt(fixed_t f) { - fixed_t x, prev; - - if (f <= 0) - return 0; - - x = f; - /* Newton-Raphson iteration: x = (x + f/x) / 2 */ - do { - prev = x; - x = fixed_div(fixed_add(x, fixed_div(f, x)), int_to_fixed(2)); - } while ( - fixed_gt(fixed_abs(fixed_sub(x, prev)), 1)); /* Precision to 1/65536 */ - - return x; -} - -/* Sine function using Taylor series */ -fixed_t fixed_sin(fixed_t f) { - fixed_t result, term, f_squared; - int i; - /* Normalize angle to [-π, π] */ - fixed_t pi2 = fixed_mul(FIXED_PI, int_to_fixed(2)); - while (fixed_gt(f, FIXED_PI)) - f = fixed_sub(f, pi2); - while (fixed_lt(f, fixed_neg(FIXED_PI))) - f = fixed_add(f, pi2); - - /* Taylor series: sin(x) = x - x³/3! + x⁵/5! - x⁷/7! + ... */ - result = f; - term = f; - f_squared = fixed_mul(f, f); - - /* Calculate first few terms for reasonable precision */ - for (i = 3; i <= 11; i += 2) { - term = fixed_mul(term, f_squared); - term = fixed_div(term, int_to_fixed(i * (i - 1))); - - if ((i / 2) % 2 == 0) { - result = fixed_add(result, term); - } else { - result = fixed_sub(result, term); - } - } - - return result; -} - -/* Cosine function using Taylor series */ -fixed_t fixed_cos(fixed_t f) { - /* cos(x) = 1 - x²/2! + x⁴/4! - x⁶/6! + ... */ - fixed_t result = FIXED_ONE; - fixed_t term = FIXED_ONE; - fixed_t f_squared = fixed_mul(f, f); - - int i; - for (i = 2; i <= 12; i += 2) { - term = fixed_mul(term, f_squared); - term = fixed_div(term, int_to_fixed(i * (i - 1))); - - if ((i / 2) % 2 == 0) { - result = fixed_add(result, term); - } else { - result = fixed_sub(result, term); - } - } - - return result; -} - -/* Tangent function */ -fixed_t fixed_tan(fixed_t f) { - fixed_t cos_val = fixed_cos(f); - if (cos_val == 0) - return 0; /* Handle undefined case */ - return fixed_div(fixed_sin(f), cos_val); -} - -/* Utility functions */ -fixed_t fixed_min(fixed_t a, fixed_t b) { return (a < b) ? a : b; } - -fixed_t fixed_max(fixed_t a, fixed_t b) { return (a > b) ? a : b; } - -fixed_t fixed_clamp(fixed_t f, fixed_t min_val, fixed_t max_val) { - if (f < min_val) - return min_val; - if (f > max_val) - return max_val; - return f; -} diff --git a/src/vm/fixed.h b/src/vm/fixed.h index 717705c..c48f99a 100644 --- a/src/vm/fixed.h +++ b/src/vm/fixed.h @@ -3,51 +3,34 @@ #include "common.h" -/* Q16.16 fixed-point type */ typedef i32 fixed_t; -/* Constants */ #define FIXED_ONE 0x00010000L /* 1.0 in Q16.16 */ #define FIXED_ZERO 0x00000000L /* 0.0 in Q16.16 */ #define FIXED_HALF 0x00008000L /* 0.5 in Q16.16 */ -#define FIXED_PI 0x0003243FL /* π ≈ 3.14159 */ -#define FIXED_E 0x0002B7E1L /* e ≈ 2.71828 */ +#define FIXED_PI 0x0003243FL /* 3.14159 */ +#define FIXED_E 0x0002B7E1L /* 2.71828 */ #define FIXED_MAX 0x7FFFFFFFL /* Maximum positive value */ #define FIXED_MIN 0x80000000L /* Minimum negative value */ -/* Conversion functions */ fixed_t int_to_fixed(i32 i); i32 fixed_to_int(fixed_t f); fixed_t float_to_fixed(f32 f); f32 fixed_to_float(fixed_t f); -/* Basic arithmetic operations */ fixed_t fixed_add(fixed_t a, fixed_t b); fixed_t fixed_sub(fixed_t a, fixed_t b); fixed_t fixed_mul(fixed_t a, fixed_t b); fixed_t fixed_div(fixed_t a, fixed_t b); -/* Comparison functions */ -int fixed_eq(fixed_t a, fixed_t b); -int fixed_ne(fixed_t a, fixed_t b); -int fixed_lt(fixed_t a, fixed_t b); -int fixed_le(fixed_t a, fixed_t b); -int fixed_gt(fixed_t a, fixed_t b); -int fixed_ge(fixed_t a, fixed_t b); +i32 fixed_eq(fixed_t a, fixed_t b); +i32 fixed_ne(fixed_t a, fixed_t b); +i32 fixed_lt(fixed_t a, fixed_t b); +i32 fixed_le(fixed_t a, fixed_t b); +i32 fixed_gt(fixed_t a, fixed_t b); +i32 fixed_ge(fixed_t a, fixed_t b); -/* Unary operations */ fixed_t fixed_neg(fixed_t f); fixed_t fixed_abs(fixed_t f); -/* Advanced math functions */ -fixed_t fixed_sqrt(fixed_t f); -fixed_t fixed_sin(fixed_t f); /* f in radians */ -fixed_t fixed_cos(fixed_t f); /* f in radians */ -fixed_t fixed_tan(fixed_t f); /* f in radians */ - -/* Utility functions */ -fixed_t fixed_min(fixed_t a, fixed_t b); -fixed_t fixed_max(fixed_t a, fixed_t b); -fixed_t fixed_clamp(fixed_t f, fixed_t min, fixed_t max); - -#endif /* FIXED_H */ +#endif diff --git a/test/paint.ul b/test/paint.ul index 1ae3af2..d6cc410 100644 --- a/test/paint.ul +++ b/test/paint.ul @@ -20,9 +20,7 @@ plex Screen implements Device { byte[] buffer; draw() { - unsafe { - write(this, this.buffer, this.buffer.length); - } + write(this, this.buffer, this.buffer.length); } } @@ -82,8 +80,6 @@ function set_color(int box_size, int bx, int by, int mx, int my, byte color) { if (my > bottom) return; selected_color = color; - - return; } /** @@ -97,22 +93,17 @@ function outline_swatch(Device screen, byte color, int x, int y) { rectangle(screen, bg_color, x, y, 20, 20); rectangle(screen, color, x + 2, y + 2, 17, 17); - return; } /** * Draw a rectangle */ function rectangle(Device screen, byte color, int x, int y, int width, int height) { - // we need unsafe because we are using pointers `.ptr` and `memset` directly - // unsafe takes the guardrails off and allows you to access/modify memory directly - unsafe { - int base = y * screen.width + x + screen.buffer.ptr + 4; - do (int i = height; i > 0; i--) { - int row = base + width; - memset(screen.buffer, row, color, width); - base += screen.width; - } - } - return; + int base = y * screen.width + x + screen.buffer.ptr + 4; + + do (int i = height; i > 0; i--) { + int row = base + width; + memset(screen.buffer, row, color, width); + base += screen.width; + } }