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,35 @@ 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-
93- // ==============
94- // INITIALIZATION
95- // ==============
96-
97101 let mut vm = VirtualMachine :: new ( trace_enabled, false ) ;
98102
99- check_builtin_order ( & builtins) ?;
100- vm. builtin_runners = initialize_builtin_runners ( & layout, & builtins, true , true ) ?;
103+ check_builtin_order ( & ( & program. entrypoint ) . builtins ) ?;
104+ vm. builtin_runners =
105+ initialize_builtin_runners ( & layout, & program. entrypoint . builtins , true , true ) ?;
101106
102107 let program_base = vm. add_memory_segment ( ) ;
103108 let execution_base = vm. add_memory_segment ( ) ;
104109
105110 initialize_builtin_runner_segments ( & mut vm. builtin_runners , & mut vm. segments ) ;
106111
107- load_program ( & mut vm, program_base, & bytecode) ?;
112+ load_program ( & mut vm, program_base, & program . bytecode ) ?;
108113
109114 let mut stack = Vec :: new ( ) ;
110115
111- let initial_pc = ( program_base + entrypoint. offset ) ?;
116+ let initial_pc = ( program_base + program . entrypoint . offset ) ?;
112117
113- let ( initial_fp, final_pc) = match entrypoint_kind {
118+ let ( initial_fp, final_pc) = match program . entrypoint . kind {
114119 EntryPointKind :: Bootloader => {
115120 // On bootloader, we execute until control flow is returned.
116121 // The stack is arranged as if we are at the start of a function call.
@@ -125,7 +130,11 @@ impl CairoRunner2 {
125130 //
126131 // The initial fp variable points to the cell after the return pc.
127132
128- extend_stack_with_builtins ( & mut stack, & builtins, & vm. builtin_runners ) ;
133+ extend_stack_with_builtins (
134+ & mut stack,
135+ & program. entrypoint . builtins ,
136+ & vm. builtin_runners ,
137+ ) ;
129138
130139 let return_fp = vm. add_memory_segment ( ) ;
131140 let return_pc = vm. add_memory_segment ( ) ;
@@ -154,7 +163,11 @@ impl CairoRunner2 {
154163
155164 let stack_prefix = & [ MaybeRelocatable :: Int ( Felt252 :: ZERO ) ] ;
156165 stack. extend_from_slice ( stack_prefix) ;
157- extend_stack_with_builtins ( & mut stack, & builtins, & vm. builtin_runners ) ;
166+ extend_stack_with_builtins (
167+ & mut stack,
168+ & program. entrypoint . builtins ,
169+ & vm. builtin_runners ,
170+ ) ;
158171
159172 let final_pc = ( initial_pc + 4 ) ?;
160173 let initial_fp = ( execution_base + stack_prefix. len ( ) ) ?;
@@ -167,26 +180,18 @@ impl CairoRunner2 {
167180 let run_context = RunContext :: new ( initial_pc, initial_ap. offset , initial_fp. offset ) ;
168181 vm. set_run_context ( run_context) ;
169182
170- load_stack ( & mut vm, execution_base, stack) ?;
183+ load_stack ( & mut vm, execution_base, & stack) ?;
171184
172185 add_builtin_validation_rules ( & mut vm. segments . memory , & mut vm. builtin_runners ) ?;
173186
174187 Ok ( Self {
175- executable,
176188 vm,
177189 program_base,
178190 execution_base,
179191 final_pc,
180192 execution_scopes : ExecutionScopes :: new ( ) ,
181- entrypoint_kind ,
193+ program ,
182194 layout,
183- trace_enabled,
184- constants,
185- error_message_attributes,
186- instruction_locations,
187- identifiers,
188- reference_manager,
189- hint_collection,
190195 } )
191196 }
192197
@@ -196,20 +201,21 @@ impl CairoRunner2 {
196201 ) -> Result < ( ) , VirtualMachineError > {
197202 #[ cfg_attr( not( feature = "extensive_hints" ) , allow( unused_mut) ) ]
198203 let mut hint_data = get_hint_data (
199- & self . hint_collection ,
200- & self . reference_manager ,
204+ & self . program . hints_collection ,
205+ & self . program . reference_manager ,
201206 hint_processor,
202207 ) ?;
203208
204209 #[ cfg( feature = "extensive_hints" ) ]
205- let mut hint_ranges = self . hint_collection . hints_ranges . clone ( ) ;
210+ let mut hint_ranges = self . program . hints_collection . hints_ranges . clone ( ) ;
206211
207212 while self . vm . get_pc ( ) != self . final_pc && !hint_processor. consumed ( ) {
208213 #[ cfg( feature = "extensive_hints" ) ]
209214 let hint_data = & mut hint_data;
210215 #[ cfg( not( feature = "extensive_hints" ) ) ]
211216 let hint_data = self
212- . hint_collection
217+ . program
218+ . hints_collection
213219 . get_hint_range_for_pc ( self . vm . get_pc ( ) . offset )
214220 . and_then ( |range| {
215221 range. and_then ( |( start, length) | hint_data. get ( start..start + length. get ( ) ) )
@@ -222,7 +228,7 @@ impl CairoRunner2 {
222228 hint_data,
223229 #[ cfg( feature = "extensive_hints" ) ]
224230 & mut hint_ranges,
225- & self . constants ,
231+ & self . program . constants ,
226232 ) ?;
227233
228234 hint_processor. consume_step ( ) ;
@@ -236,19 +242,6 @@ impl CairoRunner2 {
236242 }
237243}
238244
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-
252245pub fn check_builtin_order ( builtins : & [ BuiltinName ] ) -> Result < ( ) , RunnerError > {
253246 let ordered_builtins = vec ! [
254247 BuiltinName :: output,
@@ -413,7 +406,7 @@ fn extend_stack_with_builtins(
413406fn load_program (
414407 vm : & mut VirtualMachine ,
415408 program_base : Relocatable ,
416- bytecode : & Vec < MaybeRelocatable > ,
409+ bytecode : & [ MaybeRelocatable ] ,
417410) -> Result < ( ) , RunnerError > {
418411 vm. load_data ( program_base, bytecode)
419412 . map_err ( RunnerError :: MemoryInitializationError ) ?;
@@ -426,7 +419,7 @@ fn load_program(
426419fn load_stack (
427420 vm : & mut VirtualMachine ,
428421 execution_base : Relocatable ,
429- stack : Vec < MaybeRelocatable > ,
422+ stack : & [ MaybeRelocatable ] ,
430423) -> Result < ( ) , RunnerError > {
431424 vm. load_data ( execution_base, & stack)
432425 . map_err ( RunnerError :: MemoryInitializationError ) ?;
@@ -465,18 +458,3 @@ fn get_hint_data(
465458 } )
466459 . collect ( )
467460}
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