WIP closures + important bugfix

This commit is contained in:
prod2 2022-02-05 12:37:54 +01:00
parent 3e48b1cc52
commit 9b3b1056ba
4 changed files with 16 additions and 10 deletions

View File

@ -15,6 +15,7 @@ type
opConstant, # constant opConstant, # constant
opDefineGlobal, opGetGlobal, opSetGlobal, # globals (uses constants) opDefineGlobal, opGetGlobal, opSetGlobal, # globals (uses constants)
opGetLocal, opSetLocal, # locals opGetLocal, opSetLocal, # locals
opGetUpvalue, opSetUpvalue, # upvalues
opJumpIfFalse, opJump, opLoop, opJumpIfFalsePop, # jumps opJumpIfFalse, opJump, opLoop, opJumpIfFalsePop, # jumps
opCreateList, opCreateTable, # collection creation opCreateList, opCreateTable, # collection creation
opLen, opSetIndex, opGetIndex, # collection operators opLen, opSetIndex, opGetIndex, # collection operators
@ -114,6 +115,7 @@ const argInstructions = {
opJumpIfFalse, opJump, opLoop, opJumpIfFalsePop, opJumpIfFalse, opJump, opLoop, opJumpIfFalsePop,
opFunctionDef, opClosure, opFunctionDef, opClosure,
opCreateList, opCreateTable, opCreateList, opCreateTable,
opGetUpvalue, opSetUpvalue,
} }

View File

@ -71,7 +71,7 @@ proc newScope(comp: Compiler, function: bool): Scope =
result.goalStackIndex = comp.stackIndex + 1 result.goalStackIndex = comp.stackIndex + 1
if function: if function:
result.parentFunction = result result.parentFunction = result
elif comp.scopes[comp.scopes.high()].parentFunction != nil: elif comp.scopes.len() > 0 and comp.scopes[comp.scopes.high()].parentFunction != nil:
result.parentFunction = comp.scopes[comp.scopes.high()].parentFunction result.parentFunction = comp.scopes[comp.scopes.high()].parentFunction
comp.scopes.add(result) comp.scopes.add(result)
@ -399,13 +399,13 @@ proc addUpvalue(comp: Compiler, index: int): int =
## have the right upvalue in them (compile time) ## have the right upvalue in them (compile time)
discard discard
proc resolveLocal(comp: Compiler, name: string): Tuple[int, bool] = proc resolveLocal(comp: Compiler, name: string): tuple[index: int, upvalue: bool] =
## the bool arg specifies whether it found an upvalue ## the bool arg specifies whether it found an upvalue
## if it's a local: returns the stack index of the local of the name ## if it's a local: returns the stack index of the local of the name
## if it's an upvalue: returns the upvalue index ## if it's an upvalue: returns the upvalue index
## if the number is -1, then the name cannot be resolved at compile time ## if the number is -1, then the name cannot be resolved at compile time
var i = comp.locals.high var i = comp.locals.high
let cfunc = comp.scopes[comp.scopes.high()].parentFunction let cfunc: Scope = if comp.scopes.len() > 0: comp.scopes[comp.scopes.high()].parentFunction else: nil
while i >= 0: while i >= 0:
let local = comp.locals[i] let local = comp.locals[i]
if local.name == name: if local.name == name:
@ -417,7 +417,7 @@ proc resolveLocal(comp: Compiler, name: string): Tuple[int, bool] =
else: else:
return (comp.addUpvalue(i), true) return (comp.addUpvalue(i), true)
i.dec i.dec
return -1 return (index: -1, upvalue: false)
proc variable(comp: Compiler) = proc variable(comp: Compiler) =
# named variable # named variable

View File

@ -2,19 +2,19 @@ type
UpvalueObj[T] = object UpvalueObj[T] = object
location: ptr T location: ptr T
Upvalue[T]* = ptr UpvalueObj[T] Upvalue*[T] = ptr UpvalueObj[T]
ClosureObj[T] = object ClosureObj[T] = object
start: ptr uint8 start: ptr uint8
upvalueCount: int upvalueCount: int
upvalues: UncheckedArray[Upvalue[T]] upvalues: UncheckedArray[Upvalue[T]]
Closure[T]* = ptr ClosureObj[T] Closure*[T] = ptr ClosureObj[T]
proc newClosure[T]*(start: ptr uint8, upvalueCount: int): Closure[T] = proc newClosure*[T](start: ptr uint8, upvalueCount: int): Closure[T] =
result = cast[Closure[T]](alloc0(8 * upvalueCount + sizeof(ClosureObj[T]))) result = cast[Closure[T]](alloc0(8 * upvalueCount + sizeof(ClosureObj[T])))
result.start = start result.start = start
result.upvalueCount = upvalueCount result.upvalueCount = upvalueCount
proc getIp*(clos: Closure): ptr uint8 {.inline.} = proc getIp*[T](clos: Closure[T]): ptr uint8 {.inline.} =
clos.start clos.start

View File

@ -197,6 +197,10 @@ proc run*(chunk: Chunk): InterpretResult =
of opSetLocal: of opSetLocal:
let slot = readDU8() let slot = readDU8()
stack[slot + frameBottom] = stack.peek() stack[slot + frameBottom] = stack.peek()
of opGetUpvalue:
discard
of opSetUpvalue:
discard
of opJumpIfFalse: of opJumpIfFalse:
let offset = readDU8() let offset = readDU8()
if stack.peek().isFalsey(): if stack.peek().isFalsey():
@ -220,7 +224,7 @@ proc run*(chunk: Chunk): InterpretResult =
let offset = readDU8() let offset = readDU8()
let faddr: ptr uint8 = ip let faddr: ptr uint8 = ip
ip = ip.padd(offset) ip = ip.padd(offset)
stack.push(newClosure(faddr).fromClosure()) stack.push(newClosure[NdValue](faddr, 0).fromClosure())
of opCheckArity: of opCheckArity:
let arity = readUI8() let arity = readUI8()
let argcount = stack.high() - frameBottom let argcount = stack.high() - frameBottom
@ -259,7 +263,7 @@ proc run*(chunk: Chunk): InterpretResult =
if tbl[].tableSet(key, val): if tbl[].tableSet(key, val):
runtimeError("Attempt to redefine an existing value inside table declaration.") runtimeError("Attempt to redefine an existing value inside table declaration.")
break break
stack.deleteTopN(tblLen * 2) # stack.deleteTopN(tblLen * 2) # THIS IS NOT NEEDED, pops are done
stack.push(tbl.fromTable()) stack.push(tbl.fromTable())
of opLen: of opLen:
let res = stack.peek().getLength() let res = stack.peek().getLength()