}
}
+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);
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;
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);
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");
}
});
}
-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,
});
}
}
}
+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) {
IR_E_VAR,
IR_E_FUNC,
IR_E_CALL,
- IR_E_PARAM,
+ IR_E_LIST,
} sbIrExprType;
typedef struct sbIrLabel {
void sbList_append(hList list, hV *item);
hV *sbList_get_value(hList list, usize *length);
+
+hV sbList_index(hList list, usize index);
#include "data/value.h"
#include "data/string.h"
+#include "data/list.h"
#include "data/hashtable.h"
#define FLAG_NONINTRINSIC (1ULL << 63)
};
}
+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;
#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;
hString string;
hSymbol symbol;
hHash hash;
+ hList list;
hInteger integer;
u64 boolean;
double float_val;
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);
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') {
} 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;
}
}
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
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:
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:
#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) {
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);
+ }
+}
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);