Skip to content

Commit 475e1b9

Browse files
committed
[[ LCB ]] Initial implementation of context handlers.
A context handler operates on and with the context variables of its caller. To declare a context handler use: context handler ... ... end handler
1 parent 68a1913 commit 475e1b9

File tree

12 files changed

+80
-30
lines changed

12 files changed

+80
-30
lines changed

libscript/include/script.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,14 @@ enum MCScriptHandlerTypeParameterMode
274274
kMCScriptHandlerTypeParameterMode__Last
275275
};
276276

277+
enum MCScriptHandlerScope
278+
{
279+
kMCScriptHandlerScopeNormal,
280+
kMCScriptHandlerScopeContext,
281+
282+
kMCScriptHandlerScope__Last,
283+
};
284+
277285
void MCScriptBeginModule(MCScriptModuleKind kind, MCNameRef name, MCScriptModuleBuilderRef& r_builder);
278286
bool MCScriptEndModule(MCScriptModuleBuilderRef builder, MCStreamRef stream);
279287

@@ -305,7 +313,7 @@ void MCScriptAddConstantToModule(MCScriptModuleBuilderRef builder, MCNameRef nam
305313
void MCScriptAddVariableToModule(MCScriptModuleBuilderRef builder, MCNameRef name, uindex_t type, uindex_t index);
306314
void MCScriptAddContextVariableToModule(MCScriptModuleBuilderRef builder, MCNameRef name, uindex_t type, uindex_t index, uindex_t def_index);
307315

308-
void MCScriptBeginHandlerInModule(MCScriptModuleBuilderRef builder, MCNameRef name, uindex_t signature, uindex_t index);
316+
void MCScriptBeginHandlerInModule(MCScriptModuleBuilderRef builder, MCScriptHandlerScope scope, MCNameRef name, uindex_t signature, uindex_t index);
309317
void MCScriptAddParameterToHandlerInModule(MCScriptModuleBuilderRef builder, MCNameRef name, uindex_t type, uindex_t& r_index);
310318
void MCScriptAddVariableToHandlerInModule(MCScriptModuleBuilderRef builder, MCNameRef name, uindex_t type, uindex_t& r_index);
311319
void MCScriptEndHandlerInModule(MCScriptModuleBuilderRef builder);

libscript/src/script-builder.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1145,7 +1145,7 @@ static void __emit_position(MCScriptModuleBuilderRef self, uindex_t p_address, u
11451145
self -> module . positions[t_pindex] . line = p_line;
11461146
}
11471147

1148-
void MCScriptBeginHandlerInModule(MCScriptModuleBuilderRef self, MCNameRef p_name, uindex_t p_type, uindex_t p_index)
1148+
void MCScriptBeginHandlerInModule(MCScriptModuleBuilderRef self, MCScriptHandlerScope p_scope, MCNameRef p_name, uindex_t p_type, uindex_t p_index)
11491149
{
11501150
if (self == nil || !self -> valid)
11511151
return;
@@ -1166,6 +1166,7 @@ void MCScriptBeginHandlerInModule(MCScriptModuleBuilderRef self, MCNameRef p_nam
11661166
t_definition -> kind = kMCScriptDefinitionKindHandler;
11671167
t_definition -> type = p_type;
11681168
t_definition -> start_address = self -> module . bytecode_count;
1169+
t_definition -> scope = p_scope;
11691170

11701171
self -> current_handler = p_index;
11711172
self -> current_param_count = 0;

libscript/src/script-instance.cpp

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2171,17 +2171,25 @@ bool MCScriptCallHandlerOfInstanceInternal(MCScriptInstanceRef self, MCScriptHan
21712171
MCScriptContextVariableDefinition *t_var_definition;
21722172
t_var_definition = static_cast<MCScriptContextVariableDefinition *>(t_definition);
21732173

2174+
// If we are a normal handler we use the current frame.
2175+
// If we are context handler, we use the caller's frame.
2176+
MCScriptFrame *t_target_frame;
2177+
if (t_frame -> handler -> scope == kMCScriptHandlerScopeNormal)
2178+
t_target_frame = t_frame;
2179+
else if (t_frame -> caller != nil)
2180+
t_target_frame = t_frame -> caller;
2181+
21742182
// If there is no context table, or the value of the slot at the given
21752183
// index is nil then we use the default.
21762184
MCValueRef t_value;
2177-
if (t_frame -> context == nil ||
2178-
t_frame -> context -> count < t_var_definition -> slot_index ||
2179-
t_frame -> context -> slots[t_var_definition -> slot_index] == nil)
2180-
t_value = kMCFalse; // t_instance -> module -> values[t_var_definition -> default_value];
2185+
if (t_target_frame -> context == nil ||
2186+
t_target_frame -> context -> count < t_var_definition -> slot_index ||
2187+
t_target_frame -> context -> slots[t_var_definition -> slot_index] == nil)
2188+
t_value = t_instance -> module -> values[t_var_definition -> default_value];
21812189
else
2182-
t_value = t_frame -> context -> slots[t_var_definition -> slot_index];
2190+
t_value = t_target_frame -> context -> slots[t_var_definition -> slot_index];
21832191

2184-
t_success = MCScriptCheckedStoreToRegisterInFrame(t_frame, t_dst, t_value);
2192+
t_success = MCScriptCheckedStoreToRegisterInFrame(t_target_frame, t_dst, t_value);
21852193
}
21862194
else if (t_definition -> kind == kMCScriptDefinitionKindHandler)
21872195
{
@@ -2291,20 +2299,28 @@ bool MCScriptCallHandlerOfInstanceInternal(MCScriptInstanceRef self, MCScriptHan
22912299
!MCTypeInfoConforms(MCValueGetTypeInfo(t_value), t_output_type))
22922300
t_success = MCScriptThrowInvalidValueForContextVariableError(t_frame -> instance -> module, t_index, t_output_type, t_value);
22932301

2302+
// If we are a normal handler we use the current frame.
2303+
// If we are context handler, we use the caller's frame.
2304+
MCScriptFrame *t_target_frame;
2305+
if (t_frame -> handler -> scope == kMCScriptHandlerScopeNormal)
2306+
t_target_frame = t_frame;
2307+
else if (t_frame -> caller != nil)
2308+
t_target_frame = t_frame -> caller;
2309+
22942310
if (t_success &&
2295-
(t_frame -> context == nil ||
2296-
t_frame -> context -> count <= t_var_definition -> slot_index))
2311+
(t_target_frame -> context == nil ||
2312+
t_target_frame -> context -> count <= t_var_definition -> slot_index))
22972313
{
22982314
// Note that MCScriptFrameContext has an implement MCValueRef
22992315
// so we don't need to adjust index to be a count.
2300-
if (MCMemoryReallocate(t_frame -> context, sizeof(MCScriptFrameContext) + (sizeof(MCValueRef) * t_var_definition -> slot_index), t_frame -> context))
2301-
t_frame -> context -> count = t_var_definition -> slot_index + 1;
2316+
if (MCMemoryReallocate(t_target_frame -> context, sizeof(MCScriptFrameContext) + (sizeof(MCValueRef) * t_var_definition -> slot_index), t_target_frame -> context))
2317+
t_target_frame -> context -> count = t_var_definition -> slot_index + 1;
23022318
else
23032319
t_success = false;
23042320
}
23052321

23062322
if (t_success)
2307-
MCValueAssign(t_frame -> context -> slots[t_var_definition -> slot_index], t_value);
2323+
MCValueAssign(t_target_frame -> context -> slots[t_var_definition -> slot_index], t_value);
23082324
}
23092325
else
23102326
MCUnreachable();

libscript/src/script-module.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ MC_PICKLE_BEGIN_RECORD(MCScriptHandlerDefinition)
136136
MC_PICKLE_ARRAY_OF_NAMEREF(local_names, local_name_count)
137137
MC_PICKLE_UINDEX(start_address)
138138
MC_PICKLE_UINDEX(finish_address)
139+
MC_PICKLE_INTENUM(MCScriptHandlerScope, scope)
139140
MC_PICKLE_END_RECORD()
140141

141142
MC_PICKLE_BEGIN_RECORD(MCScriptForeignHandlerDefinition)

libscript/src/script-private.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,8 @@ struct MCScriptHandlerDefinition: public MCScriptCommonHandlerDefinition
276276
uindex_t start_address;
277277
uindex_t finish_address;
278278

279+
MCScriptHandlerScope scope;
280+
279281
// The number of slots required in a frame in order to execute this handler - computed.
280282
uindex_t slot_count;
281283
};

toolchain/lc-compile/src/bind.g

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@
116116
'rule' DeclareImportedDefinitions(contextvariable(Position, _, Name, _, _)):
117117
DeclareId(Name)
118118

119-
'rule' DeclareImportedDefinitions(handler(Position, _, Name, _, _, _)):
119+
'rule' DeclareImportedDefinitions(handler(Position, _, Name, _, _, _, _)):
120120
DeclareId(Name)
121121

122122
'rule' DeclareImportedDefinitions(foreignhandler(Position, _, Name, _, _)):
@@ -178,7 +178,7 @@
178178
'rule' Declare(contextvariable(Position, _, Name, _, _)):
179179
DeclareId(Name)
180180
181-
'rule' Declare(handler(Position, _, Name, _, _, _)):
181+
'rule' Declare(handler(Position, _, Name, _, _, _, _)):
182182
DeclareId(Name)
183183
184184
'rule' Declare(foreignhandler(Position, _, Name, _, _)):
@@ -251,7 +251,7 @@
251251
'rule' Define(ModuleId, contextvariable(Position, Access, Name, Type, _)):
252252
DefineSymbolId(Name, ModuleId, Access, context, Type)
253253
254-
'rule' Define(ModuleId, handler(Position, Access, Name, Signature:signature(Parameters, _), _, _)):
254+
'rule' Define(ModuleId, handler(Position, Access, Name, _, Signature:signature(Parameters, _), _, _)):
255255
DefineSymbolId(Name, ModuleId, Access, handler, handler(Position, Signature))
256256
DefineParameters(Name, Parameters)
257257
@@ -322,7 +322,7 @@
322322
323323
----------
324324
325-
'rule' Apply(DEFINITION'handler(_, _, Id, signature(Parameters, Type), _, Body)):
325+
'rule' Apply(DEFINITION'handler(_, _, Id, _, signature(Parameters, Type), _, Body)):
326326
-- The type of the handler is resolved in the current scope
327327
Apply(Type)
328328

@@ -709,7 +709,7 @@
709709
'rule' DumpBindings(DEFINITION'contextvariable(_, _, Name, Type, _)):
710710
DumpId("variable", Name)
711711
DumpBindings(Type)
712-
'rule' DumpBindings(DEFINITION'handler(_, _, Name, Signature, Definitions, Body)):
712+
'rule' DumpBindings(DEFINITION'handler(_, _, Name, _, Signature, Definitions, Body)):
713713
DumpId("handler", Name)
714714
DumpBindings(Signature)
715715
DumpBindings(Definitions)

toolchain/lc-compile/src/check.g

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,9 @@
263263
'rule' CheckBindingIsConstantOrVariableOrHandlerId(Id):
264264
QueryKindOfSymbolId(Id -> local)
265265
266+
'rule' CheckBindingIsConstantOrVariableOrHandlerId(Id):
267+
QueryKindOfSymbolId(Id -> context)
268+
266269
'rule' CheckBindingIsConstantOrVariableOrHandlerId(Id):
267270
QueryKindOfSymbolId(Id -> handler)
268271

toolchain/lc-compile/src/emit.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ extern "C" void EmitConstantDefinition(long p_index, PositionRef p_position, Nam
4444
extern "C" void EmitVariableDefinition(long index, PositionRef position, NameRef name, long type_index);
4545
extern "C" void EmitContextVariableDefinition(long index, PositionRef position, NameRef name, long type_index, long default_index);
4646
extern "C" void EmitBeginHandlerDefinition(long index, PositionRef position, NameRef name, long type_index);
47+
extern "C" void EmitBeginContextHandlerDefinition(long index, PositionRef position, NameRef name, long type_index);
4748
extern "C" void EmitEndHandlerDefinition(void);
4849
extern "C" void EmitForeignHandlerDefinition(long index, PositionRef position, NameRef name, long type_index, long binding);
4950
extern "C" void EmitEventDefinition(long p_index, PositionRef p_position, NameRef p_name, long p_type_index);
@@ -504,11 +505,18 @@ void EmitEventDefinition(long p_index, PositionRef p_position, NameRef p_name, l
504505

505506
void EmitBeginHandlerDefinition(long p_index, PositionRef p_position, NameRef p_name, long p_type_index)
506507
{
507-
MCScriptBeginHandlerInModule(s_builder, to_mcnameref(p_name), p_type_index, p_index);
508+
MCScriptBeginHandlerInModule(s_builder, kMCScriptHandlerScopeNormal, to_mcnameref(p_name), p_type_index, p_index);
508509

509510
MCLog("[Emit] BeginHandlerDefinition(%ld, %@, %ld)", p_index, to_mcnameref(p_name), p_type_index);
510511
}
511512

513+
void EmitBeginContextHandlerDefinition(long p_index, PositionRef p_position, NameRef p_name, long p_type_index)
514+
{
515+
MCScriptBeginHandlerInModule(s_builder, kMCScriptHandlerScopeContext, to_mcnameref(p_name), p_type_index, p_index);
516+
517+
MCLog("[Emit] BeginContextHandlerDefinition(%ld, %@, %ld)", p_index, to_mcnameref(p_name), p_type_index);
518+
}
519+
512520
void EmitEndHandlerDefinition(void)
513521
{
514522
MCScriptEndHandlerInModule(s_builder);

toolchain/lc-compile/src/generate.g

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@
192192

193193
'rule' GenerateManifestDefinitions(contextvariable(_, public, Name, _, _)):
194194

195-
'rule' GenerateManifestDefinitions(handler(_, public, Name, Signature, _, _)):
195+
'rule' GenerateManifestDefinitions(handler(_, public, Name, _, Signature, _, _)):
196196
GenerateManifestHandlerDefinition(Name, Signature)
197197

198198
'rule' GenerateManifestDefinitions(foreignhandler(_, public, Name, Signature, _)):
@@ -487,7 +487,7 @@
487487
'rule' GenerateDefinitionIndexes(contextvariable(_, _, Name, _, _)):
488488
GenerateDefinitionIndex(Name)
489489

490-
'rule' GenerateDefinitionIndexes(handler(_, _, Name, _, _, _)):
490+
'rule' GenerateDefinitionIndexes(handler(_, _, Name, _, _, _, _)):
491491
GenerateDefinitionIndex(Name)
492492

493493
'rule' GenerateDefinitionIndexes(foreignhandler(_, _, Name, _, _)):
@@ -570,7 +570,7 @@
570570
'rule' GenerateExportedDefinitions(contextvariable(_, public, Id, _, _)):
571571
GenerateExportedDefinition(Id)
572572

573-
'rule' GenerateExportedDefinitions(handler(_, public, Id, _, _, _)):
573+
'rule' GenerateExportedDefinitions(handler(_, public, Id, _, _, _, _)):
574574
GenerateExportedDefinition(Id)
575575

576576
'rule' GenerateExportedDefinitions(foreignhandler(_, public, Id, _, _)):
@@ -634,21 +634,26 @@
634634

635635
'rule' GenerateDefinitions(contextvariable(Position, _, Id, Type, Default)):
636636
GenerateType(Type -> TypeIndex)
637-
--EmitConstant(Default -> ConstIndex)
638-
where(0 -> ConstIndex)
637+
EmitConstant(Default -> ConstIndex)
639638

640639
QuerySymbolId(Id -> Info)
641640
Id'Name -> Name
642641
Info'Index -> DefIndex
643642
EmitContextVariableDefinition(DefIndex, Position, Name, TypeIndex, ConstIndex)
644643

645-
'rule' GenerateDefinitions(handler(Position, _, Id, Signature:signature(Parameters, _), _, Body)):
644+
'rule' GenerateDefinitions(handler(Position, _, Id, Scope, Signature:signature(Parameters, _), _, Body)):
646645
GenerateType(handler(Position, Signature) -> TypeIndex)
647646

648647
QuerySymbolId(Id -> Info)
649648
Id'Name -> Name
650649
Info'Index -> DefIndex
651-
EmitBeginHandlerDefinition(DefIndex, Position, Name, TypeIndex)
650+
(|
651+
where(Scope -> normal)
652+
EmitBeginHandlerDefinition(DefIndex, Position, Name, TypeIndex)
653+
||
654+
where(Scope -> context)
655+
EmitBeginContextHandlerDefinition(DefIndex, Position, Name, TypeIndex)
656+
|)
652657
GenerateParameters(Parameters)
653658
CreateParameterRegisters(Parameters)
654659
CreateVariableRegisters(Body)

toolchain/lc-compile/src/grammar.g

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@
186186
'rule' ImportDefinition(-> variable(Position, public, Id, Type)):
187187
"variable" @(-> Position) Identifier(-> Id) "as" Type(-> Type)
188188
189-
'rule' ImportDefinition(-> handler(Position, public, Id, Signature, nil, nil)):
189+
'rule' ImportDefinition(-> handler(Position, public, Id, normal, Signature, nil, nil)):
190190
"handler" @(-> Position) Identifier(-> Id) Signature(-> Signature)
191191
192192
'rule' ImportDefinition(-> foreignhandler(Position, public, Id, Signature, "")):
@@ -412,12 +412,16 @@
412412

413413
'nonterm' HandlerDefinition(-> DEFINITION)
414414

415-
'rule' HandlerDefinition(-> handler(Position, Access, Name, Signature, nil, Body)):
415+
'rule' HandlerDefinition(-> handler(Position, Access, Name, normal, Signature, nil, Body)):
416416
Access(-> Access) "handler" @(-> Position) Identifier(-> Name) Signature(-> Signature) Separator
417417
Statements(-> Body)
418418
"end" "handler"
419419

420-
--'rule' HandlerDefinition(-> handler(Position, Access, Name, Signature, nil, Body)):
420+
'rule' HandlerDefinition(-> handler(Position, Access, Name, context, Signature, nil, Body)):
421+
Access(-> Access) "context" @(-> Position) "handler" Identifier(-> Name) Signature(-> Signature) Separator
422+
Statements(-> Body)
423+
"end" "handler"
424+
--'rule' HandlerDefinition(-> handler(Position, Access, Name, Signature, nil, Body)):
421425
-- Access(-> Access) "handler" @(-> Position) Identifier(-> Name) Signature(-> Signature) Separator
422426
-- Definitions(-> Definitions)
423427
-- "begin"

0 commit comments

Comments
 (0)