ref meta
This commit is contained in:
parent
c954e5af13
commit
1a0c93f26a
|
@ -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<Cell<u16>>,
|
||||
}
|
||||
|
||||
struct Scope<'a> {
|
||||
idents: Vec<(Ident, Cell<u16>)>,
|
||||
idents: Vec<(Ident, Rc<Cell<u16>>)>,
|
||||
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<u16> {
|
||||
fn find(&self, id: &Ident) -> Rc<Cell<u16>> {
|
||||
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());
|
||||
|
|
|
@ -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<RefMeta>),
|
||||
}
|
||||
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())),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ pub mod util;
|
|||
pub enum Expr {
|
||||
// Data and variables
|
||||
Assign(Box<Expr>, Box<Expr>),
|
||||
Literal(Literal, u16),
|
||||
Literal(Literal),
|
||||
// Non-literal datatypes
|
||||
Block(Block),
|
||||
Func(Vec<Expr>, Box<Expr>),
|
||||
|
@ -122,7 +122,7 @@ where
|
|||
fn parse_expr(&mut self, min_prec: Precedence, in_group: bool) -> Result<Box<Expr>> {
|
||||
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 => {
|
||||
|
|
|
@ -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('(');
|
||||
|
|
Loading…
Reference in New Issue