plum

#treesitter#compiler#wasm

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

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


f502d22Peter John 2026-07-19T21:40:20+05:30
fix(tree-sitter-plum): fix match/generics/identifier/attribute grammar bugs
plum-core/src/parser.rs CHANGED
@@ -603,24 +603,31 @@ impl<'a> AstParser<'a> {
603
603
  }
604
604
 
605
605
  fn parse_attribute(&self, node: Node) -> Expr {
606
- // attribute: primary_expression "." (var_identifier | fn_call)
606
+ // attribute: primary_expression "." fn_identifier fn_argument_list?
607
+ // The member name is always fn_identifier (a superset of var_identifier); an
608
+ // optional trailing argument list distinguishes a method call from field access.
607
609
  let mut cursor = node.walk();
608
610
  let named: Vec<Node> = node.named_children(&mut cursor).collect();
609
611
  let object = named.first()
610
612
  .map(|n| { let u = self.unwrap_expr_node(*n); self.parse_primary_expression(u) })
611
613
  .unwrap_or(Expr::Int(0));
614
+ let member = named.get(1).map(|n| self.text(*n)).unwrap_or_default();
612
- let attr = named.get(1).map(|n| {
615
+ let attr = match named.get(2) {
616
+ Some(args_node) => {
613
- if n.kind() == "fn_call" {
617
+ let mut acursor = args_node.walk();
618
+ let args = args_node.named_children(&mut acursor)
619
+ .map(|n| self.parse_arg(n))
620
+ .collect();
614
- AttrKind::Method(self.parse_fn_call(*n))
621
+ AttrKind::Method(FnCall { name: member, args })
615
- } else {
616
- AttrKind::Field(self.text(*n))
617
622
  }
618
- }).unwrap_or(AttrKind::Field(String::new()));
623
+ None => AttrKind::Field(member),
624
+ };
619
625
  Expr::Attribute(Box::new(AttributeExpr { object, attr }))
620
626
  }
621
627
 
622
628
  fn parse_fn_call(&self, node: Node) -> FnCall {
623
- // fn_call: fn_identifier fn_argument_list
629
+ // fn_call: var_identifier fn_argument_list (the callee lexes as var_identifier
630
+ // to avoid an identifier-token tie with all-lowercase, no-underscore names)
624
631
  let name = node.named_child(0).map(|n| self.text(n)).unwrap_or_default();
625
632
  let args = node.named_child(1)
626
633
  .map(|args_node| {
tooling/tree-sitter-plum/grammar.js CHANGED
@@ -74,7 +74,15 @@ module.exports = grammar({
74
74
  choice(
75
75
  seq(
76
76
  $.type_identifier,
77
+ field(
78
+ "generics",
79
+ optional(
80
+ choice(
77
- field("generics", optional(seq("[", commaSep1($.type), "]"))),
81
+ seq("[", commaSep1($.type), "]"),
82
+ seq("(", commaSep1($.type), ")"),
83
+ ),
84
+ ),
85
+ ),
78
86
  ),
79
87
  $.generic,
80
88
  ),
@@ -183,7 +191,7 @@ module.exports = grammar({
183
191
  ),
184
192
  try: ($) => prec.right(seq("try", optional($.fn_call))),
185
193
  assert: ($) => seq("assert", $.expression),
186
- return: ($) => prec.left(seq("return", optional($.expression))),
194
+ return: ($) => prec.right(2, seq("return", optional($.expression))),
187
195
  break: (_) => prec.left("break"),
188
196
  continue: (_) => prec.left("continue"),
189
197
  todo: (_) => prec.left("todo"),
@@ -219,8 +227,9 @@ module.exports = grammar({
219
227
  seq(
220
228
  "match",
221
229
  commaSep1(field("subject", $.expression)), // remove comma use tuples (a, b) and match against tuples
222
- "is",
230
+ $._indent,
223
231
  repeat(field("case", $.case)),
232
+ $._dedent,
224
233
  ),
225
234
  ),
226
235
 
@@ -231,6 +240,7 @@ module.exports = grammar({
231
240
  1,
232
241
  choice(
233
242
  $.class_pattern,
243
+ $.type_identifier,
234
244
  $.string,
235
245
  $.integer,
236
246
  $.float,
@@ -241,7 +251,7 @@ module.exports = grammar({
241
251
 
242
252
  class_pattern: ($) =>
243
253
  seq(
244
- $.dotted_name,
254
+ $.type_identifier,
245
255
  "(",
246
256
  optional(seq(commaSep1($.case_pattern), optional(","))),
247
257
  ")",
@@ -355,22 +365,30 @@ module.exports = grammar({
355
365
  field("body", $.body),
356
366
  ),
357
367
 
368
+ // The member name always lexes as `fn_identifier` (a superset of `var_identifier`,
369
+ // since plain snake_case names are valid camelCase too) so the parser never has to
370
+ // pick between two identifier tokens that could both match the same text — that
371
+ // choice was ambiguous and broke `object.method(args)` parsing.
358
372
  attribute: ($) =>
359
373
  prec(
360
374
  PREC.call,
361
375
  seq(
362
376
  field("object", $.primary_expression),
363
377
  ".",
364
- choice(
365
- $.var_identifier,
378
+ field("member", $.fn_identifier),
366
- $.fn_call,
379
+ field("arguments", optional($.fn_argument_list)),
367
- )
368
380
  ),
369
381
  ),
370
382
 
383
+ // The callee name lexes as `var_identifier` (widened to a superset of
384
+ // `fn_identifier`'s charset below) rather than `fn_identifier` — using two
385
+ // different identifier tokens here was ambiguous for any all-lowercase,
386
+ // no-underscore callee (e.g. `factorial(...)`), since that text matches both
387
+ // token rules and the lexer would sometimes commit to the wrong one before
388
+ // the parser could see the following `(`.
371
389
  fn_call: ($) =>
372
390
  prec(PREC.call, seq(
373
- field("function", $.fn_identifier),
391
+ field("function", $.var_identifier),
374
392
  field(
375
393
  "arguments",
376
394
  $.fn_argument_list,
@@ -488,9 +506,11 @@ module.exports = grammar({
488
506
  b: (_) => token("b"),
489
507
  c: (_) => token("c"),
490
508
  d: (_) => token("d"),
491
- mod_identifier: () => /[a-z]+(_[a-z0-9]+)*/, // lower snake case
509
+ mod_identifier: () => /[a-z][a-z0-9]*(_[a-z0-9]+)*/, // lower snake case
492
- const_identifier: (_) => /[A-Z]+(_[A-Z0-9]+)*/, // upper snake case
510
+ const_identifier: (_) => /[A-Z][A-Z0-9]*(_[A-Z0-9]+)*/, // upper snake case
511
+ // Superset of fn_identifier's charset (adds "_") so fn_call's callee can share
512
+ // this single token instead of forcing the lexer to pick between two rules.
493
- var_identifier: (_) => /[a-z]+(_[a-z0-9]+)*/, // lower snake case
513
+ var_identifier: (_) => /[a-z][a-zA-Z0-9]*(_[a-zA-Z0-9]+)*/, // lower snake case (or camelCase, when used as a callee)
494
514
  fn_identifier: (_) => /[a-z][a-zA-Z0-9]*/, // camel case
495
515
  type_identifier: (_) => /[A-Z][a-zA-Z0-9]*/, // capital case
496
516
  },
tooling/tree-sitter-plum/queries/plum/highlights.scm CHANGED
@@ -7,7 +7,7 @@
7
7
  (fn_identifier) @function)
8
8
 
9
9
  (fn_call
10
- (fn_identifier) @function)
10
+ (var_identifier) @function)
11
11
 
12
12
  (var_identifier) @variable
13
13
  (self) @variable.builtin
@@ -53,7 +53,6 @@
53
53
  "<>"
54
54
  "||"
55
55
  "&&"
56
- "is"
57
56
  "..."
58
57
  ] @operator
59
58
 
@@ -85,6 +84,5 @@
85
84
  ; "panic"
86
85
  ] @keyword.control.return
87
86
 
88
- ; "match" @keyword
87
+ "match" @keyword
89
- ; "as" @keyword
88
+ ; "as" @keyword
90
- ; "is" @keyword
tooling/tree-sitter-plum/queries/plum/tags.scm CHANGED
@@ -8,4 +8,4 @@
8
8
  name: (type_identifier) @name) @definition.interface
9
9
 
10
10
  (fn
11
- name: (identifier) @name) @definition.function
11
+ name: (fn_identifier) @name) @definition.function
tooling/tree-sitter-plum/src/grammar.json CHANGED
Binary file
tooling/tree-sitter-plum/src/node-types.json CHANGED
Binary file
tooling/tree-sitter-plum/src/parser.c CHANGED
Binary file
tooling/tree-sitter-plum/src/tree_sitter/array.h CHANGED
@@ -50,69 +50,104 @@ extern "C" {
50
50
  /// memory allocated for the array's contents.
51
51
  #define array_clear(self) ((self)->size = 0)
52
52
 
53
+ #ifdef __cplusplus
54
+ #define _array__cast(self, expr) (decltype((self)->contents))(expr)
55
+ #else
56
+ #define _array__cast(self, expr) (expr)
57
+ #endif
58
+
53
59
  /// Reserve `new_capacity` elements of space in the array. If `new_capacity` is
54
60
  /// less than the array's current capacity, this function has no effect.
55
- #define array_reserve(self, new_capacity) \
61
+ #define array_reserve(self, new_capacity) \
62
+ ((self)->contents = _array__cast(self, _array__reserve( \
63
+ (void *)(self)->contents, &(self)->capacity, \
56
- _array__reserve((Array *)(self), array_elem_size(self), new_capacity)
64
+ array_elem_size(self), new_capacity)) \
65
+ )
57
66
 
58
67
  /// Free any memory allocated for this array. Note that this does not free any
59
68
  /// memory allocated for the array's contents.
60
- #define array_delete(self) _array__delete((Array *)(self))
69
+ #define array_delete(self) \
70
+ do { \
71
+ if ((self)->contents) ts_free((self)->contents); \
72
+ (self)->contents = NULL; \
73
+ (self)->size = 0; \
74
+ (self)->capacity = 0; \
75
+ } while (0)
61
76
 
62
77
  /// Push a new `element` onto the end of the array.
63
- #define array_push(self, element) \
78
+ #define array_push(self, element) \
79
+ do { \
64
- (_array__grow((Array *)(self), 1, array_elem_size(self)), \
80
+ (self)->contents = _array__cast(self, _array__grow( \
81
+ (void *)(self)->contents, (self)->size, &(self)->capacity, \
82
+ 1, array_elem_size(self) \
83
+ )); \
65
- (self)->contents[(self)->size++] = (element))
84
+ (self)->contents[(self)->size++] = (element); \
85
+ } while(0)
66
86
 
67
87
  /// Increase the array's size by `count` elements.
68
88
  /// New elements are zero-initialized.
69
- #define array_grow_by(self, count) \
89
+ #define array_grow_by(self, count) \
70
- do { \
90
+ do { \
71
- if ((count) == 0) break; \
91
+ if ((count) == 0) break; \
92
+ (self)->contents = _array__cast(self, _array__grow( \
93
+ (self)->contents, (self)->size, &(self)->capacity, \
72
- _array__grow((Array *)(self), count, array_elem_size(self)); \
94
+ count, array_elem_size(self) \
95
+ )); \
73
96
  memset((self)->contents + (self)->size, 0, (count) * array_elem_size(self)); \
74
- (self)->size += (count); \
97
+ (self)->size += (count); \
75
98
  } while (0)
76
99
 
77
100
  /// Append all elements from one array to the end of another.
78
- #define array_push_all(self, other) \
101
+ #define array_push_all(self, other) \
79
102
  array_extend((self), (other)->size, (other)->contents)
80
103
 
81
104
  /// Append `count` elements to the end of the array, reading their values from the
82
105
  /// `contents` pointer.
83
- #define array_extend(self, count, contents) \
106
+ #define array_extend(self, count, other_contents) \
84
- _array__splice( \
107
+ ((self)->contents = _array__cast(self, _array__splice( \
108
+ (void*)(self)->contents, &(self)->size, &(self)->capacity, \
85
- (Array *)(self), array_elem_size(self), (self)->size, \
109
+ array_elem_size(self), (self)->size, 0, count, other_contents \
86
- 0, count, contents \
87
- )
110
+ )))
88
111
 
89
112
  /// Remove `old_count` elements from the array starting at the given `index`. At
90
113
  /// the same index, insert `new_count` new elements, reading their values from the
91
114
  /// `new_contents` pointer.
92
- #define array_splice(self, _index, old_count, new_count, new_contents) \
115
+ #define array_splice(self, _index, old_count, new_count, new_contents) \
93
- _array__splice( \
94
- (Array *)(self), array_elem_size(self), _index, \
116
+ ((self)->contents = _array__cast(self, _array__splice( \
95
- old_count, new_count, new_contents \
117
+ (void *)(self)->contents, &(self)->size, &(self)->capacity, \
118
+ array_elem_size(self), _index, old_count, new_count, new_contents \
96
- )
119
+ )))
97
120
 
98
121
  /// Insert one `element` into the array at the given `index`.
99
- #define array_insert(self, _index, element) \
122
+ #define array_insert(self, _index, element) \
123
+ ((self)->contents = _array__cast(self, _array__splice( \
124
+ (void *)(self)->contents, &(self)->size, &(self)->capacity, \
100
- _array__splice((Array *)(self), array_elem_size(self), _index, 0, 1, &(element))
125
+ array_elem_size(self), _index, 0, 1, &(element) \
126
+ )))
101
127
 
102
128
  /// Remove one element from the array at the given `index`.
103
129
  #define array_erase(self, _index) \
104
- _array__erase((Array *)(self), array_elem_size(self), _index)
130
+ _array__erase((void *)(self)->contents, &(self)->size, array_elem_size(self), _index)
105
131
 
106
132
  /// Pop the last element off the array, returning the element by value.
107
133
  #define array_pop(self) ((self)->contents[--(self)->size])
108
134
 
109
135
  /// Assign the contents of one array to another, reallocating if necessary.
110
- #define array_assign(self, other) \
136
+ #define array_assign(self, other) \
137
+ ((self)->contents = _array__cast(self, _array__assign( \
138
+ (void *)(self)->contents, &(self)->size, &(self)->capacity, \
111
- _array__assign((Array *)(self), (const Array *)(other), array_elem_size(self))
139
+ (const void *)(other)->contents, (other)->size, array_elem_size(self) \
140
+ )))
112
141
 
113
142
  /// Swap one array with another
114
- #define array_swap(self, other) \
143
+ #define array_swap(self, other) \
144
+ do { \
115
- _array__swap((Array *)(self), (Array *)(other))
145
+ void *_array_swap_tmp = (void *)(self)->contents; \
146
+ (self)->contents = (other)->contents; \
147
+ (other)->contents = _array__cast(other, _array_swap_tmp); \
148
+ _array__swap(&(self)->size, &(self)->capacity, \
149
+ &(other)->size, &(other)->capacity); \
150
+ } while (0)
116
151
 
117
152
  /// Get the size of the array contents
118
153
  #define array_elem_size(self) (sizeof *(self)->contents)
@@ -157,82 +192,90 @@ extern "C" {
157
192
 
158
193
  // Private
159
194
 
160
- typedef Array(void) Array;
195
+ // Pointers to individual `Array` fields (rather than the entire `Array` itself)
161
-
196
+ // are passed to the various `_array__*` functions below to address strict aliasing
162
- /// This is not what you're looking for, see `array_delete`.
197
+ // violations that arises when the _entire_ `Array` struct is passed as `Array(void)*`.
198
+ //
199
+ // The `Array` type itself was not altered as a solution in order to avoid breakage
163
- static inline void _array__delete(Array *self) {
200
+ // with existing consumers (in particular, parsers with external scanners).
164
- if (self->contents) {
165
- ts_free(self->contents);
166
- self->contents = NULL;
167
- self->size = 0;
168
- self->capacity = 0;
169
- }
170
- }
171
201
 
172
202
  /// This is not what you're looking for, see `array_erase`.
173
- static inline void _array__erase(Array *self, size_t element_size,
203
+ static inline void _array__erase(void* self_contents, uint32_t *size,
174
- uint32_t index) {
204
+ size_t element_size, uint32_t index) {
175
- assert(index < self->size);
205
+ assert(index < *size);
176
- char *contents = (char *)self->contents;
206
+ char *contents = (char *)self_contents;
177
207
  memmove(contents + index * element_size, contents + (index + 1) * element_size,
178
- (self->size - index - 1) * element_size);
208
+ (*size - index - 1) * element_size);
179
- self->size--;
209
+ (*size)--;
180
210
  }
181
211
 
182
212
  /// This is not what you're looking for, see `array_reserve`.
183
- static inline void _array__reserve(Array *self, size_t element_size, uint32_t new_capacity) {
213
+ static inline void *_array__reserve(void *contents, uint32_t *capacity,
214
+ size_t element_size, uint32_t new_capacity) {
215
+ void *new_contents = contents;
184
- if (new_capacity > self->capacity) {
216
+ if (new_capacity > *capacity) {
185
- if (self->contents) {
217
+ if (contents) {
186
- self->contents = ts_realloc(self->contents, new_capacity * element_size);
218
+ new_contents = ts_realloc(contents, new_capacity * element_size);
187
219
  } else {
188
- self->contents = ts_malloc(new_capacity * element_size);
220
+ new_contents = ts_malloc(new_capacity * element_size);
189
221
  }
190
- self->capacity = new_capacity;
222
+ *capacity = new_capacity;
191
223
  }
224
+ return new_contents;
192
225
  }
193
226
 
194
227
  /// This is not what you're looking for, see `array_assign`.
195
- static inline void _array__assign(Array *self, const Array *other, size_t element_size) {
228
+ static inline void *_array__assign(void* self_contents, uint32_t *self_size, uint32_t *self_capacity,
229
+ const void *other_contents, uint32_t other_size, size_t element_size) {
196
- _array__reserve(self, element_size, other->size);
230
+ void *new_contents = _array__reserve(self_contents, self_capacity, element_size, other_size);
197
- self->size = other->size;
231
+ *self_size = other_size;
198
- memcpy(self->contents, other->contents, self->size * element_size);
232
+ memcpy(new_contents, other_contents, *self_size * element_size);
233
+ return new_contents;
199
234
  }
200
235
 
201
236
  /// This is not what you're looking for, see `array_swap`.
202
- static inline void _array__swap(Array *self, Array *other) {
237
+ static inline void _array__swap(uint32_t *self_size, uint32_t *self_capacity,
238
+ uint32_t *other_size, uint32_t *other_capacity) {
239
+ uint32_t tmp_size = *self_size;
240
+ uint32_t tmp_capacity = *self_capacity;
203
- Array swap = *other;
241
+ *self_size = *other_size;
242
+ *self_capacity = *other_capacity;
204
- *other = *self;
243
+ *other_size = tmp_size;
205
- *self = swap;
244
+ *other_capacity = tmp_capacity;
206
245
  }
207
246
 
208
247
  /// This is not what you're looking for, see `array_push` or `array_grow_by`.
209
- static inline void _array__grow(Array *self, uint32_t count, size_t element_size) {
248
+ static inline void *_array__grow(void *contents, uint32_t size, uint32_t *capacity,
249
+ uint32_t count, size_t element_size) {
250
+ void *new_contents = contents;
210
- uint32_t new_size = self->size + count;
251
+ uint32_t new_size = size + count;
211
- if (new_size > self->capacity) {
252
+ if (new_size > *capacity) {
212
- uint32_t new_capacity = self->capacity * 2;
253
+ uint32_t new_capacity = *capacity * 2;
213
254
  if (new_capacity < 8) new_capacity = 8;
214
255
  if (new_capacity < new_size) new_capacity = new_size;
215
- _array__reserve(self, element_size, new_capacity);
256
+ new_contents = _array__reserve(contents, capacity, element_size, new_capacity);
216
257
  }
258
+ return new_contents;
217
259
  }
218
260
 
219
261
  /// This is not what you're looking for, see `array_splice`.
220
- static inline void _array__splice(Array *self, size_t element_size,
262
+ static inline void *_array__splice(void *self_contents, uint32_t *size, uint32_t *capacity,
263
+ size_t element_size,
221
264
  uint32_t index, uint32_t old_count,
222
265
  uint32_t new_count, const void *elements) {
223
- uint32_t new_size = self->size + new_count - old_count;
266
+ uint32_t new_size = *size + new_count - old_count;
224
267
  uint32_t old_end = index + old_count;
225
268
  uint32_t new_end = index + new_count;
226
- assert(old_end <= self->size);
269
+ assert(old_end <= *size);
227
270
 
228
- _array__reserve(self, element_size, new_size);
271
+ void *new_contents = _array__reserve(self_contents, capacity, element_size, new_size);
229
272
 
230
- char *contents = (char *)self->contents;
273
+ char *contents = (char *)new_contents;
231
- if (self->size > old_end) {
274
+ if (*size > old_end) {
232
275
  memmove(
233
276
  contents + new_end * element_size,
234
277
  contents + old_end * element_size,
235
- (self->size - old_end) * element_size
278
+ (*size - old_end) * element_size
236
279
  );
237
280
  }
238
281
  if (new_count > 0) {
@@ -250,7 +293,9 @@ static inline void _array__splice(Array *self, size_t element_size,
250
293
  );
251
294
  }
252
295
  }
253
- self->size += new_count - old_count;
296
+ *size += new_count - old_count;
297
+
298
+ return new_contents;
254
299
  }
255
300
 
256
301
  /// A binary search routine, based on Rust's `std::slice::binary_search_by`.
tooling/tree-sitter-plum/src/tree_sitter/parser.h CHANGED
@@ -18,6 +18,11 @@ typedef uint16_t TSStateId;
18
18
  typedef uint16_t TSSymbol;
19
19
  typedef uint16_t TSFieldId;
20
20
  typedef struct TSLanguage TSLanguage;
21
+ typedef struct TSLanguageMetadata {
22
+ uint8_t major_version;
23
+ uint8_t minor_version;
24
+ uint8_t patch_version;
25
+ } TSLanguageMetadata;
21
26
  #endif
22
27
 
23
28
  typedef struct {
@@ -26,10 +31,11 @@ typedef struct {
26
31
  bool inherited;
27
32
  } TSFieldMapEntry;
28
33
 
34
+ // Used to index the field and supertype maps.
29
35
  typedef struct {
30
36
  uint16_t index;
31
37
  uint16_t length;
32
- } TSFieldMapSlice;
38
+ } TSMapSlice;
33
39
 
34
40
  typedef struct {
35
41
  bool visible;
@@ -79,6 +85,12 @@ typedef struct {
79
85
  uint16_t external_lex_state;
80
86
  } TSLexMode;
81
87
 
88
+ typedef struct {
89
+ uint16_t lex_state;
90
+ uint16_t external_lex_state;
91
+ uint16_t reserved_word_set_id;
92
+ } TSLexerMode;
93
+
82
94
  typedef union {
83
95
  TSParseAction action;
84
96
  struct {
@@ -93,7 +105,7 @@ typedef struct {
93
105
  } TSCharacterRange;
94
106
 
95
107
  struct TSLanguage {
96
- uint32_t version;
108
+ uint32_t abi_version;
97
109
  uint32_t symbol_count;
98
110
  uint32_t alias_count;
99
111
  uint32_t token_count;
@@ -109,13 +121,13 @@ struct TSLanguage {
109
121
  const TSParseActionEntry *parse_actions;
110
122
  const char * const *symbol_names;
111
123
  const char * const *field_names;
112
- const TSFieldMapSlice *field_map_slices;
124
+ const TSMapSlice *field_map_slices;
113
125
  const TSFieldMapEntry *field_map_entries;
114
126
  const TSSymbolMetadata *symbol_metadata;
115
127
  const TSSymbol *public_symbol_map;
116
128
  const uint16_t *alias_map;
117
129
  const TSSymbol *alias_sequences;
118
- const TSLexMode *lex_modes;
130
+ const TSLexerMode *lex_modes;
119
131
  bool (*lex_fn)(TSLexer *, TSStateId);
120
132
  bool (*keyword_lex_fn)(TSLexer *, TSStateId);
121
133
  TSSymbol keyword_capture_token;
@@ -129,15 +141,23 @@ struct TSLanguage {
129
141
  void (*deserialize)(void *, const char *, unsigned);
130
142
  } external_scanner;
131
143
  const TSStateId *primary_state_ids;
144
+ const char *name;
145
+ const TSSymbol *reserved_words;
146
+ uint16_t max_reserved_word_set_size;
147
+ uint32_t supertype_count;
148
+ const TSSymbol *supertype_symbols;
149
+ const TSMapSlice *supertype_map_slices;
150
+ const TSSymbol *supertype_map_entries;
151
+ TSLanguageMetadata metadata;
132
152
  };
133
153
 
134
- static inline bool set_contains(TSCharacterRange *ranges, uint32_t len, int32_t lookahead) {
154
+ static inline bool set_contains(const TSCharacterRange *ranges, uint32_t len, int32_t lookahead) {
135
155
  uint32_t index = 0;
136
156
  uint32_t size = len - index;
137
157
  while (size > 1) {
138
158
  uint32_t half_size = size / 2;
139
159
  uint32_t mid_index = index + half_size;
140
- TSCharacterRange *range = &ranges[mid_index];
160
+ const TSCharacterRange *range = &ranges[mid_index];
141
161
  if (lookahead >= range->start && lookahead <= range->end) {
142
162
  return true;
143
163
  } else if (lookahead > range->end) {
@@ -145,7 +165,7 @@ static inline bool set_contains(TSCharacterRange *ranges, uint32_t len, int32_t
145
165
  }
146
166
  size -= half_size;
147
167
  }
148
- TSCharacterRange *range = &ranges[index];
168
+ const TSCharacterRange *range = &ranges[index];
149
169
  return (lookahead >= range->start && lookahead <= range->end);
150
170
  }
151
171
 
tooling/tree-sitter-plum/test/corpus/assign.txt CHANGED
@@ -91,8 +91,8 @@ main() =
91
91
  (expression
92
92
  (primary_expression
93
93
  (fn_call
94
- (fn_identifier)
94
+ (var_identifier)
95
- (argument_list
95
+ (fn_argument_list
96
96
  (expression
97
97
  (primary_expression
98
98
  (string
@@ -116,8 +116,8 @@ main() =
116
116
  (expression
117
117
  (primary_expression
118
118
  (fn_call
119
- (fn_identifier)
119
+ (var_identifier)
120
- (argument_list
120
+ (fn_argument_list
121
121
  (expression
122
122
  (primary_expression
123
123
  (integer)))
@@ -132,29 +132,29 @@ main() =
132
132
  (expression
133
133
  (primary_expression
134
134
  (fn_call
135
- (fn_identifier)
135
+ (var_identifier)
136
- (argument_list
136
+ (fn_argument_list
137
137
  (expression
138
138
  (primary_expression
139
139
  (fn_call
140
- (fn_identifier)
140
+ (var_identifier)
141
- (argument_list
141
+ (fn_argument_list
142
142
  (expression
143
143
  (primary_expression
144
144
  (integer)))))))
145
145
  (expression
146
146
  (primary_expression
147
147
  (fn_call
148
- (fn_identifier)
148
+ (var_identifier)
149
- (argument_list
149
+ (fn_argument_list
150
150
  (expression
151
151
  (primary_expression
152
152
  (integer)))))))
153
153
  (expression
154
154
  (primary_expression
155
155
  (fn_call
156
- (fn_identifier)
156
+ (var_identifier)
157
- (argument_list
157
+ (fn_argument_list
158
158
  (expression
159
159
  (primary_expression
160
160
  (integer))))))))))))
@@ -163,8 +163,8 @@ main() =
163
163
  (expression
164
164
  (primary_expression
165
165
  (fn_call
166
- (fn_identifier)
166
+ (var_identifier)
167
- (argument_list
167
+ (fn_argument_list
168
168
  (pair_argument
169
169
  (string
170
170
  (string_start)
@@ -203,8 +203,8 @@ main() =
203
203
  (expression
204
204
  (primary_expression
205
205
  (fn_call
206
- (fn_identifier)
206
+ (var_identifier)
207
- (argument_list
207
+ (fn_argument_list
208
208
  (pair_argument
209
209
  (string
210
210
  (string_start)
@@ -226,8 +226,8 @@ main() =
226
226
  (expression
227
227
  (primary_expression
228
228
  (fn_call
229
- (fn_identifier)
229
+ (var_identifier)
230
- (argument_list
230
+ (fn_argument_list
231
231
  (pair_argument
232
232
  (string
233
233
  (string_start)
@@ -244,8 +244,8 @@ main() =
244
244
  (expression
245
245
  (primary_expression
246
246
  (fn_call
247
- (fn_identifier)
247
+ (var_identifier)
248
- (argument_list
248
+ (fn_argument_list
249
249
  (pair_argument
250
250
  (string
251
251
  (string_start)
tooling/tree-sitter-plum/test/corpus/const.txt CHANGED
@@ -93,8 +93,8 @@ COUNTRIES_LIST = listOf("US", "INDIA", "CANADA")
93
93
  (expression
94
94
  (primary_expression
95
95
  (fn_call
96
- (fn_identifier)
96
+ (var_identifier)
97
- (argument_list
97
+ (fn_argument_list
98
98
  (expression
99
99
  (primary_expression
100
100
  (string
tooling/tree-sitter-plum/test/corpus/for.txt CHANGED
@@ -25,8 +25,8 @@ main() =
25
25
  (body
26
26
  (primary_expression
27
27
  (fn_call
28
- (fn_identifier)
28
+ (var_identifier)
29
- (argument_list
29
+ (fn_argument_list
30
30
  (expression
31
31
  (primary_expression
32
32
  (string
tooling/tree-sitter-plum/test/corpus/if.txt CHANGED
@@ -31,8 +31,8 @@ main() =
31
31
  (body
32
32
  (primary_expression
33
33
  (fn_call
34
- (fn_identifier)
34
+ (var_identifier)
35
- (argument_list
35
+ (fn_argument_list
36
36
  (expression
37
37
  (primary_expression
38
38
  (string
@@ -49,8 +49,8 @@ main() =
49
49
  (body
50
50
  (primary_expression
51
51
  (fn_call
52
- (fn_identifier)
52
+ (var_identifier)
53
- (argument_list
53
+ (fn_argument_list
54
54
  (expression
55
55
  (comparison_operator
56
56
  (primary_expression
@@ -67,8 +67,8 @@ main() =
67
67
  (body
68
68
  (primary_expression
69
69
  (fn_call
70
- (fn_identifier)
70
+ (var_identifier)
71
- (argument_list
71
+ (fn_argument_list
72
72
  (expression
73
73
  (comparison_operator
74
74
  (primary_expression
@@ -87,8 +87,8 @@ main() =
87
87
  (body
88
88
  (primary_expression
89
89
  (fn_call
90
- (fn_identifier)
90
+ (var_identifier)
91
- (argument_list
91
+ (fn_argument_list
92
92
  (expression
93
93
  (primary_expression
94
94
  (var_identifier)))))))
@@ -96,8 +96,8 @@ main() =
96
96
  (body
97
97
  (primary_expression
98
98
  (fn_call
99
- (fn_identifier)
99
+ (var_identifier)
100
- (argument_list
100
+ (fn_argument_list
101
101
  (expression
102
102
  (primary_expression
103
103
  (string
tooling/tree-sitter-plum/test/corpus/match.txt CHANGED
@@ -4,15 +4,99 @@ match
4
4
 
5
5
  main() =
6
6
  match a
7
- a < b =>
7
+ 1 =>
8
- printLn(a != b)
8
+ printLn(a)
9
- a > 9 =>
9
+ "hi" =>
10
- printLn(a == 9)
10
+ printLn(a)
11
+ True =>
12
+ printLn(a)
11
- a < 9 =>
13
+ Some(b) =>
12
- printLn(b == 0)
14
+ printLn(b)
15
+ x =>
16
+ printLn(x)
13
17
  _ =>
14
- printLn(a == 9)
18
+ printLn(a)
15
19
 
16
20
  --------------------------------------------------------------------------------
17
21
 
22
+ (source
18
- ()
23
+ (fn
24
+ (fn_identifier)
25
+ (body
26
+ (match
27
+ (expression
28
+ (primary_expression
29
+ (var_identifier)))
30
+ (case
31
+ (case_pattern
32
+ (integer))
33
+ (body
34
+ (primary_expression
35
+ (fn_call
36
+ (var_identifier)
37
+ (fn_argument_list
38
+ (expression
39
+ (primary_expression
40
+ (var_identifier))))))))
41
+ (case
42
+ (case_pattern
43
+ (string
44
+ (string_start)
45
+ (string_content)
46
+ (string_end)))
47
+ (body
48
+ (primary_expression
49
+ (fn_call
50
+ (var_identifier)
51
+ (fn_argument_list
52
+ (expression
53
+ (primary_expression
54
+ (var_identifier))))))))
55
+ (case
56
+ (case_pattern
57
+ (type_identifier))
58
+ (body
59
+ (primary_expression
60
+ (fn_call
61
+ (var_identifier)
62
+ (fn_argument_list
63
+ (expression
64
+ (primary_expression
65
+ (var_identifier))))))))
66
+ (case
67
+ (case_pattern
68
+ (class_pattern
69
+ (type_identifier)
70
+ (case_pattern
71
+ (dotted_name
72
+ (var_identifier)))))
73
+ (body
74
+ (primary_expression
75
+ (fn_call
76
+ (var_identifier)
77
+ (fn_argument_list
78
+ (expression
79
+ (primary_expression
80
+ (var_identifier))))))))
81
+ (case
82
+ (case_pattern
83
+ (dotted_name
84
+ (var_identifier)))
85
+ (body
86
+ (primary_expression
87
+ (fn_call
88
+ (var_identifier)
89
+ (fn_argument_list
90
+ (expression
91
+ (primary_expression
92
+ (var_identifier))))))))
93
+ (case
94
+ (case_pattern)
95
+ (body
96
+ (primary_expression
97
+ (fn_call
98
+ (var_identifier)
99
+ (fn_argument_list
100
+ (expression
101
+ (primary_expression
102
+ (var_identifier))))))))))))
tooling/tree-sitter-plum/test/corpus/type.txt CHANGED
@@ -69,6 +69,29 @@ toStr<Cat>() -> Str =
69
69
  (expression
70
70
  (primary_expression
71
71
  (integer))))))))
72
+ (fn
73
+ (fn_identifier)
74
+ (type
75
+ (type_identifier))
76
+ (param
77
+ (var_identifier)
78
+ (type
79
+ (type_identifier)))
80
+ (return_type
81
+ (type_identifier))
82
+ (body
83
+ (primary_expression
84
+ (class_call
85
+ (type_identifier)
86
+ (class_argument_list
87
+ (var_identifier)
88
+ (expression
89
+ (primary_expression
90
+ (var_identifier)))
91
+ (var_identifier)
92
+ (expression
93
+ (primary_expression
94
+ (integer))))))))
72
95
  (fn
73
96
  (fn_identifier)
74
97
  (type
@@ -110,13 +133,13 @@ toStr<Cat>() -> Str =
110
133
  (attribute
111
134
  (primary_expression
112
135
  (self))
113
- (var_identifier))))
136
+ (fn_identifier))))
114
137
  (string_content)
115
138
  (interpolation
116
139
  (primary_expression
117
140
  (attribute
118
141
  (primary_expression
119
142
  (self))
120
- (var_identifier))))
143
+ (fn_identifier))))
121
144
  (string_content)
122
145
  (string_end))))))
tooling/tree-sitter-plum/test/corpus/while.txt CHANGED
@@ -38,8 +38,8 @@ main() =
38
38
  (integer))))))
39
39
  (primary_expression
40
40
  (fn_call
41
- (fn_identifier)
41
+ (var_identifier)
42
- (argument_list
42
+ (fn_argument_list
43
43
  (expression
44
44
  (primary_expression
45
45
  (string
tooling/tree-sitter-plum/tree-sitter.json CHANGED
@@ -9,13 +9,13 @@
9
9
  "plum"
10
10
  ],
11
11
  "highlights": [
12
- "queries/highlights.scm"
12
+ "queries/plum/highlights.scm"
13
13
  ],
14
14
  "tags": [
15
- "queries/tags.scm"
15
+ "queries/plum/tags.scm"
16
16
  ],
17
17
  "indents": [
18
- "queries/indents.scm"
18
+ "queries/plum/indents.scm"
19
19
  ],
20
20
  "injection-regex": "plum"
21
21
  }