diff --git a/doc/src/appendix/literals.md b/doc/src/appendix/literals.md
index 2d51ba36..3e5a5fdf 100644
--- a/doc/src/appendix/literals.md
+++ b/doc/src/appendix/literals.md
@@ -8,7 +8,7 @@ Literals Syntax
| `INT` | decimal: `42`, `-123`, `0`
hex: `0x????..`
binary: `0b????..`
octal: `0o????..` |
| `FLOAT` | `42.0`, `-123.456`, `0.0` |
| [String] | `"... \x?? \u???? \U???????? ..."` |
-| Character | single: `'?'`
ASCII hex: `'\x??'`
Unicode: `'\u????'`, `'\U????????'` |
+| [Character][string] | single: `'?'`
ASCII hex: `'\x??'`
Unicode: `'\u????'`, `'\U????????'` |
| [`Array`] | `[ ???, ???, ??? ]` |
| [Object map] | `#{ a: ???, b: ???, c: ???, "def": ??? }` |
| Boolean true | `true` |
diff --git a/doc/src/appendix/operators.md b/doc/src/appendix/operators.md
index e53ba01b..c0fa4292 100644
--- a/doc/src/appendix/operators.md
+++ b/doc/src/appendix/operators.md
@@ -7,46 +7,62 @@ Operators and Symbols
Operators
---------
-| 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 |
-| \|
| bit-wise _Or_, boolean _Or_ | yes | left |
-| `^` | bit-wise _Xor_, boolean _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 |
-| `&&` | boolean _And_ (short-circuits) | yes | left |
-| \|\|
| boolean _Or_ (short-circuits) | yes | left |
-| `!` | boolean _Not_ | no | left |
-| `[` .. `]` | indexing | yes | right |
-| `.` | property access, method call | yes | right |
+| Operator | Description | Binary? | Binding direction |
+| :-----------------------------------------------------------------------------------------: | -------------------------------------- | :--------: | :---------------: |
+| `+` | add | yes | left |
+| `-` | 1) subtract
2) negative | yes
no | left
right |
+| `*` | multiply | yes | left |
+| `/` | divide | yes | left |
+| `%` | modulo | yes | left |
+| `~` | power | yes | left |
+| `>>` | right bit-shift | yes | left |
+| `<<` | left bit-shift | yes | left |
+| `&` | 1) bit-wise _And_
2) boolean _And_ | yes | left |
+| \|
| 1) bit-wise _Or_
2) boolean _Or_ | yes | left |
+| `^` | 1) bit-wise _Xor_
2) boolean _Xor_ | yes | left |
+| `=`, `+=`, `-=`, `*=`, `/=`,
`~=`, `%=`, `<<=`, `>>=`, `&=`,
\|=
, `^=` | assignments | yes | right |
+| `==` | 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 |
+| `&&` | boolean _And_ (short-circuits) | yes | left |
+| \|\|
| boolean _Or_ (short-circuits) | yes | left |
+| `!` | boolean _Not_ | no | left |
+| `[` .. `]` | indexing | yes | right |
+| `.` | 1) property access
2) method call | yes | right |
-Symbols
--------
+Symbols and Patterns
+--------------------
-| Symbol | Description |
-| ------------ | ------------------------ |
-| `:` | property value separator |
-| `::` | module path separator |
-| `#` | _reserved_ |
-| `=>` | _reserved_ |
-| `->` | _reserved_ |
-| `<-` | _reserved_ |
-| `===` | _reserved_ |
-| `!==` | _reserved_ |
-| `:=` | _reserved_ |
-| `::<` .. `>` | _reserved_ |
-| `@` | _reserved_ |
-| `(*` .. `*)` | _reserved_ |
+| Symbol | Name | Description |
+| ---------------------------------- | :------------------: | ------------------------------------- |
+| `;` | semicolon | statement separator |
+| `,` | comma | list separator |
+| `:` | colon | [object map] property value separator |
+| `::` | path | module path separator |
+| `#{` .. `}` | hash map | [object map] literal |
+| `"` .. `"` | double quote | [string] |
+| `'` .. `'` | single quote | [character][string] |
+| `\` | escape | escape character literal |
+| `(` .. `)` | parentheses | expression grouping |
+| `{` .. `}` | braces | block statement |
+| \|
.. \|
| pipes | closure |
+| `[` .. `]` | brackets | [array] literal |
+| `!` | bang | function call in calling scope |
+| `//` | comment | line comment |
+| `/*` .. `*/` | comment | block comment |
+| `(*` .. `*)` | comment | _reserved_ |
+| `<` .. `>` | angular brackets | _reserved_ |
+| `#` | hash | _reserved_ |
+| `@` | at | _reserved_ |
+| `$` | dollar | _reserved_ |
+| `=>` | double arrow | _reserved_ |
+| `->` | arrow | _reserved_ |
+| `<-` | left arrow | _reserved_ |
+| `===` | strict equals to | _reserved_ |
+| `!==` | strict not equals to | _reserved_ |
+| `:=` | assignment | _reserved_ |
+| `::<` .. `>` | turbofish | _reserved_ |
diff --git a/doc/src/engine/optimize/index.md b/doc/src/engine/optimize/index.md
index 6f293181..59ae0f6a 100644
--- a/doc/src/engine/optimize/index.md
+++ b/doc/src/engine/optimize/index.md
@@ -47,9 +47,13 @@ Constants propagation is used to remove dead code:
```rust
const ABC = true;
+
if ABC || some_work() { print("done!"); } // 'ABC' is constant so it is replaced by 'true'...
+
if true || some_work() { print("done!"); } // since '||' short-circuits, 'some_work' is never called
+
if true { print("done!"); } // <- the line above is equivalent to this
+
print("done!"); // <- the line above is further simplified to this
// because the condition is always true
```
@@ -84,13 +88,15 @@ Rhai guarantees that no external function will be run (in order not to trigger s
optimization process (unless the optimization level is set to [`OptimizationLevel::Full`]).
```rust
-const DECISION = 1; // this is an integer, one of the standard types
+// The following is most likely generated by machine.
-if DECISION == 1 { // this is optimized into 'true'
+const DECISION = 1; // this is an integer, one of the standard types
+
+if DECISION == 1 { // this is optimized into 'true'
:
-} else if DECISION == 2 { // this is optimized into 'false'
+} else if DECISION == 2 { // this is optimized into 'false'
:
-} else if DECISION == 3 { // this is optimized into 'false'
+} else if DECISION == 3 { // this is optimized into 'false'
:
} else {
:
@@ -101,9 +107,9 @@ Because of the eager evaluation of operators for [standard types], many constant
and replaced by the result.
```rust
-let x = (1+2)*3-4/5%6; // will be replaced by 'let x = 9'
+let x = (1+2) * 3-4 / 5%6; // will be replaced by 'let x = 9'
-let y = (1>2) || (3<=4); // will be replaced by 'let y = true'
+let y = (1 > 2) || (3 < =4); // will be replaced by 'let y = true'
```
For operators that are not optimized away due to one of the above reasons, the function calls
@@ -116,12 +122,12 @@ const DECISION_1 = new_state(1);
const DECISION_2 = new_state(2);
const DECISION_3 = new_state(3);
-if DECISION == 1 { // NOT optimized away because the operator is not built-in
- : // and may cause side-effects if called!
+if DECISION == 1 { // NOT optimized away because the operator is not built-in
+ : // and may cause side-effects if called!
:
-} else if DECISION == 2 { // same here, NOT optimized away
+} else if DECISION == 2 { // same here, NOT optimized away
:
-} else if DECISION == 3 { // same here, NOT optimized away
+} else if DECISION == 3 { // same here, NOT optimized away
:
} else {
:
diff --git a/doc/src/start/features.md b/doc/src/start/features.md
index baf1d176..e82b1df1 100644
--- a/doc/src/start/features.md
+++ b/doc/src/start/features.md
@@ -26,8 +26,8 @@ more control over what a script can (or cannot) do.
| `no_closure` | no | disables [capturing][automatic currying] external variables in [anonymous functions] to simulate _closures_, or [capturing the calling scope]({{rootUrl}}/language/fn-capture.md) in function calls |
| `no_std` | no | builds for `no-std` (implies `no_closure`). Notice that additional dependencies will be pulled in to replace `std` features |
| `serde` | yes | enables serialization/deserialization via `serde`. Notice that the [`serde`](https://crates.io/crates/serde) crate will be pulled in together with its dependencies |
-| `internals` | yes | exposes internal data structures (e.g. [`AST`] nodes). Beware that Rhai internals are volatile and may change from version to version |
| `unicode-xid-ident` | no | allows [Unicode Standard Annex #31](http://www.unicode.org/reports/tr31/) as identifiers |
+| `internals` | yes | exposes internal data structures (e.g. [`AST`] nodes). Beware that Rhai internals are volatile and may change from version to version |
Example
diff --git a/src/token.rs b/src/token.rs
index 3494b02e..97a65862 100644
--- a/src/token.rs
+++ b/src/token.rs
@@ -1391,6 +1391,8 @@ fn get_next_token_inner(
('@', _) => return Some((Token::Reserved("@".into()), start_pos)),
+ ('$', _) => return Some((Token::Reserved("$".into()), start_pos)),
+
('\0', _) => unreachable!(),
(ch, _) if ch.is_whitespace() => (),