diff --git a/common.nim b/common.nim index f03661e..9175158 100644 --- a/common.nim +++ b/common.nim @@ -15,9 +15,10 @@ import tables import strutils -import meta/valuearray import meta/tokenobject -import types/japlvalue +import meta/japlvalue +import types/stringtype +import types/functiontype const FRAMES_MAX* = 400 # TODO: Inspect why the VM crashes if this exceeds 400 @@ -91,15 +92,15 @@ proc delete*(self: CallFrame, idx: int) = func stringify*(value: Value): string = case value.kind: - of INTEGER: + of ValueType.Integer: result = $value.toInt() - of DOUBLE: + of ValueType.Double: result = $value.toFloat() - of BOOL: + of ValueType.Bool: result = $value.toBool() - of NIL: + of ValueType.Nil: result = "nil" - of OBJECT: + of ValueType.Object: case value.obj.kind: of ObjectType.String: result = cast[ptr String](value.obj).stringify @@ -111,7 +112,7 @@ func stringify*(value: Value): string = result = "nan" of ValueType.Inf: result = "inf" - of MINF: + of ValueType.Minf: result = "-inf" @@ -131,16 +132,16 @@ proc hashFloat(f: float): uint32 = # TODO: Move this into an hash() method for objects proc hash*(value: Value): uint32 = case value.kind: - of INTEGER: + of ValueType.Integer: result = uint32 value.toInt() - of BOOL: + of ValueType.Bool: if value.boolValue: result = uint32 1 else: result = uint32 0 - of DOUBLE: + of ValueType.Double: result = hashFloat(value.toFloat()) - of OBJECT: + of ValueType.Object: case value.obj.kind: of ObjectType.String: result = hash(cast[ptr String](value.obj)) @@ -153,9 +154,9 @@ proc hash*(value: Value): uint32 = # TODO: Move this into a bool() method for objects func isFalsey*(value: Value): bool = case value.kind: - of BOOL: + of ValueType.Bool: result = not value.toBool() - of OBJECT: + of ValueType.Object: case value.obj.kind: of ObjectType.String: result = cast[ptr String](value.obj).isFalsey() @@ -163,11 +164,11 @@ func isFalsey*(value: Value): bool = result = cast[ptr Function](value.obj).isFalsey() else: result = isFalsey(value.obj) - of INTEGER: + of ValueType.Integer: result = value.toInt() == 0 - of DOUBLE: + of ValueType.Double: result = value.toFloat() == 0.0 - of NIL: + of ValueType.Nil: result = true of ValueType.Inf, ValueType.Minf: result = false @@ -181,9 +182,9 @@ func typeName*(value: Value): string = of ValueType.Bool, ValueType.Nil, ValueType.Double, ValueType.Integer, ValueType.Nan, ValueType.Inf: result = ($value.kind).toLowerAscii() - of MINF: + of ValueType.Minf: result = "inf" - of OBJECT: + of ValueType.Object: case value.obj.kind: of ObjectType.String: result = cast[ptr String](value.obj).typeName() @@ -198,15 +199,15 @@ proc valuesEqual*(a: Value, b: Value): bool = result = false else: case a.kind: - of BOOL: + of ValueType.Bool: result = a.toBool() == b.toBool() - of NIL: + of ValueType.Nil: result = true - of INTEGER: + of ValueType.Integer: result = a.toInt() == b.toInt() - of DOUBLE: + of ValueType.Double: result = a.toFloat() == b.toFloat() - of OBJECT: + of ValueType.Object: case a.obj.kind: of ObjectType.String: var a = cast[ptr String](a.obj) @@ -220,7 +221,7 @@ proc valuesEqual*(a: Value, b: Value): bool = result = valuesEqual(a.obj, b.obj) of ValueType.Inf: result = b.kind == ValueType.Inf - of MINF: + of ValueType.Minf: result = b.kind == ValueType.Minf of ValueType.Nan: result = false diff --git a/memory.nim b/memory.nim index bb7f07d..4d3b488 100644 --- a/memory.nim +++ b/memory.nim @@ -23,7 +23,7 @@ import segfaults -import types/objecttype +import meta/japlvalue proc reallocate*(pointr: pointer, oldSize: int, newSize: int): pointer = diff --git a/meta/japlvalue.nim b/meta/japlvalue.nim index e3f3b41..a4683c8 100644 --- a/meta/japlvalue.nim +++ b/meta/japlvalue.nim @@ -16,21 +16,14 @@ ## types inherit from this simple structure import tables -<<<<<<< HEAD -import ../meta/japlvalue -======= -import ../types/objecttype - ->>>>>>> upstream/master type Chunk* = ref object ## A piece of bytecode. - ## Consts represents (TODO newdoc) - ## Code represents (TODO newdoc) - ## Lines represents (TODO newdoc) -<<<<<<< HEAD - consts*: ValueArray + ## 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] code*: seq[uint8] lines*: seq[int] @@ -138,9 +131,9 @@ proc bool*(obj: ptr Obj): bool = proc eq*(a: ptr Obj, b: ptr Obj): bool = ## Compares two objects for equality - if obj.kind != ObjectType.BaseObject: - var newObj = convert obj - result = newObj.eq() + if a.kind != ObjectType.BaseObject: + var newObj = convert(a) + result = newObj.eq(b) else: result = a.kind == b.kind @@ -202,8 +195,100 @@ proc binaryXor(self, other: ptr Obj): ptr Obj = ## Returns the result of self ^ other ## or nil if the operation is unsupported result = nil -======= - consts*: seq[ptr Obj] - code*: seq[uint8] - lines*: seq[int] ->>>>>>> upstream/master + + +func isNil*(value: Value): bool = + ## Returns true if the given value + ## is a JAPL nil object + result = value.kind == ValueType.Nil + + +func isBool*(value: Value): bool = + ## Returns true if the given value + ## is a JAPL bool + result = value.kind == ValueType.Bool + + +func isInt*(value: Value): bool = + ## Returns true if the given value + ## is a JAPL integer + result = value.kind == ValueType.Integer + + +func isFloat*(value: Value): bool = + ## Returns true if the given value + ## is a JAPL float + result = value.kind == ValueType.Double + + +func isInf*(value: Value): bool = + ## Returns true if the given value + ## is a JAPL inf object + result = value.kind == ValueType.Inf or value.kind == ValueType.Minf + + +func isNan*(value: Value): bool = + ## Returns true if the given value + ## is a JAPL nan object + result = value.kind == ValueType.Nan + + +func isNum*(value: Value): bool = + ## Returns true if the given value is + ## either a JAPL number, nan or inf + result = isInt(value) or isFloat(value) or isInf(value) or isNan(value) + + +func isObj*(value: Value): bool = + ## Returns if the current value is a JAPL object + result = value.kind == ValueType.Object + + +func isStr*(value: Value): bool = + ## Returns true if the given object is a JAPL string + result = isObj(value) and value.obj.kind == ObjectType.String + + +func toBool*(value: Value): bool = + ## Converts a JAPL bool to a nim bool + result = value.boolValue + + +func toInt*(value: Value): int = + ## Converts a JAPL int to a nim int + result = value.intValue + + +func toFloat*(value: Value): float = + ## Converts a JAPL float to a nim float + result = value.floatValue + + +func toStr*(value: Value): string = + ## Converts a JAPL string into a nim string + var strObj = cast[ptr String](value.obj) + for i in 0..strObj.str.len - 1: + result.add(strObj.str[i]) + + +func asInt*(n: int): Value = + ## Creates an int object + result = Value(kind: ValueType.Integer, intValue: n) + + +func asFloat*(n: float): Value = + ## Creates a float object (double) + result = Value(kind: ValueType.Double, floatValue: n) + + +func asBool*(b: bool): Value = + ## Creates a boolean object + result = Value(kind: ValueType.Bool, boolValue: b) + +func asValue*(obj: ptr Obj): Value = + ## Creates a Value object of ValueType.Object as type and obj (arg 1) as + ## contained obj + + result = Value(kind: ValueType.Object, obj: obj) + + diff --git a/meta/opcode_b.nim b/meta/opcode.nim similarity index 81% rename from meta/opcode_b.nim rename to meta/opcode.nim index 669bdc4..fe03809 100644 --- a/meta/opcode_b.nim +++ b/meta/opcode.nim @@ -15,14 +15,7 @@ ## The module dedicated to the Chunk type ## A chunk is a piece of bytecode. -<<<<<<< HEAD:meta/opcode.nim -<<<<<<< HEAD:meta/chunk.nim -======= import japlvalue ->>>>>>> 7649cf6e3bdf4ce47c9c63bbdbe3e99a53274a8d:meta/opcode.nim -======= -import ../types/objecttype ->>>>>>> upstream/master:meta/chunk.nim type OpCode* {.pure.} = enum @@ -69,19 +62,7 @@ type Bnot -<<<<<<< HEAD:meta/chunk.nim - Chunk* = ref object - ## A piece of bytecode. - ## Consts is the chunk's constant table - ## Code contains the compiled bytecode - ## Lines maps bytecode instructions to lines - consts*: seq[ptr Obj] - code*: seq[uint8] - lines*: seq[int] # TODO: Run-length encoding? - -======= ->>>>>>> 7649cf6e3bdf4ce47c9c63bbdbe3e99a53274a8d:meta/opcode.nim - + const simpleInstructions* = {OpCode.Return, OpCode.Add, OpCode.Multiply, OpCode.Divide, OpCode.Subtract, OpCode.Mod, OpCode.Pow, OpCode.Nil, @@ -123,13 +104,13 @@ proc freeChunk*(self: Chunk) = self.lines = @[] -proc addConstant*(self: Chunk, constant: ptr Obj): int = +proc addConstant*(self: Chunk, constant: Value): int = ## Adds a constant to a chunk. Returns its index. self.consts.add(constant) return self.consts.high() # The index of the constant -proc writeConstant*(self: Chunk, constant: ptr Obj): array[3, uint8] = +proc writeConstant*(self: Chunk, constant: Value): array[3, uint8] = ## Writes a constant to a chunk. Returns its index casted to an array. ## TODO newdoc let index = self.addConstant(constant) diff --git a/meta/tokenobject.nim b/meta/tokenobject.nim index 8b0721d..a70e22f 100644 --- a/meta/tokenobject.nim +++ b/meta/tokenobject.nim @@ -13,7 +13,7 @@ # limitations under the License. import tokentype -import valueobject +import japlvalue # Token object diff --git a/meta/valuearray.nim b/meta/valuearray.nim deleted file mode 100644 index c456e10..0000000 --- a/meta/valuearray.nim +++ /dev/null @@ -1,133 +0,0 @@ -# Copyright 2020 Mattia Giambirtone -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -## This module represents the generic interface that JAPL uses internally -## to represent types. Small-sized entities such as numbers and booleans are -## treated differently with respect to bigger and more complex ones such as -## strings and functions. That is because those more comolex entities are -## allocated on the heap, while the simpler ones live on the stack - -# import ../types/functiontype -import japlvalue -import ../types/stringtype -import strformat - - -type - ValueArray* = ref object - values*: seq[Value] - - -func newValueArray*(): ValueArray = - ## Creates a new ValueArray - result = ValueArray(values: @[]) - - -func writeValueArray*(arr: var ValueArray, value: Value) = - ## Adds a value to a ValueArray object - arr.values.add(value) - - -func isNil*(value: Value): bool = - ## Returns true if the given value - ## is a JAPL nil object - result = value.kind == ValueType.Nil - - -func isBool*(value: Value): bool = - ## Returns true if the given value - ## is a JAPL bool - result = value.kind == ValueType.Bool - - -func isInt*(value: Value): bool = - ## Returns true if the given value - ## is a JAPL integer - result = value.kind == ValueType.Integer - - -func isFloat*(value: Value): bool = - ## Returns true if the given value - ## is a JAPL float - result = value.kind == ValueType.Double - - -func isInf*(value: Value): bool = - ## Returns true if the given value - ## is a JAPL inf object - result = value.kind == ValueType.Inf or value.kind == ValueType.Minf - - -func isNan*(value: Value): bool = - ## Returns true if the given value - ## is a JAPL nan object - result = value.kind == ValueType.Nan - - -func isNum*(value: Value): bool = - ## Returns true if the given value is - ## either a JAPL number, nan or inf - result = isInt(value) or isFloat(value) or isInf(value) or isNan(value) - - -func isObj*(value: Value): bool = - ## Returns if the current value is a JAPL object - result = value.kind == ValueType.Object - - -func isStr*(value: Value): bool = - ## Returns true if the given object is a JAPL string - result = isObj(value) and value.obj.kind == ObjectType.String - - -func toBool*(value: Value): bool = - ## Converts a JAPL bool to a nim bool - result = value.boolValue - - -func toInt*(value: Value): int = - ## Converts a JAPL int to a nim int - result = value.intValue - - -func toFloat*(value: Value): float = - ## Converts a JAPL float to a nim float - result = value.floatValue - - -func toStr*(value: Value): string = - ## Converts a JAPL string into a nim string - var strObj = cast[ptr String](value.obj) - for i in 0..strObj.str.len - 1: - result.add(strObj.str[i]) - - -func asInt*(n: int): Value = - ## Creates an int object - result = Value(kind: ValueType.Integer, intValue: n) - - -func asFloat*(n: float): Value = - ## Creates a float object (double) - result = Value(kind: ValueType.Double, floatValue: n) - - -func asBool*(b: bool): Value = - ## Creates a boolean object - result = Value(kind: ValueType.Bool, boolValue: b) - - -proc asStr*(s: string): Value = - ## Creates a string object - result = Value(kind: ValueType.Object, obj: newString(s)) diff --git a/types/arraylist.nim b/types/arraylist.nim index 9496ff7..a481a43 100644 --- a/types/arraylist.nim +++ b/types/arraylist.nim @@ -14,8 +14,7 @@ # WIP - Not working -import ../meta/valueobject -import objecttype +import ../meta/japlvalue import exceptions import ../memory diff --git a/types/functiontype.nim b/types/functiontype.nim index 1c83db2..4306381 100644 --- a/types/functiontype.nim +++ b/types/functiontype.nim @@ -19,12 +19,11 @@ # code objects that can be compiled inside the JAPL runtime, pretty much # like in Python -import objecttype import stringtype import strformat import ../memory -import ../meta/chunk -import ../meta/valueobject +import ../meta/opcode +import ../meta/japlvalue import tables @@ -43,7 +42,7 @@ proc newFunction*(name: string = "", chunk: Chunk = newChunk(), arity: int = 0): result.chunk = chunk -proc isFalsey*(fn: Function): bool = +proc isFalsey*(fn: ptr Function): bool = return false diff --git a/types/stringtype.nim b/types/stringtype.nim index 699206b..fd43345 100644 --- a/types/stringtype.nim +++ b/types/stringtype.nim @@ -17,7 +17,7 @@ # therefore immutable from the user's perspective. They are # natively ASCII encoded, but soon they will support for unicode. -import objecttype +import ../meta/japlvalue import strformat import ../memory @@ -65,3 +65,8 @@ proc newString*(str: string): ptr String = proc typeName*(s: ptr String): string = return "string" + + +proc asStr*(s: string): Value = + ## Creates a string object + result = Value(kind: ValueType.Object, obj: newString(s))