Ada 202x (54日目) - 12月9日の電子会議の結果¶
12月9日に行われた電子会議の議事録が公開されました。 次回の会議は1月20日になるそうです。 案の定2020年内にまとまりませんでしたね……先例からして呼称はAda 2021にはならずAda 2020のままになると思われます。 結局Ada 2022になりました。
aliased引数を持つ関数呼び出し¶
関数呼び出しではaliased引数に渡す実引数は呼び出し箇所よりも浅いレベルのものでなければなりませんでした。
type T1 is record
E1 : aliased Integer;
end record;
function F1 (A1 : aliased T1) return not null access Integer is
begin
return A1.E'Access;
end F1;
Global : aliased T1;
function Caller1 return not null access Integer is
begin
return F1 (Global);
end Caller1;
function Caller2 (Argument : aliased T1) return not null access Integer is
begin
return F1 (Argument);
end Caller1;
function Caller3 (A1 : aliased T1) return not null access Integer is
Local : aliased T1;
begin
return F1 (Local); -- error
end Caller1;
この例では Caller3
はローカル変数の要素への参照を返そうとしていますのでエラーです。
このチェックは返値がaccess型を含まなくても、引数に aliased
が付いているかどうかだけが条件でした。
function F2 (A1 : aliased T1) return Integer is
begin
return A1.E;
end F1;
function Caller4 (A1 : aliased T1) return Integer is
Local : aliased T1;
begin
return F1 (Local); -- error
end Caller1;
このような関数呼び出しが、返値の型が(匿名のaccess型を除く)基本型の場合は許されるようになります。
Stable_Propertiesの修正¶
細かい点が詰められています。
out引数には影響しないことが明記されました。
access引数には影響しないことが明記されました。
使用される
"="
演算子はin
式で用いられるものと同じものとされました。 可視性の上で別に定義した"="
演算子が見えていても使われません。 ("and"
演算子についても同じ議論がなされたようですがこちらは明記されませんでした。)派生型で指定された
Stable_Properties
が継承されてoverriding
されていないプリミティブにも影響する、とされました。pragma Assertion_Policy (Post, ...);
がStable_Properties
にも影響することが明記されました。Post'Class
も同様です。事後条件の中で
Stable_Properties
で指定された関数が使われてさえすればStable_Properties
による事後条件は生成されないことになっています。 この際引数については特に問われておらず関係の無さそうな呼び出しでも事後条件が生成されません。 この動作がこれで良いことが確認されました。in引数には影響するようです。 ただし
Stable_Properties
に指定された関数、null
手続き、既定義の演算子、列挙型の要素名、Global => null
が付けられたものには影響しません。 (副作用が無ければチェックも不要ということでしょうか。 in引数を実は変更するサブプログラムもデフォルトのGlobal => all
のままか、でなければGlobal => overriding in out ...
が明記されているかのはずですのでカバーされます。)renames
されたプリミティブにも影響するようです。
継承で使い辛そうなのは見直されてないです。 (くどい)
package引数のAccessibility_Checkの修正¶
genericのpackage引数に対して静的なAccessibility_Checkが行われないようになります。 実行時のAccessibility_Checkは引き続き行われます。
package引数に関してはgeneric側だけ見てレキシカルに浅い深いを判定しても不要なエラーになるだけ……っぽいです。 勿論ここで言う静的なチェックとはtemplate型とコード共有型両方に適用できる静的なチェックのことで、template型のコンパイラであれば展開の過程で実行時のAccessibility_Checkを前倒しして警告できるはずです。
Preelaborable_Initialization属性¶
実はBounded版コンテナは規格上実装できなかったことが発覚してしまいました。
Bounded版コンテナにはpragma Preelaborable_Initialization
が付けられています。
グローバル変数として宣言した場合に実行時の初期化を必要としてはいけません。
Bounded版コンテナは追加のアロケーションを行わずに仮引数 Element_Type
を持つコンテナです。
Element_Type
の領域はコンテナの中に持たないといけませんが、どうやっても Element_Type
の初期化が必要となります。
(Tucker先生が挑戦されている様子をAIの中で読むことができます。)
そして Element_Type
に実行時の初期化を必要とする型が実引数として渡されることを防ぐ方法はありません。
その場合pragma Preelaborable_Initialization
は破られます。
さて前回(53日目)、Preelaborable_Initialization
がアスペクトとして書けるようになりました。
pragmaとアスペクトの違いは値を持つことです。
名前だけ書かれているように見えても実際には => True
が省略されています。
Boolean
型の値を持つということは論理式が書けます。
というわけで、今度は型が Preelaborable_Initialization
かどうかを属性の形で取得できるようになりました。
これで Nonblocking
等と同様に仮引数を参照して切り替えることができるようになりました。
generic
type Element_Type is private;
-- 省略
package Ada.Containers.Bounded_Doubly_Linked_Lists is
-- 省略
type List is private
with Preelaborable_Initialization =>
Element_Type'Preelaborable_Initialization,
-- 省略
私も考えてみました。
Root_Storage_Pool
がPreelaborable_Initializationになることは確定していました(35日目を参照)ので、専用のストレージプールを作って抱え込めば Element_Type
の初期化を実際に Append
等が呼ばれるまで遅らせることができます。
Adjust
をどうやって実装するかが難しいですね……。
割り当て済みの領域を Element_Type
にキャストして再代入すれば間接に Element_Type
の Adjust
を呼ぶことはできると思いますが、1回の代入で2回のコピーが必要になります。
Bounded版コンテナに本来不要な終了処理も必要になり、効率は悪いですね。 こうすれば実装できそうというだけです。
ただこうでもしないと実装できないはずの Bounded_Indefinite_Holders
のAI(AI12-0254-1)を見ますと実装依存の最適化に期待するようなことが書かれてまして、GNATに Bounded_Indefinite_Holders
が実装される時にはこれらを効率的に実装できるような拡張を期待していいんでしょうね?
"=" 演算子が隠されている場合のgeneric中の動作¶
型引数の(unlimitedな)抽象型には "="
演算子が付いてきます。
generic
type T2 is private;
package Gen is
function F (Left, Right : T2) return (Left = Right); -- "=" を使用
end Gen;
ところがこのようなgenericはプリミティブな "="
演算子を禁止した型でもインスタンス化できてしまいます。
type T3 is new Integer;
function "=" (Left, Right : T3) return Boolean is abstract;
package P is new Gen (T3);
この時の動作が明確化されました。
実引数が基本型か基本型の配列の時は(in
演算子同様に)既定義の "="
が使用されます。
実引数が複合型の時はコンパイルエラーまたは Program_Error
になります。
基本型の "="
演算子はユーザー定義しても既定義のものが使われる場面が多々あって信用なりませんね……。
pragmaからアスペクトへの書き換え¶
パッケージの種類を表す Pure
や Preelaborate
等が全面的にアスペクトに書き換えられるようです。
その他特記事項¶
変数のqualified式のrenamesはエラーになるようになりました。 53日目を参照。
これは非互換になるとTucker先生が指摘されたようです。 AIそのものも前回からこの非互換を反映して修正されています。 非互換性に追記しました。
他には、abstract型のプリミティブの Pre'Class
からabstract関数を呼べるようになる修正が採択されています。
AI自体がまだ修正されそうですので紹介は次に回したいと思います。
その他文面等の修正¶
例によって文面等の修正やglossary(用語集)へ単語の追加が行われています。
大きい変更としては「null procedure」と「expression function」の使われ方が、宣言のみとされました。
普通のサブプログラムのように宣言されbody側で is null;
としたものは「null procedure」に対する様々なルールの適用外ということが明確になります。
関連AI¶
AI12-0402-1 Master of a function call with elementary result type
AI12-0404-1 Presentation issues from Draft 26 review
AI12-0405-1 Fixups for stable properties
AI12-0406-1 Clarifying static accessibility
AI12-0407-1 Fixups from Draft 26 review - part 1
AI12-0408-1 Definition of “null procedure” and “expression function”
AI12-0409-1 Preelaborable_Initialization and Bounded Containers
AI12-0413-1 Reemergence of "=" when defined to be abstract
AI12-0414-1 Replace categorization pragmas with aspects