plum
git clone https://git.pyrossh.dev/plum
A statically typed, imperative programming language inspired by rust, python
a2eaba8
— Peter John
2026-07-24T11:27:40+05:30
feat(plum-checker,plum-wasm-codegen): recognize uppercase generic params, use Type instead of ReturnType
plum-checker/src/lib.rs
CHANGED
|
@@ -123,7 +123,7 @@ pub fn build_global_tables(source: &ast::Source) -> (TypeEnv, ClassEnv, MethodEn
|
|
|
123
123
|
}
|
|
124
124
|
}).collect();
|
|
125
125
|
let ret = f.returns.as_ref()
|
|
126
|
-
.map(
|
|
126
|
+
.map(plum_type_from_ast)
|
|
127
127
|
.unwrap_or(PlumType::TUnit);
|
|
128
128
|
let fn_ty = PlumType::TFun(param_types, Box::new(ret));
|
|
129
129
|
if let Some(recv) = &f.type_param {
|
|
@@ -207,10 +207,7 @@ fn check_fn(f: &ast::Fn, global_env: &TypeEnv, ctx: &CheckCtx) -> Vec<CheckError
|
|
|
207
207
|
}
|
|
208
208
|
|
|
209
209
|
let declared_ret = f.returns.as_ref()
|
|
210
|
-
.map(|r| {
|
|
211
|
-
let ast_ty = ast::Type { name: r.name.clone(), generics: vec![] };
|
|
212
|
-
|
|
210
|
+
.map(plum_type_from_ast)
|
|
213
|
-
})
|
|
214
211
|
.unwrap_or(PlumType::TUnit);
|
|
215
212
|
|
|
216
213
|
match &f.body {
|
plum-checker/src/monomorphize.rs
CHANGED
|
@@ -2,14 +2,14 @@ use std::collections::BTreeMap;
|
|
|
2
2
|
use plum_core::ast;
|
|
3
3
|
use crate::types::PlumType;
|
|
4
4
|
|
|
5
|
-
/// A single
|
|
5
|
+
/// A single uppercase letter (`T`, `U`, `K`, ...) is the grammar's only legal
|
|
6
6
|
/// spelling for a generic type parameter — this is how we recognize one, since
|
|
7
7
|
/// `ast::Fn` and `ast::Enum` (unlike `ast::Class`/`ast::Trait`) carry no explicit
|
|
8
8
|
/// generics declaration list.
|
|
9
9
|
pub fn is_generic_param_name(name: &str) -> bool {
|
|
10
10
|
let mut chars = name.chars();
|
|
11
11
|
match (chars.next(), chars.next()) {
|
|
12
|
-
(Some(c), None) => c.
|
|
12
|
+
(Some(c), None) => c.is_ascii_uppercase(),
|
|
13
13
|
_ => false,
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -20,7 +20,7 @@ pub fn class_generic_params(c: &ast::Class) -> Vec<String> {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
/// The generic parameter names implicitly introduced by a `Fn` — every distinct
|
|
23
|
-
/// single-
|
|
23
|
+
/// single-uppercase-letter type name appearing in its params or return type, in
|
|
24
24
|
/// first-appearance order.
|
|
25
25
|
pub fn fn_generic_params(f: &ast::Fn) -> Vec<String> {
|
|
26
26
|
let mut names: Vec<String> = Vec::new();
|
|
@@ -45,7 +45,7 @@ pub fn fn_generic_params(f: &ast::Fn) -> Vec<String> {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
/// The generic parameter names implicitly introduced by an `Enum` — every distinct
|
|
48
|
-
/// single-
|
|
48
|
+
/// single-uppercase-letter variant field type name, in first-appearance order.
|
|
49
49
|
pub fn enum_generic_params(e: &ast::Enum) -> Vec<String> {
|
|
50
50
|
let mut names: Vec<String> = Vec::new();
|
|
51
51
|
for v in &e.variants {
|
|
@@ -148,10 +148,7 @@ pub fn specialize_fn(f: &ast::Fn, subst: &Substitution, mangled_name: &str, new_
|
|
|
148
148
|
},
|
|
149
149
|
default: p.default.clone(),
|
|
150
150
|
}).collect(),
|
|
151
|
-
returns: f.returns.as_ref().map(|r|
|
|
151
|
+
returns: f.returns.as_ref().map(|r| substitute_type(r, subst)),
|
|
152
|
-
let substituted = substitute_type(&ast::Type { name: r.name.clone(), generics: vec![] }, subst);
|
|
153
|
-
ast::ReturnType { name: substituted.name, generics: vec![] }
|
|
154
|
-
}),
|
|
155
152
|
body: f.body.clone(),
|
|
156
153
|
}
|
|
157
154
|
}
|
|
@@ -315,7 +312,7 @@ impl<'a> Monomorphizer<'a> {
|
|
|
315
312
|
}
|
|
316
313
|
};
|
|
317
314
|
if needs {
|
|
318
|
-
f.returns = Some(ast::
|
|
315
|
+
f.returns = Some(ast::Type { name: t.to_string(), generics: vec![] });
|
|
319
316
|
}
|
|
320
317
|
}
|
|
321
318
|
|
plum-wasm-codegen/src/lib.rs
CHANGED
|
@@ -387,7 +387,7 @@ fn block_type_for(result_vt: Option<ValType>) -> BlockType {
|
|
|
387
387
|
result_vt.map(BlockType::Result).unwrap_or(BlockType::Empty)
|
|
388
388
|
}
|
|
389
389
|
|
|
390
|
-
fn ret_type_to_wasm(ret: Option<&ast::
|
|
390
|
+
fn ret_type_to_wasm(ret: Option<&ast::Type>) -> Option<ValType> {
|
|
391
391
|
ret.and_then(|r| ast_type_to_wasm(&r.name))
|
|
392
392
|
}
|
|
393
393
|
|