Compare commits
2 Commits
5ac51f8c5f
...
0daa49874e
Author | SHA1 | Date |
---|---|---|
NotAFile | 0daa49874e | |
NotAFile | faa7a06aa2 |
|
@ -4,4 +4,5 @@ comb reduce_or (
|
|||
a: Logic
|
||||
)
|
||||
-> Logic<1> {
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use std::cell::Cell;
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt::Write;
|
||||
|
||||
use super::parser;
|
||||
use crate::rtlil;
|
||||
|
@ -93,7 +94,11 @@ impl Context {
|
|||
callables: BTreeMap::new(),
|
||||
signals: BTreeMap::new(),
|
||||
types: TypingContext::new(),
|
||||
typenames: [("Logic".to_string(), tcx.primitives.logic)].into(),
|
||||
typenames: [
|
||||
("Logic".to_string(), tcx.primitives.logic),
|
||||
("Num".to_string(), tcx.primitives.elabnum),
|
||||
]
|
||||
.into(),
|
||||
ids: Counter::new(),
|
||||
}
|
||||
}
|
||||
|
@ -131,7 +136,7 @@ impl Context {
|
|||
typ: signal.typ,
|
||||
}
|
||||
}
|
||||
Expression::Literal(_) => todo!(),
|
||||
Expression::Literal(_) => todo!("type literal"),
|
||||
Expression::UnOp(op) => self.type_expression(&op.a)?,
|
||||
Expression::BinOp(op) => {
|
||||
let (a, b) = (self.type_expression(&op.a)?, self.type_expression(&op.b)?);
|
||||
|
@ -141,7 +146,7 @@ impl Context {
|
|||
called: typed_ir::DefId(99),
|
||||
args: vec![a, b],
|
||||
},
|
||||
typ: self.types.primitives.elabnum,
|
||||
typ: self.types.primitives.infer,
|
||||
}
|
||||
}
|
||||
Expression::Call(call) => {
|
||||
|
@ -156,7 +161,7 @@ impl Context {
|
|||
called: typed_ir::DefId(99),
|
||||
args: args_resolved,
|
||||
},
|
||||
typ: self.types.primitives.elabnum,
|
||||
typ: self.types.primitives.infer,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -182,20 +187,11 @@ impl Context {
|
|||
}
|
||||
|
||||
let ret_typename = &comb.ret.name;
|
||||
let ret_type = self.try_get_type(ret_typename.fragment())?;
|
||||
let _ret_type = self.try_get_type(ret_typename.fragment())?;
|
||||
// TODO: use ret type
|
||||
|
||||
let root_expr = self.type_expression(&comb.expr)?;
|
||||
|
||||
// TODO: more sophisticated type compat check
|
||||
if root_expr.typ != ret_type {
|
||||
let expected = ret_type;
|
||||
let found = root_expr.typ;
|
||||
return Err(CompileError::new(CompileErrorKind::TypeError {
|
||||
expected,
|
||||
found,
|
||||
}));
|
||||
}
|
||||
|
||||
Ok(typed_ir::Block {
|
||||
signals,
|
||||
expr: root_expr,
|
||||
|
@ -206,8 +202,8 @@ impl Context {
|
|||
for item in module.items {
|
||||
let block = match &item {
|
||||
parser::ModuleItem::Comb(comb) => self.type_comb(comb)?,
|
||||
parser::ModuleItem::Proc(_) => todo!(),
|
||||
parser::ModuleItem::State(_) => todo!(),
|
||||
parser::ModuleItem::Proc(_) => todo!("proc block"),
|
||||
parser::ModuleItem::State(_) => todo!("state block"),
|
||||
};
|
||||
return Ok(block);
|
||||
}
|
||||
|
@ -215,4 +211,43 @@ impl Context {
|
|||
"no blocks in module".to_string(),
|
||||
)))
|
||||
}
|
||||
|
||||
pub fn pretty_typed_block(
|
||||
&self,
|
||||
w: &mut dyn std::fmt::Write,
|
||||
block: &typed_ir::Block,
|
||||
) -> std::fmt::Result {
|
||||
for sig in &block.signals {
|
||||
let mut typ_pretty = String::new();
|
||||
self.types.pretty_type(&mut typ_pretty, sig.typ)?;
|
||||
writeln!(w, "_{}: {}", 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 => todo!(),
|
||||
typed_ir::ExprKind::Path(path) => format!("_{}", path.0),
|
||||
typed_ir::ExprKind::Call { called, args } => {
|
||||
let args = args
|
||||
.iter()
|
||||
.map(|arg| {
|
||||
self.pretty_typed_expr(w, arg)?;
|
||||
Ok(format!("_{}", arg.id.0))
|
||||
})
|
||||
.collect::<Result<Vec<_>, std::fmt::Error>>()?;
|
||||
format!("_{}({})", called.0, args.join(", "))
|
||||
}
|
||||
};
|
||||
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(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,7 +121,7 @@ fn desugar_unop<'a>(op: parser::expression::UnOp<'a>) -> parser::expression::Cal
|
|||
let a = desugar_expression(op.a);
|
||||
let op_func = match op.kind {
|
||||
parser::expression::UnOpKind::BitNot => "not",
|
||||
parser::expression::UnOpKind::Not => todo!(),
|
||||
parser::expression::UnOpKind::Not => todo!("bin not"),
|
||||
};
|
||||
parser::expression::Call {
|
||||
name: op_func.into(),
|
||||
|
@ -195,8 +195,8 @@ fn lower_expression(
|
|||
lit.span().fragment().parse().unwrap(),
|
||||
TODO_WIDTH,
|
||||
)),
|
||||
Expression::UnOp(_) => todo!(),
|
||||
Expression::BinOp(_) => todo!(),
|
||||
Expression::UnOp(_) => todo!("unary op"),
|
||||
Expression::BinOp(_) => todo!("binary op"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,24 @@
|
|||
use super::types::Type;
|
||||
use std::fmt::Debug;
|
||||
|
||||
/// ID of a definition (e.g. variable, block, function)
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct DefId(pub u32);
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct ExprId(pub u32);
|
||||
|
||||
// more compact Debug impl
|
||||
impl Debug for DefId {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "DefId({})", self.0)
|
||||
}
|
||||
}
|
||||
impl Debug for ExprId {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "ExprId({})", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// an abstract element that performs some kind of computation on inputs
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Expr {
|
||||
|
|
|
@ -4,9 +4,16 @@ use std::fmt::Debug;
|
|||
/// easier
|
||||
pub type Type = InternedType;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub struct InternedType(usize);
|
||||
|
||||
impl Debug for InternedType {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Type({})", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TypeStruct {
|
||||
kind: TypeKind,
|
||||
}
|
||||
|
@ -21,10 +28,12 @@ enum TypeKind {
|
|||
UInt(ElabData),
|
||||
/// Callable
|
||||
Callable,
|
||||
/// A type that was not given and needs to be inferred
|
||||
Infer,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ElabData {
|
||||
pub struct ElabData {
|
||||
typ: Type,
|
||||
value: ElabValue,
|
||||
}
|
||||
|
@ -53,6 +62,7 @@ enum ElabKind {
|
|||
pub struct PrimitiveTypes {
|
||||
pub elabnum: Type,
|
||||
pub logic: Type,
|
||||
pub infer: Type,
|
||||
}
|
||||
|
||||
pub struct TypingContext {
|
||||
|
@ -65,14 +75,23 @@ impl TypingContext {
|
|||
let primitives = PrimitiveTypes {
|
||||
elabnum: InternedType(0),
|
||||
logic: InternedType(1),
|
||||
infer: InternedType(2),
|
||||
};
|
||||
Self {
|
||||
types: vec![TypeStruct {
|
||||
kind: TypeKind::Logic(ElabData {
|
||||
typ: primitives.elabnum,
|
||||
value: ElabValue::Infer,
|
||||
}),
|
||||
}],
|
||||
types: vec![
|
||||
TypeStruct {
|
||||
kind: TypeKind::ElabType(ElabKind::Num),
|
||||
},
|
||||
TypeStruct {
|
||||
kind: TypeKind::Logic(ElabData {
|
||||
typ: primitives.elabnum,
|
||||
value: ElabValue::Infer,
|
||||
}),
|
||||
},
|
||||
TypeStruct {
|
||||
kind: TypeKind::Infer,
|
||||
},
|
||||
],
|
||||
primitives,
|
||||
}
|
||||
}
|
||||
|
@ -87,12 +106,25 @@ impl TypingContext {
|
|||
&self.types[typ.0]
|
||||
}
|
||||
|
||||
pub fn pretty_value(&self, w: &mut dyn std::fmt::Write, data: &ElabData) -> std::fmt::Result {
|
||||
match data.value {
|
||||
ElabValue::Infer => write!(w, "?: ")?,
|
||||
ElabValue::Concrete(_) => todo!("concrete type value"),
|
||||
}
|
||||
self.pretty_type(w, data.typ)
|
||||
}
|
||||
|
||||
pub fn pretty_type(&self, w: &mut dyn std::fmt::Write, typ: Type) -> std::fmt::Result {
|
||||
match &self.get(typ).kind {
|
||||
TypeKind::ElabType(val) => write!(w, "{{{:?}}}", val),
|
||||
TypeKind::Logic(_) => todo!(),
|
||||
TypeKind::UInt(_) => todo!(),
|
||||
TypeKind::Callable => todo!(),
|
||||
TypeKind::ElabType(val) => write!(w, "{:?}", val),
|
||||
TypeKind::Logic(val) => {
|
||||
let mut width = String::new();
|
||||
self.pretty_value(&mut width, val)?;
|
||||
write!(w, "Logic<{}>", width)
|
||||
}
|
||||
TypeKind::Infer => write!(w, "?"),
|
||||
TypeKind::UInt(_) => todo!("print uint"),
|
||||
TypeKind::Callable => todo!("print callable"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,14 @@ fn main() {
|
|||
let mut frontendcontext = crate::frontend::Context::new();
|
||||
let typed = frontendcontext.type_module(res.1);
|
||||
if opt.debug {
|
||||
println!("{:#?}", typed);
|
||||
println!("{:#?}", &typed);
|
||||
let mut pretty_block = String::new();
|
||||
if let Ok(block) = typed {
|
||||
frontendcontext
|
||||
.pretty_typed_block(&mut pretty_block, &block)
|
||||
.unwrap();
|
||||
}
|
||||
println!("{}", &pretty_block);
|
||||
}
|
||||
/*
|
||||
match lowered {
|
||||
|
|
|
@ -15,9 +15,9 @@ pub fn typename(input: TokenSpan) -> IResult<TokenSpan, TypeName> {
|
|||
token(tk::Ident),
|
||||
opt(delimited(token(tk::LAngle), expression, token(tk::RAngle))),
|
||||
)),
|
||||
|(ident, _)| TypeName {
|
||||
|(ident, params)| TypeName {
|
||||
name: ident.span(),
|
||||
generics: (),
|
||||
generics: params,
|
||||
},
|
||||
)(input)
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ pub fn typename(input: TokenSpan) -> IResult<TokenSpan, TypeName> {
|
|||
#[derive(Debug)]
|
||||
pub struct TypeName<'a> {
|
||||
pub name: Span<'a>,
|
||||
pub generics: (),
|
||||
pub generics: Option<Expression<'a>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
Loading…
Reference in New Issue