/** * This method runs through the expression in order to generate the corresponding assembly code. * At the end of the run, the result is always stored in Register.RAX */ public StringBuffer handleExpression(Expression e, Context context) throws Exception { StringBuffer sb = new StringBuffer(); String lastReg; if (Parser.DEBUG) System.out.println("\nHandling expression: \"" + this.toString() + "\""); if (this.right == null) { // Handle leaf if (this instanceof Variable) { if (Parser.DEBUG) System.out.println("\tVariable caught: " + ((Variable) this).getValue()); sb = ExpressionHelper.handleVariable(sb, (Variable) this, Register.RAX, context); } else if (this instanceof FunctionCall) { if (Parser.DEBUG) System.out.println("\tFunction-call caught: " + ((FunctionCall) this).getTag()); sb = ExpressionHelper.handleFunctionCall(sb, (FunctionCall) this, context); } return sb; } sb.append(this.left.handleExpression(e, context)); if (this.flag != null && this.flag.equals(Flag.UMINUS)) sb.append(ExpressionHelper.asm(Assembly.NEG, Register.RAX)); if (this.right.op != null && this.right.priority == false) { // Handle expression with three or more operands if (this.right.left.priority) { // Handle priority expression first (parentheses). this.right.left.priority = false; sb.append(context.virtualPush(Register.RAX.toString())); sb.append(this.right.left.handleExpression(e, context)); sb.append(context.virtualPop(Register.RDX.toString())); sb = ExpressionHelper.handleOperation(sb, this.op, Register.RAX, Register.RDX); sb.append(context.virtualPush(Register.RAX.toString())); sb.append(this.right.right.handleExpression(e, context)); sb.append(context.virtualPop(Register.RDX.toString())); sb = ExpressionHelper.handleOperation(sb, this.right.op, Register.RAX, Register.RDX); } else if (ExpressionHelper.getPrecedence(this.op.toString()) > ExpressionHelper.getPrecedence(this.right.op.toString())) { // Handle operators of higher precedence first. if (this.right.left instanceof Variable) sb = ExpressionHelper.handleVariable( sb, (Variable) this.right.left, Register.RDX, context); else { sb.append(ExpressionHelper.asm(Assembly.MOV, Register.RAX, Register.RDX)); sb = ExpressionHelper.handleFunctionCall(sb, (FunctionCall) this.right.left, context); } sb = ExpressionHelper.handleOperation(sb, this.op, Register.RDX, Register.RAX); sb.append(context.virtualPush(Register.RAX.toString())); sb.append(this.right.right.handleExpression(e, context)); sb.append(context.virtualPop(Register.RDX.toString())); sb = ExpressionHelper.handleOperation(sb, this.right.op, Register.RAX, Register.RDX); } else { sb.append(context.virtualPush(Register.RAX.toString())); sb.append(this.right.handleExpression(e, context)); sb.append(ExpressionHelper.asm(Assembly.MOV, Register.RAX, Register.RDX)); sb.append(context.virtualPop(Register.RAX.toString())); sb = ExpressionHelper.handleOperation(sb, this.op, Register.RAX, Register.RDX); } } else { // Handle simple node (l op r) if (this.right.priority) { sb.append(context.virtualPush(Register.RAX.toString())); sb.append(this.right.handleExpression(e, context)); sb.append(context.virtualPop(Register.RDX.toString())); sb = ExpressionHelper.handleOperation(sb, this.op, Register.RAX, Register.RDX); } else if (this.right instanceof Variable) { if (((Variable) this.right).getValue() instanceof Integer) { if (this.right.flag != null && this.right.flag.equals(Flag.UMINUS)) sb = ExpressionHelper.handleOperation( sb, this.op, "$-" + ((Variable) this.right).getValue()); else sb = ExpressionHelper.handleOperation( sb, this.op, "$" + ((Variable) this.right).getValue()); } else { if (((Variable) this.right).index != null) sb.append(context.virtualPush(Register.RAX.toString())); sb = ExpressionHelper.handleVariable(sb, (Variable) this.right, Register.RDX, context); if (((Variable) this.right).index != null) { sb.append(ExpressionHelper.asm(Assembly.MOV, Register.RAX, Register.RDX)); sb.append(context.virtualPop(Register.RAX.toString())); } sb = ExpressionHelper.handleOperation(sb, this.op, Register.RDX, Register.RAX); } } else if (this.right instanceof FunctionCall) { sb.append(context.virtualPush(Register.RAX.toString())); sb = ExpressionHelper.handleFunctionCall(sb, (FunctionCall) this.right, context); sb.append(context.virtualPop(Register.RDX.toString())); sb = ExpressionHelper.handleOperation(sb, this.op, Register.RAX, Register.RDX); sb.append(ExpressionHelper.asm(Assembly.MOV, Register.RAX, Register.RDX)); } } return sb; }