add simple const generic eval
This commit is contained in:
parent
0daa49874e
commit
853021e4f8
|
@ -121,6 +121,14 @@ impl Context {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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"),
|
||||||
|
typed_ir::ExprKind::Call { called, args } => todo!("evaluate call"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn type_expression(
|
fn type_expression(
|
||||||
&self,
|
&self,
|
||||||
expr: &parser::expression::Expression,
|
expr: &parser::expression::Expression,
|
||||||
|
@ -136,8 +144,32 @@ impl Context {
|
||||||
typ: signal.typ,
|
typ: signal.typ,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expression::Literal(_) => todo!("type literal"),
|
Expression::Literal(lit) => {
|
||||||
Expression::UnOp(op) => self.type_expression(&op.a)?,
|
// TODO: make this a proper enum instead of having to match on everything
|
||||||
|
let data = match lit.kind() {
|
||||||
|
parser::tokens::TokenKind::Number => {
|
||||||
|
let num = lit.span().fragment().parse().unwrap();
|
||||||
|
self.types.make_elabnum_u32(num)
|
||||||
|
}
|
||||||
|
_ => unreachable!("non-literal token in literal?"),
|
||||||
|
};
|
||||||
|
typed_ir::Expr {
|
||||||
|
id,
|
||||||
|
kind: typed_ir::ExprKind::Literal(data),
|
||||||
|
typ: self.types.primitives.infer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Expression::UnOp(op) => {
|
||||||
|
let a = self.type_expression(&op.a)?;
|
||||||
|
typed_ir::Expr {
|
||||||
|
id,
|
||||||
|
kind: typed_ir::ExprKind::Call {
|
||||||
|
called: typed_ir::DefId(99),
|
||||||
|
args: vec![a],
|
||||||
|
},
|
||||||
|
typ: self.types.primitives.infer,
|
||||||
|
}
|
||||||
|
}
|
||||||
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)?);
|
||||||
typed_ir::Expr {
|
typed_ir::Expr {
|
||||||
|
@ -176,8 +208,18 @@ impl Context {
|
||||||
|
|
||||||
for port in comb.ports.iter() {
|
for port in comb.ports.iter() {
|
||||||
let sig_id = self.ids.next();
|
let sig_id = self.ids.next();
|
||||||
|
|
||||||
let sig_typename = &port.net.typ;
|
let sig_typename = &port.net.typ;
|
||||||
let sig_type = self.try_get_type(sig_typename.name.fragment())?;
|
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)?;
|
||||||
|
sig_type = self
|
||||||
|
.types
|
||||||
|
.parameterize(sig_type, &[types::GenericArg::Elab(elab_val)])
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
let sig = typed_ir::Signal {
|
let sig = typed_ir::Signal {
|
||||||
id: typed_ir::DefId(sig_id as u32),
|
id: typed_ir::DefId(sig_id as u32),
|
||||||
typ: sig_type,
|
typ: sig_type,
|
||||||
|
@ -220,7 +262,7 @@ impl Context {
|
||||||
for sig in &block.signals {
|
for sig in &block.signals {
|
||||||
let mut typ_pretty = String::new();
|
let mut typ_pretty = String::new();
|
||||||
self.types.pretty_type(&mut typ_pretty, sig.typ)?;
|
self.types.pretty_type(&mut typ_pretty, sig.typ)?;
|
||||||
writeln!(w, "_{}: {}", sig.id.0, typ_pretty)?
|
writeln!(w, "sig_{}: {}", sig.id.0, typ_pretty)?
|
||||||
}
|
}
|
||||||
self.pretty_typed_expr(w, &block.expr)?;
|
self.pretty_typed_expr(w, &block.expr)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -232,8 +274,8 @@ impl Context {
|
||||||
expr: &typed_ir::Expr,
|
expr: &typed_ir::Expr,
|
||||||
) -> std::fmt::Result {
|
) -> std::fmt::Result {
|
||||||
let expr_pretty = match &expr.kind {
|
let expr_pretty = match &expr.kind {
|
||||||
typed_ir::ExprKind::Literal => todo!(),
|
typed_ir::ExprKind::Literal(_) => todo!(),
|
||||||
typed_ir::ExprKind::Path(path) => format!("_{}", path.0),
|
typed_ir::ExprKind::Path(path) => format!("sig_{}", path.0),
|
||||||
typed_ir::ExprKind::Call { called, args } => {
|
typed_ir::ExprKind::Call { called, args } => {
|
||||||
let args = args
|
let args = args
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use super::types::Type;
|
use super::types::{ElabData, Type};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
/// ID of a definition (e.g. variable, block, function)
|
/// ID of a definition (e.g. variable, block, function)
|
||||||
|
@ -29,7 +29,7 @@ pub struct Expr {
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum ExprKind {
|
pub enum ExprKind {
|
||||||
Literal,
|
Literal(ElabData),
|
||||||
Path(DefId),
|
Path(DefId),
|
||||||
Call { called: DefId, args: Vec<Expr> },
|
Call { called: DefId, args: Vec<Expr> },
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,13 +32,13 @@ enum TypeKind {
|
||||||
Infer,
|
Infer,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ElabData {
|
pub struct ElabData {
|
||||||
typ: Type,
|
typ: Type,
|
||||||
value: ElabValue,
|
value: ElabValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
enum ElabValue {
|
enum ElabValue {
|
||||||
/// the value is not given and has to be inferred
|
/// the value is not given and has to be inferred
|
||||||
Infer,
|
Infer,
|
||||||
|
@ -46,7 +46,7 @@ enum ElabValue {
|
||||||
Concrete(ElabValueData),
|
Concrete(ElabValueData),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
enum ElabValueData {
|
enum ElabValueData {
|
||||||
U32(u32),
|
U32(u32),
|
||||||
Bytes(Vec<u8>),
|
Bytes(Vec<u8>),
|
||||||
|
@ -59,6 +59,12 @@ enum ElabKind {
|
||||||
Num,
|
Num,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum GenericArg {
|
||||||
|
Elab(ElabData),
|
||||||
|
Type(Type),
|
||||||
|
}
|
||||||
|
|
||||||
pub struct PrimitiveTypes {
|
pub struct PrimitiveTypes {
|
||||||
pub elabnum: Type,
|
pub elabnum: Type,
|
||||||
pub logic: Type,
|
pub logic: Type,
|
||||||
|
@ -106,10 +112,52 @@ impl TypingContext {
|
||||||
&self.types[typ.0]
|
&self.types[typ.0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn make_elabnum_u32(&self, num: u32) -> ElabData {
|
||||||
|
ElabData {
|
||||||
|
typ: self.primitives.elabnum,
|
||||||
|
value: ElabValue::Concrete(ElabValueData::U32(num)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parameterize(&mut self, typ: Type, params: &[GenericArg]) -> Option<Type> {
|
||||||
|
// TODO: return proper error type here
|
||||||
|
match &self.get(typ).kind {
|
||||||
|
// Elab types have no params yet
|
||||||
|
TypeKind::ElabType(_) => None,
|
||||||
|
TypeKind::Logic(_) => {
|
||||||
|
if params.len() != 1 {
|
||||||
|
// invalid number of typeargs
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
let param = ¶ms[0];
|
||||||
|
if let GenericArg::Elab(data) = param {
|
||||||
|
if data.typ == self.primitives.elabnum {
|
||||||
|
Some(self.add(TypeStruct {
|
||||||
|
kind: TypeKind::Logic(data.clone()),
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
// arg must be elabnum
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// arg must be an elab value
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TypeKind::UInt(_) => todo!(),
|
||||||
|
TypeKind::Callable => todo!("callable generic params"),
|
||||||
|
// need to know what the type is to parameterize it
|
||||||
|
TypeKind::Infer => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn pretty_value(&self, w: &mut dyn std::fmt::Write, data: &ElabData) -> std::fmt::Result {
|
pub fn pretty_value(&self, w: &mut dyn std::fmt::Write, data: &ElabData) -> std::fmt::Result {
|
||||||
match data.value {
|
match &data.value {
|
||||||
ElabValue::Infer => write!(w, "?: ")?,
|
ElabValue::Infer => write!(w, "?: ")?,
|
||||||
ElabValue::Concrete(_) => todo!("concrete type value"),
|
ElabValue::Concrete(val) => match val {
|
||||||
|
ElabValueData::U32(val) => write!(w, "{:?}: ", val)?,
|
||||||
|
ElabValueData::Bytes(val) => write!(w, "{:?}: ", val)?,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
self.pretty_type(w, data.typ)
|
self.pretty_type(w, data.typ)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue