LISTS in code!! wow!! so cool!!!
authorcassowarii <cassowary@cassowary.me>
Wed, 1 Jul 2026 00:58:53 +0000 (17:58 -0700)
committercassowarii <cassowary@cassowary.me>
Wed, 1 Jul 2026 00:58:53 +0000 (17:58 -0700)
src/compile/emit.c
src/compile/ir.c
src/compile/ir.h
src/data/list.h
src/data/value.c
src/data/value.h
src/parse/scanner.c
src/vm/bytecode.h
src/vm/exec.c
src/vm/operations.c
src/vm/operations.h

index fed66a9..46847d9 100644 (file)
@@ -180,10 +180,20 @@ void compile_stmt(sbVmCompiler *cm, sbIrStmt *stmt) {
   }
 }
 
+void compile_list(sbVmCompiler *cm, sbIrExpr *expr) {
+  sbIrExpr *considering = expr;
+  usize count = 0;
+  while (considering) {
+    count ++;
+    compile_expr(cm, considering->list.this);
+    considering = considering->list.next;
+  }
+  EMIT(BC_LD_IMM);
+  EARG(count); /* calling convention: store argument count on stack */
+}
+
 void compile_op(sbVmCompiler *cm, sbAstOp op);
 void compile_expr(sbVmCompiler *cm, sbIrExpr *expr) {
-  sbIrExpr *E1;
-  int count = 0;
   switch(expr->type) {
     case IR_E_OP:
       compile_expr(cm, expr->op.left);
@@ -193,14 +203,8 @@ void compile_expr(sbVmCompiler *cm, sbIrExpr *expr) {
       compile_op(cm, expr->op.type);
       break;
     case IR_E_CALL:
-      E1 = expr->call.param;
-      while (E1) {
-        count ++;
-        compile_expr(cm, E1->list.this);
-        E1 = E1->list.next;
-      }
-      EMIT(BC_LD_IMM);
-      EARG(count); /* calling convention: store argument count on stack */
+      /* calling convention: store argument count on stack */
+      compile_list(cm, expr->call.param);
       compile_expr(cm, expr->call.func);
       EMIT(BC_CALL);
       break;
@@ -212,6 +216,10 @@ void compile_expr(sbVmCompiler *cm, sbIrExpr *expr) {
       EMIT(BC_LD_BLK);
       EARG(expr->func->id);
       break;
+    case IR_E_LIST:
+      compile_list(cm, expr);
+      EMIT(BC_LIST_GATHER);
+      break;
     case IR_E_VALUE:
       if (expr->value.type == IT_NIL) {
         EMIT(BC_LD_NIL);
@@ -245,6 +253,7 @@ void compile_op(sbVmCompiler *cm, sbAstOp op) {
     case AST_OP_GT: EMIT(BC_OP_LE, BC_OP_NOT); break;
     case AST_OP_LE: EMIT(BC_OP_LE); break;
     case AST_OP_GE: EMIT(BC_OP_LT, BC_OP_NOT); break;
+    case AST_OP_INDEX: EMIT(BC_OP_INDEX); break;
     default:
       debug("unknown operation!\n");
   }
index c0ea39f..413e4f2 100644 (file)
@@ -242,9 +242,9 @@ static sbIrExpr *expr_call(hIrChunk ck, sbIrExpr *to_call, sbIrExpr *param) {
   });
 }
 
-static sbIrExpr *expr_param(hIrChunk ck, sbIrExpr *value) {
+static sbIrExpr *expr_list(hIrChunk ck, sbIrExpr *value) {
   return new_expr(ck, &(sbIrExpr) {
-    .type = IR_E_PARAM,
+    .type = IR_E_LIST,
     .list.this = value,
   });
 }
@@ -727,23 +727,31 @@ static sbIrVariable *compile_ast_var(hIrChunk ck, sbAst node) {
   }
 }
 
+static sbIrExpr *compile_ast_list(hIrChunk ck, sbAst node) {
+  sbAst considering = node;
+  sbIrExpr *list = NULL;
+  sbIrExpr **place_here = &list;
+  while (considering != NO_NODE) {
+    *place_here = expr_list(ck, compile_ast_expr(ck, considering->seq.left));
+    place_here = &(*place_here)->list.next;
+    considering = considering->seq.right;
+  }
+  return list;
+}
+
 static sbIrExpr *compile_ast_expr(hIrChunk ck, sbAst node) {
   if (node == NO_NODE) return NULL;
 
   if (node->type == AST_NODE_FUNCCALL) {
     sbIrExpr *called = compile_ast_expr(ck, node->seq.left);
-    sbAst param_ast = node->seq.right;
-    sbIrExpr *param = NULL;
-    sbIrExpr **place_here = &param;
-    while (param_ast != NO_NODE) {
-      *place_here = expr_param(ck, compile_ast_expr(ck, param_ast->seq.left));
-      place_here = &(*place_here)->list.next;
-      param_ast = param_ast->seq.right;
-    }
-    return expr_call(ck, called, param);
+    sbIrExpr *params = compile_ast_list(ck, node->seq.right);
+    return expr_call(ck, called, params);
   } else if (node->type == AST_VAL_FUNC) {
     sbIrChunk *func = compile_ast_function(ck->program, node->seq.left, node->seq.right);
     return expr_func(ck, func);
+  } else if (node->type == AST_VAL_LIST) {
+    sbIrExpr *list = compile_ast_list(ck, node->seq.left);
+    return list;
   } else if (node->type == AST_NODE_OP) {
     sbIrExpr *left = NULL, *right = NULL;
     if (node->op.left != NO_NODE) {
index a696c5d..d6f22f7 100644 (file)
@@ -46,7 +46,7 @@ typedef enum sbIrExprType {
   IR_E_VAR,
   IR_E_FUNC,
   IR_E_CALL,
-  IR_E_PARAM,
+  IR_E_LIST,
 } sbIrExprType;
 
 typedef struct sbIrLabel {
index cd7325e..7a8e102 100644 (file)
@@ -9,3 +9,5 @@ hList sbList_new(usize capacity);
 void sbList_append(hList list, hV *item);
 
 hV *sbList_get_value(hList list, usize *length);
+
+hV sbList_index(hList list, usize index);
index 46ac7b9..1c99267 100644 (file)
@@ -1,6 +1,7 @@
 #include "data/value.h"
 
 #include "data/string.h"
+#include "data/list.h"
 #include "data/hashtable.h"
 
 #define FLAG_NONINTRINSIC (1ULL << 63)
@@ -58,6 +59,13 @@ hV sbV_function(u64 id) {
   };
 }
 
+hV sbV_empty_list(usize capacity) {
+  return (hV) {
+    .type = IT_LIST,
+    .list = sbList_new(capacity),
+  };
+}
+
 flag sbV_c_eq(const hV *a, const hV *b) {
   if (a->type != b->type) return FALSE;
   if (a->type == ITX_TOMBSTONE || b->type == ITX_TOMBSTONE) return FALSE;
index c016de0..1375e7f 100644 (file)
@@ -7,6 +7,7 @@
 #define HVSTR(s) ((hV) { .type = IT_STRING, .string = s })
 #define HVBOOL(b) ((hV) { .type = IT_BOOLEAN, .boolean = b })
 #define HVFUNC(i) ((hV) { .type = IT_FUNCTION, .data = i })
+#define HVLIST(l) ((hV) { .type = IT_LIST, .list = l })
 #define HVNIL ((hV) { .type = IT_NIL })
 
 typedef u64 hHash;
@@ -37,6 +38,7 @@ typedef struct hV {
     hString string;
     hSymbol symbol;
     hHash hash;
+    hList list;
     hInteger integer;
     u64 boolean;
     double float_val;
@@ -52,6 +54,7 @@ hV sbV_hash(hHash hash);
 hV sbV_int(hInteger i);
 hV sbV_boolean(flag b);
 hV sbV_function(u64 id);
+hV sbV_empty_list(usize capacity);
 
 flag sbV_c_eq(const hV *a, const hV *b);
 flag sbV_c_falsy(const hV *a);
index fadff08..21fd009 100644 (file)
@@ -210,7 +210,9 @@ static void read_integer(hScanner sc, sbLexToken *new_token, flag negative) {
     if (ch == '0') {
         /* skip a leading zero, and see if it has some base indicator */
         ch = NEXT;
-        if (ch == 'b') {
+        if (is_digit(ch)) {
+            /* just a base 10 number with a leading zero */
+        } else if (ch == 'b') {
             ch = NEXT;
             base = 2;
         } else if (ch == 'o') {
@@ -219,11 +221,12 @@ static void read_integer(hScanner sc, sbLexToken *new_token, flag negative) {
         } else if (ch == 'x') {
             ch = NEXT;
             base = 16;
-        } else if (is_space(ch) || ch == '\n') {
-            /* it was literally just the number 0 (probably) */
+        } else if (is_alpha(ch)) {
+            /* it's like some other weird letter? */
+            new_token->type = T_BADNUMBER;
             num_done = TRUE;
         } else {
-            new_token->type = T_BADNUMBER;
+            /* it was literally just the number 0 (probably) */
             num_done = TRUE;
         }
     }
index ee024ae..b830490 100644 (file)
@@ -42,6 +42,7 @@ typedef enum sbOpcode {
   BC_OP_DEREF,          // dereference pointer
   BC_OP_LT,             // less than
   BC_OP_LE,             // less than or equal to
+  BC_OP_INDEX,          // index []
   BC_ALLOC_VARS,        // create space in rstack for local variables
   BC_LIST_GATHER,       // create list from count + list of values on stack
   BC_HASH_GATHER,       // create hash from count + list of pairs of keys/values on stack
index 16919cc..8d8a450 100644 (file)
@@ -357,6 +357,13 @@ void execute_instruction(hVm vm) {
       pop_stack(vm);
       push_stack(vm, &res);
       break;
+    case BC_OP_INDEX:
+      v = peek_stack(vm, 1);
+      w = peek_stack(vm, 0);
+      res = sbV_index(v, w);
+      npop_stack(vm, 2);
+      push_stack(vm, &res);
+      break;
     case BC_OP_DEREF:
       PANIC("todo");
     case BC_ALLOC_VARS:
@@ -370,6 +377,20 @@ void execute_instruction(hVm vm) {
       vm->fp->num_locals += param;
       break;
     case BC_LIST_GATHER:
+      v = pop_stack(vm);
+      if (v->type != IT_INTEGER) {
+        /* internal error! this should be generated correctly */
+        PANIC("internal violation: LIST_GATHER should receive an integer on top of stack");
+      }
+      param = v->integer;
+      res = sbV_empty_list(param);
+      while (param > 0) {
+        w = pop_stack(vm);
+        sbV_append(&res, w);
+        param --;
+      }
+      push_stack(vm, &res);
+      break;
     case BC_HASH_GATHER:
       PANIC("todo");
     case BC_LONG_NUM:
index d7fbcbc..b3a8f21 100644 (file)
@@ -1,6 +1,7 @@
 #include "vm/operations.h"
 
 #include "data/integer.h"
+#include "data/list.h"
 
 hV sbV_add(const hV *a, const hV *b) {
   if (a->type == IT_INTEGER && b->type == IT_INTEGER) {
@@ -81,3 +82,20 @@ hV sbV_le(const hV *a, const hV *b) {
     PANIC("todo");
   }
 }
+
+hV sbV_append(hV *a, hV *b) {
+  if (a->type == IT_LIST) {
+    sbList_append(a->list, b);
+    return HVNIL;
+  } else {
+    PANIC("todo");
+  }
+}
+
+hV sbV_index(hV *a, hV *b) {
+  if (a->type == IT_LIST && b->type == IT_INTEGER) {
+    return sbList_index(a->list, b->integer);
+  } else {
+    PANIC("todo %lld %lld", a->type, b->type);
+  }
+}
index 587411b..c4ba868 100644 (file)
@@ -17,3 +17,7 @@ hV sbV_eq(const hV *a, const hV *b);
 hV sbV_lt(const hV *a, const hV *b);
 
 hV sbV_le(const hV *a, const hV *b);
+
+hV sbV_append(hV *a, hV *b);
+
+hV sbV_index(hV *a, hV *b);