Introduce StaticType::Variadic for variadic parameters
This commit introduces `StaticType::Variadic` to represent variadic parameter types in function signatures. This allows for more precise type checking of functions that accept a variable number of arguments, such as arithmetic operators. Previously, variadic functions were handled using `StaticType::Any`, which was too permissive and could lead to runtime errors. The new `Variadic` type enforces that all arguments must conform to a specified inner type. Changes include: - Adding `StaticType::Variadic` to `src/ast/types.rs`. - Updating the type checker to handle `Variadic` types correctly when unifying with tuples or single arguments. - Modifying built-in functions like arithmetic operators to use `Variadic` for their parameter types. - Improving error messages for function call mismatches to be more specific. - Adding a new test case to ensure arithmetic type mismatches are caught at compile time. - A new example `data_stream_pipe_buffered.myc` is added. - The `HMA.myc` example now has a `Skip: output` directive.
This commit is contained in:
@@ -352,6 +352,14 @@ impl TypeChecker {
|
||||
self.unify(e, (*inner).clone(), diag);
|
||||
}
|
||||
}
|
||||
// Variadic(T) unifies with a Tuple by unifying each element with T.
|
||||
(StaticType::Variadic(inner), StaticType::Tuple(elems))
|
||||
| (StaticType::Tuple(elems), StaticType::Variadic(inner)) => {
|
||||
drop(subst);
|
||||
for e in elems {
|
||||
self.unify(e, (*inner).clone(), diag);
|
||||
}
|
||||
}
|
||||
// Any and Error are already handled by is_assignable_from — silently succeed
|
||||
(StaticType::Any, _) | (_, StaticType::Any) => {}
|
||||
(StaticType::Error, _) | (_, StaticType::Error) => {}
|
||||
@@ -394,7 +402,7 @@ impl TypeChecker {
|
||||
// If multiple overloads match (e.g. `(* TypeVar Int)` matches both
|
||||
// `(Int,Int)→Int` and `(Float,Float)→Float`), the choice is ambiguous
|
||||
// and binding the TypeVar to the first match would be incorrect.
|
||||
let is_variadic = |sig: &Signature| matches!(sig.params, StaticType::Any);
|
||||
let is_variadic = |sig: &Signature| matches!(sig.params, StaticType::Any | StaticType::Variadic(_));
|
||||
let mut unique_match: Option<&Signature> = None;
|
||||
for sig in sigs {
|
||||
if !is_variadic(sig) && sig.params.is_assignable_from(args_ty) {
|
||||
@@ -1397,10 +1405,14 @@ impl TypeChecker {
|
||||
let mut ret_ty = match callee_typed.ty.resolve_call(&args_typed.ty) {
|
||||
Some(ty) => ty,
|
||||
None => {
|
||||
let callee_name = match &callee_typed.kind {
|
||||
NodeKind::Identifier { symbol, .. } => format!("'{}'", symbol.name),
|
||||
_ => "function".to_string(),
|
||||
};
|
||||
diag.push_error(
|
||||
format!(
|
||||
"Invalid arguments for function call. Expected {}, got {}",
|
||||
callee_typed.ty, args_typed.ty
|
||||
"{}: no matching overload for ({})",
|
||||
callee_name, args_typed.ty.display_compact()
|
||||
),
|
||||
Some(node.identity.clone()),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user