prep for code gen
This commit is contained in:
parent
479fd637c3
commit
2bbc6386ed
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue