public void PeekWriteArrayType(int n, TypeRef expType) { var type = PeekType(n); var s = type.Style(RootEnv); if (s is NullTypeStyle) { // No-op. // If stack entry is generalized it must become an array type } else if (s is ArrayTypeStyle) { // If stack entry is generalized it must remain an array type expType = expType.ToRunTimeType(RootEnv, false); type = type.Arguments[0]; if (!expType.IsAssignableTo(RootEnv, type)) { throw new InvalidOperationException("array element type is not assignable from expected type"); } } else { // Parameter types not allowed throw new InvalidOperationException("stack entry is not an array type"); } }
// ---------------------------------------------------------------------- // Stack type constraints // ---------------------------------------------------------------------- private void SetUpperBound(int n, TypeRef type, BoolRef changed) { if (n >= Depth) { throw new InvalidOperationException("stack is too shallow"); } innerState.Value.Stack[n].SetUpperBound(RootEnv, type.ToRunTimeType(RootEnv, true), changed); }
public bool PeekDereferencableExpectedType(int n, TypeRef expType, bool canBeStruct, BoolRef changed) { expType = expType.ToRunTimeType(RootEnv, false); var type = PeekType(n); var s = type.Style(RootEnv); if (s is NullTypeStyle) { // Stack entry will remain a referece type (and thus never a pointer). // 'null' can be statically dereferenced if we are expecting a reference type, though // of course this will cause a null reference exception at runtime if (!(expType.Style(RootEnv) is ReferenceTypeStyle)) { throw new InvalidOperationException("expected type is not a referece type"); } // Stack type cannot be refined above expected reference type SetUpperBound(n, expType, changed); // Not dereferencing a pointer return(false); } else if (s is UnmanagedPointerTypeStyle) { throw new InvalidOperationException("unmananaged pointer"); } else if (s is ManagedPointerTypeStyle) { // Stack entry will remain a pointer of this type, so no need to impose upper bound if (!type.Arguments[0].IsAssignableTo(RootEnv, expType)) { throw new InvalidOperationException ("managed pointer element type is not assignable to expected type"); } // Dereferencing a pointer return(true); } else { // If stack entry is a value type it will remain a value type, so test is stable under generalization if (!canBeStruct && s is ValueTypeStyle) { throw new InvalidOperationException ("stack entry is a value type, but value types cannot be the target of field pointers"); } // Values and objects can be dereferenced if they are compatible with expected type // Parameter types are not allowed if (!(s is ReferenceTypeStyle) && !(s is ValueTypeStyle)) { throw new InvalidOperationException("stack entry is not a value or reference type"); } // Stack type cannot be refined above expected type SetUpperBound(n, expType, changed); // Not dereferencing a pointer return(false); } }
public void PeekBoxedType(int n, TypeRef expType, BoolRef changed) { var type = PeekType(n); var s = type.Style(RootEnv); if (s is NullTypeStyle) { // No-op. // Will fail at runtime, but still ok. // If stack entry is generalized, it must go directly to Object. } else if (s is ReferenceTypeStyle) { if (s is ObjectTypeStyle) { // This stack entry can never be refined away from object return; } if (!(s is BoxTypeStyle)) { // Parameter types not allowed throw new InvalidOperationException("stack entry is not object or a boxed type"); } if (expType.Style(RootEnv) is NullableTypeStyle) { // Account for null -> no-value coercion expType = expType.Arguments[0]; } expType = expType.ToRunTimeType(RootEnv, false); if (!type.Arguments[0].IsEquivalentTo(RootEnv, expType)) { throw new InvalidOperationException("boxed element type is not equivalent to expected type"); } // Box types are NOT invariant, so need to impose upper bound SetUpperBound(n, RootEnv.Global.BoxTypeConstructorRef.ApplyTo(expType), changed); } else { // Parameter types not allowed throw new InvalidOperationException("stack entry is not object or a boxed type"); } }
public void PeekWritePointerType(int n, TypeRef expType) { var type = PeekType(n); var s = type.Style(RootEnv); if (s is UnmanagedPointerTypeStyle) { throw new InvalidOperationException("unmanaged pointer"); } if (!(s is ManagedPointerTypeStyle)) { throw new InvalidOperationException("stack entry is not a managed pointer type"); } // Parameter types not allowed. // Stack entry will remain a pointer to this type, so no need to impose upper bound, and // following check is stable under stack refinement. if (!(expType.ToRunTimeType(RootEnv, false).IsAssignableTo(RootEnv, type.Arguments[0]))) { throw new InvalidOperationException("pointer element type is not assignable from expected type"); } }
public void PeekReadArrayType(int n, TypeRef expType, bool isExact) { var type = PeekType(n); var s = type.Style(RootEnv); if (s is NullTypeStyle) { // No-op // If stack entry is generalized it must become an array } else if (s is ArrayTypeStyle) { // If stack entry is generalized it must remain an array type expType = expType.ToRunTimeType(RootEnv, false); type = type.Arguments[0]; if (isExact) { // WARNING: Test may prematurely fail since expType may be revised downwards // TODO: Delay test till final pass? if (!type.IsEquivalentTo(RootEnv, expType)) { throw new InvalidOperationException ("array element type is not equivalent to expected type"); } } else { if (!type.IsAssignableTo(RootEnv, expType)) { throw new InvalidOperationException("array element type is not assignable to expected type"); } } } else { // Parameter types not allowed throw new InvalidOperationException("stack entry is not an array type"); } }
public MachineState PopPushType(int n, TypeRef type, PointsTo pointsTo) { return(PopPush(n, new StackEntryState(type.ToRunTimeType(RootEnv, true), pointsTo))); }