diff --git a/src/resolve/function_haystack.rs b/src/resolve/function_haystack.rs index 3650565..0748ab5 100644 --- a/src/resolve/function_haystack.rs +++ b/src/resolve/function_haystack.rs @@ -211,8 +211,13 @@ impl FunctionHaystack { let preferred_type = (i < parameters.required.len()) .then_some(PreferredType::of_parameter(function_ref, i)); - let argument_conform = - if let Some(preferred_type) = preferred_type.map(|p| p.view(ctx.resolved_ast)) { + let argument_conforms = if let Some(preferred_type) = + preferred_type.map(|p| p.view(ctx.resolved_ast)) + { + if preferred_type.kind.contains_polymorph() { + eprintln!("warning: assuming parameter type that contains polymorph matches for function argument"); + true + } else { conform_expr::( ctx, argument, @@ -221,11 +226,13 @@ impl FunctionHaystack { ctx.adept_conform_behavior(), source, ) - } else { - conform_expr_to_default::(argument, ctx.c_integer_assumptions()) - }; + .is_ok() + } + } else { + conform_expr_to_default::(argument, ctx.c_integer_assumptions()).is_ok() + }; - if argument_conform.is_err() { + if !argument_conforms { return false; } } diff --git a/src/resolve/mod.rs b/src/resolve/mod.rs index 0ea9118..a88984f 100644 --- a/src/resolve/mod.rs +++ b/src/resolve/mod.rs @@ -11,6 +11,7 @@ mod global_variable; mod helper_expr; mod initialized; mod job; +mod polymorph; mod stmt; mod type_ctx; mod type_definition; diff --git a/src/resolve/polymorph.rs b/src/resolve/polymorph.rs new file mode 100644 index 0000000..8a1ab6d --- /dev/null +++ b/src/resolve/polymorph.rs @@ -0,0 +1,63 @@ +use crate::resolved::{self, Constraint}; +use derive_more::IsVariant; +use indexmap::IndexMap; +use std::collections::HashSet; + +#[derive(Clone, Debug)] +pub struct PolyType { + constaints: HashSet, +} + +#[derive(Clone, Debug)] +pub struct PolyExpr { + expr: resolved::Expr, +} + +#[derive(Clone, Debug, IsVariant)] +pub enum PolyValue { + PolyType(PolyType), + PolyExpr(PolyExpr), +} + +#[derive(Clone, Debug)] +pub struct PolyCatalog { + polymorphs: IndexMap, +} + +#[derive(Clone, Debug)] +pub enum PolyCatalogInsertError { + /// Cannot have a single polymorph that is both a type as well as an expression + Incongruent, +} + +impl PolyCatalog { + pub fn new() -> Self { + Self { + polymorphs: IndexMap::default(), + } + } + + pub fn put_type( + &mut self, + name: String, + new_constraints: impl Iterator, + ) -> Result<(), PolyCatalogInsertError> { + if let Some(existing) = self.polymorphs.get_mut(&name) { + match existing { + PolyValue::PolyType(poly_type) => { + poly_type.constaints.extend(new_constraints); + } + PolyValue::PolyExpr(_) => return Err(PolyCatalogInsertError::Incongruent), + } + } else { + self.polymorphs.insert( + name, + PolyValue::PolyType(PolyType { + constaints: HashSet::from_iter(new_constraints), + }), + ); + } + + Ok(()) + } +} diff --git a/src/resolved/datatype/kind/constraint.rs b/src/resolved/datatype/kind/constraint.rs index 57996ca..f65d05b 100644 --- a/src/resolved/datatype/kind/constraint.rs +++ b/src/resolved/datatype/kind/constraint.rs @@ -1,6 +1,6 @@ use std::fmt::Display; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum Constraint { Add, } diff --git a/src/resolved/datatype/kind/mod.rs b/src/resolved/datatype/kind/mod.rs index 58f7bd8..e4c7bcd 100644 --- a/src/resolved/datatype/kind/mod.rs +++ b/src/resolved/datatype/kind/mod.rs @@ -45,6 +45,31 @@ impl TypeKind { Type { kind: self, source } } + pub fn contains_polymorph(&self) -> bool { + match self { + TypeKind::Unresolved => { + panic!("resolved::TypeKind::contains_polymorph was called on unresolved type") + } + TypeKind::Boolean + | TypeKind::Integer(_, _) + | TypeKind::CInteger(_, _) + | TypeKind::IntegerLiteral(_) + | TypeKind::FloatLiteral(_) + | TypeKind::Floating(_) => false, + TypeKind::Pointer(inner) => inner.kind.contains_polymorph(), + TypeKind::Void => false, + TypeKind::AnonymousStruct() => todo!(), + TypeKind::AnonymousUnion() => todo!(), + TypeKind::AnonymousEnum(_) => todo!(), + TypeKind::FixedArray(fixed_array) => fixed_array.inner.kind.contains_polymorph(), + TypeKind::FunctionPointer(_) => todo!(), + TypeKind::Enum(_, _) => false, + TypeKind::Structure(_, _) => false, + TypeKind::TypeAlias(_, _) => false, + TypeKind::Polymorph(_, _) => true, + } + } + pub fn sign(&self, target: Option<&Target>) -> Option { match self { TypeKind::Boolean => Some(IntegerSign::Unsigned),