Mercurial > lcfOS
view python/ks/nodes.py @ 149:74241ca312cc
Fixes on parser and semantics
author | Windel Bouwman |
---|---|
date | Fri, 01 Mar 2013 11:43:52 +0100 |
parents | 91af0e40f868 |
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'