Skip to content

Commit c33b8c9

Browse files
committed
metadata work
1 parent 8f79b4e commit c33b8c9

File tree

2 files changed

+93
-84
lines changed

2 files changed

+93
-84
lines changed

compiler/codegen/src/compile.rs

Lines changed: 58 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -303,23 +303,26 @@ impl<'src> Compiler<'src> {
303303
fn new(opts: CompileOpts, source_code: SourceCode<'src>, code_name: String) -> Self {
304304
let module_code = ir::CodeInfo {
305305
flags: bytecode::CodeFlags::NEW_LOCALS,
306-
posonlyarg_count: 0,
307-
arg_count: 0,
308-
kwonlyarg_count: 0,
309306
source_path: source_code.path.to_owned(),
310-
first_line_number: OneIndexed::MIN,
311-
obj_name: code_name.clone(),
312-
qualname: Some(code_name),
313307
private: None,
314308
blocks: vec![ir::Block::default()],
315309
current_block: ir::BlockIdx(0),
316-
constants: IndexSet::default(),
317-
name_cache: IndexSet::default(),
318-
varname_cache: IndexSet::default(),
319-
cellvar_cache: IndexSet::default(),
320-
freevar_cache: IndexSet::default(),
321-
fasthidden_cache: IndexMap::default(),
310+
metadata: ir::CodeUnitMetadata {
311+
name: code_name.clone(),
312+
qualname: Some(code_name),
313+
consts: IndexSet::default(),
314+
names: IndexSet::default(),
315+
varnames: IndexSet::default(),
316+
cellvars: IndexSet::default(),
317+
freevars: IndexSet::default(),
318+
fasthidden: IndexMap::default(),
319+
argcount: 0,
320+
posonlyargcount: 0,
321+
kwonlyargcount: 0,
322+
firstlineno: OneIndexed::MIN,
323+
},
322324
static_attributes: None,
325+
in_inlined_comp: false,
323326
};
324327
Compiler {
325328
code_stack: vec![module_code],
@@ -415,28 +418,30 @@ impl Compiler<'_> {
415418

416419
let info = ir::CodeInfo {
417420
flags,
418-
posonlyarg_count,
419-
arg_count,
420-
kwonlyarg_count,
421421
source_path,
422-
first_line_number,
423-
obj_name,
424-
qualname,
425422
private,
426-
427423
blocks: vec![ir::Block::default()],
428424
current_block: ir::BlockIdx(0),
429-
constants: IndexSet::default(),
430-
name_cache: IndexSet::default(),
431-
varname_cache,
432-
cellvar_cache,
433-
freevar_cache,
434-
fasthidden_cache: IndexMap::default(),
425+
metadata: ir::CodeUnitMetadata {
426+
name: obj_name,
427+
qualname,
428+
consts: IndexSet::default(),
429+
names: IndexSet::default(),
430+
varnames: varname_cache,
431+
cellvars: cellvar_cache,
432+
freevars: freevar_cache,
433+
fasthidden: IndexMap::default(),
434+
argcount: arg_count,
435+
posonlyargcount: posonlyarg_count,
436+
kwonlyargcount: kwonlyarg_count,
437+
firstlineno: first_line_number,
438+
},
435439
static_attributes: if is_class_scope {
436440
Some(IndexSet::default())
437441
} else {
438442
None
439443
},
444+
in_inlined_comp: false,
440445
};
441446
self.code_stack.push(info);
442447
}
@@ -452,15 +457,15 @@ impl Compiler<'_> {
452457
// could take impl Into<Cow<str>>, but everything is borrowed from ast structs; we never
453458
// actually have a `String` to pass
454459
fn name(&mut self, name: &str) -> bytecode::NameIdx {
455-
self._name_inner(name, |i| &mut i.name_cache)
460+
self._name_inner(name, |i| &mut i.metadata.names)
456461
}
457462
fn varname(&mut self, name: &str) -> CompileResult<bytecode::NameIdx> {
458463
if Compiler::is_forbidden_arg_name(name) {
459464
return Err(self.error(CodegenErrorType::SyntaxError(format!(
460465
"cannot assign to {name}",
461466
))));
462467
}
463-
Ok(self._name_inner(name, |i| &mut i.varname_cache))
468+
Ok(self._name_inner(name, |i| &mut i.metadata.varnames))
464469
}
465470
fn _name_inner(
466471
&mut self,
@@ -478,14 +483,14 @@ impl Compiler<'_> {
478483
/// Set the qualified name for the current code object, based on CPython's compiler_set_qualname
479484
fn set_qualname(&mut self) -> String {
480485
let qualname = self.make_qualname();
481-
self.current_code_info().qualname = Some(qualname.clone());
486+
self.current_code_info().metadata.qualname = Some(qualname.clone());
482487
qualname
483488
}
484489
fn make_qualname(&mut self) -> String {
485490
let stack_size = self.code_stack.len();
486491
assert!(stack_size >= 1);
487492

488-
let current_obj_name = self.current_code_info().obj_name.clone();
493+
let current_obj_name = self.current_code_info().metadata.name.clone();
489494

490495
// If we're at the module level (stack_size == 1), qualname is just the name
491496
if stack_size <= 1 {
@@ -497,7 +502,7 @@ impl Compiler<'_> {
497502
let mut parent = &self.code_stack[parent_idx];
498503

499504
// If parent is a type parameter scope, look at grandparent
500-
if parent.obj_name.starts_with("<generic parameters of ") {
505+
if parent.metadata.name.starts_with("<generic parameters of ") {
501506
if stack_size == 2 {
502507
// If we're immediately within the module after type params,
503508
// qualname is just the name
@@ -540,7 +545,7 @@ impl Compiler<'_> {
540545
current_obj_name
541546
} else {
542547
// Check parent scope type
543-
let parent_obj_name = &parent.obj_name;
548+
let parent_obj_name = &parent.metadata.name;
544549

545550
// Determine if parent is a function-like scope
546551
let is_function_parent = parent.flags.contains(bytecode::CodeFlags::IS_OPTIMIZED)
@@ -550,12 +555,12 @@ impl Compiler<'_> {
550555
if is_function_parent {
551556
// For functions, append .<locals> to parent qualname
552557
// Use parent's qualname if available, otherwise use parent_obj_name
553-
let parent_qualname = parent.qualname.as_ref().unwrap_or(parent_obj_name);
558+
let parent_qualname = parent.metadata.qualname.as_ref().unwrap_or(parent_obj_name);
554559
format!("{parent_qualname}.<locals>.{current_obj_name}")
555560
} else {
556561
// For classes and other scopes, use parent's qualname directly
557562
// Use parent's qualname if available, otherwise use parent_obj_name
558-
let parent_qualname = parent.qualname.as_ref().unwrap_or(parent_obj_name);
563+
let parent_qualname = parent.metadata.qualname.as_ref().unwrap_or(parent_obj_name);
559564
if parent_qualname == "<module>" {
560565
// Module level, just use the name
561566
current_obj_name
@@ -720,7 +725,7 @@ impl Compiler<'_> {
720725
.ok_or_else(|| InternalError::MissingSymbol(name.to_string())),
721726
);
722727
let info = self.code_stack.last_mut().unwrap();
723-
let mut cache = &mut info.name_cache;
728+
let mut cache = &mut info.metadata.names;
724729
enum NameOpType {
725730
Fast,
726731
Global,
@@ -729,7 +734,7 @@ impl Compiler<'_> {
729734
}
730735
let op_typ = match symbol.scope {
731736
SymbolScope::Local if self.ctx.in_func() => {
732-
cache = &mut info.varname_cache;
737+
cache = &mut info.metadata.varnames;
733738
NameOpType::Fast
734739
}
735740
SymbolScope::GlobalExplicit => NameOpType::Global,
@@ -739,16 +744,16 @@ impl Compiler<'_> {
739744
SymbolScope::GlobalImplicit | SymbolScope::Unknown => NameOpType::Local,
740745
SymbolScope::Local => NameOpType::Local,
741746
SymbolScope::Free => {
742-
cache = &mut info.freevar_cache;
747+
cache = &mut info.metadata.freevars;
743748
NameOpType::Deref
744749
}
745750
SymbolScope::Cell => {
746-
cache = &mut info.cellvar_cache;
751+
cache = &mut info.metadata.cellvars;
747752
NameOpType::Deref
748753
} // TODO: is this right?
749754
SymbolScope::TypeParams => {
750755
// Type parameters are always cell variables
751-
cache = &mut info.cellvar_cache;
756+
cache = &mut info.metadata.cellvars;
752757
NameOpType::Deref
753758
} // SymbolScope::Unknown => NameOpType::Global,
754759
};
@@ -764,7 +769,7 @@ impl Compiler<'_> {
764769
.get_index_of(name.as_ref())
765770
.unwrap_or_else(|| cache.insert_full(name.into_owned()).0);
766771
if let SymbolScope::Free = symbol.scope {
767-
idx += info.cellvar_cache.len();
772+
idx += info.metadata.cellvars.len();
768773
}
769774
let op = match op_typ {
770775
NameOpType::Fast => match usage {
@@ -1653,7 +1658,8 @@ impl Compiler<'_> {
16531658
let (doc_str, body) = split_doc(body, &self.opts);
16541659

16551660
self.current_code_info()
1656-
.constants
1661+
.metadata
1662+
.consts
16571663
.insert_full(ConstantData::None);
16581664

16591665
// Emit RESUME instruction at function start
@@ -1774,18 +1780,20 @@ impl Compiler<'_> {
17741780
);
17751781
let parent_code = self.code_stack.last().unwrap();
17761782
let vars = match symbol.scope {
1777-
SymbolScope::Free => &parent_code.freevar_cache,
1778-
SymbolScope::Cell => &parent_code.cellvar_cache,
1779-
SymbolScope::TypeParams => &parent_code.cellvar_cache,
1780-
_ if symbol.flags.contains(SymbolFlags::FREE_CLASS) => &parent_code.freevar_cache,
1783+
SymbolScope::Free => &parent_code.metadata.freevars,
1784+
SymbolScope::Cell => &parent_code.metadata.cellvars,
1785+
SymbolScope::TypeParams => &parent_code.metadata.cellvars,
1786+
_ if symbol.flags.contains(SymbolFlags::FREE_CLASS) => {
1787+
&parent_code.metadata.freevars
1788+
}
17811789
x => unreachable!(
17821790
"var {} in a {:?} should be free or cell but it's {:?}",
17831791
var, table.typ, x
17841792
),
17851793
};
17861794
let mut idx = vars.get_index_of(var).unwrap();
17871795
if let SymbolScope::Free = symbol.scope {
1788-
idx += parent_code.cellvar_cache.len();
1796+
idx += parent_code.metadata.cellvars.len();
17891797
}
17901798
emit!(self, Instruction::LoadClosure(idx.to_u32()))
17911799
}
@@ -1910,7 +1918,8 @@ impl Compiler<'_> {
19101918
.code_stack
19111919
.last_mut()
19121920
.unwrap()
1913-
.cellvar_cache
1921+
.metadata
1922+
.cellvars
19141923
.iter()
19151924
.position(|var| *var == "__class__");
19161925

@@ -3691,7 +3700,8 @@ impl Compiler<'_> {
36913700
};
36923701

36933702
self.current_code_info()
3694-
.constants
3703+
.metadata
3704+
.consts
36953705
.insert_full(ConstantData::None);
36963706

36973707
self.compile_expression(body)?;
@@ -4344,7 +4354,7 @@ impl Compiler<'_> {
43444354

43454355
fn arg_constant(&mut self, constant: ConstantData) -> u32 {
43464356
let info = self.current_code_info();
4347-
info.constants.insert_full(constant).0.to_u32()
4357+
info.metadata.consts.insert_full(constant).0.to_u32()
43484358
}
43494359

43504360
fn emit_load_const(&mut self, constant: ConstantData) {

compiler/codegen/src/ir.rs

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -67,29 +67,20 @@ impl Default for Block {
6767

6868
pub struct CodeInfo {
6969
pub flags: CodeFlags,
70-
pub posonlyarg_count: u32, // Number of positional-only arguments
71-
pub arg_count: u32,
72-
pub kwonlyarg_count: u32,
7370
pub source_path: String,
74-
pub first_line_number: OneIndexed,
75-
pub obj_name: String, // Name of the object that created this code object
76-
pub qualname: Option<String>, // Qualified name of the object
7771
pub private: Option<String>, // For private name mangling, mostly for class
7872

7973
pub blocks: Vec<Block>,
8074
pub current_block: BlockIdx,
81-
pub constants: IndexSet<ConstantData>,
82-
pub name_cache: IndexSet<String>,
83-
pub varname_cache: IndexSet<String>,
84-
pub cellvar_cache: IndexSet<String>,
85-
pub freevar_cache: IndexSet<String>,
8675

87-
// For tracking hidden fast locals (used in comprehensions)
88-
// Maps variable name to bool (true if currently fast, false if was fast)
89-
pub fasthidden_cache: IndexMap<String, bool>,
76+
// Grouped metadata fields (like CPython's u_metadata)
77+
pub metadata: CodeUnitMetadata,
9078

9179
// For class scopes: attributes accessed via self.X
9280
pub static_attributes: Option<IndexSet<String>>,
81+
82+
// True if compiling an inlined comprehension
83+
pub in_inlined_comp: bool,
9384
}
9485
impl CodeInfo {
9586
pub fn finalize_code(mut self, optimize: u8) -> crate::InternalResult<CodeObject> {
@@ -102,26 +93,31 @@ impl CodeInfo {
10293

10394
let Self {
10495
flags,
105-
posonlyarg_count,
106-
arg_count,
107-
kwonlyarg_count,
10896
source_path,
109-
first_line_number,
110-
obj_name,
111-
qualname,
11297
private: _, // private is only used during compilation
11398

11499
mut blocks,
115100
current_block: _,
116-
constants,
117-
name_cache,
118-
varname_cache,
119-
cellvar_cache,
120-
freevar_cache,
121-
fasthidden_cache: _,
101+
metadata,
122102
static_attributes: _,
103+
in_inlined_comp: _,
123104
} = self;
124105

106+
let CodeUnitMetadata {
107+
name: obj_name,
108+
qualname,
109+
consts: constants,
110+
names: name_cache,
111+
varnames: varname_cache,
112+
cellvars: cellvar_cache,
113+
freevars: freevar_cache,
114+
fasthidden: _,
115+
argcount: arg_count,
116+
posonlyargcount: posonlyarg_count,
117+
kwonlyargcount: kwonlyarg_count,
118+
firstlineno: first_line_number,
119+
} = metadata;
120+
125121
let mut instructions = Vec::new();
126122
let mut locations = Vec::new();
127123

@@ -191,21 +187,23 @@ impl CodeInfo {
191187
}
192188

193189
fn cell2arg(&self) -> Option<Box<[i32]>> {
194-
if self.cellvar_cache.is_empty() {
190+
if self.metadata.cellvars.is_empty() {
195191
return None;
196192
}
197193

198-
let total_args = self.arg_count
199-
+ self.kwonlyarg_count
194+
let total_args = self.metadata.argcount
195+
+ self.metadata.kwonlyargcount
200196
+ self.flags.contains(CodeFlags::HAS_VARARGS) as u32
201197
+ self.flags.contains(CodeFlags::HAS_VARKEYWORDS) as u32;
202198

203199
let mut found_cellarg = false;
204200
let cell2arg = self
205-
.cellvar_cache
201+
.metadata
202+
.cellvars
206203
.iter()
207204
.map(|var| {
208-
self.varname_cache
205+
self.metadata
206+
.varnames
209207
.get_index_of(var)
210208
// check that it's actually an arg
211209
.filter(|i| *i < total_args as usize)
@@ -311,18 +309,19 @@ impl CodeInfo {
311309
impl InstrDisplayContext for CodeInfo {
312310
type Constant = ConstantData;
313311
fn get_constant(&self, i: usize) -> &ConstantData {
314-
&self.constants[i]
312+
&self.metadata.consts[i]
315313
}
316314
fn get_name(&self, i: usize) -> &str {
317-
self.name_cache[i].as_ref()
315+
self.metadata.names[i].as_ref()
318316
}
319317
fn get_varname(&self, i: usize) -> &str {
320-
self.varname_cache[i].as_ref()
318+
self.metadata.varnames[i].as_ref()
321319
}
322320
fn get_cell_name(&self, i: usize) -> &str {
323-
self.cellvar_cache
321+
self.metadata
322+
.cellvars
324323
.get_index(i)
325-
.unwrap_or_else(|| &self.freevar_cache[i - self.cellvar_cache.len()])
324+
.unwrap_or_else(|| &self.metadata.freevars[i - self.metadata.cellvars.len()])
326325
.as_ref()
327326
}
328327
}

0 commit comments

Comments
 (0)