#include "mem/debug.h"
-#define IF_NOT 1
-#define IF_YES 0
-#define ALWAYS 0
-
typedef struct varmapentry {
const char *name;
usize name_len;
*ir = (sbIrProgram) {0};
sbArena_initialize(&ir->arena, initial_arena_size);
sbBuffer_initialize(&ir->chunks, 4096);
+ sbBuffer_initialize(&ir->varmapping, 4096);
}
void sbIrProgram_deinitialize(hIrProgram ir) {
}
}
+ /* TODO do a different thing here */
+ fprintf(stderr, "unknown variable name! '%s'\n", name);
return NULL;
}
return where_to_put;
}
-static sbIrExpr *expr_var(hIrChunk ck, const char *name, usize name_len) {
- sbIrVariable *var_by_name = var_name(ck, name, name_len);
- /* TODO do a different thing */
- if (!var_by_name) {
- fprintf(stderr, "unknown variable name! '%s'\n", name);
- return NULL;
- }
+static sbIrExpr *expr_var(hIrChunk ck, sbIrVariable *var) {
return new_expr(ck, &(sbIrExpr) {
.type = IR_E_VAR,
- .var = var_by_name,
+ .var = var,
});
}
});
}
+static void put_jump_if_yes(hIrChunk ck, sbIrExpr *condition, sbIrLabel *label) {
+ put_jump(ck, 0, condition, label);
+}
+
+static void put_jump_if_no(hIrChunk ck, sbIrExpr *condition, sbIrLabel *label) {
+ put_jump(ck, 1, condition, label);
+}
+
+static void put_jump_unconditional(hIrChunk ck, sbIrLabel *label) {
+ put_jump(ck, 0, NULL, label);
+}
+
static void put_expr(hIrChunk ck, sbIrExpr *expr) {
put_ir_stmt(ck, &(sbIrStmt) {
.type = IR_S_EXPR,
});
}
+static void print_expr(sbIrExpr *e);
static void put_assign(hIrChunk ck, sbIrVariable *assign_to, sbIrExpr *expr) {
put_ir_stmt(ck, &(sbIrStmt) {
.type = IR_S_ASSIGN,
static void compile_ast_stmt(hIrChunk ck, sbAst stmtast);
static sbIrExpr *compile_ast_expr(hIrChunk ck, sbAst exprast);
+static sbIrVariable *compile_ast_var(hIrChunk ck, sbAst node);
static void compile_ast_stmtseq(hIrChunk ck, sbAst seqast) {
usize varmapsize = ck->program->varmapping.size;
}
compile_ast_stmt(ck, considering->seq.left);
+ //put_return(ck);
considering = considering->seq.right;
}
sbBuffer_set_size(&ck->program->varmapping, varmapsize);
}
-void compile_ast_stmt(hIrChunk ck, sbAst node) {
- sbIrExpr *E1;//, *E2;
+static void compile_ast_stmt(hIrChunk ck, sbAst node) {
+ sbIrExpr *E1;
sbIrLabel *L1, *L2;
+ sbIrVariable *V1;
switch (node->type) {
+ case AST_NODE_LET:
+ /*
+ * LET a = 3
+ * linearizes to:
+ * LET a
+ * a = 3
+ *
+ * "LET a" doesn't actually appear in the output IR code,
+ * but it allows us to interpret the name "a" inside the
+ * current block to refer to a consistent variable slot.
+ * TODO: I need to add support for declaring multiple
+ * variables in one line.
+ */
+ if (node->seq.left->type != AST_NODE_MULTIVAL) PANIC("expected multival on left side of let!");
+ const char *vname = sbSymbol_name(node->seq.left->seq.left->symb);
+ V1 = create_var(ck, vname, strlen(vname));
+ if (node->seq.right != NO_NODE) {
+ /* let ... = ... */
+ if (node->seq.right->type != AST_NODE_MULTIVAL) PANIC("expected multival on right side of let!");
+ E1 = compile_ast_expr(ck, node->seq.right->seq.left);
+ put_assign(ck, V1, E1);
+ }
+ break;
+
+ case AST_NODE_ASSIGN:
+ if (node->seq.left->type != AST_NODE_MULTIVAL) PANIC("expected multival on left side of assign!");
+ if (node->seq.right->type != AST_NODE_MULTIVAL) PANIC("expected multival on right side of assign!");
+ V1 = compile_ast_var(ck, node->seq.left->seq.left);
+ E1 = compile_ast_expr(ck, node->seq.right->seq.left);
+ put_assign(ck, V1, E1);
+ break;
+
case AST_NODE_WHILE:
/*
* WHILE condition { things }
* to be handled by passing in labels to this
* stmtseq. If we have no labels, we're not in
* a loop, and should error. */
+ /* match continue / success jump can be handled
+ * the same way. Maybe we should have a "labels
+ * context" struct that captures all of these. */
L1 = new_label(ck);
L2 = new_label(ck);
E1 = compile_ast_expr(ck, node->seq.left);
- put_jump(ck, ALWAYS, NULL, L2);
+ put_jump_unconditional(ck, L2);
put_label(ck, L1);
compile_ast_stmtseq(ck, node->seq.right);
put_label(ck, L2);
- put_jump(ck, IF_YES, E1, L1);
+ put_jump_if_yes(ck, E1, L1);
break;
case AST_NODE_IF:
/* no else branch */
E1 = compile_ast_expr(ck, node->tri.left);
L1 = new_label(ck);
- put_jump(ck, IF_NOT, E1, L1);
+ put_jump_if_no(ck, E1, L1);
compile_ast_stmtseq(ck, node->tri.center);
put_label(ck, L1);
} else {
E1 = compile_ast_expr(ck, node->tri.left);
L1 = new_label(ck);
L2 = new_label(ck);
- put_jump(ck, IF_NOT, E1, L1);
+ put_jump_if_no(ck, E1, L1);
compile_ast_stmtseq(ck, node->tri.center);
- put_jump(ck, ALWAYS, NULL, L2);
+ put_jump_unconditional(ck, L2);
put_label(ck, L1);
compile_ast_stmtseq(ck, node->tri.right);
put_label(ck, L2);
E1 = compile_ast_expr(ck, node->seq.right);
put_label(ck, L1);
compile_ast_stmtseq(ck, node->seq.left);
- put_jump(ck, IF_YES, E1, L1);
+ put_jump_if_yes(ck, E1, L1);
} else {
put_label(ck, L1);
compile_ast_stmtseq(ck, node->seq.left);
- put_jump(ck, ALWAYS, NULL, L1);
+ put_jump_unconditional(ck, L1);
}
break;
}
}
+static sbIrVariable *compile_ast_var(hIrChunk ck, sbAst node) {
+ if (node->type == AST_NODE_NAME) {
+ return var_name(ck, sbSymbol_name(node->symb), strlen(sbSymbol_name(node->symb)));
+ } else {
+ /* TODO make errors not bad */
+ fprintf(stderr, "expecting a name at this point! (got %d)\n", node->type);
+ return NULL;
+ }
+}
+
static sbIrExpr *compile_ast_expr(hIrChunk ck, sbAst node) {
if (node == NO_NODE) return NULL;
return expr_value(ck, &HVINT(node->i));
} else if (node->type == AST_NODE_NAME) {
/* TODO: I don't want to use strlen. Can we remember the lengths of symbols? */
- return expr_var(ck, sbSymbol_name(node->symb), strlen(sbSymbol_name(node->symb)));
+ return expr_var(ck, compile_ast_var(ck, node));
} else {
PANIC("todo!");
}
printf("\n");
break;
case IR_S_ASSIGN:
+ printf("variable %zu = ", s->assign.var->created_index);
+ print_expr(s->assign.expr);
+ printf("\n");
+ break;
default:
printf("do something\n");
}
sbAst body = parse_block(pr);
return tri_node(pr, AST_NODE_MATCH, pattern, guard_clause, body);
} else if (t.type == T_rLET) {
- /* let a, b = ... */
next_token(pr);
sbAst bindings = parse_comma_exprs(pr, NULL);
- if (!expect(pr, T_EQUALS)) return syntax_error(pr);
- sbAst values = parse_comma_exprs(pr, NULL);
- return seq_node(pr, AST_NODE_LET, bindings, values);
+ if (expect(pr, T_EQUALS)) {
+ /* let a, b = ... */
+ sbAst values = parse_comma_exprs(pr, NULL);
+ return seq_node(pr, AST_NODE_LET, bindings, values);
+ } else {
+ /* let a, b */
+ return seq_node(pr, AST_NODE_LET, bindings, NO_NODE);
+ }
} else if (t.type == T_rDEF) {
/* def a b, c { ... } */
next_token(pr);
/* a, b, c = 1, 2, 3 */
next_token(pr);
sbAst assigned_values = parse_comma_exprs(pr, 0);
+ if (expr->type != AST_NODE_MULTIVAL) {
+ /* if we have an = with one thing on the left side,
+ * wrap it in a multival anyway for consistency */
+ expr = seq_node(pr, AST_NODE_MULTIVAL, expr, NO_NODE);
+ }
expr = seq_node(pr, AST_NODE_ASSIGN, expr, assigned_values);
}
}