Is there any way to control the naming convention Dafny uses for the target code?
Is it possible to use a symbolic constant globally? Something like this:
? global const MaxValue = 10000; ?
method Method1 (a : int) returns (b : int)
requires a < MaxValue
Is there any way to convert a numeric expression to string?
Yes and yes.
To control the names of various entities that Dafny uses in the target code, use the {:extern "ThisIsTheNameIWant"} attribute. This attribute is supported on most declarations. For example, you can put one on a class and another on a method inside the class. For more examples, see the Test/dafny0/Extern.dfy file in the Dafny test suite. If you want to look at what is generated, use the /spillTargetCode:1 flag from the command line.
For constants, use:
const MaxValue := 10000
(Note, until recently, you had to supply the type of constants explicitly, so you had to write
const MaxValue: int := 10000
If you're building the latest version of Dafny from sources, the type is inferred from the right-hand side expression.)
A nifty feature, borrowed from Ada language, is that you can insert an underscore between any two digits in numeric literals. If you work with large literals with a bunch a zeros in them, then this makes it easier for your eyes to see that you have written the correct number. For example:
const MaxValue := 10_000
const PhoneNumber := 512_555_1212
const SignedInt32Limit := 0x8000_0000
Rustan
Related
I have the below record generic, which overrides the Equality operator.
The idea was to get some compile-time validation, as in the example below:
TpColumn<T> = record
class operator Equal (aLeft: TpColumn<T>; aRight: String): TRec;
class operator Equal (aLeft: TpColumn<T>; aRight: Integer): TRec;
end;
function FormCreate;
var vStrRec: TpColumn<String>;
vIntRec: TpColumn<Integer>;
begin
vCond1 := vStrRec = 'hello'; // should accept
vCond2 := vIntRec = 5; // should accept
vCond1 := vStrRec = 5; // should reject, currently accepted
end;
I could define TpColumnInt and TpColumnStr as distinct types, each its equality override (and it works), but I would like to define an array of TpColumn< T > regardless of the type T.
It isn't possible to use inheritance with records.
It isn't possible to define an array that contains different types (hence generics).
It isn't possible to override operators in classes (hence records).
The natural conclusion I've reached so far is Generic Records:
can put TpColumn< String > and TpColumn< Integer > in the same array.
EDIT: i understand that I was mistaken in this assumption, guess this approach won't work then.
can overload operators
The final piece of the puzzle that still needs to be fulfilled is compile-time checking in the Equal override. Where can I add such constraint that would solve this?
I was hoping something like this would do the trick, but it did not:
aLeft: TpColumn< String >; aRight: String
"operator Equal must take at least one TpColumn< T > type in parameters" - the compiler.
Is this achievable the way I'm trying? And if not, is there any other way to achieve it?
How can I make a single constant based on a hex value where that hex value is an unsigned integer and the raw memory for the single. I would like to do something like this but it doesn't compile and this will try and cast the hex value to a single and then store the result of that cast instead of storing hex value itself:
LARGEST_SINGLE_LESS_THAN_ZERO = Single($80800000);
I get a "Invalid Typecast" error.
For example:
The single value for 1 is stored as $3F800000 in memory. I would like to be able to create a const that lets me set the value using $3F800000 instead of 1.
I have also tried other variations such as this without luck:
LARGEST_SINGLE_LESS_THAN_ZERO = PSingle(#$80800000)^;
Background
I have a method that I use to get the next smallest single when provided with a single value:
type
PInt32 = ^Int32;
function NextBefore(const aValue: Single): Single;
var
int32Value: Int32;
begin
// this function ignores special values nan/inf
int32Value := PInt32(#aValue)^;
if (UInt32(int32Value) = $80000000) or (int32Value = 0) then
begin
// special handling needed for -0 and 0. We need to go to the smallest
// negative number.
int32Value := $80800000;
end
else
begin
if int32Value >= 0 then
Dec(int32Value)
else
Inc(int32Value);
end;
Result := PSingle(#int32Value)^;
end;
This is really useful because we use vector operations that can only do a > or < so we use it to do the equivalent of a >= and a <=. We often check against 0. So where we need get all of the data >= 0 we do something like this:
MyVector.ThresholdGT(NextBefore(0));
It would be nicer to provide the other developers with a constant for these types of operations. Trying to use the PSingle format below won't work because the number is not a variable.
In order to declare a single constant with a hex value in such a way that it cannot be altered by code, it can be done in two steps:
const
iLARGEST_SINGLE_LESS_THAN_ZERO : Int32 = $80800000;
var
LARGEST_SINGLE_LESS_THAN_ZERO : Single absolute iLARGEST_SINGLE_LESS_THAN_ZERO;
Trying to change the value of LARGEST_SINGLE_LESS_THAN_ZERO will give a compiler error: Left side cannot be assigned to.
It's hard to do this cleanly with the constraints of the language. Perhaps the best that you can do is to make a variant record type that has both integer and single fields overlapped.
type
TSingleIntegerVariantRec = record
case Integer of
0: (I: Integer);
1: (S: Single);
end;
Once you have that type available you can declare typed constants using the integer field, but then read the single field.
const
LARGEST_SINGLE_LESS_THAN_ZERO: TSingleIntegerVariantRec = (I: $80800000);
....
MyVector.ThresholdGT(LARGEST_SINGLE_LESS_THAN_ZERO.S);
If you want to add an extra nuance you could implement an implicit cast operator to Single which would allow you to omit the .S. If you made that operator inline then I suspect the emitted code would be very efficient.
This does what you ask, but I wouldn't claim that it was very elegant. We're I you I would move the code to use the next value down into the library function so that you can pass 0 and shield the consumer of the library from these implementation details.
In other words you would add a ThresholdGTequal method that was implemented like this:
procedure TMyVector.ThresholdGTequal(const Value: Single);
begin
ThresholdGT(NextBefore(Value));
end;
Then the consumers of this code simply write:
MyVector.ThresholdGTequal(0);
and remain oblivious to all of the gnarly implementation details.
Consider the following program:
{$APPTYPE CONSOLE}
type
TMyEnum = (enum1, enum2, enum3);
var
Arr: TArray<TMyEnum>;
Enum: TMyEnum;
begin
Arr := [enum3, enum1]; // <-- this is an array
for Enum in Arr do
Writeln(ord(Enum));
Writeln('---');
for Enum in [enum3, enum1] do // <-- this looks very much like the array above
Writeln(ord(Enum));
Writeln('---');
Readln;
end.
The output is:
2
0
---
0
2
---
Why do the two loops produce different output?
Because an array contains order information and a set does not.
Explanation with the use of documentation:
The internal data format of a static or dynamic array:
is stored as a contiguous sequence of elements of the component type of the array. The components with the lowest indexes are stored at the lowest memory addresses.
Walking over these indices with a for in loop is done in incremental order:
The array is traversed in increasing order, starting at the lowest array bound and ending at the array size minus one.
On the other side, the internal data format of a set:
is a bit array where each bit indicates whether an element is in the set or not.
Thus all these "indiced bits" are stored in one and the same "value". That is why a set can be typecasted to an Integer type, and why the order in which the bits are added is lost: [enum3, enum1] = [enum1, enum3].
for Enum in Arr do
Writeln(ord(Enum));
Here, Arr is an array, and so the items of the array are output in order. The documentation says:
The array is traversed in increasing order.
Hence 2 is output before 0.
for Enum in [enum3, enum1] do
Writeln(ord(Enum));
Here, [enum3, enum1] is a set and the enumerator for a set happens to enumerate in order of increasing ordinal value. So the output has 0 first.
I don't think that is stated anywhere in the documentation that sets are enumerated in that order, but empirically that appears to be the case. However, since sets are an unordered type one should not be relying on their enumeration order anyway.
So the question then becomes understanding how [...] can be a set or an array at different points in the code. This all stems from the new XE7 dynamic array syntax which introduces (another) syntactical ambiguity. When we write
Arr := [enum3, enum1];
then [enum3, enum1] is an array. The compiler knows that Arr is an array and that information defines the type of the literal.
But when we write
for Enum in [enum3, enum1] do
then [enum3, enum1] is a set. Here the literal could in principle be either array or set. In such situations, I believe that the compiler will always prefer sets.
Again, I can't find any documentation that states that this is so, but empirically this is the case. Presumably since set enumerators pre-date the new dynamic array syntax they take precedence when there is ambiguity.
The meaning of a literal of the form [...] depends on its context.
While not always ideal, the compiler is using context to determine the type of the right hand side. You can look at character strings as a good example of this:
If constantExpression is a character string, the declared constant is compatible with any string type. If the character string is of length 1, it is also compatible with any character type.
In the character string case, the compiler will use the left hand side to determine the type of the right hand side. The difference between this and the code in the question is that this case is clearly documented whereas the case in the question is not.
An example using characters:
{$APPTYPE CONSOLE}
uses
SysUtils, Classes;
var
A: Char;
B: AnsiChar;
begin
A := 'a';
B := 'a';
Writeln(A);
Writeln(B);
Readln;
end.
The assembler generated from the two indicates that the right hand side is being treated differently in the two cases:
Project10.dpr.17: A := 'a';
004D6731 66C705C8034E006100 mov word ptr [$004e03c8],$0061
Project10.dpr.18: B := 'a';
004D673A C605CA034E0061 mov byte ptr [$004e03ca],$61
The compiler is using the destination type of the assignment to determine what type the character string (in this case 'a') should be. A similar thing is happening in the question.
Thanks to David for the additional information in the comments
I need to browse all published properties of some classes.
Properties where the type is an enumeration with fixed values are not listed.
See example below:
TMyEnum = (meBlue, meRed, meGreen);
TMyEnumWithVals = (mevBlue=1, mevRed=2, mevGreen=3);
TMyClass =
...
published
property Color: TMyEnum read FColor write SetColor; // This one is found
property ColorVal: TMyEnumWithVals read FColorVal write SetColorVal; // This one is never found
end;
I need fixed values because these properties are stored in a database and I need to ensure that allocated values will always be the same, regardless of Delphi compiler choices in next versions, and prevent any misplaced insert of future values in the enumeration list.
I tried with both new Delphi 2010 RTTI (with .GetDeclaredProperties) and "old" RTTI (with GetPropInfos): all properties are found except the above type of property.
The same behaviour is seen on all classes. I also reproduced this in a sample project.
Tried with and without various RTTI directives without change.
Is this a bug, a known limitation?
Is there a workaround (except removing fixed values of the enumeration)?
Using Delphi2010 Ent+Update5
[Edit] The answer below provides the workaround: The first value of the enumeration must be set to 0 instead of 1, and values contiguous. Tested and working solution.
Thanks,
Barry Kelly says:
Discontiguous enumerations and enumerations which don't start at zero don't have typeinfo. For typeinfo to be implemented, it would need to be in a different format from the existing tkEnumeration, owing to backward compatibility issues.
I considered implementing a tkDiscontiguousEnumeration (or possibly better named member) for Delphi 2010, but the benefit seemed small considering their relative scarcity and the difficulties in enumeration - how do you encode the ranges efficiently? Some encodings are better for some scenarios, worse for others.
So it's not a bug, but a known limitation.
This is a limitation. Enumerated types with explicit ordinality can not have RTTI. Documented here.
Possible solution is to declare Reserved values within your enumerated type, eg:
TMyEnum = (meReserved1, meBlue, meRed, meGreen, meReserved2, meWhite); // and so on
...
Assert(MyEnum in [meBlue..meGreen, meWhite], 'sanity check failed')
Practical enums tends to occupy contiguous ranges, so you probably will not end up in having declaring gazillions of reserved values. In case you are interoperating with C style bitfields you will have to split value to distinct enums and sets.
To add some more background information, Enums with values, are treated as subrange types with predefined constants.
For example:
type
TMyEnumWithVals = (mevBlue=1, mevRed=2, mevGreen=3);
Is treated as:
type
TMyEnumWithVals = 1..3;
const
mevBlue : TMyEnumWithVals = 1;
mevRed : TMyEnumWithVals = 2;
mevGreen : TMyEnumWithVals = 3;
However, you can't combine these with integers without casting.
var
enum : TMyEnumWithVals;
ival : Integer;
begin
enum := mevBlue;
ival := Integer(mevRed);
To make matters worse, if you use:
type
TTypeId = (tidPrimary = 100, tidSecundary = 200, tidTertiary = 300);
TTypeArray = array [TTypeID] of string;
You get an array of 201 elements, not of 3. You can use the values in between using:
var
enum : TTypeId ;
ival : Integer;
begin
enum := TTypeId(150); // Is valid.
This information can be found in the Delphi language guide, with the enum type section.
1) Does anyone know if it is possible to loop through an irregular enumeration in Delphi (XE)?
Looping over a normal enumeration is ok. From Delphi Basics:
var
suit : (Hearts, Clubs, Diamonds, Spades);
begin
// Loop 3 times
For suit := Hearts to Diamonds do
ShowMessage('Suit = '+IntToStr(Ord(suit)));
end;
But, if 'suit' instead is declared as
var
suit : (Hearts=1, Clubs, Diamonds=10, Spades);
it loops 10 times. Not suprising, but I would like to loop 3. The only solution I've found so far is converting an enumeration to a set and use the 'for ... in'-loop like on delphi.about.com.
So, if answer to question 1) is no, then:
2) How to convert from enumeration to set in Delphi?
The context I am using it in is a component array of edit-boxes (TEdit) that has an irregular numbering (edit1, edit5, edit7, edit3, ...). While it is possible to reorder all the edit-boxes, it removes the reason of using enumeration as a flexible way to allow addition of an edit-box in the middle of the enumeration.
I do not have a Delphi compiler at hand right now, but I tink that gabr's approach can be rather significantly improved by doing
type
TSuit = (Hearts = 1, Clubs, Diamonds = 10, Spades);
const
Suits: array[0..3] of TSuit = (Hearts, Clubs, Diamonds, Spades);
Who knows, maybe it doesn't even compile.
type
TSuit = (Hearts=1, Clubs, Diamonds=10, Spades);
var
suit: TSuit;
suitEnum: array [1..4] of TSuit;
//initialization
suitEnum[1] := Hearts;
suitEnum[2] := Clubs;
suitEnum[3] := Diamonds;
suitEnum[4] := Spades;
for suit in suitEnum do
DoSomething(suit);
I always use
var
s: TSuit;
begin
for s := Low(TSuit) to High(TSuit) do
{something};
end;
Loop using Ord(Hearts) to Ord(Spades) ?
A dirty option, useful for small enumerations:
type
TSuit = (Hearts = 1, Clubs, Diamonds = 10, Spades);
var
Suit: TSuit;
begin
for Suit in [Hearts, Clubs, Diamonds] do
WriteLn(Ord(Suit));
Works nice in Delphi 2007. Don't know about older versions. Be aware, using for Suit in [Hearts..Diamonds] do has the same problem as your loop.Btw, I use WriteLn() because I tested this in a console application. :-)
It should be understood (and often isn't) that the moment you put hard ordinal assignments into an enumeration, it ceases for all intents to be a Pascalian enumerated type - it just becomes a "bag of constants", which is not the same thing. This is what C-programmers call enumerations. However, a Pascalian enumerated type is ORDINAL in all criterion: It has discrete consecutive values that respond meaningfully to the base operations ORD, PRED, SUCC. Enumerations in C don't do this, and neither do enums in Pascal once you force the ordinals apart.
THIS is the reason that Delphi's RTTI basically refuses to return type information once this has been done. To all intents the type is essentially a tkUnknown, and has to be treated as a 'bag' of compile-time constants. It is only because it still plays lip service to being an ordinal and has (sometimes shaky) support for use in sets that people are led into believing it should still behave like a proper enumerated type. It's better to just understand it for what it really is: a nod to enumerated values in C. Avoid mixing the coding metaphor!
If you do this, then your solution becomes obvious: you use an enumerated type (a proper one) to index a corresponding array of CONSTANTS. Then you can make the ordinals whatever you want, and the enums retain their full RTTI definitions as a proper enumeration. So: your ENUMERATED TYPE contains proper unchanged ordinal values. You get your funny numbers by indexing the constants array using the enumeration -ergo array [MyEnums] of byte = (1,3,8,22,99,whatever)