Add is_def_var and is_def_fn.
This commit is contained in:
parent
eec3f4e1bf
commit
fbfb7677c1
@ -12,6 +12,11 @@ Breaking changes
|
|||||||
* The `merge_namespaces` parameter to `Module::eval_ast_as_new` is removed and now defaults to `true`.
|
* The `merge_namespaces` parameter to `Module::eval_ast_as_new` is removed and now defaults to `true`.
|
||||||
* `GlobalFileModuleResolver` is removed because its performance gain over the `FileModuleResolver` is no longer very significant.
|
* `GlobalFileModuleResolver` is removed because its performance gain over the `FileModuleResolver` is no longer very significant.
|
||||||
|
|
||||||
|
New features
|
||||||
|
------------
|
||||||
|
|
||||||
|
* `is_def_var()` to detect if variable is defined and `is_def_fn()` to detect if script function is defined.
|
||||||
|
|
||||||
|
|
||||||
Version 0.19.0
|
Version 0.19.0
|
||||||
==============
|
==============
|
||||||
|
@ -14,7 +14,9 @@ Versions
|
|||||||
|
|
||||||
This Book is for version **{{version}}** of Rhai.
|
This Book is for version **{{version}}** of Rhai.
|
||||||
|
|
||||||
|
{% if rootUrl != "" and not rootUrl is ending_with("vnext") %}
|
||||||
For the latest development version, see [here]({{rootUrl}}/vnext/).
|
For the latest development version, see [here]({{rootUrl}}/vnext/).
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
Etymology of the name "Rhai"
|
Etymology of the name "Rhai"
|
||||||
|
@ -3,36 +3,38 @@ Keywords List
|
|||||||
|
|
||||||
{{#include ../links.md}}
|
{{#include ../links.md}}
|
||||||
|
|
||||||
| Keyword | Description | Inactive under | Overloadable |
|
| Keyword | Description | Inactive under | Is function? | Overloadable |
|
||||||
| :-------------------: | ------------------------------------------- | :-------------: | :----------: |
|
| :-------------------: | ------------------------------------------- | :-------------: | :----------: | :----------: |
|
||||||
| `true` | boolean true literal | | no |
|
| `true` | boolean true literal | | no | |
|
||||||
| `false` | boolean false literal | | no |
|
| `false` | boolean false literal | | no | |
|
||||||
| `let` | variable declaration | | no |
|
| `let` | variable declaration | | no | |
|
||||||
| `const` | constant declaration | | no |
|
| `const` | constant declaration | | no | |
|
||||||
| `is_shared` | is a value shared? | | no |
|
| `is_def_var` | is a variable declared? | | yes | yes |
|
||||||
| `if` | if statement | | no |
|
| `is_shared` | is a value shared? | [`no_closure`] | yes | no |
|
||||||
| `else` | else block of if statement | | no |
|
| `if` | if statement | | no | |
|
||||||
| `while` | while loop | | no |
|
| `else` | else block of if statement | | no | |
|
||||||
| `loop` | infinite loop | | no |
|
| `while` | while loop | | no | |
|
||||||
| `for` | for loop | | no |
|
| `loop` | infinite loop | | no | |
|
||||||
| `in` | 1) containment test<br/>2) part of for loop | | no |
|
| `for` | for loop | | no | |
|
||||||
| `continue` | continue a loop at the next iteration | | no |
|
| `in` | 1) containment test<br/>2) part of for loop | | no | |
|
||||||
| `break` | break out of loop iteration | | no |
|
| `continue` | continue a loop at the next iteration | | no | |
|
||||||
| `return` | return value | | no |
|
| `break` | break out of loop iteration | | no | |
|
||||||
| `throw` | throw exception | | no |
|
| `return` | return value | | no | |
|
||||||
| `import` | import module | [`no_module`] | no |
|
| `throw` | throw exception | | no | |
|
||||||
| `export` | export variable | [`no_module`] | no |
|
| `import` | import module | [`no_module`] | no | |
|
||||||
| `as` | alias for variable export | [`no_module`] | no |
|
| `export` | export variable | [`no_module`] | no | |
|
||||||
| `private` | mark function private | [`no_function`] | no |
|
| `as` | alias for variable export | [`no_module`] | no | |
|
||||||
| `fn` (lower-case `f`) | function definition | [`no_function`] | no |
|
| `private` | mark function private | [`no_function`] | no | |
|
||||||
| `Fn` (capital `F`) | create a [function pointer] | | yes |
|
| `fn` (lower-case `f`) | function definition | [`no_function`] | no | |
|
||||||
| `call` | call a [function pointer] | | no |
|
| `Fn` (capital `F`) | create a [function pointer] | | yes | yes |
|
||||||
| `curry` | curry a [function pointer] | | no |
|
| `call` | call a [function pointer] | | yes | no |
|
||||||
| `this` | reference to base object for method call | [`no_function`] | no |
|
| `curry` | curry a [function pointer] | | yes | no |
|
||||||
| `type_of` | get type name of value | | yes |
|
| `this` | reference to base object for method call | [`no_function`] | no | |
|
||||||
| `print` | print value | | yes |
|
| `is_def_fn` | is a scripted function defined? | [`no_function`] | yes | yes |
|
||||||
| `debug` | print value in debug format | | yes |
|
| `type_of` | get type name of value | | yes | yes |
|
||||||
| `eval` | evaluate script | | yes |
|
| `print` | print value | | yes | yes |
|
||||||
|
| `debug` | print value in debug format | | yes | yes |
|
||||||
|
| `eval` | evaluate script | | yes | yes |
|
||||||
|
|
||||||
|
|
||||||
Reserved Keywords
|
Reserved Keywords
|
||||||
|
@ -101,6 +101,21 @@ a statement in the script can freely call a function defined afterwards.
|
|||||||
This is similar to Rust and many other modern languages, such as JavaScript's `function` keyword.
|
This is similar to Rust and many other modern languages, such as JavaScript's `function` keyword.
|
||||||
|
|
||||||
|
|
||||||
|
`is_def_fn`
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Use `is_def_fn` to detect if a function is defined (and therefore callable), based on its name
|
||||||
|
and the number of parameters.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
fn foo(x) { x + 1 }
|
||||||
|
|
||||||
|
is_def_fn("foo", 1) == true;
|
||||||
|
|
||||||
|
is_def_fn("bar", 1) == false;
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
Arguments are Passed by Value
|
Arguments are Passed by Value
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
|
@ -37,6 +37,8 @@ If none is provided, it defaults to [`()`].
|
|||||||
|
|
||||||
A variable defined within a statement block is _local_ to that block.
|
A variable defined within a statement block is _local_ to that block.
|
||||||
|
|
||||||
|
Use `is_def_var` to detect if a variable is defined.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let x; // ok - value is '()'
|
let x; // ok - value is '()'
|
||||||
let x = 3; // ok
|
let x = 3; // ok
|
||||||
@ -57,4 +59,10 @@ X == 123;
|
|||||||
x == 999; // access to local 'x'
|
x == 999; // access to local 'x'
|
||||||
}
|
}
|
||||||
x == 42; // the parent block's 'x' is not changed
|
x == 42; // the parent block's 'x' is not changed
|
||||||
|
|
||||||
|
is_def_var("x") == true;
|
||||||
|
|
||||||
|
is_def_var("_x") == true;
|
||||||
|
|
||||||
|
is_def_var("y") == false;
|
||||||
```
|
```
|
||||||
|
@ -32,28 +32,97 @@ are _merged_ into a _unified_ namespace.
|
|||||||
| my_module.rhai |
|
| my_module.rhai |
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
// This function overrides any in the main script.
|
||||||
private fn inner_message() { "hello! from module!" }
|
private fn inner_message() { "hello! from module!" }
|
||||||
|
|
||||||
fn greet(callback) { print(callback.call()); }
|
fn greet() {
|
||||||
|
print(inner_message()); // call function in module script
|
||||||
|
}
|
||||||
|
|
||||||
|
fn greet_main() {
|
||||||
|
print(main_message()); // call function not in module script
|
||||||
|
}
|
||||||
|
|
||||||
-------------
|
-------------
|
||||||
| main.rhai |
|
| main.rhai |
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
fn main_message() { "hi! from main!" }
|
// This function is overridden by the module script.
|
||||||
|
fn inner_message() { "hi! from main!" }
|
||||||
|
|
||||||
|
// This function is found by the module script.
|
||||||
|
fn main_message() { "main here!" }
|
||||||
|
|
||||||
import "my_module" as m;
|
import "my_module" as m;
|
||||||
|
|
||||||
m::greet(|| "hello, " + "world!"); // works - anonymous function in global
|
m::greet(); // prints "hello! from module!"
|
||||||
|
|
||||||
m::greet(|| inner_message()); // works - function in module
|
m::greet_main(); // prints "main here!"
|
||||||
|
|
||||||
m::greet(|| main_message()); // works - function in global
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Simulating virtual functions
|
||||||
|
|
||||||
|
When calling a namespace-qualified function defined within a module, other functions defined within
|
||||||
|
the same module script override any similar-named functions (with the same number of parameters)
|
||||||
|
defined in the global namespace. This is to ensure that a module acts as a self-contained unit and
|
||||||
|
functions defined in the calling script do not override module code.
|
||||||
|
|
||||||
|
In some situations, however, it is actually beneficial to do it in reverse: have module code call functions
|
||||||
|
defined in the calling script (i.e. in the global namespace) if they exist, and only call those defined
|
||||||
|
in the module script if none are found.
|
||||||
|
|
||||||
|
One such situation is the need to provide a _default implementation_ to a simulated _virtual_ function:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
------------------
|
||||||
|
| my_module.rhai |
|
||||||
|
------------------
|
||||||
|
|
||||||
|
// Do not do this (it will override the main script):
|
||||||
|
// fn message() { "hello! from module!" }
|
||||||
|
|
||||||
|
// This function acts as the default implementation.
|
||||||
|
private fn default_message() { "hello! from module!" }
|
||||||
|
|
||||||
|
// This function depends on a 'virtual' function 'message'
|
||||||
|
// which is not defined in the module script.
|
||||||
|
fn greet() {
|
||||||
|
if is_def_fn("message", 0) { // 'is_def_fn' detects if 'message' is defined.
|
||||||
|
print(message());
|
||||||
|
} else {
|
||||||
|
print(default_message());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-------------
|
||||||
|
| main.rhai |
|
||||||
|
-------------
|
||||||
|
|
||||||
|
// The main script defines 'message' which is needed by the module script.
|
||||||
|
fn message() { "hi! from main!" }
|
||||||
|
|
||||||
|
import "my_module" as m;
|
||||||
|
|
||||||
|
m::greet(); // prints "hi! from main!"
|
||||||
|
|
||||||
|
--------------
|
||||||
|
| main2.rhai |
|
||||||
|
--------------
|
||||||
|
|
||||||
|
// The main script does not define 'message' which is needed by the module script.
|
||||||
|
|
||||||
|
import "my_module" as m;
|
||||||
|
|
||||||
|
m::greet(); // prints "hello! from module!"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Changing the base directory
|
||||||
|
|
||||||
The base directory can be changed via the `FileModuleResolver::new_with_path` constructor function.
|
The base directory can be changed via the `FileModuleResolver::new_with_path` constructor function.
|
||||||
|
|
||||||
`FileModuleResolver::create_module` loads a script file and returns a module.
|
### Returning a module instead
|
||||||
|
|
||||||
|
`FileModuleResolver::create_module` loads a script file and returns a module with the standard behavior.
|
||||||
|
|
||||||
|
|
||||||
`StaticModuleResolver`
|
`StaticModuleResolver`
|
||||||
|
@ -99,7 +99,10 @@ pub const KEYWORD_EVAL: &str = "eval";
|
|||||||
pub const KEYWORD_FN_PTR: &str = "Fn";
|
pub const KEYWORD_FN_PTR: &str = "Fn";
|
||||||
pub const KEYWORD_FN_PTR_CALL: &str = "call";
|
pub const KEYWORD_FN_PTR_CALL: &str = "call";
|
||||||
pub const KEYWORD_FN_PTR_CURRY: &str = "curry";
|
pub const KEYWORD_FN_PTR_CURRY: &str = "curry";
|
||||||
|
#[cfg(not(feature = "no_closure"))]
|
||||||
pub const KEYWORD_IS_SHARED: &str = "is_shared";
|
pub const KEYWORD_IS_SHARED: &str = "is_shared";
|
||||||
|
pub const KEYWORD_IS_DEF_VAR: &str = "is_def_var";
|
||||||
|
pub const KEYWORD_IS_DEF_FN: &str = "is_def_fn";
|
||||||
pub const KEYWORD_THIS: &str = "this";
|
pub const KEYWORD_THIS: &str = "this";
|
||||||
pub const FN_TO_STRING: &str = "to_string";
|
pub const FN_TO_STRING: &str = "to_string";
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
@ -4,8 +4,8 @@ use crate::any::Dynamic;
|
|||||||
use crate::calc_fn_hash;
|
use crate::calc_fn_hash;
|
||||||
use crate::engine::{
|
use crate::engine::{
|
||||||
search_imports, search_namespace, search_scope_only, Engine, Imports, State, KEYWORD_DEBUG,
|
search_imports, search_namespace, search_scope_only, Engine, Imports, State, KEYWORD_DEBUG,
|
||||||
KEYWORD_EVAL, KEYWORD_FN_PTR, KEYWORD_FN_PTR_CALL, KEYWORD_FN_PTR_CURRY, KEYWORD_IS_SHARED,
|
KEYWORD_EVAL, KEYWORD_FN_PTR, KEYWORD_FN_PTR_CALL, KEYWORD_FN_PTR_CURRY, KEYWORD_IS_DEF_FN,
|
||||||
KEYWORD_PRINT, KEYWORD_TYPE_OF,
|
KEYWORD_IS_DEF_VAR, KEYWORD_PRINT, KEYWORD_TYPE_OF,
|
||||||
};
|
};
|
||||||
use crate::error::ParseErrorType;
|
use crate::error::ParseErrorType;
|
||||||
use crate::fn_native::{FnCallArgs, FnPtr};
|
use crate::fn_native::{FnCallArgs, FnPtr};
|
||||||
@ -33,6 +33,9 @@ use crate::engine::{FN_IDX_GET, FN_IDX_SET};
|
|||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
use crate::engine::{Map, Target, FN_GET, FN_SET};
|
use crate::engine::{Map, Target, FN_GET, FN_SET};
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_closure"))]
|
||||||
|
use crate::engine::KEYWORD_IS_SHARED;
|
||||||
|
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
use crate::scope::Entry as ScopeEntry;
|
use crate::scope::Entry as ScopeEntry;
|
||||||
@ -744,15 +747,18 @@ impl Engine {
|
|||||||
.into(),
|
.into(),
|
||||||
false,
|
false,
|
||||||
))
|
))
|
||||||
} else if cfg!(not(feature = "no_closure"))
|
} else if {
|
||||||
&& _fn_name == KEYWORD_IS_SHARED
|
#[cfg(not(feature = "no_closure"))]
|
||||||
&& idx.is_empty()
|
{
|
||||||
{
|
_fn_name == KEYWORD_IS_SHARED && idx.is_empty()
|
||||||
|
}
|
||||||
|
#[cfg(feature = "no_closure")]
|
||||||
|
false
|
||||||
|
} {
|
||||||
// is_shared call
|
// is_shared call
|
||||||
Ok((target.is_shared().into(), false))
|
Ok((target.is_shared().into(), false))
|
||||||
} else {
|
} else {
|
||||||
#[cfg(not(feature = "no_object"))]
|
let _redirected;
|
||||||
let redirected;
|
|
||||||
let mut hash = hash_script;
|
let mut hash = hash_script;
|
||||||
|
|
||||||
// Check if it is a map method call in OOP style
|
// Check if it is a map method call in OOP style
|
||||||
@ -761,8 +767,8 @@ impl Engine {
|
|||||||
if let Some(val) = map.get(_fn_name) {
|
if let Some(val) = map.get(_fn_name) {
|
||||||
if let Some(fn_ptr) = val.read_lock::<FnPtr>() {
|
if let Some(fn_ptr) = val.read_lock::<FnPtr>() {
|
||||||
// Remap the function name
|
// Remap the function name
|
||||||
redirected = fn_ptr.get_fn_name().clone();
|
_redirected = fn_ptr.get_fn_name().clone();
|
||||||
_fn_name = &redirected;
|
_fn_name = &_redirected;
|
||||||
// Add curried arguments
|
// Add curried arguments
|
||||||
if !fn_ptr.curry().is_empty() {
|
if !fn_ptr.curry().is_empty() {
|
||||||
fn_ptr
|
fn_ptr
|
||||||
@ -877,7 +883,8 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle is_shared()
|
// Handle is_shared()
|
||||||
if cfg!(not(feature = "no_closure")) && name == KEYWORD_IS_SHARED && args_expr.len() == 1 {
|
#[cfg(not(feature = "no_closure"))]
|
||||||
|
if name == KEYWORD_IS_SHARED && args_expr.len() == 1 {
|
||||||
let expr = args_expr.get(0).unwrap();
|
let expr = args_expr.get(0).unwrap();
|
||||||
let value = self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?;
|
let value = self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?;
|
||||||
|
|
||||||
@ -917,6 +924,48 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle is_def_var()
|
||||||
|
if name == KEYWORD_IS_DEF_VAR && args_expr.len() == 1 {
|
||||||
|
let hash_fn = calc_fn_hash(empty(), name, 1, once(TypeId::of::<ImmutableString>()));
|
||||||
|
|
||||||
|
if !self.has_override(lib, hash_fn, hash_script, pub_only) {
|
||||||
|
let expr = args_expr.get(0).unwrap();
|
||||||
|
if let Ok(var_name) = self
|
||||||
|
.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?
|
||||||
|
.as_str()
|
||||||
|
{
|
||||||
|
return Ok(scope.contains(var_name).into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is_def_fn()
|
||||||
|
if name == KEYWORD_IS_DEF_FN && args_expr.len() == 2 {
|
||||||
|
let hash_fn = calc_fn_hash(
|
||||||
|
empty(),
|
||||||
|
name,
|
||||||
|
2,
|
||||||
|
[TypeId::of::<ImmutableString>(), TypeId::of::<INT>()]
|
||||||
|
.iter()
|
||||||
|
.cloned(),
|
||||||
|
);
|
||||||
|
|
||||||
|
if !self.has_override(lib, hash_fn, hash_script, pub_only) {
|
||||||
|
let fn_name_expr = args_expr.get(0).unwrap();
|
||||||
|
let num_params_expr = args_expr.get(1).unwrap();
|
||||||
|
|
||||||
|
if let (Ok(fn_name), Ok(num_params)) = (
|
||||||
|
self.eval_expr(scope, mods, state, lib, this_ptr, fn_name_expr, level)?
|
||||||
|
.as_str(),
|
||||||
|
self.eval_expr(scope, mods, state, lib, this_ptr, num_params_expr, level)?
|
||||||
|
.as_int(),
|
||||||
|
) {
|
||||||
|
let hash = calc_fn_hash(empty(), fn_name, num_params as usize, empty());
|
||||||
|
return Ok(lib.contains_fn(hash, false).into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Handle eval()
|
// Handle eval()
|
||||||
if name == KEYWORD_EVAL && args_expr.len() == 1 {
|
if name == KEYWORD_EVAL && args_expr.len() == 1 {
|
||||||
let hash_fn = calc_fn_hash(empty(), name, 1, once(TypeId::of::<ImmutableString>()));
|
let hash_fn = calc_fn_hash(empty(), name, 1, once(TypeId::of::<ImmutableString>()));
|
||||||
|
@ -454,6 +454,9 @@ impl Module {
|
|||||||
/// Arguments are simply passed in as a mutable array of `&mut Dynamic`,
|
/// Arguments are simply passed in as a mutable array of `&mut Dynamic`,
|
||||||
/// which is guaranteed to contain enough arguments of the correct types.
|
/// which is guaranteed to contain enough arguments of the correct types.
|
||||||
///
|
///
|
||||||
|
/// The function is assumed to be a _method_, meaning that the first argument should not be consumed.
|
||||||
|
/// All other arguments can be consumed.
|
||||||
|
///
|
||||||
/// To access a primary parameter value (i.e. cloning is cheap), use: `args[n].clone().cast::<T>()`
|
/// To access a primary parameter value (i.e. cloning is cheap), use: `args[n].clone().cast::<T>()`
|
||||||
///
|
///
|
||||||
/// To access a parameter value and avoid cloning, use `std::mem::take(args[n]).cast::<T>()`.
|
/// To access a parameter value and avoid cloning, use `std::mem::take(args[n]).cast::<T>()`.
|
||||||
@ -1299,8 +1302,8 @@ impl Module {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.for_each(|ScopeEntry { value, alias, .. }| {
|
.for_each(|ScopeEntry { value, alias, .. }| {
|
||||||
// Variables with an alias left in the scope become module variables
|
// Variables with an alias left in the scope become module variables
|
||||||
if alias.is_some() {
|
if let Some(alias) = alias {
|
||||||
module.variables.insert(*alias.unwrap(), value);
|
module.variables.insert(*alias, value);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
20
src/token.rs
20
src/token.rs
@ -2,9 +2,12 @@
|
|||||||
|
|
||||||
use crate::engine::{
|
use crate::engine::{
|
||||||
Engine, KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_FN_PTR, KEYWORD_FN_PTR_CALL, KEYWORD_FN_PTR_CURRY,
|
Engine, KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_FN_PTR, KEYWORD_FN_PTR_CALL, KEYWORD_FN_PTR_CURRY,
|
||||||
KEYWORD_IS_SHARED, KEYWORD_PRINT, KEYWORD_THIS, KEYWORD_TYPE_OF,
|
KEYWORD_IS_DEF_FN, KEYWORD_IS_DEF_VAR, KEYWORD_PRINT, KEYWORD_THIS, KEYWORD_TYPE_OF,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_closure"))]
|
||||||
|
use crate::engine::KEYWORD_IS_SHARED;
|
||||||
|
|
||||||
use crate::error::LexError;
|
use crate::error::LexError;
|
||||||
use crate::parser::INT;
|
use crate::parser::INT;
|
||||||
use crate::utils::StaticVec;
|
use crate::utils::StaticVec;
|
||||||
@ -507,9 +510,11 @@ impl Token {
|
|||||||
| "await" | "yield" => Reserved(syntax.into()),
|
| "await" | "yield" => Reserved(syntax.into()),
|
||||||
|
|
||||||
KEYWORD_PRINT | KEYWORD_DEBUG | KEYWORD_TYPE_OF | KEYWORD_EVAL | KEYWORD_FN_PTR
|
KEYWORD_PRINT | KEYWORD_DEBUG | KEYWORD_TYPE_OF | KEYWORD_EVAL | KEYWORD_FN_PTR
|
||||||
| KEYWORD_FN_PTR_CALL | KEYWORD_FN_PTR_CURRY | KEYWORD_IS_SHARED | KEYWORD_THIS => {
|
| KEYWORD_FN_PTR_CALL | KEYWORD_FN_PTR_CURRY | KEYWORD_IS_DEF_VAR
|
||||||
Reserved(syntax.into())
|
| KEYWORD_IS_DEF_FN | KEYWORD_THIS => Reserved(syntax.into()),
|
||||||
}
|
|
||||||
|
#[cfg(not(feature = "no_closure"))]
|
||||||
|
KEYWORD_IS_SHARED => Reserved(syntax.into()),
|
||||||
|
|
||||||
_ => return None,
|
_ => return None,
|
||||||
})
|
})
|
||||||
@ -1455,7 +1460,9 @@ pub fn is_keyword_function(name: &str) -> bool {
|
|||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
KEYWORD_IS_SHARED => true,
|
KEYWORD_IS_SHARED => true,
|
||||||
KEYWORD_PRINT | KEYWORD_DEBUG | KEYWORD_TYPE_OF | KEYWORD_EVAL | KEYWORD_FN_PTR
|
KEYWORD_PRINT | KEYWORD_DEBUG | KEYWORD_TYPE_OF | KEYWORD_EVAL | KEYWORD_FN_PTR
|
||||||
| KEYWORD_FN_PTR_CALL | KEYWORD_FN_PTR_CURRY => true,
|
| KEYWORD_FN_PTR_CALL | KEYWORD_FN_PTR_CURRY | KEYWORD_IS_DEF_VAR | KEYWORD_IS_DEF_FN => {
|
||||||
|
true
|
||||||
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1465,7 +1472,8 @@ pub fn is_keyword_function(name: &str) -> bool {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn can_override_keyword(name: &str) -> bool {
|
pub fn can_override_keyword(name: &str) -> bool {
|
||||||
match name {
|
match name {
|
||||||
KEYWORD_PRINT | KEYWORD_DEBUG | KEYWORD_TYPE_OF | KEYWORD_EVAL | KEYWORD_FN_PTR => true,
|
KEYWORD_PRINT | KEYWORD_DEBUG | KEYWORD_TYPE_OF | KEYWORD_EVAL | KEYWORD_FN_PTR
|
||||||
|
| KEYWORD_IS_DEF_VAR | KEYWORD_IS_DEF_FN => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user