wip codegen

This commit is contained in:
minish 2025-10-06 17:18:42 -04:00
parent 167c0956b1
commit 6bc5646a03
Signed by: min
SSH Key Fingerprint: SHA256:mf+pUTmK92Y57BuCjlkBdd82LqztTfDCQIUp0fCKABc
4 changed files with 109 additions and 39 deletions

View File

@ -39,10 +39,13 @@ impl<'a> Stack<'a> for Scope<'a> {
} }
} }
impl Scope<'_> { impl Scope<'_> {
fn assigned(&mut self, id: Ident) { fn assigned(&mut self, id: Ident) -> Rc<RefMeta> {
if self.find(&id).is_none() { let Some((rm, _)) = self.find(&id) else {
self.push((id, Rc::default())); let rm: Rc<RefMeta> = Rc::default();
} self.push((id, rm.clone()));
return rm;
};
rm
} }
} }
@ -55,7 +58,7 @@ pub type FuncStat = Rc<FuncMeta>;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct RefStat { pub struct RefStat {
pub now: u16, pub now: u16,
pub stat: Rc<RefMeta>, pub meta: Rc<RefMeta>,
} }
#[derive(Debug, Default)] #[derive(Debug, Default)]
@ -67,32 +70,35 @@ pub struct RefMeta {
fn analyze(fs: &FuncStat, scope: &mut Scope, e: &mut Expr) { fn analyze(fs: &FuncStat, 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, ref_stat)) = &mut **a else {
panic!("invalid assignment"); panic!("invalid assignment");
}; };
// add to scope // add to scope
scope.assigned(id.clone()); let rm = scope.assigned(id.clone());
// add ref stat
*ref_stat = Some(RefStat { now: rm.total.get(), meta: rm });
// analyse the value // analyse the value
analyze(fs, scope, b); analyze(fs, scope, b);
} }
Expr::Literal(Literal::Ident(id, ref_stat)) => { Expr::Literal(Literal::Ident(id, ref_stat)) => {
// lookup literal // lookup literal
let Some((rs, up_levels)) = scope.find(id) else { let Some((rm, up_levels)) = scope.find(id) else {
panic!("unfound variable") panic!("unfound variable")
}; };
// increment # of uses // increment # of uses
rs.total.update(|c| c + 1); rm.total.update(|c| c + 1);
// set ref meta // set ref meta
*ref_stat = Some(RefStat { *ref_stat = Some(RefStat {
now: rs.total.get(), now: rm.total.get(),
stat: rs.clone(), meta: rm.clone(),
}); });
// if we used something external to this scope, note it // if we used something external to this scope, note it
if up_levels != 0 { if up_levels != 0 {
fs.is_unreturnable.set(true); fs.is_unreturnable.set(true);
rs.is_shared.set(true); rm.is_shared.set(true);
} }
} }
// ignore // ignore
@ -165,15 +171,17 @@ fn analyze(fs: &FuncStat, scope: &mut Scope, e: &mut Expr) {
// --- translate pass --- // // --- translate pass --- //
/* 1b is up? */ /* 1b is up? */
enum Stkval { #[derive(Debug, PartialEq, Eq)]
pub enum Stkval {
/* 4b blank ; 8b offset */ /* 4b blank ; 8b offset */
Local(u8), Local(u8),
/* 4b up levels ; 8b offset */ /* 4b up levels ; 8b offset */
Shared(u8, u8), Shared(u8, u8),
} }
/* 3b type tag */ /* 3b type tag */
enum Val { #[derive(Debug)]
Stack(Stkval), pub enum Val {
Stack(Stkval, bool),
/* u16 len, LEN data */ /* u16 len, LEN data */
String(String), String(String),
/* 1b returnability, 4b arity, insts */ /* 1b returnability, 4b arity, insts */
@ -188,7 +196,8 @@ enum Val {
Nil, Nil,
} }
/* 5b inst type */ /* 5b inst type */
enum Inst { #[derive(Debug)]
pub enum Inst {
/* ... */ /* ... */
Copy(Val), Copy(Val),
/* pop a1? ; pop a2? */ /* pop a1? ; pop a2? */
@ -217,17 +226,12 @@ enum Inst {
} }
/// Value on fake stack. /// Value on fake stack.
#[derive(Debug)]
enum FSValue { enum FSValue {
Var(Ident), Var(Ident),
Any, Any,
} }
/// Build scope of a block.
///
/// Keeps track of where on the stack a block started,
/// so it can all be cleared once the block is left
struct BlockBuild {}
/// A stack that keeps track of values during translation. /// A stack that keeps track of values during translation.
/// (Local or shared) /// (Local or shared)
struct FakeStack<'a> { struct FakeStack<'a> {
@ -259,15 +263,6 @@ impl<'a> Stack<'a> for FakeStack<'a> {
matches!(value, FSValue::Var(x) if x == input).then_some(index) matches!(value, FSValue::Var(x) if x == input).then_some(index)
} }
} }
impl FakeStack<'_> {
fn get(&mut self, id: Ident) -> (usize, u16) {
self.find(&id).unwrap_or_else(|| {
let i = self.values().len();
self.push(FSValue::Var(id));
(i, 0)
})
}
}
/// Build scope of a function. /// Build scope of a function.
/// ///
@ -297,8 +292,75 @@ impl<'a> FuncBuild<'a> {
} }
} }
fn translate(&mut self, bb: &mut BlockBuild, e: &Expr) { fn find(&mut self, id: &Ident) -> Stkval {
self.shared
.find(id)
.map(|(count, up_levels)| Stkval::Shared(up_levels as u8, count as u8))
.or_else(|| self.local.find(id).map(|(c, _)| Stkval::Local(c as u8)))
.unwrap()
}
fn push_any(&mut self) -> Stkval {
// println!("PUSHING ANY TO {:?}", self.local.values());
let i = self.local.height();
self.local.push(FSValue::Any);
Stkval::Local(i as u8)
}
fn is_drop(&mut self, v: &Val) -> bool {
if let Val::Stack(Stkval::Local(i), true) = v {
self.local.pop(*i as usize);
true
} else {
false
}
}
fn is_drop2(&mut self, v1: &Val, v2: &Val) -> (bool, bool) {
(self.is_drop(v1), self.is_drop(v2))
}
fn translate(&mut self, e: Expr, unused: bool) -> Val {
// println!("{e:?}\n\n");
match e { match e {
/* organisational */
Expr::Block(mut b) => {
let last = b.exprs.pop();
for e in b.exprs {
self.translate(e, false);
}
// yield last expr
last.map_or(Val::Nil, |e| self.translate(e, false))
}
/* 1 to 1 literals */
Expr::Literal(Literal::Boolean(b)) => Val::Bool(b),
Expr::Literal(Literal::Float(f)) => Val::Float64(f),
Expr::Literal(Literal::Integer(i)) => Val::Int64(i),
Expr::Literal(Literal::Nil) => Val::Nil,
Expr::Literal(Literal::String(s)) => Val::String(s),
/* ident */
Expr::Literal(Literal::Ident(id, Some(rs))) => {
Val::Stack(self.find(&id), rs.now == rs.meta.total.get())
}
/* math */
Expr::Add(l, r) => {
let (v1, v2) = (self.translate(*l, false), self.translate(*r, false));
let (a1, a2) = self.is_drop2(&v1, &v2);
self.insts.push(Inst::Add(a1, a2, v1, v2));
Val::Stack(self.push_any(), true)
}
Expr::Assign(l, r) => {
let Expr::Literal(Literal::Ident(id, Some(ref_stat))) = *l else {
unreachable!()
};
let unused = ref_stat.now == ref_stat.meta.total.get();
let val = self.translate(*r, unused);
if !unused {
self.local.push(FSValue::Var(id));
}
val
}
_ => unimplemented!(), _ => unimplemented!(),
} }
} }
@ -310,9 +372,9 @@ pub fn analysis_demo(e: &mut Expr) {
let mut scope = Scope::with_parent(None); let mut scope = Scope::with_parent(None);
analyze(&fs, &mut scope, e); analyze(&fs, &mut scope, e);
} }
pub fn translation_demo(e: &Expr) { pub fn translation_demo(e: Expr) -> Vec<Inst> {
// translation pass // translation pass
let mut fb = FuncBuild::new_root(); let mut fb = FuncBuild::new_root();
let mut bb = BlockBuild {}; fb.translate(e, true);
fb.translate(&mut bb, e); fb.insts
} }

View File

@ -17,6 +17,12 @@ where
fn push(&mut self, value: Self::Value) { fn push(&mut self, value: Self::Value) {
self.values_mut().push(value); self.values_mut().push(value);
} }
fn pop(&mut self, index: usize) {
self.values_mut().remove(index);
}
fn height(&self) -> usize {
self.values().len()
}
fn find(&self, input: &Self::Input) -> Option<(Self::Output, u16)> { fn find(&self, input: &Self::Input) -> Option<(Self::Output, u16)> {
let mut cur = Some(self); let mut cur = Some(self);

View File

@ -37,9 +37,9 @@ impl fmt::Display for Literal {
.as_ref() .as_ref()
.map(|rs| format!( .map(|rs| format!(
"@{}{}/{}", "@{}{}/{}",
rs.stat.is_shared.get().then_some("sh+").unwrap_or(""), rs.meta.is_shared.get().then_some("sh+").unwrap_or(""),
rs.now, rs.now,
rs.stat.total.get() rs.meta.total.get()
)) ))
.unwrap_or_default() .unwrap_or_default()
), ),

View File

@ -24,7 +24,9 @@ fn main() {
parser::util::display(&e); parser::util::display(&e);
let start = Instant::now(); let start = Instant::now();
compiler::translation_demo(&mut e); let insts = compiler::translation_demo(e);
println!("Translation took {:?}", start.elapsed()); println!("Translation took {:?}", start.elapsed());
parser::util::display(&e); for i in insts {
println!("=> {i:?}");
}
} }