From 883daa0474b6f7575d8bef09312b3b28fa456c56 Mon Sep 17 00:00:00 2001 From: gusthoff Date: Fri, 23 Oct 2026 22:39:02 +0200 Subject: [PATCH 01/10] Test script: Mark examples with variable output Example output can change between executions because of addresses, clocks, random values or task scheduling. During toolchain updates, these differences can resemble compiler regressions. Add `ada-run-expect-variable-output` as structured metadata so reviewers can distinguish expected variation from regressions when comparing toolchain versions. Extraction produces identical files with and without the annotation. Co-Authored-By: Claude Co-Authored-By: Codex --- .../chapters/03_Concurrency.rst | 8 ++++++++ .../advanced-ada/parts/control_flow/subprograms.rst | 4 ++++ .../parts/data_types/shared_variable_control.rst | 5 +++++ .../courses/advanced-ada/parts/data_types/strings.rst | 2 ++ .../parts/data_types/types_representation.rst | 6 ++++++ .../parts/resource_management/access_types.rst | 7 +++++++ .../parts/resource_management/limited_types.rst | 3 +++ .../chapters/standard_library_dates_times.rst | 4 ++++ .../chapters/standard_library_numerics.rst | 2 ++ content/courses/intro-to-ada/chapters/tasking.rst | 11 +++++++++++ .../chapters/image_attribute.rst | 1 + 11 files changed, 53 insertions(+) diff --git a/content/courses/Ada_For_The_Embedded_C_Developer/chapters/03_Concurrency.rst b/content/courses/Ada_For_The_Embedded_C_Developer/chapters/03_Concurrency.rst index 62d8ec152..9b9aa8614 100644 --- a/content/courses/Ada_For_The_Embedded_C_Developer/chapters/03_Concurrency.rst +++ b/content/courses/Ada_For_The_Embedded_C_Developer/chapters/03_Concurrency.rst @@ -62,6 +62,7 @@ of control in any of the examples, the output may be interspersed. [Ada] .. code:: ada run_button ada project=Courses.Ada_For_Embedded_C_Dev.Concurrency.My_Task + :class: ada-run-expect-variable-output with Ada.Text_IO; use Ada.Text_IO; @@ -105,6 +106,7 @@ the underlying implementation of the task scheduling algorithm. [Ada] .. code:: ada run_button project=Courses.Ada_For_Embedded_C_Dev.Concurrency.My_Task_Type + :class: ada-run-expect-variable-output package My_Tasks is @@ -141,6 +143,7 @@ and terminates when its work is completed. [Ada] .. code:: ada run_button project=Courses.Ada_For_Embedded_C_Dev.Concurrency.My_Task_Type + :class: ada-run-expect-variable-output with My_Tasks; use My_Tasks; @@ -161,6 +164,7 @@ data and coordinate execution. Let's consider the following example: [Ada] .. code:: ada run_button project=Courses.Ada_For_Embedded_C_Dev.Concurrency.Rendezvous + :class: ada-run-expect-variable-output with Ada.Text_IO; use Ada.Text_IO; @@ -199,6 +203,7 @@ and executes some code: [Ada] .. code:: ada run_button project=Courses.Ada_For_Embedded_C_Dev.Concurrency.Rendezvous_Params + :class: ada-run-expect-variable-output with Ada.Text_IO; use Ada.Text_IO; @@ -266,6 +271,7 @@ is modified by other tasks that call :ada:`Increment`, :ada:`Decrement`, and [Ada] .. code:: ada run_button project=Courses.Ada_For_Embedded_C_Dev.Concurrency.Selective_Rendezvous + :class: ada-run-expect-variable-output package Counters is @@ -498,6 +504,7 @@ a binary semaphore / persistent signal. [Ada] .. code:: ada run_button project=Courses.Ada_For_Embedded_C_Dev.Concurrency.Protected_Binary_Semaphore + :class: ada-run-expect-variable-output package Binary_Semaphores is @@ -645,6 +652,7 @@ in the main application: [Ada] .. code:: ada run_button project=Courses.Ada_For_Embedded_C_Dev.Concurrency.Ravenscar + :class: ada-run-expect-variable-output with My_Tasks; use My_Tasks; diff --git a/content/courses/advanced-ada/parts/control_flow/subprograms.rst b/content/courses/advanced-ada/parts/control_flow/subprograms.rst index acc8eba45..8aad20a09 100644 --- a/content/courses/advanced-ada/parts/control_flow/subprograms.rst +++ b/content/courses/advanced-ada/parts/control_flow/subprograms.rst @@ -58,6 +58,7 @@ actually passed. In fact, an :ada:`in out` parameter could be passed by copy. For example: .. code:: ada run_button project=Courses.Advanced_Ada.Control_Flow.Subprograms.Parameter_Modes_Associations.By_Copy_By_Ref_Params + :class: ada-run-expect-variable-output with System; @@ -196,6 +197,7 @@ more detail :ref:`in another chapter `. Let's see an example: .. code:: ada run_button project=Courses.Advanced_Ada.Control_Flow.Subprograms.Parameter_Modes_Associations.By_Copy_By_Ref_Params + :class: ada-run-expect-variable-output with System; @@ -328,6 +330,7 @@ parameter. This situation could lead to undefined behavior or to a program error. Consider the following code example: .. code:: ada run_button project=Courses.Advanced_Ada.Control_Flow.Subprograms.Parameter_Modes_Associations.By_Copy_By_Ref_Params + :class: ada-run-expect-variable-output with System; @@ -421,6 +424,7 @@ Let's rewrite a previous code example that has a parameter of elementary type and change it to *aliased*: .. code:: ada run_button project=Courses.Advanced_Ada.Control_Flow.Subprograms.Parameter_Modes_Associations.By_Copy_By_Ref_Params + :class: ada-run-expect-variable-output with System; diff --git a/content/courses/advanced-ada/parts/data_types/shared_variable_control.rst b/content/courses/advanced-ada/parts/data_types/shared_variable_control.rst index 670563393..e01d6adb2 100644 --- a/content/courses/advanced-ada/parts/data_types/shared_variable_control.rst +++ b/content/courses/advanced-ada/parts/data_types/shared_variable_control.rst @@ -1370,6 +1370,7 @@ important to ensure that no :wikipedia:`race conditions ` occur: .. code:: ada run_button project=Courses.Advanced_Ada.Data_Types.Shared_Variable_Control.Atomic_Operations.Exchange switches=Compiler(-gnat2022); + :class: ada-run-expect-variable-output with System.Atomic_Operations.Exchange; @@ -1514,6 +1515,7 @@ we'll use to generate random numbers in the expected range Let's use this package in the :ada:`Show_Lazy_Initialization` procedure: .. code:: ada run_button project=Courses.Advanced_Ada.Data_Types.Shared_Variable_Control.Atomic_Operations.Compare_And_Exchange switches=Compiler(-gnat2022); + :class: ada-run-expect-variable-output with Ada.Text_IO; use Ada.Text_IO; with Ada.Numerics.Discrete_Random; @@ -1664,6 +1666,7 @@ We can use these functions to implement an application similar to the we've seen before: .. code:: ada run_button project=Courses.Advanced_Ada.Data_Types.Shared_Variable_Control.Atomic_Operations.Test_And_Set switches=Compiler(-gnat2022); + :class: ada-run-expect-variable-output with System.Atomic_Operations.Test_And_Set; use System.Atomic_Operations.Test_And_Set; @@ -1789,6 +1792,7 @@ use the atomic operations from the :ada:`System.Atomic_Operations.Integer_Arithmetic` package: .. code:: ada run_button project=Courses.Advanced_Ada.Data_Types.Shared_Variable_Control.Atomic_Operations.Integer_Arithmetic switches=Compiler(-gnat2022); + :class: ada-run-expect-variable-output with System.Atomic_Operations.Integer_Arithmetic; @@ -1855,6 +1859,7 @@ Let's reuse the but replace the atomic integer type by an atomic modular type: .. code:: ada run_button project=Courses.Advanced_Ada.Data_Types.Shared_Variable_Control.Atomic_Operations.Modular_Arithmetic switches=Compiler(-gnat2022); + :class: ada-run-expect-variable-output with System.Atomic_Operations.Modular_Arithmetic; diff --git a/content/courses/advanced-ada/parts/data_types/strings.rst b/content/courses/advanced-ada/parts/data_types/strings.rst index cbf3e4635..320188b78 100644 --- a/content/courses/advanced-ada/parts/data_types/strings.rst +++ b/content/courses/advanced-ada/parts/data_types/strings.rst @@ -1500,6 +1500,7 @@ scalar types, but it isn't restricted to those types. In fact, we can also use this attribute when dealing with non-scalar types. For example: .. code:: ada run_button project=Courses.Advanced_Ada.Data_Types.Strings.Image_Attribute.Non_Scalar_Image switches=Compiler(-gnat2022); + :class: ada-run-expect-variable-output package Simple_Records is @@ -1662,6 +1663,7 @@ object of :ada:`Rec'Class` type. Also, we display the contents of the We can also apply the :ada:`Image` attribute to protected objects and tasks: .. code:: ada run_button project=Courses.Advanced_Ada.Data_Types.Strings.Image_Attribute.Protected_Task_Image switches=Compiler(-gnat2022); + :class: ada-run-expect-variable-output package Simple_Tasking is diff --git a/content/courses/advanced-ada/parts/data_types/types_representation.rst b/content/courses/advanced-ada/parts/data_types/types_representation.rst index 8c5760b5a..65a86d790 100644 --- a/content/courses/advanced-ada/parts/data_types/types_representation.rst +++ b/content/courses/advanced-ada/parts/data_types/types_representation.rst @@ -2464,6 +2464,7 @@ Here, we're assigning the address of the :ada:`I` object to the :ada:`A` address example: .. code:: ada run_button project=Courses.Advanced_Ada.Data_Types.Type_Representation.Addresses.Show_Address_Attribute + :class: ada-run-expect-variable-output with Ada.Text_IO; use Ada.Text_IO; with System.Address_Image; @@ -2493,6 +2494,7 @@ select an address automatically, but use the address that we're specifying. For example: .. code:: ada run_button project=Courses.Advanced_Ada.Data_Types.Type_Representation.Addresses.Address_Aspect + :class: ada-run-expect-variable-output with System; use System; with System.Address_Image; @@ -2594,6 +2596,7 @@ Address comparison We can compare addresses using the common comparison operators. For example: .. code:: ada run_button project=Courses.Advanced_Ada.Data_Types.Type_Representation.Addresses.Address_Aspect + :class: ada-run-expect-variable-output with System; use System; with System.Address_Image; @@ -2644,6 +2647,7 @@ using the :ada:`To_Address` and :ada:`To_Integer` functions. Let's see an example: .. code:: ada run_button project=Courses.Advanced_Ada.Data_Types.Type_Representation.Addresses.Pointer_Arith_Ada + :class: ada-run-expect-variable-output with System; use System; @@ -2698,6 +2702,7 @@ a code example where we iterate over an array by incrementing an address that *points* to each component in memory: .. code:: ada run_button project=Courses.Advanced_Ada.Data_Types.Type_Representation.Addresses.Pointer_Arith_Ada + :class: ada-run-expect-variable-output with System; use System; @@ -2768,6 +2773,7 @@ see the section on The code example above corresponds (more or less) to the following C code: .. code:: c manual_chop run_button main=main.c project=Courses.Advanced_Ada.Data_Types.Type_Representation.Addresses.Pointer_Arith_C + :class: ada-run-expect-variable-output !main.c #include diff --git a/content/courses/advanced-ada/parts/resource_management/access_types.rst b/content/courses/advanced-ada/parts/resource_management/access_types.rst index 1d79987d6..224b91288 100644 --- a/content/courses/advanced-ada/parts/resource_management/access_types.rst +++ b/content/courses/advanced-ada/parts/resource_management/access_types.rst @@ -283,6 +283,7 @@ type conversion is allowed is when both types have a common ancestor. Let's see an example: .. code:: ada run_button project=Courses.Advanced_Ada.Resource_Management.Access_Types.Access_Types_Allocation.Pool_Specific_Access_Types switches=Compiler(-gnat2022); + :class: ada-run-expect-variable-output with Ada.Text_IO; use Ada.Text_IO; @@ -356,6 +357,7 @@ the :ada:`A1 := A2` or the :ada:`A1 := Integer_Access_1 (A2)` assignment.) For example: .. code:: ada run_button project=Courses.Advanced_Ada.Resource_Management.Access_Types.Access_Types_Allocation.Array_Allocation switches=Compiler(-gnat2022); + :class: ada-run-expect-variable-output with Ada.Text_IO; use Ada.Text_IO; @@ -419,6 +421,7 @@ syntactic sugar is available to simplify the code that performs this allocation. For example: .. code:: ada run_button project=Courses.Advanced_Ada.Resource_Management.Access_Types.Access_Types_Allocation.Integer_Access_Array switches=Compiler(-gnat2022); + :class: ada-run-expect-variable-output with Ada.Text_IO; use Ada.Text_IO; @@ -467,6 +470,7 @@ designated objects with zero.) Let's see another code example, this time with task types: .. code:: ada run_button project=Courses.Advanced_Ada.Resource_Management.Access_Types.Access_Types_Allocation.Workers + :class: ada-run-expect-variable-output package Workers is @@ -6072,6 +6076,7 @@ convert between access types and addresses. This might be useful for specific low-level operations. Let's see an example: .. code:: ada run_button project=Courses.Advanced_Ada.Resource_Management.Access_Types.Access_Address.Address_Conversion + :class: ada-run-expect-variable-output with Ada.Text_IO; use Ada.Text_IO; @@ -6130,6 +6135,7 @@ is available to convert from an address to an object of access type. For example: .. code:: ada run_button project=Courses.Advanced_Ada.Resource_Management.Access_Types.Access_Address.Address_Conversion + :class: ada-run-expect-variable-output with Ada.Text_IO; use Ada.Text_IO; with System; use System; @@ -6187,6 +6193,7 @@ Let's adapt the previous code example and replace the :ada:`Integer` type by the (unbounded) :ada:`String` type: .. code:: ada run_button project=Courses.Advanced_Ada.Resource_Management.Access_Types.Access_Address.Address_Conversion + :class: ada-run-expect-variable-output with Ada.Text_IO; use Ada.Text_IO; with System; use System; diff --git a/content/courses/advanced-ada/parts/resource_management/limited_types.rst b/content/courses/advanced-ada/parts/resource_management/limited_types.rst index 7df8b680d..39bf295ce 100644 --- a/content/courses/advanced-ada/parts/resource_management/limited_types.rst +++ b/content/courses/advanced-ada/parts/resource_management/limited_types.rst @@ -2444,6 +2444,7 @@ For example, we can see this when looking at the address of the object type :ada:`Simple_Rec`: .. code:: ada run_button project=Courses.Advanced_Ada.Resource_Management.Limited_Types.Extended_Return_Statements_Limited_Types.Initialization_Return_Do + :class: ada-run-expect-variable-output package Limited_Types is @@ -2523,6 +2524,7 @@ procedure are the same object. nonlimited: .. code:: ada run_button project=Courses.Advanced_Ada.Resource_Management.Limited_Types.Extended_Return_Statements_Limited_Types.Initialization_Return_Copy + :class: ada-run-expect-variable-output package Non_Limited_Types is @@ -2837,6 +2839,7 @@ We can run the :ada:`Test` application below and compare the address of the not: .. code:: ada run_button project=Courses.Advanced_Ada.Resource_Management.Limited_Types.Limited_Types_Parameters.Explicitly_Limited_Types + :class: ada-run-expect-variable-output with System; diff --git a/content/courses/intro-to-ada/chapters/standard_library_dates_times.rst b/content/courses/intro-to-ada/chapters/standard_library_dates_times.rst index 6ba0e1925..faa410643 100644 --- a/content/courses/intro-to-ada/chapters/standard_library_dates_times.rst +++ b/content/courses/intro-to-ada/chapters/standard_library_dates_times.rst @@ -25,6 +25,7 @@ The :ada:`Ada.Calendar` package supports handling of dates and times. Let's look at a simple example: .. code:: ada run_button project=Courses.Intro_To_Ada.Standard_Library.Display_Current_Time + :class: ada-run-expect-variable-output with Ada.Text_IO; use Ada.Text_IO; with Ada.Calendar; use Ada.Calendar; @@ -243,6 +244,7 @@ benchmarking. We've used that package before in a previous section when discussing tasking. Let's look at an example of benchmarking: .. code:: ada run_button project=Courses.Intro_To_Ada.Standard_Library.Display_Benchmarking + :class: ada-run-expect-variable-output with Ada.Text_IO; use Ada.Text_IO; with Ada.Real_Time; use Ada.Real_Time; @@ -282,6 +284,7 @@ using the :ada:`Execution_Time` package. Let's modify the previous example to measure CPU time: .. code:: ada run_button project=Courses.Intro_To_Ada.Standard_Library.Display_Benchmarking_CPU_Time + :class: ada-run-expect-variable-output with Ada.Text_IO; use Ada.Text_IO; with Ada.Real_Time; use Ada.Real_Time; @@ -322,6 +325,7 @@ different if we change the implementation of loop. For example: .. code:: ada run_button project=Courses.Intro_To_Ada.Standard_Library.Display_Benchmarking_Math + :class: ada-run-expect-variable-output with Ada.Text_IO; use Ada.Text_IO; with Ada.Real_Time; use Ada.Real_Time; diff --git a/content/courses/intro-to-ada/chapters/standard_library_numerics.rst b/content/courses/intro-to-ada/chapters/standard_library_numerics.rst index 9b5f36b79..c1481fd19 100644 --- a/content/courses/intro-to-ada/chapters/standard_library_numerics.rst +++ b/content/courses/intro-to-ada/chapters/standard_library_numerics.rst @@ -91,6 +91,7 @@ number generator for the range between 0.0 and 1.0. To use it, declare a generator :ada:`G`, which you pass to :ada:`Random`. For example: .. code:: ada run_button project=Courses.Intro_To_Ada.Standard_Library.Show_Float_Random_Num + :class: ada-run-expect-variable-output with Ada.Text_IO; use Ada.Text_IO; @@ -124,6 +125,7 @@ following example, we create an application that displays random integers between 1 and 10: .. code:: ada run_button project=Courses.Intro_To_Ada.Standard_Library.Show_Discrete_Random_Num + :class: ada-run-expect-variable-output with Ada.Text_IO; use Ada.Text_IO; with Ada.Numerics.Discrete_Random; diff --git a/content/courses/intro-to-ada/chapters/tasking.rst b/content/courses/intro-to-ada/chapters/tasking.rst index 7fd2b7fa1..c826c68db 100644 --- a/content/courses/intro-to-ada/chapters/tasking.rst +++ b/content/courses/intro-to-ada/chapters/tasking.rst @@ -26,6 +26,7 @@ Tasks are declared using the keyword :ada:`task`. The task implementation is specified in a :ada:`task body` block. For example: .. code:: ada run_button project=Courses.Intro_To_Ada.Tasking.Show_Simple_Task + :class: ada-run-expect-variable-output with Ada.Text_IO; use Ada.Text_IO; @@ -68,6 +69,7 @@ Note that: both task :ada:`T` and the main task. For example: .. code:: ada run_button project=Courses.Intro_To_Ada.Tasking.Multiple_Simple_Task + :class: ada-run-expect-variable-output with Ada.Text_IO; use Ada.Text_IO; @@ -176,6 +178,7 @@ current task to sleep for the length of time (in seconds) specified in the delay statement. For example: .. code:: ada run_button project=Courses.Intro_To_Ada.Tasking.Show_Delay + :class: ada-run-expect-variable-output with Ada.Text_IO; use Ada.Text_IO; @@ -225,6 +228,7 @@ This synchronization between tasks is called a *rendezvous*. Let's see an example: .. code:: ada run_button project=Courses.Intro_To_Ada.Tasking.Show_Rendezvous + :class: ada-run-expect-variable-output with Ada.Text_IO; use Ada.Text_IO; @@ -278,6 +282,7 @@ automatically terminate the subtask when the master construct reaches its end. example: .. code:: ada run_button project=Courses.Intro_To_Ada.Tasking.Show_Rendezvous_Loop + :class: ada-run-expect-variable-output with Ada.Text_IO; use Ada.Text_IO; @@ -432,6 +437,7 @@ Using this auxiliary package, we're now ready to write our time-drifting application: .. code:: ada run_button project=Courses.Intro_To_Ada.Tasking.Show_Time + :class: ada-run-expect-variable-output with Ada.Text_IO; use Ada.Text_IO; with Ada.Real_Time; use Ada.Real_Time; @@ -470,6 +476,7 @@ the drift introduced by :ada:`Computational_Intensive_App`. Using the and have a regular interval of exactly one second: .. code:: ada run_button project=Courses.Intro_To_Ada.Tasking.Show_Time + :class: ada-run-expect-variable-output with Ada.Text_IO; use Ada.Text_IO; with Ada.Real_Time; use Ada.Real_Time; @@ -613,6 +620,7 @@ operation. It also contains two concurrent subprograms (main task and task :ada:`T`) that try to access the protected object. .. code:: ada run_button project=Courses.Intro_To_Ada.Tasking.Show_Protected_Objects_Entries + :class: ada-run-expect-variable-output with Ada.Text_IO; use Ada.Text_IO; @@ -707,6 +715,7 @@ objects are only created by variable definitions, not type definitions. To illustrate this, we repeat our first example: .. code:: ada run_button project=Courses.Intro_To_Ada.Tasking.Show_Simple_Task + :class: ada-run-expect-variable-output with Ada.Text_IO; use Ada.Text_IO; @@ -726,6 +735,7 @@ declare a task (:ada:`A_Task`) based on the task type :ada:`TT` after its definition: .. code:: ada run_button project=Courses.Intro_To_Ada.Tasking.Show_Simple_Task_Type + :class: ada-run-expect-variable-output with Ada.Text_IO; use Ada.Text_IO; @@ -749,6 +759,7 @@ to the individual tasks by defining a :ada:`Start` entry. Here's the updated example: .. code:: ada run_button project=Courses.Intro_To_Ada.Tasking.Show_Task_Type_Array + :class: ada-run-expect-variable-output with Ada.Text_IO; use Ada.Text_IO; diff --git a/content/courses/whats-new-in-ada-2022/chapters/image_attribute.rst b/content/courses/whats-new-in-ada-2022/chapters/image_attribute.rst index 09cea9a91..7906437b3 100644 --- a/content/courses/whats-new-in-ada-2022/chapters/image_attribute.rst +++ b/content/courses/whats-new-in-ada-2022/chapters/image_attribute.rst @@ -38,6 +38,7 @@ this works. We'll define array, record, and access types and corresponding objects and then convert these objects to strings and print them: .. code:: ada run_button project=Courses.Ada_2022_Whats_New.Image_Attribute switches=Compiler(-gnat2022); + :class: ada-run-expect-variable-output with Ada.Text_IO; From 01044161040b217d3af4ac5be85b6d450f7bb0d8 Mon Sep 17 00:00:00 2001 From: gusthoff Date: Fri, 23 Oct 2026 23:08:34 +0200 Subject: [PATCH 02/10] Correction: Make literal functions primitive operations GNAT 16 rejects the original literal aspect functions because those declared in `Main` are not primitive operations of `My_Type`. Move the type and literal functions into the `My_Types` package specification and import the package from `Main` in both examples. Both examples build and run with GNAT 16.1, producing unchanged output. Co-Authored-By: Claude Co-Authored-By: Codex --- .../chapters/user_defined_literals.rst | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/content/courses/whats-new-in-ada-2022/chapters/user_defined_literals.rst b/content/courses/whats-new-in-ada-2022/chapters/user_defined_literals.rst index 059dc62bb..a8183487f 100644 --- a/content/courses/whats-new-in-ada-2022/chapters/user_defined_literals.rst +++ b/content/courses/whats-new-in-ada-2022/chapters/user_defined_literals.rst @@ -25,10 +25,9 @@ for the internal representation: .. code:: ada run_button project=Courses.Ada_2022_Whats_New.User_Defined_Literals switches=Compiler(-gnat2022); - with Ada.Wide_Wide_Text_IO; with Ada.Characters.Conversions; - procedure Main is + package My_Types is type My_Type (Length : Natural) is record Value : Wide_Wide_String (1 .. Length); @@ -46,6 +45,13 @@ for the internal representation: function From_Integer (Value : String) return My_Type renames From_Real; + end My_Types; + + with Ada.Wide_Wide_Text_IO; + with My_Types; use My_Types; + + procedure Main is + procedure Print (Self : My_Type) is begin Ada.Wide_Wide_Text_IO.Put_Line (Self.Value); @@ -79,10 +85,9 @@ define a custom :ada:`+` operator: .. code:: ada run_button project=Courses.Ada_2022_Whats_New.User_Defined_Literals_JS switches=Compiler(-gnat2022); - with Ada.Wide_Wide_Text_IO; with Ada.Characters.Conversions; - procedure Main is + package My_Types is type My_Type (Length : Natural) is record Value : Wide_Wide_String (1 .. Length); @@ -103,6 +108,13 @@ define a custom :ada:`+` operator: function From_Integer (Value : String) return My_Type renames From_Real; + end My_Types; + + with Ada.Wide_Wide_Text_IO; + with My_Types; use My_Types; + + procedure Main is + procedure Print (Self : My_Type) is begin Ada.Wide_Wide_Text_IO.Put_Line (Self.Value); From c68652bcfb27f26809ed5a820bf800ef2d9b0dce Mon Sep 17 00:00:00 2001 From: gusthoff Date: Fri, 23 Oct 2026 23:24:21 +0200 Subject: [PATCH 03/10] Correction: Name boxed formal-package actuals GNAT 16 rejects positional boxes in the two signature-package examples. Ada RM 12.7 requires named notation for these boxed associations. Use `P => <>` and `Hash => <>` to leave the subprogram actuals unconstrained while binding the formal type to `T`. Both corrected examples pass GNAT 16.1; the positional forms fail with "box requires named notation". Co-Authored-By: Claude Co-Authored-By: Codex --- .../parts/abstraction-oriented_prog/generics.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/content/courses/advanced-ada/parts/abstraction-oriented_prog/generics.rst b/content/courses/advanced-ada/parts/abstraction-oriented_prog/generics.rst index 69ff798ed..458219e54 100644 --- a/content/courses/advanced-ada/parts/abstraction-oriented_prog/generics.rst +++ b/content/courses/advanced-ada/parts/abstraction-oriented_prog/generics.rst @@ -1821,7 +1821,8 @@ Let's briefly recapitulate these approaches: generic type T is private; - with package SP is new Sig_Pkg (T, <>); + with package SP is new + Sig_Pkg (T, P => <>); package Pkg is end Pkg; @@ -1974,7 +1975,7 @@ package: generic type T is private; with package T_Hashable is new - Hashable_Signature (T, <>); + Hashable_Signature (T, Hash => <>); package Hash_Tables is -- Missing implementation end Hash_Tables; From 68182fe75c44f10ef41d42ed31dfbe0df5433ab6 Mon Sep 17 00:00:00 2001 From: gusthoff Date: Fri, 23 Oct 2026 23:24:33 +0200 Subject: [PATCH 04/10] Correction: Initialize the volatile configuration value GNATprove 16 reports that `External_Variable` is not written by `Configuration`, despite its `Initializes` contract. Reading it to initialize `Max` during `Stack` elaboration requires this contract; removing it also fails flow analysis. Initialize the non-imported variable to a valid `Positive` value. `Max` still has variable input and must remain in `The_Stack`'s state refinement. Flow analysis passes with GNATprove 15 and 16. Removing the initializer fails with 16; removing `Max` from the refinement still fails with 16. Co-Authored-By: Claude Co-Authored-By: Codex --- .../courses/intro-to-spark/chapters/04_State_Abstraction.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/courses/intro-to-spark/chapters/04_State_Abstraction.rst b/content/courses/intro-to-spark/chapters/04_State_Abstraction.rst index e3dbebe63..592e2a974 100644 --- a/content/courses/intro-to-spark/chapters/04_State_Abstraction.rst +++ b/content/courses/intro-to-spark/chapters/04_State_Abstraction.rst @@ -377,7 +377,7 @@ Let's look at this example. package Configuration with Initializes => External_Variable is - External_Variable : Positive with Volatile; + External_Variable : Positive := 1 with Volatile; end Configuration; with Configuration; From e2302d0deb2593f25c55fc79d5eec65b3b850727 Mon Sep 17 00:00:00 2001 From: gusthoff Date: Fri, 23 Oct 2026 23:31:07 +0200 Subject: [PATCH 05/10] Toolchain: Drop obsolete pins from eight examples Six container aggregate examples and two SPARK contract examples pass with the GNAT 16 toolchain. Remove their GNAT 14.2 and GNATprove 14.1 pins and restore the run/prove buttons. All eight blocks pass the pipeline checks with GNAT/GNATprove 16.1 and GPRbuild 26, including the expected contract diagnostic. Co-Authored-By: Claude Co-Authored-By: Codex --- .../chapters/05_SPARK.rst | 7 +++---- .../parts/resource_management/containers.rst | 18 ++++++------------ 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/content/courses/Ada_For_The_Embedded_C_Developer/chapters/05_SPARK.rst b/content/courses/Ada_For_The_Embedded_C_Developer/chapters/05_SPARK.rst index 9fbf260c9..40ce0aa15 100644 --- a/content/courses/Ada_For_The_Embedded_C_Developer/chapters/05_SPARK.rst +++ b/content/courses/Ada_For_The_Embedded_C_Developer/chapters/05_SPARK.rst @@ -761,8 +761,8 @@ than the value passed to :ada:`X`. Consider a client calling this function: -.. code:: ada no_button gnatprove=14.1.0-1 project=Courses.Ada_For_Embedded_C_Dev.SPARK.Contracts_2 switches=Compiler(-gnato23); - :class: ada-prove, ada-expect-prove-error +.. code:: ada prove_button project=Courses.Ada_For_Embedded_C_Dev.SPARK.Contracts_2 switches=Compiler(-gnato23); + :class: ada-expect-prove-error with Mid; with Ada.Text_IO; use Ada.Text_IO; @@ -784,8 +784,7 @@ elsewhere.) Let's change the argument passed to :ada:`Y` in the second call (line 8). Instead of -1 we will pass -2: -.. code:: ada no_button gnatprove=14.1.0-1 project=Courses.Ada_For_Embedded_C_Dev.SPARK.Contracts_3 switches=Compiler(-gnato23); - :class: ada-prove +.. code:: ada prove_button project=Courses.Ada_For_Embedded_C_Dev.SPARK.Contracts_3 switches=Compiler(-gnato23); with Mid; with Ada.Text_IO; use Ada.Text_IO; diff --git a/content/courses/advanced-ada/parts/resource_management/containers.rst b/content/courses/advanced-ada/parts/resource_management/containers.rst index 69cc22382..33e8e3cfc 100644 --- a/content/courses/advanced-ada/parts/resource_management/containers.rst +++ b/content/courses/advanced-ada/parts/resource_management/containers.rst @@ -153,8 +153,7 @@ two scenarios: Let's see a complete code example: -.. code:: ada no_button gnat=14.2.0-1 project=Courses.Advanced_Ada.Aggregates.Container_Aggregate_Empty switches=Compiler(-gnat2022); - :class: ada-run +.. code:: ada run_button project=Courses.Advanced_Ada.Aggregates.Container_Aggregate_Empty switches=Compiler(-gnat2022); package Custom_Container_Aggregates is @@ -250,8 +249,7 @@ needed. In addition to this, we can specify a signed integer parameter |mdash| which indicates the number of components |mdash| for the :ada:`Empty` function: -.. code:: ada no_button gnat=14.2.0-1 project=Courses.Advanced_Ada.Aggregates.Container_Aggregate_Empty switches=Compiler(-gnat2022); - :class: ada-run +.. code:: ada run_button project=Courses.Advanced_Ada.Aggregates.Container_Aggregate_Empty switches=Compiler(-gnat2022); package Custom_Container_Aggregates is @@ -336,8 +334,7 @@ of these elements: :ada:`Add_Unnamed`, :ada:`New_Indexed` or :ada:`Assign_Indexed`. In other words, when we specify the :ada:`Add_Named` element, we can only use the :ada:`Empty` element in the same declaration. -.. code:: ada no_button gnat=14.2.0-1 project=Courses.Advanced_Ada.Aggregates.Container_Aggregate_Named switches=Compiler(-gnat2022); - :class: ada-run +.. code:: ada run_button project=Courses.Advanced_Ada.Aggregates.Container_Aggregate_Named switches=Compiler(-gnat2022); package Custom_Container_Aggregates is @@ -441,8 +438,7 @@ procedure that is called when we have a positional container aggregate. Let's look at an example: -.. code:: ada no_button gnat=14.2.0-1 project=Courses.Advanced_Ada.Aggregates.Container_Aggregate_Unnamed switches=Compiler(-gnat2022); - :class: ada-run +.. code:: ada run_button project=Courses.Advanced_Ada.Aggregates.Container_Aggregate_Unnamed switches=Compiler(-gnat2022); package Custom_Container_Aggregates is @@ -534,8 +530,7 @@ that, when we specify the :ada:`Assign_Indexed` element, we must also use the Let's look at an example: -.. code:: ada no_button gnat=14.2.0-1 project=Courses.Advanced_Ada.Aggregates.Container_Aggregate_Indexed switches=Compiler(-gnat2022); - :class: ada-run +.. code:: ada run_button project=Courses.Advanced_Ada.Aggregates.Container_Aggregate_Indexed switches=Compiler(-gnat2022); package Custom_Container_Aggregates is @@ -684,8 +679,7 @@ As mentioned previously, we may specify both :ada:`Add_Named` and :ada:`Assign_Indexed` elements together in the same aspect declaration. For example: -.. code:: ada no_button gnat=14.2.0-1 project=Courses.Advanced_Ada.Aggregates.Container_Aggregate_Unnamed_Indexed switches=Compiler(-gnat2022); - :class: ada-run +.. code:: ada run_button project=Courses.Advanced_Ada.Aggregates.Container_Aggregate_Unnamed_Indexed switches=Compiler(-gnat2022); package Custom_Container_Aggregates is From 681afe86d235e6a0100062c11f972df7e24e90c7 Mon Sep 17 00:00:00 2001 From: gusthoff Date: Fri, 23 Oct 2026 23:31:19 +0200 Subject: [PATCH 06/10] Toolchain: Pin ghost-code examples to GNAT 15 GNAT 16 no longer reports the ghost-use diagnostics discussed in the ring-buffer examples 2 and 4. Pin both examples to the GNAT 15 toolchain to preserve their expected errors and the accompanying explanations. Replace compile/prove buttons with classes that keep pipeline checks active while disabling the buttons for the default toolchain. Both examples pass the checks with the pinned GNAT/GNATprove 15 and GPRbuild 25 toolchain. Co-Authored-By: Claude Co-Authored-By: Codex --- .../chapters/05_Proof_Of_Functional_Correctness.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/content/courses/intro-to-spark/chapters/05_Proof_Of_Functional_Correctness.rst b/content/courses/intro-to-spark/chapters/05_Proof_Of_Functional_Correctness.rst index d6641c704..99b986213 100644 --- a/content/courses/intro-to-spark/chapters/05_Proof_Of_Functional_Correctness.rst +++ b/content/courses/intro-to-spark/chapters/05_Proof_Of_Functional_Correctness.rst @@ -1161,8 +1161,8 @@ Example #2 Instead of using a ghost function, :ada:`Get_Model`, to retrieve the contents of the ring buffer, we're now using a global ghost variable, :ada:`Model`. -.. code:: ada compile_button prove_button project=Courses.Intro_To_Spark.Proof_of_Functional_Correctness.Example_02 - :class: ada-expect-compile-error, ada-expect-prove-error +.. code:: ada no_button gnat=15.1.0-2 gnatprove=15.1.0-1 gprbuild=25.0.0-1 project=Courses.Intro_To_Spark.Proof_of_Functional_Correctness.Example_02 + :class: ada-expect-compile-error, ada-expect-prove-error, ada-compile, ada-prove package Ring_Buffer is @@ -1282,8 +1282,8 @@ Example #4 We're now modifying :ada:`Push_Last` to share the computation of the new length between the operational and ghost code. -.. code:: ada compile_button prove_button project=Courses.Intro_To_Spark.Proof_of_Functional_Correctness.Example_04 - :class: ada-expect-prove-error +.. code:: ada no_button gnat=15.1.0-2 gnatprove=15.1.0-1 gprbuild=25.0.0-1 project=Courses.Intro_To_Spark.Proof_of_Functional_Correctness.Example_04 + :class: ada-expect-prove-error, ada-compile, ada-prove package Ring_Buffer is From 155c13cc21e40440a863b9bebbe49fb0784868bd Mon Sep 17 00:00:00 2001 From: gusthoff Date: Fri, 23 Oct 2026 23:34:12 +0200 Subject: [PATCH 07/10] Toolchain: Set GNAT 16.1 as the default Use GNAT and GNATprove 16.1 with GPRbuild 26 for unpinned examples. Keep older versions required by the remaining example pins, and remove unreferenced GNATprove 14.1 and GPRbuild 22/24 releases. Validated 18 files with 537 passing block reports on the updated worktree VM, including all five pinned examples. Co-Authored-By: Claude Co-Authored-By: Codex --- .../src/rst_code_example_pipeline/data/toolchain.ini | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/frontend/python/rst_code_example_pipeline/src/rst_code_example_pipeline/data/toolchain.ini b/frontend/python/rst_code_example_pipeline/src/rst_code_example_pipeline/data/toolchain.ini index 4f048e0b8..c5f9c19dc 100644 --- a/frontend/python/rst_code_example_pipeline/src/rst_code_example_pipeline/data/toolchain.ini +++ b/frontend/python/rst_code_example_pipeline/src/rst_code_example_pipeline/data/toolchain.ini @@ -6,11 +6,11 @@ selected = /opt/ada/selected default = /opt/ada/default [default_version] -gnat = 15.1.0-2 -gnatprove = 15.1.0-1 -gprbuild = 25.0.0-1 +gnat = 16.1.0-1 +gnatprove = 16.1.0-1 +gprbuild = 26.0.0-1 [toolchains] -gnat = 12.2.0-1 14.2.0-1 15.1.0-2 -gnatprove = 12.1.0-1 14.1.0-1 15.1.0-1 -gprbuild = 22.0.0-1 24.0.0-2 25.0.0-1 +gnat = 12.2.0-1 14.2.0-1 15.1.0-2 16.1.0-1 +gnatprove = 12.1.0-1 15.1.0-1 16.1.0-1 +gprbuild = 25.0.0-1 26.0.0-1 From 67502c22f0c15fc832a0c0a37c2f7309a53a0f08 Mon Sep 17 00:00:00 2001 From: gusthoff Date: Fri, 23 Oct 2026 23:59:35 +0200 Subject: [PATCH 08/10] Sphinx: Support variable-output example metadata Recognize `ada-run-expect-variable-output` as widget metadata so Sphinx can render examples that mark expected output variation. Preserve the widget's existing buttons and execution behavior. Validated the full HTML build with warnings treated as errors, the existing parser suite, TypeScript tests, and LaTeX/EPUB fixtures. Co-Authored-By: Claude Co-Authored-By: Codex --- frontend/sphinx/widget/widget.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/frontend/sphinx/widget/widget.py b/frontend/sphinx/widget/widget.py index 58e60e2d7..44eea3191 100644 --- a/frontend/sphinx/widget/widget.py +++ b/frontend/sphinx/widget/widget.py @@ -361,6 +361,9 @@ def parseOpts(self, opts: List[str]): 'c-run-expect-failure']: # this is for testing, nothing to do here continue + elif opt == 'ada-run-expect-variable-output': + # Output variability is metadata, with no effect on the widget. + continue elif opt in ['ada-prove', 'ada-prove-flow', 'ada-prove-flow-report-all', 'ada-prove-report-all']: From ab56e843afbc00ffda89be8cb6ee0ee423c2da3e Mon Sep 17 00:00:00 2001 From: gusthoff Date: Sat, 24 Oct 2026 12:31:15 +0200 Subject: [PATCH 09/10] Correction: Align OO example project names Assign `Show_Cat` and `Show_Geo_Forms` to the projects containing their package declarations so extraction includes the required `Animals` and `Geo_Forms` units. The object-oriented chapter check passes with GNAT 16.1 and GPRbuild 26. Co-Authored-By: Claude Co-Authored-By: Codex --- .../advanced-ada/parts/abstraction-oriented_prog/oo_prog.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/courses/advanced-ada/parts/abstraction-oriented_prog/oo_prog.rst b/content/courses/advanced-ada/parts/abstraction-oriented_prog/oo_prog.rst index 0ff53f144..aa20a0ccf 100644 --- a/content/courses/advanced-ada/parts/abstraction-oriented_prog/oo_prog.rst +++ b/content/courses/advanced-ada/parts/abstraction-oriented_prog/oo_prog.rst @@ -250,7 +250,7 @@ All types implementing the :ada:`Animal` interface have to override the end Animals.Cats; -.. code:: ada run_button project=Courses.Advanced_Ada.Abstraction-Oriented_Prog.OO_Prog.Extending_Interfaces +.. code:: ada run_button project=Courses.Advanced_Ada.Abstraction-Oriented_Prog.OO_Prog.Interfaces.Extending_Interfaces with Animals.Cats; use Animals.Cats; @@ -726,7 +726,7 @@ Here is a full example: end Geo_Forms.Squares; -.. code:: ada run_button project=Courses.Advanced_Ada.Abstraction-Oriented_Prog.OO_Prog.Call_Inherited_Subprograms_2 +.. code:: ada run_button project=Courses.Advanced_Ada.Abstraction-Oriented_Prog.OO_Prog.Calling_Inherited_Subprograms.Geometric_Forms_2 with Ada.Text_IO; use Ada.Text_IO; with Geo_Forms.Squares; use Geo_Forms.Squares; From 46137721fafa10337b566658bd46661e6705852c Mon Sep 17 00:00:00 2001 From: gusthoff Date: Sat, 24 Oct 2026 12:31:25 +0200 Subject: [PATCH 10/10] Correction: Use backing array in flow contract Express `Set`'s dependency as `Ext => Ext`. The volatile objects `X` and `Y` overlay elements of `Ext`, so the contract describes the underlying array read and updated by `Set`. Co-Authored-By: Claude Co-Authored-By: Codex --- .../courses/advanced-spark/chapters/systems_programming.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/content/courses/advanced-spark/chapters/systems_programming.rst b/content/courses/advanced-spark/chapters/systems_programming.rst index 0113a33e9..8b2dc9709 100644 --- a/content/courses/advanced-spark/chapters/systems_programming.rst +++ b/content/courses/advanced-spark/chapters/systems_programming.rst @@ -214,8 +214,7 @@ Using ``Effective_Reads`` / ``Effective_Writes`` Effective_Reads; procedure Set with - Depends => (X => Y, - Y => Y); + Depends => (Ext => Ext); end Volatile_Vars; package body Volatile_Vars is