Definitive fix for closures

This commit is contained in:
Mattia Giambirtone 2022-10-08 09:18:35 +02:00
parent fc74bab529
commit 11c8c0a5ab
3 changed files with 20 additions and 19 deletions

View File

@ -31,7 +31,7 @@ when debugVM or debugMem or debugGC:
import std/terminal
{.push checks:off.} # The VM is a critical point where checks are deleterious
{.push checks:on.} # The VM is a critical point where checks are deleterious
type
PeonVM* = ref object

View File

@ -188,7 +188,7 @@ type
# Stores the position of all jumps
jumps: seq[tuple[patched: bool, offset: int]]
# List of CFI start offsets into our CFI data
cfiOffsets: seq[tuple[value, offset: int, fn: Name]]
cfiOffsets: seq[tuple[start, stop: int, fn: Name]]
CompileError* = ref object of PeonException
compiler*: Compiler
node*: ASTNode
@ -416,18 +416,20 @@ proc fixCFIOffsets(self: Compiler, oldLen: int, modifiedAt: int) =
let offset = self.chunk.code.len() - oldLen
var newCFI: array[3, uint8]
var tmp: int
for cfi in self.cfiOffsets:
if cfi.offset >= modifiedAt:
newCFI = (cfi.value + offset).toTriple()
self.chunk.cfi[cfi.offset] = newCFI[0]
self.chunk.cfi[cfi.offset + 1] = newCFI[1]
self.chunk.cfi[cfi.offset + 2] = newCFI[2]
tmp = [self.chunk.cfi[cfi.offset + 3], self.chunk.cfi[cfi.offset + 4], self.chunk.cfi[cfi.offset + 5]].fromTriple().int
for cfi in self.cfiOffsets.mitems():
if cfi.start >= modifiedAt:
newCFI = (cfi.start + offset).toTriple()
self.chunk.cfi[cfi.start] = newCFI[0]
self.chunk.cfi[cfi.start + 1] = newCFI[1]
self.chunk.cfi[cfi.start + 2] = newCFI[2]
tmp = [self.chunk.cfi[cfi.start + 3], self.chunk.cfi[cfi.start + 4], self.chunk.cfi[cfi.start + 5]].fromTriple().int
newCFI = (tmp + offset).toTriple()
self.chunk.cfi[cfi.offset + 3] = newCFI[0]
self.chunk.cfi[cfi.offset + 4] = newCFI[1]
self.chunk.cfi[cfi.offset + 5] = newCFI[2]
self.chunk.cfi[cfi.start + 3] = newCFI[0]
self.chunk.cfi[cfi.start + 4] = newCFI[1]
self.chunk.cfi[cfi.start + 5] = newCFI[2]
cfi.fn.codePos += offset
cfi.start += offset
cfi.stop += offset
proc fixJumps(self: Compiler, oldLen: int, modifiedAt: int) =
@ -444,8 +446,7 @@ proc fixJumps(self: Compiler, oldLen: int, modifiedAt: int) =
# list in cases where we shifted the jump
# instruction itself into the code!
jump.offset += offset
if jump.patched:
self.setJump(jump.offset, self.chunk.code[jump.offset..<jump.offset + 3])
self.setJump(jump.offset, self.chunk.code[jump.offset + 1..jump.offset + 3])
proc resolve(self: Compiler, name: IdentExpr,
@ -1899,14 +1900,11 @@ proc typeDecl(self: Compiler, node: TypeDecl) =
proc funDecl(self: Compiler, node: FunDecl, fn: Name = nil, args: seq[Expression] = @[]) =
## Compiles function declarations
# A function's code is just compiled linearly
# and then jumped over
if node.token.kind == Operator and node.token.lexeme in [".", ]:
self.error(&"The '{node.token.lexeme}' cannot be overridden", node)
var jmp: int
self.declareName(node)
self.dispatchPragmas(node)
# Function's code starts after the jump
var node = node
var fn = if fn.isNil(): self.names[^(node.arguments.len() + 1)] else: fn
# We store the current function
@ -1915,7 +1913,6 @@ proc funDecl(self: Compiler, node: FunDecl, fn: Name = nil, args: seq[Expression
self.currentFunction.valueType.children.add(fn.valueType)
fn.valueType.parent = function.valueType
self.currentFunction = fn
var names {.used.} = self.names[^(node.arguments.len())..^1]
if fn.valueType.isBuiltinFunction:
fn.codePos = self.chunk.code.len()
# We take the arguments off of our name list
@ -1927,11 +1924,13 @@ proc funDecl(self: Compiler, node: FunDecl, fn: Name = nil, args: seq[Expression
# can only be relatively simple
self.names = self.names[0..^node.arguments.len() + 1]
elif not node.body.isNil():
# A function's code is just compiled linearly
# and then jumped over
jmp = self.emitJump(JumpForwards, node.token.line)
fn.codePos = self.chunk.code.len()
# We let our debugger know this function's boundaries
self.chunk.cfi.add(self.chunk.code.high().toTriple())
self.cfiOffsets.add((value: self.chunk.code.high(), offset: self.chunk.cfi.high() - 2, fn: fn))
self.cfiOffsets.add((start: self.chunk.code.high(), stop: 0, fn: fn))
let idx = self.chunk.cfi.len()
self.chunk.cfi.add(0.toTriple()) # Patched it later
self.chunk.cfi.add(uint8(node.arguments.len()))
@ -1985,6 +1984,7 @@ proc funDecl(self: Compiler, node: FunDecl, fn: Name = nil, args: seq[Expression
self.chunk.cfi[idx] = stop[0]
self.chunk.cfi[idx + 1] = stop[1]
self.chunk.cfi[idx + 2] = stop[2]
self.cfiOffsets[^1].stop = self.chunk.code.len()
# Currently defer is not functional, so we
# just pop the instructions
for _ in deferStart..self.deferred.high():

View File

@ -2,6 +2,7 @@
import std;
fn makeClosure(n: int): fn: fn: int {
fn inner: fn: int {
fn deep: int {