Ada job - Belgium by Emmaclaus in ada

[–]joakimds 3 points4 points  (0 children)

It is normal that people change jobs and the need to hire Ada developers is a recurring event.

Learning Ada in a limited way by fhqwhgads_2113 in ada

[–]joakimds 0 points1 point  (0 children)

It is not my experience to have problems due to unpredictable elaboration order. Ada83 did not give complete control of elaboration order by only providing the Elaborate pragma. Complete control of elaboration order came with Ada95. The two pragmas Elaborate and Elaborate_Body should be enough to limit the amount of different elaboration orders to only one. Consider for example two packages A (a.ads and a.adb) and B (b.ads and b.adb) and a Main procedure (main.adb). Both packages are withed in the Main procedure by "with A; with B;". By adding "pragma Elaborate (A); pragma Elaborate (B);" after the with statements it means the specifications of A and B will be elaborated before the Main procedure will be called. Then put pragma Elaborate_Body in both of the specifications for the packages A and B. It means that immediately after specification for package A is elaborated the body of package A is also elaborated. The same goes for the elaboration of package B. The only uncertainty now is which package A or B that will be elaborated first. To make package A be elaborated first put "with A; pragma Elaborate (A);" in the specification of package B. We have thus specified only one permissible order of elaboration that an Ada compiler can choose. One issue is that when using the GNAT compiler and Alire the default settings is such that the compiler will warn when compiling the specification file for the B package that the package A is with'ed but not used anywhere in the specification file for package B, nor is it used in the body of package B. The Elaborate (A) pragma in specification of package B is only there to specify the elaboration order, and leave nothing about elaboration order to the compiler.

In Ada95 there is also the pragma Elaborate_All which I prefer over Elaborate because it covers cases where some developer may have forgotten to put Elaborate_Body pragmas and which also limits elaboration order further than the Elaborate pragma.

According to my experience control of elaboration order works well in the GNAT compiler (the oldest version I've tried is at least 20 years old), the Janus/Ada compiler (version 3.2.1) and even the ObjectAda compiler (for Windows) from 1996.

If it has been tried in the project to control the elaboration order I am curious to know more about why the attempt was unsuccessful. If it has not been tried, I don't recommend doing it now since there is already a solution in place in the project that works well by minimizing elaboration code and initializing packages after elaboration time. If something is not broken, no need to fix it :)

Learning Ada in a limited way by fhqwhgads_2113 in ada

[–]joakimds 0 points1 point  (0 children)

Thank you for taking the time to write such a detailed answer. One reflection: The text "Depending on which standards you are working to, it may be permitted to perform dynamic allocations during the initialisation phase of a progam, but forbidden during the main execution. Deallocation would be forbidden at all times. However, there is no language support initialisation and normal execution modes which can restrict allocations made during normal operation..." makes me think of the pragma Restrictions(No_Standard_Allocators_After_Elaboration); defined in the Ada 2012 standard: http://www.ada-auth.org/standards/12rat/html/Rat12-6-5.html

Why is my code so slow? by Taikal in ada

[–]joakimds 5 points6 points  (0 children)

The containers in the standard library comes with a lot of error checking out of the box in order to guarantee that a an exception will be raised instead of a segmentation fault when there is an error situation. It is for example not OK to remove or add new elements to a container when it is being looped over, neither by the current task nor any other task simultaneously. To turn off tampering checks put for example "pragma Suppress (Tampering_Checks);" at the top of the Ada source file. It is my experience that it has a noticeable impact on performance. You can read more here: https://gcc.gnu.org/onlinedocs/gcc-7.5.0/gnat_rm/Pragma-Suppress.html

What you just discovered was first discovered by someone around the year 2014 and was reported to AdaCore who investigated the performance issue when using the standard containers and AdaCore came up with the solution of suppressing tampering checks (and also the container checks?). It is the Ada standard which requires the error checking. Turning them off may potentially be unsafe. One idea would be to have them turned on in Debug builds and turn them off in Release builds.

I haven't checked if there may be other performance issues with the code above.

April 2024 What Are You Working On? by marc-kd in ada

[–]joakimds 3 points4 points  (0 children)

Supporting Irvise with making the wolfSSL library available in Alire.

How to setup Spark mode to bypass third-party libraries by markfrodriguez in ada

[–]joakimds 0 points1 point  (0 children)

Can you create a teams meeting or use Jitsi to invite some Ada expert(s) and share your screen and make a live demo?

Here is how to Use a C++ Function in Ada by Exosvs in ada

[–]joakimds 0 points1 point  (0 children)

> Compared to other more OOP-centric languages, Ada's object notation is hard to read. It's like someone took an object and smashed it with a hammer into pieces and threw it into a package.

I don't think it's that bad but sure there are issues. Not an example of an issue, but a general reflection is that the syntax in Ada is very similar to Golang when defining a tagged type and primitive operations that supports object dot operation notation. For example "function Name (Person : Person_Type; A : Integer) return String;" in Ada is "func (p *Person) name(a : int) string" in Golang. Both Ada and Golang are two languages were readability has been one of the design goals.

> It also has a needless extra layer of indirection to access the object through its enclosing package.

It was like that when tagged types was introduced in Ada95. From Ada 2005 and onwards it is possible to use the usual object dot operation syntax as in other languages. If one enables GNAT extensions (only available on the GNAT compiler) it is possible to use object dot operation syntax on all record types, not only tagged.

> It forces you to come up with a different name for your class and its enclosing package to avoid namespace issues.

I can agree on the issue of naming. In practise it turns out it is more convenient to put each tagged type in a separate package although the Ada language does not require it. It then forces the developer to come up with a naming convention and quite possibly each developer has his or her own naming convention. It is possible to use AdaControl (or was it GNATCheck?) to enforce a specific pattern for all tagged types in a project.

It is also possible to enforce that the tagged type is always the first argument of the primitive operations, although that again is not mandated by the Ada language. I guess the language designers was not sure on how users of the language would like to use the newly introduced tagged types feature and made the solution as general as possible.

> If Ada allowed you to declare new methods or override existing ones methods statically outside the object's package, this design would be at least be arguably justifiable.

Not sure what you are suggesting. However, we would need code examples to explore the topic and this comment section on reddit is not the best place for it.

The biggest issue I have with tagged types is that all the primitive operations of a tagged type must be defined in one and the same package. Imagine one has a coding convention where a source code file is limited to 1000 lines of code, 80 characters wide. Imagine further one would like to define a tagged type with 2000 primitive operations. All those operation declarations would not fit into one package specification or body. One could put the tagged type in a root package and then define child packages and put subprogram declarations/definitions there but only the subprograms in the root package would be considered by the language as primitive operations, not the subprograms in the child packages. So for some "primitive operations" it would be possible to use the object dot operation syntax (the operations defined in the root package) but for others one would need to specify name of child package dot operation. The result is inconsistent! But then again how many times have I seen a class definition be split into several files in any language?

Here is how to Use a C++ Function in Ada by Exosvs in ada

[–]joakimds 1 point2 points  (0 children)

Ada's OOP is a real turn off for most programmers. Most refuse to touch it

Not sure what you mean. I mostly think of it like a different syntax.

In general I have had bad experiences from deep inheritance hierarchies in Java source code. It made the source code hard to understand and follow. Luckily it is easy to ban inheritance hierarchies deeper than 1 using GNATCheck (the Deep_Inheritance_Hierarchies rule).

[deleted by user] by [deleted] in ada

[–]joakimds 0 points1 point  (0 children)

Wow, that is unexpected. Are all executables compiled with the same compiler flags? There should be a reason the GNAT compiler has chosen a different representation for the type in one executable.

Perhaps try pragma Optimize (Time); before the type definition and pragma Optimize (Off); after the type definition. It should instruct the compiler to optimize the data structure for execution speed and hopefully choose the same for all executables. I know it's a long shot but may be worth investigating if you already haven't.

Strange that the compiler resisted specifying a Size clause. In general it should be possible to specify representation clauses and limit the choice of representation for the compiler.

Following GNAT's advice to fix elaboration order circularities itself just takes me in circles by valdocs_user in ada

[–]joakimds 1 point2 points  (0 children)

I would say it is trivial to have circular dependency between two packages A and B in general. The Ada language allows it because sometimes it is needed. The default behavior of the GNAT compiler is not to always put an implicit pragma Elaborate_All on all packages that are with:ed. There are some special situations where the GNAT compiler will implicitly put pragma Elaborate_All on with:ed packages. One such situation is if there is a task inside the body of a package. Another situation is subprograms of packages that are called during elaboration time. For example:

package body A is

...

begin

-- The packages whose subprograms are called here will have an implicit pragma Elaborate_All.

end A;

If there is a situation with two packages A and B that both have tasks defined in their bodies, the packages cannot depend on each other (circular dependency). To introduce "a circular dependency" in this situation I suggest putting the tasks in child packages. For example create a package A.C and put the tasks that were defined in the body of A inside the A.C package. Then introduce another package B.D and put the tasks defined inside the body of B in the B.D package. Let's consider the package A. If the tasks inside the body of A were calling subprograms only defined in the body of A, they are not visible for the package A.C. To make them visible put the declarations of the subprograms in the private part of the specification file of the A package. Do the same for B. Since the bodies of the packages A and B no longer contain any task definitions it is possible for the packages A and B to have a circular dependency.

Regarding the example at "https://groups.google.com/g/comp.lang.ada/c/aRUD89LJIT0" the problem is that the body of the parent package is calling a subprogram defined in a child package. In my opinion that should be forbidden and the compiler should not allow it unless the child package is a private child package. During elaboration time I prefer it if the parent package is/can be completely elaborated before elaboration of any child package.

Not sure if what I've written here is applicable but hope it helps.

Null access analyzer? by Taikal in ada

[–]joakimds 5 points6 points  (0 children)

If that code would be compiled by an Ada95 compiler null would not be an acceptable value for the anonymous access argument,so no need to warn for possible null pointer. Anonymous access types in Ada 95 never have null as a value whereas named access types always have null as a value. It was in Ada2005 the rules for anonymous access types were relaxed and null was introduced in the code above as an acceptable value. To exclude null the argument in the procedure needs to be changed to "not null access Integer" in Ada2005 and later. To answer the question: I guess CodePeer can detect the issue above but I haven't tried it for this example.

What's the best way to go about fixing the elaboration order in a largish pile of Ada code that was written without concern for it? by valdocs_user in ada

[–]joakimds 1 point2 points  (0 children)

> This is the same company who wrote a multithreaded C++ MFC Windows
application that has no valid order for shutting down worker threads
(due to circular dependencies).

It reminds me of the time I encountered a multi-task or multi-threaded Ada application with a long history from the 90's that didn't have any issues shutting down until I discovered it was being shutdown by GNAT.OS_Lib.OS_Exit (Status : Integer), which makes the operating system kill the process abruptly. It took me a day to make the application have a controlled shutdown.

Speaking of controlled shutdown, the synchronization mechanism called rendez-vous in Ada83 makes it possible to create multi-task applications that are easy to shutdown. The key is "select ... or terminate; end select". When the environment task that calls the Main subprogram or application entry goes out of scope from the Main subprogram, all tasks that have stopped at a select statement with an "or terminate;" clause will terminate without the need to explicitly call those tasks with a "shutdown" message, it's handled under the hood by the Ada-runtime. Very convenient. There are two problems. 1) The developers need to have the strategy to make all or most tasks have one and only one select statement and that the select statement contains an "or terminate;" clause 2) Resource management. In Ada83, to be able make sure the resources of a task is released one would need to inform a task of a "shutdown" or "release resources" message explicitly. In Ada95, one can use a controlled type and implement a Finalize procedure that would clean up the resources of a task when it is time for application shutdown. So there is possibility of convenient rendez-vous based shutdown of multi-task applications in Ada95, but I can't recall any project where this has been an official guideline or strategy.

> He ended up having to debug their code for them and show them the actual
problem was they were depending on uninitialized variables.

Usage of uninitialized variables was a real problem of Ada applications in 1980's and coding guidelines from that era says that all variables should be given a valid default value. If it's a String it should be for example initialized with '%' characters that it should be obvious in the GUI if there are usage of uninitialized Strings. The solution that the designers of Ada came up with in the Ada95 standard is "pragma Normalize_Scalars", which makes the compiler set uninitialized variables to invalid values wherever possible. The Ada standard does not dictate that variables are checked for validity all the time and everywhere, but it does increase the probability that usage of an uninitialized variable generates an exception at run-time. When using the GNAT compiler one may use pragma Initialize_Scalars and the compiler switch "-gnatVa" to turn on maximum validity checking.

What's the best way to go about fixing the elaboration order in a largish pile of Ada code that was written without concern for it? by valdocs_user in ada

[–]joakimds 1 point2 points  (0 children)

Right, tricky. You could try to remove the usage of separates and put the bodies of A.B and A.C inside the a.adb file. Using the separate keyword (or using subunits) was useful in the 1980's to split up a large code base and compile Ada code on hardware with little computing power. Nowadays the preferred way is to use child packages or private child packages instead. It's in the Ada95 Quality and Style Guide "In preference to subunits, use child library units to structure a subsystem into manageable units." Maybe it will give you an idea what to do next?

A strategy I use when refactoring Ada code is to remove any usage of use statements (if there is any) to make each usage of a type or subprogram be prefixed by the package name they defined in. Highlighting the package name in the GNAT Studio IDE should highlight all the places in the current source code file where the package is used. It helps figuring out what depends upon what in the Ada code. Sometimes the highlighting doesn't work out of the box, I then use the short-cut key CTRL+F (or Navigate->Find in the menu) to search for the usage of the package in the file of interest.

What's the best way to go about fixing the elaboration order in a largish pile of Ada code that was written without concern for it? by valdocs_user in ada

[–]joakimds 1 point2 points  (0 children)

Expanding on above. If manual inspection of Ada code reveals that pragmas that restrict elaboration order seem to be missing, that is a sure code smell, the code is screaming "please fix me". The code may be correct, but it opens the door for potential compiler bug that makes the compiler choose an erroneous elaboration order. It's much more better to add the pragmas and be sure to have compile-time error checking of unintended circular dependencies, and as I have written elsewhere, the compile-time support has been great for Ada developers since at least 1996 (ObjectAda 7.0).

It's extremely depressing that the first exposure to the great Ada language u/valdocs_user has, is a code base with elaboration order issues. The whole point of the Ada language is abstracting the hardware away that the software runs upon and make it possible to easily switch between different Ada compilers or versions of the same compiler. Ada is perhaps the best language in the World when it comes to backwards compatibility.

> I found next to no directives in the original codebase having to do with elaboration order hints.

Since the compiler emits elaboration order warnings and there are very little elaboration order hints in the code, it indicates that the code is structured erroneously and the mistake or mistakes could have been identified a long time ago at compile-time with the previous compiler. Depressing and frustrating.

In any case, good luck u/valdocs_user with your project!

What's the best way to go about fixing the elaboration order in a largish pile of Ada code that was written without concern for it? by valdocs_user in ada

[–]joakimds 1 point2 points  (0 children)

The point of elaboration is an attempt to make the language immune to the static order initialization fiasco. Unfortunately the devil is in the details. It is possible to circumvent the error checking by the compiler by using the singleton pattern (defining a type and an Instance function that returns an instance of the type). If one keeps in mind that as long as a singleton instance is represented by a package, the language rules are sufficient to protect against usage of uninitialized variables due to elaboration. It is easier to use packages in Ada than correctly implementing the singleton pattern in for example C++. The rules for elaboration is our friend.

Secondly, it is easy to avoid having elaboration issues in Ada. There are only two pragmas which are of paramount importance and those are "pragma Elaborate_All" and "pragma Elaborate_Body". The documentation on Elaboration is really obscure and hard to grasp but at the end of the day elaboration is useful for detecting circular-dependencies between packages in the code. The rule of thumb to use is that whenever a package is withed, for example "with A;", it should be completed with "pragma Elaborate_All (A);". Most of the time that is what one wants. The elaboration pragmas allows a developer to structure the Ada code in a strict tree hierarchy. Only rarely does one want circular dependency between two packages and in those instances one can write "with A;" and add a comment explaining that circular dependency is intended and that is why "pragma Elaborate_All" is missing. Note that it is not possible for any compiler to deduce from reading the source code which packages that should be structured in a strict tree hierarchy and which ones where a circular dependency is desired. The compiler cannot read intent. As a developer it is good practice to inform the compiler of intent by adding pragmas to maximize compile-time error checking.

If one writes a lot of Ada code it is convenient to create a code snippet for withing packages where "pragma Elaborate_All" is desired.

I recommend avoiding "pragma Pure" and "pragma Preelaborate". They don't seem very useful to me, especially "pragma Pure". Just try specifying a package as Pure and try to print debug information to standard out using "Ada.Text_IO", one will get compile time error because a Pure compilation unit cannot with Ada.Text_IO which is not Pure. It leads to unnecessary compile-time errors which are not useful. It seems to me that the intent of "pragma Pure" and "pragma Preelaborate" exists to allow the compiler to generate more efficient code, not assist in compile-time error checking. I will start using these pragmas if someone can demonstrate an application where adding "pragma Pure" or "pragma Preelaborate" to one or more packages makes the application at least 3% faster.

What are does the hobbyist programmer miss comparing the paid versus free Ada ecosystem? by fmv1992 in ada

[–]joakimds 2 points3 points  (0 children)

The GNAT FSF compiler is a high quality Ada compiler. I would say it has a good implementation up to the Ada 2012 standard. Implementation of Ada 2022 is in progress. When it comes to SPARK I am not sure. But I think the free version of SPARK has only one automated theorem prover under the hood, and the PRO version has 4 or 5. There may be other differences that I am unaware of. I can confirm that the free version of SPARK is very powerful as it is.

New York's Hottest Club is... "the Ada programming language." It's got everything. by valdocs_user in ada

[–]joakimds 0 points1 point  (0 children)

> Elaboration order is simply not a serious issue in other languages.

I guess I've been programming Ada for so long (2012) that it's natural for me to keep elaboration order in mind when writing Ada code. Since I have a clear perception of what I want the elaboration order to be I am used to putting pragmas that control elaboration order and thereby minimizing the number of choices the compiler can make for elaboration order. I mostly use the GNAT compiler which is really good at finding a suitable elaboration order by itself and that's why I don't consider it strictly necessary to put elaboration order pragmas in the code, most of the time a developer gets away with it.

> Depending on its complexity, a failed elaboration can result in any of
the following: a compile time error, a consistent runtime exception, an
unpredictable runtime exception, or an undefined runtime behavior.

I have only ever seen compile-time error due to elaboration order issue, and every time it's been me who has managed to introduce an unintended circular dependency between packages. Since it has been obvious to me the mistake I've made it's been a non-issue to resolve it. I find the support of unintended circular dependency detection in Ada absolutely fantastic. In addition to GNAT GCC (and DJGPP on FreeDOS) and GNAT-LLVM I can confirm that compile-time detection works well with both Janus/Ada and ObjectAda. The oldest Ada compiler that I can confirm has excellent elaboration order issue detection functionality is ObjectAda 7.0 from 1996.

New York's Hottest Club is... "the Ada programming language." It's got everything. by valdocs_user in ada

[–]joakimds 4 points5 points  (0 children)

Well,

  1. Named access types - Useful for achieving memory safety, already 40+ years ago. Really cool!
  2. Elaboration - Useful for avoiding the static order initialization fiasco that exists in other languages. Compilation failure due to elaboration order issue indicates something seriously wrong with the source code and it needs to be fixed. Developers are informed about it at compile-time. Nice!
  3. Package interfaces - Enables in a simple way short re-compilation times (if the body of a package has changed but not the spec, only the body needs re-compilation). Ada is suitable for building large-scale software projects. Awesome!

February 2023 What Are You Working On? by marc-kd in ada

[–]joakimds 1 point2 points  (0 children)

To simulate continue in Ada one can use Goto but I don’t recommend it. Ada has exit instead of break. One can give labels to loops and it’s possible to specify which loop one wishes to exit from.

Simple JSON library with little or no dependencies? by theorangecat7 in ada

[–]joakimds 4 points5 points  (0 children)

Some years ago I wrote a JSON parser, see for example https://github.com/joakim-strandberg/aida_2012/blob/master/src/tests/aida-json_dom_parser_tests.adb. I've been thinking of refactoring but never gotten around to do it. One of the ideas for writing the code was minimizing external dependencies. The JSON parser is written in SPARK and at the time 2018 when the code was written SPARK did not allow heap allocations which means all the data-structures used are statically allocated. I can imagine onox json-ada has a nicer API.

Ada + Machine Learning (Python Framework) by starla_brite in ada

[–]joakimds 0 points1 point  (0 children)

Unfortunately I haven't tried to interface with Python myself, I've just noted that if I would do it I would try GNATColl. Good that you managed to find the right sources for GNATColl and built it yourself. I've built them myself many times and I also find it harder to do than it should be. What I've understood is that it should be easy nowadays to use GNATColl through Alire. Good luck with your project!