I am trying to print an integer in Ada83 .All the web sites have the info regarding Ada95 way of printing i.e Integer_Text_IO.Put (C); but this does not get compiled in Ada83. How Do I print an Integer in Ada83(Its a course requirement )?
Integer_Text_IO is an instantiation of Integer_IO, provided in the standard library in Ada 95.
In Ada 83, the generic package Integer_IO exists; you just have to instantiate it yourself.
(You can also use Integer'Image, but that adds an annoying leading space for non-negative values.)
(I'm not going to show code because you say it's a school assignment.)
Related
Posting for two reasons: (1) I was stuck on unhelpful compiler errors for far too long for such a simple issue and I want the next person to google those messages to come upon my (or other) answers, and (2) I still don't understand disallowing a use clause, so my own answer is really incomplete.
In order to call a program in two places with mostly the same arguments, I want to use the '&' to append to a default list inline:
declare
Exit_Code : constant Integer := GNAT.OS_Lib.Spawn (Program_Name => "gprbuild", Args => (Default_GPR_Arguments & new String'(File_Name_Parameter)));
begin
if Exit_Code /= 0 then
raise Program_Error with "Exit code:" & Exit_Code'Image;
end if;
end;
However, the compiler complains that System.Strings.String_List needs a use clause:
operator for type "System.Strings.String_List" is not directly visible
use clause would make operation legal
But inserting use System.Strings.String_List yields:
"System.Strings.String_List" is not allowed in a use clause
I also got this warning:
warning: "System.Strings" is an internal GNAT unit
warning: use "GNAT.Strings" instead
So I substituted GNAT for System in the with and the use clause and got an extra error in addition to the original 'you need a use clause for System.Strings.String_List' one:
"GNAT.Strings.String_List" is not allowed in a use clause
Why is GNAT.Strings.String_List not allowed in a use clause? Section 8.5 on use clauses doesn't seem to state anything on disallowed packages, so is this a compiler bug? Is it possible to define a new package that cannot have a use clause?
In a use clause of the form
use Name;
Name must be a package name. GNAT.Strings.String_List is a subtype name, not a package name.
There are a number of ways to invoke "&" for String_List. The simplest is to use the full name:
GNAT.Strings."&" (Left, Right)
but presumably you want to be able to use it as an operator in infix notation, Left & Right. Ways to achieve this, in decreasing specificity:
function "&" (Left : GNAT.Strings.String_List; Right : GNAT.Strings.String_List) return GNAT.Strings.String_List renames GNAT.Strings."&"; This makes this specific function directly visible.
use type GNAT.Strings.String_List; This makes all primitive operators of the type directly visible.
use all type GNAT.Strings.String_List; This makes all primitive operations of the type (including non-operator operations) directly visible.
use GNAT.Strings; This makes everything in the package directly visible.
Looks like it is a design decision. And many other packages in System follows this rule. From the s-string.ads (package specification for System.String):
-- Note: this package is in the System hierarchy so that it can be directly
-- be used by other predefined packages. User access to this package is via
-- a renaming of this package in GNAT.String (file g-string.ads).
My guess why this is done in that way: because it isn't in the Ada specification, but extension from GNAT.
I have a script to work out how much free stack space there is in each FreeRTOS task. GDB’s language is set to auto. The script works fine when the current language is c, but fails when the current language is ada.
I have, in the class Stacks,
tcb_t = gdb.lookup_type("TCB_t")
int_t = gdb.lookup_type("int")
used to:
find {Ada task control block}.Common.Thread,
thread = atcb["common"]["thread"]
convert to a pointer to the FreeRTOS task control block,
tcb = thread.cast(Stacks.tcb_t.pointer()).dereference()
find the logical top of the stack
stk = tcb["pxStack"].cast(Stacks.int_t.pointer())
Now I need to loop logically down the stack until I find an entry not equal to the initialised value,
free = 0
while stk[free] == 0xa5a5a5a5:
free = free + 1
which works fine if the current frame’s language is c, but if it’s ada I get
Python Exception <class 'gdb.error'> not an array or string:
Error occurred in Python command: not an array or string
I’ve traced this to the expression stk[free], which is being interpreted using the rules of the current language (in Ada, array indexing uses parentheses, so it would be stk(free), which is of course illegal since Python treats it as a function call).
I’ve worked round this by
def invoke(self, arg, from_tty):
gdb.execute("set language c")
...
gdb.execute("set language auto")
but it seems wrong not to set the language back to what it was originally.
So,
is there a way of detecting the current GDB language setting from Python?
is there an alternate way of indexing that doesn’t depend on the current GDB language setting?
In some code that I inherited, I get the compile error "Unsigned" not declared in "System".
I'm trying to compile this using GNAT, but ultimately the code must compile with the original tools, which I don't have ready access to. So I'd like to understand how to resolve this from within the development environment (including the project file), and not modify the existing code.
I checked the file system.ads, and Unsigned is not defined there. Am I referring to the wrong libraries? How would I resolve this with the self imposed constraint mentioned above (to compile in the original environment)?
unsigned is the name of a predefined type in C. If what you need it an Ada type that matches the C type, what you need is Interfaces.C.unsigned. An older Ada implementation (before Interfaces.C was introduced by the 1995 standard) might have defined System.Unsigned for this purpose.
It would help to know what Ada implementation the code was originally written for.
You should examine the code to see whether it uses that type to interface to C code. If not (i.e., if it's just being used as a general unsigned integer type), you might instead consider defining your own modular type.
If I understand correctly, you need the code to compile both in the original environment and with GNAT. That might be difficult. One approach would be to define a new package with two different versions, one for the original environment and one for GNAT (or, ideally, for any modern Ada implementation). For example:
-- version for original environment
with System;
package Foo is
subtype Unsigned is System.Unsigned;
end foo;
and:
-- version for GNAT
with Interfaces.C;
package Foo is
subtype Unsigned is Interfaces.C.Unsigned;
end Foo;
Picking a better name than Foo is left as an exercise, as is determining automatically which version to use.
You could rebuild the GNAT runtime system (RTS) with a slightly modified system.ads.
There’s a Makefile.adalib in the system RTS (well, there is in GNAT GPL 2014) which lets you do this. It’s at the last directory indicated in the “Object Search Path” section of the output of gnatls -v.
The RTS source is similarly indicated in the “Source Search Path” section.
Create a directory say unsigned with subdirectories adainclude, adalib.
Copy the RTS source into unsigned/adainclude, and edit system.ads to include
type Unsigned is mod 2 ** 32;
(I’m guessing a bit, but this is probably what you want!)
Then, in unsigned/adalib,
make -f Makefile.adalib ADA_INCLUDE_PATH=../adainclude ROOT=/opt/gnat-gpl-2014
(ROOT is where you have the compiler installed; it will be different on your system, it’s one above the bin directory in which gnatls and friends are installed).
There will be several errors during this, all caused (when I tried it) by units that use System.Unsigned_Types;. Work round this by inserting this immediately after the package body in the .adb:
subtype Unsigned is System.Unsigned_Types.Unsigned;
The files I had to change were
s-expmod.adb
s-expuns.adb
s-imgbiu.adb
s-imgrea.adb
s-imguns.adb
s-imgwiu.adb
s-valint.adb
s-valuns.adb
s-vercon.adb
It may be best at this stage to remove all the .ali and .a files from unsigned/adalib and repeat, to get a clean build.
Now, you should be able to use System.Unsigned by
gnatmake --RTS=/location/of/unsigned t.adb
In my case, t.adb contained
with System;
with Ada.Text_IO; use Ada.Text_IO;
procedure T is
begin
Put_Line ("first: " & System.Unsigned'First'Img);
Put_Line ("last: " & System.Unsigned'Last'Img);
Put_Line ("42: " & System.Unsigned'Value ("42")'Img);
Put_Line ("16#42#:" & System.Unsigned'Value ("16#42#")'Img);
end T;
and the output was
$ ./t
first: 0
last: 4294967295
42: 42
16#42#: 66
I am using custom LLVM pass where if I encounter a store to
where the compiler converts the value to a Constant; e.g. there is an explicit store:
X[gidx] = 10;
Then LLVM will generate this error:
aoc: ../../../Instructions.cpp:1056: void llvm::StoreInst::AssertOK(): Assertion `getOperand(0)->getType() == cast<PointerType>(getOperand(1)->getType())->getElementType() && "Ptr must be a pointer to Val type!"' failed.
The inheritance order goes as: Value<-User<-Constant, so this shouldn't be an issue, but it is. Using an a cast on the ConstantInt or ConstantFP has no effect on this error.
So I've tried this bloated solution:
Value *new_value;
if(isa<ConstantInt>(old_value) || isa<ConstantFP>(old_value)){
Instruction *allocInst = builder.CreateAlloca(old_value->getType());
builder.CreateStore(old_value, allocInst);
new_value = builder.CreateLoad(allocResultInst);
}
However this solution creates its own register errors when different type are involved, so I'd like to avoid it.
Does anyone know how to convert a Constant to a Value? It must be a simple issue that I'm not seeing. I'm developing on Ubuntu 12.04, LLVM 3, AMD gpu, OpenCL kernels.
Thanks ahead of time.
EDIT:
The original code that produces the first error listed is simply:
builder.CreateStore(old_value, store_addr);
EDIT2:
This old_value is declared as
Value *old_value = current_instruction->getOperand(0);
So I'm grabbing the value to be stored, in this case "10" from the first code line.
You didn't provide the code that caused this first assertion, but its wording is pretty clear: you are trying to create a store where the value operand and the pointer operand do not agree on their types. It would be useful for the question if you'd provide the code that generated that error.
Your second, so-called "bloated" solution, is the correct way to store old_value into the stack and then load it again. You write:
However this solution creates its own register errors when different type are involved
These "register errors" are the real issue you should be addressing.
In any case, the whole premise of "converting a constant to a value" is flawed - as you have correctly observed, all constants are values. There's no point storing a value into the stack with the sole purpose of loading it again, and indeed the standard LLVM pass "mem2reg" will completely remove such a sequence, replacing all uses of the load with the original value.
I have just started using Ada, and I'm finding the generic package declarations to be rather silly. Maybe I'm not doing it right, so I'm looking for better options.
Take a look at the below example.
package STD_Code_Maps is new
Ada.Containers.Map(Key_Type => STD_Code_Type;
Element_Type => Ada.Strings.Unbounded.Unbounded_String);
STD_Code_Map : STD_Code_Maps.Map;
-- . . .
procedure Do_Something is
Item : Ada.Strings.Unbounded.Unbounded_String;
begin
Item := STD_Code_Maps.Element(STD_Code_Maps.First(STD_Code_Map));
-- Do something with the Item
-- . . .
end Do_Something;
It would be much cleaner to simply be able to write STD_Code_Map.First.Element instead of the godforsaken STD_Code_Maps.Element(STD_Code_Maps.First(STD_Code_Map));
Obviously I'm doing this wrong -- I think. I'm repeating the phrase STD_Code_Map at least thrice over there. I'm all for verbosity and everything, but really the code I'm writing seems bad and silly to me.
I was wondering if there is solution that doesn't require you to rename the package to something like package Map renames STD_Code_Maps; which would of course shorten the code but I don't want to do this on each and every procedure entry. I really think something like STD_Code_Map.First.Element would be much simpler. Can this be done in Ada 2012?
Note: Using the Unbounded_String package by default is also so difficult. Did the standard library designers actually give much thought to the ridiculous and overly long package hierarchy?
Thanks for reading this, and potentially helping me out. I'm new to Ada.
GNAT GPL 2012 and 2013, and FSF GCC 4.7 and 4.8, support the new container indexing scheme of Ada 2012, which means that you can write
Item := STD_Code_Map ({some Cursor});
And you can do this even with the -gnat05 switch to force Ada 2005 mode! (which has to be a bug).
Ada 2005 allows you to call a primitive function of a tagged type using object.function notation, provided that the first operand is of the tagged type; so you can write STD_Code_Map.First as shorthand for STD_Code_Maps.First (STD_Code_Map).
Putting these together, you can write
Item := STD_Code_Map (STD_Code_Map.First);
which is quite short!
The issue has nothing to do with generics. As Simon pointed out, you can say STD_Code_Map.First, since the type of STD_Code_Map is a tagged type and Ada supports this notation for tagged types. On the other hand, the type of STD_Code_Map.First is a Cursor type, which isn't tagged (making it tagged would have caused problems declaring certain operations that take both a Cursor and a Map). But even without the Ada 2012 container indexing that Simon mentioned, you can say
STD_Code_Maps.Element(STD_Code_Map.First);
which is a little better. Besides renaming a package, you can also rename the function:
function Elem (Position : STD_Code_Maps.Cursor) return STD_Code_Maps.Element_Type
renames STD_Code_Maps.Element;
and you can now use just Elem instead of STD_Code_Maps.Element wherever the renaming is directly visible. (You could call it Element if you want to. The renaming name can be the same or it can be different.) This could be helpful if you use that function a lot.
Ada was designed for readability and maintainability. (written once, read & maintained for much longer) This means that it does get a little verbose at times. If you prefer terse & cryptic there are plenty of other languages out there !
If you want to avoid typing STD_Code_Map all the time, just use a use clause:
use STD_Code_Map;
which would mean your code of
Item := STD_Code_Maps.Element(STD_Code_Maps.First(STD_Code_Map));
would become
Item := Element(First(STD_Code_Map));
Getting names nice and readable in Ada can sometimes be tricky. Often times language designers made the task worse than it had to be, by designing Ada standard library packages for use with Ada use clauses, without a thought to how they'd look to some poor sap who either can't or doesn't want to use that feature.
In this case though, there are things you can do on your own end.
For example "_Maps.Map" is redundant, so why not get rid of it from the package name? Why not use names so that you can write:
package STD_Code is new
Ada.Containers.Map(Key_Type => STD_Code_Type;
Element_Type => Ada.Strings.Unbounded.Unbounded_String);
Map : STD_Code.Map;
-- . . .
procedure Do_Something is
Item : Ada.Strings.Unbounded.Unbounded_String;
begin
Item := STD_Code.Element(STD_Code.First(Map));
-- Do something with the Item
-- . . .
end Do_Something;
Now Code looks like a bit of a null-meaning word too. Everything in a program is a code. So I'd consider ditching it as well. Unsually I name my Ada container packages something that says their basic theoretical function (eg: STD_to_String), while objects are more specific nouns.
Also, I should point out that if your map is constant and you can live with names that look like identifiers, often times you can get rid of maps to strings entirely by using an enumerated type and the 'image attribute.
If you're using Ada 2012 the STD_Code_Maps.Element(STD_Code_Maps.First(STD_Code_Map)); could become:
Function Get_First( Map : STD_Code_Maps.Map ) return Unbounded_String is
( STD_Code_Maps.Element(Map.First) );
That is an example of the new Expression-functions, which were mainly introduced for pre- and post-conditions.
Of course, if you're using Ada 2012 then the precise map you'd likely want is Ada.Containers.Indefinite_Ordered_Maps -- the Indefinite_* containers are those that [can] have indefinite elements, like String.
In addition to TED's comment, using an enumeration when the maps are constant have even more advantages, namely case coverage: the compiler will flag as an error any case-statement that doesn't cover all alternatives. So if you add a new code it will flag all the case-statements that you need to modify. (Of course this benefit is lost when you use the others case.)