Add name-scanning pass to compiler
Compile::discover_locals now takes a Vec<SpExpr> instead of a single SpExpr. It is also called before the compiler starts building the list of instructions so that all names in the scope are available at compile-time. Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -1,8 +1,5 @@
|
||||
[ :x x x ] :dup
|
||||
|
||||
# This a dumb little workaround to allow for recursion so factorial inside of
|
||||
# the function definition will look in the correct scope
|
||||
0 :factorial
|
||||
[
|
||||
dup!
|
||||
[dup! 1 -! factorial! *!]
|
||||
|
||||
@@ -48,8 +48,8 @@ impl<'s> Compile<'s> {
|
||||
// Local scopes are implicit. If a variable is assigned to at
|
||||
// all in the current scope, it's considered to be a local.
|
||||
let mut code = Vec::new();
|
||||
self.discover_locals(&expr_list);
|
||||
for expr in expr_list {
|
||||
self.discover_locals(&expr);
|
||||
code.extend(self.compile_expr(&expr));
|
||||
}
|
||||
code
|
||||
@@ -102,10 +102,12 @@ impl<'s> Compile<'s> {
|
||||
///
|
||||
/// If any assignment for a local variable appears in the scope, it will be
|
||||
/// inserted.
|
||||
fn discover_locals(&mut self, expr: &SpExpr) {
|
||||
if let Expr::Atom(atom) = expr.inner() {
|
||||
if let Atom::Assign(text) = atom.inner() {
|
||||
self.scope_stack.insert_local(text);
|
||||
fn discover_locals(&mut self, exprs: &Vec<SpExpr>) {
|
||||
for expr in exprs.iter() {
|
||||
if let Expr::Atom(atom) = expr.inner() {
|
||||
if let Atom::Assign(text) = atom.inner() {
|
||||
self.scope_stack.insert_local(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user