2025-02-04 16:09:05 +02:00
use crate ::compiler ::variable ::{ Type , Value } ;
2025-02-03 18:01:39 +02:00
use std ::collections ::HashMap ;
#[ derive(Default) ]
2025-02-04 16:09:05 +02:00
pub struct SymTab < ' source , T > {
tables : Vec < HashMap < & ' source str , T > > ,
2025-02-03 18:01:39 +02:00
}
2025-02-04 16:09:05 +02:00
impl < ' source , T > SymTab < ' source , T > {
pub fn get ( & mut self , symbol : & str ) -> & mut T {
2025-02-04 00:34:56 +02:00
for i in ( 0 .. self . tables . len ( ) ) . rev ( ) {
if self . tables [ i ] . contains_key ( symbol ) {
return self . tables [ i ] . get_mut ( symbol ) . unwrap ( ) ;
}
2025-02-03 18:01:39 +02:00
}
2025-02-04 00:34:56 +02:00
panic! ( " No symbol {} found! " , symbol ) ;
2025-02-03 18:01:39 +02:00
}
2025-02-04 00:34:56 +02:00
pub fn push_level ( & mut self ) {
self . tables . push ( HashMap ::new ( ) ) ;
}
pub fn remove_level ( & mut self ) {
self . tables . pop ( ) ;
}
2025-02-04 16:09:05 +02:00
pub fn insert ( & mut self , name : & ' source str , val : T ) {
2025-02-04 00:34:56 +02:00
if self
. tables
. last_mut ( )
. expect ( " Symbols table should never be empty! " )
. insert ( name , val )
. is_some ( )
{
panic! ( " Variable {} already defined in this scope! " , name )
2025-02-03 18:01:39 +02:00
}
}
}
2025-02-04 16:09:05 +02:00
2025-02-05 17:16:17 +02:00
impl < ' source , T > SymTab < ' source , T > {
pub fn new ( ) -> SymTab < ' source , T > {
SymTab {
tables : vec ! [ HashMap ::new ( ) ] ,
}
}
}
2025-02-04 16:09:05 +02:00
impl < ' source > SymTab < ' source , Type > {
pub fn new_type_table ( ) -> SymTab < ' source , Type > {
use Type ::* ;
let globals = HashMap ::from ( [
( " + " , Func ( vec! [ Int , Int ] , Box ::new ( Int ) ) ) ,
( " * " , Func ( vec! [ Int , Int ] , Box ::new ( Int ) ) ) ,
( " - " , Func ( vec! [ Int , Int ] , Box ::new ( Int ) ) ) ,
( " / " , Func ( vec! [ Int , Int ] , Box ::new ( Int ) ) ) ,
( " % " , Func ( vec! [ Int , Int ] , Box ::new ( Int ) ) ) ,
( " < " , Func ( vec! [ Int , Int ] , Box ::new ( Bool ) ) ) ,
( " <= " , Func ( vec! [ Int , Int ] , Box ::new ( Bool ) ) ) ,
( " > " , Func ( vec! [ Int , Int ] , Box ::new ( Bool ) ) ) ,
( " >= " , Func ( vec! [ Int , Int ] , Box ::new ( Bool ) ) ) ,
2025-02-05 18:15:37 +02:00
( " unary_not " , Func ( vec! [ Bool ] , Box ::new ( Bool ) ) ) ,
( " unary_- " , Func ( vec! [ Int ] , Box ::new ( Int ) ) ) ,
2025-02-04 17:07:41 +02:00
( " or " , Func ( vec! [ Bool , Bool ] , Box ::new ( Bool ) ) ) ,
( " and " , Func ( vec! [ Bool , Bool ] , Box ::new ( Bool ) ) ) ,
2025-02-04 16:09:05 +02:00
] ) ;
SymTab {
tables : vec ! [ globals ] ,
}
}
}
impl < ' source > SymTab < ' source , Value > {
pub fn new_val_table ( ) -> SymTab < ' source , Value > {
use Value ::* ;
let globals = HashMap ::from ( [
( " + " , Func ( Value ::add ) ) ,
( " * " , Func ( Value ::mul ) ) ,
( " - " , Func ( Value ::sub ) ) ,
( " / " , Func ( Value ::div ) ) ,
( " % " , Func ( Value ::rem ) ) ,
( " == " , Func ( Value ::eq ) ) ,
( " != " , Func ( Value ::neq ) ) ,
( " < " , Func ( Value ::lt ) ) ,
( " <= " , Func ( Value ::le ) ) ,
( " > " , Func ( Value ::gt ) ) ,
( " >= " , Func ( Value ::ge ) ) ,
2025-02-05 18:15:37 +02:00
( " unary_not " , Func ( Value ::not ) ) ,
( " unary_- " , Func ( Value ::neg ) ) ,
2025-02-04 16:09:05 +02:00
] ) ;
SymTab {
tables : vec ! [ globals ] ,
}
}
}