From 8d432ae653581815d16febf2af776a1a057660f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benedikt=20B=C3=B6hm?= Date: Sat, 4 Jul 2009 10:44:47 +0200 Subject: adapt parser for backend changes - emit a prologue/epilogue for functions - emit a "JMP main" instruction in the beginning - track the last function label across genrate calls - split scope in params and local variables (they have a different layout on the stack) --- src/front/ast.py | 67 +++++++++++++++++++++++++++++++++-------------------- src/front/parser.py | 5 ++-- src/front/scope.py | 31 +++++++++++++++++++------ 3 files changed, 69 insertions(+), 34 deletions(-) diff --git a/src/front/ast.py b/src/front/ast.py index b05f7fb..875bdf0 100644 --- a/src/front/ast.py +++ b/src/front/ast.py @@ -12,9 +12,6 @@ class Node(object): def emitlabel(self, i): TACList().add(Label("L%d" % i)) - def emitfunction(self, name): - TACList().add(FunctionLabel(name)) - def emit(self, op, arg1=None, arg2=None): self.debug("emit(): op = %s, arg = %s, arg2 = %s" % (op, arg1, arg2)) TACList().add(TAC(op, arg1, arg2)) @@ -31,6 +28,7 @@ class Program(Node): def generate(self): self.debug("Program.generate(): %s" % repr(self)) + self.emit(Op.JMP, "main") for function in self.functions: function.generate() @@ -44,15 +42,23 @@ class Function(Node): self.statement = statement self.lineno = lineno + def emit_prologue(self, name): + TACList().add(FunctionPrologue(name)) + + def emit_epilogue(self, name): + TACList().add(FunctionEpilogue(name)) + def generate(self): self.debug("Function.generate(): %s" % repr(self)) - self.emitfunction(self.name) + self.emit_prologue(self.name) + Register().set_function(self.name) begin = self.newlabel() after = self.newlabel() self.emitlabel(begin) - self.statement.generate(begin, after) + self.statement.generate(begin, after, after) + self.emit(Op.RETURN, 0, after) self.emitlabel(after) - self.emit(Op.RETURN, 0) + self.emit_epilogue(self.name) def __repr__(self): return "" % (self.name, str(self.params), self.lineno, str(self.statement)) @@ -69,17 +75,17 @@ class Sequence(Statement): self.s2 = s2 self.lineno = lineno - def generate(self, before, after): + def generate(self, before, after, last): self.debug("Sequence.generate(before = %d, after = %d): %s" % (before, after, repr(self))) if not self.s1: - self.s2.generate(before, after) + self.s2.generate(before, after, last) elif not self.s2: - self.s1.generate(before, after) + self.s1.generate(before, after, last) else: label = self.newlabel() - self.s1.generate(before, label) + self.s1.generate(before, label, last) self.emitlabel(label) - self.s2.generate(label, after) + self.s2.generate(label, after, last) def __repr__(self): return "" % (self.lineno, self.s1, self.s2) @@ -91,7 +97,7 @@ class IfStatement(Statement): self.false_statement = false_statement self.lineno = lineno - def generate(self, before, after): + def generate(self, before, after, last): self.debug("IfStatement.generate(before = %d, after = %d): %s" % (before, after, repr(self))) x = self.expression.reduce() @@ -101,15 +107,15 @@ class IfStatement(Statement): false_label = self.newlabel() self.emit(Op.BEZ, x, "L%d" % false_label) self.emitlabel(true_label) - self.true_statement.generate(true_label, after) + self.true_statement.generate(true_label, after, last) self.emit(Op.JMP, "L%d" % after) self.emitlabel(false_label) - self.false_statement.generate(false_label, after) + self.false_statement.generate(false_label, after, last) else: true_label = self.newlabel() self.emit(Op.BEZ, x, "L%d" % after) self.emitlabel(true_label) - self.true_statement.generate(true_label, after) + self.true_statement.generate(true_label, after, last) def __repr__(self): return "" % self.lineno @@ -120,12 +126,12 @@ class WhileStatement(Statement): self.statement = statement self.lineno = lineno - def generate(self, before, after): + def generate(self, before, after, last): self.debug("WhileStatement.generate(before = %d, after = %d): %s" % (before, after, repr(self))) self.emit(Op.BEZ, self.expression.reduce(), "L%d" % after) label = self.newlabel() self.emitlabel(label) - self.statement.generate(label, before) + self.statement.generate(label, before, last) self.emit(Op.JMP, "L%d" % before) def __repr__(self): @@ -136,9 +142,9 @@ class ReturnStatement(Statement): self.expression = expression self.lineno = lineno - def generate(self, before, after): + def generate(self, before, after, last): self.debug("ReturnStatement.generate(before = %d, after = %d): %s" % (before, after, repr(self))) - self.emit(Op.RETURN, self.expression.reduce()) + self.emit(Op.RETURN, self.expression.reduce(), last) def __repr__(self): return "" % self.lineno @@ -149,7 +155,7 @@ class AssignStatement(Statement): self.expression = expression self.lineno = lineno - def generate(self, before, after): + def generate(self, before, after, last): self.debug("AssignStatement.generate(before = %d, after = %d): %s" % (before, after, repr(self))) self.emit(Op.STORE, self.ident, self.expression.reduce()) @@ -162,22 +168,33 @@ class FunctionCall(Statement, Expression): self.arguments = arguments self.lineno = lineno + def push_params(self): + self.arguments.reverse() + for argument in self.arguments: + self.emit(Op.PUSH, argument.reduce()) + self.arguments.reverse() + + def pop_params(self): + for argument in self.arguments: + self.emit(Op.POP, 0) + + # XXX: wrong signature? def generate(self): self.debug("FunctionCall.generate(): %s" % (repr(self))) - for argument in self.arguments: - self.emit(Op.PARAM, argument.reduce()) + self.push_params() self.emit(Op.CALL, self.ident, 0) + self.pop_params() def reduce(self): self.debug("FunctionCall.reduce(): %s" % repr(self)) - for argument in self.arguments: - self.emit(Op.PARAM, argument.reduce()) + self.push_params() r = Register().new() self.emit(Op.CALL, self.ident, r) + self.pop_params() return r def __repr__(self): - return "" % (self.ident, self.lineno) + return "" % (self.ident, self.arguments, self.lineno) class Operation(Expression): def __init__(self, op, lineno = -1): diff --git a/src/front/parser.py b/src/front/parser.py index 53818bc..8eca7a2 100644 --- a/src/front/parser.py +++ b/src/front/parser.py @@ -144,7 +144,8 @@ class Parser: self.match(Tag.LBRAK) args = [] if self.token.tag == Tag.RBRAK else self.ident_list() self.match(Tag.RBRAK, Tag.NEWLINE) - self.scope.new(name, args) + self.scope.new(name) + self.scope.add_params(args) block = self.statement_list() self.match(Tag.END, Tag.NEWLINE) return Function(name, args, block, line) @@ -198,7 +199,7 @@ class Parser: self.match(Tag.ASSIGNMENT) exp = self.boolean() self.match(Tag.NEWLINE) - self.scope.add(name) + self.scope.add_locals(name) return AssignStatement(name, exp, line) # program = function_list. diff --git a/src/front/scope.py b/src/front/scope.py index 533497d..6559a26 100644 --- a/src/front/scope.py +++ b/src/front/scope.py @@ -6,22 +6,39 @@ class Scope(object): def __init__(self): self.__dict__ = self.__shared_state + def set_function(self, name): + self.__current_function = name + def new(self, name, symbols = []): if getattr(self.__functions, name, None): raise ScopeError("multiple definitions of %s" % name) - self.__functions[name] = [] - self.__current_function = name - self.add(symbols) + self.__functions[name] = ([], []) + self.set_function(name) - def add(self, symbols): + def add(self, symbols, i): if type(symbols) != type([]): symbols = [symbols] for symbol in symbols: - if symbol not in self.__functions[self.__current_function]: - self.__functions[self.__current_function].append(symbol) + if symbol not in self.__functions[self.__current_function][i]: + self.__functions[self.__current_function][i].append(symbol) + + def add_params(self, symbols): + self.add(symbols, 0) + + def add_locals(self, symbols): + self.add(symbols, 1) def contains(self, name): - return name in self.__functions[self.__current_function] + return name in reduce(lambda x,y: x+y, self.__functions[self.__current_function]) + + def get_variable_offset(self, name): + try: + return self.__functions[self.__current_function][0].index(name) + 2 + except: + return -self.__functions[self.__current_function][1].index(name) - 1 + + def get_variables(self): + return self.__functions[self.__current_function] def __str__(self): return "" % str(self.__functions) -- cgit v1.2.3