list::iota, fix vm bug, project euler #5
authorcassowarii <cassowary@cassowary.me>
Fri, 10 Jul 2026 21:29:59 +0000 (14:29 -0700)
committercassowarii <cassowary@cassowary.me>
Fri, 10 Jul 2026 21:29:59 +0000 (14:29 -0700)
sample/project_euler/pe01.sa
sample/project_euler/pe05.sa [new file with mode: 0644]
src/compile/emit.c
src/data/integer.c
src/data/integer.h
src/lib/lib.c
src/lib/module.h
src/lib/module/global.c
src/lib/module/list.c [new file with mode: 0644]
src/vm/exec.c
src/vm/exec.h

index ed0cbc8..4b26267 100644 (file)
@@ -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 (file)
index 0000000..b5aed85
--- /dev/null
@@ -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
index 9b40754..f7ee340 100644 (file)
@@ -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);
   }
 }
index db70adb..bee7706 100644 (file)
@@ -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;
index 238d132..b7beed3 100644 (file)
@@ -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);
index b79a25e..23e0f48 100644 (file)
@@ -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);
index e76b073..65d2e3e 100644 (file)
@@ -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();
index 2b4f986..52922e3 100644 (file)
@@ -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 (file)
index 0000000..5845041
--- /dev/null
@@ -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));
+}
index 1e8ecb2..fd8d407 100644 (file)
@@ -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++);
index bdda0f6..7229c9b 100644 (file)
@@ -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 */