@@ -5,6 +5,7 @@ def build_symtable(ast):
5
5
if not isinstance (ast , Function ) or ast .name != 'main' or ast .deco ['type' ] != Type .VOID or len (ast .args )> 0 :
6
6
raise Exception ('Cannot find a valid entry point' )
7
7
symtable = SymbolTable ()
8
+ symtable .add_fun (ast .name , [], ast .deco )
8
9
process_scope (ast , symtable )
9
10
10
11
def process_scope (fun , symtable ):
@@ -14,54 +15,76 @@ def process_scope(fun, symtable):
14
15
symtable .add_var (* v )
15
16
for v in fun .var : # process local variables
16
17
symtable .add_var (* v )
18
+ for f in fun .fun : # process nested functions: first add function symbols to the table
19
+ symtable .add_fun (f .name , [d ['type' ] for v ,d in f .args ], f .deco )
17
20
for f in fun .fun : # then process nested function bodies
18
21
process_scope (f , symtable )
19
22
for s in fun .body : # process the list of statements
20
23
process_stat (s , symtable )
21
24
symtable .pop_scope ()
22
25
23
26
def process_stat (n , symtable ): # process "statement" syntax tree nodes
24
- if isinstance (n , Print ):
27
+ if isinstance (n , Print ): # no type checking is necessary
25
28
process_expr (n .expr , symtable )
26
29
elif isinstance (n , Return ):
27
30
if n .expr is None : return
28
31
process_expr (n .expr , symtable )
32
+ if symtable .ret_stack [- 1 ]['type' ] != n .expr .deco ['type' ]:
33
+ raise Exception ('Incompatible types in return statement, line %s' , n .deco ['lineno' ])
29
34
elif isinstance (n , Assign ):
30
35
process_expr (n .expr , symtable )
31
36
deco = symtable .find_var (n .name )
37
+ n .deco ['type' ] = deco ['type' ]
38
+ if n .deco ['type' ] != n .expr .deco ['type' ]:
39
+ raise Exception ('Incompatible types in assignment statement, line %s' , n .deco ['lineno' ])
32
40
update_nonlocals (n .name , symtable ) # used in "readable" python transpilation only
33
41
elif isinstance (n , FunCall ): # no type checking is necessary
34
42
process_expr (n , symtable )
35
43
elif isinstance (n , While ):
36
44
process_expr (n .expr , symtable )
45
+ if n .expr .deco ['type' ] != Type .BOOL :
46
+ raise Exception ('Non-boolean expression in while statement, line %s' , n .deco ['lineno' ])
37
47
for s in n .body :
38
48
process_stat (s , symtable )
39
49
elif isinstance (n , IfThenElse ):
40
50
process_expr (n .expr , symtable )
51
+ if n .expr .deco ['type' ] != Type .BOOL :
52
+ raise Exception ('Non-boolean expression in if statement, line %s' , n .deco ['lineno' ])
41
53
for s in n .ibody + n .ebody :
42
54
process_stat (s , symtable )
43
55
else :
44
56
raise Exception ('Unknown statement type' )
45
57
46
58
def process_expr (n , symtable ): # process "expression" syntax tree nodes
47
59
if isinstance (n , ArithOp ):
60
+ n .deco ['type' ] = Type .INT
48
61
process_expr (n .left , symtable )
49
62
process_expr (n .right , symtable )
63
+ if n .left .deco ['type' ] != Type .INT or n .right .deco ['type' ] != Type .INT :
64
+ raise Exception ('Arithmetic operation over non-integer type in line %s' , n .deco ['lineno' ])
50
65
elif isinstance (n , LogicOp ):
66
+ n .deco ['type' ] = Type .BOOL
51
67
process_expr (n .left , symtable )
52
68
process_expr (n .right , symtable )
53
- elif isinstance (n , Integer ):
69
+ if (n .left .deco ['type' ] != n .right .deco ['type' ]) or \
70
+ (n .op in ['<=' , '<' , '>=' , '>' ] and n .left .deco ['type' ] != Type .INT ) or \
71
+ (n .op in ['&&' , '||' ] and n .left .deco ['type' ] != Type .BOOL ):
72
+ raise Exception ('Boolean operation over incompatible types in line %s' , n .deco ['lineno' ])
73
+ elif isinstance (n , Integer ): # no type checking is necessary
54
74
n .deco ['type' ] = Type .INT
55
- elif isinstance (n , Boolean ):
75
+ elif isinstance (n , Boolean ): # no type checking is necessary
56
76
n .deco ['type' ] = Type .BOOL
57
- elif isinstance (n , Var ):
77
+ elif isinstance (n , Var ): # no type checking is necessary
58
78
deco = symtable .find_var (n .name )
79
+ n .deco ['type' ] = deco ['type' ]
59
80
update_nonlocals (n .name , symtable ) # used in "readable" python transpilation only
60
81
elif isinstance (n , FunCall ):
61
82
for s in n .args :
62
83
process_expr (s , symtable )
63
- elif isinstance (n , String ):
64
- pass
84
+ deco = symtable .find_fun (n .name , [a .deco ['type' ] for a in n .args ])
85
+ n .deco ['type' ] = deco ['type' ]
86
+ elif isinstance (n , String ): # no type checking is necessary
87
+ n .deco ['type' ] = Type .STRING
65
88
else :
66
89
raise Exception ('Unknown expression type' , n )
67
90
0 commit comments