Support Dynamic as function default return value.
This commit is contained in:
parent
e62d1cd3ff
commit
03dce86328
@ -32,6 +32,8 @@ New features
|
|||||||
* `AST::iter_functions` and `Module::iter_script_fn_info` to iterate functions.
|
* `AST::iter_functions` and `Module::iter_script_fn_info` to iterate functions.
|
||||||
* Functions iteration functions now take `FnMut` instead of `Fn`.
|
* Functions iteration functions now take `FnMut` instead of `Fn`.
|
||||||
* New `FileModuleResolver` that encapsulates the entire `AST` of the module script, allowing function cross-calling. The old version is renamed `MergingFileModuleResolver`.
|
* New `FileModuleResolver` that encapsulates the entire `AST` of the module script, allowing function cross-calling. The old version is renamed `MergingFileModuleResolver`.
|
||||||
|
* `split` function for splitting strings.
|
||||||
|
|
||||||
|
|
||||||
Version 0.18.3
|
Version 0.18.3
|
||||||
==============
|
==============
|
||||||
|
@ -6,20 +6,20 @@ Built-in String Functions
|
|||||||
The following standard methods (mostly defined in the [`MoreStringPackage`][packages] but excluded if
|
The following standard methods (mostly defined in the [`MoreStringPackage`][packages] but excluded if
|
||||||
using a [raw `Engine`]) operate on [strings]:
|
using a [raw `Engine`]) operate on [strings]:
|
||||||
|
|
||||||
| Function | Parameter(s) | Description |
|
| Function | Parameter(s) | Description |
|
||||||
| ------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------- |
|
| ------------------------- | ------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `len` method and property | _none_ | returns the number of characters (not number of bytes) in the string |
|
| `len` method and property | _none_ | returns the number of characters (not number of bytes) in the string |
|
||||||
| `pad` | character to pad, target length | pads the string with an character to at least a specified length |
|
| `pad` | character to pad, target length | pads the string with an character to at least a specified length |
|
||||||
| `+=` operator, `append` | character/string to append | Adds a character or a string to the end of another string |
|
| `+=` operator, `append` | character/string to append | Adds a character or a string to the end of another string |
|
||||||
| `clear` | _none_ | empties the string |
|
| `clear` | _none_ | empties the string |
|
||||||
| `truncate` | target length | cuts off the string at exactly a specified number of characters |
|
| `truncate` | target length | cuts off the string at exactly a specified number of characters |
|
||||||
| `contains` | character/sub-string to search for | checks if a certain character or sub-string occurs in the string |
|
| `contains` | character/sub-string to search for | checks if a certain character or sub-string occurs in the string |
|
||||||
| `index_of` | character/sub-string to search for, start index _(optional)_ | returns the index that a certain character or sub-string occurs in the string, or -1 if not found |
|
| `index_of` | character/sub-string to search for, start index _(optional)_ | returns the index that a certain character or sub-string occurs in the string, or -1 if not found |
|
||||||
| `sub_string` | start index, length _(optional)_ | extracts a sub-string (to the end of the string if length is not specified) |
|
| `sub_string` | start index, length _(optional)_ | extracts a sub-string (to the end of the string if length is not specified) |
|
||||||
| `split` | delimiter character/string | splits the string by the specified delimiter, returning an [array] of string segments |
|
| `split` | delimiter character/string | splits the string by the specified delimiter, returning an [array] of string segments; not available under [`no_index`] |
|
||||||
| `crop` | start index, length _(optional)_ | retains only a portion of the string (to the end of the string if length is not specified) |
|
| `crop` | start index, length _(optional)_ | retains only a portion of the string (to the end of the string if length is not specified) |
|
||||||
| `replace` | target character/sub-string, replacement character/string | replaces a sub-string with another |
|
| `replace` | target character/sub-string, replacement character/string | replaces a sub-string with another |
|
||||||
| `trim` | _none_ | trims the string of whitespace at the beginning and end |
|
| `trim` | _none_ | trims the string of whitespace at the beginning and end |
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
--------
|
--------
|
||||||
|
@ -769,7 +769,7 @@ impl Engine {
|
|||||||
let args = &mut [val, &mut idx_val2, &mut new_val];
|
let args = &mut [val, &mut idx_val2, &mut new_val];
|
||||||
|
|
||||||
self.exec_fn_call(
|
self.exec_fn_call(
|
||||||
state, lib, FN_IDX_SET, 0, args, is_ref, true, false, None, None,
|
state, lib, FN_IDX_SET, 0, args, is_ref, true, false, None, &None,
|
||||||
level,
|
level,
|
||||||
)
|
)
|
||||||
.map_err(|err| match *err {
|
.map_err(|err| match *err {
|
||||||
@ -798,8 +798,9 @@ impl Engine {
|
|||||||
// xxx.fn_name(arg_expr_list)
|
// xxx.fn_name(arg_expr_list)
|
||||||
Expr::FnCall(x) if x.1.is_none() => {
|
Expr::FnCall(x) if x.1.is_none() => {
|
||||||
let ((name, native, _, pos), _, hash, _, def_val) = x.as_ref();
|
let ((name, native, _, pos), _, hash, _, def_val) = x.as_ref();
|
||||||
|
let def_val = def_val.map(Into::<Dynamic>::into);
|
||||||
self.make_method_call(
|
self.make_method_call(
|
||||||
state, lib, name, *hash, target, idx_val, *def_val, *native, false,
|
state, lib, name, *hash, target, idx_val, &def_val, *native, false,
|
||||||
level,
|
level,
|
||||||
)
|
)
|
||||||
.map_err(|err| err.new_position(*pos))
|
.map_err(|err| err.new_position(*pos))
|
||||||
@ -833,7 +834,7 @@ impl Engine {
|
|||||||
let mut new_val = new_val;
|
let mut new_val = new_val;
|
||||||
let mut args = [target.as_mut(), new_val.as_mut().unwrap()];
|
let mut args = [target.as_mut(), new_val.as_mut().unwrap()];
|
||||||
self.exec_fn_call(
|
self.exec_fn_call(
|
||||||
state, lib, setter, 0, &mut args, is_ref, true, false, None, None,
|
state, lib, setter, 0, &mut args, is_ref, true, false, None, &None,
|
||||||
level,
|
level,
|
||||||
)
|
)
|
||||||
.map(|(v, _)| (v, true))
|
.map(|(v, _)| (v, true))
|
||||||
@ -844,7 +845,7 @@ impl Engine {
|
|||||||
let ((_, getter, _), pos) = x.as_ref();
|
let ((_, getter, _), pos) = x.as_ref();
|
||||||
let mut args = [target.as_mut()];
|
let mut args = [target.as_mut()];
|
||||||
self.exec_fn_call(
|
self.exec_fn_call(
|
||||||
state, lib, getter, 0, &mut args, is_ref, true, false, None, None,
|
state, lib, getter, 0, &mut args, is_ref, true, false, None, &None,
|
||||||
level,
|
level,
|
||||||
)
|
)
|
||||||
.map(|(v, _)| (v, false))
|
.map(|(v, _)| (v, false))
|
||||||
@ -865,9 +866,10 @@ impl Engine {
|
|||||||
// {xxx:map}.fn_name(arg_expr_list)[expr] | {xxx:map}.fn_name(arg_expr_list).expr
|
// {xxx:map}.fn_name(arg_expr_list)[expr] | {xxx:map}.fn_name(arg_expr_list).expr
|
||||||
Expr::FnCall(x) if x.1.is_none() => {
|
Expr::FnCall(x) if x.1.is_none() => {
|
||||||
let ((name, native, _, pos), _, hash, _, def_val) = x.as_ref();
|
let ((name, native, _, pos), _, hash, _, def_val) = x.as_ref();
|
||||||
|
let def_val = def_val.map(Into::<Dynamic>::into);
|
||||||
let (val, _) = self
|
let (val, _) = self
|
||||||
.make_method_call(
|
.make_method_call(
|
||||||
state, lib, name, *hash, target, idx_val, *def_val,
|
state, lib, name, *hash, target, idx_val, &def_val,
|
||||||
*native, false, level,
|
*native, false, level,
|
||||||
)
|
)
|
||||||
.map_err(|err| err.new_position(*pos))?;
|
.map_err(|err| err.new_position(*pos))?;
|
||||||
@ -898,7 +900,7 @@ impl Engine {
|
|||||||
let (mut val, updated) = self
|
let (mut val, updated) = self
|
||||||
.exec_fn_call(
|
.exec_fn_call(
|
||||||
state, lib, getter, 0, args, is_ref, true, false, None,
|
state, lib, getter, 0, args, is_ref, true, false, None,
|
||||||
None, level,
|
&None, level,
|
||||||
)
|
)
|
||||||
.map_err(|err| err.new_position(*pos))?;
|
.map_err(|err| err.new_position(*pos))?;
|
||||||
|
|
||||||
@ -924,7 +926,7 @@ impl Engine {
|
|||||||
arg_values[1] = val;
|
arg_values[1] = val;
|
||||||
self.exec_fn_call(
|
self.exec_fn_call(
|
||||||
state, lib, setter, 0, arg_values, is_ref, true, false,
|
state, lib, setter, 0, arg_values, is_ref, true, false,
|
||||||
None, None, level,
|
None, &None, level,
|
||||||
)
|
)
|
||||||
.or_else(
|
.or_else(
|
||||||
|err| match *err {
|
|err| match *err {
|
||||||
@ -942,9 +944,10 @@ impl Engine {
|
|||||||
// xxx.fn_name(arg_expr_list)[expr] | xxx.fn_name(arg_expr_list).expr
|
// xxx.fn_name(arg_expr_list)[expr] | xxx.fn_name(arg_expr_list).expr
|
||||||
Expr::FnCall(x) if x.1.is_none() => {
|
Expr::FnCall(x) if x.1.is_none() => {
|
||||||
let ((name, native, _, pos), _, hash, _, def_val) = x.as_ref();
|
let ((name, native, _, pos), _, hash, _, def_val) = x.as_ref();
|
||||||
|
let def_val = def_val.map(Into::<Dynamic>::into);
|
||||||
let (mut val, _) = self
|
let (mut val, _) = self
|
||||||
.make_method_call(
|
.make_method_call(
|
||||||
state, lib, name, *hash, target, idx_val, *def_val,
|
state, lib, name, *hash, target, idx_val, &def_val,
|
||||||
*native, false, level,
|
*native, false, level,
|
||||||
)
|
)
|
||||||
.map_err(|err| err.new_position(*pos))?;
|
.map_err(|err| err.new_position(*pos))?;
|
||||||
@ -1202,7 +1205,7 @@ impl Engine {
|
|||||||
let mut idx = idx;
|
let mut idx = idx;
|
||||||
let args = &mut [val, &mut idx];
|
let args = &mut [val, &mut idx];
|
||||||
self.exec_fn_call(
|
self.exec_fn_call(
|
||||||
state, _lib, FN_IDX_GET, 0, args, is_ref, true, false, None, None, _level,
|
state, _lib, FN_IDX_GET, 0, args, is_ref, true, false, None, &None, _level,
|
||||||
)
|
)
|
||||||
.map(|(v, _)| v.into())
|
.map(|(v, _)| v.into())
|
||||||
.map_err(|err| match *err {
|
.map_err(|err| match *err {
|
||||||
@ -1245,8 +1248,9 @@ impl Engine {
|
|||||||
let op = "==";
|
let op = "==";
|
||||||
|
|
||||||
// Call the `==` operator to compare each value
|
// Call the `==` operator to compare each value
|
||||||
|
let def_value = Some(false.into());
|
||||||
|
|
||||||
for value in rhs_value.iter_mut() {
|
for value in rhs_value.iter_mut() {
|
||||||
let def_value = Some(false);
|
|
||||||
let args = &mut [&mut lhs_value.clone(), value];
|
let args = &mut [&mut lhs_value.clone(), value];
|
||||||
|
|
||||||
// Qualifiers (none) + function name + number of arguments + argument `TypeId`'s.
|
// Qualifiers (none) + function name + number of arguments + argument `TypeId`'s.
|
||||||
@ -1254,7 +1258,7 @@ impl Engine {
|
|||||||
calc_fn_hash(empty(), op, args.len(), args.iter().map(|a| a.type_id()));
|
calc_fn_hash(empty(), op, args.len(), args.iter().map(|a| a.type_id()));
|
||||||
|
|
||||||
if self
|
if self
|
||||||
.call_native_fn(state, lib, op, hash, args, false, false, def_value)
|
.call_native_fn(state, lib, op, hash, args, false, false, &def_value)
|
||||||
.map_err(|err| err.new_position(rhs.position()))?
|
.map_err(|err| err.new_position(rhs.position()))?
|
||||||
.0
|
.0
|
||||||
.as_bool()
|
.as_bool()
|
||||||
@ -1264,7 +1268,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(false.into())
|
Ok(def_value.unwrap())
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Dynamic(Union::Map(rhs_value)) => match lhs_value {
|
Dynamic(Union::Map(rhs_value)) => match lhs_value {
|
||||||
@ -1395,7 +1399,7 @@ impl Engine {
|
|||||||
// Run function
|
// Run function
|
||||||
let (value, _) = self
|
let (value, _) = self
|
||||||
.exec_fn_call(
|
.exec_fn_call(
|
||||||
state, lib, op, 0, args, false, false, false, None, None,
|
state, lib, op, 0, args, false, false, false, None, &None,
|
||||||
level,
|
level,
|
||||||
)
|
)
|
||||||
.map_err(|err| err.new_position(*op_pos))?;
|
.map_err(|err| err.new_position(*op_pos))?;
|
||||||
@ -1431,7 +1435,7 @@ impl Engine {
|
|||||||
&mut rhs_val,
|
&mut rhs_val,
|
||||||
];
|
];
|
||||||
self.exec_fn_call(
|
self.exec_fn_call(
|
||||||
state, lib, op, 0, args, false, false, false, None, None, level,
|
state, lib, op, 0, args, false, false, false, None, &None, level,
|
||||||
)
|
)
|
||||||
.map(|(v, _)| v)
|
.map(|(v, _)| v)
|
||||||
.map_err(|err| err.new_position(*op_pos))?
|
.map_err(|err| err.new_position(*op_pos))?
|
||||||
@ -1499,8 +1503,9 @@ impl Engine {
|
|||||||
// Normal function call
|
// Normal function call
|
||||||
Expr::FnCall(x) if x.1.is_none() => {
|
Expr::FnCall(x) if x.1.is_none() => {
|
||||||
let ((name, native, capture, pos), _, hash, args_expr, def_val) = x.as_ref();
|
let ((name, native, capture, pos), _, hash, args_expr, def_val) = x.as_ref();
|
||||||
|
let def_val = def_val.map(Into::<Dynamic>::into);
|
||||||
self.make_function_call(
|
self.make_function_call(
|
||||||
scope, mods, state, lib, this_ptr, name, args_expr, *def_val, *hash, *native,
|
scope, mods, state, lib, this_ptr, name, args_expr, &def_val, *hash, *native,
|
||||||
false, *capture, level,
|
false, *capture, level,
|
||||||
)
|
)
|
||||||
.map_err(|err| err.new_position(*pos))
|
.map_err(|err| err.new_position(*pos))
|
||||||
|
@ -211,7 +211,7 @@ impl Engine {
|
|||||||
args: &mut FnCallArgs,
|
args: &mut FnCallArgs,
|
||||||
is_ref: bool,
|
is_ref: bool,
|
||||||
pub_only: bool,
|
pub_only: bool,
|
||||||
def_val: Option<bool>,
|
def_val: &Option<Dynamic>,
|
||||||
) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
|
) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
|
||||||
self.inc_operations(state)?;
|
self.inc_operations(state)?;
|
||||||
|
|
||||||
@ -281,7 +281,7 @@ impl Engine {
|
|||||||
|
|
||||||
// Return default value (if any)
|
// Return default value (if any)
|
||||||
if let Some(val) = def_val {
|
if let Some(val) = def_val {
|
||||||
return Ok((val.into(), false));
|
return Ok((val.clone(), false));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Getter function not found?
|
// Getter function not found?
|
||||||
@ -469,7 +469,7 @@ impl Engine {
|
|||||||
_is_method: bool,
|
_is_method: bool,
|
||||||
pub_only: bool,
|
pub_only: bool,
|
||||||
_capture: Option<Scope>,
|
_capture: Option<Scope>,
|
||||||
def_val: Option<bool>,
|
def_val: &Option<Dynamic>,
|
||||||
_level: usize,
|
_level: usize,
|
||||||
) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
|
) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
|
||||||
// Check for data race.
|
// Check for data race.
|
||||||
@ -669,7 +669,7 @@ impl Engine {
|
|||||||
hash_script: u64,
|
hash_script: u64,
|
||||||
target: &mut Target,
|
target: &mut Target,
|
||||||
idx_val: Dynamic,
|
idx_val: Dynamic,
|
||||||
def_val: Option<bool>,
|
def_val: &Option<Dynamic>,
|
||||||
native: bool,
|
native: bool,
|
||||||
pub_only: bool,
|
pub_only: bool,
|
||||||
level: usize,
|
level: usize,
|
||||||
@ -815,7 +815,7 @@ impl Engine {
|
|||||||
this_ptr: &mut Option<&mut Dynamic>,
|
this_ptr: &mut Option<&mut Dynamic>,
|
||||||
name: &str,
|
name: &str,
|
||||||
args_expr: &[Expr],
|
args_expr: &[Expr],
|
||||||
def_val: Option<bool>,
|
def_val: &Option<Dynamic>,
|
||||||
mut hash_script: u64,
|
mut hash_script: u64,
|
||||||
native: bool,
|
native: bool,
|
||||||
pub_only: bool,
|
pub_only: bool,
|
||||||
|
@ -145,7 +145,7 @@ impl FnPtr {
|
|||||||
has_this,
|
has_this,
|
||||||
true,
|
true,
|
||||||
None,
|
None,
|
||||||
None,
|
&None,
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
.map(|(v, _)| v)
|
.map(|(v, _)| v)
|
||||||
|
@ -142,7 +142,7 @@ fn call_fn_with_constant_arguments(
|
|||||||
arg_values.iter_mut().collect::<StaticVec<_>>().as_mut(),
|
arg_values.iter_mut().collect::<StaticVec<_>>().as_mut(),
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
None,
|
&None,
|
||||||
)
|
)
|
||||||
.ok()
|
.ok()
|
||||||
.map(|(v, _)| v)
|
.map(|(v, _)| v)
|
||||||
|
@ -790,7 +790,7 @@ pub enum Expr {
|
|||||||
Option<Box<ModuleRef>>,
|
Option<Box<ModuleRef>>,
|
||||||
u64,
|
u64,
|
||||||
StaticVec<Expr>,
|
StaticVec<Expr>,
|
||||||
Option<bool>,
|
Option<bool>, // Default value is `bool` in order for `Expr` to be `Hash`.
|
||||||
)>,
|
)>,
|
||||||
),
|
),
|
||||||
/// expr op= expr
|
/// expr op= expr
|
||||||
|
Loading…
Reference in New Issue
Block a user