Add argument variable binding
diff --git a/src/lisp/compiler.dasc b/src/lisp/compiler.dasc
index 2ac21f3..3040e45 100644
--- a/src/lisp/compiler.dasc
+++ b/src/lisp/compiler.dasc
@@ -7,6 +7,9 @@
#include <dasm_proto.h>
#include <dasm_x86.h>
+#include <stdlib.h>
+#include <string.h>
+
#define value_size sizeof(value_t)
|.arch x86;
@@ -73,6 +76,7 @@
dasm_growpc(&d, local.npc);
// Generate code
+ // TODO: first pass, extract bound and free variables
| setup 0;
@@ -84,6 +88,17 @@
if ((name & HEAP_MASK) != SYMBOL_TAG)
err("function name must be a symbol");
+ value_t a = arglist;
+ for (int i = 0; !nilp(a); a = cdr(a), i++)
+ {
+ if (!symbolp(car(a)))
+ {
+ err("defun argument must be a symbol");
+ }
+
+ add_variable(&local, V_ARGUMENT, (char *)(car(a) ^ SYMBOL_TAG), i);
+ }
+
for (; !nilp(body); body = cdr(body))
{
compile_expression(env, &local, car(body), Dst);
@@ -131,7 +146,11 @@
{
| mov eax, (nil);
}
- else if (integerp(val) || stringp(val) || symbolp(val))
+ else if (symstreq(val, "t"))
+ {
+ | mov eax, (t);
+ }
+ else if (integerp(val) || stringp(val))
{
| mov eax, val;
}
@@ -161,7 +180,7 @@
compile_expression(env, local, elt(args, 1), Dst);
| jmp =>after_label;
- |=>false_label:
+ |=>false_label:;
if (nargs == 3)
compile_expression(env, local, elt(args, 2), Dst);
|=>after_label:
@@ -171,6 +190,9 @@
struct function *func =
find_function(env, (char *)(fsym ^ SYMBOL_TAG));
+ if (func == NULL)
+ err("Function undefined");
+
if (nargs != func->nargs)
err("wrong number of args");
@@ -182,10 +204,27 @@
| mov ebx, (func->code_addr);
| call ebx;
- | add esp, (nargs * 4);
+ | add esp, (nargs * value_size);
// result in eax
}
}
+ else if (symbolp(val))
+ {
+ // For now ignore global variables, only search locally
+ struct variable *v = find_variable(local, (char *)(val ^ SYMBOL_TAG));
+
+ if (!v)
+ err("Variable unbound");
+
+ switch (v->type)
+ {
+ case V_ARGUMENT:
+ | mov eax, dword [ebp + value_size * (v->number + 2)];
+ break;
+ default:
+ err("Sorry, can only access V_ARGUMENT variables for now :(");
+ }
+ }
}
void compile_expr_to_func(struct environment *env, char *name, value_t val,
@@ -200,3 +239,37 @@
add_function(env, name, link(Dst), 0);
}
+
+struct variable *add_variable(struct local *local, enum var_type type,
+ char *name, int number)
+{
+ struct variable *var = malloc(sizeof(struct variable));
+ var->prev = local->first;
+ var->type = type;
+ var->name = name;
+ var->number = number;
+
+ local->first = var;
+
+ return var;
+}
+
+void destroy_local(struct local *local)
+{
+ for (struct variable *v = local->first; v;)
+ {
+ struct variable *t = v;
+ v = v->prev;
+ free(t);
+ }
+}
+
+struct variable *find_variable(struct local *local, char *name)
+{
+ struct variable *v = local->first;
+
+ for (; v && strcmp(v->name, name) != 0; v = v->prev)
+ {}
+
+ return v;
+}