This commit is contained in:
minish 2025-09-20 00:09:47 -04:00
parent c954e5af13
commit 1a0c93f26a
Signed by: min
SSH Key Fingerprint: SHA256:mf+pUTmK92Y57BuCjlkBdd82LqztTfDCQIUp0fCKABc
4 changed files with 31 additions and 17 deletions

View File

@ -1,12 +1,18 @@
use std::cell::Cell; use std::{cell::Cell, rc::Rc};
use crate::{ use crate::{
lexer::{Ident, Literal}, lexer::{Ident, Literal},
parser::Expr, parser::Expr,
}; };
#[derive(Debug, Clone)]
pub struct RefMeta {
now: u16,
total: Rc<Cell<u16>>,
}
struct Scope<'a> { struct Scope<'a> {
idents: Vec<(Ident, Cell<u16>)>, idents: Vec<(Ident, Rc<Cell<u16>>)>,
parent: Option<&'a Scope<'a>>, parent: Option<&'a Scope<'a>>,
} }
impl<'a> Scope<'a> { impl<'a> Scope<'a> {
@ -17,16 +23,16 @@ impl<'a> Scope<'a> {
} }
} }
fn assigned(&mut self, id: Ident) { fn assigned(&mut self, id: Ident) {
self.idents.push((id, Cell::default())); self.idents.push((id, Default::default()));
} }
fn find(&self, id: &Ident) -> &Cell<u16> { fn find(&self, id: &Ident) -> Rc<Cell<u16>> {
let mut cur = Some(self); let mut cur = Some(self);
while let Some(scope) = cur { while let Some(scope) = cur {
let Some((_, count)) = scope.idents.iter().rev().find(|i| i.0 == *id) else { let Some((_, count)) = scope.idents.iter().rev().find(|i| i.0 == *id) else {
cur = scope.parent; cur = scope.parent;
continue; continue;
}; };
return count; return count.clone();
} }
panic!("undefined variable"); panic!("undefined variable");
} }
@ -35,12 +41,13 @@ impl<'a> Scope<'a> {
pub fn compile(mut e: Expr) { pub fn compile(mut e: Expr) {
let mut scope = Scope::with_parent(None); let mut scope = Scope::with_parent(None);
analyze(&mut scope, &mut e); analyze(&mut scope, &mut e);
println!("{e:?}");
} }
fn analyze(scope: &mut Scope, e: &mut Expr) { fn analyze(scope: &mut Scope, e: &mut Expr) {
match e { match e {
Expr::Assign(a, b) => { Expr::Assign(a, b) => {
let Expr::Literal(Literal::Ident(id), _) = &**a else { let Expr::Literal(Literal::Ident(id, _)) = &**a else {
panic!("invalid assignment"); panic!("invalid assignment");
}; };
@ -50,14 +57,21 @@ fn analyze(scope: &mut Scope, e: &mut Expr) {
// analyse the value // analyse the value
analyze(scope, b); analyze(scope, b);
} }
Expr::Literal(Literal::Ident(id), _) => { Expr::Literal(Literal::Ident(id, ref_meta)) => {
// lookup literal // lookup literal
let count = scope.find(id); let count = scope.find(id);
// increment # of uses
count.update(|c| c + 1); 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 // ignore
Expr::Literal(_, _) => {} Expr::Literal(_) => {}
// for recursion.. // for recursion..
Expr::Block(a) => { Expr::Block(a) => {
// blocks have their own scope // blocks have their own scope
@ -73,7 +87,7 @@ fn analyze(scope: &mut Scope, e: &mut Expr) {
// init args // init args
for e in a { for e in a {
let Expr::Literal(Literal::Ident(id), _) = e else { let Expr::Literal(Literal::Ident(id, _)) = e else {
panic!("invalid arg def"); panic!("invalid arg def");
}; };
scope.assigned(id.clone()); scope.assigned(id.clone());

View File

@ -4,7 +4,7 @@ use std::{
num::{ParseFloatError, ParseIntError}, num::{ParseFloatError, ParseIntError},
}; };
use crate::kinds; use crate::{compiler::RefMeta, kinds};
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone)]
pub struct Ident(String); pub struct Ident(String);
@ -21,7 +21,7 @@ pub enum Literal {
Float(f64), Float(f64),
Boolean(bool), Boolean(bool),
Nil, Nil,
Ident(Ident), Ident(Ident, Option<RefMeta>),
} }
impl fmt::Display for Literal { impl fmt::Display for Literal {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 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::Integer(n) => write!(f, "{n}"),
Literal::Float(n) => write!(f, "{n}"), Literal::Float(n) => write!(f, "{n}"),
Literal::Boolean(b) => write!(f, "{b}"), Literal::Boolean(b) => write!(f, "{b}"),
Literal::Ident(id) => write!(f, "{id}"), Literal::Ident(id, _) => write!(f, "{id}"),
Literal::Nil => write!(f, "nil"), Literal::Nil => write!(f, "nil"),
} }
} }
@ -229,7 +229,7 @@ where
"true" => Token::Literal(Literal::Boolean(true)), "true" => Token::Literal(Literal::Boolean(true)),
"false" => Token::Literal(Literal::Boolean(false)), "false" => Token::Literal(Literal::Boolean(false)),
"nil" => Token::Literal(Literal::Nil), "nil" => Token::Literal(Literal::Nil),
_ => Token::Literal(Literal::Ident(Ident(word))), _ => Token::Literal(Literal::Ident(Ident(word), Default::default())),
} }
} }

View File

@ -11,7 +11,7 @@ pub mod util;
pub enum Expr { pub enum Expr {
// Data and variables // Data and variables
Assign(Box<Expr>, Box<Expr>), Assign(Box<Expr>, Box<Expr>),
Literal(Literal, u16), Literal(Literal),
// Non-literal datatypes // Non-literal datatypes
Block(Block), Block(Block),
Func(Vec<Expr>, Box<Expr>), Func(Vec<Expr>, Box<Expr>),
@ -122,7 +122,7 @@ where
fn parse_expr(&mut self, min_prec: Precedence, in_group: bool) -> Result<Box<Expr>> { fn parse_expr(&mut self, min_prec: Precedence, in_group: bool) -> Result<Box<Expr>> {
let mut lhs = match self.try_next()? { let mut lhs = match self.try_next()? {
// literal // literal
Token::Literal(lit) => Box::new(Expr::Literal(lit, 0)), Token::Literal(lit) => Box::new(Expr::Literal(lit)),
// start of group // start of group
Token::ParenOpen => { Token::ParenOpen => {

View File

@ -23,7 +23,7 @@ fn fmt_expr(e: &Expr, depth: usize) -> String {
Expr::SubtractAssign(l, r) => fmt_binop(l, r, "-=", depth), Expr::SubtractAssign(l, r) => fmt_binop(l, r, "-=", depth),
Expr::MultiplyAssign(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::DivideAssign(l, r) => fmt_binop(l, r, "/=", depth),
Expr::Literal(l, _) => l.to_string(), Expr::Literal(l) => l.to_string(),
Expr::Call(l, r) => { Expr::Call(l, r) => {
let mut result = fmt_expr(l, depth); let mut result = fmt_expr(l, depth);
result.push('('); result.push('(');