eval.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005
  1. package raymond
  2. import (
  3. "bytes"
  4. "fmt"
  5. "reflect"
  6. "strconv"
  7. "strings"
  8. "github.com/aymerick/raymond/ast"
  9. )
  10. var (
  11. // @note borrowed from https://github.com/golang/go/tree/master/src/text/template/exec.go
  12. errorType = reflect.TypeOf((*error)(nil)).Elem()
  13. fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
  14. zero reflect.Value
  15. )
  16. // evalVisitor evaluates a handlebars template with context
  17. type evalVisitor struct {
  18. tpl *Template
  19. // contexts stack
  20. ctx []reflect.Value
  21. // current data frame (chained with parent)
  22. dataFrame *DataFrame
  23. // block parameters stack
  24. blockParams []map[string]interface{}
  25. // block statements stack
  26. blocks []*ast.BlockStatement
  27. // expressions stack
  28. exprs []*ast.Expression
  29. // memoize expressions that were function calls
  30. exprFunc map[*ast.Expression]bool
  31. // used for info on panic
  32. curNode ast.Node
  33. }
  34. // NewEvalVisitor instanciate a new evaluation visitor with given context and initial private data frame
  35. //
  36. // If privData is nil, then a default data frame is created
  37. func newEvalVisitor(tpl *Template, ctx interface{}, privData *DataFrame) *evalVisitor {
  38. frame := privData
  39. if frame == nil {
  40. frame = NewDataFrame()
  41. }
  42. return &evalVisitor{
  43. tpl: tpl,
  44. ctx: []reflect.Value{reflect.ValueOf(ctx)},
  45. dataFrame: frame,
  46. exprFunc: make(map[*ast.Expression]bool),
  47. }
  48. }
  49. // at sets current node
  50. func (v *evalVisitor) at(node ast.Node) {
  51. v.curNode = node
  52. }
  53. //
  54. // Contexts stack
  55. //
  56. // pushCtx pushes new context to the stack
  57. func (v *evalVisitor) pushCtx(ctx reflect.Value) {
  58. v.ctx = append(v.ctx, ctx)
  59. }
  60. // popCtx pops last context from stack
  61. func (v *evalVisitor) popCtx() reflect.Value {
  62. if len(v.ctx) == 0 {
  63. return zero
  64. }
  65. var result reflect.Value
  66. result, v.ctx = v.ctx[len(v.ctx)-1], v.ctx[:len(v.ctx)-1]
  67. return result
  68. }
  69. // rootCtx returns root context
  70. func (v *evalVisitor) rootCtx() reflect.Value {
  71. return v.ctx[0]
  72. }
  73. // curCtx returns current context
  74. func (v *evalVisitor) curCtx() reflect.Value {
  75. return v.ancestorCtx(0)
  76. }
  77. // ancestorCtx returns ancestor context
  78. func (v *evalVisitor) ancestorCtx(depth int) reflect.Value {
  79. index := len(v.ctx) - 1 - depth
  80. if index < 0 {
  81. return zero
  82. }
  83. return v.ctx[index]
  84. }
  85. //
  86. // Private data frame
  87. //
  88. // setDataFrame sets new data frame
  89. func (v *evalVisitor) setDataFrame(frame *DataFrame) {
  90. v.dataFrame = frame
  91. }
  92. // popDataFrame sets back parent data frame
  93. func (v *evalVisitor) popDataFrame() {
  94. v.dataFrame = v.dataFrame.parent
  95. }
  96. //
  97. // Block Parameters stack
  98. //
  99. // pushBlockParams pushes new block params to the stack
  100. func (v *evalVisitor) pushBlockParams(params map[string]interface{}) {
  101. v.blockParams = append(v.blockParams, params)
  102. }
  103. // popBlockParams pops last block params from stack
  104. func (v *evalVisitor) popBlockParams() map[string]interface{} {
  105. var result map[string]interface{}
  106. if len(v.blockParams) == 0 {
  107. return result
  108. }
  109. result, v.blockParams = v.blockParams[len(v.blockParams)-1], v.blockParams[:len(v.blockParams)-1]
  110. return result
  111. }
  112. // blockParam iterates on stack to find given block parameter, and returns its value or nil if not founc
  113. func (v *evalVisitor) blockParam(name string) interface{} {
  114. for i := len(v.blockParams) - 1; i >= 0; i-- {
  115. for k, v := range v.blockParams[i] {
  116. if name == k {
  117. return v
  118. }
  119. }
  120. }
  121. return nil
  122. }
  123. //
  124. // Blocks stack
  125. //
  126. // pushBlock pushes new block statement to stack
  127. func (v *evalVisitor) pushBlock(block *ast.BlockStatement) {
  128. v.blocks = append(v.blocks, block)
  129. }
  130. // popBlock pops last block statement from stack
  131. func (v *evalVisitor) popBlock() *ast.BlockStatement {
  132. if len(v.blocks) == 0 {
  133. return nil
  134. }
  135. var result *ast.BlockStatement
  136. result, v.blocks = v.blocks[len(v.blocks)-1], v.blocks[:len(v.blocks)-1]
  137. return result
  138. }
  139. // curBlock returns current block statement
  140. func (v *evalVisitor) curBlock() *ast.BlockStatement {
  141. if len(v.blocks) == 0 {
  142. return nil
  143. }
  144. return v.blocks[len(v.blocks)-1]
  145. }
  146. //
  147. // Expressions stack
  148. //
  149. // pushExpr pushes new expression to stack
  150. func (v *evalVisitor) pushExpr(expression *ast.Expression) {
  151. v.exprs = append(v.exprs, expression)
  152. }
  153. // popExpr pops last expression from stack
  154. func (v *evalVisitor) popExpr() *ast.Expression {
  155. if len(v.exprs) == 0 {
  156. return nil
  157. }
  158. var result *ast.Expression
  159. result, v.exprs = v.exprs[len(v.exprs)-1], v.exprs[:len(v.exprs)-1]
  160. return result
  161. }
  162. // curExpr returns current expression
  163. func (v *evalVisitor) curExpr() *ast.Expression {
  164. if len(v.exprs) == 0 {
  165. return nil
  166. }
  167. return v.exprs[len(v.exprs)-1]
  168. }
  169. //
  170. // Error functions
  171. //
  172. // errPanic panics
  173. func (v *evalVisitor) errPanic(err error) {
  174. panic(fmt.Errorf("Evaluation error: %s\nCurrent node:\n\t%s", err, v.curNode))
  175. }
  176. // errorf panics with a custom message
  177. func (v *evalVisitor) errorf(format string, args ...interface{}) {
  178. v.errPanic(fmt.Errorf(format, args...))
  179. }
  180. //
  181. // Evaluation
  182. //
  183. // evalProgram eEvaluates program with given context and returns string result
  184. func (v *evalVisitor) evalProgram(program *ast.Program, ctx interface{}, data *DataFrame, key interface{}) string {
  185. blockParams := make(map[string]interface{})
  186. // compute block params
  187. if len(program.BlockParams) > 0 {
  188. blockParams[program.BlockParams[0]] = ctx
  189. }
  190. if (len(program.BlockParams) > 1) && (key != nil) {
  191. blockParams[program.BlockParams[1]] = key
  192. }
  193. // push contexts
  194. if len(blockParams) > 0 {
  195. v.pushBlockParams(blockParams)
  196. }
  197. ctxVal := reflect.ValueOf(ctx)
  198. if ctxVal.IsValid() {
  199. v.pushCtx(ctxVal)
  200. }
  201. if data != nil {
  202. v.setDataFrame(data)
  203. }
  204. // evaluate program
  205. result, _ := program.Accept(v).(string)
  206. // pop contexts
  207. if data != nil {
  208. v.popDataFrame()
  209. }
  210. if ctxVal.IsValid() {
  211. v.popCtx()
  212. }
  213. if len(blockParams) > 0 {
  214. v.popBlockParams()
  215. }
  216. return result
  217. }
  218. // evalPath evaluates all path parts with given context
  219. func (v *evalVisitor) evalPath(ctx reflect.Value, parts []string, exprRoot bool) (reflect.Value, bool) {
  220. partResolved := false
  221. for i := 0; i < len(parts); i++ {
  222. part := parts[i]
  223. // "[foo bar]"" => "foo bar"
  224. if (len(part) >= 2) && (part[0] == '[') && (part[len(part)-1] == ']') {
  225. part = part[1 : len(part)-1]
  226. }
  227. ctx = v.evalField(ctx, part, exprRoot)
  228. if !ctx.IsValid() {
  229. break
  230. }
  231. // we resolved at least one part of path
  232. partResolved = true
  233. }
  234. return ctx, partResolved
  235. }
  236. // evalField evaluates field with given context
  237. func (v *evalVisitor) evalField(ctx reflect.Value, fieldName string, exprRoot bool) reflect.Value {
  238. result := zero
  239. ctx, _ = indirect(ctx)
  240. if !ctx.IsValid() {
  241. return result
  242. }
  243. // check if this is a method call
  244. result, isMeth := v.evalMethod(ctx, fieldName, exprRoot)
  245. if !isMeth {
  246. switch ctx.Kind() {
  247. case reflect.Struct:
  248. // example: firstName => FirstName
  249. expFieldName := strings.Title(fieldName)
  250. // check if struct have this field and that it is exported
  251. if tField, ok := ctx.Type().FieldByName(expFieldName); ok && (tField.PkgPath == "") {
  252. // struct field
  253. result = ctx.FieldByIndex(tField.Index)
  254. break
  255. }
  256. // attempts to find template variable name as a struct tag
  257. result = v.evalStructTag(ctx, fieldName)
  258. case reflect.Map:
  259. nameVal := reflect.ValueOf(fieldName)
  260. if nameVal.Type().AssignableTo(ctx.Type().Key()) {
  261. // map key
  262. result = ctx.MapIndex(nameVal)
  263. }
  264. case reflect.Array, reflect.Slice:
  265. if i, err := strconv.Atoi(fieldName); (err == nil) && (i < ctx.Len()) {
  266. result = ctx.Index(i)
  267. }
  268. }
  269. }
  270. // check if result is a function
  271. result, _ = indirect(result)
  272. if result.Kind() == reflect.Func {
  273. result = v.evalFieldFunc(fieldName, result, exprRoot)
  274. }
  275. return result
  276. }
  277. // evalFieldFunc tries to evaluate given method name, and a boolean to indicate if this was a method call
  278. func (v *evalVisitor) evalMethod(ctx reflect.Value, name string, exprRoot bool) (reflect.Value, bool) {
  279. if ctx.Kind() != reflect.Interface && ctx.CanAddr() {
  280. ctx = ctx.Addr()
  281. }
  282. method := ctx.MethodByName(name)
  283. if !method.IsValid() {
  284. // example: subject() => Subject()
  285. method = ctx.MethodByName(strings.Title(name))
  286. }
  287. if !method.IsValid() {
  288. return zero, false
  289. }
  290. return v.evalFieldFunc(name, method, exprRoot), true
  291. }
  292. // evalFieldFunc evaluates given function
  293. func (v *evalVisitor) evalFieldFunc(name string, funcVal reflect.Value, exprRoot bool) reflect.Value {
  294. ensureValidHelper(name, funcVal)
  295. var options *Options
  296. if exprRoot {
  297. // create function arg with all params/hash
  298. expr := v.curExpr()
  299. options = v.helperOptions(expr)
  300. // ok, that expression was a function call
  301. v.exprFunc[expr] = true
  302. } else {
  303. // we are not at root of expression, so we are a parameter... and we don't like
  304. // infinite loops caused by trying to parse ourself forever
  305. options = newEmptyOptions(v)
  306. }
  307. return v.callFunc(name, funcVal, options)
  308. }
  309. // evalStructTag checks for the existence of a struct tag containing the
  310. // name of the variable in the template. This allows for a template variable to
  311. // be separated from the field in the struct.
  312. func (v *evalVisitor) evalStructTag(ctx reflect.Value, name string) reflect.Value {
  313. val := reflect.ValueOf(ctx.Interface())
  314. for i := 0; i < val.NumField(); i++ {
  315. field := val.Type().Field(i)
  316. tag := field.Tag.Get("handlebars")
  317. if tag == name {
  318. return val.Field(i)
  319. }
  320. }
  321. return zero
  322. }
  323. // findBlockParam returns node's block parameter
  324. func (v *evalVisitor) findBlockParam(node *ast.PathExpression) (string, interface{}) {
  325. if len(node.Parts) > 0 {
  326. name := node.Parts[0]
  327. if value := v.blockParam(name); value != nil {
  328. return name, value
  329. }
  330. }
  331. return "", nil
  332. }
  333. // evalPathExpression evaluates a path expression
  334. func (v *evalVisitor) evalPathExpression(node *ast.PathExpression, exprRoot bool) interface{} {
  335. var result interface{}
  336. if name, value := v.findBlockParam(node); value != nil {
  337. // block parameter value
  338. // We push a new context so we can evaluate the path expression (note: this may be a bad idea).
  339. //
  340. // Example:
  341. // {{#foo as |bar|}}
  342. // {{bar.baz}}
  343. // {{/foo}}
  344. //
  345. // With data:
  346. // {"foo": {"baz": "bat"}}
  347. newCtx := map[string]interface{}{name: value}
  348. v.pushCtx(reflect.ValueOf(newCtx))
  349. result = v.evalCtxPathExpression(node, exprRoot)
  350. v.popCtx()
  351. } else {
  352. ctxTried := false
  353. if node.IsDataRoot() {
  354. // context path
  355. result = v.evalCtxPathExpression(node, exprRoot)
  356. ctxTried = true
  357. }
  358. if (result == nil) && node.Data {
  359. // if it is @root, then we tried to evaluate with root context but nothing was found
  360. // so let's try with private data
  361. // private data
  362. result = v.evalDataPathExpression(node, exprRoot)
  363. }
  364. if (result == nil) && !ctxTried {
  365. // context path
  366. result = v.evalCtxPathExpression(node, exprRoot)
  367. }
  368. }
  369. return result
  370. }
  371. // evalDataPathExpression evaluates a private data path expression
  372. func (v *evalVisitor) evalDataPathExpression(node *ast.PathExpression, exprRoot bool) interface{} {
  373. // find data frame
  374. frame := v.dataFrame
  375. for i := node.Depth; i > 0; i-- {
  376. if frame.parent == nil {
  377. return nil
  378. }
  379. frame = frame.parent
  380. }
  381. // resolve data
  382. // @note Can be changed to v.evalCtx() as context can't be an array
  383. result, _ := v.evalCtxPath(reflect.ValueOf(frame.data), node.Parts, exprRoot)
  384. return result
  385. }
  386. // evalCtxPathExpression evaluates a context path expression
  387. func (v *evalVisitor) evalCtxPathExpression(node *ast.PathExpression, exprRoot bool) interface{} {
  388. v.at(node)
  389. if node.IsDataRoot() {
  390. // `@root` - remove the first part
  391. parts := node.Parts[1:len(node.Parts)]
  392. result, _ := v.evalCtxPath(v.rootCtx(), parts, exprRoot)
  393. return result
  394. }
  395. return v.evalDepthPath(node.Depth, node.Parts, exprRoot)
  396. }
  397. // evalDepthPath iterates on contexts, starting at given depth, until there is one that resolve given path parts
  398. func (v *evalVisitor) evalDepthPath(depth int, parts []string, exprRoot bool) interface{} {
  399. var result interface{}
  400. partResolved := false
  401. ctx := v.ancestorCtx(depth)
  402. for (result == nil) && ctx.IsValid() && (depth <= len(v.ctx) && !partResolved) {
  403. // try with context
  404. result, partResolved = v.evalCtxPath(ctx, parts, exprRoot)
  405. // As soon as we find the first part of a path, we must not try to resolve with parent context if result is finally `nil`
  406. // Reference: "Dotted Names - Context Precedence" mustache test
  407. if !partResolved && (result == nil) {
  408. // try with previous context
  409. depth++
  410. ctx = v.ancestorCtx(depth)
  411. }
  412. }
  413. return result
  414. }
  415. // evalCtxPath evaluates path with given context
  416. func (v *evalVisitor) evalCtxPath(ctx reflect.Value, parts []string, exprRoot bool) (interface{}, bool) {
  417. var result interface{}
  418. partResolved := false
  419. switch ctx.Kind() {
  420. case reflect.Array, reflect.Slice:
  421. // Array context
  422. var results []interface{}
  423. for i := 0; i < ctx.Len(); i++ {
  424. value, _ := v.evalPath(ctx.Index(i), parts, exprRoot)
  425. if value.IsValid() {
  426. results = append(results, value.Interface())
  427. }
  428. }
  429. result = results
  430. default:
  431. // NOT array context
  432. var value reflect.Value
  433. value, partResolved = v.evalPath(ctx, parts, exprRoot)
  434. if value.IsValid() {
  435. result = value.Interface()
  436. }
  437. }
  438. return result, partResolved
  439. }
  440. //
  441. // Helpers
  442. //
  443. // isHelperCall returns true if given expression is a helper call
  444. func (v *evalVisitor) isHelperCall(node *ast.Expression) bool {
  445. if helperName := node.HelperName(); helperName != "" {
  446. return v.findHelper(helperName) != zero
  447. }
  448. return false
  449. }
  450. // findHelper finds given helper
  451. func (v *evalVisitor) findHelper(name string) reflect.Value {
  452. // check template helpers
  453. if h := v.tpl.findHelper(name); h != zero {
  454. return h
  455. }
  456. // check global helpers
  457. return findHelper(name)
  458. }
  459. // callFunc calls function with given options
  460. func (v *evalVisitor) callFunc(name string, funcVal reflect.Value, options *Options) reflect.Value {
  461. params := options.Params()
  462. funcType := funcVal.Type()
  463. // @todo Is there a better way to do that ?
  464. strType := reflect.TypeOf("")
  465. boolType := reflect.TypeOf(true)
  466. // check parameters number
  467. addOptions := false
  468. numIn := funcType.NumIn()
  469. if numIn == len(params)+1 {
  470. lastArgType := funcType.In(numIn - 1)
  471. if reflect.TypeOf(options).AssignableTo(lastArgType) {
  472. addOptions = true
  473. }
  474. }
  475. if !addOptions && (len(params) != numIn) {
  476. v.errorf("Helper '%s' called with wrong number of arguments, needed %d but got %d", name, numIn, len(params))
  477. }
  478. // check and collect arguments
  479. args := make([]reflect.Value, numIn)
  480. for i, param := range params {
  481. arg := reflect.ValueOf(param)
  482. argType := funcType.In(i)
  483. if !arg.IsValid() {
  484. if canBeNil(argType) {
  485. arg = reflect.Zero(argType)
  486. } else if argType.Kind() == reflect.String {
  487. arg = reflect.ValueOf("")
  488. } else {
  489. // @todo Maybe we can panic on that
  490. return reflect.Zero(strType)
  491. }
  492. }
  493. if !arg.Type().AssignableTo(argType) {
  494. if strType.AssignableTo(argType) {
  495. // convert parameter to string
  496. arg = reflect.ValueOf(strValue(arg))
  497. } else if boolType.AssignableTo(argType) {
  498. // convert parameter to bool
  499. val, _ := isTrueValue(arg)
  500. arg = reflect.ValueOf(val)
  501. } else {
  502. v.errorf("Helper %s called with argument %d with type %s but it should be %s", name, i, arg.Type(), argType)
  503. }
  504. }
  505. args[i] = arg
  506. }
  507. if addOptions {
  508. args[numIn-1] = reflect.ValueOf(options)
  509. }
  510. result := funcVal.Call(args)
  511. return result[0]
  512. }
  513. // callHelper invoqs helper function for given expression node
  514. func (v *evalVisitor) callHelper(name string, helper reflect.Value, node *ast.Expression) interface{} {
  515. result := v.callFunc(name, helper, v.helperOptions(node))
  516. if !result.IsValid() {
  517. return nil
  518. }
  519. // @todo We maybe want to ensure here that helper returned a string or a SafeString
  520. return result.Interface()
  521. }
  522. // helperOptions computes helper options argument from an expression
  523. func (v *evalVisitor) helperOptions(node *ast.Expression) *Options {
  524. var params []interface{}
  525. var hash map[string]interface{}
  526. for _, paramNode := range node.Params {
  527. param := paramNode.Accept(v)
  528. params = append(params, param)
  529. }
  530. if node.Hash != nil {
  531. hash, _ = node.Hash.Accept(v).(map[string]interface{})
  532. }
  533. return newOptions(v, params, hash)
  534. }
  535. //
  536. // Partials
  537. //
  538. // findPartial finds given partial
  539. func (v *evalVisitor) findPartial(name string) *partial {
  540. // check template partials
  541. if p := v.tpl.findPartial(name); p != nil {
  542. return p
  543. }
  544. // check global partials
  545. return findPartial(name)
  546. }
  547. // partialContext computes partial context
  548. func (v *evalVisitor) partialContext(node *ast.PartialStatement) reflect.Value {
  549. if nb := len(node.Params); nb > 1 {
  550. v.errorf("Unsupported number of partial arguments: %d", nb)
  551. }
  552. if (len(node.Params) > 0) && (node.Hash != nil) {
  553. v.errorf("Passing both context and named parameters to a partial is not allowed")
  554. }
  555. if len(node.Params) == 1 {
  556. return reflect.ValueOf(node.Params[0].Accept(v))
  557. }
  558. if node.Hash != nil {
  559. hash, _ := node.Hash.Accept(v).(map[string]interface{})
  560. return reflect.ValueOf(hash)
  561. }
  562. return zero
  563. }
  564. // evalPartial evaluates a partial
  565. func (v *evalVisitor) evalPartial(p *partial, node *ast.PartialStatement) string {
  566. // get partial template
  567. partialTpl, err := p.template()
  568. if err != nil {
  569. v.errPanic(err)
  570. }
  571. // push partial context
  572. ctx := v.partialContext(node)
  573. if ctx.IsValid() {
  574. v.pushCtx(ctx)
  575. }
  576. // evaluate partial template
  577. result, _ := partialTpl.program.Accept(v).(string)
  578. // ident partial
  579. result = indentLines(result, node.Indent)
  580. if ctx.IsValid() {
  581. v.popCtx()
  582. }
  583. return result
  584. }
  585. // indentLines indents all lines of given string
  586. func indentLines(str string, indent string) string {
  587. if indent == "" {
  588. return str
  589. }
  590. var indented []string
  591. lines := strings.Split(str, "\n")
  592. for i, line := range lines {
  593. if (i == (len(lines) - 1)) && (line == "") {
  594. // input string ends with a new line
  595. indented = append(indented, line)
  596. } else {
  597. indented = append(indented, indent+line)
  598. }
  599. }
  600. return strings.Join(indented, "\n")
  601. }
  602. //
  603. // Functions
  604. //
  605. // wasFuncCall returns true if given expression was a function call
  606. func (v *evalVisitor) wasFuncCall(node *ast.Expression) bool {
  607. // check if expression was tagged as a function call
  608. return v.exprFunc[node]
  609. }
  610. //
  611. // Visitor interface
  612. //
  613. // Statements
  614. // VisitProgram implements corresponding Visitor interface method
  615. func (v *evalVisitor) VisitProgram(node *ast.Program) interface{} {
  616. v.at(node)
  617. buf := new(bytes.Buffer)
  618. for _, n := range node.Body {
  619. if str := Str(n.Accept(v)); str != "" {
  620. if _, err := buf.Write([]byte(str)); err != nil {
  621. v.errPanic(err)
  622. }
  623. }
  624. }
  625. return buf.String()
  626. }
  627. // VisitMustache implements corresponding Visitor interface method
  628. func (v *evalVisitor) VisitMustache(node *ast.MustacheStatement) interface{} {
  629. v.at(node)
  630. // evaluate expression
  631. expr := node.Expression.Accept(v)
  632. // check if this is a safe string
  633. isSafe := isSafeString(expr)
  634. // get string value
  635. str := Str(expr)
  636. if !isSafe && !node.Unescaped {
  637. // escape html
  638. str = Escape(str)
  639. }
  640. return str
  641. }
  642. // VisitBlock implements corresponding Visitor interface method
  643. func (v *evalVisitor) VisitBlock(node *ast.BlockStatement) interface{} {
  644. v.at(node)
  645. v.pushBlock(node)
  646. var result interface{}
  647. // evaluate expression
  648. expr := node.Expression.Accept(v)
  649. if v.isHelperCall(node.Expression) || v.wasFuncCall(node.Expression) {
  650. // it is the responsibility of the helper/function to evaluate block
  651. result = expr
  652. } else {
  653. val := reflect.ValueOf(expr)
  654. truth, _ := isTrueValue(val)
  655. if truth {
  656. if node.Program != nil {
  657. switch val.Kind() {
  658. case reflect.Array, reflect.Slice:
  659. concat := ""
  660. // Array context
  661. for i := 0; i < val.Len(); i++ {
  662. // Computes new private data frame
  663. frame := v.dataFrame.newIterDataFrame(val.Len(), i, nil)
  664. // Evaluate program
  665. concat += v.evalProgram(node.Program, val.Index(i).Interface(), frame, i)
  666. }
  667. result = concat
  668. default:
  669. // NOT array
  670. result = v.evalProgram(node.Program, expr, nil, nil)
  671. }
  672. }
  673. } else if node.Inverse != nil {
  674. result, _ = node.Inverse.Accept(v).(string)
  675. }
  676. }
  677. v.popBlock()
  678. return result
  679. }
  680. // VisitPartial implements corresponding Visitor interface method
  681. func (v *evalVisitor) VisitPartial(node *ast.PartialStatement) interface{} {
  682. v.at(node)
  683. // partialName: helperName | sexpr
  684. name, ok := ast.HelperNameStr(node.Name)
  685. if !ok {
  686. if subExpr, ok := node.Name.(*ast.SubExpression); ok {
  687. name, _ = subExpr.Accept(v).(string)
  688. }
  689. }
  690. if name == "" {
  691. v.errorf("Unexpected partial name: %q", node.Name)
  692. }
  693. partial := v.findPartial(name)
  694. if partial == nil {
  695. v.errorf("Partial not found: %s", name)
  696. }
  697. return v.evalPartial(partial, node)
  698. }
  699. // VisitContent implements corresponding Visitor interface method
  700. func (v *evalVisitor) VisitContent(node *ast.ContentStatement) interface{} {
  701. v.at(node)
  702. // write content as is
  703. return node.Value
  704. }
  705. // VisitComment implements corresponding Visitor interface method
  706. func (v *evalVisitor) VisitComment(node *ast.CommentStatement) interface{} {
  707. v.at(node)
  708. // ignore comments
  709. return ""
  710. }
  711. // Expressions
  712. // VisitExpression implements corresponding Visitor interface method
  713. func (v *evalVisitor) VisitExpression(node *ast.Expression) interface{} {
  714. v.at(node)
  715. var result interface{}
  716. done := false
  717. v.pushExpr(node)
  718. // helper call
  719. if helperName := node.HelperName(); helperName != "" {
  720. if helper := v.findHelper(helperName); helper != zero {
  721. result = v.callHelper(helperName, helper, node)
  722. done = true
  723. }
  724. }
  725. if !done {
  726. // literal
  727. if literal, ok := node.LiteralStr(); ok {
  728. if val := v.evalField(v.curCtx(), literal, true); val.IsValid() {
  729. result = val.Interface()
  730. done = true
  731. }
  732. }
  733. }
  734. if !done {
  735. // field path
  736. if path := node.FieldPath(); path != nil {
  737. // @todo Find a cleaner way ! Don't break the pattern !
  738. // this is an exception to visitor pattern, because we need to pass the info
  739. // that this path is at root of current expression
  740. if val := v.evalPathExpression(path, true); val != nil {
  741. result = val
  742. }
  743. }
  744. }
  745. v.popExpr()
  746. return result
  747. }
  748. // VisitSubExpression implements corresponding Visitor interface method
  749. func (v *evalVisitor) VisitSubExpression(node *ast.SubExpression) interface{} {
  750. v.at(node)
  751. return node.Expression.Accept(v)
  752. }
  753. // VisitPath implements corresponding Visitor interface method
  754. func (v *evalVisitor) VisitPath(node *ast.PathExpression) interface{} {
  755. return v.evalPathExpression(node, false)
  756. }
  757. // Literals
  758. // VisitString implements corresponding Visitor interface method
  759. func (v *evalVisitor) VisitString(node *ast.StringLiteral) interface{} {
  760. v.at(node)
  761. return node.Value
  762. }
  763. // VisitBoolean implements corresponding Visitor interface method
  764. func (v *evalVisitor) VisitBoolean(node *ast.BooleanLiteral) interface{} {
  765. v.at(node)
  766. return node.Value
  767. }
  768. // VisitNumber implements corresponding Visitor interface method
  769. func (v *evalVisitor) VisitNumber(node *ast.NumberLiteral) interface{} {
  770. v.at(node)
  771. return node.Number()
  772. }
  773. // Miscellaneous
  774. // VisitHash implements corresponding Visitor interface method
  775. func (v *evalVisitor) VisitHash(node *ast.Hash) interface{} {
  776. v.at(node)
  777. result := make(map[string]interface{})
  778. for _, pair := range node.Pairs {
  779. if value := pair.Accept(v); value != nil {
  780. result[pair.Key] = value
  781. }
  782. }
  783. return result
  784. }
  785. // VisitHashPair implements corresponding Visitor interface method
  786. func (v *evalVisitor) VisitHashPair(node *ast.HashPair) interface{} {
  787. v.at(node)
  788. return node.Val.Accept(v)
  789. }