WIP switch to custom hashtable for globals

This commit is contained in:
prod2 2022-01-29 05:38:16 +01:00
parent 2765daa55b
commit 31b0b28dca
5 changed files with 43 additions and 34 deletions

View File

@ -1,7 +1,7 @@
import strformat
import strutils
import value
import types/value
type
OpCode* = enum

View File

@ -6,7 +6,7 @@ import options
import scanner
import chunk
import value
import types/value
import bitops # needed for value
import config

View File

@ -8,7 +8,7 @@ type
proc free*(ndStr: var NdString) =
dealloc(ndStr)
# for hashtable:
# hashes
proc fnv1a*(ndStr: NdString): int =
var hash = 2166136261'u32
@ -17,5 +17,7 @@ proc fnv1a*(ndStr: NdString): int =
hash *= 16777619
return hash.int
# equals
proc equal*(left, right: NdString): bool =
left == right
left == right

View File

@ -1,8 +1,8 @@
import strformat
import bitops
import types/ndstring
import types/stringutils
import ndstring
import stringutils
type
NdValue* = uint
@ -107,11 +107,6 @@ proc isFalsey*(val: NdValue): bool =
template isTruthy*(val: NdValue): bool =
not val.isFalsey()
proc equal*(val, right: NdValue): bool =
if val.isFloat() and right.isFloat():
val.asFloat() == right.asFloat()
else:
val == right
proc friendlyType*(val: NdValue): string =
if val == ndNil:
@ -186,3 +181,20 @@ proc greater*(val: var NdValue, right: NdValue): NatReturn {.inline.} =
else:
return natError(&"Attempt to compare types {val.friendlyType()} and {right.friendlyType()}.")
return natOk
# for hashtables
proc fnv1a*(ndval: NdValue): int =
var hash = 2166136261'u32
var val = ndval
for i in countup(0, 7):
hash = hash xor val.uint8.uint32
hash *= 16777619
val = val shr 8
return hash.int
proc equal*(val, right: NdValue): bool =
if val.isFloat() and right.isFloat():
val.asFloat() == right.asFloat()
else:
val == right

41
vm.nim
View File

@ -1,8 +1,5 @@
import strformat
import tables
import value
import bitops # needed for value's templates
#import tables
import chunk
import config
@ -11,6 +8,9 @@ import pointerutils
import types/stack
import types/ndstring
import types/stringutils
import bitops # needed for value's templates
import types/value
import types/hashtable
when profileInstructions:
@ -37,7 +37,8 @@ proc run*(chunk: Chunk): InterpretResult =
ip: ptr uint8 = chunk.code[0].unsafeAddr
stack: Stack[NdValue] = newStack[NdValue](256)
hadError: bool
globals: Table[string, NdValue]
#globals: Table[string, NdValue]
globals: Table[NdValue, NdValue]
frames: Stack[Frame] = newStack[Frame](4)
proc runtimeError(msg: string) =
@ -48,12 +49,6 @@ proc run*(chunk: Chunk): InterpretResult =
frames.add(Frame(stackBottom: 0))
#template peek(stack: seq[NdValue]): NdValue =
# stack[stack.high]
#proc popn(stack: var seq[NdValue], amt: int) {.inline.} =
# for i in countup(1, amt):
# discard stack.pop()
template popn(stack: var Stack[NdValue], amt: int) =
stack.deleteTopN(amt)
@ -167,25 +162,25 @@ proc run*(chunk: Chunk): InterpretResult =
of opPrint:
echo $stack.peek()
of opDefineGlobal:
let name = $readConstant().asString()
if not globals.hasKey(name):
globals[name] = stack.pop()
else:
let name = readConstant().asString()
let existed = globals.tableSet(name.fromNdString(), stack.pop())
if existed:
runtimeError("Attempt to redefine an existing global variable.")
break
of opGetGlobal:
let name = $readConstant().asString()
if globals.hasKey(name):
stack.add(globals[name])
let name = readConstant().asString()
var val: NdValue
let existed = globals.tableGet(name, val)
if existed:
stack.add(val)
else:
runtimeError(&"Undefined global variable {name}.")
break
of opSetGlobal:
let name = $readConstant().asString()
if globals.hasKey(name):
globals[name] = stack.peek()
else:
runtimeError(&"Attempt to set undefined global variable {name}.")
let name = readConstant().asString()
let existed = globals.tableSet(name, stack.pop())
if not existed:
runtimeError("Attempt to redefine an existing global variable.")
break
of opGetLocal:
let slot = readDU8()