a ton of stuff idk more ir work

This commit is contained in:
2024-10-22 02:30:50 -04:00
parent 14a4fb1ff9
commit 87f755b763
46 changed files with 1967 additions and 540 deletions
+58
View File
@@ -0,0 +1,58 @@
use crate::ir::Instruction;
use super::{Block, ExprResult, FnLowerCtx, Node, Statement};
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> {
let ctx = &mut ctx.sub();
for statement in &self.statements {
statement.lower(ctx);
}
self.result.as_ref()?.lower(ctx)
}
}
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> {
match self {
super::Statement::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!(),
}
}
None
}
super::Statement::Return(e) => {
let res = e.lower(ctx)?;
match res {
ExprResult::Var(v) => ctx.push(Instruction::Ret { src: v }),
_ => todo!(),
}
None
}
super::Statement::Expr(e) => e.lower(ctx),
}
}
}
+59
View File
@@ -0,0 +1,59 @@
use crate::ir::{FileSpan, NamespaceGuard, Origin, Type, VarDef};
use super::{Node, ParserMsg, ParserOutput, Type as PType, VarDef as PVarDef};
impl Node<PVarDef> {
pub fn lower(
&self,
namespace: &mut NamespaceGuard,
output: &mut ParserOutput,
) -> Option<VarDef> {
let s = self.as_ref()?;
let name = s.name.as_ref()?.val().clone();
let ty = match &s.ty {
Some(ty) => ty.lower(namespace, output),
None => Type::Infer,
};
Some(VarDef {
name,
ty,
origin: Origin::File(self.span),
})
}
}
impl Node<PType> {
pub fn lower(&self, namespace: &mut NamespaceGuard, output: &mut ParserOutput) -> Type {
self.as_ref()
.map(|t| t.lower(namespace, output, self.span))
.unwrap_or(Type::Error)
}
}
impl PType {
pub fn lower(
&self,
namespace: &mut NamespaceGuard,
output: &mut ParserOutput,
span: FileSpan,
) -> Type {
match namespace.get(&self.name).map(|ids| ids.ty).flatten() {
Some(id) => {
if self.args.is_empty() {
Type::Concrete(id)
} else {
let args = self
.args
.iter()
.map(|n| n.lower(namespace, output))
.collect();
Type::Generic { base: id, args }
}
}
None => {
output.err(ParserMsg::from_span(span, "Type not found".to_string()));
Type::Error
}
}
}
}
+136
View File
@@ -0,0 +1,136 @@
use super::{func::FnLowerCtx, Expr as PExpr, Node, UnaryOp};
use crate::ir::{FnIdent, Instruction, Type, VarIdent, VarOrFnIdent};
impl PExpr {
pub fn lower(&self, ctx: &mut FnLowerCtx) -> Option<ExprResult> {
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 => {
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::BinaryOp(op, e1, e2) => {
let res1 = e1.lower(ctx)?;
let res2 = e2.lower(ctx)?;
op.traitt();
todo!();
}
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());
return None;
}
},
UnaryOp::Not => todo!(),
}
}
PExpr::Block(b) => b.lower(ctx)?,
PExpr::AsmBlock(b) => {
ctx.push(Instruction::AsmBlock {
instructions: b.as_ref()?.instructions.clone(),
});
return None;
}
PExpr::Call(e, args) => {
let fe = 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;
}
}
}
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),
}
+101
View File
@@ -0,0 +1,101 @@
use super::{Function as PFunction, Node, ParserMsg, ParserOutput};
use crate::ir::{
BuiltinType, FileSpan, FnDef, FnIdent, Function, Idents, Instruction, Instructions,
NamespaceGuard, Origin, Type, VarDef, VarIdent,
};
impl Node<PFunction> {
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> {
if let Some(f) = self.as_ref() {
Some(f.lower_body(map, output))
} else {
None
}
}
}
impl PFunction {
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()),
};
// ignoring self var for now
Some(map.def_fn(FnDef {
name: name.val().clone(),
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,
};
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!(),
}
}
Function::new(instructions)
}
}
pub struct FnLowerCtx<'a, 'n> {
pub map: &'a mut NamespaceGuard<'n>,
pub instructions: &'a mut Instructions,
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)
}
pub fn err(&mut self, msg: String) {
self.output.err(ParserMsg::from_span(self.span, msg))
}
pub fn temp(&mut self, ty: Type) -> VarIdent {
self.map.temp_var(self.span, ty)
}
pub fn push(&mut self, i: Instruction) {
self.instructions.push(i);
}
pub fn sub<'b>(&'b mut self) -> FnLowerCtx<'b, 'n> {
FnLowerCtx {
map: self.map,
instructions: self.instructions,
output: self.output,
span: self.span,
}
}
}
+12
View File
@@ -0,0 +1,12 @@
mod block;
mod def;
mod expr;
mod func;
mod module;
use super::*;
use block::*;
use def::*;
use expr::*;
use func::*;
use module::*;
+21
View File
@@ -0,0 +1,21 @@
use crate::ir::NamespaceGuard;
use super::{Module, ParserOutput};
impl Module {
pub fn lower(&self, map: &mut NamespaceGuard, output: &mut ParserOutput) {
let mut fns = Vec::new();
for f in &self.functions {
if let Some(id) = f.lower_header(map, output) {
fns.push(Some(id));
} else {
fns.push(None)
}
}
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);
}
}
}
}