aboutsummaryrefslogtreecommitdiff
path: root/compiler.d
diff options
context:
space:
mode:
authorBen Winston2023-05-23 22:49:42 -0400
committerBen Winston2023-05-23 22:49:52 -0400
commit277f7110b01a510e42fd8a75682ebe3c4daa3d40 (patch)
tree3f504df1daeea1350b4b68cf9107ec617628cacd /compiler.d
parentaafe90221e9f8e8bf15ebc87814a1bb67e5a4dce (diff)
first crack at lists (rather naive)
Diffstat (limited to 'compiler.d')
-rw-r--r--compiler.d80
1 files changed, 74 insertions, 6 deletions
diff --git a/compiler.d b/compiler.d
index 1920ae0..119414c 100644
--- a/compiler.d
+++ b/compiler.d
@@ -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;
}