tree-sitter-bynk 0.238.0 → 0.239.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/grammar.js CHANGED
@@ -184,12 +184,16 @@ module.exports = grammar({
184
184
  $.fn_decl,
185
185
  $.messages_decl,
186
186
  // Permissive: capability/service/etc. can syntactically appear
187
- // anywhere — the LSP reports semantic placement errors.
187
+ // anywhere — the LSP reports semantic placement errors. Events
188
+ // track slice 0 (spine #936): `event` follows the same permissive
189
+ // precedent (`bynk.event.outside_context` rejects it here, at the
190
+ // checker, not the grammar).
188
191
  $.capability_decl,
189
192
  $.provider_decl,
190
193
  $.service_decl,
191
194
  $.agent_decl,
192
195
  $.actor_decl,
196
+ $.event_decl,
193
197
  ),
194
198
 
195
199
  _context_body_item: ($) =>
@@ -205,6 +209,7 @@ module.exports = grammar({
205
209
  $.agent_decl,
206
210
  $.actor_decl,
207
211
  $.messages_decl,
212
+ $.event_decl,
208
213
  ),
209
214
 
210
215
  // v0.17: adapter items — a binding clause, capabilities, boundary types,
@@ -226,6 +231,7 @@ module.exports = grammar({
226
231
  $.agent_decl,
227
232
  $.actor_decl,
228
233
  $.messages_decl,
234
+ $.event_decl,
229
235
  ),
230
236
 
231
237
  _test_body_item: ($) =>
@@ -338,6 +344,18 @@ module.exports = grammar({
338
344
  optional(seq("=", field("init", $._expression))),
339
345
  ),
340
346
 
347
+ // Events track, slice 0 (spine #936): `event Name = { fields }` — a
348
+ // typed fact a context may emit and other contexts' subscriber services
349
+ // may receive. Record body only (mirrors `record_type`, not the full
350
+ // `_type_body` choice — no sum/opaque/refined event shapes).
351
+ event_decl: ($) =>
352
+ seq(
353
+ "event",
354
+ field("name", $.identifier),
355
+ "=",
356
+ field("body", $.record_type),
357
+ ),
358
+
341
359
  // v0.154 (ADR 0178): a sum body may carry a trailing `embeds E as V, …`
342
360
  // clause declaring error embeddings the `?` operator auto-converts.
343
361
  // `embeds`/`as` are contextual — matched only in this position.
@@ -702,6 +720,12 @@ module.exports = grammar({
702
720
  // types. `websocket`, `in`, and `out` are contextual (resolved by `word`).
703
721
  // #548: `websocket` lowercased to match the other protocol sources (was
704
722
  // `WebSocket`).
723
+ // Events track, slice 0 (spine #936): `from Events(E)`, optionally
724
+ // filtered by a slice-1 structural pattern, `from Events(E { field:
725
+ // value, .. })`. `Events`, capitalised, is matched as plain `identifier`
726
+ // text the same way `websocket` is matched lowercase — it names the
727
+ // `Events` capability directly, not a built-in type name, so no lexer
728
+ // reservation.
705
729
  service_protocol: ($) =>
706
730
  seq(
707
731
  "from",
@@ -722,6 +746,47 @@ module.exports = grammar({
722
746
  optional(","),
723
747
  ")",
724
748
  ),
749
+ seq(
750
+ "Events",
751
+ "(",
752
+ field("event_type", $._type_ref),
753
+ optional(field("pattern", $.event_pattern)),
754
+ ")",
755
+ ),
756
+ ),
757
+ ),
758
+ // Events track, slice 1 (spine #936): the structural delivery filter on
759
+ // a subscription header. A trailing `..` is mandatory whenever any field
760
+ // is listed — mirrors the hand-written parser's `bynk.parse.
761
+ // event_pattern_empty` rejection of `Events(E { })`. `..` is one literal
762
+ // token here (not two `.`s), keeping this grammar in agreement with the
763
+ // Rust lexer's dedicated `DotDot` token.
764
+ event_pattern: ($) =>
765
+ seq(
766
+ "{",
767
+ repeat(seq(field("field", $.event_pattern_field), ",")),
768
+ "..",
769
+ "}",
770
+ ),
771
+ event_pattern_field: ($) =>
772
+ seq(
773
+ field("name", $.identifier),
774
+ ":",
775
+ field("value", $.event_pattern_value),
776
+ ),
777
+ // A closed set, mirroring `literal_pattern` plus a nullary-variant
778
+ // reference (`variant_pattern` without a payload list — no nested
779
+ // sub-patterns in v1). The checker separately rejects a payload-carrying
780
+ // variant (`bynk.event.pattern_variant_payload`) since the grammar has
781
+ // no payload-list position here to reject it structurally.
782
+ event_pattern_value: ($) =>
783
+ choice(
784
+ seq(optional("-"), $.number_literal),
785
+ $.string_literal,
786
+ $.boolean_literal,
787
+ seq(
788
+ optional(seq(field("type", $.identifier), ".")),
789
+ field("variant", $.identifier),
725
790
  ),
726
791
  ),
727
792
 
@@ -807,6 +872,27 @@ module.exports = grammar({
807
872
  // queue-handler shape (the protocol on the service header disambiguates).
808
873
  $.ws_open_handler,
809
874
  $.ws_close_handler,
875
+ // Events track, slice 0 (spine #936): a `from Events(E)` service's
876
+ // one handler.
877
+ $.event_handler,
878
+ ),
879
+ // Events track, slice 0 (spine #936): `on event(e: E) -> Effect[()] { … }`
880
+ // — a `from Events(E)` subscriber's one handler. Same generic shape as
881
+ // every other handler form (params/by/given/body all uniform); the
882
+ // checker verifies the param count/type against the service header.
883
+ event_handler: ($) =>
884
+ seq(
885
+ "on",
886
+ "event",
887
+ "(",
888
+ optional(sep1($.param, ",")),
889
+ optional(","),
890
+ ")",
891
+ "->",
892
+ field("return_type", $._type_ref),
893
+ optional(field("by", $.by_clause)),
894
+ optional(field("given", $.given_clause)),
895
+ field("body", $.block),
810
896
  ),
811
897
  call_handler: ($) =>
812
898
  seq(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tree-sitter-bynk",
3
- "version": "0.238.0",
3
+ "version": "0.239.0",
4
4
  "description": "Tree-sitter grammar for the Bynk DSL (v0–v0.16).",
5
5
  "main": "bindings/node",
6
6
  "types": "bindings/node",
@@ -23,6 +23,7 @@
23
23
  "websocket"
24
24
  "schedule"
25
25
  "message"
26
+ "Events"
26
27
  ] @keyword
27
28
 
28
29
  [
@@ -55,6 +56,7 @@
55
56
  "requires"
56
57
  "ensures"
57
58
  "messages"
59
+ "event"
58
60
  ] @keyword.declaration
59
61
 
60
62
  [
@@ -111,6 +113,12 @@
111
113
 
112
114
  ; User-defined type names appear in type positions.
113
115
  (type_decl name: (identifier) @type)
116
+ ; Events track slice 0/1 (spine #936): an `event` declaration names a type,
117
+ ; like `type_decl`; the header's `event_type` and a pattern field's
118
+ ; qualifier both reference one.
119
+ (event_decl name: (identifier) @type)
120
+ (service_protocol event_type: (identifier) @type)
121
+ (event_pattern_value type: (identifier) @type)
114
122
  (opaque_type) @type
115
123
  (generic_type_ref arg: (identifier) @type)
116
124
  ; v0.157 (ADR 0183): a user generic-type application — the head name and each
@@ -159,6 +167,8 @@
159
167
  (field_init name: (identifier) @field)
160
168
  (field_init shorthand: (identifier) @field)
161
169
  (named_binding field: (identifier) @field)
170
+ ; Events track slice 1 (spine #936): a subscription pattern's field name.
171
+ (event_pattern_field name: (identifier) @field)
162
172
 
163
173
  ; -- Variants & constants --
164
174
 
@@ -174,6 +184,13 @@
174
184
  ; `positional_binding` capture now that the payload position is a full pattern.
175
185
  ((variant_pattern variant: (identifier) @variable)
176
186
  (#match? @variable "^[a-z_]"))
187
+ ; Events track slice 1 (spine #936): a subscription pattern's variant value
188
+ ; (`region: Region.Domestic` / bare `Domestic`) — always a nullary reference
189
+ ; (the checker rejects a payload-carrying variant), so unlike
190
+ ; `variant_pattern` there is no binding-vs-tag ambiguity; still keyed on
191
+ ; capitalisation for consistency with every other variant reference.
192
+ ((event_pattern_value variant: (identifier) @constant)
193
+ (#match? @constant "^[A-Z]"))
177
194
  (boolean_literal) @constant.builtin
178
195
 
179
196
  ; -- Literals --
package/src/grammar.json CHANGED
@@ -406,6 +406,10 @@
406
406
  {
407
407
  "type": "SYMBOL",
408
408
  "name": "actor_decl"
409
+ },
410
+ {
411
+ "type": "SYMBOL",
412
+ "name": "event_decl"
409
413
  }
410
414
  ]
411
415
  },
@@ -455,6 +459,10 @@
455
459
  {
456
460
  "type": "SYMBOL",
457
461
  "name": "messages_decl"
462
+ },
463
+ {
464
+ "type": "SYMBOL",
465
+ "name": "event_decl"
458
466
  }
459
467
  ]
460
468
  },
@@ -508,6 +516,10 @@
508
516
  {
509
517
  "type": "SYMBOL",
510
518
  "name": "messages_decl"
519
+ },
520
+ {
521
+ "type": "SYMBOL",
522
+ "name": "event_decl"
511
523
  }
512
524
  ]
513
525
  },
@@ -1194,6 +1206,35 @@
1194
1206
  }
1195
1207
  ]
1196
1208
  },
1209
+ "event_decl": {
1210
+ "type": "SEQ",
1211
+ "members": [
1212
+ {
1213
+ "type": "STRING",
1214
+ "value": "event"
1215
+ },
1216
+ {
1217
+ "type": "FIELD",
1218
+ "name": "name",
1219
+ "content": {
1220
+ "type": "SYMBOL",
1221
+ "name": "identifier"
1222
+ }
1223
+ },
1224
+ {
1225
+ "type": "STRING",
1226
+ "value": "="
1227
+ },
1228
+ {
1229
+ "type": "FIELD",
1230
+ "name": "body",
1231
+ "content": {
1232
+ "type": "SYMBOL",
1233
+ "name": "record_type"
1234
+ }
1235
+ }
1236
+ ]
1237
+ },
1197
1238
  "sum_type": {
1198
1239
  "type": "PREC_RIGHT",
1199
1240
  "value": 0,
@@ -3170,6 +3211,181 @@
3170
3211
  "value": ")"
3171
3212
  }
3172
3213
  ]
3214
+ },
3215
+ {
3216
+ "type": "SEQ",
3217
+ "members": [
3218
+ {
3219
+ "type": "STRING",
3220
+ "value": "Events"
3221
+ },
3222
+ {
3223
+ "type": "STRING",
3224
+ "value": "("
3225
+ },
3226
+ {
3227
+ "type": "FIELD",
3228
+ "name": "event_type",
3229
+ "content": {
3230
+ "type": "SYMBOL",
3231
+ "name": "_type_ref"
3232
+ }
3233
+ },
3234
+ {
3235
+ "type": "CHOICE",
3236
+ "members": [
3237
+ {
3238
+ "type": "FIELD",
3239
+ "name": "pattern",
3240
+ "content": {
3241
+ "type": "SYMBOL",
3242
+ "name": "event_pattern"
3243
+ }
3244
+ },
3245
+ {
3246
+ "type": "BLANK"
3247
+ }
3248
+ ]
3249
+ },
3250
+ {
3251
+ "type": "STRING",
3252
+ "value": ")"
3253
+ }
3254
+ ]
3255
+ }
3256
+ ]
3257
+ }
3258
+ ]
3259
+ },
3260
+ "event_pattern": {
3261
+ "type": "SEQ",
3262
+ "members": [
3263
+ {
3264
+ "type": "STRING",
3265
+ "value": "{"
3266
+ },
3267
+ {
3268
+ "type": "REPEAT",
3269
+ "content": {
3270
+ "type": "SEQ",
3271
+ "members": [
3272
+ {
3273
+ "type": "FIELD",
3274
+ "name": "field",
3275
+ "content": {
3276
+ "type": "SYMBOL",
3277
+ "name": "event_pattern_field"
3278
+ }
3279
+ },
3280
+ {
3281
+ "type": "STRING",
3282
+ "value": ","
3283
+ }
3284
+ ]
3285
+ }
3286
+ },
3287
+ {
3288
+ "type": "STRING",
3289
+ "value": ".."
3290
+ },
3291
+ {
3292
+ "type": "STRING",
3293
+ "value": "}"
3294
+ }
3295
+ ]
3296
+ },
3297
+ "event_pattern_field": {
3298
+ "type": "SEQ",
3299
+ "members": [
3300
+ {
3301
+ "type": "FIELD",
3302
+ "name": "name",
3303
+ "content": {
3304
+ "type": "SYMBOL",
3305
+ "name": "identifier"
3306
+ }
3307
+ },
3308
+ {
3309
+ "type": "STRING",
3310
+ "value": ":"
3311
+ },
3312
+ {
3313
+ "type": "FIELD",
3314
+ "name": "value",
3315
+ "content": {
3316
+ "type": "SYMBOL",
3317
+ "name": "event_pattern_value"
3318
+ }
3319
+ }
3320
+ ]
3321
+ },
3322
+ "event_pattern_value": {
3323
+ "type": "CHOICE",
3324
+ "members": [
3325
+ {
3326
+ "type": "SEQ",
3327
+ "members": [
3328
+ {
3329
+ "type": "CHOICE",
3330
+ "members": [
3331
+ {
3332
+ "type": "STRING",
3333
+ "value": "-"
3334
+ },
3335
+ {
3336
+ "type": "BLANK"
3337
+ }
3338
+ ]
3339
+ },
3340
+ {
3341
+ "type": "SYMBOL",
3342
+ "name": "number_literal"
3343
+ }
3344
+ ]
3345
+ },
3346
+ {
3347
+ "type": "SYMBOL",
3348
+ "name": "string_literal"
3349
+ },
3350
+ {
3351
+ "type": "SYMBOL",
3352
+ "name": "boolean_literal"
3353
+ },
3354
+ {
3355
+ "type": "SEQ",
3356
+ "members": [
3357
+ {
3358
+ "type": "CHOICE",
3359
+ "members": [
3360
+ {
3361
+ "type": "SEQ",
3362
+ "members": [
3363
+ {
3364
+ "type": "FIELD",
3365
+ "name": "type",
3366
+ "content": {
3367
+ "type": "SYMBOL",
3368
+ "name": "identifier"
3369
+ }
3370
+ },
3371
+ {
3372
+ "type": "STRING",
3373
+ "value": "."
3374
+ }
3375
+ ]
3376
+ },
3377
+ {
3378
+ "type": "BLANK"
3379
+ }
3380
+ ]
3381
+ },
3382
+ {
3383
+ "type": "FIELD",
3384
+ "name": "variant",
3385
+ "content": {
3386
+ "type": "SYMBOL",
3387
+ "name": "identifier"
3388
+ }
3173
3389
  }
3174
3390
  ]
3175
3391
  }
@@ -3596,6 +3812,128 @@
3596
3812
  {
3597
3813
  "type": "SYMBOL",
3598
3814
  "name": "ws_close_handler"
3815
+ },
3816
+ {
3817
+ "type": "SYMBOL",
3818
+ "name": "event_handler"
3819
+ }
3820
+ ]
3821
+ },
3822
+ "event_handler": {
3823
+ "type": "SEQ",
3824
+ "members": [
3825
+ {
3826
+ "type": "STRING",
3827
+ "value": "on"
3828
+ },
3829
+ {
3830
+ "type": "STRING",
3831
+ "value": "event"
3832
+ },
3833
+ {
3834
+ "type": "STRING",
3835
+ "value": "("
3836
+ },
3837
+ {
3838
+ "type": "CHOICE",
3839
+ "members": [
3840
+ {
3841
+ "type": "SEQ",
3842
+ "members": [
3843
+ {
3844
+ "type": "SYMBOL",
3845
+ "name": "param"
3846
+ },
3847
+ {
3848
+ "type": "REPEAT",
3849
+ "content": {
3850
+ "type": "SEQ",
3851
+ "members": [
3852
+ {
3853
+ "type": "STRING",
3854
+ "value": ","
3855
+ },
3856
+ {
3857
+ "type": "SYMBOL",
3858
+ "name": "param"
3859
+ }
3860
+ ]
3861
+ }
3862
+ }
3863
+ ]
3864
+ },
3865
+ {
3866
+ "type": "BLANK"
3867
+ }
3868
+ ]
3869
+ },
3870
+ {
3871
+ "type": "CHOICE",
3872
+ "members": [
3873
+ {
3874
+ "type": "STRING",
3875
+ "value": ","
3876
+ },
3877
+ {
3878
+ "type": "BLANK"
3879
+ }
3880
+ ]
3881
+ },
3882
+ {
3883
+ "type": "STRING",
3884
+ "value": ")"
3885
+ },
3886
+ {
3887
+ "type": "STRING",
3888
+ "value": "->"
3889
+ },
3890
+ {
3891
+ "type": "FIELD",
3892
+ "name": "return_type",
3893
+ "content": {
3894
+ "type": "SYMBOL",
3895
+ "name": "_type_ref"
3896
+ }
3897
+ },
3898
+ {
3899
+ "type": "CHOICE",
3900
+ "members": [
3901
+ {
3902
+ "type": "FIELD",
3903
+ "name": "by",
3904
+ "content": {
3905
+ "type": "SYMBOL",
3906
+ "name": "by_clause"
3907
+ }
3908
+ },
3909
+ {
3910
+ "type": "BLANK"
3911
+ }
3912
+ ]
3913
+ },
3914
+ {
3915
+ "type": "CHOICE",
3916
+ "members": [
3917
+ {
3918
+ "type": "FIELD",
3919
+ "name": "given",
3920
+ "content": {
3921
+ "type": "SYMBOL",
3922
+ "name": "given_clause"
3923
+ }
3924
+ },
3925
+ {
3926
+ "type": "BLANK"
3927
+ }
3928
+ ]
3929
+ },
3930
+ {
3931
+ "type": "FIELD",
3932
+ "name": "body",
3933
+ "content": {
3934
+ "type": "SYMBOL",
3935
+ "name": "block"
3936
+ }
3599
3937
  }
3600
3938
  ]
3601
3939
  },