plum
git clone https://git.pyrossh.dev/plum
A statically typed, imperative programming language inspired by rust, python
d0981fb
— Peter John
2026-07-23T19:47:56+05:30
feat(plum-checker,plum-wasm-codegen): add PlumType::TVariadic representation
- plum-checker/src/lib.rs +2 -2
- plum-checker/src/monomorphize.rs +4 -4
- plum-checker/src/types.rs +8 -0
- plum-wasm-codegen/src/lib.rs +3 -3
plum-checker/src/lib.rs
CHANGED
|
@@ -114,7 +114,7 @@ pub fn build_global_tables(source: &ast::Source) -> (TypeEnv, ClassEnv, MethodEn
|
|
|
114
114
|
let param_types: Vec<PlumType> = f.params.iter().map(|p| {
|
|
115
115
|
match &p.ty {
|
|
116
116
|
ast::ParamType::Type(t) => plum_type_from_ast(t),
|
|
117
|
-
ast::ParamType::Variadic(t) => plum_type_from_ast(t),
|
|
117
|
+
ast::ParamType::Variadic(t) => PlumType::TVariadic(Box::new(plum_type_from_ast(t))),
|
|
118
118
|
ast::ParamType::Fn(params, ret) => {
|
|
119
119
|
let param_types = params.iter().map(plum_type_from_ast).collect();
|
|
120
120
|
let ret_ty = ret.as_ref().map(|r| plum_type_from_ast(r)).unwrap_or(PlumType::TUnit);
|
|
@@ -184,7 +184,7 @@ fn check_fn(f: &ast::Fn, global_env: &TypeEnv, ctx: &CheckCtx) -> Vec<CheckError
|
|
|
184
184
|
for p in &f.params {
|
|
185
185
|
let ty = match &p.ty {
|
|
186
186
|
ast::ParamType::Type(t) => plum_type_from_ast(t),
|
|
187
|
-
ast::ParamType::Variadic(t) => plum_type_from_ast(t),
|
|
187
|
+
ast::ParamType::Variadic(t) => PlumType::TVariadic(Box::new(plum_type_from_ast(t))),
|
|
188
188
|
ast::ParamType::Fn(params, ret) => {
|
|
189
189
|
let param_types = params.iter().map(plum_type_from_ast).collect();
|
|
190
190
|
let ret_ty = ret.as_ref().map(|r| plum_type_from_ast(r)).unwrap_or(PlumType::TUnit);
|
plum-checker/src/monomorphize.rs
CHANGED
|
@@ -82,7 +82,7 @@ fn plum_type_to_ast_type(t: &PlumType) -> ast::Type {
|
|
|
82
82
|
PlumType::TStr => "Str".to_string(),
|
|
83
83
|
PlumType::TUnit => "Unit".to_string(),
|
|
84
84
|
PlumType::TNamed(n) => n.clone(),
|
|
85
|
-
PlumType::TVar(_) | PlumType::TFun(_, _) => t.to_string(),
|
|
85
|
+
PlumType::TVar(_) | PlumType::TFun(_, _) | PlumType::TVariadic(_) => t.to_string(),
|
|
86
86
|
};
|
|
87
87
|
ast::Type { name, generics: vec![] }
|
|
88
88
|
}
|
|
@@ -250,7 +250,7 @@ impl<'a> Monomorphizer<'a> {
|
|
|
250
250
|
for p in &f.params {
|
|
251
251
|
let ty = match &p.ty {
|
|
252
252
|
ast::ParamType::Type(t) => crate::plum_type_from_ast(t),
|
|
253
|
-
ast::ParamType::Variadic(t) => crate::plum_type_from_ast(t),
|
|
253
|
+
ast::ParamType::Variadic(t) => PlumType::TVariadic(Box::new(crate::plum_type_from_ast(t))),
|
|
254
254
|
ast::ParamType::Fn(params, ret) => {
|
|
255
255
|
let param_types = params.iter().map(crate::plum_type_from_ast).collect();
|
|
256
256
|
let ret_ty = ret.as_ref().map(|r| crate::plum_type_from_ast(r)).unwrap_or(PlumType::TUnit);
|
|
@@ -834,7 +834,7 @@ pub fn monomorphize_source(source: &ast::Source) -> Result<ast::Source, String>
|
|
|
834
834
|
// dispatches to it can resolve its concrete return type.
|
|
835
835
|
let param_types: Vec<PlumType> = specialized_method.params.iter().map(|p| match &p.ty {
|
|
836
836
|
ast::ParamType::Type(t) => crate::plum_type_from_ast(t),
|
|
837
|
-
ast::ParamType::Variadic(t) => crate::plum_type_from_ast(t),
|
|
837
|
+
ast::ParamType::Variadic(t) => PlumType::TVariadic(Box::new(crate::plum_type_from_ast(t))),
|
|
838
838
|
ast::ParamType::Fn(params, ret) => {
|
|
839
839
|
let param_types = params.iter().map(crate::plum_type_from_ast).collect();
|
|
840
840
|
let ret_ty = ret.as_ref().map(|r| crate::plum_type_from_ast(r)).unwrap_or(PlumType::TUnit);
|
|
@@ -857,7 +857,7 @@ pub fn monomorphize_source(source: &ast::Source) -> Result<ast::Source, String>
|
|
|
857
857
|
// can resolve calls to it during inference.
|
|
858
858
|
let param_types: Vec<PlumType> = specialized_fn.params.iter().map(|p| match &p.ty {
|
|
859
859
|
ast::ParamType::Type(t) => crate::plum_type_from_ast(t),
|
|
860
|
-
ast::ParamType::Variadic(t) => crate::plum_type_from_ast(t),
|
|
860
|
+
ast::ParamType::Variadic(t) => PlumType::TVariadic(Box::new(crate::plum_type_from_ast(t))),
|
|
861
861
|
ast::ParamType::Fn(params, ret) => {
|
|
862
862
|
let param_types = params.iter().map(crate::plum_type_from_ast).collect();
|
|
863
863
|
let ret_ty = ret.as_ref().map(|r| crate::plum_type_from_ast(r)).unwrap_or(PlumType::TUnit);
|
plum-checker/src/types.rs
CHANGED
|
@@ -10,6 +10,13 @@ pub enum PlumType {
|
|
|
10
10
|
TVar(String),
|
|
11
11
|
TFun(Vec<PlumType>, Box<PlumType>),
|
|
12
12
|
TNamed(String),
|
|
13
|
+
/// The type of a variadic parameter, e.g. `...Int` -> `TVariadic(TInt)`.
|
|
14
|
+
/// Appears in exactly two places: as the trailing entry of a `TFun`'s
|
|
15
|
+
/// param-types list (call-site arity/type checking), and as the type bound
|
|
16
|
+
/// to the param's name inside the function body. Its only legal use inside
|
|
17
|
+
/// a body is as a `for` loop's iterable — no other `unify`/`infer_expr` arm
|
|
18
|
+
/// handles it, so any other use is a type error by construction.
|
|
19
|
+
TVariadic(Box<PlumType>),
|
|
13
20
|
}
|
|
14
21
|
|
|
15
22
|
impl std::fmt::Display for PlumType {
|
|
@@ -26,6 +33,7 @@ impl std::fmt::Display for PlumType {
|
|
|
26
33
|
write!(f, "({}) -> {}", ps_str.join(", "), r)
|
|
27
34
|
}
|
|
28
35
|
PlumType::TNamed(n) => write!(f, "{}", n),
|
|
36
|
+
PlumType::TVariadic(inner) => write!(f, "...{}", inner),
|
|
29
37
|
}
|
|
30
38
|
}
|
|
31
39
|
}
|
plum-wasm-codegen/src/lib.rs
CHANGED
|
@@ -360,7 +360,7 @@ fn plum_type_to_valtype(t: &PlumType) -> ValType {
|
|
|
360
360
|
// A closure value is a single i32 pointer to its heap-allocated
|
|
361
361
|
// `{table_index, env_pointer}` pair, so `TFun` is an i32 like every other
|
|
362
362
|
// heap reference (`TBool`/`TStr`/`TNamed`).
|
|
363
|
-
PlumType::TBool | PlumType::TStr | PlumType::TNamed(_) | PlumType::TFun(_, _) => ValType::I32,
|
|
363
|
+
PlumType::TBool | PlumType::TStr | PlumType::TNamed(_) | PlumType::TFun(_, _) | PlumType::TVariadic(_) => ValType::I32,
|
|
364
364
|
PlumType::TVar(_) | PlumType::TUnit => ValType::I64,
|
|
365
365
|
}
|
|
366
366
|
}
|
|
@@ -886,7 +886,7 @@ fn register_int_to_string_helper(module: &mut WasmModule, bump_global: u32) -> u
|
|
|
886
886
|
fn param_plum_type(pt: &ast::ParamType) -> PlumType {
|
|
887
887
|
match pt {
|
|
888
888
|
ast::ParamType::Type(t) => plum_checker::plum_type_from_ast(t),
|
|
889
|
-
ast::ParamType::Variadic(t) => plum_checker::plum_type_from_ast(t),
|
|
889
|
+
ast::ParamType::Variadic(t) => PlumType::TVariadic(Box::new(plum_checker::plum_type_from_ast(t))),
|
|
890
890
|
ast::ParamType::Fn(params, ret) => {
|
|
891
891
|
let param_types = params.iter().map(plum_checker::plum_type_from_ast).collect();
|
|
892
892
|
let ret_ty = ret.as_ref().map(|r| plum_checker::plum_type_from_ast(r)).unwrap_or(PlumType::TUnit);
|
|
@@ -1746,7 +1746,7 @@ fn compile_fn_body(f: &ast::Fn, ctx: &CompileCtx, state: &mut ModuleState) -> Re
|
|
|
1746
1746
|
for p in &f.params {
|
|
1747
1747
|
let ty = match &p.ty {
|
|
1748
1748
|
ast::ParamType::Type(t) => plum_checker::plum_type_from_ast(t),
|
|
1749
|
-
ast::ParamType::Variadic(t) => plum_checker::plum_type_from_ast(t),
|
|
1749
|
+
ast::ParamType::Variadic(t) => PlumType::TVariadic(Box::new(plum_checker::plum_type_from_ast(t))),
|
|
1750
1750
|
ast::ParamType::Fn(params, ret) => {
|
|
1751
1751
|
let param_types = params.iter().map(plum_checker::plum_type_from_ast).collect();
|
|
1752
1752
|
let ret_ty = ret.as_ref().map(|r| plum_checker::plum_type_from_ast(r)).unwrap_or(PlumType::TUnit);
|