2

これは私の質問hereへのフォローアップです。

今の体制ではこれ以上先に進めないと感じたところまでプログラムを進めていたので、何度も書き直しました。Statement型はもはや抽象的ではなく、 の各サブタイプはの変数のStatement独自のインスタンスを作成します。Statementまた、コンパイラがそれを気に入らなかったため、Statements パッケージから抽象execute関数を削除しました (各サブタイプには独自のexecuteメソッドがあります)。受信ステートメント タイプを変更する必要があるため、execute関数はプロシージャに変更されました。statementFactory(旧 createStatement) をStatementパッケージに移動しました。

ここに私が得ているエラーがあります:

statements-compoundstatements.adb:15:29: expected type "CompoundStatement" defined at statements-compoundstatements.ads:11
statements-compoundstatements.adb:15:29: found type "Statement'Class" defined at statements.ads:6

私は Ada の初心者ですが、executeプロシージャが(Statement の "サブクラス" である) にあるため、Statementの別の "サブクラス" のメソッドCompoundStatementsを参照することはできないと思います。execute私が考えることができる唯一の解決策は、executeプロシージャを呼び出すすべてのプロシージャをexecuteパッケージにダンプするStatementことですが、それは望ましくないようです。しかし、 がで作成された型ではなくstmt.all型として使用されている理由はまだ説明されていません。Statement'ClassstatementFactory

新しいコードは次のとおりです。

package Statements is

   type Statement is tagged private;

   type Statement_Access is access all Statement'Class;
   ParserException : Exception;

   procedure createStatement(tokens : Vector; S : out Statement);
   procedure statementFactory(S: in out Statement; stmt: out Statement_Access);

--.....A bunch of other procedures and functions.....

private
   type Statement is tagged
      record
         tokens : Vector;
         executedtokens : Vector;
      end record;

end Statements;

   procedure createStatement(tokens : Vector; S : out Statement) is
   begin
      S.tokens := tokens;
   end createStatement;

   procedure statementFactory(S: in out Statement; stmt: out Statement_Access) is
      currenttoken : Unbounded_String;
      C            : CompoundStatement;
      A            : AssignmentStatement;
      P            : PrintStatement;

   begin
      currenttoken := getCurrentToken(S);
      if currenttoken = "begin" then
         createStatement(S.tokens, C);
         stmt := new CompoundStatement;
         stmt.all := Statement'Class(C);
      elsif isVariable(To_String(currenttoken)) then
         createStatement(S.tokens, A);
         stmt := new AssignmentStatement;
         stmt.all := Statement'Class(A);
      elsif currenttoken = "print" then
         createStatement(S.tokens, P);
         stmt := new PrintStatement;
         stmt.all := Statement'Class(P);
   end statementFactory;

package body Statements.CompoundStatements is

   procedure execute(skip: in Boolean; C: in out CompoundStatement; reset: out Integer) is
      stmt: Statement_Access;
      tokensexecuted: Integer;
      currenttoken : Unbounded_String;
   begin
      match(C, "begin");
      currenttoken := getCurrentToken(C);
      while(currenttoken /= "end") loop
         statementFactory(C, stmt);
         execute(skip, stmt.all, tokensexecuted); //ERROR OCCURS HERE
4

1 に答える 1

5

「コンパイラがそれを好まなかったので、Statementsパッケージから抽象実行関数も削除しました」とあなたは言います。しかし、あなたは本当にそれを必要としています。そうでなければ、コンパイラは、あなたがそれを呼び出すときに、それがディスパッチするためのを提供するexecute (skip, stmt.all, tokensexecuted)ことをどのように知るのですか?stmt.allexecute

拡張型はその親型の属性を継承するだけでなく(したがって、それぞれCompoundStatementがすでにandを持っているtokensexecutedtokens、親のプリミティブ操作を継承します。親操作がabstractである場合、子は独自の実装を提供する必要があります。そうでない場合、子は独自の(オーバーライドする)実装を提供できます。

これに関する良い議論については、Ada95RationaleWikibooksを参照してください。

于 2012-04-07T08:46:46.150 に答える