From 44e5c6709b148197176ee316ec5491e1e12da748 Mon Sep 17 00:00:00 2001 From: cassowarii Date: Tue, 30 Jun 2026 17:58:53 -0700 Subject: [PATCH] LISTS in code!! wow!! so cool!!! --- src/compile/emit.c | 29 +++++++++++++++++++---------- src/compile/ir.c | 30 +++++++++++++++++++----------- src/compile/ir.h | 2 +- src/data/list.h | 2 ++ src/data/value.c | 8 ++++++++ src/data/value.h | 3 +++ src/parse/scanner.c | 11 +++++++---- src/vm/bytecode.h | 1 + src/vm/exec.c | 21 +++++++++++++++++++++ src/vm/operations.c | 18 ++++++++++++++++++ src/vm/operations.h | 4 ++++ 11 files changed, 103 insertions(+), 26 deletions(-) diff --git a/src/compile/emit.c b/src/compile/emit.c index fed66a9..46847d9 100644 --- a/src/compile/emit.c +++ b/src/compile/emit.c @@ -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"); } diff --git a/src/compile/ir.c b/src/compile/ir.c index c0ea39f..413e4f2 100644 --- a/src/compile/ir.c +++ b/src/compile/ir.c @@ -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 = ¶m; - 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) { diff --git a/src/compile/ir.h b/src/compile/ir.h index a696c5d..d6f22f7 100644 --- a/src/compile/ir.h +++ b/src/compile/ir.h @@ -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 { diff --git a/src/data/list.h b/src/data/list.h index cd7325e..7a8e102 100644 --- a/src/data/list.h +++ b/src/data/list.h @@ -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); diff --git a/src/data/value.c b/src/data/value.c index 46ac7b9..1c99267 100644 --- a/src/data/value.c +++ b/src/data/value.c @@ -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; diff --git a/src/data/value.h b/src/data/value.h index c016de0..1375e7f 100644 --- a/src/data/value.h +++ b/src/data/value.h @@ -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); diff --git a/src/parse/scanner.c b/src/parse/scanner.c index fadff08..21fd009 100644 --- a/src/parse/scanner.c +++ b/src/parse/scanner.c @@ -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; } } diff --git a/src/vm/bytecode.h b/src/vm/bytecode.h index ee024ae..b830490 100644 --- a/src/vm/bytecode.h +++ b/src/vm/bytecode.h @@ -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 diff --git a/src/vm/exec.c b/src/vm/exec.c index 16919cc..8d8a450 100644 --- a/src/vm/exec.c +++ b/src/vm/exec.c @@ -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: diff --git a/src/vm/operations.c b/src/vm/operations.c index d7fbcbc..b3a8f21 100644 --- a/src/vm/operations.c +++ b/src/vm/operations.c @@ -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); + } +} diff --git a/src/vm/operations.h b/src/vm/operations.h index 587411b..c4ba868 100644 --- a/src/vm/operations.h +++ b/src/vm/operations.h @@ -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); -- 1.8.3.1