Fix bug where global names could only be used once in the root scope
Global names previously would only load once, and then not again because of issues with how the root scope is compiled. This is fixed. Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -104,6 +104,10 @@ impl Compile {
|
|||||||
pub(crate) fn collect_locals(&mut self, body: &Body) {
|
pub(crate) fn collect_locals(&mut self, body: &Body) {
|
||||||
locals::CollectLocals::new(self).collect(body);
|
locals::CollectLocals::new(self).collect(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn scope(&self) -> &Scope {
|
||||||
|
&self.scope
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constant data pool used for building the const pool.
|
/// Constant data pool used for building the const pool.
|
||||||
|
|||||||
@@ -69,4 +69,8 @@ impl Scope {
|
|||||||
pub fn globals_mut(&mut self) -> Option<&mut ScopeLocalSyms> {
|
pub fn globals_mut(&mut self) -> Option<&mut ScopeLocalSyms> {
|
||||||
self.scope.first_mut()
|
self.scope.first_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn layers_len(&self) -> usize {
|
||||||
|
self.scope.len()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -419,12 +419,21 @@ impl Visit for CompileBody<'_> {
|
|||||||
let thunk = match atom {
|
let thunk = match atom {
|
||||||
Atom::Ident(ident) => {
|
Atom::Ident(ident) => {
|
||||||
let sym = global_sym(ident.to_string());
|
let sym = global_sym(ident.to_string());
|
||||||
// TODO : use "LOAD_GLOBAL" instead of "LOAD_LOCAL" when inside a user function
|
// Small gotcha:
|
||||||
if let Some(local) = self.compile.lookup_local(sym) {
|
// Looking up a name will either result in a local or a global lookup. If it's
|
||||||
|
// a local variable first, then it's determined as a local and that's the end
|
||||||
|
// of the story... except when we're at the top scope level, we're both "local"
|
||||||
|
// *and* global.
|
||||||
|
//
|
||||||
|
// This checks to make sure that it's both a local variable and that there's more
|
||||||
|
// than one scope layer.
|
||||||
|
if let (true, Some(local)) = (self.compile.scope().layers_len() > 1, self.compile.lookup_local(sym)) {
|
||||||
// get local
|
// get local
|
||||||
Inst::LoadLocal(local).into()
|
Inst::LoadLocal(local).into()
|
||||||
} else {
|
} else {
|
||||||
// get or create global
|
// get or create global
|
||||||
|
// create_global only makes a new global with this symbol name if one has not
|
||||||
|
// been created yet
|
||||||
let global = self.compile.create_global(sym);
|
let global = self.compile.create_global(sym);
|
||||||
Inst::LoadGlobal(global).into()
|
Inst::LoadGlobal(global).into()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user