Add lib/std, compile_expression ()
diff --git a/src/lisp/Jmk b/src/lisp/Jmk
index d5d3001..17ee1ff 100644
--- a/src/lisp/Jmk
+++ b/src/lisp/Jmk
@@ -15,7 +15,8 @@
OBJECTS = main.o \
lisp.o \
- compiler.o
+ compiler.o \
+ lib/std.o
ifeq ($(PLAT),linux)
OBJECTS += plat/linux.o
diff --git a/src/lisp/compiler.dasc b/src/lisp/compiler.dasc
index 2bd10d1..ed97019 100644
--- a/src/lisp/compiler.dasc
+++ b/src/lisp/compiler.dasc
@@ -53,3 +53,35 @@
dasm_growpc (&d, npc);
}
+
+void compile_expression (struct environment *env, struct local *local,
+ value_t val, dasm_State **Dst)
+{
+ if ( integerp (val) || stringp (val) || symbolp (val) )
+ {
+ | mov eax, val;
+ }
+ else if ( listp (val) )
+ {
+ value_t func = car (val);
+ if ( !symbolp (func) )
+ err ("function name must be a symbol");
+
+ struct function *func = find_function (env, func ^ SYMBOL_TAG);
+ value_t args = cdr (val);
+ int nargs = length (args);
+
+ if ( nargs != func->nargs )
+ err ("wrong number of args");
+
+ for ( int i = length (args) - 1; i >= 0; i++ )
+ {
+ compile_expression (env, local, elt (args, i), Dst);
+ | push eax;
+ }
+
+ | call (func->code_addr);
+ | add esp, (nargs * 4);
+ // result in eax
+ }
+}
diff --git a/src/lisp/compiler.h b/src/lisp/compiler.h
index 9225c11..f7be765 100644
--- a/src/lisp/compiler.h
+++ b/src/lisp/compiler.h
@@ -2,6 +2,8 @@
#include "lisp.h"
#include <stdbool.h>
+#include <stdint.h>
+#include <dasm_proto.h>
struct function
{
@@ -9,12 +11,12 @@
int nargs; // number of arguments
union {
- struct value (*def0) ();
- struct value (*def1) (struct value);
- struct value (*def2) (struct value, struct value);
- struct value (*def3) (struct value, struct value, struct value);
+ value_t (*def0) ();
+ value_t (*def1) (value_t);
+ value_t (*def2) (value_t, value_t);
+ value_t (*def3) (value_t, value_t, value_t);
void *code_ptr;
- unsigned long code_addr;
+ uintrptr_t code_addr;
};
struct function *prev;
@@ -41,5 +43,7 @@
struct variable *first;
};
+void compile_expression (struct environment *env, struct local *local,
+ value_t val, dasm_State **Dst);
void compile (struct istream *is);
struct function *find_function (struct environment *env, char *name);
diff --git a/src/lisp/lib/std.c b/src/lisp/lib/std.c
new file mode 100644
index 0000000..35226da
--- /dev/null
+++ b/src/lisp/lib/std.c
@@ -0,0 +1,28 @@
+#include "std.h"
+
+value_t l_plus (value_t a, value_t b)
+{
+ if ( !integerp (a) || !integerp (b) )
+ return nil;
+
+ return (((a >> 2) + (b >> 2)) << 2) | INT_TAG;
+}
+
+void add_function (struct environment *env, char *name, void *func, int nargs)
+{
+ struct function *last,
+ *new = malloc (sizeof (struct function));
+
+ last = env->first;
+ new->prev = last;
+ new->name = name;
+ new->nargs = nargs;
+ new->code_ptr = func;
+
+ env->prev = new;
+}
+
+void load_std (struct environment *env)
+{
+ add_function (env, "+", l_plus, 2);
+}
diff --git a/src/lisp/lib/std.h b/src/lisp/lib/std.h
new file mode 100644
index 0000000..85d766c
--- /dev/null
+++ b/src/lisp/lib/std.h
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "../lisp.h"
+#include "../compiler.h"
+
+value_t l_plus (value_t a, value_t b);
+
+void add_function (struct environment *env, char *name, void *func, int nargs);
+void load_std (struct environment *env);
diff --git a/src/lisp/lisp b/src/lisp/lisp
index f104f85..6f1ba3c 100755
--- a/src/lisp/lisp
+++ b/src/lisp/lisp
Binary files differ
diff --git a/src/lisp/lisp.c b/src/lisp/lisp.c
index efb3efe..ac10eab 100644
--- a/src/lisp/lisp.c
+++ b/src/lisp/lisp.c
@@ -16,6 +16,7 @@
void err (const char *msg)
{
fprintf (stderr, "ERROR: %s\n", msg);
+ exit (1);
}
value_t intval (int i)
@@ -48,7 +49,7 @@
first_a = last_a = item;
}
- value_t v = (value_t) c;
+ value_t v = (value_t)c;
v |= CONS_TAG;
return v;
@@ -103,7 +104,7 @@
else
{
s[ i ] = 0;
- *val = (value_t) s;
+ *val = (value_t)s;
*val |= SYMBOL_TAG;
return true;
@@ -156,7 +157,7 @@
{
is->get (is);
- *val = (value_t) s;
+ *val = (value_t)s;
*val |= STRING_TAG;
return true;
@@ -171,11 +172,11 @@
if ( symbolp (v) )
{
- printf ("'%s\n", (char *) (v ^ SYMBOL_TAG));
+ printf ("'%s\n", (char *)(v ^ SYMBOL_TAG));
}
else if ( stringp (v) )
{
- printf ("\"%s\"\n", (char *) (v ^ STRING_TAG));
+ printf ("\"%s\"\n", (char *)(v ^ STRING_TAG));
}
else if ( integerp (v) )
{
@@ -408,7 +409,7 @@
value_t v;
char *a = malloc_aligned (strlen (str) + 1);
- v = (value_t) a;
+ v = (value_t)a;
v |= STRING_TAG;
return v;
@@ -467,7 +468,7 @@
if ( !consp (v) )
return NULL;
- struct cons *c = (void *) (v ^ CONS_TAG);
+ struct cons *c = (void *)(v ^ CONS_TAG);
return &c->car;
}
@@ -476,7 +477,7 @@
if ( !consp (v) )
return NULL;
- struct cons *c = (void *) (v ^ CONS_TAG);
+ struct cons *c = (void *)(v ^ CONS_TAG);
return &c->cdr;
}
@@ -491,9 +492,19 @@
FOREACH (item, v)
{
- (void) item;
+ (void)item;
i++;
}
return i;
}
+
+value_t elt (value_t v, int index)
+{
+ for ( int = 0; i < index; i++ )
+ {
+ v = cdr (v);
+ }
+
+ return car (v);
+}
diff --git a/src/lisp/lisp.h b/src/lisp/lisp.h
index 3c2cb3b..b781828 100644
--- a/src/lisp/lisp.h
+++ b/src/lisp/lisp.h
@@ -46,8 +46,7 @@
struct alloc_list
{
int type;
- union
- {
+ union {
struct cons *cons_val;
};
struct alloc_list *next, *prev;
@@ -92,6 +91,7 @@
bool listp (value_t v);
bool nilp (value_t v);
int length (value_t v);
+value_t elt (value_t v, int index);
void printval (value_t v, int depth);