1// Copyright 2009 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 5package types 6 7import ( 8 "fmt" 9 "internal/goversion" 10 "internal/lazyregexp" 11 "log" 12 "strconv" 13 14 "cmd/compile/internal/base" 15) 16 17// A lang is a language version broken into major and minor numbers. 18type lang struct { 19 major, minor int 20} 21 22// langWant is the desired language version set by the -lang flag. 23// If the -lang flag is not set, this is the zero value, meaning that 24// any language version is supported. 25var langWant lang 26 27// AllowsGoVersion reports whether local package is allowed 28// to use Go version major.minor. 29func AllowsGoVersion(major, minor int) bool { 30 if langWant.major == 0 && langWant.minor == 0 { 31 return true 32 } 33 return langWant.major > major || (langWant.major == major && langWant.minor >= minor) 34} 35 36// ParseLangFlag verifies that the -lang flag holds a valid value, and 37// exits if not. It initializes data used by AllowsGoVersion. 38func ParseLangFlag() { 39 if base.Flag.Lang == "" { 40 return 41 } 42 43 var err error 44 langWant, err = parseLang(base.Flag.Lang) 45 if err != nil { 46 log.Fatalf("invalid value %q for -lang: %v", base.Flag.Lang, err) 47 } 48 49 if def := currentLang(); base.Flag.Lang != def { 50 defVers, err := parseLang(def) 51 if err != nil { 52 log.Fatalf("internal error parsing default lang %q: %v", def, err) 53 } 54 if langWant.major > defVers.major || (langWant.major == defVers.major && langWant.minor > defVers.minor) { 55 log.Fatalf("invalid value %q for -lang: max known version is %q", base.Flag.Lang, def) 56 } 57 } 58} 59 60// parseLang parses a -lang option into a langVer. 61func parseLang(s string) (lang, error) { 62 if s == "go1" { // cmd/go's new spelling of "go1.0" (#65528) 63 s = "go1.0" 64 } 65 66 matches := goVersionRE.FindStringSubmatch(s) 67 if matches == nil { 68 return lang{}, fmt.Errorf(`should be something like "go1.12"`) 69 } 70 major, err := strconv.Atoi(matches[1]) 71 if err != nil { 72 return lang{}, err 73 } 74 minor, err := strconv.Atoi(matches[2]) 75 if err != nil { 76 return lang{}, err 77 } 78 return lang{major: major, minor: minor}, nil 79} 80 81// currentLang returns the current language version. 82func currentLang() string { 83 return fmt.Sprintf("go1.%d", goversion.Version) 84} 85 86// goVersionRE is a regular expression that matches the valid 87// arguments to the -lang flag. 88var goVersionRE = lazyregexp.New(`^go([1-9]\d*)\.(0|[1-9]\d*)$`) 89