예제 #1
0
            public static TypeOnStack Get(Type t)
            {
                lock (Cache)
                {
                    TypeOnStack ret;
                    if (!Cache.TryGetValue(t, out ret))
                    {
                        ret =
                            new TypeOnStack
                        {
                            Type = t
                        };

                        Cache[t] = ret;
                    }

                    return(ret);
                }
            }
예제 #2
0
 public bool IsAssignableFrom(TypeOnStack other)
 {
     return(ExtensionMethods.IsAssignableFrom(this, other));
 }
예제 #3
0
 public static bool IsAssignableFrom(Type type1, TypeOnStack type2)
 {
     return(TypeOnStack.Get(type1).IsAssignableFrom(type2));
 }
예제 #4
0
        public static bool IsAssignableFrom(TypeOnStack type1, TypeOnStack type2)
        {
            // voids aren't assignable
            if (type1.IsVoid || type2.IsVoid)
            {
                return(false);
            }

            // wildcards match *everything*
            if (type1 == TypeOnStack.Get <WildcardType>() || type2 == TypeOnStack.Get <WildcardType>())
            {
                return(true);
            }

            if (type1.IsArray && type2.IsArray)
            {
                if (type1.Type.GetArrayRank() == type2.Type.GetArrayRank())
                {
                    var t1Elem = type1.Type.GetElementType();
                    var t2Elem = type2.Type.GetElementType();

                    while (t1Elem.HasElementType)
                    {
                        t1Elem = t1Elem.GetElementType();
                    }
                    while (t2Elem.HasElementType)
                    {
                        t2Elem = t2Elem.GetElementType();
                    }

                    if (t1Elem == typeof(WildcardType) || t2Elem == typeof(WildcardType))
                    {
                        return(true);
                    }
                }
            }

            if (type1.IsPointer && type2.IsPointer)
            {
                if (type1.Type.GetElementType() == typeof(WildcardType) || type2.Type.GetElementType() == typeof(WildcardType))
                {
                    return(true);
                }
            }

            if (type1.IsReference && type2.IsReference)
            {
                if (type1.Type.GetElementType() == typeof(WildcardType) || type2.Type.GetElementType() == typeof(WildcardType))
                {
                    return(true);
                }
            }

            // any pointer type matches, well, any pointer
            if (type1.Type == typeof(AnyPointerType) && type2.IsPointer)
            {
                return(true);
            }
            if (type2.Type == typeof(AnyPointerType) && type1.IsPointer)
            {
                return(true);
            }

            // likewise for any by ref
            if (type1.Type == typeof(AnyByRefType) && type2.IsReference)
            {
                return(true);
            }
            if (type2.Type == typeof(AnyByRefType) && type1.IsReference)
            {
                return(true);
            }

            // Native int can be convereted to any pointer type
            if (type1.IsPointer && type2 == TypeOnStack.Get <NativeIntType>())
            {
                return(true);
            }
            if (type2.IsPointer && type1 == TypeOnStack.Get <NativeIntType>())
            {
                return(true);
            }

            // it's possible to assign a struct* to an interface or object
            if (!(type2.IsPointerToValueType && (type1.IsInterface || type1.Type.Equals(typeof(object)))))
            {
                if ((type1.IsPointer || type1.IsReference) && !(type2.IsPointer || type2.IsReference))
                {
                    return(false);
                }
                if ((type2.IsPointer || type2.IsReference) && !(type1.IsPointer || type1.IsReference))
                {
                    return(false);
                }
            }

            if (type1.IsPointer || type1.IsReference)
            {
                return(type1.Type.GetElementType() == type2.Type.GetElementType());
            }

            var t1 = type1.Type;
            var t2 = type2.Type;


            // The null type can be assigned to any reference type
            if (t1 == typeof(NullType) && !TypeHelpers.IsValueType(t2))
            {
                return(true);
            }
            if (t2 == typeof(NullType) && !TypeHelpers.IsValueType(t1))
            {
                return(true);
            }

            t1 = Alias(t1);
            t2 = Alias(t2);

            return(ReallyIsAssignableFrom(t1, t2));
        }
예제 #5
0
 public static StackTransition[] Pop(Type popType)
 {
     return(Pop(TypeOnStack.Get(popType)));
 }
예제 #6
0
        private static bool ReallyIsAssignableFrom(Type t1, Type t2)
        {
            if (t1 == t2)
            {
                return(true);
            }

            if (t1 == typeof(OnlyObjectType))
            {
                if (t2 == typeof(object))
                {
                    return(true);
                }

                return(false);
            }

            // quick and dirty base case
            if (t1 == typeof(object) && !TypeHelpers.IsValueType(t2))
            {
                return(true);
            }

            // you have to box in this case
            if ((t1 == typeof(object) || TypeHelpers.IsInterface(t1)) && TypeHelpers.IsValueType(t2))
            {
                return(false);
            }

            var t1Bases = GetBases(t1);
            var t2Bases = GetBases(t2);

            if (t2Bases.Any(t2b => TypeOnStack.Get(t1).IsAssignableFrom(TypeOnStack.Get(t2b))))
            {
                return(true);
            }

            if (TypeHelpers.IsInterface(t1))
            {
                var t2Interfaces = t2.IsPointer ? (LinqArray <Type>)t2.GetElementType().GetInterfaces() : (LinqArray <Type>)t2.GetInterfaces();

                return(t2Interfaces.Any(t2i => TypeOnStack.Get(t1).IsAssignableFrom(TypeOnStack.Get(t2i))));
            }

            if (TypeHelpers.IsGenericType(t1) && TypeHelpers.IsGenericType(t2))
            {
                var t1Def = t1.GetGenericTypeDefinition();
                var t2Def = t2.GetGenericTypeDefinition();

                if (t1Def != t2Def)
                {
                    return(false);
                }

                var t1Args = t1.GetGenericArguments();
                var t2Args = t2.GetGenericArguments();

                for (var i = 0; i < t1Args.Length; i++)
                {
                    if (!TypeOnStack.Get(t1Args[i]).IsAssignableFrom(TypeOnStack.Get(t2Args[i])))
                    {
                        return(false);
                    }
                }

                return(true);
            }

            try
            {
                return(t1.IsAssignableFrom(t2));
            }
            catch (NotSupportedException)
            {
                // Builders, some generic types, and so on don't implement this; just assume it's *no good* for now
                return(false);
            }
        }
예제 #7
0
 public static StackTransition[] Push(Type pushType)
 {
     return(Push(TypeOnStack.Get(pushType)));
 }
예제 #8
0
 public static StackTransition[] Push(TypeOnStack pushType)
 {
     return(new[] { new StackTransition(new TypeOnStack[0], new[] { pushType }) });
 }
예제 #9
0
 public StackTransition(bool isDuplicate)
     : this(new TypeOnStack[0], new[] { TypeOnStack.Get <WildcardType>() }, null)
 {
     IsDuplicate = isDuplicate;
 }
예제 #10
0
 public static StackTransition[] Pop(TypeOnStack popType)
 {
     return(new[] { new StackTransition(new[] { popType }, new TypeOnStack[0]) });
 }
예제 #11
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));
        }
예제 #12
0
        private LinqList <StackTransition> GetLegalTransitions(LinqList <StackTransition> ops, LinqStack <LinqList <TypeOnStack> > runningStack)
        {
            var ret = new LinqList <StackTransition>(ops.Count);

            for (var i = 0; i < ops.Count; i++)
            {
                var w = ops[i];

                if (LinqAlternative.All(w.PoppedFromStack, u => u == TypeOnStack.Get <PopAllType>()))
                {
                    ret.Add(w);
                    continue;
                }

                var onStack = runningStack.Peek(IsBaseless, w.PoppedCount);

                if (onStack == null)
                {
                    continue;
                }

                if (LinqAlternative.Any(w.PushedToStack, p => p == TypeOnStack.Get <SamePointerType>()))
                {
                    if (w.PushedToStack.Length > 1)
                    {
                        throw new Exception("SamePointerType can be only product of a transition which contains it");
                    }

                    var shouldBePointer = LinqAlternative.SelectMany(onStack, p => p.Where(x => x.IsPointer || x == TypeOnStack.Get <WildcardType>()).AsEnumerable()).Distinct().ToList();

                    if (shouldBePointer.Count == 0)
                    {
                        continue;
                    }
                    w = new StackTransition(w.PoppedFromStack, new [] { shouldBePointer.Single() });
                }

                if (LinqAlternative.Any(w.PushedToStack, p => p == TypeOnStack.Get <SameByRefType>()))
                {
                    if (w.PushedToStack.Length > 1)
                    {
                        throw new Exception("SameByRefType can be only product of a transition which contains it");
                    }

                    var shouldBeByRef = LinqAlternative.SelectMany(onStack, p => p.Where(x => x.IsReference || x == TypeOnStack.Get <WildcardType>()).AsEnumerable()).Distinct().ToList();

                    if (shouldBeByRef.Count == 0)
                    {
                        continue;
                    }
                    w = new StackTransition(w.PoppedFromStack, new[] { shouldBeByRef.Single() });
                }

                bool outerContinue = false;

                for (var j = 0; j < w.PoppedCount; j++)
                {
                    var shouldBe   = w.PoppedFromStack[j];
                    var actuallyIs = onStack[j];

                    if (!actuallyIs.Any(a => shouldBe.IsAssignableFrom(a)))
                    {
                        outerContinue = true;
                        break;
                    }
                }

                if (outerContinue)
                {
                    continue;
                }

                ret.Add(w);
            }

            return(ret);
        }
예제 #13
0
        private static void UpdateStack(LinqStack <LinqList <TypeOnStack> > stack, InstructionAndTransitions wrapped, bool isBaseless)
        {
            var legal = wrapped.Transitions;
            var instr = wrapped.Instruction;

            var legalSize = 0;

            legal.Each(
                t =>
            {
                legalSize += t.PushedToStack.Length;

                if (t.Before != null)
                {
                    t.Before(stack, isBaseless);
                }
            }
                );

            if (legal.Any(l => LinqAlternative.Any(l.PoppedFromStack, u => u == TypeOnStack.Get <PopAllType>())))
            {
                if (instr.HasValue)
                {
                    for (var i = 0; i < stack.Count; i++)
                    {
                        var ix = stack.Count - i - 1;
                        stack.ElementAt(i).Each(y => y.Mark(wrapped, ix));
                    }
                }

                stack.Clear();
            }
            else
            {
                var toPop = legal.First().PoppedCount;

                for (var j = 0; j < toPop && stack.Count > 0; j++)
                {
                    var popped = stack.Pop();

                    if (instr.HasValue)
                    {
                        var ix = toPop - j - 1;
                        popped.Each(y => y.Mark(wrapped, ix));
                    }
                }
            }

            var toPush = new LinqList <TypeOnStack>(legalSize);
            var pushed = new LinqHashSet <TypeOnStack>();

            for (var i = 0; i < legal.Count; i++)
            {
                foreach (var p in legal[i].PushedToStack)
                {
                    if (pushed.Contains(p))
                    {
                        continue;
                    }

                    toPush.Add(p);
                    pushed.Add(p);
                }
            }

            if (toPush.Count > 0)
            {
                stack.Push(toPush);
            }
        }