aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chunk.d1
-rw-r--r--compiler.d18
-rw-r--r--parser.d28
-rw-r--r--vm.d5
4 files changed, 52 insertions, 0 deletions
diff --git a/chunk.d b/chunk.d
index 7a532f5..68df45b 100644
--- a/chunk.d
+++ b/chunk.d
@@ -139,6 +139,7 @@ enum OpCode {
OP_ADD,
OP_LESS,
OP_NOT,
+ OP_EQUAL,
OP_GREATER,
OP_NEGATE,
OP_RETURN,
diff --git a/compiler.d b/compiler.d
index eccc4ce..4fb37f2 100644
--- a/compiler.d
+++ b/compiler.d
@@ -304,6 +304,20 @@ class Compiler {
return ValueType.BOOLEAN;
}
+ ValueType compileEq(Form[] args) {
+ if (args.length != 2) {
+ this.error(format("'eq?': expected [1] argument, received %d", to!int(args.length)), -1);
+ this.advance();
+ return ValueType.NIL;
+ }
+ ValueType vt1 = this.resolve(args[0], ValueType.ANY);
+ ValueType vt2 = this.resolve(args[1], ValueType.ANY);
+
+ this.func.chunk.writeOp(OpCode.OP_EQUAL, args[1].line);
+
+ return ValueType.BOOLEAN;
+ }
+
//int parseVariable(Def def) {
int parseVariable(Symbol sym) {
@@ -726,6 +740,8 @@ class Compiler {
return this.compileSubtract(cons.tail, ValueType.NUMBER);
}
break;
+
+ // BOOLEAN
case "<":
return this.compileLess(cons.tail, ValueType.NUMBER);
break;
@@ -742,6 +758,8 @@ class Compiler {
return vt;
case "not":
return this.compileNot(cons.tail);
+ case "eq?":
+ return this.compileEq(cons.tail);
// STRINGS
case "concat":
diff --git a/parser.d b/parser.d
index 6974662..440cae0 100644
--- a/parser.d
+++ b/parser.d
@@ -320,6 +320,34 @@ struct Value {
As as;
}
+bool areValuesEqual(Value left, Value right) {
+ if (left.type != right.type) {
+ return false;
+ }
+
+ switch (left.type) {
+ case ValueType.NUMBER:
+ return left.as.number == right.as.number;
+ case ValueType.BOOLEAN:
+ return left.as.boolean == right.as.boolean;
+ case ValueType.SEQ:
+ Seq leftSeq = cast(Seq)left.as.seq;
+ Seq rightSeq = cast(Seq)right.as.seq;
+ if (leftSeq.type != rightSeq.type) {
+ return false;
+ } else if (leftSeq.type == SeqType.STRING) {
+ return (cast(String)leftSeq).str == (cast(String)rightSeq).str;
+ } else {
+ // NOTE if eq? should work for lists, that logic goes here
+ return false;
+ }
+ default:
+ writeln("!!! THIS VALUE TYPE IS NOT SUPPORTED BY eq?");
+ return false;
+ }
+
+}
+
Value makeStringValue(string str) {
As as = { str: str };
Value val = { ValueType.STRING, as };
diff --git a/vm.d b/vm.d
index dcacd28..c7e5e8e 100644
--- a/vm.d
+++ b/vm.d
@@ -447,6 +447,11 @@ class VM {
bool bval = asBoolean(val);
this.pushA(makeBooleanValue(!bval));
break;
+ case OpCode.OP_EQUAL:
+ Value b = this.popA();
+ Value a = this.popA();
+ this.pushA(makeBooleanValue(areValuesEqual(a, b)));
+ break;
case OpCode.OP_CONCAT:
Seq b = asSeq(this.popA());
Seq a = asSeq(this.popA());