func (options *Options) FnWith(ctx interface{}) string {
	return options.evalBlock(ctx, nil, nil)
}
FnWith evaluates block with given context.
package raymond
import (
	"fmt"
	"log"
	"reflect"
	"sync"
)
type Options struct {
	eval *evalVisitor
	params []interface{}
	hash   map[string]interface{}
}
var helpers = make(map[string]reflect.Value)
var helpersMutex sync.RWMutex
func init() {
	RegisterHelper("if", ifHelper)
	RegisterHelper("unless", unlessHelper)
	RegisterHelper("with", withHelper)
	RegisterHelper("each", eachHelper)
	RegisterHelper("log", logHelper)
	RegisterHelper("lookup", lookupHelper)
	RegisterHelper("equal", equalHelper)
}
func RegisterHelper(name string, helper interface{}) {
	helpersMutex.Lock()
	defer helpersMutex.Unlock()
	if helpers[name] != zero {
		panic(fmt.Errorf("Helper already registered: %s", name))
	}
	val := reflect.ValueOf(helper)
	ensureValidHelper(name, val)
	helpers[name] = val
}
func RegisterHelpers(helpers map[string]interface{}) {
	for name, helper := range helpers {
		RegisterHelper(name, helper)
	}
}
func RemoveHelper(name string) {
	helpersMutex.Lock()
	defer helpersMutex.Unlock()
	delete(helpers, name)
}
func RemoveAllHelpers() {
	helpersMutex.Lock()
	defer helpersMutex.Unlock()
	helpers = make(map[string]reflect.Value)
}
func ensureValidHelper(name string, funcValue reflect.Value) {
	if funcValue.Kind() != reflect.Func {
		panic(fmt.Errorf("Helper must be a function: %s", name))
	}
	funcType := funcValue.Type()
	if funcType.NumOut() != 1 {
		panic(fmt.Errorf("Helper function must return a string or a SafeString: %s", name))
	}
}
func findHelper(name string) reflect.Value {
	helpersMutex.RLock()
	defer helpersMutex.RUnlock()
	return helpers[name]
}
func newOptions(eval *evalVisitor, params []interface{}, hash map[string]interface{}) *Options {
	return &Options{
		eval:   eval,
		params: params,
		hash:   hash,
	}
}
func newEmptyOptions(eval *evalVisitor) *Options {
	return &Options{
		eval: eval,
		hash: make(map[string]interface{}),
	}
}
func (options *Options) Value(name string) interface{} {
	value := options.eval.evalField(options.eval.curCtx(), name, false)
	if !value.IsValid() {
		return nil
	}
	return value.Interface()
}
func (options *Options) ValueStr(name string) string {
	return Str(options.Value(name))
}
func (options *Options) Ctx() interface{} {
	return options.eval.curCtx().Interface()
}
func (options *Options) HashProp(name string) interface{} {
	return options.hash[name]
}
func (options *Options) HashStr(name string) string {
	return Str(options.hash[name])
}
func (options *Options) Hash() map[string]interface{} {
	return options.hash
}
func (options *Options) Param(pos int) interface{} {
	if len(options.params) > pos {
		return options.params[pos]
	}
	return nil
}
func (options *Options) ParamStr(pos int) string {
	return Str(options.Param(pos))
}
func (options *Options) Params() []interface{} {
	return options.params
}
func (options *Options) Data(name string) interface{} {
	return options.eval.dataFrame.Get(name)
}
func (options *Options) DataStr(name string) string {
	return Str(options.eval.dataFrame.Get(name))
}
func (options *Options) DataFrame() *DataFrame {
	return options.eval.dataFrame
}
func (options *Options) NewDataFrame() *DataFrame {
	return options.eval.dataFrame.Copy()
}
func (options *Options) newIterDataFrame(length int, i int, key interface{}) *DataFrame {
	return options.eval.dataFrame.newIterDataFrame(length, i, key)
}
func (options *Options) evalBlock(ctx interface{}, data *DataFrame, key interface{}) string {
	result := ""
	if block := options.eval.curBlock(); (block != nil) && (block.Program != nil) {
		result = options.eval.evalProgram(block.Program, ctx, data, key)
	}
	return result
}
func (options *Options) Fn() string {
	return options.evalBlock(nil, nil, nil)
}
func (options *Options) FnCtxData(ctx interface{}, data *DataFrame) string {
	return options.evalBlock(ctx, data, nil)
}