Skip to content

Commit c6502fa

Browse files
committed
type check C
1 parent 10fd80e commit c6502fa

File tree

3 files changed

+151
-0
lines changed

3 files changed

+151
-0
lines changed

type_check_Cif.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
from ast import *
2+
from utils import CProgram, Goto, trace, Bottom
3+
import copy
4+
5+
def check_type_equal(t1, t2, e):
6+
if t1 == Bottom() or t2 == Bottom():
7+
pass
8+
elif t1 != t2:
9+
raise Exception('error: ' + repr(t1) + ' != ' + repr(t2) \
10+
+ ' in ' + repr(e))
11+
12+
class TypeCheckCif:
13+
14+
def type_check_atm(self, e, env):
15+
match e:
16+
case Name(id):
17+
return env.get(id, Bottom())
18+
case Constant(value) if isinstance(value, bool):
19+
return bool
20+
case Constant(value) if isinstance(value, int):
21+
return int
22+
case _:
23+
raise Exception('error in type_check_atm, unexpected ' + repr(e))
24+
25+
def type_check_exp(self, e, env):
26+
match e:
27+
case Name(id):
28+
return self.type_check_atm(e, env)
29+
case Constant(value):
30+
return self.type_check_atm(e, env)
31+
case BinOp(left, op, right) if isinstance(op, Add) or isinstance(op, Sub):
32+
l = self.type_check_atm(left, env)
33+
check_type_equal(l, int, e)
34+
r = self.type_check_atm(right, env)
35+
check_type_equal(r, int, e)
36+
return int
37+
case UnaryOp(USub(), v):
38+
t = self.type_check_atm(v, env)
39+
check_type_equal(t, int, e)
40+
return int
41+
case UnaryOp(Not(), v):
42+
t = self.type_check_exp(v, env)
43+
check_type_equal(t, bool, e)
44+
return bool
45+
case Compare(left, [cmp], [right]) if isinstance(cmp, Eq) or isinstance(cmp, NotEq):
46+
l = self.type_check_atm(left, env)
47+
r = self.type_check_atm(right, env)
48+
check_type_equal(l, r, e)
49+
return bool
50+
case Compare(left, [cmp], [right]):
51+
l = self.type_check_atm(left, env)
52+
check_type_equal(l, int, left)
53+
r = self.type_check_atm(right, env)
54+
check_type_equal(r, int, right)
55+
return bool
56+
case Call(Name('input_int'), []):
57+
return int
58+
case _:
59+
raise Exception('error in type_check_exp, unexpected ' + repr(e))
60+
61+
def type_check_stmt(self, s, env):
62+
match s:
63+
case Assign([lhs], value):
64+
t = self.type_check_exp(value, env)
65+
if lhs.id in env:
66+
check_type_equal(env.get(lhs.id, Bottom()), t, s)
67+
else:
68+
env[lhs.id] = t
69+
case Expr(Call(Name('print'), [arg])):
70+
t = self.type_check_exp(arg, env)
71+
check_type_equal(t, int, s)
72+
case Expr(value):
73+
self.type_check_exp(value, env)
74+
case If(Compare(left, [cmp], [right]), body, orelse):
75+
left_t = self.type_check_atm(left, env)
76+
right_t = self.type_check_atm(right, env)
77+
check_type_equal(left_t, right_t, s) # not quite strict enough
78+
self.type_check_stmts(body, env)
79+
self.type_check_stmts(orelse, env)
80+
case Goto(label):
81+
pass
82+
case Return(value):
83+
value_t = self.type_check_exp(value, env);
84+
case _:
85+
raise Exception('error in type_check_stmt, unexpected' + repr(s))
86+
87+
def type_check_stmts(self, ss, env):
88+
for s in ss:
89+
self.type_check_stmt(s, env)
90+
91+
def type_check(self, p):
92+
match p:
93+
case CProgram(body):
94+
env = {}
95+
while True:
96+
trace("env:\n" + str(env))
97+
old_env = copy.deepcopy(env)
98+
for (l, ss) in body.items():
99+
self.type_check_stmts(ss, env)
100+
if env == old_env:
101+
break;
102+
p.var_types = env
103+
trace("var_types")
104+
trace(p.var_types)
105+
case _:
106+
raise Exception('error in type_check, unexpected ' + repr(p))

type_check_Ctup.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from ast import *
2+
from type_check_Cif import check_type_equal
3+
from type_check_Cwhile import TypeCheckCwhile
4+
from utils import Allocate, Begin, GlobalValue, Collect, TupleType
5+
6+
class TypeCheckCtup(TypeCheckCwhile):
7+
8+
def type_check_exp(self, e, env):
9+
match e:
10+
case Allocate(length, typ):
11+
return typ;
12+
case Begin(ss, e):
13+
self.type_check_stmts(ss, env)
14+
return self.type_check_exp(e, env)
15+
case GlobalValue(name):
16+
return int
17+
case Subscript(tup, Constant(index), Load()):
18+
tup_t = self.type_check_atm(tup, env)
19+
match tup_t:
20+
case TupleType(ts):
21+
return ts[index]
22+
case _:
23+
raise Exception('error, expected a tuple, not ' + repr(tup_t))
24+
case _:
25+
return super().type_check_exp(e, env)
26+
27+
def type_check_stmt(self, s, env):
28+
match s:
29+
case Collect(size):
30+
pass
31+
case Assign([Subscript(tup, Constant(index))], value):
32+
tup_t = self.type_check_atm(tup, env)
33+
value_t = self.type_check_atm(value, env)
34+
match tup_t:
35+
case TupleType(ts):
36+
check_type_equal(ts[index], value_t, s)
37+
case _:
38+
raise Exception('error, expected a tuple, not ' + repr(tup_t))
39+
case _:
40+
return super().type_check_stmt(s, env)
41+

type_check_Cwhile.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from type_check_Cif import TypeCheckCif
2+
3+
class TypeCheckCwhile(TypeCheckCif):
4+
pass

0 commit comments

Comments
 (0)