Ada 202x (36日目) - 一時オブジェクト ==================================== .. post:: Jan 05, 2020 :tags: ada, ada_2022 対訳表を作っておくべきだった気もしてきました。 そんな厳密なの期待されてないですよね、ね。 オブジェクト ------------ これまでこのシリーズでは「\*型のオブジェクト」という言葉を説明なく使ってきました。 ニュアンスとしては ``constant`` を付けて宣言した定数や ``new`` で割り当てたもの等も含めた「変数」よりは大きなくくりを意図してはいました、一応、ふわっと。 改めて、Adaでのオブジェクトって何でしょうね? 規格では次のように説明されています。 `3.3 Objects and Named Numbers `_ Objects are created at run time and contain a value of a given type. An object can be created and initialized as part of elaborating a declaration, evaluating an allocator, aggregate, or function_call, or passing a parameter by copy. Prior to reclaiming the storage for an object, it is finalized if necessary (see 7.6.1). `Glossarry `_ An object is either a constant or a variable. An object contains a value. An object is created by an object_declaration or by an allocator. A formal parameter is (a view of) an object. A subcomponent of an object is an object. イメージはつかめましたでしょうか。 ……わかんないですよねー。 規格の文面なんて前提知識がないと意味不明です。 (天丼) とりあえず宣言した変数や定数、それにアロケーターで割り当てたものがオブジェクトなのは間違いなさそうです。 メモリ上でその型の内部表現を取っている入れ物であることは間違いないでしょう。 しかし、何かに代入する前の途中の式は果たしてオブジェクトなのでしょうか。 - リテラル(例えば ``1.0``)はオブジェクトなのでしょうか? - named number(例えば ``U : constant := 1.0;``)はオブジェクトなのでしょうか? - リテラルのqualified式(例えば ``Float'(1.0)``)はオブジェクトなのでしょうか? - オブジェクトのqualified式(例えば ``X : constant Float := 1.0;`` として ``Float'(X)``)はオブジェクトなのでしょうか? - 型変換の結果(例えば ``Float (1)``)はオブジェクトなのでしょうか? - 関数の返値(例えば ``Cos (0.0)``)はオブジェクトなのでしょうか? ある式がオブジェクトかどうかを手元のコンパイラで試す簡単な方法は ``renames`` できるか試すことです。 .. code-block:: ada with Ada.Numerics.Elementary_Functions; procedure Whether_It_Is_Object_1 is use Ada.Numerics.Elementary_Functions; U : constant := 1.0; X : constant Float := 1.0; -- Case1_Literal : Float renames 1.0; -- error -- Case2_Named_Number : Float renames U; -- error -- Case3_Qualified_L : Float renames Float'(1.0); -- error Case4_Qualified_X : Float renames Float'(X); -- Case5_Converted : Float renames Float (1.0); -- error Case6_Result : Float renames Cos (0.0); begin null; end Whether_It_Is_Object_1; .. container:: inserted 値のrenamesが認められてしまいましたのでAda 202x対応コンパイラではこの方法は使えなくなりました。 Ada 2012 with Technical Corrigendum 1以前のコンパイラ或いはモードを使ってください。 或いは属性を付けられるか試す方法もあります。 .. code-block:: ada with Ada.Text_IO; with Ada.Numerics.Elementary_Functions; procedure Whether_It_Is_Object_2 is use Ada.Numerics.Elementary_Functions; U : constant := 1.0; X : constant Float := 1.0; begin -- Ada.Text_IO.Put (1.0'Image); -- error -- Ada.Text_IO.Put (U'Image); -- error -- Ada.Text_IO.Put (Float'(1.0)'Image); -- error Ada.Text_IO.Put (Float'(X)'Image); -- Ada.Text_IO.Put (Float (1.0)'Image); -- error Ada.Text_IO.Put (Cos (0.0)'Image); end Whether_It_Is_Object_2; まあ、手元の処理系が正しく規格を実装しているとは限りませんけれどね。 実際GNAT(Community Edition 2019)は ``Case4_Qualified_X`` はエラーにしやがりましたし ``U'Image`` 、 ``Float'(1.0)'Image`` 、 ``Float (1.0)'Image`` をコンパイル通しやがりましたし……。 とまあくだらない事を書いて水増ししてみました。 経緯 ---- GNATのバグはともかくとしまして、規格上型変換がオブジェクト扱いされないのは不便です。 型変換は間違いなくメモリ上にその型の内部表現を持つ値を作っているわけです。 関数の返値と扱いが違うのは変です。 またqualified式に関しては複雑なルールがありましてaliasedやconstrained等の情報が抜け落ちる場合があります。 オーバーロードされた関数呼び出しを解決するためにqualified式で修飾したら他に影響が出るのは困ります。 .. code-block:: ada procedure Qualified_Error is F : aliased Float; L : aliased Long_Float; function Overloaded return not null access Float is (F'Access); function Overloaded return not null access Long_Float is (L'Access); X : Float renames Float'(Overloaded.all); A : not null access Float := X'Access; -- error begin null; end Qualified_Error; この例では ``X`` を宣言している行の ``Float'(`` ``)`` を消すとエラーがなくなります。 Ada 202xでの改善 ---------------- 型変換の結果がオブジェクト扱いになりました。 qualified式のルールは改善されました。 上の例 ``Qualified_Error`` はAda 202xではコンパイルできるようになりますし、最初の例はこうなります。 .. code-block:: ada with Ada.Numerics.Elementary_Functions; procedure whether_it_is_object1 is use Ada.Numerics.Elementary_Functions; U : constant := 1.0; X : constant Float := 1.0; -- Case1_Literal : Float renames 1.0; -- error -- Case2_Named_Number : Float renames U; -- error -- Case3_Qualified_L : Float renames Float'(1.0); -- error Case4_Qualified_X : Float renames Float'(X); Case5_Converted : Float renames Float (1.0); Case6_Result : Float renames Cos (0.0); begin null; end whether_it_is_object1; .. container:: inserted 値のrenamesが認められてしまいましたので全部OKです。 Ada 202xでは全ての型とそのオブジェクトに ``'Image`` 属性が使えるようになりましたから益々printデバッグが捗ります。 関連AI ------ - `AI12-0225-1`_ **Prefix of Obj'Image** - `AI12-0226-1`_ **Make objects more consistent** - `AI12-0228-1`_ **Properties of qualified expressions used as names** .. _`AI12-0225-1`: http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0225-1.txt .. _`AI12-0226-1`: http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0226-1.txt .. _`AI12-0228-1`: http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0228-1.txt