summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenedikt Böhm <bb@xnull.de>2009-07-04 10:44:47 +0200
committerBenedikt Böhm <bb@xnull.de>2009-07-04 10:44:47 +0200
commit8d432ae653581815d16febf2af776a1a057660f7 (patch)
tree97e08265155d1ca2d9dcfa211e9fc7e13f0c48dd
parentd06b1dfc51a263a12c00e00c81461b67fa11afe8 (diff)
downloadswppy-8d432ae653581815d16febf2af776a1a057660f7.tar.gz
swppy-8d432ae653581815d16febf2af776a1a057660f7.tar.xz
swppy-8d432ae653581815d16febf2af776a1a057660f7.zip
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)
-rw-r--r--src/front/ast.py67
-rw-r--r--src/front/parser.py5
-rw-r--r--src/front/scope.py31
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 "<Function: %s(%s) at line %d: %s>" % (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 "<Sequence at line %d: %s, %s>" % (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 "<IfStatement at line %d>" % 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 "<ReturnStatement at line %d>" % 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 "<FunctionCall for %s at line %d>" % (self.ident, self.lineno)
+ return "<FunctionCall for %s(%s) at line %d>" % (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 "<Scope: %s>" % str(self.__functions)