11use cairo_lang_casm:: builder:: CasmBuilder ;
22use cairo_lang_casm:: cell_expression:: CellExpression ;
3+ use cairo_lang_casm:: instructions:: Instruction ;
34use cairo_lang_casm:: operand:: CellRef ;
45use cairo_lang_casm:: { casm, casm_build_extend, casm_extend} ;
56use cairo_lang_sierra:: extensions:: ConcreteLibfunc ;
@@ -230,8 +231,20 @@ fn build_enum_match_short(
230231 Item = impl ExactSizeIterator < Item = ReferenceExpression > ,
231232 > ,
232233) -> Result < CompiledInvocation , InvocationError > {
233- let mut instructions = Vec :: new ( ) ;
234+ build_enum_match_short_ex ( builder, variant_selector, output_expressions, Vec :: with_capacity ( 1 ) )
235+ }
236+
237+ /// Extended version of `build_enum_match_short` that allows prepending instructions.
238+ fn build_enum_match_short_ex (
239+ builder : CompiledInvocationBuilder < ' _ > ,
240+ variant_selector : CellRef ,
241+ output_expressions : impl ExactSizeIterator <
242+ Item = impl ExactSizeIterator < Item = ReferenceExpression > ,
243+ > ,
244+ mut instructions : Vec < Instruction > ,
245+ ) -> Result < CompiledInvocation , InvocationError > {
234246 let mut relocations = Vec :: new ( ) ;
247+ let base_instruction_count = instructions. len ( ) ;
235248
236249 // First branch is fallthrough. If there is only one branch, this `match` statement is
237250 // translated to nothing in Casm.
@@ -245,7 +258,7 @@ fn build_enum_match_short(
245258
246259 instructions. extend ( casm ! { jmp rel 0 if variant_selector != 0 ; } . instructions ) ;
247260 relocations. push ( RelocationEntry {
248- instruction_idx : 0 ,
261+ instruction_idx : base_instruction_count ,
249262 relocation : Relocation :: RelativeStatementId ( statement_id) ,
250263 } ) ;
251264 }
@@ -284,12 +297,32 @@ fn build_enum_match_long(
284297 output_expressions : impl ExactSizeIterator <
285298 Item = impl ExactSizeIterator < Item = ReferenceExpression > ,
286299 > ,
300+ ) -> Result < CompiledInvocation , InvocationError > {
301+ let expected_instruction_count = builder. invocation . branches . len ( ) + 1 ;
302+ build_enum_match_long_ex (
303+ builder,
304+ variant_selector,
305+ output_expressions,
306+ Vec :: with_capacity ( expected_instruction_count) ,
307+ )
308+ }
309+
310+ /// Extended version of `build_enum_match_long` that allows prepending instructions.
311+ fn build_enum_match_long_ex (
312+ builder : CompiledInvocationBuilder < ' _ > ,
313+ variant_selector : CellRef ,
314+ output_expressions : impl ExactSizeIterator <
315+ Item = impl ExactSizeIterator < Item = ReferenceExpression > ,
316+ > ,
317+ mut instructions : Vec < Instruction > ,
287318) -> Result < CompiledInvocation , InvocationError > {
288319 let target_statement_ids = builder. invocation . branches [ 1 ..] . iter ( ) . map ( |b| match b {
289320 BranchInfo { target : BranchTarget :: Statement ( stmnt_id) , .. } => * stmnt_id,
290321 _ => panic ! ( "malformed invocation" ) ,
291322 } ) ;
292323
324+ let base_instruction_count = instructions. len ( ) ;
325+
293326 // The first instruction is the jmp to the relevant index in the jmp table.
294327 let mut ctx = casm ! { jmp rel variant_selector; } ;
295328 let mut relocations = Vec :: new ( ) ;
@@ -300,12 +333,13 @@ fn build_enum_match_long(
300333 // Add the jump instruction to the relevant target.
301334 casm_extend ! ( ctx, jmp rel 0 ; ) ;
302335 relocations. push ( RelocationEntry {
303- instruction_idx : i + 1 ,
336+ instruction_idx : base_instruction_count + i + 1 ,
304337 relocation : Relocation :: RelativeStatementId ( stmnt_id) ,
305338 } ) ;
306339 }
307340
308- Ok ( builder. build ( ctx. instructions , relocations, output_expressions) )
341+ instructions. extend ( ctx. instructions ) ;
342+ Ok ( builder. build ( instructions, relocations, output_expressions) )
309343}
310344
311345/// A struct representing an actual enum value in the Sierra program.
0 commit comments