From aab6510a0e59c26a31526ff303a9d581736815fc Mon Sep 17 00:00:00 2001 From: mryouse Date: Fri, 26 May 2023 02:52:39 +0000 Subject: eq? for many things --- chunk.d | 1 + compiler.d | 18 ++++++++++++++++++ parser.d | 28 ++++++++++++++++++++++++++++ vm.d | 5 +++++ 4 files changed, 52 insertions(+) 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()); -- cgit v1.2.3