tree-sitter-bynk 0.111.0 → 0.120.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
@@ -22,7 +22,7 @@
22
22
  // @ts-check
23
23
 
24
24
  const PREC = {
25
- assert: 0,
25
+ expect: 0,
26
26
  // v0.80: `implies` is the lowest-precedence binary operator (below `||`).
27
27
  implies: 1,
28
28
  or: 2,
@@ -59,6 +59,15 @@ module.exports = grammar({
59
59
  // closing `)` is followed — or not — by `=>`.
60
60
  [$.lambda_param, $._primary],
61
61
  [$._primary, $.lambda_expr],
62
+ // v0.117: after `expect Cap.op called`, one token of lookahead can't tell a
63
+ // following `<n> times` count from the end of the observation — GLR keeps
64
+ // both parses alive until the next token decides.
65
+ [$.observation_expr],
66
+ // The subject `Cap.op` overlaps a `field_access` (start of an ordinary
67
+ // predicate); both parses survive until the token after the op reveals
68
+ // whether a matcher (`called`/`never`/`before`) or an ordinary continuation
69
+ // (`(`, an operator, …) follows.
70
+ [$.observation_expr, $._primary],
62
71
  ],
63
72
 
64
73
  rules: {
@@ -86,8 +95,7 @@ module.exports = grammar({
86
95
  $.commons_decl,
87
96
  $.context_decl,
88
97
  $.adapter_decl,
89
- $.integration_decl,
90
- $.test_decl,
98
+ $.suite_decl,
91
99
  ),
92
100
  ),
93
101
  repeat1($._item_fragment),
@@ -144,11 +152,16 @@ module.exports = grammar({
144
152
  // (a test case is `test "string" …`, so it never collides with a new
145
153
  // `test <qualified_name>` unit — but the disambiguation needs one extra
146
154
  // token of lookahead, handled by a declared conflict).
147
- test_decl: ($) =>
155
+ // v0.118 (testing track slice 6): an optional `as <tier>` classifier —
156
+ // `unit` | `integration` | `system`. The tier words are contextual (they
157
+ // lex as ordinary identifiers except right after `as` in a suite/case
158
+ // header), like the observation matcher words.
159
+ suite_decl: ($) =>
148
160
  prec.right(
149
161
  seq(
150
- "test",
162
+ "suite",
151
163
  field("target", $.qualified_name),
164
+ optional(seq("as", field("tier", choice("unit", "integration", "system")))),
152
165
  choice(
153
166
  seq("{", repeat($._test_body_item), "}"),
154
167
  repeat($._test_body_item),
@@ -156,27 +169,6 @@ module.exports = grammar({
156
169
  ),
157
170
  ),
158
171
 
159
- // v0.16: a multi-Worker integration test. `integration` is contextual
160
- // after `test` and before the suite-name string; `wires` lists the
161
- // participating contexts. Body holds `uses` and `test "name"` cases (no
162
- // `mocks` — integration tests wire real implementations).
163
- integration_decl: ($) =>
164
- prec.right(
165
- seq(
166
- "test",
167
- "integration",
168
- field("name", $.string_literal),
169
- choice(
170
- seq("{", $.wires_decl, repeat($._integration_body_item), "}"),
171
- seq($.wires_decl, repeat($._integration_body_item)),
172
- ),
173
- ),
174
- ),
175
-
176
- wires_decl: ($) => seq("wires", sep1(field("participant", $.qualified_name), ",")),
177
-
178
- _integration_body_item: ($) => choice($.uses_decl, $.test_case),
179
-
180
172
  qualified_name: ($) => sep1($.identifier, "."),
181
173
 
182
174
  _commons_body_item: ($) =>
@@ -228,7 +220,7 @@ module.exports = grammar({
228
220
  ),
229
221
 
230
222
  _test_body_item: ($) =>
231
- choice($.uses_decl, $.consumes_decl, $.mocks_decl, $.test_case),
223
+ choice($.uses_decl, $.consumes_decl, $.provides_clause, $.case, $.property_decl),
232
224
 
233
225
  // -- Headers / clauses --
234
226
 
@@ -440,6 +432,9 @@ module.exports = grammar({
440
432
  alias("Stream", $.builtin_type),
441
433
  alias("Query", $.builtin_type),
442
434
  alias("Connection", $.builtin_type),
435
+ // v0.119 (testing track slice 7): `History[Agent]` — a generated,
436
+ // driven call-history (test-only generator).
437
+ alias("History", $.builtin_type),
443
438
  ),
444
439
  ),
445
440
  "[",
@@ -460,11 +455,23 @@ module.exports = grammar({
460
455
  ")",
461
456
  "->",
462
457
  field("return_type", $._type_ref),
458
+ // v0.115: contract clauses between the return type and the body.
459
+ repeat($.requires_clause),
460
+ repeat($.ensures_clause),
463
461
  field("body", $.block),
464
462
  ),
465
463
  method_name: ($) =>
466
464
  seq(field("type", $.identifier), ".", field("method", $.identifier)),
467
465
 
466
+ // v0.115 (testing track slice 3): a function contract clause. `requires` is a
467
+ // precondition over the parameters; `ensures` is a postcondition over the
468
+ // parameters and the contextual `result` binding. The predicate is the one
469
+ // predicate surface (same grammar as an `invariant_decl`).
470
+ requires_clause: ($) =>
471
+ seq("requires", field("name", $.identifier), ":", field("predicate", $._expression)),
472
+ ensures_clause: ($) =>
473
+ seq("ensures", field("name", $.identifier), ":", field("predicate", $._expression)),
474
+
468
475
  _params: ($) =>
469
476
  seq(
470
477
  choice($.self_param, $.param),
@@ -571,7 +578,7 @@ module.exports = grammar({
571
578
  field("key", $.key_decl),
572
579
  // v0.81 (storage track): the agent's `store` fields (ADR 0108).
573
580
  repeat($.store_field),
574
- repeat($.invariant_decl),
581
+ repeat(choice($.invariant_decl, $.transition_decl)),
575
582
  repeat($.handler),
576
583
  "}",
577
584
  ),
@@ -584,6 +591,17 @@ module.exports = grammar({
584
591
  ":",
585
592
  field("predicate", $._expression),
586
593
  ),
594
+ // v0.116 (testing track slice 4): an agent step invariant —
595
+ // `transition <name>: <predicate over old/new>`. Sits beside the snapshot
596
+ // invariants, between the store fields and the handlers. `old`/`new` are
597
+ // ordinary identifiers in the predicate (contextual, not keywords).
598
+ transition_decl: ($) =>
599
+ seq(
600
+ "transition",
601
+ field("name", $.identifier),
602
+ ":",
603
+ field("predicate", $._expression),
604
+ ),
587
605
  key_decl: ($) =>
588
606
  seq("key", field("name", $.identifier), ":", field("type", $._type_ref)),
589
607
  // v0.81 (storage track): `store <name>: <Kind>[…] [= init]`. `store` is a
@@ -805,18 +823,85 @@ module.exports = grammar({
805
823
 
806
824
  // -- v0.7: test bodies --
807
825
 
808
- mocks_decl: ($) =>
826
+ // v0.118 (testing track slice 6): a test-scope stub for one capability
827
+ // operation — `provides Cap.op(<arg pattern>, …) <rhs>`. Distinguished from
828
+ // the production provider declaration (`provides Cap = Impl …`) by the
829
+ // `.op(` shape, and only admitted inside a suite/case body. An arg pattern
830
+ // is `_` (any) or a value expression; the right-hand side is
831
+ // `returns <expr>`, `returns each [ <outcome>, … ]` (a scripted sequence,
832
+ // where an outcome is `fails` or an expr), or `fails`. `returns`/`each`/
833
+ // `fails` are contextual words.
834
+ provides_clause: ($) =>
809
835
  seq(
810
- "mocks",
811
- field("capability", $.identifier),
812
- "=",
813
- field("impl", $.identifier),
836
+ "provides",
837
+ field("cap", $.identifier),
838
+ ".",
839
+ field("op", $.identifier),
840
+ "(",
841
+ optional(
842
+ seq(
843
+ sep1(field("arg", choice(alias("_", $.wildcard), $._expression)), ","),
844
+ optional(","),
845
+ ),
846
+ ),
847
+ ")",
848
+ choice(
849
+ seq(
850
+ "returns",
851
+ "each",
852
+ "[",
853
+ optional(
854
+ seq(
855
+ sep1(field("outcome", choice("fails", $._expression)), ","),
856
+ optional(","),
857
+ ),
858
+ ),
859
+ "]",
860
+ ),
861
+ seq("returns", field("value", $._expression)),
862
+ "fails",
863
+ ),
864
+ ),
865
+ // v0.118: an optional `as <tier>` classifier plus a body of leading
866
+ // `provides` stubs, then the ordinary statements and tail. The tier words
867
+ // (`unit`/`integration`/`system`) are contextual, as on `suite_decl`.
868
+ case: ($) =>
869
+ seq(
870
+ "case",
871
+ field("name", $.string_literal),
872
+ optional(seq("as", field("tier", choice("unit", "integration", "system")))),
873
+ "{",
874
+ repeat($.provides_clause),
875
+ repeat($._statement),
876
+ optional(field("tail", $._expression)),
877
+ "}",
878
+ ),
879
+
880
+ // v0.114 (testing track slice 2): a generative `property` — its body is a
881
+ // single `for all` binder over generated inhabitants of each binding's type.
882
+ property_decl: ($) =>
883
+ seq(
884
+ "property",
885
+ field("name", $.string_literal),
814
886
  "{",
815
- repeat($.provider_op),
887
+ field("forall", $.for_all),
816
888
  "}",
817
889
  ),
818
- test_case: ($) =>
819
- seq("test", field("name", $.string_literal), field("body", $.block)),
890
+
891
+ // `for all x: T, y: U where <pred> { … expect … }` — the generated bindings,
892
+ // an optional `where` filter, and the predicate body.
893
+ for_all: ($) =>
894
+ seq(
895
+ "for",
896
+ "all",
897
+ $.for_all_binding,
898
+ repeat(seq(",", $.for_all_binding)),
899
+ optional(seq("where", field("filter", $._expression))),
900
+ field("body", $.block),
901
+ ),
902
+
903
+ for_all_binding: ($) =>
904
+ seq(field("name", $.identifier), ":", field("type", $._type_ref)),
820
905
 
821
906
  // -- Block & statements --
822
907
 
@@ -834,7 +919,7 @@ module.exports = grammar({
834
919
  $.effect_let_stmt,
835
920
  $.effect_send_stmt,
836
921
  $.assign_stmt,
837
- prec(1, $.assert_expr),
922
+ prec(1, $.expect_expr),
838
923
  ),
839
924
 
840
925
  let_stmt: ($) =>
@@ -869,15 +954,64 @@ module.exports = grammar({
869
954
  $.if_expr,
870
955
  $.match_expr,
871
956
  $.is_expr,
872
- $.assert_expr,
957
+ $.expect_expr,
873
958
  $.binary_expr,
874
959
  $.unary_expr,
875
960
  $._primary,
876
961
  ),
877
962
 
878
963
  // v0.9.1: `assert` is an expression of type `()`.
879
- assert_expr: ($) =>
880
- prec.right(PREC.assert, seq("assert", field("cond", $._expression))),
964
+ // v0.117 (testing track slice 5): `expect` also admits an observation over a
965
+ // capability seam (`expect Cap.op called …`), sitting ahead of the ordinary
966
+ // predicate. The subject `Cap.op` overlaps a `field_access`, so the matcher
967
+ // words disambiguate contextually.
968
+ expect_expr: ($) =>
969
+ prec.right(
970
+ PREC.expect,
971
+ seq("expect", field("cond", choice($.observation_expr, $._expression))),
972
+ ),
973
+
974
+ // v0.117: an observation — a `Cap.op` seam reference followed by one of the
975
+ // sugar matchers. `called` / `never` / `once` / `times` / `with` / `before`
976
+ // are contextual (state-lexed as keywords only here; ordinary identifiers
977
+ // elsewhere), mirroring the compiler's lookahead parse (DECISION F3).
978
+ observation_expr: ($) =>
979
+ seq(
980
+ field("cap", $.identifier),
981
+ ".",
982
+ field("op", $.identifier),
983
+ choice(
984
+ seq(
985
+ "called",
986
+ // An optional call-count matcher: `once` or `<n> times`.
987
+ optional(choice("once", seq(field("count", $.number_literal), "times"))),
988
+ optional(seq("with", field("predicate", $._expression))),
989
+ ),
990
+ seq("never", "called"),
991
+ seq(
992
+ "before",
993
+ field("other_cap", $.identifier),
994
+ ".",
995
+ field("other_op", $.identifier),
996
+ ),
997
+ ),
998
+ ),
999
+
1000
+ // v0.117: `trace(Cap.op)` — the escape hatch yielding the recorded calls as a
1001
+ // `List` of per-op records. A test-only builtin recognised by its
1002
+ // `trace ( Ident . Ident )` shape.
1003
+ trace_expr: ($) =>
1004
+ prec(
1005
+ PREC.postfix + 1,
1006
+ seq(
1007
+ "trace",
1008
+ "(",
1009
+ field("cap", $.identifier),
1010
+ ".",
1011
+ field("op", $.identifier),
1012
+ ")",
1013
+ ),
1014
+ ),
881
1015
 
882
1016
  if_expr: ($) =>
883
1017
  seq(
@@ -980,7 +1114,8 @@ module.exports = grammar({
980
1114
  $.some_expr,
981
1115
  $.none_expr,
982
1116
  $.effect_pure_expr,
983
- $.mock_expr,
1117
+ $.val_expr,
1118
+ $.trace_expr,
984
1119
  $.list_literal,
985
1120
  $.block,
986
1121
  $.number_literal,
@@ -1105,23 +1240,23 @@ module.exports = grammar({
1105
1240
  effect_pure_expr: ($) =>
1106
1241
  seq("Effect", ".", "pure", "(", $._expression, ")"),
1107
1242
 
1108
- // v0.9.4 Part B: `Mock[T]` test-context construction. The `[ … ]` here is
1109
- // the bracket syntax otherwise reserved for generics; in expression
1110
- // position it carries the mocked type. The optional argument is either a
1111
- // parenthesised literal-/variant-pin or a brace record-override (the latter
1112
- // reuses `field_init`, identical to record construction). The test-context
1113
- // restriction is semantic and left to the LSP.
1114
- mock_expr: ($) =>
1243
+ // v0.114 (was `Mock[T]`, v0.9.4): `Val[T]` test-context value fabrication.
1244
+ // The `[ … ]` here is the bracket syntax otherwise reserved for generics; in
1245
+ // expression position it carries the fabricated type. The optional argument
1246
+ // is either a parenthesised literal-/variant-pin or a brace record-override
1247
+ // (the latter reuses `field_init`, identical to record construction). The
1248
+ // test-context restriction is semantic and left to the LSP.
1249
+ val_expr: ($) =>
1115
1250
  prec.right(
1116
1251
  seq(
1117
- "Mock",
1252
+ "Val",
1118
1253
  "[",
1119
1254
  field("type", $._type_ref),
1120
1255
  "]",
1121
- optional(field("arg", $.mock_arg)),
1256
+ optional(field("arg", $.val_arg)),
1122
1257
  ),
1123
1258
  ),
1124
- mock_arg: ($) =>
1259
+ val_arg: ($) =>
1125
1260
  choice(
1126
1261
  seq("(", sep1(field("pin", $._expression), ","), optional(","), ")"),
1127
1262
  seq("{", optional(sep1($.field_init, ",")), optional(","), "}"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tree-sitter-bynk",
3
- "version": "0.111.0",
3
+ "version": "0.120.0",
4
4
  "description": "Tree-sitter grammar for the Bynk DSL (v0–v0.16).",
5
5
  "main": "bindings/node",
6
6
  "types": "bindings/node",
@@ -11,7 +11,7 @@
11
11
  "let"
12
12
  "match"
13
13
  "is"
14
- "assert"
14
+ "expect"
15
15
  "on"
16
16
  "given"
17
17
  "call"
@@ -41,11 +41,13 @@
41
41
  "store"
42
42
  "exports"
43
43
  "key"
44
- "test"
45
- "mocks"
46
- "integration"
47
- "wires"
44
+ "suite"
45
+ "case"
46
+ "property"
48
47
  "invariant"
48
+ "transition"
49
+ "requires"
50
+ "ensures"
49
51
  ] @keyword.declaration
50
52
 
51
53
  [
@@ -58,8 +60,38 @@
58
60
  "and"
59
61
  "implies"
60
62
  "enum"
63
+ "for"
64
+ "all"
61
65
  ] @keyword.operator
62
66
 
67
+ ; v0.117: the observation sugar words — contextual (these tokens exist only
68
+ ; inside an `observation_expr`, so matching them globally never repaints an
69
+ ; ordinary identifier of the same spelling).
70
+ [
71
+ "called"
72
+ "never"
73
+ "once"
74
+ "times"
75
+ "with"
76
+ "before"
77
+ ] @keyword.operator
78
+
79
+ ; v0.118: the contextual test-tier words on a `suite`/`case` header (after `as`)
80
+ ; and the `provides` stub right-hand-side words. Like the observation words,
81
+ ; these tokens exist only in their clauses, so a global match never repaints an
82
+ ; ordinary identifier of the same spelling.
83
+ [
84
+ "unit"
85
+ "integration"
86
+ "system"
87
+ "returns"
88
+ "each"
89
+ "fails"
90
+ ] @keyword.operator
91
+
92
+ ; v0.117: the `trace(Cap.op)` escape hatch — a test-only builtin.
93
+ "trace" @keyword
94
+
63
95
  ; HTTP method on `on http METHOD "path"` handlers.
64
96
  (http_method) @keyword
65
97
 
@@ -97,7 +129,7 @@
97
129
  (none_expr) @constant.builtin
98
130
  (effect_pure_expr "Effect" @type.builtin
99
131
  "pure" @function.builtin)
100
- (mock_expr "Mock" @function.builtin)
132
+ (val_expr "Val" @function.builtin)
101
133
 
102
134
  ; -- Variables / parameters --
103
135
 
@@ -144,7 +176,7 @@
144
176
  (qualified_name (identifier) @module)
145
177
  (uses_decl target: (qualified_name) @module)
146
178
  (consumes_decl target: (qualified_name) @module)
147
- (test_decl target: (qualified_name) @module)
179
+ (suite_decl target: (qualified_name) @module)
148
180
 
149
181
  ; -- Operators & punctuation --
150
182