Reverted variable hoisting and fixed minor issue during name resolution. Updated comments
This commit is contained in:
parent
a706fdad7a
commit
cd853bb140
|
@ -208,19 +208,16 @@ proc markRoots(self: var PeonVM): HashSet[ptr HeapObject] =
|
|||
# Unlike what Bob does in his book, we keep track
|
||||
# of objects another way, mainly due to the difference
|
||||
# of our respective designs. Specifically, our VM only
|
||||
# handles a single type (uint64), while Lox has a stack
|
||||
# of heap-allocated structs (which is convenient, but slow).
|
||||
# The previous implementation would just store all pointers
|
||||
# allocated by us in a hash set and then check if any source
|
||||
# of roots contained any of the integer values that it was
|
||||
# keeping track of, but this meant that if a primitive object's
|
||||
# value happened to collide with an active pointer the GC would
|
||||
# mistakenly assume the object was reachable, potentially leading
|
||||
# to a nasty memory leak. The current implementation uses pointer
|
||||
# tagging: we know that modern CPUs never use bit 63 in addresses,
|
||||
# so if it set we know it cannot be a pointer, and if it is set we
|
||||
# just need to check if it's in our list of active addresses or not.
|
||||
# This should resolve the potential memory leak (hopefully)
|
||||
# handles a single type (uint64) while Lox stores all objects
|
||||
# in heap-allocated structs (which is convenient, but slow).
|
||||
# What we do is store the pointers to the objects we allocated in
|
||||
# a hash set and then, at collection time, do a set difference
|
||||
# between the reachable objects and the whole set and discard
|
||||
# whatever is left; Unfortunately, this means that if a primitive
|
||||
# object's value happens to collide with an active pointer the GC
|
||||
# will mistakenly assume the object to be reachable, potentially
|
||||
# leading to a nasty memory leak. Let's just hope a 48+ bit address
|
||||
# space makes this occurrence rare enough not to be a problem
|
||||
var result = initHashSet[uint64](self.gc.pointers.len())
|
||||
for obj in self.calls:
|
||||
if obj in self.gc.pointers:
|
||||
|
@ -691,7 +688,7 @@ proc dispatch*(self: var PeonVM) =
|
|||
while true:
|
||||
{.computedgoto.} # https://nim-lang.org/docs/manual.html#pragmas-computedgoto-pragma
|
||||
when debugVM:
|
||||
if self.ip in self.breakpoints or self.breakpoints.len() == 0 or self.debugNext:
|
||||
if self.ip in self.breakpoints or self.debugNext:
|
||||
self.debug()
|
||||
instruction = OpCode(self.readByte())
|
||||
case instruction:
|
||||
|
|
|
@ -341,11 +341,9 @@ proc step*(self: Compiler): ASTNode {.inline.} =
|
|||
# and can be reused across multiple compilation backends
|
||||
|
||||
proc resolve*(self: Compiler, name: string): Name =
|
||||
## Traverses all existing namespaces and returns
|
||||
## the first object with the given name. Returns
|
||||
## nil when the name can't be found. Note that
|
||||
## when a type or function declaration is first
|
||||
## resolved, it is also compiled on-the-fly
|
||||
## Traverses all existing namespaces in reverse order
|
||||
## and returns the first object with the given name.
|
||||
## Returns nil when the name can't be found
|
||||
for obj in reversed(self.names):
|
||||
if obj.ident.token.lexeme == name:
|
||||
if obj.owner.path != self.currentModule.path:
|
||||
|
@ -361,6 +359,7 @@ proc resolve*(self: Compiler, name: string): Name =
|
|||
# module and said module has explicitly
|
||||
# exported it to us: we can use it
|
||||
result = obj
|
||||
result.resolved = true
|
||||
break
|
||||
# If the name is public but not exported in
|
||||
# its owner module, then we act as if it's
|
||||
|
@ -370,6 +369,7 @@ proc resolve*(self: Compiler, name: string): Name =
|
|||
# might not want to also have access to C's and D's
|
||||
# names as they might clash with its own stuff)
|
||||
continue
|
||||
# We own this name, so we can definitely access it
|
||||
result = obj
|
||||
result.resolved = true
|
||||
break
|
||||
|
|
|
@ -95,7 +95,7 @@ proc compile*(self: BytecodeCompiler, ast: seq[Declaration], file: string, lines
|
|||
mode: CompileMode = Debug): Chunk
|
||||
proc statement(self: BytecodeCompiler, node: Statement)
|
||||
proc declaration(self: BytecodeCompiler, node: Declaration)
|
||||
proc varDecl(self: BytecodeCompiler, node: VarDecl, hoist: bool = false)
|
||||
proc varDecl(self: BytecodeCompiler, node: VarDecl)
|
||||
proc specialize(self: BytecodeCompiler, typ: Type, args: seq[Expression]): Type {.discardable.}
|
||||
proc patchReturnAddress(self: BytecodeCompiler, pos: int)
|
||||
proc handleMagicPragma(self: BytecodeCompiler, pragma: Pragma, name: Name)
|
||||
|
@ -1864,10 +1864,8 @@ proc statement(self: BytecodeCompiler, node: Statement) =
|
|||
self.expression(Expression(node))
|
||||
|
||||
|
||||
proc varDecl(self: BytecodeCompiler, node: VarDecl, hoist: bool = false) =
|
||||
proc varDecl(self: BytecodeCompiler, node: VarDecl) =
|
||||
## Compiles variable declarations
|
||||
if node.name.depth == 0 and not hoist:
|
||||
return
|
||||
var typ: Type
|
||||
# Our parser guarantees that the variable declaration
|
||||
# will have a type declaration or a value (or both)
|
||||
|
@ -2078,9 +2076,6 @@ proc compile*(self: BytecodeCompiler, ast: seq[Declaration], file: string, lines
|
|||
self.jumps = @[]
|
||||
let pos = self.beginProgram()
|
||||
let idx = self.stackIndex
|
||||
for node in ast:
|
||||
if node.kind == varDecl and VarDecl(node).name.depth == 0:
|
||||
self.varDecl(VarDecl(node), hoist=true)
|
||||
self.stackIndex = idx
|
||||
while not self.done():
|
||||
self.declaration(Declaration(self.step()))
|
||||
|
|
|
@ -51,7 +51,7 @@ proc getLineEditor: LineEditor =
|
|||
result.bindHistory(history)
|
||||
|
||||
|
||||
proc repl(warnings: seq[WarningKind] = @[], mismatches: bool = false, mode: CompileMode = Debug) =
|
||||
proc repl(warnings: seq[WarningKind] = @[], mismatches: bool = false, mode: CompileMode = Debug, breakpoints: seq[uint64] = @[]) =
|
||||
styledEcho fgMagenta, "Welcome into the peon REPL!"
|
||||
var
|
||||
keep = true
|
||||
|
@ -136,7 +136,7 @@ proc repl(warnings: seq[WarningKind] = @[], mismatches: bool = false, mode: Comp
|
|||
else:
|
||||
styledEcho fgRed, "Corrupted"
|
||||
if not first:
|
||||
vm.run(serialized.chunk, repl=true)
|
||||
vm.run(serialized.chunk, repl=true, breakpoints=breakpoints)
|
||||
first = true
|
||||
else:
|
||||
vm.resume(serialized.chunk)
|
||||
|
@ -407,7 +407,9 @@ when isMainModule:
|
|||
else:
|
||||
echo "usage: peon [options] [filename.pn]"
|
||||
quit()
|
||||
if breaks.len() == 0 and debugVM:
|
||||
breaks.add(0)
|
||||
if file == "":
|
||||
repl(warnings, mismatches, mode)
|
||||
repl(warnings, mismatches, mode, breaks)
|
||||
else:
|
||||
runFile(file, fromString, dump, breaks, dis, warnings, mismatches, mode, run, backend, output)
|
||||
|
|
Loading…
Reference in New Issue