Merge pull request #229 from schungx/master

Plugins.
This commit is contained in:
Stephen Chung 2020-08-31 12:30:55 +08:00 committed by GitHub
commit 91963d10dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
147 changed files with 7825 additions and 1238 deletions

View File

@ -4,6 +4,7 @@ on:
push:
branches:
- master
- plugins
pull_request: {}
jobs:
@ -76,3 +77,25 @@ jobs:
with:
command: build
args: --manifest-path=no_std/no_std_test/Cargo.toml ${{matrix.flags}}
codegen_build:
name: Codegen Build
runs-on: ${{matrix.os}}
continue-on-error: ${{matrix.experimental}}
strategy:
matrix:
include:
- {toolchain: nightly, os: ubuntu-latest, experimental: false, flags: ""}
- {toolchain: nightly, os: windows-latest, experimental: false, flags: ""}
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup Toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: ${{matrix.toolchain}}
override: true
- name: Build Project
uses: actions-rs/cargo@v1
with:
command: test
args: --manifest-path=codegen/Cargo.toml ${{matrix.flags}}

View File

@ -17,8 +17,8 @@ keywords = [ "scripting" ]
categories = [ "no-std", "embedded", "wasm", "parser-implementations" ]
[dependencies]
num-traits = { version = "0.2.11", default-features = false }
smallvec = { version = "1.4.1", default-features = false }
rhai_codegen = { version = "0.1", path = "codegen" }
[features]
#default = ["unchecked", "sync", "no_optimize", "no_float", "only_i32", "no_index", "no_object", "no_function", "no_module"]
@ -51,6 +51,11 @@ version = "0.2.1"
default_features = false
optional = true
[dependencies.num-traits]
version = "0.2.11"
default-features = false
optional = true
[dependencies.core-error]
version = "0.0.0"
default_features = false

View File

@ -17,6 +17,7 @@ Supported targets and builds
* All common CPU targets for Windows, Linux and MacOS.
* WebAssembly (WASM)
* `no-std`
* Minimum Rust version 1.45
Standard features
-----------------
@ -37,6 +38,7 @@ Standard features
* Serialization/deserialization support via [serde](https://crates.io/crates/serde) (requires the `serde` feature).
* Scripts are [optimized](https://schungx.github.io/rhai/engine/optimize.html) (useful for template-based machine-generated scripts) for repeated evaluations.
* Support for [minimal builds](https://schungx.github.io/rhai/start/builds/minimal.html) by excluding unneeded language [features](https://schungx.github.io/rhai/start/features.html).
* Easy custom API development via [plugins](https://schungx.github.io/rhai/plugins/index.html) system powered by procedural macros.
Protection against attacks
--------------------------

View File

@ -1,6 +1,15 @@
Rhai Release Notes
==================
Version 0.19.0
==============
New features
------------
* Plugins support via procedural macros.
Version 0.18.3
==============
@ -12,6 +21,15 @@ Bug fixes
* Closures that capture now work under `no_object`.
Version 0.18.2
==============
New features
------------
* Adds `Module::combine_flatten` to combine two modules while flattening to the root level.
Version 0.18.2
==============

21
codegen/Cargo.toml Normal file
View File

@ -0,0 +1,21 @@
[package]
name = "rhai_codegen"
version = "0.1.0"
edition = "2018"
authors = ["jhwgh1968", "Stephen Chung"]
description = "Proceducral macro support package for Rhai, a scripting language for Rust"
homepage = "https://github.com/jonathandturner/rhai"
repository = "https://github.com/jonathandturner/rhai"
license = "MIT OR Apache-2.0"
[lib]
proc-macro = true
[dev-dependencies]
rhai = { path = ".." }
trybuild = "1"
[dependencies]
proc-macro2 = "1"
syn = { version = "1", features = ["full", "parsing", "printing", "proc-macro", "extra-traits"] }
quote = "1"

117
codegen/src/attrs.rs Normal file
View File

@ -0,0 +1,117 @@
use syn::{parse::ParseStream, parse::Parser, spanned::Spanned};
pub trait ExportedParams: Sized {
fn parse_stream(args: ParseStream) -> syn::Result<Self>;
fn no_attrs() -> Self;
fn from_info(info: ExportInfo) -> syn::Result<Self>;
}
pub struct AttrItem {
pub key: proc_macro2::Ident,
pub value: Option<syn::LitStr>,
}
pub struct ExportInfo {
pub item_span: proc_macro2::Span,
pub items: Vec<AttrItem>,
}
pub fn parse_attr_items(args: ParseStream) -> syn::Result<ExportInfo> {
if args.is_empty() {
return Ok(ExportInfo { item_span: args.span(), items: Vec::new()});
}
let arg_list = args
.call(syn::punctuated::Punctuated::<syn::Expr, syn::Token![,]>::parse_separated_nonempty)?;
parse_punctuated_items(arg_list)
}
pub fn parse_punctuated_items(
arg_list: syn::punctuated::Punctuated<syn::Expr, syn::Token![,]>,
) -> syn::Result<ExportInfo> {
let list_span = arg_list.span();
let mut attrs: Vec<AttrItem> = Vec::new();
for arg in arg_list {
let (key, value) = match arg {
syn::Expr::Assign(syn::ExprAssign {
ref left,
ref right,
..
}) => {
let attr_name: syn::Ident = match left.as_ref() {
syn::Expr::Path(syn::ExprPath {
path: attr_path, ..
}) => attr_path.get_ident().cloned().ok_or_else(|| {
syn::Error::new(attr_path.span(), "expecting attribute name")
})?,
x => return Err(syn::Error::new(x.span(), "expecting attribute name")),
};
let attr_value = match right.as_ref() {
syn::Expr::Lit(syn::ExprLit {
lit: syn::Lit::Str(string),
..
}) => string.clone(),
x => return Err(syn::Error::new(x.span(), "expecting string literal")),
};
(attr_name, Some(attr_value))
}
syn::Expr::Path(syn::ExprPath {
path: attr_path, ..
}) => attr_path
.get_ident()
.cloned()
.map(|a| (a, None))
.ok_or_else(|| syn::Error::new(attr_path.span(), "expecting attribute name"))?,
x => return Err(syn::Error::new(x.span(), "expecting identifier")),
};
attrs.push(AttrItem { key, value });
}
Ok(ExportInfo { item_span: list_span, items: attrs })
}
pub(crate) fn outer_item_attributes<T: ExportedParams>(
args: proc_macro2::TokenStream,
_attr_name: &str,
) -> syn::Result<T> {
if args.is_empty() {
return Ok(T::no_attrs());
}
let parser = syn::punctuated::Punctuated::<syn::Expr, syn::Token![,]>::parse_separated_nonempty;
let arg_list = parser.parse2(args)?;
let export_info = parse_punctuated_items(arg_list)?;
T::from_info(export_info)
}
pub(crate) fn inner_item_attributes<T: ExportedParams>(
attrs: &mut Vec<syn::Attribute>,
attr_name: &str,
) -> syn::Result<T> {
// Find the #[rhai_fn] attribute which will turn be read for the function parameters.
if let Some(rhai_fn_idx) = attrs
.iter()
.position(|a| a.path.get_ident().map(|i| *i == attr_name).unwrap_or(false))
{
let rhai_fn_attr = attrs.remove(rhai_fn_idx);
rhai_fn_attr.parse_args_with(T::parse_stream)
} else {
Ok(T::no_attrs())
}
}
pub(crate) fn deny_cfg_attr(attrs: &Vec<syn::Attribute>) -> syn::Result<()> {
if let Some(cfg_attr) = attrs
.iter()
.find(|a| a.path.get_ident().map(|i| *i == "cfg").unwrap_or(false))
{
Err(syn::Error::new(
cfg_attr.span(),
"cfg attributes not allowed on this item",
))
} else {
Ok(())
}
}

1050
codegen/src/function.rs Normal file

File diff suppressed because it is too large Load Diff

172
codegen/src/lib.rs Normal file
View File

@ -0,0 +1,172 @@
//!
//! This crate contains procedural macros to make creating Rhai modules much easier.
//!
//! # Exporting a Macro to Rhai
//!
//! ```
//! use rhai::{EvalAltResult, FLOAT};
//! use rhai::plugin::*;
//! use rhai::module_resolvers::*;
//!
//! #[rhai::export_module]
//! pub mod advanced_math {
//! use rhai::FLOAT;
//!
//! pub const MYSTIC_NUMBER: FLOAT = 42.0 as FLOAT;
//!
//! pub fn euclidean_distance(x1: FLOAT, y1: FLOAT, x2: FLOAT, y2: FLOAT) -> FLOAT {
//! ((y2 - y1).abs().powf(2.0) + (x2 -x1).abs().powf(2.0)).sqrt()
//! }
//! }
//!
//! fn main() -> Result<(), Box<EvalAltResult>> {
//! let mut engine = Engine::new();
//! let m = rhai::exported_module!(advanced_math);
//! let mut r = StaticModuleResolver::new();
//! r.insert("Math::Advanced".to_string(), m);
//! engine.set_module_resolver(Some(r));
//!
//! assert_eq!(engine.eval::<FLOAT>(
//! r#"import "Math::Advanced" as math;
//! let m = math::MYSTIC_NUMBER;
//! let x = math::euclidean_distance(0.0, 1.0, 0.0, m);
//! x"#)?, 41.0);
//! Ok(())
//! }
//! ```
//!
//! # Exporting a Function to a Rhai Module
//!
//! ```
//! use rhai::{EvalAltResult, FLOAT, Module, RegisterFn};
//! use rhai::plugin::*;
//! use rhai::module_resolvers::*;
//!
//! #[rhai::export_fn]
//! pub fn distance_function(x1: FLOAT, y1: FLOAT, x2: FLOAT, y2: FLOAT) -> FLOAT {
//! ((y2 - y1).abs().powf(2.0) + (x2 -x1).abs().powf(2.0)).sqrt()
//! }
//!
//! fn main() -> Result<(), Box<EvalAltResult>> {
//!
//! let mut engine = Engine::new();
//! engine.register_fn("get_mystic_number", || { 42 as FLOAT });
//! let mut m = Module::new();
//! rhai::set_exported_fn!(m, "euclidean_distance", distance_function);
//! let mut r = StaticModuleResolver::new();
//! r.insert("Math::Advanced".to_string(), m);
//! engine.set_module_resolver(Some(r));
//!
//! assert_eq!(engine.eval::<FLOAT>(
//! r#"import "Math::Advanced" as math;
//! let m = get_mystic_number();
//! let x = math::euclidean_distance(0.0, 1.0, 0.0, m);
//! x"#)?, 41.0);
//! Ok(())
//! }
//! ```
//!
//! # Exporting a Function to an Engine
//!
//! ```
//! use rhai::{EvalAltResult, FLOAT, Module, RegisterFn};
//! use rhai::plugin::*;
//! use rhai::module_resolvers::*;
//!
//! #[rhai::export_fn]
//! pub fn distance_function(x1: FLOAT, y1: FLOAT, x2: FLOAT, y2: FLOAT) -> FLOAT {
//! ((y2 - y1).abs().powf(2.0) + (x2 -x1).abs().powf(2.0)).sqrt()
//! }
//!
//! fn main() -> Result<(), Box<EvalAltResult>> {
//!
//! let mut engine = Engine::new();
//! engine.register_fn("get_mystic_number", || { 42 as FLOAT });
//! rhai::register_exported_fn!(engine, "euclidean_distance", distance_function);
//!
//! assert_eq!(engine.eval::<FLOAT>(
//! r#"let m = get_mystic_number();
//! let x = euclidean_distance(0.0, 1.0, 0.0, m);
//! x"#)?, 41.0);
//! Ok(())
//! }
//! ```
//!
use quote::quote;
use syn::parse_macro_input;
mod attrs;
mod function;
mod module;
mod register;
mod rhai_module;
#[proc_macro_attribute]
pub fn export_fn(
args: proc_macro::TokenStream,
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
let mut output = proc_macro2::TokenStream::from(input.clone());
let parsed_params = match crate::attrs::outer_item_attributes(args.into(), "export_fn") {
Ok(args) => args,
Err(err) => return proc_macro::TokenStream::from(err.to_compile_error()),
};
let mut function_def = parse_macro_input!(input as function::ExportedFn);
if let Err(e) = function_def.set_params(parsed_params) {
return e.to_compile_error().into();
}
output.extend(function_def.generate());
proc_macro::TokenStream::from(output)
}
#[proc_macro_attribute]
pub fn export_module(
_args: proc_macro::TokenStream,
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
let module_def = parse_macro_input!(input as module::Module);
let tokens = module_def.generate();
proc_macro::TokenStream::from(tokens)
}
#[proc_macro]
pub fn exported_module(module_path: proc_macro::TokenStream) -> proc_macro::TokenStream {
let module_path = parse_macro_input!(module_path as syn::Path);
let tokens = quote::quote! {
#module_path::rhai_module_generate()
};
proc_macro::TokenStream::from(tokens)
}
#[proc_macro]
pub fn register_exported_fn(args: proc_macro::TokenStream) -> proc_macro::TokenStream {
let (engine_expr, export_name, rust_modpath) = match crate::register::parse_register_macro(args)
{
Ok(triple) => triple,
Err(e) => return e.to_compile_error().into(),
};
let gen_mod_path = crate::register::generated_module_path(&rust_modpath);
let tokens = quote! {
#engine_expr.register_result_fn(&(#export_name), #gen_mod_path::dynamic_result_fn);
};
proc_macro::TokenStream::from(tokens)
}
#[proc_macro]
pub fn set_exported_fn(args: proc_macro::TokenStream) -> proc_macro::TokenStream {
let (module_expr, export_name, rust_modpath) = match crate::register::parse_register_macro(args)
{
Ok(triple) => triple,
Err(e) => return e.to_compile_error().into(),
};
let gen_mod_path = crate::register::generated_module_path(&rust_modpath);
let tokens = quote! {
#module_expr.set_fn(#export_name, FnAccess::Public,
#gen_mod_path::token_input_types().as_ref(),
#gen_mod_path::token_callable());
};
proc_macro::TokenStream::from(tokens)
}

1538
codegen/src/module.rs Normal file

File diff suppressed because it is too large Load Diff

49
codegen/src/register.rs Normal file
View File

@ -0,0 +1,49 @@
use quote::{quote, quote_spanned};
use syn::{parse::Parser, spanned::Spanned};
pub(crate) fn generated_module_path(
fn_path: &syn::Path,
) -> syn::punctuated::Punctuated<syn::PathSegment, syn::Token![::]> {
let mut g = fn_path.clone().segments;
g.pop();
let ident = syn::Ident::new(
&format!("rhai_fn_{}", fn_path.segments.last().unwrap().ident),
fn_path.span(),
);
g.push_value(syn::PathSegment {
ident,
arguments: syn::PathArguments::None,
});
g
}
type RegisterMacroInput = (syn::Expr, proc_macro2::TokenStream, syn::Path);
pub fn parse_register_macro(
args: proc_macro::TokenStream,
) -> Result<RegisterMacroInput, syn::Error> {
let parser = syn::punctuated::Punctuated::<syn::Expr, syn::Token![,]>::parse_separated_nonempty;
let args = parser.parse(args).unwrap();
let arg_span = args.span();
let mut items: Vec<syn::Expr> = args.into_iter().collect();
if items.len() != 3 {
return Err(syn::Error::new(
arg_span,
"this macro requires three arguments",
));
}
let export_name = match &items[1] {
syn::Expr::Lit(litstr) => quote_spanned!(items[1].span()=>
#litstr.to_string()),
expr => quote! { #expr },
};
let rust_modpath = if let syn::Expr::Path(ref path) = &items[2] {
path.path.clone()
} else {
return Err(syn::Error::new(
items[2].span(),
"third argument must be a function name",
));
};
let module = items.remove(0);
Ok((module, export_name, rust_modpath))
}

208
codegen/src/rhai_module.rs Normal file
View File

@ -0,0 +1,208 @@
use std::collections::HashMap;
use quote::{quote, ToTokens};
use crate::function::ExportedFn;
use crate::module::Module;
pub(crate) type ExportedConst = (String, syn::Expr);
pub(crate) fn generate_body(
fns: &[ExportedFn],
consts: &[ExportedConst],
submodules: &[Module],
) -> proc_macro2::TokenStream {
let mut set_fn_stmts: Vec<syn::Stmt> = Vec::new();
let mut set_const_stmts: Vec<syn::Stmt> = Vec::new();
let mut add_mod_blocks: Vec<syn::ExprBlock> = Vec::new();
let str_type_path = syn::parse2::<syn::Path>(quote! { str }).unwrap();
for (const_name, const_expr) in consts {
let const_literal = syn::LitStr::new(&const_name, proc_macro2::Span::call_site());
set_const_stmts.push(
syn::parse2::<syn::Stmt>(quote! {
m.set_var(#const_literal, #const_expr);
})
.unwrap(),
);
}
for itemmod in submodules {
if itemmod.skipped() {
continue;
}
let module_name: &syn::Ident = itemmod.module_name().unwrap();
let exported_name: syn::LitStr = if let Some(name) = itemmod.exported_name() {
syn::LitStr::new(&name, proc_macro2::Span::call_site())
} else {
syn::LitStr::new(&module_name.to_string(), proc_macro2::Span::call_site())
};
let cfg_attrs: Vec<&syn::Attribute> = itemmod
.attrs()
.unwrap()
.iter()
.filter(|&a| a.path.get_ident().map(|i| *i == "cfg").unwrap_or(false))
.collect();
add_mod_blocks.push(
syn::parse2::<syn::ExprBlock>(quote! {
#(#cfg_attrs)* {
m.set_sub_module(#exported_name, self::#module_name::rhai_module_generate());
}
})
.unwrap(),
);
}
// NB: these are token streams, because reparsing messes up "> >" vs ">>"
let mut gen_fn_tokens: Vec<proc_macro2::TokenStream> = Vec::new();
for function in fns {
if function.skipped() {
continue;
}
let fn_token_name = syn::Ident::new(
&format!("{}_token", function.name().to_string()),
function.name().span(),
);
let reg_name = function
.params()
.name
.clone()
.unwrap_or_else(|| function.name().to_string());
let fn_literal = syn::LitStr::new(&reg_name, proc_macro2::Span::call_site());
let fn_input_types: Vec<syn::Expr> = function
.arg_list()
.map(|fnarg| match fnarg {
syn::FnArg::Receiver(_) => panic!("internal error: receiver fn outside impl!?"),
syn::FnArg::Typed(syn::PatType { ref ty, .. }) => {
let arg_type = match ty.as_ref() {
syn::Type::Reference(syn::TypeReference {
mutability: None,
ref elem,
..
}) => match elem.as_ref() {
syn::Type::Path(ref p) if p.path == str_type_path => {
syn::parse2::<syn::Type>(quote! {
ImmutableString })
.unwrap()
}
_ => panic!("internal error: non-string shared reference!?"),
},
syn::Type::Reference(syn::TypeReference {
mutability: Some(_),
ref elem,
..
}) => match elem.as_ref() {
syn::Type::Path(ref p) => syn::parse2::<syn::Type>(quote! {
#p })
.unwrap(),
_ => panic!("internal error: non-string shared reference!?"),
},
t => t.clone(),
};
syn::parse2::<syn::Expr>(quote! {
core::any::TypeId::of::<#arg_type>()})
.unwrap()
}
})
.collect();
set_fn_stmts.push(
syn::parse2::<syn::Stmt>(quote! {
m.set_fn(#fn_literal, FnAccess::Public, &[#(#fn_input_types),*],
CallableFunction::from_plugin(#fn_token_name()));
})
.unwrap(),
);
gen_fn_tokens.push(quote! {
#[allow(non_camel_case_types)]
struct #fn_token_name();
});
gen_fn_tokens.push(function.generate_impl(&fn_token_name.to_string()));
gen_fn_tokens.push(function.generate_callable(&fn_token_name.to_string()));
gen_fn_tokens.push(function.generate_input_types(&fn_token_name.to_string()));
}
let mut generate_fncall = syn::parse2::<syn::ItemMod>(quote! {
pub mod generate_info {
#[allow(unused_imports)]
use super::*;
#[allow(unused_mut)]
pub fn rhai_module_generate() -> Module {
let mut m = Module::new();
#(#set_fn_stmts)*
#(#set_const_stmts)*
#(#add_mod_blocks)*
m
}
}
})
.unwrap();
let (_, generate_call_content) = generate_fncall.content.take().unwrap();
quote! {
#(#generate_call_content)*
#(#gen_fn_tokens)*
}
}
pub(crate) fn check_rename_collisions(fns: &Vec<ExportedFn>) -> Result<(), syn::Error> {
let mut renames = HashMap::<String, proc_macro2::Span>::new();
let mut names = HashMap::<String, proc_macro2::Span>::new();
for itemfn in fns.iter() {
if let Some(ref name) = itemfn.params().name {
let current_span = itemfn.params().span.as_ref().unwrap();
let key = itemfn.arg_list().fold(name.clone(), |mut argstr, fnarg| {
let type_string: String = match fnarg {
syn::FnArg::Receiver(_) => unimplemented!("receiver rhai_fns not implemented"),
syn::FnArg::Typed(syn::PatType { ref ty, .. }) => {
ty.as_ref().to_token_stream().to_string()
}
};
argstr.push('.');
argstr.push_str(&type_string);
argstr
});
if let Some(other_span) = renames.insert(key, *current_span) {
let mut err = syn::Error::new(
*current_span,
format!("duplicate Rhai signature for '{}'", &name),
);
err.combine(syn::Error::new(
other_span,
format!("duplicated function renamed '{}'", &name),
));
return Err(err);
}
} else {
let ident = itemfn.name();
if let Some(other_span) = names.insert(ident.to_string(), ident.span()) {
let mut err = syn::Error::new(
ident.span(),
format!("duplicate function '{}'", ident.to_string()),
);
err.combine(syn::Error::new(
other_span,
format!("duplicated function '{}'", ident.to_string()),
));
return Err(err);
}
}
}
for (new_name, attr_span) in renames.drain() {
let new_name = new_name.split('.').next().unwrap();
if let Some(fn_span) = names.get(new_name) {
let mut err = syn::Error::new(
attr_span,
format!("duplicate Rhai signature for '{}'", &new_name),
);
err.combine(syn::Error::new(
*fn_span,
format!("duplicated function '{}'", &new_name),
));
return Err(err);
}
}
Ok(())
}

View File

@ -0,0 +1,202 @@
use rhai::module_resolvers::*;
use rhai::plugin::*;
use rhai::{Engine, EvalAltResult, Module, RegisterFn, FLOAT};
pub mod raw_fn {
use rhai::plugin::*;
use rhai::FLOAT;
#[export_fn]
pub fn distance_function(x1: FLOAT, y1: FLOAT, x2: FLOAT, y2: FLOAT) -> FLOAT {
((y2 - y1).abs().powf(2.0) + (x2 - x1).abs().powf(2.0)).sqrt()
}
}
#[test]
fn raw_fn_test() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new();
engine.register_fn("get_mystic_number", || 42 as FLOAT);
let mut m = Module::new();
rhai::set_exported_fn!(
m,
"euclidean_distance".to_string(),
raw_fn::distance_function
);
let mut r = StaticModuleResolver::new();
r.insert("Math::Advanced".to_string(), m);
engine.set_module_resolver(Some(r));
assert_eq!(
engine.eval::<FLOAT>(
r#"import "Math::Advanced" as math;
let x = math::euclidean_distance(0.0, 1.0, 0.0, get_mystic_number()); x"#
)?,
41.0
);
Ok(())
}
mod raw_fn_mut {
use rhai::plugin::*;
use rhai::FLOAT;
#[export_fn]
pub fn add_in_place(f1: &mut FLOAT, f2: FLOAT) {
*f1 += f2;
}
}
#[test]
fn raw_fn_mut_test() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new();
engine.register_fn("get_mystic_number", || 42 as FLOAT);
let mut m = Module::new();
rhai::set_exported_fn!(m, "add_in_place", raw_fn_mut::add_in_place);
let mut r = StaticModuleResolver::new();
r.insert("Math::Advanced".to_string(), m);
engine.set_module_resolver(Some(r));
assert_eq!(
engine.eval::<FLOAT>(
r#"import "Math::Advanced" as math;
let x = get_mystic_number();
math::add_in_place(x, 1.0);
x"#
)?,
43.0
);
Ok(())
}
mod raw_fn_str {
use rhai::plugin::*;
#[export_fn]
pub fn write_out_str(message: &str) -> bool {
eprintln!("{}", message);
true
}
}
#[test]
fn raw_fn_str_test() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new();
engine.register_fn("get_mystic_number", || 42 as FLOAT);
let mut m = Module::new();
rhai::set_exported_fn!(m, "write_out_str", raw_fn_str::write_out_str);
let mut r = StaticModuleResolver::new();
r.insert("Host::IO".to_string(), m);
engine.set_module_resolver(Some(r));
assert_eq!(
engine.eval::<bool>(
r#"import "Host::IO" as io;
let x = io::write_out_str("hello world!");
x"#
)?,
true
);
Ok(())
}
mod mut_opaque_ref {
use rhai::plugin::*;
use rhai::INT;
#[derive(Clone)]
pub struct StatusMessage {
os_code: Option<INT>,
message: String,
is_ok: bool,
}
#[export_fn]
pub fn new_message(is_ok: bool, message: &str) -> StatusMessage {
StatusMessage {
is_ok,
os_code: None,
message: message.to_string(),
}
}
#[export_fn]
pub fn new_os_message(is_ok: bool, os_code: INT) -> StatusMessage {
StatusMessage {
is_ok,
os_code: Some(os_code),
message: format!("OS Code {}", os_code),
}
}
#[export_fn]
pub fn write_out_message(message: &mut StatusMessage) -> bool {
eprintln!("{}", message.message);
true
}
}
#[test]
fn mut_opaque_ref_test() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new();
let mut m = Module::new();
rhai::set_exported_fn!(m, "new_message", mut_opaque_ref::new_message);
rhai::set_exported_fn!(m, "new_os_message", mut_opaque_ref::new_os_message);
rhai::set_exported_fn!(m, "write_out_message", mut_opaque_ref::write_out_message);
let mut r = StaticModuleResolver::new();
r.insert("Host::Msg".to_string(), m);
engine.set_module_resolver(Some(r));
assert_eq!(
engine.eval::<bool>(
r#"import "Host::Msg" as msg;
let message1 = msg::new_message(true, "it worked");
let ok1 = msg::write_out_message(message1);
let message2 = msg::new_os_message(true, 0);
let ok2 = msg::write_out_message(message2);
ok1 && ok2"#
)?,
true
);
Ok(())
}
pub mod raw_returning_fn {
use rhai::plugin::*;
use rhai::FLOAT;
#[export_fn(return_raw)]
pub fn distance_function(
x1: FLOAT,
y1: FLOAT,
x2: FLOAT,
y2: FLOAT,
) -> Result<rhai::Dynamic, Box<rhai::EvalAltResult>> {
Ok(Dynamic::from(
((y2 - y1).abs().powf(2.0) + (x2 - x1).abs().powf(2.0)).sqrt(),
))
}
}
#[test]
fn raw_returning_fn_test() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new();
engine.register_fn("get_mystic_number", || 42 as FLOAT);
let mut m = Module::new();
rhai::set_exported_fn!(
m,
"euclidean_distance".to_string(),
raw_returning_fn::distance_function
);
let mut r = StaticModuleResolver::new();
r.insert("Math::Advanced".to_string(), m);
engine.set_module_resolver(Some(r));
assert_eq!(
engine.eval::<FLOAT>(
r#"import "Math::Advanced" as math;
let x = math::euclidean_distance(0.0, 1.0, 0.0, get_mystic_number()); x"#
)?,
41.0
);
Ok(())
}

View File

@ -0,0 +1,223 @@
use rhai::module_resolvers::*;
use rhai::{Array, Engine, EvalAltResult, RegisterFn, FLOAT, INT};
pub mod empty_module {
use rhai::plugin::*;
#[export_module]
pub mod EmptyModule {}
}
#[test]
fn empty_module_test() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new();
let m = rhai::exported_module!(crate::empty_module::EmptyModule);
let mut r = StaticModuleResolver::new();
r.insert("Module::Empty".to_string(), m);
engine.set_module_resolver(Some(r));
assert_eq!(
engine.eval::<INT>(r#"import "Module::Empty" as m; 42"#)?,
42
);
Ok(())
}
pub mod one_fn_module {
use rhai::plugin::*;
#[export_module]
pub mod advanced_math {
use rhai::FLOAT;
pub fn get_mystic_number() -> FLOAT {
42.0 as FLOAT
}
}
}
#[test]
fn one_fn_module_test() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new();
let m = rhai::exported_module!(crate::one_fn_module::advanced_math);
let mut r = StaticModuleResolver::new();
r.insert("Math::Advanced".to_string(), m);
engine.set_module_resolver(Some(r));
assert_eq!(
engine.eval::<FLOAT>(
r#"import "Math::Advanced" as math;
let m = math::get_mystic_number();
m"#
)?,
42.0
);
Ok(())
}
pub mod one_fn_and_const_module {
use rhai::plugin::*;
#[export_module]
pub mod advanced_math {
use rhai::FLOAT;
pub const MYSTIC_NUMBER: FLOAT = 42.0 as FLOAT;
pub fn euclidean_distance(x1: FLOAT, y1: FLOAT, x2: FLOAT, y2: FLOAT) -> FLOAT {
((y2 - y1).abs().powf(2.0) + (x2 - x1).abs().powf(2.0)).sqrt()
}
}
}
#[test]
fn one_fn_and_const_module_test() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new();
let m = rhai::exported_module!(crate::one_fn_and_const_module::advanced_math);
let mut r = StaticModuleResolver::new();
r.insert("Math::Advanced".to_string(), m);
engine.set_module_resolver(Some(r));
assert_eq!(
engine.eval::<FLOAT>(
r#"import "Math::Advanced" as math;
let m = math::MYSTIC_NUMBER;
let x = math::euclidean_distance(0.0, 1.0, 0.0, m);
x"#
)?,
41.0
);
Ok(())
}
pub mod raw_fn_str_module {
use rhai::plugin::*;
#[export_module]
pub mod host_io {
pub fn write_out_str(message: &str) -> bool {
eprintln!("{}", message);
true
}
}
}
#[test]
fn raw_fn_str_module_test() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new();
let m = rhai::exported_module!(crate::raw_fn_str_module::host_io);
let mut r = StaticModuleResolver::new();
r.insert("Host::IO".to_string(), m);
engine.set_module_resolver(Some(r));
assert_eq!(
engine.eval::<bool>(
r#"import "Host::IO" as io;
let x = io::write_out_str("hello world!");
x"#
)?,
true
);
Ok(())
}
pub mod mut_opaque_ref_module {
use rhai::plugin::*;
use rhai::INT;
#[derive(Clone)]
pub struct StatusMessage {
os_code: Option<INT>,
message: String,
is_ok: bool,
}
#[export_module]
pub mod host_msg {
use super::{StatusMessage, INT};
pub fn new_message(is_ok: bool, message: &str) -> StatusMessage {
StatusMessage {
is_ok,
os_code: None,
message: message.to_string(),
}
}
pub fn new_os_message(is_ok: bool, os_code: INT) -> StatusMessage {
StatusMessage {
is_ok,
os_code: Some(os_code),
message: format!("OS Code {}", os_code),
}
}
pub fn write_out_message(message: &mut StatusMessage) -> bool {
eprintln!("{}", message.message);
true
}
}
}
#[test]
fn mut_opaque_ref_test() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new();
let m = rhai::exported_module!(crate::mut_opaque_ref_module::host_msg);
let mut r = StaticModuleResolver::new();
r.insert("Host::Msg".to_string(), m);
engine.set_module_resolver(Some(r));
assert_eq!(
engine.eval::<bool>(
r#"import "Host::Msg" as msg;
let success = "it worked";
let message1 = msg::new_message(true, success);
let ok1 = msg::write_out_message(message1);
let message2 = msg::new_os_message(true, 0);
let ok2 = msg::write_out_message(message2);
ok1 && ok2"#
)?,
true
);
Ok(())
}
mod duplicate_fn_rename {
use rhai::plugin::*;
#[export_module]
pub mod my_adds {
use rhai::{FLOAT, INT};
#[rhai_fn(name = "add")]
pub fn add_float(f1: FLOAT, f2: FLOAT) -> FLOAT {
f1 + f2
}
#[rhai_fn(name = "add")]
pub fn add_int(i1: INT, i2: INT) -> INT {
i1 + i2
}
}
}
#[test]
fn duplicate_fn_rename_test() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new();
engine.register_fn("get_mystic_number", || 42 as FLOAT);
let m = rhai::exported_module!(crate::duplicate_fn_rename::my_adds);
let mut r = StaticModuleResolver::new();
r.insert("Math::Advanced".to_string(), m);
engine.set_module_resolver(Some(r));
let output_array = engine.eval::<Array>(
r#"import "Math::Advanced" as math;
let fx = get_mystic_number();
let fy = math::add(fx, 1.0);
let ix = 42;
let iy = math::add(ix, 1);
[fy, iy]
"#,
)?;
assert_eq!(&output_array[0].as_float().unwrap(), &43.0);
assert_eq!(&output_array[1].as_int().unwrap(), &43);
Ok(())
}

View File

@ -0,0 +1,72 @@
use rhai::module_resolvers::*;
use rhai::{Engine, EvalAltResult, RegisterFn, FLOAT, INT};
pub mod one_fn_module_nested_attr {
use rhai::plugin::*;
#[export_module]
pub mod advanced_math {
use rhai::plugin::*;
use rhai::FLOAT;
#[rhai_fn(return_raw)]
pub fn get_mystic_number() -> Result<Dynamic, Box<EvalAltResult>> {
Ok(Dynamic::from(42.0 as FLOAT))
}
}
}
#[test]
fn one_fn_module_nested_attr_test() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new();
let m = rhai::exported_module!(crate::one_fn_module_nested_attr::advanced_math);
let mut r = StaticModuleResolver::new();
r.insert("Math::Advanced".to_string(), m);
engine.set_module_resolver(Some(r));
assert_eq!(
engine.eval::<FLOAT>(
r#"import "Math::Advanced" as math;
let m = math::get_mystic_number();
m"#
)?,
42.0
);
Ok(())
}
pub mod one_fn_submodule_nested_attr {
use rhai::plugin::*;
#[export_module]
pub mod advanced_math {
#[rhai_mod(name = "constants")]
pub mod my_module {
use rhai::plugin::*;
use rhai::FLOAT;
#[rhai_fn(return_raw)]
pub fn get_mystic_number() -> Result<Dynamic, Box<EvalAltResult>> {
Ok(Dynamic::from(42.0 as FLOAT))
}
}
}
}
#[test]
fn one_fn_submodule_nested_attr_test() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new();
let m = rhai::exported_module!(crate::one_fn_submodule_nested_attr::advanced_math);
let mut r = StaticModuleResolver::new();
r.insert("Math::Advanced".to_string(), m);
engine.set_module_resolver(Some(r));
assert_eq!(
engine.eval::<FLOAT>(
r#"import "Math::Advanced" as math;
let m = math::constants::get_mystic_number();
m"#
)?,
42.0
);
Ok(())
}

View File

@ -0,0 +1,8 @@
#![cfg(test)]
mod ui_tests {
#[test]
fn all() {
let t = trybuild::TestCases::new();
t.compile_fail("ui_tests/*.rs");
}
}

View File

@ -0,0 +1,24 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_fn(unknown = "thing")]
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: unknown attribute 'unknown'
--> $DIR/export_fn_bad_attr.rs:9:13
|
9 | #[export_fn(unknown = "thing")]
| ^^^^^^^
error[E0425]: cannot find function `test_fn` in this scope
--> $DIR/export_fn_bad_attr.rs:19:8
|
19 | if test_fn(n) {
| ^^^^^^^ not found in this scope

View File

@ -0,0 +1,24 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_fn(name = true)]
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: expecting string literal
--> $DIR/export_fn_bad_value.rs:9:20
|
9 | #[export_fn(name = true)]
| ^^^^
error[E0425]: cannot find function `test_fn` in this scope
--> $DIR/export_fn_bad_value.rs:19:8
|
19 | if test_fn(n) {
| ^^^^^^^ not found in this scope

View File

@ -0,0 +1,25 @@
use rhai::plugin::*;
#[derive(Clone)]
pub struct Point {
x: f32,
y: f32,
}
#[cfg(not(feature = "foo"))]
#[export_fn]
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: cfg attributes not allowed on this item
--> $DIR/export_fn_cfg.rs:9:1
|
9 | #[cfg(not(feature = "foo"))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0425]: cannot find function `test_fn` in this scope
--> $DIR/export_fn_cfg.rs:20:8
|
20 | if test_fn(n) {
| ^^^^^^^ not found in this scope

View File

@ -0,0 +1,24 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_fn(return_raw = "yes")]
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: extraneous value
--> $DIR/export_fn_extra_value.rs:9:26
|
9 | #[export_fn(return_raw = "yes")]
| ^^^^^
error[E0425]: cannot find function `test_fn` in this scope
--> $DIR/export_fn_extra_value.rs:19:8
|
19 | if test_fn(n) {
| ^^^^^^^ not found in this scope

View File

@ -0,0 +1,24 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_fn("wheeeee")]
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: expecting identifier
--> $DIR/export_fn_junk_arg.rs:9:13
|
9 | #[export_fn("wheeeee")]
| ^^^^^^^^^
error[E0425]: cannot find function `test_fn` in this scope
--> $DIR/export_fn_junk_arg.rs:19:8
|
19 | if test_fn(n) {
| ^^^^^^^ not found in this scope

View File

@ -0,0 +1,24 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_fn(name)]
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: requires value
--> $DIR/export_fn_missing_value.rs:9:13
|
9 | #[export_fn(name)]
| ^^^^
error[E0425]: cannot find function `test_fn` in this scope
--> $DIR/export_fn_missing_value.rs:19:8
|
19 | if test_fn(n) {
| ^^^^^^^ not found in this scope

View File

@ -0,0 +1,24 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_fn(rhai::name = "thing")]
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: expecting attribute name
--> $DIR/export_fn_path_attr.rs:9:13
|
9 | #[export_fn(rhai::name = "thing")]
| ^^^^^^^^^^
error[E0425]: cannot find function `test_fn` in this scope
--> $DIR/export_fn_path_attr.rs:19:8
|
19 | if test_fn(n) {
| ^^^^^^^ not found in this scope

View File

@ -0,0 +1,25 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_fn(return_raw)]
pub fn test_fn(input: &mut Point) {
input.x += 1.0;
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
test_fn(&mut n);
if n.x >= 10.0 {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: return_raw functions must return Result<T>
--> $DIR/export_fn_raw_noreturn.rs:10:5
|
10 | pub fn test_fn(input: &mut Point) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0425]: cannot find function `test_fn` in this scope
--> $DIR/export_fn_raw_noreturn.rs:19:5
|
19 | test_fn(&mut n);
| ^^^^^^^ not found in this scope

View File

@ -0,0 +1,24 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_fn(return_raw)]
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,21 @@
error[E0308]: mismatched types
--> $DIR/export_fn_raw_return.rs:10:8
|
9 | #[export_fn(return_raw)]
| ------------------------ expected `std::result::Result<rhai::Dynamic, std::boxed::Box<rhai::EvalAltResult>>` because of return type
10 | pub fn test_fn(input: Point) -> bool {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found `bool`
|
= note: expected enum `std::result::Result<rhai::Dynamic, std::boxed::Box<rhai::EvalAltResult>>`
found type `bool`
error[E0308]: mismatched types
--> $DIR/export_fn_raw_return.rs:10:33
|
9 | #[export_fn(return_raw)]
| ------------------------ expected `std::result::Result<rhai::Dynamic, std::boxed::Box<rhai::EvalAltResult>>` because of return type
10 | pub fn test_fn(input: Point) -> bool {
| ^^^^ expected enum `std::result::Result`, found `bool`
|
= note: expected enum `std::result::Result<rhai::Dynamic, std::boxed::Box<rhai::EvalAltResult>>`
found type `bool`

View File

@ -0,0 +1,27 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_module]
pub mod test_mod {
#[rhai_fn(unknown = "thing")]
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_mod::test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: unknown attribute 'unknown'
--> $DIR/export_mod_bad_attr.rs:11:11
|
11 | #[rhai_fn(unknown = "thing")]
| ^^^^^^^
error[E0433]: failed to resolve: use of undeclared type or module `test_mod`
--> $DIR/export_mod_bad_attr.rs:22:8
|
22 | if test_mod::test_fn(n) {
| ^^^^^^^^ use of undeclared type or module `test_mod`

View File

@ -0,0 +1,27 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_module]
pub mod test_mod {
#[rhai_fn(name = true)]
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_mod::test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: expecting string literal
--> $DIR/export_mod_bad_value.rs:11:18
|
11 | #[rhai_fn(name = true)]
| ^^^^
error[E0433]: failed to resolve: use of undeclared type or module `test_mod`
--> $DIR/export_mod_bad_value.rs:22:8
|
22 | if test_mod::test_fn(n) {
| ^^^^^^^^ use of undeclared type or module `test_mod`

View File

@ -0,0 +1,28 @@
use rhai::plugin::*;
#[derive(Clone)]
pub struct Point {
x: f32,
y: f32,
}
#[export_module]
pub mod test_mod {
#[cfg(not(feature = "foo"))]
#[rhai_fn]
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_mod::test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: cfg attributes not allowed on this item
--> $DIR/export_mod_cfg.rs:11:1
|
11 | #[cfg(not(feature = "foo"))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0433]: failed to resolve: use of undeclared type or module `test_mod`
--> $DIR/export_mod_cfg.rs:23:8
|
23 | if test_mod::test_fn(n) {
| ^^^^^^^^ use of undeclared type or module `test_mod`

View File

@ -0,0 +1,27 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_module]
pub mod test_mod {
#[rhai_fn(return_raw = "yes")]
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_mod::test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: extraneous value
--> $DIR/export_mod_extra_value.rs:11:24
|
11 | #[rhai_fn(return_raw = "yes")]
| ^^^^^
error[E0433]: failed to resolve: use of undeclared type or module `test_mod`
--> $DIR/export_mod_extra_value.rs:22:8
|
22 | if test_mod::test_fn(n) {
| ^^^^^^^^ use of undeclared type or module `test_mod`

View File

@ -0,0 +1,27 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_module]
pub mod test_mod {
#[rhai_fn("wheeeee")]
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_mod::test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: expecting identifier
--> $DIR/export_mod_junk_arg.rs:11:11
|
11 | #[rhai_fn("wheeeee")]
| ^^^^^^^^^
error[E0433]: failed to resolve: use of undeclared type or module `test_mod`
--> $DIR/export_mod_junk_arg.rs:22:8
|
22 | if test_mod::test_fn(n) {
| ^^^^^^^^ use of undeclared type or module `test_mod`

View File

@ -0,0 +1,27 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_module]
pub mod test_mod {
#[rhai_fn(name)]
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_mod::test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: requires value
--> $DIR/export_mod_missing_value.rs:11:11
|
11 | #[rhai_fn(name)]
| ^^^^
error[E0433]: failed to resolve: use of undeclared type or module `test_mod`
--> $DIR/export_mod_missing_value.rs:22:8
|
22 | if test_mod::test_fn(n) {
| ^^^^^^^^ use of undeclared type or module `test_mod`

View File

@ -0,0 +1,27 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_module]
pub mod test_mod {
#[rhai_fn(rhai::name = "thing")]
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_mod::test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: expecting attribute name
--> $DIR/export_mod_path_attr.rs:11:11
|
11 | #[rhai_fn(rhai::name = "thing")]
| ^^^^^^^^^^
error[E0433]: failed to resolve: use of undeclared type or module `test_mod`
--> $DIR/export_mod_path_attr.rs:22:8
|
22 | if test_mod::test_fn(n) {
| ^^^^^^^^ use of undeclared type or module `test_mod`

View File

@ -0,0 +1,28 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_module]
pub mod test_mod {
#[rhai_fn(return_raw)]
pub fn test_fn(input: &mut Point) {
input.x += 1.0;
}
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
test_mod::test_fn(&mut n);
if n.x >= 10.0 {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: return_raw functions must return Result<T>
--> $DIR/export_mod_raw_noreturn.rs:12:5
|
12 | pub fn test_fn(input: &mut Point) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0433]: failed to resolve: use of undeclared type or module `test_mod`
--> $DIR/export_mod_raw_noreturn.rs:22:5
|
22 | test_mod::test_fn(&mut n);
| ^^^^^^^^ use of undeclared type or module `test_mod`

View File

@ -0,0 +1,27 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_module]
pub mod test_mod {
#[rhai_fn(return_raw)]
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_mod::test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error[E0308]: mismatched types
--> $DIR/export_mod_raw_return.rs:12:8
|
9 | #[export_module]
| ---------------- expected `std::result::Result<rhai::Dynamic, std::boxed::Box<rhai::EvalAltResult>>` because of return type
...
12 | pub fn test_fn(input: Point) -> bool {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found `bool`
|
= note: expected enum `std::result::Result<rhai::Dynamic, std::boxed::Box<rhai::EvalAltResult>>`
found type `bool`

View File

@ -0,0 +1,27 @@
use rhai::plugin::*;
struct NonClonable {
a: f32,
b: u32,
c: char,
d: bool,
}
#[export_fn]
pub fn test_fn(input: &NonClonable) -> bool {
input.d
}
fn main() {
let n = NonClonable {
a: 0.0,
b: 10,
c: 'a',
d: true,
};
if test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: references from Rhai in this position must be mutable
--> $DIR/first_shared_ref.rs:11:23
|
11 | pub fn test_fn(input: &NonClonable) -> bool {
| ^^^^^^^^^^^^
error[E0425]: cannot find function `test_fn` in this scope
--> $DIR/first_shared_ref.rs:22:8
|
22 | if test_fn(n) {
| ^^^^^^^ not found in this scope

View File

@ -0,0 +1,31 @@
use rhai::plugin::*;
#[derive(Clone)]
pub struct Point {
x: f32,
y: f32,
}
#[export_module]
pub mod test_module {
use rhai::FLOAT;
#[cfg(feature = "foo")]
pub const MAGIC: FLOAT = 42.0 as FLOAT;
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_module::test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: cfg attributes not allowed on this item
--> $DIR/module_cfg_const.rs:13:5
|
13 | #[cfg(feature = "foo")]
| ^^^^^^^^^^^^^^^^^^^^^^^
error[E0433]: failed to resolve: use of undeclared type or module `test_module`
--> $DIR/module_cfg_const.rs:26:8
|
26 | if test_module::test_fn(n) {
| ^^^^^^^^^^^ use of undeclared type or module `test_module`

View File

@ -0,0 +1,27 @@
use rhai::plugin::*;
#[derive(Clone)]
pub struct Point {
x: f32,
y: f32,
}
#[export_module]
pub mod test_module {
#[cfg(not(feature = "foo"))]
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_module::test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: cfg attributes not allowed on this item
--> $DIR/module_cfg_fn.rs:11:5
|
11 | #[cfg(not(feature = "foo"))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0433]: failed to resolve: use of undeclared type or module `test_module`
--> $DIR/module_cfg_fn.rs:22:8
|
22 | if test_module::test_fn(n) {
| ^^^^^^^^^^^ use of undeclared type or module `test_module`

View File

@ -0,0 +1,27 @@
use rhai::plugin::*;
struct NonClonable {
a: f32,
b: u32,
c: char,
d: bool,
}
#[export_fn]
pub fn test_fn(input: NonClonable) -> bool {
input.d
}
fn main() {
let n = NonClonable {
a: 0.0,
b: 10,
c: 'a',
d: true,
};
if test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,5 @@
error[E0277]: the trait bound `NonClonable: std::clone::Clone` is not satisfied
--> $DIR/non_clonable.rs:11:23
|
11 | pub fn test_fn(input: NonClonable) -> bool {
| ^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `NonClonable`

View File

@ -0,0 +1,27 @@
use rhai::plugin::*;
struct NonClonable {
a: f32,
b: u32,
c: char,
d: bool,
}
#[export_fn]
pub fn test_fn(a: u32, b: NonClonable) -> bool {
a == 0 && b.d
}
fn main() {
let n = NonClonable {
a: 0.0,
b: 10,
c: 'a',
d: true,
};
if test_fn(10, n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,5 @@
error[E0277]: the trait bound `NonClonable: std::clone::Clone` is not satisfied
--> $DIR/non_clonable_second.rs:11:27
|
11 | pub fn test_fn(a: u32, b: NonClonable) -> bool {
| ^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `NonClonable`

View File

@ -0,0 +1,28 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Clonable {
a: f32,
b: u32,
c: char,
d: bool,
}
#[export_fn]
pub fn test_fn(input: &mut Clonable) -> &mut bool {
&mut input.d
}
fn main() {
let n = Clonable {
a: 0.0,
b: 10,
c: 'a',
d: true,
};
if test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: cannot return a reference to Rhai
--> $DIR/return_mut_ref.rs:12:38
|
12 | pub fn test_fn(input: &mut Clonable) -> &mut bool {
| ^^^^^^^^^^^^
error[E0425]: cannot find function `test_fn` in this scope
--> $DIR/return_mut_ref.rs:23:8
|
23 | if test_fn(n) {
| ^^^^^^^ not found in this scope

View File

@ -0,0 +1,27 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Clonable {
a: f32,
b: u32,
c: char,
d: bool,
}
#[export_fn]
pub fn test_fn(input: Clonable) -> *const str {
"yes"
}
fn main() {
let n = Clonable {
a: 0.0,
b: 10,
c: 'a',
d: true,
};
println!("{}", unsafe {
let ptr = test_fn(n);
*ptr
});
}

View File

@ -0,0 +1,11 @@
error: cannot return a pointer to Rhai
--> $DIR/return_pointer.rs:12:33
|
12 | pub fn test_fn(input: Clonable) -> *const str {
| ^^^^^^^^^^^^^
error[E0425]: cannot find function `test_fn` in this scope
--> $DIR/return_pointer.rs:24:19
|
24 | let ptr = test_fn(n);
| ^^^^^^^ not found in this scope

View File

@ -0,0 +1,24 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Clonable {
a: f32,
b: u32,
c: char,
d: bool,
}
#[export_fn]
pub fn test_fn(input: Clonable) -> &'static str {
"yes"
}
fn main() {
let n = Clonable {
a: 0.0,
b: 10,
c: 'a',
d: true,
};
println!("{}", test_fn(n));
}

View File

@ -0,0 +1,11 @@
error: cannot return a reference to Rhai
--> $DIR/return_shared_ref.rs:12:33
|
12 | pub fn test_fn(input: Clonable) -> &'static str {
| ^^^^^^^^^^^^^^^
error[E0425]: cannot find function `test_fn` in this scope
--> $DIR/return_shared_ref.rs:23:20
|
23 | println!("{}", test_fn(n));
| ^^^^^^^ not found in this scope

View File

@ -0,0 +1,27 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_module]
pub mod test_module {
#[rhai_fn(unknown = "thing")]
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_module::test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: unknown attribute 'unknown'
--> $DIR/rhai_fn_bad_attr.rs:11:11
|
11 | #[rhai_fn(unknown = "thing")]
| ^^^^^^^
error[E0433]: failed to resolve: use of undeclared type or module `test_module`
--> $DIR/rhai_fn_bad_attr.rs:22:8
|
22 | if test_module::test_fn(n) {
| ^^^^^^^^^^^ use of undeclared type or module `test_module`

View File

@ -0,0 +1,27 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_module]
pub mod test_module {
#[rhai_fn(name = true)]
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_module::test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: expecting string literal
--> $DIR/rhai_fn_bad_value.rs:11:18
|
11 | #[rhai_fn(name = true)]
| ^^^^
error[E0433]: failed to resolve: use of undeclared type or module `test_module`
--> $DIR/rhai_fn_bad_value.rs:22:8
|
22 | if test_module::test_fn(n) {
| ^^^^^^^^^^^ use of undeclared type or module `test_module`

View File

@ -0,0 +1,27 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_module]
pub mod test_module {
#[rhai_fn(return_raw = "yes")]
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_module::test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: extraneous value
--> $DIR/rhai_fn_extra_value.rs:11:24
|
11 | #[rhai_fn(return_raw = "yes")]
| ^^^^^
error[E0433]: failed to resolve: use of undeclared type or module `test_module`
--> $DIR/rhai_fn_extra_value.rs:22:8
|
22 | if test_module::test_fn(n) {
| ^^^^^^^^^^^ use of undeclared type or module `test_module`

View File

@ -0,0 +1,27 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_module]
pub mod test_module {
#[rhai_fn("wheeeee")]
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_module::test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: expecting identifier
--> $DIR/rhai_fn_junk_arg.rs:11:11
|
11 | #[rhai_fn("wheeeee")]
| ^^^^^^^^^
error[E0433]: failed to resolve: use of undeclared type or module `test_module`
--> $DIR/rhai_fn_junk_arg.rs:22:8
|
22 | if test_module::test_fn(n) {
| ^^^^^^^^^^^ use of undeclared type or module `test_module`

View File

@ -0,0 +1,27 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_module]
pub mod test_module {
#[rhai_fn(name)]
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_module::test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: requires value
--> $DIR/rhai_fn_missing_value.rs:11:11
|
11 | #[rhai_fn(name)]
| ^^^^
error[E0433]: failed to resolve: use of undeclared type or module `test_module`
--> $DIR/rhai_fn_missing_value.rs:22:8
|
22 | if test_module::test_fn(n) {
| ^^^^^^^^^^^ use of undeclared type or module `test_module`

View File

@ -0,0 +1,27 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_module]
pub mod test_module {
#[rhai_fn(rhai::name = "thing")]
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_module::test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: expecting attribute name
--> $DIR/rhai_fn_path_attr.rs:11:11
|
11 | #[rhai_fn(rhai::name = "thing")]
| ^^^^^^^^^^
error[E0433]: failed to resolve: use of undeclared type or module `test_module`
--> $DIR/rhai_fn_path_attr.rs:22:8
|
22 | if test_module::test_fn(n) {
| ^^^^^^^^^^^ use of undeclared type or module `test_module`

View File

@ -0,0 +1,33 @@
use rhai::plugin::*;
#[derive(Clone)]
pub struct Point {
x: f32,
y: f32,
}
#[export_module]
pub mod test_module {
pub use super::Point;
#[rhai_fn(name = "foo")]
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
#[rhai_fn(name = "foo")]
pub fn test_fn_2(input: Point) -> bool {
input.x < input.y
}
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_module::test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,17 @@
error: duplicate Rhai signature for 'foo'
--> $DIR/rhai_fn_rename_collision.rs:17:15
|
17 | #[rhai_fn(name = "foo")]
| ^^^^^^^^^^^^
error: duplicated function renamed 'foo'
--> $DIR/rhai_fn_rename_collision.rs:12:15
|
12 | #[rhai_fn(name = "foo")]
| ^^^^^^^^^^^^
error[E0433]: failed to resolve: use of undeclared type or module `test_module`
--> $DIR/rhai_fn_rename_collision.rs:28:8
|
28 | if test_module::test_fn(n) {
| ^^^^^^^^^^^ use of undeclared type or module `test_module`

View File

@ -0,0 +1,32 @@
use rhai::plugin::*;
#[derive(Clone)]
pub struct Point {
x: f32,
y: f32,
}
#[export_module]
pub mod test_module {
pub use super::Point;
#[rhai_fn(name = "foo")]
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
pub fn foo(input: Point) -> bool {
input.x < input.y
}
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_module::test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,17 @@
error: duplicate Rhai signature for 'foo'
--> $DIR/rhai_fn_rename_collision_oneattr.rs:12:15
|
12 | #[rhai_fn(name = "foo")]
| ^^^^^^^^^^^^
error: duplicated function 'foo'
--> $DIR/rhai_fn_rename_collision_oneattr.rs:17:12
|
17 | pub fn foo(input: Point) -> bool {
| ^^^
error[E0433]: failed to resolve: use of undeclared type or module `test_module`
--> $DIR/rhai_fn_rename_collision_oneattr.rs:27:8
|
27 | if test_module::test_fn(n) {
| ^^^^^^^^^^^ use of undeclared type or module `test_module`

View File

@ -0,0 +1,28 @@
use rhai::plugin::*;
#[derive(Clone)]
pub struct Point {
x: f32,
y: f32,
}
#[export_module]
pub mod test_module {
pub use super::Point;
#[rhai_fn(name = "foo.bar")]
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_module::test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: Rhai function names may not contain dot
--> $DIR/rhai_fn_rename_dot.rs:12:22
|
12 | #[rhai_fn(name = "foo.bar")]
| ^^^^^^^^^
error[E0433]: failed to resolve: use of undeclared type or module `test_module`
--> $DIR/rhai_fn_rename_dot.rs:23:8
|
23 | if test_module::test_fn(n) {
| ^^^^^^^^^^^ use of undeclared type or module `test_module`

View File

@ -0,0 +1,29 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_module]
pub mod test_module {
#[rhai_mod(unknown = "thing")]
pub mod test_mod {
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
}
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_module::test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: unknown attribute 'unknown'
--> $DIR/rhai_mod_bad_attr.rs:11:12
|
11 | #[rhai_mod(unknown = "thing")]
| ^^^^^^^
error[E0433]: failed to resolve: use of undeclared type or module `test_module`
--> $DIR/rhai_mod_bad_attr.rs:24:8
|
24 | if test_module::test_fn(n) {
| ^^^^^^^^^^^ use of undeclared type or module `test_module`

View File

@ -0,0 +1,29 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_module]
pub mod test_module {
#[rhai_mod(name = true)]
pub mod test_mod {
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
}
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_module::test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: expecting string literal
--> $DIR/rhai_mod_bad_value.rs:11:19
|
11 | #[rhai_mod(name = true)]
| ^^^^
error[E0433]: failed to resolve: use of undeclared type or module `test_module`
--> $DIR/rhai_mod_bad_value.rs:24:8
|
24 | if test_module::test_fn(n) {
| ^^^^^^^^^^^ use of undeclared type or module `test_module`

View File

@ -0,0 +1,29 @@
use rhai::plugin::*;
#[derive(Clone)]
pub struct Point {
x: f32,
y: f32,
}
#[export_module]
pub mod test_module {
#[cfg(feature = "unset_feature")]
pub mod test_mod {
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
}
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_module::test_mod::test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,5 @@
error[E0433]: failed to resolve: could not find `test_mod` in `test_module`
--> $DIR/rhai_mod_inner_cfg_false.rs:24:21
|
24 | if test_module::test_mod::test_fn(n) {
| ^^^^^^^^ could not find `test_mod` in `test_module`

View File

@ -0,0 +1,29 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_module]
pub mod test_module {
#[rhai_mod("wheeeee")]
pub mod test_mod {
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
}
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_module::test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: expecting identifier
--> $DIR/rhai_mod_junk_arg.rs:11:12
|
11 | #[rhai_mod("wheeeee")]
| ^^^^^^^^^
error[E0433]: failed to resolve: use of undeclared type or module `test_module`
--> $DIR/rhai_mod_junk_arg.rs:24:8
|
24 | if test_module::test_fn(n) {
| ^^^^^^^^^^^ use of undeclared type or module `test_module`

View File

@ -0,0 +1,29 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_module]
pub mod test_module {
#[rhai_mod(name)]
pub mod test_mod {
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
}
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_module::test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: requires value
--> $DIR/rhai_mod_missing_value.rs:11:12
|
11 | #[rhai_mod(name)]
| ^^^^
error[E0433]: failed to resolve: use of undeclared type or module `test_module`
--> $DIR/rhai_mod_missing_value.rs:24:8
|
24 | if test_module::test_fn(n) {
| ^^^^^^^^^^^ use of undeclared type or module `test_module`

View File

@ -0,0 +1,31 @@
use rhai::plugin::*;
#[derive(Clone)]
pub struct Point {
x: f32,
y: f32,
}
#[export_module]
pub mod test_module {
pub use super::Point;
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
pub fn test_fn(input: Point) -> bool {
input.x < input.y
}
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_module::test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,17 @@
error: duplicate function 'test_fn'
--> $DIR/rhai_mod_name_collisions.rs:16:12
|
16 | pub fn test_fn(input: Point) -> bool {
| ^^^^^^^
error: duplicated function 'test_fn'
--> $DIR/rhai_mod_name_collisions.rs:12:12
|
12 | pub fn test_fn(input: Point) -> bool {
| ^^^^^^^
error[E0433]: failed to resolve: use of undeclared type or module `test_module`
--> $DIR/rhai_mod_name_collisions.rs:26:8
|
26 | if test_module::test_fn(n) {
| ^^^^^^^^^^^ use of undeclared type or module `test_module`

View File

@ -0,0 +1,29 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_module]
pub mod test_module {
#[rhai_mod(rhai::name = "thing")]
pub mod test_mod {
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
}
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_module::test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: expecting attribute name
--> $DIR/rhai_mod_path_attr.rs:11:12
|
11 | #[rhai_mod(rhai::name = "thing")]
| ^^^^^^^^^^
error[E0433]: failed to resolve: use of undeclared type or module `test_module`
--> $DIR/rhai_mod_path_attr.rs:24:8
|
24 | if test_module::test_fn(n) {
| ^^^^^^^^^^^ use of undeclared type or module `test_module`

View File

@ -0,0 +1,29 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_module]
pub mod test_module {
#[rhai_mod(return_raw = "yes")]
pub mod test_mod {
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
}
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_module::test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

Some files were not shown because too many files have changed in this diff Show More