Initial work on simplifying the type system and added more VM utility functions

This commit is contained in:
Mattia Giambirtone 2022-05-02 23:19:17 +02:00
parent b4fffe18aa
commit f189b0214e
2 changed files with 66 additions and 81 deletions

View File

@ -17,65 +17,39 @@ type
ObjectKind* = enum
## Enumeration of Peon
## types
objFloat, objInt, objBool,
objNil, objNan, objInf,
objString
PeonObject* = ref object of RootObj
Int8, UInt8, Int16, UInt16, Int32,
UInt32, Int64, UInt64, Float32, Float64,
Char, Byte, String, Function, CustomType,
Nil, Nan, Bool, Inf
PeonObject* = object
## A generic Peon object
kind*: ObjectKind
Nil* = ref object of PeonObject
Nan* = ref object of PeonObject
Inf* = ref object of PeonObject
positive*: bool
Bool* = ref object of PeonObject
value*: bool
Int8* = ref object of PeonObject
value*: int8
Int16* = ref object of PeonObject
value*: int16
Int32* = ref object of PeonObject
value*: int32
Int64* = ref object of PeonObject
value*: int64
UInt8* = ref object of PeonObject
value*: uint8
UInt16* = ref object of PeonObject
value*: uint16
UInt32* = ref object of PeonObject
value*: uint32
UInt64* = ref object of PeonObject
value*: uint64
Float32* = ref object of PeonObject
value*: float32
Float64* = ref object of PeonObject
value*: float64
# We create a type alias for floats
# and integers depending on the current
# platform's native sizes
when sizeof(int) == 8:
type Int = Int64
elif sizeof(int) == 4:
type Int = Int32
elif sizeof(int) == 2:
type Int = Int16
else:
type Int = Int8
when sizeof(float) == 8:
type Float = Float64
else:
type Float = Float32
# Simple constructors for builtin types
proc newNil*: Nil = Nil(kind: objNil)
proc newNan*: Nan = Nan(kind: objNan)
proc newInf*(positive: bool): Inf = Inf(kind: objInf, positive: positive)
proc newBool*(value: bool): Bool = Bool(kind: objBool, value: value)
proc newInt*(value: int): Int = Int(kind: objInt, value: value)
proc newFloat*(value: float): Float = Float(kind: objFloat, value: value)
proc `$`*(self: PeonObject): string =
## Stringifies a peon object
case kind*: ObjectKind:
of Bool:
boolean*: bool
of Inf:
positive*: bool
of Byte:
`byte`*: byte
of Int8:
tiny*: uint8
of UInt8:
uTiny*: uint8
of Int16:
short*: int16
of UInt16:
uShort*: uint16
of Int32:
`int`*: int32
of UInt32:
uInt*: uint32
of Int64:
long*: int64
of UInt64:
uLong*: uint64
of Nil, Nan:
discard
of CustomType:
fields*: seq[PeonObject]
else:
discard # TODO

View File

@ -31,12 +31,12 @@ type
proc initCache*(self: PeonVM) =
## Initializes the VM's
## singletons cache
self.cache[0] = newNil()
self.cache[1] = newBool(true)
self.cache[2] = newBool(false)
self.cache[3] = newInf(true)
self.cache[4] = newInf(false)
self.cache[5] = newNan()
self.cache[0] = PeonObject(kind: Nil)
self.cache[1] = PeonObject(kind: Bool, boolean: true)
self.cache[2] = PeonObject(kind: Bool, boolean: false)
self.cache[3] = PeonObject(kind: ObjectKind.Inf, positive: true)
self.cache[4] = PeonObject(kind: ObjectKind.Inf, positive: false)
self.cache[5] = PeonObject(kind: ObjectKind.Nan)
proc newPeonVM*: PeonVM =
@ -50,30 +50,30 @@ proc newPeonVM*: PeonVM =
for _ in 0..<INITIAL_STACK_SIZE:
result.stack.add(result.cache[0])
# Getters for singleton types (they are cached!)
## Getters for singleton types (they are cached!)
proc getNil*(self: PeonVM): Nil = Nil(self.cache[0])
proc getNil*(self: PeonVM): PeonObject = self.cache[0]
proc getBool*(self: PeonVM, value: bool): Bool =
proc getBool*(self: PeonVM, value: bool): PeonObject =
if value:
return Bool(self.cache[1])
return Bool(self.cache[2])
return self.cache[1]
return self.cache[2]
proc getInf*(self: PeonVM, positive: bool): Inf =
proc getInf*(self: PeonVM, positive: bool): PeonObject =
if positive:
return types.Inf(self.cache[3])
return types.Inf(self.cache[4])
return self.cache[3]
return self.cache[4]
proc getNan*(self: PeonVM): Nan = types.Nan(self.cache[5])
proc getNan*(self: PeonVM): PeonObject = self.cache[5]
# Stack primitives
## Stack primitives
proc push(self: PeonVM, obj: PeonObject) =
## Pushes a Peon object onto the
## stack
if self.sp >= self.stack.high():
for _ in 0..self.stack.len():
self.stack.add(newNil())
self.stack.add(self.getNil())
self.stack[self.sp] = obj
inc(self.sp)
@ -103,7 +103,7 @@ proc readShort(self: PeonVM): uint16 =
copyMem(result.addr, unsafeAddr(arr), sizeof(arr))
proc readBytes(self: PeonVM): uint32 =
proc readLong(self: PeonVM): uint32 =
## Reads three bytes from the
## bytecode and returns them
## as an unsigned 32 bit
@ -114,14 +114,25 @@ proc readBytes(self: PeonVM): uint32 =
copyMem(result.addr, unsafeAddr(arr), sizeof(arr))
proc readConstant(self: PeonVM): PeonObject =
proc readLongLong(self: PeonVM): uint64 =
## Reads 4 bytes from the
## bytecode and returns them
## as an unsigned 64 bit
## integer
var arr: array[4, uint8]
copyMem(result.addr, unsafeAddr(arr), sizeof(arr))
proc readInt64(self: PeonVM): PeonObject =
## Reads a constant from the
## chunk's constant table
## chunk's constant table and
## returns a Peon object. Assumes
## the constant's type is an Int64
var arr = [self.readByte(), self.readByte(), self.readByte()]
var idx: int
copyMem(idx.addr, arr.addr, sizeof(arr))
# TODO
# result = self.chunk.consts[idx]
# result = PeonObject()
proc dispatch*(self: PeonVM) =