I struggle with extension aggregates with limited types. I thought I understood the syntax but it seems not:
function Percent_cell
(Sheet : in out Spreadsheet_type'Class; Value : String)
return Percent_cell_type'Class is
((Formula_Cell (Sheet, Value) with null record))
The last line causes this error:
je-spreadsheets.adb:26:31: error: expect ancestor type of “Percent_cell_type’CLASS”
The fomula_cell function returns an element of Formula_cell_type, which is the direct ancestor of Percent_cell_type. What do I do ?
I can’t reproduce your specific error with the code provided but try to qualify your return type and see if that helps (note the apostrophe for type qualification rather than type conversion):
function Percent_cell
(Sheet : in out Spreadsheet_type'Class;
Value : String)
return Percent_cell_type'Class is
(Percent_cell_type'(Formula_Cell (Sheet, Value) with null record));
Okay, so I think I understood the issue.
You can’t change a discriminant of an expression in a delta aggregate, and you can’t provide one (or all) in the ancestral part of an extension aggregate either ! Meaning I can’t do anything with them. Or did I miss something ?
This fails:
pragma Ada_2022;
with Ada.Text_IO;
use Ada.Text_IO;
package test is
type SType is tagged null record;
type FC_type (Sheet: access Stype'Class) is tagged null record;
type BFC_type (Sheet: access stype'Class) is new fc_type (Sheet) with null record;
package Constructor is
function FC (Sheet : in out Stype'Class;
Value : String) return FC_type is (Seet => Sheet'Access);
function BFC (Sheet : in out Stype'Class; Value : String) return BFC_type is
(FC (Sheet, Value) with null record); -- HERE
end Constructor;
end test;
I don’t understand the reason. I thought both delta and extension aggregates worked like a macro expansion, taking the original expression and changing fields ?
When limited types are involved it is not considered copying, and I don’t think a tagged type can be derived without its full definition at least in the private part. As for unknown discriminant, here a value is given through a function.
I don’t know offhand how to fix the expression function version, but if you are ok using a full function body (so you’ll need an adb file for your package), then you can try to qualify it using subtypes to tell the compiler exactly what you expect:
package test is
type Spreadsheet_Type is abstract tagged limited null record;
type Spreadsheet_access is access all Spreadsheet_type'Class;
type Cell_Type (Sheet : Spreadsheet_Access) is abstract tagged limited null record;
type Formula_Cell_Type (Sheet : Spreadsheet_Access) is new Cell_Type(Sheet) with null record;
type Based_Formula_Cell_Type (Sheet : Spreadsheet_Access; Base: Ada.Text_IO.Number_Base)
is new Formula_Cell_Type (Sheet) with null record;
package Constr is
function Formula_Cell
(Sheet : in out Spreadsheet_type'Class)
return Formula_cell_type
is (Cell_type with Sheet'Unchecked_Access);
function Based_Formula_Cell
(Sheet : in out Spreadsheet_type'Class;
Value : String; Base: Ada.Text_IO.Number_Base)
return Based_Formula_Cell_Type;
end CONSTR;
end test;
package body test is
package body constr is
function Based_Formula_Cell
(Sheet : in out Spreadsheet_type'Class;
Value : String; Base: Ada.Text_IO.Number_Base)
return Based_Formula_Cell_Type
is
-- setup a subtype to qualify the function result
subtype Parent is Formula_Cell_Type(Sheet'Unchecked_Access);
begin
return (Parent'(Formula_cell(Sheet))
with Sheet => Sheet'Unchecked_Access,
Base => Base);
end Based_Formula_Cell;
end constr;
end test;
I haven’t tested passed getting it to compile in jdoodle, but something to explore?