From: cassowarii Date: Fri, 10 Jul 2026 21:29:59 +0000 (-0700) Subject: list::iota, fix vm bug, project euler #5 X-Git-Url: https://git.cassowary.me/gitweb.cgi?a=commitdiff_plain;h=df2e4d7190e1c035012aad3bd34e6be15d409e31;p=sarabande.git list::iota, fix vm bug, project euler #5 --- diff --git a/sample/project_euler/pe01.sa b/sample/project_euler/pe01.sa index ed0cbc8..4b26267 100644 --- a/sample/project_euler/pe01.sa +++ b/sample/project_euler/pe01.sa @@ -6,16 +6,6 @@ def sum list { s } -def iota N { - let L = [] - let x = 1 - while x < N { - L.push x - x = x + 1 - } - L -} - -println sum iota(1000).filter => num { +println sum list::iota(1000).filter => num { [3, 5].any? => factor { num %% factor } } diff --git a/sample/project_euler/pe05.sa b/sample/project_euler/pe05.sa new file mode 100644 index 0000000..b5aed85 --- /dev/null +++ b/sample/project_euler/pe05.sa @@ -0,0 +1,18 @@ +def gcd a, b { + # Euclid's algorithm + if b == 0 { + a + } else { + gcd b, a % b + } +} + +def lcm nums { + let result = 1 + nums.each => num { + result = result * num // gcd(result, num) + } + result +} + +println lcm list::iota 1, 21 diff --git a/src/compile/emit.c b/src/compile/emit.c index 9b40754..f7ee340 100644 --- a/src/compile/emit.c +++ b/src/compile/emit.c @@ -436,6 +436,6 @@ void compile_op(sbVmCompiler *cm, sbAstOp op) { case AST_OP_INDEX: EMIT(BC_OP_INDEX); break; case AST_OP_DIVBY: EMIT(BC_OP_MOD, BC_LD_IMM); EARG(0); EMIT(BC_OP_EQ); break; default: - PANIC("unknown operation!\n"); + PANIC("unknown operation! (%lld / %c)", (long long)op, op); } } diff --git a/src/data/integer.c b/src/data/integer.c index db70adb..bee7706 100644 --- a/src/data/integer.c +++ b/src/data/integer.c @@ -136,6 +136,27 @@ hInteger sbInteger_diff(hInteger a, hInteger b) { PANIC("I haven't implemented this yet!"); } +flag sbInteger_lt(hInteger a, hInteger b) { + if (!is_bigint(a) && !is_bigint(b)) { + return a < b; + } + PANIC("I haven't implemented this yet!"); +} + +flag sbInteger_le(hInteger a, hInteger b) { + if (!is_bigint(a) && !is_bigint(b)) { + return a <= b; + } + PANIC("I haven't implemented this yet!"); +} + +flag sbInteger_eq(hInteger a, hInteger b) { + if (!is_bigint(a) && !is_bigint(b)) { + return a == b; + } + PANIC("I haven't implemented this yet!"); +} + double sbInteger_as_double(hInteger a) { if (!is_bigint(a)) { return (double)a; diff --git a/src/data/integer.h b/src/data/integer.h index 238d132..b7beed3 100644 --- a/src/data/integer.h +++ b/src/data/integer.h @@ -23,6 +23,12 @@ hInteger sbInteger_mul(hInteger a, hInteger b); hInteger sbInteger_floordiv(hInteger a, hInteger b); +flag sbInteger_lt(hInteger a, hInteger b); + +flag sbInteger_le(hInteger a, hInteger b); + +flag sbInteger_eq(hInteger a, hInteger b); + void sbInteger_fprint(FILE *out, hInteger a); usize sbInteger_snprint(char *buf, usize size, hInteger a); diff --git a/src/lib/lib.c b/src/lib/lib.c index b79a25e..23e0f48 100644 --- a/src/lib/lib.c +++ b/src/lib/lib.c @@ -56,7 +56,7 @@ void sbLib_resolve_method(hVm vm) { table_to_use = &g_float_methods; break; default: - PANIC("Have not implemented this method table yet!"); + PANIC("Have not implemented this method table yet! (%lld)", (long long)target->type); } sbLibMethod f = sbLibTable_find_method(table_to_use, method_name_val->symbol); diff --git a/src/lib/module.h b/src/lib/module.h index e76b073..65d2e3e 100644 --- a/src/lib/module.h +++ b/src/lib/module.h @@ -1,4 +1,6 @@ extern sbLibTable g_global_module; +extern sbLibTable g_list_module; void sbLib_loadmodule_global(); void sbLib_loadmodule_math(); +void sbLib_loadmodule_list(); diff --git a/src/lib/module/global.c b/src/lib/module/global.c index 2b4f986..52922e3 100644 --- a/src/lib/module/global.c +++ b/src/lib/module/global.c @@ -36,6 +36,9 @@ void sbLib_loadmodule_global() { REGISTER_VALUE(&g_string_namespace, "convert", &HVSYM(S_OP_TO_STRING)); REGISTER_VALUE(&g_global_module, "string", &HVMODULE(&g_string_namespace)); + sbLib_loadmodule_list(); + REGISTER_VALUE(&g_global_module, "list", &HVMODULE(&g_list_module)); + sbLib_loadmodule_math(); REGISTER_VALUE(&g_global_module, "math", &HVMODULE(&g_math_module)); } diff --git a/src/lib/module/list.c b/src/lib/module/list.c new file mode 100644 index 0000000..5845041 --- /dev/null +++ b/src/lib/module/list.c @@ -0,0 +1,50 @@ +#include "common.h" + +#include "lib/table.h" +#include "lib/sentinel.h" +#include "data/list.h" +#include "data/string.h" +#include "data/symbol.h" +#include "data/integer.h" +#include "vm/exec.h" + +sbLibTable g_list_module; + +static void iota(hVm vm, usize argc) { + if (argc != 1 && argc != 2) { + PANIC("list::iota takes 1 or 2 arguments"); + } + + hV *first = sbVm_pop(vm); + + hInteger min, max; + if (argc == 1) { + if (first->type != IT_INTEGER) { + PANIC("list::iota's argument must be an integer!"); + } + min = 0; + max = first->integer; + } else { + hV *second = sbVm_pop(vm); + if (first->type != IT_INTEGER || second->type != IT_INTEGER) { + PANIC("list::iota's arguments must be integers!"); + } + min = first->integer; + max = second->integer; + } + + hList result = sbList_new((usize)sbInteger_diff(max, min)); + hInteger count = min; + while (sbInteger_lt(count, max)) { + sbList_append(result, &HVINT(count)); + count = sbInteger_sum(count, 1); + } + + sbVm_push_immediate(vm, &HVLIST(result)); +} + +void sbLib_loadmodule_list() { + sbLibTable_initialize(&g_list_module, 16, FALSE); + REGISTER_VALUE(&g_list_module, "iota", &HVBUILTIN(iota)); + REGISTER_VALUE(&g_list_module, "convert", &HVSYM(S_OP_TO_LIST)); +} diff --git a/src/vm/exec.c b/src/vm/exec.c index 1e8ecb2..fd8d407 100644 --- a/src/vm/exec.c +++ b/src/vm/exec.c @@ -158,6 +158,13 @@ void return_from_block(hVm vm) { sbV_release(&vm->fp->locals[i]); } + /* move thing that is being returned to the xstack: if we were + * originally returning a local variable, we don't want it to get + * overwritten by a subsequent function call (and if we were + * already returning an immediate value, it does nothing) */ + ((hV*)(vm->xsp))[-1] = *((hV**)(vm->vsp))[-1]; + ((hV**)(vm->vsp))[-1] = &((hV*)(vm->xsp))[-1]; + sbVmStackFrame *frame = (sbVmStackFrame*)vm->fp; if (frame->return_addr == NULL) { @@ -242,6 +249,10 @@ hV *peek_stack(hVm vm, isize offset) { return ((hV**)(vm->vsp))[-offset - 1]; } +hV *peek_xstack(hVm vm, isize offset) { + return &((hV*)(vm->xsp))[-offset - 1]; +} + sbOpcode get_opcode(hVm vm) { if (vm->ip >= vm->fp->block_func.block->bytecode_end) PANIC("execution outside defined code area"); return *(vm->ip++); diff --git a/src/vm/exec.h b/src/vm/exec.h index bdda0f6..7229c9b 100644 --- a/src/vm/exec.h +++ b/src/vm/exec.h @@ -72,8 +72,8 @@ typedef struct sbVm { const u8 *ip; /* instruction pointer */ sbVmStackFrame *fp; /* frame pointer */ - u8 *vsp; /* stack pointer */ - u8 *xsp; /* rstack pointer */ + u8 *vsp; /* vstack pointer */ + u8 *xsp; /* xstack pointer */ u8 *rsp; /* rstack pointer */ usize stacksize; /* to detect overflow, save these */