// 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 }
// 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 }