Spracherkennung für: .go vermutete Sprache: Abap {ABAP[95] Corba[72] CS[72]} [Methode: maximale Elemente, drei Dimensionen]
// Copyright
2014 Google Inc. All rights reserved.
//
// Licensed
under the Apache License, Version
2.
0 (the
"License");
// you may not use this
file except
in compliance with the License.
// You may obtain a
copy of the License
at
//
//
http://www.apache.org/licenses/LICENSE-2.
0
//
// Unless required
by applicable law
or agreed
to in writing, software
// distributed
under the License
is distributed
on an
"AS IS" BASIS,
// WITHOUT WARRANTIES
OR CONDITIONS
OF ANY KIND, either express
or implied.
// See the License
for the specific
language governing permissions
and
// limitations
under the License.
package blueprint
import (
"fmt"
"strings"
"unicode"
"unicode/utf8"
)
// A Variable represents a global Ninja variable
definition that will be written
//
to the output .ninja
file. A variable may contain references
to other global
// Ninja variables, but circular variable references are not allowed.
type Variable
interface {
packageContext()
*packageContext
name()
string //
"foo"
fullName(pkgNames map[
*packageContext]string) string // "pkg.foo" or "path.to.pkg.foo"
value(ctx VariableFuncContext, config
interface{}) (
*ninjaString, error)
String()
string
}
// A Pool represents a Ninja pool that will be written
to the output .ninja
//
file.
type Pool
interface {
packageContext()
*packageContext
name()
string //
"foo"
fullName(pkgNames map[
*packageContext]string) string // "pkg.foo" or "path.to.pkg.foo"
def(config
interface{}) (
*poolDef, error)
String()
string
}
// A Rule represents a Ninja build rule that will be written
to the output
// .ninja
file.
type Rule
interface {
packageContext()
*packageContext
name()
string //
"foo"
fullName(pkgNames map[
*packageContext]string) string // "pkg.foo" or "path.to.pkg.foo"
def(config
interface{}) (
*ruleDef, error)
scope()
*basicScope
isArg(argName
string) bool
String()
string
}
type basicScope struct {
parent
*basicScope
variables map[
string]Variable
pools map[
string]Pool
rules map[
string]Rule
imports map[
string]
*basicScope
}
func newScope(parent
*basicScope) *basicScope {
return &basicScope{
parent: parent,
variables: make(map[
string]Variable),
pools: make(map[
string]Pool),
rules: make(map[
string]Rule),
imports: make(map[
string]
*basicScope),
}
}
func makeRuleScope(parent
*basicScope, argNames map[string]bool) *basicScope {
scope := newScope(parent)
for argName := range argNames {
_, err := scope.LookupVariable(argName)
if err != nil {
arg := &argVariable{argName}
err = scope.AddVariable(arg)
if err != nil {
// This should not happen. We should have already checked that
// the name
is valid
and that the scope doesn
't have a variable
// with this name.
panic(err)
}
}
}
// We treat built-
in variables
like arguments
for the purpose
of this scope.
for _, builtin := range builtinRuleArgs {
arg := &argVariable{builtin}
err := scope.AddVariable(arg)
if err != nil {
panic(err)
}
}
return scope
}
func (s
*basicScope) LookupVariable(name string) (Variable, error) {
dotIndex := strings.IndexRune(name,
'.')
if dotIndex >=
0 {
// The variable name looks
like "pkg.var"
if dotIndex+
1 == len(name) {
return nil, fmt.Errorf(
"variable name %q ends with a '.'", name)
}
if strings.ContainsRune(name[dotIndex+
1:],
'.') {
return nil, fmt.Errorf(
"variable name %q contains multiple '.' "+
"characters", name)
}
pkgName := name[:dotIndex]
varName := name[dotIndex+
1:]
first, _ := utf8.DecodeRuneInString(varName)
if !unicode.IsUpper(first) {
return nil, fmt.Errorf(
"cannot refer to unexported name %q", name)
}
importedScope, err := s.lookupImportedScope(pkgName)
if err != nil {
return nil, err
}
v, ok := importedScope.variables[varName]
if !ok {
return nil, fmt.Errorf(
"package %q does not contain variable %q",
pkgName, varName)
}
return v, nil
}
else {
// The variable name has no package part; just
"var"
for ; s != nil; s = s.parent {
v, ok := s.variables[name]
if ok {
return v, nil
}
}
return nil, fmt.Errorf(
"undefined variable %q", name)
}
}
func (s
*basicScope) IsRuleVisible(rule Rule) bool {
_, isBuiltin := rule.(
*builtinRule)
if isBuiltin {
return true
}
name := rule.name()
for s != nil {
if s.rules[name] == rule {
return true
}
for _, import_ := range s.imports {
if import_.rules[name] == rule {
return true
}
}
s = s.parent
}
return false
}
func (s
*basicScope) IsPoolVisible(pool Pool) bool {
_, isBuiltin := pool.(
*builtinPool)
if isBuiltin {
return true
}
name := pool.name()
for s != nil {
if s.pools[name] == pool {
return true
}
for _, import_ := range s.imports {
if import_.pools[name] == pool {
return true
}
}
s = s.parent
}
return false
}
func (s
*basicScope) lookupImportedScope(pkgName string) (*basicScope, error) {
for ; s != nil; s = s.parent {
importedScope, ok := s.imports[pkgName]
if ok {
return importedScope, nil
}
}
return nil, fmt.Errorf(
"unknown imported package %q (missing call to "+
"blueprint.Import()?)", pkgName)
}
func (s
*basicScope) AddImport(name string, importedScope *basicScope) error {
_, present := s.imports[name]
if present {
return fmt.Errorf(
"import %q is already defined in this scope", name)
}
s.imports[name] = importedScope
return nil
}
func (s
*basicScope) AddVariable(v Variable) error {
name := v.name()
_, present := s.variables[name]
if present {
return fmt.Errorf(
"variable %q is already defined in this scope", name)
}
s.variables[name] = v
return nil
}
func (s
*basicScope) AddPool(p Pool) error {
name := p.name()
_, present := s.pools[name]
if present {
return fmt.Errorf(
"pool %q is already defined in this scope", name)
}
s.pools[name] = p
return nil
}
func (s
*basicScope) AddRule(r Rule) error {
name := r.name()
_, present := s.rules[name]
if present {
return fmt.Errorf(
"rule %q is already defined in this scope", name)
}
s.rules[name] = r
return nil
}
type localScope struct {
namePrefix
string
scope
*basicScope
}
func newLocalScope(parent
*basicScope, namePrefix string) *localScope {
return &localScope{
namePrefix: namePrefix,
scope: newScope(parent),
}
}
// ReparentTo sets the localScope
's parent scope to the scope of the given
// package context. This allows a ModuleContext
and SingletonContext
to call
// a
function defined
in a different Go package
and have that
function retain
// access
to all
of the package-scoped variables
of its own package.
func (s
*localScope) ReparentTo(pctx PackageContext) {
s.scope.parent = pctx.getScope()
}
func (s
*localScope) LookupVariable(name string) (Variable, error) {
return s.scope.LookupVariable(name)
}
func (s
*localScope) IsRuleVisible(rule Rule) bool {
return s.scope.IsRuleVisible(rule)
}
func (s
*localScope) IsPoolVisible(pool Pool) bool {
return s.scope.IsPoolVisible(pool)
}
func (s
*localScope) AddLocalVariable(name, value string) (*localVariable,
error) {
err := validateNinjaName(name)
if err != nil {
return nil, err
}
if strings.ContainsRune(name,
'.') {
return nil, fmt.Errorf(
"local variable name %q contains '.'", name)
}
ninjaValue, err := parseNinjaString(s.scope, value)
if err != nil {
return nil, err
}
v := &localVariable{
fullName_: s.namePrefix + name,
name_: name,
value_: ninjaValue,
}
err = s.scope.AddVariable(v)
if err != nil {
return nil, err
}
return v, nil
}
func (s
*localScope) AddLocalRule(config any, name string, params *RuleParams,
argNames ...
string) (
*localRule, error) {
err := validateNinjaName(name)
if err != nil {
return nil, err
}
err = validateArgNames(argNames)
if err != nil {
return nil, fmt.Errorf(
"invalid argument name: %s", err)
}
argNamesSet := make(map[
string]bool)
for _, argName := range argNames {
argNamesSet[argName] = true
}
ruleScope := makeRuleScope(s.scope, argNamesSet)
def, err := parseRuleParams(config, ruleScope, params)
if err != nil {
return nil, err
}
r := &localRule{
fullName_: s.namePrefix + name,
name_: name,
def_: def,
argNames: argNamesSet,
scope_: ruleScope,
}
err = s.scope.AddRule(r)
if err != nil {
return nil, err
}
return r, nil
}
type localVariable struct {
fullName_
string
name_
string
value_
*ninjaString
}
func (l
*localVariable) packageContext() *packageContext {
return nil
}
func (l
*localVariable) name() string {
return l.name_
}
func (l
*localVariable) fullName(pkgNames map[*packageContext]string) string {
return l.fullName_
}
func (l
*localVariable) value(VariableFuncContext, interface{}) (*ninjaString, error) {
return l.value_, nil
}
func (l
*localVariable) String() string {
return
"<local var>:" + l.fullName_
}
type localRule struct {
fullName_
string
name_
string
def_
*ruleDef
argNames map[
string]bool
scope_
*basicScope
}
func (l
*localRule) packageContext() *packageContext {
return nil
}
func (l
*localRule) name() string {
return l.name_
}
func (l
*localRule) fullName(pkgNames map[*packageContext]string) string {
return l.fullName_
}
func (l
*localRule) def(interface{}) (*ruleDef, error) {
return l.def_, nil
}
func (r
*localRule) scope() *basicScope {
return r.scope_
}
func (r
*localRule) isArg(argName string) bool {
return r.argNames[argName]
}
func (r
*localRule) String() string {
return
"<local rule>:" + r.fullName_
}
type nameTracker struct {
variables map[Variable]
string
rules map[Rule]
string
pools map[Pool]
string
pkgNames map[
*packageContext]string
}
func (m
*nameTracker) Variable(v Variable) string {
if m == nil {
return v.fullName(nil)
}
if name, ok := m.variables[v]; ok {
return name
}
return v.fullName(m.pkgNames)
}
func (m
*nameTracker) Rule(r Rule) string {
if m == nil {
return r.fullName(nil)
}
if name, ok := m.rules[r]; ok {
return name
}
return r.fullName(m.pkgNames)
}
func (m
*nameTracker) Pool(p Pool) string {
if m == nil {
return p.fullName(nil)
}
if name, ok := m.pools[p]; ok {
return name
}
return p.fullName(m.pkgNames)
}