@@ -11,6 +11,7 @@ use crate::error::{CompileError, CompileErrorType};
1111use indexmap:: map:: IndexMap ;
1212use rustpython_parser:: ast;
1313use rustpython_parser:: location:: Location ;
14+ use std:: fmt;
1415
1516pub fn make_symbol_table ( program : & ast:: Program ) -> Result < SymbolTable , SymbolTableError > {
1617 let mut builder: SymbolTableBuilder = Default :: default ( ) ;
@@ -29,11 +30,17 @@ pub fn statements_to_symbol_table(
2930}
3031
3132/// Captures all symbols in the current scope, and has a list of subscopes in this scope.
32- #[ derive( Clone , Default ) ]
33+ #[ derive( Clone ) ]
3334pub struct SymbolTable {
3435 /// The name of this symbol table. Often the name of the class or function.
3536 pub name : String ,
3637
38+ /// The type of symbol table
39+ pub typ : SymbolTableType ,
40+
41+ /// The line number in the sourcecode where this symboltable begins.
42+ pub line_number : usize ,
43+
3744 /// A set of symbols present on this scope level.
3845 pub symbols : IndexMap < String , Symbol > ,
3946
@@ -43,15 +50,34 @@ pub struct SymbolTable {
4350}
4451
4552impl SymbolTable {
46- fn new ( name : String ) -> Self {
53+ fn new ( name : String , typ : SymbolTableType , line_number : usize ) -> Self {
4754 SymbolTable {
4855 name,
56+ typ,
57+ line_number,
4958 symbols : Default :: default ( ) ,
5059 sub_tables : vec ! [ ] ,
5160 }
5261 }
5362}
5463
64+ #[ derive( Clone ) ]
65+ pub enum SymbolTableType {
66+ Module ,
67+ Class ,
68+ Function ,
69+ }
70+
71+ impl fmt:: Display for SymbolTableType {
72+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
73+ match self {
74+ SymbolTableType :: Module => write ! ( f, "module" ) ,
75+ SymbolTableType :: Class => write ! ( f, "class" ) ,
76+ SymbolTableType :: Function => write ! ( f, "function" ) ,
77+ }
78+ }
79+ }
80+
5581/// Indicator for a single symbol what the scope of this symbol is.
5682/// The scope can be unknown, which is unfortunate, but not impossible.
5783#[ derive( Debug , Clone ) ]
@@ -263,7 +289,7 @@ enum ExpressionContext {
263289
264290impl SymbolTableBuilder {
265291 fn prepare ( & mut self ) {
266- self . enter_block ( "top" )
292+ self . enter_scope ( "top" , SymbolTableType :: Module , 0 )
267293 }
268294
269295 fn finish ( & mut self ) -> Result < SymbolTable , SymbolTableError > {
@@ -273,14 +299,13 @@ impl SymbolTableBuilder {
273299 Ok ( symbol_table)
274300 }
275301
276- fn enter_block ( & mut self , name : & str ) {
277- // let parent = Some(self.tables.last().unwrap().clone());
278- let table = SymbolTable :: new ( name. to_string ( ) ) ;
302+ fn enter_scope ( & mut self , name : & str , typ : SymbolTableType , line_number : usize ) {
303+ let table = SymbolTable :: new ( name. to_string ( ) , typ, line_number) ;
279304 self . tables . push ( table) ;
280305 }
281306
282- fn leave_block ( & mut self ) {
283- // Pop symbol table and add to sub table of parent table.
307+ /// Pop symbol table and add to sub table of parent table.
308+ fn leave_scope ( & mut self ) {
284309 let table = self . tables . pop ( ) . unwrap ( ) ;
285310 self . tables . last_mut ( ) . unwrap ( ) . sub_tables . push ( table) ;
286311 }
@@ -348,9 +373,9 @@ impl SymbolTableBuilder {
348373 if let Some ( expression) = returns {
349374 self . scan_expression ( expression, & ExpressionContext :: Load ) ?;
350375 }
351- self . enter_function ( name, args) ?;
376+ self . enter_function ( name, args, statement . location . row ( ) ) ?;
352377 self . scan_statements ( body) ?;
353- self . leave_block ( ) ;
378+ self . leave_scope ( ) ;
354379 }
355380 ClassDef {
356381 name,
@@ -360,9 +385,9 @@ impl SymbolTableBuilder {
360385 decorator_list,
361386 } => {
362387 self . register_name ( name, SymbolUsage :: Assigned ) ?;
363- self . enter_block ( name) ;
388+ self . enter_scope ( name, SymbolTableType :: Class , statement . location . row ( ) ) ;
364389 self . scan_statements ( body) ?;
365- self . leave_block ( ) ;
390+ self . leave_scope ( ) ;
366391 self . scan_expressions ( bases, & ExpressionContext :: Load ) ?;
367392 for keyword in keywords {
368393 self . scan_expression ( & keyword. value , & ExpressionContext :: Load ) ?;
@@ -612,9 +637,9 @@ impl SymbolTableBuilder {
612637 }
613638 }
614639 Lambda { args, body } => {
615- self . enter_function ( "lambda" , args) ?;
640+ self . enter_function ( "lambda" , args, expression . location . row ( ) ) ?;
616641 self . scan_expression ( body, & ExpressionContext :: Load ) ?;
617- self . leave_block ( ) ;
642+ self . leave_scope ( ) ;
618643 }
619644 IfExpression { test, body, orelse } => {
620645 self . scan_expression ( test, & ExpressionContext :: Load ) ?;
@@ -625,7 +650,12 @@ impl SymbolTableBuilder {
625650 Ok ( ( ) )
626651 }
627652
628- fn enter_function ( & mut self , name : & str , args : & ast:: Parameters ) -> SymbolTableResult {
653+ fn enter_function (
654+ & mut self ,
655+ name : & str ,
656+ args : & ast:: Parameters ,
657+ line_number : usize ,
658+ ) -> SymbolTableResult {
629659 // Evaluate eventual default parameters:
630660 self . scan_expressions ( & args. defaults , & ExpressionContext :: Load ) ?;
631661 for kw_default in & args. kw_defaults {
@@ -644,7 +674,7 @@ impl SymbolTableBuilder {
644674 self . scan_parameter_annotation ( name) ?;
645675 }
646676
647- self . enter_block ( name) ;
677+ self . enter_scope ( name, SymbolTableType :: Function , line_number ) ;
648678
649679 // Fill scope with parameter names:
650680 self . scan_parameters ( & args. args ) ?;
0 commit comments