❌ About FreshRSS

Normal view

There are new articles available, click to refresh the page.
Before yesterdayNews from the Ada programming language world

Access-to-variable designates constant when trying to pass a pointer to vector element

This question is a follow-up to How to get access to a record field .

The more complex (now) code involves binding a whole vector of records. Something along the lines below:

type Tag is record
  Field : String := "value";
end record;

type Tag_Access is access all Tag;

package Tags_Vectors is new Indefinite_Vectors
  (Index_Type   => Positive,
   Element_Type => Wheel_Tag);

procedure Bind_Tag (T : in out Tag_Access; Stmt : Gnade.Statement) is
begin
    Gnade.Bind_Text (Stmt, T.Field'Address, T.Field'Length);
end Bind_Tag;

procedure Insert_Tags is
  Stmt : Gnade.Statement;
  Tags : Tags_Vectors.Vector;
  --  Make necessary arrangements to populate the Stmt and Tags
  C : Tags_Vectors.Cursor := Tags.First;
begin
  while Tags_Vectors.Has_Element (C) loop
         Bind_Tag (Stmt, Tags_Vectors.Element (C)'Access);
         Tags_Vectors.Next (C);
  end loop;
  Gnade.Step (Db, Stmt);
end Insert_Tag;

I'm not sure what kind of thing Tags_Vector.Element (C) returns. Syntactically, at least, it seems Ada doesn't object to this having an access attribute. But, I don't understand the error (which side does it think is the variable and which side is the constant?) Why is it bad that access to variable designates a constant? (Is it trying to say that I might be changing the value of a constant? -- but I never wanted any of those things to be constants...)

How to get access to a record field

Some general context for my problem first.

I need to bind some arguments of a prepared statement using GNATCOLL SQLite bindings. These bindings expect C character pointer as an input (beside other things). This requirements creates two problems on Ada's end:

Problem 1

The variable pointed to by the "bound" pointer must not perish until the prepared statement is finalized (otherwise it will store a pointer to garbage). But, for queries that operate on the same type of record it would be desirable to extract the part of binding of arguments (which are obtained from the record fields) into a separate procedure. If such procedure returns before the statement is finalized the variables (on the stack of such procedure) will be deleted, and pointers now point to garbage.

Problem 2

I only know of three instances in Ada of creating pointers: new-ing, taking a pointer to a function / procedure and taking a pointer to a variable. Since the bindings want a pointer, I don't know how to extract such a pointer from a record unless I "manually unpack" it into a bunch of local variables. Needless to say this is ugly, repetitive and very prone to copy-and-paste error. This also leads to the lifetime issues (since variables "unpacked" in such a way will be deleted before the actual value they are used to capture still exists.)

Example

type Tag is record
  Field : String := "value";
end record;

type Tag_Access is access all Tag;

procedure Bind_Tag (T : Tag_Access; Stmt : Gnade.Statement) is
  --  This variable will vanish before the statement is executed
  Field : aliased constant String := T.Field;
begin
    Gnade.Bind_Text (Stmt, Field'Address, Field'Length);
end Bind_Tag;

procedure Insert_Tag (T : Tag) is
  --  Necessary connection initialization and building of prepared statement
  Tc : Tag := T;  --  Creating a useless variable only to please the compiler
  Ta : Tag_Access := Tc'Access;
begin
  Bind_Tag (Ta, Stmt);
  --  Here, bindings are dead, so we are executing garbage
  Gnade.Step (Db, Stmt);
end Insert_Tag;

If I may enter a plea

I suspect this may be helped by using objects (i.e. new-ing something). I haven't researched this approach because my first experience with Ada (I'm still learning) was very negative when contracting objects. Deallocation combined with absence of convenient object lifetime management (eg. equivalent of C++ RAII) makes using objects a very daunting task. I would like to stay away from this functionality as much as possible.


Edit

I found a way out of this particular conundrum: turns out SQlite can be instructed to make copies when binding strings. This isn't ideal, but at least I can get the strings into the database.

This doesn't mean that the question is solved though. I'd still like to know a more general way of dealing with record fields. Something that in eg. C would be accomplished by taking a pointer to the struct and then adding the size of the fields preceding the field of interest and adding that the the pointer.

Ada Tech stack

I am trying to learn Ada. I am not into Embedded domain. Mostly Java(Springboot/Mysql etc and now Golang). I would like to know Ada's usage in standard enterprise areas where Java/Golang is used. After referring multiple videos and Reddit posts, i know Ada's usage may not be as high as java/golang, but would like to know what typical tech stack is used for Ada?

submitted by /u/lispLaiBhari
[link] [comments]

Trouble running Ada on VSCode M1 Mac

Hello everyone, I hope you are having a happy holiday.

The thing is, I have a problem understanding why I can't run Ada on VSCode, don't know if it's a compiler problem or something.

I have the gcc compiler that I downloaded for Objective-C and C++ in the past, this is what the terminal throw when I run --version

Apple clang version 15.0.0 (clang-1500.1.0.2.5) Target: arm64-apple-darwin23.1.0 Thread model: posix InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin 

Next, I followed the instruction of the GitHub page of Getting Started with Ada, but the follow errors are shown:

can't find a toolchain for the following configuration: language 'Ada', target 'aarch64-darwin', default runtime 

shown on .gpr

No project found in root directory. Please create a project file and add it to the configuration. 

shown on .adb

Tried to follow the simonjwright well written readMe, but can't figure what to do.

​

Thank you very much!

submitted by /u/AdEnvironmental6534
[link] [comments]

Overthinking “new”: Types vs Records

Hello,

When I declare a record in the heap I use:

declare type my_record is record: my_var : Integer; end record; type my_record_access_type is access my_record; record_1 : my_record_access_type; record_2 : my_record_access_type; begin record_1 := new my_record; record_1.my_var := 1; record_2 := record_1 record_2.my_var := 2; end 

So here’s what we did: - Declare a record with one variable, my_var of type integer. - Declare an access type that will point to the type, my_record. In my brain this is like saying “Declare an array filled with integers” except here we’re saying “declare an access type that is filled with the necessary information to access my_record(s)” - Declare two instances of this access type - Begin - Instantiate the first record we declared. Because we use “new”, it will do it on the heap. - set the variable in the record to 1; - make a reference of record_1 and save it in record_2. Since record_1 is an access type, record_2 is only a second name (alias) for record 1. - change the value of the variable in the record (the one and only record with two names) from 1 to 2. - end

Is that correct?

Secondly, I see multiple ways to make new types:

package types is type distance1 is new Float; type distance2 is range 0..100; — No new because range? type distance is Integer; — why no new here? end types 

Clearly the type creation “new” is different than the object creation new. However, the nuance of when to use “new” in type creation eludes me.

Would someone please provide some guidance?

I’m familiar and comfortable with C++ if using an analogy is helpful and appropriate.

submitted by /u/Exosvs
[link] [comments]

AEiC 2024 - Ada-Europe conference - grants for Open Access publication

Season's greetings from the organizers of the 28th Ada-Europe International Conference on Reliable Software Technologies (AEiC 2024), to be held 11-14 June 2024, in Barcelona, Spain!

Accepted Journal Track papers will be published in the conference's Special Issue of the Journal of Systems Architecture (JSA). Note that the Ada-Europe organization will waive the Open Access fees for the first four accepted papers, which do not already enjoy OA from other agreements with the Publisher.

www.ada-europe.org/conference2024/cfp.html#cfpjournal

#AEiC2024 #AdaEurope #AdaProgramming

submitted by /u/Dirk042
[link] [comments]

Record size from a lib differs from one executable to another

Hi,

I'm facing a problem that leaves me extremely perplexed (I can hardly believe what I'm seeing). I have a library that defines a record. This record will be used to instantiate a shared memory between different executables.

The first executable calls a function in this library which will create the shared memory. The other executables will communicate through it. Except that it doesn't work. After hours of debugging, I noticed that the size of my structure (aspect 'Size) is different between the first executable and the others: it's 4 times smaller!

Everything was recompiled and tested multiple times to make sure this was the case. In every executables, 'Size and 'Object_Size are the same. Printing the size of the record in the package initialization returns the correct value, the one used by every executables except the first one.

I think this will leave you really perplex too. Have you ever encounter a similar issue?

I believe there is a way to ask the gnat compiler (or gprbuild) for a file that gives the size given for each types, right? Which flag is it?

Thanks for your help.

submitted by /u/louis_etn
[link] [comments]

How do you use the Reference_Type in Ada Hashed_Maps?

I want to create a symbol table as a hash map and keep a list of pointers into the symbol table to keep track of symbol table entries that need to be updated. I probably can't use cursors as pointers since they might change when new items are added to the symbol table. I can't use access types as I don't know whether the Insert procedure stores the element passed to it or makes a copy and stores that. It looks like I'm supposed to use a Reference_Type. But the Reference_Type is causing me problems because it is unconstrained.

This doesn't work:

with Ada.Containers.Indefinite_Hashed_Maps;
with Ada.Containers.Vectors;
with Ada.Strings.Hash;

package Types is
type Memory_Address is mod 2**64;
type ID_Code        is (ID_VARIABLE, ID_LABEL); -- ...extend as necessary...

NULL_ADDRESS : constant Memory_Address := 0;

type Symbol_Table_Entry is record
    id      : ID_Code;
    address : Memory_Address;
end record;

package Symbol_Tables is new Ada.Containers.Indefinite_Hashed_Maps (
    Key_Type        => String,
    Element_Type    => Symbol_Table_Entry,
    Hash            => Ada.Strings.Hash,
    Equivalent_Keys => "="
);

subtype Symbol_Table is Symbol_Tables.Map;

subtype Symbol_Table_Pointer is Symbol_Tables.Reference_Type;

-- Quadruple: Red Dragon Book, p. 470

type Opcode is new Natural;

type Quadruple_List_Index is new Natural;

type Quadruple is record
    op     : Opcode;
    arg1   : Symbol_Table_Pointer;
    arg2   : Symbol_Table_Pointer;
    result : Symbol_Table_Pointer; -- lvalue or branch destination
end record;

package Quadruple_Lists is new Ada.Containers.Vectors (
    Index_Type   => Quadruple_List_Index,
    Element_Type => Quadruple
);

subtype Quadruple_List is Quadruple_Lists.Vector;

type Label_List is array(Natural range <>) of Quadruple_List_Index;

end Types;

I get "error: unconstrained subtype in component declaration" for the fields of Quadruple defined as Symbol_Table_Pointer. I have searched on the internet but have found no good examples of how to use Reference_Type. Could someone please explain how to make this work?

🏆 Top Ada open source projects and contributors

Hello everyone,

I'd like to introduce you some interesting lists and rankings related to the Ada open source ecosystem:

- Top Contributors (global or by country): https://opensource-heroes.com/contributors?language=ada
- Awesome projects: https://opensource-heroes.com/awesome/ada (we plan to add soon a new feature to allow everyone to contribute to that list directly from the site)
- Country stats: https://opensource-heroes.com/ada

You can also find "stars" history in the detail page of some repos (it will be available soon for all Ada repos, we're still processing some data!) and embed this chart in your project's README or docs.

Hope you find this content useful! Any feedback is really appreciated. Please note that be are still in beta 🙏 We want to build a platform that allows everybody to easily explore the open source world! And if you are interested in other languages too, you should check out this page: https://opensource-heroes.com/languages

​

submitted by /u/markets86
[link] [comments]

How a newbie can land job with ada?

I recently drawn towards aerospace and military tech, and got to know about this language and I actually like this language and plan to go deep with it but want to make career with it.

Is it possible for a average dev to do something feasible with this language and get job in it.

Kindly mentor me if anyone is will to, I will be extremely great full to you.

Thank you in advance.

submitted by /u/AnkiBloom
[link] [comments]

What is "extension aggregate" and why do I need it?

I'm trying to use GNAT's SQLite bindings. And I want some way to get errors from these bindings. Trying to read through the code, I found that I can set up the connection by providing a mystery object that is supposed to handle errors...

No matter how I try to shape and provide this object, the library either won't accept it, or I get runtime access check errors (another bizarre aspect of this program as the pointer should be always alive since it's never leaving the scope of the procedure that declared it... but maybe it works differently in Ada).

The error I'm getting looks like this:

type of aggregate has private ancestor "Error_Reporter"
must use extension aggregate

The original Error_Reporter is defined as follows:

type Error_Reporter is abstract tagged private;
...
private

   type Error_Reporter is abstract tagged null record;

Anyways, below is the outline of the problematic code:

The header file:

   -- type Error_Handler is new Gse.Error_Reporter with private;
   type Error_Handler is new Gse.Error_Reporter with record
      Message : Asu.Unbounded_String;
   end record;
   
   type Error_Handler_Access is access Error_Handler;

   procedure On_Error
     (Self       : in out Error_Handler;
      Connection : access Gse.Database_Connection_Record'Class;
      Message    : String);

-- more stuff ...
   
-- private
--    type Error_Handler is new Gse.Error_Reporter with record
--       Message : Asu.Unbounded_String;
--    end record;

the implementation:

...
      declare
         pragma Suppress (Accessibility_Check);
         -- Handler : constant Error_Handler_Access :=
         --   new Error_Handler'(Message => Asu.Null_Unbounded_String);
         Handler : constant access Error_Handler :=
           new Error_Handler'(Message => Asu.Null_Unbounded_String);
         -- Handler : aliased Error_Handler;
         Descr         : Gse.Database_Description    :=
           Gss.Setup (Db_File, Errors => Handler);
--         Gss.Setup (Db_File, Errors => Handler'Access);
...

Commented code shows various things I tried. (Also, pragma has no effect).

Ideally, I don't want to new anything, unless this is the requirement from GNAT's interface.

Even better: if I could entirely avoid using this object (it should be possible to salvage the actual Sqlite connection from this wrapper and get access to return code and the error message), but the code is not very easy to read and is trying to make the user do things that I don't want (ORM, multiple layers of bindings that only complicate things) all while hiding the essential useful functionality. I'd appreciate any guidance in this direction.


UPDATE: In the end, my problem was I couldn't figure out how to use Bind_XXX group of procedures from Gnade package. And this is what prompted me to use the Execute package, which ultimately led to the problem with error reporting. To solve this, I finally figured out how to use Bind_XXX (the one giving me the most problems was Bind_Text due to pointer translation between Ada and C). Once that worked, I rewrote the code to use just Gnade.

Using GNATTest with Alire and GNATStudio

Hi All.
For context, I am working on a small code challenge that saw online. Essentially, is implementing an Ulam Spiral, in CLI, using different languages. I did this for fun, and to learn new things on the way.

I am currently working on the implementation of the Ada language. Coming from Java/Python/Javascript backgrounds, was challenging and fun figuring out how Ada does things. I am also using Alire for some small dependency management I need.

In any case, I want to implement some unit testing, just for completion, and quick verification for other parts that may be wrong. I read some articles online, and found two things:

  1. This git repository: https://github.com/alire-project/ada_spark_workflow shows a basic library on Ada, and shows that Unit Tests can be implemented as a separate crate
  2. The documentation for AUnit (https://docs.adacore.com/live/wave/aunit/html/aunit_cb/aunit_cb.html) shows how to implement tests, suites, fixtures, etc, which seems easy enough.

However, I also came into GNATTest and how is integrated into GNATStudio (which I am using for this development). Seems that make it easier to just use it to generate the test files, while I have to provide the actual test code, asserts, etc.

I added the libadalang_tools crate as a dependency, and it compiles fine. I can even see the build binaries in a folder (location: ${project_root_folder}/alire/cache/dependencies/libadalang_tools_23.0.0_75f92679/bin). However, GNATStudio complains that the binary can not be found, which makes sense, as it is not in the PATH environment variable

Here are my questions then:

  1. Can Alire set those binaries to the path? that way, when I run `alr edit`, they will be already on the path, and all will run without any issues.
  2. If #1 is not possible, then how can I configure the path to the binaries for GNATest (and other tools if needed) in a way that is portable to others (or even a future me) who want to clone the repository and build/run the code?

As a workaround, I changed the command that is executed on the GNATtest generation window and hardcoded the path. It works, but did not feel that was the correct way.

Any help on this is very welcome. Let me know if you need other details.

Regards!

submitted by /u/egamboau
[link] [comments]

Advent of Code 2023, day 10

10 December 2023 at 17:12

The puzzle: https://adventofcode.com/2023/day/10

My Ada solution: here.

In a picture (generated by the program linked above)...

Click to enlarge

 

It is always a pleasure to display the data created by Eric Wastl.

Here, an improved representation with the five cases (outside tile, inside tile, inside pixel on a path tile, outside pixel on a path tile, path pixel) in shown different colors:

Click to enlarge


Creating custom Sax reader

There's something about polymorphism in Ada that I don't understand. (Or maybe it's the package naming?) I'm trying to parse an XML file using xmlada library and I followed the example I found in tests for this library that uses Debug_Reader. Below is the problematic code:

--  cog_cli-xml.adb
with Ada.Strings.Unbounded;
with Sax.Readers;
with Input_Sources.Strings;
with Unicode.CES.Basic_8bit;
with Cog_Cli.Xml_Reader;
with Cog_Cli_Doc;

package body Cog_Cli.Xml is
   
   package Asu renames Ada.Strings.Unbounded;
   package Ccxr renames Cog_Cli.Xml_Reader;
   package Sr renames Sax.Readers;
   package Iss renames Input_Sources.Strings;
   package Ccd renames Cog_Cli_Doc;
   package U8bit renames Unicode.CES.Basic_8bit;

   function Cli_Help (Command : String) return String is
      Doc_Reader : Ccxr.Reader;
      Input      : Iss.String_Input;
      Cli_Help   : constant Ccd.Content_Type := Ccd.Get_Content ("cli.xml");
   begin
      Iss.Open (Cli_Help.Content.all,
                Encoding => U8bit.Basic_8bit_Encoding,
                Input => Input);
      Ccxr.Set_Command (Doc_Reader, Command);

      Sr.Set_Feature (Doc_Reader, Sr.Namespace_Prefixes_Feature, False);
      Sr.Set_Feature (Doc_Reader, Sr.Namespace_Feature, False);
      Sr.Set_Feature (Doc_Reader, Sr.Validation_Feature, False);

      Sr.Parse (Doc_Reader, Input);

      Iss.Close (Input);

      return Asu.To_String (Doc_Reader.Help);
   end Cli_Help;

end Cog_Cli.Xml;
--  cog_cli-xml_reader.ads
with Sax.Readers;
with Unicode.CES;
with Sax.Attributes;
with Ada.Strings.Unbounded;

package Cog_Cli.Xml_Reader is
   
   package Asu renames Ada.Strings.Unbounded;

   type Reader is new Sax.Readers.Reader with private;

   procedure Start_Element
     (Handler       : in out Reader;
      Namespace_URI : Unicode.CES.Byte_Sequence := "";
      Local_Name    : Unicode.CES.Byte_Sequence := "";
      Qname         : Unicode.CES.Byte_Sequence := "";
      Atts          : Sax.Attributes.Attributes'Class);

   procedure End_Element
     (Handler       : in out Reader;
      Namespace_URI : Unicode.CES.Byte_Sequence := "";
      Local_Name    : Unicode.CES.Byte_Sequence := "";
      Qname         : Unicode.CES.Byte_Sequence := "");

   procedure Characters
     (Handler : in out Reader;
      Ch      : Unicode.CES.Byte_Sequence);

   procedure Set_Command (Handler : in out Reader; Command : String);

   procedure Set_Help (Handler : in out Reader; Help : String);
   
private
   type Reader is new Sax.Readers.Reader with record
      Command : Asu.Unbounded_String;
      Help    : Asu.Unbounded_String;
   end record;

end Cog_Cli.Xml_Reader;
with Ada.Text_IO;
with Ada.Strings.Unbounded;

package body Cog_Cli.Xml_Reader is
   
   package Ati renames Ada.Text_IO;
   package Asu renames with Ada.Strings.Unbounded;

   procedure Start_Element
     (Handler       : in out Reader;
      Namespace_URI : Unicode.CES.Byte_Sequence := "";
      Local_Name    : Unicode.CES.Byte_Sequence := "";
      Qname         : Unicode.CES.Byte_Sequence := "";
      Atts          : Sax.Attributes.Attributes'Class) is
   begin
      null;
   end Start_Element;
   
   procedure Characters
     (Handler : in out Reader;
      Ch      : Unicode.CES.Byte_Sequence) is
   begin
      null;
   end Characters;
   
   procedure End_Element
     (Handler       : in out Reader;
      Namespace_URI : Unicode.CES.Byte_Sequence := "";
      Local_Name    : Unicode.CES.Byte_Sequence := "";
      Qname         : Unicode.CES.Byte_Sequence := "") is
   begin
      null;
   end End_Element;

   procedure Set_Command (Handler : in out Reader; Command : String) is
   begin
      Handler.Command := Asu.To_Unbounded_String (Command);
   end Set_Command;

   procedure Set_Help (Handler : in out Reader; Help : String) is
   begin
      Handler.Help := Asu.To_Unbounded_String (Help);
   end Set_Help;

end Cog_Cli.Xml_Reader;

The problem is that Sr.Set_Feature doesn't believe that Doc_Reader is the right type... I have no idea why. The literal error I'm getting is:

cog_cli-xml.adb:27:09: error: no candidate interpretations match the actuals:
cog_cli-xml.adb:27:23: error: expected private type "Readers.Reader" defined at sax-readers.ads:778
cog_cli-xml.adb:27:23: error: found private type "Xml_Reader.Reader" defined at cog_cli-xml_reader.ads:10
❌
❌