aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chunk.d72
-rw-r--r--compiler.d56
-rw-r--r--parser.d20
-rw-r--r--vm.d57
4 files changed, 46 insertions, 159 deletions
diff --git a/chunk.d b/chunk.d
index 6e572aa..ea05d61 100644
--- a/chunk.d
+++ b/chunk.d
@@ -169,57 +169,70 @@ class List : Seq {
}
enum OpCode {
+
+ // MATH
OP_ADD,
- OP_LESS,
- OP_NOT,
+ OP_DIVIDE,
+ OP_INCREMENT,
+ OP_MULTIPLY,
+ OP_NEGATE,
+ OP_SUBTRACT,
+ OP_ZERO,
+
+ // BOOLEAN
OP_EQUAL,
OP_GREATER,
- OP_NEGATE,
- OP_RETURN,
+ OP_LESS,
+ OP_NOT,
+
+ // LISTS
+ OP_LIST,
+ OP_LIST_N,
+
+ // SEQUENCES
+ OP_CONCAT, // No?
+ OP_FIRST, // No?
+ OP_LENGTH,
+ OP_MEMBER,
+ OP_REST,
+
+ // DEFINITIONS/VARIABLES
OP_CONSTANT,
OP_DEF_GLOBAL,
- OP_GET_GLOBAL,
- OP_SET_GLOBAL,
OP_DEF_LOCAL,
+ OP_GET_GLOBAL,
OP_GET_LOCAL,
+ OP_SET_GLOBAL,
OP_SET_LOCAL,
- OP_POP,
- OP_POPB,
- OP_POP_SCOPE,
- OP_SUBTRACT,
- OP_MULTIPLY,
- OP_DIVIDE,
- OP_NIL,
+ // JUMPS
OP_JUMP,
OP_JUMP_IF_FALSE,
OP_JUMP_IF_TRUE,
OP_JUMP_TO,
- OP_IS_NIL,
+ // STACK THINGS
OP_DUPLICATE,
OP_DUPLICATE_2,
+ OP_POP,
+ OP_POPB,
+ OP_POP_SCOPE,
OP_ROTATE_N,
- OP_ZERO,
- OP_INCREMENT,
- OP_LIST_N,
-
- OP_CALL,
-
- OP_LIST,
- OP_CONCAT, // No?
+ // RANDOM
+ OP_NIL,
- OP_FIRST, // No?
- OP_REST,
- OP_LENGTH,
- OP_MEMBER,
+ // FUNCTIONS
+ OP_CALL,
+ OP_RETURN,
- OP_TYPE_CHECK_NUMBER,
+ // TYPES
+ OP_IS_NIL,
OP_TYPE_CHECK_BOOLEAN,
- OP_TYPE_CHECK_STRING,
OP_TYPE_CHECK_LIST,
+ OP_TYPE_CHECK_NUMBER,
OP_TYPE_CHECK_SEQ,
+ OP_TYPE_CHECK_STRING,
}
class Chunk {
@@ -228,7 +241,6 @@ class Chunk {
int[] lines;
Value[] constants;
- //int writeOp(OpCode opCode, int line) {
int writeOp(ubyte opCode, int line) {
this.code ~= opCode;
this.lines ~= line;
@@ -244,5 +256,3 @@ class Chunk {
}
}
-
-
diff --git a/compiler.d b/compiler.d
index a436323..e04e5c8 100644
--- a/compiler.d
+++ b/compiler.d
@@ -287,43 +287,18 @@ class Compiler {
this.func.chunk.writeOp(OpCode.OP_DIVIDE, args[1].line);
}
- //ValueType compileLess(Form[] args, ValueType expected = ValueType.ANY) {
ValueType compileLess(Form[] args, ValueType expected) {
if (args.length != 2) {
- /*
- writeln("'<' requires 2 arguments");
- */
- this.error("'<' requires 2 arguments", -1);
+ this.error(format("'<': expected [2] arguments, received %d", args.length) -1);
this.advance();
return ValueType.NIL;
}
ValueType vt1 = this.resolve(args[0], ValueType.NUMBER);
- /*
- TC tc1 = typeCheck(vt1, expected);
- if (tc1.maybe) {
- func.chunk.writeOp(to!ubyte(tc1.op), currentLine);
- } else if (!tc1.exact) {
- writeln("COMPILE ERROR: bad type (less)");
- }
- */
this.func.chunk.writeOp(OpCode.OP_TYPE_CHECK_NUMBER, args[0].line);
ValueType vt2 = this.resolve(args[1], ValueType.NUMBER);
- /*
- TC tc2 = typeCheck(vt2, expected);
- if (tc2.maybe) {
- func.chunk.writeOp(to!ubyte(tc2.op), currentLine);
- } else if (!tc2.exact) {
- writeln("COMPILE ERROR: bad type (less)");
- }
- */
this.func.chunk.writeOp(OpCode.OP_TYPE_CHECK_NUMBER, args[1].line);
-
- //ValueType vt1 = resolve(args[0], expected);
- //func.chunk.writeOp(OpCode.OP_TYPE_CHECK_NUMBER, currentLine);
- //ValueType vt2 = resolve(args[1], expected);
- //func.chunk.writeOp(OpCode.OP_TYPE_CHECK_NUMBER, currentLine);
this.func.chunk.writeOp(OpCode.OP_LESS, args[1].line);
// this should probably return a ValueType
@@ -332,11 +307,8 @@ class Compiler {
ValueType compileGreater(Form[] args) {
if (args.length != 2) {
- this.error("'>' requires 2 arguments", -1);
+ this.error(format("'>': expected [2] arguments, received %d", to!int(args.length)) -1);
this.advance();
- /*
- writeln("'>' requires 2 arguments");
- */
return ValueType.NIL;
}
ValueType vt1 = this.resolve(args[0], ValueType.NUMBER);
@@ -365,8 +337,6 @@ class Compiler {
return ValueType.BOOLEAN;
}
-
- //int parseVariable(Def def) {
int parseVariable(Symbol sym) {
this.declareVariable(sym);
@@ -400,7 +370,6 @@ class Compiler {
if (sym.name == local.sym.name) {
this.error(format("already a variable named '%s' in this scope", sym.name), sym.line);
- //writefln("ERROR: already a variable named '%s' in this scope", sym.name);
return;
}
}
@@ -432,13 +401,6 @@ class Compiler {
this.defineVariable(addr);
}
- /*
- struct LV {
- int i;
- bool needsTypeCheck;
- }
- */
-
int resolveLocal(Symbol sym) {
for (int i = this.localCount - 1; i >= 0; i--) {
Local local = this.locals[i];
@@ -633,7 +595,6 @@ class Compiler {
// TODO how do we identify/propagate errors?
if (args.length != 1) {
this.error("'length': expected [1] argument, received 0", -1);
- //writeln("COMPILE ERROR: 'first' expects exactly one argument");
this.advance();
return;
}
@@ -664,7 +625,6 @@ class Compiler {
if (args.length != 2) {
this.error(format("'in?': expected [2] arguments, received %d", args.length), -1);
this.advance();
- //writeln("COMPILE ERROR: 'first' expects exactly one argument");
return;
}
ValueType vt1 = this.resolve(args[0], ValueType.ANY);
@@ -747,7 +707,6 @@ class Compiler {
if (args.length != 1) {
this.error("'first': expected [1] argument, received 0", -1);
this.advance();
- //writeln("COMPILE ERROR: 'first' expects exactly one argument");
return;
}
ValueType vt = this.resolve(args[0], ValueType.SEQ); // TODO need a new type
@@ -766,18 +725,12 @@ class Compiler {
if (args.length != 1) {
this.error("'rest': expected [1] argument, received ?", -1);
this.advance();
- //writeln("COMPILE ERROR: 'first' expects exactly one argument");
return;
}
ValueType vt = this.resolve(args[0], ValueType.OBJ); // TODO need a new type
this.func.chunk.writeOp(OpCode.OP_TYPE_CHECK_SEQ, args[0].line);
this.func.chunk.writeOp(OpCode.OP_REST, args[0].line);
-
- // there's probably a nicer way to copy
- //List lst = new List();
-
- // create a copy of the list
}
void compileLambda(Form form) {
@@ -951,10 +904,6 @@ class Compiler {
this.compileRest(cons.tail);
break;
default:
- /*
- writefln("unsure how to compile %s", sym.name);
- advance();
- */
this.resolve(head);
this.call(cons.tail);
this.advance();
@@ -965,7 +914,6 @@ class Compiler {
}
ValueType resolve(Form form, const ValueType expecting = ValueType.ANY) {
- //printForm(form);
this.currentLine = form.line;
switch(form.type) {
case FormType.ATOM:
diff --git a/parser.d b/parser.d
index 440cae0..c62a762 100644
--- a/parser.d
+++ b/parser.d
@@ -24,13 +24,6 @@ enum FormType {
PARSE_ERROR
}
-/*
-struct Form {
- FormType type;
- bool evaluate;
-}
-*/
-
abstract class Form {
FormType type;
bool evaluate;
@@ -38,9 +31,6 @@ abstract class Form {
ValueType returnType = ValueType.ANY;
- //ubyte compile(Chunk chunk);
- //ubyte[] asBytecode();
- //abstract void compile(Chunk chunk);
void compile(Chunk chunk) {
writeln("writing default op");
chunk.writeOp(OpCode.OP_NIL, line);
@@ -398,27 +388,18 @@ class Parser {
if (pos < source.length) {
return source[pos];
} else {
- //writeln("peek returns null");
return '\0';
}
}
char advance() {
if (!peekable()) {
- //writeln("trying to advance() beyond the end!!!");
return '\0';
} else {
char ret = peek();
pos++;
return ret;
}
- /*
- char ret = peek();
- if (ret != '\0') {
- pos++;
- }
- return ret;
- */
}
void skipWhitespace() {
@@ -644,7 +625,6 @@ class Parser {
advance(); // consume closing paren
return block;
-
}
diff --git a/vm.d b/vm.d
index 68a148e..fbf874c 100644
--- a/vm.d
+++ b/vm.d
@@ -80,7 +80,6 @@ class VM {
return this.aStack[this.aTop];
}
- //InterpretResult push(Value value) {
void pushA(Value value) {
if (this.aStack.length > this.aTop) {
this.aStack[this.aTop] = value;
@@ -144,8 +143,6 @@ class VM {
uint high = this.current.func.chunk.code[this.current.ip - 2] << 8;
uint low = this.current.func.chunk.code[this.current.ip - 1];
return high | low;
-
- //return 0;
}
bool isNumber(Value value) {
@@ -224,12 +221,6 @@ class VM {
}
*/
- /*
- CallFrame currentFrame() {
- return frames[frameCount - 1];
- }
- */
-
bool callValue(Value callee, int argCount) {
if (isObj(callee)) {
switch (callee.as.obj.type) {
@@ -259,7 +250,9 @@ class VM {
}
InterpretResult run() {
- writeln("== VM running ==");
+ if (DEBUG) {
+ writeln("== VM running ==");
+ }
while (true) {
if (DEBUG) {
writeln(" Stacks:");
@@ -270,7 +263,6 @@ class VM {
write("\n B> ");
for (int i = 0; i < this.bTop; i++) {
writef("[ %s ]", printableValue(bStack[i]));
- //writef("[ %s ]", printableValue(this.current.slots[i]));
}
write("\n constants> ");
@@ -346,7 +338,6 @@ class VM {
break;
case OpCode.OP_GET_GLOBAL:
Value name = this.current.func.chunk.constants[this.readByte()];
- //writefln(asString(name));
if (!isString(name)) {
writefln("variables must be strings, got %s", printableValue(name));
return InterpretResult.RUNTIME_ERROR; // TODO error
@@ -361,7 +352,6 @@ class VM {
case OpCode.OP_DEF_LOCAL:
Value val = this.popA();
this.pushB(val);
- //current.slots ~= val;
/*
Value nil = { ValueType.NIL };
@@ -398,7 +388,6 @@ class VM {
List lst = new List(length);
if (length > 0) {
for (int i = length - 1; i >= 0; i--) {
- //lst.appendItem(this.popA());
lst.addItemAtIndex(this.popA(), i);
}
}
@@ -406,7 +395,6 @@ class VM {
break;
case OpCode.OP_CONSTANT:
Value constant = this.current.func.chunk.constants[this.readByte()];
- //Value constant = current.func.chunk.constants[b];
this.pushA(constant);
break;
case OpCode.OP_NEGATE:
@@ -466,38 +454,14 @@ class VM {
break;
case OpCode.OP_ADD:
Value b = this.popA();
- /*
- if (!isNumber(b)) {
- writeln("b is not a number!");
- return InterpretResult.RUNTIME_ERROR; // TODO error
- }
- */
Value a = this.popA();
- /*
- if (!isNumber(a)) {
- writeln("a is not a number!");
- return InterpretResult.RUNTIME_ERROR; // TODO error
- }
- */
double bnum = asNumber(b);
double anum = asNumber(a);
this.pushA(makeNumberValue(anum + bnum));
break;
case OpCode.OP_SUBTRACT:
Value b = this.popA();
- /*
- if (!isNumber(b)) {
- writeln("b is not a number!");
- return InterpretResult.RUNTIME_ERROR; // TODO error
- }
- */
Value a = this.popA();
- /*
- if (!isNumber(a)) {
- writeln("a is not a number!");
- return InterpretResult.RUNTIME_ERROR; // TODO error
- }
- */
double bnum = asNumber(b);
double anum = asNumber(a);
this.pushA(makeNumberValue(anum - bnum));
@@ -540,25 +504,12 @@ class VM {
break;
case OpCode.OP_LESS:
Value b = this.popA();
- /*
- if (!isNumber(b)) {
- writeln("b is not a number!");
- return InterpretResult.RUNTIME_ERROR; // TODO error
- }
- */
Value a = this.popA();
- /*
- if (!isNumber(a)) {
- writeln("a is not a number!");
- return InterpretResult.RUNTIME_ERROR; // TODO error
- }
- */
double bnum = asNumber(b);
double anum = asNumber(a);
this.pushA(makeBooleanValue(anum < bnum));
break;
case OpCode.OP_RETURN:
-
Value ret = this.popA();
this.popA(); // function
this.frameCount--;
@@ -591,7 +542,6 @@ class VM {
break;
case OpCode.OP_JUMP:
uint offset = this.readShort();
- //ip += offset;
this.current.ip += offset;
break;
case OpCode.OP_JUMP_IF_FALSE:
@@ -601,7 +551,6 @@ class VM {
return InterpretResult.RUNTIME_ERROR; // TODO error
}
if (!asBoolean(this.peekA(0))) {
- //ip += offset;
this.current.ip += offset;
}
break;