diff --git a/src/backend/vm.nim b/src/backend/vm.nim index 59803e5..695a707 100644 --- a/src/backend/vm.nim +++ b/src/backend/vm.nim @@ -80,6 +80,22 @@ proc getInf*(self: PeonVM, positive: bool): PeonObject {.inline.} = proc getNan*(self: PeonVM): PeonObject {.inline.} = self.cache[5] + +# Thanks to nim's *genius* idea of making x !> y a template +# for y < x (which by itself is fine) together with the fact +# that the order of evaluation of templates with the same +# expression is fucking stupid (see https://nim-lang.org/docs/manual.html#order-of-evaluation +# and https://github.com/nim-lang/Nim/issues/10425 and try not to +# bang your head against the nearest wall), we need a custom operator +# that preserves the natural order of evaluation +proc `!>`[T](a, b: T): auto {.inline.} = + b < a + + +proc `!>=`[T](a, b: T): auto {.inline, used.} = + b <= a + + # Stack primitives. Note: all stack accessing that goes # through the get(c)/set(c)/peek(c) wrappers is frame-relative, # meaning that the index is added to the current stack frame's @@ -268,7 +284,7 @@ proc constReadString(self: PeonVM, size: int, idx: int): PeonObject = ## chunk's constant table and ## returns a Peon object. Assumes ## the constant is a string - result = PeonObject(kind: String, str: self.chunk.consts[idx..< idx + size].fromBytes()) + result = PeonObject(kind: String, str: self.chunk.consts[idx.. 0: + if self.calls.len() !> 0: echo &"Call Stack: {self.calls}" - if self.operands.len() > 0: + if self.operands.len() !> 0: echo &"Operand Stack: {self.operands}" - if self.frames.len() > 0: + if self.frames.len() !> 0: echo &"Current Frame: {self.calls[self.frames[^1]..^1]}" echo &"Frames: {self.frames}" - if self.closedOver.len() > 0: + if self.closedOver.len() !> 0: echo &"Closure Array: {self.closedOver}" - if self.results.len() > 0: + if self.results.len() !> 0: echo &"Results: {self.results}" discard readLine stdin instruction = OpCode(self.readByte()) @@ -390,7 +406,7 @@ proc dispatch*(self: PeonVM) = # TODO: Use the frame's initial size once # we have more control over the # memory - #[while argc > 0: + #[while argc !> 0: dec(argc) self.pushc(self.getNil()) ]# @@ -400,7 +416,7 @@ proc dispatch*(self: PeonVM) = # in a hidden function, so this # will also exit the VM if we're # at the end of the program - while self.calls.len() > self.frames[^1] + 2: + while self.calls.len() !> self.frames[^1] + 2: # Discards the function's local variables, # if there is any discard self.popc() @@ -437,7 +453,7 @@ proc dispatch*(self: PeonVM) = # Stores/updates the value of a closed-over # variable let idx = self.readLong().int - if idx > self.closedOver.high(): + if idx !> self.closedOver.high(): # Note: we *peek* the stack, but we # don't pop! self.closedOver.add(self.peek()) @@ -468,7 +484,7 @@ proc dispatch*(self: PeonVM) = # Pops a peon object off the # operand stack and prints it. # Used in interactive REPL mode - if self.frames.len() > 1: + if self.frames.len() !> 1: discard self.pop() continue echo self.pop() @@ -599,7 +615,7 @@ proc dispatch*(self: PeonVM) = of LessThanInt64: self.push(PeonObject(kind: Bool, boolean: self.pop().long < self.pop().long)) of GreaterThanInt64: - self.push(PeonObject(kind: Bool, boolean: self.pop().long > self.pop().long)) + self.push(PeonObject(kind: Bool, boolean: self.pop().long !> self.pop().long)) of EqualInt64: self.push(PeonObject(kind: Bool, boolean: self.pop().long == self.pop().long)) of NotEqualInt64: @@ -607,7 +623,7 @@ proc dispatch*(self: PeonVM) = of LessThanUInt64: self.push(PeonObject(kind: Bool, boolean: self.pop().long < self.pop().long)) of GreaterThanUInt64: - self.push(PeonObject(kind: Bool, boolean: self.pop().long > self.pop().long)) + self.push(PeonObject(kind: Bool, boolean: self.pop().long !> self.pop().long)) of EqualUInt64: self.push(PeonObject(kind: Bool, boolean: self.pop().long == self.pop().long)) of NotEqualUInt64: @@ -615,7 +631,7 @@ proc dispatch*(self: PeonVM) = of LessThanInt32: self.push(PeonObject(kind: Bool, boolean: self.pop().`int` < self.pop().`int`)) of GreaterThanInt32: - self.push(PeonObject(kind: Bool, boolean: self.pop().`int` > self.pop().`int`)) + self.push(PeonObject(kind: Bool, boolean: self.pop().`int` !> self.pop().`int`)) of EqualInt32: self.push(PeonObject(kind: Bool, boolean: self.pop().`int` == self.pop().`int`)) of NotEqualInt32: @@ -623,7 +639,7 @@ proc dispatch*(self: PeonVM) = of LessThanUInt32: self.push(PeonObject(kind: Bool, boolean: self.pop().uInt < self.pop().uInt)) of GreaterThanUInt32: - self.push(PeonObject(kind: Bool, boolean: self.pop().uInt > self.pop().uInt)) + self.push(PeonObject(kind: Bool, boolean: self.pop().uInt !> self.pop().uInt)) of EqualUInt32: self.push(PeonObject(kind: Bool, boolean: self.pop().uInt == self.pop().uInt)) of NotEqualUInt32: @@ -631,7 +647,7 @@ proc dispatch*(self: PeonVM) = of LessThanInt16: self.push(PeonObject(kind: Bool, boolean: self.pop().short < self.pop().short)) of GreaterThanInt16: - self.push(PeonObject(kind: Bool, boolean: self.pop().short > self.pop().short)) + self.push(PeonObject(kind: Bool, boolean: self.pop().short !> self.pop().short)) of EqualInt16: self.push(PeonObject(kind: Bool, boolean: self.pop().short == self.pop().short)) of NotEqualInt16: @@ -639,7 +655,7 @@ proc dispatch*(self: PeonVM) = of LessThanUInt16: self.push(PeonObject(kind: Bool, boolean: self.pop().uShort < self.pop().uShort)) of GreaterThanUInt16: - self.push(PeonObject(kind: Bool, boolean: self.pop().uShort > self.pop().uShort)) + self.push(PeonObject(kind: Bool, boolean: self.pop().uShort !> self.pop().uShort)) of EqualUInt16: self.push(PeonObject(kind: Bool, boolean: self.pop().uShort == self.pop().uShort)) of NotEqualUInt16: @@ -647,7 +663,7 @@ proc dispatch*(self: PeonVM) = of LessThanInt8: self.push(PeonObject(kind: Bool, boolean: self.pop().tiny < self.pop().tiny)) of GreaterThanInt8: - self.push(PeonObject(kind: Bool, boolean: self.pop().tiny > self.pop().tiny)) + self.push(PeonObject(kind: Bool, boolean: self.pop().tiny !> self.pop().tiny)) of EqualInt8: self.push(PeonObject(kind: Bool, boolean: self.pop().tiny == self.pop().tiny)) of NotEqualInt8: @@ -655,7 +671,7 @@ proc dispatch*(self: PeonVM) = of LessThanUInt8: self.push(PeonObject(kind: Bool, boolean: self.pop().uTiny < self.pop().uTiny)) of GreaterThanUInt8: - self.push(PeonObject(kind: Bool, boolean: self.pop().uTiny > self.pop().uTiny)) + self.push(PeonObject(kind: Bool, boolean: self.pop().uTiny !> self.pop().uTiny)) of EqualUInt8: self.push(PeonObject(kind: Bool, boolean: self.pop().uTiny == self.pop().uTiny)) of NotEqualUInt8: @@ -663,7 +679,7 @@ proc dispatch*(self: PeonVM) = of LessThanFloat64: self.push(PeonObject(kind: Bool, boolean: self.pop().`float` < self.pop().`float`)) of GreaterThanFloat64: - self.push(PeonObject(kind: Bool, boolean: self.pop().`float` > self.pop().`float`)) + self.push(PeonObject(kind: Bool, boolean: self.pop().`float` !> self.pop().`float`)) of EqualFloat64: self.push(PeonObject(kind: Bool, boolean: self.pop().`float` == self.pop().`float`)) of NotEqualFLoat64: @@ -671,7 +687,7 @@ proc dispatch*(self: PeonVM) = of LessThanFloat32: self.push(PeonObject(kind: Bool, boolean: self.pop().halfFloat < self.pop().halfFloat)) of GreaterThanFloat32: - self.push(PeonObject(kind: Bool, boolean: self.pop().halfFloat > self.pop().halfFloat)) + self.push(PeonObject(kind: Bool, boolean: self.pop().halfFloat !> self.pop().halfFloat)) of EqualFloat32: self.push(PeonObject(kind: Bool, boolean: self.pop().halfFloat == self.pop().halfFloat)) of NotEqualFloat32: diff --git a/tests/comparisons.pn b/tests/comparisons.pn index 48681e2..d567ae8 100644 --- a/tests/comparisons.pn +++ b/tests/comparisons.pn @@ -2,6 +2,7 @@ import std; print(3 > 2); # true -print(2 < 3); # false +print(2 < 3); # true +print(3 < 2); # false print(2 == 3); # false print(2 != 3); # true