Mercurial > lcfOS
diff 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 |
line wrap: on
line diff
--- a/python/c3/typecheck.py Sun Mar 10 11:36:55 2013 +0100 +++ b/python/c3/typecheck.py Mon Mar 18 20:13:57 2013 +0100 @@ -1,61 +1,67 @@ -from .astnodes import BaseType, Variable, Designator, Function -from .astnodes import CompoundStatement, Assignment, VariableUse -from .astnodes import Binop, Unop, Constant -from .astnodes import IfStatement, WhileStatement, ReturnStatement, ProcedureCall -from .astnodes import FunctionType, BaseType -from . import astnodes -from .scope import topScope +from .astnodes import * +from .scope import * +from .visitor import Visitor + +def equalTypes(a, b): + """ Compare types a and b for equality. Not equal until proven otherwise. """ + if type(a) is type(b): + if type(a) is BaseType: + return a.name == b.name + return False class TypeChecker: def __init__(self, diag): self.diag = diag + self.visitor = Visitor(self.precheck, self.check2) def checkPackage(self, pkg): - for s in pkg.scope: - self.check(s) - def resolveDesignator(self, d): - if d.scope.hasSymbol(d.tname): - return d.scope.getSymbol(d.tname) - else: - msg = 'Cannot resolve name {0}'.format(d.tname) - self.diag.error(msg, d.loc) - def check(self, sym): - if type(sym) is Variable: - if type(sym.typ) is Designator: - sym.typ = self.resolveDesignator(sym.typ) - elif type(sym) is Function: - for s in sym.scope: - self.check(s) - self.check(sym.typ) - self.check(sym.body) - elif type(sym) is CompoundStatement: - for s in sym.statements: - self.check(s) + self.visitor.visit(pkg) + def precheck(self, sym): + pass + def check2(self, sym): + if type(sym) is Function: + pass elif type(sym) is IfStatement: - self.check(sym.condition) - self.check(sym.truestatement) - self.check(sym.falsestatement) - elif type(sym) is VariableUse: - if type(sym.target) is Designator: - sym.target = self.resolveDesignator(sym.target) - elif type(sym) is ProcedureCall: - if type(sym.proc) is Designator: - sym.proc = self.resolveDesignator(sym.proc) + print(sym.condition) + if not equalTypes(sym.condition.typ, boolType): + self.diag.error('Condition must be a boolean expression', sym.condition.loc) elif type(sym) is Assignment: - self.check(sym.lval) - self.check(sym.rval) + pass elif type(sym) is ReturnStatement: - self.check(sym.expr) - elif type(sym) is Constant: - if type(sym.value) is int: - sym.typ = topScope.getSymbol('int') - elif type(sym) is FunctionType: - if type(sym.returntype) is Designator: - sym.returntype = self.resolveDesignator(sym.returntype) - self.check(sym.returntype) + pass + elif type(sym) is ProcedureCall: + # Check arguments: + + # determine return type: + sym.typ = sym.proc.typ.returntype + elif type(sym) is VariableUse: + if sym.target: + sym.typ = sym.target.typ + else: + sym.typ = voidType + elif type(sym) is Literal: + if type(sym.val) is int: + sym.typ = intType + elif type(sym.val) is float: + sym.typ = doubleType + else: + self.diag.error('Unknown literal type', sym.loc) elif type(sym) is Binop: - self.check(sym.a) - self.check(sym.b) - if type(sym.a) is Constant and type(sym.b) is Constant: - # Possibly fold expression - pass + if sym.op in ['+', '-', '*', '/']: + if equalTypes(sym.a.typ, sym.b.typ): + sym.typ = sym.a.typ + else: + # assume void here? + sym.typ = voidType + self.diag.error('Types unequal', sym.loc) + elif sym.op in ['>', '<']: + if equalTypes(sym.a.typ, sym.b.typ): + sym.typ = boolType + else: + sym.typ = voidType + self.diag.error('Types unequal', sym.loc) + else: + sym.typ = voidType + print('unknown binop', sym.op) + else: + print('Unknown type check', sym)