rework typed_ir to have flat expressions
This commit is contained in:
parent
b71f9f09ae
commit
a2cca95dbd
|
@ -1,7 +1,7 @@
|
|||
comb comparator (
|
||||
a: Logic<8>,
|
||||
b: Logic<8>
|
||||
) -> Logic
|
||||
) -> Logic<1>
|
||||
{
|
||||
~reduce_or(a ^ b)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
comb identity (
|
||||
a: Logic
|
||||
) -> Logic
|
||||
a: Logic<5>
|
||||
) -> Logic<5>
|
||||
{
|
||||
a
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use std::cell::Cell;
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
|
||||
use super::parser;
|
||||
use super::parser::block_expression::BlockExpr;
|
||||
|
@ -122,20 +122,32 @@ impl Context {
|
|||
}
|
||||
}
|
||||
|
||||
fn type_expression(
|
||||
fn intern_expression(
|
||||
&self,
|
||||
exprs: &mut HashMap<typed_ir::ExprId, typed_ir::Expr>,
|
||||
expr: typed_ir::Expr,
|
||||
) -> typed_ir::ExprId {
|
||||
let expr_id = expr.id;
|
||||
exprs.insert(expr.id, expr);
|
||||
expr_id
|
||||
}
|
||||
|
||||
fn type_expression(
|
||||
&mut self,
|
||||
exprs: &mut HashMap<typed_ir::ExprId, typed_ir::Expr>,
|
||||
expr: &parser::expression::Expression,
|
||||
) -> Result<typed_ir::Expr, CompileError> {
|
||||
) -> Result<typed_ir::ExprId, CompileError> {
|
||||
use parser::expression::Expression;
|
||||
let id = typed_ir::ExprId(self.ids.next() as u32);
|
||||
let t_expr = match expr {
|
||||
Expression::Path(name) => {
|
||||
let signal = self.try_get_signal(name)?;
|
||||
typed_ir::Expr {
|
||||
let this_expr = typed_ir::Expr {
|
||||
id,
|
||||
kind: typed_ir::ExprKind::Path(signal.id),
|
||||
typ: signal.typ,
|
||||
}
|
||||
};
|
||||
self.intern_expression(exprs, this_expr)
|
||||
}
|
||||
Expression::Literal(lit) => {
|
||||
let data = match lit.kind {
|
||||
|
@ -144,15 +156,16 @@ impl Context {
|
|||
self.types.make_const_u32(width, val as u32)
|
||||
}
|
||||
};
|
||||
typed_ir::Expr {
|
||||
let this_expr = typed_ir::Expr {
|
||||
id,
|
||||
kind: typed_ir::ExprKind::Literal(data),
|
||||
typ: self.types.primitives.infer,
|
||||
}
|
||||
};
|
||||
self.intern_expression(exprs, this_expr)
|
||||
}
|
||||
Expression::UnOp(op) => {
|
||||
let a = self.type_expression(&op.a)?;
|
||||
typed_ir::Expr {
|
||||
let a = self.type_expression(exprs, &op.a)?;
|
||||
let this_expr = typed_ir::Expr {
|
||||
id,
|
||||
kind: typed_ir::ExprKind::Call(typed_ir::Call {
|
||||
called: self.callables.builtins.bitnot,
|
||||
|
@ -160,11 +173,15 @@ impl Context {
|
|||
genargs: vec![],
|
||||
}),
|
||||
typ: self.types.primitives.infer,
|
||||
}
|
||||
};
|
||||
self.intern_expression(exprs, this_expr)
|
||||
}
|
||||
Expression::BinOp(op) => {
|
||||
let (a, b) = (self.type_expression(&op.a)?, self.type_expression(&op.b)?);
|
||||
typed_ir::Expr {
|
||||
let (a, b) = (
|
||||
self.type_expression(exprs, &op.a)?,
|
||||
self.type_expression(exprs, &op.b)?,
|
||||
);
|
||||
let this_expr = typed_ir::Expr {
|
||||
id,
|
||||
kind: typed_ir::ExprKind::Call(typed_ir::Call {
|
||||
called: self.callables.builtins.xor,
|
||||
|
@ -172,13 +189,14 @@ impl Context {
|
|||
genargs: vec![],
|
||||
}),
|
||||
typ: self.types.primitives.infer,
|
||||
}
|
||||
};
|
||||
self.intern_expression(exprs, this_expr)
|
||||
}
|
||||
Expression::Call(call) => {
|
||||
let args_resolved = call
|
||||
.args
|
||||
.iter()
|
||||
.map(|expr| self.type_expression(expr))
|
||||
.map(|expr| self.type_expression(exprs, expr))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let called = self.try_get_callable(call.name.fragment())?;
|
||||
let called_callable = self.callables.get(called);
|
||||
|
@ -187,13 +205,13 @@ impl Context {
|
|||
received: args_resolved.len(),
|
||||
expected: called_callable.argcount(),
|
||||
}));
|
||||
}
|
||||
};
|
||||
let genargs_resolved = called_callable
|
||||
.genargs
|
||||
.iter()
|
||||
.map(|genarg| genarg.1)
|
||||
.collect();
|
||||
typed_ir::Expr {
|
||||
let this_expr = typed_ir::Expr {
|
||||
id,
|
||||
kind: typed_ir::ExprKind::Call(typed_ir::Call {
|
||||
called,
|
||||
|
@ -201,28 +219,43 @@ impl Context {
|
|||
genargs: genargs_resolved,
|
||||
}),
|
||||
typ: self.types.primitives.infer,
|
||||
}
|
||||
};
|
||||
self.intern_expression(exprs, this_expr)
|
||||
}
|
||||
Expression::BlockExpr(block) => match &**block {
|
||||
BlockExpr::IfElse(_) => todo!(),
|
||||
BlockExpr::Match(match_) => {
|
||||
let expr = self.type_expression(&match_.expr)?;
|
||||
let expr = self.type_expression(exprs, &match_.expr)?;
|
||||
let arms = match_
|
||||
.arms
|
||||
.iter()
|
||||
.map(|(cond, val)| {
|
||||
Ok((self.type_expression(cond)?, self.type_expression(val)?))
|
||||
Ok((
|
||||
self.type_expression(exprs, cond)?,
|
||||
self.type_expression(exprs, val)?,
|
||||
))
|
||||
})
|
||||
.collect::<Result<_, _>>()?;
|
||||
let typed = typed_ir::Match { expr, arms };
|
||||
typed_ir::Expr {
|
||||
let this_expr = typed_ir::Expr {
|
||||
id,
|
||||
kind: typed_ir::ExprKind::Match(Box::new(typed)),
|
||||
typ: self.types.primitives.infer,
|
||||
}
|
||||
};
|
||||
self.intern_expression(exprs, this_expr)
|
||||
}
|
||||
BlockExpr::Block(block) => {
|
||||
todo!("expression blocks not representable in typed ir yet")
|
||||
// TODO: we need to find some way of resolving a name to an expression
|
||||
todo!("can not convert blocks to typed_ir yet");
|
||||
for (name, expr) in &block.assignments {
|
||||
let signal = typed_ir::Signal {
|
||||
id: typed_ir::DefId(self.ids.next() as u32),
|
||||
typ: self.types.primitives.infer,
|
||||
};
|
||||
// TODO: need to add this signal to the block from here, somehow
|
||||
self.signals.insert(name.span().to_string(), signal);
|
||||
}
|
||||
self.type_expression(exprs, &block.value)?
|
||||
}
|
||||
},
|
||||
Expression::StructInit(_) => todo!("structure initialization"),
|
||||
|
@ -247,8 +280,9 @@ impl Context {
|
|||
let sig_typename = &port.net.typ;
|
||||
let mut sig_type = self.try_get_type(sig_typename.name.fragment())?;
|
||||
if let Some(arg) = &sig_typename.generics {
|
||||
let elab_expr = self.type_expression(arg)?;
|
||||
let elab_val = self.eval_expression(&elab_expr)?;
|
||||
let mut exprs = Default::default();
|
||||
let elab_expr = self.type_expression(&mut exprs, arg)?;
|
||||
let elab_val = self.eval_expression(exprs.get(&elab_expr).unwrap())?;
|
||||
sig_type = self
|
||||
.types
|
||||
.parameterize(sig_type, &[types::GenericArg::Elab(elab_val)])
|
||||
|
@ -294,11 +328,14 @@ impl Context {
|
|||
}
|
||||
}
|
||||
|
||||
let root_expr = self.type_expression(&comb.expr)?;
|
||||
let mut exprs = Default::default();
|
||||
|
||||
let root_expr = self.type_expression(&mut exprs, &comb.expr)?;
|
||||
|
||||
Ok(typed_ir::Body {
|
||||
signature: callable_id,
|
||||
signals,
|
||||
exprs,
|
||||
expr: root_expr,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -4,13 +4,18 @@ use super::{make_pubid, CompileError, Context};
|
|||
use crate::rtlil;
|
||||
use crate::rtlil::RtlilWrite;
|
||||
|
||||
fn wire_for_expr(expr: typed_ir::ExprId) -> rtlil::SigSpec {
|
||||
rtlil::SigSpec::Wire(format!("$_expr_{}", expr.0))
|
||||
}
|
||||
|
||||
fn lower_expression(
|
||||
ctx: &Context,
|
||||
module: &mut rtlil::Module,
|
||||
body: &typed_ir::Body,
|
||||
expr: &typed_ir::Expr,
|
||||
) -> Result<rtlil::SigSpec, CompileError> {
|
||||
let expr_width = ctx.types.get_width(expr.typ).expect("signal needs width");
|
||||
let expr_wire_name = format!("$_sig_{}", expr.id.0);
|
||||
let expr_wire_name = format!("$_expr_{}", expr.id.0);
|
||||
let expr_wire = rtlil::Wire::new(expr_wire_name.clone(), expr_width, None);
|
||||
module.add_wire(expr_wire);
|
||||
match &expr.kind {
|
||||
|
@ -19,15 +24,21 @@ fn lower_expression(
|
|||
let args_resolved = call
|
||||
.args
|
||||
.iter()
|
||||
.map(|expr| lower_expression(ctx, module, expr))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
.map(|expr| wire_for_expr(*expr))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let args: Vec<_> = call
|
||||
.args
|
||||
.iter()
|
||||
.map(|expr_id| body.exprs.get(expr_id).unwrap())
|
||||
.collect();
|
||||
|
||||
let callable = ctx.callables.get(call.called);
|
||||
let cell_id = module.make_genid(callable.name());
|
||||
|
||||
if call.called == ctx.callables.builtins.xor {
|
||||
let a_width = ctx.types.get_width(call.args[0].typ).unwrap();
|
||||
let b_width = ctx.types.get_width(call.args[1].typ).unwrap();
|
||||
let a_width = ctx.types.get_width(args[0].typ).unwrap();
|
||||
let b_width = ctx.types.get_width(args[1].typ).unwrap();
|
||||
let y_width = ctx.types.get_width(expr.typ).unwrap();
|
||||
let mut cell = rtlil::Cell::new(&cell_id, "$xor");
|
||||
cell.add_param("\\A_SIGNED", "0");
|
||||
|
@ -40,7 +51,7 @@ fn lower_expression(
|
|||
cell.add_connection("\\Y", &rtlil::SigSpec::Wire(expr_wire_name.clone()));
|
||||
module.add_cell(cell);
|
||||
} else if call.called == ctx.callables.builtins.reduce_or {
|
||||
let a_width = ctx.types.get_width(call.args[0].typ).unwrap();
|
||||
let a_width = ctx.types.get_width(args[0].typ).unwrap();
|
||||
let y_width = ctx.types.get_width(expr.typ).unwrap();
|
||||
let mut cell = rtlil::Cell::new(&cell_id, "$reduce_or");
|
||||
cell.add_param("\\A_SIGNED", "0");
|
||||
|
@ -50,7 +61,7 @@ fn lower_expression(
|
|||
cell.add_connection("\\Y", &rtlil::SigSpec::Wire(expr_wire_name.clone()));
|
||||
module.add_cell(cell);
|
||||
} else if call.called == ctx.callables.builtins.bitnot {
|
||||
let a_width = ctx.types.get_width(call.args[0].typ).unwrap();
|
||||
let a_width = ctx.types.get_width(args[0].typ).unwrap();
|
||||
let y_width = ctx.types.get_width(expr.typ).unwrap();
|
||||
let mut cell = rtlil::Cell::new(&cell_id, "$not");
|
||||
cell.add_param("\\A_SIGNED", "0");
|
||||
|
@ -75,11 +86,11 @@ fn lower_expression(
|
|||
.iter()
|
||||
.map(|(pat, val)| {
|
||||
Ok((
|
||||
lower_expression(ctx, module, pat)?,
|
||||
wire_for_expr(*pat),
|
||||
rtlil::CaseRule {
|
||||
assign: vec![(
|
||||
rtlil::SigSpec::Wire(expr_wire_name.clone()),
|
||||
lower_expression(ctx, module, val)?,
|
||||
wire_for_expr(*val),
|
||||
)],
|
||||
switches: vec![],
|
||||
},
|
||||
|
@ -88,7 +99,7 @@ fn lower_expression(
|
|||
.collect::<Result<Vec<_>, CompileError>>()
|
||||
.unwrap();
|
||||
let root_switch = rtlil::SwitchRule {
|
||||
signal: lower_expression(ctx, module, &match_.expr)?,
|
||||
signal: wire_for_expr(match_.expr),
|
||||
cases,
|
||||
};
|
||||
let root_case = rtlil::CaseRule {
|
||||
|
@ -125,11 +136,15 @@ fn lower_comb(
|
|||
module.add_wire(rtlil::Wire::new(
|
||||
ret_id.clone(),
|
||||
ctx.types
|
||||
.get_width(block.expr.typ)
|
||||
.get_width(block.exprs.get(&block.expr).unwrap().typ)
|
||||
.expect("signal has no size"),
|
||||
Some(rtlil::PortOption::Output(block.signals.len() as i32)),
|
||||
));
|
||||
let out_sig = lower_expression(ctx, module, &block.expr)?;
|
||||
for (_, expr) in &block.exprs {
|
||||
let expr_wire = lower_expression(ctx, module, block, &expr)?;
|
||||
module.add_connection(&wire_for_expr(expr.id), &expr_wire);
|
||||
}
|
||||
let out_sig = wire_for_expr(block.expr);
|
||||
module.add_connection(&rtlil::SigSpec::Wire(ret_id), &out_sig);
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -5,9 +5,9 @@ impl Context {
|
|||
pub fn pretty_typed_block(
|
||||
&self,
|
||||
w: &mut dyn std::fmt::Write,
|
||||
block: &typed_ir::Body,
|
||||
body: &typed_ir::Body,
|
||||
) -> std::fmt::Result {
|
||||
let callsig = self.callables.get(block.signature);
|
||||
let callsig = self.callables.get(body.signature);
|
||||
{
|
||||
// TODO: ugly copy paste job
|
||||
let args = callsig
|
||||
|
@ -36,12 +36,15 @@ impl Context {
|
|||
args.join(", ")
|
||||
)?;
|
||||
}
|
||||
for sig in &block.signals {
|
||||
for sig in &body.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)?;
|
||||
for (_, expr) in &body.exprs {
|
||||
self.pretty_typed_expr(w, &expr)?;
|
||||
}
|
||||
writeln!(w, "return _{}", body.expr.0)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -61,10 +64,7 @@ impl Context {
|
|||
let args = call
|
||||
.args
|
||||
.iter()
|
||||
.map(|arg| {
|
||||
self.pretty_typed_expr(w, arg)?;
|
||||
Ok(format!("_{}", arg.id.0))
|
||||
})
|
||||
.map(|arg| Ok(format!("_{}", arg.0)))
|
||||
.collect::<Result<Vec<_>, std::fmt::Error>>()?;
|
||||
let callable = self.callables.get(call.called);
|
||||
let genargs = call
|
||||
|
@ -84,21 +84,12 @@ impl Context {
|
|||
)
|
||||
}
|
||||
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))
|
||||
})
|
||||
.map(|(pat, val)| Ok(format!(" _{} => _{}", pat.0, val.0)))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
format!(
|
||||
"match (_{}) {{\n{}\n}}",
|
||||
&match_.expr.id.0,
|
||||
arms.join(",\n")
|
||||
)
|
||||
format!("match (_{}) {{\n{}\n}}", &match_.expr.0, arms.join(",\n"))
|
||||
}
|
||||
};
|
||||
let mut type_pretty = String::new();
|
||||
|
|
|
@ -1,87 +1,104 @@
|
|||
use super::typed_ir;
|
||||
use super::typed_ir::{Expr, ExprId, ExprKind};
|
||||
use super::types;
|
||||
use super::Context;
|
||||
use super::{CompileError, CompileErrorKind, Context};
|
||||
use std::collections::HashMap;
|
||||
|
||||
impl Context {
|
||||
pub fn infer_types(&mut self, mut block: typed_ir::Body) -> typed_ir::Body {
|
||||
let new_root = self.infer_expr_types(&block.expr);
|
||||
block.expr = new_root;
|
||||
block
|
||||
pub fn infer_types(&mut self, block: typed_ir::Body) -> typed_ir::Body {
|
||||
// TODO: ugly ugly hack
|
||||
let try_1 = self
|
||||
.infer_body_types(&block)
|
||||
.expect("could not infer types");
|
||||
let try_2 = self
|
||||
.infer_body_types(&try_1)
|
||||
.expect("could not infer types");
|
||||
self.infer_body_types(&try_2)
|
||||
.expect("could not infer types")
|
||||
}
|
||||
|
||||
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);
|
||||
pub fn infer_body_types(
|
||||
&mut self,
|
||||
body: &typed_ir::Body,
|
||||
) -> Result<typed_ir::Body, CompileError> {
|
||||
let mut new_exprs = HashMap::new();
|
||||
for (expr_id, expr) in &body.exprs {
|
||||
if self.types.is_fully_typed(expr.typ) {
|
||||
new_exprs.insert(*expr_id, expr.clone());
|
||||
continue;
|
||||
}
|
||||
match &expr.kind {
|
||||
ExprKind::Literal(lit) => {
|
||||
// TODO: don't try to overwrite the type of a literal
|
||||
let infres = self.types.infer_type(expr.typ, lit.typ);
|
||||
new_exprs.insert(*expr_id, expr.clone().with_type(lit.typ));
|
||||
}
|
||||
ExprKind::Path(_) => {
|
||||
new_exprs.insert(*expr_id, expr.clone());
|
||||
}
|
||||
ExprKind::Call(call) => {
|
||||
let called_def = self.callables.get(call.called);
|
||||
let param_types = called_def.args.iter().map(|param| param.1);
|
||||
|
||||
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<_> = called_def.genargs.iter().map(|a| a.1).collect();
|
||||
let inferred_args: Vec<_> = param_types
|
||||
.zip(&call.args)
|
||||
.map(|(param, arg)| {
|
||||
self.types
|
||||
.infer_type(param, body.exprs.get(arg).unwrap().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;
|
||||
if !genargs.is_empty() {
|
||||
// need to infer generic arguments
|
||||
for inf_res in inferred_args {
|
||||
match inf_res {
|
||||
types::InferenceResult::TypeVar(dbi, tvar, typ) => {
|
||||
assert_eq!(dbi, 0);
|
||||
// TODO: type check argument instead of just using it
|
||||
genargs[tvar as usize] = typ;
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
types::InferenceResult::Incompatible => todo!(),
|
||||
types::InferenceResult::Ambigous => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: HACKY HACKY HACK
|
||||
new_type = genargs[0];
|
||||
let ret_type = match self.types.infer_type(expr.typ, called_def.ret_type) {
|
||||
types::InferenceResult::TypeVar(dbi, tvar, typ) => {
|
||||
assert_eq!(dbi, 0);
|
||||
genargs[tvar as usize]
|
||||
}
|
||||
types::InferenceResult::First(typ) => typ,
|
||||
x => todo!("{x:?}"),
|
||||
};
|
||||
let new_expr = typed_ir::Expr {
|
||||
kind: typed_ir::ExprKind::Call(typed_ir::Call {
|
||||
genargs,
|
||||
..call.clone()
|
||||
}),
|
||||
typ: ret_type,
|
||||
..expr.clone()
|
||||
};
|
||||
new_exprs.insert(*expr_id, new_expr);
|
||||
}
|
||||
ExprKind::Match(match_) => {
|
||||
// TODO: hacky hacky hacky
|
||||
let res_type = body.exprs.get(&match_.arms.first().unwrap().1).unwrap().typ;
|
||||
let new_expr = expr.clone().with_type(res_type);
|
||||
new_exprs.insert(*expr_id, new_expr);
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
/*
|
||||
for (expr_id, expr) in &new_exprs {
|
||||
if !self.types.is_fully_typed(expr.typ) {
|
||||
return Err(CompileError::new(CompileErrorKind::TodoError("fail".to_owned())))
|
||||
}
|
||||
}
|
||||
*/
|
||||
let new_body = typed_ir::Body {
|
||||
exprs: new_exprs,
|
||||
..body.clone()
|
||||
};
|
||||
Ok(new_body)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
use super::callable::CallableId;
|
||||
use super::types::{ElabData, Type};
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Debug;
|
||||
|
||||
/// ID of a definition (e.g. variable, block, function)
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct DefId(pub u32);
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone, Copy, Hash, PartialEq, Eq)]
|
||||
pub struct ExprId(pub u32);
|
||||
|
||||
// more compact Debug impl
|
||||
|
@ -31,14 +32,14 @@ pub struct Expr {
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct Call {
|
||||
pub called: CallableId,
|
||||
pub args: Vec<Expr>,
|
||||
pub args: Vec<ExprId>,
|
||||
pub genargs: Vec<Type>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Match {
|
||||
pub expr: Expr,
|
||||
pub arms: Vec<(Expr, Expr)>,
|
||||
pub expr: ExprId,
|
||||
pub arms: Vec<(ExprId, ExprId)>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -60,7 +61,8 @@ pub struct Signal {
|
|||
pub struct Body {
|
||||
pub signature: CallableId,
|
||||
pub signals: Vec<Signal>,
|
||||
pub expr: Expr,
|
||||
pub exprs: HashMap<ExprId, Expr>,
|
||||
pub expr: ExprId,
|
||||
}
|
||||
|
||||
impl Expr {
|
||||
|
|
|
@ -5,7 +5,7 @@ use std::fmt::Debug;
|
|||
/// easier
|
||||
pub type Type = InternedType;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub struct InternedType(usize);
|
||||
|
||||
impl Debug for InternedType {
|
||||
|
@ -14,12 +14,12 @@ impl Debug for InternedType {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct TypeStruct {
|
||||
kind: TypeKind,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
enum TypeKind {
|
||||
/// Elaboration-time types
|
||||
ElabType(ElabKind),
|
||||
|
@ -34,23 +34,23 @@ enum TypeKind {
|
|||
TypeVar(u32, u32),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum Adt {
|
||||
Struct(Struct),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Struct {
|
||||
members: Vec<Type>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct ElabData {
|
||||
pub typ: Type,
|
||||
value: ElabValue,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
enum ElabValue {
|
||||
/// the value is not given and has to be inferred
|
||||
Infer,
|
||||
|
@ -58,14 +58,14 @@ enum ElabValue {
|
|||
Concrete(ElabValueData),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
enum ElabValueData {
|
||||
U32(u32),
|
||||
Bytes(Vec<u8>),
|
||||
}
|
||||
|
||||
/// Types that are only valid during Elaboration
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
enum ElabKind {
|
||||
/// general, unsized number type
|
||||
Num,
|
||||
|
@ -85,6 +85,8 @@ pub enum InferenceResult {
|
|||
Second(Type),
|
||||
/// A typevar was inferred
|
||||
TypeVar(u32, u32, Type),
|
||||
/// The types are equivalent
|
||||
Equivalent,
|
||||
/// The types were incompatible
|
||||
Incompatible,
|
||||
/// Neither of the types were complete
|
||||
|
@ -244,7 +246,7 @@ impl TypingContext {
|
|||
|
||||
fn is_fully_typed_kind(&self, kind: &TypeKind) -> bool {
|
||||
match kind {
|
||||
TypeKind::ElabType(_) => todo!(),
|
||||
TypeKind::ElabType(_) => true,
|
||||
TypeKind::Logic(data) => {
|
||||
matches!(data.value, ElabValue::Concrete(_))
|
||||
}
|
||||
|
|
|
@ -15,8 +15,8 @@ use crate::parser::{
|
|||
/// a block that is a single expression
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ExpressionBlock<'a> {
|
||||
assignments: Vec<(Token<'a>, Expression<'a>)>,
|
||||
value: Expression<'a>,
|
||||
pub assignments: Vec<(Token<'a>, Expression<'a>)>,
|
||||
pub value: Expression<'a>,
|
||||
}
|
||||
|
||||
/// an expression that contains a block
|
||||
|
|
|
@ -8,11 +8,11 @@ use super::{
|
|||
use nom::{
|
||||
branch::alt,
|
||||
bytes::complete::{is_not, tag, take_until},
|
||||
character::complete::{anychar, digit1, line_ending},
|
||||
combinator::{consumed, map, recognize},
|
||||
character::complete::{alpha1, anychar, digit1, line_ending},
|
||||
combinator::{consumed, map, not, peek, recognize},
|
||||
error::ParseError,
|
||||
multi::many0,
|
||||
sequence::tuple,
|
||||
sequence::{terminated, tuple},
|
||||
InputTake,
|
||||
};
|
||||
use std::fmt;
|
||||
|
@ -227,16 +227,19 @@ fn lex_punctuation(input: Span) -> IResult<Span, Token> {
|
|||
|
||||
fn lex_keywords(input: Span) -> IResult<Span, Token> {
|
||||
map(
|
||||
consumed(alt((
|
||||
map(tag("module"), |_| TokenKind::Module),
|
||||
map(tag("assign"), |_| TokenKind::Assign),
|
||||
map(tag("match"), |_| TokenKind::Match),
|
||||
map(tag("proc"), |_| TokenKind::Proc),
|
||||
map(tag("comb"), |_| TokenKind::Comb),
|
||||
map(tag("state"), |_| TokenKind::State),
|
||||
map(tag("let"), |_| TokenKind::Let),
|
||||
map(tag("struct"), |_| TokenKind::Struct),
|
||||
))),
|
||||
terminated(
|
||||
consumed(alt((
|
||||
map(tag("module"), |_| TokenKind::Module),
|
||||
map(tag("assign"), |_| TokenKind::Assign),
|
||||
map(tag("match"), |_| TokenKind::Match),
|
||||
map(tag("proc"), |_| TokenKind::Proc),
|
||||
map(tag("comb"), |_| TokenKind::Comb),
|
||||
map(tag("state"), |_| TokenKind::State),
|
||||
map(tag("let"), |_| TokenKind::Let),
|
||||
map(tag("struct"), |_| TokenKind::Struct),
|
||||
))),
|
||||
peek(not(alt((alpha1, tag("_"))))),
|
||||
),
|
||||
|(span, kind)| Token::new(span, kind),
|
||||
)(input)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue