@@ -222,6 +222,11 @@ bool MCScriptThrowInvalidValueForGlobalVariableError(MCScriptModuleRef p_module,
222222 return MCErrorCreateAndThrow (kMCScriptInvalidVariableValueErrorTypeInfo , " module" , p_module -> name, " variable" , MCScriptGetNameOfGlobalVariableInModule (p_module, p_index), " type" , MCNamedTypeInfoGetName (p_expected_type), " value" , p_value, nil);
223223}
224224
225+ bool MCScriptThrowInvalidValueForContextVariableError (MCScriptModuleRef p_module, uindex_t p_index, MCTypeInfoRef p_expected_type, MCValueRef p_value)
226+ {
227+ return MCErrorCreateAndThrow (kMCScriptInvalidVariableValueErrorTypeInfo , " module" , p_module -> name, " variable" , MCScriptGetNameOfContextVariableInModule (p_module, p_index), " type" , MCNamedTypeInfoGetName (p_expected_type), " value" , p_value, nil);
228+ }
229+
225230bool MCScriptThrowNotABooleanError (MCValueRef p_value)
226231{
227232 return MCErrorCreateAndThrow (kMCScriptNotABooleanValueErrorTypeInfo , " value" , p_value, nil);
@@ -285,6 +290,11 @@ bool MCScriptThrowNotAHandlerValueError(MCValueRef p_value)
285290 return MCErrorCreateAndThrow (kMCScriptNotAHandlerValueErrorTypeInfo , " value" , p_value, nil);
286291}
287292
293+ bool MCScriptThrowCannotCallContextHandlerError (MCScriptModuleRef p_module, MCScriptDefinition *p_handler)
294+ {
295+ return MCErrorCreateAndThrow (kMCScriptCannotCallContextHandlerErrorTypeInfo , " module" , p_module -> name, " handler" , MCScriptGetNameOfDefinitionInModule (p_module, p_handler), nil);
296+ }
297+
288298// /////////
289299
290300MCScriptVariableDefinition *MCScriptDefinitionAsVariable (MCScriptDefinition *self)
@@ -464,6 +474,11 @@ static bool MCScriptCallHandlerOfInstanceDirect(MCScriptInstanceRef self, MCScri
464474 MCTypeInfoRef t_signature;
465475 t_signature = self -> module -> types[p_handler -> type] -> typeinfo;
466476
477+ // If the handler is of context scope, then we cannot call it directly - only
478+ // from a LCB frame.
479+ if (p_handler -> scope == kMCScriptHandlerScopeContext )
480+ return MCScriptThrowCannotCallContextHandlerError (self -> module , p_handler);
481+
467482 // Check the number of arguments.
468483 uindex_t t_required_param_count;
469484 t_required_param_count = MCHandlerTypeInfoGetParameterCount (t_signature);
@@ -526,6 +541,12 @@ bool MCScriptCallHandlerOfInstanceIfFound(MCScriptInstanceRef self, MCNameRef p_
526541
527542// //////////////////////////////////////////////////////////////////////////////
528543
544+ struct MCScriptFrameContext
545+ {
546+ uindex_t count;
547+ MCValueRef slots[1 ];
548+ };
549+
529550// This structure is a single frame on the execution stack.
530551struct MCScriptFrame
531552{
@@ -546,6 +567,9 @@ struct MCScriptFrame
546567 // <locals>
547568 // <registers>
548569 MCValueRef *slots;
570+
571+ // The context slots for the current handler invocation (if initialized)
572+ MCScriptFrameContext *context;
549573
550574 // The result register in the caller.
551575 uindex_t result;
@@ -2155,7 +2179,31 @@ bool MCScriptCallHandlerOfInstanceInternal(MCScriptInstanceRef self, MCScriptHan
21552179
21562180 if (t_success)
21572181 t_success = MCScriptCheckedStoreToRegisterInFrame (t_frame, t_dst, t_value);
2182+ }
2183+ else if (t_definition -> kind == kMCScriptDefinitionKindContextVariable )
2184+ {
2185+ MCScriptContextVariableDefinition *t_var_definition;
2186+ t_var_definition = static_cast <MCScriptContextVariableDefinition *>(t_definition);
2187+
2188+ // If we are a normal handler we use the current frame.
2189+ // If we are context handler, we use the caller's frame.
2190+ MCScriptFrame *t_target_frame;
2191+ if (t_frame -> handler -> scope == kMCScriptHandlerScopeNormal )
2192+ t_target_frame = t_frame;
2193+ else if (t_frame -> caller != nil)
2194+ t_target_frame = t_frame -> caller;
2195+
2196+ // If there is no context table, or the value of the slot at the given
2197+ // index is nil then we use the default.
2198+ MCValueRef t_value;
2199+ if (t_target_frame -> context == nil ||
2200+ t_target_frame -> context -> count < t_var_definition -> slot_index ||
2201+ t_target_frame -> context -> slots[t_var_definition -> slot_index] == nil)
2202+ t_value = t_instance -> module -> values[t_var_definition -> default_value];
2203+ else
2204+ t_value = t_target_frame -> context -> slots[t_var_definition -> slot_index];
21582205
2206+ t_success = MCScriptCheckedStoreToRegisterInFrame (t_target_frame, t_dst, t_value);
21592207 }
21602208 else if (t_definition -> kind == kMCScriptDefinitionKindHandler )
21612209 {
@@ -2235,30 +2283,61 @@ bool MCScriptCallHandlerOfInstanceInternal(MCScriptInstanceRef self, MCScriptHan
22352283 MCScriptDefinition *t_definition;
22362284 MCScriptResolveDefinitionInFrame (t_frame, t_index, t_instance, t_definition);
22372285
2238- __MCScriptAssert__ (t_definition -> kind == kMCScriptDefinitionKindVariable ,
2239- " definition not a variable in store global" );
2240-
2241- MCScriptVariableDefinition *t_var_definition;
2242- t_var_definition = static_cast <MCScriptVariableDefinition *>(t_definition);
2243-
2244- MCTypeInfoRef t_output_type;
2245- t_output_type = t_instance -> module -> types[t_var_definition -> type] -> typeinfo;
2246-
22472286 MCValueRef t_value;
22482287 t_success = MCScriptCheckedFetchFromRegisterInFrame (t_frame, t_dst, t_value);
22492288
2250- if (t_success &&
2251- !MCTypeInfoConforms (MCValueGetTypeInfo (t_value), t_output_type))
2252- t_success = MCScriptThrowInvalidValueForGlobalVariableError (t_frame -> instance -> module , t_index, t_output_type, t_value);
2253-
2254- if (t_success)
2289+ if (t_definition -> kind == kMCScriptDefinitionKindVariable )
22552290 {
2256- if (t_instance -> slots[t_var_definition -> slot_index] != t_value)
2291+ MCScriptVariableDefinition *t_var_definition;
2292+ t_var_definition = static_cast <MCScriptVariableDefinition *>(t_definition);
2293+
2294+ MCTypeInfoRef t_output_type;
2295+ t_output_type = t_instance -> module -> types[t_var_definition -> type] -> typeinfo;
2296+
2297+ if (t_success &&
2298+ !MCTypeInfoConforms (MCValueGetTypeInfo (t_value), t_output_type))
2299+ t_success = MCScriptThrowInvalidValueForGlobalVariableError (t_frame -> instance -> module , t_index, t_output_type, t_value);
2300+
2301+ if (t_success)
2302+ MCValueAssign (t_instance -> slots[t_var_definition -> slot_index], t_value);
2303+ }
2304+ else if (t_definition -> kind == kMCScriptDefinitionKindContextVariable )
2305+ {
2306+ MCScriptContextVariableDefinition *t_var_definition;
2307+ t_var_definition = static_cast <MCScriptContextVariableDefinition *>(t_definition);
2308+
2309+ MCTypeInfoRef t_output_type;
2310+ t_output_type = t_instance -> module -> types[t_var_definition -> type] -> typeinfo;
2311+
2312+ if (t_success &&
2313+ !MCTypeInfoConforms (MCValueGetTypeInfo (t_value), t_output_type))
2314+ t_success = MCScriptThrowInvalidValueForContextVariableError (t_frame -> instance -> module , t_index, t_output_type, t_value);
2315+
2316+ // If we are a normal handler we use the current frame.
2317+ // If we are context handler, we use the caller's frame.
2318+ MCScriptFrame *t_target_frame;
2319+ if (t_frame -> handler -> scope == kMCScriptHandlerScopeNormal )
2320+ t_target_frame = t_frame;
2321+ else if (t_frame -> caller != nil)
2322+ t_target_frame = t_frame -> caller;
2323+
2324+ if (t_success &&
2325+ (t_target_frame -> context == nil ||
2326+ t_target_frame -> context -> count <= t_var_definition -> slot_index))
22572327 {
2258- MCValueRelease (t_instance -> slots[t_var_definition -> slot_index]);
2259- t_instance -> slots[t_var_definition -> slot_index] = MCValueRetain (t_value);
2328+ // Note that MCScriptFrameContext has an implement MCValueRef
2329+ // so we don't need to adjust index to be a count.
2330+ if (MCMemoryReallocate (t_target_frame -> context, sizeof (MCScriptFrameContext) + (sizeof (MCValueRef) * t_var_definition -> slot_index), t_target_frame -> context))
2331+ t_target_frame -> context -> count = t_var_definition -> slot_index + 1 ;
2332+ else
2333+ t_success = false ;
22602334 }
2335+
2336+ if (t_success)
2337+ MCValueAssign (t_target_frame -> context -> slots[t_var_definition -> slot_index], t_value);
22612338 }
2339+ else
2340+ MCUnreachable ();
22622341 }
22632342 break ;
22642343 case kMCScriptBytecodeOpAssignList :
0 commit comments