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::{
|
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());
|
||||||
|
|
|
@ -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())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 => {
|
||||||
|
|
|
@ -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('(');
|
||||||
|
|
Loading…
Reference in New Issue