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)