func TestTypeUnderlying(t *testing.T) { tests := []struct { t Type u Type }{ {t: intType, u: intType}, {t: byteType, u: byteType}, {t: t0, u: intType}, {t: t1, u: intType}, {t: &Star{Target: t0}, u: &Star{Target: t0}}, { t: &SliceType{Element: intType}, u: &SliceType{Element: intType}, }, { t: &ArrayType{Size: intLit("5"), Element: intType}, u: &ArrayType{Size: intLit("5"), Element: intType}, }, { t: &MapType{Key: t0, Value: intType}, u: &MapType{Key: t0, Value: intType}, }, { t: &ChannelType{Send: true, Element: intType}, u: &ChannelType{Send: true, Element: intType}, }, {t: &FunctionType{}, u: &FunctionType{}}, {t: &InterfaceType{}, u: &InterfaceType{}}, {t: &StructType{}, u: &StructType{}}, } for _, test := range tests { u := test.t.Underlying() if eq.Deep(u, test.u) { continue } t.Errorf("(%s).Underlying()=%s, want %s", pretty.String(test.t), pretty.String(u), pretty.String(test.u)) } }
func TestCheckTypes(t *testing.T) { // The source must contain an identifier α. // The test calls Check and compares the type of α to the given Type. tests := []struct { src string t Type }{ // Literals {`package a; const α = 1`, Untyped(IntegerConst)}, {`package a; const α = 1.0`, Untyped(FloatConst)}, {`package a; const α = 1.0i`, Untyped(ComplexConst)}, {`package a; const α = 'a'`, Untyped(RuneConst)}, {`package a; const α = "Hello, World!"`, Untyped(StringConst)}, // Identifiers {`package a; const α = true`, Untyped(BoolConst)}, {`package a; const α = false`, Untyped(BoolConst)}, {`package a; const α = iota`, Untyped(IntegerConst)}, {`package a; const ( a = iota; α )`, Untyped(IntegerConst)}, {`package a; const α int = 1`, intType}, {`package a; const α float64 = 'a'`, float64Type}, {`package a; const a, b, c, α int = 1, 2, 3, 4`, intType}, {`package a; const ( a int = iota; α )`, intType}, // UnaryOps {`package a; const α = -1`, Untyped(IntegerConst)}, {`package a; const α = -1.0`, Untyped(FloatConst)}, {`package a; const α = -1.0i`, Untyped(ComplexConst)}, {`package a; const α = -'a'`, Untyped(RuneConst)}, {`package a; const α = !true`, Untyped(BoolConst)}, {`package a; const α = -iota`, Untyped(IntegerConst)}, {`package a; const α = ^1`, Untyped(IntegerConst)}, {`package a; const α = +1.189`, Untyped(FloatConst)}, {`package a; const α int = -1`, intType}, {`package a; const α int = +1.0`, intType}, {`package a; const α int = ^1`, intType}, {`package a; const α int = ^1`, intType}, } for _, test := range tests { l := token.NewLexer("", test.src) p := NewParser(l) f := parseFile(p) if err := Check([]*File{f}); err != nil { t.Errorf("Check(%v), unexpected error: %v", test.src, err) continue } d := f.syms.Find("α") if d == nil { t.Errorf("Check(%v): failed to find symbol α", test.src) continue } var typ Type switch d := d.(type) { case *constSpecView: typ = d.Type case *varSpecView: typ = d.Type default: panic("declaration type not supported") } if !eq.Deep(typ, test.t) { t.Errorf("Check(%v)=%v: α's type is %v, want %v", test.src, pretty.String(f), pretty.String(typ), pretty.String(test.t)) } } }
func TestConstFolding(t *testing.T) { runeNeg97 := intLit("-97") runeNeg97.Rune = true // The source must contain a const α. The test calls Check on the source and // compares the resulting value of α to the given Expression. tests := []struct { src string v Expression }{ {`package a; const α = 1`, intLit("1")}, {`package a; const α = 1.0`, floatLit("1.0")}, {`package a; const α = 1.0i`, imgLit("1.0")}, {`package a; const α = 'a'`, runeLit('a')}, {`package a; const α = "Hello, World!"`, strLit("Hello, World!")}, {`package a; const α = true`, &BoolLiteral{Value: true}}, {`package a; const α = false`, &BoolLiteral{Value: false}}, {`package a; const α, b = b, 5`, intLit("5")}, {`package a; const α = iota`, intLit("0")}, {`package a; const ( zero = iota; α )`, intLit("1")}, {`package a; const ( zero = iota; one; α )`, intLit("2")}, {`package a; const α = +1`, intLit("1")}, {`package a; const α = -1`, intLit("-1")}, {`package a; const α = - -1`, intLit("1")}, {`package a; const α = +'a'`, runeLit('a')}, {`package a; const α = -'a'`, runeNeg97}, {`package a; const α = +1.0`, floatLit("1.0")}, {`package a; const α = - - -1.0`, floatLit("-1.0")}, {`package a; const α = +1.0i`, imgLit("1.0")}, {`package a; const α = - - -1.0i`, imgLit("-1.0")}, {`package a; const α = ^0`, intLit("-1")}, {`package a; const α = ^1`, intLit("-2")}, {`package a; const α float64 = ^256`, intLit("-257")}, {`package a; const α = !true`, &BoolLiteral{Value: false}}, {`package a; const α = !!true`, &BoolLiteral{Value: true}}, {`package a; const α = !false`, &BoolLiteral{Value: true}}, {`package a; const α = !!false`, &BoolLiteral{Value: false}}, {`package a; const f, α = false, !f`, &BoolLiteral{Value: true}}, } for _, test := range tests { l := token.NewLexer("", test.src) p := NewParser(l) f := parseFile(p) if err := Check([]*File{f}); err != nil { t.Errorf("Check(%v), unexpected error: %v", test.src, err) continue } d := f.syms.Find("α") if d == nil { t.Errorf("Check(%v): failed to find symbol α", test.src) continue } a, ok := d.(*constSpecView) if !ok { t.Errorf("Check(%v): α is not a const", test.src) continue } if !eq.Deep(a.Value, test.v) { t.Errorf("Check(%v)=%v: α folded to %v, want %v", test.src, pretty.String(f), pretty.String(a.Value), pretty.String(test.v)) } } }