blob: a28ae12e318c20b90a7a1f8b29a1bb71e341c01a [file] [log] [blame]
// Copyright 2015 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 kati
import (
"bytes"
"fmt"
"io"
)
type Var interface {
Value
Append(*Evaluator, string) Var
AppendVar(*Evaluator, Value) Var
Flavor() string
Origin() string
IsDefined() bool
}
type TargetSpecificVar struct {
v Var
op string
}
func (v *TargetSpecificVar) Append(ev *Evaluator, s string) Var {
return &TargetSpecificVar{
v: v.v.Append(ev, s),
op: v.op,
}
}
func (v *TargetSpecificVar) AppendVar(ev *Evaluator, v2 Value) Var {
return &TargetSpecificVar{
v: v.v.AppendVar(ev, v2),
op: v.op,
}
}
func (v *TargetSpecificVar) Flavor() string {
return v.v.Flavor()
}
func (v *TargetSpecificVar) Origin() string {
return v.v.Origin()
}
func (v *TargetSpecificVar) IsDefined() bool {
return v.v.IsDefined()
}
func (v *TargetSpecificVar) String() string {
// TODO: If we add the info of |op| a test starts
// failing. Shouldn't we use this only for debugging?
return v.v.String()
// return v.v.String() + " (op=" + v.op + ")"
}
func (v *TargetSpecificVar) Eval(w io.Writer, ev *Evaluator) {
v.v.Eval(w, ev)
}
func (v *TargetSpecificVar) Serialize() SerializableVar {
return SerializableVar{
Type: v.op,
Children: []SerializableVar{v.v.Serialize()},
}
}
func (v *TargetSpecificVar) Dump(w io.Writer) {
dumpByte(w, valueTypeTSV)
dumpString(w, v.op)
v.v.Dump(w)
}
type SimpleVar struct {
value string
origin string
}
func (v *SimpleVar) Flavor() string { return "simple" }
func (v *SimpleVar) Origin() string { return v.origin }
func (v *SimpleVar) IsDefined() bool { return true }
func (v *SimpleVar) String() string { return v.value }
func (v *SimpleVar) Eval(w io.Writer, ev *Evaluator) {
io.WriteString(w, v.value)
}
func (v *SimpleVar) Serialize() SerializableVar {
return SerializableVar{
Type: "simple",
V: v.value,
Origin: v.origin,
}
}
func (v *SimpleVar) Dump(w io.Writer) {
dumpByte(w, valueTypeSimple)
dumpString(w, v.value)
dumpString(w, v.origin)
}
func (v *SimpleVar) Append(ev *Evaluator, s string) Var {
val, _, err := parseExpr([]byte(s), nil, false)
if err != nil {
panic(err)
}
abuf := newBuf()
io.WriteString(abuf, v.value)
writeByte(abuf, ' ')
val.Eval(abuf, ev)
v.value = abuf.String()
freeBuf(abuf)
return v
}
func (v *SimpleVar) AppendVar(ev *Evaluator, val Value) Var {
abuf := newBuf()
io.WriteString(abuf, v.value)
writeByte(abuf, ' ')
val.Eval(abuf, ev)
v.value = abuf.String()
freeBuf(abuf)
return v
}
type AutomaticVar struct {
value []byte
}
func (v *AutomaticVar) Flavor() string { return "simple" }
func (v *AutomaticVar) Origin() string { return "automatic" }
func (v *AutomaticVar) IsDefined() bool { return true }
func (v *AutomaticVar) String() string { return string(v.value) }
func (v *AutomaticVar) Eval(w io.Writer, ev *Evaluator) {
w.Write(v.value)
}
func (v *AutomaticVar) Serialize() SerializableVar {
panic(fmt.Sprintf("cannnot serialize automatic var:%s", v.value))
}
func (v *AutomaticVar) Dump(w io.Writer) {
panic(fmt.Sprintf("cannnot dump automatic var:%s", v.value))
}
func (v *AutomaticVar) Append(ev *Evaluator, s string) Var {
val, _, err := parseExpr([]byte(s), nil, false)
if err != nil {
panic(err)
}
buf := bytes.NewBuffer(v.value)
buf.WriteByte(' ')
val.Eval(buf, ev)
v.value = buf.Bytes()
return v
}
func (v *AutomaticVar) AppendVar(ev *Evaluator, val Value) Var {
buf := bytes.NewBuffer(v.value)
buf.WriteByte(' ')
val.Eval(buf, ev)
v.value = buf.Bytes()
return v
}
type RecursiveVar struct {
expr Value
origin string
}
func (v *RecursiveVar) Flavor() string { return "recursive" }
func (v *RecursiveVar) Origin() string { return v.origin }
func (v *RecursiveVar) IsDefined() bool { return true }
func (v *RecursiveVar) String() string { return v.expr.String() }
func (v *RecursiveVar) Eval(w io.Writer, ev *Evaluator) {
v.expr.Eval(w, ev)
}
func (v *RecursiveVar) Serialize() SerializableVar {
return SerializableVar{
Type: "recursive",
Children: []SerializableVar{v.expr.Serialize()},
Origin: v.origin,
}
}
func (v *RecursiveVar) Dump(w io.Writer) {
dumpByte(w, valueTypeRecursive)
v.expr.Dump(w)
dumpString(w, v.origin)
}
func (v *RecursiveVar) Append(_ *Evaluator, s string) Var {
var expr Expr
if e, ok := v.expr.(Expr); ok {
expr = append(e, literal(" "))
} else {
expr = Expr{v.expr, literal(" ")}
}
sv, _, err := parseExpr([]byte(s), nil, true)
if err != nil {
panic(err)
}
if aexpr, ok := sv.(Expr); ok {
expr = append(expr, aexpr...)
} else {
expr = append(expr, sv)
}
v.expr = expr
return v
}
func (v *RecursiveVar) AppendVar(ev *Evaluator, val Value) Var {
var buf bytes.Buffer
buf.WriteString(v.expr.String())
buf.WriteByte(' ')
buf.WriteString(val.String())
e, _, err := parseExpr(buf.Bytes(), nil, true)
if err != nil {
panic(err)
}
v.expr = e
return v
}
type UndefinedVar struct{}
func (UndefinedVar) Flavor() string { return "undefined" }
func (UndefinedVar) Origin() string { return "undefined" }
func (UndefinedVar) IsDefined() bool { return false }
func (UndefinedVar) String() string { return "" }
func (UndefinedVar) Eval(_ io.Writer, _ *Evaluator) {
}
func (UndefinedVar) Serialize() SerializableVar {
return SerializableVar{Type: "undefined"}
}
func (UndefinedVar) Dump(w io.Writer) {
dumpByte(w, valueTypeUndefined)
}
func (UndefinedVar) Append(*Evaluator, string) Var {
return UndefinedVar{}
}
func (UndefinedVar) AppendVar(_ *Evaluator, val Value) Var {
return UndefinedVar{}
}
type Vars map[string]Var
func (vt Vars) Lookup(name string) Var {
if v, ok := vt[name]; ok {
return v
}
return UndefinedVar{}
}
func (vt Vars) Assign(name string, v Var) {
switch v.Origin() {
case "override", "environment override":
default:
if ov, ok := vt[name]; ok {
if ov.Origin() == "command line" {
return
}
}
}
vt[name] = v
}
func NewVars(vt Vars) Vars {
r := make(Vars)
r.Merge(vt)
return r
}
func (vt Vars) Merge(vt2 Vars) {
for k, v := range vt2 {
vt[k] = v
}
}
// save saves value of the variable named name.
// calling returned value will restore to the old value at the time
// when save called.
func (vt Vars) save(name string) func() {
if v, ok := vt[name]; ok {
return func() {
vt[name] = v
}
}
return func() {
delete(vt, name)
}
}