Mercurial > lcfOS
comparison python/c3/typecheck.py @ 163:8104fc8b5e90
Added visitor to c3
author | Windel Bouwman |
---|---|
date | Mon, 18 Mar 2013 20:13:57 +0100 |
parents | b28a11c01dbe |
children | e023d3ce1d63 |
comparison
equal
deleted
inserted
replaced
162:d8c735dc31f9 | 163:8104fc8b5e90 |
---|---|
1 from .astnodes import BaseType, Variable, Designator, Function | 1 from .astnodes import * |
2 from .astnodes import CompoundStatement, Assignment, VariableUse | 2 from .scope import * |
3 from .astnodes import Binop, Unop, Constant | 3 from .visitor import Visitor |
4 from .astnodes import IfStatement, WhileStatement, ReturnStatement, ProcedureCall | 4 |
5 from .astnodes import FunctionType, BaseType | 5 def equalTypes(a, b): |
6 from . import astnodes | 6 """ Compare types a and b for equality. Not equal until proven otherwise. """ |
7 from .scope import topScope | 7 if type(a) is type(b): |
8 if type(a) is BaseType: | |
9 return a.name == b.name | |
10 return False | |
8 | 11 |
9 class TypeChecker: | 12 class TypeChecker: |
10 def __init__(self, diag): | 13 def __init__(self, diag): |
11 self.diag = diag | 14 self.diag = diag |
15 self.visitor = Visitor(self.precheck, self.check2) | |
12 def checkPackage(self, pkg): | 16 def checkPackage(self, pkg): |
13 for s in pkg.scope: | 17 self.visitor.visit(pkg) |
14 self.check(s) | 18 def precheck(self, sym): |
15 def resolveDesignator(self, d): | 19 pass |
16 if d.scope.hasSymbol(d.tname): | 20 def check2(self, sym): |
17 return d.scope.getSymbol(d.tname) | 21 if type(sym) is Function: |
22 pass | |
23 elif type(sym) is IfStatement: | |
24 print(sym.condition) | |
25 if not equalTypes(sym.condition.typ, boolType): | |
26 self.diag.error('Condition must be a boolean expression', sym.condition.loc) | |
27 elif type(sym) is Assignment: | |
28 pass | |
29 elif type(sym) is ReturnStatement: | |
30 pass | |
31 elif type(sym) is ProcedureCall: | |
32 # Check arguments: | |
33 | |
34 # determine return type: | |
35 sym.typ = sym.proc.typ.returntype | |
36 elif type(sym) is VariableUse: | |
37 if sym.target: | |
38 sym.typ = sym.target.typ | |
39 else: | |
40 sym.typ = voidType | |
41 elif type(sym) is Literal: | |
42 if type(sym.val) is int: | |
43 sym.typ = intType | |
44 elif type(sym.val) is float: | |
45 sym.typ = doubleType | |
46 else: | |
47 self.diag.error('Unknown literal type', sym.loc) | |
48 elif type(sym) is Binop: | |
49 if sym.op in ['+', '-', '*', '/']: | |
50 if equalTypes(sym.a.typ, sym.b.typ): | |
51 sym.typ = sym.a.typ | |
52 else: | |
53 # assume void here? | |
54 sym.typ = voidType | |
55 self.diag.error('Types unequal', sym.loc) | |
56 elif sym.op in ['>', '<']: | |
57 if equalTypes(sym.a.typ, sym.b.typ): | |
58 sym.typ = boolType | |
59 else: | |
60 sym.typ = voidType | |
61 self.diag.error('Types unequal', sym.loc) | |
62 else: | |
63 sym.typ = voidType | |
64 print('unknown binop', sym.op) | |
18 else: | 65 else: |
19 msg = 'Cannot resolve name {0}'.format(d.tname) | 66 print('Unknown type check', sym) |
20 self.diag.error(msg, d.loc) | |
21 def check(self, sym): | |
22 if type(sym) is Variable: | |
23 if type(sym.typ) is Designator: | |
24 sym.typ = self.resolveDesignator(sym.typ) | |
25 elif type(sym) is Function: | |
26 for s in sym.scope: | |
27 self.check(s) | |
28 self.check(sym.typ) | |
29 self.check(sym.body) | |
30 elif type(sym) is CompoundStatement: | |
31 for s in sym.statements: | |
32 self.check(s) | |
33 elif type(sym) is IfStatement: | |
34 self.check(sym.condition) | |
35 self.check(sym.truestatement) | |
36 self.check(sym.falsestatement) | |
37 elif type(sym) is VariableUse: | |
38 if type(sym.target) is Designator: | |
39 sym.target = self.resolveDesignator(sym.target) | |
40 elif type(sym) is ProcedureCall: | |
41 if type(sym.proc) is Designator: | |
42 sym.proc = self.resolveDesignator(sym.proc) | |
43 elif type(sym) is Assignment: | |
44 self.check(sym.lval) | |
45 self.check(sym.rval) | |
46 elif type(sym) is ReturnStatement: | |
47 self.check(sym.expr) | |
48 elif type(sym) is Constant: | |
49 if type(sym.value) is int: | |
50 sym.typ = topScope.getSymbol('int') | |
51 elif type(sym) is FunctionType: | |
52 if type(sym.returntype) is Designator: | |
53 sym.returntype = self.resolveDesignator(sym.returntype) | |
54 self.check(sym.returntype) | |
55 elif type(sym) is Binop: | |
56 self.check(sym.a) | |
57 self.check(sym.b) | |
58 if type(sym.a) is Constant and type(sym.b) is Constant: | |
59 # Possibly fold expression | |
60 pass | |
61 | 67 |