|
8 | 8 | use num_bigint::BigInt;
|
9 | 9 | use num_complex::Complex64;
|
10 | 10 | use rustpython_parser::ast;
|
11 |
| -use std::collections::HashMap; |
| 11 | +use std::collections::{HashMap, HashSet}; |
12 | 12 | use std::fmt;
|
13 | 13 |
|
14 | 14 | /// Primary container of a single code object. Each python function has
|
@@ -173,6 +173,8 @@ pub enum Instruction {
|
173 | 173 | },
|
174 | 174 | }
|
175 | 175 |
|
| 176 | +use self::Instruction::*; |
| 177 | + |
176 | 178 | #[derive(Debug, Clone, PartialEq)]
|
177 | 179 | pub enum CallType {
|
178 | 180 | Positional(usize),
|
@@ -277,17 +279,123 @@ impl CodeObject {
|
277 | 279 | }
|
278 | 280 | }
|
279 | 281 |
|
| 282 | +impl fmt::Display for CodeObject { |
| 283 | + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| 284 | + let label_targets: HashSet<&usize> = self.label_map.values().collect(); |
| 285 | + for (offset, instruction) in self.instructions.iter().enumerate() { |
| 286 | + let arrow = if label_targets.contains(&offset) { |
| 287 | + ">>" |
| 288 | + } else { |
| 289 | + " " |
| 290 | + }; |
| 291 | + write!(f, " {} {:5} ", arrow, offset)?; |
| 292 | + instruction.fmt_dis(f, &self.label_map)?; |
| 293 | + } |
| 294 | + Ok(()) |
| 295 | + } |
| 296 | +} |
| 297 | + |
| 298 | +impl Instruction { |
| 299 | + fn fmt_dis(&self, f: &mut fmt::Formatter, label_map: &HashMap<Label, usize>) -> fmt::Result { |
| 300 | + macro_rules! w { |
| 301 | + ($variant:ident) => { |
| 302 | + write!(f, "{:20}\n", stringify!($variant)) |
| 303 | + }; |
| 304 | + ($variant:ident, $var:expr) => { |
| 305 | + write!(f, "{:20} ({})\n", stringify!($variant), $var) |
| 306 | + }; |
| 307 | + ($variant:ident, $var1:expr, $var2:expr) => { |
| 308 | + write!(f, "{:20} ({}, {})\n", stringify!($variant), $var1, $var2) |
| 309 | + }; |
| 310 | + } |
| 311 | + |
| 312 | + match self { |
| 313 | + Import { name, symbol } => w!(Import, name, format!("{:?}", symbol)), |
| 314 | + ImportStar { name } => w!(ImportStar, name), |
| 315 | + LoadName { name } => w!(LoadName, name), |
| 316 | + StoreName { name } => w!(StoreName, name), |
| 317 | + DeleteName { name } => w!(DeleteName, name), |
| 318 | + StoreSubscript => w!(StoreSubscript), |
| 319 | + DeleteSubscript => w!(DeleteSubscript), |
| 320 | + StoreAttr { name } => w!(StoreAttr, name), |
| 321 | + DeleteAttr { name } => w!(DeleteAttr, name), |
| 322 | + LoadConst { value } => w!(LoadConst, value), |
| 323 | + UnaryOperation { op } => w!(UnaryOperation, format!("{:?}", op)), |
| 324 | + BinaryOperation { op, inplace } => w!(BinaryOperation, format!("{:?}", op), inplace), |
| 325 | + LoadAttr { name } => w!(LoadAttr, name), |
| 326 | + CompareOperation { op } => w!(CompareOperation, format!("{:?}", op)), |
| 327 | + Pop => w!(Pop), |
| 328 | + Rotate { amount } => w!(Rotate, amount), |
| 329 | + Duplicate => w!(Duplicate), |
| 330 | + GetIter => w!(GetIter), |
| 331 | + Pass => w!(Pass), |
| 332 | + Continue => w!(Continue), |
| 333 | + Break => w!(Break), |
| 334 | + Jump { target } => w!(Jump, label_map[target]), |
| 335 | + JumpIf { target } => w!(JumpIf, label_map[target]), |
| 336 | + JumpIfFalse { target } => w!(JumpIfFalse, label_map[target]), |
| 337 | + MakeFunction { flags } => w!(MakeFunction, format!("{:?}", flags)), |
| 338 | + CallFunction { typ } => w!(CallFunction, format!("{:?}", typ)), |
| 339 | + ForIter { target } => w!(ForIter, label_map[target]), |
| 340 | + ReturnValue => w!(ReturnValue), |
| 341 | + YieldValue => w!(YieldValue), |
| 342 | + YieldFrom => w!(YieldFrom), |
| 343 | + SetupLoop { start, end } => w!(SetupLoop, label_map[start], label_map[end]), |
| 344 | + SetupExcept { handler } => w!(SetupExcept, handler), |
| 345 | + SetupWith { end } => w!(SetupWith, end), |
| 346 | + CleanupWith { end } => w!(CleanupWith, end), |
| 347 | + PopBlock => w!(PopBlock), |
| 348 | + Raise { argc } => w!(Raise, argc), |
| 349 | + BuildString { size } => w!(BuildString, size), |
| 350 | + BuildTuple { size, unpack } => w!(BuildTuple, size, unpack), |
| 351 | + BuildList { size, unpack } => w!(BuildList, size, unpack), |
| 352 | + BuildSet { size, unpack } => w!(BuildSet, size, unpack), |
| 353 | + BuildMap { size, unpack } => w!(BuildMap, size, unpack), |
| 354 | + BuildSlice { size } => w!(BuildSlice, size), |
| 355 | + ListAppend { i } => w!(ListAppend, i), |
| 356 | + SetAdd { i } => w!(SetAdd, i), |
| 357 | + MapAdd { i } => w!(MapAdd, i), |
| 358 | + PrintExpr => w!(PrintExpr), |
| 359 | + LoadBuildClass => w!(LoadBuildClass), |
| 360 | + StoreLocals => w!(StoreLocals), |
| 361 | + UnpackSequence { size } => w!(UnpackSequence, size), |
| 362 | + UnpackEx { before, after } => w!(UnpackEx, before, after), |
| 363 | + Unpack => w!(Unpack), |
| 364 | + FormatValue { spec } => w!(FormatValue, spec), |
| 365 | + } |
| 366 | + } |
| 367 | +} |
| 368 | + |
| 369 | +impl fmt::Display for Constant { |
| 370 | + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| 371 | + match self { |
| 372 | + Constant::Integer { value } => write!(f, "{}", value), |
| 373 | + Constant::Float { value } => write!(f, "{}", value), |
| 374 | + Constant::Complex { value } => write!(f, "{}", value), |
| 375 | + Constant::Boolean { value } => write!(f, "{}", value), |
| 376 | + Constant::String { value } => write!(f, "{:?}", value), |
| 377 | + Constant::Bytes { value } => write!(f, "{:?}", value), |
| 378 | + Constant::Code { code } => write!(f, "{:?}", code), |
| 379 | + Constant::Tuple { elements } => write!( |
| 380 | + f, |
| 381 | + "({})", |
| 382 | + elements |
| 383 | + .iter() |
| 384 | + .map(|e| format!("{}", e)) |
| 385 | + .collect::<Vec<_>>() |
| 386 | + .join(", ") |
| 387 | + ), |
| 388 | + Constant::None => write!(f, "None"), |
| 389 | + } |
| 390 | + } |
| 391 | +} |
| 392 | + |
280 | 393 | impl fmt::Debug for CodeObject {
|
281 | 394 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
282 |
| - let inst_str = self |
283 |
| - .instructions |
284 |
| - .iter() |
285 |
| - .zip(self.locations.iter()) |
286 |
| - .enumerate() |
287 |
| - .map(|(i, inst)| format!("Inst {}: {:?}", i, inst)) |
288 |
| - .collect::<Vec<_>>() |
289 |
| - .join("\n"); |
290 |
| - let labelmap_str = format!("label_map: {:?}", self.label_map); |
291 |
| - write!(f, "Code Object {{ \n{}\n{} }}", inst_str, labelmap_str) |
| 395 | + write!( |
| 396 | + f, |
| 397 | + "<code object {} at ??? file {:?}, line {}>", |
| 398 | + self.obj_name, self.source_path, self.first_line_number |
| 399 | + ) |
292 | 400 | }
|
293 | 401 | }
|
0 commit comments