22
33use core:: any:: Any ;
44
5- use cairo_lang_executable:: executable:: { EntryPointKind , Executable , ExecutableEntryPoint } ;
6-
75use crate :: {
86 hint_processor:: hint_processor_definition:: { HintProcessor , HintReference } ,
9- serde:: deserialize_program:: { Attribute , HintParams , Identifier , InstructionLocation } ,
7+ serde:: deserialize_program:: HintParams ,
108 stdlib:: {
119 collections:: { BTreeMap , HashMap , HashSet } ,
12- mem,
1310 prelude:: * ,
1411 } ,
1512 types:: {
1613 builtin_name:: BuiltinName ,
14+ errors:: program_errors:: ProgramError ,
1715 exec_scope:: ExecutionScopes ,
1816 layout:: CairoLayout ,
1917 program:: HintsCollection ,
@@ -34,6 +32,52 @@ use crate::{
3432 Felt252 ,
3533} ;
3634
35+ /// This type is originally defined in `cairo-lang-executable`.
36+ /// We redefine it here to avoid a cyclic dependencies.
37+ #[ derive( Debug ) ]
38+ pub struct ExecutableEntryPoint {
39+ pub builtins : Vec < BuiltinName > ,
40+ pub offset : usize ,
41+ pub kind : EntryPointKind ,
42+ }
43+
44+ /// This type is originally defined in `cairo-lang-executable`.
45+ /// We redefine it here to avoid a cyclic dependencies.
46+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
47+ pub enum EntryPointKind {
48+ Bootloader ,
49+ Standalone ,
50+ }
51+
52+ pub struct Program2 {
53+ pub bytecode : Vec < MaybeRelocatable > ,
54+ pub hints_collection : HintsCollection ,
55+ pub entrypoint : ExecutableEntryPoint ,
56+
57+ pub reference_manager : Vec < HintReference > ,
58+ pub constants : HashMap < String , Felt252 > ,
59+ }
60+
61+ impl Program2 {
62+ pub fn new (
63+ bytecode : Vec < MaybeRelocatable > ,
64+ hints : BTreeMap < usize , Vec < HintParams > > ,
65+ entrypoint : ExecutableEntryPoint ,
66+ reference_manager : Vec < HintReference > ,
67+ constants : HashMap < String , Felt252 > ,
68+ ) -> Result < Program2 , ProgramError > {
69+ let hints_collection = HintsCollection :: new ( & hints, bytecode. len ( ) ) ?;
70+
71+ Ok ( Self {
72+ bytecode,
73+ hints_collection,
74+ entrypoint,
75+ reference_manager,
76+ constants,
77+ } )
78+ }
79+ }
80+
3781#[ allow( dead_code) ]
3882pub struct CairoRunner2 {
3983 vm : VirtualMachine ,
@@ -43,74 +87,39 @@ pub struct CairoRunner2 {
4387 execution_scopes : ExecutionScopes ,
4488
4589 // Configuration
46- executable : Executable ,
47- entrypoint_kind : EntryPointKind ,
90+ program : Program2 ,
4891 layout : CairoLayout ,
49- trace_enabled : bool ,
50- constants : HashMap < String , Felt252 > ,
51- error_message_attributes : Vec < Attribute > ,
52- instruction_locations : Option < HashMap < usize , InstructionLocation > > ,
53- identifiers : HashMap < String , Identifier > ,
54- reference_manager : Vec < HintReference > ,
55-
56- // Preprocessed Data
57- hint_collection : HintsCollection ,
5892}
5993
6094impl CairoRunner2 {
6195 #[ allow( clippy:: too_many_arguments) ]
6296 pub fn new (
63- executable : Executable ,
64- entrypoint_kind : EntryPointKind ,
97+ program : Program2 ,
6598 layout : CairoLayout ,
6699 trace_enabled : bool ,
67- constants : HashMap < String , Felt252 > ,
68- error_message_attributes : Vec < Attribute > ,
69- instruction_locations : Option < HashMap < usize , InstructionLocation > > ,
70- identifiers : HashMap < String , Identifier > ,
71- reference_manager : Vec < HintReference > ,
72- hints : BTreeMap < usize , Vec < HintParams > > ,
73100 ) -> Result < Self , RunnerError > {
74- // =============
75- // PREPROCESSING
76- // =============
77-
78- let entrypoint = find_entrypoint_of_kind ( & executable. entrypoints , entrypoint_kind. clone ( ) ) ;
79-
80- let bytecode = executable
81- . program
82- . bytecode
83- . iter ( )
84- . map ( Felt252 :: from)
85- . map ( MaybeRelocatable :: from)
86- . collect :: < Vec < _ > > ( ) ;
87-
88- let hint_collection =
89- HintsCollection :: new ( & hints, bytecode. len ( ) ) . expect ( "failed to build hint collection" ) ;
90-
91- let builtins = get_entrypoint_builtins ( entrypoint) ;
92-
93101 // ==============
94102 // INITIALIZATION
95103 // ==============
96104
97105 let mut vm = VirtualMachine :: new ( trace_enabled, false ) ;
98106
99- check_builtin_order ( & builtins) ?;
100- vm. builtin_runners = initialize_builtin_runners ( & layout, & builtins, true , true ) ?;
107+ check_builtin_order ( & ( & program. entrypoint ) . builtins ) ?;
108+ vm. builtin_runners =
109+ initialize_builtin_runners ( & layout, & program. entrypoint . builtins , true , true ) ?;
101110
102111 let program_base = vm. add_memory_segment ( ) ;
103112 let execution_base = vm. add_memory_segment ( ) ;
104113
105114 initialize_builtin_runner_segments ( & mut vm. builtin_runners , & mut vm. segments ) ;
106115
107- load_program ( & mut vm, program_base, & bytecode) ?;
116+ load_program ( & mut vm, program_base, & program . bytecode ) ?;
108117
109118 let mut stack = Vec :: new ( ) ;
110119
111- let initial_pc = ( program_base + entrypoint. offset ) ?;
120+ let initial_pc = ( program_base + ( & program . entrypoint ) . offset ) ?;
112121
113- let ( initial_fp, final_pc) = match entrypoint_kind {
122+ let ( initial_fp, final_pc) = match ( & program . entrypoint ) . kind {
114123 EntryPointKind :: Bootloader => {
115124 // On bootloader, we execute until control flow is returned.
116125 // The stack is arranged as if we are at the start of a function call.
@@ -125,7 +134,11 @@ impl CairoRunner2 {
125134 //
126135 // The initial fp variable points to the cell after the return pc.
127136
128- extend_stack_with_builtins ( & mut stack, & builtins, & vm. builtin_runners ) ;
137+ extend_stack_with_builtins (
138+ & mut stack,
139+ & program. entrypoint . builtins ,
140+ & vm. builtin_runners ,
141+ ) ;
129142
130143 let return_fp = vm. add_memory_segment ( ) ;
131144 let return_pc = vm. add_memory_segment ( ) ;
@@ -154,7 +167,11 @@ impl CairoRunner2 {
154167
155168 let stack_prefix = & [ MaybeRelocatable :: Int ( Felt252 :: ZERO ) ] ;
156169 stack. extend_from_slice ( stack_prefix) ;
157- extend_stack_with_builtins ( & mut stack, & builtins, & vm. builtin_runners ) ;
170+ extend_stack_with_builtins (
171+ & mut stack,
172+ & program. entrypoint . builtins ,
173+ & vm. builtin_runners ,
174+ ) ;
158175
159176 let final_pc = ( initial_pc + 4 ) ?;
160177 let initial_fp = ( execution_base + stack_prefix. len ( ) ) ?;
@@ -172,21 +189,13 @@ impl CairoRunner2 {
172189 add_builtin_validation_rules ( & mut vm. segments . memory , & mut vm. builtin_runners ) ?;
173190
174191 Ok ( Self {
175- executable,
176192 vm,
177193 program_base,
178194 execution_base,
179195 final_pc,
180196 execution_scopes : ExecutionScopes :: new ( ) ,
181- entrypoint_kind ,
197+ program ,
182198 layout,
183- trace_enabled,
184- constants,
185- error_message_attributes,
186- instruction_locations,
187- identifiers,
188- reference_manager,
189- hint_collection,
190199 } )
191200 }
192201
@@ -196,20 +205,21 @@ impl CairoRunner2 {
196205 ) -> Result < ( ) , VirtualMachineError > {
197206 #[ cfg_attr( not( feature = "extensive_hints" ) , allow( unused_mut) ) ]
198207 let mut hint_data = get_hint_data (
199- & self . hint_collection ,
200- & self . reference_manager ,
208+ & self . program . hints_collection ,
209+ & self . program . reference_manager ,
201210 hint_processor,
202211 ) ?;
203212
204213 #[ cfg( feature = "extensive_hints" ) ]
205- let mut hint_ranges = self . hint_collection . hints_ranges . clone ( ) ;
214+ let mut hint_ranges = self . program . hints_collection . hints_ranges . clone ( ) ;
206215
207216 while self . vm . get_pc ( ) != self . final_pc && !hint_processor. consumed ( ) {
208217 #[ cfg( feature = "extensive_hints" ) ]
209218 let hint_data = & mut hint_data;
210219 #[ cfg( not( feature = "extensive_hints" ) ) ]
211220 let hint_data = self
212- . hint_collection
221+ . program
222+ . hints_collection
213223 . get_hint_range_for_pc ( self . vm . get_pc ( ) . offset )
214224 . and_then ( |range| {
215225 range. and_then ( |( start, length) | hint_data. get ( start..start + length. get ( ) ) )
@@ -222,7 +232,7 @@ impl CairoRunner2 {
222232 hint_data,
223233 #[ cfg( feature = "extensive_hints" ) ]
224234 & mut hint_ranges,
225- & self . constants ,
235+ & self . program . constants ,
226236 ) ?;
227237
228238 hint_processor. consume_step ( ) ;
@@ -236,19 +246,6 @@ impl CairoRunner2 {
236246 }
237247}
238248
239- fn find_entrypoint_of_kind (
240- entrypoints : & [ ExecutableEntryPoint ] ,
241- entrypoint_kind : EntryPointKind ,
242- ) -> & ExecutableEntryPoint {
243- entrypoints
244- . iter ( )
245- . find ( |entrypoint| {
246- // TODO: Use `Eq` once implemented on `EntryPointKind`.
247- mem:: discriminant ( & entrypoint. kind ) == mem:: discriminant ( & entrypoint_kind)
248- } )
249- . expect ( "executable had no entrypoint of required kind" )
250- }
251-
252249pub fn check_builtin_order ( builtins : & [ BuiltinName ] ) -> Result < ( ) , RunnerError > {
253250 let ordered_builtins = vec ! [
254251 BuiltinName :: output,
@@ -465,18 +462,3 @@ fn get_hint_data(
465462 } )
466463 . collect ( )
467464}
468-
469- /// TODO: Remove this once cyclic dependency is fixed.
470- /// It should not be necessary, but cargo treats executable BuiltinName as a separate type
471- /// which is why I had to create this adapter function.
472- pub fn get_entrypoint_builtins ( entrypoint : & ExecutableEntryPoint ) -> Vec < BuiltinName > {
473- let mut builtins = Vec :: with_capacity ( entrypoint. builtins . len ( ) ) ;
474-
475- for builtin in & entrypoint. builtins {
476- let adapted_builtin = BuiltinName :: from_str ( builtin. to_str ( ) )
477- . expect ( "should never fail under the same implementation" ) ;
478- builtins. push ( adapted_builtin) ;
479- }
480-
481- builtins
482- }
0 commit comments