@@ -48,6 +48,60 @@ program, err := expr.Compile(code, expr.Patch(&visitor{}))
48
48
```
49
49
50
50
This 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
+
51
105
Type information is also available. Here is an example, there all ` fmt.Stringer ` interface automatically
52
106
converted to ` string ` type.
53
107
0 commit comments