Exemple #1
0
        private VerificationResult CompareStacks(Label label, SigilTuple <bool, LinqStack <LinqList <TypeOnStack> > > actual, SigilTuple <bool, LinqStack <LinqList <TypeOnStack> > > expected)
        {
            if (!actual.Item1 && !expected.Item1)
            {
                if (expected.Item2.Count != actual.Item2.Count)
                {
                    // Both stacks are based, so the wrong size is a serious error as well
                    return(VerificationResult.FailureUnderflow(label, expected.Item2.Count));
                }
            }

            for (var i = 0; i < expected.Item2.Count; i++)
            {
                if (i >= actual.Item2.Count && !actual.Item1)
                {
                    // actual is based and expected wanted a value, this is an UNDERFLOW
                    return(VerificationResult.FailureUnderflow(label, expected.Item2.Count));
                }

                var expectedTypes = expected.Item2.ElementAt(i);
                LinqList <TypeOnStack> actualTypes;
                if (i < actual.Item2.Count)
                {
                    actualTypes = actual.Item2.ElementAt(i);
                }
                else
                {
                    // Underflowed, but our actual stack is baseless; so we assume we're good until proven otherwise
                    break;
                }

                bool typesMatch = false;
                foreach (var a in actualTypes.AsEnumerable())
                {
                    foreach (var e in expectedTypes.AsEnumerable())
                    {
                        typesMatch |= e.IsAssignableFrom(a);
                    }
                }

                if (!typesMatch)
                {
                    // Just went through what's on the stack, and we the types are known to not be compatible
                    return(VerificationResult.FailureTypeMismatch(label, actualTypes, expectedTypes));
                }
            }

            return(null);
        }
Exemple #2
0
        public VerificationResult CollapseAndVerify()
        {
            var runningStack = CachedVerifyStack ?? new LinqStack <LinqList <TypeOnStack> >(StartingStack.Reverse());

            int i = CachedVerifyIndex ?? 0;

            for (; i < Transitions.Count; i++)
            {
                var wrapped = Transitions[i];
                var ops     = wrapped.Transitions;

                if (ops.Any(o => o.StackSizeMustBe.HasValue))
                {
                    if (ops.Count > 1)
                    {
                        throw new Exception("Shouldn't have multiple 'must be size' transitions at the same point");
                    }

                    var doIt = ops[0];

                    if (doIt.StackSizeMustBe != runningStack.Count)
                    {
                        return(VerificationResult.FailureStackSize(this, i, doIt.StackSizeMustBe.Value));
                    }
                }

                var legal = GetLegalTransitions(ops, runningStack);

                if (legal.Count == 0)
                {
                    var wouldPop = ops.GroupBy(g => g.PoppedFromStack.Length).Single().Key;

                    if (runningStack.Count < wouldPop)
                    {
                        return(VerificationResult.FailureUnderflow(this, i, wouldPop, runningStack));
                    }

                    IEnumerable <TypeOnStack> expected;
                    var stackI = FindStackFailureIndex(runningStack, ops.AsEnumerable(), out expected);

                    return(VerificationResult.FailureTypeMismatch(this, i, stackI, expected, runningStack));
                }

                if (legal.GroupBy(g => new { a = g.PoppedCount, b = g.PushedToStack.Length }).Count() > 1)
                {
                    throw new Exception("Shouldn't be possible; legal transitions should have same push/pop #s");
                }

                // No reason to do all this work again
                Transitions[i] = new InstructionAndTransitions(wrapped.Instruction, wrapped.InstructionIndex, legal);

                bool popAll = legal.Any(l => ((LinqArray <TypeOnStack>)l.PoppedFromStack).Contains(TypeOnStack.Get <PopAllType>()));
                if (popAll && legal.Count() != 1)
                {
                    throw new Exception("PopAll cannot coexist with any other transitions");
                }

                if (!popAll)
                {
                    var toPop = legal.First().PoppedCount;

                    if (toPop > runningStack.Count && !IsBaseless)
                    {
                        return(VerificationResult.FailureUnderflow(this, i, toPop, runningStack));
                    }
                }

                bool isDuplicate = legal.Any(l => l.IsDuplicate);
                if (isDuplicate && legal.Count() > 1)
                {
                    throw new Exception("Duplicate must be only transition");
                }

                if (isDuplicate)
                {
                    if (!IsBaseless && runningStack.Count == 0)
                    {
                        return(VerificationResult.FailureUnderflow(this, i, 1, runningStack));
                    }

                    var toPush = runningStack.Count > 0 ? runningStack.Peek() : new LinqList <TypeOnStack>(new[] { TypeOnStack.Get <WildcardType>() });

                    UpdateStack(runningStack, new InstructionAndTransitions(wrapped.Instruction, wrapped.InstructionIndex, new LinqList <StackTransition>(new[] { new StackTransition(new TypeOnStack[0], toPush.AsEnumerable()) })), IsBaseless);
                }
                else
                {
                    UpdateStack(runningStack, new InstructionAndTransitions(wrapped.Instruction, wrapped.InstructionIndex, legal), IsBaseless);
                }
            }

            CachedVerifyIndex = i;
            CachedVerifyStack = runningStack;

            return(VerificationResult.Successful(this, runningStack));
        }