From d77bf48fe94a3dafcf53a844db1dd5d0de196308 Mon Sep 17 00:00:00 2001 From: Alek Ratzloff Date: Wed, 16 Feb 2022 15:19:14 -0800 Subject: [PATCH] Add name-scanning pass to compiler Compile::discover_locals now takes a Vec 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 --- examples/factorial.sy | 3 --- src/compile.rs | 12 +++++++----- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/examples/factorial.sy b/examples/factorial.sy index 95d12f8..35fc30f 100644 --- a/examples/factorial.sy +++ b/examples/factorial.sy @@ -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! *!] diff --git a/src/compile.rs b/src/compile.rs index 3e05109..a9bfab5 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -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) { + 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); + } } } }