// zeroLiteral returns a new "zero" literal of the specified type, // which must not be an array or struct type: the zero values of // aggregates are well-defined but cannot be represented by Literal. // func zeroLiteral(t types.Type) *Literal { switch t := t.(type) { case *types.Basic: switch { case t.Info&types.IsBoolean != 0: return newLiteral(exact.MakeBool(false), t) case t.Info&types.IsNumeric != 0: return newLiteral(exact.MakeInt64(0), t) case t.Info&types.IsString != 0: return newLiteral(exact.MakeString(""), t) case t.Kind == types.UnsafePointer: fallthrough case t.Kind == types.UntypedNil: return nilLiteral(t) default: panic(fmt.Sprint("zeroLiteral for unexpected type:", t)) } case *types.Pointer, *types.Slice, *types.Interface, *types.Chan, *types.Map, *types.Signature: return nilLiteral(t) case *types.NamedType: return newLiteral(zeroLiteral(t.Underlying).Value, t) case *types.Array, *types.Struct: panic(fmt.Sprint("zeroLiteral applied to aggregate:", t)) } panic(fmt.Sprint("zeroLiteral: unexpected ", t)) }
func (check *checker) comparison(x, y *operand, op token.Token) { // TODO(gri) deal with interface vs non-interface comparison valid := false if x.isAssignable(check.ctxt, y.typ) || y.isAssignable(check.ctxt, x.typ) { switch op { case token.EQL, token.NEQ: valid = isComparable(x.typ) || x.isNil() && hasNil(y.typ) || y.isNil() && hasNil(x.typ) case token.LSS, token.LEQ, token.GTR, token.GEQ: valid = isOrdered(x.typ) default: unreachable() } } if !valid { check.invalidOp(x.pos(), "cannot compare %s %s %s", x, op, y) x.mode = invalid return } if x.mode == constant && y.mode == constant { x.val = exact.MakeBool(exact.Compare(x.val, op, y.val)) // The operands are never materialized; no need to update // their types. } else { x.mode = value // The operands have now their final types, which at run- // time will be materialized. Update the expression trees. // If the current types are untyped, the materialized type // is the respective default type. check.updateExprType(x.expr, defaultType(x.typ), true) check.updateExprType(y.expr, defaultType(y.typ), true) } // spec: "Comparison operators compare two operands and yield // an untyped boolean value." x.typ = Typ[UntypedBool] }
// ConstDecl = "const" ExportedName [ Type ] "=" Literal . // Literal = bool_lit | int_lit | float_lit | complex_lit | rune_lit | string_lit . // bool_lit = "true" | "false" . // complex_lit = "(" float_lit "+" float_lit "i" ")" . // rune_lit = "(" int_lit "+" int_lit ")" . // string_lit = `"` { unicode_char } `"` . // func (p *gcParser) parseConstDecl() { p.expectKeyword("const") pkg, name := p.parseExportedName() obj := declConst(pkg, name) var x operand if p.tok != '=' { obj.Type = p.parseType() } p.expect('=') switch p.tok { case scanner.Ident: // bool_lit if p.lit != "true" && p.lit != "false" { p.error("expected true or false") } x.typ = Typ[UntypedBool] x.val = exact.MakeBool(p.lit == "true") p.next() case '-', scanner.Int: // int_lit x = p.parseNumber() case '(': // complex_lit or rune_lit p.next() if p.tok == scanner.Char { p.next() p.expect('+') x = p.parseNumber() x.typ = Typ[UntypedRune] p.expect(')') break } re := p.parseNumber() p.expect('+') im := p.parseNumber() p.expectKeyword("i") p.expect(')') x.typ = Typ[UntypedComplex] // TODO(gri) fix this _, _ = re, im x.val = exact.MakeInt64(0) case scanner.Char: // rune_lit x.setConst(token.CHAR, p.lit) p.next() case scanner.String: // string_lit x.setConst(token.STRING, p.lit) p.next() default: p.errorf("expected literal got %s", scanner.TokenString(p.tok)) } if obj.Type == nil { obj.Type = x.typ } assert(x.val != nil) obj.Val = x.val }
UntypedBool: {UntypedBool, IsBoolean | IsUntyped, 0, "untyped boolean"}, UntypedInt: {UntypedInt, IsInteger | IsUntyped, 0, "untyped integer"}, UntypedRune: {UntypedRune, IsInteger | IsUntyped, 0, "untyped rune"}, UntypedFloat: {UntypedFloat, IsFloat | IsUntyped, 0, "untyped float"}, UntypedComplex: {UntypedComplex, IsComplex | IsUntyped, 0, "untyped complex"}, UntypedString: {UntypedString, IsString | IsUntyped, 0, "untyped string"}, UntypedNil: {UntypedNil, IsUntyped, 0, "untyped nil"}, } var aliases = [...]*Basic{ {Byte, IsInteger | IsUnsigned, 1, "byte"}, {Rune, IsInteger, 4, "rune"}, } var predeclaredConstants = [...]*Const{ {Name: "true", Type: Typ[UntypedBool], Val: exact.MakeBool(true)}, {Name: "false", Type: Typ[UntypedBool], Val: exact.MakeBool(false)}, {Name: "iota", Type: Typ[UntypedInt], Val: exact.MakeInt64(0)}, {Name: "nil", Type: Typ[UntypedNil], Val: exact.MakeNil()}, } var predeclaredFunctions = [...]*builtin{ {_Append, "append", 1, true, false}, {_Cap, "cap", 1, false, false}, {_Close, "close", 1, false, true}, {_Complex, "complex", 2, false, false}, {_Copy, "copy", 2, false, true}, {_Delete, "delete", 2, false, true}, {_Imag, "imag", 1, false, false}, {_Len, "len", 1, false, false}, {_Make, "make", 1, true, false},