prep for code gen

This commit is contained in:
minish 2025-09-20 02:48:38 -04:00
parent 479fd637c3
commit 2bbc6386ed
Signed by: min
SSH Key Fingerprint: SHA256:mf+pUTmK92Y57BuCjlkBdd82LqztTfDCQIUp0fCKABc
1 changed files with 51 additions and 6 deletions

View File

@ -14,6 +14,7 @@ pub struct RefMeta {
} }
struct Scope<'a> { struct Scope<'a> {
/* Faster than a hashmap for now? */
idents: Vec<(Ident, Rc<Cell<u16>>)>, idents: Vec<(Ident, Rc<Cell<u16>>)>,
parent: Option<&'a Scope<'a>>, parent: Option<&'a Scope<'a>>,
} }
@ -27,16 +28,16 @@ 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>>, bool) { fn find(&self, id: &Ident) -> (Rc<Cell<u16>>, u8) {
let mut cur = Some(self); let mut cur = Some(self);
let mut went_up = false; let mut up_levels = 0;
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; up_levels += 1;
continue; continue;
}; };
return (count.clone(), went_up); return (count.clone(), up_levels);
} }
panic!("undefined variable"); panic!("undefined variable");
} }
@ -48,6 +49,50 @@ pub fn compile(e: &mut Expr) {
analyze(&fm, &mut scope, e); analyze(&fm, &mut scope, e);
} }
/* 5b up levels, 8b offset */
struct Stkval(u8, u8);
/* 3b type tag */
enum Val {
Stack(Stkval),
/* u16 len, LEN data */
String(String),
/* 1b returnability, insts */
Func(bool, Vec<Inst>),
/* 1b value */
Bool(bool),
/* i64 data */
Int64(i64),
/* f64 data */
Float64(f64),
/* ... */
Nil,
}
enum Inst {
/* ... */
Copy(Val),
/* pop a1? ; pop a2? */
Eq(bool, bool, Val, Val),
Gt(bool, bool, Val, Val),
/* is conditional? ; what condition? ; pop result? */
Call(bool, bool, bool, Val),
/* pop a1? ; pop a2 */
Add(bool, bool, Val, Val),
Mul(bool, bool, Val, Val),
Div(bool, bool, Val, Val),
Mod(bool, bool, Val, Val),
Pow(bool, bool, Val, Val),
And(bool, bool, Val, Val),
Or(bool, bool, Val, Val),
/* pop a1? */
Not(bool, Val),
/* ... */
Pop(Stkval),
/* pop a2? */
Write(bool, Stkval, Val),
/* ... */
Return(Val),
}
fn analyze(fm: &FuncMeta, 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) => {
@ -63,7 +108,7 @@ fn analyze(fm: &FuncMeta, scope: &mut Scope, e: &mut Expr) {
} }
Expr::Literal(Literal::Ident(id, ref_meta)) => { Expr::Literal(Literal::Ident(id, ref_meta)) => {
// lookup literal // lookup literal
let (count, went_up) = scope.find(id); let (count, up_levels) = 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
@ -72,7 +117,7 @@ fn analyze(fm: &FuncMeta, scope: &mut Scope, e: &mut Expr) {
total: count, total: count,
}); });
// if we used something external to this scope, note it // if we used something external to this scope, note it
if went_up { if up_levels != 0 {
fm.set(true); fm.set(true);
} }
} }