I can see the light
This commit is contained in:
+65
-77
@@ -1,60 +1,61 @@
|
||||
use super::{func::FnLowerCtx, FnLowerable, PExpr, PostfixOp};
|
||||
use crate::{
|
||||
ir::{FieldRef, Type, UData, UInstruction, VarInst},
|
||||
ir::{Type, UData, UInstruction, VarInst},
|
||||
parser::InfixOp,
|
||||
};
|
||||
|
||||
impl FnLowerable for PExpr {
|
||||
type Output = VarInst;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<VarInst> {
|
||||
Some(match self {
|
||||
PExpr::Lit(l) => match l.as_ref()? {
|
||||
let mut e = self;
|
||||
let mut path = Vec::new();
|
||||
while let PExpr::Member(node, ident) = e {
|
||||
e = if let Some(t) = node.as_ref() {
|
||||
path.push(ident);
|
||||
&**t
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
}
|
||||
Some(match e {
|
||||
PExpr::Lit(l) => match l {
|
||||
super::PLiteral::String(s) => {
|
||||
let dest = ctx.program.temp_var(l.origin, Type::Bits(8).slice());
|
||||
let dest = ctx.b.temp_var(ctx.origin, Type::Bits(8).slice());
|
||||
let data = s.as_bytes().to_vec();
|
||||
let src = ctx.program.def(
|
||||
&format!("string \"{}\"", s.replace("\n", "\\n")),
|
||||
Some(UData {
|
||||
ty: Type::Bits(8).arr(data.len() as u32),
|
||||
content: data,
|
||||
}),
|
||||
l.origin,
|
||||
);
|
||||
ctx.push(UInstruction::LoadSlice { dest, src });
|
||||
let src = ctx.b.def_data(UData {
|
||||
name: format!("string \"{}\"", s.replace("\n", "\\n")),
|
||||
ty: Type::Bits(8).arr(data.len() as u32),
|
||||
content: data,
|
||||
});
|
||||
ctx.push(UInstruction::LoadSlice { dst: dest, src });
|
||||
dest
|
||||
}
|
||||
super::PLiteral::Char(c) => {
|
||||
let ty = Type::Bits(8);
|
||||
let dest = ctx.program.temp_var(l.origin, ty.clone());
|
||||
let src = ctx.program.def(
|
||||
&format!("char '{c}'"),
|
||||
Some(UData {
|
||||
ty,
|
||||
content: c.to_string().as_bytes().to_vec(),
|
||||
}),
|
||||
l.origin,
|
||||
);
|
||||
ctx.push(UInstruction::LoadData { dest, src });
|
||||
let dest = ctx.b.temp_var(ctx.origin, ty.clone());
|
||||
let src = ctx.b.def_data(UData {
|
||||
name: format!("char '{c}'"),
|
||||
ty,
|
||||
content: c.to_string().as_bytes().to_vec(),
|
||||
});
|
||||
ctx.push(UInstruction::LoadData { dst: dest, src });
|
||||
dest
|
||||
}
|
||||
super::PLiteral::Number(n) => {
|
||||
// TODO: temp
|
||||
let ty = Type::Bits(64);
|
||||
let dest = ctx.program.temp_var(l.origin, ty.clone());
|
||||
let src = ctx.program.def(
|
||||
&format!("num {n:?}"),
|
||||
Some(UData {
|
||||
ty,
|
||||
content: n.whole.parse::<i64>().unwrap().to_le_bytes().to_vec(),
|
||||
}),
|
||||
l.origin,
|
||||
);
|
||||
ctx.push(UInstruction::LoadData { dest, src });
|
||||
let dest = ctx.b.temp_var(ctx.origin, ty.clone());
|
||||
let src = ctx.b.def_data(UData {
|
||||
name: format!("num {n:?}"),
|
||||
ty,
|
||||
content: n.whole.parse::<i64>().unwrap().to_le_bytes().to_vec(),
|
||||
});
|
||||
ctx.push(UInstruction::LoadData { dst: dest, src });
|
||||
dest
|
||||
}
|
||||
super::PLiteral::Unit => ctx.program.temp_var(l.origin, Type::Unit),
|
||||
super::PLiteral::Unit => ctx.b.temp_var(ctx.origin, Type::Unit),
|
||||
},
|
||||
PExpr::Ident(i) => ctx.get_var(i)?,
|
||||
PExpr::Ident(i) => ctx.get_var(i),
|
||||
PExpr::BinaryOp(op, e1, e2) => match op {
|
||||
InfixOp::Add => todo!(),
|
||||
InfixOp::Sub => todo!(),
|
||||
@@ -62,49 +63,30 @@ impl FnLowerable for PExpr {
|
||||
InfixOp::Div => todo!(),
|
||||
InfixOp::LessThan => todo!(),
|
||||
InfixOp::GreaterThan => todo!(),
|
||||
InfixOp::Member => {
|
||||
let res1 = e1.lower(ctx)?;
|
||||
let Some(box PExpr::Ident(ident)) = &e2.inner else {
|
||||
ctx.err("Field accessors must be identifiers".to_string());
|
||||
return None;
|
||||
};
|
||||
let fname = ident.as_ref()?.0.clone();
|
||||
ctx.temp(Type::Field(FieldRef {
|
||||
parent: res1.id,
|
||||
name: fname,
|
||||
}))
|
||||
}
|
||||
InfixOp::Assign => {
|
||||
let res1 = e1.lower(ctx)?;
|
||||
let res2 = e2.lower(ctx)?;
|
||||
ctx.push(UInstruction::Mv {
|
||||
dest: res1,
|
||||
dst: res1,
|
||||
src: res2,
|
||||
});
|
||||
res1
|
||||
}
|
||||
},
|
||||
PExpr::PostfixOp(op, e) => {
|
||||
PExpr::PostfixOp(e, op) => {
|
||||
let res = e.lower(ctx)?;
|
||||
match op {
|
||||
PostfixOp::Ref => {
|
||||
let temp = ctx.temp(ctx.program.expect(res.id).ty.clone().rf());
|
||||
ctx.push(UInstruction::Ref {
|
||||
dest: temp,
|
||||
src: res,
|
||||
});
|
||||
temp
|
||||
let ty = ctx.b.vars[res.id].ty.rf();
|
||||
let dest = ctx.temp(ty);
|
||||
ctx.push(UInstruction::Ref { dst: dest, src: res });
|
||||
dest
|
||||
}
|
||||
PostfixOp::Deref => {
|
||||
let t = &ctx.program.expect(res.id).ty;
|
||||
let Type::Ref(_) = t else {
|
||||
ctx.err(format!(
|
||||
"Cannot dereference type {:?}",
|
||||
ctx.program.type_name(t)
|
||||
));
|
||||
return None;
|
||||
};
|
||||
todo!();
|
||||
let ty = ctx.b.vars[res.id].ty.derf();
|
||||
let dest = ctx.temp(ty);
|
||||
ctx.push(UInstruction::Deref { dst: dest, src: res });
|
||||
dest
|
||||
}
|
||||
PostfixOp::Not => todo!(),
|
||||
}
|
||||
@@ -118,37 +100,36 @@ impl FnLowerable for PExpr {
|
||||
let arg = arg.lower(ctx)?;
|
||||
nargs.push(arg);
|
||||
}
|
||||
let ty = ctx
|
||||
.program
|
||||
.get_fn_var(fe.id)
|
||||
.map(|f| f.ret.clone())
|
||||
.unwrap_or(Type::Placeholder);
|
||||
let temp = ctx.temp(ty);
|
||||
let dest = ctx.temp(Type::Placeholder);
|
||||
ctx.push(UInstruction::Call {
|
||||
dest: temp,
|
||||
dst: dest,
|
||||
f: fe,
|
||||
args: nargs,
|
||||
});
|
||||
temp
|
||||
dest
|
||||
}
|
||||
PExpr::Group(e) => e.lower(ctx)?,
|
||||
PExpr::Construct(c) => c.lower(ctx)?,
|
||||
PExpr::Construct(e, map) => {
|
||||
let dest = ctx.temp(Type::Placeholder);
|
||||
ctx.push(UInstruction::Construct { dst: dest, fields: () });
|
||||
dest
|
||||
}
|
||||
PExpr::If(cond, body) => {
|
||||
let cond = cond.lower(ctx)?;
|
||||
ctx.program.push();
|
||||
ctx.b.push();
|
||||
let mut body_ctx = ctx.branch();
|
||||
body.lower(&mut body_ctx);
|
||||
let body = body_ctx.instructions;
|
||||
ctx.program.pop();
|
||||
ctx.b.pop();
|
||||
ctx.push(UInstruction::If { cond, body });
|
||||
return None;
|
||||
}
|
||||
PExpr::Loop(body) => {
|
||||
ctx.program.push();
|
||||
ctx.b.push();
|
||||
let mut body_ctx = ctx.branch();
|
||||
body.lower(&mut body_ctx);
|
||||
let body = body_ctx.instructions;
|
||||
ctx.program.pop();
|
||||
ctx.b.pop();
|
||||
ctx.push(UInstruction::Loop { body });
|
||||
return None;
|
||||
}
|
||||
@@ -160,6 +141,13 @@ impl FnLowerable for PExpr {
|
||||
ctx.push(UInstruction::Continue);
|
||||
return None;
|
||||
}
|
||||
PExpr::Member(e, name) => {
|
||||
ctx.err("Can't access a member here".to_string());
|
||||
return None;
|
||||
}
|
||||
PExpr::Field(e, name) => {
|
||||
todo!()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user