@@ -11,7 +11,7 @@ use crate::{
1111 IndexSet , ToPythonName ,
1212 error:: { CodegenError , CodegenErrorType , PatternUnreachableReason } ,
1313 ir:: { self , BlockIdx } ,
14- symboltable:: { self , SymbolFlags , SymbolScope , SymbolTable } ,
14+ symboltable:: { self , SymbolFlags , SymbolScope , SymbolTable , SymbolTableType } ,
1515 unparse:: unparse_expr,
1616} ;
1717use itertools:: Itertools ;
@@ -385,6 +385,30 @@ impl Compiler<'_> {
385385 let source_path = self . source_code . path . to_owned ( ) ;
386386 let first_line_number = self . get_source_line_number ( ) ;
387387
388+ // Check if this is a class declared as global in parent scope before pushing symbol table
389+ let is_global_class =
390+ if !self . symbol_table_stack . is_empty ( ) && !self . qualified_path . is_empty ( ) {
391+ // Look at the next table to be pushed (not yet removed from parent)
392+ let parent_table = self . symbol_table_stack . last ( ) . unwrap ( ) ;
393+ let next_table = parent_table. sub_tables . first ( ) ;
394+
395+ if let Some ( next_table) = next_table {
396+ if next_table. typ == SymbolTableType :: Class {
397+ // Check if the class is global in parent scope
398+ parent_table
399+ . lookup ( & obj_name)
400+ . map ( |symbol| symbol. is_global ( ) )
401+ . unwrap_or ( false )
402+ } else {
403+ false
404+ }
405+ } else {
406+ false
407+ }
408+ } else {
409+ false
410+ } ;
411+
388412 let table = self . push_symbol_table ( ) ;
389413
390414 let cellvar_cache = table
@@ -405,6 +429,9 @@ impl Compiler<'_> {
405429 // Calculate qualname based on the current qualified path
406430 let qualname = if self . qualified_path . is_empty ( ) {
407431 Some ( obj_name. clone ( ) )
432+ } else if is_global_class {
433+ // If the class is global, use just the class name as qualname
434+ Some ( obj_name. clone ( ) )
408435 } else {
409436 Some ( self . qualified_path . join ( "." ) )
410437 } ;
@@ -638,7 +665,11 @@ impl Compiler<'_> {
638665 cache = & mut info. cellvar_cache ;
639666 NameOpType :: Deref
640667 } // TODO: is this right?
641- // SymbolScope::Unknown => NameOpType::Global,
668+ SymbolScope :: TypeParams => {
669+ // Type parameters are always cell variables
670+ cache = & mut info. cellvar_cache ;
671+ NameOpType :: Deref
672+ } // SymbolScope::Unknown => NameOpType::Global,
642673 } ;
643674
644675 if NameUsage :: Load == usage && name == "__debug__" {
@@ -1630,6 +1661,7 @@ impl Compiler<'_> {
16301661 let vars = match symbol. scope {
16311662 SymbolScope :: Free => & parent_code. freevar_cache ,
16321663 SymbolScope :: Cell => & parent_code. cellvar_cache ,
1664+ SymbolScope :: TypeParams => & parent_code. cellvar_cache ,
16331665 _ if symbol. flags . contains ( SymbolFlags :: FREE_CLASS ) => & parent_code. freevar_cache ,
16341666 x => unreachable ! (
16351667 "var {} in a {:?} should be free or cell but it's {:?}" ,
@@ -1706,20 +1738,7 @@ impl Compiler<'_> {
17061738
17071739 let prev_class_name = self . class_name . replace ( name. to_owned ( ) ) ;
17081740
1709- // Check if the class is declared global
1710- let symbol_table = self . symbol_table_stack . last ( ) . unwrap ( ) ;
1711- let symbol = unwrap_internal (
1712- self ,
1713- symbol_table
1714- . lookup ( name. as_ref ( ) )
1715- . ok_or_else ( || InternalError :: MissingSymbol ( name. to_owned ( ) ) ) ,
1716- ) ;
1717- let mut global_path_prefix = Vec :: new ( ) ;
1718- if symbol. scope == SymbolScope :: GlobalExplicit {
1719- global_path_prefix. append ( & mut self . qualified_path ) ;
1720- }
17211741 self . push_qualified_path ( name) ;
1722- let qualified_name = self . qualified_path . join ( "." ) ;
17231742
17241743 // If there are type params, we need to push a special symbol table just for them
17251744 if let Some ( type_params) = type_params {
@@ -1732,17 +1751,23 @@ impl Compiler<'_> {
17321751
17331752 self . push_output ( bytecode:: CodeFlags :: empty ( ) , 0 , 0 , 0 , name. to_owned ( ) ) ;
17341753
1735- // Update the qualname in the current code info
1736- self . code_stack . last_mut ( ) . unwrap ( ) . qualname = Some ( qualified_name. clone ( ) ) ;
1737-
17381754 let ( doc_str, body) = split_doc ( body, & self . opts ) ;
17391755
17401756 let dunder_name = self . name ( "__name__" ) ;
17411757 emit ! ( self , Instruction :: LoadGlobal ( dunder_name) ) ;
17421758 let dunder_module = self . name ( "__module__" ) ;
17431759 emit ! ( self , Instruction :: StoreLocal ( dunder_module) ) ;
1760+
1761+ // Get the qualname from the current code info (set by push_output)
1762+ let current_qualname = self
1763+ . code_stack
1764+ . last ( )
1765+ . unwrap ( )
1766+ . qualname
1767+ . clone ( )
1768+ . unwrap_or_else ( || name. to_owned ( ) ) ;
17441769 self . emit_load_const ( ConstantData :: Str {
1745- value : qualified_name . into ( ) ,
1770+ value : current_qualname . into ( ) ,
17461771 } ) ;
17471772 let qualname = self . name ( "__qualname__" ) ;
17481773 emit ! ( self , Instruction :: StoreLocal ( qualname) ) ;
@@ -1790,7 +1815,7 @@ impl Compiler<'_> {
17901815
17911816 self . class_name = prev_class_name;
17921817 self . qualified_path . pop ( ) ;
1793- self . qualified_path . append ( global_path_prefix. as_mut ( ) ) ;
1818+ // self.qualified_path.append(global_path_prefix.as_mut());
17941819 self . ctx = prev_ctx;
17951820
17961821 emit ! ( self , Instruction :: LoadBuildClass ) ;
@@ -3529,10 +3554,16 @@ impl Compiler<'_> {
35293554 if self . build_closure ( & code) {
35303555 func_flags |= bytecode:: MakeFunctionFlags :: CLOSURE ;
35313556 }
3557+
3558+ // Get the qualname from the code object
3559+ let qualname = code. qualname . clone ( ) ;
3560+
35323561 self . emit_load_const ( ConstantData :: Code {
35333562 code : Box :: new ( code) ,
35343563 } ) ;
3535- self . emit_load_const ( ConstantData :: Str { value : name. into ( ) } ) ;
3564+ self . emit_load_const ( ConstantData :: Str {
3565+ value : qualname. into ( ) ,
3566+ } ) ;
35363567 // Turn code object into function object:
35373568 emit ! ( self , Instruction :: MakeFunction ( func_flags) ) ;
35383569
0 commit comments