mirror of https://github.com/japl-lang/japl.git
Fixed identity operator bug and added isnot for consistency. Changed behavior for gt/lt comparisons to account for more complex expressions
This commit is contained in:
parent
607d88f0c0
commit
5d8c31fb07
2
build.py
2
build.py
|
@ -196,7 +196,7 @@ def build(path: str, flags: Optional[Dict[str, str]] = {}, options: Optional[Dic
|
||||||
logging.debug("Running tests")
|
logging.debug("Running tests")
|
||||||
start = time()
|
start = time()
|
||||||
# TODO: Find a better way of running the test suite
|
# TODO: Find a better way of running the test suite
|
||||||
process = run_command(f"{tests_path}", mode="run", shell=True, stderr=PIPE)
|
process = run_command(f"{tests_path} {'--stdout' if verbose else ''}", mode="run", shell=True, stderr=PIPE)
|
||||||
if status != 0:
|
if status != 0:
|
||||||
logging.error(f"Command '{command}' exited with non-0 exit code {status}, output below:\n{stderr.decode()}")
|
logging.error(f"Command '{command}' exited with non-0 exit code {status}, output below:\n{stderr.decode()}")
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -312,11 +312,11 @@ proc binary(self: Compiler, canAssign: bool) =
|
||||||
of TokenType.GT:
|
of TokenType.GT:
|
||||||
self.emitByte(OpCode.Greater)
|
self.emitByte(OpCode.Greater)
|
||||||
of TokenType.GE:
|
of TokenType.GE:
|
||||||
self.emitBytes(OpCode.Less, OpCode.Not)
|
self.emitByte(OpCode.GreaterOrEqual)
|
||||||
of TokenType.LT:
|
of TokenType.LT:
|
||||||
self.emitByte(OpCode.Less)
|
self.emitByte(OpCode.Less)
|
||||||
of TokenType.LE:
|
of TokenType.LE:
|
||||||
self.emitBytes(OpCode.Greater, OpCode.Not)
|
self.emitByte(OpCode.LessOrEqual)
|
||||||
of TokenType.CARET:
|
of TokenType.CARET:
|
||||||
self.emitByte(OpCode.Xor)
|
self.emitByte(OpCode.Xor)
|
||||||
of TokenType.SHL:
|
of TokenType.SHL:
|
||||||
|
@ -329,6 +329,8 @@ proc binary(self: Compiler, canAssign: bool) =
|
||||||
self.emitByte(OpCode.Band)
|
self.emitByte(OpCode.Band)
|
||||||
of TokenType.IS:
|
of TokenType.IS:
|
||||||
self.emitByte(OpCode.Is)
|
self.emitByte(OpCode.Is)
|
||||||
|
of TokenType.ISNOT:
|
||||||
|
self.emitBytes(OpCode.Is, Opcode.Not)
|
||||||
of TokenType.AS:
|
of TokenType.AS:
|
||||||
self.emitByte(OpCode.As)
|
self.emitByte(OpCode.As)
|
||||||
else:
|
else:
|
||||||
|
@ -991,7 +993,7 @@ proc statement(self: Compiler) =
|
||||||
## Parses statements
|
## Parses statements
|
||||||
if self.parser.match(TokenType.FOR):
|
if self.parser.match(TokenType.FOR):
|
||||||
self.forStatement()
|
self.forStatement()
|
||||||
elif self.parser.match(IF):
|
elif self.parser.match(TokenType.IF):
|
||||||
self.ifStatement()
|
self.ifStatement()
|
||||||
elif self.parser.match(TokenType.WHILE):
|
elif self.parser.match(TokenType.WHILE):
|
||||||
self.whileStatement()
|
self.whileStatement()
|
||||||
|
@ -1102,7 +1104,8 @@ var rules: array[TokenType, ParseRule] = [
|
||||||
makeRule(unary, nil, Precedence.None), # TILDE
|
makeRule(unary, nil, Precedence.None), # TILDE
|
||||||
makeRule(nil, binary, Precedence.Is), # IS
|
makeRule(nil, binary, Precedence.Is), # IS
|
||||||
makeRule(nil, binary, Precedence.As), # AS
|
makeRule(nil, binary, Precedence.As), # AS
|
||||||
makeRule(parseLambda, nil, Precedence.None) # LAMBDA
|
makeRule(parseLambda, nil, Precedence.None), # LAMBDA
|
||||||
|
makeRule(nil, binary, Precedence.Is), # ISNOT
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ const RESERVED = to_table({
|
||||||
"continue": TokenType.CONTINUE, "inf": TokenType.INF,
|
"continue": TokenType.CONTINUE, "inf": TokenType.INF,
|
||||||
"nan": TokenType.NAN, "is": TokenType.IS,
|
"nan": TokenType.NAN, "is": TokenType.IS,
|
||||||
"not": TokenType.NEG, "as": TokenType.AS,
|
"not": TokenType.NEG, "as": TokenType.AS,
|
||||||
"lambda": TokenType.LAMBDA})
|
"lambda": TokenType.LAMBDA, "isnot": TokenType.ISNOT})
|
||||||
type
|
type
|
||||||
Lexer* = ref object
|
Lexer* = ref object
|
||||||
source*: string
|
source*: string
|
||||||
|
|
|
@ -44,6 +44,8 @@ type
|
||||||
Greater,
|
Greater,
|
||||||
Less,
|
Less,
|
||||||
Equal,
|
Equal,
|
||||||
|
GreaterOrEqual,
|
||||||
|
LessOrEqual,
|
||||||
Not,
|
Not,
|
||||||
GetItem,
|
GetItem,
|
||||||
Slice,
|
Slice,
|
||||||
|
@ -81,7 +83,7 @@ const simpleInstructions* = {OpCode.Return, OpCode.Add, OpCode.Multiply,
|
||||||
OpCode.Xor, OpCode.Not, OpCode.Equal,
|
OpCode.Xor, OpCode.Not, OpCode.Equal,
|
||||||
OpCode.Greater, OpCode.Less, OpCode.GetItem,
|
OpCode.Greater, OpCode.Less, OpCode.GetItem,
|
||||||
OpCode.Slice, OpCode.Pop, OpCode.Negate,
|
OpCode.Slice, OpCode.Pop, OpCode.Negate,
|
||||||
OpCode.Is, OpCode.As}
|
OpCode.Is, OpCode.As, GreaterOrEqual, LessOrEqual}
|
||||||
const constantInstructions* = {OpCode.Constant, OpCode.DefineGlobal,
|
const constantInstructions* = {OpCode.Constant, OpCode.DefineGlobal,
|
||||||
OpCode.GetGlobal, OpCode.SetGlobal,
|
OpCode.GetGlobal, OpCode.SetGlobal,
|
||||||
OpCode.DeleteGlobal}
|
OpCode.DeleteGlobal}
|
||||||
|
|
|
@ -29,7 +29,8 @@ type
|
||||||
WHILE, DEL, BREAK, EOF,
|
WHILE, DEL, BREAK, EOF,
|
||||||
COLON, CONTINUE, CARET,
|
COLON, CONTINUE, CARET,
|
||||||
SHL, SHR, NAN, INF, BAND,
|
SHL, SHR, NAN, INF, BAND,
|
||||||
BOR, TILDE, IS, AS, LAMBDA
|
BOR, TILDE, IS, AS, LAMBDA,
|
||||||
|
ISNOT
|
||||||
Token* = object
|
Token* = object
|
||||||
kind*: TokenType
|
kind*: TokenType
|
||||||
lexeme*: string
|
lexeme*: string
|
||||||
|
|
|
@ -31,7 +31,7 @@ proc newFunction*(name: string = "", chunk: Chunk, arity: int = 0): ptr Function
|
||||||
## anonymous code object
|
## anonymous code object
|
||||||
# TODO: Add support for optional parameters
|
# TODO: Add support for optional parameters
|
||||||
result = allocateObj(Function, ObjectType.Function)
|
result = allocateObj(Function, ObjectType.Function)
|
||||||
if name.len > 1:
|
if name.len >= 1:
|
||||||
result.name = name.asStr()
|
result.name = name.asStr()
|
||||||
else:
|
else:
|
||||||
result.name = nil
|
result.name = nil
|
||||||
|
|
|
@ -391,7 +391,7 @@ proc binaryNot*(self: ptr Obj): returnType =
|
||||||
raise newException(NotImplementedError, "")
|
raise newException(NotImplementedError, "")
|
||||||
|
|
||||||
|
|
||||||
proc lt*(self: ptr Obj, other: ptr Obj): bool =
|
proc lt*(self: ptr Obj, other: ptr Obj): tuple[result: bool, obj: ptr Obj] =
|
||||||
## Returns the result of self < other or
|
## Returns the result of self < other or
|
||||||
## raises an error if the operation
|
## raises an error if the operation
|
||||||
## is unsupported
|
## is unsupported
|
||||||
|
@ -406,7 +406,7 @@ proc lt*(self: ptr Obj, other: ptr Obj): bool =
|
||||||
raise newException(NotImplementedError, "")
|
raise newException(NotImplementedError, "")
|
||||||
|
|
||||||
|
|
||||||
proc gt*(self: ptr Obj, other: ptr Obj): bool =
|
proc gt*(self: ptr Obj, other: ptr Obj): tuple[result: bool, obj: ptr Obj] =
|
||||||
## Returns the result of self > other or
|
## Returns the result of self > other or
|
||||||
## raises an error if the operation
|
## raises an error if the operation
|
||||||
## is unsupported
|
## is unsupported
|
||||||
|
|
|
@ -133,50 +133,50 @@ proc eq*(self, other: ptr Infinity): bool =
|
||||||
result = self.isNegative == other.isNegative
|
result = self.isNegative == other.isNegative
|
||||||
|
|
||||||
|
|
||||||
proc lt*(self: ptr Infinity, other: ptr Obj): bool =
|
proc lt*(self: ptr Infinity, other: ptr Obj): tuple[result: bool, obj: ptr Obj] =
|
||||||
case other.kind:
|
case other.kind:
|
||||||
of ObjectType.Integer:
|
of ObjectType.Integer:
|
||||||
let other = cast[ptr Integer](other)
|
let other = cast[ptr Integer](other)
|
||||||
if self.isNegative and other.intValue > 0:
|
if self.isNegative:
|
||||||
result = true
|
result = (result: true, obj: other)
|
||||||
else:
|
else:
|
||||||
result = false
|
result = (result: false, obj: nil)
|
||||||
of ObjectType.Float:
|
of ObjectType.Float:
|
||||||
let other = cast[ptr Float](other)
|
let other = cast[ptr Float](other)
|
||||||
if self.isNegative and other.floatValue > 0.0:
|
if self.isNegative:
|
||||||
result = true
|
result = (result: true, obj: other)
|
||||||
else:
|
else:
|
||||||
result = false
|
result = (result: false, obj: nil)
|
||||||
of ObjectType.Infinity:
|
of ObjectType.Infinity:
|
||||||
let other = cast[ptr Infinity](other)
|
let other = cast[ptr Infinity](other)
|
||||||
if other.isNegative and not self.isNegative:
|
if other.isNegative and not self.isNegative:
|
||||||
result = false
|
result = (result: true, obj: other)
|
||||||
else:
|
else:
|
||||||
result = false
|
result = (result: false, obj: nil)
|
||||||
else:
|
else:
|
||||||
raise newException(NotImplementedError, "")
|
raise newException(NotImplementedError, "")
|
||||||
|
|
||||||
|
|
||||||
proc gt*(self: ptr Infinity, other: ptr Obj): bool =
|
proc gt*(self: ptr Infinity, other: ptr Obj): tuple[result: bool, obj: ptr Obj] =
|
||||||
case other.kind:
|
case other.kind:
|
||||||
of ObjectType.Integer:
|
of ObjectType.Integer:
|
||||||
let other = cast[ptr Integer](other)
|
let other = cast[ptr Integer](other)
|
||||||
if self.isNegative and other.intValue > 0:
|
if self.isNegative:
|
||||||
result = false
|
result = (result: false, obj: nil)
|
||||||
else:
|
else:
|
||||||
result = true
|
result = (result: true, obj: other)
|
||||||
of ObjectType.Float:
|
of ObjectType.Float:
|
||||||
let other = cast[ptr Float](other)
|
let other = cast[ptr Float](other)
|
||||||
if self.isNegative and other.floatValue > 0.0:
|
if self.isNegative:
|
||||||
result = false
|
result = (result: false, obj: nil)
|
||||||
else:
|
else:
|
||||||
result = true
|
result = (result: true, obj: other)
|
||||||
of ObjectType.Infinity:
|
of ObjectType.Infinity:
|
||||||
let other = cast[ptr Infinity](other)
|
let other = cast[ptr Infinity](other)
|
||||||
if other.isNegative and not self.isNegative:
|
if other.isNegative and not self.isNegative:
|
||||||
result = true
|
result = (result: false, obj: nil)
|
||||||
else:
|
else:
|
||||||
result = false
|
result = (result: true, obj: other)
|
||||||
else:
|
else:
|
||||||
raise newException(NotImplementedError, "")
|
raise newException(NotImplementedError, "")
|
||||||
|
|
||||||
|
@ -216,7 +216,7 @@ proc stringify*(self: ptr Float): string =
|
||||||
|
|
||||||
|
|
||||||
proc isFalsey*(self: ptr Float): bool =
|
proc isFalsey*(self: ptr Float): bool =
|
||||||
result = self.floatValue == 0.0
|
result = false
|
||||||
|
|
||||||
|
|
||||||
proc hash*(self: ptr Float): uint64 =
|
proc hash*(self: ptr Float): uint64 =
|
||||||
|
@ -243,7 +243,7 @@ proc stringify*(self: ptr Integer): string =
|
||||||
|
|
||||||
|
|
||||||
proc isFalsey*(self: ptr Integer): bool =
|
proc isFalsey*(self: ptr Integer): bool =
|
||||||
result = self.intValue == 0
|
result = false
|
||||||
|
|
||||||
|
|
||||||
proc eq*(self, other: ptr Integer): bool =
|
proc eq*(self, other: ptr Integer): bool =
|
||||||
|
@ -259,66 +259,90 @@ proc hash*(self: ptr Integer): uint64 =
|
||||||
result = uint64 self.intValue
|
result = uint64 self.intValue
|
||||||
|
|
||||||
|
|
||||||
proc lt*(self: ptr Integer, other: ptr Obj): bool =
|
proc lt*(self: ptr Integer, other: ptr Obj): tuple[result: bool, obj: ptr Obj] =
|
||||||
case other.kind:
|
case other.kind:
|
||||||
of ObjectType.Integer:
|
of ObjectType.Integer:
|
||||||
result = self.intValue < cast[ptr Integer](other).intValue
|
if self.intValue < cast[ptr Integer](other).intValue:
|
||||||
|
result = (result: true, obj: other)
|
||||||
|
else:
|
||||||
|
result = (result: false, obj: nil)
|
||||||
of ObjectType.Float:
|
of ObjectType.Float:
|
||||||
result = (float self.intValue) < cast[ptr Float](other).floatValue
|
if (float self.intValue) < cast[ptr Float](other).floatValue:
|
||||||
|
result = (result: true, obj: other)
|
||||||
|
else:
|
||||||
|
result = (result: false, obj: nil)
|
||||||
of ObjectType.Infinity:
|
of ObjectType.Infinity:
|
||||||
let other = cast[ptr Infinity](other)
|
let other = cast[ptr Infinity](other)
|
||||||
if other.isNegative:
|
if other.isNegative:
|
||||||
result = false
|
result = (result: true, obj: other)
|
||||||
else:
|
else:
|
||||||
result = true
|
result = (result: false, obj: nil)
|
||||||
else:
|
else:
|
||||||
raise newException(NotImplementedError, "")
|
raise newException(NotImplementedError, "")
|
||||||
|
|
||||||
|
|
||||||
proc lt*(self: ptr Float, other: ptr Obj): bool =
|
proc lt*(self: ptr Float, other: ptr Obj): tuple[result: bool, obj: ptr Obj] =
|
||||||
case other.kind:
|
case other.kind:
|
||||||
of ObjectType.Integer:
|
of ObjectType.Integer:
|
||||||
result = self.floatValue < (float cast[ptr Integer](other).intValue)
|
if self.floatValue < (float cast[ptr Integer](other).intValue):
|
||||||
|
result = (result: true, obj: other)
|
||||||
|
else:
|
||||||
|
result = (result: false, obj: nil)
|
||||||
of ObjectType.Float:
|
of ObjectType.Float:
|
||||||
result = self.floatValue < cast[ptr Float](other).floatValue
|
if self.floatValue < cast[ptr Float](other).floatValue:
|
||||||
|
result = (result: true, obj: other)
|
||||||
|
else:
|
||||||
|
result = (result: false, obj: nil)
|
||||||
of ObjectType.Infinity:
|
of ObjectType.Infinity:
|
||||||
let other = cast[ptr Infinity](other)
|
let other = cast[ptr Infinity](other)
|
||||||
if other.isNegative:
|
if other.isNegative:
|
||||||
result = false
|
result = (result: true, obj: other)
|
||||||
else:
|
else:
|
||||||
result = true
|
result = (result: false, obj: nil)
|
||||||
else:
|
else:
|
||||||
raise newException(NotImplementedError, "")
|
raise newException(NotImplementedError, "")
|
||||||
|
|
||||||
|
|
||||||
proc gt*(self: ptr Integer, other: ptr Obj): bool =
|
proc gt*(self: ptr Integer, other: ptr Obj): tuple[result: bool, obj: ptr Obj] =
|
||||||
case other.kind:
|
case other.kind:
|
||||||
of ObjectType.Integer:
|
of ObjectType.Integer:
|
||||||
result = self.intValue > cast[ptr Integer](other).intValue
|
if self.intValue > cast[ptr Integer](other).intValue:
|
||||||
|
result = (result: true, obj: other)
|
||||||
|
else:
|
||||||
|
result = (result: false, obj: nil)
|
||||||
of ObjectType.Float:
|
of ObjectType.Float:
|
||||||
result = (float self.intValue) > cast[ptr Float](other).floatValue
|
if (float self.intValue) > cast[ptr Float](other).floatValue:
|
||||||
|
result = (result: true, obj: other)
|
||||||
|
else:
|
||||||
|
result = (result: false, obj: nil)
|
||||||
of ObjectType.Infinity:
|
of ObjectType.Infinity:
|
||||||
let other = cast[ptr Infinity](other)
|
let other = cast[ptr Infinity](other)
|
||||||
if other.isNegative:
|
if other.isNegative:
|
||||||
result = true
|
result = (result: true, obj: other)
|
||||||
else:
|
else:
|
||||||
result = false
|
result = (result: false, obj: nil)
|
||||||
else:
|
else:
|
||||||
raise newException(NotImplementedError, "")
|
raise newException(NotImplementedError, "")
|
||||||
|
|
||||||
|
|
||||||
proc gt*(self: ptr Float, other: ptr Obj): bool =
|
proc gt*(self: ptr Float, other: ptr Obj): tuple[result: bool, obj: ptr Obj] =
|
||||||
case other.kind:
|
case other.kind:
|
||||||
of ObjectType.Integer:
|
of ObjectType.Integer:
|
||||||
result = self.floatValue > (float cast[ptr Integer](other).intValue)
|
if self.floatValue > (float cast[ptr Integer](other).intValue):
|
||||||
|
result = (result: true, obj: other)
|
||||||
|
else:
|
||||||
|
result = (result: false, obj: nil)
|
||||||
of ObjectType.Float:
|
of ObjectType.Float:
|
||||||
result = self.floatValue > cast[ptr Float](other).floatValue
|
if self.floatValue > cast[ptr Float](other).floatValue:
|
||||||
|
result = (result: true, obj: other)
|
||||||
|
else:
|
||||||
|
result = (result: false, obj: nil)
|
||||||
of ObjectType.Infinity:
|
of ObjectType.Infinity:
|
||||||
let other = cast[ptr Infinity](other)
|
let other = cast[ptr Infinity](other)
|
||||||
if other.isNegative:
|
if other.isNegative:
|
||||||
result = true
|
result = (result: true, obj: other)
|
||||||
else:
|
else:
|
||||||
result = false
|
result = (result: false, obj: nil)
|
||||||
else:
|
else:
|
||||||
raise newException(NotImplementedError, "")
|
raise newException(NotImplementedError, "")
|
||||||
|
|
||||||
|
|
51
src/vm.nim
51
src/vm.nim
|
@ -505,8 +505,13 @@ proc run(self: VM): InterpretResult =
|
||||||
# Binary less (<)
|
# Binary less (<)
|
||||||
var right = self.pop()
|
var right = self.pop()
|
||||||
var left = self.pop()
|
var left = self.pop()
|
||||||
|
var comp: tuple[result: bool, obj: ptr Obj]
|
||||||
try:
|
try:
|
||||||
self.push(self.getBoolean(left.lt(right)))
|
comp = left.lt(right)
|
||||||
|
if system.`==`(comp.obj, nil):
|
||||||
|
self.push(self.getBoolean(comp.result))
|
||||||
|
else:
|
||||||
|
self.push(comp.obj)
|
||||||
except NotImplementedError:
|
except NotImplementedError:
|
||||||
self.error(newTypeError(&"unsupported binary operator '<' for objects of type '{left.typeName()}' and '{right.typeName()}'"))
|
self.error(newTypeError(&"unsupported binary operator '<' for objects of type '{left.typeName()}' and '{right.typeName()}'"))
|
||||||
return RuntimeError
|
return RuntimeError
|
||||||
|
@ -514,18 +519,55 @@ proc run(self: VM): InterpretResult =
|
||||||
# Binary greater (>)
|
# Binary greater (>)
|
||||||
var right = self.pop()
|
var right = self.pop()
|
||||||
var left = self.pop()
|
var left = self.pop()
|
||||||
|
var comp: tuple[result: bool, obj: ptr Obj]
|
||||||
try:
|
try:
|
||||||
self.push(self.getBoolean(left.gt(right)))
|
comp = left.gt(right)
|
||||||
|
if system.`==`(comp.obj, nil):
|
||||||
|
self.push(self.getBoolean(comp.result))
|
||||||
|
else:
|
||||||
|
self.push(comp.obj)
|
||||||
|
except NotImplementedError:
|
||||||
|
self.error(newTypeError(&"unsupported binary operator '>' for objects of type '{left.typeName()}' and '{right.typeName()}'"))
|
||||||
|
return RuntimeError
|
||||||
|
of OpCode.LessOrEqual:
|
||||||
|
var right = self.pop()
|
||||||
|
var left = self.pop()
|
||||||
|
var comp: tuple[result: bool, obj: ptr Obj]
|
||||||
|
try:
|
||||||
|
comp = left.lt(right)
|
||||||
|
if not comp.result and left == right:
|
||||||
|
comp.result = true
|
||||||
|
if system.`==`(comp.obj, nil):
|
||||||
|
self.push(self.getBoolean(comp.result))
|
||||||
|
else:
|
||||||
|
self.push(comp.obj)
|
||||||
|
except NotImplementedError:
|
||||||
|
self.error(newTypeError(&"unsupported binary operator '<' for objects of type '{left.typeName()}' and '{right.typeName()}'"))
|
||||||
|
return RuntimeError
|
||||||
|
of OpCode.GreaterOrEqual:
|
||||||
|
var right = self.pop()
|
||||||
|
var left = self.pop()
|
||||||
|
var comp: tuple[result: bool, obj: ptr Obj]
|
||||||
|
try:
|
||||||
|
comp = left.gt(right)
|
||||||
|
if not comp.result and left == right:
|
||||||
|
comp.result = true
|
||||||
|
if system.`==`(comp.obj, nil):
|
||||||
|
self.push(self.getBoolean(comp.result))
|
||||||
|
else:
|
||||||
|
self.push(comp.obj)
|
||||||
except NotImplementedError:
|
except NotImplementedError:
|
||||||
self.error(newTypeError(&"unsupported binary operator '>' for objects of type '{left.typeName()}' and '{right.typeName()}'"))
|
self.error(newTypeError(&"unsupported binary operator '>' for objects of type '{left.typeName()}' and '{right.typeName()}'"))
|
||||||
return RuntimeError
|
return RuntimeError
|
||||||
of OpCode.Is:
|
of OpCode.Is:
|
||||||
# Implements object identity (i.e. same pointer)
|
# Implements object identity (i.e. same pointer)
|
||||||
# This is implemented internally for obvious
|
# This is implemented internally for obvious
|
||||||
# reasons and works on any pair of objects
|
# reasons and works on any pair of objects, which
|
||||||
|
# is why we call nim's system.== operator and NOT
|
||||||
|
# our custom one
|
||||||
var right = self.pop()
|
var right = self.pop()
|
||||||
var left = self.pop()
|
var left = self.pop()
|
||||||
self.push(self.getBoolean(left == right))
|
self.push(self.getBoolean(system.`==`(left, right)))
|
||||||
of OpCode.As:
|
of OpCode.As:
|
||||||
# Implements type casting (TODO: Only allow classes)
|
# Implements type casting (TODO: Only allow classes)
|
||||||
var right = self.pop()
|
var right = self.pop()
|
||||||
|
@ -629,6 +671,7 @@ proc run(self: VM): InterpretResult =
|
||||||
# Handles returning values from the callee to the caller
|
# Handles returning values from the callee to the caller
|
||||||
# and sets up the stack to proceed with execution
|
# and sets up the stack to proceed with execution
|
||||||
var retResult = self.pop()
|
var retResult = self.pop()
|
||||||
|
# Pops the function's frame
|
||||||
discard self.frames.pop()
|
discard self.frames.pop()
|
||||||
if self.frames.len() == 0:
|
if self.frames.len() == 0:
|
||||||
discard self.pop()
|
discard self.pop()
|
||||||
|
|
|
@ -9,17 +9,17 @@ print(false and 3 or 4);//stdout:4
|
||||||
print(true and 3 or 4);//stdout:3
|
print(true and 3 or 4);//stdout:3
|
||||||
print(true and 2);//stdout:2
|
print(true and 2);//stdout:2
|
||||||
print(false or 5);//stdout:5
|
print(false or 5);//stdout:5
|
||||||
print(0 or 4);//stdout:4
|
print(nil or 4);//stdout:4
|
||||||
print(0 and true);//stdout:0
|
print(0 or true);//stdout:0
|
||||||
print("" and true);//stdout:''
|
print("" and true);//stdout:''
|
||||||
print("" or true);//stdout:true
|
print("" or true);//stdout:true
|
||||||
print(1 or 2 or 3 or 4);//stdout:1
|
print(1 or 2 or 3 or 4);//stdout:1
|
||||||
print(1 and 2 and 3 and 4);//stdout:4
|
print(1 and 2 and 3 and 4);//stdout:4
|
||||||
print(1 and 2 or 3 and 4);//stdout:2
|
print(1 and 2 or 3 and 4);//stdout:2
|
||||||
print(1 and false or 3 and 4);//stdout:4
|
print(1 and false or 3 and 4);//stdout:4
|
||||||
print(not 0);//stdout:true
|
print(not false);//stdout:true
|
||||||
print(not 1);//stdout:false
|
print(not 1);//stdout:false
|
||||||
print(not 1 and not 2);//stdout:false
|
print(not 1 and not 2);//stdout:false
|
||||||
print(not (1 and 0));//stdout:true
|
print(not (1 and false));//stdout:true
|
||||||
[end]
|
[end]
|
||||||
[end]
|
[end]
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
[Test: is]
|
[Test: is]
|
||||||
[skip]
|
|
||||||
[source:mixed]
|
[source:mixed]
|
||||||
var x = 4;
|
var x = 4;
|
||||||
var y = x;
|
var y = x;
|
||||||
|
|
Loading…
Reference in New Issue