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