Implement capturing.

This commit is contained in:
Stephen Chung
2020-07-30 18:18:28 +08:00
parent e505a06839
commit 98b294c699
17 changed files with 410 additions and 180 deletions

View File

@@ -686,7 +686,7 @@ impl Engine {
let args = &mut [target.as_mut(), &mut idx_val2, &mut new_val];
self.exec_fn_call(
state, lib, FN_IDX_SET, true, 0, args, is_ref, true, false,
state, lib, FN_IDX_SET, 0, args, is_ref, true, false, None,
None, level,
)
.or_else(|err| match *err {
@@ -710,7 +710,7 @@ impl Engine {
let args = &mut [target.as_mut(), &mut idx_val2, &mut new_val];
self.exec_fn_call(
state, lib, FN_IDX_SET, true, 0, args, is_ref, true, false,
state, lib, FN_IDX_SET, 0, args, is_ref, true, false, None,
None, level,
)?;
}
@@ -732,7 +732,7 @@ impl Engine {
match rhs {
// xxx.fn_name(arg_expr_list)
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();
self.make_method_call(
state, lib, name, *hash, target, idx_val, *def_val, *native, false,
level,
@@ -766,7 +766,7 @@ impl Engine {
let ((_, _, setter), pos) = x.as_ref();
let mut args = [target.as_mut(), _new_val.as_mut().unwrap()];
self.exec_fn_call(
state, lib, setter, true, 0, &mut args, is_ref, true, false, None,
state, lib, setter, 0, &mut args, is_ref, true, false, None, None,
level,
)
.map(|(v, _)| (v, true))
@@ -777,7 +777,7 @@ impl Engine {
let ((_, getter, _), pos) = x.as_ref();
let mut args = [target.as_mut()];
self.exec_fn_call(
state, lib, getter, true, 0, &mut args, is_ref, true, false, None,
state, lib, getter, 0, &mut args, is_ref, true, false, None, None,
level,
)
.map(|(v, _)| (v, false))
@@ -795,7 +795,7 @@ impl Engine {
}
// {xxx:map}.fn_name(arg_expr_list)[expr] | {xxx:map}.fn_name(arg_expr_list).expr
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 (val, _) = self
.make_method_call(
state, lib, name, *hash, target, idx_val, *def_val,
@@ -828,7 +828,7 @@ impl Engine {
let args = &mut arg_values[..1];
let (mut val, updated) = self
.exec_fn_call(
state, lib, getter, true, 0, args, is_ref, true, false,
state, lib, getter, 0, args, is_ref, true, false, None,
None, level,
)
.map_err(|err| err.new_position(*pos))?;
@@ -848,8 +848,8 @@ impl Engine {
// Re-use args because the first &mut parameter will not be consumed
arg_values[1] = val;
self.exec_fn_call(
state, lib, setter, true, 0, arg_values, is_ref, true,
false, None, level,
state, lib, setter, 0, arg_values, is_ref, true, false,
None, None, level,
)
.or_else(
|err| match *err {
@@ -866,7 +866,7 @@ impl Engine {
}
// xxx.fn_name(arg_expr_list)[expr] | xxx.fn_name(arg_expr_list).expr
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 (mut val, _) = self
.make_method_call(
state, lib, name, *hash, target, idx_val, *def_val,
@@ -1138,7 +1138,7 @@ impl Engine {
let type_name = val.type_name();
let args = &mut [val, &mut _idx];
self.exec_fn_call(
state, _lib, FN_IDX_GET, true, 0, args, is_ref, true, false, None, _level,
state, _lib, FN_IDX_GET, 0, args, is_ref, true, false, None, None, _level,
)
.map(|(v, _)| v.into())
.map_err(|err| match *err {
@@ -1186,15 +1186,13 @@ impl Engine {
let def_value = Some(false);
let args = &mut [&mut lhs_value.clone(), value];
let hashes = (
// Qualifiers (none) + function name + number of arguments + argument `TypeId`'s.
calc_fn_hash(empty(), op, args.len(), args.iter().map(|a| a.type_id())),
0,
);
// Qualifiers (none) + function name + number of arguments + argument `TypeId`'s.
let hash =
calc_fn_hash(empty(), op, args.len(), args.iter().map(|a| a.type_id()));
let (r, _) = self
.call_fn_raw(
&mut scope, mods, state, lib, op, hashes, args, false, false, false,
&mut scope, mods, state, lib, op, hash, args, false, false, false,
def_value, level,
)
.map_err(|err| err.new_position(rhs.position()))?;
@@ -1301,14 +1299,14 @@ impl Engine {
} else if run_builtin_op_assignment(op, lhs_ptr, &rhs_val)?.is_none() {
// Not built in, map to `var = var op rhs`
let op = &op[..op.len() - 1]; // extract operator without =
let hash = calc_fn_hash(empty(), op, 2, empty());
// Clone the LHS value
let args = &mut [&mut lhs_ptr.clone(), &mut rhs_val];
// Run function
let (value, _) = self
.exec_fn_call(
state, lib, op, true, hash, args, false, false, false, None,
level,
state, lib, op, 0, args, false, false, false, None, None, level,
)
.map_err(|err| err.new_position(*op_pos))?;
// Set value to LHS
@@ -1331,13 +1329,12 @@ impl Engine {
} else {
// Op-assignment - always map to `lhs = lhs op rhs`
let op = &op[..op.len() - 1]; // extract operator without =
let hash = calc_fn_hash(empty(), op, 2, empty());
let args = &mut [
&mut self.eval_expr(scope, mods, state, lib, this_ptr, lhs_expr, level)?,
&mut rhs_val,
];
self.exec_fn_call(
state, lib, op, true, hash, args, false, false, false, None, level,
state, lib, op, 0, args, false, false, false, None, None, level,
)
.map(|(v, _)| v)
.map_err(|err| err.new_position(*op_pos))?
@@ -1407,20 +1404,20 @@ impl Engine {
// Normal function call
Expr::FnCall(x) if x.1.is_none() => {
let ((name, native, pos), _, hash, args_expr, def_val) = x.as_ref();
let ((name, native, capture, pos), _, hash, args_expr, def_val) = x.as_ref();
self.make_function_call(
scope, mods, state, lib, this_ptr, name, args_expr, *def_val, *hash, *native,
false, level,
false, *capture, level,
)
.map_err(|err| err.new_position(*pos))
}
// Module-qualified function call
Expr::FnCall(x) if x.1.is_some() => {
let ((name, _, pos), modules, hash, args_expr, def_val) = x.as_ref();
let ((name, _, capture, pos), modules, hash, args_expr, def_val) = x.as_ref();
self.make_qualified_function_call(
scope, mods, state, lib, this_ptr, modules, name, args_expr, *def_val, *hash,
level,
*capture, level,
)
.map_err(|err| err.new_position(*pos))
}