1- use std:: fmt:: format;
1+ use std:: { collections :: HashMap , fmt:: format, hash :: Hash } ;
22
33use crate :: { ast, error:: Error , shared_types:: Identifier } ;
44
5- struct VariableResolution { }
5+ type VarTable = HashMap < String , String > ;
6+ struct VariableResolution {
7+ var_table : VarTable ,
8+ var_index : i32 ,
9+ }
10+
611impl VariableResolution {
7- fn record_var_name ( & mut self , name : & Identifier ) -> Identifier {
8- Identifier :: new ( & format ! ( "{}_new" , name. val( ) ) )
12+ fn new ( ) -> VariableResolution {
13+ VariableResolution {
14+ var_table : VarTable :: new ( ) ,
15+ var_index : 0 ,
16+ }
917 }
18+ fn record_var_name ( & mut self , name : & Identifier ) -> Result < Identifier , Error > {
19+ let new_name = self . var_table . get ( name. val ( ) ) ;
20+ if let Some ( name) = new_name {
21+ return Err ( format ! ( "Variable {} already defined" , name) ) ;
22+ }
23+ let new_name = format ! ( "{}.{}" , name. val( ) , self . var_index) ;
24+ self . var_index += 1 ;
25+ Ok ( Identifier :: new ( & new_name) )
26+ }
27+
1028 fn resolve_in_expr ( & self , init : & mut ast:: Expr ) -> Result < ( ) , Error > {
1129 todo ! ( )
1230 }
13- fn resolve_in_stmt ( & self , stmt : & mut ast:: Stmt ) -> Result < ( ) , String > {
14- todo ! ( )
31+ fn resolve_in_stmt ( & mut self , stmt : & mut ast:: Stmt ) -> Result < ( ) , String > {
32+ match stmt {
33+ ast:: Stmt :: Return ( expr) | ast:: Stmt :: Expr ( expr) => self . resolve_in_expr ( expr) ,
34+ ast:: Stmt :: Null => Ok ( ( ) ) ,
35+ ast:: Stmt :: If {
36+ cond,
37+ true_stmt,
38+ false_stmt,
39+ } => {
40+ self . resolve_in_expr ( cond) ?;
41+ self . resolve_in_stmt ( true_stmt) ?;
42+ if let Some ( stmt) = false_stmt {
43+ self . resolve_in_stmt ( stmt) ?;
44+ }
45+ Ok ( ( ) )
46+ }
47+ }
1548 }
1649 fn resolve_in_block ( & mut self , block : & mut ast:: BlockItem ) -> Result < ( ) , Error > {
1750 match block {
1851 ast:: BlockItem :: Declaration ( identifier, expr) => {
19- let new_name = self . record_var_name ( identifier) ;
52+ let new_name = self . record_var_name ( identifier) ? ;
2053 if let Some ( init) = expr {
2154 self . resolve_in_expr ( init) ?;
2255 }
@@ -42,7 +75,7 @@ impl VariableResolution {
4275/// The result is a new ast::Program
4376/// TODO should I mutate?
4477pub fn run_semantic_analysis ( prog : & mut ast:: Program ) -> Result < ( ) , Error > {
45- let mut resolver = VariableResolution { } ;
78+ let mut resolver = VariableResolution :: new ( ) ;
4679 resolver. resolve_vars ( prog)
4780}
4881
@@ -77,7 +110,7 @@ Program(
77110 r#"
78111Program(
79112 Function main() {
80- Declaration(var_new );
113+ Declaration(var.0 );
81114 }
82115)
83116"# ,
0 commit comments