MCPcopy Index your code
hub / github.com/RustPython/RustPython / extract_annotations_from_annotate_code

Function extract_annotations_from_annotate_code

crates/jit/tests/common.rs:80–172  ·  view source on GitHub ↗

Extract annotations from an annotate function's bytecode. The annotate function uses BUILD_MAP with key-value pairs loaded before it. Keys are parameter names (from LOAD_CONST), values are type names (from LOAD_NAME/LOAD_GLOBAL).

(code: &CodeObject)

Source from the content-addressed store, hash-verified

78/// The annotate function uses BUILD_MAP with key-value pairs loaded before it.
79/// Keys are parameter names (from LOAD_CONST), values are type names (from LOAD_NAME/LOAD_GLOBAL).
80fn extract_annotations_from_annotate_code(code: &CodeObject) -> HashMap<Wtf8Buf, StackValue> {
81 let mut annotations = HashMap::new();
82 let mut stack: Vec<(bool, usize)> = Vec::new(); // (is_const, index)
83 let mut op_arg_state = OpArgState::default();
84
85 for &word in code.instructions.iter() {
86 let (instruction, arg) = op_arg_state.get(word);
87
88 match instruction {
89 Instruction::LoadConst { consti } => {
90 stack.push((true, consti.get(arg).as_usize()));
91 }
92 Instruction::LoadName { namei } => {
93 stack.push((false, namei.get(arg) as usize));
94 }
95 Instruction::LoadGlobal { namei } => {
96 stack.push((false, (namei.get(arg) >> 1) as usize));
97 }
98 Instruction::BuildMap { count } => {
99 let count = count.get(arg) as usize;
100 // Stack has key-value pairs in order: k1, v1, k2, v2, ...
101 // So we need count * 2 items from the stack
102 let start = stack.len().saturating_sub(count * 2);
103 let pairs: Vec<_> = stack.drain(start..).collect();
104
105 for chunk in pairs.chunks(2) {
106 if chunk.len() == 2 {
107 let (key_is_const, key_idx) = chunk[0];
108 let (val_is_const, val_idx) = chunk[1];
109
110 // Key should be a const string (parameter name)
111 if key_is_const
112 && let ConstantData::Str { value } =
113 &code.constants[(key_idx as u32).into()]
114 {
115 let param_name = value;
116 // Value can be a name (type ref) or a const string (forward ref)
117 let type_name = if val_is_const {
118 match code.constants.get(val_idx) {
119 Some(ConstantData::Str { value }) => value
120 .as_str()
121 .map(|s| s.to_owned())
122 .unwrap_or_else(|_| value.to_string_lossy().into_owned()),
123 Some(other) => panic!(
124 "Unsupported annotation const for '{:?}' at idx {}: {:?}",
125 param_name, val_idx, other
126 ),
127 None => panic!(
128 "Annotation const idx out of bounds for '{:?}': {} (len={})",
129 param_name,
130 val_idx,
131 code.constants.len()
132 ),
133 }
134 } else {
135 match code.names.get(val_idx) {
136 Some(name) => name.clone(),
137 None => panic!(

Callers 1

process_instructionMethod · 0.85

Calls 15

newFunction · 0.85
collectMethod · 0.80
into_ownedMethod · 0.80
StringClass · 0.50
iterMethod · 0.45
getMethod · 0.45
pushMethod · 0.45
lenMethod · 0.45
drainMethod · 0.45
chunksMethod · 0.45
mapMethod · 0.45
as_strMethod · 0.45

Tested by

no test coverage detected