actually compiles and does stuff now
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
pub mod riscv64;
|
||||
pub use super::*;
|
||||
@@ -0,0 +1,109 @@
|
||||
use super::{PAsmArg, FnLowerCtx, PIdent, Node, PInstruction};
|
||||
use crate::{
|
||||
compiler::arch::riscv64::*,
|
||||
ir::{
|
||||
arch::riscv64::{RV64Instruction, RegRef},
|
||||
VarID,
|
||||
},
|
||||
};
|
||||
|
||||
impl RV64Instruction {
|
||||
pub fn parse(inst: &PInstruction, ctx: &mut FnLowerCtx) -> Option<Self> {
|
||||
let args = &inst.args[..];
|
||||
Some(match &**inst.op.inner.as_ref()? {
|
||||
"ecall" => Self::Ecall,
|
||||
"li" => {
|
||||
let [dest, imm] = args else {
|
||||
ctx.err("li requires 2 arguments".to_string());
|
||||
return None;
|
||||
};
|
||||
let dest = RegRef::from_arg(dest, ctx)?;
|
||||
let imm = i64_from_arg(imm, ctx)?;
|
||||
Self::Li { dest, imm }
|
||||
}
|
||||
"la" => {
|
||||
let [dest, src] = args else {
|
||||
ctx.err("la requires 2 arguments".to_string());
|
||||
return None;
|
||||
};
|
||||
let dest = RegRef::from_arg(dest, ctx)?;
|
||||
let src = arg_to_var(src, ctx)?;
|
||||
Self::La { dest, src }
|
||||
}
|
||||
"ld" => {
|
||||
let [dest, offset, base] = args else {
|
||||
ctx.err("ld requires 3 arguments".to_string());
|
||||
return None;
|
||||
};
|
||||
let dest = RegRef::from_arg(dest, ctx)?;
|
||||
let offset = i64_from_arg(offset, ctx)?;
|
||||
let base = RegRef::from_arg(base, ctx)?;
|
||||
Self::Ld { dest, offset, base }
|
||||
}
|
||||
"mv" => {
|
||||
let [dest, src] = args else {
|
||||
ctx.err("la requires 2 arguments".to_string());
|
||||
return None;
|
||||
};
|
||||
let dest = RegRef::from_arg(dest, ctx)?;
|
||||
let src = RegRef::from_arg(src, ctx)?;
|
||||
Self::Mv { dest, src }
|
||||
}
|
||||
w => {
|
||||
ctx.err_at(inst.op.span, format!("Unknown instruction '{}'", w));
|
||||
return None;
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn arg_to_var(node: &Node<PAsmArg>, ctx: &mut FnLowerCtx) -> Option<VarID> {
|
||||
let PAsmArg::Ref(node) = node.inner.as_ref()? else {
|
||||
ctx.err_at(
|
||||
node.span,
|
||||
"Expected variable / function reference".to_string(),
|
||||
);
|
||||
return None;
|
||||
};
|
||||
ctx.get_var(node)
|
||||
}
|
||||
|
||||
impl RegRef {
|
||||
pub fn from_arg(node: &Node<PAsmArg>, ctx: &mut FnLowerCtx) -> Option<Self> {
|
||||
Some(match node.inner.as_ref()? {
|
||||
PAsmArg::Value(node) => {
|
||||
let Some(reg) = Reg::from_ident(node, ctx) else {
|
||||
return None;
|
||||
};
|
||||
Self::Reg(reg)
|
||||
}
|
||||
PAsmArg::Ref(node) => Self::Var(ctx.get_var(node)?),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Reg {
|
||||
pub fn from_ident(node: &Node<PIdent>, ctx: &mut FnLowerCtx) -> Option<Self> {
|
||||
let s = &**node.inner.as_ref()?;
|
||||
let res = Reg::from_str(s);
|
||||
if res.is_none() {
|
||||
ctx.err_at(node.span, format!("Unknown reg name '{}'", s));
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
fn i64_from_arg(node: &Node<PAsmArg>, ctx: &mut FnLowerCtx) -> Option<i64> {
|
||||
let PAsmArg::Value(node) = node.inner.as_ref()? else {
|
||||
ctx.err_at(node.span, format!("Expected an i64, found reference"));
|
||||
return None;
|
||||
};
|
||||
let word = node.inner.as_ref()?;
|
||||
match word.parse::<i64>() {
|
||||
Ok(x) => Some(x),
|
||||
Err(_) => {
|
||||
ctx.err_at(node.span, format!("Expected an i64, found {}", word));
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
use crate::{
|
||||
compiler::arch::riscv64::Reg,
|
||||
ir::{arch::riscv64::RV64Instruction, IRUInstruction, VarID},
|
||||
};
|
||||
|
||||
use super::{PAsmBlock, PAsmBlockArg, FnLowerCtx, FnLowerable, PInstruction};
|
||||
|
||||
impl FnLowerable for PInstruction {
|
||||
type Output = RV64Instruction;
|
||||
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<RV64Instruction> {
|
||||
RV64Instruction::parse(self, ctx)
|
||||
}
|
||||
}
|
||||
|
||||
impl FnLowerable for PAsmBlock {
|
||||
type Output = ();
|
||||
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<Self::Output> {
|
||||
let block = IRUInstruction::AsmBlock {
|
||||
instructions: {
|
||||
let mut v = Vec::new();
|
||||
for i in &self.instructions {
|
||||
if let Some(i) = i.lower(ctx) {
|
||||
v.push(i);
|
||||
}
|
||||
}
|
||||
v
|
||||
},
|
||||
args: {
|
||||
let mut v = Vec::new();
|
||||
for a in &self.args {
|
||||
if let Some(a) = a.lower(ctx) {
|
||||
v.push(a);
|
||||
}
|
||||
}
|
||||
v
|
||||
},
|
||||
};
|
||||
ctx.push(block);
|
||||
Some(())
|
||||
}
|
||||
}
|
||||
|
||||
impl FnLowerable for PAsmBlockArg {
|
||||
type Output = (Reg, VarID);
|
||||
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<Self::Output> {
|
||||
let var = ctx.get_var(&self.var)?;
|
||||
let reg = Reg::from_ident(&self.reg, ctx)?;
|
||||
Some((reg, var))
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,10 @@
|
||||
use crate::ir::Instruction;
|
||||
use crate::ir::{IRUInstruction, VarID};
|
||||
|
||||
use super::{Block, ExprResult, FnLowerCtx, Node, Statement};
|
||||
use super::{PBlock, FnLowerCtx, FnLowerable, PStatement};
|
||||
|
||||
impl Node<Block> {
|
||||
pub fn lower(&self, ctx: &mut FnLowerCtx) -> Option<ExprResult> {
|
||||
self.as_ref()?.lower(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
impl Block {
|
||||
pub fn lower(&self, ctx: &mut FnLowerCtx) -> Option<ExprResult> {
|
||||
impl FnLowerable for PBlock {
|
||||
type Output = VarID;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<VarID> {
|
||||
let ctx = &mut ctx.sub();
|
||||
for statement in &self.statements {
|
||||
statement.lower(ctx);
|
||||
@@ -18,41 +13,24 @@ impl Block {
|
||||
}
|
||||
}
|
||||
|
||||
impl Node<Box<Statement>> {
|
||||
pub fn lower(&self, ctx: &mut FnLowerCtx) -> Option<ExprResult> {
|
||||
self.as_ref()?.lower(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
impl Node<Statement> {
|
||||
pub fn lower(&self, ctx: &mut FnLowerCtx) -> Option<ExprResult> {
|
||||
self.as_ref()?.lower(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
impl Statement {
|
||||
pub fn lower(&self, ctx: &mut FnLowerCtx) -> Option<ExprResult> {
|
||||
impl FnLowerable for PStatement {
|
||||
type Output = VarID;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<VarID> {
|
||||
match self {
|
||||
super::Statement::Let(def, e) => {
|
||||
super::PStatement::Let(def, e) => {
|
||||
let def = def.lower(ctx.map, ctx.output)?;
|
||||
let res = e.lower(ctx);
|
||||
if let Some(res) = res {
|
||||
match res {
|
||||
ExprResult::Var(v) => ctx.map.name_var(&def, v),
|
||||
ExprResult::Fn(_) => todo!(),
|
||||
}
|
||||
ctx.map.name_var(&def, res);
|
||||
}
|
||||
None
|
||||
}
|
||||
super::Statement::Return(e) => {
|
||||
let res = e.lower(ctx)?;
|
||||
match res {
|
||||
ExprResult::Var(v) => ctx.push(Instruction::Ret { src: v }),
|
||||
_ => todo!(),
|
||||
}
|
||||
super::PStatement::Return(e) => {
|
||||
let src = e.lower(ctx)?;
|
||||
ctx.push(IRUInstruction::Ret { src });
|
||||
None
|
||||
}
|
||||
super::Statement::Expr(e) => e.lower(ctx),
|
||||
super::PStatement::Expr(e) => e.lower(ctx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::ir::{FileSpan, NamespaceGuard, Origin, Type, VarDef};
|
||||
|
||||
use super::{Node, ParserMsg, ParserOutput, Type as PType, VarDef as PVarDef};
|
||||
use super::{Node, ParserMsg, ParserOutput, PType, PVarDef};
|
||||
|
||||
impl Node<PVarDef> {
|
||||
pub fn lower(
|
||||
@@ -9,7 +9,7 @@ impl Node<PVarDef> {
|
||||
output: &mut ParserOutput,
|
||||
) -> Option<VarDef> {
|
||||
let s = self.as_ref()?;
|
||||
let name = s.name.as_ref()?.val().clone();
|
||||
let name = s.name.as_ref()?.to_string();
|
||||
let ty = match &s.ty {
|
||||
Some(ty) => ty.lower(namespace, output),
|
||||
None => Type::Infer,
|
||||
|
||||
+57
-103
@@ -1,32 +1,37 @@
|
||||
use super::{func::FnLowerCtx, Expr as PExpr, Node, UnaryOp};
|
||||
use crate::ir::{FnIdent, Instruction, Type, VarIdent, VarOrFnIdent};
|
||||
use super::{func::FnLowerCtx, FnLowerable, PExpr, UnaryOp};
|
||||
use crate::ir::{IRUInstruction, Type, VarID};
|
||||
|
||||
impl PExpr {
|
||||
pub fn lower(&self, ctx: &mut FnLowerCtx) -> Option<ExprResult> {
|
||||
impl FnLowerable for PExpr {
|
||||
type Output = VarID;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<VarID> {
|
||||
Some(match self {
|
||||
PExpr::Lit(l) => match l.as_ref()? {
|
||||
super::Literal::String(s) => todo!(),
|
||||
super::Literal::Char(c) => todo!(),
|
||||
super::Literal::Number(n) => todo!(),
|
||||
super::Literal::Unit => {
|
||||
super::PLiteral::String(s) => {
|
||||
let dest = ctx.map.temp_var(l.span, Type::Bits(8).arr().rf());
|
||||
let src = ctx.map.def_data(s.as_bytes().to_vec());
|
||||
ctx.push(IRUInstruction::LoadData { dest, src });
|
||||
dest
|
||||
}
|
||||
super::PLiteral::Char(c) => {
|
||||
let dest = ctx.map.temp_var(l.span, Type::Bits(8).arr().rf());
|
||||
let src = ctx.map.def_data(c.to_string().as_bytes().to_vec());
|
||||
ctx.push(IRUInstruction::LoadData { dest, src });
|
||||
dest
|
||||
}
|
||||
super::PLiteral::Number(n) => {
|
||||
// TODO: temp
|
||||
let dest = ctx.map.temp_var(l.span, Type::Bits(8).arr().rf());
|
||||
let src = ctx
|
||||
.map
|
||||
.def_data(n.whole.parse::<i64>().unwrap().to_le_bytes().to_vec());
|
||||
ctx.push(IRUInstruction::LoadData { dest, src });
|
||||
dest
|
||||
}
|
||||
super::PLiteral::Unit => {
|
||||
todo!();
|
||||
}
|
||||
},
|
||||
PExpr::Ident(i) => {
|
||||
let name = i.as_ref()?.val();
|
||||
let Some(id) = ctx.get(name) else {
|
||||
ctx.err(format!("Identifier '{}' not found.", name));
|
||||
return None;
|
||||
};
|
||||
let Some(vf) = id.var_func else {
|
||||
ctx.err(format!("Variable or function '{}' not found; Found type, but types cannot be used here.", name));
|
||||
return None;
|
||||
};
|
||||
match vf {
|
||||
VarOrFnIdent::Var(var) => ExprResult::Var(var),
|
||||
VarOrFnIdent::Fn(f) => ExprResult::Fn(f),
|
||||
}
|
||||
}
|
||||
PExpr::Ident(i) => ctx.get_var(i)?,
|
||||
PExpr::BinaryOp(op, e1, e2) => {
|
||||
let res1 = e1.lower(ctx)?;
|
||||
let res2 = e2.lower(ctx)?;
|
||||
@@ -36,101 +41,50 @@ impl PExpr {
|
||||
PExpr::UnaryOp(op, e) => {
|
||||
let res = e.lower(ctx)?;
|
||||
match op {
|
||||
UnaryOp::Ref => ExprResult::Var(match res {
|
||||
ExprResult::Var(v) => {
|
||||
let temp = ctx.temp(ctx.map.get_var(v).ty.clone());
|
||||
ctx.push(Instruction::Ref { dest: temp, src: v });
|
||||
temp
|
||||
}
|
||||
ExprResult::Fn(f) => {
|
||||
let temp = ctx.temp(Type::Ref(Box::new(ctx.map.get_fn(f).ty())));
|
||||
ctx.push(Instruction::Lf { dest: temp, src: f });
|
||||
temp
|
||||
}
|
||||
}),
|
||||
UnaryOp::Deref => match res {
|
||||
ExprResult::Var(v) => match &ctx.map.get_var(v).ty {
|
||||
Type::Ref(inner) => {
|
||||
todo!()
|
||||
}
|
||||
t => {
|
||||
ctx.err(format!(
|
||||
"Cannot dereference type {:?}",
|
||||
ctx.map.type_name(t)
|
||||
));
|
||||
return None;
|
||||
}
|
||||
},
|
||||
ExprResult::Fn(f) => {
|
||||
ctx.err("Cannot dereference functions".to_string());
|
||||
UnaryOp::Ref => {
|
||||
let temp = ctx.temp(ctx.map.get_var(res).ty.clone());
|
||||
ctx.push(IRUInstruction::Ref {
|
||||
dest: temp,
|
||||
src: res,
|
||||
});
|
||||
temp
|
||||
}
|
||||
UnaryOp::Deref => {
|
||||
let t = &ctx.map.get_var(res).ty;
|
||||
let Type::Ref(inner) = t else {
|
||||
ctx.err(format!(
|
||||
"Cannot dereference type {:?}",
|
||||
ctx.map.type_name(t)
|
||||
));
|
||||
return None;
|
||||
}
|
||||
},
|
||||
};
|
||||
todo!();
|
||||
}
|
||||
UnaryOp::Not => todo!(),
|
||||
}
|
||||
}
|
||||
PExpr::Block(b) => b.lower(ctx)?,
|
||||
PExpr::AsmBlock(b) => {
|
||||
ctx.push(Instruction::AsmBlock {
|
||||
instructions: b.as_ref()?.instructions.clone(),
|
||||
});
|
||||
b.lower(ctx);
|
||||
return None;
|
||||
}
|
||||
PExpr::Call(e, args) => {
|
||||
let fe = e.lower(ctx)?;
|
||||
let f = e.lower(ctx)?;
|
||||
let mut nargs = Vec::new();
|
||||
for arg in args.iter() {
|
||||
let arg = arg.lower(ctx)?;
|
||||
nargs.push(match arg {
|
||||
ExprResult::Var(v) => v,
|
||||
ExprResult::Fn(_) => todo!(),
|
||||
});
|
||||
}
|
||||
match fe {
|
||||
ExprResult::Fn(f) => {
|
||||
let temp = ctx.temp(ctx.map.get_fn(f).ret.clone());
|
||||
ctx.push(Instruction::Call {
|
||||
dest: temp,
|
||||
f,
|
||||
args: nargs,
|
||||
});
|
||||
ExprResult::Var(temp)
|
||||
}
|
||||
o => {
|
||||
ctx.err(format!("Expected function, found {:?}", o));
|
||||
return None;
|
||||
}
|
||||
nargs.push(arg);
|
||||
}
|
||||
let temp = ctx.temp(ctx.map.get_fn_var(f).ret.clone());
|
||||
ctx.push(IRUInstruction::Call {
|
||||
dest: temp,
|
||||
f,
|
||||
args: nargs,
|
||||
});
|
||||
// ctx.err(format!("Expected function, found {:?}", f));
|
||||
return None;
|
||||
}
|
||||
PExpr::Group(e) => e.lower(ctx)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Node<PExpr> {
|
||||
pub fn lower(&self, ctx: &mut FnLowerCtx) -> Option<ExprResult> {
|
||||
self.inner.as_ref()?.lower(&mut FnLowerCtx {
|
||||
map: ctx.map,
|
||||
instructions: ctx.instructions,
|
||||
output: ctx.output,
|
||||
span: self.span,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Node<Box<PExpr>> {
|
||||
pub fn lower(&self, ctx: &mut FnLowerCtx) -> Option<ExprResult> {
|
||||
self.inner.as_ref()?.lower(&mut FnLowerCtx {
|
||||
map: ctx.map,
|
||||
instructions: ctx.instructions,
|
||||
output: ctx.output,
|
||||
span: self.span,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ExprResult {
|
||||
Var(VarIdent),
|
||||
Fn(FnIdent),
|
||||
}
|
||||
|
||||
+127
-28
@@ -1,7 +1,10 @@
|
||||
use super::{Function as PFunction, Node, ParserMsg, ParserOutput};
|
||||
use crate::ir::{
|
||||
BuiltinType, FileSpan, FnDef, FnIdent, Function, Idents, Instruction, Instructions,
|
||||
NamespaceGuard, Origin, Type, VarDef, VarIdent,
|
||||
use super::{FnLowerable, PFunction, Node, ParserMsg, ParserOutput};
|
||||
use crate::{
|
||||
ir::{
|
||||
BuiltinType, FileSpan, FnDef, FnID, IRUFunction, Idents, IRUInstruction, IRInstructions,
|
||||
NamespaceGuard, Origin, Type, VarDef, VarID,
|
||||
},
|
||||
parser,
|
||||
};
|
||||
|
||||
impl Node<PFunction> {
|
||||
@@ -9,15 +12,16 @@ impl Node<PFunction> {
|
||||
&self,
|
||||
map: &mut NamespaceGuard,
|
||||
output: &mut ParserOutput,
|
||||
) -> Option<FnIdent> {
|
||||
) -> Option<FnID> {
|
||||
self.as_ref()?.lower_header(map, output)
|
||||
}
|
||||
pub fn lower_body(&self, map: &mut NamespaceGuard, output: &mut ParserOutput) -> Option<Function> {
|
||||
if let Some(f) = self.as_ref() {
|
||||
Some(f.lower_body(map, output))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
pub fn lower_body(
|
||||
&self,
|
||||
id: FnID,
|
||||
map: &mut NamespaceGuard,
|
||||
output: &mut ParserOutput,
|
||||
) -> Option<IRUFunction> {
|
||||
Some(self.as_ref()?.lower_body(id, map, output))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +30,7 @@ impl PFunction {
|
||||
&self,
|
||||
map: &mut NamespaceGuard,
|
||||
output: &mut ParserOutput,
|
||||
) -> Option<FnIdent> {
|
||||
) -> Option<FnID> {
|
||||
let header = self.header.as_ref()?;
|
||||
let name = header.name.as_ref()?;
|
||||
let args = header
|
||||
@@ -44,50 +48,145 @@ impl PFunction {
|
||||
Some(ty) => ty.lower(map, output),
|
||||
None => Type::Concrete(BuiltinType::Unit.id()),
|
||||
};
|
||||
// ignoring self var for now
|
||||
Some(map.def_fn(FnDef {
|
||||
name: name.val().clone(),
|
||||
name: name.to_string(),
|
||||
origin: Origin::File(self.header.span),
|
||||
args,
|
||||
ret,
|
||||
}))
|
||||
}
|
||||
pub fn lower_body(&self, map: &mut NamespaceGuard, output: &mut ParserOutput) -> Function {
|
||||
let mut instructions = Instructions::new();
|
||||
pub fn lower_body(
|
||||
&self,
|
||||
id: FnID,
|
||||
map: &mut NamespaceGuard,
|
||||
output: &mut ParserOutput,
|
||||
) -> IRUFunction {
|
||||
let mut instructions = IRInstructions::new();
|
||||
let def = map.get_fn(id).clone();
|
||||
let args = def.args.iter().map(|a| {
|
||||
map.named_var(a.clone())
|
||||
}).collect();
|
||||
let mut ctx = FnLowerCtx {
|
||||
instructions: &mut instructions,
|
||||
map,
|
||||
output,
|
||||
span: self.body.span,
|
||||
};
|
||||
if let Some(res) = self.body.lower(&mut ctx) {
|
||||
match res {
|
||||
super::ExprResult::Var(v) => instructions.push(Instruction::Ret { src: v }),
|
||||
super::ExprResult::Fn(_) => todo!(),
|
||||
}
|
||||
if let Some(src) = self.body.lower(&mut ctx) {
|
||||
instructions.push(IRUInstruction::Ret { src });
|
||||
}
|
||||
Function::new(instructions)
|
||||
IRUFunction::new(def.name.clone(), args, instructions)
|
||||
}
|
||||
}
|
||||
|
||||
// impl Node<AsmFunction> {
|
||||
// pub fn lower_header(
|
||||
// &self,
|
||||
// map: &mut NamespaceGuard,
|
||||
// output: &mut ParserOutput,
|
||||
// ) -> Option<FnIdent> {
|
||||
// self.as_ref()?.lower_header(map, output)
|
||||
// }
|
||||
// pub fn lower_body(
|
||||
// &self,
|
||||
// map: &mut NamespaceGuard,
|
||||
// output: &mut ParserOutput,
|
||||
// ) -> Option<Function> {
|
||||
// Some(self.as_ref()?.lower_body(map, output))
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// impl AsmFunction {
|
||||
// pub fn lower_header(
|
||||
// &self,
|
||||
// map: &mut NamespaceGuard,
|
||||
// output: &mut ParserOutput,
|
||||
// ) -> Option<FnIdent> {
|
||||
// let header = self.header.as_ref()?;
|
||||
// let name = header.name.as_ref()?;
|
||||
// let args = header
|
||||
// .args
|
||||
// .iter()
|
||||
// .map(|a| {
|
||||
// // a.lower(map, output).unwrap_or(VarDef {
|
||||
// // name: "{error}".to_string(),
|
||||
// // origin: Origin::File(a.span),
|
||||
// // ty: Type::Error,
|
||||
// // })
|
||||
// })
|
||||
// .collect();
|
||||
// // let ret = match &header.ret {
|
||||
// // Some(ty) => ty.lower(map, output),
|
||||
// // None => Type::Concrete(BuiltinType::Unit.id()),
|
||||
// // };
|
||||
// let ret = Type::Concrete(BuiltinType::Unit.id());
|
||||
// Some(map.def_fn(FnDef {
|
||||
// name: name.to_string(),
|
||||
// origin: Origin::File(self.header.span),
|
||||
// args,
|
||||
// ret,
|
||||
// }))
|
||||
// }
|
||||
// pub fn lower_body(&self, map: &mut NamespaceGuard, output: &mut ParserOutput) -> Function {
|
||||
// let mut instructions = Instructions::new();
|
||||
// let mut ctx = FnLowerCtx {
|
||||
// instructions: &mut instructions,
|
||||
// map,
|
||||
// output,
|
||||
// span: self.body.span,
|
||||
// };
|
||||
// self.body.lower(&mut ctx);
|
||||
// Function::new(instructions)
|
||||
// }
|
||||
// }
|
||||
|
||||
pub struct FnLowerCtx<'a, 'n> {
|
||||
pub map: &'a mut NamespaceGuard<'n>,
|
||||
pub instructions: &'a mut Instructions,
|
||||
pub instructions: &'a mut IRInstructions,
|
||||
pub output: &'a mut ParserOutput,
|
||||
pub span: FileSpan,
|
||||
}
|
||||
|
||||
impl<'a, 'n> FnLowerCtx<'a, 'n> {
|
||||
pub fn get(&self, name: &str) -> Option<Idents> {
|
||||
self.map.get(name)
|
||||
impl<'n> FnLowerCtx<'_, 'n> {
|
||||
pub fn span<'b>(&'b mut self, span: FileSpan) -> FnLowerCtx<'b, 'n> {
|
||||
FnLowerCtx {
|
||||
map: self.map,
|
||||
instructions: self.instructions,
|
||||
output: self.output,
|
||||
span,
|
||||
}
|
||||
}
|
||||
pub fn get(&mut self, node: &Node<parser::PIdent>) -> Option<Idents> {
|
||||
let name = node.inner.as_ref()?;
|
||||
let res = self.map.get(name);
|
||||
if res.is_none() {
|
||||
self.err_at(node.span, format!("Identifier '{}' not found", name));
|
||||
}
|
||||
res
|
||||
}
|
||||
pub fn get_var(&mut self, node: &Node<parser::PIdent>) -> Option<VarID> {
|
||||
let ids = self.get(node)?;
|
||||
if ids.var.is_none() {
|
||||
self.err_at(
|
||||
node.span,
|
||||
format!(
|
||||
"Variable '{}' not found; Type found but cannot be used here",
|
||||
node.inner.as_ref()?
|
||||
),
|
||||
);
|
||||
}
|
||||
ids.var
|
||||
}
|
||||
pub fn err(&mut self, msg: String) {
|
||||
self.output.err(ParserMsg::from_span(self.span, msg))
|
||||
}
|
||||
pub fn temp(&mut self, ty: Type) -> VarIdent {
|
||||
pub fn err_at(&mut self, span: FileSpan, msg: String) {
|
||||
self.output.err(ParserMsg::from_span(span, msg))
|
||||
}
|
||||
pub fn temp(&mut self, ty: Type) -> VarID {
|
||||
self.map.temp_var(self.span, ty)
|
||||
}
|
||||
pub fn push(&mut self, i: Instruction) {
|
||||
pub fn push(&mut self, i: IRUInstruction) {
|
||||
self.instructions.push(i);
|
||||
}
|
||||
pub fn sub<'b>(&'b mut self) -> FnLowerCtx<'b, 'n> {
|
||||
|
||||
@@ -1,12 +1,30 @@
|
||||
mod asm;
|
||||
mod block;
|
||||
mod def;
|
||||
mod expr;
|
||||
mod func;
|
||||
mod module;
|
||||
mod arch;
|
||||
|
||||
use super::*;
|
||||
use block::*;
|
||||
use def::*;
|
||||
use expr::*;
|
||||
use func::*;
|
||||
use module::*;
|
||||
|
||||
pub use func::FnLowerCtx;
|
||||
|
||||
pub trait FnLowerable {
|
||||
type Output;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<Self::Output>;
|
||||
}
|
||||
|
||||
impl<T: FnLowerable> FnLowerable for Node<T> {
|
||||
type Output = T::Output;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<T::Output> {
|
||||
self.as_ref()?.lower(&mut ctx.span(self.span))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: FnLowerable> FnLowerable for Box<T> {
|
||||
type Output = T::Output;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<T::Output> {
|
||||
self.as_ref().lower(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use crate::ir::NamespaceGuard;
|
||||
|
||||
use super::{Module, ParserOutput};
|
||||
use super::{PModule, ParserOutput};
|
||||
|
||||
impl Module {
|
||||
impl PModule {
|
||||
pub fn lower(&self, map: &mut NamespaceGuard, output: &mut ParserOutput) {
|
||||
let mut fns = Vec::new();
|
||||
for f in &self.functions {
|
||||
@@ -13,8 +13,10 @@ impl Module {
|
||||
}
|
||||
}
|
||||
for (f, id) in self.functions.iter().zip(fns) {
|
||||
if let (Some(res), Some(id)) = (f.lower_body(map, output), id) {
|
||||
map.write_fn(id, res);
|
||||
if let Some(id) = id {
|
||||
if let Some(res) = f.lower_body(id, map, output) {
|
||||
map.write_fn(id, res);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user