with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;

procedure test is
	Function Random return Integer is begin return 3; end;
	Function Random return Float is begin return 3.5; end;
	Function Random return Unbounded_String is begin return To_Unbounded_String( "abc" ); end;

	Procedure Print( V : Integer ) is begin Put_Line( Integer'Image(V) ); end;
	Procedure Print( V : Float ) is begin Put_Line( Float'Image(V) ); end;
	Procedure Print( V : Unbounded_String ) is begin Put_Line( Ada.Strings.Unbounded.To_String(V) ); end;

	Function Func( V : Integer ) return Integer is begin return V; end;
	Function Func( V : Float ) return Float is begin return V; end;
	Function Func( V : Unbounded_String ) return Unbounded_String is begin return V; end;
	Function Func( V1 : Integer; V2 : Float ) return Float is begin return Float(V1) + V2; end;

	subtype Int		 is Integer;
	J : Int;
	Function "-"( L, R : Int ) return Int is begin Put_Line( "X" ); return Integer(L) + (-Integer(R)); end; --  prevent infinite recusion

	--	duplicate body for "-" declared at line 20
	--	subtype SInt is Integer range -10 .. 10;
	--	Function "-"( L, R : SInt ) return SInt is begin Put_Line( "X" ); return Integer(L) + (-Integer(R)); end; --  prevent infinite recusion

	i : Integer;
	f : Float;
	s : Unbounded_String;

	Type Complex is
		record
		 Re, Im : Float;
		end record;
	c : Complex := (Re => 1.0, Im => 1.0);
	Procedure Grind (X : Complex) is begin Put_Line( "Grind1" ); end;
	Procedure Grind (X : Unbounded_String) is begin Put_Line( "Grind2" ); end;

	generic
		type T is private;
		with function "+"( X, Y: T ) return T;
	function twice( X : T ) return T;

	function twice( X: T ) return T is
	begin
		Put_Line( "XXX" ); return X + X;	-- The formal operator "*".
	end twice;

	function Int_Twice is new Twice( Integer, "+" => "+" );
	function float_Twice is new Twice( float, "+" => "+" );

	--	generic units cannot be overloaded
	--	generic
	--		type T is private;
	--		with function "+"( X, Y: T ) return T;
	--	function twice( X : T; Y : T ) return T;

	--	function twice( X: T; Y : T ) return T is
	--	begin
	--		Put_Line( "XXX" ); return X + X;	-- The formal operator "*".
	--	end twice;
begin
	I := 3;
	I := 7 - 3;
	Print( i );
	F := 3.8;
	I := 7 - 2;
	Print( i );
	J := 7 - 3;
	Print( j );

	i := Random;
	Print( i );
	f := Random;
	Print( f );
	s := Random;
	Print( s );

	Print( Func( V => 7 ) );
	Print( Func( 7.5 ) );
	Print( Func( To_Unbounded_String( "abc" ) ) );
	Print( Func( 3, 3.5 ) );
	--		Print( Func( 3, 3 ) );

	Grind( X => (Re => 1.0, Im => 1.0) );
	Grind( c );
	Grind( To_Unbounded_String( "abc" ) );

	i := Int_Twice( 2 );
	Put_Line( Integer'Image(i) );
	f := float_Twice( 2.5 );
	Print( f );
end test;

-- Local Variables: --
-- tab-width: 4 --
-- compile-command: "gnatmake test.adb" --
-- End: --
