Add beginning of Lips compiler, DynASM
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..b997271
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "src/lisp/vendor/luajit"]
+	path = src/lisp/vendor/luajit
+	url = https://luajit.org/git/luajit.git
diff --git a/src/lisp/.clang-format b/src/lisp/.clang-format
index bfc16c1..419e428 100644
--- a/src/lisp/.clang-format
+++ b/src/lisp/.clang-format
@@ -8,3 +8,5 @@
 UseTab: ForIndentation
 TabWidth: 4
 ColumnLimit: 80
+
+ForEachMacros: ['FOREACH']
\ No newline at end of file
diff --git a/src/lisp/.gitignore b/src/lisp/.gitignore
new file mode 100644
index 0000000..a21650e
--- /dev/null
+++ b/src/lisp/.gitignore
@@ -0,0 +1 @@
+compiler.c
\ No newline at end of file
diff --git a/src/lisp/Jmk b/src/lisp/Jmk
index 7afda0c..42a0e51 100644
--- a/src/lisp/Jmk
+++ b/src/lisp/Jmk
@@ -7,7 +7,21 @@
 
 archetype(c)
 
-OBJECTS = main.o lisp.o
+CFLAGS += -Ivendor/luajit/dynasm
+
+OBJECTS = main.o \
+			lisp.o \
+			compiler.o
+
+LUA = vendor/luajit/src/host/minilua
+
+vendor/luajit/src/host/minilua: vendor/luajit/src/host/minilua.c
+	status_log(CC, $<)
+	@$(CC) $< -o $@ -lm
+
+compiler.c: compiler.dasc
+	status_log(DYNASM, $<)
+	@$(LUA) vendor/luajit/dynasm/dynasm.lua -o $@ $<
 
 type(executable)
 
@@ -17,6 +31,6 @@
 
 format:
 	status_log(FORMAT, *)
-	@clang-format -i *.c *.h
+	@clang-format -i *.c *.h *.dasc
 
 finish
diff --git a/src/lisp/compiler.dasc b/src/lisp/compiler.dasc
new file mode 100644
index 0000000..b6d23e7
--- /dev/null
+++ b/src/lisp/compiler.dasc
@@ -0,0 +1,67 @@
+#include "compiler.h"
+
+#include <dasm_proto.h>
+#include <dasm_x86.h>
+
+#define value_size sizeof (struct value)
+
+|.arch x86;
+
+|.macro setup, nvars;
+| push ebp;
+| mov ebp, esp;
+| sub esp, value_size *nvars;
+|.endmacro;
+
+|.macro cleanup;
+| mov esp, ebp;
+| pop ebp;
+| ret;
+|.endmacro;
+
+dasm_State *d;
+unsigned int npc = 8;
+
+struct function *find_function (struct environment *env, char *name)
+{
+	struct function *f = env->first;
+
+	while ( strcmp (f->name, name) != 0 )
+	{
+		if ( f->prev )
+			f = f->prev;
+		else
+			return NULL;
+	}
+
+	return f;
+}
+
+void compile (struct istream *is)
+{
+	|.section code;
+	dasm_init (&d, DASM_MAXSECTION);
+
+	|.globals lbl_;
+	void *labels[ lbl__MAX ];
+	dasm_setupglobal (&d, labels, lbl__MAX);
+
+	|.actionlist lisp_actions;
+	dasm_setup (&d, lisp_actions);
+
+	dasm_growpc (&d, npc);
+}
+
+// First pass populates local
+void firstpass (struct value val, struct environment *env, struct local *local)
+{
+}
+
+// Second pass generates code
+void secondpass (struct value val, struct environment *env, struct local *local)
+{
+}
+
+void toplevel (struct value val, struct environment *env)
+{
+}
diff --git a/src/lisp/compiler.h b/src/lisp/compiler.h
new file mode 100644
index 0000000..9342a12
--- /dev/null
+++ b/src/lisp/compiler.h
@@ -0,0 +1,51 @@
+#pragma once
+
+#include "lisp.h"
+#include <stdbool.h>
+
+struct function
+{
+	char *name;
+	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);
+		void *code_ptr;
+		unsigned long code_addr;
+	};
+
+	struct function *prev;
+};
+
+struct environment
+{
+	struct function *first;
+};
+
+struct variable
+{
+	char *name;
+	int number;
+	struct variable *prev;
+};
+
+// local environment
+struct local
+{
+	// temps are accessed at ebp - 8 * (num_vars + temp)
+	bool temps[ 64 ];
+	int num_vars;
+	struct variable *first;
+};
+
+// First pass populates local
+void firstpass (struct value val, struct environment *env, struct local *local);
+// Second pass generates code
+void secondpass (struct value val, struct environment *env,
+                 struct local *local);
+void toplevel (struct value val, struct environment *env);
+void compile (struct istream *is);
+struct function *find_function (struct environment *env, char *name);
diff --git a/src/lisp/lisp b/src/lisp/lisp
index 1732c3b..9f20723 100755
--- a/src/lisp/lisp
+++ b/src/lisp/lisp
Binary files differ
diff --git a/src/lisp/lisp-notes.org b/src/lisp/lisp-notes.org
new file mode 100644
index 0000000..614ac8f
--- /dev/null
+++ b/src/lisp/lisp-notes.org
@@ -0,0 +1,36 @@
+#+TITLE: Lisp Notes
+#+AUTHOR: swissChili
+
+* Compiler
+
+  The compiler will using DynASM to generate code at runtime. It won’t
+  be a JIT (no interpreter), strictly a dynamic compiler.
+
+  For now I won’t even have a register allocator, all variables and
+  temporaries will be stored on the stack. This makes more or less
+  sense considering they will need to be put on the stack anyway when
+  a function is called.
+
+  An example assembly is in =scratch.s=.
+
+** First Pass
+
+   The first pass will involve finding all the local variables
+   (i.e. anything defined with =let=) and all the temporary values
+   necessary. Once a variable is out of scope, its stack space becomes
+   usable by other variables. Similarly, once a temporary is used, its
+   space becomes available. Variables are addressable by name but
+   temporaries are not.
+
+** Second Pass
+
+   The second pass will actually generate assembly. First enough space
+   will be reserved on the stack for the variables and temporaries,
+   then the AST will be walked as before to generate all the
+   appropriate function calls.
+
+   When a function call is generated, first temporaries are allocated
+   for all its arguments. Then the sub-expressions are compiled left to
+   right given these temporary locations as the outputs. For now we
+   will assume that everything is either a variable or a function
+   call, there will be no literals yet.
diff --git a/src/lisp/lisp.c b/src/lisp/lisp.c
index 8be2b4c..51a3270 100644
--- a/src/lisp/lisp.c
+++ b/src/lisp/lisp.c
@@ -176,7 +176,7 @@
 		{
 			printf ("list:\n");
 
-			for (struct value n = v; !nilp (n); n = cdr (n))
+			for ( struct value n = v; !nilp (n); n = cdr (n) )
 			{
 				printval (car (n), depth + 1);
 			}
@@ -384,8 +384,7 @@
 {
 	struct value *next = &v;
 
-	while ( next->tag.type == T_CONS &&
-	        cdr(*next).tag.type == T_CONS )
+	while ( next->tag.type == T_CONS && cdr (*next).tag.type == T_CONS )
 	{
 		next = &next->value.cons_val->cdr;
 	}
@@ -413,3 +412,13 @@
 {
 	return v.tag.type == T_NIL;
 }
+
+int length (struct value v)
+{
+	int i = 0;
+
+	FOREACH (item, v)
+		i++;
+
+	return i;
+}
diff --git a/src/lisp/lisp.h b/src/lisp/lisp.h
index a02b1b3..d8bc0e4 100644
--- a/src/lisp/lisp.h
+++ b/src/lisp/lisp.h
@@ -80,6 +80,7 @@
 struct value cdr (struct value v);
 bool listp (struct value v);
 bool nilp (struct value v);
+int length (struct value v);
 
 void printval (struct value v, int depth);
 
@@ -91,3 +92,10 @@
 void err (const char *msg);
 
 extern struct value nil;
+
+#define FOREACH(item, list)                                                    \
+	for ( ; listp (list); )                                                    \
+		for ( struct value item = car (list), _foreach_current = list;         \
+		      !nilp (_foreach_current);                                        \
+		      _foreach_current = cdr (_foreach_current),                       \
+		                   item = car (_foreach_current) )
diff --git a/src/lisp/scratch.s b/src/lisp/scratch.s
index 1775a0a..5428dce 100644
--- a/src/lisp/scratch.s
+++ b/src/lisp/scratch.s
@@ -40,4 +40,7 @@
 	push [ebp - 4]
 	push [ebp + 4]				; The function's return address
 	call whatever
+
+	mov esp, ebp 				; Finally clean up
+	pop ebp
 	ret
diff --git a/src/lisp/test.lisp b/src/lisp/test.lisp
index ee6773e..2ddedd8 100644
--- a/src/lisp/test.lisp
+++ b/src/lisp/test.lisp
@@ -1,2 +1,5 @@
 (defun my-fun (a b)
   (display t "%a\n" (+ a b)))
+
+(defun main ()
+  (my-fun pi four))
diff --git a/src/lisp/vendor/luajit b/src/lisp/vendor/luajit
new file mode 160000
index 0000000..20f556e
--- /dev/null
+++ b/src/lisp/vendor/luajit
@@ -0,0 +1 @@
+Subproject commit 20f556e53190ab9a735b932f5d868d45ec536a70