futilehdl/src/frontend.rs

367 lines
13 KiB
Rust
Raw Permalink Normal View History

2022-02-06 22:19:55 +00:00
use std::cell::Cell;
use std::collections::{BTreeMap, HashMap};
2022-01-05 01:08:25 +00:00
2022-02-06 22:19:55 +00:00
use super::parser;
2022-04-04 19:40:08 +00:00
use super::parser::block_expression::BlockExpr;
2022-02-16 21:17:25 +00:00
pub use callable::{Callable, CallableContext, CallableId};
2022-02-15 20:32:55 +00:00
pub use types::{Type, TypeStruct, TypingContext};
mod callable;
2022-02-06 22:19:55 +00:00
pub mod lowering;
2022-04-05 14:08:10 +00:00
mod pretty_ir;
mod type_infer;
2022-01-30 22:54:19 +00:00
pub mod typed_ir;
2022-02-01 18:46:06 +00:00
pub mod types;
2022-01-04 22:05:25 +00:00
2022-02-15 20:32:55 +00:00
#[cfg(never)]
2022-02-06 22:19:55 +00:00
use crate::builtin_cells::get_builtins;
// pub use lowering::lower_module;
2022-01-04 22:05:25 +00:00
fn make_pubid(id: &str) -> String {
"\\".to_owned() + id
}
#[derive(Debug)]
pub enum CompileErrorKind {
2022-01-05 01:09:08 +00:00
UndefinedReference(String),
2022-01-14 14:32:00 +00:00
BadArgCount { received: usize, expected: usize },
2022-02-06 22:19:55 +00:00
TodoError(String),
2022-02-15 20:32:55 +00:00
TypeError { expected: Type, found: Type },
}
#[derive(Debug)]
pub struct CompileError {
kind: CompileErrorKind,
}
impl CompileError {
fn new(kind: CompileErrorKind) -> Self {
2022-01-05 01:09:08 +00:00
Self { kind }
}
}
2022-02-23 22:36:01 +00:00
#[derive(Debug)]
pub struct Module {
2022-04-05 14:42:30 +00:00
pub blocks: Vec<typed_ir::Body>,
2022-01-17 20:04:22 +00:00
}
2022-02-15 20:32:55 +00:00
pub struct Context {
2022-01-17 20:02:11 +00:00
/// map callable name to callable
2022-02-16 16:38:56 +00:00
callable_names: BTreeMap<String, CallableId>,
2022-02-16 21:17:25 +00:00
callables: CallableContext,
2022-02-15 20:32:55 +00:00
/// type names
typenames: BTreeMap<String, Type>,
types: TypingContext,
2022-01-17 20:02:11 +00:00
/// map signal name to Signal
2022-02-15 20:32:55 +00:00
signals: BTreeMap<String, typed_ir::Signal>,
2022-02-06 22:19:55 +00:00
/// incrementing counter for unique IDs
ids: Counter,
}
struct Counter(Cell<usize>);
impl Counter {
fn new() -> Counter {
Counter(Cell::new(0))
}
fn next(&self) -> usize {
let next = self.0.get() + 1;
self.0.set(next);
next
}
}
2022-01-04 22:05:25 +00:00
2022-02-15 20:32:55 +00:00
impl Context {
2022-02-06 22:19:55 +00:00
pub fn new() -> Self {
2022-02-16 21:17:25 +00:00
let mut tcx = TypingContext::new();
let ccx = CallableContext::new(&mut tcx);
let typenames = [
("Logic".to_string(), tcx.primitives.logic),
("Num".to_string(), tcx.primitives.elabnum),
]
.into();
let callable_names = [("reduce_or".to_string(), ccx.builtins.reduce_or)].into();
2022-02-06 22:19:55 +00:00
Context {
2022-02-16 21:17:25 +00:00
callables: ccx,
callable_names,
2022-02-06 22:19:55 +00:00
signals: BTreeMap::new(),
2022-02-16 21:17:25 +00:00
types: tcx,
typenames,
2022-02-06 22:19:55 +00:00
ids: Counter::new(),
}
}
2022-01-17 20:04:22 +00:00
2022-02-06 22:19:55 +00:00
fn try_get_signal(&self, signame: &str) -> Result<&typed_ir::Signal, CompileError> {
2022-02-15 20:32:55 +00:00
self.signals.get(signame).ok_or_else(|| {
2022-01-20 18:55:17 +00:00
CompileError::new(CompileErrorKind::UndefinedReference(signame.to_owned()))
})
2022-01-17 20:04:22 +00:00
}
2022-02-06 20:02:55 +00:00
2022-02-15 20:32:55 +00:00
fn try_get_type(&self, typename: &str) -> Result<Type, CompileError> {
2022-02-15 20:41:01 +00:00
self.typenames.get(typename).copied().ok_or_else(|| {
2022-02-06 20:02:55 +00:00
CompileError::new(CompileErrorKind::UndefinedReference(typename.to_owned()))
})
}
2022-01-17 20:04:22 +00:00
2022-02-16 16:38:56 +00:00
fn try_get_callable(&self, callname: &str) -> Result<CallableId, CompileError> {
self.callable_names.get(callname).copied().ok_or_else(|| {
2022-02-15 20:32:55 +00:00
CompileError::new(CompileErrorKind::UndefinedReference(callname.to_owned()))
})
}
2022-02-16 15:37:12 +00:00
fn eval_expression(&self, expr: &typed_ir::Expr) -> Result<types::ElabData, CompileError> {
match &expr.kind {
typed_ir::ExprKind::Literal(lit) => Ok(lit.clone()),
typed_ir::ExprKind::Path(_) => todo!("evaluate path"),
2022-04-04 19:40:08 +00:00
typed_ir::ExprKind::Call(_call) => todo!("evaluate call"),
typed_ir::ExprKind::Match(_) => todo!(),
2022-02-16 15:37:12 +00:00
}
}
fn intern_expression(
2022-02-06 22:19:55 +00:00
&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>,
2022-02-06 22:19:55 +00:00
expr: &parser::expression::Expression,
) -> Result<typed_ir::ExprId, CompileError> {
2022-02-15 20:32:55 +00:00
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)?;
let this_expr = typed_ir::Expr {
2022-02-15 20:32:55 +00:00
id,
kind: typed_ir::ExprKind::Path(signal.id),
typ: signal.typ,
};
self.intern_expression(exprs, this_expr)
2022-02-15 20:32:55 +00:00
}
2022-02-16 15:37:12 +00:00
Expression::Literal(lit) => {
2022-04-04 19:40:08 +00:00
let data = match lit.kind {
parser::expression::LiteralKind::Num(num) => self.types.make_elabnum_u32(num),
parser::expression::LiteralKind::Const(width, val) => {
self.types.make_const_u32(width, val as u32)
2022-02-16 15:37:12 +00:00
}
};
let this_expr = typed_ir::Expr {
2022-02-16 15:37:12 +00:00
id,
kind: typed_ir::ExprKind::Literal(data),
typ: self.types.primitives.infer,
};
self.intern_expression(exprs, this_expr)
2022-02-16 15:37:12 +00:00
}
Expression::UnOp(op) => {
let a = self.type_expression(exprs, &op.a)?;
let this_expr = typed_ir::Expr {
2022-02-16 15:37:12 +00:00
id,
2022-04-04 19:40:08 +00:00
kind: typed_ir::ExprKind::Call(typed_ir::Call {
2022-02-16 21:17:25 +00:00
called: self.callables.builtins.bitnot,
2022-02-16 15:37:12 +00:00
args: vec![a],
genargs: vec![],
2022-04-04 19:40:08 +00:00
}),
2022-02-16 15:37:12 +00:00
typ: self.types.primitives.infer,
};
self.intern_expression(exprs, this_expr)
2022-02-16 15:37:12 +00:00
}
2022-02-15 20:32:55 +00:00
Expression::BinOp(op) => {
let (a, b) = (
self.type_expression(exprs, &op.a)?,
self.type_expression(exprs, &op.b)?,
);
let this_expr = typed_ir::Expr {
2022-02-15 20:32:55 +00:00
id,
2022-04-04 19:40:08 +00:00
kind: typed_ir::ExprKind::Call(typed_ir::Call {
2022-02-16 21:17:25 +00:00
called: self.callables.builtins.xor,
2022-02-15 20:32:55 +00:00
args: vec![a, b],
genargs: vec![],
2022-04-04 19:40:08 +00:00
}),
2022-02-15 22:56:52 +00:00
typ: self.types.primitives.infer,
};
self.intern_expression(exprs, this_expr)
2022-02-15 20:32:55 +00:00
}
Expression::Call(call) => {
let args_resolved = call
.args
.iter()
.map(|expr| self.type_expression(exprs, expr))
2022-02-15 20:32:55 +00:00
.collect::<Result<Vec<_>, _>>()?;
2022-02-16 21:17:25 +00:00
let called = self.try_get_callable(call.name.fragment())?;
2022-02-18 11:59:53 +00:00
let called_callable = self.callables.get(called);
if args_resolved.len() != called_callable.argcount() {
return Err(CompileError::new(CompileErrorKind::BadArgCount {
received: args_resolved.len(),
expected: called_callable.argcount(),
}));
};
let genargs_resolved = called_callable
.genargs
.iter()
.map(|genarg| genarg.1)
.collect();
let this_expr = typed_ir::Expr {
2022-02-15 20:32:55 +00:00
id,
2022-04-04 19:40:08 +00:00
kind: typed_ir::ExprKind::Call(typed_ir::Call {
2022-02-16 21:17:25 +00:00
called,
2022-02-15 20:32:55 +00:00
args: args_resolved,
genargs: genargs_resolved,
2022-04-04 19:40:08 +00:00
}),
2022-02-15 22:56:52 +00:00
typ: self.types.primitives.infer,
};
self.intern_expression(exprs, this_expr)
2022-02-15 20:32:55 +00:00
}
2022-04-04 19:40:08 +00:00
Expression::BlockExpr(block) => match &**block {
BlockExpr::IfElse(_) => todo!(),
BlockExpr::Match(match_) => {
let expr = self.type_expression(exprs, &match_.expr)?;
2022-04-04 19:40:08 +00:00
let arms = match_
.arms
.iter()
.map(|(cond, val)| {
Ok((
self.type_expression(exprs, cond)?,
self.type_expression(exprs, val)?,
))
2022-04-04 19:40:08 +00:00
})
.collect::<Result<_, _>>()?;
let typed = typed_ir::Match { expr, arms };
let this_expr = typed_ir::Expr {
2022-04-04 19:40:08 +00:00
id,
kind: typed_ir::ExprKind::Match(Box::new(typed)),
typ: self.types.primitives.infer,
};
self.intern_expression(exprs, this_expr)
2022-04-04 19:40:08 +00:00
}
2022-04-05 12:40:47 +00:00
BlockExpr::Block(block) => {
// TODO: we need to find some way of resolving a name to an expression
todo!("can not convert blocks to typed_ir yet");
2022-08-07 16:14:55 +00:00
for (kind, 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)?
2022-04-05 12:40:47 +00:00
}
2022-04-04 19:40:08 +00:00
},
2022-04-05 12:52:56 +00:00
Expression::StructInit(_) => todo!("structure initialization"),
2022-02-06 22:19:55 +00:00
};
2022-02-15 20:32:55 +00:00
Ok(t_expr)
2022-01-17 18:20:51 +00:00
}
2022-02-23 22:36:01 +00:00
fn callable_from_block(
2022-02-06 22:19:55 +00:00
&mut self,
comb: &parser::comb::CombBlock,
2022-02-23 22:36:01 +00:00
) -> Result<CallableId, CompileError> {
let mut genargs = vec![];
2022-02-20 21:44:58 +00:00
for (idx, tvarname) in comb.genparams.iter().enumerate() {
let tvar = self.types.make_typevar(0, idx as u32);
2022-02-23 22:36:01 +00:00
// hacky workaround for no scopes
2022-02-20 21:44:58 +00:00
self.typenames.insert(tvarname.name.to_string(), tvar);
2022-02-23 22:36:01 +00:00
genargs.push((Some(tvarname.name.to_string()), tvar));
2022-02-20 21:44:58 +00:00
}
2022-02-23 22:36:01 +00:00
let mut args = vec![];
2022-02-06 22:19:55 +00:00
for port in comb.ports.iter() {
let sig_typename = &port.net.typ;
2022-02-16 15:37:12 +00:00
let mut sig_type = self.try_get_type(sig_typename.name.fragment())?;
if let Some(arg) = &sig_typename.generics {
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())?;
2022-02-16 15:37:12 +00:00
sig_type = self
.types
.parameterize(sig_type, &[types::GenericArg::Elab(elab_val)])
.unwrap();
}
2022-02-23 22:36:01 +00:00
args.push((Some(port.net.name.to_string()), sig_type));
}
let ret_typename = &comb.ret.name;
let ret_type = self.try_get_type(ret_typename.fragment())?;
let signature = Callable {
name: comb.name.to_string(),
args,
genargs,
ret_type,
};
let signature_id = self.callables.add(signature);
self.callable_names
.insert(comb.name.to_string(), signature_id);
Ok(signature_id)
}
fn type_comb(
&mut self,
comb: &parser::comb::CombBlock,
2022-04-05 14:42:30 +00:00
) -> Result<typed_ir::Body, CompileError> {
2022-02-23 22:36:01 +00:00
let mut signals = Vec::new();
let callable_id = self.callable_from_block(comb)?;
let callable = self.callables.get(callable_id);
for (argname, typ) in &callable.args {
let sig_id = self.ids.next();
2022-02-06 22:19:55 +00:00
let sig = typed_ir::Signal {
2022-02-15 20:32:55 +00:00
id: typed_ir::DefId(sig_id as u32),
2022-02-23 22:36:01 +00:00
typ: *typ,
2022-02-06 22:19:55 +00:00
};
2022-02-15 20:32:55 +00:00
signals.push(sig.clone());
2022-02-23 22:36:01 +00:00
if let Some(argname) = argname {
self.signals.insert(argname.clone(), sig);
}
2022-01-20 18:55:17 +00:00
}
2022-01-05 01:09:08 +00:00
let mut exprs = Default::default();
2022-08-07 16:14:55 +00:00
// TODO: fixme
let root_expr = self.type_expression(&mut exprs, &comb.expr.value)?;
2022-01-05 01:38:56 +00:00
2022-04-05 14:42:30 +00:00
Ok(typed_ir::Body {
2022-02-23 22:36:01 +00:00
signature: callable_id,
2022-02-06 22:19:55 +00:00
signals,
exprs,
2022-02-06 22:19:55 +00:00
expr: root_expr,
})
2022-02-04 23:58:47 +00:00
}
2022-02-23 22:36:01 +00:00
pub fn type_module(&mut self, module: parser::Module) -> Result<Module, CompileError> {
let mut typed_module = Module { blocks: vec![] };
// hacky loop to predefine all names
for item in &module.items {
match &item {
parser::ModuleItem::Comb(comb) => self.callable_from_block(comb)?,
parser::ModuleItem::Proc(_) => todo!("proc block"),
parser::ModuleItem::State(_) => todo!("state block"),
2022-04-05 12:40:47 +00:00
parser::ModuleItem::Struct(_) => todo!("struct block"),
2022-02-23 22:36:01 +00:00
};
}
2022-02-06 22:19:55 +00:00
for item in module.items {
let block = match &item {
parser::ModuleItem::Comb(comb) => self.type_comb(comb)?,
2022-02-15 20:44:10 +00:00
parser::ModuleItem::Proc(_) => todo!("proc block"),
parser::ModuleItem::State(_) => todo!("state block"),
2022-04-05 12:40:47 +00:00
parser::ModuleItem::Struct(_) => todo!("struct block"),
2022-02-06 22:19:55 +00:00
};
2022-02-23 22:36:01 +00:00
typed_module.blocks.push(block);
2022-01-04 22:05:25 +00:00
}
2022-02-23 22:36:01 +00:00
Ok(typed_module)
2022-01-04 22:05:25 +00:00
}
}