Add custom operators.
This commit is contained in:
@@ -95,18 +95,19 @@ The Rhai Scripting Language
|
||||
8. [Maximum Call Stack Depth](safety/max-call-stack.md)
|
||||
9. [Maximum Statement Depth](safety/max-stmt-depth.md)
|
||||
8. [Advanced Topics](advanced.md)
|
||||
1. [Disable Keywords and/or Operators](engine/disable.md)
|
||||
2. [Object-Oriented Programming (OOP)](language/oop.md)
|
||||
3. [Serialization/Deserialization of `Dynamic` with `serde`](rust/serde.md)
|
||||
4. [Script Optimization](engine/optimize/index.md)
|
||||
1. [Object-Oriented Programming (OOP)](language/oop.md)
|
||||
2. [Serialization/Deserialization of `Dynamic` with `serde`](rust/serde.md)
|
||||
3. [Script Optimization](engine/optimize/index.md)
|
||||
1. [Optimization Levels](engine/optimize/optimize-levels.md)
|
||||
2. [Re-Optimize an AST](engine/optimize/reoptimize.md)
|
||||
3. [Eager Function Evaluation](engine/optimize/eager.md)
|
||||
4. [Side-Effect Considerations](engine/optimize/side-effects.md)
|
||||
5. [Volatility Considerations](engine/optimize/volatility.md)
|
||||
6. [Subtle Semantic Changes](engine/optimize/semantics.md)
|
||||
5. [Eval Statement](language/eval.md)
|
||||
9. [Appendix](appendix/index.md)
|
||||
6. [Keywords](appendix/keywords.md)
|
||||
7. [Operators](appendix/operators.md)
|
||||
8. [Literals](appendix/literals.md)
|
||||
4. [Disable Keywords and/or Operators](engine/disable.md)
|
||||
5. [Custom Operators](engine/custom-op.md)
|
||||
6. [Eval Statement](language/eval.md)
|
||||
9. [Appendix](appendix/index.md)
|
||||
1. [Keywords](appendix/keywords.md)
|
||||
2. [Operators](appendix/operators.md)
|
||||
3. [Literals](appendix/literals.md)
|
||||
|
@@ -66,3 +66,5 @@ Flexible
|
||||
* Supports [most build targets](targets.md) including `no-std` and [WASM].
|
||||
|
||||
* Surgically [disable keywords and operators] to restrict the language.
|
||||
|
||||
* [Custom operators].
|
||||
|
@@ -3,28 +3,28 @@ Operators
|
||||
|
||||
{{#include ../links.md}}
|
||||
|
||||
| Operator | Description | Binary? |
|
||||
| :---------------: | ------------------------------ | :-----: |
|
||||
| `+` | Add | Yes |
|
||||
| `-` | Subtract, Minus | Yes/No |
|
||||
| `*` | Multiply | Yes |
|
||||
| `/` | Divide | Yes |
|
||||
| `%` | Modulo | Yes |
|
||||
| `~` | Power | Yes |
|
||||
| `>>` | Right bit-shift | Yes |
|
||||
| `<<` | Left bit-shift | Yes |
|
||||
| `&` | Bit-wise _And_, Boolean _And_ | Yes |
|
||||
| <code>\|</code> | Bit-wise _Or_, Boolean _Or_ | Yes |
|
||||
| `^` | Bit-wise _Xor_ | Yes |
|
||||
| `==` | Equals to | Yes |
|
||||
| `~=` | Not equals to | Yes |
|
||||
| `>` | Greater than | Yes |
|
||||
| `>=` | Greater than or equals to | Yes |
|
||||
| `<` | Less than | Yes |
|
||||
| `<=` | Less than or equals to | Yes |
|
||||
| `>=` | Greater than or equals to | Yes |
|
||||
| `&&` | Boolean _And_ (short-circuits) | Yes |
|
||||
| <code>\|\|</code> | Boolean _Or_ (short-circuits) | Yes |
|
||||
| `!` | Boolean _Not_ | No |
|
||||
| `[` .. `]` | Indexing | Yes |
|
||||
| `.` | Property access, Method call | Yes |
|
||||
| Operator | Description | Binary? | Binding direction |
|
||||
| :---------------: | ------------------------------ | :-----: | :---------------: |
|
||||
| `+` | Add | Yes | Left |
|
||||
| `-` | Subtract, Minus | Yes/No | Left |
|
||||
| `*` | Multiply | Yes | Left |
|
||||
| `/` | Divide | Yes | Left |
|
||||
| `%` | Modulo | Yes | Left |
|
||||
| `~` | Power | Yes | Left |
|
||||
| `>>` | Right bit-shift | Yes | Left |
|
||||
| `<<` | Left bit-shift | Yes | Left |
|
||||
| `&` | Bit-wise _And_, Boolean _And_ | Yes | Left |
|
||||
| <code>\|</code> | Bit-wise _Or_, Boolean _Or_ | Yes | Left |
|
||||
| `^` | Bit-wise _Xor_ | Yes | Left |
|
||||
| `==` | Equals to | Yes | Left |
|
||||
| `~=` | Not equals to | Yes | Left |
|
||||
| `>` | Greater than | Yes | Left |
|
||||
| `>=` | Greater than or equals to | Yes | Left |
|
||||
| `<` | Less than | Yes | Left |
|
||||
| `<=` | Less than or equals to | Yes | Left |
|
||||
| `>=` | Greater than or equals to | Yes | Left |
|
||||
| `&&` | Boolean _And_ (short-circuits) | Yes | Left |
|
||||
| <code>\|\|</code> | Boolean _Or_ (short-circuits) | Yes | Left |
|
||||
| `!` | Boolean _Not_ | No | Left |
|
||||
| `[` .. `]` | Indexing | Yes | Right |
|
||||
| `.` | Property access, Method call | Yes | Right |
|
||||
|
105
doc/src/engine/custom-op.md
Normal file
105
doc/src/engine/custom-op.md
Normal file
@@ -0,0 +1,105 @@
|
||||
Custom Operators
|
||||
================
|
||||
|
||||
{{#include ../links.md}}
|
||||
|
||||
For use as a DSL (Domain-Specific Languages), it is sometimes more convenient to augment Rhai with
|
||||
customized operators performing specific logic.
|
||||
|
||||
`Engine::register_custom_operator` registers a keyword as a custom operator.
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
```rust
|
||||
use rhai::{Engine, RegisterFn};
|
||||
|
||||
let mut engine = Engine::new();
|
||||
|
||||
// Register a custom operator called 'foo' and give it
|
||||
// a precedence of 140 (i.e. between +|- and *|/)
|
||||
engine.register_custom_operator("foo", 140).unwrap();
|
||||
|
||||
// Register the implementation of the customer operator as a function
|
||||
engine.register_fn("foo", |x: i64, y: i64| (x * y) - (x + y));
|
||||
|
||||
// The custom operator can be used in expressions
|
||||
let result = engine.eval_expression::<i64>("1 + 2 * 3 foo 4 - 5 / 6")?;
|
||||
// ^ custom operator
|
||||
|
||||
// The above is equivalent to: 1 + ((2 * 3) foo 4) - (5 / 6)
|
||||
result == 15;
|
||||
```
|
||||
|
||||
|
||||
Alternatives to a Custom Operator
|
||||
--------------------------------
|
||||
|
||||
Custom operators are merely _syntactic sugar_. They map directly to registered functions.
|
||||
|
||||
Therefore, the following are equivalent (assuming `foo` has been registered as a custom operator):
|
||||
|
||||
```rust
|
||||
1 + 2 * 3 foo 4 - 5 / 6 // use custom operator
|
||||
|
||||
1 + foo(2 * 3, 4) - 5 / 6 // use function call
|
||||
```
|
||||
|
||||
A script using custom operators can always be pre-processed, via a pre-processor application,
|
||||
into a syntax that uses the corresponding function calls.
|
||||
|
||||
Using `Engine::register_custom_operator` merely enables a convenient short-cut.
|
||||
|
||||
|
||||
Must Follow Variable Naming
|
||||
--------------------------
|
||||
|
||||
All custom operators must be _identifiers_ that follow the same naming rules as [variables].
|
||||
|
||||
```rust
|
||||
engine.register_custom_operator("foo", 20); // 'foo' is a valid custom operator
|
||||
|
||||
engine.register_custom_operator("=>", 30); // <- error: '=>' is not a valid custom operator
|
||||
```
|
||||
|
||||
|
||||
Binary Operators Only
|
||||
---------------------
|
||||
|
||||
All custom operators must be _binary_ (i.e. they take two operands).
|
||||
_Unary_ custom operators are not supported.
|
||||
|
||||
```rust
|
||||
engine.register_custom_operator("foo", 140).unwrap();
|
||||
|
||||
engine.register_fn("foo", |x: i64| x * x);
|
||||
|
||||
engine.eval::<i64>("1 + 2 * 3 foo 4 - 5 / 6")?; // error: function 'foo (i64, i64)' not found
|
||||
```
|
||||
|
||||
|
||||
Operator Precedence
|
||||
-------------------
|
||||
|
||||
All operators in Rhai has a _precedence_ indicating how tightly they bind.
|
||||
|
||||
The following _precedence table_ show the built-in precedence of standard Rhai operators:
|
||||
|
||||
| Category | Operators | Precedence (0-255) |
|
||||
| ------------------- | :-------------------------------------------------------------------------------------: | :----------------: |
|
||||
| Assignments | `=`, `+=`, `-=`, `*=`, `/=`, `~=`, `%=`,<br/>`<<=`, `>>=`, `&=`, <code>\|=</code>, `^=` | 0 |
|
||||
| Logic and bit masks | <code>\|\|</code>, <code>\|</code>, `^` | 30 |
|
||||
| Logic and bit masks | `&`, `&&` | 60 |
|
||||
| Comparisons | `==`, `!=`, `>`, `>=`, `<`, `<=` | 90 |
|
||||
| | `in` | 110 |
|
||||
| Arithmetic | `+`, `-` | 130 |
|
||||
| Arithmetic | `*`, `/`, `~` | 160 |
|
||||
| Bit-shifts | `<<`, `>>` | 190 |
|
||||
| Arithmetic | `%` | 210 |
|
||||
| Object | `.` _(binds to right)_ | 240 |
|
||||
| _Others_ | | 0 |
|
||||
|
||||
A higher precedence binds more tightly than a lower precedence, so `*` and `/` binds before `+` and `-` etc.
|
||||
|
||||
When registering a custom operator, the operator's precedence must also be provided.
|
@@ -104,3 +104,5 @@
|
||||
[`OptimizationLevel::None`]: {{rootUrl}}/engine/optimize/optimize-levels.md
|
||||
|
||||
[disable keywords and operators]: {{rootUrl}}/engine/disable.md
|
||||
[custom operator]: {{rootUrl}}/engine/custom-op.md
|
||||
[custom operators]: {{rootUrl}}/engine/custom-op.md
|
||||
|
Reference in New Issue
Block a user