view python/c3/astnodes.py @ 150:4ae0e02599de

Added type check start and analyze phase
author Windel Bouwman
date Fri, 01 Mar 2013 16:53:22 +0100
parents 74241ca312cc
children b28a11c01dbe
line wrap: on
line source

"""
AST nodes for the c3 language.
"""

class Node:
   location = None
   def getChildren(self):
      children = []
      members = dir(self)
      for member in members:
         member = getattr(self, member)
         if isinstance(member, Node):
            children.append(member)
         elif type(member) is list:
            for mi in member:
               if isinstance(mi, Node):
                  children.append(mi)
      return children

class Designator(Node):
   def __init__(self, tname):
      self.tname = tname
   def __repr__(self):
      return 'DESIGNATOR {0}'.format(self.tname)

"""
Type classes
"""
def isType(a, b):
   """ Compare types a and b and check if they are equal """
   if type(a) is type(b):
      if type(a) is BaseType:
         return (a.name == b.name) and (a.size == b.size)
      elif type(a) is ProcedureType:
         if len(a.parameters) != len(b.parameters):
            print('Number of parameters does not match')
            return False
         for aparam, bparam in zip(a.parameters, b.parameters):
            if not isType(aparam.typ, bparam.typ):
               print('Parameter {0} does not match parameter {1}'.format(aparam, bparam))
               return False
         if a.result is None:
            # TODO: how to handle a None return type??
            pass
         if not isType(a.result, b.result):
            print('Procedure return value mismatch {0} != {1}'.format(a.result, b.result))
            return False
         return True
      else:
         print(a)
         print(b)
         Error('Not implemented {0}'.format(a))
   else:
      return False

class Type(Node):
   def isType(self, b):
      return isType(self, b)

class BaseType(Type):
  def __init__(self, name):
    self.name = name
  def __repr__(self):
    return '[TYPE {0}]'.format(self.name)

class FunctionType(Type):
   def __init__(self, parameters, returntype):
      self.parameters = parameters
      self.returntype = returntype
   def __repr__(self):
      return '[PROCTYPE {0} RET {1}]'.format(self.parameters, self.returntype)

class DefinedType(Type):
   def __init__(self, name, typ):
      self.name = name
      self.typ = typ
   def __repr__(self):
      return 'Named type {0} of type {1}'.format(self.name, self.typ)

# Variables, parameters, local variables, constants:
class Symbol(Node):
   pass

class Constant(Symbol):
   def __init__(self, value, name=None):
      self.name = name
      self.value = value
   def __repr__(self):
      return 'CONSTANT {0} = {1}'.format(self.name, self.value)

class Variable(Symbol):
   def __init__(self, name, typ):
      self.name = name
      self.typ = typ
      self.isLocal = False
      self.isReadOnly = False
      self.isParameter = False
   def __repr__(self):
      return 'VAR {0} : {1}'.format(self.name, self.typ)

# Procedure types
class Function(Symbol):
   """ Actual implementation of a function """
   def __init__(self, name, typ=None, block=None):
      self.name = name
      self.body = block
      self.typ = typ
   def __repr__(self):
      return 'PROCEDURE {0} {1}'.format(self.name, self.typ)

# Operations:
class Unop(Node):
   def __init__(self, a, op):
      self.a = a
      self.op = op 
   def __repr__(self):
      return 'UNOP {0}'.format(self.op)

class Binop(Node):
   def __init__(self, a, op, b):
      self.a = a
      self.b = b
      self.op = op # Operation: '+', '-', '*', '/', 'mod'
   def __repr__(self):
      return 'BINOP {0}'.format(self.op)

class VariableUse(Node):
   def __init__(self, target):
      self.target = target
   def __repr__(self):
      return 'VAR USE {0}'.format(self.target)

# Modules
class Package(Node):
   def __init__(self, name):
      self.name = name
   def __repr__(self):
      return 'PACKAGE {0}'.format(self.name)

# Statements
class CompoundStatement(Node):
   def __init__(self, statements):
      self.statements = statements
   def __repr__(self):
      return 'COMPOUND STATEMENT'

class ReturnStatement(Node):
   def __init__(self, expr):
      self.expr = expr
   def __repr__(self):
      return 'RETURN STATEMENT'

class Assignment(Node):
   def __init__(self, lval, rval):
      self.lval = lval
      self.rval = rval
   def __repr__(self):
      return 'ASSIGNMENT'

class ProcedureCall(Node):
  def __init__(self, proc, args):
    self.proc = proc
    self.args = args
  def __repr__(self):
    return 'CALL {0} '.format(self.proc)

class IfStatement(Node):
   def __init__(self, condition, truestatement, falsestatement=None):
      self.condition = condition
      self.truestatement = truestatement
      self.falsestatement = falsestatement
   def __repr__(self):
      return 'IF-statement'

class WhileStatement(Node):
   def __init__(self, condition, statements):
      self.condition = condition
      self.dostatements = statements
   def __repr__(self):
      return 'WHILE-statement'