public StackTransition(IEnumerable <Type> popped, IEnumerable <Type> pushed, VerificationCallback before = null) : this ( LinqEnumerable <Type> .For(popped).Select(s => TypeOnStack.Get(s)).AsEnumerable(), LinqEnumerable <Type> .For(pushed).Select(s => TypeOnStack.Get(s)).AsEnumerable(), before ) { }
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)); }
public static bool IsAssignableFrom(Type type1, TypeOnStack type2) { return(TypeOnStack.Get(type1).IsAssignableFrom(type2)); }
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); } }
public static StackTransition[] Pop(Type popType) { return(Pop(TypeOnStack.Get(popType))); }
public static StackTransition[] Push(Type pushType) { return(Push(TypeOnStack.Get(pushType))); }
public StackTransition(bool isDuplicate) : this(new TypeOnStack[0], new[] { TypeOnStack.Get <WildcardType>() }, null) { IsDuplicate = isDuplicate; }
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)); }
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); }
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); } }