~mna/snow

b30d2cc5f982ec6a470ce9984e37ce9c4251e9f7 — Martin Angers 1 year, 10 months ago 134eb76
pkg/semantic: finish type-assign pass, update tests
187 files changed, 2007 insertions(+), 63 deletions(-)

M cmd/snowc/main.go
M pkg/parser/parser_test.go
M pkg/printer/printer.go
M pkg/printer/printer_test.go
M pkg/semantic/runner.go
M pkg/semantic/scope.go
R pkg/semantic/testdata/{struct_var_expr_call_method.snow => struct_var_expr_call_method.snow.notyet}
A pkg/semantic/testdata/types/cycle.snow.err
A pkg/semantic/testdata/types/cycle.snow.want
A pkg/semantic/testdata/types/empty.snow.err
A pkg/semantic/testdata/types/empty.snow.want
A pkg/semantic/testdata/types/fn.snow.err
A pkg/semantic/testdata/types/fn.snow.want
A pkg/semantic/testdata/types/fn_access_invalid_struct_field.snow.err
A pkg/semantic/testdata/types/fn_access_invalid_struct_field.snow.want
A pkg/semantic/testdata/types/fn_access_struct_type_field.snow.err
A pkg/semantic/testdata/types/fn_access_struct_type_field.snow.want
A pkg/semantic/testdata/types/fn_access_var_outside_struct.snow.err
A pkg/semantic/testdata/types/fn_access_var_outside_struct.snow.want
A pkg/semantic/testdata/types/fn_assign_invalid.snow.err
A pkg/semantic/testdata/types/fn_assign_invalid.snow.want
A pkg/semantic/testdata/types/fn_assign_let.snow.err
A pkg/semantic/testdata/types/fn_assign_let.snow.want
A pkg/semantic/testdata/types/fn_assign_struct_fields.snow.err
A pkg/semantic/testdata/types/fn_assign_struct_fields.snow.want
A pkg/semantic/testdata/types/fn_assign_struct_method_to_var.snow.err
A pkg/semantic/testdata/types/fn_assign_struct_method_to_var.snow.want
A pkg/semantic/testdata/types/fn_assign_type.snow.err
A pkg/semantic/testdata/types/fn_assign_type.snow.want
A pkg/semantic/testdata/types/fn_assign_unifying_type.snow.err
A pkg/semantic/testdata/types/fn_assign_unifying_type.snow.want
A pkg/semantic/testdata/types/fn_call_fn_value_with_labels.snow.err
A pkg/semantic/testdata/types/fn_call_fn_value_with_labels.snow.want
A pkg/semantic/testdata/types/fn_call_struct_init.snow.err
A pkg/semantic/testdata/types/fn_call_struct_init.snow.want
A pkg/semantic/testdata/types/fn_call_struct_init_no_label.snow.err
A pkg/semantic/testdata/types/fn_call_struct_init_no_label.snow.want
A pkg/semantic/testdata/types/fn_call_struct_method.snow.err
A pkg/semantic/testdata/types/fn_call_struct_method.snow.want
A pkg/semantic/testdata/types/fn_call_unifying_type.snow.err
A pkg/semantic/testdata/types/fn_call_unifying_type.snow.want
A pkg/semantic/testdata/types/fn_call_with_invalid_labels.snow.err
A pkg/semantic/testdata/types/fn_call_with_invalid_labels.snow.want
A pkg/semantic/testdata/types/fn_call_with_labels.snow.err
A pkg/semantic/testdata/types/fn_call_with_labels.snow.want
A pkg/semantic/testdata/types/fn_call_wrong_arity.snow.err
A pkg/semantic/testdata/types/fn_call_wrong_arity.snow.want
A pkg/semantic/testdata/types/fn_compare.snow.err
A pkg/semantic/testdata/types/fn_compare.snow.want
A pkg/semantic/testdata/types/fn_complex_selectors.snow.err
A pkg/semantic/testdata/types/fn_complex_selectors.snow.want
A pkg/semantic/testdata/types/fn_extern_pkg_before_conflict_name.snow.err
A pkg/semantic/testdata/types/fn_extern_pkg_before_conflict_name.snow.want
A pkg/semantic/testdata/types/fn_extern_pkg_conflict_name.snow.err
A pkg/semantic/testdata/types/fn_extern_pkg_conflict_name.snow.want
A pkg/semantic/testdata/types/fn_extern_ref_method.snow.err
A pkg/semantic/testdata/types/fn_extern_ref_method.snow.want
A pkg/semantic/testdata/types/fn_extern_with_body.snow.err
A pkg/semantic/testdata/types/fn_extern_with_body.snow.want
A pkg/semantic/testdata/types/fn_fn_arg.snow.err
A pkg/semantic/testdata/types/fn_fn_arg.snow.want
A pkg/semantic/testdata/types/fn_guard_fallthrough.snow.err
A pkg/semantic/testdata/types/fn_guard_fallthrough.snow.want
A pkg/semantic/testdata/types/fn_ident_as_type.snow.err
A pkg/semantic/testdata/types/fn_ident_as_type.snow.want
A pkg/semantic/testdata/types/fn_init_order.snow.err
A pkg/semantic/testdata/types/fn_init_order.snow.want
A pkg/semantic/testdata/types/fn_invalid_attr.snow.err
A pkg/semantic/testdata/types/fn_invalid_attr.snow.want
A pkg/semantic/testdata/types/fn_invalid_main.snow.err
A pkg/semantic/testdata/types/fn_invalid_main.snow.want
A pkg/semantic/testdata/types/fn_invalid_ref.snow.err
A pkg/semantic/testdata/types/fn_invalid_ref.snow.want
A pkg/semantic/testdata/types/fn_invalid_ref_call.snow.err
A pkg/semantic/testdata/types/fn_invalid_ref_call.snow.want
A pkg/semantic/testdata/types/fn_invalid_ref_call_via_value.snow.err
A pkg/semantic/testdata/types/fn_invalid_ref_call_via_value.snow.want
A pkg/semantic/testdata/types/fn_invalid_return.snow.err
A pkg/semantic/testdata/types/fn_invalid_return.snow.want
A pkg/semantic/testdata/types/fn_invalid_tuple_access.snow.err
A pkg/semantic/testdata/types/fn_invalid_tuple_access.snow.want
A pkg/semantic/testdata/types/fn_main_extern.snow.err
A pkg/semantic/testdata/types/fn_main_extern.snow.want
A pkg/semantic/testdata/types/fn_many_extern.snow.err
A pkg/semantic/testdata/types/fn_many_extern.snow.want
A pkg/semantic/testdata/types/fn_method_explicit_self.snow.err
A pkg/semantic/testdata/types/fn_method_explicit_self.snow.want
A pkg/semantic/testdata/types/fn_nested_block.snow.err
A pkg/semantic/testdata/types/fn_nested_block.snow.want
A pkg/semantic/testdata/types/fn_nested_fn.snow.err
A pkg/semantic/testdata/types/fn_nested_fn.snow.want
A pkg/semantic/testdata/types/fn_nested_fn_init_order.snow.err
A pkg/semantic/testdata/types/fn_nested_fn_init_order.snow.want
A pkg/semantic/testdata/types/fn_nested_struct_method.snow.err
A pkg/semantic/testdata/types/fn_nested_struct_method.snow.want
A pkg/semantic/testdata/types/fn_nested_struct_self.snow.err
A pkg/semantic/testdata/types/fn_nested_struct_self.snow.want
A pkg/semantic/testdata/types/fn_nested_structs.snow.err
A pkg/semantic/testdata/types/fn_nested_structs.snow.want
A pkg/semantic/testdata/types/fn_nested_tuple_type.snow.err
A pkg/semantic/testdata/types/fn_nested_tuple_type.snow.want
A pkg/semantic/testdata/types/fn_non_type_selectors.snow.err
A pkg/semantic/testdata/types/fn_non_type_selectors.snow.want
A pkg/semantic/testdata/types/fn_param_type_is_var_in_body.snow.err
A pkg/semantic/testdata/types/fn_param_type_is_var_in_body.snow.want
A pkg/semantic/testdata/types/fn_params.snow.err
A pkg/semantic/testdata/types/fn_params.snow.want
A pkg/semantic/testdata/types/fn_params_locals.snow.err
A pkg/semantic/testdata/types/fn_params_locals.snow.want
A pkg/semantic/testdata/types/fn_recursion.snow.err
A pkg/semantic/testdata/types/fn_recursion.snow.want
A pkg/semantic/testdata/types/fn_return_internal_struct.snow.err
A pkg/semantic/testdata/types/fn_return_internal_struct.snow.want
A pkg/semantic/testdata/types/fn_return_missing_value.snow.err
A pkg/semantic/testdata/types/fn_return_missing_value.snow.want
A pkg/semantic/testdata/types/fn_return_struct.snow.err
A pkg/semantic/testdata/types/fn_return_struct.snow.want
A pkg/semantic/testdata/types/fn_return_unifying_type.snow.err
A pkg/semantic/testdata/types/fn_return_unifying_type.snow.want
A pkg/semantic/testdata/types/fn_struct_main_method.snow.err
A pkg/semantic/testdata/types/fn_struct_main_method.snow.want
A pkg/semantic/testdata/types/fn_struct_method_access_top_level.snow.err
A pkg/semantic/testdata/types/fn_struct_method_access_top_level.snow.want
A pkg/semantic/testdata/types/fn_struct_order_independent.snow.err
A pkg/semantic/testdata/types/fn_struct_order_independent.snow.want
A pkg/semantic/testdata/types/fn_struct_same_name_diff_scope.snow.err
A pkg/semantic/testdata/types/fn_struct_same_name_diff_scope.snow.want
A pkg/semantic/testdata/types/fn_struct_selector.snow.err
A pkg/semantic/testdata/types/fn_struct_selector.snow.want
A pkg/semantic/testdata/types/fn_struct_self_shadow.snow.err
A pkg/semantic/testdata/types/fn_struct_self_shadow.snow.want
A pkg/semantic/testdata/types/fn_struct_self_uses.snow.err
A pkg/semantic/testdata/types/fn_struct_self_uses.snow.want
A pkg/semantic/testdata/types/fn_tuple_assign_compatible_types.snow.err
A pkg/semantic/testdata/types/fn_tuple_assign_compatible_types.snow.want
A pkg/semantic/testdata/types/fn_tuple_assign_incompatible_types.snow.err
A pkg/semantic/testdata/types/fn_tuple_assign_incompatible_types.snow.want
A pkg/semantic/testdata/types/fn_tuple_expr_select_field.snow.err
A pkg/semantic/testdata/types/fn_tuple_expr_select_field.snow.want
A pkg/semantic/testdata/types/fn_type_as_value.snow.err
A pkg/semantic/testdata/types/fn_type_as_value.snow.want
A pkg/semantic/testdata/types/fn_unknown_symbol.snow.err
A pkg/semantic/testdata/types/fn_unknown_symbol.snow.want
A pkg/semantic/testdata/types/fn_var_as_param_type.snow.err
A pkg/semantic/testdata/types/fn_var_as_param_type.snow.want
A pkg/semantic/testdata/types/fn_without_body.snow.err
A pkg/semantic/testdata/types/fn_without_body.snow.want
A pkg/semantic/testdata/types/fns.snow.err
A pkg/semantic/testdata/types/fns.snow.want
A pkg/semantic/testdata/types/guard_else.snow.err
A pkg/semantic/testdata/types/guard_else.snow.want
A pkg/semantic/testdata/types/if_else_if.snow.err
A pkg/semantic/testdata/types/if_else_if.snow.want
A pkg/semantic/testdata/types/if_non_bool.snow.err
A pkg/semantic/testdata/types/if_non_bool.snow.want
A pkg/semantic/testdata/types/invalid_binary_op.snow.err
A pkg/semantic/testdata/types/invalid_binary_op.snow.want
A pkg/semantic/testdata/types/let.snow.err
A pkg/semantic/testdata/types/let.snow.want
A pkg/semantic/testdata/types/let_invalid_tuple_type.snow.err
A pkg/semantic/testdata/types/let_invalid_tuple_type.snow.want
A pkg/semantic/testdata/types/let_invalid_unary.snow.err
A pkg/semantic/testdata/types/let_invalid_unary.snow.want
A pkg/semantic/testdata/types/let_unary.snow.err
A pkg/semantic/testdata/types/let_unary.snow.want
A pkg/semantic/testdata/types/paren_type.snow.err
A pkg/semantic/testdata/types/paren_type.snow.want
A pkg/semantic/testdata/types/top_level_fn_init_order.snow.err
A pkg/semantic/testdata/types/top_level_fn_init_order.snow.want
A pkg/semantic/testdata/types/top_level_init_order.snow.err
A pkg/semantic/testdata/types/top_level_init_order.snow.want
A pkg/semantic/testdata/types/var.snow.err
A pkg/semantic/testdata/types/var.snow.want
A pkg/semantic/testdata/types/var_auto_ref.snow.err
A pkg/semantic/testdata/types/var_auto_ref.snow.want
A pkg/semantic/testdata/types/var_bool.snow.err
A pkg/semantic/testdata/types/var_bool.snow.want
A pkg/semantic/testdata/types/var_duplicate_symbol.snow.err
A pkg/semantic/testdata/types/var_duplicate_symbol.snow.want
A pkg/semantic/testdata/types/var_tuple_type.snow.err
A pkg/semantic/testdata/types/var_tuple_type.snow.want
M pkg/semantic/translate_pass.go
M pkg/semantic/translate_pass_test.go
M pkg/semantic/typeassign_pass.go
A pkg/semantic/typeassign_pass_test.go
M pkg/typecheck/check_pass_test.go
M pkg/typecheck/type_pass_test.go
M cmd/snowc/main.go => cmd/snowc/main.go +2 -2
@@ 177,7 177,7 @@ func (c *cmd) Parse(stdio *mainer.Stdio, args []string) error {
		WithComments: true,
	}
	for _, file := range files {
		p.Print(file, fs.File(file.Pos()))
		_ = p.PrintAST(file, fs.File(file.Pos()))
	}

	var el scanner.ErrorList


@@ 198,7 198,7 @@ func (c *cmd) Typecheck(stdio *mainer.Stdio, args []string) error {
		WithTypes: unit.Types,
	}
	for _, file := range unit.Files {
		p.Print(file, unit.FileSet.File(file.Pos()))
		_ = p.PrintAST(file, unit.FileSet.File(file.Pos()))
	}

	var el scanner.ErrorList

M pkg/parser/parser_test.go => pkg/parser/parser_test.go +1 -1
@@ 28,7 28,7 @@ func TestParser(t *testing.T) {

			var buf bytes.Buffer
			pp := printer.Printer{W: &buf, Pos: printer.PosOffsets, WithComments: true}
			if err := pp.Print(files[0], fset.File(files[0].Pos())); err != nil {
			if err := pp.PrintAST(files[0], fset.File(files[0].Pos())); err != nil {
				t.Fatal(err)
			}


M pkg/printer/printer.go => pkg/printer/printer.go +126 -45
@@ 7,6 7,7 @@ import (
	"strings"

	"git.sr.ht/~mna/snow/pkg/ast"
	"git.sr.ht/~mna/snow/pkg/semantic"
	"git.sr.ht/~mna/snow/pkg/token"
	"git.sr.ht/~mna/snow/pkg/typecheck"
)


@@ 72,8 73,8 @@ type Printer struct {
	err    error
}

// Print pretty-prints the AST node n from the specified file.
func (p *Printer) Print(n ast.Node, file *token.File) error {
// PrintAST pretty-prints the AST node n from the specified file.
func (p *Printer) PrintAST(n ast.Node, file *token.File) error {
	if file == nil {
		return nil
	}


@@ 82,7 83,21 @@ func (p *Printer) Print(n ast.Node, file *token.File) error {
	p.maxPos = token.Pos(p.file.Base() + p.file.Size())
	p.depth = 0
	p.err = nil
	ast.Walk(p, n)
	ast.Walk(&astPrinter{p}, n)
	return p.err
}

// PrintSemantic pretty-prints the semantic node n from the specified file.
func (p *Printer) PrintSemantic(n semantic.Node, file *token.File) error {
	if file == nil {
		return nil
	}

	p.file = file
	p.maxPos = token.Pos(p.file.Base() + p.file.Size())
	p.depth = 0
	p.err = nil
	semantic.Walk(&semanticPrinter{p}, n)
	return p.err
}



@@ 104,7 119,18 @@ func (p *Printer) clamp(pos token.Pos) token.Pos {
	return pos
}

func (p *Printer) printPosln(n ast.Node) {
type posNode interface {
	Pos() token.Pos
	End() token.Pos
}

type ender struct {
	semantic.Node
}

func (e ender) End() token.Pos { return e.Pos() }

func (p *Printer) printPosln(n posNode) {
	if p.err != nil {
		return
	}


@@ 114,7 140,102 @@ func (p *Printer) printPosln(n ast.Node) {
	)
}

func (p *Printer) Visit(n ast.Node) ast.Visitor {
type semanticPrinter struct {
	*Printer
}

type typedExpr interface {
	Type() semantic.Type
	TypeContext() semantic.TypeContext
}

func (p *semanticPrinter) Visit(n semantic.Node) semantic.Visitor {
	if n == nil || p.err != nil {
		p.depth--
		return nil
	}
	p.depth++

	switch n := n.(type) {
	case *semantic.File:
		p.printMsg(fmt.Sprintf("file %s [%d, %d, %d]", p.file.Name(), len(n.Vars), len(n.Fns), len(n.Structs)), true)
	case *semantic.Fn:
		if n.IsRef {
			p.printMsg(fmt.Sprintf("ref fn %s", n.Ident()), true)
		} else {
			p.printMsg(fmt.Sprintf("fn %s", n.Ident()), true)
		}
	case *semantic.Var:
		lbl := n.Ctx.String()
		if n.TypeExpr != nil {
			lbl += ":"
		}
		if n.Value != nil {
			lbl += "="
		}
		p.printMsg(fmt.Sprintf("%s %s", lbl, n.Ident()), true)
	case *semantic.Struct:
		p.printMsg(fmt.Sprintf("struct %s [%d, %d, %d]", n.Ident(), len(n.Vars), len(n.Fns), len(n.Structs)), true)
	case *semantic.Block:
		p.printMsg(fmt.Sprintf("block [%d]", len(n.Stmts)), true)
	case *semantic.Return:
		p.printMsg("return", true)
	case *semantic.Assign:
		p.printMsg("assign", true)
	case *semantic.ExprStmt:
		p.printMsg("expr", true)
	case *semantic.If:
		p.printMsg(fmt.Sprintf("if [%d]", len(n.Conds)), true)
	case *semantic.Guard:
		p.printMsg(fmt.Sprintf("guard [%d]", len(n.Conds)), true)
	case *semantic.FnTypeExpr:
		ret := 0
		if n.Return != nil {
			ret = 1
		}
		p.printMsg(fmt.Sprintf("sig [%d->%d]", len(n.Params), ret), true)
	case *semantic.TupleTypeExpr:
		p.printMsg(fmt.Sprintf("tuple type [%d]", len(n.Fields)), true)
	case *semantic.TupleVal:
		p.printMsg(fmt.Sprintf("tuple value [%d]", len(n.Values)), true)
	case *semantic.Binary:
		p.printMsg(fmt.Sprintf("binary [%s]", n.Op), true)
	case *semantic.Unary:
		p.printMsg(fmt.Sprintf("unary [%s]", n.Op), true)
	case *semantic.Paren:
		p.printMsg("paren", true)
	case *semantic.Call:
		p.printMsg(fmt.Sprintf("call [%d]", len(n.Args)), true)
	case *semantic.Selector:
		p.printMsg("select", true)
	case *semantic.LitString:
		p.printMsg(fmt.Sprintf("string [%s]", n.Repr), true)
	case *semantic.LitInt:
		p.printMsg(fmt.Sprintf("int [%s]", n.Repr), true)
	case *semantic.Ident:
		p.printMsg(fmt.Sprintf("ident %s", n.Name), true)
	case *semantic.ImplicitConv:
		p.printMsg("implicit conv", true)
	}

	if te, ok := n.(typedExpr); ok {
		p.printMsg(fmt.Sprintf(" [%s: %s]", te.TypeContext(), te.Type()), false)
	}

	if p.Pos != PosNone {
		p.printPosln(ender{n})
	} else {
		p.printMsg("\n", false)
	}

	return p
}

type astPrinter struct {
	*Printer
}

func (p *astPrinter) Visit(n ast.Node) ast.Visitor {
	if n == nil || p.err != nil {
		p.depth--
		return nil


@@ 228,43 349,3 @@ func (p *Printer) Visit(n ast.Node) ast.Visitor {

	return p
}

// TODO: maybe simplify AST printing with this...
/*
type compactPrint struct {
	buf bytes.Buffer
}

func (c *compactPrint) String() string {
	return c.buf.String()
}

func (c *compactPrint) printf(s string, vs ...interface{}) {
	fmt.Fprintf(&c.buf, s, vs...)
}

func (c *compactPrint) Visit(n ast.Node) ast.Visitor {
	// only used to print types on the same line
	switch n := n.(type) {
	case *ast.FnType:
		c.printf("(")
		for i, param := range n.Params {
			if i > 0 {
				c.printf(", ")
			}
			ast.Walk(c, param.Type)
		}
		c.printf(") -> ")
		ast.Walk(c, n.RetType)

	case *ast.ParenExpr:
		c.printf("(")
		ast.Walk(c, n.Value)
		c.printf(")")

	case *ast.Ident:
		c.printf("%s", n.Name)
	}
	return nil
}
*/

M pkg/printer/printer_test.go => pkg/printer/printer_test.go +1 -1
@@ 220,7 220,7 @@ file [2, #1] [test:1:1::1:70]
				WithComments: c.withComments,
				Pos:          c.posMode,
			}
			if err := p.Print(f, fsf); err != nil {
			if err := p.PrintAST(f, fsf); err != nil {
				t.Fatal(err)
			}


M pkg/semantic/runner.go => pkg/semantic/runner.go +17 -4
@@ 7,10 7,15 @@ import (
	"git.sr.ht/~mna/snow/pkg/token"
)

const (
	TranslatePass = iota
	TypeAssignPass
)

// Run parses and typechecks code for the provided source files. It returns the
// typechecked *Unit and an error.  The error, if non-nil, is guaranteed to be
// a scanner.ErrorList.
func Run(files ...string) (*Unit, error) {
func Run(maxPass int, files ...string) (*Unit, error) {
	if len(files) == 0 {
		return nil, nil
	}


@@ 25,9 30,17 @@ func Run(files ...string) (*Unit, error) {
		errs.Add(fset.Position(pos), msg)
	}

	// step 1: translate to semantic tree and generate scopes
	unit := translate(fs, errh)
	unit.FileSet = fset
	var unit *Unit
	if maxPass >= TranslatePass {
		// step 1: translate to semantic tree and generate scopes
		unit = translate(fs, errh)
		unit.FileSet = fset
	}

	if maxPass >= TypeAssignPass {
		// step 2: assign types to expressions and declarations
		typeassign(unit, errh)
	}

	return unit, removeDuplicateErrs(errs).Err()
}

M pkg/semantic/scope.go => pkg/semantic/scope.go +10 -2
@@ 41,6 41,7 @@ func NewUniverse(owner *Unit) *Scope {
	s.Parent = s
	defer func() { s.Parent = nil }()

	s.OrderIndependent = true
	for id, decl := range universeIdents {
		s.Register(id, decl)
	}


@@ 49,7 50,12 @@ func NewUniverse(owner *Unit) *Scope {

// New creates a new child scope for s, opened by node.
func (s *Scope) New(owner Node) *Scope {
	return newScope(owner, s)
	child := newScope(owner, s)
	switch owner.(type) {
	case *File, *Struct:
		child.OrderIndependent = true
	}
	return child
}

func newScope(owner Node, parent *Scope) *Scope {


@@ 162,7 168,8 @@ var universeIdents = func() map[string]Decl {
	m := make(map[string]Decl)

	for b := kindStart + 1; b < kindEnd; b++ {
		v := &Var{Ctx: Typ} // TODO: does that make sense, a Var that is a Type? That would be cool for predefined types.
		v := &Var{Ctx: Typ}
		v.typ = &BasicType{Kind: b}
		v.ident = b.String()
		m[v.Ident()] = v
	}


@@ 170,6 177,7 @@ var universeIdents = func() map[string]Decl {
	// add true and false constants
	for _, id := range []string{"true", "false"} {
		v := &Var{Ctx: Immutable}
		v.typ = &BasicType{Kind: Bool}
		v.ident = id
		m[v.Ident()] = v
	}

R pkg/semantic/testdata/struct_var_expr_call_method.snow => pkg/semantic/testdata/struct_var_expr_call_method.snow.notyet +0 -0
A pkg/semantic/testdata/types/cycle.snow.err => pkg/semantic/testdata/types/cycle.snow.err +0 -0
A pkg/semantic/testdata/types/cycle.snow.want => pkg/semantic/testdata/types/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/types/empty.snow.err => pkg/semantic/testdata/types/empty.snow.err +0 -0
A pkg/semantic/testdata/types/empty.snow.want => pkg/semantic/testdata/types/empty.snow.want +0 -0
A pkg/semantic/testdata/types/fn.snow.err => pkg/semantic/testdata/types/fn.snow.err +0 -0
A pkg/semantic/testdata/types/fn.snow.want => pkg/semantic/testdata/types/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/types/fn_access_invalid_struct_field.snow.err => pkg/semantic/testdata/types/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/types/fn_access_invalid_struct_field.snow.want => pkg/semantic/testdata/types/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/types/fn_access_struct_type_field.snow.err => pkg/semantic/testdata/types/fn_access_struct_type_field.snow.err +0 -0
A pkg/semantic/testdata/types/fn_access_struct_type_field.snow.want => pkg/semantic/testdata/types/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/types/fn_access_var_outside_struct.snow.err => pkg/semantic/testdata/types/fn_access_var_outside_struct.snow.err +0 -0
A pkg/semantic/testdata/types/fn_access_var_outside_struct.snow.want => pkg/semantic/testdata/types/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/types/fn_assign_invalid.snow.err => pkg/semantic/testdata/types/fn_assign_invalid.snow.err +0 -0
A pkg/semantic/testdata/types/fn_assign_invalid.snow.want => pkg/semantic/testdata/types/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/types/fn_assign_let.snow.err => pkg/semantic/testdata/types/fn_assign_let.snow.err +0 -0
A pkg/semantic/testdata/types/fn_assign_let.snow.want => pkg/semantic/testdata/types/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/types/fn_assign_struct_fields.snow.err => pkg/semantic/testdata/types/fn_assign_struct_fields.snow.err +0 -0
A pkg/semantic/testdata/types/fn_assign_struct_fields.snow.want => pkg/semantic/testdata/types/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/types/fn_assign_struct_method_to_var.snow.err => pkg/semantic/testdata/types/fn_assign_struct_method_to_var.snow.err +0 -0
A pkg/semantic/testdata/types/fn_assign_struct_method_to_var.snow.want => pkg/semantic/testdata/types/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/types/fn_assign_type.snow.err => pkg/semantic/testdata/types/fn_assign_type.snow.err +0 -0
A pkg/semantic/testdata/types/fn_assign_type.snow.want => pkg/semantic/testdata/types/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/types/fn_assign_unifying_type.snow.err => pkg/semantic/testdata/types/fn_assign_unifying_type.snow.err +0 -0
A pkg/semantic/testdata/types/fn_assign_unifying_type.snow.want => pkg/semantic/testdata/types/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/types/fn_call_fn_value_with_labels.snow.err => pkg/semantic/testdata/types/fn_call_fn_value_with_labels.snow.err +0 -0
A pkg/semantic/testdata/types/fn_call_fn_value_with_labels.snow.want => pkg/semantic/testdata/types/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/types/fn_call_struct_init.snow.err => pkg/semantic/testdata/types/fn_call_struct_init.snow.err +0 -0
A pkg/semantic/testdata/types/fn_call_struct_init.snow.want => pkg/semantic/testdata/types/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/types/fn_call_struct_init_no_label.snow.err => pkg/semantic/testdata/types/fn_call_struct_init_no_label.snow.err +0 -0
A pkg/semantic/testdata/types/fn_call_struct_init_no_label.snow.want => pkg/semantic/testdata/types/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/types/fn_call_struct_method.snow.err => pkg/semantic/testdata/types/fn_call_struct_method.snow.err +0 -0
A pkg/semantic/testdata/types/fn_call_struct_method.snow.want => pkg/semantic/testdata/types/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/types/fn_call_unifying_type.snow.err => pkg/semantic/testdata/types/fn_call_unifying_type.snow.err +0 -0
A pkg/semantic/testdata/types/fn_call_unifying_type.snow.want => pkg/semantic/testdata/types/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/types/fn_call_with_invalid_labels.snow.err => pkg/semantic/testdata/types/fn_call_with_invalid_labels.snow.err +0 -0
A pkg/semantic/testdata/types/fn_call_with_invalid_labels.snow.want => pkg/semantic/testdata/types/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/types/fn_call_with_labels.snow.err => pkg/semantic/testdata/types/fn_call_with_labels.snow.err +0 -0
A pkg/semantic/testdata/types/fn_call_with_labels.snow.want => pkg/semantic/testdata/types/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/types/fn_call_wrong_arity.snow.err => pkg/semantic/testdata/types/fn_call_wrong_arity.snow.err +0 -0
A pkg/semantic/testdata/types/fn_call_wrong_arity.snow.want => pkg/semantic/testdata/types/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/types/fn_compare.snow.err => pkg/semantic/testdata/types/fn_compare.snow.err +0 -0
A pkg/semantic/testdata/types/fn_compare.snow.want => pkg/semantic/testdata/types/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/types/fn_complex_selectors.snow.err => pkg/semantic/testdata/types/fn_complex_selectors.snow.err +0 -0
A pkg/semantic/testdata/types/fn_complex_selectors.snow.want => pkg/semantic/testdata/types/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/types/fn_extern_pkg_before_conflict_name.snow.err => pkg/semantic/testdata/types/fn_extern_pkg_before_conflict_name.snow.err +0 -0
A pkg/semantic/testdata/types/fn_extern_pkg_before_conflict_name.snow.want => pkg/semantic/testdata/types/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/types/fn_extern_pkg_conflict_name.snow.err => pkg/semantic/testdata/types/fn_extern_pkg_conflict_name.snow.err +0 -0
A pkg/semantic/testdata/types/fn_extern_pkg_conflict_name.snow.want => pkg/semantic/testdata/types/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/types/fn_extern_ref_method.snow.err => pkg/semantic/testdata/types/fn_extern_ref_method.snow.err +0 -0
A pkg/semantic/testdata/types/fn_extern_ref_method.snow.want => pkg/semantic/testdata/types/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/types/fn_extern_with_body.snow.err => pkg/semantic/testdata/types/fn_extern_with_body.snow.err +0 -0
A pkg/semantic/testdata/types/fn_extern_with_body.snow.want => pkg/semantic/testdata/types/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/types/fn_fn_arg.snow.err => pkg/semantic/testdata/types/fn_fn_arg.snow.err +0 -0
A pkg/semantic/testdata/types/fn_fn_arg.snow.want => pkg/semantic/testdata/types/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/types/fn_guard_fallthrough.snow.err => pkg/semantic/testdata/types/fn_guard_fallthrough.snow.err +0 -0
A pkg/semantic/testdata/types/fn_guard_fallthrough.snow.want => pkg/semantic/testdata/types/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/types/fn_ident_as_type.snow.err => pkg/semantic/testdata/types/fn_ident_as_type.snow.err +0 -0
A pkg/semantic/testdata/types/fn_ident_as_type.snow.want => pkg/semantic/testdata/types/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/types/fn_init_order.snow.err => pkg/semantic/testdata/types/fn_init_order.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/fn_init_order.snow:2:11: undefined: B

A pkg/semantic/testdata/types/fn_init_order.snow.want => pkg/semantic/testdata/types/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/types/fn_invalid_attr.snow.err => pkg/semantic/testdata/types/fn_invalid_attr.snow.err +0 -0
A pkg/semantic/testdata/types/fn_invalid_attr.snow.want => pkg/semantic/testdata/types/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/types/fn_invalid_main.snow.err => pkg/semantic/testdata/types/fn_invalid_main.snow.err +0 -0
A pkg/semantic/testdata/types/fn_invalid_main.snow.want => pkg/semantic/testdata/types/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/types/fn_invalid_ref.snow.err => pkg/semantic/testdata/types/fn_invalid_ref.snow.err +0 -0
A pkg/semantic/testdata/types/fn_invalid_ref.snow.want => pkg/semantic/testdata/types/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/types/fn_invalid_ref_call.snow.err => pkg/semantic/testdata/types/fn_invalid_ref_call.snow.err +0 -0
A pkg/semantic/testdata/types/fn_invalid_ref_call.snow.want => pkg/semantic/testdata/types/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/types/fn_invalid_ref_call_via_value.snow.err => pkg/semantic/testdata/types/fn_invalid_ref_call_via_value.snow.err +0 -0
A pkg/semantic/testdata/types/fn_invalid_ref_call_via_value.snow.want => pkg/semantic/testdata/types/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/types/fn_invalid_return.snow.err => pkg/semantic/testdata/types/fn_invalid_return.snow.err +0 -0
A pkg/semantic/testdata/types/fn_invalid_return.snow.want => pkg/semantic/testdata/types/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/types/fn_invalid_tuple_access.snow.err => pkg/semantic/testdata/types/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/types/fn_invalid_tuple_access.snow.want => pkg/semantic/testdata/types/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/types/fn_main_extern.snow.err => pkg/semantic/testdata/types/fn_main_extern.snow.err +0 -0
A pkg/semantic/testdata/types/fn_main_extern.snow.want => pkg/semantic/testdata/types/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/types/fn_many_extern.snow.err => pkg/semantic/testdata/types/fn_many_extern.snow.err +0 -0
A pkg/semantic/testdata/types/fn_many_extern.snow.want => pkg/semantic/testdata/types/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/types/fn_method_explicit_self.snow.err => pkg/semantic/testdata/types/fn_method_explicit_self.snow.err +0 -0
A pkg/semantic/testdata/types/fn_method_explicit_self.snow.want => pkg/semantic/testdata/types/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/types/fn_nested_block.snow.err => pkg/semantic/testdata/types/fn_nested_block.snow.err +0 -0
A pkg/semantic/testdata/types/fn_nested_block.snow.want => pkg/semantic/testdata/types/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/types/fn_nested_fn.snow.err => pkg/semantic/testdata/types/fn_nested_fn.snow.err +0 -0
A pkg/semantic/testdata/types/fn_nested_fn.snow.want => pkg/semantic/testdata/types/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/types/fn_nested_fn_init_order.snow.err => pkg/semantic/testdata/types/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/types/fn_nested_fn_init_order.snow.want => pkg/semantic/testdata/types/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/types/fn_nested_struct_method.snow.err => pkg/semantic/testdata/types/fn_nested_struct_method.snow.err +0 -0
A pkg/semantic/testdata/types/fn_nested_struct_method.snow.want => pkg/semantic/testdata/types/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/types/fn_nested_struct_self.snow.err => pkg/semantic/testdata/types/fn_nested_struct_self.snow.err +0 -0
A pkg/semantic/testdata/types/fn_nested_struct_self.snow.want => pkg/semantic/testdata/types/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/types/fn_nested_structs.snow.err => pkg/semantic/testdata/types/fn_nested_structs.snow.err +0 -0
A pkg/semantic/testdata/types/fn_nested_structs.snow.want => pkg/semantic/testdata/types/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/types/fn_nested_tuple_type.snow.err => pkg/semantic/testdata/types/fn_nested_tuple_type.snow.err +0 -0
A pkg/semantic/testdata/types/fn_nested_tuple_type.snow.want => pkg/semantic/testdata/types/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/types/fn_non_type_selectors.snow.err => pkg/semantic/testdata/types/fn_non_type_selectors.snow.err +0 -0
A pkg/semantic/testdata/types/fn_non_type_selectors.snow.want => pkg/semantic/testdata/types/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/types/fn_param_type_is_var_in_body.snow.err => pkg/semantic/testdata/types/fn_param_type_is_var_in_body.snow.err +0 -0
A pkg/semantic/testdata/types/fn_param_type_is_var_in_body.snow.want => pkg/semantic/testdata/types/fn_param_type_is_var_in_body.snow.want +11 -0
@@ 0,0 1,11 @@
file [1, #0]
  fn
    ident [test] [let: (int) -> void]
    sig [1->0]
      param
        ident [x] [let: int]
        ident [int] [type: int]
    block [1]
      var=
        ident [int] [var: string]
        string ["abc"] [const: string]

A pkg/semantic/testdata/types/fn_params.snow.err => pkg/semantic/testdata/types/fn_params.snow.err +0 -0
A pkg/semantic/testdata/types/fn_params.snow.want => pkg/semantic/testdata/types/fn_params.snow.want +16 -0
@@ 0,0 1,16 @@
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 [1]
      return
        binary [+] [value: int]
          ident [x] [let: int]
          ident [y] [let: int]

A pkg/semantic/testdata/types/fn_params_locals.snow.err => pkg/semantic/testdata/types/fn_params_locals.snow.err +0 -0
A pkg/semantic/testdata/types/fn_params_locals.snow.want => pkg/semantic/testdata/types/fn_params_locals.snow.want +19 -0
@@ 0,0 1,19 @@
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]
      var=
        ident [z] [var: int]
        binary [+] [value: int]
          ident [x] [let: int]
          ident [y] [let: int]
      return
        ident [z] [var: int]

A pkg/semantic/testdata/types/fn_recursion.snow.err => pkg/semantic/testdata/types/fn_recursion.snow.err +0 -0
A pkg/semantic/testdata/types/fn_recursion.snow.want => pkg/semantic/testdata/types/fn_recursion.snow.want +24 -0
@@ 0,0 1,24 @@
file [1, #0]
  fn
    ident [test] [let: (int) -> int]
    sig [1->1]
      param
        ident [x] [let: int]
        ident [int] [type: int]
      ident [int] [type: int]
    block [2]
      if [1]
        item
          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]
          item
            binary [-] [value: int]
              ident [x] [let: int]
              int [1] [const: int]

A pkg/semantic/testdata/types/fn_return_internal_struct.snow.err => pkg/semantic/testdata/types/fn_return_internal_struct.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/fn_return_internal_struct.snow:1:14: undefined: S

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

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

A pkg/semantic/testdata/types/fn_return_struct.snow.err => pkg/semantic/testdata/types/fn_return_struct.snow.err +0 -0
A pkg/semantic/testdata/types/fn_return_struct.snow.want => pkg/semantic/testdata/types/fn_return_struct.snow.want +61 -0
@@ 0,0 1,61 @@
file [3, #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 [newS] [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 [test] [let: () -> void]
    sig [0->0]
    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]

A pkg/semantic/testdata/types/fn_return_unifying_type.snow.err => pkg/semantic/testdata/types/fn_return_unifying_type.snow.err +0 -0
A pkg/semantic/testdata/types/fn_return_unifying_type.snow.want => pkg/semantic/testdata/types/fn_return_unifying_type.snow.want +8 -0
@@ 0,0 1,8 @@
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
        ident x [var: i8]

A pkg/semantic/testdata/types/fn_struct_main_method.snow.err => pkg/semantic/testdata/types/fn_struct_main_method.snow.err +0 -0
A pkg/semantic/testdata/types/fn_struct_main_method.snow.want => pkg/semantic/testdata/types/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/types/fn_struct_method_access_top_level.snow.err => pkg/semantic/testdata/types/fn_struct_method_access_top_level.snow.err +0 -0
A pkg/semantic/testdata/types/fn_struct_method_access_top_level.snow.want => pkg/semantic/testdata/types/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/types/fn_struct_order_independent.snow.err => pkg/semantic/testdata/types/fn_struct_order_independent.snow.err +0 -0
A pkg/semantic/testdata/types/fn_struct_order_independent.snow.want => pkg/semantic/testdata/types/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/types/fn_struct_same_name_diff_scope.snow.err => pkg/semantic/testdata/types/fn_struct_same_name_diff_scope.snow.err +0 -0
A pkg/semantic/testdata/types/fn_struct_same_name_diff_scope.snow.want => pkg/semantic/testdata/types/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/types/fn_struct_selector.snow.err => pkg/semantic/testdata/types/fn_struct_selector.snow.err +0 -0
A pkg/semantic/testdata/types/fn_struct_selector.snow.want => pkg/semantic/testdata/types/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/types/fn_struct_self_shadow.snow.err => pkg/semantic/testdata/types/fn_struct_self_shadow.snow.err +0 -0
A pkg/semantic/testdata/types/fn_struct_self_shadow.snow.want => pkg/semantic/testdata/types/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/types/fn_struct_self_uses.snow.err => pkg/semantic/testdata/types/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/types/fn_struct_self_uses.snow.want => pkg/semantic/testdata/types/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/types/fn_tuple_assign_compatible_types.snow.err => pkg/semantic/testdata/types/fn_tuple_assign_compatible_types.snow.err +0 -0
A pkg/semantic/testdata/types/fn_tuple_assign_compatible_types.snow.want => pkg/semantic/testdata/types/fn_tuple_assign_compatible_types.snow.want +18 -0
@@ 0,0 1,18 @@
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)]
        tuple value [3] [value: (i16, u8, bool)]
          ident i [var: i16]
          ident u [var: u8]
          ident true [let: bool]

A pkg/semantic/testdata/types/fn_tuple_assign_incompatible_types.snow.err => pkg/semantic/testdata/types/fn_tuple_assign_incompatible_types.snow.err +0 -0
A pkg/semantic/testdata/types/fn_tuple_assign_incompatible_types.snow.want => pkg/semantic/testdata/types/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/types/fn_tuple_expr_select_field.snow.err => pkg/semantic/testdata/types/fn_tuple_expr_select_field.snow.err +0 -0
A pkg/semantic/testdata/types/fn_tuple_expr_select_field.snow.want => pkg/semantic/testdata/types/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/types/fn_type_as_value.snow.err => pkg/semantic/testdata/types/fn_type_as_value.snow.err +0 -0
A pkg/semantic/testdata/types/fn_type_as_value.snow.want => pkg/semantic/testdata/types/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/types/fn_unknown_symbol.snow.err => pkg/semantic/testdata/types/fn_unknown_symbol.snow.err +3 -0
@@ 0,0 1,3 @@
testdata/fn_unknown_symbol.snow:2:3: undefined: add
testdata/fn_unknown_symbol.snow:2:7: undefined: x
testdata/fn_unknown_symbol.snow:2:10: undefined: y

A pkg/semantic/testdata/types/fn_unknown_symbol.snow.want => pkg/semantic/testdata/types/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/types/fn_var_as_param_type.snow.err => pkg/semantic/testdata/types/fn_var_as_param_type.snow.err +0 -0
A pkg/semantic/testdata/types/fn_var_as_param_type.snow.want => pkg/semantic/testdata/types/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/types/fn_without_body.snow.err => pkg/semantic/testdata/types/fn_without_body.snow.err +0 -0
A pkg/semantic/testdata/types/fn_without_body.snow.want => pkg/semantic/testdata/types/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/types/fns.snow.err => pkg/semantic/testdata/types/fns.snow.err +0 -0
A pkg/semantic/testdata/types/fns.snow.want => pkg/semantic/testdata/types/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]
    call [2] [invalid: %!s(<nil>)]
      ident extern [invalid: %!s(<nil>)]
      string ["fmt"] [invalid: %!s(<nil>)]
      string ["Println"] [invalid: %!s(<nil>)]
    let: x [let: int]
      ident int [type: int]

A pkg/semantic/testdata/types/guard_else.snow.err => pkg/semantic/testdata/types/guard_else.snow.err +0 -0
A pkg/semantic/testdata/types/guard_else.snow.want => pkg/semantic/testdata/types/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/types/if_else_if.snow.err => pkg/semantic/testdata/types/if_else_if.snow.err +0 -0
A pkg/semantic/testdata/types/if_else_if.snow.want => pkg/semantic/testdata/types/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/types/if_non_bool.snow.err => pkg/semantic/testdata/types/if_non_bool.snow.err +0 -0
A pkg/semantic/testdata/types/if_non_bool.snow.want => pkg/semantic/testdata/types/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/types/invalid_binary_op.snow.err => pkg/semantic/testdata/types/invalid_binary_op.snow.err +0 -0
A pkg/semantic/testdata/types/invalid_binary_op.snow.want => pkg/semantic/testdata/types/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/types/let.snow.err => pkg/semantic/testdata/types/let.snow.err +0 -0
A pkg/semantic/testdata/types/let.snow.want => pkg/semantic/testdata/types/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/types/let_invalid_tuple_type.snow.err => pkg/semantic/testdata/types/let_invalid_tuple_type.snow.err +0 -0
A pkg/semantic/testdata/types/let_invalid_tuple_type.snow.want => pkg/semantic/testdata/types/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/types/let_invalid_unary.snow.err => pkg/semantic/testdata/types/let_invalid_unary.snow.err +0 -0
A pkg/semantic/testdata/types/let_invalid_unary.snow.want => pkg/semantic/testdata/types/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/types/let_unary.snow.err => pkg/semantic/testdata/types/let_unary.snow.err +0 -0
A pkg/semantic/testdata/types/let_unary.snow.want => pkg/semantic/testdata/types/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/types/paren_type.snow.err => pkg/semantic/testdata/types/paren_type.snow.err +0 -0
A pkg/semantic/testdata/types/paren_type.snow.want => pkg/semantic/testdata/types/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/types/top_level_fn_init_order.snow.err => pkg/semantic/testdata/types/top_level_fn_init_order.snow.err +0 -0
A pkg/semantic/testdata/types/top_level_fn_init_order.snow.want => pkg/semantic/testdata/types/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/types/top_level_init_order.snow.err => pkg/semantic/testdata/types/top_level_init_order.snow.err +0 -0
A pkg/semantic/testdata/types/top_level_init_order.snow.want => pkg/semantic/testdata/types/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/types/var.snow.err => pkg/semantic/testdata/types/var.snow.err +0 -0
A pkg/semantic/testdata/types/var.snow.want => pkg/semantic/testdata/types/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/types/var_auto_ref.snow.err => pkg/semantic/testdata/types/var_auto_ref.snow.err +0 -0
A pkg/semantic/testdata/types/var_auto_ref.snow.want => pkg/semantic/testdata/types/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/types/var_bool.snow.err => pkg/semantic/testdata/types/var_bool.snow.err +0 -0
A pkg/semantic/testdata/types/var_bool.snow.want => pkg/semantic/testdata/types/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/types/var_duplicate_symbol.snow.err => pkg/semantic/testdata/types/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/types/var_duplicate_symbol.snow.want => pkg/semantic/testdata/types/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/types/var_tuple_type.snow.err => pkg/semantic/testdata/types/var_tuple_type.snow.err +0 -0
A pkg/semantic/testdata/types/var_tuple_type.snow.want => pkg/semantic/testdata/types/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/translate_pass.go => pkg/semantic/translate_pass.go +9 -1
@@ 122,6 122,10 @@ func (t *translateVisitor) Visit(n ast.Node) ast.Visitor {

	case *ast.VarDecl:
		v := t.buildVarOrExpr(n.Kw, n.Name, n.Type).(*Var)
		v.Ctx = Immutable
		if n.Kw == token.Var {
			v.Ctx = Mutable
		}
		if n.Value != nil {
			ast.Walk(t, n.Value)
			v.Value = t.generated.(Expr)


@@ 428,7 432,11 @@ func (t *translateVisitor) Visit(n ast.Node) ast.Visitor {
	case *ast.ParamDef:
		// ParamDef are treated just like VarDecl if there is a Name, otherwise
		// just an Expr (the type).
		t.generated = t.buildVarOrExpr(token.Let, n.Name, n.Type)
		ve := t.buildVarOrExpr(token.Let, n.Name, n.Type)
		if v, ok := ve.(*Var); ok {
			v.Ctx = Immutable
		}
		t.generated = ve

	case *ast.ExprItem:
		// ExprItem ignores the label (it is extracted directly in CallExpr, the

M pkg/semantic/translate_pass_test.go => pkg/semantic/translate_pass_test.go +1 -1
@@ 18,7 18,7 @@ func TestScopes(t *testing.T) {

	for _, fi := range filetest.SourceFiles(t, baseDir) {
		t.Run(fi.Name(), func(t *testing.T) {
			unit, err := Run(filepath.Join(baseDir, fi.Name()))
			unit, err := Run(TranslatePass, filepath.Join(baseDir, fi.Name()))

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

M pkg/semantic/typeassign_pass.go => pkg/semantic/typeassign_pass.go +6 -4
@@ 22,7 22,7 @@ func typeassign(unit *Unit, errh func(token.Pos, string)) {
		// run deferred processing to try and resolve unresolved types
		pass := make([]func(), len(v.deferred))
		copy(pass, v.deferred)
		v.deferred = nil
		v.deferred = v.deferred[:0]
		for _, fn := range pass {
			fn()
		}


@@ 229,7 229,9 @@ func (t *typeassignVisitor) Visit(n Node) Visitor {
		}
		n.Ref = decl
		n.ctx = decl.TypeContext()
		n.typ = decl.Type()
		if n.typ = decl.Type(); n.typ == nil {
			n.typ = unresolvedType{}
		}

	case *LitString:
		n.ctx = Constant


@@ 272,10 274,10 @@ func (t *typeassignVisitor) typeAssignSelector(left Type, leftCtx TypeContext, s
	case *TupleType:
		sel.ctx = leftCtx
		if sel.Index < 0 || sel.Index >= len(left.Fields) {
			sel.typ = left.Fields[sel.Index]
			t.errUndefined(sel, left)
			return
		}
		t.errUndefined(sel, left)
		sel.typ = left.Fields[sel.Index]

	default:
		sel.ctx = Invalid

A pkg/semantic/typeassign_pass_test.go => pkg/semantic/typeassign_pass_test.go +41 -0
@@ 0,0 1,41 @@
package semantic_test

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

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

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

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

	for _, fi := range filetest.SourceFiles(t, baseDir) {
		t.Run(fi.Name(), func(t *testing.T) {
			unit, err := semantic.Run(semantic.TypeAssignPass, 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, testUpdateTypesTests)
			filetest.DiffErrors(t, fi, ebuf.String(), expectDir, testUpdateTypesTests)
		})
	}
}

M pkg/typecheck/check_pass_test.go => pkg/typecheck/check_pass_test.go +1 -1
@@ 31,7 31,7 @@ func TestCheck(t *testing.T) {
			var buf bytes.Buffer
			pp := printer.Printer{W: &buf, Pos: printer.PosNone, WithTypes: unit.Types}
			for _, f := range unit.Files {
				pp.Print(f, unit.FileSet.File(f.Pos()))
				_ = pp.PrintAST(f, unit.FileSet.File(f.Pos()))
			}

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

M pkg/typecheck/type_pass_test.go => pkg/typecheck/type_pass_test.go +1 -1
@@ 32,7 32,7 @@ func TestTypes(t *testing.T) {
			var buf bytes.Buffer
			pp := printer.Printer{W: &buf, Pos: printer.PosNone, WithTypes: unit.Types}
			for _, f := range unit.Files {
				pp.Print(f, unit.FileSet.File(f.Pos()))
				_ = pp.PrintAST(f, unit.FileSet.File(f.Pos()))
			}

			filetest.DiffOutput(t, fi, buf.String(), expectDir, testUpdateTypesTests)