Skip to content

Commit f26780c

Browse files
committed
ucode: Add 'operator execute'
It can be useful to call a resource as if it was a function. This commit adds a way to do so. When a non-callable is supplied to uc_vm_insn_call(), and it is an object or has a prototype, then the object/prototype stack is searched for a callable named 'operator()', and if found, that is called instead. So in the script var(...); is a functional synonym to var['operator()'](); Signed-off-by: Isaac de Wolff <[email protected]>
1 parent 61679aa commit f26780c

File tree

1 file changed

+47
-4
lines changed

1 file changed

+47
-4
lines changed

vm.c

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2427,6 +2427,20 @@ uc_vm_insn_close_upval(uc_vm_t *vm, uc_vm_insn_t insn)
24272427
ucv_put(uc_vm_stack_pop(vm));
24282428
}
24292429

2430+
static uc_value_t *
2431+
uc_vm_get_operator_exec( uc_value_t *proto )
2432+
{
2433+
int i;
2434+
for( i=0; i<16 && proto; i++ ) {
2435+
bool found = false;
2436+
uc_value_t *fn = ucv_object_get( proto, "operator()", &found );
2437+
if( found && ucv_is_callable( fn ) )
2438+
return fn;
2439+
proto = ucv_prototype_get( proto );
2440+
}
2441+
return 0;
2442+
}
2443+
24302444
static void
24312445
uc_vm_insn_call(uc_vm_t *vm, uc_vm_insn_t insn)
24322446
{
@@ -2435,10 +2449,39 @@ uc_vm_insn_call(uc_vm_t *vm, uc_vm_insn_t insn)
24352449
uc_value_t *fno = uc_vm_stack_peek(vm, nargs);
24362450
uc_value_t *ctx = NULL;
24372451

2438-
if (!ucv_is_arrowfn(fno))
2439-
ctx = mcall ? uc_vm_stack_peek(vm, nargs + 1) : NULL;
2440-
else if (vm->callframes.count > 0)
2441-
ctx = uc_vm_current_frame(vm)->ctx;
2452+
switch( ucv_type( fno ) )
2453+
{
2454+
case UC_OBJECT: {
2455+
uc_value_t *fn = uc_vm_get_operator_exec( fno );
2456+
if( fn ) {
2457+
fno = fn;
2458+
if( ucv_is_arrowfn( fno ) )
2459+
ctx = uc_vm_current_frame(vm)->ctx;
2460+
else
2461+
ctx = uc_vm_stack_peek( vm, nargs );
2462+
break;
2463+
}
2464+
break;
2465+
}
2466+
case UC_RESOURCE:
2467+
case UC_ARRAY: {
2468+
uc_value_t *fn = uc_vm_get_operator_exec( ucv_prototype_get( fno ) );
2469+
if( fn ) {
2470+
fno = fn;
2471+
if( ucv_is_arrowfn( fno ) )
2472+
ctx = uc_vm_current_frame(vm)->ctx;
2473+
else
2474+
ctx = uc_vm_stack_peek( vm, nargs );
2475+
break;
2476+
}
2477+
default:
2478+
if (!ucv_is_arrowfn(fno))
2479+
ctx = mcall ? uc_vm_stack_peek(vm, nargs + 1) : NULL;
2480+
else if (vm->callframes.count > 0)
2481+
ctx = uc_vm_current_frame(vm)->ctx;
2482+
break;
2483+
}
2484+
}
24422485

24432486
uc_vm_call_function(vm, ucv_get(ctx), ucv_get(fno), mcall, vm->arg.u32);
24442487
}

0 commit comments

Comments
 (0)