|
6 | 6 |
|
7 | 7 | use crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor; |
8 | 8 | use crate::hint_processor::hint_processor_definition::HintProcessor; |
| 9 | +use crate::serde::deserialize_program::Identifier; |
9 | 10 | use crate::types::builtin_name::BuiltinName; |
10 | 11 | use crate::types::errors::program_errors::ProgramError; |
11 | 12 | use crate::types::instance_definitions::mod_instance_def::ModInstanceDef; |
@@ -260,17 +261,73 @@ impl CairoFunctionRunner { |
260 | 261 | .map(|builtin_runner| MaybeRelocatable::from((builtin_runner.base() as isize, 0))) |
261 | 262 | } |
262 | 263 |
|
263 | | - /// Gets the program counter (PC) for a function entrypoint. |
| 264 | + /// Returns the program counter (PC) for a function entrypoint by name. |
| 265 | + /// |
| 266 | + /// Looks up the identifier `__main__.{entrypoint}` in the program, then resolves it to a PC |
| 267 | + /// (following alias chains if needed) via [`get_pc_from_identifier`](Self::get_pc_from_identifier). |
| 268 | + /// |
| 269 | + /// # Errors |
| 270 | + /// - [`ProgramError::EntrypointNotFound`] if no identifier exists for the given name. |
| 271 | + /// - [`RunnerError::NoPC`] if the resolved identifier has no PC (e.g. corrupt alias). |
| 272 | + /// - [`ProgramError::AliasMissingDestination`] if an alias has no `destination`. |
| 273 | + /// - [`ProgramError::InvalidIdentifierTypeForPc`] if the identifier type is not `"function"` or `"alias"`. |
264 | 274 | #[allow(clippy::result_large_err)] |
265 | | - fn get_function_pc(&self, entrypoint: &str) -> std::result::Result<usize, CairoRunError> { |
| 275 | + pub(crate) fn get_function_pc( |
| 276 | + &self, |
| 277 | + entrypoint: &str, |
| 278 | + ) -> std::result::Result<usize, CairoRunError> { |
266 | 279 | let full_name = format!("__main__.{entrypoint}"); |
267 | 280 | let identifier = self |
268 | 281 | .program |
269 | 282 | .get_identifier(&full_name) |
270 | 283 | .ok_or_else(|| ProgramError::EntrypointNotFound(entrypoint.to_string()))?; |
271 | 284 |
|
272 | | - let pc = identifier.pc.ok_or(RunnerError::NoPC)?; |
| 285 | + self.get_pc_from_identifier(identifier) |
| 286 | + } |
273 | 287 |
|
274 | | - Ok(pc) |
| 288 | + /// Resolves an identifier to its program counter (PC), following alias chains. |
| 289 | + /// |
| 290 | + /// - **`function`**: returns the identifier's `pc` if present. |
| 291 | + /// - **`alias`**: resolves `destination` to another identifier and recurses until a function is found. |
| 292 | + /// - **Other types** (e.g. `struct`, `const`): returns [`ProgramError::InvalidIdentifierTypeForPc`]. |
| 293 | + /// |
| 294 | + /// # Errors |
| 295 | + /// - [`RunnerError::NoPC`] when the identifier is a function but has no `pc`. |
| 296 | + /// - [`ProgramError::AliasMissingDestination`] when the identifier is an alias but has no `destination`. |
| 297 | + /// - [`ProgramError::EntrypointNotFound`] when the alias destination is not in the program. |
| 298 | + /// - [`ProgramError::InvalidIdentifierTypeForPc`] when the identifier type is not `"function"` or `"alias"`. |
| 299 | + #[allow(clippy::result_large_err)] |
| 300 | + fn get_pc_from_identifier( |
| 301 | + &self, |
| 302 | + idetifier: &Identifier, |
| 303 | + ) -> std::result::Result<usize, CairoRunError> { |
| 304 | + match idetifier.type_.as_deref() { |
| 305 | + Some("function") => { |
| 306 | + let pc = idetifier.pc.ok_or(RunnerError::NoPC)?; |
| 307 | + Ok(pc) |
| 308 | + } |
| 309 | + Some("alias") => { |
| 310 | + let destination = idetifier.destination.as_deref().ok_or( |
| 311 | + ProgramError::AliasMissingDestination( |
| 312 | + idetifier.full_name.as_deref().unwrap_or("").to_string(), |
| 313 | + ), |
| 314 | + )?; |
| 315 | + |
| 316 | + let destination_identifier = self |
| 317 | + .runner |
| 318 | + .program |
| 319 | + .get_identifier(destination) |
| 320 | + .ok_or_else(|| ProgramError::EntrypointNotFound(destination.to_string()))?; |
| 321 | + self.get_pc_from_identifier(destination_identifier) |
| 322 | + } |
| 323 | + v => { |
| 324 | + let name = idetifier |
| 325 | + .full_name |
| 326 | + .clone() |
| 327 | + .unwrap_or_else(|| "<unknown>".to_string()); |
| 328 | + let type_str = v.unwrap_or("<unknown>").to_string(); |
| 329 | + Err(ProgramError::InvalidIdentifierTypeForPc(name, type_str).into()) |
| 330 | + } |
| 331 | + } |
275 | 332 | } |
276 | 333 | } |
0 commit comments