Example #1
0
func (v *evalOutput) Eval(s ast.Scope, stack *ast.Stack) (interface{}, ast.Type, error) {
	// The expressions should all be on the stack in reverse
	// order. So pop them off, reverse their order, and concatenate.
	nodes := make([]*ast.LiteralNode, 0, len(v.Exprs))
	for range v.Exprs {
		nodes = append(nodes, stack.Pop().(*ast.LiteralNode))
	}

	// Special case the single list and map
	if len(nodes) == 1 {
		switch t := nodes[0].Typex; t {
		case ast.TypeList:
			fallthrough
		case ast.TypeMap:
			fallthrough
		case ast.TypeUnknown:
			return nodes[0].Value, t, nil
		}
	}

	// Otherwise concatenate the strings
	var buf bytes.Buffer
	for i := len(nodes) - 1; i >= 0; i-- {
		buf.WriteString(nodes[i].Value.(string))
	}

	return buf.String(), ast.TypeString, nil
}
Example #2
0
func (v *evalConditional) Eval(s ast.Scope, stack *ast.Stack) (interface{}, ast.Type, error) {
	// On the stack we have literal nodes representing the resulting values
	// of the condition, true and false expressions, but they are in reverse
	// order.
	falseLit := stack.Pop().(*ast.LiteralNode)
	trueLit := stack.Pop().(*ast.LiteralNode)
	condLit := stack.Pop().(*ast.LiteralNode)

	if condLit.Value.(bool) {
		return trueLit.Value, trueLit.Typex, nil
	} else {
		return falseLit.Value, trueLit.Typex, nil
	}
}
Example #3
0
func (v *evalConcat) Eval(s ast.Scope, stack *ast.Stack) (interface{}, ast.Type, error) {
	// The expressions should all be on the stack in reverse
	// order. So pop them off, reverse their order, and concatenate.
	nodes := make([]*ast.LiteralNode, 0, len(v.Exprs))
	for range v.Exprs {
		nodes = append(nodes, stack.Pop().(*ast.LiteralNode))
	}

	var buf bytes.Buffer
	for i := len(nodes) - 1; i >= 0; i-- {
		buf.WriteString(nodes[i].Value.(string))
	}

	return buf.String(), ast.TypeString, nil
}
Example #4
0
func (v *evalIndex) Eval(scope ast.Scope, stack *ast.Stack) (interface{}, ast.Type, error) {
	key := stack.Pop().(*ast.LiteralNode)
	target := stack.Pop().(*ast.LiteralNode)

	variableName := v.Index.Target.(*ast.VariableAccess).Name

	switch target.Typex {
	case ast.TypeList:
		return v.evalListIndex(variableName, target.Value, key.Value)
	case ast.TypeMap:
		return v.evalMapIndex(variableName, target.Value, key.Value)
	default:
		return nil, ast.TypeInvalid, fmt.Errorf(
			"target %q for indexing must be ast.TypeList or ast.TypeMap, is %s",
			variableName, target.Typex)
	}
}
Example #5
0
func (v *evalCall) Eval(s ast.Scope, stack *ast.Stack) (interface{}, ast.Type, error) {
	// Look up the function in the map
	function, ok := s.LookupFunc(v.Func)
	if !ok {
		return nil, ast.TypeInvalid, fmt.Errorf(
			"unknown function called: %s", v.Func)
	}

	// The arguments are on the stack in reverse order, so pop them off.
	args := make([]interface{}, len(v.Args))
	for i, _ := range v.Args {
		node := stack.Pop().(*ast.LiteralNode)
		args[len(v.Args)-1-i] = node.Value
	}

	// Call the function
	result, err := function.Callback(args)
	if err != nil {
		return nil, ast.TypeInvalid, fmt.Errorf("%s: %s", v.Func, err)
	}

	return result, function.ReturnType, nil
}