plum

#treesitter#compiler#wasm

git clone https://git.pyrossh.dev/plum

A statically typed, imperative programming language inspired by rust, python


a2eaba8Peter 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(|r| plum_type_from_ast(&ast::Type { name: r.name.clone(), generics: vec![] }))
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
- plum_type_from_ast(&ast_ty)
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 lowercase letter (`a`, `b`, `c`, `d`, ...) is the grammar's only legal
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.is_ascii_lowercase(),
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-lowercase-letter type name appearing in its params or return type, in
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-lowercase-letter variant field type name, in first-appearance order.
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::ReturnType { name: t.to_string(), generics: vec![] });
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::ReturnType>) -> Option<ValType> {
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