~mna/snow

7cefbf5e86570f8c10e5771bdbff31d95d1d5ee4 — Martin Angers 1 year, 10 months ago 43b7e7d
pkg/semantic: add typecheck tests, fix many tests
178 files changed, 1922 insertions(+), 9 deletions(-)

M pkg/semantic/scope.go
A pkg/semantic/testdata/check/cycle.snow.err
A pkg/semantic/testdata/check/cycle.snow.want
A pkg/semantic/testdata/check/empty.snow.err
A pkg/semantic/testdata/check/empty.snow.want
A pkg/semantic/testdata/check/fn.snow.err
A pkg/semantic/testdata/check/fn.snow.want
A pkg/semantic/testdata/check/fn_access_invalid_struct_field.snow.err
A pkg/semantic/testdata/check/fn_access_invalid_struct_field.snow.want
A pkg/semantic/testdata/check/fn_access_struct_type_field.snow.err
A pkg/semantic/testdata/check/fn_access_struct_type_field.snow.want
A pkg/semantic/testdata/check/fn_access_var_outside_struct.snow.err
A pkg/semantic/testdata/check/fn_access_var_outside_struct.snow.want
A pkg/semantic/testdata/check/fn_assign_invalid.snow.err
A pkg/semantic/testdata/check/fn_assign_invalid.snow.want
A pkg/semantic/testdata/check/fn_assign_let.snow.err
A pkg/semantic/testdata/check/fn_assign_let.snow.want
A pkg/semantic/testdata/check/fn_assign_struct_fields.snow.err
A pkg/semantic/testdata/check/fn_assign_struct_fields.snow.want
A pkg/semantic/testdata/check/fn_assign_struct_method_to_var.snow.err
A pkg/semantic/testdata/check/fn_assign_struct_method_to_var.snow.want
A pkg/semantic/testdata/check/fn_assign_type.snow.err
A pkg/semantic/testdata/check/fn_assign_type.snow.want
A pkg/semantic/testdata/check/fn_assign_unifying_type.snow.err
A pkg/semantic/testdata/check/fn_assign_unifying_type.snow.want
A pkg/semantic/testdata/check/fn_call_fn_value_with_labels.snow.err
A pkg/semantic/testdata/check/fn_call_fn_value_with_labels.snow.want
A pkg/semantic/testdata/check/fn_call_struct_init.snow.err
A pkg/semantic/testdata/check/fn_call_struct_init.snow.want
A pkg/semantic/testdata/check/fn_call_struct_init_no_label.snow.err
A pkg/semantic/testdata/check/fn_call_struct_init_no_label.snow.want
A pkg/semantic/testdata/check/fn_call_struct_method.snow.err
A pkg/semantic/testdata/check/fn_call_struct_method.snow.want
A pkg/semantic/testdata/check/fn_call_unifying_type.snow.err
A pkg/semantic/testdata/check/fn_call_unifying_type.snow.want
A pkg/semantic/testdata/check/fn_call_with_invalid_labels.snow.err
A pkg/semantic/testdata/check/fn_call_with_invalid_labels.snow.want
A pkg/semantic/testdata/check/fn_call_with_labels.snow.err
A pkg/semantic/testdata/check/fn_call_with_labels.snow.want
A pkg/semantic/testdata/check/fn_call_wrong_arity.snow.err
A pkg/semantic/testdata/check/fn_call_wrong_arity.snow.want
A pkg/semantic/testdata/check/fn_compare.snow.err
A pkg/semantic/testdata/check/fn_compare.snow.want
A pkg/semantic/testdata/check/fn_complex_selectors.snow.err
A pkg/semantic/testdata/check/fn_complex_selectors.snow.want
A pkg/semantic/testdata/check/fn_extern_pkg_before_conflict_name.snow.err
A pkg/semantic/testdata/check/fn_extern_pkg_before_conflict_name.snow.want
A pkg/semantic/testdata/check/fn_extern_pkg_conflict_name.snow.err
A pkg/semantic/testdata/check/fn_extern_pkg_conflict_name.snow.want
A pkg/semantic/testdata/check/fn_extern_ref_method.snow.err
A pkg/semantic/testdata/check/fn_extern_ref_method.snow.want
A pkg/semantic/testdata/check/fn_extern_with_body.snow.err
A pkg/semantic/testdata/check/fn_extern_with_body.snow.want
A pkg/semantic/testdata/check/fn_fn_arg.snow.err
A pkg/semantic/testdata/check/fn_fn_arg.snow.want
A pkg/semantic/testdata/check/fn_guard_fallthrough.snow.err
A pkg/semantic/testdata/check/fn_guard_fallthrough.snow.want
A pkg/semantic/testdata/check/fn_ident_as_type.snow.err
A pkg/semantic/testdata/check/fn_ident_as_type.snow.want
A pkg/semantic/testdata/check/fn_init_order.snow.err
A pkg/semantic/testdata/check/fn_init_order.snow.want
A pkg/semantic/testdata/check/fn_invalid_attr.snow.err
A pkg/semantic/testdata/check/fn_invalid_attr.snow.want
A pkg/semantic/testdata/check/fn_invalid_main.snow.err
A pkg/semantic/testdata/check/fn_invalid_main.snow.want
A pkg/semantic/testdata/check/fn_invalid_ref.snow.err
A pkg/semantic/testdata/check/fn_invalid_ref.snow.want
A pkg/semantic/testdata/check/fn_invalid_ref_call.snow.err
A pkg/semantic/testdata/check/fn_invalid_ref_call.snow.want
A pkg/semantic/testdata/check/fn_invalid_ref_call_via_value.snow.err
A pkg/semantic/testdata/check/fn_invalid_ref_call_via_value.snow.want
A pkg/semantic/testdata/check/fn_invalid_return.snow.err
A pkg/semantic/testdata/check/fn_invalid_return.snow.want
A pkg/semantic/testdata/check/fn_invalid_tuple_access.snow.err
A pkg/semantic/testdata/check/fn_invalid_tuple_access.snow.want
A pkg/semantic/testdata/check/fn_main_extern.snow.err
A pkg/semantic/testdata/check/fn_main_extern.snow.want
A pkg/semantic/testdata/check/fn_many_extern.snow.err
A pkg/semantic/testdata/check/fn_many_extern.snow.want
A pkg/semantic/testdata/check/fn_method_explicit_self.snow.err
A pkg/semantic/testdata/check/fn_method_explicit_self.snow.want
A pkg/semantic/testdata/check/fn_nested_block.snow.err
A pkg/semantic/testdata/check/fn_nested_block.snow.want
A pkg/semantic/testdata/check/fn_nested_fn.snow.err
A pkg/semantic/testdata/check/fn_nested_fn.snow.want
A pkg/semantic/testdata/check/fn_nested_fn_init_order.snow.err
A pkg/semantic/testdata/check/fn_nested_fn_init_order.snow.want
A pkg/semantic/testdata/check/fn_nested_struct_method.snow.err
A pkg/semantic/testdata/check/fn_nested_struct_method.snow.want
A pkg/semantic/testdata/check/fn_nested_struct_self.snow.err
A pkg/semantic/testdata/check/fn_nested_struct_self.snow.want
A pkg/semantic/testdata/check/fn_nested_structs.snow.err
A pkg/semantic/testdata/check/fn_nested_structs.snow.want
A pkg/semantic/testdata/check/fn_nested_tuple_type.snow.err
A pkg/semantic/testdata/check/fn_nested_tuple_type.snow.want
A pkg/semantic/testdata/check/fn_non_type_selectors.snow.err
A pkg/semantic/testdata/check/fn_non_type_selectors.snow.want
A pkg/semantic/testdata/check/fn_param_type_is_var_in_body.snow.err
A pkg/semantic/testdata/check/fn_param_type_is_var_in_body.snow.want
A pkg/semantic/testdata/check/fn_params.snow.err
A pkg/semantic/testdata/check/fn_params.snow.want
A pkg/semantic/testdata/check/fn_params_locals.snow.err
A pkg/semantic/testdata/check/fn_params_locals.snow.want
A pkg/semantic/testdata/check/fn_recursion.snow.err
A pkg/semantic/testdata/check/fn_recursion.snow.want
A pkg/semantic/testdata/check/fn_return_internal_struct.snow.err
A pkg/semantic/testdata/check/fn_return_internal_struct.snow.want
A pkg/semantic/testdata/check/fn_return_missing_value.snow.err
A pkg/semantic/testdata/check/fn_return_missing_value.snow.want
A pkg/semantic/testdata/check/fn_return_struct.snow.err
A pkg/semantic/testdata/check/fn_return_struct.snow.want
A pkg/semantic/testdata/check/fn_return_unifying_type.snow.err
A pkg/semantic/testdata/check/fn_return_unifying_type.snow.want
A pkg/semantic/testdata/check/fn_struct_main_method.snow.err
A pkg/semantic/testdata/check/fn_struct_main_method.snow.want
A pkg/semantic/testdata/check/fn_struct_method_access_top_level.snow.err
A pkg/semantic/testdata/check/fn_struct_method_access_top_level.snow.want
A pkg/semantic/testdata/check/fn_struct_order_independent.snow.err
A pkg/semantic/testdata/check/fn_struct_order_independent.snow.want
A pkg/semantic/testdata/check/fn_struct_same_name_diff_scope.snow.err
A pkg/semantic/testdata/check/fn_struct_same_name_diff_scope.snow.want
A pkg/semantic/testdata/check/fn_struct_selector.snow.err
A pkg/semantic/testdata/check/fn_struct_selector.snow.want
A pkg/semantic/testdata/check/fn_struct_self_shadow.snow.err
A pkg/semantic/testdata/check/fn_struct_self_shadow.snow.want
A pkg/semantic/testdata/check/fn_struct_self_uses.snow.err
A pkg/semantic/testdata/check/fn_struct_self_uses.snow.want
A pkg/semantic/testdata/check/fn_tuple_assign_compatible_types.snow.err
A pkg/semantic/testdata/check/fn_tuple_assign_compatible_types.snow.want
A pkg/semantic/testdata/check/fn_tuple_assign_incompatible_types.snow.err
A pkg/semantic/testdata/check/fn_tuple_assign_incompatible_types.snow.want
A pkg/semantic/testdata/check/fn_tuple_expr_select_field.snow.err
A pkg/semantic/testdata/check/fn_tuple_expr_select_field.snow.want
A pkg/semantic/testdata/check/fn_type_as_value.snow.err
A pkg/semantic/testdata/check/fn_type_as_value.snow.want
A pkg/semantic/testdata/check/fn_unknown_symbol.snow.err
A pkg/semantic/testdata/check/fn_unknown_symbol.snow.want
A pkg/semantic/testdata/check/fn_var_as_param_type.snow.err
A pkg/semantic/testdata/check/fn_var_as_param_type.snow.want
A pkg/semantic/testdata/check/fn_without_body.snow.err
A pkg/semantic/testdata/check/fn_without_body.snow.want
A pkg/semantic/testdata/check/fns.snow.err
A pkg/semantic/testdata/check/fns.snow.want
A pkg/semantic/testdata/check/guard_else.snow.err
A pkg/semantic/testdata/check/guard_else.snow.want
A pkg/semantic/testdata/check/if_else_if.snow.err
A pkg/semantic/testdata/check/if_else_if.snow.want
A pkg/semantic/testdata/check/if_non_bool.snow.err
A pkg/semantic/testdata/check/if_non_bool.snow.want
A pkg/semantic/testdata/check/invalid_binary_op.snow.err
A pkg/semantic/testdata/check/invalid_binary_op.snow.want
A pkg/semantic/testdata/check/let.snow.err
A pkg/semantic/testdata/check/let.snow.want
A pkg/semantic/testdata/check/let_invalid_tuple_type.snow.err
A pkg/semantic/testdata/check/let_invalid_tuple_type.snow.want
A pkg/semantic/testdata/check/let_invalid_unary.snow.err
A pkg/semantic/testdata/check/let_invalid_unary.snow.want
A pkg/semantic/testdata/check/let_unary.snow.err
A pkg/semantic/testdata/check/let_unary.snow.want
A pkg/semantic/testdata/check/paren_type.snow.err
A pkg/semantic/testdata/check/paren_type.snow.want
A pkg/semantic/testdata/check/top_level_fn_init_order.snow.err
A pkg/semantic/testdata/check/top_level_fn_init_order.snow.want
A pkg/semantic/testdata/check/top_level_init_order.snow.err
A pkg/semantic/testdata/check/top_level_init_order.snow.want
A pkg/semantic/testdata/check/var.snow.err
A pkg/semantic/testdata/check/var.snow.want
A pkg/semantic/testdata/check/var_auto_ref.snow.err
A pkg/semantic/testdata/check/var_auto_ref.snow.want
A pkg/semantic/testdata/check/var_bool.snow.err
A pkg/semantic/testdata/check/var_bool.snow.want
A pkg/semantic/testdata/check/var_duplicate_symbol.snow.err
A pkg/semantic/testdata/check/var_duplicate_symbol.snow.want
A pkg/semantic/testdata/check/var_tuple_type.snow.err
A pkg/semantic/testdata/check/var_tuple_type.snow.want
M pkg/semantic/typeassign_pass_test.go
M pkg/semantic/typecheck_pass.go
M pkg/semantic/typecheck_pass_test.go
M pkg/semantic/scope.go => pkg/semantic/scope.go +3 -0
@@ 59,6 59,9 @@ func NewUniverse(owner *Unit) *Scope {
		v.ident = varNm
		v.typ = &BasicType{Kind: String}
		v.Ctx = Immutable
		if varNm == "pkg" {
			v.Value = &LitString{Repr: `""`}
		}
		str.Vars[i] = &v
		strScope.Register(varNm, &v)
	}

A pkg/semantic/testdata/check/cycle.snow.err => pkg/semantic/testdata/check/cycle.snow.err +9 -0
@@ 0,0 1,9 @@
testdata/cycle.snow:1:5: cannot assign type unresolved to variable A of type unresolved
testdata/cycle.snow:1:5: invalid type for identifier A: unresolved
testdata/cycle.snow:1:9: invalid type for identifier B: unresolved
testdata/cycle.snow:2:5: cannot assign type unresolved to variable B of type unresolved
testdata/cycle.snow:2:5: invalid type for identifier B: unresolved
testdata/cycle.snow:2:9: invalid type for identifier C: unresolved
testdata/cycle.snow:3:5: cannot assign type unresolved to variable C of type unresolved
testdata/cycle.snow:3:5: invalid type for identifier C: unresolved
testdata/cycle.snow:3:9: invalid type for identifier A: unresolved

A pkg/semantic/testdata/check/cycle.snow.want => pkg/semantic/testdata/check/cycle.snow.want +10 -0
@@ 0,0 1,10 @@
file [3, #0]
  var=
    ident [A] [var: unresolved]
    ident [B] [var: unresolved]
  var=
    ident [B] [var: unresolved]
    ident [C] [var: unresolved]
  var=
    ident [C] [var: unresolved]
    ident [A] [var: unresolved]

A pkg/semantic/testdata/check/empty.snow.err => pkg/semantic/testdata/check/empty.snow.err +0 -0
A pkg/semantic/testdata/check/empty.snow.want => pkg/semantic/testdata/check/empty.snow.want +0 -0
A pkg/semantic/testdata/check/fn.snow.err => pkg/semantic/testdata/check/fn.snow.err +0 -0
A pkg/semantic/testdata/check/fn.snow.want => pkg/semantic/testdata/check/fn.snow.want +5 -0
@@ 0,0 1,5 @@
file [1, #0]
  fn
    ident [test] [let: () -> void]
    sig [0->0]
    block [0]

A pkg/semantic/testdata/check/fn_access_invalid_struct_field.snow.err => pkg/semantic/testdata/check/fn_access_invalid_struct_field.snow.err +3 -0
@@ 0,0 1,3 @@
testdata/fn_access_invalid_struct_field.snow:8:3: undefined in struct S: y
testdata/fn_access_invalid_struct_field.snow:9:3: undefined in struct S: y
testdata/fn_access_invalid_struct_field.snow:10:11: undefined in struct S: z

A pkg/semantic/testdata/check/fn_access_invalid_struct_field.snow.want => pkg/semantic/testdata/check/fn_access_invalid_struct_field.snow.want +27 -0
@@ 0,0 1,27 @@
file [2, #0]
  struct [1]
    ident [S] [type: struct S]
    var:
      ident [x] [var: int]
      ident [int] [type: int]
  fn
    ident [test] [let: () -> void]
    sig [0->0]
    block [4]
      var:
        ident [s] [var: struct S]
        ident [S] [type: struct S]
      expr
        select [var: unresolved]
          ident [s] [var: struct S]
          ident [y] [invalid: unresolved]
      assign
        select [var: unresolved]
          ident [s] [var: struct S]
          ident [y] [invalid: unresolved]
        int [1] [const: int]
      var=
        ident [x] [var: unresolved]
        select [var: unresolved]
          ident [s] [var: struct S]
          ident [z] [invalid: unresolved]

A pkg/semantic/testdata/check/fn_access_struct_type_field.snow.err => pkg/semantic/testdata/check/fn_access_struct_type_field.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/fn_access_struct_type_field.snow:6:11: expected type context to be one of const, value, var, let; got invalid

A pkg/semantic/testdata/check/fn_access_struct_type_field.snow.want => pkg/semantic/testdata/check/fn_access_struct_type_field.snow.want +15 -0
@@ 0,0 1,15 @@
file [2, #0]
  struct [1]
    ident [Point] [type: struct Point]
    var:
      ident [x] [var: int]
      ident [int] [type: int]
  fn
    ident [test] [let: () -> void]
    sig [0->0]
    block [1]
      var=
        ident [y] [var: int]
        select [invalid: int]
          ident [Point] [type: struct Point]
          ident [x] [var: int]

A pkg/semantic/testdata/check/fn_access_var_outside_struct.snow.err => pkg/semantic/testdata/check/fn_access_var_outside_struct.snow.err +2 -0
@@ 0,0 1,2 @@
testdata/fn_access_var_outside_struct.snow:7:14: x is not a field on struct S nor a top-level symbol
testdata/fn_access_var_outside_struct.snow:12:16: y is not a field on struct T nor a top-level symbol

A pkg/semantic/testdata/check/fn_access_var_outside_struct.snow.want => pkg/semantic/testdata/check/fn_access_var_outside_struct.snow.want +29 -0
@@ 0,0 1,29 @@
file [1, #0]
  fn
    ident [main] [let: () -> void]
    sig [0->0]
    block [2]
      var:
        ident [x] [var: int]
        ident [int] [type: int]
      struct [3]
        ident [S] [type: struct S]
        var:
          ident [y] [var: string]
          ident [string] [type: string]
        fn
          ident [get] [let: () -> int]
          sig [0->1]
            ident [int] [type: int]
          block [1]
            return
              ident [x] [var: int]
        struct [1]
          ident [T] [type: struct T]
          fn
            ident [get] [let: () -> string]
            sig [0->1]
              ident [string] [type: string]
            block [1]
              return
                ident [y] [var: string]

A pkg/semantic/testdata/check/fn_assign_invalid.snow.err => pkg/semantic/testdata/check/fn_assign_invalid.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/fn_assign_invalid.snow:3:7: cannot assign type string to variable of type f64

A pkg/semantic/testdata/check/fn_assign_invalid.snow.want => pkg/semantic/testdata/check/fn_assign_invalid.snow.want +11 -0
@@ 0,0 1,11 @@
file [1, #0]
  fn
    ident [test] [let: () -> void]
    sig [0->0]
    block [2]
      var:
        ident [x] [var: f64]
        ident [f64] [type: f64]
      assign
        ident [x] [var: f64]
        string ["a"] [const: string]

A pkg/semantic/testdata/check/fn_assign_let.snow.err => pkg/semantic/testdata/check/fn_assign_let.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/fn_assign_let.snow:3:3: expected type context to be var; got let

A pkg/semantic/testdata/check/fn_assign_let.snow.want => pkg/semantic/testdata/check/fn_assign_let.snow.want +11 -0
@@ 0,0 1,11 @@
file [1, #0]
  fn
    ident [main] [let: () -> void]
    sig [0->0]
    block [2]
      let=
        ident [x] [let: int]
        int [1] [const: int]
      assign
        ident [x] [let: int]
        int [2] [const: int]

A pkg/semantic/testdata/check/fn_assign_struct_fields.snow.err => pkg/semantic/testdata/check/fn_assign_struct_fields.snow.err +5 -0
@@ 0,0 1,5 @@
testdata/fn_assign_struct_fields.snow:12:3: expected type context to be var; got let
testdata/fn_assign_struct_fields.snow:14:3: expected type context to be var; got let
testdata/fn_assign_struct_fields.snow:16:3: expected type context to be var; got let
testdata/fn_assign_struct_fields.snow:17:3: expected type context to be var; got let
testdata/fn_assign_struct_fields.snow:18:3: expected type context to be var; got let

A pkg/semantic/testdata/check/fn_assign_struct_fields.snow.want => pkg/semantic/testdata/check/fn_assign_struct_fields.snow.want +53 -0
@@ 0,0 1,53 @@
file [2, #0]
  struct [3]
    ident [S] [type: struct S]
    let:
      ident [x] [let: int]
      ident [int] [type: int]
    var:
      ident [y] [var: int]
      ident [int] [type: int]
    fn
      ident [z] [let: () -> void]
      sig [0->0]
      block [0]
  fn
    ident [test] [let: () -> void]
    sig [0->0]
    block [8]
      var:
        ident [vs] [var: struct S]
        ident [S] [type: struct S]
      let:
        ident [ls] [let: struct S]
        ident [S] [type: struct S]
      assign
        select [let: int]
          ident [vs] [var: struct S]
          ident [x] [let: int]
        int [1] [const: int]
      assign
        select [var: int]
          ident [vs] [var: struct S]
          ident [y] [var: int]
        int [2] [const: int]
      assign
        select [let: () -> void]
          ident [vs] [var: struct S]
          ident [z] [let: () -> void]
        ident [test] [let: () -> void]
      assign
        select [let: int]
          ident [ls] [let: struct S]
          ident [x] [let: int]
        int [1] [const: int]
      assign
        select [let: int]
          ident [ls] [let: struct S]
          ident [y] [var: int]
        int [2] [const: int]
      assign
        select [let: () -> void]
          ident [ls] [let: struct S]
          ident [z] [let: () -> void]
        ident [test] [let: () -> void]

A pkg/semantic/testdata/check/fn_assign_struct_method_to_var.snow.err => pkg/semantic/testdata/check/fn_assign_struct_method_to_var.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/fn_assign_struct_method_to_var.snow:19:11: cannot access ref fn set; left-hand side must be var, is let

A pkg/semantic/testdata/check/fn_assign_struct_method_to_var.snow.want => pkg/semantic/testdata/check/fn_assign_struct_method_to_var.snow.want +59 -0
@@ 0,0 1,59 @@
file [2, #0]
  struct [3]
    ident [S] [type: struct S]
    var:
      ident [x] [var: int]
      ident [int] [type: int]
    fn
      ident [get] [let: () -> int]
      sig [0->1]
        ident [int] [type: int]
      block [1]
        return
          ident [x] [var: int]
    ref fn
      ident [set] [let: (int) -> void]
      sig [1->0]
        param
          ident [v] [let: int]
          ident [int] [type: int]
      block [1]
        assign
          ident [x] [var: int]
          ident [v] [let: int]
  fn
    ident [main] [let: () -> void]
    sig [0->0]
    block [6]
      var:
        ident [s] [var: struct S]
        ident [S] [type: struct S]
      var:=
        ident [f1] [var: () -> int]
        sig [0->1] [type: () -> int]
          ident [int] [type: int]
        select [let: () -> int]
          ident [s] [var: struct S]
          ident [get] [let: () -> int]
      var:=
        ident [f2] [var: (int) -> void]
        sig [1->1] [type: (int) -> void]
          param
            ident [int] [type: int]
          ident [void] [type: void]
        select [let: (int) -> void]
          ident [s] [var: struct S]
          ident [set] [let: (int) -> void]
      let:
        ident [s2] [let: struct S]
        ident [S] [type: struct S]
      assign
        ident [f1] [var: () -> int]
        select [let: () -> int]
          ident [s2] [let: struct S]
          ident [get] [let: () -> int]
      assign
        ident [f2] [var: (int) -> void]
        select [let: (int) -> void]
          ident [s2] [let: struct S]
          ident [set] [let: (int) -> void]

A pkg/semantic/testdata/check/fn_assign_type.snow.err => pkg/semantic/testdata/check/fn_assign_type.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/fn_assign_type.snow:2:3: expected type context to be var; got type

A pkg/semantic/testdata/check/fn_assign_type.snow.want => pkg/semantic/testdata/check/fn_assign_type.snow.want +8 -0
@@ 0,0 1,8 @@
file [1, #0]
  fn
    ident [test] [let: () -> void]
    sig [0->0]
    block [1]
      assign
        ident [int] [type: int]
        int [3] [const: int]

A pkg/semantic/testdata/check/fn_assign_unifying_type.snow.err => pkg/semantic/testdata/check/fn_assign_unifying_type.snow.err +0 -0
A pkg/semantic/testdata/check/fn_assign_unifying_type.snow.want => pkg/semantic/testdata/check/fn_assign_unifying_type.snow.want +14 -0
@@ 0,0 1,14 @@
file [1, #0]
  fn
    ident [test] [let: () -> void]
    sig [0->0]
    block [3]
      var:
        ident [x] [var: u8]
        ident [u8] [type: u8]
      var:
        ident [y] [var: uint]
        ident [uint] [type: uint]
      assign
        ident [y] [var: uint]
        ident [x] [var: u8]

A pkg/semantic/testdata/check/fn_call_fn_value_with_labels.snow.err => pkg/semantic/testdata/check/fn_call_fn_value_with_labels.snow.err +2 -0
@@ 0,0 1,2 @@
testdata/fn_call_fn_value_with_labels.snow:8:5: label provided but not allowed on function value (int, int) -> int
testdata/fn_call_fn_value_with_labels.snow:8:11: label provided but not allowed on function value (int, int) -> int

A pkg/semantic/testdata/check/fn_call_fn_value_with_labels.snow.want => pkg/semantic/testdata/check/fn_call_fn_value_with_labels.snow.want +40 -0
@@ 0,0 1,40 @@
file [2, #0]
  fn
    ident [add] [let: (int, int) -> int]
    sig [2->1]
      param
        ident [x] [let: int]
        ident [int] [type: int]
      param
        ident [y] [let: int]
        ident [int] [type: int]
      ident [int] [type: int]
    block [1]
      return
        binary [+] [value: int]
          ident [x] [let: int]
          ident [y] [let: int]
  fn
    ident [main] [let: () -> void]
    sig [0->0]
    block [3]
      var:
        ident [f] [var: (int, int) -> int]
        sig [2->1] [type: (int, int) -> int]
          param
            ident [int] [type: int]
          param
            ident [int] [type: int]
          ident [int] [type: int]
      assign
        ident [f] [var: (int, int) -> int]
        ident [add] [let: (int, int) -> int]
      expr
        call [2] [value: int]
          ident [f] [var: (int, int) -> int]
          item:
            ident [x] [<nil>]
            int [1] [const: int]
          item:
            ident [y] [<nil>]
            int [2] [const: int]

A pkg/semantic/testdata/check/fn_call_struct_init.snow.err => pkg/semantic/testdata/check/fn_call_struct_init.snow.err +0 -0
A pkg/semantic/testdata/check/fn_call_struct_init.snow.want => pkg/semantic/testdata/check/fn_call_struct_init.snow.want +23 -0
@@ 0,0 1,23 @@
file [2, #0]
  struct [2]
    ident [S] [type: struct S]
    var:
      ident [x] [var: int]
      ident [int] [type: int]
    let:
      ident [y] [let: string]
      ident [string] [type: string]
  fn
    ident [main] [let: () -> void]
    sig [0->0]
    block [1]
      var=
        ident [s] [var: struct S]
        call [2] [value: struct S]
          ident [S] [type: struct S]
          item:
            ident [x] [<nil>]
            int [1] [const: int]
          item:
            ident [y] [<nil>]
            string ["a"] [const: string]

A pkg/semantic/testdata/check/fn_call_struct_init_no_label.snow.err => pkg/semantic/testdata/check/fn_call_struct_init_no_label.snow.err +2 -0
@@ 0,0 1,2 @@
testdata/fn_call_struct_init_no_label.snow:2:13: label required for struct initializer
testdata/fn_call_struct_init_no_label.snow:2:16: label required for struct initializer

A pkg/semantic/testdata/check/fn_call_struct_init_no_label.snow.want => pkg/semantic/testdata/check/fn_call_struct_init_no_label.snow.want +21 -0
@@ 0,0 1,21 @@
file [2, #0]
  fn
    ident [main] [let: () -> void]
    sig [0->0]
    block [1]
      var=
        ident [s] [var: struct S]
        call [2] [value: struct S]
          ident [S] [type: struct S]
          item
            int [1] [const: int]
          item
            string ["a"] [const: string]
  struct [2]
    ident [S] [type: struct S]
    var:
      ident [x] [var: int]
      ident [int] [type: int]
    let:
      ident [y] [let: string]
      ident [string] [type: string]

A pkg/semantic/testdata/check/fn_call_struct_method.snow.err => pkg/semantic/testdata/check/fn_call_struct_method.snow.err +0 -0
A pkg/semantic/testdata/check/fn_call_struct_method.snow.want => pkg/semantic/testdata/check/fn_call_struct_method.snow.want +32 -0
@@ 0,0 1,32 @@
file [2, #0]
  struct [2]
    ident [Point] [type: struct Point]
    var:
      ident [x] [var: int]
      ident [int] [type: int]
    fn
      ident [add] [let: (int) -> void]
      sig [1->0]
        param
          ident [y] [let: int]
          ident [int] [type: int]
      block [1]
        assign
          ident [x] [var: int]
          binary [+] [value: int]
            ident [x] [var: int]
            ident [y] [let: int]
  fn
    ident [test] [let: () -> void]
    sig [0->0]
    block [2]
      var:
        ident [p] [var: struct Point]
        ident [Point] [type: struct Point]
      expr
        call [1] [value: void]
          select [let: (int) -> void]
            ident [p] [var: struct Point]
            ident [add] [let: (int) -> void]
          item
            int [1] [const: int]

A pkg/semantic/testdata/check/fn_call_unifying_type.snow.err => pkg/semantic/testdata/check/fn_call_unifying_type.snow.err +0 -0
A pkg/semantic/testdata/check/fn_call_unifying_type.snow.want => pkg/semantic/testdata/check/fn_call_unifying_type.snow.want +33 -0
@@ 0,0 1,33 @@
file [2, #0]
  fn
    ident [add] [let: (int, int) -> int]
    sig [2->1]
      param
        ident [x] [let: int]
        ident [int] [type: int]
      param
        ident [y] [let: int]
        ident [int] [type: int]
      ident [int] [type: int]
    block [1]
      return
        binary [+] [value: int]
          ident [x] [let: int]
          ident [y] [let: int]
  fn
    ident [test] [let: () -> void]
    sig [0->0]
    block [3]
      var:
        ident [x] [var: i32]
        ident [i32] [type: i32]
      var:
        ident [y] [var: i16]
        ident [i16] [type: i16]
      expr
        call [2] [value: int]
          ident [add] [let: (int, int) -> int]
          item
            ident [x] [var: i32]
          item
            ident [y] [var: i16]

A pkg/semantic/testdata/check/fn_call_with_invalid_labels.snow.err => pkg/semantic/testdata/check/fn_call_with_invalid_labels.snow.err +5 -0
@@ 0,0 1,5 @@
testdata/fn_call_with_invalid_labels.snow:6:13: expected label y at argument index 1, got z
testdata/fn_call_with_invalid_labels.snow:7:7: expected label x at argument index 0, got y
testdata/fn_call_with_invalid_labels.snow:7:13: expected label y at argument index 1, got x
testdata/fn_call_with_invalid_labels.snow:8:10: invalid mix of labelled and unlabelled arguments
testdata/fn_call_with_invalid_labels.snow:9:13: invalid mix of labelled and unlabelled arguments

A pkg/semantic/testdata/check/fn_call_with_invalid_labels.snow.want => pkg/semantic/testdata/check/fn_call_with_invalid_labels.snow.want +54 -0
@@ 0,0 1,54 @@
file [2, #0]
  fn
    ident [add] [let: (int, int) -> int]
    sig [2->1]
      param
        ident [x] [let: int]
        ident [int] [type: int]
      param
        ident [y] [let: int]
        ident [int] [type: int]
      ident [int] [type: int]
    block [1]
      return
        binary [+] [value: int]
          ident [x] [let: int]
          ident [y] [let: int]
  fn
    ident [main] [let: () -> void]
    sig [0->0]
    block [4]
      expr
        call [2] [value: int]
          ident [add] [let: (int, int) -> int]
          item:
            ident [x] [<nil>]
            int [1] [const: int]
          item:
            ident [z] [<nil>]
            int [2] [const: int]
      expr
        call [2] [value: int]
          ident [add] [let: (int, int) -> int]
          item:
            ident [y] [<nil>]
            int [1] [const: int]
          item:
            ident [x] [<nil>]
            int [2] [const: int]
      expr
        call [2] [value: int]
          ident [add] [let: (int, int) -> int]
          item
            int [1] [const: int]
          item:
            ident [y] [<nil>]
            int [2] [const: int]
      expr
        call [2] [value: int]
          ident [add] [let: (int, int) -> int]
          item:
            ident [x] [<nil>]
            int [1] [const: int]
          item
            int [2] [const: int]

A pkg/semantic/testdata/check/fn_call_with_labels.snow.err => pkg/semantic/testdata/check/fn_call_with_labels.snow.err +0 -0
A pkg/semantic/testdata/check/fn_call_with_labels.snow.want => pkg/semantic/testdata/check/fn_call_with_labels.snow.want +36 -0
@@ 0,0 1,36 @@
file [2, #1]
    fn
      ident [add] [let: (int, int) -> int]
      sig [2->1]
        param
          ident [x] [let: int]
          ident [int] [type: int]
        param
          ident [y] [let: int]
          ident [int] [type: int]
        ident [int] [type: int]
      block [1]
        return
          binary [+] [value: int]
            ident [x] [let: int]
            ident [y] [let: int]
    fn
      ident [main] [let: () -> void]
      sig [0->0]
      block [2]
        expr
          call [2] [value: int]
            ident [add] [let: (int, int) -> int]
            item:
              ident [x] [<nil>]
              int [1] [const: int]
            item:
              ident [y] [<nil>]
              int [2] [const: int]
        expr
          call [2] [value: int]
            ident [add] [let: (int, int) -> int]
            item
              int [1] [const: int]
            item
              int [2] [const: int]

A pkg/semantic/testdata/check/fn_call_wrong_arity.snow.err => pkg/semantic/testdata/check/fn_call_wrong_arity.snow.err +5 -0
@@ 0,0 1,5 @@
testdata/fn_call_wrong_arity.snow:7:3: wrong number of arguments in call: expected 2, got 0
testdata/fn_call_wrong_arity.snow:8:3: wrong number of arguments in call: expected 2, got 1
testdata/fn_call_wrong_arity.snow:10:3: wrong number of arguments in call: expected 2, got 3
testdata/fn_call_wrong_arity.snow:11:7: invalid type for argument: expected int, got string
testdata/fn_call_wrong_arity.snow:11:12: invalid type for argument: expected int, got string

A pkg/semantic/testdata/check/fn_call_wrong_arity.snow.want => pkg/semantic/testdata/check/fn_call_wrong_arity.snow.want +54 -0
@@ 0,0 1,54 @@
file [2, #0]
  fn
    ident [add] [let: (int, int) -> int]
    sig [2->1]
      param
        ident [x] [let: int]
        ident [int] [type: int]
      param
        ident [y] [let: int]
        ident [int] [type: int]
      ident [int] [type: int]
    block [1]
      return
        binary [+] [value: int]
          ident [x] [let: int]
          ident [y] [let: int]
  fn
    ident [test] [let: () -> void]
    sig [0->0]
    block [6]
      let=
        ident [a] [let: int]
        int [1] [const: int]
      expr
        call [0] [value: int]
          ident [add] [let: (int, int) -> int]
      expr
        call [1] [value: int]
          ident [add] [let: (int, int) -> int]
          item
            ident [a] [let: int]
      expr
        call [2] [value: int]
          ident [add] [let: (int, int) -> int]
          item
            ident [a] [let: int]
          item
            int [2] [const: int]
      expr
        call [3] [value: int]
          ident [add] [let: (int, int) -> int]
          item
            ident [a] [let: int]
          item
            int [2] [const: int]
          item
            int [3] [const: int]
      expr
        call [2] [value: int]
          ident [add] [let: (int, int) -> int]
          item
            string ["a"] [const: string]
          item
            string ["b"] [const: string]

A pkg/semantic/testdata/check/fn_compare.snow.err => pkg/semantic/testdata/check/fn_compare.snow.err +0 -0
A pkg/semantic/testdata/check/fn_compare.snow.want => pkg/semantic/testdata/check/fn_compare.snow.want +20 -0
@@ 0,0 1,20 @@
file [1, #0]
  fn
    ident [test] [let: () -> void]
    sig [0->0]
    block [2]
      var=
        ident [x] [var: int]
        int [1] [const: int]
      if [1]
        item
          binary [==] [value: bool]
            ident [x] [var: int]
            int [1] [const: int]
        block [1]
          var=
            ident [z] [var: bool]
            paren [value: bool]
              binary [>] [value: bool]
                ident [x] [var: int]
                int [0] [const: int]

A pkg/semantic/testdata/check/fn_complex_selectors.snow.err => pkg/semantic/testdata/check/fn_complex_selectors.snow.err +0 -0
A pkg/semantic/testdata/check/fn_complex_selectors.snow.want => pkg/semantic/testdata/check/fn_complex_selectors.snow.want +79 -0
@@ 0,0 1,79 @@
file [3, #0]
  struct [3]
    ident [S] [type: struct S]
    var:
      ident [s1] [var: int]
      ident [int] [type: int]
    var:
      ident [s2] [var: struct T]
      ident [T] [type: struct T]
    struct [2]
      ident [T] [type: struct T]
      var:
        ident [t1] [var: string]
        ident [string] [type: string]
      fn
        ident [do] [let: () -> (int, () -> int)]
        sig [0->1]
          tuple type [2] [type: (int, () -> int)]
            param
              ident [int] [type: int]
            param
              sig [0->1] [type: () -> int]
                ident [int] [type: int]
        block [2]
          fn
            ident [func] [let: () -> int]
            sig [0->1]
              ident [int] [type: int]
            block [1]
              return
                int [1] [const: int]
          return
            tuple value [2] [value: (int, () -> int)]
              item
                int [3] [const: int]
              item
                ident [func] [let: () -> int]
  fn
    ident [create] [let: () -> struct S]
    sig [0->1]
      ident [S] [type: struct S]
    block [2]
      var:
        ident [s] [var: struct S]
        ident [S] [type: struct S]
      return
        ident [s] [var: struct S]
  fn
    ident [main] [let: () -> void]
    sig [0->0]
    block [3]
      expr
        select [value: string]
          select [value: struct T]
            call [0] [value: struct S]
              ident [create] [let: () -> struct S]
            ident [s2] [var: struct T]
          ident [t1] [var: string]
      expr
        select [value: int]
          call [0] [value: (int, () -> int)]
            select [value: () -> (int, () -> int)]
              select [value: struct T]
                call [0] [value: struct S]
                  ident [create] [let: () -> struct S]
                ident [s2] [var: struct T]
              ident [do] [let: () -> (int, () -> int)]
          ident [0] [value: int]
      expr
        call [0] [value: int]
          select [value: () -> int]
            call [0] [value: (int, () -> int)]
              select [value: () -> (int, () -> int)]
                select [value: struct T]
                  call [0] [value: struct S]
                    ident [create] [let: () -> struct S]
                  ident [s2] [var: struct T]
                ident [do] [let: () -> (int, () -> int)]
            ident [1] [value: () -> int]

A pkg/semantic/testdata/check/fn_extern_pkg_before_conflict_name.snow.err => pkg/semantic/testdata/check/fn_extern_pkg_before_conflict_name.snow.err +0 -0
A pkg/semantic/testdata/check/fn_extern_pkg_before_conflict_name.snow.want => pkg/semantic/testdata/check/fn_extern_pkg_before_conflict_name.snow.want +32 -0
@@ 0,0 1,32 @@
file [1, #0]
  fn
    ident [test] [let: () -> void]
    sig [0->0]
    block [4]
      fn
        @ [2]
          ident [extern] [<nil>]
          field
            ident [import] [<nil>]
            string ["fmt"] [<nil>]
          field
            ident [symbol] [<nil>]
            string ["Print"] [<nil>]
        ident [print] [let: (int) -> void]
        sig [1->0]
          param
            ident [x] [let: int]
            ident [int] [type: int]
      var:
        ident [fmt] [var: int]
        ident [int] [type: int]
      assign
        ident [fmt] [var: int]
        binary [+] [value: int]
          ident [fmt] [var: int]
          int [1] [const: int]
      expr
        call [1] [value: void]
          ident [print] [let: (int) -> void]
          item
            ident [fmt] [var: int]

A pkg/semantic/testdata/check/fn_extern_pkg_conflict_name.snow.err => pkg/semantic/testdata/check/fn_extern_pkg_conflict_name.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/fn_extern_pkg_conflict_name.snow:4:3: external package identifier fmt already declared

A pkg/semantic/testdata/check/fn_extern_pkg_conflict_name.snow.want => pkg/semantic/testdata/check/fn_extern_pkg_conflict_name.snow.want +32 -0
@@ 0,0 1,32 @@
file [1, #0]
  fn
    ident [test] [let: () -> void]
    sig [0->0]
    block [4]
      var:
        ident [fmt] [var: int]
        ident [int] [type: int]
      fn
        @ [2]
          ident [extern] [<nil>]
          field
            ident [import] [<nil>]
            string ["fmt"] [<nil>]
          field
            ident [symbol] [<nil>]
            string ["Print"] [<nil>]
        ident [print] [let: (int) -> void]
        sig [1->0]
          param
            ident [x] [let: int]
            ident [int] [type: int]
      assign
        ident [fmt] [var: int]
        binary [+] [value: int]
          ident [fmt] [var: int]
          int [1] [const: int]
      expr
        call [1] [value: void]
          ident [print] [let: (int) -> void]
          item
            ident [fmt] [var: int]

A pkg/semantic/testdata/check/fn_extern_ref_method.snow.err => pkg/semantic/testdata/check/fn_extern_ref_method.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/fn_extern_ref_method.snow:4:5: external function f cannot have a ref modifier

A pkg/semantic/testdata/check/fn_extern_ref_method.snow.want => pkg/semantic/testdata/check/fn_extern_ref_method.snow.want +18 -0
@@ 0,0 1,18 @@
file [1, #0]
  fn
    ident [main] [let: () -> void]
    sig [0->0]
    block [1]
      struct [1]
        ident [S] [type: struct S]
        ref fn
          @ [2]
            ident [extern] [<nil>]
            field
              ident [import] [<nil>]
              string ["fmt"] [<nil>]
            field
              ident [symbol] [<nil>]
              string ["Println"] [<nil>]
          ident [f] [let: () -> void]
          sig [0->0]

A pkg/semantic/testdata/check/fn_extern_with_body.snow.err => pkg/semantic/testdata/check/fn_extern_with_body.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/fn_extern_with_body.snow:2:4: external function test cannot have a body

A pkg/semantic/testdata/check/fn_extern_with_body.snow.want => pkg/semantic/testdata/check/fn_extern_with_body.snow.want +16 -0
@@ 0,0 1,16 @@
file [1, #0]
  fn
    @ [2]
      ident [extern] [<nil>]
      field
        ident [import] [<nil>]
        string ["x"] [<nil>]
      field
        ident [symbol] [<nil>]
        string ["y"] [<nil>]
    ident [test] [let: () -> void]
    sig [0->0]
    block [1]
      var:
        ident [x] [var: int]
        ident [int] [type: int]

A pkg/semantic/testdata/check/fn_fn_arg.snow.err => pkg/semantic/testdata/check/fn_fn_arg.snow.err +0 -0
A pkg/semantic/testdata/check/fn_fn_arg.snow.want => pkg/semantic/testdata/check/fn_fn_arg.snow.want +41 -0
@@ 0,0 1,41 @@
file [3, #0]
  fn
    ident [do] [let: (int, (int) -> int) -> int]
    sig [2->1]
      param
        ident [x] [let: int]
        ident [int] [type: int]
      param
        ident [ap] [let: (int) -> int]
        sig [1->1] [type: (int) -> int]
          param
            ident [int] [type: int]
          ident [int] [type: int]
      ident [int] [type: int]
    block [1]
      return
        call [1] [value: int]
          ident [ap] [let: (int) -> int]
          item
            ident [x] [let: int]
  fn
    ident [id] [let: (int) -> int]
    sig [1->1]
      param
        ident [x] [let: int]
        ident [int] [type: int]
      ident [int] [type: int]
    block [1]
      return
        ident [x] [let: int]
  fn
    ident [test] [let: () -> void]
    sig [0->0]
    block [1]
      expr
        call [2] [value: int]
          ident [do] [let: (int, (int) -> int) -> int]
          item
            int [1] [const: int]
          item
            ident [id] [let: (int) -> int]

A pkg/semantic/testdata/check/fn_guard_fallthrough.snow.err => pkg/semantic/testdata/check/fn_guard_fallthrough.snow.err +0 -0
A pkg/semantic/testdata/check/fn_guard_fallthrough.snow.want => pkg/semantic/testdata/check/fn_guard_fallthrough.snow.want +14 -0
@@ 0,0 1,14 @@
file [1, #0]
  fn
    ident [test] [let: () -> void]
    sig [0->0]
    block [3]
      var:
        ident [x] [var: bool]
        ident [bool] [type: bool]
      guard [1]
        item
          ident [x] [var: bool]
        else
          block [0]
      return

A pkg/semantic/testdata/check/fn_ident_as_type.snow.err => pkg/semantic/testdata/check/fn_ident_as_type.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/fn_ident_as_type.snow:4:8: expected type context to be type; got let

A pkg/semantic/testdata/check/fn_ident_as_type.snow.want => pkg/semantic/testdata/check/fn_ident_as_type.snow.want +8 -0
@@ 0,0 1,8 @@
file [2, #0]
  fn
    ident [test] [let: () -> void]
    sig [0->0]
    block [0]
  var:
    ident [x] [var: () -> void]
    ident [test] [let: () -> void]

A pkg/semantic/testdata/check/fn_init_order.snow.err => pkg/semantic/testdata/check/fn_init_order.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/fn_init_order.snow:2:11: undefined: B

A pkg/semantic/testdata/check/fn_init_order.snow.want => pkg/semantic/testdata/check/fn_init_order.snow.want +11 -0
@@ 0,0 1,11 @@
file [1, #0]
  fn
    ident [test] [let: () -> void]
    sig [0->0]
    block [2]
      var=
        ident [A] [var: unresolved]
        ident [B] [let: unresolved]
      let=
        ident [B] [let: int]
        int [1] [const: int]

A pkg/semantic/testdata/check/fn_invalid_attr.snow.err => pkg/semantic/testdata/check/fn_invalid_attr.snow.err +5 -0
@@ 0,0 1,5 @@
testdata/fn_invalid_attr.snow:1:2: invalid attribute invalid
testdata/fn_invalid_attr.snow:2:9: invalid key badField
testdata/fn_invalid_attr.snow:3:1: missing value for field import
testdata/fn_invalid_attr.snow:4:2: invalid type for field import: expected string, got int
testdata/fn_invalid_attr.snow:5:4: 3 external attributes applied to test

A pkg/semantic/testdata/check/fn_invalid_attr.snow.want => pkg/semantic/testdata/check/fn_invalid_attr.snow.want +30 -0
@@ 0,0 1,30 @@
file [1, #0]
  fn
    @ [1]
      ident [invalid] [<nil>]
      field
        ident [x] [<nil>]
        string ["a"] [<nil>]
    @ [1]
      ident [extern] [<nil>]
      field
        ident [badField] [<nil>]
        string ["z"] [<nil>]
    @ [2]
      ident [extern] [<nil>]
      field
        ident [pkg] [<nil>]
        string ["z"] [<nil>]
      field
        ident [pkg] [<nil>]
        string ["y"] [<nil>]
    @ [2]
      ident [extern] [<nil>]
      field
        ident [pkg] [<nil>]
        string ["z"] [<nil>]
      field
        ident [import] [<nil>]
        int [3] [<nil>]
    ident [test] [let: () -> void]
    sig [0->0]

A pkg/semantic/testdata/check/fn_invalid_main.snow.err => pkg/semantic/testdata/check/fn_invalid_main.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/fn_invalid_main.snow:1:4: main function must not have any parameter and return value, is (int) -> string

A pkg/semantic/testdata/check/fn_invalid_main.snow.want => pkg/semantic/testdata/check/fn_invalid_main.snow.want +9 -0
@@ 0,0 1,9 @@
file [1, #0]
  fn
    ident [main] [let: (int) -> string]
    sig [1->1]
      param
        ident [x] [let: int]
        ident [int] [type: int]
      ident [string] [type: string]
    block [0]

A pkg/semantic/testdata/check/fn_invalid_ref.snow.err => pkg/semantic/testdata/check/fn_invalid_ref.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/fn_invalid_ref.snow:2:3: function test cannot have a ref modifier; only valid for struct functions (aka methods)

A pkg/semantic/testdata/check/fn_invalid_ref.snow.want => pkg/semantic/testdata/check/fn_invalid_ref.snow.want +9 -0
@@ 0,0 1,9 @@
file [1, #0]
  fn
    ident [main] [let: () -> void]
    sig [0->0]
    block [1]
      ref fn
        ident [test] [let: () -> void]
        sig [0->0]
        block [0]

A pkg/semantic/testdata/check/fn_invalid_ref_call.snow.err => pkg/semantic/testdata/check/fn_invalid_ref_call.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/fn_invalid_ref_call.snow:9:5: cannot access ref fn set; left-hand side must be var, is let

A pkg/semantic/testdata/check/fn_invalid_ref_call.snow.want => pkg/semantic/testdata/check/fn_invalid_ref_call.snow.want +30 -0
@@ 0,0 1,30 @@
file [1, #0]
  fn
    ident [main] [let: () -> void]
    sig [0->0]
    block [3]
      struct [2]
        ident [S] [type: struct S]
        var:
          ident [x] [var: int]
          ident [int] [type: int]
        ref fn
          ident [set] [let: (int) -> void]
          sig [1->0]
            param
              ident [v] [let: int]
              ident [int] [type: int]
          block [1]
            assign
              ident [x] [var: int]
              ident [v] [let: int]
      let:
        ident [s] [let: struct S]
        ident [S] [type: struct S]
      expr
        call [1] [value: void]
          select [let: (int) -> void]
            ident [s] [let: struct S]
            ident [set] [let: (int) -> void]
          item
            int [1] [const: int]

A pkg/semantic/testdata/check/fn_invalid_ref_call_via_value.snow.err => pkg/semantic/testdata/check/fn_invalid_ref_call_via_value.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/fn_invalid_ref_call_via_value.snow:13:12: cannot access ref fn set; left-hand side must be var, is value

A pkg/semantic/testdata/check/fn_invalid_ref_call_via_value.snow.want => pkg/semantic/testdata/check/fn_invalid_ref_call_via_value.snow.want +38 -0
@@ 0,0 1,38 @@
file [1, #0]
  fn
    ident [main] [let: () -> void]
    sig [0->0]
    block [3]
      struct [2]
        ident [S] [type: struct S]
        var:
          ident [x] [var: int]
          ident [int] [type: int]
        ref fn
          ident [set] [let: (int) -> void]
          sig [1->0]
            param
              ident [v] [let: int]
              ident [int] [type: int]
          block [1]
            assign
              ident [x] [var: int]
              ident [v] [let: int]
      fn
        ident [create] [let: () -> struct S]
        sig [0->1]
          ident [S] [type: struct S]
        block [2]
          var:
            ident [s] [var: struct S]
            ident [S] [type: struct S]
          return
            ident [s] [var: struct S]
      expr
        call [1] [value: void]
          select [value: (int) -> void]
            call [0] [value: struct S]
              ident [create] [let: () -> struct S]
            ident [set] [let: (int) -> void]
          item
            int [1] [const: int]

A pkg/semantic/testdata/check/fn_invalid_return.snow.err => pkg/semantic/testdata/check/fn_invalid_return.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/fn_invalid_return.snow:2:10: invalid type for return value: expected uint, got int

A pkg/semantic/testdata/check/fn_invalid_return.snow.want => pkg/semantic/testdata/check/fn_invalid_return.snow.want +9 -0
@@ 0,0 1,9 @@
file [1, #0]
  fn
    ident [test] [let: () -> uint]
    sig [0->1]
      ident [uint] [type: uint]
    block [1]
      return
        unary [-] [value: int]
          int [1] [const: int]

A pkg/semantic/testdata/check/fn_invalid_tuple_access.snow.err => pkg/semantic/testdata/check/fn_invalid_tuple_access.snow.err +2 -0
@@ 0,0 1,2 @@
testdata/fn_invalid_tuple_access.snow:3:3: undefined in (int, string, (bool, uint)): 3
testdata/fn_invalid_tuple_access.snow:4:3: undefined in (bool, uint): 2

A pkg/semantic/testdata/check/fn_invalid_tuple_access.snow.want => pkg/semantic/testdata/check/fn_invalid_tuple_access.snow.want +28 -0
@@ 0,0 1,28 @@
file [1, #0]
  fn
    ident [main] [let: () -> void]
    sig [0->0]
    block [3]
      var:
        ident [x] [var: (int, string, (bool, uint))]
        tuple type [3] [type: (int, string, (bool, uint))]
          param
            ident [int] [type: int]
          param
            ident [string] [type: string]
          param
            tuple type [2] [type: (bool, uint)]
              param
                ident [bool] [type: bool]
              param
                ident [uint] [type: uint]
      expr
        select [var: unresolved]
          ident [x] [var: (int, string, (bool, uint))]
          ident [3] [invalid: unresolved]
      expr
        select [var: unresolved]
          select [var: (bool, uint)]
            ident [x] [var: (int, string, (bool, uint))]
            ident [2] [var: (bool, uint)]
          ident [2] [invalid: unresolved]

A pkg/semantic/testdata/check/fn_main_extern.snow.err => pkg/semantic/testdata/check/fn_main_extern.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/fn_main_extern.snow:2:4: main function cannot be external

A pkg/semantic/testdata/check/fn_main_extern.snow.want => pkg/semantic/testdata/check/fn_main_extern.snow.want +12 -0
@@ 0,0 1,12 @@
file [1, #0]
  fn
    @ [2]
      ident [extern] [<nil>]
      field
        ident [import] [<nil>]
        string ["fmt"] [<nil>]
      field
        ident [symbol] [<nil>]
        string ["Println"] [<nil>]
    ident [main] [let: () -> void]
    sig [0->0]

A pkg/semantic/testdata/check/fn_many_extern.snow.err => pkg/semantic/testdata/check/fn_many_extern.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/fn_many_extern.snow:3:4: 2 external attributes applied to test

A pkg/semantic/testdata/check/fn_many_extern.snow.want => pkg/semantic/testdata/check/fn_many_extern.snow.want +20 -0
@@ 0,0 1,20 @@
file [1, #0]
  fn
    @ [2]
      ident [extern] [<nil>]
      field
        ident [import] [<nil>]
        string ["x"] [<nil>]
      field
        ident [symbol] [<nil>]
        string ["y"] [<nil>]
    @ [2]
      ident [extern] [<nil>]
      field
        ident [import] [<nil>]
        string ["z"] [<nil>]
      field
        ident [symbol] [<nil>]
        string ["a"] [<nil>]
    ident [test] [let: () -> void]
    sig [0->0]

A pkg/semantic/testdata/check/fn_method_explicit_self.snow.err => pkg/semantic/testdata/check/fn_method_explicit_self.snow.err +0 -0
A pkg/semantic/testdata/check/fn_method_explicit_self.snow.want => pkg/semantic/testdata/check/fn_method_explicit_self.snow.want +27 -0
@@ 0,0 1,27 @@
file [2, #0]
  struct [2]
    ident [S] [type: struct S]
    var:
      ident [x] [var: int]
      ident [int] [type: int]
    fn
      ident [getX] [let: () -> int]
      sig [0->1]
        ident [int] [type: int]
      block [1]
        return
          select [let: int]
            ident [self] [let: struct S]
            ident [x] [var: int]
  fn
    ident [main] [let: () -> void]
    sig [0->0]
    block [2]
      var:
        ident [s] [var: struct S]
        ident [S] [type: struct S]
      expr
        call [0] [value: int]
          select [let: () -> int]
            ident [s] [var: struct S]
            ident [getX] [let: () -> int]

A pkg/semantic/testdata/check/fn_nested_block.snow.err => pkg/semantic/testdata/check/fn_nested_block.snow.err +0 -0
A pkg/semantic/testdata/check/fn_nested_block.snow.want => pkg/semantic/testdata/check/fn_nested_block.snow.want +29 -0
@@ 0,0 1,29 @@
file [1, #0]
  fn
    ident [test] [let: (int, int) -> int]
    sig [2->1]
      param
        ident [x] [let: int]
        ident [int] [type: int]
      param
        ident [y] [let: int]
        ident [int] [type: int]
      ident [int] [type: int]
    block [2]
      let:
        ident [s1] [let: int]
        ident [int] [type: int]
      block [3]
        let:
          ident [s2] [let: int]
          ident [int] [type: int]
        block [2]
          let:
            ident [inside] [let: int]
            ident [int] [type: int]
          var:
            ident [s1] [var: int]
            ident [int] [type: int]
        let:
          ident [s2b] [let: int]
          ident [int] [type: int]

A pkg/semantic/testdata/check/fn_nested_fn.snow.err => pkg/semantic/testdata/check/fn_nested_fn.snow.err +0 -0
A pkg/semantic/testdata/check/fn_nested_fn.snow.want => pkg/semantic/testdata/check/fn_nested_fn.snow.want +34 -0
@@ 0,0 1,34 @@
file [1, #0]
  fn
    ident [main] [let: () -> void]
    sig [0->0]
    block [4]
      fn
        ident [add] [let: (int, int) -> int]
        sig [2->1]
          param
            ident [x] [let: int]
            ident [int] [type: int]
          param
            ident [y] [let: int]
            ident [int] [type: int]
          ident [int] [type: int]
        block [1]
          return
            binary [+] [value: int]
              ident [x] [let: int]
              ident [y] [let: int]
      let=
        ident [x] [let: int]
        int [1] [const: int]
      let=
        ident [y] [let: int]
        int [2] [const: int]
      let=
        ident [z] [let: int]
        call [2] [value: int]
          ident [add] [let: (int, int) -> int]
          item
            ident [x] [let: int]
          item
            ident [y] [let: int]

A pkg/semantic/testdata/check/fn_nested_fn_init_order.snow.err => pkg/semantic/testdata/check/fn_nested_fn_init_order.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/fn_nested_fn_init_order.snow:3:5: undefined: B

A pkg/semantic/testdata/check/fn_nested_fn_init_order.snow.want => pkg/semantic/testdata/check/fn_nested_fn_init_order.snow.want +22 -0
@@ 0,0 1,22 @@
file [1, #0]
  fn
    ident [main] [let: () -> void]
    sig [0->0]
    block [3]
      fn
        ident [A] [let: () -> void]
        sig [0->0]
        block [1]
          expr
            call [0] [value: unresolved]
              ident [B] [let: unresolved]
      fn
        ident [B] [let: () -> void]
        sig [0->0]
        block [1]
          expr
            call [0] [value: void]
              ident [A] [let: () -> void]
      expr
        call [0] [value: void]
          ident [A] [let: () -> void]

A pkg/semantic/testdata/check/fn_nested_struct_method.snow.err => pkg/semantic/testdata/check/fn_nested_struct_method.snow.err +0 -0
A pkg/semantic/testdata/check/fn_nested_struct_method.snow.want => pkg/semantic/testdata/check/fn_nested_struct_method.snow.want +63 -0
@@ 0,0 1,63 @@
file [1, #0]
  fn
    ident [main] [let: () -> void]
    sig [0->0]
    block [6]
      struct [3]
        ident [S] [type: struct S]
        var:
          ident [x] [var: string]
          ident [string] [type: string]
        struct [2]
          ident [T] [type: struct T]
          var:
            ident [y] [var: string]
            ident [string] [type: string]
          ref fn
            ident [append] [let: (string) -> void]
            sig [1->0]
              param
                ident [s] [let: string]
                ident [string] [type: string]
            block [1]
              assign
                ident [y] [var: string]
                binary [+] [value: string]
                  ident [y] [var: string]
                  ident [s] [let: string]
        ref fn
          ident [init] [let: () -> void]
          sig [0->0]
          block [1]
            assign
              ident [x] [var: string]
              string ["hello"] [const: string]
      var:
        ident [s] [var: struct S]
        ident [S] [type: struct S]
      var:
        ident [t] [var: struct T]
        select [type: struct T]
          ident [S] [type: struct S]
          ident [T] [type: struct T]
      expr
        call [0] [value: void]
          select [let: () -> void]
            ident [s] [var: struct S]
            ident [init] [let: () -> void]
      expr
        call [1] [value: void]
          select [let: (string) -> void]
            ident [t] [var: struct T]
            ident [append] [let: (string) -> void]
          item
            select [var: string]
              ident [s] [var: struct S]
              ident [x] [var: string]
      expr
        call [1] [value: void]
          select [let: (string) -> void]
            ident [t] [var: struct T]
            ident [append] [let: (string) -> void]
          item
            string [", world"] [const: string]

A pkg/semantic/testdata/check/fn_nested_struct_self.snow.err => pkg/semantic/testdata/check/fn_nested_struct_self.snow.err +0 -0
A pkg/semantic/testdata/check/fn_nested_struct_self.snow.want => pkg/semantic/testdata/check/fn_nested_struct_self.snow.want +21 -0
@@ 0,0 1,21 @@
file [1, #0]
  struct [2]
    ident [S] [type: struct S]
    var:
      ident [x] [var: string]
      ident [string] [type: string]
    struct [2]
      ident [T] [type: struct T]
      var:
        ident [x] [var: int]
        ident [int] [type: int]
      fn
        ident [negate] [let: () -> int]
        sig [0->1]
          ident [int] [type: int]
        block [1]
          return
            unary [-] [value: int]
              select [let: int]
                ident [self] [let: struct T]
                ident [x] [var: int]

A pkg/semantic/testdata/check/fn_nested_structs.snow.err => pkg/semantic/testdata/check/fn_nested_structs.snow.err +0 -0
A pkg/semantic/testdata/check/fn_nested_structs.snow.want => pkg/semantic/testdata/check/fn_nested_structs.snow.want +24 -0
@@ 0,0 1,24 @@
file [1, #0]
  fn
    ident [test] [let: () -> void]
    sig [0->0]
    block [3]
      struct [2]
        ident [Outer] [type: struct Outer]
        struct [1]
          ident [Inner] [type: struct Inner]
          let:
            ident [y] [let: int]
            ident [int] [type: int]
        let:
          ident [x] [let: struct Inner]
          ident [Inner] [type: struct Inner]
      var:
        ident [o] [var: struct Outer]
        ident [Outer] [type: struct Outer]
      expr
        select [let: int]
          select [let: struct Inner]
            ident [o] [var: struct Outer]
            ident [x] [let: struct Inner]
          ident [y] [let: int]

A pkg/semantic/testdata/check/fn_nested_tuple_type.snow.err => pkg/semantic/testdata/check/fn_nested_tuple_type.snow.err +0 -0
A pkg/semantic/testdata/check/fn_nested_tuple_type.snow.want => pkg/semantic/testdata/check/fn_nested_tuple_type.snow.want +16 -0
@@ 0,0 1,16 @@
file [1, #0]
  fn
    ident [main] [let: () -> void]
    sig [0->0]
    block [1]
      var:
        ident [x] [var: (int, (bool, string))]
        tuple type [2] [type: (int, (bool, string))]
          param
            ident [int] [type: int]
          param
            tuple type [2] [type: (bool, string)]
              param
                ident [bool] [type: bool]
              param
                ident [string] [type: string]

A pkg/semantic/testdata/check/fn_non_type_selectors.snow.err => pkg/semantic/testdata/check/fn_non_type_selectors.snow.err +16 -0
@@ 0,0 1,16 @@
testdata/fn_non_type_selectors.snow:12:7: invalid type for identifier v1: unresolved
testdata/fn_non_type_selectors.snow:12:11: expected type context to be type; got var
testdata/fn_non_type_selectors.snow:12:11: invalid type int for field selection
testdata/fn_non_type_selectors.snow:12:13: expected type context to be one of type, var, let; got invalid
testdata/fn_non_type_selectors.snow:13:7: invalid type for identifier v2: unresolved
testdata/fn_non_type_selectors.snow:13:11: expected type context to be type; got var
testdata/fn_non_type_selectors.snow:13:11: invalid type int for field selection
testdata/fn_non_type_selectors.snow:13:13: expected type context to be one of type, var, let; got invalid
testdata/fn_non_type_selectors.snow:14:11: expected type context to be type; got invalid
testdata/fn_non_type_selectors.snow:15:11: expected type context to be type; got invalid
testdata/fn_non_type_selectors.snow:16:7: invalid type for identifier v5: unresolved
testdata/fn_non_type_selectors.snow:16:11: expected type context to be type; got var
testdata/fn_non_type_selectors.snow:16:12: invalid type int for field selection
testdata/fn_non_type_selectors.snow:16:14: expected type context to be one of type, var, let; got invalid
testdata/fn_non_type_selectors.snow:17:11: expected type context to be type; got invalid
testdata/fn_non_type_selectors.snow:18:11: expected type context to be type; got invalid

A pkg/semantic/testdata/check/fn_non_type_selectors.snow.want => pkg/semantic/testdata/check/fn_non_type_selectors.snow.want +63 -0
@@ 0,0 1,63 @@
file [4, #0]
  struct [2]
    ident [S] [type: struct S]
    var:
      ident [ss] [var: int]
      ident [int] [type: int]
    struct [1]
      ident [T] [type: struct T]
      var:
        ident [tt] [var: int]
        ident [int] [type: int]
  var:
    ident [x] [var: int]
    ident [int] [type: int]
  let:
    ident [y] [let: string]
    ident [string] [type: string]
  fn
    ident [main] [let: () -> void]
    sig [0->0]
    block [7]
      var:
        ident [v1] [var: unresolved]
        select [var: unresolved]
          ident [x] [var: int]
          ident [y] [invalid: unresolved]
      var:
        ident [v2] [var: unresolved]
        select [var: unresolved]
          ident [x] [var: int]
          ident [S] [invalid: unresolved]
      var:
        ident [v3] [var: int]
        select [invalid: int]
          ident [S] [type: struct S]
          ident [ss] [var: int]
      var:
        ident [v4] [var: int]
        select [invalid: int]
          select [type: struct T]
            ident [S] [type: struct S]
            ident [T] [type: struct T]
          ident [tt] [var: int]
      var:
        ident [v5] [var: unresolved]
        paren [var: unresolved]
          select [var: unresolved]
            ident [x] [var: int]
            ident [y] [invalid: unresolved]
      var:
        ident [v6] [var: int]
        paren [invalid: int]
          select [invalid: int]
            ident [S] [type: struct S]
            ident [ss] [var: int]
      var:
        ident [v7] [var: int]
        paren [invalid: int]
          select [invalid: int]
            select [type: struct T]
              ident [S] [type: struct S]
              ident [T] [type: struct T]
            ident [tt] [var: int]

A pkg/semantic/testdata/check/fn_param_type_is_var_in_body.snow.err => pkg/semantic/testdata/check/fn_param_type_is_var_in_body.snow.err +0 -0
A pkg/semantic/testdata/check/fn_param_type_is_var_in_body.snow.want => pkg/semantic/testdata/check/fn_param_type_is_var_in_body.snow.want +7 -0
@@ 0,0 1,7 @@
file testdata/fn_param_type_is_var_in_body.snow [0, 1, 0]
  fn test [let: (int) -> void]
    let: x [let: int]
      ident int [type: int]
    block [1]
      var= int [var: string]
        string ["abc"] [const: string]

A pkg/semantic/testdata/check/fn_params.snow.err => pkg/semantic/testdata/check/fn_params.snow.err +0 -0
A pkg/semantic/testdata/check/fn_params.snow.want => pkg/semantic/testdata/check/fn_params.snow.want +12 -0
@@ 0,0 1,12 @@
file testdata/fn_params.snow [0, 1, 0]
  fn test [let: (int, int) -> int]
    let: x [let: int]
      ident int [type: int]
    let: y [let: int]
      ident int [type: int]
    ident int [type: int]
    block [1]
      return
        binary [+] [value: int]
          ident x [let: int]
          ident y [let: int]

A pkg/semantic/testdata/check/fn_params_locals.snow.err => pkg/semantic/testdata/check/fn_params_locals.snow.err +0 -0
A pkg/semantic/testdata/check/fn_params_locals.snow.want => pkg/semantic/testdata/check/fn_params_locals.snow.want +14 -0
@@ 0,0 1,14 @@
file testdata/fn_params_locals.snow [0, 1, 0]
  fn test [let: (int, int) -> int]
    let: x [let: int]
      ident int [type: int]
    let: y [let: int]
      ident int [type: int]
    ident int [type: int]
    block [2]
      var= z [var: int]
        binary [+] [value: int]
          ident x [let: int]
          ident y [let: int]
      return
        ident z [var: int]

A pkg/semantic/testdata/check/fn_recursion.snow.err => pkg/semantic/testdata/check/fn_recursion.snow.err +0 -0
A pkg/semantic/testdata/check/fn_recursion.snow.want => pkg/semantic/testdata/check/fn_recursion.snow.want +19 -0
@@ 0,0 1,19 @@
file testdata/fn_recursion.snow [0, 1, 0]
  fn test [let: (int) -> int]
    let: x [let: int]
      ident int [type: int]
    ident int [type: int]
    block [2]
      if [1]
        binary [<] [value: bool]
          ident x [let: int]
          int [0] [const: int]
        block [1]
          return
            ident x [let: int]
      return
        call [1] [value: int]
          ident test [let: (int) -> int]
          binary [-] [value: int]
            ident x [let: int]
            int [1] [const: int]

A pkg/semantic/testdata/check/fn_return_internal_struct.snow.err => pkg/semantic/testdata/check/fn_return_internal_struct.snow.err +3 -0
@@ 0,0 1,3 @@
testdata/fn_return_internal_struct.snow:1:4: invalid type for declaration test: () -> unresolved
testdata/fn_return_internal_struct.snow:1:14: invalid type for identifier S: unresolved
testdata/fn_return_internal_struct.snow:1:14: undefined: S

A pkg/semantic/testdata/check/fn_return_internal_struct.snow.want => pkg/semantic/testdata/check/fn_return_internal_struct.snow.want +9 -0
@@ 0,0 1,9 @@
file testdata/fn_return_internal_struct.snow [0, 1, 0]
  fn test [let: () -> unresolved]
    ident S [invalid: unresolved]
    block [3]
      struct S [0, 0, 0] [type: struct S]
      var: s [var: struct S]
        ident S [type: struct S]
      return
        ident s [var: struct S]

A pkg/semantic/testdata/check/fn_return_missing_value.snow.err => pkg/semantic/testdata/check/fn_return_missing_value.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/fn_return_missing_value.snow:2:3: missing return value, expected a value of type int

A pkg/semantic/testdata/check/fn_return_missing_value.snow.want => pkg/semantic/testdata/check/fn_return_missing_value.snow.want +5 -0
@@ 0,0 1,5 @@
file testdata/fn_return_missing_value.snow [0, 1, 0]
  fn test [let: () -> int]
    ident int [type: int]
    block [1]
      return

A pkg/semantic/testdata/check/fn_return_struct.snow.err => pkg/semantic/testdata/check/fn_return_struct.snow.err +3 -0
@@ 0,0 1,3 @@
testdata/fn_return_struct.snow:17:3: expected type context to be var; got value
testdata/fn_return_struct.snow:18:3: expected type context to be var; got value
testdata/fn_return_struct.snow:19:3: expected type context to be var; got value

A pkg/semantic/testdata/check/fn_return_struct.snow.want => pkg/semantic/testdata/check/fn_return_struct.snow.want +53 -0
@@ 0,0 1,53 @@
file testdata/fn_return_struct.snow [0, 2, 1]
  fn newS [let: () -> struct S]
    ident S [type: struct S]
    block [2]
      var: s [var: struct S]
        ident S [type: struct S]
      return
        ident s [var: struct S]
  fn test [let: () -> void]
    block [6]
      expr
        select [value: int]
          call [0] [value: struct S]
            ident newS [let: () -> struct S]
          ident x [let: int]
      expr
        select [value: int]
          call [0] [value: struct S]
            ident newS [let: () -> struct S]
          ident y [var: int]
      expr
        call [0] [value: void]
          select [value: () -> void]
            call [0] [value: struct S]
              ident newS [let: () -> struct S]
            ident z [let: () -> void]
      assign
        select [value: int]
          call [0] [value: struct S]
            ident newS [let: () -> struct S]
          ident x [let: int]
        int [1] [const: int]
      assign
        select [value: int]
          call [0] [value: struct S]
            ident newS [let: () -> struct S]
          ident y [var: int]
        int [2] [const: int]
      assign
        select [value: () -> void]
          call [0] [value: struct S]
            ident newS [let: () -> struct S]
          ident z [let: () -> void]
        ident test [let: () -> void]
  struct S [2, 1, 0] [type: struct S]
    let: x [let: int]
      ident int [type: int]
    var: y [var: int]
      ident int [type: int]
    fn z [let: () -> void]
      block [1]
        let: self [let: struct S]
          ident S [type: struct S]

A pkg/semantic/testdata/check/fn_return_unifying_type.snow.err => pkg/semantic/testdata/check/fn_return_unifying_type.snow.err +0 -0
A pkg/semantic/testdata/check/fn_return_unifying_type.snow.want => pkg/semantic/testdata/check/fn_return_unifying_type.snow.want +9 -0
@@ 0,0 1,9 @@
file testdata/fn_return_unifying_type.snow [0, 1, 0]
  fn test [let: () -> i16]
    ident i16 [type: i16]
    block [2]
      var: x [var: i8]
        ident i8 [type: i8]
      return
        implicit conv [var: i16]
          ident x [var: i8]

A pkg/semantic/testdata/check/fn_struct_main_method.snow.err => pkg/semantic/testdata/check/fn_struct_main_method.snow.err +0 -0
A pkg/semantic/testdata/check/fn_struct_main_method.snow.want => pkg/semantic/testdata/check/fn_struct_main_method.snow.want +10 -0
@@ 0,0 1,10 @@
file testdata/fn_struct_main_method.snow [0, 1, 1]
  fn main [let: () -> void]
    block [0]
  struct S [0, 1, 0] [type: struct S]
    fn main [let: (int) -> void]
      let: x [let: int]
        ident int [type: int]
      block [1]
        let: self [let: struct S]
          ident S [type: struct S]

A pkg/semantic/testdata/check/fn_struct_method_access_top_level.snow.err => pkg/semantic/testdata/check/fn_struct_method_access_top_level.snow.err +0 -0
A pkg/semantic/testdata/check/fn_struct_method_access_top_level.snow.want => pkg/semantic/testdata/check/fn_struct_method_access_top_level.snow.want +13 -0
@@ 0,0 1,13 @@
file testdata/fn_struct_method_access_top_level.snow [1, 1, 1]
  var: x [var: int]
    ident int [type: int]
  fn main [let: () -> void]
    block [0]
  struct S [0, 1, 0] [type: struct S]
    fn get [let: () -> int]
      ident int [type: int]
      block [2]
        let: self [let: struct S]
          ident S [type: struct S]
        return
          ident x [var: int]

A pkg/semantic/testdata/check/fn_struct_order_independent.snow.err => pkg/semantic/testdata/check/fn_struct_order_independent.snow.err +0 -0
A pkg/semantic/testdata/check/fn_struct_order_independent.snow.want => pkg/semantic/testdata/check/fn_struct_order_independent.snow.want +15 -0
@@ 0,0 1,15 @@
file testdata/fn_struct_order_independent.snow [0, 0, 1]
  struct S [2, 1, 0] [type: struct S]
    var: x [var: int]
      ident int [type: int]
    let: y [let: int]
      ident int [type: int]
    fn test [let: () -> int]
      ident int [type: int]
      block [2]
        let: self [let: struct S]
          ident S [type: struct S]
        return
          binary [+] [value: int]
            ident x [var: int]
            ident y [let: int]

A pkg/semantic/testdata/check/fn_struct_same_name_diff_scope.snow.err => pkg/semantic/testdata/check/fn_struct_same_name_diff_scope.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/fn_struct_same_name_diff_scope.snow:7:9: cannot assign type struct A to variable of type struct A

A pkg/semantic/testdata/check/fn_struct_same_name_diff_scope.snow.want => pkg/semantic/testdata/check/fn_struct_same_name_diff_scope.snow.want +13 -0
@@ 0,0 1,13 @@
file testdata/fn_struct_same_name_diff_scope.snow [0, 1, 0]
  fn test [let: () -> void]
    block [3]
      struct A [0, 0, 0] [type: struct A]
      var: a [var: struct A]
        ident A [type: struct A]
      block [3]
        struct A [0, 0, 0] [type: struct A]
        var: b [var: struct A]
          ident A [type: struct A]
        assign
          ident a [var: struct A]
          ident b [var: struct A]

A pkg/semantic/testdata/check/fn_struct_selector.snow.err => pkg/semantic/testdata/check/fn_struct_selector.snow.err +0 -0
A pkg/semantic/testdata/check/fn_struct_selector.snow.want => pkg/semantic/testdata/check/fn_struct_selector.snow.want +12 -0
@@ 0,0 1,12 @@
file testdata/fn_struct_selector.snow [0, 1, 1]
  fn test [let: () -> void]
    block [2]
      var: p [var: struct Point]
        ident Point [type: struct Point]
      expr
        select [let: int]
          ident p [var: struct Point]
          ident x [let: int]
  struct Point [1, 0, 0] [type: struct Point]
    let: x [let: int]
      ident int [type: int]

A pkg/semantic/testdata/check/fn_struct_self_shadow.snow.err => pkg/semantic/testdata/check/fn_struct_self_shadow.snow.err +0 -0
A pkg/semantic/testdata/check/fn_struct_self_shadow.snow.want => pkg/semantic/testdata/check/fn_struct_self_shadow.snow.want +13 -0
@@ 0,0 1,13 @@
file testdata/fn_struct_self_shadow.snow [0, 0, 1]
  struct S [1, 1, 0] [type: struct S]
    var: self [var: int]
      ident int [type: int]
    fn get [let: () -> int]
      ident int [type: int]
      block [2]
        let: self [let: struct S]
          ident S [type: struct S]
        return
          select [let: int]
            ident self [let: struct S]
            ident self [var: int]

A pkg/semantic/testdata/check/fn_struct_self_uses.snow.err => pkg/semantic/testdata/check/fn_struct_self_uses.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/fn_struct_self_uses.snow:3:9: var self: symbol already declared in this scope

A pkg/semantic/testdata/check/fn_struct_self_uses.snow.want => pkg/semantic/testdata/check/fn_struct_self_uses.snow.want +8 -0
@@ 0,0 1,8 @@
file testdata/fn_struct_self_uses.snow [0, 0, 1]
  struct S [0, 1, 0] [type: struct S]
    fn set [let: () -> void]
      block [2]
        let: self [let: struct S]
          ident S [type: struct S]
        var: self [var: int]
          ident int [type: int]

A pkg/semantic/testdata/check/fn_tuple_assign_compatible_types.snow.err => pkg/semantic/testdata/check/fn_tuple_assign_compatible_types.snow.err +0 -0
A pkg/semantic/testdata/check/fn_tuple_assign_compatible_types.snow.want => pkg/semantic/testdata/check/fn_tuple_assign_compatible_types.snow.want +19 -0
@@ 0,0 1,19 @@
file testdata/fn_tuple_assign_compatible_types.snow [0, 1, 0]
  fn main [let: () -> void]
    block [4]
      var: i [var: i16]
        ident i16 [type: i16]
      var: u [var: u8]
        ident u8 [type: u8]
      var: t [var: (i32, u16, bool)]
        tuple type [3] [type: (i32, u16, bool)]
          ident i32 [type: i32]
          ident u16 [type: u16]
          ident bool [type: bool]
      assign
        ident t [var: (i32, u16, bool)]
        implicit conv [value: (i32, u16, bool)]
          tuple value [3] [value: (i16, u8, bool)]
            ident i [var: i16]
            ident u [var: u8]
            ident true [let: bool]

A pkg/semantic/testdata/check/fn_tuple_assign_incompatible_types.snow.err => pkg/semantic/testdata/check/fn_tuple_assign_incompatible_types.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/fn_tuple_assign_incompatible_types.snow:6:7: cannot assign type (i64, u32, bool) to variable of type (i32, u16, bool)

A pkg/semantic/testdata/check/fn_tuple_assign_incompatible_types.snow.want => pkg/semantic/testdata/check/fn_tuple_assign_incompatible_types.snow.want +18 -0
@@ 0,0 1,18 @@
file testdata/fn_tuple_assign_incompatible_types.snow [0, 1, 0]
  fn main [let: () -> void]
    block [4]
      var: t [var: (i32, u16, bool)]
        tuple type [3] [type: (i32, u16, bool)]
          ident i32 [type: i32]
          ident u16 [type: u16]
          ident bool [type: bool]
      var: a [var: i64]
        ident i64 [type: i64]
      var: b [var: u32]
        ident u32 [type: u32]
      assign
        ident t [var: (i32, u16, bool)]
        tuple value [3] [value: (i64, u32, bool)]
          ident a [var: i64]
          ident b [var: u32]
          ident false [let: bool]

A pkg/semantic/testdata/check/fn_tuple_expr_select_field.snow.err => pkg/semantic/testdata/check/fn_tuple_expr_select_field.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/fn_tuple_expr_select_field.snow:6:3: expected type context to be var; got let

A pkg/semantic/testdata/check/fn_tuple_expr_select_field.snow.want => pkg/semantic/testdata/check/fn_tuple_expr_select_field.snow.want +22 -0
@@ 0,0 1,22 @@
file testdata/fn_tuple_expr_select_field.snow [0, 1, 0]
  fn main [let: () -> void]
    block [4]
      var= t1 [var: (int, int, int)]
        tuple value [3] [value: (int, int, int)]
          int [1] [const: int]
          int [2] [const: int]
          int [3] [const: int]
      let= t2 [let: (string, string)]
        tuple value [2] [value: (string, string)]
          string ["a"] [const: string]
          string ["b"] [const: string]
      assign
        select [var: int]
          ident t1 [var: (int, int, int)]
          ident 0 [var: int]
        int [4] [const: int]
      assign
        select [let: string]
          ident t2 [let: (string, string)]
          ident 1 [let: string]
        string ["c"] [const: string]

A pkg/semantic/testdata/check/fn_type_as_value.snow.err => pkg/semantic/testdata/check/fn_type_as_value.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/fn_type_as_value.snow:2:13: expected type context to be one of const, value, var, let; got type

A pkg/semantic/testdata/check/fn_type_as_value.snow.want => pkg/semantic/testdata/check/fn_type_as_value.snow.want +7 -0
@@ 0,0 1,7 @@
file testdata/fn_type_as_value.snow [0, 1, 0]
  fn test [let: () -> void]
    block [1]
      let= res [let: int]
        binary [+] [value: int]
          ident int [type: int]
          int [3] [const: int]

A pkg/semantic/testdata/check/fn_unknown_symbol.snow.err => pkg/semantic/testdata/check/fn_unknown_symbol.snow.err +8 -0
@@ 0,0 1,8 @@
testdata/fn_unknown_symbol.snow:2:3: expected type SignatureType; got unresolved
testdata/fn_unknown_symbol.snow:2:3: invalid type for identifier add: unresolved
testdata/fn_unknown_symbol.snow:2:3: invalid type: unresolved
testdata/fn_unknown_symbol.snow:2:3: undefined: add
testdata/fn_unknown_symbol.snow:2:7: invalid type for identifier x: unresolved
testdata/fn_unknown_symbol.snow:2:7: undefined: x
testdata/fn_unknown_symbol.snow:2:10: invalid type for identifier y: unresolved
testdata/fn_unknown_symbol.snow:2:10: undefined: y

A pkg/semantic/testdata/check/fn_unknown_symbol.snow.want => pkg/semantic/testdata/check/fn_unknown_symbol.snow.want +8 -0
@@ 0,0 1,8 @@
file testdata/fn_unknown_symbol.snow [0, 1, 0]
  fn test [let: () -> void]
    block [1]
      expr
        call [2] [value: unresolved]
          ident add [invalid: unresolved]
          ident x [invalid: unresolved]
          ident y [invalid: unresolved]

A pkg/semantic/testdata/check/fn_var_as_param_type.snow.err => pkg/semantic/testdata/check/fn_var_as_param_type.snow.err +3 -0
@@ 0,0 1,3 @@
testdata/fn_var_as_param_type.snow:3:10: expected type context to be type; got var
testdata/fn_var_as_param_type.snow:5:12: expected type context to be type; got var
testdata/fn_var_as_param_type.snow:5:18: expected type context to be type; got var

A pkg/semantic/testdata/check/fn_var_as_param_type.snow.want => pkg/semantic/testdata/check/fn_var_as_param_type.snow.want +17 -0
@@ 0,0 1,17 @@
file testdata/fn_var_as_param_type.snow [3, 1, 0]
  var: x [var: int]
    ident int [type: int]
  var: f [var: (int) -> void]
    sig [1->1] [type: (int) -> void]
      ident int [type: int]
      ident void [type: void]
  var: f2 [var: (int) -> string]
    sig [1->1] [type: (int) -> string]
      ident x [var: int]
      ident string [type: string]
  fn test [let: (int, (int) -> void) -> void]
    let: y [let: int]
      ident x [var: int]
    let: z [let: (int) -> void]
      ident f [var: (int) -> void]
    block [0]

A pkg/semantic/testdata/check/fn_without_body.snow.err => pkg/semantic/testdata/check/fn_without_body.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/fn_without_body.snow:1:4: function test must have a body

A pkg/semantic/testdata/check/fn_without_body.snow.want => pkg/semantic/testdata/check/fn_without_body.snow.want +2 -0
@@ 0,0 1,2 @@
file testdata/fn_without_body.snow [0, 1, 0]
  fn test [let: () -> void]

A pkg/semantic/testdata/check/fns.snow.err => pkg/semantic/testdata/check/fns.snow.err +0 -0
A pkg/semantic/testdata/check/fns.snow.want => pkg/semantic/testdata/check/fns.snow.want +33 -0
@@ 0,0 1,33 @@
file testdata/fns.snow [0, 3, 0]
  fn add [let: (int, int) -> int]
    let: x [let: int]
      ident int [type: int]
    let: y [let: int]
      ident int [type: int]
    ident int [type: int]
    block [2]
      let= z [let: int]
        binary [+] [value: int]
          ident x [let: int]
          ident y [let: int]
      return
        ident z [let: int]
  fn main [let: () -> void]
    block [2]
      let:= result [let: int]
        ident int [type: int]
        call [2] [value: int]
          ident add [let: (int, int) -> int]
          int [1] [const: int]
          int [3] [const: int]
      expr
        call [1] [value: void]
          ident println [let: (int) -> void]
          ident result [let: int]
  fn println [let: (int) -> void]
    @ [import, symbol] [2] [value: struct extern]
      ident extern [type: struct extern]
      string ["fmt"] [const: string]
      string ["Println"] [const: string]
    let: x [let: int]
      ident int [type: int]

A pkg/semantic/testdata/check/guard_else.snow.err => pkg/semantic/testdata/check/guard_else.snow.err +0 -0
A pkg/semantic/testdata/check/guard_else.snow.want => pkg/semantic/testdata/check/guard_else.snow.want +20 -0
@@ 0,0 1,20 @@
file testdata/guard_else.snow [0, 1, 0]
  fn test [let: () -> void]
    block [3]
      var= x [var: bool]
        ident true [let: bool]
      var= y [var: bool]
        ident false [let: bool]
      guard [2]
        ident x [var: bool]
        ident y [var: bool]
        block [3]
          var= a [var: int]
            int [1] [const: int]
          var= b [var: bool]
            ident true [let: bool]
          guard [1]
            ident b [var: bool]
            block [1]
              let= c [let: int]
                int [2] [const: int]

A pkg/semantic/testdata/check/if_else_if.snow.err => pkg/semantic/testdata/check/if_else_if.snow.err +0 -0
A pkg/semantic/testdata/check/if_else_if.snow.want => pkg/semantic/testdata/check/if_else_if.snow.want +23 -0
@@ 0,0 1,23 @@
file testdata/if_else_if.snow [0, 1, 0]
  fn test [let: () -> void]
    block [3]
      var= x [var: bool]
        ident true [let: bool]
      var= y [var: bool]
        ident false [let: bool]
      if [1]
        ident x [var: bool]
        block [1]
          var= a [var: int]
            int [1] [const: int]
        if [1]
          ident y [var: bool]
          block [1]
            var= b [var: int]
              int [2] [const: int]
          block [2]
            var= c [var: int]
              int [3] [const: int]
            block [1]
              var= d [var: int]
                int [4] [const: int]

A pkg/semantic/testdata/check/if_non_bool.snow.err => pkg/semantic/testdata/check/if_non_bool.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/if_non_bool.snow:3:6: non-bool (type int) used as condition

A pkg/semantic/testdata/check/if_non_bool.snow.want => pkg/semantic/testdata/check/if_non_bool.snow.want +8 -0
@@ 0,0 1,8 @@
file testdata/if_non_bool.snow [0, 1, 0]
  fn test [let: () -> void]
    block [2]
      var= x [var: int]
        int [3] [const: int]
      if [1]
        ident x [var: int]
        block [0]

A pkg/semantic/testdata/check/invalid_binary_op.snow.err => pkg/semantic/testdata/check/invalid_binary_op.snow.err +2 -0
@@ 0,0 1,2 @@
testdata/invalid_binary_op.snow:3:9: incompatible operand types: string * int
testdata/invalid_binary_op.snow:3:9: invalid type: unresolved

A pkg/semantic/testdata/check/invalid_binary_op.snow.want => pkg/semantic/testdata/check/invalid_binary_op.snow.want +9 -0
@@ 0,0 1,9 @@
file testdata/invalid_binary_op.snow [3, 0, 0]
  var= x [var: int]
    int [3] [const: int]
  var= y [var: string]
    string ["a"] [const: string]
  var= z [var: unresolved]
    binary [*] [value: unresolved]
      ident y [var: string]
      ident x [var: int]

A pkg/semantic/testdata/check/let.snow.err => pkg/semantic/testdata/check/let.snow.err +0 -0
A pkg/semantic/testdata/check/let.snow.want => pkg/semantic/testdata/check/let.snow.want +4 -0
@@ 0,0 1,4 @@
file testdata/let.snow [1, 0, 0]
  let:= y [let: string]
    ident string [type: string]
    string ["abc"] [const: string]

A pkg/semantic/testdata/check/let_invalid_tuple_type.snow.err => pkg/semantic/testdata/check/let_invalid_tuple_type.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/let_invalid_tuple_type.snow:1:14: expected type context to be type; got let

A pkg/semantic/testdata/check/let_invalid_tuple_type.snow.want => pkg/semantic/testdata/check/let_invalid_tuple_type.snow.want +5 -0
@@ 0,0 1,5 @@
file testdata/let_invalid_tuple_type.snow [1, 0, 0]
  let: x [let: (int, bool)]
    tuple type [2] [type: (int, bool)]
      ident int [type: int]
      ident true [let: bool]

A pkg/semantic/testdata/check/let_invalid_unary.snow.err => pkg/semantic/testdata/check/let_invalid_unary.snow.err +2 -0
@@ 0,0 1,2 @@
testdata/let_invalid_unary.snow:1:9: invalid operation: ! string
testdata/let_invalid_unary.snow:1:9: invalid type: unresolved

A pkg/semantic/testdata/check/let_invalid_unary.snow.want => pkg/semantic/testdata/check/let_invalid_unary.snow.want +4 -0
@@ 0,0 1,4 @@
file testdata/let_invalid_unary.snow [1, 0, 0]
  let= x [let: unresolved]
    unary [!] [value: unresolved]
      string ["a"] [const: string]

A pkg/semantic/testdata/check/let_unary.snow.err => pkg/semantic/testdata/check/let_unary.snow.err +0 -0
A pkg/semantic/testdata/check/let_unary.snow.want => pkg/semantic/testdata/check/let_unary.snow.want +4 -0
@@ 0,0 1,4 @@
file testdata/let_unary.snow [1, 0, 0]
  let= x [let: int]
    unary [-] [value: int]
      int [1] [const: int]

A pkg/semantic/testdata/check/paren_type.snow.err => pkg/semantic/testdata/check/paren_type.snow.err +0 -0
A pkg/semantic/testdata/check/paren_type.snow.want => pkg/semantic/testdata/check/paren_type.snow.want +5 -0
@@ 0,0 1,5 @@
file testdata/paren_type.snow [1, 0, 0]
  var:= x [var: int]
    paren [type: int]
      ident int [type: int]
    int [1] [const: int]

A pkg/semantic/testdata/check/top_level_fn_init_order.snow.err => pkg/semantic/testdata/check/top_level_fn_init_order.snow.err +0 -0
A pkg/semantic/testdata/check/top_level_fn_init_order.snow.want => pkg/semantic/testdata/check/top_level_fn_init_order.snow.want +11 -0
@@ 0,0 1,11 @@
file testdata/top_level_fn_init_order.snow [0, 2, 0]
  fn A [let: () -> void]
    block [1]
      expr
        call [0] [value: void]
          ident B [let: () -> void]
  fn B [let: () -> void]
    block [1]
      expr
        call [0] [value: void]
          ident A [let: () -> void]

A pkg/semantic/testdata/check/top_level_init_order.snow.err => pkg/semantic/testdata/check/top_level_init_order.snow.err +0 -0
A pkg/semantic/testdata/check/top_level_init_order.snow.want => pkg/semantic/testdata/check/top_level_init_order.snow.want +5 -0
@@ 0,0 1,5 @@
file testdata/top_level_init_order.snow [2, 0, 0]
  var= A [var: int]
    ident B [let: int]
  let= B [let: int]
    int [1] [const: int]

A pkg/semantic/testdata/check/var.snow.err => pkg/semantic/testdata/check/var.snow.err +0 -0
A pkg/semantic/testdata/check/var.snow.want => pkg/semantic/testdata/check/var.snow.want +3 -0
@@ 0,0 1,3 @@
file testdata/var.snow [1, 0, 0]
  var: x [var: int]
    ident int [type: int]

A pkg/semantic/testdata/check/var_auto_ref.snow.err => pkg/semantic/testdata/check/var_auto_ref.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/var_auto_ref.snow:1:9: invalid type for identifier x: unresolved

A pkg/semantic/testdata/check/var_auto_ref.snow.want => pkg/semantic/testdata/check/var_auto_ref.snow.want +3 -0
@@ 0,0 1,3 @@
file testdata/var_auto_ref.snow [1, 0, 0]
  var= x [var: unresolved]
    ident x [var: unresolved]

A pkg/semantic/testdata/check/var_bool.snow.err => pkg/semantic/testdata/check/var_bool.snow.err +0 -0
A pkg/semantic/testdata/check/var_bool.snow.want => pkg/semantic/testdata/check/var_bool.snow.want +5 -0
@@ 0,0 1,5 @@
file testdata/var_bool.snow [2, 0, 0]
  var= t [var: bool]
    ident true [let: bool]
  var= f [var: bool]
    ident false [let: bool]

A pkg/semantic/testdata/check/var_duplicate_symbol.snow.err => pkg/semantic/testdata/check/var_duplicate_symbol.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/var_duplicate_symbol.snow:2:5: var x: symbol already declared in this scope

A pkg/semantic/testdata/check/var_duplicate_symbol.snow.want => pkg/semantic/testdata/check/var_duplicate_symbol.snow.want +5 -0
@@ 0,0 1,5 @@
file testdata/var_duplicate_symbol.snow [2, 0, 0]
  var: x [var: int]
    ident int [type: int]
  var: x [var: string]
    ident string [type: string]

A pkg/semantic/testdata/check/var_tuple_type.snow.err => pkg/semantic/testdata/check/var_tuple_type.snow.err +0 -0
A pkg/semantic/testdata/check/var_tuple_type.snow.want => pkg/semantic/testdata/check/var_tuple_type.snow.want +6 -0
@@ 0,0 1,6 @@
file testdata/var_tuple_type.snow [1, 0, 0]
  var: x [var: (int, string, bool)]
    tuple type [3] [type: (int, string, bool)]
      ident int [type: int]
      ident string [type: string]
      ident bool [type: bool]

M pkg/semantic/typeassign_pass_test.go => pkg/semantic/typeassign_pass_test.go +1 -1
@@ 40,7 40,7 @@ func TestTypes(t *testing.T) {
			// sanity check invariants:
			// - all expressions have a type
			// - all declarations have a type
			// - all valid identifiers have a Ref
			// - all valid (non-tuple) identifiers have a Ref
			var check visitorFunc
			check = func(n semantic.Node) semantic.Visitor {
				if n == nil {

M pkg/semantic/typecheck_pass.go => pkg/semantic/typecheck_pass.go +24 -8
@@ 64,7 64,14 @@ func (t *typecheckVisitor) expectTypeCtx(typed Typed, target interface{}, ctxs .
	}

	if !typ.Valid() {
		t.errh(typed.Pos(), fmt.Sprintf("invalid type: %s", typ))
		switch n := typed.(type) {
		case *Ident:
			t.errh(typed.Pos(), fmt.Sprintf("invalid type for identifier %s: %s", n.Name, typ))
		case Decl:
			t.errh(typed.Pos(), fmt.Sprintf("invalid type for declaration %s: %s", n.Ident(), typ))
		default:
			t.errh(typed.Pos(), fmt.Sprintf("invalid type: %s", typ))
		}
		return false
	}



@@ 244,27 251,31 @@ func (t *typecheckVisitor) Visit(n Node) Visitor {
		// ************** EXPRESSIONS *****************

	case *FnTypeExpr:
		var T Type
		for _, p := range n.Params {
			Walk(t, p)
			t.expectTypeCtx(p, &T, Typ)
		}
		if n.Return != nil {
			Walk(t, n.Return)
			t.expectTypeCtx(n.Return, &T, Typ)
		}
		var T Type
		t.expectTypeCtx(n, &T, Typ)

	case *TupleTypeExpr:
		var T Type
		for _, f := range n.Fields {
			Walk(t, f)
			t.expectTypeCtx(f, &T, Typ)
		}
		var T Type
		t.expectTypeCtx(n, &T, Typ)

	case *TupleVal:
		var T Type
		for _, v := range n.Values {
			Walk(t, v)
			t.expectTypeCtx(n, &T, TypeContextValues...)
		}
		var T Type
		t.expectTypeCtx(n, &T, Value)

	case *Binary:


@@ 404,6 415,12 @@ func (t *typecheckVisitor) typecheckFnAttrs(fn *Fn) {

	attrs := make(map[string]bool, len(fn.Attrs))
	for _, attr := range fn.Attrs {
		if attr.InitOf == nil {
			// invalid attribute (symbol not found), will have already raised an error,
			// just skip it.
			continue
		}

		nm := attr.InitOf.Ident()
		if attrs[nm] {
			t.errh(attr.Pos(), fmt.Sprintf("duplicate attribute @%s applied to function %s", nm, fn.Ident()))


@@ 428,11 445,10 @@ func (t *typecheckVisitor) typecheckFnAttrs(fn *Fn) {
		if fn.IsRef && fn.MethodOf != nil {
			t.errh(fn.Pos(), fmt.Sprintf("@%s function %s cannot have a ref modifier", ExternAttrName, fn.Ident()))
		}
		vals := extern.Values()
		if len(vals) > 0 {
			pkg := vals["pkg"].(string)
		if vals := extern.Values(); len(vals) > 0 {
			pkg, _ := vals["pkg"].(string)
			if pkg == "" {
				imp := vals["import"].(string)
				imp, _ := vals["import"].(string)
				pkg = filepath.Base(imp)
			}
			if decl := fn.Scope().LookupChain(pkg, fn.Pos()); decl != nil {

M pkg/semantic/typecheck_pass_test.go => pkg/semantic/typecheck_pass_test.go +40 -0
@@ 1,1 1,41 @@
package semantic_test

import (
	"bytes"
	"flag"
	"path/filepath"
	"testing"

	"git.sr.ht/~mna/snow/pkg/internal/filetest"
	"git.sr.ht/~mna/snow/pkg/printer"
	"git.sr.ht/~mna/snow/pkg/scanner"
	"git.sr.ht/~mna/snow/pkg/semantic"
)

var testUpdateCheckTests = flag.Bool("test.update-check-tests", false, "If set, replace expected semantic check test results with actual results.")

func TestCheck(t *testing.T) {
	baseDir := "testdata"
	expectDir := filepath.Join(baseDir, "check")

	for _, fi := range filetest.SourceFiles(t, baseDir) {
		t.Run(fi.Name(), func(t *testing.T) {
			unit, err := semantic.Run(semantic.TypeCheckPass, filepath.Join(baseDir, fi.Name()))
			if unit == nil && err != nil {
				t.Fatal(err)
			}

			var ebuf bytes.Buffer
			scanner.PrintError(&ebuf, err)

			var buf bytes.Buffer
			pp := printer.Printer{W: &buf, Pos: printer.PosNone}
			for _, f := range unit.Files {
				_ = pp.PrintSemantic(f, unit.FileSet.File(f.Pos()))
			}

			filetest.DiffOutput(t, fi, buf.String(), expectDir, testUpdateCheckTests)
			filetest.DiffErrors(t, fi, ebuf.String(), expectDir, testUpdateCheckTests)
		})
	}
}