diff options
Diffstat (limited to 'androidmk/parser/scope.go')
-rw-r--r-- | androidmk/parser/scope.go | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/androidmk/parser/scope.go b/androidmk/parser/scope.go new file mode 100644 index 00000000..742ad388 --- /dev/null +++ b/androidmk/parser/scope.go @@ -0,0 +1,88 @@ +package parser + +import "strings" + +type Scope interface { + Get(name string) string + Set(name, value string) + Call(name string, args []string) string + SetFunc(name string, f func([]string) string) +} + +type scope struct { + variables map[string]string + functions map[string]func([]string) string + parent Scope +} + +func (s *scope) Get(name string) string { + if val, ok := s.variables[name]; ok { + return val + } else if s.parent != nil { + return s.parent.Get(name) + } else if val, ok := builtinScope[name]; ok { + return val + } else { + return "<'" + name + "' unset>" + } +} + +func (s *scope) Set(name, value string) { + s.variables[name] = value +} + +func (s *scope) Call(name string, args []string) string { + if f, ok := s.functions[name]; ok { + return f(args) + } + + return "<func:'" + name + "' unset>" +} + +func (s *scope) SetFunc(name string, f func([]string) string) { + s.functions[name] = f +} + +func NewScope(parent Scope) Scope { + return &scope{ + variables: make(map[string]string), + functions: make(map[string]func([]string) string), + parent: parent, + } +} + +var builtinScope map[string]string + +func init() { + builtinScope := make(map[string]string) + builtinScope["__builtin_dollar"] = "$" +} + +func (v Variable) Value(scope Scope) string { + f := v.Name.SplitN(" \t", 2) + if len(f) > 1 && f[0].Const() { + fname := f[0].Value(nil) + if isFunctionName(fname) { + args := f[1].Split(",") + argVals := make([]string, len(args)) + for i, a := range args { + argVals[i] = a.Value(scope) + } + + if fname == "call" { + return scope.Call(argVals[0], argVals[1:]) + } else { + return "__builtin_func:" + fname + " " + strings.Join(argVals, " ") + } + } + } + + return scope.Get(v.Name.Value(scope)) +} + +func toVariable(ms *MakeString) (Variable, bool) { + if len(ms.Variables) == 1 && ms.Strings[0] == "" && ms.Strings[1] == "" { + return ms.Variables[0], true + } + return Variable{}, false +} |