Пример #1
0
        private void _emitIncrementDecrementCode(CompilerTarget target, StackSemantics value)
        {
            var symbolCall = _operand as AstIndirectCall;
            var symbol = symbolCall == null ? null : symbolCall.Subject as AstReference;
            EntityRef.Variable variableRef = null;
            var isVariable = symbol != null && symbol.Entity.TryGetVariable(out variableRef);
            var isPre = _operator == UnaryOperator.PreDecrement || _operator == UnaryOperator.PreIncrement;
            switch (_operator)
            {
                case UnaryOperator.PreIncrement:
                case UnaryOperator.PostIncrement:
                case UnaryOperator.PreDecrement:
                case UnaryOperator.PostDecrement:
                    var isIncrement = 
                        _operator == UnaryOperator.PostIncrement ||
                        _operator == UnaryOperator.PreIncrement;
                    if (isVariable)
                    {
                        Debug.Assert(variableRef != null);
                        EntityRef.Variable.Local localRef;
                        Action loadVar;
                        Action perform;
                        EntityRef.Variable.Global globalRef;

                        // First setup the two actions
                        if (variableRef.TryGetLocalVariable(out localRef))
                        {
                            loadVar = () => target.EmitLoadLocal(Position, localRef.Id);
                            perform =
                                () => target.Emit(Position, isIncrement ? OpCode.incloc : OpCode.decloc, localRef.Id);
                        }
                        else if(variableRef.TryGetGlobalVariable(out globalRef))
                        {
                            loadVar = () => target.EmitLoadGlobal(Position, globalRef.Id, globalRef.ModuleName);

                            perform =
                                () =>
                                target.Emit(Position, isIncrement ? OpCode.incglob : OpCode.decglob, globalRef.Id,
                                            globalRef.ModuleName);
                        }
                        else
                        {
                            throw new InvalidOperationException("Found variable entity that is neither a global nor a local variable.");
                        }

                        // Then decide in what order to apply them.
                        if (!isPre && value == StackSemantics.Value)
                        {
                            loadVar();
                        }

                        perform();

                        if (isPre && value == StackSemantics.Value)
                        {
                            loadVar();
                        }
                    }
                    else
                        throw new PrexoniteException(
                            "Node of type " + _operand.GetType() +
                                " does not support increment/decrement operators.");
                    break;
                // ReSharper disable RedundantCaseLabel
                case UnaryOperator.UnaryNegation:
                case UnaryOperator.LogicalNot:
                case UnaryOperator.OnesComplement:
                // ReSharper restore RedundantCaseLabel
                // ReSharper disable RedundantEmptyDefaultSwitchBranch
                default:
                    break; //No effect
                // ReSharper restore RedundantEmptyDefaultSwitchBranch
            }
        }