plum

#treesitter#compiler#wasm

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

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


b48d3a3Peter John 2026-08-09T18:35:29+05:30
test: migrate embedded plum fixtures to `fun` keyword syntax
plum-checker/tests/checker_tests.rs CHANGED
@@ -53,14 +53,14 @@ fn mono_scheme() {
53
53
 
54
54
  #[test]
55
55
  fn valid_add_fn_passes() {
56
- let src = "add(a: Int, b: Int) -> Int =\n a + b\n";
56
+ let src = "fun add(a: Int, b: Int) -> Int =\n a + b\n";
57
57
  let source = parse(src);
58
58
  assert!(check_source(&source).is_ok(), "expected Ok");
59
59
  }
60
60
 
61
61
  #[test]
62
62
  fn wrong_return_type_is_error() {
63
- let src = "bad() -> Int =\n True\n";
63
+ let src = "fun bad() -> Int =\n True\n";
64
64
  let source = parse(src);
65
65
  let result = check_source(&source);
66
66
  assert!(result.is_err());
@@ -70,7 +70,7 @@ fn wrong_return_type_is_error() {
70
70
 
71
71
  #[test]
72
72
  fn undeclared_var_is_error() {
73
- let src = "bad() -> Int =\n x\n";
73
+ let src = "fun bad() -> Int =\n x\n";
74
74
  let source = parse(src);
75
75
  let result = check_source(&source);
76
76
  assert!(result.is_err());
@@ -78,7 +78,7 @@ fn undeclared_var_is_error() {
78
78
 
79
79
  #[test]
80
80
  fn type_mismatch_in_binary_op_is_error() {
81
- let src = "bad() -> Int =\n 1 + 2.0\n";
81
+ let src = "fun bad() -> Int =\n 1 + 2.0\n";
82
82
  let source = parse(src);
83
83
  let result = check_source(&source);
84
84
  assert!(result.is_err());
@@ -86,14 +86,14 @@ fn type_mismatch_in_binary_op_is_error() {
86
86
 
87
87
  #[test]
88
88
  fn bool_literal_true_false_are_bool() {
89
- let src = "isTrue() -> Bool =\n True\n";
89
+ let src = "fun isTrue() -> Bool =\n True\n";
90
90
  let source = parse(src);
91
91
  assert!(check_source(&source).is_ok(), "expected Ok, got {:?}", check_source(&source).err());
92
92
  }
93
93
 
94
94
  #[test]
95
95
  fn bool_literal_wrong_return_type_is_error() {
96
- let src = "bad() -> Int =\n False\n";
96
+ let src = "fun bad() -> Int =\n False\n";
97
97
  let source = parse(src);
98
98
  let result = check_source(&source);
99
99
  assert!(result.is_err());
@@ -101,7 +101,7 @@ fn bool_literal_wrong_return_type_is_error() {
101
101
 
102
102
  #[test]
103
103
  fn method_self_field_access_passes() {
104
- let src = "type Cat =\n name: Str\n age: Int\n\ngetName<Cat>() -> Str =\n self.name\n";
104
+ let src = "type Cat =\n name: Str\n age: Int\n\nfun getName<Cat>() -> Str =\n self.name\n";
105
105
  let source = parse(src);
106
106
  let result = check_source(&source);
107
107
  assert!(result.is_ok(), "expected Ok, got {:?}", result.err());
@@ -109,7 +109,7 @@ fn method_self_field_access_passes() {
109
109
 
110
110
  #[test]
111
111
  fn method_self_unknown_field_is_error() {
112
- let src = "type Cat =\n name: Str\n\ngetAge<Cat>() -> Int =\n self.age\n";
112
+ let src = "type Cat =\n name: Str\n\nfun getAge<Cat>() -> Int =\n self.age\n";
113
113
  let source = parse(src);
114
114
  let result = check_source(&source);
115
115
  assert!(result.is_err());
@@ -117,7 +117,7 @@ fn method_self_unknown_field_is_error() {
117
117
 
118
118
  #[test]
119
119
  fn self_outside_method_is_error() {
120
- let src = "bad() -> Int =\n self\n";
120
+ let src = "fun bad() -> Int =\n self\n";
121
121
  let source = parse(src);
122
122
  let result = check_source(&source);
123
123
  assert!(result.is_err());
@@ -125,7 +125,7 @@ fn self_outside_method_is_error() {
125
125
 
126
126
  #[test]
127
127
  fn class_call_checks_field_types() {
128
- let src = "type Cat =\n name: Str\n age: Int\n\nmakeCat() -> Cat =\n Cat(name: \"x\", age: 1)\n";
128
+ let src = "type Cat =\n name: Str\n age: Int\n\nfun makeCat() -> Cat =\n Cat(name: \"x\", age: 1)\n";
129
129
  let source = parse(src);
130
130
  let result = check_source(&source);
131
131
  assert!(result.is_ok(), "expected Ok, got {:?}", result.err());
@@ -133,7 +133,7 @@ fn class_call_checks_field_types() {
133
133
 
134
134
  #[test]
135
135
  fn class_call_wrong_field_type_is_error() {
136
- let src = "type Cat =\n name: Str\n age: Int\n\nmakeCat() -> Cat =\n Cat(name: \"x\", age: \"y\")\n";
136
+ let src = "type Cat =\n name: Str\n age: Int\n\nfun makeCat() -> Cat =\n Cat(name: \"x\", age: \"y\")\n";
137
137
  let source = parse(src);
138
138
  let result = check_source(&source);
139
139
  assert!(result.is_err());
@@ -141,7 +141,7 @@ fn class_call_wrong_field_type_is_error() {
141
141
 
142
142
  #[test]
143
143
  fn class_call_unknown_field_is_error() {
144
- let src = "type Cat =\n name: Str\n\nmakeCat() -> Cat =\n Cat(name: \"x\", age: 1)\n";
144
+ let src = "type Cat =\n name: Str\n\nfun makeCat() -> Cat =\n Cat(name: \"x\", age: 1)\n";
145
145
  let source = parse(src);
146
146
  let result = check_source(&source);
147
147
  assert!(result.is_err());
@@ -149,7 +149,7 @@ fn class_call_unknown_field_is_error() {
149
149
 
150
150
  #[test]
151
151
  fn method_call_via_attribute_type_checks_args() {
152
- let src = "type Cat =\n name: Str\n\nrename<Cat>(n: Str) -> Str =\n n\n\nuse(c: Cat) -> Str =\n c.rename(\"x\")\n";
152
+ let src = "type Cat =\n name: Str\n\nfun rename<Cat>(n: Str) -> Str =\n n\n\nfun use(c: Cat) -> Str =\n c.rename(\"x\")\n";
153
153
  let source = parse(src);
154
154
  let result = check_source(&source);
155
155
  assert!(result.is_ok(), "expected Ok, got {:?}", result.err());
@@ -157,7 +157,7 @@ fn method_call_via_attribute_type_checks_args() {
157
157
 
158
158
  #[test]
159
159
  fn match_binds_name_pattern_to_subject_type() {
160
- let src = "main(a: Int) -> Int =\n match a\n x =>\n x\n _ =>\n 0\n";
160
+ let src = "fun main(a: Int) -> Int =\n match a\n x =>\n x\n _ =>\n 0\n";
161
161
  let source = parse(src);
162
162
  let result = check_source(&source);
163
163
  assert!(result.is_ok(), "expected Ok, got {:?}", result.err());
@@ -166,7 +166,7 @@ fn match_binds_name_pattern_to_subject_type() {
166
166
  #[test]
167
167
  fn match_inline_case_body_type_checks() {
168
168
  // Case bodies can be a single inline expression, not just an indented block.
169
- let src = "main(a: Int) -> Int =\n match a\n 1 => 10\n _ => 0\n";
169
+ let src = "fun main(a: Int) -> Int =\n match a\n 1 => 10\n _ => 0\n";
170
170
  let source = parse(src);
171
171
  let result = check_source(&source);
172
172
  assert!(result.is_ok(), "expected Ok, got {:?}", result.err());
@@ -178,7 +178,7 @@ fn match_true_false_are_variant_patterns_not_bindings_without_enum_decl() {
178
178
  // comparisons even when the source doesn't redeclare `enum Bool`, so a
179
179
  // later `_` wildcard arm remains reachable (each pattern binds/compares,
180
180
  // it doesn't just re-bind the subject under the name "True").
181
- let src = "pick(a: Bool) -> Int =\n match a\n True =>\n 1\n False =>\n 0\n";
181
+ let src = "fun pick(a: Bool) -> Int =\n match a\n True =>\n 1\n False =>\n 0\n";
182
182
  let source = parse(src);
183
183
  let result = check_source(&source);
184
184
  assert!(result.is_ok(), "expected Ok, got {:?}", result.err());
@@ -186,7 +186,7 @@ fn match_true_false_are_variant_patterns_not_bindings_without_enum_decl() {
186
186
 
187
187
  #[test]
188
188
  fn match_int_pattern_against_str_subject_is_error() {
189
- let src = "main(a: Str) -> Int =\n match a\n 1 =>\n 1\n _ =>\n 0\n";
189
+ let src = "fun main(a: Str) -> Int =\n match a\n 1 =>\n 1\n _ =>\n 0\n";
190
190
  let source = parse(src);
191
191
  let result = check_source(&source);
192
192
  assert!(result.is_err());
@@ -202,7 +202,7 @@ enum Option =
202
202
  | Some(Int)
203
203
  | None
204
204
 
205
- isNone(o: Option) -> Bool = o == None
205
+ fun isNone(o: Option) -> Bool = o == None
206
206
  ";
207
207
  let source = parse(src);
208
208
  let result = check_source(&source);
@@ -216,7 +216,7 @@ enum Option =
216
216
  | Some[Int]
217
217
  | None
218
218
 
219
- makeSome(v: Int) -> Option =
219
+ fun makeSome(v: Int) -> Option =
220
220
  Some(v)
221
221
  ";
222
222
  let source = parse(src);
@@ -231,7 +231,7 @@ enum Option =
231
231
  | Some(Int)
232
232
  | None
233
233
 
234
- bad() -> Option =
234
+ fun bad() -> Option =
235
235
  Some(\"x\")
236
236
  ";
237
237
  let source = parse(src);
@@ -246,7 +246,7 @@ enum Shape =
246
246
  | Rect[Float, Float]
247
247
  | Circle[Float]
248
248
 
249
- bad() -> Shape =
249
+ fun bad() -> Shape =
250
250
  Rect(1.0)
251
251
  ";
252
252
  let source = parse(src);
@@ -261,7 +261,7 @@ enum Shape =
261
261
  | Rect[Float, Float]
262
262
  | Circle[Float]
263
263
 
264
- area(s: Shape) -> Float =
264
+ fun area(s: Shape) -> Float =
265
265
  match s
266
266
  Rect(w, h) =>
267
267
  w * h
@@ -280,7 +280,7 @@ enum Shape =
280
280
  | Rect[Float, Float]
281
281
  | Circle[Float]
282
282
 
283
- bad(s: Shape) -> Float =
283
+ fun bad(s: Shape) -> Float =
284
284
  match s
285
285
  Rect(w) =>
286
286
  w
@@ -322,10 +322,10 @@ fn generic_class_instantiated_at_two_concrete_types_type_checks() {
322
322
  type Box[T] =
323
323
  value: T
324
324
 
325
- makeIntBox() -> Box =
325
+ fun makeIntBox() -> Box =
326
326
  Box(value: 5)
327
327
 
328
- makeStrBox() -> Box =
328
+ fun makeStrBox() -> Box =
329
329
  Box(value: \"x\")
330
330
  ";
331
331
  let source = parse(src);
@@ -336,13 +336,13 @@ makeStrBox() -> Box =
336
336
  #[test]
337
337
  fn generic_function_called_with_different_concrete_types_per_site_type_checks() {
338
338
  let src = "\
339
- wrap(value: T) -> Bool =
339
+ fun wrap(value: T) -> Bool =
340
340
  True
341
341
 
342
- useInt() -> Bool =
342
+ fun useInt() -> Bool =
343
343
  wrap(5)
344
344
 
345
- useStr() -> Bool =
345
+ fun useStr() -> Bool =
346
346
  wrap(\"x\")
347
347
  ";
348
348
  let source = parse(src);
@@ -353,10 +353,10 @@ useStr() -> Bool =
353
353
  #[test]
354
354
  fn generic_function_with_two_independent_type_params_type_checks() {
355
355
  let src = "\
356
- pair(first: T, second: U) -> Bool =
356
+ fun pair(first: T, second: U) -> Bool =
357
357
  True
358
358
 
359
- use() -> Bool =
359
+ fun use() -> Bool =
360
360
  pair(1, \"x\")
361
361
  ";
362
362
  let source = parse(src);
@@ -372,10 +372,10 @@ fn generic_function_with_internally_inconsistent_body_is_rejected_after_speciali
372
372
  // behavior — rewriting `wrong$Str`'s `-> Int` to `-> Str` — would make the
373
373
  // whole program type-check, masking the real `expected Int, found Str` error.
374
374
  let src = "\
375
- wrong(x: T) -> Int =
375
+ fun wrong(x: T) -> Int =
376
376
  \"hello\"
377
377
 
378
- useIt() -> Str =
378
+ fun useIt() -> Str =
379
379
  wrong(\"s\")
380
380
  ";
381
381
  let source = parse(src);
@@ -395,7 +395,7 @@ enum Option =
395
395
  | Some[T]
396
396
  | None
397
397
 
398
- get() -> Int =
398
+ fun get() -> Int =
399
399
  o = Some(5)
400
400
  match o
401
401
  Some(v) =>
@@ -438,7 +438,7 @@ enum Option =
438
438
  | Some[T]
439
439
  | None
440
440
 
441
- useInt() -> Int =
441
+ fun useInt() -> Int =
442
442
  o = Some(5)
443
443
  match o
444
444
  Some(v) =>
@@ -446,7 +446,7 @@ useInt() -> Int =
446
446
  None =>
447
447
  0
448
448
 
449
- useStr() -> Str =
449
+ fun useStr() -> Str =
450
450
  o = Some(\"x\")
451
451
  match o
452
452
  Some(v) =>
@@ -476,10 +476,10 @@ fn generic_method_on_generic_class_type_checks() {
476
476
  type Box[T] =
477
477
  value: T
478
478
 
479
- getValue<Box>() -> T =
479
+ fun getValue<Box>() -> T =
480
480
  self.value
481
481
 
482
- use() -> Int =
482
+ fun use() -> Int =
483
483
  b = Box(value: 5)
484
484
  b.getValue()
485
485
  ";
@@ -502,11 +502,11 @@ fn unbounded_recursive_generic_instantiation_is_a_clear_error() {
502
502
  type Box[T] =
503
503
  value: T
504
504
 
505
- recurse(v: T) -> Int =
505
+ fun recurse(v: T) -> Int =
506
506
  b = Box(value: v)
507
507
  recurse(b)
508
508
 
509
- use() -> Int =
509
+ fun use() -> Int =
510
510
  recurse(5)
511
511
  ";
512
512
  let source = parse(src);
@@ -528,14 +528,14 @@ enum Option =
528
528
  | Some[T]
529
529
  | None
530
530
 
531
- unwrapOr(o: Option, default: Int) -> Int =
531
+ fun unwrapOr(o: Option, default: Int) -> Int =
532
532
  match o
533
533
  Some(v) =>
534
534
  v
535
535
  None =>
536
536
  default
537
537
 
538
- use() -> Int =
538
+ fun use() -> Int =
539
539
  unwrapOr(Some(5), 0)
540
540
  ";
541
541
  let source = parse(src);
@@ -559,13 +559,13 @@ fn ordinary_function_with_bare_generic_class_param_type_checks() {
559
559
  type Box[T] =
560
560
  value: T
561
561
 
562
- getBoxValue<Box>() -> T =
562
+ fun getBoxValue<Box>() -> T =
563
563
  self.value
564
564
 
565
- sumBox(b: Box) -> Int =
565
+ fun sumBox(b: Box) -> Int =
566
566
  b.getBoxValue()
567
567
 
568
- use() -> Int =
568
+ fun use() -> Int =
569
569
  sumBox(Box(value: 5))
570
570
  ";
571
571
  let source = parse(src);
@@ -576,7 +576,7 @@ use() -> Int =
576
576
  #[test]
577
577
  fn closure_literal_infers_as_a_function_type() {
578
578
  let src = "\
579
- useClosure() -> Bool =
579
+ fun useClosure() -> Bool =
580
580
  cb = |v|
581
581
  True
582
582
  cb(5)
@@ -589,7 +589,7 @@ useClosure() -> Bool =
589
589
  #[test]
590
590
  fn fn_value_typed_param_can_be_called() {
591
591
  let src = "\
592
- each(cb: fn(Int) -> Bool) -> Bool =
592
+ fun each(cb: fn(Int) -> Bool) -> Bool =
593
593
  cb(5)
594
594
  ";
595
595
  let source = parse(src);
@@ -604,7 +604,7 @@ type Cat =
604
604
  name: Str
605
605
  age: Int
606
606
 
607
- haveBirthday<Cat>() =
607
+ fun haveBirthday<Cat>() =
608
608
  self.age = self.age + 1
609
609
  ";
610
610
  let source = parse(src);
@@ -618,7 +618,7 @@ type Cat =
618
618
  name: Str
619
619
  age: Int
620
620
 
621
- breakCat<Cat>() =
621
+ fun breakCat<Cat>() =
622
622
  self.age = \"oops\"
623
623
  ";
624
624
  let source = parse(src);
@@ -633,7 +633,7 @@ type Cat =
633
633
  name: Str
634
634
  age: Int
635
635
 
636
- breakCat<Cat>() =
636
+ fun breakCat<Cat>() =
637
637
  self.nope = 1
638
638
  ";
639
639
  let source = parse(src);
@@ -644,10 +644,10 @@ breakCat<Cat>() =
644
644
  #[test]
645
645
  fn closure_passed_to_fn_value_typed_param_type_checks() {
646
646
  let src = "\
647
- each(cb: fn(Int) -> Bool) -> Bool =
647
+ fun each(cb: fn(Int) -> Bool) -> Bool =
648
648
  cb(5)
649
649
 
650
- use() -> Bool =
650
+ fun use() -> Bool =
651
651
  each(|v|
652
652
  True)
653
653
  ";
@@ -659,10 +659,10 @@ use() -> Bool =
659
659
  #[test]
660
660
  fn variadic_call_with_zero_trailing_args_passes() {
661
661
  let src = "\
662
- sumAll(nums: ...Int) -> Int =
662
+ fun sumAll(nums: ...Int) -> Int =
663
663
  0
664
664
 
665
- useSumAll() -> Int =
665
+ fun useSumAll() -> Int =
666
666
  sumAll()
667
667
  ";
668
668
  let source = parse(src);
@@ -672,10 +672,10 @@ useSumAll() -> Int =
672
672
  #[test]
673
673
  fn variadic_call_with_several_trailing_args_passes() {
674
674
  let src = "\
675
- sumAll(nums: ...Int) -> Int =
675
+ fun sumAll(nums: ...Int) -> Int =
676
676
  0
677
677
 
678
- useSumAll() -> Int =
678
+ fun useSumAll() -> Int =
679
679
  sumAll(1, 2, 3)
680
680
  ";
681
681
  let source = parse(src);
@@ -685,10 +685,10 @@ useSumAll() -> Int =
685
685
  #[test]
686
686
  fn variadic_call_with_mismatched_trailing_arg_type_is_error() {
687
687
  let src = "\
688
- sumAll(nums: ...Int) -> Int =
688
+ fun sumAll(nums: ...Int) -> Int =
689
689
  0
690
690
 
691
- useSumAll() -> Int =
691
+ fun useSumAll() -> Int =
692
692
  sumAll(1, \"two\")
693
693
  ";
694
694
  let source = parse(src);
@@ -698,10 +698,10 @@ useSumAll() -> Int =
698
698
  #[test]
699
699
  fn variadic_call_with_fixed_prefix_passes() {
700
700
  let src = "\
701
- combine(prefix: Int, rest: ...Int) -> Int =
701
+ fun combine(prefix: Int, rest: ...Int) -> Int =
702
702
  prefix
703
703
 
704
- useCombine() -> Int =
704
+ fun useCombine() -> Int =
705
705
  combine(1, 2, 3)
706
706
  ";
707
707
  let source = parse(src);
@@ -711,7 +711,7 @@ useCombine() -> Int =
711
711
  #[test]
712
712
  fn two_variadic_params_is_error() {
713
713
  let src = "\
714
- bad(a: ...Int, b: ...Int) -> Int =
714
+ fun bad(a: ...Int, b: ...Int) -> Int =
715
715
  0
716
716
  ";
717
717
  let source = parse(src);
@@ -721,7 +721,7 @@ bad(a: ...Int, b: ...Int) -> Int =
721
721
  #[test]
722
722
  fn variadic_param_not_last_is_error() {
723
723
  let src = "\
724
- bad(a: ...Int, b: Int) -> Int =
724
+ fun bad(a: ...Int, b: Int) -> Int =
725
725
  0
726
726
  ";
727
727
  let source = parse(src);
@@ -731,7 +731,7 @@ bad(a: ...Int, b: Int) -> Int =
731
731
  #[test]
732
732
  fn for_loop_over_variadic_binds_element_type() {
733
733
  let src = "\
734
- sumAll(nums: ...Int) -> Int =
734
+ fun sumAll(nums: ...Int) -> Int =
735
735
  total = 0
736
736
  for v in nums
737
737
  total = total + v
@@ -744,7 +744,7 @@ sumAll(nums: ...Int) -> Int =
744
744
  #[test]
745
745
  fn for_loop_over_variadic_with_two_vars_is_error() {
746
746
  let src = "\
747
- bad(nums: ...Int) -> Int =
747
+ fun bad(nums: ...Int) -> Int =
748
748
  for v, i in nums
749
749
  v
750
750
  0
plum-core/tests/formatter_test.rs CHANGED
@@ -2,7 +2,7 @@ use plum_core::format_source;
2
2
 
3
3
  #[test]
4
4
  fn formats_simple_function() {
5
- let input = "main() =\n x = 1\n";
5
+ let input = "fun main() =\n x = 1\n";
6
6
  let result = format_source(input).expect("format_source should succeed");
7
7
  assert!(result.contains("main()"));
8
8
  assert!(result.contains("x ="));
@@ -10,7 +10,7 @@ fn formats_simple_function() {
10
10
 
11
11
  #[test]
12
12
  fn formats_binary_operator_spacing() {
13
- let input = "add<Int>(a: Int, b: Int) -> Int =\n a+b\n";
13
+ let input = "fun add<Int>(a: Int, b: Int) -> Int =\n a+b\n";
14
14
  let result = format_source(input).expect("format_source should succeed");
15
15
  assert!(result.contains("a + b"));
16
16
  }
@@ -24,7 +24,7 @@ fn rejects_syntax_error() {
24
24
 
25
25
  #[test]
26
26
  fn idempotent_on_already_formatted() {
27
- let input = "main() =\n x = 1 + 2\n";
27
+ let input = "fun main() =\n x = 1 + 2\n";
28
28
  let first = format_source(input).expect("first pass");
29
29
  let second = format_source(&first).expect("second pass");
30
30
  assert_eq!(first, second, "formatting should be idempotent");
plum-core/tests/loader_test.rs CHANGED
@@ -16,8 +16,8 @@ fn write_lib_file(lib_path: &std::path::Path, name: &str, contents: &str) -> std
16
16
  fn import_sees_imported_declarations() {
17
17
  let dir = TempDir::new().unwrap();
18
18
  let lib_path = dir.path().join("libs");
19
- write_lib_file(&lib_path, "helper", "module fixtures\n\nhelperFn() -> Int =\n 42\n");
19
+ write_lib_file(&lib_path, "helper", "module fixtures\n\nfun helperFn() -> Int =\n 42\n");
20
- let entry = write_lib_file(&lib_path, "main", "module fixtures\n\nimport helper\n\nmain() -> Int =\n helperFn()\n");
20
+ let entry = write_lib_file(&lib_path, "main", "module fixtures\n\nimport helper\n\nfun main() -> Int =\n helperFn()\n");
21
21
 
22
22
  let merged = load_and_merge(&entry, &lib_path).expect("load_and_merge failed");
23
23
  let names: Vec<&str> = merged.items.iter().filter_map(|i| match i {
@@ -32,9 +32,9 @@ fn import_sees_imported_declarations() {
32
32
  fn transitive_import_surfaces_grandchild_declarations() {
33
33
  let dir = TempDir::new().unwrap();
34
34
  let lib_path = dir.path().join("libs");
35
- write_lib_file(&lib_path, "c", "module fixtures\n\ncFn() -> Int =\n 3\n");
35
+ write_lib_file(&lib_path, "c", "module fixtures\n\nfun cFn() -> Int =\n 3\n");
36
- write_lib_file(&lib_path, "b", "module fixtures\n\nimport c\n\nbFn() -> Int =\n cFn()\n");
36
+ write_lib_file(&lib_path, "b", "module fixtures\n\nimport c\n\nfun bFn() -> Int =\n cFn()\n");
37
- let entry = write_lib_file(&lib_path, "a", "module fixtures\n\nimport b\n\nmain() -> Int =\n bFn()\n");
37
+ let entry = write_lib_file(&lib_path, "a", "module fixtures\n\nimport b\n\nfun main() -> Int =\n bFn()\n");
38
38
 
39
39
  let merged = load_and_merge(&entry, &lib_path).expect("load_and_merge failed");
40
40
  let names: Vec<&str> = merged.items.iter().filter_map(|i| match i {
@@ -48,10 +48,10 @@ fn transitive_import_surfaces_grandchild_declarations() {
48
48
  fn diamond_import_includes_shared_dependency_once() {
49
49
  let dir = TempDir::new().unwrap();
50
50
  let lib_path = dir.path().join("libs");
51
- write_lib_file(&lib_path, "d", "module fixtures\n\ndFn() -> Int =\n 4\n");
51
+ write_lib_file(&lib_path, "d", "module fixtures\n\nfun dFn() -> Int =\n 4\n");
52
- write_lib_file(&lib_path, "b", "module fixtures\n\nimport d\n\nbFn() -> Int =\n dFn()\n");
52
+ write_lib_file(&lib_path, "b", "module fixtures\n\nimport d\n\nfun bFn() -> Int =\n dFn()\n");
53
- write_lib_file(&lib_path, "c", "module fixtures\n\nimport d\n\ncFn() -> Int =\n dFn()\n");
53
+ write_lib_file(&lib_path, "c", "module fixtures\n\nimport d\n\nfun cFn() -> Int =\n dFn()\n");
54
- let entry = write_lib_file(&lib_path, "a", "module fixtures\n\nimport b\nimport c\n\nmain() -> Int =\n bFn() + cFn()\n");
54
+ let entry = write_lib_file(&lib_path, "a", "module fixtures\n\nimport b\nimport c\n\nfun main() -> Int =\n bFn() + cFn()\n");
55
55
 
56
56
  let merged = load_and_merge(&entry, &lib_path).expect("load_and_merge failed");
57
57
  let d_count = merged.items.iter().filter(|i| matches!(i, plum_core::ast::Item::Fn(f) if f.name == "dFn")).count();
@@ -62,8 +62,8 @@ fn diamond_import_includes_shared_dependency_once() {
62
62
  fn import_cycle_resolves_without_hanging_or_erroring() {
63
63
  let dir = TempDir::new().unwrap();
64
64
  let lib_path = dir.path().join("libs");
65
- write_lib_file(&lib_path, "b", "module fixtures\n\nimport a\n\nbFn() -> Int =\n 1\n");
65
+ write_lib_file(&lib_path, "b", "module fixtures\n\nimport a\n\nfun bFn() -> Int =\n 1\n");
66
- let entry = write_lib_file(&lib_path, "a", "module fixtures\n\nimport b\n\nmain() -> Int =\n bFn()\n");
66
+ let entry = write_lib_file(&lib_path, "a", "module fixtures\n\nimport b\n\nfun main() -> Int =\n bFn()\n");
67
67
 
68
68
  let merged = load_and_merge(&entry, &lib_path).expect("import cycle should resolve, not error");
69
69
  let names: Vec<&str> = merged.items.iter().filter_map(|i| match i {
@@ -78,7 +78,7 @@ fn import_cycle_resolves_without_hanging_or_erroring() {
78
78
  fn unresolvable_import_is_a_clear_error() {
79
79
  let dir = TempDir::new().unwrap();
80
80
  let lib_path = dir.path().join("libs");
81
- let entry = write_lib_file(&lib_path, "main", "module fixtures\n\nimport does_not_exist\n\nmain() -> Int =\n 0\n");
81
+ let entry = write_lib_file(&lib_path, "main", "module fixtures\n\nimport does_not_exist\n\nfun main() -> Int =\n 0\n");
82
82
 
83
83
  let result = load_and_merge(&entry, &lib_path);
84
84
  assert!(result.is_err());
@@ -90,8 +90,8 @@ fn unresolvable_import_is_a_clear_error() {
90
90
  fn duplicate_top_level_name_across_files_is_a_clear_error() {
91
91
  let dir = TempDir::new().unwrap();
92
92
  let lib_path = dir.path().join("libs");
93
- write_lib_file(&lib_path, "helper", "module fixtures\n\nsharedFn() -> Int =\n 1\n");
93
+ write_lib_file(&lib_path, "helper", "module fixtures\n\nfun sharedFn() -> Int =\n 1\n");
94
- let entry = write_lib_file(&lib_path, "main", "module fixtures\n\nimport helper\n\nsharedFn() -> Int =\n 2\n");
94
+ let entry = write_lib_file(&lib_path, "main", "module fixtures\n\nimport helper\n\nfun sharedFn() -> Int =\n 2\n");
95
95
 
96
96
  let result = load_and_merge(&entry, &lib_path);
97
97
  assert!(result.is_err());
@@ -109,7 +109,7 @@ module fixtures
109
109
  type Cat =
110
110
  age: Int
111
111
 
112
- length<Cat>(self) -> Int =
112
+ fun length<Cat>(self) -> Int =
113
113
  self.age
114
114
  ");
115
115
  let entry = write_lib_file(&lib_path, "main", "\
@@ -120,10 +120,10 @@ import cat
120
120
  type Box =
121
121
  items: Int
122
122
 
123
- length<Box>(self) -> Int =
123
+ fun length<Box>(self) -> Int =
124
124
  self.items
125
125
 
126
- main() -> Int =
126
+ fun main() -> Int =
127
127
  0
128
128
  ");
129
129
 
plum-core/tests/parser_test.rs CHANGED
@@ -21,7 +21,7 @@ fn only_trait(source: &Source) -> &Trait {
21
21
  #[test]
22
22
  fn closure_literal_parses_with_params_and_body() {
23
23
  let src = "\
24
- useClosure() -> Bool =
24
+ fun useClosure() -> Bool =
25
25
  cb = |v|
26
26
  True
27
27
  cb(5)
@@ -38,7 +38,7 @@ useClosure() -> Bool =
38
38
  #[test]
39
39
  fn closure_literal_parses_with_no_params() {
40
40
  let src = "\
41
- useClosure() -> Bool =
41
+ fun useClosure() -> Bool =
42
42
  cb = ||
43
43
  True
44
44
  cb()
@@ -53,7 +53,7 @@ useClosure() -> Bool =
53
53
 
54
54
  #[test]
55
55
  fn fn_without_receiver_but_with_return_type_has_no_type_param() {
56
- let src = "main() -> Int =\n 0\n";
56
+ let src = "fun main() -> Int =\n 0\n";
57
57
  let source = parse(src);
58
58
  let f = only_fn(&source);
59
59
  assert_eq!(f.type_param, None, "return type must not be mistaken for a method receiver");
@@ -62,7 +62,7 @@ fn fn_without_receiver_but_with_return_type_has_no_type_param() {
62
62
 
63
63
  #[test]
64
64
  fn fn_with_receiver_and_return_type_has_correct_type_param() {
65
- let src = "toStr<Cat>() -> Str =\n \"x\"\n";
65
+ let src = "fun toStr<Cat>() -> Str =\n \"x\"\n";
66
66
  let source = parse(src);
67
67
  let f = only_fn(&source);
68
68
  assert_eq!(f.type_param, Some("Cat".to_string()));
@@ -71,7 +71,7 @@ fn fn_with_receiver_and_return_type_has_correct_type_param() {
71
71
 
72
72
  #[test]
73
73
  fn fn_value_type_param_parses_with_positional_types_and_return() {
74
- let src = "each(cb: fn(Int) -> Bool) -> Bool =\n True\n";
74
+ let src = "fun each(cb: fn(Int) -> Bool) -> Bool =\n True\n";
75
75
  let source = parse(src);
76
76
  let f = only_fn(&source);
77
77
  let ParamType::Fn(param_types, ret) = &f.params[0].ty else { panic!("expected ParamType::Fn, got {:?}", f.params[0].ty) };
@@ -96,7 +96,7 @@ fn trait_method_return_type_is_not_mangled_to_arrow_token() {
96
96
 
97
97
  #[test]
98
98
  fn fn_value_type_param_parses_with_no_return() {
99
- let src = "each(cb: fn(Int)) -> Bool =\n True\n";
99
+ let src = "fun each(cb: fn(Int)) -> Bool =\n True\n";
100
100
  let source = parse(src);
101
101
  let f = only_fn(&source);
102
102
  let ParamType::Fn(param_types, ret) = &f.params[0].ty else { panic!("expected ParamType::Fn") };
plum-wasm-codegen/tests/codegen_tests.rs CHANGED
@@ -12,7 +12,7 @@ fn parse(src: &str) -> plum_core::ast::Source {
12
12
 
13
13
  #[test]
14
14
  fn compiles_to_valid_wasm() {
15
- let src = "add(a: Int, b: Int) -> Int =\n a + b\n";
15
+ let src = "fun add(a: Int, b: Int) -> Int =\n a + b\n";
16
16
  let source = parse(src);
17
17
  let bytes = compile_source(&source).expect("compile failed");
18
18
  // Valid WASM starts with the magic number
@@ -22,7 +22,7 @@ fn compiles_to_valid_wasm() {
22
22
 
23
23
  #[test]
24
24
  fn output_validates() {
25
- let src = "add(a: Int, b: Int) -> Int =\n a + b\n";
25
+ let src = "fun add(a: Int, b: Int) -> Int =\n a + b\n";
26
26
  let source = parse(src);
27
27
  let bytes = compile_source(&source).expect("compile failed");
28
28
  // wasmparser should accept the output
@@ -33,7 +33,7 @@ fn output_validates() {
33
33
  #[test]
34
34
  fn factorial_compiles() {
35
35
  let src = "\
36
- factorial(x: Int) -> Int =
36
+ fun factorial(x: Int) -> Int =
37
37
  if x < 2
38
38
  return 1
39
39
  return x * factorial(x - 1)
@@ -47,7 +47,7 @@ factorial(x: Int) -> Int =
47
47
 
48
48
  #[test]
49
49
  fn give42_compiles_and_exports() {
50
- let src = "give42() -> Int =\n 42\n";
50
+ let src = "fun give42() -> Int =\n 42\n";
51
51
  let source = parse(src);
52
52
  let bytes = compile_source(&source).expect("compile failed");
53
53
  assert_eq!(&bytes[0..4], b"\0asm");
@@ -65,23 +65,23 @@ fn assert_valid(src: &str) -> Vec<u8> {
65
65
 
66
66
  #[test]
67
67
  fn bool_literals_compile() {
68
- assert_valid("main() -> Bool =\n True\n");
68
+ assert_valid("fun main() -> Bool =\n True\n");
69
- assert_valid("main() -> Bool =\n False\n");
69
+ assert_valid("fun main() -> Bool =\n False\n");
70
70
  }
71
71
 
72
72
  #[test]
73
73
  fn string_literal_compiles() {
74
- assert_valid("main() -> Str =\n \"hello\"\n");
74
+ assert_valid("fun main() -> Str =\n \"hello\"\n");
75
75
  }
76
76
 
77
77
  #[test]
78
78
  fn empty_string_literal_compiles() {
79
- assert_valid("main() -> Str =\n \"\"\n");
79
+ assert_valid("fun main() -> Str =\n \"\"\n");
80
80
  }
81
81
 
82
82
  #[test]
83
83
  fn string_interpolation_of_an_int_runs_correctly() {
84
- let src = "main() -> Str =\n x = 42\n \"{x}\"\n";
84
+ let src = "fun main() -> Str =\n x = 42\n \"{x}\"\n";
85
85
  let source = parse(src);
86
86
  let bytes = compile_source(&source).expect("compile failed");
87
87
  assert_eq!(run_main_str(&bytes), "42");
@@ -89,7 +89,7 @@ fn string_interpolation_of_an_int_runs_correctly() {
89
89
 
90
90
  #[test]
91
91
  fn string_interpolation_of_a_negative_int_runs_correctly() {
92
- let src = "main() -> Str =\n x = -7\n \"{x}\"\n";
92
+ let src = "fun main() -> Str =\n x = -7\n \"{x}\"\n";
93
93
  let source = parse(src);
94
94
  let bytes = compile_source(&source).expect("compile failed");
95
95
  assert_eq!(run_main_str(&bytes), "-7");
@@ -97,7 +97,7 @@ fn string_interpolation_of_a_negative_int_runs_correctly() {
97
97
 
98
98
  #[test]
99
99
  fn string_interpolation_of_zero_runs_correctly() {
100
- let src = "main() -> Str =\n x = 0\n \"{x}\"\n";
100
+ let src = "fun main() -> Str =\n x = 0\n \"{x}\"\n";
101
101
  let source = parse(src);
102
102
  let bytes = compile_source(&source).expect("compile failed");
103
103
  assert_eq!(run_main_str(&bytes), "0");
@@ -105,7 +105,7 @@ fn string_interpolation_of_zero_runs_correctly() {
105
105
 
106
106
  #[test]
107
107
  fn string_interpolation_with_surrounding_text_and_multiple_interps_runs_correctly() {
108
- let src = "main() -> Str =\n count = 3\n total = 10\n \"{count} of {total} complete\"\n";
108
+ let src = "fun main() -> Str =\n count = 3\n total = 10\n \"{count} of {total} complete\"\n";
109
109
  let source = parse(src);
110
110
  let bytes = compile_source(&source).expect("compile failed");
111
111
  assert_eq!(run_main_str(&bytes), "3 of 10 complete");
@@ -113,7 +113,7 @@ fn string_interpolation_with_surrounding_text_and_multiple_interps_runs_correctl
113
113
 
114
114
  #[test]
115
115
  fn string_interpolation_of_a_str_runs_correctly() {
116
- let src = "greet(name: Str) -> Str =\n \"Hello, {name}!\"\n\nmain() -> Str =\n greet(\"World\")\n";
116
+ let src = "fun greet(name: Str) -> Str =\n \"Hello, {name}!\"\n\nfun main() -> Str =\n greet(\"World\")\n";
117
117
  let source = parse(src);
118
118
  let bytes = compile_source(&source).expect("compile failed");
119
119
  assert_eq!(run_main_str(&bytes), "Hello, World!");
@@ -121,7 +121,7 @@ fn string_interpolation_of_a_str_runs_correctly() {
121
121
 
122
122
  #[test]
123
123
  fn string_interpolation_of_a_bool_runs_correctly() {
124
- let src = "main() -> Str =\n b = True\n \"is {b}\"\n";
124
+ let src = "fun main() -> Str =\n b = True\n \"is {b}\"\n";
125
125
  let source = parse(src);
126
126
  let bytes = compile_source(&source).expect("compile failed");
127
127
  assert_eq!(run_main_str(&bytes), "is True");
@@ -132,7 +132,7 @@ fn string_interpolation_of_a_float_is_a_clear_error() {
132
132
  // Float-to-decimal-string formatting is a substantial separate undertaking
133
133
  // (correct rounding needs something like Grisu/Ryu); scoped out for now with
134
134
  // an explicit error rather than emitting an incorrect conversion.
135
- let src = "main() -> Str =\n x = 1.5\n \"{x}\"\n";
135
+ let src = "fun main() -> Str =\n x = 1.5\n \"{x}\"\n";
136
136
  let source = parse(src);
137
137
  let err = compile_source(&source).expect_err("float interpolation should not silently compile");
138
138
  assert!(err.contains("Float"), "got: {}", err);
@@ -140,7 +140,7 @@ fn string_interpolation_of_a_float_is_a_clear_error() {
140
140
 
141
141
  #[test]
142
142
  fn float_arithmetic_and_negation_compile() {
143
- assert_valid("main(x: Float) -> Float =\n y = -x\n y + 1.5\n");
143
+ assert_valid("fun main(x: Float) -> Float =\n y = -x\n y + 1.5\n");
144
144
  }
145
145
 
146
146
  #[test]
@@ -150,10 +150,10 @@ type Cat =
150
150
  name: Str
151
151
  age: Int
152
152
 
153
- getAge<Cat>() -> Int =
153
+ fun getAge<Cat>() -> Int =
154
154
  self.age
155
155
 
156
- makeCat() -> Int =
156
+ fun makeCat() -> Int =
157
157
  c = Cat(name: \"x\", age: 3)
158
158
  c.getAge()
159
159
  ";
@@ -171,7 +171,7 @@ type Wrapper =
171
171
  inner: Pair
172
172
  tag: Int
173
173
 
174
- make() -> Int =
174
+ fun make() -> Int =
175
175
  w = Wrapper(inner: Pair(a: 1, b: 2), tag: 9)
176
176
  w.tag
177
177
  ";
@@ -180,32 +180,32 @@ make() -> Int =
180
180
 
181
181
  #[test]
182
182
  fn match_with_int_and_wildcard_compiles() {
183
- let src = "main(a: Int) -> Int =\n match a\n 1 =>\n return 10\n _ =>\n return 0\n";
183
+ let src = "fun main(a: Int) -> Int =\n match a\n 1 =>\n return 10\n _ =>\n return 0\n";
184
184
  assert_valid(src);
185
185
  }
186
186
 
187
187
  #[test]
188
188
  fn match_binding_pattern_compiles() {
189
- let src = "main(a: Int) -> Int =\n match a\n x =>\n return x\n";
189
+ let src = "fun main(a: Int) -> Int =\n match a\n x =>\n return x\n";
190
190
  assert_valid(src);
191
191
  }
192
192
 
193
193
  #[test]
194
194
  fn match_inline_case_body_compiles() {
195
195
  // Case bodies can be a single inline expression, not just an indented block.
196
- let src = "main(a: Int) =\n match a\n 1 => 10\n _ => 0\n";
196
+ let src = "fun main(a: Int) =\n match a\n 1 => 10\n _ => 0\n";
197
197
  assert_valid(src);
198
198
  }
199
199
 
200
200
  #[test]
201
201
  fn match_bool_variant_pattern_compiles() {
202
- let src = "main(a: Bool) -> Int =\n match a\n True =>\n return 1\n False =>\n return 0\n";
202
+ let src = "fun main(a: Bool) -> Int =\n match a\n True =>\n return 1\n False =>\n return 0\n";
203
203
  assert_valid(src);
204
204
  }
205
205
 
206
206
  #[test]
207
207
  fn match_string_pattern_is_a_clear_error() {
208
- let src = "main(a: Str) -> Int =\n match a\n \"x\" =>\n 1\n _ =>\n 0\n";
208
+ let src = "fun main(a: Str) -> Int =\n match a\n \"x\" =>\n 1\n _ =>\n 0\n";
209
209
  let source = parse(src);
210
210
  let err = compile_source(&source).expect_err("string match patterns are not yet supported");
211
211
  assert!(err.contains("string match"), "got: {}", err);
@@ -222,7 +222,7 @@ enum Nested =
222
222
  | Wrap[Option]
223
223
  | Empty
224
224
 
225
- f(n: Nested) -> Int =
225
+ fun f(n: Nested) -> Int =
226
226
  match n
227
227
  Wrap(Some(v)) =>
228
228
  return v
@@ -231,7 +231,7 @@ f(n: Nested) -> Int =
231
231
  Empty =>
232
232
  return 0
233
233
 
234
- main() -> Int =
234
+ fun main() -> Int =
235
235
  f(Wrap(Some(5)))
236
236
  ";
237
237
  let source = parse(src);
@@ -252,7 +252,7 @@ enum Nested =
252
252
  | Wrap[Option]
253
253
  | Empty
254
254
 
255
- f(n: Nested) -> Int =
255
+ fun f(n: Nested) -> Int =
256
256
  match n
257
257
  Wrap(Some(v)) =>
258
258
  return v
@@ -261,7 +261,7 @@ f(n: Nested) -> Int =
261
261
  Empty =>
262
262
  return 0
263
263
 
264
- main() -> Int =
264
+ fun main() -> Int =
265
265
  f(Wrap(None))
266
266
  ";
267
267
  let source = parse(src);
@@ -285,13 +285,13 @@ enum Box =
285
285
  | Full[T]
286
286
  | Empty
287
287
 
288
- unwrap(b: Box) -> Int =
288
+ fun unwrap(b: Box) -> Int =
289
289
  match b
290
290
  Full(Some(v)) => v
291
291
  Full(None) => -1
292
292
  Empty => 0
293
293
 
294
- main() -> Int =
294
+ fun main() -> Int =
295
295
  unwrap(Full(Some(7)))
296
296
  ";
297
297
  let source = parse(src);
@@ -308,14 +308,14 @@ enum Option =
308
308
  | Some[Option]
309
309
  | None
310
310
 
311
- unwrapTwice(o: Option) -> Int =
311
+ fun unwrapTwice(o: Option) -> Int =
312
312
  match o
313
313
  Some(Some(None)) => 1
314
314
  Some(None) => 2
315
315
  None => 3
316
316
  _ => 0
317
317
 
318
- main() -> Int =
318
+ fun main() -> Int =
319
319
  unwrapTwice(Some(Some(None)))
320
320
  ";
321
321
  let source = parse(src);
@@ -371,12 +371,12 @@ fn run_main_str(bytes: &[u8]) -> String {
371
371
  #[test]
372
372
  fn factorial_runs_correctly() {
373
373
  let src = "\
374
- factorial(x: Int) -> Int =
374
+ fun factorial(x: Int) -> Int =
375
375
  if x < 2
376
376
  return 1
377
377
  return x * factorial(x - 1)
378
378
 
379
- main() -> Int =
379
+ fun main() -> Int =
380
380
  factorial(5)
381
381
  ";
382
382
  let source = parse(src);
@@ -391,10 +391,10 @@ type Cat =
391
391
  name: Str
392
392
  age: Int
393
393
 
394
- getAge<Cat>() -> Int =
394
+ fun getAge<Cat>() -> Int =
395
395
  self.age
396
396
 
397
- main() -> Int =
397
+ fun main() -> Int =
398
398
  c = Cat(name: \"x\", age: 7)
399
399
  c.getAge()
400
400
  ";
@@ -414,7 +414,7 @@ type Wrapper =
414
414
  inner: Pair
415
415
  tag: Int
416
416
 
417
- main() -> Int =
417
+ fun main() -> Int =
418
418
  w = Wrapper(inner: Pair(a: 11, b: 22), tag: 99)
419
419
  w.inner.b
420
420
  ";
@@ -433,14 +433,14 @@ fn repeated_class_call_in_a_loop_does_not_alias() {
433
433
  type Box =
434
434
  v: Int
435
435
 
436
- sumBoxes() -> Int =
436
+ fun sumBoxes() -> Int =
437
437
  total = 0
438
438
  for i in 0..5
439
439
  b = Box(v: i)
440
440
  total = total + b.v
441
441
  return total
442
442
 
443
- main() -> Int =
443
+ fun main() -> Int =
444
444
  sumBoxes()
445
445
  ";
446
446
  let source = parse(src);
@@ -451,7 +451,7 @@ main() -> Int =
451
451
  #[test]
452
452
  fn match_int_and_wildcard_run_correctly() {
453
453
  let src = "\
454
- classify(a: Int) -> Int =
454
+ fun classify(a: Int) -> Int =
455
455
  match a
456
456
  1 =>
457
457
  return 100
@@ -460,7 +460,7 @@ classify(a: Int) -> Int =
460
460
  _ =>
461
461
  return 0
462
462
 
463
- main() -> Int =
463
+ fun main() -> Int =
464
464
  classify(2)
465
465
  ";
466
466
  let source = parse(src);
@@ -475,14 +475,14 @@ fn match_bool_variant_pattern_runs_correctly() {
475
475
  // source file — otherwise the first arm always "matches" (as a rebinding) and
476
476
  // `pick(False)` would wrongly return 1.
477
477
  let src = "\
478
- pick(a: Bool) -> Int =
478
+ fun pick(a: Bool) -> Int =
479
479
  match a
480
480
  True =>
481
481
  return 1
482
482
  False =>
483
483
  return 0
484
484
 
485
- main() -> Int =
485
+ fun main() -> Int =
486
486
  pick(False)
487
487
  ";
488
488
  let source = parse(src);
@@ -497,10 +497,10 @@ fn lowercase_single_word_function_call_runs_correctly() {
497
497
  // matched its text and the grammar's lexer would nondeterministically commit to
498
498
  // `var_identifier`, breaking every such call site.
499
499
  let src = "\
500
- double(n: Int) -> Int =
500
+ fun double(n: Int) -> Int =
501
501
  n * 2
502
502
 
503
- main() -> Int =
503
+ fun main() -> Int =
504
504
  double(21)
505
505
  ";
506
506
  let source = parse(src);
@@ -511,11 +511,11 @@ main() -> Int =
511
511
  #[test]
512
512
  fn assert_traps_on_false_and_passes_through_on_true() {
513
513
  let src_ok = "\
514
- check(n: Int) -> Int =
514
+ fun check(n: Int) -> Int =
515
515
  assert n > 0
516
516
  n
517
517
 
518
- main() -> Int =
518
+ fun main() -> Int =
519
519
  check(5)
520
520
  ";
521
521
  let source = parse(src_ok);
@@ -523,11 +523,11 @@ main() -> Int =
523
523
  assert_eq!(run_main(&bytes), 5);
524
524
 
525
525
  let src_trap = "\
526
- check(n: Int) -> Int =
526
+ fun check(n: Int) -> Int =
527
527
  assert n > 0
528
528
  n
529
529
 
530
- main() -> Int =
530
+ fun main() -> Int =
531
531
  check(-1)
532
532
  ";
533
533
  let source = parse(src_trap);
@@ -545,10 +545,10 @@ main() -> Int =
545
545
  fn todo_traps_at_runtime() {
546
546
  // `todo` marks an unimplemented body — it must trap, not silently do nothing.
547
547
  let src = "\
548
- notDoneYet() -> Int =
548
+ fun notDoneYet() -> Int =
549
549
  todo
550
550
 
551
- main() -> Int =
551
+ fun main() -> Int =
552
552
  notDoneYet()
553
553
  ";
554
554
  let source = parse(src);
@@ -570,7 +570,7 @@ enum Color =
570
570
  | Green
571
571
  | Blue
572
572
 
573
- main() -> Int =\n x = Green\n 0\n";
573
+ fun main() -> Int =\n x = Green\n 0\n";
574
574
  assert_valid(src);
575
575
  }
576
576
 
@@ -581,14 +581,14 @@ enum Option =
581
581
  | Some[Int]
582
582
  | None
583
583
 
584
- unwrapOr(o: Option, default: Int) -> Int =
584
+ fun unwrapOr(o: Option, default: Int) -> Int =
585
585
  match o
586
586
  Some(v) =>
587
587
  return v
588
588
  None =>
589
589
  return default
590
590
 
591
- main() -> Int =
591
+ fun main() -> Int =
592
592
  unwrapOr(Some(7), 0)
593
593
  ";
594
594
  let source = parse(src);
@@ -603,14 +603,14 @@ enum Shape =
603
603
  | Rect[Int, Int]
604
604
  | Circle[Int]
605
605
 
606
- area(s: Shape) -> Int =
606
+ fun area(s: Shape) -> Int =
607
607
  match s
608
608
  Rect(w, h) =>
609
609
  return w * h
610
610
  Circle(r) =>
611
611
  return r * r
612
612
 
613
- main() -> Int =
613
+ fun main() -> Int =
614
614
  area(Rect(3, 4))
615
615
  ";
616
616
  let source = parse(src);
@@ -626,7 +626,7 @@ enum Color =
626
626
  | Green
627
627
  | Blue
628
628
 
629
- code(c: Color) -> Int =
629
+ fun code(c: Color) -> Int =
630
630
  match c
631
631
  Red =>
632
632
  return 1
@@ -635,7 +635,7 @@ code(c: Color) -> Int =
635
635
  Blue =>
636
636
  return 3
637
637
 
638
- main() -> Int =
638
+ fun main() -> Int =
639
639
  code(Green)
640
640
  ";
641
641
  let source = parse(src);
@@ -650,14 +650,14 @@ enum Option =
650
650
  | Some[Int]
651
651
  | None
652
652
 
653
- isSome(o: Option) -> Int =
653
+ fun isSome(o: Option) -> Int =
654
654
  match o
655
655
  Some(_) =>
656
656
  return 1
657
657
  None =>
658
658
  return 0
659
659
 
660
- main() -> Int =
660
+ fun main() -> Int =
661
661
  isSome(Some(99))
662
662
  ";
663
663
  let source = parse(src);
@@ -675,14 +675,14 @@ enum Option =
675
675
  | Some[Int]
676
676
  | None
677
677
 
678
- unwrapOr(o: Option, default: Int) -> Int =
678
+ fun unwrapOr(o: Option, default: Int) -> Int =
679
679
  match o
680
680
  Some(v) =>
681
681
  return v
682
682
  None =>
683
683
  return default
684
684
 
685
- main() -> Int =
685
+ fun main() -> Int =
686
686
  unwrapOr(None, 5)
687
687
  ";
688
688
  let source = parse(src);
@@ -702,14 +702,14 @@ enum Option =
702
702
  type Box =
703
703
  value: Option
704
704
 
705
- unwrap<Box>(default: Int) -> Int =
705
+ fun unwrap<Box>(default: Int) -> Int =
706
706
  match self.value
707
707
  Some(v) =>
708
708
  return v
709
709
  None =>
710
710
  return default
711
711
 
712
- main() -> Int =
712
+ fun main() -> Int =
713
713
  b = Box(value: Some(42))
714
714
  b.unwrap(0)
715
715
  ";
@@ -721,12 +721,12 @@ main() -> Int =
721
721
  #[test]
722
722
  fn tail_match_without_return_runs_correctly() {
723
723
  let src = "\
724
- bindExample(n: Int) -> Int =
724
+ fun bindExample(n: Int) -> Int =
725
725
  match n
726
726
  x =>
727
727
  x
728
728
 
729
- main() -> Int =
729
+ fun main() -> Int =
730
730
  bindExample(5)
731
731
  ";
732
732
  let source = parse(src);
@@ -737,13 +737,13 @@ main() -> Int =
737
737
  #[test]
738
738
  fn tail_if_without_return_runs_correctly() {
739
739
  let src = "\
740
- abs(n: Int) -> Int =
740
+ fun abs(n: Int) -> Int =
741
741
  if n < 0
742
742
  -n
743
743
  else
744
744
  n
745
745
 
746
- main() -> Int =
746
+ fun main() -> Int =
747
747
  abs(-7)
748
748
  ";
749
749
  let source = parse(src);
@@ -754,7 +754,7 @@ main() -> Int =
754
754
  #[test]
755
755
  fn tail_if_nested_inside_match_arm_without_return_runs_correctly() {
756
756
  let src = "\
757
- classify(n: Int) -> Int =
757
+ fun classify(n: Int) -> Int =
758
758
  match n
759
759
  0 =>
760
760
  1
@@ -764,7 +764,7 @@ classify(n: Int) -> Int =
764
764
  else
765
765
  2
766
766
 
767
- main() -> Int =
767
+ fun main() -> Int =
768
768
  classify(-5)
769
769
  ";
770
770
  let source = parse(src);
@@ -775,14 +775,14 @@ main() -> Int =
775
775
  #[test]
776
776
  fn tail_match_mixing_return_and_bare_expr_arms_runs_correctly() {
777
777
  let src = "\
778
- describe(n: Int) -> Int =
778
+ fun describe(n: Int) -> Int =
779
779
  match n
780
780
  0 =>
781
781
  return 100
782
782
  x =>
783
783
  x * 2
784
784
 
785
- main() -> Int =
785
+ fun main() -> Int =
786
786
  describe(21)
787
787
  ";
788
788
  let source = parse(src);
@@ -797,14 +797,14 @@ enum Option =
797
797
  | Some[Int]
798
798
  | None
799
799
 
800
- unwrapOr(o: Option, default: Int) -> Int =
800
+ fun unwrapOr(o: Option, default: Int) -> Int =
801
801
  match o
802
802
  Some(v) =>
803
803
  v
804
804
  None =>
805
805
  default
806
806
 
807
- main() -> Int =
807
+ fun main() -> Int =
808
808
  unwrapOr(Some(9), 0)
809
809
  ";
810
810
  let source = parse(src);
@@ -815,7 +815,7 @@ main() -> Int =
815
815
  #[test]
816
816
  fn tail_if_without_else_is_a_clear_error() {
817
817
  let src = "\
818
- bad(n: Int) -> Int =
818
+ fun bad(n: Int) -> Int =
819
819
  if n < 0
820
820
  return 1
821
821
  ";
@@ -827,7 +827,7 @@ bad(n: Int) -> Int =
827
827
  #[test]
828
828
  fn tail_match_non_exhaustive_is_a_clear_error() {
829
829
  let src = "\
830
- bad(n: Int) -> Int =
830
+ fun bad(n: Int) -> Int =
831
831
  match n
832
832
  0 =>
833
833
  1
@@ -840,7 +840,7 @@ bad(n: Int) -> Int =
840
840
  #[test]
841
841
  fn tail_match_arm_ending_in_non_value_statement_is_a_clear_error() {
842
842
  let src = "\
843
- bad(n: Int) -> Int =
843
+ fun bad(n: Int) -> Int =
844
844
  match n
845
845
  x =>
846
846
  y = x
@@ -856,14 +856,14 @@ fn generic_class_specialized_at_two_types_does_not_alias() {
856
856
  type Box[T] =
857
857
  value: T
858
858
 
859
- getIntValue<Box>() -> Int =
859
+ fun getIntValue<Box>() -> Int =
860
860
  self.value
861
861
 
862
- useInt() -> Int =
862
+ fun useInt() -> Int =
863
863
  b = Box(value: 7)
864
864
  b.getIntValue()
865
865
 
866
- main() -> Int =
866
+ fun main() -> Int =
867
867
  useInt()
868
868
  ";
869
869
  let source = parse(src);
@@ -874,10 +874,10 @@ main() -> Int =
874
874
  #[test]
875
875
  fn generic_function_called_at_multiple_concrete_types_runs_correctly() {
876
876
  let src = "\
877
- identity(value: T) -> T =
877
+ fun identity(value: T) -> T =
878
878
  value
879
879
 
880
- main() -> Int =
880
+ fun main() -> Int =
881
881
  identity(5) + identity(37)
882
882
  ";
883
883
  let source = parse(src);
@@ -891,10 +891,10 @@ fn generic_method_on_generic_class_runs_correctly() {
891
891
  type Box[T] =
892
892
  value: T
893
893
 
894
- getValue<Box>() -> Int =
894
+ fun getValue<Box>() -> Int =
895
895
  self.value
896
896
 
897
- main() -> Int =
897
+ fun main() -> Int =
898
898
  b = Box(value: 9)
899
899
  b.getValue()
900
900
  ";
@@ -906,13 +906,13 @@ main() -> Int =
906
906
  #[test]
907
907
  fn transitively_generic_call_chain_runs_correctly() {
908
908
  let src = "\
909
- identity(value: T) -> T =
909
+ fun identity(value: T) -> T =
910
910
  value
911
911
 
912
- doubled(value: T) -> Int =
912
+ fun doubled(value: T) -> Int =
913
913
  identity(value) + identity(value)
914
914
 
915
- main() -> Int =
915
+ fun main() -> Int =
916
916
  doubled(21)
917
917
  ";
918
918
  let source = parse(src);
@@ -927,14 +927,14 @@ enum Option =
927
927
  | Some[T]
928
928
  | None
929
929
 
930
- unwrapOr(o: Option, default: Int) -> Int =
930
+ fun unwrapOr(o: Option, default: Int) -> Int =
931
931
  match o
932
932
  Some(v) =>
933
933
  v
934
934
  None =>
935
935
  default
936
936
 
937
- main() -> Int =
937
+ fun main() -> Int =
938
938
  unwrapOr(Some(13), 0)
939
939
  ";
940
940
  let source = parse(src);
@@ -956,21 +956,21 @@ enum Option =
956
956
  | Some[T]
957
957
  | None
958
958
 
959
- unwrapIntOr(o: Option, default: Int) -> Int =
959
+ fun unwrapIntOr(o: Option, default: Int) -> Int =
960
960
  match o
961
961
  Some(v) =>
962
962
  v
963
963
  None =>
964
964
  default
965
965
 
966
- unwrapStrOr(o: Option, default: Int) -> Int =
966
+ fun unwrapStrOr(o: Option, default: Int) -> Int =
967
967
  match o
968
968
  Some(v) =>
969
969
  4
970
970
  None =>
971
971
  default
972
972
 
973
- main() -> Int =
973
+ fun main() -> Int =
974
974
  unwrapIntOr(Some(13), 0) + unwrapStrOr(Some(\"abcd\"), 0)
975
975
  ";
976
976
  let source = parse(src);
@@ -989,14 +989,14 @@ enum Option =
989
989
  | Some[T]
990
990
  | None
991
991
 
992
- unwrapOr(o: Option, default: Int) -> Int =
992
+ fun unwrapOr(o: Option, default: Int) -> Int =
993
993
  match o
994
994
  Some(v) =>
995
995
  v
996
996
  None =>
997
997
  default
998
998
 
999
- main() -> Int =
999
+ fun main() -> Int =
1000
1000
  unwrapOr(Some(5), 0) + unwrapOr(Some(37), 0)
1001
1001
  ";
1002
1002
  let source = parse(src);
@@ -1010,13 +1010,13 @@ fn ordinary_function_with_bare_generic_class_param_runs_correctly() {
1010
1010
  type Box[T] =
1011
1011
  value: T
1012
1012
 
1013
- getBoxValue<Box>() -> Int =
1013
+ fun getBoxValue<Box>() -> Int =
1014
1014
  self.value
1015
1015
 
1016
- sumBox(b: Box) -> Int =
1016
+ fun sumBox(b: Box) -> Int =
1017
1017
  b.getBoxValue()
1018
1018
 
1019
- main() -> Int =
1019
+ fun main() -> Int =
1020
1020
  sumBox(Box(value: 11))
1021
1021
  ";
1022
1022
  let source = parse(src);
@@ -1069,10 +1069,10 @@ fn wasm_module_with_a_table_element_validates_and_call_indirect_works() {
1069
1069
  #[test]
1070
1070
  fn non_capturing_closure_passed_and_called_runs_correctly() {
1071
1071
  let src = "\
1072
- each(cb: fn(Int) -> Int) -> Int =
1072
+ fun each(cb: fn(Int) -> Int) -> Int =
1073
1073
  cb(5)
1074
1074
 
1075
- main() -> Int =
1075
+ fun main() -> Int =
1076
1076
  each(|v| v)
1077
1077
  ";
1078
1078
  let source = parse(src);
@@ -1086,10 +1086,10 @@ fn multi_line_closure_call_argument_with_closing_paren_on_last_statement_line_ru
1086
1086
  // multi-line closure body immediately followed by `)` on the same line as the
1087
1087
  // body's last statement, so this shape didn't parse at all before.
1088
1088
  let src = "\
1089
- each(cb: fn(Int) -> Int) -> Int =
1089
+ fun each(cb: fn(Int) -> Int) -> Int =
1090
1090
  cb(5)
1091
1091
 
1092
- main() -> Int =
1092
+ fun main() -> Int =
1093
1093
  each(|v|
1094
1094
  x = v + 1
1095
1095
  x * 2)
@@ -1102,17 +1102,17 @@ main() -> Int =
1102
1102
  #[test]
1103
1103
  fn capturing_closure_snapshots_value_at_creation_time_runs_correctly() {
1104
1104
  let src = "\
1105
- each(cb: fn(Int) -> Int) -> Int =
1105
+ fun each(cb: fn(Int) -> Int) -> Int =
1106
1106
  cb(0)
1107
1107
 
1108
- useClosure() -> Int =
1108
+ fun useClosure() -> Int =
1109
1109
  x = 10
1110
1110
  cb = |v|
1111
1111
  x + v
1112
1112
  x = 999
1113
1113
  each(cb)
1114
1114
 
1115
- main() -> Int =
1115
+ fun main() -> Int =
1116
1116
  useClosure()
1117
1117
  ";
1118
1118
  let source = parse(src);
@@ -1132,16 +1132,16 @@ fn closure_assigned_then_called_at_float_type_runs_correctly() {
1132
1132
  // Float param silently defaulted to Int, producing a `call_indirect` signature
1133
1133
  // mismatch between the compiled closure body and its call site.
1134
1134
  let src = "\
1135
- eachF(cb: fn(Float) -> Float) -> Float =
1135
+ fun eachF(cb: fn(Float) -> Float) -> Float =
1136
1136
  cb(0.0)
1137
1137
 
1138
- useClosure() -> Float =
1138
+ fun useClosure() -> Float =
1139
1139
  offset = 2.5
1140
1140
  cb = |v|
1141
1141
  offset + v
1142
1142
  eachF(cb)
1143
1143
 
1144
- main() -> Float =
1144
+ fun main() -> Float =
1145
1145
  useClosure()
1146
1146
  ";
1147
1147
  let source = parse(src);
@@ -1155,15 +1155,15 @@ fn closure_assigned_then_called_at_class_type_runs_correctly() {
1155
1155
  type Cat =
1156
1156
  age: Int
1157
1157
 
1158
- eachCat(cb: fn(Cat) -> Int) -> Int =
1158
+ fun eachCat(cb: fn(Cat) -> Int) -> Int =
1159
1159
  cb(Cat(age: 7))
1160
1160
 
1161
- useClosure() -> Int =
1161
+ fun useClosure() -> Int =
1162
1162
  cb = |c|
1163
1163
  c.age
1164
1164
  eachCat(cb)
1165
1165
 
1166
- main() -> Int =
1166
+ fun main() -> Int =
1167
1167
  useClosure()
1168
1168
  ";
1169
1169
  let source = parse(src);
@@ -1174,13 +1174,13 @@ main() -> Int =
1174
1174
  #[test]
1175
1175
  fn closure_passed_through_already_generic_higher_order_function_runs_correctly() {
1176
1176
  let src = "\
1177
- identity(value: T) -> T =
1177
+ fun identity(value: T) -> T =
1178
1178
  value
1179
1179
 
1180
- each(cb: fn(Int) -> Int) -> Int =
1180
+ fun each(cb: fn(Int) -> Int) -> Int =
1181
1181
  cb(identity(7))
1182
1182
 
1183
- main() -> Int =
1183
+ fun main() -> Int =
1184
1184
  each(|v| v * 2)
1185
1185
  ";
1186
1186
  let source = parse(src);
@@ -1198,10 +1198,10 @@ fn nested_closure_literal_runs_correctly() {
1198
1198
  // exercises the multi-level capture chain: `outer` must itself capture `offset`
1199
1199
  // purely because `inner` needs it, not because `outer` uses it.
1200
1200
  let src = "\
1201
- each(cb: fn(Int) -> Int) -> Int =
1201
+ fun each(cb: fn(Int) -> Int) -> Int =
1202
1202
  cb(5)
1203
1203
 
1204
- useNested() -> Int =
1204
+ fun useNested() -> Int =
1205
1205
  offset = 100
1206
1206
  outer = |v|
1207
1207
  inner = |w|
@@ -1209,7 +1209,7 @@ useNested() -> Int =
1209
1209
  inner(v)
1210
1210
  each(outer)
1211
1211
 
1212
- main() -> Int =
1212
+ fun main() -> Int =
1213
1213
  useNested()
1214
1214
  ";
1215
1215
  let source = parse(src);
@@ -1220,10 +1220,10 @@ main() -> Int =
1220
1220
  #[test]
1221
1221
  fn nested_closure_literal_passed_directly_as_call_argument_runs_correctly() {
1222
1222
  let src = "\
1223
- each(cb: fn(Int) -> Int) -> Int =
1223
+ fun each(cb: fn(Int) -> Int) -> Int =
1224
1224
  cb(5)
1225
1225
 
1226
- main() -> Int =
1226
+ fun main() -> Int =
1227
1227
  each(|v|
1228
1228
  each(|w| w + v))
1229
1229
  ";
@@ -1238,13 +1238,13 @@ fn named_function_used_as_a_closure_typed_value_runs_correctly() {
1238
1238
  // wherever a `fn(...)`-typed value is expected — no closure literal involved at
1239
1239
  // the call site at all.
1240
1240
  let src = "\
1241
- double(x: Int) -> Int =
1241
+ fun double(x: Int) -> Int =
1242
1242
  x * 2
1243
1243
 
1244
- each(cb: fn(Int) -> Int) -> Int =
1244
+ fun each(cb: fn(Int) -> Int) -> Int =
1245
1245
  cb(21)
1246
1246
 
1247
- main() -> Int =
1247
+ fun main() -> Int =
1248
1248
  each(double)
1249
1249
  ";
1250
1250
  let source = parse(src);
@@ -1255,10 +1255,10 @@ main() -> Int =
1255
1255
  #[test]
1256
1256
  fn named_function_used_as_a_value_assigned_then_called_runs_correctly() {
1257
1257
  let src = "\
1258
- double(x: Int) -> Int =
1258
+ fun double(x: Int) -> Int =
1259
1259
  x * 2
1260
1260
 
1261
- main() -> Int =
1261
+ fun main() -> Int =
1262
1262
  f = double
1263
1263
  f(21)
1264
1264
  ";
@@ -1273,13 +1273,13 @@ fn named_function_used_as_a_value_alongside_a_closure_at_the_same_call_type_runs
1273
1273
  // closure of the same signature (both must resolve to the same wasm function
1274
1274
  // type, since both flow through the exact same `cb(...)` call site).
1275
1275
  let src = "\
1276
- double(x: Int) -> Int =
1276
+ fun double(x: Int) -> Int =
1277
1277
  x * 2
1278
1278
 
1279
- each(cb: fn(Int) -> Int) -> Int =
1279
+ fun each(cb: fn(Int) -> Int) -> Int =
1280
1280
  cb(10)
1281
1281
 
1282
- main() -> Int =
1282
+ fun main() -> Int =
1283
1283
  each(double) + each(|v| v + 1)
1284
1284
  ";
1285
1285
  let source = parse(src);
@@ -1292,14 +1292,14 @@ fn multi_subject_match_with_enum_tags_runs_correctly() {
1292
1292
  // Mirrors libs/std/bool.plum's `and`/`or`: `match self, o` against two Bool
1293
1293
  // subjects, each case naming a tag pattern per position.
1294
1294
  let src = "\
1295
- and(a: Bool, b: Bool) -> Bool =
1295
+ fun and(a: Bool, b: Bool) -> Bool =
1296
1296
  match a, b
1297
1297
  True, True => True
1298
1298
  True, False => False
1299
1299
  False, True => False
1300
1300
  False, False => False
1301
1301
 
1302
- main() -> Int =
1302
+ fun main() -> Int =
1303
1303
  x = and(True, True)
1304
1304
  y = and(True, False)
1305
1305
  match x, y
@@ -1317,13 +1317,13 @@ fn multi_subject_match_falls_through_to_next_case_when_only_first_position_match
1317
1317
  // doesn't (b is 2) — codegen must fall through to the *next case* (trying its
1318
1318
  // own position 0 again), not just "move on" within the first case.
1319
1319
  let src = "\
1320
- classify(a: Int, b: Int) -> Int =
1320
+ fun classify(a: Int, b: Int) -> Int =
1321
1321
  match a, b
1322
1322
  1, 1 => 100
1323
1323
  1, 2 => 200
1324
1324
  _, _ => 0
1325
1325
 
1326
- main() -> Int =
1326
+ fun main() -> Int =
1327
1327
  classify(1, 2)
1328
1328
  ";
1329
1329
  let source = parse(src);
@@ -1334,13 +1334,13 @@ main() -> Int =
1334
1334
  #[test]
1335
1335
  fn multi_subject_match_with_binding_and_wildcard_runs_correctly() {
1336
1336
  let src = "\
1337
- combine(a: Int, b: Int) -> Int =
1337
+ fun combine(a: Int, b: Int) -> Int =
1338
1338
  match a, b
1339
1339
  0, y => y
1340
1340
  x, 0 => x
1341
1341
  x, y => x + y
1342
1342
 
1343
- main() -> Int =
1343
+ fun main() -> Int =
1344
1344
  combine(3, 4)
1345
1345
  ";
1346
1346
  let source = parse(src);
@@ -1357,12 +1357,12 @@ enum Option =
1357
1357
  | Some[T]
1358
1358
  | None
1359
1359
 
1360
- both(a: Option, b: Option) -> Int =
1360
+ fun both(a: Option, b: Option) -> Int =
1361
1361
  match a, b
1362
1362
  Some(x), Some(y) => x + y
1363
1363
  _, _ => 0
1364
1364
 
1365
- main() -> Int =
1365
+ fun main() -> Int =
1366
1366
  both(Some(3), Some(4))
1367
1367
  ";
1368
1368
  let source = parse(src);
@@ -1376,10 +1376,10 @@ fn field_assignment_target_runs_correctly() {
1376
1376
  type Counter =
1377
1377
  value: Int
1378
1378
 
1379
- bump<Counter>() =
1379
+ fun bump<Counter>() =
1380
1380
  self.value = self.value + 1
1381
1381
 
1382
- main() -> Int =
1382
+ fun main() -> Int =
1383
1383
  c = Counter(value: 41)
1384
1384
  c.bump()
1385
1385
  c.value
@@ -1398,10 +1398,10 @@ type Inner =
1398
1398
  type Outer =
1399
1399
  inner: Inner
1400
1400
 
1401
- bump<Outer>() =
1401
+ fun bump<Outer>() =
1402
1402
  self.inner.value = self.inner.value + 1
1403
1403
 
1404
- main() -> Int =
1404
+ fun main() -> Int =
1405
1405
  o = Outer(inner: Inner(value: 9))
1406
1406
  o.bump()
1407
1407
  o.inner.value
@@ -1417,7 +1417,7 @@ fn mixed_multi_assign_with_field_target_runs_correctly() {
1417
1417
  type Counter =
1418
1418
  value: Int
1419
1419
 
1420
- main() -> Int =
1420
+ fun main() -> Int =
1421
1421
  c = Counter(value: 5)
1422
1422
  a, c.value = 100, 7
1423
1423
  a + c.value
@@ -1430,10 +1430,10 @@ main() -> Int =
1430
1430
  #[test]
1431
1431
  fn variadic_call_with_varying_trailing_arg_counts_runs_correctly() {
1432
1432
  let src = "\
1433
- combine(prefix: Int, rest: ...Int) -> Int =
1433
+ fun combine(prefix: Int, rest: ...Int) -> Int =
1434
1434
  prefix
1435
1435
 
1436
- main() -> Int =
1436
+ fun main() -> Int =
1437
1437
  a = combine(10)
1438
1438
  b = combine(20, 1)
1439
1439
  c = combine(30, 1, 2, 3)
@@ -1447,13 +1447,13 @@ main() -> Int =
1447
1447
  #[test]
1448
1448
  fn sum_all_variadic_int_runs_correctly() {
1449
1449
  let src = "\
1450
- sumAll(nums: ...Int) -> Int =
1450
+ fun sumAll(nums: ...Int) -> Int =
1451
1451
  total = 0
1452
1452
  for v in nums
1453
1453
  total = total + v
1454
1454
  total
1455
1455
 
1456
- main() -> Int =
1456
+ fun main() -> Int =
1457
1457
  sumAll(1, 2, 3, 4)
1458
1458
  ";
1459
1459
  let source = parse(src);
@@ -1464,13 +1464,13 @@ main() -> Int =
1464
1464
  #[test]
1465
1465
  fn sum_all_variadic_int_with_zero_args_runs_correctly() {
1466
1466
  let src = "\
1467
- sumAll(nums: ...Int) -> Int =
1467
+ fun sumAll(nums: ...Int) -> Int =
1468
1468
  total = 0
1469
1469
  for v in nums
1470
1470
  total = total + v
1471
1471
  total
1472
1472
 
1473
- main() -> Int =
1473
+ fun main() -> Int =
1474
1474
  sumAll()
1475
1475
  ";
1476
1476
  let source = parse(src);