@@ -48,6 +48,60 @@ program, err := expr.Compile(code, expr.Patch(&visitor{}))
4848```
4949
5050This can be useful for some edge cases, there you want to extend functionality of ** Expr** language.
51+ In next example we are going to replace expression ` list[-1] ` with ` list[len(list)-1] ` .
52+
53+ ``` go
54+ package main
55+
56+ import (
57+ " fmt"
58+
59+ " github.com/antonmedv/expr"
60+ " github.com/antonmedv/expr/ast"
61+ )
62+
63+ func main () {
64+ env := map [string ]interface {}{
65+ " list" : []int {1 , 2 , 3 },
66+ }
67+
68+ code := ` list[-1]` // will output 3
69+
70+ program , err := expr.Compile (code, expr.Env (env), expr.Patch (&patcher{}))
71+ if err != nil {
72+ panic (err)
73+ }
74+
75+ output , err := expr.Run (program, env)
76+ if err != nil {
77+ panic (err)
78+ }
79+ fmt.Print (output)
80+ }
81+
82+ type patcher struct {}
83+
84+ func (p *patcher ) Enter (_ *ast .Node ) {}
85+ func (p *patcher ) Exit (node *ast .Node ) {
86+ n , ok := (*node).(*ast.IndexNode )
87+ if !ok {
88+ return
89+ }
90+ unary , ok := n.Index .(*ast.UnaryNode )
91+ if !ok {
92+ return
93+ }
94+ if unary.Operator == " -" {
95+ ast.Patch (&n.Index , &ast.BinaryNode {
96+ Operator: " -" ,
97+ Left: &ast.BuiltinNode {Name: " len" , Arguments: []ast.Node {n.Node }},
98+ Right: unary.Node ,
99+ })
100+ }
101+
102+ }
103+ ```
104+
51105Type information is also available. Here is an example, there all ` fmt.Stringer ` interface automatically
52106converted to ` string ` type.
53107
0 commit comments