Skip to content

Commit 6d94de5

Browse files
committed
Update docs
1 parent c30485d commit 6d94de5

File tree

10 files changed

+161
-419
lines changed

10 files changed

+161
-419
lines changed

docs/Custom-Functions.md

Lines changed: 0 additions & 173 deletions
This file was deleted.

docs/Getting-Started.md

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
# Getting Started
22

3-
**Expr** provides a package for evaluating arbitrary expressions as well as type checking of such expression.
3+
**Expr** provides a package for evaluating arbitrary expressions as well as type
4+
checking of such expression.
45

56
## Evaluate
67

8+
For simple use cases with one execution of an expression, you can use the
9+
`expr.Eval` function. It takes an expression and a map of variables and returns
10+
the result of the expression.
11+
712
```go
813
package main
914

@@ -29,7 +34,9 @@ func main() {
2934

3035
## Compile
3136

32-
Usually we want to compile the code on save (For example, in [web user interface](https://antonmedv.github.io/expr/)).
37+
Usually we want to compile, type check and verify what the expression returns a
38+
boolean (or another type). For example, if a user saves an expression from
39+
[web UI](https://antonmedv.github.io/expr/).
3340

3441
```go
3542
package main
@@ -44,13 +51,13 @@ func main() {
4451
env := map[string]interface{}{
4552
"greet": "Hello, %v!",
4653
"names": []string{"world", "you"},
47-
"sprintf": fmt.Sprintf, // You can pass any functions.
54+
"sprintf": fmt.Sprintf, // Use any functions.
4855
}
4956

5057
code := `sprintf(greet, names[0])`
5158

52-
// Compile code into bytecode. This step can be done once and program may be reused.
53-
// Specify environment for type check.
59+
// Compile the code into a bytecode. This step can be done once
60+
// and program may be reused. Specify an environment for type check.
5461
program, err := expr.Compile(code, expr.Env(env))
5562
if err != nil {
5663
panic(err)
@@ -66,8 +73,7 @@ func main() {
6673
```
6774

6875
You may use existing types. For example, an environment can be a struct. The
69-
struct fields can be renamed by adding struct tags such as `expr:"timestamp"` in
70-
the example below:
76+
struct fields can be renamed by adding struct tags such as `expr:"name"`.
7177

7278
```go
7379
package main
@@ -83,16 +89,16 @@ type Env struct {
8389
Tweets []Tweet
8490
}
8591

86-
// Methods defined on such struct will be functions.
92+
// Methods defined on the struct become functions.
8793
func (Env) Format(t time.Time) string { return t.Format(time.RFC822) }
8894

8995
type Tweet struct {
9096
Text string
91-
Date time.Time `expr:"Timestamp"`
97+
Date time.Time `expr:"timestamp"`
9298
}
9399

94100
func main() {
95-
code := `map(filter(Tweets, {len(.Text) > 0}), {.Text + Format(.Timestamp)})`
101+
code := `map(filter(Tweets, {len(.Text) > 0}), {.Text + Format(.timestamp)})`
96102

97103
// We can use an empty instance of the struct as an environment.
98104
program, err := expr.Compile(code, expr.Env(Env{}))
@@ -101,7 +107,11 @@ func main() {
101107
}
102108

103109
env := Env{
104-
Tweets: []Tweet{{"Oh My God!", time.Now()}, {"How you doin?", time.Now()}, {"Could I be wearing any more clothes?", time.Now()}},
110+
Tweets: []Tweet{
111+
{"Oh My God!", time.Now()},
112+
{"How you doin?", time.Now()},
113+
{"Could I be wearing any more clothes?", time.Now()},
114+
},
105115
}
106116

107117
output, err := expr.Run(program, env)
@@ -113,5 +123,4 @@ func main() {
113123
}
114124
```
115125

116-
- [Contents](README.md)
117-
- Next: [Custom functions](Custom-Functions.md)
126+
* Next: [Operator Overloading](Operator-Overloading.md)

docs/Internals.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Internals
2+
3+
Expr is a stack based virtual machine. It compiles expressions to bytecode and
4+
runs it.
5+
6+
Compilation is done in a few steps:
7+
- Parse expression to AST
8+
- Type check AST
9+
- Apply operator overloading
10+
- Apply custom AST patching
11+
- Optimize AST
12+
- Compile AST to a bytecode
13+
14+
Compiler has a bunch of optimization which will produce a more optimal program.
15+
16+
## In array
17+
18+
```js
19+
value in ['foo', 'bar', 'baz']
20+
```
21+
22+
If Expr finds an `in` or `not in` expression with an array, it will be
23+
transformed into:
24+
25+
```js
26+
value in {"foo": true, "bar": true, "baz": true}
27+
```
28+
29+
## Constant folding
30+
31+
Arithmetic expressions with constants is computed on compile step and replaced
32+
with the result.
33+
34+
```js
35+
-(2-5)**3-2/(+4-3)+-2
36+
```
37+
38+
Will be compiled to just single number:
39+
40+
```js
41+
23
42+
```
43+
44+
## In range
45+
46+
```js
47+
user.Age in 18..32
48+
```
49+
50+
Will be replaced with a binary operator:
51+
52+
```js
53+
18 <= user.Age && user.Age <= 32
54+
```
55+
56+
## Const range
57+
58+
```js
59+
1..10_000
60+
```
61+
62+
Ranges computed on compile stage, replaced with precreated slices.
63+
64+
## Const expr
65+
66+
If some function marked as constant expression with `expr.ConstExpr`. It will be
67+
replaced with result of the call, if all arguments are constants.
68+
69+
```go
70+
expr.ConstExpt("fib")
71+
```
72+
73+
```js
74+
fib(42)
75+
```
76+
77+
Will be replaced with result of `fib(42)` on the compile step.
78+
79+
[ConstExpr Example](https://pkg.go.dev/github.com/antonmedv/expr?tab=doc#ConstExpr)

docs/Operator-Override.md renamed to docs/Operator-Overloading.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
# Operator Override
1+
# Operator Overloading
22

3-
**Expr** supports operator overriding. For example, you may rewrite such expression:
3+
**Expr** supports operator overloading. For example, you may rewrite a such
4+
expression:
45

56
```js
67
Now().Sub(CreatedAt)
@@ -12,7 +13,8 @@ To use `-` operator:
1213
Now() - CreatedAt
1314
```
1415

15-
To override operator use [expr.Operator](https://pkg.go.dev/github.com/antonmedv/expr?tab=doc#Operator):
16+
To overloading the operator use
17+
[expr.Operator](https://pkg.go.dev/github.com/antonmedv/expr?tab=doc#Operator):
1618

1719
```go
1820
package main
@@ -25,12 +27,12 @@ import (
2527
)
2628

2729
func main() {
28-
code := `(Now() - CreatedAt).Hours() / 24 / 365`
30+
code := `Now() - CreatedAt`
2931

3032
// We can define options before compiling.
3133
options := []expr.Option{
3234
expr.Env(Env{}),
33-
expr.Operator("-", "Sub"), // Override `-` with function `Sub`.
35+
expr.Operator("-", "Sub"), // Replace `-` operator with function `Sub`.
3436
}
3537

3638
program, err := expr.Compile(code, options...)
@@ -61,10 +63,8 @@ func (datetime) Now() time.Time { return time.Now() }
6163
func (datetime) Sub(a, b time.Time) time.Duration { return a.Sub(b) }
6264
```
6365

64-
**Expr** uses defined functions on `Env` for operator overloading. If types of operands match types of a function,
65-
the operator will be replaced with the function call.
66+
**Expr** uses functions from `Env` for operator overloading. If types of
67+
operands match types of a function, the operator will be replaced with a
68+
function call.
6669

67-
Complete example can be found here: [dates_test.go](examples/dates_test.go).
68-
69-
* [Contents](README.md)
7070
* Next: [Visitor and Patch](Visitor-and-Patch.md)

0 commit comments

Comments
 (0)