diff --git a/memory.nim b/memory.nim index 9109765..d793de5 100644 --- a/memory.nim +++ b/memory.nim @@ -23,7 +23,6 @@ import segfaults -import types/japlvalue 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 = ## Allocates an object and casts its pointer to the specified type 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)) diff --git a/types/japlvalue.nim b/types/japlvalue.nim index 5d10893..f5cbed3 100644 --- a/types/japlvalue.nim +++ b/types/japlvalue.nim @@ -12,10 +12,11 @@ # See the License for the specific language governing permissions and # 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 import tables +import ../memory type Chunk* = ref object @@ -23,58 +24,46 @@ type ## Consts represents the constants the code is referring to ## Code represents the bytecode ## Lines represents which lines the corresponding bytecode was one (1 to 1 correspondence) - consts*: seq[Value] + consts*: seq[ptr Obj] code*: seq[uint8] 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 ## All the possible object types String, Exception, Function, - Class, Module, BaseObject + Class, Module, BaseObject, + Integer, Float, Bool, Nan, + Infinity, Nil Obj* = object of RootObj # The object that rules them all kind*: ObjectType - hashValue*: uint32 + hashobj*: uint32 String* = object of Obj # A string object str*: ptr UncheckedArray[char] # TODO -> Unicode support len*: int Integer* = object of Obj # An integer object 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 floatValue: float - JAPLInf* = object of Float # Inf is considered a float - JAPLNan* = object of Obj # While (logically) NaN is a separate type altogether + Infinity* = object of Float # Inf is considered a float + isNegative: bool # This differentiates inf and -inf + NotANumber* = object of Float # NaN is as well (IEEE 754) Function* = object of Obj name*: ptr String arity*: int optionals*: int - defaults*: Table[string, Value] + defaults*: seq[ptr Obj] chunk*: Chunk JAPLException* = object of Obj errName*: ptr String message*: ptr String -proc `convert`(a: ptr Obj): ptr Obj = +proc `convert`*(a: ptr Obj): ptr Obj = ## Performs conversions from a JAPL ## supertype to a subtype @@ -83,12 +72,36 @@ proc `convert`(a: ptr Obj): ptr Obj = result = cast[ptr String](a) of ObjectType.Function: 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 else: 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 = ## Returns the type of the object return obj.kind @@ -117,7 +130,7 @@ proc typeName*(obj: ptr Obj): string = # TODO migrate to operations proc bool*(obj: ptr Obj): bool = ## Returns wheter the object should - ## be considered a falsey value + ## be considered a falsey obj ## or not. Returns true if the ## object is truthy, or false ## if it is falsey @@ -127,6 +140,7 @@ proc bool*(obj: ptr Obj): bool = else: result = false + # TODO migrate to operations proc eq*(a: ptr Obj, b: ptr Obj): bool = ## Compares two objects for equality @@ -197,98 +211,95 @@ proc binaryXor(self, other: ptr Obj): ptr Obj = result = nil -func isNil*(value: Value): bool = - ## Returns true if the given value +func isNil*(obj: ptr Obj): bool = + ## Returns true if the given obj ## is a JAPL nil object - result = value.kind == ValueType.Nil + result = obj.kind == ObjectType.Nil -func isBool*(value: Value): bool = - ## Returns true if the given value +func isBool*(obj: ptr Obj): bool = + ## Returns true if the given obj ## is a JAPL bool - result = value.kind == ValueType.Bool + result = obj.kind == ObjectType.Bool -func isInt*(value: Value): bool = - ## Returns true if the given value +func isInt*(obj: ptr Obj): bool = + ## Returns true if the given obj ## is a JAPL integer - result = value.kind == ValueType.Integer + result = obj.kind == ObjectType.Integer -func isFloat*(value: Value): bool = - ## Returns true if the given value +func isFloat*(obj: ptr Obj): bool = + ## Returns true if the given obj ## is a JAPL float - result = value.kind == ValueType.Double + result = obj.kind == ObjectType.Float -func isInf*(value: Value): bool = - ## Returns true if the given value +func isInf*(obj: ptr Obj): bool = + ## Returns true if the given obj ## 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 = - ## Returns true if the given value +func isNan*(obj: ptr Obj): bool = + ## Returns true if the given obj ## is a JAPL nan object - result = value.kind == ValueType.Nan + result = obj.kind == ObjectType.Nan -func isNum*(value: Value): bool = - ## Returns true if the given value is +func isNum*(obj: ptr Obj): bool = + ## Returns true if the given obj is ## 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*(value: Value): bool = +func isStr*(obj: ptr Obj): bool = ## 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 - 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 - 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 - result = value.floatValue + result = cast[ptr Float](obj).floatValue -# TODO ambiguous naming: conflict with toString(value: Value) that does JAPL->JAPL -func toStr*(value: Value): string = +# TODO ambiguous naming: conflict with toString(obj: obj) that does JAPL->JAPL +func toStr*(obj: ptr Obj): 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: result.add(strObj.str[i]) -func asInt*(n: int): Value = +func asInt*(n: int): ptr Obj = ## 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) - 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 - 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 - result = Value(kind: ValueType.Object, obj: obj) + result = Object(kind: objType.Object, obj: obj) diff --git a/types/operations.nim b/types/operations.nim index 923c291..5007d19 100644 --- a/types/operations.nim +++ b/types/operations.nim @@ -18,61 +18,30 @@ import function import exceptions 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 = - case value.kind: - of ValueType.Bool: - result = not value.toBool() - of ValueType.Object: - case value.obj.kind: - of ObjectType.String: - result = cast[ptr String](value.obj).isFalsey() - of ObjectType.Function: - result = cast[ptr Function](value.obj).isFalsey() - of ObjectType.Exception: - result = cast[ptr JaplException](value.obj).isFalsey() - of ObjectType.Class: - result = cast[ptr JaplException](value.obj).isFalsey() # TODO Class - of ObjectType.Module: - result = cast[ptr JaplException](value.obj).isFalsey() # TODO Module - of ObjectType.BaseObject: - result = cast[ptr JaplException](value.obj).isFalsey() # TODO BaseObject - of ValueType.Integer: - 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 stringify(obj: ptr Obj): string = + ## Returns a string representation of an object + result = convert(obj).stringify() + + +func isFalsey*(obj: ptr Obj): bool = + case obj.kind: + of ObjectType.String: + result = cast[ptr String](value.obj).isFalsey() + of ObjectType.Function: + result = cast[ptr Function](value.obj).isFalsey() + of ObjectType.Exception: + result = cast[ptr JaplException](value.obj).isFalsey() + of ObjectType.Class: + discard # TODO Class + of ObjectType.Module: + discard # TODO Module + of ObjectType.BaseObject: + result = cast[ptr BaseObject](value.obj).isFalsey() # TODO BaseObject + func typeName*(obj: ptr Obj): string = + ## Returns the name of the type of the object case obj.kind: of ObjectType.String: result = cast[ptr String](obj).typeName() @@ -81,46 +50,19 @@ func typeName*(obj: ptr Obj): string = else: 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: result = false else: case a.kind: - of ValueType.Bool: - result = a.toBool() == b.toBool() - of ValueType.Nil: - result = true - of ValueType.Integer: - result = a.toInt() == b.toInt() - of ValueType.Double: - result = a.toFloat() == b.toFloat() - of ValueType.Object: - case a.obj.kind: - 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 - + of ObjectType.String: + var a = cast[ptr String](a) + var b = cast[ptr String](b) + result = eq(a, b) + of ObjectType.Function: + var a = cast[ptr Function](a) + var b = cast[ptr Function](b) + result = eq(a, b) + else: + discard # TODO: Implement