func buildPkgConstDecl(b *builder, d *ast.ConstDecl) []*pkgConst { if d.Type != nil { b.Errorf(ast.ExprPos(d.Type), "typed const not implemented") return nil } nident := len(d.Idents.Idents) nexpr := len(d.Exprs.Exprs) if nident != nexpr { b.Errorf(d.Eq.Pos, "%d consts with %d expressions", nident, nexpr, ) return nil } var ret []*pkgConst zero := types.NewNumber(0) // place holding the const for i, ident := range d.Idents.Idents { s := declareConst(b, ident, zero) if s == nil { return nil } expr := d.Exprs.Exprs[i] c := &pkgConst{ sym: s, tok: ident, expr: expr, deps: symUse(expr), } ret = append(ret, c) } return ret }
func unaryOpConst(b *builder, opTok *lex8.Token, B tast.Expr) tast.Expr { op := opTok.Lit bref := B.R() if !bref.IsSingle() { b.Errorf(opTok.Pos, "invalid operation: %q on %s", op, bref) return nil } v, ok := types.NumConst(bref.T) if !ok { // TODO: support type const b.Errorf(opTok.Pos, "typed const operation not implemented") return nil } switch op { case "+": return B // just shortcut this case "-": return &tast.Const{tast.NewRef(types.NewNumber(-v))} } b.Errorf(opTok.Pos, "invalid operation: %q on %s", op, B) return nil }
func buildInt(b *builder, op *lex8.Token) tast.Expr { ret, e := strconv.ParseInt(op.Lit, 0, 64) if e != nil { b.Errorf(op.Pos, "invalid integer: %s", e) return nil } if ret < math.MinInt32 { b.Errorf(op.Pos, "integer too small to fit in 32-bit") return nil } else if ret > math.MaxUint32 { b.Errorf(op.Pos, "integer too large to fit in 32-bit") return nil } ref := tast.NewConstRef(types.NewNumber(ret), ret) return &tast.Const{ref} }
func binaryOpConst(b *builder, opTok *lex8.Token, A, B tast.Expr) tast.Expr { op := opTok.Lit aref := A.R() bref := B.R() if aref.List != nil || bref.List != nil { b.Errorf(opTok.Pos, "invalid %s %q %s", aref.T, op, bref.T) return nil } va, oka := types.NumConst(aref.T) vb, okb := types.NumConst(bref.T) if !(oka && okb) { b.Errorf(opTok.Pos, "non-numeric consts ops not implemented") return nil } r := func(v int64) tast.Expr { return &tast.Const{tast.NewRef(types.NewNumber(v))} } switch op { case "+": return r(va + vb) case "-": return r(va - vb) case "*": return r(va * vb) case "&": return r(va & vb) case "|": return r(va | vb) case "^": return r(va ^ vb) case "%": if vb == 0 { b.Errorf(opTok.Pos, "modular by zero") return nil } return r(va % vb) case "/": if vb == 0 { b.Errorf(opTok.Pos, "divide by zero") return nil } return r(va / vb) case "==", "!=", ">", "<", ">=", "<=": return &tast.OpExpr{A, opTok, B, tast.NewRef(types.Bool)} case "<<": if vb < 0 { b.Errorf(opTok.Pos, "shift with negative value", vb) return nil } return r(va << uint64(vb)) case ">>": if vb < 0 { b.Errorf(opTok.Pos, "shift with negative value", vb) return nil } return r(va >> uint64(vb)) } b.Errorf(opTok.Pos, "%q on consts", op) return nil }