anything above

This commit is contained in:
minish 2025-09-20 00:39:28 -04:00
parent 67e701bc7c
commit 479fd637c3
Signed by: min
SSH Key Fingerprint: SHA256:mf+pUTmK92Y57BuCjlkBdd82LqztTfDCQIUp0fCKABc
3 changed files with 40 additions and 23 deletions

View File

@ -5,6 +5,8 @@ use crate::{
parser::Expr, parser::Expr,
}; };
pub type FuncMeta = Rc<Cell<bool>>;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct RefMeta { pub struct RefMeta {
pub now: u16, pub now: u16,
@ -25,25 +27,28 @@ impl<'a> Scope<'a> {
fn assigned(&mut self, id: Ident) { fn assigned(&mut self, id: Ident) {
self.idents.push((id, Rc::default())); self.idents.push((id, Rc::default()));
} }
fn find(&self, id: &Ident) -> Rc<Cell<u16>> { fn find(&self, id: &Ident) -> (Rc<Cell<u16>>, bool) {
let mut cur = Some(self); let mut cur = Some(self);
let mut went_up = false;
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;
went_up = true;
continue; continue;
}; };
return count.clone(); return (count.clone(), went_up);
} }
panic!("undefined variable"); panic!("undefined variable");
} }
} }
pub fn compile(e: &mut Expr) { pub fn compile(e: &mut Expr) {
let fm = FuncMeta::default();
let mut scope = Scope::with_parent(None); let mut scope = Scope::with_parent(None);
analyze(&mut scope, e); analyze(&fm, &mut scope, e);
} }
fn analyze(scope: &mut Scope, e: &mut Expr) { fn analyze(fm: &FuncMeta, 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 {
@ -54,11 +59,11 @@ fn analyze(scope: &mut Scope, e: &mut Expr) {
scope.assigned(id.clone()); scope.assigned(id.clone());
// analyse the value // analyse the value
analyze(scope, b); analyze(fm, scope, b);
} }
Expr::Literal(Literal::Ident(id, ref_meta)) => { Expr::Literal(Literal::Ident(id, ref_meta)) => {
// lookup literal // lookup literal
let count = scope.find(id); let (count, went_up) = scope.find(id);
// increment # of uses // increment # of uses
count.update(|c| c + 1); count.update(|c| c + 1);
// set ref meta // set ref meta
@ -66,6 +71,10 @@ fn analyze(scope: &mut Scope, e: &mut Expr) {
now: count.get(), now: count.get(),
total: count, total: count,
}); });
// if we used something external to this scope, note it
if went_up {
fm.set(true);
}
} }
// ignore // ignore
Expr::Literal(_) => {} Expr::Literal(_) => {}
@ -75,10 +84,13 @@ fn analyze(scope: &mut Scope, e: &mut Expr) {
let mut scope = Scope::with_parent(Some(scope)); let mut scope = Scope::with_parent(Some(scope));
// analyze the contents in the new scope // analyze the contents in the new scope
for e in &mut a.exprs { for e in &mut a.exprs {
analyze(&mut scope, e); analyze(fm, &mut scope, e);
} }
} }
Expr::Func(a, b) => { Expr::Func(a, b, func_meta) => {
// new function new context
let fm = FuncMeta::default();
*func_meta = Some(fm.clone());
// functions have their own scope, because they have args // functions have their own scope, because they have args
let mut scope = Scope::with_parent(Some(scope)); let mut scope = Scope::with_parent(Some(scope));
@ -91,22 +103,22 @@ fn analyze(scope: &mut Scope, e: &mut Expr) {
} }
// now analyze the body in the new scope // now analyze the body in the new scope
analyze(&mut scope, b); analyze(&fm, &mut scope, b);
} }
Expr::If(a, b, c) => { Expr::If(a, b, c) => {
analyze(scope, a); analyze(fm, scope, a);
analyze(scope, b); analyze(fm, scope, b);
if let Some(c) = c { if let Some(c) = c {
analyze(scope, c); analyze(fm, scope, c);
} }
} }
Expr::Call(a, b) => { Expr::Call(a, b) => {
analyze(scope, a); analyze(fm, scope, a);
for e in b { for e in b {
analyze(scope, e); analyze(fm, scope, e);
} }
} }
Expr::Return(a) | Expr::Negate(a) | Expr::Not(a) => analyze(scope, a), Expr::Return(a) | Expr::Negate(a) | Expr::Not(a) => analyze(fm, scope, a),
Expr::EqualTo(a, b) Expr::EqualTo(a, b)
| Expr::NotEqualTo(a, b) | Expr::NotEqualTo(a, b)
| Expr::And(a, b) | Expr::And(a, b)
@ -125,8 +137,8 @@ fn analyze(scope: &mut Scope, e: &mut Expr) {
| Expr::SubtractAssign(a, b) | Expr::SubtractAssign(a, b)
| Expr::MultiplyAssign(a, b) | Expr::MultiplyAssign(a, b)
| Expr::DivideAssign(a, b) => { | Expr::DivideAssign(a, b) => {
analyze(scope, a); analyze(fm, scope, a);
analyze(scope, b); analyze(fm, scope, b);
} }
} }
} }

View File

@ -1,20 +1,21 @@
use std::{fmt, iter::Peekable}; use std::{fmt, iter::Peekable};
use crate::{ use crate::{
compiler::FuncMeta,
kind::Kind, kind::Kind,
lexer::{Associativity, LexError, Literal, Precedence, Token, TokenKind}, lexer::{Associativity, LexError, Literal, Precedence, Token, TokenKind},
}; };
pub mod util; pub mod util;
#[derive(Debug, Clone)] #[derive(Debug)]
pub enum Expr { pub enum Expr {
// Data and variables // Data and variables
Assign(Box<Expr>, Box<Expr>), Assign(Box<Expr>, Box<Expr>),
Literal(Literal), Literal(Literal),
// Non-literal datatypes // Non-literal datatypes
Block(Block), Block(Block),
Func(Vec<Expr>, Box<Expr>), Func(Vec<Expr>, Box<Expr>, Option<FuncMeta>),
// Control flow // Control flow
If(Box<Expr>, Box<Expr>, Option<Box<Expr>>), If(Box<Expr>, Box<Expr>, Option<Box<Expr>>),
Return(Box<Expr>), Return(Box<Expr>),
@ -46,7 +47,7 @@ pub enum Expr {
DivideAssign(Box<Expr>, Box<Expr>), DivideAssign(Box<Expr>, Box<Expr>),
} }
#[derive(Debug, Default, Clone)] #[derive(Debug, Default)]
pub struct Block { pub struct Block {
pub exprs: Vec<Expr>, pub exprs: Vec<Expr>,
} }
@ -154,7 +155,7 @@ where
// parse body // parse body
let body = self.parse_expr(prec, in_group)?; let body = self.parse_expr(prec, in_group)?;
// pack // pack
Box::new(Expr::Func(args, body)) Box::new(Expr::Func(args, body, None))
} }
// parse if // parse if
Token::If => { Token::If => {

View File

@ -60,12 +60,16 @@ fn fmt_expr(e: &Expr, depth: usize) -> String {
} }
result result
} }
Expr::Func(a, e) => format!( Expr::Func(a, e, func_meta) => format!(
"(func({}) ({}))", "(func({}){} ({}))",
a.iter() a.iter()
.map(|e| fmt_expr(e, depth)) .map(|e| fmt_expr(e, depth))
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join(", "), .join(", "),
func_meta
.as_ref()
.map(|fm| format!("@{}", fm.get()))
.unwrap_or_default(),
fmt_expr(e, depth) fmt_expr(e, depth)
), ),
Expr::Negate(l) => format!("(-{})", fmt_expr(l, depth)), Expr::Negate(l) => format!("(-{})", fmt_expr(l, depth)),