diff options
| author | Ben Winston | 2023-05-23 22:49:42 -0400 |
|---|---|---|
| committer | Ben Winston | 2023-05-23 22:49:52 -0400 |
| commit | 277f7110b01a510e42fd8a75682ebe3c4daa3d40 (patch) | |
| tree | 3f504df1daeea1350b4b68cf9107ec617628cacd /compiler.d | |
| parent | aafe90221e9f8e8bf15ebc87814a1bb67e5a4dce (diff) | |
first crack at lists (rather naive)
Diffstat (limited to 'compiler.d')
| -rw-r--r-- | compiler.d | 80 |
1 files changed, 74 insertions, 6 deletions
@@ -356,20 +356,27 @@ class Compiler { } void compileSymbol(Form form, ValueType expecting = ValueType.ANY) { + if (form.type != FormType.SYMBOL) { + writeln("NOT A SYMBOL!"); + } else { + writeln("it's a symbol"); + } Symbol sym = cast(Symbol)form; int arg = resolveLocal(sym); if (arg != -1) { - func.chunk.writeOp(OpCode.OP_GET_LOCAL, sym.line); + this.func.chunk.writeOp(OpCode.OP_GET_LOCAL, sym.line); } else { - arg = func.chunk.addConstant(makeStringValue(sym.name)); - func.chunk.writeOp(OpCode.OP_GET_GLOBAL, sym.line); + arg = this.func.chunk.addConstant(makeStringValue(sym.name)); + this.func.chunk.writeOp(OpCode.OP_GET_GLOBAL, sym.line); } + writefln("this is the addr: %d", arg); + // get the variable - func.chunk.writeOp(to!ubyte(arg), sym.line); + this.func.chunk.writeOp(to!ubyte(arg), sym.line); - //advance(); + advance(); } int jump(OpCode type) { @@ -465,6 +472,16 @@ class Compiler { return vt; } + ValueType compileConcat(Form[] args) { + ValueType vt = resolve(args[0], ValueType.STRING); + for (int i = 1; i < args.length; i++) { + vt = resolve(args[i], ValueType.STRING); + func.chunk.writeOp(OpCode.OP_TYPE_CHECK_STRING, currentLine); + func.chunk.writeOp(OpCode.OP_CONCAT, currentLine); + } + return ValueType.STRING; + } + void compileBlock(Form form) { Block block = cast(Block)form; beginScope(); @@ -499,6 +516,44 @@ class Compiler { func.chunk.writeOp(to!ubyte(args.length), -1); } + void compileList(Form[] args) { + List lst = new List(); + ValueType vt; + int addr; + foreach (Form arg ; args) { + vt = resolve(arg, ValueType.ANY); + // how do we get at the address? + addr = to!int(this.func.chunk.constants.length) - 1; // this is probably often wrong + lst.addItem(addr); + this.func.chunk.writeOp(OpCode.OP_POP, arg.line); // shouldn't use the stack for this (but how?) + } + + this.func.chunk.writeOp(OpCode.OP_CONSTANT, args[0].line); + int idx = this.func.chunk.addConstant(makeObjValue(lst)); + this.func.chunk.writeOp(to!ubyte(idx), args[0].line); + //return ValueType.OBJ; + + + //advance(); // ?? + } + + void compileFirst(Form[] args) { + // TODO how do we identify/propagate errors? + if (args.length != 1) { + writeln("COMPILE ERROR: 'first' expects exactly one argument"); + return; + } + ValueType vt = resolve(args[0], ValueType.OBJ); // TODO need a new type + this.func.chunk.writeOp(OpCode.OP_TYPE_CHECK_LIST, args[0].line); + + // pop the value off the stack + // get the address of the first item in the list + // push that item onto the stack + + // or, use a special instruction + this.func.chunk.writeOp(OpCode.OP_FIRST, args[0].line); + } + void compileFunc(Form form) { Func f = cast(Func)form; @@ -580,6 +635,19 @@ class Compiler { return vt; case "not": return compileNot(cons.tail); + + // STRINGS + case "concat": + return compileConcat(cons.tail); + + // LISTS + case "first": + compileFirst(cons.tail); + break; + case "list": + //return compileList(cons.tail); + compileList(cons.tail); + break; default: /* writefln("unsure how to compile %s", sym.name); @@ -648,7 +716,7 @@ class Compiler { Function finish() { this.func.chunk.writeOp(OpCode.OP_RETURN, current.line); - disassembleChunk(func.chunk, to!string(func)); + disassembleChunk(this.func.chunk, to!string(func)); return this.func; } |
