github.com/bir3/gocompiler@v0.3.205/src/go/types/version.go (about) 1 // Copyright 2021 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package types 6 7 import ( 8 "fmt" 9 "github.com/bir3/gocompiler/src/go/ast" 10 "github.com/bir3/gocompiler/src/go/token" 11 . "github.com/bir3/gocompiler/src/internal/types/errors" 12 "regexp" 13 "strconv" 14 "strings" 15 ) 16 17 // langCompat reports an error if the representation of a numeric 18 // literal is not compatible with the current language version. 19 func (check *Checker) langCompat(lit *ast.BasicLit) { 20 s := lit.Value 21 if len(s) <= 2 || check.allowVersion(check.pkg, 1, 13) { 22 return 23 } 24 // len(s) > 2 25 if strings.Contains(s, "_") { 26 check.error(lit, UnsupportedFeature, "underscores in numeric literals requires go1.13 or later") 27 return 28 } 29 if s[0] != '0' { 30 return 31 } 32 radix := s[1] 33 if radix == 'b' || radix == 'B' { 34 check.error(lit, UnsupportedFeature, "binary literals requires go1.13 or later") 35 return 36 } 37 if radix == 'o' || radix == 'O' { 38 check.error(lit, UnsupportedFeature, "0o/0O-style octal literals requires go1.13 or later") 39 return 40 } 41 if lit.Kind != token.INT && (radix == 'x' || radix == 'X') { 42 check.error(lit, UnsupportedFeature, "hexadecimal floating-point literals requires go1.13 or later") 43 } 44 } 45 46 // allowVersion reports whether the given package 47 // is allowed to use version major.minor. 48 func (check *Checker) allowVersion(pkg *Package, major, minor int) bool { 49 // We assume that imported packages have all been checked, 50 // so we only have to check for the local package. 51 if pkg != check.pkg { 52 return true 53 } 54 ma, mi := check.version.major, check.version.minor 55 return ma == 0 && mi == 0 || ma > major || ma == major && mi >= minor 56 } 57 58 type version struct { 59 major, minor int 60 } 61 62 // parseGoVersion parses a Go version string (such as "go1.12") 63 // and returns the version, or an error. If s is the empty 64 // string, the version is 0.0. 65 func parseGoVersion(s string) (v version, err error) { 66 if s == "" { 67 return 68 } 69 matches := goVersionRx.FindStringSubmatch(s) 70 if matches == nil { 71 err = fmt.Errorf(`should be something like "go1.12"`) 72 return 73 } 74 v.major, err = strconv.Atoi(matches[1]) 75 if err != nil { 76 return 77 } 78 v.minor, err = strconv.Atoi(matches[2]) 79 return 80 } 81 82 // goVersionRx matches a Go version string, e.g. "go1.12". 83 var goVersionRx = regexp.MustCompile(`^go([1-9]\d*)\.(0|[1-9]\d*)$`)