Code cleanup
This commit is contained in:
parent
edb10db545
commit
80d9c67b9e
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -11,127 +11,127 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* 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 "<invalid-opcode>";
|
||||
|
|
@ -141,7 +141,6 @@ const char *opcode_to_string(Opcode op) {
|
|||
return name ? name : "<unknown-opcode>";
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#include "lexer.h"
|
||||
#include "compiler.h"
|
||||
#include "../../vm/common.h"
|
||||
#include "../../vm/opcodes.h"
|
||||
#include "../../vm/libc.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
128
src/vm/fixed.c
128
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue