Пример #1
0
            private void InvocationsReExecutor(
                SecondaryEntity state,
                MyGssNode stack,
                Node position,
                MyTransition currentTransition,
                PrimaryEntity newType)
            {
                var invocation = (ResolvedInvocationStatement <Node>)currentTransition.Statement;

                if (newType is IInvokable <Node> invocable)
                {
                    //Logging.Log("dynamic re-invocation");

                    if (state is UnknownEntity)
                    {
                        Push(state, new MyStackData(currentTransition, state, true), invocable.EntryPoint);
                        invocable.MarkAsInvoked();
                    }
                    else
                    {
                        var recipientId = invocation.PassedParameters[state];
                        var exists      = invocable.Variables.TryGetValue(recipientId.Value, out var recipient);

                        if (exists)
                        {
                            Push(recipient, new MyStackData(currentTransition, state, true), invocable.EntryPoint);
                        }
                    }
                }

                if (newType is ResolvedClassId classId)
                {
                    var target = myProcessingProgram
                                 .FindClassById(classId)
                                 .FindMethodInFullHierarchy(invocation.TargetMethodId);

                    if (target == null)
                    {
                        return;
                    }

                    if (state is UnknownEntity)
                    {
                        Push(state, new MyStackData(currentTransition, state, true), target.EntryPoint);
                        target.MarkAsInvoked();
                    }
                    else
                    {
                        var recipientId = invocation.PassedParameters[state];
                        var exists      = target.Variables.TryGetValue(recipientId.Value, out var recipient);

                        if (exists)
                        {
                            Push(recipient, new MyStackData(currentTransition, state, true), target.Start);
                        }
                    }
                }
            }
Пример #2
0
 public override void Action(SecondaryEntity state, MyGssNode stack)
 {
     if (stack.Symbol.Trampoline)
     {
         if (state is FakeTrampolineEntity fake)
         {
             Pop(fake.OriginalTarget, stack.Symbol.CallingEdge.Target);
         }
         else
         {
             Push(state, new MyStackData(stack.Symbol.CallingEdge, stack.Symbol.TrackedEntity, false));
         }
     }
 }
Пример #3
0
            public override void Step(SecondaryEntity state, MyGssNode stack, Node position, MyTransition currentTransition)
            {
                if (stack.Symbol.Trampoline)
                {
                    return;
                }

                var statement = currentTransition.Statement;

                switch (statement.Type)
                {
                case StatementType.Internal:
                    var internalStatement = (InternalStatement)statement;

                    ParameterIndex recipientId;
                    bool           exists;
                    switch (internalStatement.InternalType)
                    {
                    case InternalStatementType.ResolvedInvocation:
                        var invocation = (ResolvedInvocationStatement <Node>)internalStatement;
                        exists = invocation.PassedParameters.TryGetValue(state, out recipientId);
                        var scanning = state is UnknownEntity;

                        Skip(state);

                        if (exists || scanning)
                        {
                            if (invocation.TargetEntity is SecondaryEntity variable)
                            {
                                var instances = CollectInstances(
                                    variable,
                                    invocation.TargetMethodId);

                                foreach (var instance in instances.ToList())
                                {
                                    //Logging.Log("dynamic invocation");
                                    if (exists)
                                    {
                                        instance.Variables.TryGetValue(recipientId.Value, out var recipient);
                                        if (recipient != null)
                                        {
                                            Push(recipient, new MyStackData(currentTransition, state, true),
                                                 instance.EntryPoint);
                                            //Logging.Log("recipient is not null");
                                        }
                                        else
                                        {
                                            //Logging.Log($"recipient is null: {myProcessingProgram.GetMethodByStartPoint(instance.EntryPoint)}, {recipientId.Value}");
                                        }
                                    }

                                    if (scanning)
                                    {
                                        Push(state, new MyStackData(currentTransition, state, true), instance.EntryPoint);
                                        instance.MarkAsInvoked();
                                    }
                                }

                                var head = ExtractHead();
                                variable.Subscriptions.OnNewPrimaryAdded +=
                                    newType =>
                                {
                                    myForcedExecutor(head, currentTransition,
                                                     InvocationsReExecutor, newType);
                                };
                            }

                            if (invocation.TargetEntity is ResolvedClassId classId)
                            {
                                var clazz  = myProcessingProgram.FindClassById(classId);
                                var method = clazz.FindMethodInFullHierarchy(invocation.TargetMethodId);

                                if (method != null)
                                {
                                    if (exists)
                                    {
                                        method.Variables.TryGetValue(recipientId.Value, out var recipient);
                                        if (recipient != null)
                                        {
                                            Push(recipient, new MyStackData(currentTransition, state, true),
                                                 method.Start);
                                            //Logging.Log("recipient is not null");
                                        }
                                        else
                                        {
                                            //Logging.Log($"recipient is null: {myProcessingProgram.GetMethodByStartPoint(method.EntryPoint)}, {recipientId.Value}");
                                        }
                                    }

                                    if (scanning)
                                    {
                                        Push(state, new MyStackData(currentTransition, state, true), method.EntryPoint);
                                        method.MarkAsInvoked();
                                    }
                                }
                            }
                        }

                        break;

                    case InternalStatementType.Return:
                        var stackTop = stack.Symbol;
                        if (stackTop.CallingEdge.Statement is NopStatement)
                        {
                            break;
                        }

                        var callingStatement = (ResolvedInvocationStatement <Node>)stackTop.CallingEdge.Statement;

                        if (state is ResolvedLocalVariable localVariable)
                        {
                            var id = new ParameterIndex(localVariable.LocalId);
                            exists = callingStatement.ReturnedValues.TryGetValue(id, out var recipient);
                            if (exists)
                            {
                                Pop(new FakeTrampolineEntity(recipient));
                            }
                        }

                        break;

                    case InternalStatementType.ResolvedAssignment:
                        var assignment = (ResolvedAssignmentStatement)currentTransition.Statement;

                        Skip(state);

                        //Trace.Assert(assignment.Target != null);
                        if (assignment.Target == null)
                        {
                            break;
                        }

                        if (state is UnknownEntity)
                        {
                            if (assignment.Source is PrimaryEntity primary)
                            {
                                assignment.Target.AddPrimary(primary);
                                Accept(assignment.Target);
                            }
                            else
                            {
                                ((SecondaryEntity)assignment.Source).PropagateForward(assignment.Target);
                                if (assignment.Target is ResolvedLocalVariable)
                                {
                                    Accept(assignment.Target);
                                }
                            }
                        }

                        /*
                         * if ((assignment.Source is ResolvedObjectField ||
                         *   assignment.Source is ResolvedClassField ||
                         *   assignment.Source is ResolvedObjectMethodReference<Node>) &&
                         *  state is UnknownEntity)
                         * {
                         *  var asSecondary = (SecondaryEntity) assignment.Source;
                         *  asSecondary.PropagateForward(assignment.Target);
                         *  Accept(assignment.Target);
                         * }
                         */

                        if (ReferenceEquals(assignment.Source, state))
                        {
                            Accept(assignment.Target);
                        }

                        break;
                    }
                    break;

                default:
                    Skip(state);
                    break;
                }
            }