Type system refactoring complete, some recursion debugging. Bumped up version to 0.3.0

This commit is contained in:
nocturn9x 2020-10-27 18:59:36 +01:00
parent ef08fee976
commit 1b8b8d9096
3 changed files with 702 additions and 41 deletions

View File

@ -15,10 +15,10 @@
import strformat
const MAP_LOAD_FACTOR = 0.75 # Load factor for builtin hashmaps (TODO)
const ARRAY_GROW_FACTOR = 2 # How much extra memory to allocate for dynamic arrays (TODO)
const FRAMES_MAX* = 400 # TODO: Inspect why the VM crashes if this exceeds 400
const JAPL_VERSION* = "0.2.0"
const MAP_LOAD_FACTOR* = 0.75 # Load factor for builtin hashmaps (TODO)
const ARRAY_GROW_FACTOR* = 2 # How much extra memory to allocate for dynamic arrays (TODO)
const FRAMES_MAX* = 805 # TODO: Inspect why the VM crashes if this exceeds this value
const JAPL_VERSION* = "0.3.0"
const JAPL_RELEASE* = "alpha"
const DEBUG_TRACE_VM* = false # Traces VM execution
const DEBUG_TRACE_GC* = false # Traces the garbage collector (TODO)

View File

@ -18,6 +18,7 @@
import ../memory
import strformat
import math
type
@ -79,6 +80,11 @@ type
message*: ptr String
# Custom operators
proc `**`(a, b: int): int = pow(a.float, b.float).int
proc `**`(a, b: float): float = pow(a, b)
## Object constructors and allocators
proc allocateObject*(size: int, kind: ObjectType): ptr Obj =
@ -307,10 +313,22 @@ proc typeName(self: ptr Integer): string =
result = "integer"
proc typeName(self: ptr NotANumber): string =
result = "float"
proc typeName(self: ptr Float): string =
result = "float"
proc typeName(self: ptr Infinity): string =
result = "infinity"
proc typeName(self: ptr Nil): string =
result = "nil"
proc typeName(self: ptr Bool): string =
result = "bool"
@ -565,11 +583,13 @@ proc eq(self, other: ptr Bool): bool =
proc eq(self, other: ptr Function): bool =
result = self.name.stringify() == other.name.stringify()
result = self.name.stringify() == other.name.stringify() # Since in JAPL functions cannot
# be overridden, if two function names are equal they are also the same
# function object (TODO: Verify this)
proc eq(self, other: ptr NotANumber): bool =
result = false
result = false # As per IEEE 754 spec, nan != nan
proc eq(self, other: ptr Nil): bool =
@ -584,7 +604,8 @@ proc eq*(self, other: ptr Obj): bool =
## Compares two objects for equality,
## returns true if self equals other
## and false otherwise
if self.kind != other.kind:
if self.kind != other.kind: # If the types are different it's not
# even worth going any further (and you couldn't anyway)
return false
case self.kind:
of ObjectType.BaseObject:
@ -609,10 +630,215 @@ proc eq*(self, other: ptr Obj): bool =
var self = cast[ptr Function](self)
var other = cast[ptr Function](other)
result = self.eq(other)
of ObjectType.Infinity:
var self = cast[ptr Infinity](self)
var other = cast[ptr Infinity](other)
result = self.eq(other)
of ObjectType.NotANumber:
var self = cast[ptr NotANumber](self)
var other = cast[ptr NotANumber](other)
result = self.eq(other)
of ObjectType.Nil:
var self = cast[ptr Nil](self)
var other = cast[ptr Nil](other)
result = self.eq(other)
else:
discard # TODO
proc negate(self: ptr Integer): ptr Integer =
result = (-self.toInt()).asInt()
proc negate(self: ptr Float): ptr Float =
result = (-self.toFloat()).asFloat()
proc negate(self: ptr Infinity): ptr Infinity =
result = asInf()
result.isNegative = true
proc negate*(self: ptr Obj): ptr Obj =
## Returns the result of -self or
## raises an error if the operation
## is unsupported
case self.kind:
of ObjectType.Integer:
result = cast[ptr Integer](self).negate()
of ObjectType.Float:
result = cast[ptr Float](self).negate()
of ObjectType.Infinity:
result = cast[ptr Infinity](self).negate()
else:
raise newException(NotImplementedError, &"unsupported unary operator '-' for object of type '{self.typeName()}'")
proc lt(self: ptr Integer, other: ptr Obj): bool =
case other.kind:
of ObjectType.Integer:
result = self.intValue < cast[ptr Integer](other).intValue
of ObjectType.Float:
result = (float self.intValue) < cast[ptr Float](other).floatValue
of ObjectType.Infinity:
let other = cast[ptr Infinity](other)
if other.isNegative:
result = false
else:
result = true
else:
raise newException(NotImplementedError, &"unsupported binary operator '<' for object of type '{self.typeName()}'")
proc lt(self: ptr Float, other: ptr Obj): bool =
case other.kind:
of ObjectType.Integer:
result = self.floatValue < (float cast[ptr Integer](other).intValue)
of ObjectType.Float:
result = self.floatValue < cast[ptr Float](other).floatValue
of ObjectType.Infinity:
let other = cast[ptr Infinity](other)
if other.isNegative:
result = false
else:
result = true
else:
raise newException(NotImplementedError, &"unsupported binary operator '<' for object of type '{self.typeName()}'")
proc lt(self: ptr Infinity, other: ptr Obj): bool =
case other.kind:
of ObjectType.Integer:
let other = cast[ptr Integer](other)
if self.isNegative and other.intValue > 0:
result = true
else:
result = false
of ObjectType.Float:
let other = cast[ptr Float](other)
if self.isNegative and other.floatValue > 0.0:
result = true
else:
result = false
of ObjectType.Infinity:
let other = cast[ptr Infinity](other)
if other.isNegative and not self.isNegative:
result = false
else:
result = false
else:
raise newException(NotImplementedError, &"unsupported binary operator '<' for object of type '{self.typeName()}'")
proc lt*(self: ptr Obj, other: ptr Obj): bool =
## Returns the result of self < other or
## raises an error if the operation
## is unsupported
case self.kind:
of ObjectType.Integer:
result = cast[ptr Integer](self).lt(other)
of ObjectType.Float:
result = cast[ptr Float](self).lt(other)
of ObjectType.Infinity:
result = cast[ptr Infinity](self).lt(other)
else:
raise newException(NotImplementedError, &"unsupported binary operator '<' for object of type '{self.typeName()}'")
proc gt(self: ptr Integer, other: ptr Obj): bool =
case other.kind:
of ObjectType.Integer:
result = self.intValue > cast[ptr Integer](other).intValue
of ObjectType.Float:
result = (float self.intValue) > cast[ptr Float](other).floatValue
of ObjectType.Infinity:
let other = cast[ptr Infinity](other)
if other.isNegative:
result = true
else:
result = false
else:
raise newException(NotImplementedError, &"unsupported binary operator '>' for object of type '{self.typeName()}'")
proc gt(self: ptr Float, other: ptr Obj): bool =
case other.kind:
of ObjectType.Integer:
result = self.floatValue > (float cast[ptr Integer](other).intValue)
of ObjectType.Float:
result = self.floatValue > cast[ptr Float](other).floatValue
of ObjectType.Infinity:
let other = cast[ptr Infinity](other)
if other.isNegative:
result = true
else:
result = false
else:
raise newException(NotImplementedError, &"unsupported binary operator '>' for object of type '{self.typeName()}'")
proc gt(self: ptr Infinity, other: ptr Obj): bool =
case other.kind:
of ObjectType.Integer:
let other = cast[ptr Integer](other)
if self.isNegative and other.intValue > 0:
result = false
else:
result = true
of ObjectType.Float:
let other = cast[ptr Float](other)
if self.isNegative and other.floatValue > 0.0:
result = false
else:
result = true
of ObjectType.Infinity:
let other = cast[ptr Infinity](other)
if other.isNegative and not self.isNegative:
result = true
else:
result = false
else:
raise newException(NotImplementedError, &"unsupported binary operator '>' for object of type '{self.typeName()}'")
proc gt*(self: ptr Obj, other: ptr Obj): bool =
## Returns the result of self < other or
## raises an error if the operation
## is unsupported
case self.kind:
of ObjectType.Integer:
result = cast[ptr Integer](self).gt(other)
of ObjectType.Float:
result = cast[ptr Float](self).gt(other)
of ObjectType.Infinity:
result = cast[ptr Infinity](self).gt(other)
else:
raise newException(NotImplementedError, &"unsupported binary operator '>' for object of type '{self.typeName()}'")
proc sum(self: ptr Infinity, other: ptr Obj): ptr Infinity =
result = asInf()
case other.kind:
of ObjectType.Infinity:
var other = cast[ptr Infinity](other)
if self.isNegative or other.isNegative:
result.isNegative = true
of ObjectType.Integer, ObjectType.Float:
discard
else:
raise newException(NotImplementedError, &"unsupported binary operator '+' for objects of type '{self.typeName()}' and '{other.typeName()}'")
proc sum(self: ptr NotANumber, other: ptr Obj): ptr NotANumber =
result = asNan()
case other.kind:
of ObjectType.NotANumber, ObjectType.Integer, ObjectType.Float:
discard
else:
raise newException(NotImplementedError, &"unsupported binary operator '+' for objects of type '{self.typeName()}' and '{other.typeName()}'")
proc sum(self: ptr String, other: ptr Obj): ptr String =
if other.kind == ObjectType.String:
var other = cast[ptr String](other)
@ -681,34 +907,427 @@ proc sum*(self, other: ptr Obj): ptr Obj =
result = cast[ptr Integer](self).sum(other)
of ObjectType.Float:
result = cast[ptr Float](self).sum(other)
of ObjectType.NotANumber:
result = cast[ptr NotANumber](self).sum(other)
of ObjectType.Infinity:
result = cast[ptr Infinity](self).sum(other)
else:
raise newException(NotImplementedError, &"unsupported binary operator '+' for objects of type '{self.typeName()}' and '{other.typeName()}'")
proc sub(self, other: ptr Obj): ptr Obj =
proc sub(self: ptr Infinity, other: ptr Obj): ptr Infinity =
result = asInf()
case other.kind:
of ObjectType.Infinity:
var other = cast[ptr Infinity](other)
if self.isNegative or other.isNegative:
result.isNegative = true
of ObjectType.Integer, ObjectType.Float:
discard
else:
raise newException(NotImplementedError, &"unsupported binary operator '+' for objects of type '{self.typeName()}' and '{other.typeName()}'")
proc sub(self: ptr NotANumber, other: ptr Obj): ptr NotANumber =
result = asNan()
case other.kind:
of ObjectType.NotANumber, ObjectType.Integer, ObjectType.Float:
discard
else:
raise newException(NotImplementedError, &"unsupported binary operator '+' for objects of type '{self.typeName()}' and '{other.typeName()}'")
proc sub(self: ptr Integer, other: ptr Obj): ptr Obj = # This can yield a float!
case other.kind:
of ObjectType.Integer:
result = (self.toInt() - cast[ptr Integer](other).toInt()).asInt()
of ObjectType.Float:
let res = ((float self.toInt()) - cast[ptr Float](other).toFloat())
if res == system.Inf:
result = asInf()
elif res == -system.Inf:
let negInf = asInf()
negInf.isNegative = true
result = negInf
else:
result = res.asFloat()
of ObjectType.NotANumber:
result = asNan()
of ObjectType.Infinity:
result = cast[ptr Infinity](other)
else:
raise newException(NotImplementedError, &"unsupported binary operator '+' for objects of type '{self.typeName()}' and '{other.typeName()}'")
proc sub(self: ptr Float, other: ptr Obj): ptr Obj =
case other.kind:
of ObjectType.Integer:
result = (self.toFloat() - float cast[ptr Integer](other).toInt()).asFloat()
of ObjectType.Float:
let res = (self.toFloat() - cast[ptr Float](other).toFloat())
if res == system.Inf:
result = asInf()
elif res == -system.Inf:
let negInf = asInf()
negInf.isNegative = true
result = negInf
else:
result = res.asFloat()
of ObjectType.NotANumber:
result = asNan()
of ObjectType.Infinity:
result = cast[ptr Infinity](other)
else:
raise newException(NotImplementedError, &"unsupported binary operator '+' for objects of type '{self.typeName()}' and '{other.typeName()}'")
proc sub*(self, other: ptr Obj): ptr Obj =
## Returns the result of self - other
## or raises NotImplementedError if the operation is unsupported
result = nil
case self.kind:
of ObjectType.Integer:
result = cast[ptr Integer](self).sub(other)
of ObjectType.Float:
result = cast[ptr Float](self).sub(other)
of ObjectType.NotANumber:
result = cast[ptr NotANumber](self).sub(other)
of ObjectType.Infinity:
result = cast[ptr Infinity](self).sub(other)
else:
raise newException(NotImplementedError, &"unsupported binary operator '+' for objects of type '{self.typeName()}' and '{other.typeName()}'")
proc mul(self, other: ptr Obj): ptr Obj =
## Returns the result of self * other
proc mul(self: ptr Infinity, other: ptr Obj): ptr Infinity =
result = asInf()
case other.kind:
of ObjectType.Infinity:
var other = cast[ptr Infinity](other)
if self.isNegative or other.isNegative:
result.isNegative = true
of ObjectType.Integer, ObjectType.Float:
discard
else:
raise newException(NotImplementedError, &"unsupported binary operator '+' for objects of type '{self.typeName()}' and '{other.typeName()}'")
proc mul(self: ptr NotANumber, other: ptr Obj): ptr NotANumber =
result = asNan()
case other.kind:
of ObjectType.NotANumber, ObjectType.Integer, ObjectType.Float:
discard
else:
raise newException(NotImplementedError, &"unsupported binary operator '*' for objects of type '{self.typeName()}' and '{other.typeName()}'")
proc mul(self: ptr Integer, other: ptr Obj): ptr Obj = # This can yield a float!
case other.kind:
of ObjectType.Integer:
result = (self.toInt() * cast[ptr Integer](other).toInt()).asInt()
of ObjectType.Float:
let res = ((float self.toInt()) * cast[ptr Float](other).toFloat())
if res == system.Inf:
result = asInf()
elif res == -system.Inf:
let negInf = asInf()
negInf.isNegative = true
result = negInf
else:
result = res.asFloat()
of ObjectType.NotANumber:
result = asNan()
of ObjectType.Infinity:
result = cast[ptr Infinity](other)
else:
raise newException(NotImplementedError, &"unsupported binary operator '*' for objects of type '{self.typeName()}' and '{other.typeName()}'")
proc mul(self: ptr Float, other: ptr Obj): ptr Obj =
case other.kind:
of ObjectType.Integer:
result = (self.toFloat() * float cast[ptr Integer](other).toInt()).asFloat()
of ObjectType.Float:
let res = (self.toFloat() * cast[ptr Float](other).toFloat())
if res == system.Inf:
result = asInf()
elif res == -system.Inf:
let negInf = asInf()
negInf.isNegative = true
result = negInf
else:
result = res.asFloat()
of ObjectType.NotANumber:
result = asNan()
of ObjectType.Infinity:
result = cast[ptr Infinity](other)
else:
raise newException(NotImplementedError, &"unsupported binary operator '*' for objects of type '{self.typeName()}' and '{other.typeName()}'")
proc mul*(self, other: ptr Obj): ptr Obj =
## Returns the result of self + other
## or raises NotImplementedError if the operation is unsupported
result = nil
case self.kind:
of ObjectType.Integer:
result = cast[ptr Integer](self).mul(other)
of ObjectType.Float:
result = cast[ptr Float](self).mul(other)
of ObjectType.NotANumber:
result = cast[ptr NotANumber](self).mul(other)
of ObjectType.Infinity:
result = cast[ptr Infinity](self).mul(other)
else:
raise newException(NotImplementedError, &"unsupported binary operator '*' for objects of type '{self.typeName()}' and '{other.typeName()}'")
proc trueDiv(self, other: ptr Obj): ptr Obj =
proc trueDiv(self: ptr Infinity, other: ptr Obj): ptr Infinity =
result = asInf()
case other.kind:
of ObjectType.Infinity:
var other = cast[ptr Infinity](other)
if self.isNegative or other.isNegative:
result.isNegative = true
of ObjectType.Integer, ObjectType.Float:
discard
else:
raise newException(NotImplementedError, &"unsupported binary operator '/' for objects of type '{self.typeName()}' and '{other.typeName()}'")
proc trueDiv(self: ptr NotANumber, other: ptr Obj): ptr NotANumber =
result = asNan()
case other.kind:
of ObjectType.NotANumber, ObjectType.Integer, ObjectType.Float:
discard
else:
raise newException(NotImplementedError, &"unsupported binary operator '/' for objects of type '{self.typeName()}' and '{other.typeName()}'")
proc trueDiv(self: ptr Integer, other: ptr Obj): ptr Obj =
case other.kind:
of ObjectType.Integer:
result = ((float self.toInt()) / (float cast[ptr Integer](other).toInt())).asFloat() # so that 4 / 2 == 2.0
of ObjectType.Float:
let res = ((float self.toInt()) / cast[ptr Float](other).toFloat())
if res == system.Inf:
result = asInf()
elif res == -system.Inf:
let negInf = asInf()
negInf.isNegative = true
result = negInf
else:
result = res.asFloat()
of ObjectType.NotANumber:
result = asNan()
of ObjectType.Infinity:
result = cast[ptr Infinity](other)
else:
raise newException(NotImplementedError, &"unsupported binary operator '/' for objects of type '{self.typeName()}' and '{other.typeName()}'")
proc trueDiv(self: ptr Float, other: ptr Obj): ptr Obj =
case other.kind:
of ObjectType.Integer:
result = (self.toFloat() / float cast[ptr Integer](other).toInt()).asFloat()
of ObjectType.Float:
let res = (self.toFloat() / cast[ptr Float](other).toFloat())
if res == system.Inf:
result = asInf()
elif res == -system.Inf:
let negInf = asInf()
negInf.isNegative = true
result = negInf
else:
result = res.asFloat()
of ObjectType.NotANumber:
result = asNan()
of ObjectType.Infinity:
result = cast[ptr Infinity](other)
else:
raise newException(NotImplementedError, &"unsupported binary operator '/' for objects of type '{self.typeName()}' and '{other.typeName()}'")
proc trueDiv*(self, other: ptr Obj): ptr Obj =
## Returns the result of self / other
## or raises NotImplementedError if the operation is unsupported
result = nil
case self.kind:
of ObjectType.Integer:
result = cast[ptr Integer](self).trueDiv(other)
of ObjectType.Float:
result = cast[ptr Float](self).trueDiv(other)
of ObjectType.NotANumber:
result = cast[ptr NotANumber](self).trueDiv(other)
of ObjectType.Infinity:
result = cast[ptr Infinity](self).trueDiv(other)
else:
raise newException(NotImplementedError, &"unsupported binary operator '/' for objects of type '{self.typeName()}' and '{other.typeName()}'")
proc exp(self, other: ptr Obj): ptr Obj =
## Returns the result of self ** other
proc pow(self: ptr Infinity, other: ptr Obj): ptr Infinity =
result = asInf()
case other.kind:
of ObjectType.Infinity:
var other = cast[ptr Infinity](other)
if self.isNegative or other.isNegative:
result.isNegative = true
of ObjectType.Integer, ObjectType.Float:
discard
else:
raise newException(NotImplementedError, &"unsupported binary operator '**' for objects of type '{self.typeName()}' and '{other.typeName()}'")
proc pow(self: ptr NotANumber, other: ptr Obj): ptr NotANumber =
result = asNan()
case other.kind:
of ObjectType.NotANumber, ObjectType.Integer, ObjectType.Float:
discard
else:
raise newException(NotImplementedError, &"unsupported binary operator '**' for objects of type '{self.typeName()}' and '{other.typeName()}'")
proc pow(self: ptr Integer, other: ptr Obj): ptr Obj = # This can yield a float!
case other.kind:
of ObjectType.Integer:
result = (self.toInt() ** cast[ptr Integer](other).toInt()).asInt()
of ObjectType.Float:
let res = ((float self.toInt()) ** cast[ptr Float](other).toFloat())
if res == system.Inf:
result = asInf()
elif res == -system.Inf:
let negInf = asInf()
negInf.isNegative = true
result = negInf
else:
result = res.asFloat()
of ObjectType.NotANumber:
result = asNan()
of ObjectType.Infinity:
result = cast[ptr Infinity](other)
else:
raise newException(NotImplementedError, &"unsupported binary operator '**' for objects of type '{self.typeName()}' and '{other.typeName()}'")
proc pow(self: ptr Float, other: ptr Obj): ptr Obj =
case other.kind:
of ObjectType.Integer:
result = (self.toFloat() ** float cast[ptr Integer](other).toInt()).asFloat()
of ObjectType.Float:
let res = (self.toFloat() ** cast[ptr Float](other).toFloat())
if res == system.Inf:
result = asInf()
elif res == -system.Inf:
let negInf = asInf()
negInf.isNegative = true
result = negInf
else:
result = res.asFloat()
of ObjectType.NotANumber:
result = asNan()
of ObjectType.Infinity:
result = cast[ptr Infinity](other)
else:
raise newException(NotImplementedError, &"unsupported binary operator '**' for objects of type '{self.typeName()}' and '{other.typeName()}'")
proc pow*(self, other: ptr Obj): ptr Obj =
## Returns the result of self ** other (exponentiation)
## or raises NotImplementedError if the operation is unsupported
result = nil
case self.kind:
of ObjectType.Integer:
result = cast[ptr Integer](self).pow(other)
of ObjectType.Float:
result = cast[ptr Float](self).pow(other)
of ObjectType.NotANumber:
result = cast[ptr NotANumber](self).pow(other)
of ObjectType.Infinity:
result = cast[ptr Infinity](self).pow(other)
else:
raise newException(NotImplementedError, &"unsupported binary operator '**' for objects of type '{self.typeName()}' and '{other.typeName()}'")
proc divMod(self: ptr Infinity, other: ptr Obj): ptr Infinity =
result = asInf()
case other.kind:
of ObjectType.Infinity:
var other = cast[ptr Infinity](other)
if self.isNegative or other.isNegative:
result.isNegative = true
of ObjectType.Integer, ObjectType.Float:
discard
else:
raise newException(NotImplementedError, &"unsupported binary operator '%' for objects of type '{self.typeName()}' and '{other.typeName()}'")
proc divMod(self: ptr NotANumber, other: ptr Obj): ptr NotANumber =
result = asNan()
case other.kind:
of ObjectType.NotANumber, ObjectType.Integer, ObjectType.Float:
discard
else:
raise newException(NotImplementedError, &"unsupported binary operator '%' for objects of type '{self.typeName()}' and '{other.typeName()}'")
proc divMod(self: ptr Integer, other: ptr Obj): ptr Obj = # This can yield a float!
case other.kind:
of ObjectType.Integer:
result = (self.toInt() mod cast[ptr Integer](other).toInt()).asInt()
of ObjectType.Float:
let res = ((float self.toInt()) mod cast[ptr Float](other).toFloat())
if res == system.Inf:
result = asInf()
elif res == -system.Inf:
let negInf = asInf()
negInf.isNegative = true
result = negInf
else:
result = res.asFloat()
of ObjectType.NotANumber:
result = asNan()
of ObjectType.Infinity:
result = cast[ptr Infinity](other)
else:
raise newException(NotImplementedError, &"unsupported binary operator '%' for objects of type '{self.typeName()}' and '{other.typeName()}'")
proc divMod(self: ptr Float, other: ptr Obj): ptr Obj =
case other.kind:
of ObjectType.Integer:
result = (self.toFloat() mod float cast[ptr Integer](other).toInt()).asFloat()
of ObjectType.Float:
let res = (self.toFloat() mod cast[ptr Float](other).toFloat())
if res == system.Inf:
result = asInf()
elif res == -system.Inf:
let negInf = asInf()
negInf.isNegative = true
result = negInf
else:
result = res.asFloat()
of ObjectType.NotANumber:
result = asNan()
of ObjectType.Infinity:
result = cast[ptr Infinity](other)
else:
raise newException(NotImplementedError, &"unsupported binary operator '%' for objects of type '{self.typeName()}' and '{other.typeName()}'")
proc divMod*(self, other: ptr Obj): ptr Obj =
## Returns the result of self % other
## or raises NotImplementedError if the operation is unsupported
case self.kind:
of ObjectType.Integer:
result = cast[ptr Integer](self).divMod(other)
of ObjectType.Float:
result = cast[ptr Float](self).divMod(other)
of ObjectType.NotANumber:
result = cast[ptr NotANumber](self).divMod(other)
of ObjectType.Infinity:
result = cast[ptr Infinity](self).divMod(other)
else:
raise newException(NotImplementedError, &"unsupported binary operator '%' for objects of type '{self.typeName()}' and '{other.typeName()}'")
proc binaryAnd(self, other: ptr Obj): ptr Obj =
## Returns the result of self & other
## or raises NotImplementedError if the operation is unsupported

View File

@ -31,9 +31,6 @@ when DEBUG_TRACE_VM:
## Move these into appropriate int/float modules
proc `**`(a, b: int): int = pow(a.float, b.float).int
proc `**`(a, b: float): float = pow(a, b)
type
KeyboardInterrupt* = object of CatchableError
@ -299,9 +296,24 @@ proc run(self: var VM, repl: bool): InterpretResult =
self.push(readConstant())
of OpCode.ConstantLong:
self.push(readLongConstant())
of OpCode.Negate: # TODO: Call appropriate methods
of OpCode.Negate:
try:
self.push(self.pop().negate())
except NotImplementedError:
self.error(newTypeError(getCurrentExceptionMsg()))
return RuntimeError
of OpCode.Shl: # Binary left-shift
discard
of OpCode.Shr: # Binary right-shift
discard
of OpCode.Xor: # Binary xor
discard
of OpCode.Bor: # Binary or
discard
of OpCode.Bnot: # Binary not
discard
of OpCode.Band: # Binary and
discard
# self.push(self.pop().negate())
of OpCode.Add:
var left = self.pop()
var right = self.pop()
@ -310,28 +322,46 @@ proc run(self: var VM, repl: bool): InterpretResult =
except NotImplementedError:
self.error(newTypeError(getCurrentExceptionMsg()))
return RuntimeError
of OpCode.Shl:
discard
of OpCode.Shr:
discard
of OpCode.Xor:
discard
of OpCode.Bor:
discard
of OpCode.Bnot:
discard
of OpCode.Band:
discard
of OpCode.Subtract:
discard
var left = self.pop()
var right = self.pop()
try:
self.push(right.sub(left))
except NotImplementedError:
self.error(newTypeError(getCurrentExceptionMsg()))
return RuntimeError
of OpCode.Divide:
discard
var left = self.pop()
var right = self.pop()
try:
self.push(right.trueDiv(left))
except NotImplementedError:
self.error(newTypeError(getCurrentExceptionMsg()))
return RuntimeError
of OpCode.Multiply:
discard
var left = self.pop()
var right = self.pop()
try:
self.push(right.mul(left))
except NotImplementedError:
self.error(newTypeError(getCurrentExceptionMsg()))
return RuntimeError
of OpCode.Mod:
discard
var left = self.pop()
var right = self.pop()
try:
self.push(right.divMod(left))
except NotImplementedError:
self.error(newTypeError(getCurrentExceptionMsg()))
return RuntimeError
of OpCode.Pow:
discard
var left = self.pop()
var right = self.pop()
try:
self.push(right.pow(left))
except NotImplementedError:
self.error(newTypeError(getCurrentExceptionMsg()))
return RuntimeError
of OpCode.True:
self.push((true).asBool())
of OpCode.False:
@ -351,9 +381,21 @@ proc run(self: var VM, repl: bool): InterpretResult =
# Doesn't this chain of calls look beautifully
# intuitive?
of OpCode.Less:
discard
var left = self.pop()
var right = self.pop()
try:
self.push(right.lt(left).asBool())
except NotImplementedError:
self.error(newTypeError(getCurrentExceptionMsg()))
return RuntimeError
of OpCode.Greater:
discard
var left = self.pop()
var right = self.pop()
try:
self.push(right.gt(left).asBool())
except NotImplementedError:
self.error(newTypeError(getCurrentExceptionMsg()))
return RuntimeError
of OpCode.Slice:
if not self.slice():
return RuntimeError