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*)$`)