I am trying, again, to design a 2D array that expands automagically.
Rectangular.ads
generic
type Value_Type is private;
package Rectangular is
function Get ( Row, Col : Integer) return Value_Type;
procedure Set ( Row, Col : Integer; Value : Value_Type);
private
type Matrix is array (Integer range <>, Integer range <>) of aliased Value_Type;
Item : access Matrix;
end Rectangular;
Rectangular.adb
package body Rectangular is
function Create (Rowmin, Rowmax, Colmin, Colmax : Integer) return access Matrix is
begin
return Answer : constant access Matrix :=
new Matrix (Rowmin .. Rowmax, Colmin .. Colmax)
do
null; -- maybe something later...
end return;
end Create;
procedure Adjust_Bounds (Row, Col : Integer) is
Rowmin, Rowmax, Colmin, Colmax : Integer;
Newitem : access Matrix;
begin
if Row >= Item'First (1) and Row <= Item'Last (1) and
Col >= Item'First (2) and Col <= Item'Last (2) then
return;
end if;
-- Matrix needs expanding, establish new bounds
Rowmin := Integer'Min (Item'First (1), Row);
Rowmax := Integer'Min (Item'Last (1), Row);
Colmin := Integer'Min (Item'First (2), Col);
Colmax := Integer'Min (Item'Last (2), Col);
Newitem := Create (Rowmin, Rowmax, Colmin, Colmax);
-- Copy old to new
for R in Item'Range (1) loop
for C in Item'Range (2) loop
Newitem (R, C) := Item (R, C);
end loop;
end loop;
-- How to free Item here?
Item := Newitem;
end Adjust_Bounds;
function Get (Row, Col : Integer) return Value_Type is
Result : Value_Type;
begin
Adjust_Bounds (Row, Col);
Result := Item (Row, Col);
return Result;
end Get;
procedure Set ( Row, Col : Integer; Value : Value_Type) is
begin
Adjust_Bounds (Row, Col);
Item (Row, Col) := Value;
end Set;
begin
Item := Create (0, 0, 0, 0);
end Rectangular;
main.adb
with Ada.Text_IO; use Ada.Text_IO;
with Rectangular;
procedure Main is
begin
declare
package Rect is new Rectangular (Value_Type => Integer);
X : Integer;
begin
-- Only 0,0 exists initially
Rect.Set (0, 0, 2);
X := Rect.Get (0, 0);
Put_Line (X'Image);
-- Make the matrix expand
Rect.Set (1, 1, 42);
X := Rect.Get (1, 1);
Put_Line (X'Image);
end;
end Main;
This compiles, but with
6:17 warning: "Program_Error" will be raised at run time
6:17 warning: accessibility check failure
6:17 warning: in instantiation at rectangular.adb:29
and I of course get "raised PROGRAM_ERROR : rectangular.adb:59 accessibility check failed" when I try and run it.
I don't understand why, as 'Rect' is not clearly accessible outside the scope of the block;
I've been trying to get this to work for several days with no success, help with working code examples would be greatly appreciated.
Add after type Matrix
type Matrix_P is access Matrix;
(use your own convention for naming access types).
Then, globally replace access Matrix
by Matrix_P
.
Then, in Adjust_Bounds
, you appear to need to replace
Rowmax := Integer'Min (Item'Last (1), Row);
by
Rowmax := Integer'Max (Item'Last (1), Row);
and likewise for Colmax
.