reorganize module
This commit is contained in:
@@ -1,176 +0,0 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
@@ -1,23 +0,0 @@
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
@@ -1,37 +0,0 @@
|
||||
# Sample Applications
|
||||
|
||||
## Standard Examples
|
||||
|
||||
| Example | Description |
|
||||
| --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [`arrays_and_structs`](arrays_and_structs.rs) | shows how to register a Rust type and using it with arrays |
|
||||
| [`callback`](callback.rs) | shows how to store a Rhai closure and call it later within Rust |
|
||||
| [`custom_types_and_methods`](custom_types_and_methods.rs) | shows how to register a Rust type and methods/getters/setters for it |
|
||||
| [`custom_types`](custom_types.rs) | shows how to register a Rust type and methods/getters/setters using the `CustomType` trait. |
|
||||
| [`definitions`](./definitions) | shows how to generate definition files for use with the [Rhai Language Server](https://github.com/rhaiscript/lsp) (requires the `metadata` feature) |
|
||||
| [`hello`](hello.rs) | simple example that evaluates an expression and prints the result |
|
||||
| [`pause_and_resume`](pause_and_resume.rs) | shows how to pause/resume/stop an `Engine` running in a separate thread via an MPSC channel |
|
||||
| [`reuse_scope`](reuse_scope.rs) | evaluates two pieces of code in separate runs, but using a common `Scope` |
|
||||
| [`serde`](serde.rs) | example to serialize and deserialize Rust types with [`serde`](https://crates.io/crates/serde) (requires the `serde` feature) |
|
||||
| [`simple_fn`](simple_fn.rs) | shows how to register a simple Rust function |
|
||||
| [`strings`](strings.rs) | shows different ways to register Rust functions taking string arguments |
|
||||
| [`threading`](threading.rs) | shows how to communicate in duplex with an `Engine` running in a separate thread via a pair of MPSC channels |
|
||||
|
||||
## Scriptable Event Handler With State Examples
|
||||
|
||||
Because of its popularity, included are sample implementations for the pattern
|
||||
[_Scriptable Event Handler With State_](https://rhai.rs/book/patterns/events.html) in different styles.
|
||||
|
||||
| Example | Handler Script | Description |
|
||||
| ------------------------------------------ | ------------------------------------------------------------------ | :---------------------------------------------------------: |
|
||||
| [`event_handler_main`](event_handler_main) | [`event_handler_main/script.rhai`](event_handler_main/script.rhai) | [_Main Style_](https://rhai.rs/book/patterns/events-1.html) |
|
||||
| [`event_handler_js`](event_handler_js) | [`event_handler_js/script.rhai`](event_handler_js/script.rhai) | [_JS Style_](https://rhai.rs/book/patterns/events-2.html) |
|
||||
| [`event_handler_map`](event_handler_map) | [`event_handler_map/script.rhai`](event_handler_map/script.rhai) | [_Map Style_](https://rhai.rs/book/patterns/events-3.html) |
|
||||
|
||||
## Running Examples
|
||||
|
||||
Examples can be run with the following command:
|
||||
|
||||
```sh
|
||||
cargo run --example {example_name}
|
||||
```
|
@@ -1,67 +0,0 @@
|
||||
//! An example showing how to register a Rust type and use it with arrays.
|
||||
|
||||
#[cfg(any(feature = "no_index", feature = "no_object"))]
|
||||
fn main() {
|
||||
panic!("This example does not run under 'no_index' or 'no_object'.")
|
||||
}
|
||||
|
||||
use rhai::{Engine, EvalAltResult};
|
||||
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
fn main() -> Result<(), Box<EvalAltResult>> {
|
||||
#[derive(Debug, Clone)]
|
||||
struct TestStruct {
|
||||
x: i64,
|
||||
}
|
||||
|
||||
impl TestStruct {
|
||||
pub fn new() -> Self {
|
||||
Self { x: 1 }
|
||||
}
|
||||
pub fn update(&mut self) {
|
||||
self.x += 1000;
|
||||
}
|
||||
}
|
||||
|
||||
let mut engine = Engine::new();
|
||||
|
||||
engine
|
||||
.register_type_with_name::<TestStruct>("TestStruct")
|
||||
.register_fn("new_ts", TestStruct::new)
|
||||
.register_fn("update", TestStruct::update);
|
||||
|
||||
#[cfg(feature = "metadata")]
|
||||
{
|
||||
println!("Functions registered:");
|
||||
|
||||
engine
|
||||
.gen_fn_signatures(false)
|
||||
.into_iter()
|
||||
.for_each(|func| println!("{func}"));
|
||||
|
||||
println!();
|
||||
}
|
||||
|
||||
let result = engine.eval::<TestStruct>(
|
||||
"
|
||||
let x = new_ts();
|
||||
x.update();
|
||||
x
|
||||
",
|
||||
)?;
|
||||
|
||||
println!("{result:?}");
|
||||
|
||||
let result = engine.eval::<TestStruct>(
|
||||
"
|
||||
let x = [ new_ts() ];
|
||||
x[0].update();
|
||||
x[0]
|
||||
",
|
||||
)?;
|
||||
|
||||
println!("{result:?}");
|
||||
|
||||
Ok(())
|
||||
}
|
@@ -1,42 +0,0 @@
|
||||
//! This example stores a Rhai closure for later use as a callback.
|
||||
|
||||
use rhai::{Engine, EvalAltResult, FnPtr};
|
||||
|
||||
// To call a Rhai closure at a later time, you'd need three things:
|
||||
// 1) an `Engine` (with all needed functions registered),
|
||||
// 2) a compiled `AST`,
|
||||
// 3) the closure (of type `FnPtr`).
|
||||
fn main() -> Result<(), Box<EvalAltResult>> {
|
||||
let engine = Engine::new();
|
||||
|
||||
// This script creates a closure which captures a variable and returns it.
|
||||
let ast = engine.compile(
|
||||
"
|
||||
let x = 18;
|
||||
|
||||
// The following closure captures 'x'
|
||||
return |a, b| {
|
||||
x += 1; // x is incremented each time
|
||||
(x + a) * b
|
||||
};
|
||||
",
|
||||
)?;
|
||||
|
||||
let closure = engine.eval_ast::<FnPtr>(&ast)?;
|
||||
|
||||
// Create a closure by encapsulating the `Engine`, `AST` and `FnPtr`.
|
||||
// In a real application, you'd be handling errors.
|
||||
let func = move |x: i64, y: i64| -> i64 { closure.call(&engine, &ast, (x, y)).unwrap() };
|
||||
|
||||
// Now we can call `func` anywhere just like a normal function!
|
||||
let r1 = func(1, 2);
|
||||
|
||||
// Notice that each call to `func` returns a different value
|
||||
// because the captured `x` is always changing!
|
||||
let r2 = func(1, 2);
|
||||
let r3 = func(1, 2);
|
||||
|
||||
println!("The Answers: {r1}, {r2}, {r3}"); // prints 40, 42, 44
|
||||
|
||||
Ok(())
|
||||
}
|
@@ -1,85 +0,0 @@
|
||||
//! An example showing how to register a Rust type and methods/getters/setters using the `CustomType` trait.
|
||||
|
||||
#[cfg(feature = "no_object")]
|
||||
fn main() {
|
||||
panic!("This example does not run under 'no_object'.");
|
||||
}
|
||||
|
||||
use rhai::{CustomType, Engine, EvalAltResult, TypeBuilder};
|
||||
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
fn main() -> Result<(), Box<EvalAltResult>> {
|
||||
#[derive(Debug, Clone, CustomType)]
|
||||
#[rhai_type(extra = Self::build_extra)]
|
||||
struct TestStruct {
|
||||
x: i64,
|
||||
}
|
||||
|
||||
impl TestStruct {
|
||||
pub fn new() -> Self {
|
||||
Self { x: 1 }
|
||||
}
|
||||
pub fn update(&mut self) {
|
||||
self.x += 1000;
|
||||
}
|
||||
pub fn calculate(&mut self, data: i64) -> i64 {
|
||||
self.x * data
|
||||
}
|
||||
fn build_extra(builder: &mut TypeBuilder<Self>) {
|
||||
builder
|
||||
.with_name("TestStruct")
|
||||
.with_fn("new_ts", Self::new)
|
||||
.with_fn("update", Self::update)
|
||||
.with_fn("calc", Self::calculate)
|
||||
.is_iterable();
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoIterator for TestStruct {
|
||||
type Item = i64;
|
||||
type IntoIter = std::vec::IntoIter<Self::Item>;
|
||||
|
||||
#[inline]
|
||||
#[must_use]
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
vec![self.x - 1, self.x, self.x + 1].into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
let mut engine = Engine::new();
|
||||
|
||||
engine.build_type::<TestStruct>();
|
||||
|
||||
#[cfg(feature = "metadata")]
|
||||
{
|
||||
println!("Functions registered:");
|
||||
|
||||
engine
|
||||
.gen_fn_signatures(false)
|
||||
.into_iter()
|
||||
.for_each(|func| println!("{func}"));
|
||||
|
||||
println!();
|
||||
}
|
||||
|
||||
let result = engine.eval::<i64>(
|
||||
"
|
||||
let x = new_ts();
|
||||
|
||||
x.x = 42;
|
||||
|
||||
for n in x {
|
||||
x.x += n;
|
||||
print(`n = ${n}, total = ${x.x}`);
|
||||
}
|
||||
|
||||
x.update();
|
||||
|
||||
x.calc(x.x)
|
||||
",
|
||||
)?;
|
||||
|
||||
println!("result: {result}"); // prints 1085764
|
||||
|
||||
Ok(())
|
||||
}
|
@@ -1,114 +0,0 @@
|
||||
//! An example showing how to register a Rust type and methods/getters/setters for it.
|
||||
|
||||
#[cfg(feature = "no_object")]
|
||||
fn main() {
|
||||
panic!("This example does not run under 'no_object'.");
|
||||
}
|
||||
|
||||
use rhai::{CustomType, Engine, EvalAltResult, TypeBuilder};
|
||||
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
fn main() -> Result<(), Box<EvalAltResult>> {
|
||||
/// This is a test structure. If the metadata feature
|
||||
/// is enabled, this comment will be exported.
|
||||
#[derive(Debug, Clone, CustomType)]
|
||||
#[rhai_type(extra = Self::build_extra)]
|
||||
struct TestStruct {
|
||||
/// A number.
|
||||
///
|
||||
/// ```js
|
||||
/// let t = new_ts();
|
||||
/// print(t.x); // Get the value of x.
|
||||
/// t.x = 42; // Set the value of x.
|
||||
/// ```
|
||||
x: i64,
|
||||
}
|
||||
|
||||
impl TestStruct {
|
||||
pub fn new() -> Self {
|
||||
Self { x: 1 }
|
||||
}
|
||||
pub fn update(&mut self) {
|
||||
self.x += 1000;
|
||||
}
|
||||
pub fn calculate(&mut self, data: i64) -> i64 {
|
||||
self.x * data
|
||||
}
|
||||
|
||||
fn build_extra(builder: &mut TypeBuilder<Self>) {
|
||||
builder
|
||||
.with_fn("new_ts", TestStruct::new)
|
||||
.with_fn("update", TestStruct::update)
|
||||
.with_fn("calc", TestStruct::calculate);
|
||||
}
|
||||
}
|
||||
|
||||
let mut engine = Engine::new();
|
||||
|
||||
engine.build_type::<TestStruct>();
|
||||
|
||||
#[cfg(feature = "metadata")]
|
||||
{
|
||||
println!("Functions registered:");
|
||||
|
||||
engine
|
||||
.gen_fn_signatures(false)
|
||||
.into_iter()
|
||||
.for_each(|func| println!("{func}"));
|
||||
|
||||
println!();
|
||||
|
||||
let docs: serde_json::Value =
|
||||
serde_json::from_str(&engine.gen_fn_metadata_to_json(false).unwrap()).unwrap();
|
||||
|
||||
// compare comments from the type.
|
||||
assert_eq!(
|
||||
docs["customTypes"][0]["docComments"],
|
||||
serde_json::json!([
|
||||
"/// This is a test structure. If the metadata feature",
|
||||
"/// is enabled, this comment will be exported."
|
||||
])
|
||||
);
|
||||
|
||||
// compare comments from the getter.
|
||||
assert_eq!(
|
||||
docs["functions"][1]["docComments"],
|
||||
serde_json::json!([
|
||||
"/// A number.",
|
||||
"///",
|
||||
"/// ```js",
|
||||
"/// let t = new_ts();",
|
||||
"/// print(t.x); // Get the value of x.",
|
||||
"/// t.x = 42; // Set the value of x.",
|
||||
"/// ```"
|
||||
])
|
||||
);
|
||||
|
||||
// compare comments from the setter.
|
||||
assert_eq!(
|
||||
docs["functions"][3]["docComments"],
|
||||
serde_json::json!([
|
||||
"/// A number.",
|
||||
"///",
|
||||
"/// ```js",
|
||||
"/// let t = new_ts();",
|
||||
"/// print(t.x); // Get the value of x.",
|
||||
"/// t.x = 42; // Set the value of x.",
|
||||
"/// ```"
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
let result = engine.eval::<i64>(
|
||||
"
|
||||
let x = new_ts();
|
||||
x.x = 42;
|
||||
x.update();
|
||||
x.calc(x.x)
|
||||
",
|
||||
)?;
|
||||
|
||||
println!("result: {result}"); // prints 1085764
|
||||
|
||||
Ok(())
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,14 +0,0 @@
|
||||
module static;
|
||||
|
||||
op minus(int, int) -> int;
|
||||
|
||||
module general_kenobi {
|
||||
const CONSTANT: int;
|
||||
|
||||
/// Returns a string where "hello there" is repeated `n` times.
|
||||
fn hello_there(n: int) -> String;
|
||||
}
|
||||
|
||||
let hello_there: string;
|
||||
|
||||
const HELLO: string;
|
@@ -1,259 +0,0 @@
|
||||
module static;
|
||||
|
||||
op ==(int, int) -> bool;
|
||||
op !=(int, int) -> bool;
|
||||
op >(int, int) -> bool;
|
||||
op >=(int, int) -> bool;
|
||||
op <(int, int) -> bool;
|
||||
op <=(int, int) -> bool;
|
||||
op &(int, int) -> int;
|
||||
op |(int, int) -> int;
|
||||
op ^(int, int) -> int;
|
||||
op ..(int, int) -> Range<int>;
|
||||
op ..=(int, int) -> RangeInclusive<int>;
|
||||
|
||||
op ==(bool, bool) -> bool;
|
||||
op !=(bool, bool) -> bool;
|
||||
op >(bool, bool) -> bool;
|
||||
op >=(bool, bool) -> bool;
|
||||
op <(bool, bool) -> bool;
|
||||
op <=(bool, bool) -> bool;
|
||||
op &(bool, bool) -> bool;
|
||||
op |(bool, bool) -> bool;
|
||||
op ^(bool, bool) -> bool;
|
||||
|
||||
op ==((), ()) -> bool;
|
||||
op !=((), ()) -> bool;
|
||||
op >((), ()) -> bool;
|
||||
op >=((), ()) -> bool;
|
||||
op <((), ()) -> bool;
|
||||
op <=((), ()) -> bool;
|
||||
|
||||
op +(int, int) -> int;
|
||||
op -(int, int) -> int;
|
||||
op *(int, int) -> int;
|
||||
op /(int, int) -> int;
|
||||
op %(int, int) -> int;
|
||||
op **(int, int) -> int;
|
||||
op >>(int, int) -> int;
|
||||
op <<(int, int) -> int;
|
||||
|
||||
op +(float, float) -> float;
|
||||
op -(float, float) -> float;
|
||||
op *(float, float) -> float;
|
||||
op /(float, float) -> float;
|
||||
op %(float, float) -> float;
|
||||
op **(float, float) -> float;
|
||||
op ==(float, float) -> bool;
|
||||
op !=(float, float) -> bool;
|
||||
op >(float, float) -> bool;
|
||||
op >=(float, float) -> bool;
|
||||
op <(float, float) -> bool;
|
||||
op <=(float, float) -> bool;
|
||||
|
||||
op +(float, int) -> float;
|
||||
op -(float, int) -> float;
|
||||
op *(float, int) -> float;
|
||||
op /(float, int) -> float;
|
||||
op %(float, int) -> float;
|
||||
op **(float, int) -> float;
|
||||
op ==(float, int) -> bool;
|
||||
op !=(float, int) -> bool;
|
||||
op >(float, int) -> bool;
|
||||
op >=(float, int) -> bool;
|
||||
op <(float, int) -> bool;
|
||||
op <=(float, int) -> bool;
|
||||
|
||||
op +(int, float) -> float;
|
||||
op -(int, float) -> float;
|
||||
op *(int, float) -> float;
|
||||
op /(int, float) -> float;
|
||||
op %(int, float) -> float;
|
||||
op **(int, float) -> float;
|
||||
op ==(int, float) -> bool;
|
||||
op !=(int, float) -> bool;
|
||||
op >(int, float) -> bool;
|
||||
op >=(int, float) -> bool;
|
||||
op <(int, float) -> bool;
|
||||
op <=(int, float) -> bool;
|
||||
|
||||
op +(Decimal, Decimal) -> Decimal;
|
||||
op -(Decimal, Decimal) -> Decimal;
|
||||
op *(Decimal, Decimal) -> Decimal;
|
||||
op /(Decimal, Decimal) -> Decimal;
|
||||
op %(Decimal, Decimal) -> Decimal;
|
||||
op **(Decimal, Decimal) -> Decimal;
|
||||
op ==(Decimal, Decimal) -> bool;
|
||||
op !=(Decimal, Decimal) -> bool;
|
||||
op >(Decimal, Decimal) -> bool;
|
||||
op >=(Decimal, Decimal) -> bool;
|
||||
op <(Decimal, Decimal) -> bool;
|
||||
op <=(Decimal, Decimal) -> bool;
|
||||
|
||||
op +(Decimal, int) -> Decimal;
|
||||
op -(Decimal, int) -> Decimal;
|
||||
op *(Decimal, int) -> Decimal;
|
||||
op /(Decimal, int) -> Decimal;
|
||||
op %(Decimal, int) -> Decimal;
|
||||
op **(Decimal, int) -> Decimal;
|
||||
op ==(Decimal, int) -> bool;
|
||||
op !=(Decimal, int) -> bool;
|
||||
op >(Decimal, int) -> bool;
|
||||
op >=(Decimal, int) -> bool;
|
||||
op <(Decimal, int) -> bool;
|
||||
op <=(Decimal, int) -> bool;
|
||||
|
||||
op +(int, Decimal) -> Decimal;
|
||||
op -(int, Decimal) -> Decimal;
|
||||
op *(int, Decimal) -> Decimal;
|
||||
op /(int, Decimal) -> Decimal;
|
||||
op %(int, Decimal) -> Decimal;
|
||||
op **(int, Decimal) -> Decimal;
|
||||
op ==(int, Decimal) -> bool;
|
||||
op !=(int, Decimal) -> bool;
|
||||
op >(int, Decimal) -> bool;
|
||||
op >=(int, Decimal) -> bool;
|
||||
op <(int, Decimal) -> bool;
|
||||
op <=(int, Decimal) -> bool;
|
||||
|
||||
op +(String, String) -> String;
|
||||
op -(String, String) -> String;
|
||||
op ==(String, String) -> bool;
|
||||
op !=(String, String) -> bool;
|
||||
op >(String, String) -> bool;
|
||||
op >=(String, String) -> bool;
|
||||
op <(String, String) -> bool;
|
||||
op <=(String, String) -> bool;
|
||||
|
||||
op +(char, char) -> String;
|
||||
op ==(char, char) -> bool;
|
||||
op !=(char, char) -> bool;
|
||||
op >(char, char) -> bool;
|
||||
op >=(char, char) -> bool;
|
||||
op <(char, char) -> bool;
|
||||
op <=(char, char) -> bool;
|
||||
|
||||
op +(char, String) -> String;
|
||||
op ==(char, String) -> bool;
|
||||
op !=(char, String) -> bool;
|
||||
op >(char, String) -> bool;
|
||||
op >=(char, String) -> bool;
|
||||
op <(char, String) -> bool;
|
||||
op <=(char, String) -> bool;
|
||||
|
||||
op +(String, char) -> String;
|
||||
op -(String, char) -> String;
|
||||
op ==(String, char) -> bool;
|
||||
op !=(String, char) -> bool;
|
||||
op >(String, char) -> bool;
|
||||
op >=(String, char) -> bool;
|
||||
op <(String, char) -> bool;
|
||||
op <=(String, char) -> bool;
|
||||
|
||||
op +((), String) -> String;
|
||||
op ==((), String) -> bool;
|
||||
op !=((), String) -> bool;
|
||||
op >((), String) -> bool;
|
||||
op >=((), String) -> bool;
|
||||
op <((), String) -> bool;
|
||||
op <=((), String) -> bool;
|
||||
|
||||
op +(String, ()) -> String;
|
||||
op ==(String, ()) -> bool;
|
||||
op !=(String, ()) -> bool;
|
||||
op >(String, ()) -> bool;
|
||||
op >=(String, ()) -> bool;
|
||||
op <(String, ()) -> bool;
|
||||
op <=(String, ()) -> bool;
|
||||
|
||||
op +(Blob, Blob) -> Blob;
|
||||
op +(Blob, char) -> Blob;
|
||||
op ==(Blob, Blob) -> bool;
|
||||
op !=(Blob, Blob) -> bool;
|
||||
|
||||
|
||||
op ==(Range<int>, RangeInclusive<int>) -> bool;
|
||||
op !=(Range<int>, RangeInclusive<int>) -> bool;
|
||||
|
||||
op ==(RangeInclusive<int>, Range<int>) -> bool;
|
||||
op !=(RangeInclusive<int>, Range<int>) -> bool;
|
||||
|
||||
op ==(Range<int>, Range<int>) -> bool;
|
||||
op !=(Range<int>, Range<int>) -> bool;
|
||||
|
||||
op ==(RangeInclusive<int>, RangeInclusive<int>) -> bool;
|
||||
op !=(RangeInclusive<int>, RangeInclusive<int>) -> bool;
|
||||
|
||||
op ==(?, ?) -> bool;
|
||||
op !=(?, ?) -> bool;
|
||||
op >(?, ?) -> bool;
|
||||
op >=(?, ?) -> bool;
|
||||
op <(?, ?) -> bool;
|
||||
op <=(?, ?) -> bool;
|
||||
|
||||
|
||||
op &=(bool, bool);
|
||||
op |=(bool, bool);
|
||||
|
||||
op +=(int, int);
|
||||
op -=(int, int);
|
||||
op *=(int, int);
|
||||
op /=(int, int);
|
||||
op %=(int, int);
|
||||
op **=(int, int);
|
||||
op >>=(int, int);
|
||||
op <<=(int, int);
|
||||
op &=(int, int);
|
||||
op |=(int, int);
|
||||
op ^=(int, int);
|
||||
|
||||
op +=(float, float);
|
||||
op -=(float, float);
|
||||
op *=(float, float);
|
||||
op /=(float, float);
|
||||
op %=(float, float);
|
||||
op **=(float, float);
|
||||
|
||||
op +=(float, int);
|
||||
op -=(float, int);
|
||||
op *=(float, int);
|
||||
op /=(float, int);
|
||||
op %=(float, int);
|
||||
op **=(float, int);
|
||||
|
||||
op +=(Decimal, Decimal);
|
||||
op -=(Decimal, Decimal);
|
||||
op *=(Decimal, Decimal);
|
||||
op /=(Decimal, Decimal);
|
||||
op %=(Decimal, Decimal);
|
||||
op **=(Decimal, Decimal);
|
||||
|
||||
op +=(Decimal, int);
|
||||
op -=(Decimal, int);
|
||||
op *=(Decimal, int);
|
||||
op /=(Decimal, int);
|
||||
op %=(Decimal, int);
|
||||
op **=(Decimal, int);
|
||||
|
||||
op +=(String, String);
|
||||
op -=(String, String);
|
||||
op +=(String, char);
|
||||
op -=(String, char);
|
||||
op +=(char, String);
|
||||
op +=(char, char);
|
||||
|
||||
op +=(Array, Array);
|
||||
op +=(Array, ?);
|
||||
|
||||
op +=(Blob, Blob);
|
||||
op +=(Blob, int);
|
||||
op +=(Blob, char);
|
||||
op +=(Blob, String);
|
||||
|
||||
op in(?, Array) -> bool;
|
||||
op in(String, String) -> bool;
|
||||
op in(char, String) -> bool;
|
||||
op in(int, Range<int>) -> bool;
|
||||
op in(int, RangeInclusive<int>) -> bool;
|
||||
op in(String, Map) -> bool;
|
||||
op in(int, Blob) -> bool;
|
@@ -1,261 +0,0 @@
|
||||
module static;
|
||||
|
||||
/// Display any data to the standard output.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rhai
|
||||
/// let answer = 42;
|
||||
///
|
||||
/// print(`The Answer is ${answer}`);
|
||||
/// ```
|
||||
fn print(data: ?);
|
||||
|
||||
/// Display any data to the standard output in debug format.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rhai
|
||||
/// let answer = 42;
|
||||
///
|
||||
/// debug(answer);
|
||||
/// ```
|
||||
fn debug(data: ?);
|
||||
|
||||
/// Get the type of a value.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rhai
|
||||
/// let x = "hello, world!";
|
||||
///
|
||||
/// print(x.type_of()); // prints "string"
|
||||
/// ```
|
||||
fn type_of(data: ?) -> String;
|
||||
|
||||
/// Create a function pointer to a named function.
|
||||
///
|
||||
/// If the specified name is not a valid function name, an error is raised.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rhai
|
||||
/// let f = Fn("foo"); // function pointer to 'foo'
|
||||
///
|
||||
/// f.call(42); // call: foo(42)
|
||||
/// ```
|
||||
fn Fn(fn_name: String) -> FnPtr;
|
||||
|
||||
/// Call a function pointed to by a function pointer,
|
||||
/// passing following arguments to the function call.
|
||||
///
|
||||
/// If an appropriate function is not found, an error is raised.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rhai
|
||||
/// let f = Fn("foo"); // function pointer to 'foo'
|
||||
///
|
||||
/// f.call(1, 2, 3); // call: foo(1, 2, 3)
|
||||
/// ```
|
||||
fn call(fn_ptr: FnPtr, ...args: ?) -> ?;
|
||||
|
||||
/// Call a function pointed to by a function pointer, binding the `this` pointer
|
||||
/// to the object of the method call, and passing on following arguments to the function call.
|
||||
///
|
||||
/// If an appropriate function is not found, an error is raised.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rhai
|
||||
/// fn add(x) {
|
||||
/// this + x
|
||||
/// }
|
||||
///
|
||||
/// let f = Fn("add"); // function pointer to 'add'
|
||||
///
|
||||
/// let x = 41;
|
||||
///
|
||||
/// let r = x.call(f, 1); // call: add(1) with 'this' = 'x'
|
||||
///
|
||||
/// print(r); // prints 42
|
||||
/// ```
|
||||
fn call(obj: ?, fn_ptr: FnPtr, ...args: ?) -> ?;
|
||||
|
||||
/// Curry a number of arguments into a function pointer and return it as a new function pointer.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rhai
|
||||
/// fn foo(x, y, z) {
|
||||
/// x + y + z
|
||||
/// }
|
||||
///
|
||||
/// let f = Fn("foo");
|
||||
///
|
||||
/// let g = f.curry(1, 2); // curried arguments: 1, 2
|
||||
///
|
||||
/// g.call(3); // call: foo(1, 2, 3)
|
||||
/// ```
|
||||
fn curry(fn_ptr: FnPtr, ...args: ?) -> FnPtr;
|
||||
|
||||
/// Return `true` if a script-defined function exists with a specified name and
|
||||
/// number of parameters.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rhai
|
||||
/// fn foo(x) { }
|
||||
///
|
||||
/// print(is_def_fn("foo", 1)); // prints true
|
||||
/// print(is_def_fn("foo", 2)); // prints false
|
||||
/// print(is_def_fn("foo", 0)); // prints false
|
||||
/// print(is_def_fn("bar", 1)); // prints false
|
||||
/// ```
|
||||
fn is_def_fn(fn_name: String, num_params: int) -> bool;
|
||||
|
||||
/// Return `true` if a variable matching a specified name is defined.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rhai
|
||||
/// let x = 42;
|
||||
///
|
||||
/// print(is_def_var("x")); // prints true
|
||||
/// print(is_def_var("foo")); // prints false
|
||||
///
|
||||
/// {
|
||||
/// let y = 1;
|
||||
/// print(is_def_var("y")); // prints true
|
||||
/// }
|
||||
///
|
||||
/// print(is_def_var("y")); // prints false
|
||||
/// ```
|
||||
fn is_def_var(var_name: String) -> bool;
|
||||
|
||||
/// Return `true` if the variable is shared.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rhai
|
||||
/// let x = 42;
|
||||
///
|
||||
/// print(is_shared(x)); // prints false
|
||||
///
|
||||
/// let f = || x; // capture 'x', making it shared
|
||||
///
|
||||
/// print(is_shared(x)); // prints true
|
||||
/// ```
|
||||
fn is_shared(variable: ?) -> bool;
|
||||
|
||||
/// Evaluate a text script within the current scope.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rhai
|
||||
/// let x = 42;
|
||||
///
|
||||
/// eval("let y = x; x = 123;");
|
||||
///
|
||||
/// print(x); // prints 123
|
||||
/// print(y); // prints 42
|
||||
/// ```
|
||||
fn eval(script: String) -> ?;
|
||||
|
||||
/// Return `true` if the string contains another string.
|
||||
///
|
||||
/// This function also drives the `in` operator.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rhai
|
||||
/// let x = "hello world!";
|
||||
///
|
||||
/// // The 'in' operator calls 'contains' in the background
|
||||
/// if "world" in x {
|
||||
/// print("found!");
|
||||
/// }
|
||||
/// ```
|
||||
fn contains(string: String, find: String) -> bool;
|
||||
|
||||
/// Return `true` if the string contains a character.
|
||||
///
|
||||
/// This function also drives the `in` operator.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rhai
|
||||
/// let x = "hello world!";
|
||||
///
|
||||
/// // The 'in' operator calls 'contains' in the background
|
||||
/// if 'w' in x {
|
||||
/// print("found!");
|
||||
/// }
|
||||
/// ```
|
||||
fn contains(string: String, ch: char) -> bool;
|
||||
|
||||
/// Return `true` if a value falls within the exclusive range.
|
||||
///
|
||||
/// This function also drives the `in` operator.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rhai
|
||||
/// let r = 1..100;
|
||||
///
|
||||
/// // The 'in' operator calls 'contains' in the background
|
||||
/// if 42 in r {
|
||||
/// print("found!");
|
||||
/// }
|
||||
/// ```
|
||||
fn contains(range: Range<int>, value: int) -> bool;
|
||||
|
||||
/// Return `true` if a value falls within the inclusive range.
|
||||
///
|
||||
/// This function also drives the `in` operator.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rhai
|
||||
/// let r = 1..=100;
|
||||
///
|
||||
/// // The 'in' operator calls 'contains' in the background
|
||||
/// if 42 in r {
|
||||
/// print("found!");
|
||||
/// }
|
||||
/// ```
|
||||
fn contains(range: RangeInclusive<int>, value: int) -> bool;
|
||||
|
||||
/// Return `true` if a key exists within the object map.
|
||||
///
|
||||
/// This function also drives the `in` operator.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rhai
|
||||
/// let m = #{a:1, b:2, c:3};
|
||||
///
|
||||
/// // The 'in' operator calls 'contains' in the background
|
||||
/// if "c" in m {
|
||||
/// print("found!");
|
||||
/// }
|
||||
/// ```
|
||||
fn contains(map: Map, string: String) -> bool;
|
||||
|
||||
/// Return `true` if a value is found within the BLOB.
|
||||
///
|
||||
/// This function also drives the `in` operator.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rhai
|
||||
/// let b = blob();
|
||||
///
|
||||
/// b += 1; b += 2; b += 3; b += 4; b += 5;
|
||||
///
|
||||
/// // The 'in' operator calls 'contains' in the background
|
||||
/// if 3 in b {
|
||||
/// print("found!");
|
||||
/// }
|
||||
/// ```
|
||||
fn contains(blob: Blob, value: int) -> bool;
|
@@ -1,5 +0,0 @@
|
||||
module static;
|
||||
|
||||
let hello_there: string;
|
||||
|
||||
const HELLO: string;
|
File diff suppressed because it is too large
Load Diff
@@ -1,6 +0,0 @@
|
||||
module general_kenobi;
|
||||
|
||||
const CONSTANT: int;
|
||||
|
||||
/// Returns a string where "hello there" is repeated `n` times.
|
||||
fn hello_there(n: int) -> String;
|
@@ -1,49 +0,0 @@
|
||||
{
|
||||
"modules": {
|
||||
"general_kenobi": {
|
||||
"functions": [
|
||||
{
|
||||
"baseHash": 3873007749982070651,
|
||||
"fullHash": 5865213555928423624,
|
||||
"namespace": "internal",
|
||||
"access": "public",
|
||||
"name": "hello_there",
|
||||
"type": "native",
|
||||
"numParams": 1,
|
||||
"params": [
|
||||
{
|
||||
"name": "n",
|
||||
"type": "i64"
|
||||
}
|
||||
],
|
||||
"returnType": "String",
|
||||
"signature": "hello_there(n: i64) -> String",
|
||||
"docComments": [
|
||||
"/// Returns a string where \"hello there\" is repeated `n` times."
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"functions": [
|
||||
{
|
||||
"baseHash": 12461724250411739075,
|
||||
"fullHash": 14530626537296006176,
|
||||
"namespace": "global",
|
||||
"access": "public",
|
||||
"name": "minus",
|
||||
"type": "native",
|
||||
"numParams": 2,
|
||||
"params": [
|
||||
{
|
||||
"type": "i64"
|
||||
},
|
||||
{
|
||||
"type": "i64"
|
||||
}
|
||||
],
|
||||
"returnType": "i64",
|
||||
"signature": "minus(_: i64, _: i64) -> i64"
|
||||
}
|
||||
]
|
||||
}
|
@@ -1,70 +0,0 @@
|
||||
use rhai::plugin::*;
|
||||
use rhai::{Engine, EvalAltResult, Scope};
|
||||
|
||||
#[export_module]
|
||||
pub mod general_kenobi {
|
||||
/// General Kenobi's Constant.
|
||||
pub const CONSTANT: i64 = 42;
|
||||
|
||||
/// Returns a string where "hello there" is repeated `n` times.
|
||||
pub fn hello_there(n: i64) -> String {
|
||||
use std::convert::TryInto;
|
||||
"hello there ".repeat(n.try_into().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<EvalAltResult>> {
|
||||
let mut engine = Engine::new();
|
||||
let mut scope = Scope::new();
|
||||
|
||||
// This variable will also show up in the definitions, since it will be part of the scope.
|
||||
scope.push("hello_there", "hello there");
|
||||
|
||||
// This constant will also show up in the definitions, since it will be part of the scope.
|
||||
scope.push_constant("HELLO", "hello there");
|
||||
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
engine.register_static_module("general_kenobi", exported_module!(general_kenobi).into());
|
||||
|
||||
// Custom operators also show up in definitions.
|
||||
#[cfg(not(feature = "no_custom_syntax"))]
|
||||
{
|
||||
engine.register_custom_operator("minus", 100).unwrap();
|
||||
engine.register_fn("minus", |a: i64, b: i64| a - b);
|
||||
}
|
||||
|
||||
engine.run_with_scope(
|
||||
&mut scope,
|
||||
"hello_there = general_kenobi::hello_there(4 minus 2);",
|
||||
)?;
|
||||
|
||||
// Generate definitions for the contents of the engine and the scope.
|
||||
engine
|
||||
.definitions_with_scope(&scope)
|
||||
.write_to_dir("examples/definitions/.rhai/definitions")
|
||||
.unwrap();
|
||||
|
||||
// Alternatively we can write all of the above to a single file.
|
||||
engine
|
||||
.definitions_with_scope(&scope)
|
||||
.write_to_file("examples/definitions/.rhai/all_in_one.d.rhai")
|
||||
.unwrap();
|
||||
|
||||
// Skip standard packages if not needed (e.g. they are provided elsewhere).
|
||||
engine
|
||||
.definitions_with_scope(&scope)
|
||||
.include_standard_packages(false)
|
||||
.write_to_file("examples/definitions/.rhai/all_in_one_without_standard.d.rhai")
|
||||
.unwrap();
|
||||
|
||||
// Write function definitions as JSON.
|
||||
let json = engine
|
||||
.definitions()
|
||||
.include_standard_packages(false)
|
||||
.json()
|
||||
.unwrap();
|
||||
|
||||
std::fs::write("examples/definitions/.rhai/defs.json", json).unwrap();
|
||||
|
||||
Ok(())
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
// The following will be valid based on the definitions.
|
||||
hello_there = general_kenobi::hello_there(123);
|
||||
print(hello_there);
|
@@ -1,168 +0,0 @@
|
||||
//! Implementation of the Event Handler With State Pattern - JS Style
|
||||
|
||||
#[cfg(any(feature = "no_function", feature = "no_object"))]
|
||||
pub fn main() {
|
||||
panic!("This example does not run under 'no_function' or 'no_object'.")
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
pub fn main() {
|
||||
use rhai::{CallFnOptions, Dynamic, Engine, Map, Scope, AST};
|
||||
use std::io::{stdin, stdout, Write};
|
||||
|
||||
const SCRIPT_FILE: &str = "event_handler_js/script.rhai";
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Handler {
|
||||
pub engine: Engine,
|
||||
pub scope: Scope<'static>,
|
||||
pub states: Dynamic,
|
||||
pub ast: AST,
|
||||
}
|
||||
|
||||
fn print_scope(scope: &Scope) {
|
||||
for (i, (name, constant, value)) in scope.iter_raw().enumerate() {
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
let value_is_shared = if value.is_shared() { " (shared)" } else { "" };
|
||||
#[cfg(feature = "no_closure")]
|
||||
let value_is_shared = "";
|
||||
|
||||
println!(
|
||||
"[{}] {}{}{} = {:?}",
|
||||
i + 1,
|
||||
if constant { "const " } else { "" },
|
||||
name,
|
||||
value_is_shared,
|
||||
*value.read_lock::<Dynamic>().unwrap(),
|
||||
)
|
||||
}
|
||||
println!();
|
||||
}
|
||||
|
||||
println!("Events Handler Example - JS Style");
|
||||
println!("==================================");
|
||||
|
||||
let mut input = String::new();
|
||||
|
||||
// Read script file
|
||||
print!("Script file [{}]: ", SCRIPT_FILE);
|
||||
stdout().flush().expect("flush stdout");
|
||||
|
||||
input.clear();
|
||||
|
||||
stdin().read_line(&mut input).expect("read input");
|
||||
|
||||
let path = match input.trim() {
|
||||
"" => SCRIPT_FILE,
|
||||
path => path,
|
||||
};
|
||||
|
||||
// Create Engine
|
||||
let engine = Engine::new();
|
||||
|
||||
// Use an object map to hold state
|
||||
let mut states = Map::new();
|
||||
|
||||
// Default states can be added
|
||||
states.insert("bool_state".into(), Dynamic::FALSE);
|
||||
|
||||
// Convert the object map into 'Dynamic'
|
||||
let mut states: Dynamic = states.into();
|
||||
|
||||
// Create a custom 'Scope' to hold state
|
||||
let mut scope = Scope::new();
|
||||
|
||||
// Add any system-provided state into the custom 'Scope'.
|
||||
// Constants can be used to optimize the script.
|
||||
scope.push_constant("MY_CONSTANT", 42_i64);
|
||||
|
||||
// Compile the handler script.
|
||||
println!("> Loading script file: {path}");
|
||||
|
||||
let ast = match engine.compile_file_with_scope(&scope, path.into()) {
|
||||
Ok(ast) => ast,
|
||||
Err(err) => {
|
||||
eprintln!("! Error: {err}");
|
||||
println!("Cannot continue. Bye!");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
println!("> Script file loaded.");
|
||||
println!();
|
||||
println!("quit = exit program");
|
||||
println!("scope = print scope");
|
||||
println!("states = print states");
|
||||
println!("event arg = run function with argument");
|
||||
println!();
|
||||
|
||||
// Run the 'init' function to initialize the state, retaining variables.
|
||||
|
||||
let options = CallFnOptions::new()
|
||||
.eval_ast(false)
|
||||
.bind_this_ptr(&mut states);
|
||||
|
||||
let result = engine.call_fn_with_options::<()>(options, &mut scope, &ast, "init", ());
|
||||
|
||||
if let Err(err) = result {
|
||||
eprintln!("! {err}")
|
||||
}
|
||||
|
||||
// Create handler instance
|
||||
let mut handler = Handler {
|
||||
engine,
|
||||
scope,
|
||||
states,
|
||||
ast,
|
||||
};
|
||||
|
||||
// Events loop
|
||||
loop {
|
||||
print!("event> ");
|
||||
stdout().flush().expect("flush stdout");
|
||||
|
||||
// Read event
|
||||
input.clear();
|
||||
stdin().read_line(&mut input).expect("read input");
|
||||
|
||||
let mut fields = input.trim().splitn(2, ' ');
|
||||
|
||||
let event = fields.next().expect("event").trim();
|
||||
let arg = fields.next().unwrap_or("").to_string();
|
||||
|
||||
// Process event
|
||||
match event {
|
||||
"quit" => break,
|
||||
|
||||
"scope" => {
|
||||
print_scope(&handler.scope);
|
||||
continue;
|
||||
}
|
||||
|
||||
"states" => {
|
||||
println!("{:?}", handler.states);
|
||||
println!();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Map all other events to function calls
|
||||
_ => {
|
||||
let engine = &handler.engine;
|
||||
let scope = &mut handler.scope;
|
||||
let ast = &handler.ast;
|
||||
let options = CallFnOptions::new()
|
||||
.eval_ast(false)
|
||||
.bind_this_ptr(&mut handler.states);
|
||||
|
||||
let result = engine.call_fn_with_options::<()>(options, scope, ast, event, (arg,));
|
||||
|
||||
if let Err(err) = result {
|
||||
eprintln!("! {err}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!("Bye!");
|
||||
}
|
@@ -1,50 +0,0 @@
|
||||
//! Implementation of the Event Handler With State Pattern - JS Style
|
||||
|
||||
/// Initialize user-provided state.
|
||||
fn init() {
|
||||
// Can detect system-provided default states!
|
||||
// Add 'bool_state' as new state variable if one does not exist
|
||||
if "bool_state" !in this {
|
||||
this.bool_state = false;
|
||||
}
|
||||
// Add 'value' as new state variable (overwrites any existing)
|
||||
this.value = 0;
|
||||
|
||||
// Can also add OOP-style functions!
|
||||
this.log = |x| print(`State = ${this.value}, data = ${x}`);
|
||||
}
|
||||
|
||||
/// 'start' event handler
|
||||
fn start(data) {
|
||||
if this.bool_state {
|
||||
throw "Already started!";
|
||||
}
|
||||
if this.value <= 0 {
|
||||
throw "Conditions not yet ready to start!";
|
||||
}
|
||||
|
||||
// Constant 'MY_CONSTANT' in custom scope is also visible!
|
||||
print(`MY_CONSTANT = ${MY_CONSTANT}`);
|
||||
|
||||
this.value += parse_int(data);
|
||||
this.bool_state = true;
|
||||
}
|
||||
|
||||
/// 'end' event handler
|
||||
fn end(data) {
|
||||
if !this.bool_state {
|
||||
throw "Not yet started!";
|
||||
}
|
||||
if this.value > 0 {
|
||||
throw "Conditions not yet ready to end!";
|
||||
}
|
||||
this.value = parse_int(data);
|
||||
this.bool_state = false;
|
||||
}
|
||||
|
||||
/// 'update' event handler
|
||||
fn update(data) {
|
||||
let data = parse_int(data);
|
||||
this.value += data;
|
||||
this.log(data);
|
||||
}
|
@@ -1,139 +0,0 @@
|
||||
//! Implementation of the Event Handler With State Pattern - Main Style
|
||||
|
||||
#[cfg(feature = "no_function")]
|
||||
pub fn main() {
|
||||
panic!("This example does not run under 'no_function'.")
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
pub fn main() {
|
||||
use rhai::{CallFnOptions, Dynamic, Engine, Scope, AST};
|
||||
use std::io::{stdin, stdout, Write};
|
||||
|
||||
const SCRIPT_FILE: &str = "event_handler_main/script.rhai";
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Handler {
|
||||
pub engine: Engine,
|
||||
pub scope: Scope<'static>,
|
||||
pub ast: AST,
|
||||
}
|
||||
|
||||
fn print_scope(scope: &Scope) {
|
||||
for (i, (name, constant, value)) in scope.iter_raw().enumerate() {
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
let value_is_shared = if value.is_shared() { " (shared)" } else { "" };
|
||||
#[cfg(feature = "no_closure")]
|
||||
let value_is_shared = "";
|
||||
|
||||
println!(
|
||||
"[{}] {}{}{} = {:?}",
|
||||
i + 1,
|
||||
if constant { "const " } else { "" },
|
||||
name,
|
||||
value_is_shared,
|
||||
*value.read_lock::<Dynamic>().unwrap(),
|
||||
)
|
||||
}
|
||||
println!();
|
||||
}
|
||||
|
||||
println!("Events Handler Example - Main Style");
|
||||
println!("===================================");
|
||||
|
||||
let mut input = String::new();
|
||||
|
||||
// Read script file
|
||||
print!("Script file [{SCRIPT_FILE}]: ");
|
||||
stdout().flush().expect("flush stdout");
|
||||
|
||||
input.clear();
|
||||
|
||||
stdin().read_line(&mut input).expect("read input");
|
||||
|
||||
let path = match input.trim() {
|
||||
"" => SCRIPT_FILE,
|
||||
path => path,
|
||||
};
|
||||
|
||||
// Create Engine
|
||||
let engine = Engine::new();
|
||||
|
||||
// Create a custom 'Scope' to hold state
|
||||
let mut scope = Scope::new();
|
||||
|
||||
// Add any system-provided state into the custom 'Scope'.
|
||||
// Constants can be used to optimize the script.
|
||||
scope.push_constant("MY_CONSTANT", 42_i64);
|
||||
|
||||
// Compile the handler script.
|
||||
println!("> Loading script file: {path}");
|
||||
|
||||
let ast = match engine.compile_file_with_scope(&scope, path.into()) {
|
||||
Ok(ast) => ast,
|
||||
Err(err) => {
|
||||
eprintln!("! Error: {}", err);
|
||||
println!("Cannot continue. Bye!");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
println!("> Script file loaded.");
|
||||
println!();
|
||||
println!("quit = exit program");
|
||||
println!("scope = print scope");
|
||||
println!("event arg = run function with argument");
|
||||
println!();
|
||||
|
||||
// Run the 'init' function to initialize the state, retaining variables.
|
||||
let options = CallFnOptions::new().eval_ast(false).rewind_scope(false);
|
||||
|
||||
let result = engine.call_fn_with_options::<()>(options, &mut scope, &ast, "init", ());
|
||||
|
||||
if let Err(err) = result {
|
||||
eprintln!("! {err}")
|
||||
}
|
||||
|
||||
// Create handler instance
|
||||
let mut handler = Handler { engine, scope, ast };
|
||||
|
||||
// Events loop
|
||||
loop {
|
||||
print!("event> ");
|
||||
stdout().flush().expect("flush stdout");
|
||||
|
||||
// Read event
|
||||
input.clear();
|
||||
stdin().read_line(&mut input).expect("read input");
|
||||
|
||||
let mut fields = input.trim().splitn(2, ' ');
|
||||
|
||||
let event = fields.next().expect("event").trim();
|
||||
let arg = fields.next().unwrap_or("").to_string();
|
||||
|
||||
// Process event
|
||||
match event {
|
||||
"quit" => break,
|
||||
|
||||
"scope" => {
|
||||
print_scope(&handler.scope);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Map all other events to function calls
|
||||
_ => {
|
||||
let engine = &handler.engine;
|
||||
let scope = &mut handler.scope;
|
||||
let ast = &handler.ast;
|
||||
|
||||
let result = engine.call_fn::<()>(scope, ast, event, (arg,));
|
||||
|
||||
if let Err(err) = result {
|
||||
eprintln!("! {err}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!("Bye!");
|
||||
}
|
@@ -1,56 +0,0 @@
|
||||
//! Implementation of the Event Handler With State Pattern - Main Style
|
||||
|
||||
/// Initialize user-provided state (shadows system-provided state, if any).
|
||||
fn init() {
|
||||
// Add 'bool_state' and 'value' as new state variables
|
||||
let bool_state = false;
|
||||
let value = 0;
|
||||
|
||||
// Constants can also be added!
|
||||
const EXTRA_CONSTANT = "hello, world!";
|
||||
}
|
||||
|
||||
/// Without 'OOP' support, the can only be a function.
|
||||
fn log(value, data) {
|
||||
print(`State = ${value}, data = ${data}`);
|
||||
}
|
||||
|
||||
/// 'start' event handler
|
||||
fn start(data) {
|
||||
if bool_state {
|
||||
throw "Already started!";
|
||||
}
|
||||
if value <= 0 {
|
||||
throw "Conditions not yet ready to start!";
|
||||
}
|
||||
|
||||
// Constants 'MY_CONSTANT' and 'EXTRA_CONSTANT'
|
||||
// in custom scope are also visible!
|
||||
print(`MY_CONSTANT = ${MY_CONSTANT}`);
|
||||
print(`EXTRA_CONSTANT = ${EXTRA_CONSTANT}`);
|
||||
|
||||
value += parse_int(data);
|
||||
bool_state = true;
|
||||
}
|
||||
|
||||
/// 'end' event handler
|
||||
fn end(data) {
|
||||
if !bool_state {
|
||||
throw "Not yet started!";
|
||||
}
|
||||
if value > 0 {
|
||||
throw "Conditions not yet ready to end!";
|
||||
}
|
||||
value = parse_int(data);
|
||||
bool_state = false;
|
||||
}
|
||||
|
||||
/// 'update' event handler
|
||||
fn update(data) {
|
||||
let data = parse_int(data);
|
||||
|
||||
value += data;
|
||||
|
||||
// Without OOP support, can only call function
|
||||
log(value, data);
|
||||
}
|
@@ -1,151 +0,0 @@
|
||||
//! Implementation of the Event Handler With State Pattern - Map Style
|
||||
|
||||
#[cfg(any(feature = "no_function", feature = "no_object"))]
|
||||
pub fn main() {
|
||||
panic!("This example does not run under 'no_function' or 'no_object'.")
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
pub fn main() {
|
||||
use rhai::{Dynamic, Engine, Map, Scope, AST};
|
||||
use std::io::{stdin, stdout, Write};
|
||||
|
||||
const SCRIPT_FILE: &str = "event_handler_map/script.rhai";
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Handler {
|
||||
pub engine: Engine,
|
||||
pub scope: Scope<'static>,
|
||||
pub ast: AST,
|
||||
}
|
||||
|
||||
fn print_scope(scope: &Scope) {
|
||||
for (i, (name, constant, value)) in scope.iter_raw().enumerate() {
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
let value_is_shared = if value.is_shared() { " (shared)" } else { "" };
|
||||
#[cfg(feature = "no_closure")]
|
||||
let value_is_shared = "";
|
||||
|
||||
println!(
|
||||
"[{}] {}{}{} = {:?}",
|
||||
i + 1,
|
||||
if constant { "const " } else { "" },
|
||||
name,
|
||||
value_is_shared,
|
||||
*value.read_lock::<Dynamic>().unwrap(),
|
||||
)
|
||||
}
|
||||
println!();
|
||||
}
|
||||
|
||||
println!("Events Handler Example - Map Style");
|
||||
println!("==================================");
|
||||
|
||||
let mut input = String::new();
|
||||
|
||||
// Read script file
|
||||
print!("Script file [{}]: ", SCRIPT_FILE);
|
||||
stdout().flush().expect("flush stdout");
|
||||
|
||||
input.clear();
|
||||
|
||||
stdin().read_line(&mut input).expect("read input");
|
||||
|
||||
let path = match input.trim() {
|
||||
"" => SCRIPT_FILE,
|
||||
path => path,
|
||||
};
|
||||
|
||||
// Create Engine
|
||||
let mut engine = Engine::new();
|
||||
|
||||
// Prevent shadowing of `state`
|
||||
#[allow(deprecated)]
|
||||
engine.on_def_var(|_, info, _| Ok(info.name() != "state"));
|
||||
|
||||
// Create a custom 'Scope' to hold state
|
||||
let mut scope = Scope::new();
|
||||
|
||||
// Add any system-provided state into the custom 'Scope'.
|
||||
// Constants can be used to optimize the script.
|
||||
scope.push_constant("MY_CONSTANT", 42_i64);
|
||||
|
||||
// Use an object map to hold state
|
||||
let mut states = Map::new();
|
||||
|
||||
// Default states can be added
|
||||
states.insert("bool_state".into(), Dynamic::FALSE);
|
||||
|
||||
// Add the main states-holding object map and call it 'state'
|
||||
scope.push("state", states);
|
||||
|
||||
// Compile the handler script.
|
||||
println!("> Loading script file: {path}");
|
||||
|
||||
let ast = match engine.compile_file_with_scope(&scope, path.into()) {
|
||||
Ok(ast) => ast,
|
||||
Err(err) => {
|
||||
eprintln!("! Error: {err}");
|
||||
println!("Cannot continue. Bye!");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
println!("> Script file loaded.");
|
||||
println!();
|
||||
println!("quit = exit program");
|
||||
println!("scope = print scope");
|
||||
println!("event arg = run function with argument");
|
||||
println!();
|
||||
|
||||
// Run the 'init' function to initialize the state, retaining variables.
|
||||
let result = engine.call_fn::<()>(&mut scope, &ast, "init", ());
|
||||
|
||||
if let Err(err) = result {
|
||||
eprintln!("! {err}")
|
||||
}
|
||||
|
||||
// Create handler instance
|
||||
let mut handler = Handler { engine, scope, ast };
|
||||
|
||||
// Events loop
|
||||
loop {
|
||||
print!("event> ");
|
||||
stdout().flush().expect("flush stdout");
|
||||
|
||||
// Read event
|
||||
input.clear();
|
||||
stdin().read_line(&mut input).expect("read input");
|
||||
|
||||
let mut fields = input.trim().splitn(2, ' ');
|
||||
|
||||
let event = fields.next().expect("event").trim();
|
||||
let arg = fields.next().unwrap_or("").to_string();
|
||||
|
||||
// Process event
|
||||
match event {
|
||||
"quit" => break,
|
||||
|
||||
"scope" => {
|
||||
print_scope(&handler.scope);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Map all other events to function calls
|
||||
_ => {
|
||||
let engine = &handler.engine;
|
||||
let scope = &mut handler.scope;
|
||||
let ast = &handler.ast;
|
||||
|
||||
let result = engine.call_fn::<()>(scope, ast, event, (arg,));
|
||||
|
||||
if let Err(err) = result {
|
||||
eprintln!("! {err}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!("Bye!");
|
||||
}
|
@@ -1,58 +0,0 @@
|
||||
//! Implementation of the Event Handler With State Pattern - Map Style
|
||||
|
||||
/// Initialize user-provided state.
|
||||
/// State is stored inside an object map bound to 'state'.
|
||||
fn init() {
|
||||
// Add 'bool_state' as new state variable if one does not exist
|
||||
if "bool_state" !in state {
|
||||
state.bool_state = false;
|
||||
}
|
||||
// Add 'obj_state' as new state variable (overwrites any existing)
|
||||
state.value = 0;
|
||||
|
||||
// Can also add OOP-style functions!
|
||||
state.log = |x| print(`State = ${this.value}, data = ${x}`);
|
||||
}
|
||||
|
||||
/// 'start' event handler
|
||||
fn start(data) {
|
||||
// Can detect system-provided default states!
|
||||
// Access state variables in 'state'
|
||||
if state.bool_state {
|
||||
throw "Already started!";
|
||||
}
|
||||
|
||||
// New values can be added to the state
|
||||
state.start_mode = data;
|
||||
|
||||
if state.value <= 0 {
|
||||
throw "Conditions not yet ready to start!";
|
||||
}
|
||||
|
||||
// Constant 'MY_CONSTANT' in custom scope is also visible!
|
||||
print(`MY_CONSTANT = ${MY_CONSTANT}`);
|
||||
|
||||
state.value = parse_int(data);
|
||||
state.bool_state = true;
|
||||
}
|
||||
|
||||
/// 'end' event handler
|
||||
fn end(data) {
|
||||
if !state.bool_state || "start_mode" !in state {
|
||||
throw "Not yet started!";
|
||||
}
|
||||
if state.value > 0 {
|
||||
throw "Conditions not yet ready to end!";
|
||||
}
|
||||
state.value = parse_int(data);
|
||||
state.bool_state = false;
|
||||
}
|
||||
|
||||
/// 'update' event handler
|
||||
fn update(data) {
|
||||
let data = parse_int(data);
|
||||
state.value += data;
|
||||
|
||||
// Call user-defined function OOP-style!
|
||||
state.log(data);
|
||||
}
|
@@ -1,15 +0,0 @@
|
||||
//! A simple example that evaluates an expression and prints the result.
|
||||
|
||||
use rhai::{Engine, EvalAltResult};
|
||||
|
||||
fn main() -> Result<(), Box<EvalAltResult>> {
|
||||
let engine = Engine::new();
|
||||
|
||||
engine.run(r#"print("hello, world!")"#)?;
|
||||
|
||||
let result = engine.eval::<i64>("40 + 2")?;
|
||||
|
||||
println!("The Answer: {result}"); // prints 42
|
||||
|
||||
Ok(())
|
||||
}
|
@@ -1,112 +0,0 @@
|
||||
//! An advanced example showing how to pause/resume/stop an `Engine` via an MPSC channel.
|
||||
|
||||
#[cfg(feature = "unchecked")]
|
||||
fn main() {
|
||||
panic!("This example does not run under 'unchecked'.");
|
||||
}
|
||||
|
||||
use rhai::{Dynamic, Engine};
|
||||
|
||||
#[cfg(feature = "sync")]
|
||||
use std::sync::Mutex;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
fn main() {
|
||||
let (tx, rx) = std::sync::mpsc::channel::<String>();
|
||||
|
||||
#[cfg(feature = "sync")]
|
||||
let rx = Mutex::new(rx);
|
||||
|
||||
// Spawn thread with Engine, capturing the channel
|
||||
std::thread::spawn(move || {
|
||||
// Create Engine
|
||||
let mut engine = Engine::new();
|
||||
|
||||
engine.on_progress(move |_ops| {
|
||||
#[cfg(feature = "sync")]
|
||||
if _ops % 5 != 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
#[cfg(feature = "sync")]
|
||||
let rx = &*rx.lock().unwrap();
|
||||
|
||||
let mut paused = false;
|
||||
|
||||
loop {
|
||||
match rx.try_recv() {
|
||||
Ok(cmd) => match cmd.as_str() {
|
||||
"pause" => {
|
||||
println!("[Thread] Script paused. Type 'resume' to continue or 'stop' to terminate.");
|
||||
paused = true;
|
||||
}
|
||||
"resume" => {
|
||||
println!("[Thread] Resuming script...");
|
||||
return None;
|
||||
}
|
||||
"stop" => {
|
||||
println!("[Thread] Stopping script...");
|
||||
return Some(Dynamic::UNIT);
|
||||
}
|
||||
cmd if paused => {
|
||||
println!("[Thread] I don't understand '{cmd}'!");
|
||||
println!("Type 'resume' to continue script, or 'stop' to terminate!");
|
||||
}
|
||||
_ => {
|
||||
println!("[Thread] I don't understand '{cmd}'!");
|
||||
return None;
|
||||
}
|
||||
},
|
||||
Err(_) if paused => (),
|
||||
Err(_) => return None,
|
||||
}
|
||||
|
||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||
}
|
||||
});
|
||||
|
||||
// Run script
|
||||
let _ = engine
|
||||
.run(
|
||||
r#"
|
||||
let counter = 0;
|
||||
|
||||
loop {
|
||||
print("[Script] One Potato...");
|
||||
sleep(1);
|
||||
|
||||
counter += 1;
|
||||
|
||||
print("[Script] Two Potatoes...");
|
||||
sleep(1);
|
||||
|
||||
print(`[Script] Boring Counter: ${counter}...`);
|
||||
sleep(1);
|
||||
|
||||
print("[Script] Three Potatoes...");
|
||||
sleep(1);
|
||||
}
|
||||
"#,
|
||||
)
|
||||
.expect_err("Error expected");
|
||||
|
||||
println!("[Thread] Script stopped!");
|
||||
});
|
||||
|
||||
println!("[Main] Type 'pause' or 'stop' to control the script.");
|
||||
|
||||
let mut input = String::new();
|
||||
|
||||
loop {
|
||||
input.clear();
|
||||
|
||||
match std::io::stdin().read_line(&mut input) {
|
||||
Ok(0) => (),
|
||||
Ok(_) => match tx.send(input.trim().to_string()) {
|
||||
Ok(_) => (),
|
||||
Err(_) => break,
|
||||
},
|
||||
Err(_) => break,
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,22 +0,0 @@
|
||||
//! An example that evaluates two pieces of code in separate runs, but using a common `Scope`.
|
||||
|
||||
use rhai::{Engine, EvalAltResult, Scope};
|
||||
|
||||
fn main() -> Result<(), Box<EvalAltResult>> {
|
||||
let engine = Engine::new();
|
||||
let mut scope = Scope::new();
|
||||
|
||||
engine.run_with_scope(&mut scope, "let x = 4 + 5")?;
|
||||
|
||||
println!("x = {}", scope.get_value::<i64>("x").unwrap());
|
||||
|
||||
for _ in 0..10 {
|
||||
let result = engine.eval_with_scope::<i64>(&mut scope, "x += 1; x")?;
|
||||
|
||||
println!("result: {result}");
|
||||
}
|
||||
|
||||
println!("x = {}", scope.get_value::<i64>("x").unwrap());
|
||||
|
||||
Ok(())
|
||||
}
|
@@ -1,86 +0,0 @@
|
||||
//! An example to serialize and deserialize Rust types.
|
||||
|
||||
#[cfg(feature = "no_object")]
|
||||
fn main() {
|
||||
panic!("This example does not run under 'no_object'.")
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
fn main() {
|
||||
use rhai::serde::{from_dynamic, to_dynamic};
|
||||
use rhai::{Dynamic, Engine, Map};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
struct Point {
|
||||
x: f64,
|
||||
y: f64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
struct MyStruct {
|
||||
a: i64,
|
||||
b: Vec<String>,
|
||||
c: bool,
|
||||
d: Point,
|
||||
}
|
||||
|
||||
pub fn ser() {
|
||||
let x = MyStruct {
|
||||
a: 42,
|
||||
b: vec!["hello".into(), "world".into()],
|
||||
c: true,
|
||||
d: Point {
|
||||
x: 123.456,
|
||||
y: 999.0,
|
||||
},
|
||||
};
|
||||
|
||||
println!("Source struct: {x:#?}");
|
||||
|
||||
// Convert the 'MyStruct' into a 'Dynamic'
|
||||
let map: Dynamic = to_dynamic(x).unwrap();
|
||||
|
||||
assert!(map.is::<Map>());
|
||||
println!("Serialized to Dynamic: {map:#?}");
|
||||
}
|
||||
|
||||
pub fn de() {
|
||||
let engine = Engine::new();
|
||||
let result: Dynamic = engine
|
||||
.eval(
|
||||
r#"
|
||||
#{
|
||||
a: 42,
|
||||
b: [ "hello", "world" ],
|
||||
c: true,
|
||||
d: #{ x: 123.456, y: 999.0 }
|
||||
}
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
println!("Source Dynamic: {result:#?}");
|
||||
|
||||
// Convert the 'Dynamic' object map into 'MyStruct'
|
||||
let x: MyStruct = from_dynamic(&result).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
x,
|
||||
MyStruct {
|
||||
a: 42,
|
||||
b: vec!["hello".into(), "world".into()],
|
||||
c: true,
|
||||
d: Point {
|
||||
x: 123.456,
|
||||
y: 999.0,
|
||||
},
|
||||
}
|
||||
);
|
||||
println!("Deserialized to struct: {x:#?}");
|
||||
}
|
||||
|
||||
ser();
|
||||
println!();
|
||||
de();
|
||||
}
|
@@ -1,19 +0,0 @@
|
||||
//! An example showing how to register a simple Rust function.
|
||||
|
||||
use rhai::{Engine, EvalAltResult};
|
||||
|
||||
fn add(x: i64, y: i64) -> i64 {
|
||||
x + y
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<EvalAltResult>> {
|
||||
let mut engine = Engine::new();
|
||||
|
||||
engine.register_fn("add", add);
|
||||
|
||||
let result = engine.eval::<i64>("add(40, 2)")?;
|
||||
|
||||
println!("Answer: {result}"); // prints 42
|
||||
|
||||
Ok(())
|
||||
}
|
@@ -1,79 +0,0 @@
|
||||
//! An example that registers a variety of functions that operate on strings.
|
||||
//! Remember to use `ImmutableString` or `&str` instead of `String` as parameters.
|
||||
|
||||
use rhai::{Engine, EvalAltResult, ImmutableString, Scope};
|
||||
use std::io::{stdin, stdout, Write};
|
||||
|
||||
/// Trim whitespace from a string. The original string argument is changed.
|
||||
///
|
||||
/// This version uses `&mut ImmutableString`
|
||||
fn trim_string(s: &mut ImmutableString) {
|
||||
*s = s.trim().into();
|
||||
}
|
||||
|
||||
/// Notice this is different from the built-in Rhai 'len' function for strings
|
||||
/// which counts the actual number of Unicode _characters_ in a string.
|
||||
///
|
||||
/// This version simply counts the number of _bytes_ in the UTF-8 representation.
|
||||
///
|
||||
/// This version uses `&str`.
|
||||
fn count_string_bytes(s: &str) -> i64 {
|
||||
s.len() as i64
|
||||
}
|
||||
|
||||
/// This version uses `ImmutableString` and `&str`.
|
||||
fn find_substring(s: ImmutableString, sub: &str) -> i64 {
|
||||
s.find(sub).map(|x| x as i64).unwrap_or(-1)
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<EvalAltResult>> {
|
||||
// Create a `raw` Engine with no built-in string functions.
|
||||
let mut engine = Engine::new_raw();
|
||||
|
||||
engine
|
||||
// Register string functions
|
||||
.register_fn("trim", trim_string)
|
||||
.register_fn("len", count_string_bytes)
|
||||
.register_fn("index_of", find_substring)
|
||||
// Register string functions using closures
|
||||
.register_fn("display", |label: &str, value: i64| {
|
||||
println!("{label}: {value}")
|
||||
})
|
||||
.register_fn("display", |label: ImmutableString, value: &str| {
|
||||
println!(r#"{label}: "{value}""#) // Quote the input string
|
||||
});
|
||||
|
||||
let mut scope = Scope::new();
|
||||
let mut input = String::new();
|
||||
|
||||
loop {
|
||||
scope.clear();
|
||||
|
||||
println!("Type something. Press Ctrl-C to exit.");
|
||||
print!("strings> ");
|
||||
stdout().flush().expect("couldn't flush stdout");
|
||||
|
||||
input.clear();
|
||||
|
||||
if let Err(err) = stdin().read_line(&mut input) {
|
||||
panic!("input error: {}", err);
|
||||
}
|
||||
|
||||
scope.push("x", input.clone());
|
||||
|
||||
println!("Line: {}", input.replace('\r', "\\r").replace('\n', "\\n"));
|
||||
|
||||
engine.run_with_scope(
|
||||
&mut scope,
|
||||
r#"
|
||||
display("Length", x.len());
|
||||
x.trim();
|
||||
display("Trimmed", x);
|
||||
display("Trimmed Length", x.len());
|
||||
display("Index of \"!!!\"", x.index_of("!!!"));
|
||||
"#,
|
||||
)?;
|
||||
|
||||
println!();
|
||||
}
|
||||
}
|
@@ -1,69 +0,0 @@
|
||||
//! An advanced example showing how to communicate with an `Engine` running in a separate thread via
|
||||
//! an MPSC channel.
|
||||
|
||||
use rhai::Engine;
|
||||
|
||||
#[cfg(feature = "sync")]
|
||||
use std::sync::Mutex;
|
||||
|
||||
fn main() {
|
||||
// Channel: Script -> Master
|
||||
let (tx_script, rx_master) = std::sync::mpsc::channel();
|
||||
// Channel: Master -> Script
|
||||
let (tx_master, rx_script) = std::sync::mpsc::channel();
|
||||
|
||||
#[cfg(feature = "sync")]
|
||||
let (tx_script, rx_script) = (Mutex::new(tx_script), Mutex::new(rx_script));
|
||||
|
||||
// Spawn thread with Engine
|
||||
std::thread::spawn(move || {
|
||||
// Create Engine
|
||||
let mut engine = Engine::new();
|
||||
|
||||
// Register API
|
||||
// Notice that the API functions are blocking
|
||||
|
||||
#[cfg(not(feature = "sync"))]
|
||||
engine
|
||||
.register_fn("get", move || rx_script.recv().unwrap_or_default())
|
||||
.register_fn("put", move |v: i64| tx_script.send(v).unwrap());
|
||||
|
||||
#[cfg(feature = "sync")]
|
||||
engine
|
||||
.register_fn("get", move || rx_script.lock().unwrap().recv().unwrap())
|
||||
.register_fn("put", move |v: i64| {
|
||||
tx_script.lock().unwrap().send(v).unwrap()
|
||||
});
|
||||
|
||||
// Run script
|
||||
engine
|
||||
.run(
|
||||
r#"
|
||||
print("Starting script loop...");
|
||||
|
||||
loop {
|
||||
let x = get();
|
||||
print(`Script Read: ${x}`);
|
||||
x += 1;
|
||||
print(`Script Write: ${x}`);
|
||||
put(x);
|
||||
}
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
});
|
||||
|
||||
// This is the main processing thread
|
||||
|
||||
println!("Starting main loop...");
|
||||
|
||||
let mut value: i64 = 0;
|
||||
|
||||
while value < 10 {
|
||||
println!("Value: {value}");
|
||||
// Send value to script
|
||||
tx_master.send(value).unwrap();
|
||||
// Receive value from script
|
||||
value = rx_master.recv().unwrap();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user