import std.stdio; import std.string; import parser; import chunk; import dbg; enum FunctionType { FUNCTION, SCRIPT, } struct Local { Symbol sym; int depth; } class Compiler { Function func; FunctionType type; Parser* parser; Local[] locals; int scopeDepth; Form current; Form previous; Form outer; int outerIdx; void advance() { previous = current; /* if (outer.type != FormType.EOF && outerIdx < outer) { current = parser.parseForm(); } else { } */ current = parser.parseForm(); } void compileNil(Form form) { form.compile(func); advance(); } void compileAtom(Form form) { form.compile(func); advance(); } void compileAdd(Form[] args) { resolve(args[0]); // (+ n) always returns n if (args.length == 1) { return; } for (int i = 1; i < args.length; i++) { resolve(args[i]); func.chunk.writeOp(OpCode.OP_ADD, current.line); } } void compileNegate(Form arg) { resolve(arg); func.chunk.writeOp(OpCode.OP_NEGATE, current.line); } void compileSubtract(Form[] args) { resolve(args[0]); for (int i = 1; i < args.length; i++) { resolve(args[i]); func.chunk.writeOp(OpCode.OP_SUBTRACT, current.line); } } void compileLess(Form[] args) { if (args.length != 2) { writeln("'<' requires 2 arguments"); return; } resolve(args[0]); resolve(args[1]); func.chunk.writeOp(OpCode.OP_LESS, current.line); } void compileCons(Form form) { Cons cons = cast(Cons)form; Form head = cons.head; if (head.type != FormType.SYMBOL) { writeln("cons must start with a symbol"); return; } Symbol sym = cast(Symbol)head; switch (sym.name) { case "+": compileAdd(cons.tail); break; case "-": if (cons.tail.length == 1) { compileNegate(cons.tail[0]); } else { compileSubtract(cons.tail); } break; case "<": compileLess(cons.tail); break; default: writefln("unsure how to compile %s", sym.name); advance(); break; } } void resolve(Form form) { write("resolving: "); printForm(form); switch(form.type) { case FormType.ATOM: this.compileAtom(form); break; case FormType.CONS: this.compileCons(form); break; case FormType.NIL: this.compileNil(form); break; default: write("not sure how to resolve: "); printForm(form); advance(); break; } } Function compile() { writeln("compiling"); advance(); while(current.type != FormType.EOF) { resolve(current); } return finish(); } Function finish() { //emitReturn(); writeln("finishing the compiler!"); this.func.chunk.writeOp(OpCode.OP_RETURN, current.line); writeln("wrote a return code"); return func; } this(FunctionType type, Parser* parser) { this.parser = parser; this.func = new Function(); this.type = type; locals ~= Local(new Symbol("", -1), 0); } }