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;
        }