Definitive fix for closures
This commit is contained in:
parent
fc74bab529
commit
11c8c0a5ab
|
@ -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
|
||||
|
|
|
@ -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():
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
import std;
|
||||
|
||||
|
||||
|
||||
fn makeClosure(n: int): fn: fn: int {
|
||||
fn inner: fn: int {
|
||||
fn deep: int {
|
||||
|
|
Loading…
Reference in New Issue