From b7fba62e9f1f9f7a5a67fd64d4aed55646d1b58e Mon Sep 17 00:00:00 2001 From: Ben Winston Date: Mon, 22 May 2023 20:12:40 -0400 Subject: runtime type checking --- vm.d | 44 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) (limited to 'vm.d') diff --git a/vm.d b/vm.d index ef6efbf..5b69a23 100644 --- a/vm.d +++ b/vm.d @@ -139,7 +139,12 @@ class VM { } bool isString(Value value) { - return value.type == ValueType.STRING; + return value.type == ValueType.STRING || + value.type == ValueType.TYPE; + } + + bool isType(Value value) { + return value.type == ValueType.TYPE; } bool isBoolean(Value value) { @@ -159,7 +164,11 @@ class VM { } string asString(Value value) { - return value.as.str; + if (value.type == ValueType.TYPE) { + return value.as.type; + } else { + return value.as.str; + } } bool asBoolean(Value value) { @@ -292,47 +301,71 @@ class VM { double val = asNumber(popA()); pushA(makeNumberValue(val * -1)); break; + case OpCode.OP_TYPE_CHECK_NUMBER: + if (!isNumber(peekA(0))) { + writeln("VM type check: not a number!"); + return InterpretResult.RUNTIME_ERROR; // TODO error + } + break; + case OpCode.OP_TYPE_CHECK_BOOLEAN: + if (!isBoolean(peekA(0))) { + writeln("VM type check: not a boolean!"); + return InterpretResult.RUNTIME_ERROR; // TODO error + } + break; case OpCode.OP_ADD: Value b = popA(); + /* if (!isNumber(b)) { writeln("b is not a number!"); return InterpretResult.RUNTIME_ERROR; // TODO error } + */ Value a = popA(); + /* if (!isNumber(a)) { writeln("a is not a number!"); return InterpretResult.RUNTIME_ERROR; // TODO error } + */ double bnum = asNumber(b); double anum = asNumber(a); pushA(makeNumberValue(anum + bnum)); break; case OpCode.OP_SUBTRACT: Value b = popA(); + /* if (!isNumber(b)) { writeln("b is not a number!"); return InterpretResult.RUNTIME_ERROR; // TODO error } + */ Value a = popA(); + /* if (!isNumber(a)) { writeln("a is not a number!"); return InterpretResult.RUNTIME_ERROR; // TODO error } + */ double bnum = asNumber(b); double anum = asNumber(a); pushA(makeNumberValue(anum - bnum)); break; case OpCode.OP_LESS: Value b = popA(); + /* if (!isNumber(b)) { writeln("b is not a number!"); return InterpretResult.RUNTIME_ERROR; // TODO error } + */ Value a = popA(); + /* if (!isNumber(a)) { writeln("a is not a number!"); return InterpretResult.RUNTIME_ERROR; // TODO error } + */ double bnum = asNumber(b); double anum = asNumber(a); pushA(makeBooleanValue(anum < bnum)); @@ -342,10 +375,7 @@ class VM { Value ret = popA(); popA(); // function this.frameCount--; - //writefln("frameCount: %d", frameCount); - //if (this.frameCount == 0) { if (this.frameCount == 1) { - popA(); writefln("returned %s", printableValue(ret)); return InterpretResult.OK; } @@ -387,10 +417,12 @@ class VM { break; case OpCode.OP_JUMP_IF_TRUE: uint offset = readShort(); + /* if (!isBoolean(peekA(0))) { writeln("expecting a boolean condition"); return InterpretResult.RUNTIME_ERROR; // TODO error } + */ if (asBoolean(peekA(0))) { current.ip += offset; } @@ -432,6 +464,8 @@ InterpretResult interpret(string source) { VM vm = new VM(); +// vm.globals[":int"] = makeTypeValue(":int"); + vm.pushA(makeObjValue(func)); CallFrame frame = { func, 0, vm.bStack, 0 }; vm.pushFrame(frame); -- cgit v1.2.3