Ada 202x (45日目) - その他のその他の変更 ======================================== .. post:: Jan 14, 2020 :tags: ada, ada_2022 まとめていきます。 目指せ完結。 固定小数点数関連 ---------------- "*"演算子 +++++++++ 固定小数点型の値と任意の整数型の値とで掛け算(``"*"``)ができるように受け取れる文章が修正されました。 既定義で用意されるのは ``Integer`` との演算です。 サブプログラム関連 ------------------ 同じオブジェクトを複数の引数に使うケースの緩和 ++++++++++++++++++++++++++++++++++++++++++++++ ``@`` のときに「ひとつの文中で ``in out`` パラメータに渡したオブジェクトを同時に他に使うことはできません。」と説明しました。 :doc:`4日目 `\ を参照。 この判定のためのルールが若干緩和、というより本来の意図通りの文面に修正されました。 この変更はAARMでもwording changeに分類されるぐらい影響は超レアなのですが折角読み解いたので書かせてください。 まず、先のざっくりした説明では説明しきれていないことがあります。 参照渡しなら同じ呼び出しでは同時に複数引数に渡してもセーフです。 .. code-block:: ada declare type By_Ref is tagged null record; procedure P1 (A, B : in out By_Ref); -- P1の実装は省略 X : By_Ref; begin P1 (X, X); 参照渡しでも同じ呼び出しでなければ評価順の影響を受けますのでアウトです。 .. code-block:: ada declare function F1 (A : in out By_Ref) return Integer; -- F1の実装は省略 Z : Integer; begin Z := F1 (X) + F1 (X); -- error 値渡しは同じ呼び出しでも評価順の影響を受けますので全部アウトです。 値渡しの ``out`` パラメータは値渡しして値返しされた結果を書き戻すことで実現されます。 この書き戻しの順番が同じ呼び出し内でも不定です。 複合型は値渡しも参照渡しもあります。 最適化で変化する可能性もあります。 例では確実に参照渡しにするためにtagged型にしています。 基本型は常に値渡しです。 ……というのを踏まえまして。 影響するのは4引数以上のサブプログラム呼び出しで、2つの引数が同じ複合型、残り2つの引数が基本型の場合のみです。 モードは全部 ``in out`` か ``out`` のどちらかとします。 複合型の2つの引数は参照渡しならセーフ、値渡しならアウトです。 基本型の2つの引数は常に値渡しのため確実に別のオブジェクトでなければなりません。 このように規格の文面はまず複合型か基本型かで分けられてその次に参照渡しか値渡しかで分けられています。 実際にはもっと細かいですが。 で、基本型のときの文面が複合型のほうに影響してしまっていました。 つまり本来セーフの次の例がアウトになっていました。 .. code-block:: ada declare procedure P2 (A, B : in out By_Ref; C, D : in out Integer); -- P2の実装は省略 X : By_Ref; Y, Z : Integer; begin P2 (X, X, Y, Z); 複合型の方のルールでは参照渡しですのでセーフです。 基本型の方のルールが問題で2つの引数は ``Y`` と ``Z`` という別々のオブジェクトを渡しているにも関わらず、複合型の方に両方 ``X`` を渡しているのが引っかかってしまっていました。 この超細かい問題がAda 202xで修正されました。 パッケージ関連 -------------- incomplete型とfreezing ++++++++++++++++++++++ 特殊な用法においてincomplete型がサブプログラムの引数に使える場面が増えました。 incomplete型は名前だけ先行宣言された型です。 C言語でいうopaque型です。 freezingされるより前に完全な宣言を行う必要があります。 freezingは型の定義をそれ以降変更できなくなることです。 :doc:`42日目 `\ を参照。 よく使われる例としてはリンクリストの定義があります。 .. code-block:: ada declare type Node; type Node_Access is access Node; type Node is record Previous : Node_Access; Element : Float; end record; 1つ目の ``type Node;`` がincomplete型としての宣言です。 このような相互に参照しあう型の他、 ``generic`` や ``limited with`` のためにも活用されます。 少々特殊な用法としてbody部内の型をprivate部でincomplete型として宣言して使うことができます。 この用法自体は昔からあります。 .. code-block:: ada package Pkg1 is procedure Proc1; private type T; X : access T; end Pkg1; package body Pkg1 is procedure Proc1 is begin null; end Proc1; type T is null record; end Pkg1; ところがこの用法ではincomplete型をサブプログラムの引数にできませんでした。 .. code-block:: ada package Pkg2 is private type T; X : access T; procedure Proc2 (Object : in T); -- error end Pkg2; -- bodyは省略 本来incomplete型はサブプログラムの引数にできます。 先程の ``Node`` の例で途中にサブプログラムの宣言を挟んでも問題ありません。 .. code-block:: ada declare type Node; type Node_Access is access Node; procedure Add (Root : in out Node; Element : in Float); type Node is record Previous : Node_Access; Element : Float; end record; では何が駄目なのかといいますと、パッケージの仕様部の最後まで到達しますと宣言されたサブプログラムの引数に使われている型が全部freezingされるルールに引っかかっていました。 周りくどいルールですが必要だからあるルールではあるのです。 しかしincomplete型と完全な宣言が分かれる特殊な用法を考慮されていませんでした。 Ada 202xで修正され ``Proc2`` のようなサブプログラムも存在できるようになります。 private procedureとprivate with +++++++++++++++++++++++++++++++ ``private procedure`` の仕様部から親パッケージの ``private with`` が見えるようになりました。 .. code-block:: ada package Lib is type T is null record; end Lib; private with Lib; package Parent is end Parent; private procedure Parent.Child (A : Lib.T); アスペクト関連 -------------- 自己参照の禁止 ++++++++++++++ .. code-block:: ada X : constant Natural := 1 with Atomic => X > 0; この手の自己参照が禁止されました。 (GNATはAIの中で出された例は弾きましたがちょっと変えてこうするとクラッシュしました。 わはは。) 抽象型と内部表現のアスペクト ++++++++++++++++++++++++++++ 抽象型には内部表現のアスペクトは付けられなくなりました。 .. code-block:: ada package Pkg3 is type T is private with Size => 8; -- error private type T is mod 2 ** 8; end Pkg3; 内部表現はprivate部に書く必要があります。 .. code-block:: ada package Pkg4 is type T is private; private type T is mod 2 ** 8 with Size => 8; end Pkg4; Remote_Call_Interface関連 ------------------------- 'Read/'Write属性の実装禁止 ++++++++++++++++++++++++++ ``Remote_Call_Interface`` パッケージで宣言されたサブプログラムの呼び出しはRPC(remote procedure call)に変換されます。 主にCORBA(死語)やO/Rマッピング等に使われます。 その中で定義した型の ``'Read``/``'Write`` 属性をユーザー定義の実装に置き換えることは禁止されました。 .. code-block:: ada private with Ada.Streams; package RCI with Remote_Call_Interface is type T is null record; procedure RPC (X : in T); private procedure Read (Stream : not null access Ada.Streams.Root_Stream_Type'Class; Item : out T); procedure Write (Stream : not null access Ada.Streams.Root_Stream_Type'Class; Item : in T); for T'Read use Read; -- error for T'Write use Write; -- error end RCI; RPCにおいて引数をバイト列にして転送するために ``'Read``/``'Write`` 属性が使われます。 ところが ``Remote_Call_Interface`` パッケージ中で定義された ``'Read``/``'Write`` 属性の実装になるサブプログラムはそれ自体もRPCの対象になってしまいます。 ``'Read``/``'Write`` 属性をカスタマイズしたければ型ごと別のパッケージに分離する必要があります。 この修正はAda 2012に入るはずでしたが間に合いませんでした。 Nonblocking +++++++++++ ``Remote_Call_Interface`` パッケージのサブプログラムや ``Remote_Types`` パッケージの型の ``Nonblocking`` アスペクトは ``False`` でなければなりません。 他言語関連 ---------- C言語側でinパラメータを書き換えてはいけない +++++++++++++++++++++++++++++++++++++++++++ 小見出しの通りです。 はっきり言って今までも駄目でした。 念押しの記述が追加されました。 正直変更ではないのですが意図を汲んで私からも念押ししておきます。 .. code-block:: ada with Interfaces.C; package Imported is type t is record a, b : Interfaces.C.int; end record with Convention => C; procedure c_ffi1 (x : in t) with Import, Convention => C; end Imported; .. code-block:: c /* This is BAD example! */ struct t { int a, b; }; void c_ffi1 (struct t *x) { x->a = 1; } Ada側で ``in`` としているものをC側で変更するな! ……とのことです。 よほど守らない奴がいてSteve先生も腹に据えかねたのでしょう。 Fortranのバージョンの更新 +++++++++++++++++++++++++ 規格が参照しているFortranのバージョンがISO/IEC 1594-1:2018に更新されました。 Fortran 2018になります。 もしFortranに古いイメージをお持ちでしたら調べてみると面白いかもしれません。 関連AI ------ - `AI12-0002-1`_ **RCI units do not allow specification of user-defined stream-oriented attributes** - `AI12-0155-1`_ **Freezing of an incomplete view has no effect** - `AI12-0181-1`_ **Self-referencing representation aspects** - `AI12-0216-1`_ **6.4.1(6.16-17/3) should never apply to composite objects** - `AI12-0219-1`_ **Clarify C interfacing advice** - `AI12-0222-1`_ **Representation aspects and private types** - `AI12-0224-1`_ **Use of Fortran C Interfacing features** - `AI12-0261-1`_ **Conflict in "private with" rules** - `AI12-0283-1`_ **Nonblocking and remote calls** - `AI12-0300-1`_ **Annex G text for Fixed * integer** .. _`AI12-0002-1`: http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0002-1.txt .. _`AI12-0155-1`: http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0155-1.txt .. _`AI12-0181-1`: http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0181-1.txt .. _`AI12-0216-1`: http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0216-1.txt .. _`AI12-0219-1`: http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0219-1.txt .. _`AI12-0222-1`: http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0222-1.txt .. _`AI12-0224-1`: http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0224-1.txt .. _`AI12-0261-1`: http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0261-1.txt .. _`AI12-0283-1`: http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0283-1.txt .. _`AI12-0300-1`: http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0300-1.txt