diff options
| author | Ben Winston | 2023-05-20 15:12:30 -0400 |
|---|---|---|
| committer | Ben Winston | 2023-05-20 15:12:30 -0400 |
| commit | 0c70372774297272dd14133d48e40e9a3624420a (patch) | |
| tree | 4e66fb1b97a0fd537a20dca4ddcd26003f83c94d /compiler.d | |
| parent | 6902cc5abe09da9f6f2d86f22d06684d97cfa9f3 (diff) | |
initial commit of compiler/VM with a couple basic instructions
Diffstat (limited to 'compiler.d')
| -rw-r--r-- | compiler.d | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/compiler.d b/compiler.d new file mode 100644 index 0000000..51e45ba --- /dev/null +++ b/compiler.d @@ -0,0 +1,166 @@ +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); + } +} |
