예제 #1
0
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]
}
예제 #2
0
	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", typ: Typ[UntypedBool], val: exact.MakeBool(true)},
	{name: "false", typ: Typ[UntypedBool], val: exact.MakeBool(false)},
	{name: "iota", typ: Typ[UntypedInt], val: exact.MakeInt64(0)},
	{name: "nil", typ: 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},
예제 #3
0
// 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.typ = 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.typ == nil {
		obj.typ = x.typ
	}
	assert(x.val != nil)
	obj.val = x.val
}