// setConst sets x to the untyped constant for literal lit. func (x *operand) setConst(tok token.Token, lit string) { val := exact.MakeFromLiteral(lit, tok) if val == nil { // TODO(gri) Should we make it an unknown constant instead? x.mode = invalid return } var kind BasicKind switch tok { case token.INT: kind = UntypedInt case token.FLOAT: kind = UntypedFloat case token.IMAG: kind = UntypedComplex case token.CHAR: kind = UntypedRune case token.STRING: kind = UntypedString } x.mode = constant x.typ = Typ[kind] x.val = val }
// number = int_lit [ "p" int_lit ] . // func (p *parser) parseNumber() (typ *types.Basic, val exact.Value) { // mantissa mant := exact.MakeFromLiteral(p.parseInt(), token.INT) if mant == nil { panic("invalid mantissa") } if p.lit == "p" { // exponent (base 2) p.next() exp, err := strconv.ParseInt(p.parseInt(), 10, 0) if err != nil { p.error(err) } if exp < 0 { denom := exact.MakeInt64(1) denom = exact.Shift(denom, token.SHL, uint(-exp)) typ = types.Typ[types.UntypedFloat] val = exact.BinaryOp(mant, token.QUO, denom) return } if exp > 0 { mant = exact.Shift(mant, token.SHL, uint(exp)) } typ = types.Typ[types.UntypedFloat] val = mant return } typ = types.Typ[types.UntypedInt] val = mant return }
// number = int_lit [ "p" int_lit ] . // func (p *gcParser) parseNumber() (x operand) { x.mode = constant // mantissa mant := exact.MakeFromLiteral(p.parseInt(), token.INT) assert(mant != nil) if p.lit == "p" { // exponent (base 2) p.next() exp, err := strconv.ParseInt(p.parseInt(), 10, 0) if err != nil { p.error(err) } if exp < 0 { denom := exact.MakeInt64(1) denom = exact.Shift(denom, token.SHL, uint(-exp)) x.typ = Typ[UntypedFloat] x.val = exact.BinaryOp(mant, token.QUO, denom) return } if exp > 0 { mant = exact.Shift(mant, token.SHL, uint(exp)) } x.typ = Typ[UntypedFloat] x.val = mant return } x.typ = Typ[UntypedInt] x.val = mant return }
func val(lit string) exact.Value { if len(lit) == 0 { return exact.MakeUnknown() } switch lit { case "?": return exact.MakeUnknown() case "true": return exact.MakeBool(true) case "false": return exact.MakeBool(false) } tok := token.INT switch first, last := lit[0], lit[len(lit)-1]; { case first == '"' || first == '`': tok = token.STRING lit = strings.Replace(lit, "_", " ", -1) case first == '\'': tok = token.CHAR case last == 'i': tok = token.IMAG default: if !strings.HasPrefix(lit, "0x") && strings.ContainsAny(lit, "./Ee") { tok = token.FLOAT } } return exact.MakeFromLiteral(lit, tok) }
func val(lit string) exact.Value { if len(lit) == 0 { return exact.MakeUnknown() } switch lit { case "?": return exact.MakeUnknown() case "nil": return nil case "true": return exact.MakeBool(true) case "false": return exact.MakeBool(false) } tok := token.FLOAT switch first, last := lit[0], lit[len(lit)-1]; { case first == '"' || first == '`': tok = token.STRING lit = strings.Replace(lit, "_", " ", -1) case first == '\'': tok = token.CHAR case last == 'i': tok = token.IMAG } return exact.MakeFromLiteral(lit, tok) }
// 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 *parser) parseConstDecl() { p.expectKeyword("const") pkg, name := p.parseExportedName() var typ0 types.Type if p.tok != '=' { typ0 = p.parseType() } p.expect('=') var typ types.Type var val exact.Value switch p.tok { case scanner.Ident: // bool_lit if p.lit != "true" && p.lit != "false" { p.error("expected true or false") } typ = types.Typ[types.UntypedBool] val = exact.MakeBool(p.lit == "true") p.next() case '-', scanner.Int: // int_lit typ, val = p.parseNumber() case '(': // complex_lit or rune_lit p.next() if p.tok == scanner.Char { p.next() p.expect('+') typ = types.Typ[types.UntypedRune] _, val = p.parseNumber() p.expect(')') break } _, re := p.parseNumber() p.expect('+') _, im := p.parseNumber() p.expectKeyword("i") p.expect(')') typ = types.Typ[types.UntypedComplex] val = exact.BinaryOp(re, token.ADD, exact.MakeImag(im)) case scanner.Char: // rune_lit typ = types.Typ[types.UntypedRune] val = exact.MakeFromLiteral(p.lit, token.CHAR) p.next() case scanner.String: // string_lit typ = types.Typ[types.UntypedString] val = exact.MakeFromLiteral(p.lit, token.STRING) p.next() default: p.errorf("expected literal got %s", scanner.TokenString(p.tok)) } if typ0 == nil { typ0 = typ } pkg.Scope().Insert(types.NewConst(token.NoPos, pkg, name, typ0, val)) }
// ConstValue = string | "false" | "true" | ["-"] (int ["'"] | FloatOrComplex) . // FloatOrComplex = float ["i" | ("+"|"-") float "i"] . func (p *parser) parseConstValue() (val exact.Value, typ types.Type) { switch p.tok { case scanner.String: str := p.parseString() val = exact.MakeString(str) typ = types.Typ[types.UntypedString] return case scanner.Ident: b := false switch p.lit { case "false": case "true": b = true default: p.errorf("expected const value, got %s (%q)", scanner.TokenString(p.tok), p.lit) } p.next() val = exact.MakeBool(b) typ = types.Typ[types.UntypedBool] return } sign := "" if p.tok == '-' { p.next() sign = "-" } switch p.tok { case scanner.Int: val = exact.MakeFromLiteral(sign+p.lit, token.INT) if val == nil { p.error("could not parse integer literal") } p.next() if p.tok == '\'' { p.next() typ = types.Typ[types.UntypedRune] } else { typ = types.Typ[types.UntypedInt] } case scanner.Float: re := sign + p.lit p.next() var im string switch p.tok { case '+': p.next() im = p.expect(scanner.Float) case '-': p.next() im = "-" + p.expect(scanner.Float) case scanner.Ident: // re is in fact the imaginary component. Expect "i" below. im = re re = "0" default: val = exact.MakeFromLiteral(re, token.FLOAT) if val == nil { p.error("could not parse float literal") } typ = types.Typ[types.UntypedFloat] return } p.expectKeyword("i") reval := exact.MakeFromLiteral(re, token.FLOAT) if reval == nil { p.error("could not parse real component of complex literal") } imval := exact.MakeFromLiteral(im+"i", token.IMAG) if imval == nil { p.error("could not parse imag component of complex literal") } val = exact.BinaryOp(reval, token.ADD, imval) typ = types.Typ[types.UntypedComplex] default: p.errorf("expected const value, got %s (%q)", scanner.TokenString(p.tok), p.lit) } return }
// matchExpr reports whether pattern x matches y. // // If tr.allowWildcards, Idents in x that refer to parameters are // treated as wildcards, and match any y that is assignable to the // parameter type; matchExpr records this correspondence in tr.env. // Otherwise, matchExpr simply reports whether the two trees are // equivalent. // // A wildcard appearing more than once in the pattern must // consistently match the same tree. // func (tr *Transformer) matchExpr(x, y ast.Expr) bool { if x == nil && y == nil { return true } if x == nil || y == nil { return false } x = unparen(x) y = unparen(y) // Is x a wildcard? (a reference to a 'before' parameter) if x, ok := x.(*ast.Ident); ok && x != nil && tr.allowWildcards { if xobj, ok := tr.info.Uses[x].(*types.Var); ok && tr.wildcards[xobj] { return tr.matchWildcard(xobj, y) } } // Object identifiers (including pkg-qualified ones) // are handled semantically, not syntactically. xobj := isRef(x, &tr.info) yobj := isRef(y, &tr.info) if xobj != nil { return xobj == yobj } if yobj != nil { return false } // TODO(adonovan): audit: we cannot assume these ast.Exprs // contain non-nil pointers. e.g. ImportSpec.Name may be a // nil *ast.Ident. if reflect.TypeOf(x) != reflect.TypeOf(y) { return false } switch x := x.(type) { case *ast.Ident: log.Fatalf("unexpected Ident: %s", astString(tr.fset, x)) case *ast.BasicLit: y := y.(*ast.BasicLit) xval := exact.MakeFromLiteral(x.Value, x.Kind) yval := exact.MakeFromLiteral(y.Value, y.Kind) return exact.Compare(xval, token.EQL, yval) case *ast.FuncLit: // func literals (and thus statement syntax) never match. return false case *ast.CompositeLit: y := y.(*ast.CompositeLit) return (x.Type == nil) == (y.Type == nil) && (x.Type == nil || tr.matchType(x.Type, y.Type)) && tr.matchExprs(x.Elts, y.Elts) case *ast.SelectorExpr: y := y.(*ast.SelectorExpr) return tr.matchExpr(x.X, y.X) && tr.info.Selections[x].Obj() == tr.info.Selections[y].Obj() case *ast.IndexExpr: y := y.(*ast.IndexExpr) return tr.matchExpr(x.X, y.X) && tr.matchExpr(x.Index, y.Index) case *ast.SliceExpr: y := y.(*ast.SliceExpr) return tr.matchExpr(x.X, y.X) && tr.matchExpr(x.Low, y.Low) && tr.matchExpr(x.High, y.High) && tr.matchExpr(x.Max, y.Max) && x.Slice3 == y.Slice3 case *ast.TypeAssertExpr: y := y.(*ast.TypeAssertExpr) return tr.matchExpr(x.X, y.X) && tr.matchType(x.Type, y.Type) case *ast.CallExpr: y := y.(*ast.CallExpr) match := tr.matchExpr // function call if tr.info.IsType(x.Fun) { match = tr.matchType // type conversion } return x.Ellipsis.IsValid() == y.Ellipsis.IsValid() && match(x.Fun, y.Fun) && tr.matchExprs(x.Args, y.Args) case *ast.StarExpr: y := y.(*ast.StarExpr) return tr.matchExpr(x.X, y.X) case *ast.UnaryExpr: y := y.(*ast.UnaryExpr) return x.Op == y.Op && tr.matchExpr(x.X, y.X) case *ast.BinaryExpr: y := y.(*ast.BinaryExpr) return x.Op == y.Op && tr.matchExpr(x.X, y.X) && tr.matchExpr(x.Y, y.Y) case *ast.KeyValueExpr: y := y.(*ast.KeyValueExpr) return tr.matchExpr(x.Key, y.Key) && tr.matchExpr(x.Value, y.Value) } panic(fmt.Sprintf("unhandled AST node type: %T", x)) }