diff --git a/src/frontend.rs b/src/frontend.rs index 55ad308..29436b3 100644 --- a/src/frontend.rs +++ b/src/frontend.rs @@ -4,7 +4,7 @@ use std::fmt::Write; use super::parser; use crate::rtlil; -pub use callable::{Callable, CallableId}; +pub use callable::{Callable, CallableContext, CallableId}; pub use types::{Type, TypeStruct, TypingContext}; mod callable; @@ -65,7 +65,7 @@ impl Signal { pub struct Context { /// map callable name to callable callable_names: BTreeMap, - callables: BTreeMap, + callables: CallableContext, /// type names typenames: BTreeMap, types: TypingContext, @@ -90,17 +90,23 @@ impl Counter { impl Context { pub fn new() -> Self { - let tcx = TypingContext::new(); + 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(); + Context { - callables: BTreeMap::new(), - callable_names: BTreeMap::new(), + callables: ccx, + callable_names, signals: BTreeMap::new(), - types: TypingContext::new(), - typenames: [ - ("Logic".to_string(), tcx.primitives.logic), - ("Num".to_string(), tcx.primitives.elabnum), - ] - .into(), + types: tcx, + typenames, ids: Counter::new(), } } @@ -166,7 +172,7 @@ impl Context { typed_ir::Expr { id, kind: typed_ir::ExprKind::Call { - called: typed_ir::DefId(99), + called: self.callables.builtins.bitnot, args: vec![a], }, typ: self.types.primitives.infer, @@ -177,7 +183,7 @@ impl Context { typed_ir::Expr { id, kind: typed_ir::ExprKind::Call { - called: typed_ir::DefId(99), + called: self.callables.builtins.xor, args: vec![a, b], }, typ: self.types.primitives.infer, @@ -189,10 +195,11 @@ impl Context { .iter() .map(|expr| self.type_expression(expr)) .collect::, _>>()?; + let called = self.try_get_callable(call.name.fragment())?; typed_ir::Expr { id, kind: typed_ir::ExprKind::Call { - called: typed_ir::DefId(99), + called, args: args_resolved, }, typ: self.types.primitives.infer, @@ -286,7 +293,8 @@ impl Context { Ok(format!("_{}", arg.id.0)) }) .collect::, std::fmt::Error>>()?; - format!("_{}({})", called.0, args.join(", ")) + let callable = self.callables.get(*called); + format!("{}({})", callable.name(), args.join(", ")) } }; let mut type_pretty = String::new(); diff --git a/src/frontend/callable.rs b/src/frontend/callable.rs index f81ed33..5025419 100644 --- a/src/frontend/callable.rs +++ b/src/frontend/callable.rs @@ -1,7 +1,8 @@ -use super::types::Type; +use super::types::{Type, TypingContext}; +use std::collections::HashMap; -#[derive(Copy, Clone, PartialEq)] -pub struct CallableId(u32); +#[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Eq, Ord)] +pub struct CallableId(pub usize); pub struct Callable { pub name: String, @@ -18,3 +19,54 @@ impl<'ty> Callable { self.args.len() } } + +pub struct BuiltinCallables { + pub xor: CallableId, + pub bitnot: CallableId, + pub reduce_or: CallableId, +} + +pub struct CallableContext { + pub builtins: BuiltinCallables, + callables: Vec, +} + +impl CallableContext { + pub fn new(typectx: &mut TypingContext) -> Self { + let builtins = BuiltinCallables { + xor: CallableId(0), + bitnot: CallableId(1), + reduce_or: CallableId(2), + }; + Self { + callables: vec![ + Callable { + name: "builtin::xor".to_string(), + args: vec![], + ret_type: Some(typectx.primitives.logic), + }, + Callable { + name: "builtin::bitnot".to_string(), + args: vec![], + ret_type: Some(typectx.primitives.logic), + }, + Callable { + name: "builtin::reduce_or".to_string(), + args: vec![], + ret_type: Some(typectx.primitives.logic), + }, + ], + builtins, + } + } + + pub fn add(&mut self, callable: Callable) -> CallableId { + let id = self.callables.len(); + self.callables.push(callable); + CallableId(id) + } + + pub fn get(&self, id: CallableId) -> &Callable { + &self.callables[id.0] + } +} diff --git a/src/frontend/typed_ir.rs b/src/frontend/typed_ir.rs index 8bcc635..77b0d88 100644 --- a/src/frontend/typed_ir.rs +++ b/src/frontend/typed_ir.rs @@ -1,3 +1,4 @@ +use super::callable::CallableId; use super::types::{ElabData, Type}; use std::fmt::Debug; @@ -31,7 +32,7 @@ pub struct Expr { pub enum ExprKind { Literal(ElabData), Path(DefId), - Call { called: DefId, args: Vec }, + Call { called: CallableId, args: Vec }, } #[derive(Debug, Clone)] diff --git a/src/frontend/types.rs b/src/frontend/types.rs index 4c05b83..cef1dc3 100644 --- a/src/frontend/types.rs +++ b/src/frontend/types.rs @@ -27,11 +27,17 @@ enum TypeKind { /// UInt of generic width UInt(ElabData), /// Callable - Callable, + Callable(FnSig), /// A type that was not given and needs to be inferred Infer, } +#[derive(Debug, Clone)] +pub struct FnSig { + params: Vec, + ret: Type, +} + #[derive(Debug, Clone)] pub struct ElabData { typ: Type, @@ -145,7 +151,7 @@ impl TypingContext { } } TypeKind::UInt(_) => todo!(), - TypeKind::Callable => todo!("callable generic params"), + TypeKind::Callable(_sig) => todo!("callable generic params"), // need to know what the type is to parameterize it TypeKind::Infer => None, } @@ -172,7 +178,7 @@ impl TypingContext { } TypeKind::Infer => write!(w, "?"), TypeKind::UInt(_) => todo!("print uint"), - TypeKind::Callable => todo!("print callable"), + TypeKind::Callable(_sig) => todo!("print callable"), } } }