Skip to content

Commit 62546e8

Browse files
committed
[[ LCB ]] Implement dynamic handler calls for non-foreign handlers.
1 parent 2024fb2 commit 62546e8

4 files changed

Lines changed: 128 additions & 22 deletions

File tree

libscript/src/script-instance.cpp

Lines changed: 117 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,24 @@
2929

3030
////////////////////////////////////////////////////////////////////////////////
3131

32+
struct MCScriptHandlerContext
33+
{
34+
MCScriptInstanceRef instance;
35+
MCScriptHandlerDefinition *definition;
36+
};
37+
38+
static bool MCScriptHandlerInvoke(void *context, MCValueRef *p_arguments, uindex_t p_argument_count, MCValueRef& r_value);
39+
static void MCScriptHandlerRelease(void *context);
40+
41+
static const MCHandlerCallbacks kMCScriptHandlerCallbacks =
42+
{
43+
sizeof(MCScriptHandlerContext),
44+
MCScriptHandlerRelease,
45+
MCScriptHandlerInvoke,
46+
};
47+
48+
////////////////////////////////////////////////////////////////////////////////
49+
3250
bool MCScriptCreateInstanceOfModule(MCScriptModuleRef p_module, MCScriptInstanceRef& r_instance)
3351
{
3452
bool t_success;
@@ -252,6 +270,11 @@ bool MCScriptThrowUnableToResolveMultiInvoke(MCScriptModuleRef p_module, MCScrip
252270
return MCErrorCreateAndThrow(kMCScriptNoMatchingHandlerErrorTypeInfo, "handlers", *t_handler_list, "types", *t_type_list, nil);
253271
}
254272

273+
bool MCScriptThrowNotAHandlerValueError(MCValueRef p_value)
274+
{
275+
return MCErrorCreateAndThrow(kMCScriptNotAHandlerValueErrorTypeInfo, "value", p_value, nil);
276+
}
277+
255278
///////////
256279

257280
MCScriptVariableDefinition *MCScriptDefinitionAsVariable(MCScriptDefinition *self)
@@ -684,6 +707,17 @@ static inline MCValueRef MCScriptFetchFromRegisterInFrame(MCScriptFrame *p_frame
684707
return p_frame -> slots[p_frame -> handler -> register_offset + p_register];
685708
}
686709

710+
static inline void MCScriptStoreToRegisterInFrameAndRelease(MCScriptFrame *p_frame, int p_register, MCValueRef p_value)
711+
{
712+
/* LOAD CHECK */ __MCScriptAssert__(p_register >= 0 && p_register < p_frame -> handler -> slot_count - p_frame -> handler -> register_offset,
713+
"register out of range on store");
714+
if (p_frame -> slots[p_frame -> handler -> register_offset + p_register] != p_value)
715+
{
716+
MCValueRelease(p_frame -> slots[p_frame -> handler -> register_offset + p_register]);
717+
p_frame -> slots[p_frame -> handler -> register_offset + p_register] = p_value;
718+
}
719+
}
720+
687721
static inline void MCScriptStoreToRegisterInFrame(MCScriptFrame *p_frame, int p_register, MCValueRef p_value)
688722
{
689723
/* LOAD CHECK */ __MCScriptAssert__(p_register >= 0 && p_register < p_frame -> handler -> slot_count - p_frame -> handler -> register_offset,
@@ -1598,6 +1632,21 @@ bool MCScriptBytecodeIterate(byte_t*& x_bytecode, byte_t *p_bytecode_limit, MCSc
15981632
return true;
15991633
}
16001634

1635+
static bool MCScriptHandlerInvoke(void *p_context, MCValueRef *p_arguments, uindex_t p_argument_count, MCValueRef& r_result)
1636+
{
1637+
MCScriptHandlerContext *context;
1638+
context = (MCScriptHandlerContext *)p_context;
1639+
1640+
return MCScriptCallHandlerOfInstanceDirect(context -> instance, context -> definition, p_arguments, p_argument_count, r_result);
1641+
}
1642+
1643+
static void MCScriptHandlerRelease(void *p_context)
1644+
{
1645+
MCScriptHandlerContext *context;
1646+
context = (MCScriptHandlerContext *)p_context;
1647+
MCScriptReleaseInstance(context -> instance);
1648+
}
1649+
16011650
bool MCScriptCallHandlerOfInstanceInternal(MCScriptInstanceRef self, MCScriptHandlerDefinition *p_handler, MCValueRef *p_arguments, uindex_t p_argument_count, MCValueRef& r_value)
16021651
{
16031652
// As this method is called internally, we can be sure that the arguments conform
@@ -1877,13 +1926,40 @@ bool MCScriptCallHandlerOfInstanceInternal(MCScriptInstanceRef self, MCScriptHan
18771926

18781927
__MCScriptAssert__(MCValueGetTypeCode(t_handler) == kMCValueTypeCodeHandler,
18791928
"handler argument to invoke not a handler");
1929+
1930+
if (MCValueGetTypeCode(t_handler) != kMCValueTypeCodeHandler)
1931+
t_success = MCScriptThrowNotAHandlerValueError(t_handler);
1932+
1933+
// Build the argument list (arg_1 onwards).
1934+
MCValueRef *t_handler_args;
1935+
if (t_success)
1936+
t_success = MCMemoryNewArray(t_arity - 2, t_handler_args);
18801937

1881-
MCScriptInstanceRef t_instance;
1882-
MCScriptDefinition *t_definition;
1883-
t_instance = (MCScriptInstanceRef)MCHandlerGetInstance((MCHandlerRef)t_handler);
1884-
t_definition = (MCScriptDefinition *)MCHandlerGetDefinition((MCHandlerRef)t_handler);
1885-
1886-
t_success = MCScriptPerformInvoke(t_frame, t_next_bytecode, t_instance, t_definition, t_arguments + 1, t_arity - 1);
1938+
if (t_success)
1939+
{
1940+
for(int i = 0; i < t_arity - 2; i++)
1941+
t_handler_args[i] = MCScriptFetchFromRegisterInFrame(t_frame, t_arguments[i + 2]);
1942+
1943+
MCValueRef t_result;
1944+
t_success = MCHandlerInvoke((MCHandlerRef)t_handler, t_handler_args, t_arity - 2, t_result);
1945+
1946+
// If the call succeeded, we must copy back all 'out' / 'inout' mode parameters
1947+
// to the register file, and also the result.
1948+
if (t_success)
1949+
{
1950+
MCTypeInfoRef t_signature;
1951+
t_signature = MCValueGetTypeInfo(t_handler);
1952+
1953+
for(uindex_t i = 0; i < MCHandlerTypeInfoGetParameterCount(t_signature); i++)
1954+
if (MCHandlerTypeInfoGetParameterMode(t_signature, i) != kMCHandlerTypeFieldModeIn)
1955+
MCScriptStoreToRegisterInFrameAndRelease(t_frame, t_arguments[i + 2], t_handler_args[i]);
1956+
1957+
1958+
MCScriptStoreToRegisterInFrameAndRelease(t_frame, t_arguments[1], t_result);
1959+
}
1960+
1961+
MCMemoryDeleteArray(t_handler_args);
1962+
}
18871963
}
18881964
break;
18891965
case kMCScriptBytecodeOpFetchLocal:
@@ -1993,21 +2069,46 @@ bool MCScriptCallHandlerOfInstanceInternal(MCScriptInstanceRef self, MCScriptHan
19932069
MCScriptDefinition *t_definition;
19942070
MCScriptResolveDefinitionInFrame(t_frame, t_index, t_instance, t_definition);
19952071

1996-
__MCScriptAssert__(t_definition -> kind == kMCScriptDefinitionKindVariable,
1997-
"definition not a variable in fetch global");
1998-
1999-
MCScriptVariableDefinition *t_var_definition;
2000-
t_var_definition = static_cast<MCScriptVariableDefinition *>(t_definition);
2001-
2072+
// Fetch the value - if it is a variable fetch from the slot; if
2073+
// it is a handler construct a handler value.
20022074
MCValueRef t_value;
2003-
t_value = t_instance -> slots[t_var_definition -> slot_index];
2075+
if (t_definition -> kind == kMCScriptDefinitionKindVariable)
2076+
{
2077+
MCScriptVariableDefinition *t_var_definition;
2078+
t_var_definition = static_cast<MCScriptVariableDefinition *>(t_definition);
20042079

2005-
if (t_value == kMCNull &&
2006-
!MCTypeInfoIsOptional(t_instance -> module -> types[t_var_definition -> type] -> typeinfo))
2007-
t_success = MCScriptThrowGlobalVariableUsedBeforeDefinedError(t_frame -> instance -> module, t_index);
2080+
t_value = t_instance -> slots[t_var_definition -> slot_index];
2081+
2082+
if (t_value == kMCNull &&
2083+
!MCTypeInfoIsOptional(t_instance -> module -> types[t_var_definition -> type] -> typeinfo))
2084+
t_success = MCScriptThrowGlobalVariableUsedBeforeDefinedError(t_frame -> instance -> module, t_index);
2085+
}
2086+
else if (t_definition -> kind == kMCScriptDefinitionKindHandler)
2087+
{
2088+
MCScriptHandlerDefinition *t_handler_definition;
2089+
t_handler_definition = static_cast<MCScriptHandlerDefinition *>(t_definition);
2090+
2091+
MCTypeInfoRef t_signature;
2092+
t_signature = t_instance -> module -> types[t_handler_definition -> type] -> typeinfo;
2093+
2094+
// The context struct is 'moved' into the handlerref.
2095+
MCScriptHandlerContext t_context;
2096+
t_context . instance = MCScriptRetainInstance(t_instance);
2097+
t_context . definition = t_handler_definition;
2098+
2099+
t_success = MCHandlerCreate(t_signature, &kMCScriptHandlerCallbacks, &t_context, (MCHandlerRef&)t_value);
2100+
}
2101+
else
2102+
{
2103+
// TODO: Implement support for foreign handler evaluation
2104+
t_success = false;
2105+
}
20082106

20092107
if (t_success)
2108+
{
20102109
MCScriptStoreToRegisterInFrame(t_frame, t_dst, t_value);
2110+
MCValueRelease(t_value);
2111+
}
20112112
}
20122113
break;
20132114
case kMCScriptBytecodeOpStoreGlobal:

libscript/src/script-module.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ bool MCScriptValidateModule(MCScriptModuleRef self)
307307
case kMCScriptBytecodeOpStoreGlobal:
308308
// check arity is 2
309309
// check glob index is in definition range
310-
// check definition[index] is variable
310+
// check definition[index] is variable or handler
311311
t_temporary_count = MCMax(t_temporary_count, t_operands[0] + 1);
312312
break;
313313
}

libscript/src/script-object.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ MCTypeInfoRef kMCScriptTypeBindingErrorTypeInfo;
3535
MCTypeInfoRef kMCScriptNoMatchingHandlerErrorTypeInfo;
3636
MCTypeInfoRef kMCScriptCannotSetReadOnlyPropertyErrorTypeInfo;
3737
MCTypeInfoRef kMCScriptInvalidPropertyValueErrorTypeInfo;
38+
MCTypeInfoRef kMCScriptNotAHandlerValueErrorTypeInfo;
3839

3940
////////////////////////////////////////////////////////////////////////////////
4041

@@ -268,6 +269,7 @@ bool MCScriptInitialize(void)
268269
MCScriptCreateNamedErrorType(MCNAME("livecode.lang.NoMatchingHandlerError"), MCSTR("No matching handler for arguments with types (%{types}) - possible handlers (%{handlers})"), kMCScriptNoMatchingHandlerErrorTypeInfo);
269270
MCScriptCreateNamedErrorType(MCNAME("livecode.lang.CannotSetReadOnlyPropertyError"), MCSTR("Cannot set read-only property %{module}.%{property}"), kMCScriptCannotSetReadOnlyPropertyErrorTypeInfo);
270271
MCScriptCreateNamedErrorType(MCNAME("livecode.lang.PropertyValueTypeError"), MCSTR("Value is not of correct type for setting property - expected type %{type} for setting property %{module}.%{property}"), kMCScriptInvalidPropertyValueErrorTypeInfo);
272+
MCScriptCreateNamedErrorType(MCNAME("livecode.lang.NotAHandlerValueError"), MCSTR("Value is not a handler"), kMCScriptNotAHandlerValueErrorTypeInfo);
271273
}
272274

273275
return true;

libscript/src/script-private.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ extern MCTypeInfoRef kMCScriptTypeBindingErrorTypeInfo;
4040
extern MCTypeInfoRef kMCScriptNoMatchingHandlerErrorTypeInfo;
4141
extern MCTypeInfoRef kMCScriptCannotSetReadOnlyPropertyErrorTypeInfo;
4242
extern MCTypeInfoRef kMCScriptInvalidPropertyValueErrorTypeInfo;
43+
extern MCTypeInfoRef kMCScriptNotAHandlerValueErrorTypeInfo;
4344

4445
////////////////////////////////////////////////////////////////////////////////
4546

@@ -249,10 +250,13 @@ struct MCScriptVariableDefinition: public MCScriptDefinition
249250
uindex_t slot_index;
250251
};
251252

252-
struct MCScriptHandlerDefinition: public MCScriptDefinition
253+
struct MCScriptCommonHandlerDefinition: public MCScriptDefinition
254+
{
255+
uindex_t type;
256+
};
257+
258+
struct MCScriptHandlerDefinition: public MCScriptCommonHandlerDefinition
253259
{
254-
uindex_t type;
255-
256260
uindex_t *locals;
257261
uindex_t local_count;
258262

@@ -287,9 +291,8 @@ struct MCScriptSyntaxDefinition: public MCScriptDefinition
287291
uindex_t method_count;
288292
};
289293

290-
struct MCScriptForeignHandlerDefinition: public MCScriptDefinition
294+
struct MCScriptForeignHandlerDefinition: public MCScriptCommonHandlerDefinition
291295
{
292-
uindex_t type;
293296
MCStringRef binding;
294297

295298
// Bound function information - not pickled.

0 commit comments

Comments
 (0)