URL
https://opencores.org/ocsvn/tcp_socket/tcp_socket/trunk
Subversion Repositories tcp_socket
[/] [tcp_socket/] [trunk/] [chips2/] [chips/] [compiler/] [parse_tree.py] - Rev 3
Go to most recent revision | Compare with Previous | Blame | View Log
__author__ = "Jon Dawson" __copyright__ = "Copyright (C) 2012, Jonathan P Dawson" __version__ = "0.1" class NotConstant(Exception): pass def value(expression): """If an expression can be evaluated at compile time, return the value""" if hasattr(expression, "value"): return truncate(expression.value()) else: raise NotConstant def constant_fold(expression): """Replace an expression with a constant if possible""" try: return Constant(value(expression)) except NotConstant: return expression def truncate(number): """Truncate arithmetic results to the target number of bits""" #sign = number & 0x10000 #number = number & 0xffff #if sign: #number = ~0xffff | number return int(number) class Process: def generate(self): instructions = [] for function in self.functions: if hasattr(function, "declarations"): instructions.extend(function.generate()) instructions.append({"op" :"jmp_and_link", "dest" :self.main.return_address, "label":"function_%s"%id(self.main)}) instructions.append({"op":"stop"}) for function in self.functions: if not hasattr(function, "declarations"): instructions.extend(function.generate()) return instructions class Function: def generate(self): instructions = [] instructions.append({"op":"label", "label":"function_%s"%id(self)}) instructions.extend(self.statement.generate()) if not hasattr(self, "return_value"): instructions.append({"op":"jmp_to_reg", "src":self.return_address}) return instructions class Break: def generate(self): return [{"op":"goto", "label":"break_%s"%id(self.loop)}] class Continue: def generate(self): return [{"op":"goto", "label":"continue_%s"%id(self.loop)}] class Assert: def generate(self): result = self.allocator.new(self.expression.size) instructions = self.expression.generate(result) self.allocator.free(result) instructions.append({"op":"assert", "src":result, "line":self.line, "file":self.filename}) return instructions class Return: def generate(self): if hasattr(self, "expression"): instructions = self.expression.generate(self.function.return_value) else: instructions = [] instructions.append({"op":"jmp_to_reg", "src":self.function.return_address}) return instructions class Report: def generate(self): result = self.allocator.new(self.expression.size) instructions = self.expression.generate(result) self.allocator.free(result) instructions.append({"op":"report", "src":result, "line":self.line, "file":self.filename, "signed":self.expression.signed}) return instructions class WaitClocks: def generate(self): result = self.allocator.new(self.expression.size) instructions = self.expression.generate(result) self.allocator.free(result) instructions.append({"op":"wait_clocks", "src":result}) return instructions class If: def generate(self): try: if value(self.expression): return self.true_statement.generate() else: if self.false_statement: return self.false_statement.generate() else: return [] except NotConstant: result = self.allocator.new(self.expression.size) instructions = [] instructions.extend(self.expression.generate(result)) instructions.append({"op" :"jmp_if_false", "src" :result, "label":"else_%s"%id(self)}) self.allocator.free(result) instructions.extend(self.true_statement.generate()) instructions.append({"op":"goto", "label":"end_%s"%id(self)}) instructions.append({"op":"label", "label":"else_%s"%id(self)}) if self.false_statement: instructions.extend(self.false_statement.generate()) instructions.append({"op":"label", "label":"end_%s"%id(self)}) return instructions class Switch: def generate(self): result = self.allocator.new(self.expression.size) test = self.allocator.new(self.expression.size) instructions = self.expression.generate(result) for value, case in self.cases.iteritems(): instructions.append({"op":"==", "dest":test, "src":result, "right":value, "signed":True}) instructions.append({"op":"jmp_if_true", "src":test, "label":"case_%s"%id(case)}) if hasattr(self, "default"): instructions.append({"op":"goto", "label":"case_%s"%id(self.default)}) self.allocator.free(result) self.allocator.free(test) instructions.extend(self.statement.generate()) instructions.append({"op":"label", "label":"break_%s"%id(self)}) return instructions class Case: def generate(self): return [{"op":"label", "label":"case_%s"%id(self)}] class Default: def generate(self): return [{"op":"label", "label":"case_%s"%id(self)}] class Loop: def generate(self): instructions = [{"op":"label", "label":"begin_%s"%id(self)}] instructions.append({"op":"label", "label":"continue_%s"%id(self)}) instructions.extend(self.statement.generate()) instructions.append({"op":"goto", "label":"begin_%s"%id(self)}) instructions.append({"op":"label", "label":"break_%s"%id(self)}) return instructions class For: def generate(self): instructions = [] if hasattr(self, "statement1"): instructions.extend(self.statement1.generate()) instructions.append({"op":"label", "label":"begin_%s"%id(self)}) if hasattr(self, "expression"): result = self.allocator.new(self.expression.size) instructions.extend(self.expression.generate(result)) instructions.append({"op":"jmp_if_false", "src":result, "label":"end_%s"%id(self)}) self.allocator.free(result) instructions.extend(self.statement3.generate()) instructions.append({"op":"label", "label":"continue_%s"%id(self)}) if hasattr(self, "statement2"): instructions.extend(self.statement2.generate()) instructions.append({"op":"goto", "label":"begin_%s"%id(self)}) instructions.append({"op":"label", "label":"end_%s"%id(self)}) instructions.append({"op":"label", "label":"break_%s"%id(self)}) return instructions class Block: def generate(self): instructions = [] for statement in self.statements: instructions.extend(statement.generate()) return instructions class CompoundDeclaration: def __init__(self, declarations): self.declarations = declarations def generate(self): instructions = [] for declaration in self.declarations: instructions.extend(declaration.generate()); return instructions class VariableDeclaration: def __init__(self, allocator, initializer, name, type_, size, signed): self.initializer = initializer self.allocator = allocator self.type_ = type_ self.size = size self.signed = signed self.name = name def instance(self): register = self.allocator.new(self.size, "variable "+self.name) return VariableInstance(register, self.initializer, self.type_, self.size, self.signed) class VariableInstance: def __init__(self, register, initializer, type_, size, signed): self.register = register self.type_ = type_ self.initializer = initializer self.size = size self.signed = signed def generate(self): return self.initializer.generate(self.register) class ArrayDeclaration: def __init__(self, allocator, size, type_, element_type, element_size, element_signed, initializer = None, initialize_memory = False): self.allocator = allocator self.type_ = type_ self.size = size self.signed = False self.element_type = element_type self.element_size = element_size self.element_signed = element_signed self.initializer = initializer self.initialize_memory = initialize_memory def instance(self): location = self.allocator.new_array(self.size, self.initializer, self.element_size) register = self.allocator.new(2, "array") return ArrayInstance(location, register, self.size, self.type_, self.initializer, self.initialize_memory, self.element_type, self.element_size, self.element_signed) class ArrayInstance: def __init__(self, location, register, size, type_, initializer, initialize_memory, element_type, element_size, element_signed): self.register = register self.location = location self.type_ = type_ self.size = size self.signed = False self.element_type = element_type self.element_size = element_size self.element_signed = element_signed self.initializer = initializer self.initialize_memory = initialize_memory def generate(self, result=None): instructions = [] #If initialize memory is true, the memory content will initialised (as at configuration time) #If initialize memory is false, then the memory will need to be filled by the program. if not self.initialize_memory and self.initializer is not None: location = 0 for value in self.initializer: instructions.append({ "op":"memory_write_literal", "address":location, "value":value, "element_size":self.element_size }) location += 1 instructions.append({ "op":"literal", "literal":self.location, "dest":self.register }) #this bit here is to make string literals work, #in this case an array instance is created implicitly, #but the value of the expression is the array register. if result is not None and result != self.register: instructions.append({ "op" :"move", "dest":result, "src" :self.register }) return instructions class StructDeclaration: def __init__(self, members): self.members = members def instance(self): instances = {} for name, declaration in self.members.iteritems(): instances[name] = declaration.instance() return StructInstance(instances) class StructInstance: def __init__(self, members): self.members = members self.type_ = "struct" def generate(self): instructions = [] for member in self.members.values(): instructions.extend(member.generate()) return instructions class Argument: def __init__(self, name, type_, size, signed, parser, element_type, element_size, element_signed): self.type_=type_ self.size=size self.signed=signed self.element_type = element_type self.element_size = element_size self.element_signed = element_signed parser.scope[name] = self self.register = parser.allocator.new(size, "function argument "+name) def generate(self): return [] class DiscardExpression: def __init__(self, expression, allocator): self.expression = expression self.allocator = allocator def generate(self): result = self.allocator.new(self.expression.size) instructions = self.expression.generate(result) self.allocator.free(result) return instructions #...then Expressions... #Expressions generate methods accept a result argument. #This indicates which register to put the result in. #Expressions may also provide a value method which returns the value of an xpression #if it can be calculated at compile time. def AND(left, right): return ANDOR(left, right, "jmp_if_false") def OR(left, right): return ANDOR(left, right, "jmp_if_true") class ANDOR: def __init__(self, left, right, op): self.left = constant_fold(left) self.right = constant_fold(right) self.op = op self.type_ = "int" self.size = left.size self.signed = left.signed def generate(self, result): instructions = self.left.generate(result) instructions.append({"op":self.op, "src":result, "label":"end_%s"%id(self)}) instructions.extend(self.right.generate(result)) instructions.append({"op":"label", "label":"end_%s"%id(self)}) return instructions def value(self): if self.op == "jmp_if_false": return value(self.left) and value(self.right) else: return value(self.left) or value(self.right) class Binary: def __init__(self, operator, left, right, allocator): self.left = constant_fold(left) self.right = constant_fold(right) self.operator = operator self.allocator = allocator self.type_ = self.left.type_ self.size = max(left.size, right.size) self.signed = left.signed and right.signed def generate(self, result): new_register = self.allocator.new(self.size) try: instructions = self.right.generate(new_register) instructions.append({"op" :self.operator, "dest":result, "left":value(self.left), "src":new_register, "signed":self.signed}) except NotConstant: try: instructions = self.left.generate(new_register) instructions.append({"op" :self.operator, "dest" :result, "src" :new_register, "right":value(self.right), "signed" :self.signed}) except NotConstant: instructions = self.left.generate(new_register) right = self.allocator.new(self.right.size) instructions.extend(self.right.generate(right)) instructions.append({"op" :self.operator, "dest":result, "src" :new_register, "srcb":right, "signed":self.signed}) self.allocator.free(right) self.allocator.free(new_register) return instructions def value(self): return eval("%s %s %s"%(value(self.left), self.operator, value(self.right))) def SizeOf(expression): return Constant(expression.size) class Unary: def __init__(self, operator, expression, allocator): self.expression = constant_fold(expression) self.operator = operator self.type_ = self.expression.type_ self.size = expression.size self.signed = expression.signed self.allocator = allocator def generate(self, result): new_register = self.allocator.new(self.size) instructions = self.expression.generate(new_register) instructions.extend([{"op":self.operator, "dest":result, "src":new_register}]) self.allocator.free(new_register) return instructions def value(self): return eval("%s%s"%(self.operator, value(self.expression))) class FunctionCall: def generate(self, result): instructions = [] for expression, argument in zip(self.arguments, self.function.arguments): instructions.extend(expression.generate(argument.register)) instructions.append({"op" :"jmp_and_link", "dest" :self.function.return_address, "label":"function_%s"%id(self.function)}) if hasattr(self.function, "return_value"): instructions.append({"op" :"move", "dest" :result, "src" :self.function.return_value}) return instructions class Output: def __init__(self, name, expression): self.name = name self.expression = expression self.type_ = "int" self.size = expression.size def generate(self, result): instructions = self.expression.generate(result); instructions.append({"op" :"write", "src" :result, "output":self.name}) return instructions class FileWrite: def __init__(self, name, expression): self.name = name self.expression = expression self.type_ = "int" self.size = expression.size def generate(self, result): instructions = self.expression.generate(result); instructions.append({"op" :"file_write", "src" :result, "file_name":self.name}) return instructions class Input: def __init__(self, name): self.name = name self.type_ = "int" self.size = 2 self.signed = True def generate(self, result): return [{"op" :"read", "dest" :result, "input":self.name}] class FileRead: def __init__(self, name): self.name = name self.type_ = "int" self.size = 2 self.signed = True def generate(self, result): return [{"op" :"file_read", "dest" :result, "file_name":self.name}] class Ready: def __init__(self, name): self.name = name self.type_ = "int" self.size = 2 self.signed = True def generate(self, result): return [{"op" :"ready", "dest" :result, "input":self.name}] class Array: def __init__(self, declaration, allocator): self.declaration = declaration self.allocator = allocator self.storage = "register" self.type_ = self.declaration.type_ self.size = int(self.declaration.size) * 2 self.signed = False def generate(self, result): instructions = [] if result != self.declaration.register: instructions.append({"op" :"move", "dest":result, "src" :self.declaration.register}) return instructions class ArrayIndex: def __init__(self, declaration, index_expression, allocator): self.declaration = declaration self.allocator = allocator self.index_expression = index_expression self.storage = "memory" self.type_ = self.declaration.element_type self.size = self.declaration.element_size self.signed = self.declaration.element_signed def generate(self, result): instructions = [] offset = self.allocator.new(2) address = self.allocator.new(2) instructions.extend(self.index_expression.generate(offset)) instructions.append({"op" :"+", "dest" :address, "src" :offset, "srcb" :self.declaration.register, "signed":False}) instructions.append({"op" :"memory_read_request", "src" :address, "sequence": id(self), "element_size":self.size}) instructions.append({"op" :"memory_read_wait", "src" :address, "sequence": id(self), "element_size":self.size}) instructions.append({"op" :"memory_read", "src" :address, "dest" :result, "sequence": id(self), "element_size":self.size}) self.allocator.free(address) self.allocator.free(offset) return instructions class Variable: def __init__(self, declaration, allocator): self.declaration = declaration self.allocator = allocator self.storage = "register" self.type_ = self.declaration.type_ self.size = self.declaration.size self.signed = self.declaration.signed def generate(self, result): instructions = [] if result != self.declaration.register: instructions.append({"op" :"move", "dest":result, "src" :self.declaration.register}) return instructions class PostIncrement: def __init__(self, operator, lvalue, allocator): self.operator = operator self.lvalue = lvalue self.allocator = allocator self.type_ = self.lvalue.declaration.type_ self.size = self.lvalue.declaration.size self.signed = self.lvalue.declaration.signed def generate(self, result): instructions = [] instructions.append({"op" :"move", "src" :self.lvalue.declaration.register, "dest" :result}) instructions.append({"op" :self.operator, "dest" :self.lvalue.declaration.register, "right" :1, "src" :self.lvalue.declaration.register, "signed":self.signed}) return instructions class Assignment: def __init__(self, lvalue, expression, allocator): self.lvalue = lvalue self.expression = expression self.allocator = allocator self.type_ = self.lvalue.type_ self.size = self.lvalue.size self.signed = self.lvalue.signed def generate(self, result): instructions = self.expression.generate(result) if self.lvalue.storage == "register": if result != self.lvalue.declaration.register: instructions.append({"op" : "move", "dest" : self.lvalue.declaration.register, "src" : result}) elif self.lvalue.storage == "memory": index = self.allocator.new(2) address = self.allocator.new(2) instructions.extend(self.lvalue.index_expression.generate(index)) instructions.append({"op" :"+", "dest" :address, "src" :index, "srcb" :self.lvalue.declaration.register, "signed" :self.signed}) instructions.append({"op" :"memory_write", "src" :address, "srcb" :result, "element_size" :self.lvalue.declaration.element_size}) self.allocator.free(index) self.allocator.free(address) return instructions class Constant: def __init__(self, value, size=2, signed=True): self._value = value self.type_ = "int" self.size = size self.signed = signed def generate(self, result): instructions = [{"op":"literal", "dest":result, "literal":self._value}] return instructions def value(self): return self._value
Go to most recent revision | Compare with Previous | Blame | View Log