= compiler_nameop
(&mut self, name: &str, usage: NameUsage)
| 2023 | |
| 2024 | // = compiler_nameop |
| 2025 | fn compile_name(&mut self, name: &str, usage: NameUsage) -> CompileResult<()> { |
| 2026 | enum NameOp { |
| 2027 | Fast, |
| 2028 | Global, |
| 2029 | Deref, |
| 2030 | Name, |
| 2031 | DictOrGlobals, // PEP 649: can_see_class_scope |
| 2032 | } |
| 2033 | |
| 2034 | let name = self.mangle(name); |
| 2035 | |
| 2036 | // Special handling for __debug__ |
| 2037 | if NameUsage::Load == usage && name == "__debug__" { |
| 2038 | self.emit_load_const(ConstantData::Boolean { |
| 2039 | value: self.opts.optimize == 0, |
| 2040 | }); |
| 2041 | return Ok(()); |
| 2042 | } |
| 2043 | |
| 2044 | // Determine the operation type based on symbol scope |
| 2045 | let is_function_like = self.ctx.in_func(); |
| 2046 | |
| 2047 | // Look up the symbol, handling ast::TypeParams and Annotation scopes specially |
| 2048 | let (symbol_scope, can_see_class_scope) = { |
| 2049 | let current_table = self.current_symbol_table(); |
| 2050 | let is_typeparams = current_table.typ == CompilerScope::TypeParams; |
| 2051 | let is_annotation = current_table.typ == CompilerScope::Annotation; |
| 2052 | let can_see_class = current_table.can_see_class_scope; |
| 2053 | |
| 2054 | // First try to find in current table |
| 2055 | let symbol = current_table.lookup(name.as_ref()); |
| 2056 | |
| 2057 | // If not found and we're in ast::TypeParams or Annotation scope, try parent scope |
| 2058 | let symbol = if symbol.is_none() && (is_typeparams || is_annotation) { |
| 2059 | self.symbol_table_stack |
| 2060 | .get(self.symbol_table_stack.len() - 2) // Try to get parent index |
| 2061 | .expect("Symbol has no parent! This is a compiler bug.") |
| 2062 | .lookup(name.as_ref()) |
| 2063 | } else { |
| 2064 | symbol |
| 2065 | }; |
| 2066 | |
| 2067 | (symbol.map(|s| s.scope), can_see_class) |
| 2068 | }; |
| 2069 | |
| 2070 | // Special handling for class scope implicit cell variables |
| 2071 | // These are treated as Cell even if not explicitly marked in symbol table |
| 2072 | // __class__ and __classdict__: only LOAD uses Cell (stores go to class namespace) |
| 2073 | // __conditional_annotations__: both LOAD and STORE use Cell (it's a mutable set |
| 2074 | // that the annotation scope accesses through the closure) |
| 2075 | let symbol_scope = { |
| 2076 | let current_table = self.current_symbol_table(); |
| 2077 | if current_table.typ == CompilerScope::Class |
| 2078 | && ((usage == NameUsage::Load |
| 2079 | && (name == "__class__" |
| 2080 | || name == "__classdict__" |
| 2081 | || name == "__conditional_annotations__")) |
| 2082 | || (name == "__conditional_annotations__" && usage == NameUsage::Store)) |
no test coverage detected