split up frontend file
This commit is contained in:
parent
86e3bf4d32
commit
5dca566cca
189
src/frontend.rs
189
src/frontend.rs
|
@ -8,6 +8,8 @@ pub use types::{Type, TypeStruct, TypingContext};
|
||||||
|
|
||||||
mod callable;
|
mod callable;
|
||||||
pub mod lowering;
|
pub mod lowering;
|
||||||
|
mod pretty_ir;
|
||||||
|
mod type_infer;
|
||||||
pub mod typed_ir;
|
pub mod typed_ir;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
|
|
||||||
|
@ -323,191 +325,4 @@ impl Context {
|
||||||
}
|
}
|
||||||
Ok(typed_module)
|
Ok(typed_module)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn infer_expr_types(&mut self, expr: &typed_ir::Expr) -> typed_ir::Expr {
|
|
||||||
if self.types.is_fully_typed(expr.typ) {
|
|
||||||
// there is nothing more to infer
|
|
||||||
return expr.clone();
|
|
||||||
}
|
|
||||||
match &expr.kind {
|
|
||||||
typed_ir::ExprKind::Literal(lit) => expr.clone().with_type(lit.typ),
|
|
||||||
// we can not see beyond this expression right now
|
|
||||||
typed_ir::ExprKind::Path(_) => expr.clone(),
|
|
||||||
typed_ir::ExprKind::Call(call) => {
|
|
||||||
let args_typed: Vec<_> = call
|
|
||||||
.args
|
|
||||||
.iter()
|
|
||||||
.map(|ex| self.infer_expr_types(ex))
|
|
||||||
.collect();
|
|
||||||
let callee_def = self.callables.get(call.called);
|
|
||||||
|
|
||||||
let param_types: Vec<_> = callee_def.args.iter().map(|param| param.1).collect();
|
|
||||||
let inferred_args: Vec<_> = param_types
|
|
||||||
.iter()
|
|
||||||
.zip(&args_typed)
|
|
||||||
.map(|(param, arg)| self.types.infer_type(*param, arg.typ))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let mut genargs: Vec<_> = callee_def.genargs.iter().map(|a| a.1).collect();
|
|
||||||
|
|
||||||
let mut new_type = callee_def.ret_type;
|
|
||||||
|
|
||||||
if !genargs.is_empty() {
|
|
||||||
// need to infer generic arguments
|
|
||||||
for inf_res in inferred_args {
|
|
||||||
match inf_res {
|
|
||||||
types::InferenceResult::First(_) => todo!(),
|
|
||||||
types::InferenceResult::Second(_) => todo!(),
|
|
||||||
types::InferenceResult::TypeVar(dbi, tvar, typ) => {
|
|
||||||
assert_eq!(dbi, 0);
|
|
||||||
// TODO: type check argument instead of just using it
|
|
||||||
genargs[tvar as usize] = typ;
|
|
||||||
}
|
|
||||||
types::InferenceResult::Incompatible => todo!(),
|
|
||||||
types::InferenceResult::Ambigous => todo!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: HACKY HACKY HACK
|
|
||||||
new_type = genargs[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut new_expr = expr.clone();
|
|
||||||
new_expr.typ = new_type;
|
|
||||||
new_expr.kind = typed_ir::ExprKind::Call(typed_ir::Call {
|
|
||||||
called: call.called,
|
|
||||||
args: args_typed,
|
|
||||||
genargs,
|
|
||||||
});
|
|
||||||
new_expr
|
|
||||||
}
|
|
||||||
typed_ir::ExprKind::Match(match_) => {
|
|
||||||
let new_arms: Vec<_> = match_
|
|
||||||
.arms
|
|
||||||
.iter()
|
|
||||||
.map(|(pat, val)| (self.infer_expr_types(pat), self.infer_expr_types(val)))
|
|
||||||
.collect();
|
|
||||||
// TODO: hacky hacky hacky
|
|
||||||
let res_type = new_arms.first().unwrap().1.typ;
|
|
||||||
let new_match = typed_ir::Match {
|
|
||||||
expr: self.infer_expr_types(&match_.expr),
|
|
||||||
arms: new_arms,
|
|
||||||
};
|
|
||||||
let mut new_expr = expr.clone().with_type(res_type);
|
|
||||||
new_expr.kind = typed_ir::ExprKind::Match(Box::new(new_match));
|
|
||||||
new_expr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn infer_types(&mut self, mut block: typed_ir::Block) -> typed_ir::Block {
|
|
||||||
let new_root = self.infer_expr_types(&block.expr);
|
|
||||||
block.expr = new_root;
|
|
||||||
block
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pretty_typed_block(
|
|
||||||
&self,
|
|
||||||
w: &mut dyn std::fmt::Write,
|
|
||||||
block: &typed_ir::Block,
|
|
||||||
) -> std::fmt::Result {
|
|
||||||
let callsig = self.callables.get(block.signature);
|
|
||||||
{
|
|
||||||
// TODO: ugly copy paste job
|
|
||||||
let args = callsig
|
|
||||||
.args
|
|
||||||
.iter()
|
|
||||||
.map(|(_name, typ)| {
|
|
||||||
let mut out = String::new();
|
|
||||||
self.types.pretty_type(&mut out, *typ)?;
|
|
||||||
Ok(out)
|
|
||||||
})
|
|
||||||
.collect::<Result<Vec<String>, std::fmt::Error>>()?;
|
|
||||||
let genargs = callsig
|
|
||||||
.genargs
|
|
||||||
.iter()
|
|
||||||
.map(|(_name, typ)| {
|
|
||||||
let mut type_str = String::new();
|
|
||||||
self.types.pretty_type(&mut type_str, *typ)?;
|
|
||||||
Ok(type_str)
|
|
||||||
})
|
|
||||||
.collect::<Result<Vec<String>, std::fmt::Error>>()?;
|
|
||||||
writeln!(
|
|
||||||
w,
|
|
||||||
"block {}<{}>({})",
|
|
||||||
callsig.name(),
|
|
||||||
genargs.join(", "),
|
|
||||||
args.join(", ")
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
for sig in &block.signals {
|
|
||||||
let mut typ_pretty = String::new();
|
|
||||||
self.types.pretty_type(&mut typ_pretty, sig.typ)?;
|
|
||||||
writeln!(w, "sig_{}: {}", sig.id.0, typ_pretty)?
|
|
||||||
}
|
|
||||||
self.pretty_typed_expr(w, &block.expr)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pretty_typed_expr(
|
|
||||||
&self,
|
|
||||||
w: &mut dyn std::fmt::Write,
|
|
||||||
expr: &typed_ir::Expr,
|
|
||||||
) -> std::fmt::Result {
|
|
||||||
let expr_pretty = match &expr.kind {
|
|
||||||
typed_ir::ExprKind::Literal(lit) => {
|
|
||||||
let mut lit_str = String::new();
|
|
||||||
self.types.pretty_value(&mut lit_str, lit)?;
|
|
||||||
lit_str
|
|
||||||
}
|
|
||||||
typed_ir::ExprKind::Path(path) => format!("sig_{}", path.0),
|
|
||||||
typed_ir::ExprKind::Call(call) => {
|
|
||||||
let args = call
|
|
||||||
.args
|
|
||||||
.iter()
|
|
||||||
.map(|arg| {
|
|
||||||
self.pretty_typed_expr(w, arg)?;
|
|
||||||
Ok(format!("_{}", arg.id.0))
|
|
||||||
})
|
|
||||||
.collect::<Result<Vec<_>, std::fmt::Error>>()?;
|
|
||||||
let callable = self.callables.get(call.called);
|
|
||||||
let genargs = call
|
|
||||||
.genargs
|
|
||||||
.iter()
|
|
||||||
.map(|param| {
|
|
||||||
let mut type_str = String::new();
|
|
||||||
self.types.pretty_type(&mut type_str, *param)?;
|
|
||||||
Ok(type_str)
|
|
||||||
})
|
|
||||||
.collect::<Result<Vec<_>, std::fmt::Error>>()?;
|
|
||||||
format!(
|
|
||||||
"{}<{}>({})",
|
|
||||||
callable.name(),
|
|
||||||
genargs.join(", "),
|
|
||||||
args.join(", ")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
typed_ir::ExprKind::Match(match_) => {
|
|
||||||
self.pretty_typed_expr(w, &match_.expr)?;
|
|
||||||
let arms = match_
|
|
||||||
.arms
|
|
||||||
.iter()
|
|
||||||
.map(|(pat, val)| {
|
|
||||||
self.pretty_typed_expr(w, pat)?;
|
|
||||||
self.pretty_typed_expr(w, val)?;
|
|
||||||
Ok(format!(" _{} => _{}", pat.id.0, val.id.0))
|
|
||||||
})
|
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
|
||||||
format!(
|
|
||||||
"match (_{}) {{\n{}\n}}",
|
|
||||||
&match_.expr.id.0,
|
|
||||||
arms.join(",\n")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let mut type_pretty = String::new();
|
|
||||||
self.types.pretty_type(&mut type_pretty, expr.typ)?;
|
|
||||||
writeln!(w, "let _{}: {} = {}", expr.id.0, type_pretty, expr_pretty)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
use super::typed_ir;
|
||||||
|
use super::Context;
|
||||||
|
|
||||||
|
impl Context {
|
||||||
|
pub fn pretty_typed_block(
|
||||||
|
&self,
|
||||||
|
w: &mut dyn std::fmt::Write,
|
||||||
|
block: &typed_ir::Block,
|
||||||
|
) -> std::fmt::Result {
|
||||||
|
let callsig = self.callables.get(block.signature);
|
||||||
|
{
|
||||||
|
// TODO: ugly copy paste job
|
||||||
|
let args = callsig
|
||||||
|
.args
|
||||||
|
.iter()
|
||||||
|
.map(|(_name, typ)| {
|
||||||
|
let mut out = String::new();
|
||||||
|
self.types.pretty_type(&mut out, *typ)?;
|
||||||
|
Ok(out)
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<String>, std::fmt::Error>>()?;
|
||||||
|
let genargs = callsig
|
||||||
|
.genargs
|
||||||
|
.iter()
|
||||||
|
.map(|(_name, typ)| {
|
||||||
|
let mut type_str = String::new();
|
||||||
|
self.types.pretty_type(&mut type_str, *typ)?;
|
||||||
|
Ok(type_str)
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<String>, std::fmt::Error>>()?;
|
||||||
|
writeln!(
|
||||||
|
w,
|
||||||
|
"block {}<{}>({})",
|
||||||
|
callsig.name(),
|
||||||
|
genargs.join(", "),
|
||||||
|
args.join(", ")
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
for sig in &block.signals {
|
||||||
|
let mut typ_pretty = String::new();
|
||||||
|
self.types.pretty_type(&mut typ_pretty, sig.typ)?;
|
||||||
|
writeln!(w, "sig_{}: {}", sig.id.0, typ_pretty)?
|
||||||
|
}
|
||||||
|
self.pretty_typed_expr(w, &block.expr)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pretty_typed_expr(
|
||||||
|
&self,
|
||||||
|
w: &mut dyn std::fmt::Write,
|
||||||
|
expr: &typed_ir::Expr,
|
||||||
|
) -> std::fmt::Result {
|
||||||
|
let expr_pretty = match &expr.kind {
|
||||||
|
typed_ir::ExprKind::Literal(lit) => {
|
||||||
|
let mut lit_str = String::new();
|
||||||
|
self.types.pretty_value(&mut lit_str, lit)?;
|
||||||
|
lit_str
|
||||||
|
}
|
||||||
|
typed_ir::ExprKind::Path(path) => format!("sig_{}", path.0),
|
||||||
|
typed_ir::ExprKind::Call(call) => {
|
||||||
|
let args = call
|
||||||
|
.args
|
||||||
|
.iter()
|
||||||
|
.map(|arg| {
|
||||||
|
self.pretty_typed_expr(w, arg)?;
|
||||||
|
Ok(format!("_{}", arg.id.0))
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<_>, std::fmt::Error>>()?;
|
||||||
|
let callable = self.callables.get(call.called);
|
||||||
|
let genargs = call
|
||||||
|
.genargs
|
||||||
|
.iter()
|
||||||
|
.map(|param| {
|
||||||
|
let mut type_str = String::new();
|
||||||
|
self.types.pretty_type(&mut type_str, *param)?;
|
||||||
|
Ok(type_str)
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<_>, std::fmt::Error>>()?;
|
||||||
|
format!(
|
||||||
|
"{}<{}>({})",
|
||||||
|
callable.name(),
|
||||||
|
genargs.join(", "),
|
||||||
|
args.join(", ")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
typed_ir::ExprKind::Match(match_) => {
|
||||||
|
self.pretty_typed_expr(w, &match_.expr)?;
|
||||||
|
let arms = match_
|
||||||
|
.arms
|
||||||
|
.iter()
|
||||||
|
.map(|(pat, val)| {
|
||||||
|
self.pretty_typed_expr(w, pat)?;
|
||||||
|
self.pretty_typed_expr(w, val)?;
|
||||||
|
Ok(format!(" _{} => _{}", pat.id.0, val.id.0))
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
format!(
|
||||||
|
"match (_{}) {{\n{}\n}}",
|
||||||
|
&match_.expr.id.0,
|
||||||
|
arms.join(",\n")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let mut type_pretty = String::new();
|
||||||
|
self.types.pretty_type(&mut type_pretty, expr.typ)?;
|
||||||
|
writeln!(w, "let _{}: {} = {}", expr.id.0, type_pretty, expr_pretty)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
use super::typed_ir;
|
||||||
|
use super::types;
|
||||||
|
use super::Context;
|
||||||
|
|
||||||
|
impl Context {
|
||||||
|
pub fn infer_types(&mut self, mut block: typed_ir::Block) -> typed_ir::Block {
|
||||||
|
let new_root = self.infer_expr_types(&block.expr);
|
||||||
|
block.expr = new_root;
|
||||||
|
block
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn infer_expr_types(&mut self, expr: &typed_ir::Expr) -> typed_ir::Expr {
|
||||||
|
if self.types.is_fully_typed(expr.typ) {
|
||||||
|
// there is nothing more to infer
|
||||||
|
return expr.clone();
|
||||||
|
}
|
||||||
|
match &expr.kind {
|
||||||
|
typed_ir::ExprKind::Literal(lit) => expr.clone().with_type(lit.typ),
|
||||||
|
// we can not see beyond this expression right now
|
||||||
|
typed_ir::ExprKind::Path(_) => expr.clone(),
|
||||||
|
typed_ir::ExprKind::Call(call) => {
|
||||||
|
let args_typed: Vec<_> = call
|
||||||
|
.args
|
||||||
|
.iter()
|
||||||
|
.map(|ex| self.infer_expr_types(ex))
|
||||||
|
.collect();
|
||||||
|
let callee_def = self.callables.get(call.called);
|
||||||
|
|
||||||
|
let param_types: Vec<_> = callee_def.args.iter().map(|param| param.1).collect();
|
||||||
|
let inferred_args: Vec<_> = param_types
|
||||||
|
.iter()
|
||||||
|
.zip(&args_typed)
|
||||||
|
.map(|(param, arg)| self.types.infer_type(*param, arg.typ))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let mut genargs: Vec<_> = callee_def.genargs.iter().map(|a| a.1).collect();
|
||||||
|
|
||||||
|
let mut new_type = callee_def.ret_type;
|
||||||
|
|
||||||
|
if !genargs.is_empty() {
|
||||||
|
// need to infer generic arguments
|
||||||
|
for inf_res in inferred_args {
|
||||||
|
match inf_res {
|
||||||
|
types::InferenceResult::First(_) => todo!(),
|
||||||
|
types::InferenceResult::Second(_) => todo!(),
|
||||||
|
types::InferenceResult::TypeVar(dbi, tvar, typ) => {
|
||||||
|
assert_eq!(dbi, 0);
|
||||||
|
// TODO: type check argument instead of just using it
|
||||||
|
genargs[tvar as usize] = typ;
|
||||||
|
}
|
||||||
|
types::InferenceResult::Incompatible => todo!(),
|
||||||
|
types::InferenceResult::Ambigous => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: HACKY HACKY HACK
|
||||||
|
new_type = genargs[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut new_expr = expr.clone();
|
||||||
|
new_expr.typ = new_type;
|
||||||
|
new_expr.kind = typed_ir::ExprKind::Call(typed_ir::Call {
|
||||||
|
called: call.called,
|
||||||
|
args: args_typed,
|
||||||
|
genargs,
|
||||||
|
});
|
||||||
|
new_expr
|
||||||
|
}
|
||||||
|
typed_ir::ExprKind::Match(match_) => {
|
||||||
|
let new_arms: Vec<_> = match_
|
||||||
|
.arms
|
||||||
|
.iter()
|
||||||
|
.map(|(pat, val)| (self.infer_expr_types(pat), self.infer_expr_types(val)))
|
||||||
|
.collect();
|
||||||
|
// TODO: hacky hacky hacky
|
||||||
|
let res_type = new_arms.first().unwrap().1.typ;
|
||||||
|
let new_match = typed_ir::Match {
|
||||||
|
expr: self.infer_expr_types(&match_.expr),
|
||||||
|
arms: new_arms,
|
||||||
|
};
|
||||||
|
let mut new_expr = expr.clone().with_type(res_type);
|
||||||
|
new_expr.kind = typed_ir::ExprKind::Match(Box::new(new_match));
|
||||||
|
new_expr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue