mirror of https://github.com/japl-lang/japl.git
Started to ditch value objects in favor of object pointers
This commit is contained in:
parent
a910445bd4
commit
823f4c622b
13
memory.nim
13
memory.nim
|
@ -23,7 +23,6 @@
|
||||||
|
|
||||||
|
|
||||||
import segfaults
|
import segfaults
|
||||||
import types/japlvalue
|
|
||||||
|
|
||||||
|
|
||||||
proc reallocate*(pointr: pointer, oldSize: int, newSize: int): pointer =
|
proc reallocate*(pointr: pointer, oldSize: int, newSize: int): pointer =
|
||||||
|
@ -67,15 +66,3 @@ template growCapacity*(capacity: int): untyped =
|
||||||
template allocate*(castTo: untyped, sizeTo: untyped, count: int): untyped =
|
template allocate*(castTo: untyped, sizeTo: untyped, count: int): untyped =
|
||||||
## Allocates an object and casts its pointer to the specified type
|
## Allocates an object and casts its pointer to the specified type
|
||||||
cast[ptr castTo](reallocate(nil, 0, sizeof(sizeTo) * count))
|
cast[ptr castTo](reallocate(nil, 0, sizeof(sizeTo) * count))
|
||||||
|
|
||||||
|
|
||||||
proc allocateObject*(size: int, kind: ObjectType): ptr Obj =
|
|
||||||
## Wrapper around reallocate to create a new generic JAPL object
|
|
||||||
result = cast[ptr Obj](reallocate(nil, 0, size))
|
|
||||||
result.kind = kind
|
|
||||||
|
|
||||||
|
|
||||||
template allocateObj*(kind: untyped, objType: ObjectType): untyped =
|
|
||||||
## Wrapper around allocateObject to cast a generic object
|
|
||||||
## to a more specific type
|
|
||||||
cast[ptr kind](allocateObject(sizeof kind, objType))
|
|
||||||
|
|
|
@ -12,10 +12,11 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
## Base structure for values and objects in JAPL, all
|
## Base structure for objs and objects in JAPL, all
|
||||||
## types inherit from this simple structure
|
## types inherit from this simple structure
|
||||||
|
|
||||||
import tables
|
import tables
|
||||||
|
import ../memory
|
||||||
|
|
||||||
type
|
type
|
||||||
Chunk* = ref object
|
Chunk* = ref object
|
||||||
|
@ -23,58 +24,46 @@ type
|
||||||
## Consts represents the constants the code is referring to
|
## Consts represents the constants the code is referring to
|
||||||
## Code represents the bytecode
|
## Code represents the bytecode
|
||||||
## Lines represents which lines the corresponding bytecode was one (1 to 1 correspondence)
|
## Lines represents which lines the corresponding bytecode was one (1 to 1 correspondence)
|
||||||
consts*: seq[Value]
|
consts*: seq[ptr Obj]
|
||||||
code*: seq[uint8]
|
code*: seq[uint8]
|
||||||
lines*: seq[int]
|
lines*: seq[int]
|
||||||
|
|
||||||
ValueType* {.pure.} = enum
|
|
||||||
# All possible value types (this is the VM's notion of 'type', not the end user's)
|
|
||||||
Integer, Double, Bool, Nil, Object, Nan, Inf, Minf
|
|
||||||
Value* = object
|
|
||||||
## Represents an internal JAPL type
|
|
||||||
case kind*: ValueType
|
|
||||||
of ValueType.Integer:
|
|
||||||
intValue*: int
|
|
||||||
of ValueType.Double:
|
|
||||||
floatValue*: float
|
|
||||||
of ValueType.Bool:
|
|
||||||
boolValue*: bool
|
|
||||||
of ValueType.Nil, ValueType.Inf, ValueType.Nan, ValueType.Minf:
|
|
||||||
discard
|
|
||||||
of ValueType.Object:
|
|
||||||
obj*: ptr Obj
|
|
||||||
|
|
||||||
ObjectType* {.pure.} = enum
|
ObjectType* {.pure.} = enum
|
||||||
## All the possible object types
|
## All the possible object types
|
||||||
String, Exception, Function,
|
String, Exception, Function,
|
||||||
Class, Module, BaseObject
|
Class, Module, BaseObject,
|
||||||
|
Integer, Float, Bool, Nan,
|
||||||
|
Infinity, Nil
|
||||||
Obj* = object of RootObj
|
Obj* = object of RootObj
|
||||||
# The object that rules them all
|
# The object that rules them all
|
||||||
kind*: ObjectType
|
kind*: ObjectType
|
||||||
hashValue*: uint32
|
hashobj*: uint32
|
||||||
String* = object of Obj # A string object
|
String* = object of Obj # A string object
|
||||||
str*: ptr UncheckedArray[char] # TODO -> Unicode support
|
str*: ptr UncheckedArray[char] # TODO -> Unicode support
|
||||||
len*: int
|
len*: int
|
||||||
Integer* = object of Obj
|
Integer* = object of Obj
|
||||||
# An integer object
|
# An integer object
|
||||||
intValue: int # TODO: Bignum arithmetic
|
intValue: int # TODO: Bignum arithmetic
|
||||||
Float* = object of Obj
|
Bool* = object of Integer
|
||||||
|
boolValue: bool # If the boolean is true or false
|
||||||
|
Nil* = object of Bool
|
||||||
|
Float* = object of Integer
|
||||||
# A float object
|
# A float object
|
||||||
floatValue: float
|
floatValue: float
|
||||||
JAPLInf* = object of Float # Inf is considered a float
|
Infinity* = object of Float # Inf is considered a float
|
||||||
JAPLNan* = object of Obj # While (logically) NaN is a separate type altogether
|
isNegative: bool # This differentiates inf and -inf
|
||||||
|
NotANumber* = object of Float # NaN is as well (IEEE 754)
|
||||||
Function* = object of Obj
|
Function* = object of Obj
|
||||||
name*: ptr String
|
name*: ptr String
|
||||||
arity*: int
|
arity*: int
|
||||||
optionals*: int
|
optionals*: int
|
||||||
defaults*: Table[string, Value]
|
defaults*: seq[ptr Obj]
|
||||||
chunk*: Chunk
|
chunk*: Chunk
|
||||||
JAPLException* = object of Obj
|
JAPLException* = object of Obj
|
||||||
errName*: ptr String
|
errName*: ptr String
|
||||||
message*: ptr String
|
message*: ptr String
|
||||||
|
|
||||||
|
|
||||||
proc `convert`(a: ptr Obj): ptr Obj =
|
proc `convert`*(a: ptr Obj): ptr Obj =
|
||||||
## Performs conversions from a JAPL
|
## Performs conversions from a JAPL
|
||||||
## supertype to a subtype
|
## supertype to a subtype
|
||||||
|
|
||||||
|
@ -83,12 +72,36 @@ proc `convert`(a: ptr Obj): ptr Obj =
|
||||||
result = cast[ptr String](a)
|
result = cast[ptr String](a)
|
||||||
of ObjectType.Function:
|
of ObjectType.Function:
|
||||||
result = cast[ptr Function](a)
|
result = cast[ptr Function](a)
|
||||||
of ObjectType.Class, ObjectType.Module, ObjectType.BaseObject:
|
of ObjectType.Integer:
|
||||||
|
result = cast[ptr Integer](a)
|
||||||
|
of ObjectType.Float:
|
||||||
|
result = cast[ptr Float](a)
|
||||||
|
of ObjectType.Bool:
|
||||||
|
result = cast[ptr Bool](a)
|
||||||
|
of ObjectType.Nan:
|
||||||
|
result = cast[ptr NotANumber](a)
|
||||||
|
of ObjectType.Infinity:
|
||||||
|
result = cast[ptr Infinity](a)
|
||||||
|
of ObjectType.BaseObject:
|
||||||
|
result = cast[ptr Obj](a)
|
||||||
|
of ObjectType.Class, ObjectType.Module:
|
||||||
discard # TODO: Implement
|
discard # TODO: Implement
|
||||||
else:
|
else:
|
||||||
raise newException(Exception, "Attempted JAPL type conversion with unknown source object")
|
raise newException(Exception, "Attempted JAPL type conversion with unknown source object")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
proc allocateObject*(size: int, kind: ObjectType): ptr Obj =
|
||||||
|
## Wrapper around reallocate to create a new generic JAPL object
|
||||||
|
result = cast[ptr Obj](reallocate(nil, 0, size))
|
||||||
|
result.kind = kind
|
||||||
|
|
||||||
|
|
||||||
|
template allocateObj*(kind: untyped, objType: ObjectType): untyped =
|
||||||
|
## Wrapper around allocateObject to cast a generic object
|
||||||
|
## to a more specific type
|
||||||
|
cast[ptr kind](allocateObject(sizeof kind, objType))
|
||||||
|
|
||||||
proc objType*(obj: ptr Obj): ObjectType =
|
proc objType*(obj: ptr Obj): ObjectType =
|
||||||
## Returns the type of the object
|
## Returns the type of the object
|
||||||
return obj.kind
|
return obj.kind
|
||||||
|
@ -117,7 +130,7 @@ proc typeName*(obj: ptr Obj): string =
|
||||||
# TODO migrate to operations
|
# TODO migrate to operations
|
||||||
proc bool*(obj: ptr Obj): bool =
|
proc bool*(obj: ptr Obj): bool =
|
||||||
## Returns wheter the object should
|
## Returns wheter the object should
|
||||||
## be considered a falsey value
|
## be considered a falsey obj
|
||||||
## or not. Returns true if the
|
## or not. Returns true if the
|
||||||
## object is truthy, or false
|
## object is truthy, or false
|
||||||
## if it is falsey
|
## if it is falsey
|
||||||
|
@ -127,6 +140,7 @@ proc bool*(obj: ptr Obj): bool =
|
||||||
else:
|
else:
|
||||||
result = false
|
result = false
|
||||||
|
|
||||||
|
|
||||||
# TODO migrate to operations
|
# TODO migrate to operations
|
||||||
proc eq*(a: ptr Obj, b: ptr Obj): bool =
|
proc eq*(a: ptr Obj, b: ptr Obj): bool =
|
||||||
## Compares two objects for equality
|
## Compares two objects for equality
|
||||||
|
@ -197,98 +211,95 @@ proc binaryXor(self, other: ptr Obj): ptr Obj =
|
||||||
result = nil
|
result = nil
|
||||||
|
|
||||||
|
|
||||||
func isNil*(value: Value): bool =
|
func isNil*(obj: ptr Obj): bool =
|
||||||
## Returns true if the given value
|
## Returns true if the given obj
|
||||||
## is a JAPL nil object
|
## is a JAPL nil object
|
||||||
result = value.kind == ValueType.Nil
|
result = obj.kind == ObjectType.Nil
|
||||||
|
|
||||||
|
|
||||||
func isBool*(value: Value): bool =
|
func isBool*(obj: ptr Obj): bool =
|
||||||
## Returns true if the given value
|
## Returns true if the given obj
|
||||||
## is a JAPL bool
|
## is a JAPL bool
|
||||||
result = value.kind == ValueType.Bool
|
result = obj.kind == ObjectType.Bool
|
||||||
|
|
||||||
|
|
||||||
func isInt*(value: Value): bool =
|
func isInt*(obj: ptr Obj): bool =
|
||||||
## Returns true if the given value
|
## Returns true if the given obj
|
||||||
## is a JAPL integer
|
## is a JAPL integer
|
||||||
result = value.kind == ValueType.Integer
|
result = obj.kind == ObjectType.Integer
|
||||||
|
|
||||||
|
|
||||||
func isFloat*(value: Value): bool =
|
func isFloat*(obj: ptr Obj): bool =
|
||||||
## Returns true if the given value
|
## Returns true if the given obj
|
||||||
## is a JAPL float
|
## is a JAPL float
|
||||||
result = value.kind == ValueType.Double
|
result = obj.kind == ObjectType.Float
|
||||||
|
|
||||||
|
|
||||||
func isInf*(value: Value): bool =
|
func isInf*(obj: ptr Obj): bool =
|
||||||
## Returns true if the given value
|
## Returns true if the given obj
|
||||||
## is a JAPL inf object
|
## is a JAPL inf object
|
||||||
result = value.kind == ValueType.Inf or value.kind == ValueType.Minf
|
result = obj.kind == ObjectType.Infinity
|
||||||
|
|
||||||
|
|
||||||
func isNan*(value: Value): bool =
|
func isNan*(obj: ptr Obj): bool =
|
||||||
## Returns true if the given value
|
## Returns true if the given obj
|
||||||
## is a JAPL nan object
|
## is a JAPL nan object
|
||||||
result = value.kind == ValueType.Nan
|
result = obj.kind == ObjectType.Nan
|
||||||
|
|
||||||
|
|
||||||
func isNum*(value: Value): bool =
|
func isNum*(obj: ptr Obj): bool =
|
||||||
## Returns true if the given value is
|
## Returns true if the given obj is
|
||||||
## either a JAPL number, nan or inf
|
## either a JAPL number, nan or inf
|
||||||
result = isInt(value) or isFloat(value) or isInf(value) or isNan(value)
|
result = isInt(obj) or isFloat(obj) or isInf(obj) or isNan(obj)
|
||||||
|
|
||||||
|
|
||||||
func isObj*(value: Value): bool =
|
|
||||||
## Returns if the current value is a JAPL object
|
|
||||||
result = value.kind == ValueType.Object
|
|
||||||
|
|
||||||
|
func isStr*(obj: ptr Obj): bool =
|
||||||
func isStr*(value: Value): bool =
|
|
||||||
## Returns true if the given object is a JAPL string
|
## Returns true if the given object is a JAPL string
|
||||||
result = isObj(value) and value.obj.kind == ObjectType.String
|
result = obj.kind == ObjectType.String
|
||||||
|
|
||||||
|
|
||||||
func toBool*(value: Value): bool =
|
func toBool*(obj: ptr Obj): bool =
|
||||||
## Converts a JAPL bool to a nim bool
|
## Converts a JAPL bool to a nim bool
|
||||||
result = value.boolValue
|
result = cast[ptr Bool](obj).boolValue
|
||||||
|
|
||||||
|
|
||||||
func toInt*(value: Value): int =
|
func toInt*(obj: ptr Obj): int =
|
||||||
## Converts a JAPL int to a nim int
|
## Converts a JAPL int to a nim int
|
||||||
result = value.intValue
|
result = cast[ptr Integer](obj).intValue
|
||||||
|
|
||||||
|
|
||||||
func toFloat*(value: Value): float =
|
func toFloat*(obj: ptr Obj): float =
|
||||||
## Converts a JAPL float to a nim float
|
## Converts a JAPL float to a nim float
|
||||||
result = value.floatValue
|
result = cast[ptr Float](obj).floatValue
|
||||||
|
|
||||||
# TODO ambiguous naming: conflict with toString(value: Value) that does JAPL->JAPL
|
# TODO ambiguous naming: conflict with toString(obj: obj) that does JAPL->JAPL
|
||||||
func toStr*(value: Value): string =
|
func toStr*(obj: ptr Obj): string =
|
||||||
## Converts a JAPL string into a nim string
|
## Converts a JAPL string into a nim string
|
||||||
var strObj = cast[ptr String](value.obj)
|
var strObj = cast[ptr String](obj)
|
||||||
for i in 0..strObj.str.len - 1:
|
for i in 0..strObj.str.len - 1:
|
||||||
result.add(strObj.str[i])
|
result.add(strObj.str[i])
|
||||||
|
|
||||||
|
|
||||||
func asInt*(n: int): Value =
|
func asInt*(n: int): ptr Obj =
|
||||||
## Creates an int object
|
## Creates an int object
|
||||||
result = Value(kind: ValueType.Integer, intValue: n)
|
result = allocateOb
|
||||||
|
|
||||||
|
|
||||||
func asFloat*(n: float): Value =
|
func asFloat*(n: float): ptr Obj =
|
||||||
## Creates a float object (double)
|
## Creates a float object (double)
|
||||||
result = Value(kind: ValueType.Double, floatValue: n)
|
result = obj(kind: objType.Double, floatobj: n)
|
||||||
|
|
||||||
|
|
||||||
func asBool*(b: bool): Value =
|
func asBool*(b: bool): ptr Obj =
|
||||||
## Creates a boolean object
|
## Creates a boolean object
|
||||||
result = Value(kind: ValueType.Bool, boolValue: b)
|
result = obj(kind: objType.Bool, boolobj: b)
|
||||||
|
|
||||||
func asValue*(obj: ptr Obj): Value =
|
|
||||||
## Creates a Value object of ValueType.Object as type and obj (arg 1) as
|
func asObj*(obj: ptr Obj): obj =
|
||||||
|
## Creates a object of ObjectType.BaseObject as type and obj (arg 1) as
|
||||||
## contained obj
|
## contained obj
|
||||||
|
|
||||||
result = Value(kind: ValueType.Object, obj: obj)
|
result = Object(kind: objType.Object, obj: obj)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,61 +18,30 @@ import function
|
||||||
import exceptions
|
import exceptions
|
||||||
import strutils
|
import strutils
|
||||||
|
|
||||||
func stringify*(value: Value): string =
|
|
||||||
case value.kind:
|
|
||||||
of ValueType.Integer:
|
|
||||||
result = $value.toInt()
|
|
||||||
of ValueType.Double:
|
|
||||||
result = $value.toFloat()
|
|
||||||
of ValueType.Bool:
|
|
||||||
result = $value.toBool()
|
|
||||||
of ValueType.Nil:
|
|
||||||
result = "nil"
|
|
||||||
of ValueType.Object:
|
|
||||||
case value.obj.kind:
|
|
||||||
of ObjectType.String:
|
|
||||||
result = cast[ptr String](value.obj).stringify
|
|
||||||
of ObjectType.Function:
|
|
||||||
result = cast[ptr Function](value.obj).stringify
|
|
||||||
else:
|
|
||||||
result = "TODO this was not implemented"
|
|
||||||
of ValueType.Nan:
|
|
||||||
result = "nan"
|
|
||||||
of ValueType.Inf:
|
|
||||||
result = "inf"
|
|
||||||
of ValueType.Minf:
|
|
||||||
result = "-inf"
|
|
||||||
|
|
||||||
func isFalsey*(value: Value): bool =
|
func stringify(obj: ptr Obj): string =
|
||||||
case value.kind:
|
## Returns a string representation of an object
|
||||||
of ValueType.Bool:
|
result = convert(obj).stringify()
|
||||||
result = not value.toBool()
|
|
||||||
of ValueType.Object:
|
|
||||||
case value.obj.kind:
|
func isFalsey*(obj: ptr Obj): bool =
|
||||||
of ObjectType.String:
|
case obj.kind:
|
||||||
result = cast[ptr String](value.obj).isFalsey()
|
of ObjectType.String:
|
||||||
of ObjectType.Function:
|
result = cast[ptr String](value.obj).isFalsey()
|
||||||
result = cast[ptr Function](value.obj).isFalsey()
|
of ObjectType.Function:
|
||||||
of ObjectType.Exception:
|
result = cast[ptr Function](value.obj).isFalsey()
|
||||||
result = cast[ptr JaplException](value.obj).isFalsey()
|
of ObjectType.Exception:
|
||||||
of ObjectType.Class:
|
result = cast[ptr JaplException](value.obj).isFalsey()
|
||||||
result = cast[ptr JaplException](value.obj).isFalsey() # TODO Class
|
of ObjectType.Class:
|
||||||
of ObjectType.Module:
|
discard # TODO Class
|
||||||
result = cast[ptr JaplException](value.obj).isFalsey() # TODO Module
|
of ObjectType.Module:
|
||||||
of ObjectType.BaseObject:
|
discard # TODO Module
|
||||||
result = cast[ptr JaplException](value.obj).isFalsey() # TODO BaseObject
|
of ObjectType.BaseObject:
|
||||||
of ValueType.Integer:
|
result = cast[ptr BaseObject](value.obj).isFalsey() # TODO BaseObject
|
||||||
result = value.toInt() == 0
|
|
||||||
of ValueType.Double:
|
|
||||||
result = value.toFloat() == 0.0
|
|
||||||
of ValueType.Nil:
|
|
||||||
result = true
|
|
||||||
of ValueType.Inf, ValueType.Minf:
|
|
||||||
result = false
|
|
||||||
of ValueType.Nan:
|
|
||||||
result = true
|
|
||||||
|
|
||||||
func typeName*(obj: ptr Obj): string =
|
func typeName*(obj: ptr Obj): string =
|
||||||
|
## Returns the name of the type of the object
|
||||||
case obj.kind:
|
case obj.kind:
|
||||||
of ObjectType.String:
|
of ObjectType.String:
|
||||||
result = cast[ptr String](obj).typeName()
|
result = cast[ptr String](obj).typeName()
|
||||||
|
@ -81,46 +50,19 @@ func typeName*(obj: ptr Obj): string =
|
||||||
else:
|
else:
|
||||||
result = "" # TODO unimplemented
|
result = "" # TODO unimplemented
|
||||||
|
|
||||||
func typeName*(value: Value): string =
|
|
||||||
case value.kind:
|
|
||||||
of ValueType.Bool, ValueType.Nil, ValueType.Double,
|
|
||||||
ValueType.Integer, ValueType.Nan, ValueType.Inf:
|
|
||||||
result = ($value.kind).toLowerAscii()
|
|
||||||
of ValueType.Minf:
|
|
||||||
result = "inf"
|
|
||||||
of ValueType.Object:
|
|
||||||
result = typeName(value.obj)
|
|
||||||
|
|
||||||
proc eq*(a: Value, b: Value): bool =
|
proc eq*(a: ptr Obj, b: ptr Obj): bool =
|
||||||
if a.kind != b.kind:
|
if a.kind != b.kind:
|
||||||
result = false
|
result = false
|
||||||
else:
|
else:
|
||||||
case a.kind:
|
case a.kind:
|
||||||
of ValueType.Bool:
|
of ObjectType.String:
|
||||||
result = a.toBool() == b.toBool()
|
var a = cast[ptr String](a)
|
||||||
of ValueType.Nil:
|
var b = cast[ptr String](b)
|
||||||
result = true
|
result = eq(a, b)
|
||||||
of ValueType.Integer:
|
of ObjectType.Function:
|
||||||
result = a.toInt() == b.toInt()
|
var a = cast[ptr Function](a)
|
||||||
of ValueType.Double:
|
var b = cast[ptr Function](b)
|
||||||
result = a.toFloat() == b.toFloat()
|
result = eq(a, b)
|
||||||
of ValueType.Object:
|
else:
|
||||||
case a.obj.kind:
|
discard # TODO: Implement
|
||||||
of ObjectType.String:
|
|
||||||
var a = cast[ptr String](a.obj)
|
|
||||||
var b = cast[ptr String](b.obj)
|
|
||||||
result = eq(a, b)
|
|
||||||
of ObjectType.Function:
|
|
||||||
var a = cast[ptr Function](a.obj)
|
|
||||||
var b = cast[ptr Function](b.obj)
|
|
||||||
result = eq(a, b)
|
|
||||||
else:
|
|
||||||
result = false # TODO unimplemented
|
|
||||||
|
|
||||||
of ValueType.Inf:
|
|
||||||
result = b.kind == ValueType.Inf
|
|
||||||
of ValueType.Minf:
|
|
||||||
result = b.kind == ValueType.Minf
|
|
||||||
of ValueType.Nan:
|
|
||||||
result = false
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue