From 1a0c93f26a379cb914ad8cac708b671e1a662ea3 Mon Sep 17 00:00:00 2001 From: min Date: Sat, 20 Sep 2025 00:09:47 -0400 Subject: [PATCH] ref meta --- src/compiler.rs | 34 ++++++++++++++++++++++++---------- src/lexer.rs | 8 ++++---- src/parser.rs | 4 ++-- src/parser/util.rs | 2 +- 4 files changed, 31 insertions(+), 17 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 4a31507..9e95a59 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -1,12 +1,18 @@ -use std::cell::Cell; +use std::{cell::Cell, rc::Rc}; use crate::{ lexer::{Ident, Literal}, parser::Expr, }; +#[derive(Debug, Clone)] +pub struct RefMeta { + now: u16, + total: Rc>, +} + struct Scope<'a> { - idents: Vec<(Ident, Cell)>, + idents: Vec<(Ident, Rc>)>, parent: Option<&'a Scope<'a>>, } impl<'a> Scope<'a> { @@ -17,16 +23,16 @@ impl<'a> Scope<'a> { } } fn assigned(&mut self, id: Ident) { - self.idents.push((id, Cell::default())); + self.idents.push((id, Default::default())); } - fn find(&self, id: &Ident) -> &Cell { + fn find(&self, id: &Ident) -> Rc> { let mut cur = Some(self); while let Some(scope) = cur { let Some((_, count)) = scope.idents.iter().rev().find(|i| i.0 == *id) else { cur = scope.parent; continue; }; - return count; + return count.clone(); } panic!("undefined variable"); } @@ -35,12 +41,13 @@ impl<'a> Scope<'a> { pub fn compile(mut e: Expr) { let mut scope = Scope::with_parent(None); analyze(&mut scope, &mut e); + println!("{e:?}"); } fn analyze(scope: &mut Scope, e: &mut Expr) { match e { Expr::Assign(a, b) => { - let Expr::Literal(Literal::Ident(id), _) = &**a else { + let Expr::Literal(Literal::Ident(id, _)) = &**a else { panic!("invalid assignment"); }; @@ -50,14 +57,21 @@ fn analyze(scope: &mut Scope, e: &mut Expr) { // analyse the value analyze(scope, b); } - Expr::Literal(Literal::Ident(id), _) => { + Expr::Literal(Literal::Ident(id, ref_meta)) => { // lookup literal let count = scope.find(id); + // increment # of uses count.update(|c| c + 1); - println!("ref {id} #{}", count.get()); + // set ref meta + let now = count.get(); + *ref_meta = Some(RefMeta { + now: count.get(), + total: count, + }); + println!("ref {id} #{now}"); } // ignore - Expr::Literal(_, _) => {} + Expr::Literal(_) => {} // for recursion.. Expr::Block(a) => { // blocks have their own scope @@ -73,7 +87,7 @@ fn analyze(scope: &mut Scope, e: &mut Expr) { // init args for e in a { - let Expr::Literal(Literal::Ident(id), _) = e else { + let Expr::Literal(Literal::Ident(id, _)) = e else { panic!("invalid arg def"); }; scope.assigned(id.clone()); diff --git a/src/lexer.rs b/src/lexer.rs index 2e896d9..258229b 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -4,7 +4,7 @@ use std::{ num::{ParseFloatError, ParseIntError}, }; -use crate::kinds; +use crate::{compiler::RefMeta, kinds}; #[derive(Debug, PartialEq, Eq, Clone)] pub struct Ident(String); @@ -21,7 +21,7 @@ pub enum Literal { Float(f64), Boolean(bool), Nil, - Ident(Ident), + Ident(Ident, Option), } impl fmt::Display for Literal { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -30,7 +30,7 @@ impl fmt::Display for Literal { Literal::Integer(n) => write!(f, "{n}"), Literal::Float(n) => write!(f, "{n}"), Literal::Boolean(b) => write!(f, "{b}"), - Literal::Ident(id) => write!(f, "{id}"), + Literal::Ident(id, _) => write!(f, "{id}"), Literal::Nil => write!(f, "nil"), } } @@ -229,7 +229,7 @@ where "true" => Token::Literal(Literal::Boolean(true)), "false" => Token::Literal(Literal::Boolean(false)), "nil" => Token::Literal(Literal::Nil), - _ => Token::Literal(Literal::Ident(Ident(word))), + _ => Token::Literal(Literal::Ident(Ident(word), Default::default())), } } diff --git a/src/parser.rs b/src/parser.rs index 1a0b052..d7a8505 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, u16), + Literal(Literal), // 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, 0)), + Token::Literal(lit) => Box::new(Expr::Literal(lit)), // start of group Token::ParenOpen => { diff --git a/src/parser/util.rs b/src/parser/util.rs index efb6444..68c28ff 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('(');