From 134c5abd0f7b8de99c31920297a9afd5cc74b963 Mon Sep 17 00:00:00 2001 From: min Date: Fri, 19 Sep 2025 23:50:25 -0400 Subject: [PATCH] wip refactor --- src/compiler.rs | 253 +++++++++++++++++++-------------------------- src/main.rs | 8 +- src/parser.rs | 4 +- src/parser/util.rs | 2 +- 4 files changed, 113 insertions(+), 154 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index bdb1f14..2481130 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -1,165 +1,122 @@ +use std::cell::Cell; + use crate::{ lexer::{Ident, Literal}, parser::Expr, }; -type ScopeIdx = usize; - -#[derive(Default, Debug)] -struct AnalysisScope { - prev: Option, - next: Vec, - idents: Vec<(Ident, u16)>, - top_level_exprs: Vec, +struct Scope<'a> { + idents: Vec<(Ident, Cell)>, + parent: Option<&'a Scope<'a>>, } - -impl AnalysisScope { - pub fn new() -> Self { - Self::default() - } - - fn initialize(&mut self, id: Ident) { - self.idents.push((id, 0)); - } -} - -#[derive(Default, Debug)] -pub struct Analyzer { - scopes: Vec, -} -impl Analyzer { - pub fn new() -> Self { - Self::default() - } - - fn new_scope(&mut self) { - // Get indices - let cur_idx = self.scopes.len().checked_sub(1); - let next_idx = cur_idx.map(|i| i + 1).unwrap_or_default(); - - // If we have a current scope, add in the new scope's index - if let Some(Some(cur_scope)) = cur_idx.map(|i| self.scopes.get_mut(i)) { - cur_scope.next.push(next_idx); - } - - // Create new scope - self.scopes.push(AnalysisScope::new()); - let next_scope = self.scopes.get_mut(next_idx).unwrap(); - // Tie it back to the current scope (if there is one) - next_scope.prev = cur_idx; - } - - fn get_scope(&mut self) -> &mut AnalysisScope { - self.scopes.last_mut().unwrap() - } - - fn increment_ident(&mut self, id: &Ident) -> Option { - let mut cur = self.get_scope(); - - loop { - // Try to find it - if let Some(count) = cur - .idents - .iter_mut() - .rev() - .find(|(i, _)| id == i) - .map(|(_, c)| c) - { - let old_count = *count; - *count += 1; - return Some(old_count); - } - // Didn't find it so try scope above - if let Some(prev) = cur.prev { - cur = self.scopes.get_mut(prev).unwrap(); - } else { - // No more scopes above - return None; - } +impl<'a> Scope<'a> { + fn with_parent(parent: Option<&'a Scope>) -> Self { + Scope { + idents: Vec::new(), + parent, } } + fn assigned(&mut self, id: Ident) { + self.idents.push((id, Cell::default())); + } +} - pub fn analyze(&mut self, e: Expr) { - match e { - Expr::Assign(a, b) => { - let Expr::Literal(Literal::Ident(id)) = *a else { - panic!("invalid assignment"); +pub fn compile(mut e: Expr) { + let mut scope = Scope::with_parent(None); + analyze(&mut scope, &mut e); +} + +fn analyze(scope: &mut Scope, e: &mut Expr) { + match e { + Expr::Assign(a, b) => { + let Expr::Literal(Literal::Ident(id), _) = &**a else { + panic!("invalid assignment"); + }; + + // add to scope + scope.assigned(id.clone()); + + // analyse the value + analyze(scope, b); + } + Expr::Literal(Literal::Ident(id), _) => { + // lookup literal + let mut cur = &*scope; + loop { + let Some((_, count)) = cur.idents.iter().find(|i| i.0 == *id) else { + if let Some(parent) = cur.parent { + cur = parent; + } else { + panic!("undefined variable"); + } + continue; }; + count.update(|c| c + 1); + let count = count.get(); + println!("ref {id} #{count}"); + break; + } + } + // ignore + Expr::Literal(_, _) => {} + // for recursion.. + Expr::Block(a) => { + // blocks have their own scope + let mut scope2 = Scope::with_parent(Some(scope)); + // analyze the contents in the new scope + for e in &mut a.exprs { + analyze(&mut scope2, e); + } + } + Expr::Func(a, b) => { + // functions have their own scope, because they have args + let mut scope = Scope::with_parent(Some(scope)); - // make new counter for ident in our scope - let sc = self.get_scope(); - sc.initialize(id); + // init args + for e in a { + let Expr::Literal(Literal::Ident(id), _) = e else { + panic!("invalid arg def"); + }; + scope.assigned(id.clone()); + } - // analyse the value - self.analyze(*b); + // now analyze the body in the new scope + analyze(&mut scope, b); + } + Expr::If(a, b, c) => { + analyze(scope, a); + analyze(scope, b); + if let Some(c) = c { + analyze(scope, c); } - Expr::Literal(Literal::Ident(id)) => { - // lookup literal - self.increment_ident(&id).expect("not found var"); - } - // ignore - Expr::Literal(_) => {} - // for recursion.. - Expr::Block(a) => { - // blocks have their own scope - self.new_scope(); - let sc = self.get_scope(); - // analyze the contents in the new scope - sc.top_level_exprs = a.exprs.clone(); - for e in a.exprs { - self.analyze(e); - } - } - Expr::Func(a, b) => { - // functions have their own scope, because they have args - self.new_scope(); - let new_sc = self.get_scope(); - - for e in a { - let Expr::Literal(Literal::Ident(id)) = e else { - panic!("invalid arg def"); - }; - new_sc.initialize(id); - } - - // now analyze the body in the new scope - self.analyze(*b); - } - Expr::If(a, b, c) => { - self.analyze(*a); - self.analyze(*b); - if let Some(c) = c { - self.analyze(*c); - } - } - Expr::Call(a, b) => { - self.analyze(*a); - for e in b { - self.analyze(e); - } - } - Expr::Return(a) | Expr::Negate(a) | Expr::Not(a) => self.analyze(*a), - Expr::EqualTo(a, b) - | Expr::NotEqualTo(a, b) - | Expr::And(a, b) - | Expr::Or(a, b) - | Expr::LessThan(a, b) - | Expr::LessThanOrEqualTo(a, b) - | Expr::GreaterThan(a, b) - | Expr::GreaterThanOrEqualTo(a, b) - | Expr::Add(a, b) - | Expr::Subtract(a, b) - | Expr::Multiply(a, b) - | Expr::Divide(a, b) - | Expr::Exponent(a, b) - | Expr::Modulo(a, b) - | Expr::AddAssign(a, b) - | Expr::SubtractAssign(a, b) - | Expr::MultiplyAssign(a, b) - | Expr::DivideAssign(a, b) => { - self.analyze(*a); - self.analyze(*b); + } + Expr::Call(a, b) => { + analyze(scope, a); + for e in b { + analyze(scope, e); } } + Expr::Return(a) | Expr::Negate(a) | Expr::Not(a) => analyze(scope, a), + Expr::EqualTo(a, b) + | Expr::NotEqualTo(a, b) + | Expr::And(a, b) + | Expr::Or(a, b) + | Expr::LessThan(a, b) + | Expr::LessThanOrEqualTo(a, b) + | Expr::GreaterThan(a, b) + | Expr::GreaterThanOrEqualTo(a, b) + | Expr::Add(a, b) + | Expr::Subtract(a, b) + | Expr::Multiply(a, b) + | Expr::Divide(a, b) + | Expr::Exponent(a, b) + | Expr::Modulo(a, b) + | Expr::AddAssign(a, b) + | Expr::SubtractAssign(a, b) + | Expr::MultiplyAssign(a, b) + | Expr::DivideAssign(a, b) => { + analyze(scope, a); + analyze(scope, b); + } } } diff --git a/src/main.rs b/src/main.rs index fbd2397..a1bb305 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,15 +10,17 @@ mod parser; fn main() { let script = std::fs::read_to_string("./start.lf").unwrap(); let lexer = Lexer::new(script.chars()); + let mut parser = Parser::new(lexer.map(Result::unwrap)); let start = Instant::now(); let block = parser.parse().unwrap(); println!("Parse took {:?}", start.elapsed()); + let e = parser::Expr::Block(block); parser::util::display(&e); + let start = Instant::now(); - let mut analysis = compiler::Analyzer::new(); - analysis.analyze(e); + compiler::compile(e); + println!("Analysis took {:?}", start.elapsed()); - println!("{analysis:?}"); } diff --git a/src/parser.rs b/src/parser.rs index d7a8505..1a0b052 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -11,7 +11,7 @@ pub mod util; pub enum Expr { // Data and variables Assign(Box, Box), - Literal(Literal), + Literal(Literal, u16), // Non-literal datatypes Block(Block), Func(Vec, Box), @@ -122,7 +122,7 @@ where fn parse_expr(&mut self, min_prec: Precedence, in_group: bool) -> Result> { let mut lhs = match self.try_next()? { // literal - Token::Literal(lit) => Box::new(Expr::Literal(lit)), + Token::Literal(lit) => Box::new(Expr::Literal(lit, 0)), // start of group Token::ParenOpen => { diff --git a/src/parser/util.rs b/src/parser/util.rs index 68c28ff..efb6444 100644 --- a/src/parser/util.rs +++ b/src/parser/util.rs @@ -23,7 +23,7 @@ fn fmt_expr(e: &Expr, depth: usize) -> String { Expr::SubtractAssign(l, r) => fmt_binop(l, r, "-=", depth), Expr::MultiplyAssign(l, r) => fmt_binop(l, r, "*=", depth), Expr::DivideAssign(l, r) => fmt_binop(l, r, "/=", depth), - Expr::Literal(l) => l.to_string(), + Expr::Literal(l, _) => l.to_string(), Expr::Call(l, r) => { let mut result = fmt_expr(l, depth); result.push('(');