From 0646f064d524785c4e154eb7be35924a21b86e8b Mon Sep 17 00:00:00 2001
From: Anton Trunov <anton@ton.org>
Date: Mon, 10 Jun 2024 17:25:49 +0530
Subject: [PATCH 1/2] feat: optional trailing semicolons for struct/message
 field declarations

---
 CHANGELOG.md                                  |   2 +
 .../__snapshots__/grammar.spec.ts.snap        | 401 +++++++++++++++++-
 src/grammar/grammar.ohm                       |   9 +-
 src/grammar/grammar.ts                        |  12 +-
 src/grammar/test-failed/case-32.tact          |   2 +
 src/grammar/test-failed/case-33.tact          |   2 +
 src/grammar/test-failed/case-34.tact          |   2 +
 src/grammar/test/case-36.tact                 |  16 +
 .../resolveDescriptors.spec.ts.snap           |  72 ++--
 9 files changed, 452 insertions(+), 66 deletions(-)
 create mode 100644 src/grammar/test-failed/case-32.tact
 create mode 100644 src/grammar/test-failed/case-33.tact
 create mode 100644 src/grammar/test-failed/case-34.tact
 create mode 100644 src/grammar/test/case-36.tact

diff --git a/CHANGELOG.md b/CHANGELOG.md
index fa97832cd..af2a5f42b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ### Changed
 
+- Trailing semicolons in struct and message declarations are optional now: PR [#XXX](https://github.com/tact-lang/tact/pull/XXX)
+
 ### Fixed
 
 - Return type of `skipBits` now matches FunC and does not lead to compilation errors: PR [#388](https://github.com/tact-lang/tact/pull/388)
diff --git a/src/grammar/__snapshots__/grammar.spec.ts.snap b/src/grammar/__snapshots__/grammar.spec.ts.snap
index 7574e43bd..900cb30d4 100644
--- a/src/grammar/__snapshots__/grammar.spec.ts.snap
+++ b/src/grammar/__snapshots__/grammar.spec.ts.snap
@@ -304,6 +304,36 @@ Line 1, col 17:
 "
 `;
 
+exports[`grammar should fail case-32 1`] = `
+"<unknown>:2:19: Syntax error: expected "}" 
+Line 2, col 19:
+  1 | // too many semicolons
+> 2 | struct A { x: Int;; }
+                        ^
+  3 | 
+"
+`;
+
+exports[`grammar should fail case-33 1`] = `
+"<unknown>:2:19: Syntax error: expected "}", ";", "=", "as", or "?" 
+Line 2, col 19:
+  1 | // missing ; between fields
+> 2 | struct B { x: Int y: Int }
+                        ^
+  3 | 
+"
+`;
+
+exports[`grammar should fail case-34 1`] = `
+"<unknown>:2:24: Syntax error: expected "}", ";", ".", "!!", "%", "/", "*", ">>", "<<", "-", "+", "==", "!=", "<=", "<", ">=", ">", "^", "&", "&&", "|", "?", or "||" 
+Line 2, col 24:
+  1 | // missing ; between fields
+> 2 | struct B { x: Int = 42 y: Int }
+                             ^
+  3 | 
+"
+`;
+
 exports[`grammar should parse case-0 1`] = `
 {
   "entries": [
@@ -1733,7 +1763,7 @@ exports[`grammar should parse case-14 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "a",
-          "ref": a: Int;,
+          "ref": a: Int,
           "type": {
             "id": 1,
             "kind": "type_ref_simple",
@@ -1748,7 +1778,7 @@ exports[`grammar should parse case-14 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "b",
-          "ref": b: Int;,
+          "ref": b: Int,
           "type": {
             "id": 3,
             "kind": "type_ref_simple",
@@ -2194,7 +2224,7 @@ exports[`grammar should parse case-17 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "x",
-          "ref": x: Int;,
+          "ref": x: Int,
           "type": {
             "id": 1,
             "kind": "type_ref_simple",
@@ -2209,7 +2239,7 @@ exports[`grammar should parse case-17 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "y",
-          "ref": y: Int;,
+          "ref": y: Int,
           "type": {
             "id": 3,
             "kind": "type_ref_simple",
@@ -2338,7 +2368,7 @@ exports[`grammar should parse case-17 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "x",
-          "ref": x: Int;,
+          "ref": x: Int,
           "type": {
             "id": 19,
             "kind": "type_ref_simple",
@@ -2353,7 +2383,7 @@ exports[`grammar should parse case-17 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "y",
-          "ref": y: Int;,
+          "ref": y: Int,
           "type": {
             "id": 21,
             "kind": "type_ref_simple",
@@ -2500,7 +2530,7 @@ exports[`grammar should parse case-18 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "x",
-          "ref": x: Int;,
+          "ref": x: Int,
           "type": {
             "id": 1,
             "kind": "type_ref_simple",
@@ -2528,7 +2558,7 @@ exports[`grammar should parse case-18 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "x",
-          "ref": x: Int as coin;,
+          "ref": x: Int as coin,
           "type": {
             "id": 4,
             "kind": "type_ref_simple",
@@ -2570,7 +2600,7 @@ exports[`grammar should parse case-19 1`] = `
           },
           "kind": "def_field",
           "name": "x",
-          "ref": x: Int = 1000;,
+          "ref": x: Int = 1000,
           "type": {
             "id": 1,
             "kind": "type_ref_simple",
@@ -2603,7 +2633,7 @@ exports[`grammar should parse case-19 1`] = `
           },
           "kind": "def_field",
           "name": "x",
-          "ref": x: Int as coins = 1000;,
+          "ref": x: Int as coins = 1000,
           "type": {
             "id": 5,
             "kind": "type_ref_simple",
@@ -2623,7 +2653,7 @@ exports[`grammar should parse case-19 1`] = `
           },
           "kind": "def_field",
           "name": "y",
-          "ref": y: Bool = true;,
+          "ref": y: Bool = true,
           "type": {
             "id": 8,
             "kind": "type_ref_simple",
@@ -2661,7 +2691,7 @@ exports[`grammar should parse case-20 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "y",
-          "ref": y: map<Int, Int>;,
+          "ref": y: map<Int, Int>,
           "type": {
             "id": 1,
             "key": "Int",
@@ -2691,7 +2721,7 @@ exports[`grammar should parse case-20 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "x",
-          "ref": x: map<Int, Int>;,
+          "ref": x: map<Int, Int>,
           "type": {
             "id": 4,
             "key": "Int",
@@ -2778,7 +2808,7 @@ exports[`grammar should parse case-22 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "c",
-          "ref": c: Int;,
+          "ref": c: Int,
           "type": {
             "id": 2,
             "kind": "type_ref_simple",
@@ -2806,7 +2836,7 @@ exports[`grammar should parse case-22 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "a",
-          "ref": a: Int;,
+          "ref": a: Int,
           "type": {
             "id": 5,
             "kind": "type_ref_simple",
@@ -2841,7 +2871,7 @@ exports[`grammar should parse case-22 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "b",
-          "ref": b: Int;,
+          "ref": b: Int,
           "type": {
             "id": 9,
             "kind": "type_ref_simple",
@@ -2892,7 +2922,7 @@ exports[`grammar should parse case-23 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "a",
-          "ref": a: Int;,
+          "ref": a: Int,
           "type": {
             "id": 2,
             "kind": "type_ref_simple",
@@ -2960,7 +2990,7 @@ exports[`grammar should parse case-23 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "b",
-          "ref": b: Int;,
+          "ref": b: Int,
           "type": {
             "id": 9,
             "kind": "type_ref_simple",
@@ -3051,7 +3081,7 @@ exports[`grammar should parse case-24 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "a",
-          "ref": a: Int;,
+          "ref": a: Int,
           "type": {
             "id": 2,
             "kind": "type_ref_simple",
@@ -3119,7 +3149,7 @@ exports[`grammar should parse case-24 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "b",
-          "ref": b: Int;,
+          "ref": b: Int,
           "type": {
             "id": 9,
             "kind": "type_ref_simple",
@@ -5358,7 +5388,7 @@ exports[`grammar should parse case-34 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "x",
-          "ref": x: Int;,
+          "ref": x: Int,
           "type": {
             "id": 1,
             "kind": "type_ref_simple",
@@ -5373,7 +5403,7 @@ exports[`grammar should parse case-34 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "y",
-          "ref": y: Int;,
+          "ref": y: Int,
           "type": {
             "id": 3,
             "kind": "type_ref_simple",
@@ -5853,3 +5883,330 @@ exports[`grammar should parse case-35 1`] = `
   "kind": "program",
 }
 `;
+
+exports[`grammar should parse case-36 1`] = `
+{
+  "entries": [
+    {
+      "fields": [
+        {
+          "as": null,
+          "id": 2,
+          "init": null,
+          "kind": "def_field",
+          "name": "x",
+          "ref": x: Int,
+          "type": {
+            "id": 1,
+            "kind": "type_ref_simple",
+            "name": "Int",
+            "optional": false,
+            "ref": Int,
+          },
+        },
+      ],
+      "id": 3,
+      "kind": "def_struct",
+      "message": false,
+      "name": "A",
+      "origin": "user",
+      "prefix": null,
+      "ref": struct A { x: Int },
+    },
+    {
+      "fields": [
+        {
+          "as": null,
+          "id": 5,
+          "init": null,
+          "kind": "def_field",
+          "name": "x",
+          "ref": x: Int,
+          "type": {
+            "id": 4,
+            "kind": "type_ref_simple",
+            "name": "Int",
+            "optional": false,
+            "ref": Int,
+          },
+        },
+        {
+          "as": null,
+          "id": 7,
+          "init": null,
+          "kind": "def_field",
+          "name": "y",
+          "ref": y: Int,
+          "type": {
+            "id": 6,
+            "kind": "type_ref_simple",
+            "name": "Int",
+            "optional": false,
+            "ref": Int,
+          },
+        },
+      ],
+      "id": 8,
+      "kind": "def_struct",
+      "message": false,
+      "name": "B",
+      "origin": "user",
+      "prefix": null,
+      "ref": struct B { x: Int; y: Int },
+    },
+    {
+      "fields": [
+        {
+          "as": null,
+          "id": 10,
+          "init": null,
+          "kind": "def_field",
+          "name": "x",
+          "ref": x: Int,
+          "type": {
+            "id": 9,
+            "kind": "type_ref_simple",
+            "name": "Int",
+            "optional": false,
+            "ref": Int,
+          },
+        },
+        {
+          "as": null,
+          "id": 13,
+          "init": {
+            "id": 12,
+            "kind": "number",
+            "ref": 42,
+            "value": 42n,
+          },
+          "kind": "def_field",
+          "name": "y",
+          "ref": y: Int = 42,
+          "type": {
+            "id": 11,
+            "kind": "type_ref_simple",
+            "name": "Int",
+            "optional": false,
+            "ref": Int,
+          },
+        },
+      ],
+      "id": 14,
+      "kind": "def_struct",
+      "message": false,
+      "name": "C",
+      "origin": "user",
+      "prefix": null,
+      "ref": struct C { x: Int; y: Int = 42 },
+    },
+    {
+      "fields": [
+        {
+          "as": null,
+          "id": 17,
+          "init": {
+            "id": 16,
+            "kind": "number",
+            "ref": 42,
+            "value": 42n,
+          },
+          "kind": "def_field",
+          "name": "x",
+          "ref": x: Int = 42,
+          "type": {
+            "id": 15,
+            "kind": "type_ref_simple",
+            "name": "Int",
+            "optional": false,
+            "ref": Int,
+          },
+        },
+        {
+          "as": null,
+          "id": 19,
+          "init": null,
+          "kind": "def_field",
+          "name": "y",
+          "ref": y: Int,
+          "type": {
+            "id": 18,
+            "kind": "type_ref_simple",
+            "name": "Int",
+            "optional": false,
+            "ref": Int,
+          },
+        },
+      ],
+      "id": 20,
+      "kind": "def_struct",
+      "message": false,
+      "name": "D",
+      "origin": "user",
+      "prefix": null,
+      "ref": struct D { x: Int = 42; y: Int },
+    },
+    {
+      "fields": [
+        {
+          "as": null,
+          "id": 22,
+          "init": null,
+          "kind": "def_field",
+          "name": "x",
+          "ref": x: Int,
+          "type": {
+            "id": 21,
+            "kind": "type_ref_simple",
+            "name": "Int",
+            "optional": false,
+            "ref": Int,
+          },
+        },
+      ],
+      "id": 23,
+      "kind": "def_struct",
+      "message": true,
+      "name": "E",
+      "origin": "user",
+      "prefix": null,
+      "ref": message E { x: Int },
+    },
+    {
+      "fields": [
+        {
+          "as": null,
+          "id": 25,
+          "init": null,
+          "kind": "def_field",
+          "name": "x",
+          "ref": x: Int,
+          "type": {
+            "id": 24,
+            "kind": "type_ref_simple",
+            "name": "Int",
+            "optional": false,
+            "ref": Int,
+          },
+        },
+        {
+          "as": null,
+          "id": 27,
+          "init": null,
+          "kind": "def_field",
+          "name": "y",
+          "ref": y: Int,
+          "type": {
+            "id": 26,
+            "kind": "type_ref_simple",
+            "name": "Int",
+            "optional": false,
+            "ref": Int,
+          },
+        },
+      ],
+      "id": 28,
+      "kind": "def_struct",
+      "message": true,
+      "name": "F",
+      "origin": "user",
+      "prefix": null,
+      "ref": message F { x: Int; y: Int },
+    },
+    {
+      "fields": [
+        {
+          "as": null,
+          "id": 30,
+          "init": null,
+          "kind": "def_field",
+          "name": "x",
+          "ref": x: Int,
+          "type": {
+            "id": 29,
+            "kind": "type_ref_simple",
+            "name": "Int",
+            "optional": false,
+            "ref": Int,
+          },
+        },
+        {
+          "as": null,
+          "id": 33,
+          "init": {
+            "id": 32,
+            "kind": "number",
+            "ref": 42,
+            "value": 42n,
+          },
+          "kind": "def_field",
+          "name": "y",
+          "ref": y: Int = 42,
+          "type": {
+            "id": 31,
+            "kind": "type_ref_simple",
+            "name": "Int",
+            "optional": false,
+            "ref": Int,
+          },
+        },
+      ],
+      "id": 34,
+      "kind": "def_struct",
+      "message": true,
+      "name": "G",
+      "origin": "user",
+      "prefix": null,
+      "ref": message G { x: Int; y: Int = 42 },
+    },
+    {
+      "fields": [
+        {
+          "as": null,
+          "id": 37,
+          "init": {
+            "id": 36,
+            "kind": "number",
+            "ref": 42,
+            "value": 42n,
+          },
+          "kind": "def_field",
+          "name": "x",
+          "ref": x: Int = 42,
+          "type": {
+            "id": 35,
+            "kind": "type_ref_simple",
+            "name": "Int",
+            "optional": false,
+            "ref": Int,
+          },
+        },
+        {
+          "as": null,
+          "id": 39,
+          "init": null,
+          "kind": "def_field",
+          "name": "y",
+          "ref": y: Int,
+          "type": {
+            "id": 38,
+            "kind": "type_ref_simple",
+            "name": "Int",
+            "optional": false,
+            "ref": Int,
+          },
+        },
+      ],
+      "id": 40,
+      "kind": "def_struct",
+      "message": true,
+      "name": "G",
+      "origin": "user",
+      "prefix": null,
+      "ref": message G { x: Int = 42; y: Int },
+    },
+  ],
+  "id": 41,
+  "kind": "program",
+}
+`;
diff --git a/src/grammar/grammar.ohm b/src/grammar/grammar.ohm
index ec0c68d7d..2be2d2372 100644
--- a/src/grammar/grammar.ohm
+++ b/src/grammar/grammar.ohm
@@ -26,7 +26,7 @@ Tact {
          | map "<" typeId (as id)? "," typeId (as id)? ">" --map
          | "bounced" "<" typeId ">" --bounced
 
-    FieldDecl = id ":" Type (as id)? ("=" Expression)? ";"
+    FieldDecl = id ":" Type (as id)? ("=" Expression)?
 
     ConstantAttribute = virtual    --virtual
                       | override   --override
@@ -36,10 +36,11 @@ Tact {
 
     ConstantDeclaration = ConstantAttribute* const id ":" Type ";"
 
-    StructDecl = "struct" typeId "{" StructField* "}" --regular
-               | "message" ("(" integerLiteral ")")? typeId "{" StructField* "}" --message
+    StructDecl = "struct" typeId "{" StructFields "}" --regular
+               | "message" ("(" integerLiteral ")")? typeId "{" StructFields "}" --message
 
     StructField = FieldDecl
+    StructFields = ListOf<StructField, ";"> ";"?
 
     Contract = ContractAttribute* contract id (with NonemptyListOf<id,","> ","?)? "{" ContractItemDecl* "}"
 
@@ -58,7 +59,7 @@ Tact {
                   | ConstantDefinition
                   | ConstantDeclaration
 
-    StorageVar = FieldDecl
+    StorageVar = FieldDecl ";"
 
     ContractInit = "init" "(" ListOf<Parameter,","> ","? ")" "{" Statement* "}"
 
diff --git a/src/grammar/grammar.ts b/src/grammar/grammar.ts
index cdb81c855..cc857cb98 100644
--- a/src/grammar/grammar.ts
+++ b/src/grammar/grammar.ts
@@ -115,7 +115,9 @@ semantics.addOperation<ASTNode>("astOfModuleItem", {
             kind: "def_struct",
             origin: ctx!.origin,
             name: typeId.sourceString,
-            fields: fields.children.map((f) => f.astOfDeclaration()),
+            fields: fields.children[0]
+                .asIteration()
+                .children.map((field, _semicolon) => field.astOfDeclaration()),
             prefix: null,
             message: false,
             ref: createRef(this),
@@ -136,7 +138,10 @@ semantics.addOperation<ASTNode>("astOfModuleItem", {
             kind: "def_struct",
             origin: ctx!.origin,
             name: typeId.sourceString,
-            fields: fields.children.map((f) => f.astOfDeclaration()),
+            //            fields: fields.children.map((f) => f.astOfDeclaration()),
+            fields: fields.children[0]
+                .asIteration()
+                .children.map((field, _semicolon) => field.astOfDeclaration()),
             prefix: unwrapOptNode(optId, (id) => parseInt(id.sourceString)),
             message: true,
             ref: createRef(this),
@@ -254,7 +259,7 @@ semantics.addOperation<ASTNode>("astOfItem", {
             ref: createRef(this),
         });
     },
-    StorageVar(fieldDecl) {
+    StorageVar(fieldDecl, _semicolon) {
         return fieldDecl.astOfDeclaration();
     },
     FunctionDefinition(
@@ -525,7 +530,6 @@ semantics.addOperation<ASTNode>("astOfDeclaration", {
         optStorageType,
         _optEq,
         optInitializer,
-        _semicolon,
     ) {
         return createNode({
             kind: "def_field",
diff --git a/src/grammar/test-failed/case-32.tact b/src/grammar/test-failed/case-32.tact
new file mode 100644
index 000000000..d871fd0e5
--- /dev/null
+++ b/src/grammar/test-failed/case-32.tact
@@ -0,0 +1,2 @@
+// too many semicolons
+struct A { x: Int;; }
diff --git a/src/grammar/test-failed/case-33.tact b/src/grammar/test-failed/case-33.tact
new file mode 100644
index 000000000..4282d0b33
--- /dev/null
+++ b/src/grammar/test-failed/case-33.tact
@@ -0,0 +1,2 @@
+// missing ; between fields
+struct B { x: Int y: Int }
diff --git a/src/grammar/test-failed/case-34.tact b/src/grammar/test-failed/case-34.tact
new file mode 100644
index 000000000..b7e461096
--- /dev/null
+++ b/src/grammar/test-failed/case-34.tact
@@ -0,0 +1,2 @@
+// missing ; between fields
+struct B { x: Int = 42 y: Int }
diff --git a/src/grammar/test/case-36.tact b/src/grammar/test/case-36.tact
new file mode 100644
index 000000000..cc65ef59b
--- /dev/null
+++ b/src/grammar/test/case-36.tact
@@ -0,0 +1,16 @@
+// optional trailing semicolon
+struct A { x: Int }
+
+struct B { x: Int; y: Int }
+
+struct C { x: Int; y: Int = 42 }
+
+struct D { x: Int = 42; y: Int }
+
+message E { x: Int }
+
+message F { x: Int; y: Int }
+
+message G { x: Int; y: Int = 42 }
+
+message G { x: Int = 42; y: Int }
diff --git a/src/types/__snapshots__/resolveDescriptors.spec.ts.snap b/src/types/__snapshots__/resolveDescriptors.spec.ts.snap
index 682894398..558d43690 100644
--- a/src/types/__snapshots__/resolveDescriptors.spec.ts.snap
+++ b/src/types/__snapshots__/resolveDescriptors.spec.ts.snap
@@ -63,7 +63,7 @@ exports[`resolveDescriptors should fail descriptors for case-6 1`] = `
 Line 11, col 3:
   10 |   b: Int;
 > 11 |   b: Int;
-         ^~~~~~~
+         ^~~~~~
   12 | }
 "
 `;
@@ -73,7 +73,7 @@ exports[`resolveDescriptors should fail descriptors for case-7 1`] = `
 Line 11, col 3:
   10 |   b: Int;
 > 11 |   b: Int;
-         ^~~~~~~
+         ^~~~~~
   12 | }
 "
 `;
@@ -243,7 +243,7 @@ exports[`resolveDescriptors should fail descriptors for case-24 1`] = `
 Line 15, col 3:
   14 | contract Test {
 > 15 |   src: bounced<A>;
-         ^~~~~~~~~~~~~~~~
+         ^~~~~~~~~~~~~~~
   16 |   init() {}
 "
 `;
@@ -472,7 +472,7 @@ exports[`resolveDescriptors should resolve descriptors for case-1 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "a",
-          "ref": a: Int;,
+          "ref": a: Int,
           "type": {
             "id": 4,
             "kind": "type_ref_simple",
@@ -487,7 +487,7 @@ exports[`resolveDescriptors should resolve descriptors for case-1 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "b",
-          "ref": b: Bool;,
+          "ref": b: Bool,
           "type": {
             "id": 6,
             "kind": "type_ref_simple",
@@ -528,7 +528,7 @@ exports[`resolveDescriptors should resolve descriptors for case-1 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "a",
-          "ref": a: Int;,
+          "ref": a: Int,
           "type": {
             "id": 4,
             "kind": "type_ref_simple",
@@ -540,7 +540,7 @@ exports[`resolveDescriptors should resolve descriptors for case-1 1`] = `
         "default": undefined,
         "index": 0,
         "name": "a",
-        "ref": a: Int;,
+        "ref": a: Int,
         "type": {
           "kind": "ref",
           "name": "Int",
@@ -563,7 +563,7 @@ exports[`resolveDescriptors should resolve descriptors for case-1 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "b",
-          "ref": b: Bool;,
+          "ref": b: Bool,
           "type": {
             "id": 6,
             "kind": "type_ref_simple",
@@ -575,7 +575,7 @@ exports[`resolveDescriptors should resolve descriptors for case-1 1`] = `
         "default": undefined,
         "index": 1,
         "name": "b",
-        "ref": b: Bool;,
+        "ref": b: Bool,
         "type": {
           "kind": "ref",
           "name": "Bool",
@@ -606,7 +606,7 @@ exports[`resolveDescriptors should resolve descriptors for case-1 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "a",
-          "ref": a: Struct1;,
+          "ref": a: Struct1,
           "type": {
             "id": 9,
             "kind": "type_ref_simple",
@@ -645,7 +645,7 @@ exports[`resolveDescriptors should resolve descriptors for case-1 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "a",
-          "ref": a: Struct1;,
+          "ref": a: Struct1,
           "type": {
             "id": 9,
             "kind": "type_ref_simple",
@@ -657,7 +657,7 @@ exports[`resolveDescriptors should resolve descriptors for case-1 1`] = `
         "default": undefined,
         "index": 0,
         "name": "a",
-        "ref": a: Struct1;,
+        "ref": a: Struct1,
         "type": {
           "kind": "ref",
           "name": "Struct1",
@@ -1015,7 +1015,7 @@ exports[`resolveDescriptors should resolve descriptors for case-3 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "a",
-          "ref": a: Int;,
+          "ref": a: Int,
           "type": {
             "id": 4,
             "kind": "type_ref_simple",
@@ -1030,7 +1030,7 @@ exports[`resolveDescriptors should resolve descriptors for case-3 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "b",
-          "ref": b: Bool;,
+          "ref": b: Bool,
           "type": {
             "id": 6,
             "kind": "type_ref_simple",
@@ -1117,7 +1117,7 @@ exports[`resolveDescriptors should resolve descriptors for case-3 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "a",
-          "ref": a: Int;,
+          "ref": a: Int,
           "type": {
             "id": 4,
             "kind": "type_ref_simple",
@@ -1129,7 +1129,7 @@ exports[`resolveDescriptors should resolve descriptors for case-3 1`] = `
         "default": undefined,
         "index": 0,
         "name": "a",
-        "ref": a: Int;,
+        "ref": a: Int,
         "type": {
           "kind": "ref",
           "name": "Int",
@@ -1152,7 +1152,7 @@ exports[`resolveDescriptors should resolve descriptors for case-3 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "b",
-          "ref": b: Bool;,
+          "ref": b: Bool,
           "type": {
             "id": 6,
             "kind": "type_ref_simple",
@@ -1164,7 +1164,7 @@ exports[`resolveDescriptors should resolve descriptors for case-3 1`] = `
         "default": undefined,
         "index": 1,
         "name": "b",
-        "ref": b: Bool;,
+        "ref": b: Bool,
         "type": {
           "kind": "ref",
           "name": "Bool",
@@ -1869,7 +1869,7 @@ exports[`resolveDescriptors should resolve descriptors for case-7 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "a",
-          "ref": a: Int;,
+          "ref": a: Int,
           "type": {
             "id": 7,
             "kind": "type_ref_simple",
@@ -2039,7 +2039,7 @@ exports[`resolveDescriptors should resolve descriptors for case-7 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "a",
-          "ref": a: Int;,
+          "ref": a: Int,
           "type": {
             "id": 7,
             "kind": "type_ref_simple",
@@ -2051,7 +2051,7 @@ exports[`resolveDescriptors should resolve descriptors for case-7 1`] = `
         "default": undefined,
         "index": 0,
         "name": "a",
-        "ref": a: Int;,
+        "ref": a: Int,
         "type": {
           "kind": "ref",
           "name": "Int",
@@ -2282,7 +2282,7 @@ exports[`resolveDescriptors should resolve descriptors for case-7 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "p",
-          "ref": p: Int;,
+          "ref": p: Int,
           "type": {
             "id": 4,
             "kind": "type_ref_simple",
@@ -2322,7 +2322,7 @@ exports[`resolveDescriptors should resolve descriptors for case-7 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "p",
-          "ref": p: Int;,
+          "ref": p: Int,
           "type": {
             "id": 4,
             "kind": "type_ref_simple",
@@ -2334,7 +2334,7 @@ exports[`resolveDescriptors should resolve descriptors for case-7 1`] = `
         "default": undefined,
         "index": 0,
         "name": "p",
-        "ref": p: Int;,
+        "ref": p: Int,
         "type": {
           "kind": "ref",
           "name": "Int",
@@ -2372,7 +2372,7 @@ exports[`resolveDescriptors should resolve descriptors for case-8 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "a",
-          "ref": a: Int as uint32;,
+          "ref": a: Int as uint32,
           "type": {
             "id": 4,
             "kind": "type_ref_simple",
@@ -2412,7 +2412,7 @@ exports[`resolveDescriptors should resolve descriptors for case-8 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "a",
-          "ref": a: Int as uint32;,
+          "ref": a: Int as uint32,
           "type": {
             "id": 4,
             "kind": "type_ref_simple",
@@ -2424,7 +2424,7 @@ exports[`resolveDescriptors should resolve descriptors for case-8 1`] = `
         "default": undefined,
         "index": 0,
         "name": "a",
-        "ref": a: Int as uint32;,
+        "ref": a: Int as uint32,
         "type": {
           "kind": "ref",
           "name": "Int",
@@ -2737,7 +2737,7 @@ exports[`resolveDescriptors should resolve descriptors for case-9 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "a",
-          "ref": a: Int as uint32;,
+          "ref": a: Int as uint32,
           "type": {
             "id": 4,
             "kind": "type_ref_simple",
@@ -2752,7 +2752,7 @@ exports[`resolveDescriptors should resolve descriptors for case-9 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "b",
-          "ref": b: Bool;,
+          "ref": b: Bool,
           "type": {
             "id": 6,
             "kind": "type_ref_simple",
@@ -2767,7 +2767,7 @@ exports[`resolveDescriptors should resolve descriptors for case-9 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "c",
-          "ref": c: Int as uint256;,
+          "ref": c: Int as uint256,
           "type": {
             "id": 8,
             "kind": "type_ref_simple",
@@ -2809,7 +2809,7 @@ exports[`resolveDescriptors should resolve descriptors for case-9 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "a",
-          "ref": a: Int as uint32;,
+          "ref": a: Int as uint32,
           "type": {
             "id": 4,
             "kind": "type_ref_simple",
@@ -2821,7 +2821,7 @@ exports[`resolveDescriptors should resolve descriptors for case-9 1`] = `
         "default": undefined,
         "index": 0,
         "name": "a",
-        "ref": a: Int as uint32;,
+        "ref": a: Int as uint32,
         "type": {
           "kind": "ref",
           "name": "Int",
@@ -2844,7 +2844,7 @@ exports[`resolveDescriptors should resolve descriptors for case-9 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "b",
-          "ref": b: Bool;,
+          "ref": b: Bool,
           "type": {
             "id": 6,
             "kind": "type_ref_simple",
@@ -2856,7 +2856,7 @@ exports[`resolveDescriptors should resolve descriptors for case-9 1`] = `
         "default": undefined,
         "index": 1,
         "name": "b",
-        "ref": b: Bool;,
+        "ref": b: Bool,
         "type": {
           "kind": "ref",
           "name": "Bool",
@@ -2880,7 +2880,7 @@ exports[`resolveDescriptors should resolve descriptors for case-9 1`] = `
           "init": null,
           "kind": "def_field",
           "name": "c",
-          "ref": c: Int as uint256;,
+          "ref": c: Int as uint256,
           "type": {
             "id": 8,
             "kind": "type_ref_simple",
@@ -2892,7 +2892,7 @@ exports[`resolveDescriptors should resolve descriptors for case-9 1`] = `
         "default": undefined,
         "index": 2,
         "name": "c",
-        "ref": c: Int as uint256;,
+        "ref": c: Int as uint256,
         "type": {
           "kind": "ref",
           "name": "Int",

From 0b101b897eac36d8f2606ad4e5ebe0e031370da1 Mon Sep 17 00:00:00 2001
From: Anton Trunov <anton@ton.org>
Date: Mon, 10 Jun 2024 19:59:55 +0400
Subject: [PATCH 2/2] update changelog

---
 CHANGELOG.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index af2a5f42b..b8fede3d2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,7 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ### Changed
 
-- Trailing semicolons in struct and message declarations are optional now: PR [#XXX](https://github.com/tact-lang/tact/pull/XXX)
+- Trailing semicolons in struct and message declarations are optional now: PR [#395](https://github.com/tact-lang/tact/pull/395)
 
 ### Fixed