From: cassowarii Date: Tue, 30 Jun 2026 05:08:56 +0000 (-0700) Subject: forward jumps! now if and while work X-Git-Url: https://git.cassowary.me/gitweb.cgi?a=commitdiff_plain;h=953434306856ea92bc12bdd5da777aceadeebf96;p=sarabande.git forward jumps! now if and while work --- diff --git a/src/compile/emit.c b/src/compile/emit.c index 209c8c0..e37f528 100644 --- a/src/compile/emit.c +++ b/src/compile/emit.c @@ -35,7 +35,7 @@ void sbEmit_compile_program(sbVmProgram *vp, sbIrProgram *ir) { void emit_arg(sbVmCompiler *cm, usize number) { printf(" arg %zu\n", number); u8 buf[9]; - if (number < 256) { + if (number < 253) { buf[0] = number; sbVmCompiler_write_code(cm, buf, 1); } else if (number < 65536) { @@ -79,11 +79,29 @@ void compile_chunk(sbVmCompiler *cm, sbIrChunk *chunk) { EMIT(BC_NUMARG); EARG(chunk->num_args); } + + EMIT(BC_ALLOC_VARS); + EARG(chunk->variable_count); + for (int i = 0; i < nstmts; i++) { sbIrStmt *stmt = ((sbIrStmt**)chunk->stmts.data)[i]; - compile_stmt(cm, stmt); } + + /* Go back and fill in locations for forward jumps, whose + * positions we now know. */ + usize nlabelpos = cm->label_positions.size / sizeof(struct labelpos); + for (int i = 0; i < nlabelpos; i++) { + struct labelpos lp = ((struct labelpos*)cm->label_positions.data)[i]; + u8 location_bytes[4]; + u32 position = lp.label->block_position; + printf("now we know that the jump at %d should go to %d\n", lp.offset - 2, position); + location_bytes[0] = (position >> 24) & 0xFF; + location_bytes[1] = (position >> 16) & 0xFF; + location_bytes[2] = (position >> 8) & 0xFF; + location_bytes[3] = (position >> 0) & 0xFF; + sbVmCompiler_overwrite_code_at(cm, lp.offset, location_bytes, 4); + } } /* when compiling one line at a time, we don't know the position @@ -91,6 +109,8 @@ void compile_chunk(sbVmCompiler *cm, sbIrChunk *chunk) { * address, and say "please put the address of this label here later!" */ void record_labelpos(sbVmCompiler *cm, sbIrLabel *label, u32 offset) { struct labelpos lp = { + .label = label, + .offset = offset, }; sbBuffer_append(&cm->label_positions, &lp, sizeof(struct labelpos)); @@ -104,20 +124,28 @@ void compile_stmt(sbVmCompiler *cm, sbIrStmt *stmt) { EMIT(BC_POP); break; case IR_S_JUMP: - if (stmt->jump.label->found_yet) { - if (stmt->jump.condition == NULL) { - EMIT(BC_JMP); + if (stmt->jump.condition == NULL) { + EMIT(BC_JMP); + } else { + compile_expr(cm, stmt->jump.condition); + printf("%3zu ", sbVmCompiler_get_position(cm)); + if (stmt->jump.inverted) { + EMIT(BC_JF); } else { - compile_expr(cm, stmt->jump.condition); - if (stmt->jump.inverted) { - EMIT(BC_JF); - } else { - EMIT(BC_JT); - } + EMIT(BC_JT); } + } + if (stmt->jump.label->found_yet) { EARG(stmt->jump.label->block_position); } else { - printf("haven't implemented forward jump yet!\n"); + printf("\n"); + EMIT(BC_VLONG_NUM); + /* we have to remember to come back and fill in the address later when we + * know where this label is! */ + record_labelpos(cm, stmt->jump.label, sbVmCompiler_get_position(cm)); + /* leave behind four zeroes at this offset that we can later put the + * address into */ + EMIT(0, 0, 0, 0); } break; case IR_S_LABEL: diff --git a/src/data/operations.c b/src/data/operations.c index ed117b9..4ca5827 100644 --- a/src/data/operations.c +++ b/src/data/operations.c @@ -14,7 +14,7 @@ hV sbV_sub(const hV *a, const hV *b) { if (a->type == IT_INTEGER && b->type == IT_INTEGER) { return sbV_int(sbInteger_diff(a->integer, b->integer)); } else { - PANIC("todo"); + PANIC("todo (subtract type %llu minus %llu)", a->type, b->type); } } diff --git a/src/data/value.h b/src/data/value.h index 5cd07e1..b6bc921 100644 --- a/src/data/value.h +++ b/src/data/value.h @@ -7,6 +7,7 @@ #define HVSTR(s) ((hV) { .type = IT_STRING, .string = OBJSL(s) }) #define HVBOOL(b) ((hV) { .type = IT_BOOLEAN, .boolean = b }) #define HVFUNC(i) ((hV) { .type = IT_FUNCTION, .data = i }) +#define HVNIL ((hV) { .type = IT_NIL }) typedef u64 hHash; typedef u64 hString; diff --git a/src/vm/block.c b/src/vm/block.c index 804f476..202b09f 100644 --- a/src/vm/block.c +++ b/src/vm/block.c @@ -25,6 +25,11 @@ void sbVmCompiler_write_code(sbVmCompiler *cm, const u8 *data, usize length) { sbBuffer_append(&cm->bytecode, data, length); } +void sbVmCompiler_overwrite_code_at(sbVmCompiler *cm, usize offset, const u8 *data, usize length) { + if (offset + length > cm->bytecode.size) PANIC("buffer overflow with overwrite_code_at!"); + memcpy(&cm->bytecode.data[offset], data, length); +} + usize sbVmCompiler_get_position(sbVmCompiler *cm) { return cm->bytecode.size; } diff --git a/src/vm/block.h b/src/vm/block.h index 2e63326..c3e3745 100644 --- a/src/vm/block.h +++ b/src/vm/block.h @@ -43,6 +43,8 @@ void sbVmCompiler_deinitialize(sbVmCompiler *pb); void sbVmCompiler_write_code(sbVmCompiler *pb, const u8 *data, usize length); +void sbVmCompiler_overwrite_code_at(sbVmCompiler *cm, usize offset, const u8 *data, usize length); + usize sbVmCompiler_get_position(sbVmCompiler *cm); void sbVmCompiler_add_constant(sbVmCompiler *pb, hV *constant); diff --git a/src/vm/exec.c b/src/vm/exec.c index ea50f2b..6491a0c 100644 --- a/src/vm/exec.c +++ b/src/vm/exec.c @@ -165,7 +165,7 @@ u64 get_param(hVm vm) { /* execute one instruction! wow! */ void execute_instruction(hVm vm) { sbOpcode op = get_opcode(vm); - u32 param; + u64 param; hV *v, *w, res; switch (op) { @@ -195,6 +195,9 @@ void execute_instruction(hVm vm) { param = get_param(vm); push_stack(vm, &HVFUNC(param)); return; + case BC_LD_NIL: + push_stack(vm, &HVNIL); + return; case BC_ST_VAR: param = get_param(vm); v = peek_stack(vm, 0);