Example #1
0
// typEnumDecl type checks enum declarations.
func (c *checker) typEnumDecl(e *ast.EnumDecl) Type {
	var values []*Const

	c.iota = constant.MakeInt64(-1)
	for _, e := range e.List {
		var x operand

		if e.X != nil {
			c.constExpr(&x, e.X)
			if x.mode == invalid {
				return Typ[Invalid]
			}
		} else {
			x.val = constant.BinaryOp(c.iota, scan.Plus, constant.MakeInt64(1))
		}
		c.iota = x.val

		pos := e.Name.Span().Start
		name := e.Name.Name
		obj := NewConst(pos, name, Typ[Int], c.iota)
		values = append(values, obj)
		c.declare(Ord, c.scope, e.Name, obj, scan.NoPos)
	}

	t := new(Enum)
	t.values = values
	return t
}
Example #2
0
// binary type checks a binary expression.
func (c *checker) binary(x *operand, lhs, rhs ast.Expr, op scan.Type) {
	var y operand

	c.expr(x, lhs)
	c.expr(&y, rhs)

	if x.mode == invalid {
		return
	}
	if y.mode == invalid {
		x.mode = invalid
		x.expr = y.expr
		return
	}

	_, hasAssign := c.assignOp(op)

	switch {
	case op == scan.Comma:
		// nothing

	case op == scan.Assign || hasAssign:
		c.assignment(x, &y)
		if x.mode == invalid {
			return
		}
		if !hasAssign {
			break
		}

		fallthrough
	default:
		if !c.op(binaryOpPredicates, x, op) || !c.op(binaryOpPredicates, &y, op) {
			x.mode = invalid
			return
		}
	}

	if x.mode == constant_ && y.mode == constant_ && validConstBinOp(op) {
		x.val = constant.BinaryOp(x.val, op, y.val)
		return
	}

	x.typ = c.binaryCast(*x, y, op)
	x.mode = value
}