Code cleanup

This commit is contained in:
zongor 2025-12-08 21:42:59 -08:00
parent edb10db545
commit 80d9c67b9e
9 changed files with 321 additions and 545 deletions

View File

@ -66,7 +66,6 @@ void mainloop() {
mouse_data.btn4 = 0; mouse_data.btn4 = 0;
break; break;
// Touch events (map to mouse_data as left-click equivalent)
case SDL_FINGERMOTION: case SDL_FINGERMOTION:
case SDL_FINGERDOWN: case SDL_FINGERDOWN:
case SDL_FINGERUP: { case SDL_FINGERUP: {
@ -77,8 +76,6 @@ void mainloop() {
mouse_data.x = (int)x; mouse_data.x = (int)x;
mouse_data.y = (int)y; 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.tfinger.fingerId == 0) {
if (event.type == SDL_FINGERDOWN || event.type == SDL_FINGERMOTION) { if (event.type == SDL_FINGERDOWN || event.type == SDL_FINGERMOTION) {
mouse_data.btn1 = 1; 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 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) { while (cycles_this_frame < max_cycles_per_frame) {
if (!step_vm(&vm)) { if (!step_vm(&vm)) {
emscripten_cancel_main_loop(); emscripten_cancel_main_loop();
@ -102,13 +98,12 @@ void mainloop() {
cycles_this_frame++; cycles_this_frame++;
} }
// Render only if the screen buffer was updated AND at a reasonable rate
if (screen_data.update) { if (screen_data.update) {
if (screen_data.renderer && screen_data.texture) { if (screen_data.renderer && screen_data.texture) {
SDL_RenderCopy(screen_data.renderer, screen_data.texture, NULL, NULL); SDL_RenderCopy(screen_data.renderer, screen_data.texture, NULL, NULL);
SDL_RenderPresent(screen_data.renderer); 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; return false;
} }
// Read VM state
if (fread(&vm->pc, sizeof(u32), 1, file) != 1 || if (fread(&vm->pc, sizeof(u32), 1, file) != 1 ||
fread(&vm->cp, sizeof(u32), 1, file) != 1 || fread(&vm->cp, sizeof(u32), 1, file) != 1 ||
fread(&vm->fp, 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; return false;
} }
// Read code section
if (fread(vm->code, 1, vm->cp, file) != vm->cp) { if (fread(vm->code, 1, vm->cp, file) != vm->cp) {
printf("Failed to read code section\n"); printf("Failed to read code section\n");
fclose(file); fclose(file);
return false; return false;
} }
// Read memory section
if (fread(vm->memory, 1, vm->mp, file) != vm->mp) { if (fread(vm->memory, 1, vm->mp, file) != vm->mp) {
printf("Failed to read memory section\n"); printf("Failed to read memory section\n");
fclose(file); fclose(file);
@ -187,7 +179,6 @@ int main(int argc, char **argv) {
vm_register_device(&vm, "/dev/term/0", "terminal", &console_data, vm_register_device(&vm, "/dev/term/0", "terminal", &console_data,
&console_device_ops, 4); &console_device_ops, 4);
// Set up main loop
emscripten_set_main_loop(mainloop, 0, 1); emscripten_set_main_loop(mainloop, 0, 1);
return 0; return 0;
} }

View File

@ -11,9 +11,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
/* FIXME: technically this is not allowed in C89 find another way */
const char *opcode_to_string(Opcode op) { const char *opcode_to_string(Opcode op) {
static const char *names[] = { static const char *names[] = {[OP_EXIT] = "exit",
[OP_EXIT] = "exit",
[OP_JMP] = "jump", [OP_JMP] = "jump",
[OP_JMPF] = "jump_if_flag", [OP_JMPF] = "jump_if_flag",
[OP_CALL] = "call", [OP_CALL] = "call",
@ -141,7 +141,6 @@ const char *opcode_to_string(Opcode op) {
return name ? name : "<unknown-opcode>"; return name ? name : "<unknown-opcode>";
} }
void emit_op(VM *vm, u8 byte) { void emit_op(VM *vm, u8 byte) {
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
printf("code[%d] = %s\n", vm->cp, opcode_to_string(byte)); printf("code[%d] = %s\n", vm->cp, opcode_to_string(byte));
@ -187,8 +186,10 @@ u32 symbol_table_add(SymbolTable *table, Symbol s) {
if (!resize_or_check_size(table)) { if (!resize_or_check_size(table)) {
fprintf(stderr, fprintf(stderr,
"Error: Symbol table is out of memory! This is likely because you built this in static mode." "Error: Symbol table is out of memory! This is likely because you "
"if you built using malloc, that means your computer is out of memory. Close a few tabs in your web browser and try again." "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", "Count was %d, while capacity was %d\n",
table->count, table->capacity); table->count, table->capacity);
exit(1); exit(1);
@ -212,7 +213,8 @@ u32 symbol_table_add(SymbolTable *table, Symbol s) {
u32 get_ref(SymbolTable *st, const char *name, u32 length) { u32 get_ref(SymbolTable *st, const char *name, u32 length) {
Symbol *sym = symbol_table_lookup(st, name, length); Symbol *sym = symbol_table_lookup(st, name, length);
if (!sym) { 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); exit(1);
return 0; return 0;
} }
@ -232,15 +234,15 @@ u32 get_ptr(Token token, SymbolTable *st) {
char *endptr; char *endptr;
u32 out = (u32)strtoul(token.start, &endptr, 10); u32 out = (u32)strtoul(token.start, &endptr, 10);
if (endptr == token.start || *endptr != '\0') { if (endptr == token.start || *endptr != '\0') {
fprintf(stderr, "Invalid decimal literal: '%.*s'\n", token.length, fprintf(stderr, "Invalid decimal literal at line %d: %.*s\n", token.line,
token.start); token.length, token.start);
exit(1); exit(1);
} }
return out; return out;
} }
fprintf(stderr, "Error: Not a pointer or symbol '%.*s'\n", token.length, fprintf(stderr, "Error: Not a pointer or symbol at line %d: %.*s\n",
token.start); token.line, token.length, token.start);
exit(1); exit(1);
} }
@ -254,8 +256,8 @@ u32 get_reg(Token token, SymbolTable *st) {
return atoi(token.start); return atoi(token.start);
} }
fprintf(stderr, "Error: Not a register or symbol '%.*s'\n", token.length, fprintf(stderr, "Error: Not a register or symbol at line %d: %.*s\n",
token.start); token.line, token.length, token.start);
exit(1); exit(1);
} }
@ -439,16 +441,16 @@ bool define_global(VM *vm, SymbolTable *st) {
case '\\': case '\\':
case '"': case '"':
case '\'': case '\'':
break; // Keep as-is break;
default: default:
i--; // Rewind for unknown escapes i--; /* Rewind for unknown escapes */
} }
} }
write_u8(vm, memory, addr + 4 + len, c); write_u8(vm, memory, addr + 4 + len, c);
len++; len++;
} }
u32 size = len + 5; // 4 (len) + dst_len + 1 (null) u32 size = len + 5; /* 4 (len) + dst_len + 1 (null) */
s.size = size; s.size = size;
vm->mp += size; vm->mp += size;
@ -610,9 +612,8 @@ void define_branch(VM *vm, SymbolTable *st) {
int get_instruction_byte_size(const char *opname) { int get_instruction_byte_size(const char *opname) {
// Return (1 + 1)
if (strcmp(opname, "return") == 0) { 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 || 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, "store_indirect_32") == 0 ||
strcmp(opname, "real_to_nat") == 0 || strcmp(opname, "nat_to_int") == 0 || strcmp(opname, "real_to_nat") == 0 || strcmp(opname, "nat_to_int") == 0 ||
strcmp(opname, "int_to_nat") == 0 || strcmp(opname, "int_to_nat") == 0 ||
strcmp(opname, "string_length") == 0 || strcmp(opname, "string_length") == 0 || strcmp(opname, "memset") == 0 ||
strcmp(opname, "memset") == 0 || strcmp(opname, "memset") == 0 || strcmp(opname, "memset") == 0 || strcmp(opname, "memset_8") == 0 ||
strcmp(opname, "memset_8") == 0 || strcmp(opname, "memset_16") == 0 || strcmp(opname, "memset_16") == 0 ||
strcmp(opname, "register_move") == 0 || strcmp(opname, "malloc") == 0) { strcmp(opname, "register_move") == 0 || strcmp(opname, "malloc") == 0) {
return 3; return 3;
} }
// Register_register_register opcodes (4 bytes: 1 + 3)
if (strcmp(opname, "add_int") == 0 || strcmp(opname, "sub_int") == 0 || if (strcmp(opname, "add_int") == 0 || strcmp(opname, "sub_int") == 0 ||
strcmp(opname, "mul_int") == 0 || strcmp(opname, "div_int") == 0 || strcmp(opname, "mul_int") == 0 || strcmp(opname, "div_int") == 0 ||
strcmp(opname, "add_nat") == 0 || strcmp(opname, "sub_nat") == 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; return 4;
} }
// (5 bytes: 1 + 4)
if (strcmp(opname, "halt") == 0 || strcmp(opname, "jump_if_flag") == 0 || if (strcmp(opname, "halt") == 0 || strcmp(opname, "jump_if_flag") == 0 ||
strcmp(opname, "jump") == 0) { strcmp(opname, "jump") == 0) {
return 5; return 5;
} }
// Load, Load_immediate (6 bytes: 1 + 1 + 4)
if (strcmp(opname, "load_absolute_32") == 0 || if (strcmp(opname, "load_absolute_32") == 0 ||
strcmp(opname, "load_immediate") == 0 || strcmp(opname, "load_immediate") == 0 ||
strcmp(opname, "load_address") == 0 || strcmp(opname, "load_address") == 0 ||
@ -672,7 +670,6 @@ int get_instruction_byte_size(const char *opname) {
return 6; return 6;
} }
// jump compare (7 bytes: 1 + 4 + 1 + 1)
if (strcmp(opname, "jump_eq_int") == 0 || if (strcmp(opname, "jump_eq_int") == 0 ||
strcmp(opname, "jump_neq_int") == 0 || strcmp(opname, "jump_neq_int") == 0 ||
strcmp(opname, "jump_gt_int") == 0 || strcmp(opname, "jump_gt_int") == 0 ||
@ -710,9 +707,11 @@ int get_instruction_byte_size(const char *opname) {
while (token.type != TOKEN_SEMICOLON) { \ while (token.type != TOKEN_SEMICOLON) { \
token = next_token(); \ 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)); */\ /*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); \ vm->cp += get_instruction_byte_size(op); \
} while(0); } while (0);
/** /**
* Build the symbol table and calculate the types/size/offsets of all values. * 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; continue;
} }
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
printf("-- %.*s --\n", token.length, token.start); printf("-- %.*s --\n", token.length, token.start);
#endif #endif
if (token.type == TOKEN_IDENTIFIER) { 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)) { if (strleq(token.start, "exit", token.length)) {
vm->cp++; vm->cp++;
@ -783,9 +782,9 @@ void build_symbol_table(VM *vm, char *source, SymbolTable *st) {
next_token(); next_token();
vm->cp += 4; vm->cp += 4;
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
printf("code[%d] = exit\n", vm->cp); printf("code[%d] = exit\n", vm->cp);
#endif #endif
next_token_is(TOKEN_SEMICOLON); next_token_is(TOKEN_SEMICOLON);
} else if (strleq(token.start, "call", token.length)) { } else if (strleq(token.start, "call", token.length)) {
@ -812,9 +811,9 @@ void build_symbol_table(VM *vm, char *source, SymbolTable *st) {
get_reg(next, st); get_reg(next, st);
vm->cp++; vm->cp++;
} }
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
printf("code[%d] = call\n", vm->cp); printf("code[%d] = call\n", vm->cp);
#endif #endif
continue; continue;
} else if (strleq(token.start, "syscall", token.length)) { } else if (strleq(token.start, "syscall", token.length)) {
@ -829,9 +828,9 @@ void build_symbol_table(VM *vm, char *source, SymbolTable *st) {
vm->cp++; vm->cp++;
next = next_token(); next = next_token();
} }
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
printf("code[%d] = syscall\n", vm->cp); printf("code[%d] = syscall\n", vm->cp);
#endif #endif
continue; continue;
FAKE_OP("load_immediate") FAKE_OP("load_immediate")
FAKE_OP("load_address") FAKE_OP("load_address")
@ -919,7 +918,7 @@ void build_symbol_table(VM *vm, char *source, SymbolTable *st) {
FAKE_OP("string_to_nat") FAKE_OP("string_to_nat")
FAKE_OP("string_to_real") FAKE_OP("string_to_real")
} else { } else {
// some other identifier /* some other identifier */
printf("Unknown id at line %d: %.*s\n", token.line, token.length, printf("Unknown id at line %d: %.*s\n", token.line, token.length,
token.start); token.start);
exit(1); exit(1);
@ -944,17 +943,17 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) {
if (token.type != TOKEN_EOF) { if (token.type != TOKEN_EOF) {
if (token.type == TOKEN_KEYWORD_GLOBAL) { if (token.type == TOKEN_KEYWORD_GLOBAL) {
// ignore, already processed /* ignore, already processed */
next_token(); // type next_token(); /* type */
next_token(); // var next_token(); /* var */
next_token(); // eq next_token(); /* eq */
next_token(); // value next_token(); /* value */
next_token(); // ; next_token(); /* ; */
continue; continue;
} }
if (token.type == TOKEN_KEYWORD_FN) { if (token.type == TOKEN_KEYWORD_FN) {
// ignore, already processed /* ignore, already processed */
Token next = next_token(); Token next = next_token();
while (next.type != TOKEN_RPAREN) { while (next.type != TOKEN_RPAREN) {
next = next_token(); 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_U8 || token.type == TOKEN_TYPE_U16 ||
token.type == TOKEN_TYPE_NAT || token.type == TOKEN_TYPE_REAL || token.type == TOKEN_TYPE_NAT || token.type == TOKEN_TYPE_REAL ||
token.type == TOKEN_TYPE_STR) { token.type == TOKEN_TYPE_STR) {
// ignore, already processed /* ignore, already processed */
next_token(); // type next_token(); /* type */
next_token(); // var next_token(); /* var */
next_token(); // reg next_token(); /* reg */
next_token(); // ; next_token(); /* ; */
continue; continue;
} }
if (token.type == TOKEN_KEYWORD_LOOP || token.type == TOKEN_KEYWORD_IF || 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_ELSE || token.type == TOKEN_KEYWORD_DO ||
token.type == TOKEN_KEYWORD_FOR) { token.type == TOKEN_KEYWORD_FOR) {
// ignore, already processed /* ignore, already processed */
next_token(); // id next_token(); /* id */
} }
if (token.type == TOKEN_KEYWORD_RETURN) { if (token.type == TOKEN_KEYWORD_RETURN) {
@ -1001,11 +1000,11 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) {
continue; continue;
} }
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
printf("-- %.*s --\n", token.length, token.start); printf("-- %.*s --\n", token.length, token.start);
#endif #endif
if (token.type == TOKEN_IDENTIFIER) { 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)) { if (strleq(token.start, "exit", token.length)) {
emit_op(vm, OP_EXIT); emit_op(vm, OP_EXIT);
@ -1041,9 +1040,9 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) {
vm->code[arg_pos] = arg_count; vm->code[arg_pos] = arg_count;
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
printf("^code[%d] = %d\n", arg_pos, arg_count); printf("^code[%d] = %d\n", arg_pos, arg_count);
#endif #endif
next = next_token(); next = next_token();
if (next.type == TOKEN_SEMICOLON) { if (next.type == TOKEN_SEMICOLON) {
@ -1085,8 +1084,9 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) {
vm->cp += 4; vm->cp += 4;
next = next_token(); next = next_token();
while (next.type != TOKEN_SEMICOLON && next.type != TOKEN_ARROW_RIGHT) { while (next.type != TOKEN_SEMICOLON &&
u8 arg =get_reg(next, st); next.type != TOKEN_ARROW_RIGHT) {
u8 arg = get_reg(next, st);
emit_byte(vm, arg); emit_byte(vm, arg);
vm->cp++; vm->cp++;
next = next_token(); next = next_token();
@ -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_nat", token.length)) {
} else if (strleq(token.start, "string_to_real", token.length)) { } else if (strleq(token.start, "string_to_real", token.length)) {
} else { } else {
// some other identifier /* some other identifier */
printf("Unknown id at line %d: %.*s\n", token.line, token.length, printf("Unknown id at line %d: %.*s\n", token.line, token.length,
token.start); token.start);
exit(1); exit(1);

View File

@ -1,5 +1,7 @@
#include "lexer.h"
#include "compiler.h" #include "compiler.h"
#include "../../vm/common.h" #include "../../vm/common.h"
#include "../../vm/opcodes.h"
#include "../../vm/libc.h" #include "../../vm/libc.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.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); 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 { typedef struct {
Token current; Token current;
Token previous; Token previous;
@ -420,18 +327,18 @@ void number(Compiler *c, VM *vm) {
c->last = Symbol{ .type=parser.previous.type }; c->last = Symbol{ .type=parser.previous.type };
switch (parser.previous.type) { switch (parser.previous.type) {
case TOKEN_INT_LITERAL: { case TOKEN_LITERAL_INT: {
char *endptr; char *endptr;
i32 value = (i32)strtol(parser.previous.start, &endptr, 10); i32 value = (i32)strtol(parser.previous.start, &endptr, 10);
emit_u32(vm, value); emit_u32(vm, value);
return; return;
} }
case TOKEN_UINT_LITERAL: { case TOKEN_LITERAL_NAT: {
long value = atol(parser.previous.start); long value = atol(parser.previous.start);
emit_u32(vm, value); emit_u32(vm, value);
return; return;
} }
case TOKEN_FLOAT_LITERAL: { case TOKEN_LITERAL_REAL: {
float value = atof(parser.previous.start); float value = atof(parser.previous.start);
fixed_t fvalue = float_to_fixed(value); fixed_t fvalue = float_to_fixed(value);
emit_u32(vm, fvalue); emit_u32(vm, fvalue);
@ -454,10 +361,10 @@ static void unary(Compiler *c, VM *vm) {
switch (operatorType) { switch (operatorType) {
case TOKEN_MINUS: { case TOKEN_MINUS: {
switch (c->last.type) { switch (c->last.type) {
case TOKEN_UINT_LITERAL: case TOKEN_LITERAL_NAT:
emit_opcode(vm, OP_NEG_UINT); emit_opcode(vm, OP_NEG_NAT);
case TOKEN_FLOAT_LITERAL: case TOKEN_LITERAL_REAL:
emit_opcode(vm, OP_NEG_FLOAT); emit_opcode(vm, OP_NEG_REAL);
default: default:
emit_opcode(vm, OP_NEG_INT); emit_opcode(vm, OP_NEG_INT);
} }
@ -472,7 +379,7 @@ static void unary(Compiler *c, VM *vm) {
} }
static void emitHalt(Compiler *c, VM *vm) { static void emitHalt(Compiler *c, VM *vm) {
emit_opcode(vm, OP_HALT); emit_opcode(vm, OP_EXIT);
advance(); advance();
number(c, vm); number(c, vm);
} }

View File

@ -3,7 +3,6 @@
#import "../../vm/common.h" #import "../../vm/common.h"
typedef enum { GLOBAL, LOCAL } ScopeType;
typedef enum { typedef enum {
VOID, VOID,
BOOL, BOOL,
@ -33,6 +32,8 @@ typedef struct symbol_s Symbol;
typedef struct symbol_tab_s SymbolTable; typedef struct symbol_tab_s SymbolTable;
typedef struct names_tab_s NamesTable; typedef struct names_tab_s NamesTable;
typedef struct plex_fields_tab_s PlexFieldsTable; typedef struct plex_fields_tab_s PlexFieldsTable;
typedef struct scope_s Scope;
typedef struct scope_tab_s ScopeTable;
struct value_type_s { struct value_type_s {
SymbolType type; SymbolType type;
@ -65,7 +66,6 @@ struct array_def_s {
struct symbol_s { struct symbol_s {
u32 name; u32 name;
ValueType type; ValueType type;
ScopeType scope;
union { union {
u32 local; // register u32 local; // register
u32 global; // address u32 global; // address
@ -103,14 +103,20 @@ struct names_tab_s {
u32 capacity; u32 capacity;
}; };
/**
* FIXME:
* Symbols need to be inside a scope so we can have duplicates
*/
struct symbol_tab_s { struct symbol_tab_s {
Symbol *symbols; Symbol *symbols;
u32 count; u32 count;
u32 capacity; u32 capacity;
}; };
struct scope_s {
SymbolTable table;
};
struct scope_tab_s {
Scope *scopes;
u32 count;
u32 capacity;
};
#endif #endif

View File

@ -1,8 +1,5 @@
/* fixed.c - Q16.16 Fixed-Point Math Implementation */
#include "fixed.h" #include "fixed.h"
/* Conversion functions */
fixed_t int_to_fixed(i32 i) { return i << 16; } fixed_t int_to_fixed(i32 i) { return i << 16; }
i32 fixed_to_int(fixed_t f) { return f >> 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_sub(fixed_t a, fixed_t b) { return a - b; }
fixed_t fixed_mul(fixed_t a, fixed_t b) { fixed_t fixed_mul(fixed_t a, fixed_t b) {
/* Extract high and low parts */
i32 a_hi = a >> 16; i32 a_hi = a >> 16;
u32 a_lo = (u32)a & 0xFFFFU; u32 a_lo = (u32)a & 0xFFFFU;
i32 b_hi = b >> 16; i32 b_hi = b >> 16;
u32 b_lo = (u32)b & 0xFFFFU; u32 b_lo = (u32)b & 0xFFFFU;
/* Compute partial products */ i32 p0 = (i32)(a_lo * b_lo) >> 16;
i32 p0 = (i32)(a_lo * b_lo) >> 16; /* Low * Low */ i32 p1 = a_hi * (i32)b_lo;
i32 p1 = a_hi * (i32)b_lo; /* High * Low */ i32 p2 = (i32)a_lo * b_hi;
i32 p2 = (i32)a_lo * b_hi; /* Low * High */ i32 p3 = (a_hi * b_hi) << 16;
i32 p3 = (a_hi * b_hi) << 16; /* High * High */
/* Combine results */
return p0 + p1 + p2 + p3; return p0 + p1 + p2 + p3;
} }
fixed_t fixed_div(fixed_t a, fixed_t b) { fixed_t fixed_div(fixed_t a, fixed_t b) {
int negative; i32 negative;
u32 ua, ub, quotient, remainder; u32 ua, ub, quotient, remainder;
int i; i32 i;
if (b == 0) if (b == 0)
return 0; /* Handle division by zero */ return 0;
/* Determine sign */
negative = ((a < 0) ^ (b < 0)); negative = ((a < 0) ^ (b < 0));
/* Work with absolute values */
ua = (a < 0) ? -a : a; ua = (a < 0) ? -a : a;
ub = (b < 0) ? -b : b; ub = (b < 0) ? -b : b;
/* Perform division using long division in base 2^16 */
quotient = 0; quotient = 0;
remainder = 0; remainder = 0;
@ -71,111 +62,18 @@ fixed_t fixed_div(fixed_t a, fixed_t b) {
return negative ? -(i32)quotient : (i32)quotient; 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_neg(fixed_t f) { return -f; }
fixed_t fixed_abs(fixed_t f) { return (f < 0) ? -f : 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;
}

View File

@ -3,51 +3,34 @@
#include "common.h" #include "common.h"
/* Q16.16 fixed-point type */
typedef i32 fixed_t; typedef i32 fixed_t;
/* Constants */
#define FIXED_ONE 0x00010000L /* 1.0 in Q16.16 */ #define FIXED_ONE 0x00010000L /* 1.0 in Q16.16 */
#define FIXED_ZERO 0x00000000L /* 0.0 in Q16.16 */ #define FIXED_ZERO 0x00000000L /* 0.0 in Q16.16 */
#define FIXED_HALF 0x00008000L /* 0.5 in Q16.16 */ #define FIXED_HALF 0x00008000L /* 0.5 in Q16.16 */
#define FIXED_PI 0x0003243FL /* π ≈ 3.14159 */ #define FIXED_PI 0x0003243FL /* 3.14159 */
#define FIXED_E 0x0002B7E1L /* e ≈ 2.71828 */ #define FIXED_E 0x0002B7E1L /* 2.71828 */
#define FIXED_MAX 0x7FFFFFFFL /* Maximum positive value */ #define FIXED_MAX 0x7FFFFFFFL /* Maximum positive value */
#define FIXED_MIN 0x80000000L /* Minimum negative value */ #define FIXED_MIN 0x80000000L /* Minimum negative value */
/* Conversion functions */
fixed_t int_to_fixed(i32 i); fixed_t int_to_fixed(i32 i);
i32 fixed_to_int(fixed_t f); i32 fixed_to_int(fixed_t f);
fixed_t float_to_fixed(f32 f); fixed_t float_to_fixed(f32 f);
f32 fixed_to_float(fixed_t f); f32 fixed_to_float(fixed_t f);
/* Basic arithmetic operations */
fixed_t fixed_add(fixed_t a, fixed_t b); fixed_t fixed_add(fixed_t a, fixed_t b);
fixed_t fixed_sub(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_mul(fixed_t a, fixed_t b);
fixed_t fixed_div(fixed_t a, fixed_t b); fixed_t fixed_div(fixed_t a, fixed_t b);
/* Comparison functions */ i32 fixed_eq(fixed_t a, fixed_t b);
int fixed_eq(fixed_t a, fixed_t b); i32 fixed_ne(fixed_t a, fixed_t b);
int fixed_ne(fixed_t a, fixed_t b); i32 fixed_lt(fixed_t a, fixed_t b);
int fixed_lt(fixed_t a, fixed_t b); i32 fixed_le(fixed_t a, fixed_t b);
int fixed_le(fixed_t a, fixed_t b); i32 fixed_gt(fixed_t a, fixed_t b);
int fixed_gt(fixed_t a, fixed_t b); i32 fixed_ge(fixed_t a, fixed_t b);
int fixed_ge(fixed_t a, fixed_t b);
/* Unary operations */
fixed_t fixed_neg(fixed_t f); fixed_t fixed_neg(fixed_t f);
fixed_t fixed_abs(fixed_t f); fixed_t fixed_abs(fixed_t f);
/* Advanced math functions */ #endif
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 */

View File

@ -20,10 +20,8 @@ plex Screen implements Device {
byte[] buffer; byte[] buffer;
draw() { draw() {
unsafe {
write(this, this.buffer, this.buffer.length); write(this, this.buffer, this.buffer.length);
} }
}
} }
plex Mouse implements Device { plex Mouse implements Device {
@ -82,8 +80,6 @@ function set_color(int box_size, int bx, int by, int mx, int my, byte color) {
if (my > bottom) return; if (my > bottom) return;
selected_color = color; 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, bg_color, x, y, 20, 20);
rectangle(screen, color, x + 2, y + 2, 17, 17); rectangle(screen, color, x + 2, y + 2, 17, 17);
return;
} }
/** /**
* Draw a rectangle * Draw a rectangle
*/ */
function rectangle(Device screen, byte color, int x, int y, int width, int height) { 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; int base = y * screen.width + x + screen.buffer.ptr + 4;
do (int i = height; i > 0; i--) { do (int i = height; i > 0; i--) {
int row = base + width; int row = base + width;
memset(screen.buffer, row, color, width); memset(screen.buffer, row, color, width);
base += screen.width; base += screen.width;
} }
}
return;
} }