Add multiple instantiation.
This commit is contained in:
parent
f9807a3c1e
commit
111f5931b3
@ -88,6 +88,7 @@ The Rhai Scripting Language
|
||||
4. [Create from AST](language/modules/ast.md)
|
||||
5. [Module Resolvers](rust/modules/resolvers.md)
|
||||
1. [Custom Implementation](rust/modules/imp-resolver.md)
|
||||
18. [Eval Statement](language/eval.md)
|
||||
6. [Safety and Protection](safety/index.md)
|
||||
1. [Checked Arithmetic](safety/checked.md)
|
||||
2. [Sand-Boxing](safety/sandbox.md)
|
||||
@ -119,7 +120,7 @@ The Rhai Scripting Language
|
||||
1. [Disable Keywords and/or Operators](engine/disable.md)
|
||||
2. [Custom Operators](engine/custom-op.md)
|
||||
3. [Extending with Custom Syntax](engine/custom-syntax.md)
|
||||
7. [Eval Statement](language/eval.md)
|
||||
7. [Multiple Instantiation](patterns/multiple.md)
|
||||
8. [Appendix](appendix/index.md)
|
||||
1. [Keywords](appendix/keywords.md)
|
||||
2. [Operators and Symbols](appendix/operators.md)
|
||||
|
89
doc/src/patterns/multiple.md
Normal file
89
doc/src/patterns/multiple.md
Normal file
@ -0,0 +1,89 @@
|
||||
Multiple Instantiation
|
||||
======================
|
||||
|
||||
{{#include ../links.md}}
|
||||
|
||||
|
||||
Background
|
||||
----------
|
||||
|
||||
Rhai's [features] are not strictly additive. This is easily deduced from the [`no_std`] feature
|
||||
which prepares the crate for `no-std` builds. Obviously, turning on this feature has a material
|
||||
impact on how Rhai behaves.
|
||||
|
||||
Many crates resolve this by going the opposite direction: build for `no-std` in default,
|
||||
but add a `std` feature, included by default, which builds for the `stdlib`.
|
||||
|
||||
|
||||
Rhai Language Features Are Not Additive
|
||||
--------------------------------------
|
||||
|
||||
Rhai, however, is more complex. Language features cannot be easily made _additive_.
|
||||
|
||||
That is because the _lack_ of a language feature is a feature by itself.
|
||||
|
||||
For example, by including [`no_float`], a project sets the Rhai language to ignore floating-point math.
|
||||
Floating-point numbers do not even parse under this case and will generate syntax errors.
|
||||
Assume that the project expects this behavior (why? perhaps integers are all that make sense
|
||||
within the project domain).
|
||||
|
||||
Now, assume that a dependent crate also depends on Rhai. Under such circumstances,
|
||||
unless _exact_ versioning is used and the dependent crate depends on a _different_ version
|
||||
of Rhai, Cargo automatically _merges_ both dependencies, with the [`no_float`] feature turned on
|
||||
because Cargo features are _additive_.
|
||||
|
||||
This will break the dependent crate, which does not by itself specify [`no_float`]
|
||||
and expects floating-point numbers and math to work normally.
|
||||
|
||||
There is no way out of this dilemma. Reversing the [features] set with a `float` feature
|
||||
causes the project to break because floating-point numbers are not rejected as expected.
|
||||
|
||||
|
||||
Multiple Instantiations of Rhai Within The Same Project
|
||||
------------------------------------------------------
|
||||
|
||||
The trick is to differentiate between multiple identical copies of Rhai, each having
|
||||
a different [features] set, by their _sources_:
|
||||
|
||||
* Different versions from [`crates.io`](https://crates.io/crates/rhai/) - The official crate.
|
||||
|
||||
* Different releases from [`GitHub`](https://github.com/jonathandturner/rhai) - Crate source on GitHub.
|
||||
|
||||
* Forked copy of [https://github.com/jonathandturner/rhai](https://github.com/jonathandturner/rhai) on GitHub.
|
||||
|
||||
* Local copy of [https://github.com/jonathandturner/rhai](https://github.com/jonathandturner/rhai) downloaded form GitHub.
|
||||
|
||||
Use the following configuration in `Cargo.toml` to pull in multiple copies of Rhai within the same project:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
rhai = { version = "{{version}}", features = [ "no_float" ] }
|
||||
rhai_github = { git = "https://github.com/jonathandturner/rhai", features = [ "unchecked" ] }
|
||||
rhai_my_github = { git = "https://github.com/my_github/rhai", branch = "variation1", features = [ "serde", "no_closure" ] }
|
||||
rhai_local = { path = "../rhai_copy" }
|
||||
```
|
||||
|
||||
The example above creates four different modules: `rhai`, `rhai_github`, `rhai_my_github` and
|
||||
`rhai_local`, each referring to a different Rhai copy with the appropriate [features] set.
|
||||
|
||||
Only one crate of any particular version can be used from each source, because Cargo merges
|
||||
all candidate cases within the same source, adding all [features] together.
|
||||
|
||||
If more than four different instantiations of Rhai is necessary (why?), create more local repositories
|
||||
or GitHub forks or branches.
|
||||
|
||||
|
||||
Caveat - No Way To Avoid Dependency Conflicts
|
||||
--------------------------------------------
|
||||
|
||||
Unfortunately, pulling in Rhai from different sources do not resolve the problem of
|
||||
[features] conflict between dependencies. Even overriding `crates.io` via the `[patch]` manifest
|
||||
section doesn't work - all dependencies will eventually find the only one copy.
|
||||
|
||||
What is necessary - multiple copies of Rhai, one for each dependent crate that requires it,
|
||||
together with their _unique_ [features] set intact. In other words, turning off Cargo's
|
||||
crate merging feature _just for Rhai_.
|
||||
|
||||
Unfortunately, as of this writing, there is no known method to achieve it.
|
||||
|
||||
Therefore, moral of the story: avoid pulling in multiple crates that depend on Rhai.
|
@ -52,3 +52,15 @@ no floating-point, is `Send + Sync` (so it can be safely used across threads), a
|
||||
nor loading external [modules].
|
||||
|
||||
This configuration is perfect for an expression parser in a 32-bit embedded system without floating-point hardware.
|
||||
|
||||
|
||||
Caveat - Features Are Not Additive
|
||||
---------------------------------
|
||||
|
||||
Rhai features are not strictly _additive_ - i.e. they do not only add optional functionalities.
|
||||
|
||||
In fact, most features are _subtractive_ - i.e. they _remove_ functionalities.
|
||||
|
||||
There is a reason for this design, because the _lack_ of a language feature by itself is a feature.
|
||||
|
||||
See [here]({{rootUrl}}/patterns/multiple.md) for more details.
|
||||
|
Loading…
Reference in New Issue
Block a user