wip codegen
This commit is contained in:
parent
167c0956b1
commit
6bc5646a03
132
src/compiler.rs
132
src/compiler.rs
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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()
|
||||||
),
|
),
|
||||||
|
|
|
@ -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:?}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue