private List<ZInstruction> ConvertValueExpression(Expression expression, string currentPassage) { List<ZInstruction> instructions = new List<ZInstruction>(); IntValue intValue = expression as IntValue; BoolValue boolValue = expression as BoolValue; VariableValue variableValue = expression as VariableValue; FunctionValue functionValue = expression as FunctionValue; NormalOp operandValue = expression as NormalOp; if (intValue != null) { short value = Convert.ToInt16((short)intValue.Value); instructions.Add(new Push(value)); } else if (boolValue != null) { short value = boolValue.Value ? (short)1 : (short)0; instructions.Add(new Push(value)); } else if (variableValue != null) { instructions.Add(new Push(_symbolTable.GetSymbol(variableValue.Name))); } else if (functionValue != null) { instructions.AddRange(ConvertFunctionValue(functionValue, currentPassage)); } else if (operandValue != null) { short? leftAsShort = null; ZVariable leftAsVariable = null; bool leftIsSubExpression = false; short? rightAsShort = null; ZVariable rightAsVariable = null; bool rightIsSubExpression = false; if (operandValue.RightExpr is VariableValue) rightAsVariable = _symbolTable.GetSymbol(((VariableValue)(operandValue.RightExpr.BaseValue)).Name); else if (operandValue.RightExpr is IntValue) rightAsShort = Convert.ToInt16(((IntValue)(operandValue.RightExpr.BaseValue)).Value); else if (operandValue.RightExpr is BoolValue) rightAsShort = Convert.ToInt16(((BoolValue)(operandValue.RightExpr.BaseValue)).Value); else if (operandValue.RightExpr is FunctionValue) { instructions.AddRange(ConvertFunctionValue((FunctionValue)operandValue.RightExpr, currentPassage)); rightAsVariable = new ZStackVariable(); } else { rightIsSubExpression = true; instructions.AddRange(ConvertValueExpression(operandValue.RightExpr, currentPassage)); } if (operandValue.LeftExpr is VariableValue) leftAsVariable = _symbolTable.GetSymbol(((VariableValue)(operandValue.LeftExpr.BaseValue)).Name); else if (operandValue.LeftExpr is IntValue) leftAsShort = Convert.ToInt16(((IntValue)(operandValue.LeftExpr.BaseValue)).Value); else if (operandValue.LeftExpr is BoolValue) leftAsShort = Convert.ToInt16(((BoolValue)(operandValue.LeftExpr.BaseValue)).Value); else if (operandValue.LeftExpr is FunctionValue) { instructions.AddRange(ConvertFunctionValue((FunctionValue)operandValue.LeftExpr, currentPassage)); leftAsVariable = new ZStackVariable(); } else { leftIsSubExpression = true; instructions.AddRange(ConvertValueExpression(operandValue.LeftExpr, currentPassage)); } switch (operandValue.Type) { case NormalOp.NormalOpEnum.Add: if (leftAsShort != null && rightAsShort != null) instructions.Add(new Add(leftAsShort.Value, rightAsShort.Value, new ZStackVariable())); else if (leftAsShort != null && rightAsVariable != null) instructions.Add(new Add(leftAsShort.Value, rightAsVariable, new ZStackVariable())); else if (leftAsShort != null && rightIsSubExpression != null) instructions.Add(new Add(leftAsShort.Value, new ZStackVariable(), new ZStackVariable())); else if (leftAsVariable != null && rightAsShort != null) instructions.Add(new Add(leftAsVariable, rightAsShort.Value, new ZStackVariable())); else if (leftAsVariable != null && rightAsVariable != null) instructions.Add(new Add(leftAsVariable, rightAsVariable, new ZStackVariable())); else if (leftAsVariable != null && rightIsSubExpression != null) instructions.Add(new Add(leftAsVariable, new ZStackVariable(), new ZStackVariable())); else if (leftIsSubExpression && rightAsShort != null) instructions.Add(new Add(new ZStackVariable(), rightAsShort.Value, new ZStackVariable())); else if (leftIsSubExpression && rightAsVariable != null) instructions.Add(new Add(new ZStackVariable(), rightAsVariable, new ZStackVariable())); else if (leftIsSubExpression && rightIsSubExpression) instructions.Add(new Add(new ZStackVariable(), new ZStackVariable(), new ZStackVariable())); break; case NormalOp.NormalOpEnum.Sub: if (leftAsShort != null && rightAsShort != null) instructions.Add(new Sub(leftAsShort.Value, rightAsShort.Value, new ZStackVariable())); else if (leftAsShort != null && rightAsVariable != null) instructions.Add(new Sub(leftAsShort.Value, rightAsVariable, new ZStackVariable())); else if (leftAsShort != null && rightIsSubExpression != null) instructions.Add(new Sub(leftAsShort.Value, new ZStackVariable(), new ZStackVariable())); else if (leftAsVariable != null && rightAsShort != null) instructions.Add(new Sub(leftAsVariable, rightAsShort.Value, new ZStackVariable())); else if (leftAsVariable != null && rightAsVariable != null) instructions.Add(new Sub(leftAsVariable, rightAsVariable, new ZStackVariable())); else if (leftAsVariable != null && rightIsSubExpression != null) instructions.Add(new Sub(leftAsVariable, new ZStackVariable(), new ZStackVariable())); else if (leftIsSubExpression && rightAsShort != null) instructions.Add(new Sub(new ZStackVariable(), rightAsShort.Value, new ZStackVariable())); else if (leftIsSubExpression && rightAsVariable != null) instructions.Add(new Sub(new ZStackVariable(), rightAsVariable, new ZStackVariable())); else if (leftIsSubExpression && rightIsSubExpression) instructions.Add(new Sub(new ZStackVariable(), new ZStackVariable(), new ZStackVariable())); break; case NormalOp.NormalOpEnum.Mul: if (leftAsShort != null && rightAsShort != null) instructions.Add(new Mul(leftAsShort.Value, rightAsShort.Value, new ZStackVariable())); else if (leftAsShort != null && rightAsVariable != null) instructions.Add(new Mul(leftAsShort.Value, rightAsVariable, new ZStackVariable())); else if (leftAsShort != null && rightIsSubExpression != null) instructions.Add(new Mul(leftAsShort.Value, new ZStackVariable(), new ZStackVariable())); else if (leftAsVariable != null && rightAsShort != null) instructions.Add(new Mul(leftAsVariable, rightAsShort.Value, new ZStackVariable())); else if (leftAsVariable != null && rightAsVariable != null) instructions.Add(new Mul(leftAsVariable, rightAsVariable, new ZStackVariable())); else if (leftAsVariable != null && rightIsSubExpression != null) instructions.Add(new Mul(leftAsVariable, new ZStackVariable(), new ZStackVariable())); else if (leftIsSubExpression && rightAsShort != null) instructions.Add(new Mul(new ZStackVariable(), rightAsShort.Value, new ZStackVariable())); else if (leftIsSubExpression && rightAsVariable != null) instructions.Add(new Mul(new ZStackVariable(), rightAsVariable, new ZStackVariable())); else if (leftIsSubExpression && rightIsSubExpression) instructions.Add(new Mul(new ZStackVariable(), new ZStackVariable(), new ZStackVariable())); break; case NormalOp.NormalOpEnum.Div: if (leftAsShort != null && rightAsShort != null) instructions.Add(new Div(leftAsShort.Value, rightAsShort.Value, new ZStackVariable())); else if (leftAsShort != null && rightAsVariable != null) instructions.Add(new Div(leftAsShort.Value, rightAsVariable, new ZStackVariable())); else if (leftAsShort != null && rightIsSubExpression != null) instructions.Add(new Div(leftAsShort.Value, new ZStackVariable(), new ZStackVariable())); else if (leftAsVariable != null && rightAsShort != null) instructions.Add(new Div(leftAsVariable, rightAsShort.Value, new ZStackVariable())); else if (leftAsVariable != null && rightAsVariable != null) instructions.Add(new Div(leftAsVariable, rightAsVariable, new ZStackVariable())); else if (leftAsVariable != null && rightIsSubExpression != null) instructions.Add(new Div(leftAsVariable, new ZStackVariable(), new ZStackVariable())); else if (leftIsSubExpression && rightAsShort != null) instructions.Add(new Div(new ZStackVariable(), rightAsShort.Value, new ZStackVariable())); else if (leftIsSubExpression && rightAsVariable != null) instructions.Add(new Div(new ZStackVariable(), rightAsVariable, new ZStackVariable())); else if (leftIsSubExpression && rightIsSubExpression) instructions.Add(new Div(new ZStackVariable(), new ZStackVariable(), new ZStackVariable())); break; case NormalOp.NormalOpEnum.Mod: if (leftAsShort != null && rightAsShort != null) instructions.Add(new Mod(leftAsShort.Value, rightAsShort.Value, new ZStackVariable())); else if (leftAsShort != null && rightAsVariable != null) instructions.Add(new Mod(leftAsShort.Value, rightAsVariable, new ZStackVariable())); else if (leftAsShort != null && rightIsSubExpression != null) instructions.Add(new Mod(leftAsShort.Value, new ZStackVariable(), new ZStackVariable())); else if (leftAsVariable != null && rightAsShort != null) instructions.Add(new Mod(leftAsVariable, rightAsShort.Value, new ZStackVariable())); else if (leftAsVariable != null && rightAsVariable != null) instructions.Add(new Mod(leftAsVariable, rightAsVariable, new ZStackVariable())); else if (leftAsVariable != null && rightIsSubExpression != null) instructions.Add(new Mod(leftAsVariable, new ZStackVariable(), new ZStackVariable())); else if (leftIsSubExpression && rightAsShort != null) instructions.Add(new Mod(new ZStackVariable(), rightAsShort.Value, new ZStackVariable())); else if (leftIsSubExpression && rightAsVariable != null) instructions.Add(new Mod(new ZStackVariable(), rightAsVariable, new ZStackVariable())); else if (leftIsSubExpression && rightIsSubExpression) instructions.Add(new Mod(new ZStackVariable(), new ZStackVariable(), new ZStackVariable())); break; default: throw new Exception("Unknown operand: " + operandValue.Type.ToString()); } } else throw new NotImplementedException("The given expression " + expression.GetType().Name + " for assign is not implemented yet."); return instructions; }
private List<ZInstruction> ConvertBranchExpression(Expression expression, string branchOnTrueLabel, string branchOnFalseLabel, string currentPassage) { List<ZInstruction> instructions = new List<ZInstruction>(); // Expression has logical operand with a left and right side if (expression is LogicalOp) { LogicalOp log = (LogicalOp)expression; Guid expGuid = Guid.NewGuid(); string expTrueLabel = "exp_True_" + expGuid; string expFalseLabel = "exp_False_" + expGuid; short? leftAsShort = null; ZVariable leftAsVariable = null; bool leftIsSubExpression = false; short? rightAsShort = null; ZVariable rightAsVariable = null; bool rightIsSubExpression = false; int subExpressionCounter = 0; if (log.LeftExpr is VariableValue) // left side is a variable leftAsVariable = _symbolTable.GetSymbol(((VariableValue)(log.LeftExpr.BaseValue)).Name); else if (log.LeftExpr is IntValue) // left side is an integer leftAsShort = Convert.ToInt16(((IntValue)(log.LeftExpr.BaseValue)).Value); else if (log.LeftExpr is BoolValue) // left side is a boolean leftAsShort = Convert.ToInt16(((BoolValue)(log.LeftExpr.BaseValue)).Value); else if (log.LeftExpr is FunctionValue) // left side is a function { instructions.AddRange(ConvertFunctionValue((FunctionValue)log.LeftExpr, currentPassage)); leftAsVariable = new ZStackVariable(); } else // left side is in any other case a sub expression { subExpressionCounter++; leftIsSubExpression = true; if (log.Type == LogicalOp.LocicalOpEnum.And) { // in case of AND there is no need to evaluate the right side Guid andGuid = Guid.NewGuid(); string andBranchOnTrueLabel = "and_True_" + andGuid; string andBranchOnFalseLabel = "and_False_" + andGuid; instructions.AddRange(ConvertBranchExpression(log.LeftExpr, andBranchOnTrueLabel, andBranchOnFalseLabel, currentPassage)); //instructions.Add(new Nop() { Label = new ZLabel(andBranchOnFalseLabel) }); instructions.Add(new Jump(new ZJumpLabel(expFalseLabel)) { Label = new ZLabel(andBranchOnFalseLabel) }); instructions.Add(new Nop() { Label = new ZLabel(andBranchOnTrueLabel) }); } else if (log.Type == LogicalOp.LocicalOpEnum.Or) { // if OR is used we can stop evalutating on true; on false we have to continue with the left side Guid orGuid = Guid.NewGuid(); string orBranchOnTrueLabel = "or_True_" + orGuid; string orBranchOnFalseLabel = "or_False_" + orGuid; instructions.AddRange(ConvertBranchExpression(log.LeftExpr, orBranchOnTrueLabel, orBranchOnFalseLabel, currentPassage)); //instructions.Add(new Nop() { Label = new ZLabel(orBranchOnTrueLabel) }); instructions.Add(new Jump(new ZJumpLabel(expTrueLabel)) { Label = new ZLabel(orBranchOnTrueLabel) }); instructions.Add(new Nop() { Label = new ZLabel(orBranchOnFalseLabel) }); } else if (log.Type == LogicalOp.LocicalOpEnum.Xor) { // XOR behaves like OR on the left side string xorBranchOnAnyLabel = "xor_Any_" + Guid.NewGuid(); instructions.AddRange(ConvertBranchExpression(log.LeftExpr, xorBranchOnAnyLabel, xorBranchOnAnyLabel, currentPassage)); instructions.Add(new Nop() { Label = new ZLabel(xorBranchOnAnyLabel) }); } else { // logical operands are for sub expressions supported only throw new InvalidOperationException("Only logical operands like AND, OR and XOR are supported on sub expressions. Given opreand: " + log.Type.ToString()); } } if (log.RightExpr is VariableValue) rightAsVariable = _symbolTable.GetSymbol(((VariableValue)(log.RightExpr.BaseValue)).Name); else if (log.RightExpr is IntValue) rightAsShort = Convert.ToInt16(((IntValue)(log.RightExpr.BaseValue)).Value); else if (log.RightExpr is BoolValue) rightAsShort = Convert.ToInt16(((BoolValue)(log.RightExpr.BaseValue)).Value); else if (log.RightExpr is FunctionValue) { instructions.AddRange(ConvertFunctionValue((FunctionValue)log.RightExpr, currentPassage)); rightAsVariable = new ZStackVariable(); } else { subExpressionCounter++; rightIsSubExpression = true; if (log.Type == LogicalOp.LocicalOpEnum.And) { // due to the AND operand we have to evaluate the right side as well Guid andGuid = Guid.NewGuid(); string andBranchOnTrueLabel = "and_True_" + andGuid; string andBranchOnFalseLabel = "and_False_" + andGuid; instructions.AddRange(ConvertBranchExpression(log.RightExpr, andBranchOnTrueLabel, andBranchOnFalseLabel, currentPassage)); //instructions.Add(new Nop() { Label = new ZLabel(andBranchOnFalseLabel) }); instructions.Add(new Jump(new ZJumpLabel(expFalseLabel)) { Label = new ZLabel(andBranchOnFalseLabel) }); //instructions.Add(new Nop() { Label = new ZLabel(andBranchOnTrueLabel) }); instructions.Add(new Jump(new ZJumpLabel(expTrueLabel)) { Label = new ZLabel(andBranchOnTrueLabel) }); } else if (log.Type == LogicalOp.LocicalOpEnum.Or) { // we would have gotten here only if the left side was false // and due to the OR we still have to evaluate the right side Guid orGuid = Guid.NewGuid(); string orBranchOnTrueLabel = "or_True_" + orGuid; string orBranchOnFalseLabel = "or_False_" + orGuid; instructions.AddRange(ConvertBranchExpression(log.RightExpr, orBranchOnTrueLabel, orBranchOnFalseLabel, currentPassage)); //instructions.Add(new Nop() { Label = new ZLabel(orBranchOnFalseLabel) }); instructions.Add(new Jump(new ZJumpLabel(expFalseLabel)) { Label = new ZLabel(orBranchOnFalseLabel) }); //instructions.Add(new Nop() { Label = new ZLabel(orBranchOnTrueLabel) }); instructions.Add(new Jump(new ZJumpLabel(expTrueLabel)) { Label = new ZLabel(orBranchOnTrueLabel) }); } else if (log.Type == LogicalOp.LocicalOpEnum.Xor) { // for XOR we have to know the result of the left side // thankfully we pushed it onto the stack (0 false; 1 true) string xorBranchOnAnyLabel = "xor_Any_" + Guid.NewGuid(); instructions.AddRange(ConvertBranchExpression(log.RightExpr, xorBranchOnAnyLabel, xorBranchOnAnyLabel, currentPassage)); // if both sides were true or false then branch to false label instructions.Add(new Je(new ZStackVariable(), new ZStackVariable(), new ZBranchLabel(expFalseLabel))); instructions.Add(new Jump(new ZJumpLabel(expTrueLabel))); } else { // logical operands are for sub expressions supported only throw new InvalidOperationException("Only logical operands like AND, OR and XOR are supported on sub expressions. Given opreand: " + log.Type.ToString()); } } if (subExpressionCounter < 2) // if both sides are sub expressions then the following is not needed { switch (log.Type) { case LogicalOp.LocicalOpEnum.And: if (leftAsShort != null && rightAsShort != null) { instructions.Add(new Jg(leftAsShort.Value, 0, new ZBranchLabel(expFalseLabel) { BranchOn = false })); instructions.Add(new Jg(rightAsShort.Value, 0, new ZBranchLabel(expFalseLabel) { BranchOn = false })); } else if (leftAsShort != null && rightAsVariable != null) { instructions.Add(new Jg(leftAsShort.Value, 0, new ZBranchLabel(expFalseLabel) { BranchOn = false })); instructions.Add(new Jg(rightAsVariable, 0, new ZBranchLabel(expFalseLabel) { BranchOn = false })); } else if (leftAsShort != null && rightIsSubExpression) { instructions.Add(new Jg(leftAsShort.Value, 0, new ZBranchLabel(expFalseLabel) { BranchOn = false })); instructions.Add(new Jg(new ZStackVariable(), 0, new ZBranchLabel(expFalseLabel) { BranchOn = false })); } else if (leftAsVariable != null && rightAsShort != null) { instructions.Add(new Jg(leftAsVariable, 0, new ZBranchLabel(expFalseLabel) { BranchOn = false })); instructions.Add(new Jg(rightAsShort.Value, 0, new ZBranchLabel(expFalseLabel) { BranchOn = false })); } else if (leftAsVariable != null && rightAsVariable != null) { instructions.Add(new Jg(leftAsVariable, 0, new ZBranchLabel(expFalseLabel) { BranchOn = false })); instructions.Add(new Jg(rightAsVariable, 0, new ZBranchLabel(expFalseLabel) { BranchOn = false })); } else if (leftAsVariable != null && rightIsSubExpression) { instructions.Add(new Jg(leftAsVariable, 0, new ZBranchLabel(expFalseLabel) { BranchOn = false })); instructions.Add(new Jg(new ZStackVariable(), 0, new ZBranchLabel(expFalseLabel) { BranchOn = false })); } else if (leftIsSubExpression && rightAsShort != null) { instructions.Add(new Jg(new ZStackVariable(), 0, new ZBranchLabel(expFalseLabel) { BranchOn = false })); instructions.Add(new Jg(rightAsShort.Value, 0, new ZBranchLabel(expFalseLabel) { BranchOn = false })); } else if (leftIsSubExpression && rightAsVariable != null) { instructions.Add(new Jg(new ZStackVariable(), 0, new ZBranchLabel(expFalseLabel) { BranchOn = false })); instructions.Add(new Jg(rightAsVariable, 0, new ZBranchLabel(expFalseLabel) { BranchOn = false })); } else throw new Exception("Something went wrong while converting an expression with " + LogicalOp.LocicalOpEnum.And.ToString() + " operand."); instructions.Add(new Jump(new ZJumpLabel(expTrueLabel))); break; case LogicalOp.LocicalOpEnum.Or: if (leftAsShort != null && rightAsShort != null) { instructions.Add(new Jg(leftAsShort.Value, 0, new ZBranchLabel(expTrueLabel) { BranchOn = true })); instructions.Add(new Jg(rightAsShort.Value, 0, new ZBranchLabel(expFalseLabel) { BranchOn = false })); } else if (leftAsShort != null && rightAsVariable != null) { instructions.Add(new Jg(leftAsShort.Value, 0, new ZBranchLabel(expTrueLabel) { BranchOn = true })); instructions.Add(new Jg(rightAsVariable, 0, new ZBranchLabel(expFalseLabel) { BranchOn = false })); } else if (leftAsShort != null && rightIsSubExpression) { instructions.Add(new Jg(leftAsShort.Value, 0, new ZBranchLabel(expTrueLabel) { BranchOn = true })); instructions.Add(new Jg(new ZStackVariable(), 0, new ZBranchLabel(expFalseLabel) { BranchOn = false })); } else if (leftAsVariable != null && rightAsShort != null) { instructions.Add(new Jg(leftAsVariable, 0, new ZBranchLabel(expTrueLabel) { BranchOn = true })); instructions.Add(new Jg(rightAsShort.Value, 0, new ZBranchLabel(expFalseLabel) { BranchOn = false })); } else if (leftAsVariable != null && rightAsVariable != null) { instructions.Add(new Jg(leftAsVariable, 0, new ZBranchLabel(expTrueLabel) { BranchOn = true })); instructions.Add(new Jg(rightAsVariable, 0, new ZBranchLabel(expFalseLabel) { BranchOn = false })); } else if (leftAsVariable != null && rightIsSubExpression) { instructions.Add(new Jg(leftAsVariable, 0, new ZBranchLabel(expTrueLabel) { BranchOn = true })); instructions.Add(new Jg(new ZStackVariable(), 0, new ZBranchLabel(expFalseLabel) { BranchOn = false })); } else if (leftIsSubExpression && rightAsShort != null) { instructions.Add(new Jg(new ZStackVariable(), 0, new ZBranchLabel(expTrueLabel) { BranchOn = true })); instructions.Add(new Jg(rightAsShort.Value, 0, new ZBranchLabel(expFalseLabel) { BranchOn = false })); } else if (leftIsSubExpression && rightAsVariable != null) { instructions.Add(new Jg(new ZStackVariable(), 0, new ZBranchLabel(expTrueLabel) { BranchOn = true })); instructions.Add(new Jg(rightAsVariable, 0, new ZBranchLabel(expFalseLabel) { BranchOn = false })); } else throw new Exception("Something went wrong while converting an expression with " + LogicalOp.LocicalOpEnum.Or.ToString() + " operand."); instructions.Add(new Jump(new ZJumpLabel(expTrueLabel))); break; case LogicalOp.LocicalOpEnum.Xor: throw new NotImplementedException("The operand " + LogicalOp.LocicalOpEnum.Xor.ToString() + " is not implemented yet."); case LogicalOp.LocicalOpEnum.Not: throw new NotImplementedException("The operand " + LogicalOp.LocicalOpEnum.Not.ToString() + " is not implemented yet."); case LogicalOp.LocicalOpEnum.Neq: if (leftIsSubExpression || rightIsSubExpression) throw new InvalidOperationException("Arithmetic operands are not supported on sub expressions. Given operand: " + LogicalOp.LocicalOpEnum.Neq.ToString()); if (leftAsShort != null && rightAsShort != null) instructions.Add(new Je(leftAsShort.Value, rightAsShort.Value, new ZBranchLabel(expFalseLabel) { BranchOn = true })); else if (leftAsShort != null && rightAsVariable != null) instructions.Add(new Je(leftAsShort.Value, rightAsVariable, new ZBranchLabel(expFalseLabel) { BranchOn = true })); else if (leftAsVariable != null && rightAsShort != null) instructions.Add(new Je(leftAsVariable, rightAsShort.Value, new ZBranchLabel(expFalseLabel) { BranchOn = true })); else if (leftAsVariable != null && rightAsVariable != null) instructions.Add(new Je(leftAsVariable, rightAsVariable, new ZBranchLabel(expFalseLabel) { BranchOn = true })); instructions.Add(new Jump(new ZJumpLabel(expTrueLabel))); break; case LogicalOp.LocicalOpEnum.Eq: if (leftIsSubExpression || rightIsSubExpression) throw new InvalidOperationException("Arithmetic operands are not supported on sub expressions. Given operand: " + LogicalOp.LocicalOpEnum.Eq.ToString()); if (leftAsShort != null && rightAsShort != null) instructions.Add(new Je(leftAsShort.Value, rightAsShort.Value, new ZBranchLabel(expFalseLabel) { BranchOn = false })); else if (leftAsShort != null && rightAsVariable != null) instructions.Add(new Je(leftAsShort.Value, rightAsVariable, new ZBranchLabel(expFalseLabel) { BranchOn = false })); else if (leftAsVariable != null && rightAsShort != null) instructions.Add(new Je(leftAsVariable, rightAsShort.Value, new ZBranchLabel(expFalseLabel) { BranchOn = false })); else if (leftAsVariable != null && rightAsVariable != null) instructions.Add(new Je(leftAsVariable, rightAsVariable, new ZBranchLabel(expFalseLabel) { BranchOn = false })); instructions.Add(new Jump(new ZJumpLabel(expTrueLabel))); break; case LogicalOp.LocicalOpEnum.Gt: if (leftIsSubExpression || rightIsSubExpression) throw new InvalidOperationException("Arithmetic operands are not supported on sub expressions. Given operand: " + LogicalOp.LocicalOpEnum.Gt.ToString()); if (leftAsShort != null && rightAsShort != null) instructions.Add(new Jg(leftAsShort.Value, rightAsShort.Value, new ZBranchLabel(expFalseLabel) { BranchOn = false })); else if (leftAsShort != null && rightAsVariable != null) instructions.Add(new Jg(leftAsShort.Value, rightAsVariable, new ZBranchLabel(expFalseLabel) { BranchOn = false })); else if (leftAsVariable != null && rightAsShort != null) instructions.Add(new Jg(leftAsVariable, rightAsShort.Value, new ZBranchLabel(expFalseLabel) { BranchOn = false })); else if (leftAsVariable != null && rightAsVariable != null) instructions.Add(new Jg(leftAsVariable, rightAsVariable, new ZBranchLabel(expFalseLabel) { BranchOn = false })); instructions.Add(new Jump(new ZJumpLabel(expTrueLabel))); break; case LogicalOp.LocicalOpEnum.Ge: throw new NotImplementedException("The operand " + LogicalOp.LocicalOpEnum.Ge.ToString() + " is not implemented yet."); case LogicalOp.LocicalOpEnum.Lt: if (leftIsSubExpression || rightIsSubExpression) throw new InvalidOperationException("Arithmetic operands are not supported on sub expressions. Given operand: " + LogicalOp.LocicalOpEnum.Lt.ToString()); if (leftAsShort != null && rightAsShort != null) instructions.Add(new Jl(leftAsShort.Value, rightAsShort.Value, new ZBranchLabel(expFalseLabel) { BranchOn = false })); else if (leftAsShort != null && rightAsVariable != null) instructions.Add(new Jl(leftAsShort.Value, rightAsVariable, new ZBranchLabel(expFalseLabel) { BranchOn = false })); else if (leftAsVariable != null && rightAsShort != null) instructions.Add(new Jl(leftAsVariable, rightAsShort.Value, new ZBranchLabel(expFalseLabel) { BranchOn = false })); else if (leftAsVariable != null && rightAsVariable != null) instructions.Add(new Jl(leftAsVariable, rightAsVariable, new ZBranchLabel(expFalseLabel) { BranchOn = false })); instructions.Add(new Jump(new ZJumpLabel(expTrueLabel))); break; case LogicalOp.LocicalOpEnum.Le: throw new NotImplementedException("The operand " + LogicalOp.LocicalOpEnum.Le.ToString() + " is not implemented yet."); default: throw new Exception("Unknown operand used: " + log.Type.ToString()); } } // the expression above was true instructions.Add(new Push(1) { Label = new ZLabel(expTrueLabel) }); instructions.Add(new Jump(new ZJumpLabel(branchOnTrueLabel))); // the expression above was false instructions.Add(new Push(0) { Label = new ZLabel(expFalseLabel) }); instructions.Add(new Jump(new ZJumpLabel(branchOnFalseLabel))); } else if (expression is BoolValue) { BoolValue boolean = (BoolValue)expression; instructions.Add(new Je(1, Convert.ToInt16(boolean.Value), new ZBranchLabel(branchOnFalseLabel) { BranchOn = false })); } else if (expression is VariableValue) { instructions.Add(new Je(1, _symbolTable.GetSymbol(((VariableValue)expression).Name), new ZBranchLabel(branchOnFalseLabel) { BranchOn = false })); } else if (expression is FunctionValue) { instructions.AddRange(ConvertFunctionValue((FunctionValue)expression, currentPassage)); } else throw new Exception("Unknown expression type " + expression.GetType().Name + " for converting branches."); return instructions; }