Skip to content
Snippets Groups Projects
Commit e0251572 authored by Xun Yang's avatar Xun Yang
Browse files

ifNode and iffalse and boolean literals

parent 4c9bc8f3
No related branches found
No related tags found
No related merge requests found
......@@ -15,9 +15,17 @@ def p(instruction, arg1, arg2="", comment=""):
# (local label are just for local running of the code)
used_labels = set()
local_labels = 0
control_flow_label = 0
def getCFlowLabel():
global control_flow_label
control_flow_label += 1
return str(control_flow_label)
def pLabel(name, type, comment=""):
if type == "local":
global local_labels
global used_labels
if type == "local":
l = "_" + str(local_labels)
local_labels += 1
else:
......@@ -70,6 +78,23 @@ def genMethodInvoke(method):
return (pro, epi)
# generates shorter code for constant value conditionals and comparison conditionals
# cond is either literalNode or ExprNode
def iffalse(cond, label):
result = ""
val = cond.getConstant()
if val != None:
if val == True:
result = "" # no jump if true
elif val == False:
result += p("jmp", label)
# else val == Int shouldn't happen here, since we already done typeCheck
else:
result = cond.getIfFalse(label)
return result
####################################################
......
......@@ -247,7 +247,7 @@ class AssignNode(ASTNode):
def codeGen(self):
self.right.codeGen()
self.code = self.right.code
if self.left.__class__.__name__ == "NameNode":
if self.left.prefixLink.__class__.__name__ == "VarDclNode":
# move init result to var location
......@@ -431,6 +431,9 @@ class ExprNode(ASTNode):
raise Exception("ERROR: Incompatible types. Left of {} type can't be used with right of {} type on operation {}".format(self.left.myType.name, self.right.myType.name, self.op))
def codeGen(self):
if hasattr(self, "code") and self.code != "":
return
self.code = ""
# Unary:
......@@ -438,17 +441,7 @@ class ExprNode(ASTNode):
self.code = ""
return
# get left output
if not hasattr(self.left, "code"):
self.left.codeGen()
self.code += self.left.code
self.code += p("push", "eax") # left result onto stack
# get right output
if not hasattr(self.right, "code"):
self.right.codeGen()
self.code += self.right.code
self.code += p("pop", "ebx") # left output into ebx
self.code += self.codeGenLeftRight()
# now:
# ebx = left result
......@@ -464,6 +457,46 @@ class ExprNode(ASTNode):
self.code += p(ops[self.op], "ebx", "eax", " " + ops[self.op] + " left and right")
self.code += p("mov", "eax", "ebx", " move result to eax")
# generate shorter code if self.op = comparison
def getIfFalse(self, label):
if self.op not in ['==', '!=', '<=', '>=', '>', '<']:
self.codeGen()
return self.code
else:
result = self.codeGenLeftRight()
result += p("cmp", "ebx", "eax", "left " + self.op + " right")
if self.op == '==':
result += p("jne", label) # jump if false (not equal)
elif self.op == '!=':
result += p("je", label) # jump if false (equal)
elif self.op == '>':
result += p("jle", label) # jump if false (le)
elif self.op == '<':
result += p("jge", label) # jump if false (ge)
elif self.op == '>=':
result += p("jl", label) # jump if false (lt)
elif self.op == '<=':
result += p("jg", label) # jump if false (gt)
return result
# helper for codeGen for getting code from left and right
def codeGenLeftRight(self):
result = ""
# get left output
if not hasattr(self.left, "code"):
self.left.codeGen()
result += self.left.code
result += p("push", "eax") # left result onto stack
# get right output
if not hasattr(self.right, "code"):
self.right.codeGen()
result += self.right.code
result += p("pop", "ebx") # left output into ebx
return result
# returns True, False, Int or None (for non-constant expr)
# children of exprNode is either exprNode or literalNode
def getConstant(self):
......
......@@ -2,7 +2,7 @@ from AST import ASTNode, getParseTreeNodes, getASTNode
from Environment import Env
from ExprPrimaryNodes import makeNodeFromExpr, makeNodeFromAllPrimary, MethodInvNode, ClassCreateNode
from TheTypeNode import TypeNode, TypeStruct
from CodeGenUtils import p
from CodeGenUtils import p, getCFlowLabel, iffalse
# Contains:
# block
......@@ -231,6 +231,38 @@ class IfNode(ASTNode):
# no need to check reachability for empty elseBody, since in[elseBody] = in[L]
self.outMaybe = self.ifBody.outMaybe
def codeGen(self):
if hasattr(self, "code") and self.code != "":
return
n = getCFlowLabel()
elseLabel = "_else" + n
endLabel = "_end" + n
self.code = "; start of if clause" + n + "\n"
if self.elseBody:
self.code += iffalse(self.ifConditional, elseLabel)
else:
self.code += iffalse(self.ifConditional, endLabel)
self.code += "; start of ifBody code for if clause" + n + "\n"
self.ifBody.codeGen()
self.code += self.ifBody.code
if self.elseBody:
self.code += "; start of elseBody code for if clause" + n + "\n"
self.code += p("jmp", endLabel)
self.code += elseLabel + ":\n"
self.elseBody.codeGen()
self.code += self.elseBody.code
self.code += endLabel + ":\n"
self.code += "; end of if clause" + n + "\n"
# whileStatement, whileStatementNoShortIf
# Rules:
......
public class J1_01_ifelse {
public J1_01_ifelse() {}
public static int test() {
return J1_01_ifelse.test2();
}
public static int test2(){
int i = 2;
if (1 == 2)
i = 4;
if (i >= 1+1) {
i = 6;
} else {
i = 8;
}
return i;
}
}
......@@ -47,6 +47,11 @@ class LiteralNode(ASTNode):
# int
if self.name == 'int':
self.code += p("mov", "eax", str(self.getConstant()), " set to literal int")
if self.name == 'boolean':
if self.getConstant:
self.code = p("mov", "eax", "1", " set to literal true")
else:
self.code = p("mov", "eax", "0", " set to literal false")
def getConstant(self):
if self.name == 'int':
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment