Compare commits
No commits in common. "0daa49874e981ec59ef5f175ace21e6cd612c306" and "5ac51f8c5fb2bade0d1a506d4fa55e67e303d169" have entirely different histories.
0daa49874e
...
5ac51f8c5f
|
@ -4,5 +4,4 @@ comb reduce_or (
|
||||||
a: Logic
|
a: Logic
|
||||||
)
|
)
|
||||||
-> Logic<1> {
|
-> Logic<1> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
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;
|
||||||
|
@ -94,11 +93,7 @@ impl Context {
|
||||||
callables: BTreeMap::new(),
|
callables: BTreeMap::new(),
|
||||||
signals: BTreeMap::new(),
|
signals: BTreeMap::new(),
|
||||||
types: TypingContext::new(),
|
types: TypingContext::new(),
|
||||||
typenames: [
|
typenames: [("Logic".to_string(), tcx.primitives.logic)].into(),
|
||||||
("Logic".to_string(), tcx.primitives.logic),
|
|
||||||
("Num".to_string(), tcx.primitives.elabnum),
|
|
||||||
]
|
|
||||||
.into(),
|
|
||||||
ids: Counter::new(),
|
ids: Counter::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,7 +131,7 @@ impl Context {
|
||||||
typ: signal.typ,
|
typ: signal.typ,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expression::Literal(_) => todo!("type literal"),
|
Expression::Literal(_) => todo!(),
|
||||||
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)?);
|
||||||
|
@ -146,7 +141,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.infer,
|
typ: self.types.primitives.elabnum,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expression::Call(call) => {
|
Expression::Call(call) => {
|
||||||
|
@ -161,7 +156,7 @@ impl Context {
|
||||||
called: typed_ir::DefId(99),
|
called: typed_ir::DefId(99),
|
||||||
args: args_resolved,
|
args: args_resolved,
|
||||||
},
|
},
|
||||||
typ: self.types.primitives.infer,
|
typ: self.types.primitives.elabnum,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -187,11 +182,20 @@ 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,
|
||||||
|
@ -202,8 +206,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!("proc block"),
|
parser::ModuleItem::Proc(_) => todo!(),
|
||||||
parser::ModuleItem::State(_) => todo!("state block"),
|
parser::ModuleItem::State(_) => todo!(),
|
||||||
};
|
};
|
||||||
return Ok(block);
|
return Ok(block);
|
||||||
}
|
}
|
||||||
|
@ -211,43 +215,4 @@ 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!("bin not"),
|
parser::expression::UnOpKind::Not => todo!(),
|
||||||
};
|
};
|
||||||
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!("unary op"),
|
Expression::UnOp(_) => todo!(),
|
||||||
Expression::BinOp(_) => todo!("binary op"),
|
Expression::BinOp(_) => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,24 +1,11 @@
|
||||||
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(Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct DefId(pub u32);
|
pub struct DefId(pub u32);
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Debug, 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,16 +4,9 @@ use std::fmt::Debug;
|
||||||
/// easier
|
/// easier
|
||||||
pub type Type = InternedType;
|
pub type Type = InternedType;
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Debug, 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,
|
||||||
}
|
}
|
||||||
|
@ -28,12 +21,10 @@ 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)]
|
||||||
pub struct ElabData {
|
struct ElabData {
|
||||||
typ: Type,
|
typ: Type,
|
||||||
value: ElabValue,
|
value: ElabValue,
|
||||||
}
|
}
|
||||||
|
@ -62,7 +53,6 @@ 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 {
|
||||||
|
@ -75,23 +65,14 @@ 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![
|
types: vec![TypeStruct {
|
||||||
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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,25 +87,12 @@ 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(val) => {
|
TypeKind::Logic(_) => todo!(),
|
||||||
let mut width = String::new();
|
TypeKind::UInt(_) => todo!(),
|
||||||
self.pretty_value(&mut width, val)?;
|
TypeKind::Callable => todo!(),
|
||||||
write!(w, "Logic<{}>", width)
|
|
||||||
}
|
|
||||||
TypeKind::Infer => write!(w, "?"),
|
|
||||||
TypeKind::UInt(_) => todo!("print uint"),
|
|
||||||
TypeKind::Callable => todo!("print callable"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,14 +61,7 @@ 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, params)| TypeName {
|
|(ident, _)| TypeName {
|
||||||
name: ident.span(),
|
name: ident.span(),
|
||||||
generics: params,
|
generics: (),
|
||||||
},
|
},
|
||||||
)(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: Option<Expression<'a>>,
|
pub generics: (),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
Loading…
Reference in New Issue