A user recently posted a question, and deleted it (perhaps because we were less than welcoming). Effectively, this was the problem: compiling with gnatmake -gnatwl person_1.adb, the result was
1. with Ada.Text_IO; use Ada.Text_IO;
2. with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
3. procedure Person_1 is
4. type String is
5. array (Positive range <>) of Character;
6. S: String (1..10);
7. begin
8. Put("Write a name: ");
9. Get(S);
1 6
>>> no candidate interpretations match the actuals:
>>> missing argument for parameter "Item" in call to "Get" declared at a-tiinio.ads:90, instance at a-inteio.ads:18
>>> missing argument for parameter "Item" in call to "Get" declared at a-tiinio.ads:51, instance at a-inteio.ads:18
>>> missing argument for parameter "Item" in call to "Get" declared at a-textio.ads:451
>>> missing argument for parameter "Item" in call to "Get" declared at a-textio.ads:378
>>> expected type "Standard.Integer"
>>> found type "String" defined at line 4
>>> ==> in call to "Get" at a-tiinio.ads:59, instance at a-inteio.ads:18
>>> ==> in call to "Get" at a-textio.ads:454
>>> ==> in call to "Get" at a-textio.ads:381
10. end Person_1;
which is quite confusing. What’s going on?
The trouble is, this code defines its own type String, which hides the standard type String. Ada.Text_IO.Get expects a parameter of the standard String type, but it’s actually been given a parameter of the local String type.
The Ada Wikibook says, under the bullet point Name Equivalence,
Two types are compatible if and only if they have the same name; not if they just happen to have the same size or bit representation. You can thus declare two integer types with the same ranges that are totally incompatible, or two record types with exactly the same components, but which are incompatible.
But, these two types do have the same name! (String). Don’t they?
The reason that they don’t, after all, is that the fully qualified names are actually different. Get expects Standard.String (ARM A.1(37)), but the local version is Person_1.String.
You might have hoped that -gnatwh (turn on warnings for hiding declarations) would report this, but unfortunately not.
I’m not sure why the compiler only reports the failed match within Ada.Integer_Text_IO (with Integer); if we remove this with and use (it isn’t used, after all), things become much more helpful,
1. with Ada.Text_IO; use Ada.Text_IO;
2. -- with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
3. procedure Person_1 is
4. type String is
5. array (Positive range <>) of Character;
6. S: String (1..10);
7. begin
8. Put("Write a name: ");
9. Get(S);
1 4
>>> no candidate interpretations match the actuals:
>>> missing argument for parameter "Item" in call to "Get" declared at a-textio.ads:451
>>> missing argument for parameter "Item" in call to "Get" declared at a-textio.ads:378
>>> expected type "Standard.String"
>>> found type "String" defined at line 4
>>> ==> in call to "Get" at a-textio.ads:454
>>> ==> in call to "Get" at a-textio.ads:381
10. end Person_1;
Related
I'm a very beginner of Ada code. I use GPS from AdaCore.
I would create a variable sized by the user.
I write this :
-- My ada program --
with Ada.Text_IO, Ada.Integer_Text_IO;
use Ada.Text_IO, Ada.Integer_Text_IO;
procedure main is
wanted : Integer := 10;
type custom is range 0..wanted;
...
But something went wrong in line 8 :
Builder results
C:\Users\**********\Desktop\ada project\src\main.adb
8:26 "wanted" is not static constant or named number (RM 4.9(5))
8:26 non-static expression used for integer type bound
I really don't understand what this mean... Can someone help me ?
Variable wanted is not a constant, it may change its value during program execution, therefore this variable is not allowed to be used as range constraint when declaring new types. You may however make it constant by using constant keyword (Wanted : constant Integer := 10;). It should resolve your problem.
As said by Timur, wanted has to be constant in its scope. This allows you some nice things such as declaring a type inside a procedure. Look at this, it might be of interest :)
-- My ada program --
with Ada.Text_IO, Ada.Integer_Text_IO;
use Ada.Text_IO, Ada.Integer_Text_IO;
procedure Main is
procedure Test (Wanted : Integer) is
type custom is new Integer range 0..wanted;
begin
Put_Line("First value " & Custom'Image (Custom'First)
& " Last value " & Custom'Image (Custom'Last));
end Test;
begin
Test (10);
Test (12);
end Main;
Output is
First value 0 Last value 10
First value 0 Last value 12
In this case, your type is different from one call to another but it works as wanted is constant within the procedure. The only thing is that the type defined has to be a new derived type of the type of your parameter.
I let you think about the possibilities :)
Porting some old code to a newer CentOs Linux machine.
I am using linux gnat with a couple of flags:
Default_Switches ("ada") use ("-fstack-check", "-g", "-gnatVr", "-gnato", "-gnatE", "-gnatwmuv", "-gnata", "-m32");
and I have the gnat version:
gcc-gnat.i686 4.8.5-11.el7
So these are the preconditions.
I have now an for sure working self-written storage manager which is called by
St_Wa.Alloc(StoragePool, BitSize)
So now to my problem and to be honest I do not really get the point why the compiler is failing, so I would be really grateful for a detailed explanation why it is not working!
function AllocMem(StoragePool : in St_Wa.Mem_Pool_Type;
Option: in Option_Type)
return Option_Ref is
subtype New_Type is Option_Type (Option.Kind);
New_Option : New_Type;
for New_Option use at St_Wa.Alloc( StoragePool => StoragePool,
BitSize => New_Type'Size)
begin
Bl_Bl.Move( ... sth happens here ... )
return Pointer(New_Option'Address);
end AllocMem;
Whereas:
type Option_Type ( Kind : Option_Kind_Type := Marker) is
record
Next : Option_Ref;
case Kind is
when First_Procedure => First_Procedure : First_Procedure_Type;
when Sec_Procedure => Sec_Procedure : Sec_Procedure_Type;
end case;
end record;
And I get the following Error:
invalid address clause for initialized object "New_Option"
function "Alloc" is not pure (RM 13.1 (22))
Do I get this error because I have a switch case in the type with conditions and therefore the size is only determined depending on kind? How can I avoid this without rewriting everything?
Do I get this error because I have a switch case in the type with conditions and therefore the size is only determined depending on kind?
No. The paragraph referenced by the error message (RM 13.1 (22)) in the LRM reads:
An implementation need not support representation items containing nonstatic expressions, except that an implementation should support a representation item for a given entity if each nonstatic expression in the representation item is a name that statically denotes a constant declared before the entity.
Now, the representation item here is the call to Alloc since your code:
for New_Option use at St_Wa.Alloc(StoragePool => StoragePool,
BitSize => New_Type'Size);
is Ada83-style for
for New_Option'Address use St_Wa.Alloc(StoragePool => StoragePool,
BitSize => New_Type'Size);
And since Alloc (...) is a function call, it is not a static expression, since static functions are, according to RM 4.9:
a predefined operator whose parameter and result types are all scalar types none of which are descendants of formal scalar types;
a predefined concatenation operator whose result type is a string type;
an enumeration literal;
a language-defined attribute that is a function, if the prefix denotes a static scalar subtype, and if the parameter and result types are scalar.
Since Alloc is none of the above, as RM 13.1 states, the implementation does not need to support it in the representation item. However, the actual error message tells us that "Alloc" is not pure, so GNAT tells it it would support this if Alloc was pure.
So one way to fix this would be to make Alloc pure, which means: Add pragma Pure; to the package St_Wa, which contains Alloc. Whether this is possible depends on the package and it might require additional changes.
If this is not feasible, RM 13.1 (22) hints at another way: A nonstatic expression should be supported if it denotes a constant declared before the entity. Thus, this should work:
My_Address : constant System.Address :=
St_Wa.Alloc(StoragePool => StoragePool, BitSize => New_Type'Size);
New_Option : New_Type;
for New_Option use at My_Address;
I want to generate a Dict with undef values so I can later loop over the keys and fill in correct values. I can initialise an such a Dict using concrete types in the following way and it all works fine:
currencies = ["USD", "AUD", "GBP"]
struct example
num::Float64
end
undef_array = Array{example}(undef,3)
Dict{String,example}(zip(currencies, undef_array))
When my struct has an abstract type however I can still generate the undef array but I cannot create the dict. I get an error "UndefRefError: access to undefined reference"
abstract type abstract_num end
struct example2
num::abstract_num
end
undef_array = Array{example2}(undef,3)
Dict{String,example2}(zip(currencies, undef_array))
Although it is possible to create such a Dict with a concrete array:
struct numnum <: abstract_num
num::Float64
end
def_array = [example2(numnum(5.0)), example2(numnum(6.0)), example2(numnum(4.5))]
Dict{String,example2}(zip(currencies, def_array))
Question
My question is whether it is possible to generate a Dict with undef values of a type that relies on an abstract type? Is it is possible what is the best way to do it?
In your second (not working) example, undef_array is an array whos elements aren't initialized:
julia> undef_array = Array{example2}(undef,3)
3-element Array{example2,1}:
#undef
#undef
#undef
The reason is that it's not possible to instantiate an object of type example2 because your abstract type abstract_num (the type of the field of example2) doesn't have any concrete subtypes and, thus, can't be instantiated either. As a consequence even indexing undef_array[1] gives an UndefRefError and, hence, also zip won't work.
Compare this to the first case where the array elements are (arbitrarily) initialized:
julia> undef_array = Array{example}(undef,3)
3-element Array{example,1}:
example(1.17014136e-315)
example(1.17014144e-315)
example(1.17014152e-315)
and undef_array[1] works just fine.
Having said that, I'm not really sure what you try to achieve here. Why not just create a mydict = Dict{String, example2}() and fill it with content when the time comes? (As said above, you would have to define concrete subtypes of abstract_num first)
For performance reasons you should, in general, avoid creating types with fields of an abstract type.
Try:
a=Dict{String,Union{example3,UndefInitializer}}(currencies .=>undef)
However, for representing missing values the type Missing is usually more appropriate:
b=Dict{String,Union{example3,Missing}}(currencies .=>missing)
Please note that typeof(undef) yields UndefInitializer while typeof(missing) yields Missing - hence the need for Union types in the Dict. The dot (.) you can see above (.=>) is the famous Julia dot operator.
Moreover, I recommend to keep to Julia's naming conversion - struct and DataType names should start with a Capital Letter.
Last but not least, in your first example where concrete type Float64 was given, Julia has allocated the array to some concrete address in memory - beware that it can contain some garbage data (have a look at console log below):
julia> undef_array = Array{example}(undef,3)
3-element Array{example,1}:
example(9.13315366e-316)
example(1.43236026e-315)
example(1.4214423e-316)
With GNAT, I'm trying to print out System.Min_Int
Ada.Integer_Text_IO.Put(System.Min_Int);
Yields this:
"warning: value not in range of type "Ada.Text_Io.Integer_Io.Num" "
I also tried
Ada.Integer_Text_IO.Put_Line(Integer'Image(System.Min_Int));
Which yields:
value not in range of type "Standard.Integer"
How can I print System.Min_Int ?
System.Min_Int and System.Max_Int are named numbers. Logically they are of type universal_integer. They can be implicitly converted to an integer type (just like integer constants like 42), but of course the type needs to be big enough to hold it.
There is no predefined integer type that's guaranteed to be able to hold the values of System.Min_Int and System.Max_Int. An implementation isn't even required to define Long_Integer, and Integer is only required to be at least 16 bits.
Fortunately it's easy to define your own integer type with the necessary range.
with Ada.Text_IO;
with System;
procedure Min_Max is
type Max_Integer is range System.Min_Int .. System.Max_Int;
begin
Ada.Text_IO.Put_Line("System.Min_Int = " & Max_Integer'Image(System.Min_Int));
Ada.Text_IO.Put_Line("System.Max_Int = " & Max_Integer'Image(System.Max_Int));
end Min_Max;
The output on my system:
System.Min_Int = -9223372036854775808
System.Max_Int = 9223372036854775807
Confusingly, System.Min_Int in at least one recent Gnat, appears to be a Long_Integer (though as Simon points out, it is actually Long_Long_Integer, and on some compilers but not all, these have the same range).
So, the following works (in gcc4.9.3):
Put_Line(Long_Integer'Image(System.Min_Int));
reporting -9223372036854775808.
And so does Ada.Long_Integer_Text_IO.Put(System.Min_Int);
On the other hand, you may have been trying to find the minimum value of the Integer type, which is ...Integer'First, and sure enough,
Put_Line(Integer'Image(Integer'First));
reports -2147483648
The rationale for the difference is that Ada can support an uncountable number of integer types, but provides a few default ones like Integer for convenience.
System.Min_Int and friends reflect the limits of your specific system : attempting to declare larger integer types is legal, but will not compile on your system (i.e. until you upgrade the compiler).
In normal use, you will either use Integer or better, integer typ4es you declare with ranges appropriate to your problem. And the limits of each such type obviously can't be built into the language or even the System package. Instead, you use the predefined attributes, such as 'First and 'Last to query the relevant integer type.
So you can explore your machine's limits with the following:
with Ada.Text_IO; use Ada.Text_IO;
with System;
procedure pmin is
type Big_Integer is range System.Min_Int ..System.Max_Int;
package Big_Integer_IO is new Integer_IO(Num => Big_Integer);
begin
Big_Integer_IO.Put(System.Min_Int);
Put(" to ");
Big_Integer_IO.Put(System.Max_Int);
New_Line;
end pmin;
Here (gcc4.9.3) I get the result:
-9223372036854775808 to 9223372036854775807
If System.Min_Int is no longer in the range of Long_Integer in Gnat/gcc 6.1 I'm curious to see what this does on your system. Please add your test result in a comment.
I get Subtype mark required in this context at (*). What exactly is subtype mask and why is it complaining here?
main.adb
(*)Open_Route : Route(1..3) := (others => new Location(X=>1.0,Y=>1.0, id=>1));
-- Closed_Route : Route (Open_Route'First .. Open_Route'Last + 1);
-- P1 : Population (1..2);
Location.ads package spec
type Location is record
Id : Positive;
X : Float;
Y : Float;
end record;
type Location_Acess is access all Location;
type Route is array (Positive range<>) of Location_Acess;
type Route_Acess is access all Route;
type Population is array (Positive range<>) of Route_Acess;
A subtype_mark is basically a name that denotes a type or subtype (ARM 3.2.2(4)). The reason why the ARM uses subtype_mark throughout is to do with some arcane distinction (ARM 3.2.1); when you say type Foo is you are declaring both a type and its first subtype, and the name Foo refers to the first subtype.
I think your problem is that you have a package Location containing an entity of the same name, and that this has confused the compiler.
You haven’t supplied a complete compilable code example, but reading between the lines I think it’d be something like this, after applying #ajb’s suggestion:
package Location is
type Location is record
Id : Positive;
X : Float;
Y : Float;
end record;
type Location_Acess is access all Location;
type Route is array (Positive range<>) of Location_Acess;
type Route_Acess is access all Route;
type Population is array (Positive range<>) of Route_Acess;
end Location;
with Location; use Location;
package Location_User is
Open_Route : Route(1..3) := (others => new Location'(X=>1.0,Y=>1.0, id=>1));
end Location_User;
and the compiler error message would be
location_user.ads:3:47: subtype mark required in this context
location_user.ads:3:47: found "Location" declared at location.ads:1
(see how it’s telling you to look at line 1 of location.ads, the package name?)
You could work round this by saying new Location.Location, but then you’d need to say it everywhere.
There are two canonical solutions, and there is a religious divide between the supporters of the two camps.
The first (my preferred one) would be to call the package Locations and leave the types Location, Route, Population as they are.
The second (which I consider ugly and would only use in dire need) would be to decorate type names with a suffix:
type Location_Type is
or
type Location_T is
The source code given in the question is not complete (you did not state whether you used or merely withed the Location package. I assume the latter since (at least with the compiler I have installed) the error message given is invalid constraint: type has no discriminant.
#ajb has already pointed out the solution to that problem: without the quote mark, the compiler looks for a type with a discriminant (a type parameterised by another type), but Location does not have a discriminant.
Moreover, unless you used the Location package, new Location does not actually refer to a type (or subtype), but to a package. If you do not want to use Location, type
new Location.Location'(… here. One way to avoid such errors (and get better error messages) is to use different names for packages and type: when both have the same name, it is not always intuitively clear how the compiler interprets the occurrence of the name, and when the opinions of compiler and programmer differ, confusion ensues.
Personally, I like to use the plural for for the package, so in this case, there would be a package Locations containing the type Location, but there are other possibilities.