// evalCtxPathExpression evaluates a context path expression func (v *evalVisitor) evalCtxPathExpression(node *ast.PathExpression, exprRoot bool) interface{} { v.at(node) if node.IsDataRoot() { // `@root` - remove the first part parts := node.Parts[1:len(node.Parts)] result, _ := v.evalCtxPath(v.rootCtx(), parts, exprRoot) return result } return v.evalDepthPath(node.Depth, node.Parts, exprRoot) }
// evalPathExpression evaluates a path expression func (v *evalVisitor) evalPathExpression(node *ast.PathExpression, exprRoot bool) interface{} { var result interface{} if name, value := v.findBlockParam(node); value != nil { // block parameter value // We push a new context so we can evaluate the path expression (note: this may be a bad idea). // // Example: // {{#foo as |bar|}} // {{bar.baz}} // {{/foo}} // // With data: // {"foo": {"baz": "bat"}} newCtx := map[string]interface{}{name: value} v.pushCtx(reflect.ValueOf(newCtx)) result = v.evalCtxPathExpression(node, exprRoot) v.popCtx() } else { ctxTried := false if node.IsDataRoot() { // context path result = v.evalCtxPathExpression(node, exprRoot) ctxTried = true } if (result == nil) && node.Data { // if it is @root, then we tried to evaluate with root context but nothing was found // so let's try with private data // private data result = v.evalDataPathExpression(node, exprRoot) } if (result == nil) && !ctxTried { // context path result = v.evalCtxPathExpression(node, exprRoot) } } return result }