~mna/snow

d05616d4b14908b986dd7c8d1cbd9b42c10796e0 — Martin Angers 1 year, 9 months ago 49f254b
pkg/parser: fix tests with new var groups
48 files changed, 446 insertions(+), 358 deletions(-)

M pkg/grammar/grammar.ebnf
M pkg/parser/parser.go
M pkg/parser/testdata/fn_assign.snow.want
M pkg/parser/testdata/fn_compare_ops.snow.want
M pkg/parser/testdata/fn_invalid_empty_tuple.snow.want
M pkg/parser/testdata/fn_nested_struct_type.snow.want
M pkg/parser/testdata/fn_nested_tuples.snow.want
M pkg/parser/testdata/fn_ref_method.snow.want
M pkg/parser/testdata/fn_struct_selector.snow.want
M pkg/parser/testdata/fn_type_literal.snow.want
M pkg/parser/testdata/guard_else.snow.want
M pkg/parser/testdata/guard_nested.snow.want
M pkg/parser/testdata/guard_no_body.snow.want
M pkg/parser/testdata/guard_no_else.snow.want
M pkg/parser/testdata/if.snow.want
M pkg/parser/testdata/if_else.snow.want
M pkg/parser/testdata/if_else_if.snow.want
M pkg/parser/testdata/if_else_if_else.snow.want
M pkg/parser/testdata/if_nested.snow.want
M pkg/parser/testdata/if_no_block.snow.want
M pkg/parser/testdata/let.snow.want
M pkg/parser/testdata/let_full.snow.want
M pkg/parser/testdata/let_infer.snow.want
M pkg/parser/testdata/let_kwonly.snow.err
M pkg/parser/testdata/let_kwonly.snow.want
M pkg/parser/testdata/let_question.snow.want
M pkg/parser/testdata/struct_decl.snow.want
M pkg/parser/testdata/var.snow.want
M pkg/parser/testdata/var_bang.snow.want
M pkg/parser/testdata/var_comma_for_semi.snow.err
M pkg/parser/testdata/var_comma_for_semi.snow.want
M pkg/parser/testdata/var_full.snow.want
M pkg/parser/testdata/var_infer.snow.want
M pkg/parser/testdata/var_invalid_empty_tuple.snow.want
M pkg/parser/testdata/var_invalid_type.snow.want
M pkg/parser/testdata/var_kw_as_ident.snow.want
M pkg/parser/testdata/var_kwonly.snow.err
M pkg/parser/testdata/var_kwonly.snow.want
M pkg/parser/testdata/var_missing_type_init.snow.err
M pkg/parser/testdata/var_missing_type_init.snow.want
M pkg/parser/testdata/var_op_precedence.snow.want
M pkg/parser/testdata/var_paren_type.snow.want
M pkg/parser/testdata/var_paren_type_trail_comma.snow.want
M pkg/parser/testdata/var_tuple.snow.want
M pkg/parser/testdata/var_tuple_type.snow.want
M pkg/printer/printer.go
M pkg/printer/printer_test.go
M pkg/semantic/translate_pass.go
M pkg/grammar/grammar.ebnf => pkg/grammar/grammar.ebnf +1 -1
@@ 18,7 18,7 @@ Declaration = VarDecl | FuncDecl | StructDecl .
SimpleStmt = ExprStmt | AssignStmt .

// => Variable declaration statement
VarDecl = ( "let" | "var" ) VarList [ "," ] .
VarDecl = ( "let" | "var" ) VarList . // there is no semicolon inserted after a comma, so cannot have a trailing comma
VarList = Var { "," Var } .
Var = ident ( TypedVarDecl | InitializedVarDecl ) .
TypedVarDecl = ":" Type [ InitializedVarDecl ] .

M pkg/parser/parser.go => pkg/parser/parser.go +3 -0
@@ 217,6 217,9 @@ func (p *parser) parseVarDecl() *ast.VarDecl {

	p.next()
	vars := p.parseVarDefList()
	if len(vars) == 0 {
		p.expect(token.Ident)
	}
	p.expectSemi()
	vd.Vars = vars


M pkg/parser/testdata/fn_assign.snow.want => pkg/parser/testdata/fn_assign.snow.want +4 -3
@@ 6,9 6,10 @@ file [1, #0] [0:40]
        ident [x] [8:9]
        ident [int] [11:14]
    block [2] [16:40]
      var: [20:30]
        ident [y] [24:25]
        ident [int] [27:30]
      var [20:30]
        y: [24:30]
          ident [y] [24:25]
          ident [int] [27:30]
      assign [33:38]
        ident [y] [33:34]
        ident [x] [37:38]

M pkg/parser/testdata/fn_compare_ops.snow.want => pkg/parser/testdata/fn_compare_ops.snow.want +25 -24
@@ 3,27 3,28 @@ file [1, #0] [0:81]
    ident [test] [3:7]
    sig [0->0] [7:9]
    block [1] [10:81]
      let= [14:79]
        ident [a] [18:19]
        binary [||] [22:79]
          binary [||] [22:70]
            binary [!=] [22:53]
              binary [==] [22:48]
                binary [<=] [22:43]
                  binary [>=] [22:38]
                    binary [<] [22:33]
                      binary [>] [22:28]
                        int [1] [22:23]
                        unary [-] [26:28]
                          int [2] [27:28]
                      unary [+] [31:33]
                        int [3] [32:33]
                    int [4] [37:38]
                  int [5] [42:43]
                int [6] [47:48]
              int [7] [52:53]
            binary [&&] [57:70]
              ident [true] [57:61]
              ident [false] [65:70]
          unary [!] [74:79]
            ident [true] [75:79]
      let [14:79]
        a= [18:79]
          ident [a] [18:19]
          binary [||] [22:79]
            binary [||] [22:70]
              binary [!=] [22:53]
                binary [==] [22:48]
                  binary [<=] [22:43]
                    binary [>=] [22:38]
                      binary [<] [22:33]
                        binary [>] [22:28]
                          int [1] [22:23]
                          unary [-] [26:28]
                            int [2] [27:28]
                        unary [+] [31:33]
                          int [3] [32:33]
                      int [4] [37:38]
                    int [5] [42:43]
                  int [6] [47:48]
                int [7] [52:53]
              binary [&&] [57:70]
                ident [true] [57:61]
                ident [false] [65:70]
            unary [!] [74:79]
              ident [true] [75:79]

M pkg/parser/testdata/fn_invalid_empty_tuple.snow.want => pkg/parser/testdata/fn_invalid_empty_tuple.snow.want +4 -3
@@ 3,6 3,7 @@ file [1, #0] [0:26]
    ident [main] [3:7]
    sig [0->0] [7:9]
    block [1] [10:26]
      let= [14:24]
        ident [x] [18:19]
        bad expr [22:24]
      let [14:24]
        x= [18:24]
          ident [x] [18:19]
          bad expr [22:24]

M pkg/parser/testdata/fn_nested_struct_type.snow.want => pkg/parser/testdata/fn_nested_struct_type.snow.want +8 -7
@@ 9,10 9,11 @@ file [1, #0] [0:92]
          ident [T] [36:37]
          struct [0] [46:64]
            ident [U] [53:54]
      var: [78:90]
        ident [u] [82:83]
        select [85:90]
          select [85:88]
            ident [S] [85:86]
            ident [T] [87:88]
          ident [U] [89:90]
      var [78:90]
        u: [82:90]
          ident [u] [82:83]
          select [85:90]
            select [85:88]
              ident [S] [85:86]
              ident [T] [87:88]
            ident [U] [89:90]

M pkg/parser/testdata/fn_nested_tuples.snow.want => pkg/parser/testdata/fn_nested_tuples.snow.want +30 -26
@@ 3,29 3,33 @@ file [1, #0] [0:79]
    ident [main] [3:7]
    sig [0->0] [7:9]
    block [4] [10:79]
      var= [14:28]
        ident [a] [18:19]
        tuple value [2] [22:28]
          item [23:25]
            int [1] [23:24]
          item [26:27]
            int [2] [26:27]
      var= [31:47]
        ident [b] [35:36]
        tuple value [2] [39:47]
          item [40:44]
            string ["x"] [40:43]
          item [45:46]
            ident [a] [45:46]
      var= [50:61]
        ident [c] [54:55]
        select [58:61]
          ident [a] [58:59]
          ident [0] [60:61]
      var= [64:77]
        ident [d] [68:69]
        select [72:77]
          select [72:75]
            ident [b] [72:73]
            ident [1] [74:75]
          ident [1] [76:77]
      var [14:28]
        a= [18:28]
          ident [a] [18:19]
          tuple value [2] [22:28]
            item [23:25]
              int [1] [23:24]
            item [26:27]
              int [2] [26:27]
      var [31:47]
        b= [35:47]
          ident [b] [35:36]
          tuple value [2] [39:47]
            item [40:44]
              string ["x"] [40:43]
            item [45:46]
              ident [a] [45:46]
      var [50:61]
        c= [54:61]
          ident [c] [54:55]
          select [58:61]
            ident [a] [58:59]
            ident [0] [60:61]
      var [64:77]
        d= [68:77]
          ident [d] [68:69]
          select [72:77]
            select [72:75]
              ident [b] [72:73]
              ident [1] [74:75]
            ident [1] [76:77]

M pkg/parser/testdata/fn_ref_method.snow.want => pkg/parser/testdata/fn_ref_method.snow.want +4 -3
@@ 1,9 1,10 @@
file [1, #0] [0:60]
  struct [2] [0:60]
    ident [S] [7:8]
    var: [13:23]
      ident [x] [17:18]
      ident [int] [20:23]
    var [13:23]
      x: [17:23]
        ident [x] [17:18]
        ident [int] [20:23]
    ref fn [26:58]
      ident [inc] [33:36]
      sig [0->0] [36:38]

M pkg/parser/testdata/fn_struct_selector.snow.want => pkg/parser/testdata/fn_struct_selector.snow.want +8 -6
@@ 1,16 1,18 @@
file [2, #0] [0:65]
  struct [1] [0:29]
    ident [Point] [7:12]
    var: [17:27]
      ident [x] [21:22]
      ident [int] [24:27]
    var [17:27]
      x: [21:27]
        ident [x] [21:22]
        ident [int] [24:27]
  fn [31:65]
    ident [test] [34:38]
    sig [0->0] [38:40]
    block [2] [41:65]
      var: [45:57]
        ident [p] [49:50]
        ident [Point] [52:57]
      var [45:57]
        p: [49:57]
          ident [p] [49:50]
          ident [Point] [52:57]
      expr [60:63]
        select [60:63]
          ident [p] [60:61]

M pkg/parser/testdata/fn_type_literal.snow.want => pkg/parser/testdata/fn_type_literal.snow.want +9 -8
@@ 18,14 18,15 @@ file [2, #0] [0:101]
    ident [test] [53:57]
    sig [0->0] [57:59]
    block [2] [60:101]
      var: [64:88]
        ident [f] [68:69]
        sig [2->1] [71:88]
          param [72:76]
            ident [int] [72:75]
          param [77:80]
            ident [int] [77:80]
          ident [int] [85:88]
      var [64:88]
        f: [68:88]
          ident [f] [68:69]
          sig [2->1] [71:88]
            param [72:76]
              ident [int] [72:75]
            param [77:80]
              ident [int] [77:80]
            ident [int] [85:88]
      assign [92:99]
        ident [f] [92:93]
        ident [add] [96:99]

M pkg/parser/testdata/guard_else.snow.want => pkg/parser/testdata/guard_else.snow.want +4 -3
@@ 3,9 3,10 @@ file [1, #0] [0:45]
    ident [test] [3:7]
    sig [0->0] [7:9]
    block [2] [10:45]
      var: [14:25]
        ident [x] [18:19]
        ident [bool] [21:25]
      var [14:25]
        x: [18:25]
          ident [x] [18:19]
          ident [bool] [21:25]
      guard [1] [28:43]
        item [34:35]
          ident [x] [34:35]

M pkg/parser/testdata/guard_nested.snow.want => pkg/parser/testdata/guard_nested.snow.want +8 -6
@@ 3,12 3,14 @@ file [1, #0] [0:88]
    ident [test] [3:7]
    sig [0->0] [7:9]
    block [3] [10:88]
      var: [14:25]
        ident [x] [18:19]
        ident [bool] [21:25]
      var: [28:39]
        ident [y] [32:33]
        ident [bool] [35:39]
      var [14:25]
        x: [18:25]
          ident [x] [18:19]
          ident [bool] [21:25]
      var [28:39]
        y: [32:39]
          ident [y] [32:33]
          ident [bool] [35:39]
      guard [1] [43:86]
        item [49:50]
          ident [x] [49:50]

M pkg/parser/testdata/guard_no_body.snow.want => pkg/parser/testdata/guard_no_body.snow.want +4 -3
@@ 3,9 3,10 @@ file [1, #0] [0:43]
    ident [test] [3:7]
    sig [0->0] [7:9]
    block [2] [10:43]
      var: [14:25]
        ident [x] [18:19]
        ident [bool] [21:25]
      var [14:25]
        x: [18:25]
          ident [x] [18:19]
          ident [bool] [21:25]
      guard [1] [28:43]
        item [34:35]
          ident [x] [34:35]

M pkg/parser/testdata/guard_no_else.snow.want => pkg/parser/testdata/guard_no_else.snow.want +4 -3
@@ 3,9 3,10 @@ file [1, #0] [0:45]
    ident [test] [3:7]
    sig [0->0] [7:9]
    block [2] [10:45]
      var: [14:25]
        ident [x] [18:19]
        ident [bool] [21:25]
      var [14:25]
        x: [18:25]
          ident [x] [18:19]
          ident [bool] [21:25]
      guard [1] [29:45]
        item [35:36]
          ident [x] [35:36]

M pkg/parser/testdata/if.snow.want => pkg/parser/testdata/if.snow.want +4 -3
@@ 3,9 3,10 @@ file [1, #0] [0:49]
    ident [test] [3:7]
    sig [0->0] [7:9]
    block [3] [10:49]
      var: [14:25]
        ident [x] [18:19]
        ident [bool] [21:25]
      var [14:25]
        x: [18:25]
          ident [x] [18:19]
          ident [bool] [21:25]
      if [1] [28:38]
        item [31:32]
          ident [x] [31:32]

M pkg/parser/testdata/if_else.snow.want => pkg/parser/testdata/if_else.snow.want +4 -3
@@ 3,9 3,10 @@ file [1, #0] [0:60]
    ident [test] [3:7]
    sig [0->0] [7:9]
    block [3] [10:60]
      var: [14:25]
        ident [x] [18:19]
        ident [bool] [21:25]
      var [14:25]
        x: [18:25]
          ident [x] [18:19]
          ident [bool] [21:25]
      if [1] [28:49]
        item [31:32]
          ident [x] [31:32]

M pkg/parser/testdata/if_else_if.snow.want => pkg/parser/testdata/if_else_if.snow.want +8 -6
@@ 3,12 3,14 @@ file [1, #0] [0:79]
    ident [test] [3:7]
    sig [0->0] [7:9]
    block [4] [10:79]
      var: [14:25]
        ident [x] [18:19]
        ident [bool] [21:25]
      var: [28:39]
        ident [y] [32:33]
        ident [bool] [35:39]
      var [14:25]
        x: [18:25]
          ident [x] [18:19]
          ident [bool] [21:25]
      var [28:39]
        y: [32:39]
          ident [y] [32:33]
          ident [bool] [35:39]
      if [1] [42:68]
        item [45:46]
          ident [x] [45:46]

M pkg/parser/testdata/if_else_if_else.snow.want => pkg/parser/testdata/if_else_if_else.snow.want +8 -6
@@ 3,12 3,14 @@ file [1, #0] [0:90]
    ident [test] [3:7]
    sig [0->0] [7:9]
    block [4] [10:90]
      var: [14:25]
        ident [x] [18:19]
        ident [bool] [21:25]
      var: [28:39]
        ident [y] [32:33]
        ident [bool] [35:39]
      var [14:25]
        x: [18:25]
          ident [x] [18:19]
          ident [bool] [21:25]
      var [28:39]
        y: [32:39]
          ident [y] [32:33]
          ident [bool] [35:39]
      if [1] [42:79]
        item [45:46]
          ident [x] [45:46]

M pkg/parser/testdata/if_nested.snow.want => pkg/parser/testdata/if_nested.snow.want +8 -6
@@ 3,12 3,14 @@ file [1, #0] [0:93]
    ident [test] [3:7]
    sig [0->0] [7:9]
    block [4] [10:93]
      var: [14:25]
        ident [x] [18:19]
        ident [bool] [21:25]
      var: [28:39]
        ident [y] [32:33]
        ident [bool] [35:39]
      var [14:25]
        x: [18:25]
          ident [x] [18:19]
          ident [bool] [21:25]
      var [28:39]
        y: [32:39]
          ident [y] [32:33]
          ident [bool] [35:39]
      if [1] [42:82]
        item [45:46]
          ident [x] [45:46]

M pkg/parser/testdata/if_no_block.snow.want => pkg/parser/testdata/if_no_block.snow.want +4 -3
@@ 3,9 3,10 @@ file [1, #0] [0:35]
    ident [test] [3:7]
    sig [0->0] [7:9]
    block [2] [10:35]
      var: [14:25]
        ident [x] [18:19]
        ident [bool] [21:25]
      var [14:25]
        x: [18:25]
          ident [x] [18:19]
          ident [bool] [21:25]
      if [1] [28:34]
        item [31:32]
          ident [x] [31:32]

M pkg/parser/testdata/let.snow.want => pkg/parser/testdata/let.snow.want +4 -3
@@ 1,4 1,5 @@
file [1, #0] [0:10]
  let: [0:10]
    ident [x] [4:5]
    ident [int] [7:10]
  let [0:10]
    x: [4:10]
      ident [x] [4:5]
      ident [int] [7:10]

M pkg/parser/testdata/let_full.snow.want => pkg/parser/testdata/let_full.snow.want +5 -4
@@ 1,5 1,6 @@
file [1, #0] [0:21]
  let:= [0:21]
    ident [x] [4:5]
    ident [string] [7:13]
    string ["abc"] [16:21]
  let [0:21]
    x:= [4:21]
      ident [x] [4:5]
      ident [string] [7:13]
      string ["abc"] [16:21]

M pkg/parser/testdata/let_infer.snow.want => pkg/parser/testdata/let_infer.snow.want +4 -3
@@ 1,4 1,5 @@
file [1, #0] [0:11]
  let= [0:11]
    ident [x] [4:5]
    string ["a"] [8:11]
  let [0:11]
    x= [4:11]
      ident [x] [4:5]
      string ["a"] [8:11]

M pkg/parser/testdata/let_kwonly.snow.err => pkg/parser/testdata/let_kwonly.snow.err +0 -1
@@ 1,3 1,2 @@
testdata/let_kwonly.snow:1:5: expected 'ident', found 'eof'
testdata/let_kwonly.snow:1:5: expected ';', found 'eof'
testdata/let_kwonly.snow:1:1: missing variable type or initialization

M pkg/parser/testdata/let_kwonly.snow.want => pkg/parser/testdata/let_kwonly.snow.want +2 -3
@@ 1,3 1,2 @@
file [1, #0] [0:4]
  let [0:4]
    ident [] [4:4]
file [1, #0] [0:3]
  let [0:3]

M pkg/parser/testdata/let_question.snow.want => pkg/parser/testdata/let_question.snow.want +4 -3
@@ 1,4 1,5 @@
file [1, #0] [0:18]
  let: [0:18]
    ident [results?] [4:12]
    ident [bool] [14:18]
  let [0:18]
    results?: [4:18]
      ident [results?] [4:12]
      ident [bool] [14:18]

M pkg/parser/testdata/struct_decl.snow.want => pkg/parser/testdata/struct_decl.snow.want +8 -6
@@ 1,9 1,11 @@
file [1, #0] [0:42]
  struct [2] [0:42]
    ident [Point] [7:12]
    var: [17:27]
      ident [x] [21:22]
      ident [int] [24:27]
    var: [30:40]
      ident [y] [34:35]
      ident [int] [37:40]
    var [17:27]
      x: [21:27]
        ident [x] [21:22]
        ident [int] [24:27]
    var [30:40]
      y: [34:40]
        ident [y] [34:35]
        ident [int] [37:40]

M pkg/parser/testdata/var.snow.want => pkg/parser/testdata/var.snow.want +4 -3
@@ 1,4 1,5 @@
file [1, #0] [0:10]
  var: [0:10]
    ident [x] [4:5]
    ident [int] [7:10]
  var [0:10]
    x: [4:10]
      ident [x] [4:5]
      ident [int] [7:10]

M pkg/parser/testdata/var_bang.snow.want => pkg/parser/testdata/var_bang.snow.want +4 -3
@@ 1,4 1,5 @@
file [1, #0] [0:17]
  var= [0:17]
    ident [ready!] [4:10]
    ident [true] [13:17]
  var [0:17]
    ready!= [4:17]
      ident [ready!] [4:10]
      ident [true] [13:17]

M pkg/parser/testdata/var_comma_for_semi.snow.err => pkg/parser/testdata/var_comma_for_semi.snow.err +1 -1
@@ 1,1 1,1 @@
testdata/var_comma_for_semi.snow:1:11: expected ';', found ','
testdata/var_comma_for_semi.snow:1:13: expected ';', found 'eof'

M pkg/parser/testdata/var_comma_for_semi.snow.want => pkg/parser/testdata/var_comma_for_semi.snow.want +5 -4
@@ 1,4 1,5 @@
file [1, #0] [0:10]
  var: [0:10]
    ident [x] [4:5]
    ident [int] [7:10]
file [1, #0] [0:11]
  var [0:11]
    x: [4:11]
      ident [x] [4:5]
      ident [int] [7:10]

M pkg/parser/testdata/var_full.snow.want => pkg/parser/testdata/var_full.snow.want +5 -4
@@ 1,5 1,6 @@
file [1, #0] [0:16]
  var:= [0:16]
    ident [x] [4:5]
    ident [int] [7:10]
    int [123] [13:16]
  var [0:16]
    x:= [4:16]
      ident [x] [4:5]
      ident [int] [7:10]
      int [123] [13:16]

M pkg/parser/testdata/var_infer.snow.want => pkg/parser/testdata/var_infer.snow.want +4 -3
@@ 1,4 1,5 @@
file [1, #0] [0:10]
  var= [0:10]
    ident [x] [4:5]
    int [10] [8:10]
  var [0:10]
    x= [4:10]
      ident [x] [4:5]
      int [10] [8:10]

M pkg/parser/testdata/var_invalid_empty_tuple.snow.want => pkg/parser/testdata/var_invalid_empty_tuple.snow.want +4 -3
@@ 1,4 1,5 @@
file [1, #0] [0:9]
  var: [0:9]
    ident [x] [4:5]
    bad expr [7:9]
  var [0:9]
    x: [4:9]
      ident [x] [4:5]
      bad expr [7:9]

M pkg/parser/testdata/var_invalid_type.snow.want => pkg/parser/testdata/var_invalid_type.snow.want +4 -3
@@ 1,4 1,5 @@
file [1, #0] [0:7]
  var: [0:7]
    ident [x] [4:5]
    bad expr [7:7]
  var [0:7]
    x: [4:7]
      ident [x] [4:5]
      bad expr [7:7]

M pkg/parser/testdata/var_kw_as_ident.snow.want => pkg/parser/testdata/var_kw_as_ident.snow.want +112 -84
@@ 1,85 1,113 @@
file [28, #0] [0:444]
  var: [0:13]
    ident [] [4:4]
    ident [bool] [9:13]
  var: [14:29]
    ident [] [18:18]
    ident [string] [23:29]
  var: [30:40]
    ident [] [34:34]
    ident [i8] [38:40]
  var: [41:56]
    ident [] [45:45]
    ident [i16] [53:56]
  var: [57:67]
    ident [] [61:61]
    ident [u8] [65:67]
  var: [68:82]
    ident [] [72:72]
    ident [i32] [79:82]
  var: [83:96]
    ident [] [87:87]
    ident [i64] [93:96]
  var: [97:112]
    ident [] [101:101]
    ident [u16] [109:112]
  let: [114:129]
    ident [break] [118:123]
    ident [bool] [125:129]
  let: [131:143]
    ident [case] [135:139]
    ident [i8] [141:143]
  let: [145:158]
    ident [chan] [149:153]
    ident [i16] [155:158]
  let: [160:174]
    ident [const] [164:169]
    ident [i32] [171:174]
  let: [176:193]
    ident [continue] [180:188]
    ident [i64] [190:193]
  let: [195:211]
    ident [default] [199:206]
    ident [int] [208:211]
  let: [213:226]
    ident [defer] [217:222]
    ident [u8] [224:226]
  let: [228:248]
    ident [fallthrough] [232:243]
    ident [u16] [245:248]
  let: [250:262]
    ident [for] [254:257]
    ident [u32] [259:262]
  let: [264:277]
    ident [func] [268:272]
    ident [u64] [274:277]
  let: [279:291]
    ident [go] [283:285]
    ident [uint] [287:291]
  let: [293:308]
    ident [goto] [297:301]
    ident [float] [303:308]
  let: [310:325]
    ident [import] [314:320]
    ident [f32] [322:325]
  let: [327:345]
    ident [interface] [331:340]
    ident [f64] [342:345]
  let: [347:362]
    ident [map] [351:354]
    ident [string] [356:362]
  let: [364:379]
    ident [package] [368:375]
    ident [i8] [377:379]
  let: [381:395]
    ident [range] [385:390]
    ident [i16] [392:395]
  let: [397:412]
    ident [select] [401:407]
    ident [i32] [409:412]
  let: [414:429]
    ident [switch] [418:424]
    ident [i64] [426:429]
  let: [431:444]
    ident [type] [435:439]
    ident [int] [441:444]
  var [0:13]
    : [4:13]
      ident [] [4:4]
      ident [bool] [9:13]
  var [14:29]
    : [18:29]
      ident [] [18:18]
      ident [string] [23:29]
  var [30:40]
    : [34:40]
      ident [] [34:34]
      ident [i8] [38:40]
  var [41:56]
    : [45:56]
      ident [] [45:45]
      ident [i16] [53:56]
  var [57:67]
    : [61:67]
      ident [] [61:61]
      ident [u8] [65:67]
  var [68:82]
    : [72:82]
      ident [] [72:72]
      ident [i32] [79:82]
  var [83:96]
    : [87:96]
      ident [] [87:87]
      ident [i64] [93:96]
  var [97:112]
    : [101:112]
      ident [] [101:101]
      ident [u16] [109:112]
  let [114:129]
    break: [118:129]
      ident [break] [118:123]
      ident [bool] [125:129]
  let [131:143]
    case: [135:143]
      ident [case] [135:139]
      ident [i8] [141:143]
  let [145:158]
    chan: [149:158]
      ident [chan] [149:153]
      ident [i16] [155:158]
  let [160:174]
    const: [164:174]
      ident [const] [164:169]
      ident [i32] [171:174]
  let [176:193]
    continue: [180:193]
      ident [continue] [180:188]
      ident [i64] [190:193]
  let [195:211]
    default: [199:211]
      ident [default] [199:206]
      ident [int] [208:211]
  let [213:226]
    defer: [217:226]
      ident [defer] [217:222]
      ident [u8] [224:226]
  let [228:248]
    fallthrough: [232:248]
      ident [fallthrough] [232:243]
      ident [u16] [245:248]
  let [250:262]
    for: [254:262]
      ident [for] [254:257]
      ident [u32] [259:262]
  let [264:277]
    func: [268:277]
      ident [func] [268:272]
      ident [u64] [274:277]
  let [279:291]
    go: [283:291]
      ident [go] [283:285]
      ident [uint] [287:291]
  let [293:308]
    goto: [297:308]
      ident [goto] [297:301]
      ident [float] [303:308]
  let [310:325]
    import: [314:325]
      ident [import] [314:320]
      ident [f32] [322:325]
  let [327:345]
    interface: [331:345]
      ident [interface] [331:340]
      ident [f64] [342:345]
  let [347:362]
    map: [351:362]
      ident [map] [351:354]
      ident [string] [356:362]
  let [364:379]
    package: [368:379]
      ident [package] [368:375]
      ident [i8] [377:379]
  let [381:395]
    range: [385:395]
      ident [range] [385:390]
      ident [i16] [392:395]
  let [397:412]
    select: [401:412]
      ident [select] [401:407]
      ident [i32] [409:412]
  let [414:429]
    switch: [418:429]
      ident [switch] [418:424]
      ident [i64] [426:429]
  let [431:444]
    type: [435:444]
      ident [type] [435:439]
      ident [int] [441:444]

M pkg/parser/testdata/var_kwonly.snow.err => pkg/parser/testdata/var_kwonly.snow.err +0 -1
@@ 1,3 1,2 @@
testdata/var_kwonly.snow:1:5: expected 'ident', found 'eof'
testdata/var_kwonly.snow:1:5: expected ';', found 'eof'
testdata/var_kwonly.snow:1:1: missing variable type or initialization

M pkg/parser/testdata/var_kwonly.snow.want => pkg/parser/testdata/var_kwonly.snow.want +2 -3
@@ 1,3 1,2 @@
file [1, #0] [0:4]
  var [0:4]
    ident [] [4:4]
file [1, #0] [0:3]
  var [0:3]

M pkg/parser/testdata/var_missing_type_init.snow.err => pkg/parser/testdata/var_missing_type_init.snow.err +1 -1
@@ 1,1 1,1 @@
testdata/var_missing_type_init.snow:1:1: missing variable type or initialization
testdata/var_missing_type_init.snow:1:5: missing variable type or initialization

M pkg/parser/testdata/var_missing_type_init.snow.want => pkg/parser/testdata/var_missing_type_init.snow.want +2 -1
@@ 1,3 1,4 @@
file [1, #0] [0:5]
  var [0:5]
    ident [x] [4:5]
    x [4:5]
      ident [x] [4:5]

M pkg/parser/testdata/var_op_precedence.snow.want => pkg/parser/testdata/var_op_precedence.snow.want +22 -21
@@ 1,22 1,23 @@
file [1, #0] [0:43]
  var= [0:43]
    ident [x] [4:5]
    binary [-] [8:43]
      binary [+] [8:34]
        binary [-] [8:29]
          binary [+] [8:17]
            int [1] [8:9]
            binary [*] [12:17]
              int [2] [12:13]
              int [3] [16:17]
          binary [%] [20:29]
            binary [/] [20:25]
              int [4] [20:21]
              int [5] [24:25]
            int [6] [28:29]
        unary [-] [32:34]
          int [7] [33:34]
      binary [*] [37:43]
        unary [+] [37:39]
          int [8] [38:39]
        int [9] [42:43]
  var [0:43]
    x= [4:43]
      ident [x] [4:5]
      binary [-] [8:43]
        binary [+] [8:34]
          binary [-] [8:29]
            binary [+] [8:17]
              int [1] [8:9]
              binary [*] [12:17]
                int [2] [12:13]
                int [3] [16:17]
            binary [%] [20:29]
              binary [/] [20:25]
                int [4] [20:21]
                int [5] [24:25]
              int [6] [28:29]
          unary [-] [32:34]
            int [7] [33:34]
        binary [*] [37:43]
          unary [+] [37:39]
            int [8] [38:39]
          int [9] [42:43]

M pkg/parser/testdata/var_paren_type.snow.want => pkg/parser/testdata/var_paren_type.snow.want +5 -4
@@ 1,5 1,6 @@
file [1, #0] [0:12]
  var: [0:12]
    ident [x] [4:5]
    paren [7:12]
      ident [int] [8:11]
  var [0:12]
    x: [4:12]
      ident [x] [4:5]
      paren [7:12]
        ident [int] [8:11]

M pkg/parser/testdata/var_paren_type_trail_comma.snow.want => pkg/parser/testdata/var_paren_type_trail_comma.snow.want +5 -4
@@ 1,5 1,6 @@
file [1, #0] [0:14]
  var: [0:14]
    ident [x] [4:5]
    paren [7:14]
      ident [int] [8:11]
  var [0:14]
    x: [4:14]
      ident [x] [4:5]
      paren [7:14]
        ident [int] [8:11]

M pkg/parser/testdata/var_tuple.snow.want => pkg/parser/testdata/var_tuple.snow.want +10 -9
@@ 1,10 1,11 @@
file [1, #0] [0:23]
  var= [0:23]
    ident [t] [4:5]
    tuple value [3] [8:23]
      item [9:11]
        int [1] [9:10]
      item [12:16]
        string ["a"] [12:15]
      item [17:22]
        ident [true] [17:21]
  var [0:23]
    t= [4:23]
      ident [t] [4:5]
      tuple value [3] [8:23]
        item [9:11]
          int [1] [9:10]
        item [12:16]
          string ["a"] [12:15]
        item [17:22]
          ident [true] [17:21]

M pkg/parser/testdata/var_tuple_type.snow.want => pkg/parser/testdata/var_tuple_type.snow.want +8 -7
@@ 1,8 1,9 @@
file [1, #0] [0:19]
  var: [0:19]
    ident [x] [4:5]
    tuple type [2] [7:19]
      param [8:12]
        ident [int] [8:11]
      param [13:18]
        ident [uint] [13:17]
  var [0:19]
    x: [4:19]
      ident [x] [4:5]
      tuple type [2] [7:19]
        param [8:12]
          ident [int] [8:11]
        param [13:18]
          ident [uint] [13:17]

M pkg/printer/printer.go => pkg/printer/printer.go +0 -7
@@ 306,13 306,6 @@ func (p *astPrinter) Visit(n ast.Node) ast.Visitor {
			lbl += "="
		}
		p.printMsg(lbl, true)
		if n.Type != nil {
			ast.Walk(p, n.Type)
		}
		if n.Value != nil {
			ast.Walk(p, n.Value)
		}
		return nil
	case *ast.StructDecl:
		p.printMsg(fmt.Sprintf("struct [%d]", len(n.Decls)), true)
	case *ast.ReturnStmt:

M pkg/printer/printer_test.go => pkg/printer/printer_test.go +38 -30
@@ 28,20 28,24 @@ func TestPrinter(t *testing.T) {
			&ast.VarDecl{
				Kw:    token.Var,
				KwPos: 9,
				Name: &ast.Ident{
					Name:     "a",
					IdentPos: 13,
				},
				Colon: 14,
				Type: &ast.Ident{
					Name:     "int",
					IdentPos: 16,
				},
				Assign: 20,
				Value: &ast.BasicLit{
					LitPos:  22,
					Literal: token.Int,
					Value:   "1",
				Vars: []*ast.VarDef{
					{
						Name: &ast.Ident{
							Name:     "a",
							IdentPos: 13,
						},
						Colon: 14,
						Type: &ast.Ident{
							Name:     "int",
							IdentPos: 16,
						},
						Assign: 20,
						Value: &ast.BasicLit{
							LitPos:  22,
							Literal: token.Int,
							Value:   "1",
						},
					},
				},
			},



@@ 112,10 116,11 @@ func TestPrinter(t *testing.T) {

	wantNoPos := `
file [2, #1]
    var:=
      ident [a]
      ident [int]
      int [1]
    var
      a:=
        ident [a]
        ident [int]
        int [1]
    fn
      ident [add]
      sig [2->1]


@@ 137,10 142,11 @@ file [2, #1]
  comments [2]
    comment [#abc]
    comment [#def]
  var:=
    ident [a]
    ident [int]
    int [1]
  var
    a:=
      ident [a]
      ident [int]
      int [1]
  fn
    ident [add]
    sig [2->1]


@@ 159,10 165,11 @@ file [2, #1]
`
	wantShort := `
file [2, #1] [0:69]
    var:= [8:22]
      ident [a] [12:13]
      ident [int] [15:18]
      int [1] [21:22]
    var [8:22]
      a:= [12:22]
        ident [a] [12:13]
        ident [int] [15:18]
        int [1] [21:22]
    fn [23:69]
      ident [add] [26:29]
      sig [2->1] [30:51]


@@ 181,10 188,11 @@ file [2, #1] [0:69]
`
	wantLong := `
file [2, #1] [test:1:1::1:70]
    var:= [test:1:9::1:23]
      ident [a] [test:1:13::1:14]
      ident [int] [test:1:16::1:19]
      int [1] [test:1:22::1:23]
    var [test:1:9::1:23]
      a:= [test:1:13::1:23]
        ident [a] [test:1:13::1:14]
        ident [int] [test:1:16::1:19]
        int [1] [test:1:22::1:23]
    fn [test:1:24::1:70]
      ident [add] [test:1:27::1:30]
      sig [2->1] [test:1:31::1:52]

M pkg/semantic/translate_pass.go => pkg/semantic/translate_pass.go +31 -16
@@ 37,7 37,7 @@ type translateVisitor struct {
	errh              func(token.Pos, string)
	scope             *Scope
	preventBlockScope bool
	generated         Node
	generated         interface{}
}

func (t *translateVisitor) clone(s *Scope) *translateVisitor {


@@ 68,8 68,8 @@ func (t *translateVisitor) Visit(n ast.Node) ast.Visitor {
		for _, decl := range n.Decls {
			ast.Walk(tt, decl)
			switch gn := tt.generated.(type) {
			case *Var:
				f.Vars = append(f.Vars, gn)
			case []*Var:
				f.Vars = append(f.Vars, gn...)
			case *Fn:
				f.Fns = append(f.Fns, gn)
			case *Struct:


@@ 126,19 126,25 @@ func (t *translateVisitor) Visit(n ast.Node) ast.Visitor {
		t.generated = &fn

	case *ast.VarDecl:
		v := t.buildVarOrExpr(n.Kw, n.Name, n.Type).(*Var)
		v.Ctx = Immutable
		ctx := Immutable
		if n.Kw == token.Var {
			v.Ctx = Mutable
			ctx = Mutable
		}
		if n.Value != nil {
			ast.Walk(t, n.Value)
			v.Value = t.generated.(Expr)
		}
		if str, ok := v.scope.Owner.(*Struct); ok {
			v.PropOf = str

		list := make([]*Var, len(n.Vars))
		for i, vd := range n.Vars {
			v := t.buildVarOrExpr(n.Kw, vd.Name, vd.Type).(*Var)
			v.Ctx = ctx
			if vd.Value != nil {
				ast.Walk(t, vd.Value)
				v.Value = t.generated.(Expr)
			}
			if str, ok := v.scope.Owner.(*Struct); ok {
				v.PropOf = str
			}
			list[i] = v
		}
		t.generated = v
		t.generated = list

	case *ast.StructDecl:
		var str Struct


@@ 153,8 159,8 @@ func (t *translateVisitor) Visit(n ast.Node) ast.Visitor {
		for _, decl := range n.Decls {
			ast.Walk(tt, decl)
			switch gn := tt.generated.(type) {
			case *Var:
				str.Vars = append(str.Vars, gn)
			case []*Var:
				str.Vars = append(str.Vars, gn...)
			case *Fn:
				str.Fns = append(str.Fns, gn)
			case *Struct:


@@ 228,7 234,16 @@ func (t *translateVisitor) Visit(n ast.Node) ast.Visitor {
		}
		for _, stmt := range n.Stmts {
			ast.Walk(tt, stmt)
			b.Stmts = append(b.Stmts, tt.generated.(Stmt))
			switch nn := tt.generated.(type) {
			case Stmt:
				b.Stmts = append(b.Stmts, nn)
			case []*Var:
				for _, stmt := range nn {
					b.Stmts = append(b.Stmts, stmt)
				}
			default:
				panic(fmt.Sprintf("invalid generated block node: %T", nn))
			}
		}
		t.generated = &b