view python/ppci/frontends/ks/nodes.py @ 110:9e552d34bd60

Work on compiler
author Windel Bouwman
date Fri, 04 Jan 2013 15:25:58 +0100
parents 1544e7a4aa98
children
line wrap: on
line source

"""
AST nodes for the K# 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 Symbol(Node):
   pass

class Id(Node):
   def __init__(self, name):
      self.name = name
   def __repr__(self):
      return 'ID {0}'.format(self.name)

# Selectors:
class Field(Node):
   def __init__(self, fieldname):
      self.fieldname = fieldname
   def __repr__(self):
      return 'FIELD {0}'.format(self.fieldname)

class Index(Node):
   def __init__(self, index, typ):
      self.index = index
      self.typ = typ
   def __repr__(self):
      return 'INDEX {0}'.format(self.index)

class Deref(Node):
   pass

class Designator(Node):
   def __init__(self, obj, selectors, typ):
      self.obj = obj
      self.selectors = selectors
      self.typ = typ
   def __repr__(self):
      return 'DESIGNATOR {0}, selectors {1}, type {2}'.format(self.obj, self.selectors, self.typ)

"""
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 ArrayType:
         return (a.dimension == b.dimension) and isType(a.elementType, b.elementType)
      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:
   def isType(self, b):
      return isType(self, b)

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

class NilType(Node):
   # TODO: how to handle nil values??
   def __repr__(self):
      return 'NILTYPE'

class ArrayType(Type):
  def __init__(self, dimension, elementType):
    self.dimension = dimension
    self.elementType = elementType
    self.size = elementType.size * dimension
  def __repr__(self):
    return '[ARRAY {0} of {1}]'.format(self.dimension, self.elementType)

class RecordType(Type):
   def __init__(self, fields):
      self.fields = fields
      self.size = 0
      for fieldname in self.fields:
         self.size += self.fields[fieldname].size
   def __repr__(self):
      return '[RECORD {0}]'.format(self.fields)

class PointerType(Type):
   def __init__(self, pointedType):
      self.pointedType = pointedType
      self.size = 8
   def __repr__(self):
      return '[POINTER {0}]'.format(self.pointedType)

class ProcedureType(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)

# Classes for constants like numbers and strings:
class StringConstant(Symbol):
  def __init__(self, txt):
    self.txt = txt
    self.typ = 'string'
  def __repr__(self):
    return "STRING '{0}'".format(self.txt)

# Variables, parameters, local variables, constants:
class Constant(Symbol):
   def __init__(self, value, typ, name=None, public=False):
      self.name = name
      self.value = value
      self.typ = typ
      self.public = public
   def __repr__(self):
      return 'CONSTANT {0} = {1}'.format(self.name, self.value)

class Variable(Symbol):
   def __init__(self, name, typ, public):
      self.name = name
      self.typ = typ
      self.public = public
      self.isLocal = False
      self.isReadOnly = False
      self.isParameter = False
   def __repr__(self):
      txt = '[public] ' if self.public else ''
      return '{2}VAR {0} : {1}'.format(self.name, self.typ, txt)

class Parameter(Node):
   """ A parameter has a passing method, name and typ """
   def __init__(self, kind, name, typ):
      self.kind = kind
      self.name = name
      self.typ = typ
   def __repr__(self):
      return 'PARAM {0} {1} {2}'.format(self.kind, self.name, self.typ)

# Operations:
class Unop(Node):
   def __init__(self, a, op, typ):
      self.a = a
      self.op = op # Operation: '+', '-', '*', '/', 'mod'
      self.typ = typ
      self.place = None
   def __repr__(self):
      return 'UNOP {0}'.format(self.op)

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

class Relop(Node):
   def __init__(self, a, relop, b, typ):
      self.a = a
      self.relop = relop
      self.b = b
      self.typ = typ
   def __repr__(self):
      return 'RELOP {0}'.format(self.relop)

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

# Imports and Exports:
class ImportedSymbol(Node):
   def __init__(self, modname, name):
      self.modname = modname
      self.name  = name
   def __repr__(self):
      return 'IMPORTED SYMBOL {0}'.format(self.name)

class ExportedSymbol(Node):
   def __init__(self, name, typ):
      self.name  = name
      self.typ = typ
   def __repr__(self):
      return 'EXPORTED PROCEDURE {0} : {1}'.format(self.name, self.typ)

# Procedure types
class BuiltinProcedure(Node):
   def __init__(self, name, typ):
      self.name  = name
      self.typ = typ
   def __repr__(self):
      return 'BUILTIN PROCEDURE {0} : {1}'.format(self.name, self.typ)

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

# Statements
class StatementSequence(Node):
   def __init__(self, statements):
      self.statements = statements
   def __repr__(self):
      return 'STATEMENTSEQUENCE'

class EmptyStatement(Node):
   def __repr__(self):
      return 'EMPTY 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
    self.typ = proc.typ.returntype
  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 CaseStatement(Node):
   def __init__(self, condition):
      self.condition = condition
   def __repr__(self):
     return 'CASE-statement'

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

class ForStatement(Node):
   def __init__(self, variable, begin, end, increment, statements):
      self.variable = variable
      self.begin = begin
      self.end = end
      self.increment = increment
      self.statements = statements
   def __repr__(self):
      return 'FOR-statement'

class AsmCode(Node):
   def __init__(self, asmcode):
      self.asmcode = asmcode
   def __repr__(self):
      return 'ASM CODE'