github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/soong/androidmk/parser/scope.go (about) 1 // Copyright 2017 Google Inc. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package parser 16 17 import ( 18 "strings" 19 ) 20 21 type Scope interface { 22 Get(name string) string 23 Set(name, value string) 24 Call(name string, args []string) string 25 SetFunc(name string, f func([]string) string) 26 } 27 28 type scope struct { 29 variables map[string]string 30 functions map[string]func([]string) string 31 parent Scope 32 } 33 34 func (s *scope) Get(name string) string { 35 if val, ok := s.variables[name]; ok { 36 return val 37 } else if s.parent != nil { 38 return s.parent.Get(name) 39 } else if val, ok := builtinScope[name]; ok { 40 return val 41 } else { 42 return "<'" + name + "' unset>" 43 } 44 } 45 46 func (s *scope) Set(name, value string) { 47 s.variables[name] = value 48 } 49 50 func (s *scope) Call(name string, args []string) string { 51 if f, ok := s.functions[name]; ok { 52 return f(args) 53 } 54 55 return "<func:'" + name + "' unset>" 56 } 57 58 func (s *scope) SetFunc(name string, f func([]string) string) { 59 s.functions[name] = f 60 } 61 62 func NewScope(parent Scope) Scope { 63 return &scope{ 64 variables: make(map[string]string), 65 functions: make(map[string]func([]string) string), 66 parent: parent, 67 } 68 } 69 70 var builtinScope map[string]string 71 72 func init() { 73 builtinScope := make(map[string]string) 74 builtinScope["__builtin_dollar"] = "$" 75 } 76 77 func (v Variable) EvalFunction(scope Scope) (string, bool) { 78 f := v.Name.SplitN(" \t", 2) 79 if len(f) > 1 && f[0].Const() { 80 fname := f[0].Value(nil) 81 if isFunctionName(fname) { 82 args := f[1].Split(",") 83 argVals := make([]string, len(args)) 84 for i, a := range args { 85 argVals[i] = a.Value(scope) 86 } 87 88 if fname == "call" { 89 return scope.Call(argVals[0], argVals[1:]), true 90 } else { 91 return "__builtin_func:" + fname + " " + strings.Join(argVals, " "), true 92 } 93 } 94 } 95 96 return "", false 97 } 98 99 func (v Variable) Value(scope Scope) string { 100 if ret, ok := v.EvalFunction(scope); ok { 101 return ret 102 } 103 if scope == nil { 104 panic("Cannot take the value of a variable in a nil scope") 105 } 106 return scope.Get(v.Name.Value(scope)) 107 } 108 109 func toVariable(ms *MakeString) (Variable, bool) { 110 if len(ms.Variables) == 1 && ms.Strings[0] == "" && ms.Strings[1] == "" { 111 return ms.Variables[0], true 112 } 113 return Variable{}, false 114 }