mirror of https://github.com/japl-lang/japl.git
Started to refactor the object structure
This commit is contained in:
parent
18c7a04703
commit
abc6a48457
27
common.nim
27
common.nim
|
@ -18,28 +18,26 @@ import strutils
|
|||
import meta/valueobject
|
||||
import meta/tokenobject
|
||||
import types/objecttype
|
||||
import types/functiontype
|
||||
import types/stringtype
|
||||
|
||||
|
||||
const FRAMES_MAX* = 400 # TODO: Inspect why the VM crashes if this exceeds 400
|
||||
const JAPL_VERSION* = "0.2.0"
|
||||
const JAPL_RELEASE* = "alpha"
|
||||
const DEBUG_TRACE_VM* = false
|
||||
const DEBUG_TRACE_GC* = true
|
||||
const DEBUG_TRACE_ALLOCATION* = true
|
||||
const DEBUG_TRACE_COMPILER* = true
|
||||
const DEBUG_TRACE_VM* = true # Traces VM execution
|
||||
const DEBUG_TRACE_GC* = true # Traces the garbage collector (TODO)
|
||||
const DEBUG_TRACE_ALLOCATION* = true # Traces memory allocation/deallocation (WIP)
|
||||
const DEBUG_TRACE_COMPILER* = true # Traces the compiler (TODO)
|
||||
|
||||
|
||||
type
|
||||
CallFrame* = ref object
|
||||
CallFrame* = ref object # FIXME: Call frames are broken (end indexes are likely wrong)
|
||||
function*: ptr Function
|
||||
ip*: int
|
||||
slot*: int
|
||||
endSlot*: int
|
||||
stack*: seq[Value]
|
||||
|
||||
VM* = ref object
|
||||
VM* = ref object # The VM object
|
||||
lastPop*: Value
|
||||
frameCount*: int
|
||||
source*: string
|
||||
|
@ -50,12 +48,12 @@ type
|
|||
globals*: Table[string, Value]
|
||||
file*: string
|
||||
|
||||
Local* = ref object
|
||||
Local* = ref object # A local variable
|
||||
name*: Token
|
||||
depth*: int
|
||||
|
||||
|
||||
Parser* = ref object
|
||||
Parser* = ref object # A Parser object
|
||||
current*: int
|
||||
tokens*: seq[Token]
|
||||
hadError*: bool
|
||||
|
@ -68,7 +66,7 @@ proc getView*(self: CallFrame): seq[Value] =
|
|||
|
||||
|
||||
proc getAbsIndex(self: CallFrame, idx: int): int =
|
||||
return idx + len(self.getView()) - 1 # Inspect this code (locals, functions)
|
||||
return idx + len(self.getView()) - 1 # TODO: Inspect this code (locals, functions)
|
||||
|
||||
|
||||
proc len*(self: CallFrame): int =
|
||||
|
@ -117,6 +115,8 @@ func stringify*(value: Value): string =
|
|||
result = "-inf"
|
||||
|
||||
|
||||
## TODO: Move this stuff back to their respective module
|
||||
|
||||
proc initParser*(tokens: seq[Token], file: string): Parser =
|
||||
result = Parser(current: 0, tokens: tokens, hadError: false, panicMode: false, file: file)
|
||||
|
||||
|
@ -128,6 +128,7 @@ proc hashFloat(f: float): uint32 =
|
|||
result *= 16777619
|
||||
|
||||
|
||||
# TODO: Move this into an hash() method for objects
|
||||
proc hash*(value: Value): uint32 =
|
||||
case value.kind:
|
||||
of INTEGER:
|
||||
|
@ -149,6 +150,7 @@ proc hash*(value: Value): uint32 =
|
|||
result = uint32 0
|
||||
|
||||
|
||||
# TODO: Move this into a bool() method for objects
|
||||
func isFalsey*(value: Value): bool =
|
||||
case value.kind:
|
||||
of BOOL:
|
||||
|
@ -173,6 +175,7 @@ func isFalsey*(value: Value): bool =
|
|||
result = true
|
||||
|
||||
|
||||
# TODO: Move this to a toString() method for objects
|
||||
func typeName*(value: Value): string =
|
||||
case value.kind:
|
||||
of ValueType.Bool, ValueType.Nil, ValueType.Double,
|
||||
|
@ -189,7 +192,7 @@ func typeName*(value: Value): string =
|
|||
else:
|
||||
result = value.obj.typeName()
|
||||
|
||||
|
||||
# TODO: Move this to a eq() method for objects
|
||||
proc valuesEqual*(a: Value, b: Value): bool =
|
||||
if a.kind != b.kind:
|
||||
result = false
|
||||
|
|
|
@ -21,11 +21,6 @@ import strformat
|
|||
import ../memory
|
||||
|
||||
|
||||
type JAPLException* = object of Obj
|
||||
errName*: ptr String
|
||||
message*: ptr String
|
||||
|
||||
|
||||
proc stringify*(self: ptr JAPLException): string =
|
||||
return &"{self.errName.stringify}: {self.message.stringify}"
|
||||
|
||||
|
|
|
@ -29,12 +29,6 @@ import tables
|
|||
|
||||
|
||||
type
|
||||
Function* = object of Obj
|
||||
name*: ptr String
|
||||
arity*: int
|
||||
optionals*: int
|
||||
defaults*: Table[string, Value]
|
||||
chunk*: Chunk
|
||||
FunctionType* = enum
|
||||
FUNC, SCRIPT
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
## Base structure for objects in JAPL, all
|
||||
## types inherit from this simple structure
|
||||
|
||||
import tables
|
||||
|
||||
|
||||
type
|
||||
ObjectType* {.pure.} = enum
|
||||
|
@ -25,9 +27,41 @@ type
|
|||
Obj* = object of RootObj
|
||||
kind*: ObjectType
|
||||
hashValue*: uint32
|
||||
String* = object of Obj # A string object
|
||||
str*: ptr UncheckedArray[char] # TODO -> Unicode support
|
||||
len*: int
|
||||
Function* = object of Obj
|
||||
name*: ptr String
|
||||
arity*: int
|
||||
optionals*: int
|
||||
defaults*: Table[string, Value]
|
||||
chunk*: Chunk
|
||||
JAPLException* = object of Obj
|
||||
errName*: ptr String
|
||||
message*: ptr String
|
||||
|
||||
|
||||
func objType*(obj: ptr Obj): ObjectType =
|
||||
|
||||
|
||||
|
||||
# Maps enum types to actual JAPL object types
|
||||
const objectMapping = to_table({
|
||||
String: Obj, # TODO
|
||||
Exception: Obj,
|
||||
Function: Obj,
|
||||
Class: Obj,
|
||||
Module: Obj
|
||||
})
|
||||
|
||||
|
||||
template `convert`(a: ptr Obj): untyped =
|
||||
## Performs conversions from a JAPL
|
||||
## supertype to a subtype
|
||||
|
||||
cast[ptr objectMapping[a.kind]](a)
|
||||
|
||||
|
||||
proc objType*(obj: ptr Obj): ObjectType =
|
||||
## Returns the type of the object
|
||||
return obj.kind
|
||||
|
||||
|
|
|
@ -22,11 +22,6 @@ import strformat
|
|||
import ../memory
|
||||
|
||||
|
||||
type String* = object of Obj
|
||||
str*: ptr UncheckedArray[char] # TODO -> Maybe ptr UncheckedArray[array[4, char]]?
|
||||
len*: int
|
||||
|
||||
|
||||
proc stringify*(s: ptr String): string =
|
||||
result = ""
|
||||
for i in 0..<s.len:
|
||||
|
|
12
vm.nim
12
vm.nim
|
@ -583,8 +583,8 @@ proc run(self: var VM, repl: bool): InterpretResult =
|
|||
of OpCode.Return:
|
||||
var retResult = self.pop()
|
||||
if repl:
|
||||
if not self.lastPop.isNil() and self.frameCount == 1: # This is to avoid long outputs
|
||||
# with recursive calls
|
||||
if not self.lastPop.isNil() and self.frameCount == 1: # This is to avoid
|
||||
# useless output with recursive calls
|
||||
echo stringify(self.lastPop)
|
||||
self.lastPop = Value(kind: ValueType.Nil) # TODO: asNil()?
|
||||
self.frameCount -= 1
|
||||
|
@ -604,13 +604,13 @@ proc freeObject(obj: ptr Obj) =
|
|||
of ObjectType.Function:
|
||||
var fun = cast[ptr Function](obj)
|
||||
when DEBUG_TRACE_ALLOCATION:
|
||||
echo &"Freeing function object with value '{stringify(fun)}'"
|
||||
echo &"DEBUG: Freeing function object with value '{stringify(fun)}'"
|
||||
fun.chunk.freeChunk()
|
||||
discard free(ObjectType.Function, fun)
|
||||
of ObjectType.String:
|
||||
var str = cast[ptr String](obj)
|
||||
when DEBUG_TRACE_ALLOCATION:
|
||||
echo &"Freeing string object with value '{stringify(str)}' of length {str.len}"
|
||||
echo &"DEBUG: Freeing string object with value '{stringify(str)}' of length {str.len}"
|
||||
discard freeArray(char, str.str, str.len)
|
||||
discard free(ObjectType.String, obj)
|
||||
else:
|
||||
|
@ -625,13 +625,13 @@ proc freeObjects(self: var VM) =
|
|||
freeObject(obj)
|
||||
discard self.objects.pop()
|
||||
when DEBUG_TRACE_ALLOCATION:
|
||||
echo &"Freed {objCount} objects"
|
||||
echo &"DEBUG: Freed {objCount} objects"
|
||||
|
||||
|
||||
proc freeVM*(self: var VM) =
|
||||
## Tears down the VM
|
||||
when DEBUG_TRACE_ALLOCATION:
|
||||
echo "\nFreeing all allocated memory before exiting"
|
||||
echo "\nDEBUG: Freeing all allocated memory before exiting"
|
||||
unsetControlCHook()
|
||||
try:
|
||||
self.freeObjects()
|
||||
|
|
Loading…
Reference in New Issue