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);