forked from dafny-lang/dafny
-
Notifications
You must be signed in to change notification settings - Fork 0
/
NewtypeDecl.cs
179 lines (161 loc) · 7.83 KB
/
NewtypeDecl.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Numerics;
namespace Microsoft.Dafny;
public class NewtypeDecl : TopLevelDeclWithMembers, RevealableTypeDecl, RedirectingTypeDecl, IHasDocstring, ICanVerify {
public override string WhatKind { get { return "newtype"; } }
public override bool CanBeRevealed() { return true; }
public PreType BasePreType;
public Type BaseType { get; set; } // null when refining
public BoundVar Var { get; set; } // can be null (if non-null, then object.ReferenceEquals(Var.Type, BaseType))
public Expression Constraint { get; set; } // is null iff Var is
public SubsetTypeDecl.WKind WitnessKind { get; set; } = SubsetTypeDecl.WKind.CompiledZero;
public Expression/*?*/ Witness { get; set; } // non-null iff WitnessKind is Compiled or Ghost
[FilledInDuringResolution] public NativeType NativeType; // non-null for fixed-size representations (otherwise, use BigIntegers for integers)
[FilledInDuringResolution] bool RedirectingTypeDecl.ConstraintIsCompilable { get; set; }
[FilledInDuringResolution] public bool NativeTypeRangeImpliesAllConstraints; // indicates that all values in the range of the native type are values of the newtype
[FilledInDuringResolution] public bool TargetTypeCoversAllBitPatterns; // "target complete" -- indicates that any bit pattern that can fill the target type is a value of the newtype
public NewtypeDecl(RangeToken rangeToken, Name name, ModuleDefinition module, Type baseType, List<Type> parentTraits,
List<MemberDecl> members, Attributes attributes, bool isRefining)
: base(rangeToken, name, module, new List<TypeParameter>(), members, attributes, isRefining, parentTraits) {
Contract.Requires(rangeToken != null);
Contract.Requires(name != null);
Contract.Requires(module != null);
Contract.Requires(isRefining ^ (baseType != null));
Contract.Requires(members != null);
BaseType = baseType;
this.NewSelfSynonym();
}
public NewtypeDecl(RangeToken rangeToken, Name name, ModuleDefinition module, BoundVar bv, Expression constraint,
SubsetTypeDecl.WKind witnessKind, Expression witness, List<Type> parentTraits, List<MemberDecl> members, Attributes attributes, bool isRefining)
: base(rangeToken, name, module, new List<TypeParameter>(), members, attributes, isRefining, parentTraits) {
Contract.Requires(rangeToken != null);
Contract.Requires(name != null);
Contract.Requires(module != null);
Contract.Requires(bv != null && bv.Type != null);
Contract.Requires((witnessKind == SubsetTypeDecl.WKind.Compiled || witnessKind == SubsetTypeDecl.WKind.Ghost) == (witness != null));
Contract.Requires(members != null);
BaseType = bv.Type;
Var = bv;
Constraint = constraint;
Witness = witness;
WitnessKind = witnessKind;
this.NewSelfSynonym();
}
/// <summary>
/// Return .BaseType instantiated with "typeArgs", but only look at the part of .BaseType that is in scope.
/// </summary>
public Type RhsWithArgument(List<Type> typeArgs) {
Contract.Requires(typeArgs != null);
Contract.Requires(typeArgs.Count == TypeArgs.Count);
var scope = Type.GetScope();
var rtd = BaseType.AsRevealableType;
if (rtd != null) {
Contract.Assume(rtd.AsTopLevelDecl.IsVisibleInScope(scope));
if (!rtd.IsRevealedInScope(scope)) {
// type is actually hidden in this scope
return rtd.SelfSynonym(typeArgs);
}
}
return RhsWithArgumentIgnoringScope(typeArgs);
}
/// <summary>
/// Returns the declared .BaseType but with formal type arguments replaced by the given actuals.
/// </summary>
public Type RhsWithArgumentIgnoringScope(List<Type> typeArgs) {
Contract.Requires(typeArgs != null);
Contract.Requires(typeArgs.Count == TypeArgs.Count);
// Instantiate with the actual type arguments
if (typeArgs.Count == 0) {
// this optimization seems worthwhile
return BaseType;
} else {
var subst = TypeParameter.SubstitutionMap(TypeArgs, typeArgs);
return BaseType.Subst(subst);
}
}
public TopLevelDecl AsTopLevelDecl => this;
public TypeDeclSynonymInfo SynonymInfo { get; set; }
public TypeParameter.EqualitySupportValue EqualitySupport {
get {
if (this.BaseType.SupportsEquality) {
return TypeParameter.EqualitySupportValue.Required;
} else {
return TypeParameter.EqualitySupportValue.Unspecified;
}
}
}
string RedirectingTypeDecl.Name { get { return Name; } }
IToken RedirectingTypeDecl.tok { get { return tok; } }
Attributes RedirectingTypeDecl.Attributes { get { return Attributes; } }
ModuleDefinition RedirectingTypeDecl.Module { get { return EnclosingModuleDefinition; } }
BoundVar RedirectingTypeDecl.Var { get { return Var; } }
Expression RedirectingTypeDecl.Constraint { get { return Constraint; } }
SubsetTypeDecl.WKind RedirectingTypeDecl.WitnessKind { get { return WitnessKind; } }
Expression RedirectingTypeDecl.Witness { get { return Witness; } }
FreshIdGenerator RedirectingTypeDecl.IdGenerator { get { return IdGenerator; } }
bool ICodeContext.IsGhost {
get { throw new NotSupportedException(); } // if .IsGhost is needed, the object should always be wrapped in an CodeContextWrapper
}
List<TypeParameter> ICodeContext.TypeArgs { get { return new List<TypeParameter>(); } }
List<Formal> ICodeContext.Ins { get { return new List<Formal>(); } }
ModuleDefinition IASTVisitorContext.EnclosingModule { get { return EnclosingModuleDefinition; } }
bool ICodeContext.MustReverify { get { return false; } }
bool ICodeContext.AllowsNontermination { get { return false; } }
string ICallable.NameRelativeToModule { get { return Name; } }
Specification<Expression> ICallable.Decreases {
get {
// The resolver checks that a NewtypeDecl sits in its own SSC in the call graph. Therefore,
// the question of what its Decreases clause is should never arise.
throw new cce.UnreachableException();
}
}
bool ICallable.InferredDecreases {
get { throw new cce.UnreachableException(); } // see comment above about ICallable.Decreases
set { throw new cce.UnreachableException(); } // see comment above about ICallable.Decreases
}
public override bool AcceptThis => true;
public override bool IsEssentiallyEmpty() {
// A "newtype" is not considered "essentially empty", because it always has a parent type to be resolved.
return false;
}
public string GetTriviaContainingDocstring() {
IToken candidate = null;
foreach (var token in OwnedTokens) {
if (token.val == "{") {
candidate = token.Prev;
if (candidate.TrailingTrivia.Trim() != "") {
return candidate.TrailingTrivia;
}
}
}
if (candidate == null && EndToken.TrailingTrivia.Trim() != "") {
return EndToken.TrailingTrivia;
}
return GetTriviaContainingDocstringFromStartTokenOrNull();
}
public ModuleDefinition ContainingModule => EnclosingModuleDefinition;
public bool ShouldVerify => true; // This could be made more accurate
}
public class NativeType {
public readonly string Name;
public readonly BigInteger LowerBound;
public readonly BigInteger UpperBound;
public readonly int Bitwidth; // for unassigned types, this shows the number of bits in the type; else is 0
public enum Selection { Byte, SByte, UShort, Short, UInt, Int, Number, ULong, Long }
public readonly Selection Sel;
public NativeType(string Name, BigInteger LowerBound, BigInteger UpperBound, int bitwidth, Selection sel) {
Contract.Requires(Name != null);
Contract.Requires(0 <= bitwidth && (bitwidth == 0 || LowerBound == 0));
this.Name = Name;
this.LowerBound = LowerBound;
this.UpperBound = UpperBound;
this.Bitwidth = bitwidth;
this.Sel = sel;
}
}
public interface RevealableTypeDecl {
TopLevelDecl AsTopLevelDecl { get; }
TypeDeclSynonymInfo SynonymInfo { get; set; }
}