2017-07-14 02:18:23 +02:00
// Package expressions parses and evaluates the expression language.
2017-07-10 15:38:46 +02:00
//
// This is the language that is used inside Liquid object and tags; e.g. "a.b[c]" in {{ a.b[c] }}, and "pages = site.pages | reverse" in {% assign pages = site.pages | reverse %}.
2017-07-14 02:18:23 +02:00
package expressions
2017-06-26 14:23:50 +02:00
2017-06-27 23:29:50 +02:00
import (
2017-07-05 17:35:07 +02:00
"github.com/osteele/liquid/evaluator"
2017-06-27 23:29:50 +02:00
)
2017-06-27 22:11:32 +02:00
2017-07-09 16:36:32 +02:00
// TODO Expression and Closure are confusing names.
// An Expression is a compiled expression.
2017-06-28 17:24:24 +02:00
type Expression interface {
// Evaluate evaluates an expression in a context.
Evaluate ( ctx Context ) ( interface { } , error )
}
2017-07-09 16:36:32 +02:00
// A Closure is an expression within a lexical environment.
// A closure may refer to variables that are not defined in the
// environment. (Therefore it's not a technically a closure.)
2017-06-28 17:24:24 +02:00
type Closure interface {
2017-07-09 16:36:32 +02:00
// Bind creates a new closure with a new binding.
2017-06-28 17:24:24 +02:00
Bind ( name string , value interface { } ) Closure
Evaluate ( ) ( interface { } , error )
}
type closure struct {
expr Expression
context Context
}
func ( c closure ) Bind ( name string , value interface { } ) Closure {
2017-07-09 16:36:32 +02:00
ctx := c . context . Clone ( )
ctx . Set ( name , value )
return closure { c . expr , ctx }
2017-06-28 17:24:24 +02:00
}
func ( c closure ) Evaluate ( ) ( interface { } , error ) {
return c . expr . Evaluate ( c . context )
}
type expression struct {
evaluator func ( Context ) interface { }
}
2017-06-27 22:11:32 +02:00
func ( e expression ) Evaluate ( ctx Context ) ( out interface { } , err error ) {
defer func ( ) {
if r := recover ( ) ; r != nil {
switch e := r . ( type ) {
2017-07-06 01:09:59 +02:00
case evaluator . TypeError :
2017-06-27 23:29:50 +02:00
err = e
2017-06-27 22:53:34 +02:00
case InterpreterError :
err = e
2017-06-29 13:54:31 +02:00
case UndefinedFilter :
2017-06-27 22:11:32 +02:00
err = e
default :
panic ( r )
}
}
} ( )
2017-06-26 16:52:23 +02:00
return e . evaluator ( ctx ) , nil
2017-06-26 15:06:55 +02:00
}