//&jp \section{ OX スタックマシン } //&eg \section{ OX stack machine } \label{sec:stackmachine} /*&jp この節では, OX スタックマシン operator の説明 (TCP/IP ソケット上での標準 encoding 法 を用いる), および, サンプルサーバとリンクする場合または open XM ライブラリとしてリンクして使用する場合の ための C の関数の仕様を説明する. 説明の前に, OX サーバスタックマシンの動作の原則を 説明しておく. サーバスタックマシンは, {\tt SM\_pop*} 系のスタックマシンコマンドがこないかぎり, 自発的にメッセージを送信することはない. この原則に基づいて分散計算のプログラミングをおこなう. イベントドリブンなプログラム法とはちがうことに 注意しよう. */ /*&eg In this section we describe the OX stack machine operators. In the descriptions OX messages are represented by th standard encoding scheme on TCP/IP sockets. In principle, an OX stack machine never sends data to the output stream unless it receives {\tt SM\_pop*} commands. Note that the programming style should be different from that for event-driven programming. */ //&jp \subsection{サーバスタックマシン } //&eg \subsection{Server stack machine} /*&jp サンプルサーバである {\tt oxserver00.c} は以下の仕様の C の関数を用意して, {\tt nullstackmachine.c } を置き換えれば一応動作するはずである. */ /*&eg {\tt oxserver00.c} is implemented as a sample server. If you want to implement you own server, write the following functions and use them instead of those in {\tt nullstackmachine.c}. */ //&jp \subsubsection{サーバスタックマシンのグループ SMobject/Primitive に属するオペレータ} //&eg \subsubsection{Operators in the group SMobject/Primitive} /*&jp \noindent サーバスタックマシンは最低で1本のスタック \begin{verbatim} Object xxx_OperandStack[SIZE]; \end{verbatim} をもつ. ここで, {\tt Object} はそのシステム固有の Object 型で構わない. CMObject は各サーバ固有のローカルオブジェクトに変換してスタックへプッ シュしてよい. ただし変換, 逆変換を合成したものは恒等写像であることが のぞましい. CMObject をどのように (local) Object に変換するか, Object が受け付けるメッセージの定義は,各システムが独自にきめて文書化しておく ものとする. つまりすべてのメッセージは, private である. たとえば, {\tt add } のような基本的な メッセージにたいしても, OX スタックマシン はなにもきめていない. 将来的には open math \cite{openmath} のように CMObject に対する最大公約数的なメッセージの仕様をcontent dictionary (CD) の形で定義したい. 以下, \verb+ xxx_ + は誤解の恐れがないときは省略する. \verb+ xxx_ + は local サーバシステムに固有の識別子である. {\tt Asir} の場合は \verb+ Asir_ + を用いる. {\tt kan/sm1} の場合は \verb+ Sm1_ + を用いる. 関数名, タグ名は長いので省略形を用いてもよい. 以下では次のようにパケットを記述する. 各フィールドは, \fbox{データ型 \quad データ} なる形式 で書く. たとえば, {\tt int32 OX\_DATA} は 32 bit network byte order の数字 {\tt OX\_DATA}という意味である. ``イタリックで書かれているフィー ルドは,定義が別のところでなされているか解釈に誤解のないような自然言語 で説明されている object を表す.'' たとえば, {\it String commandName} は, String データ型の local object {\it commandName} を意味する. (サー バスタックマシン上の object は, CMO 形式の objectとは限らないことに注 意. CMO 形式で書いてあっても, それはサーバスタックマシンのlocal 形式 でスタック上にあると解釈して下さい.) すべてのサーバスタックマシンは以下の操作を実装していないといけない. 各操作に対し, その前後におけるスタックの状態を示す. 図において, 右端のオブジェクトがスタックのトップに対応する. */ /*&eg \noindent Any OX stack machine has at least one stack. \begin{verbatim} Object xxx_OperandStack[SIZE]; \end{verbatim} Here {\tt Object} may be local to the system {\tt xxx} wrapped by the stack machine. That is, the server may translate CMObjects into its local objects and push them onto the stack. It is preferable that the composition of such a translation and its inverse is equal to the identity map. The translation scheme is called the {\it phrase book} of the server and it should be documented for each stack machine. In OpenXM, any message is private to a connection. In future we will provide a content dictionary (CD; see OpenMath \cite{openmath}) for basic specifications of CMObjects. In the following, \verb+ xxx_ + may be omitted if no confusion occurs. As the names of functions and tags are long, one may use abbreviated names. Message packets are represented as follows. Each field is shown as \fbox{data type \quad data}. For example {\tt int32 OX\_DATA} denotes a number {\tt OX\_DATA} which is represented by a 32 bit integer with the network byte order. If a field is displayed by italic characters, it should be defined elsewhere or its meaning should be clear. For example {\it String commandName} denotes a local object {\it commandName} whose data type is String. Note that an object on the stack may have a local data type even if it is represented as CMO. Any server stack machine has to implement the following operations. For each operation we show the states of the stack before and after the operation. In the figures the rightmost object corresponds to the top of the stack. Only the modified part of the stack are shown. */ \begin{enumerate} \item /*&jp CMObject/Primitive の CMO データのうち必須のもの, {\tt CMO\_ERROR2}, {\tt CMO\_NULL}, {\tt CMO\_INT32}, {\tt CMO\_STRING}, {\tt CMO\_LIST}がおく られて来た場合それをスタックに push する. たとえば, {\tt CMO\_NULL} あるいは {\tt CMO\_String} の場合次のようになる. */ /*&eg Any server should accept CMObjects in the group CMObject/Primitive. The server pushes such data onto the stack. The following examples show the states of the stack after receiving {\tt CMO\_NULL} or {\tt CMO\_String} respectively. */ Request: \begin{tabular}{|c|c|} \hline {\tt int32 OX\_DATA} & {\tt int32 CMO\_NULL} \\ \hline \end{tabular} Stack after the request: \begin{tabular}{|c|} \hline {\it NULL} \\ \hline \end{tabular} Output: none. Request:\\ \begin{tabular}{|c|c|c|c|c|c|} \hline {\tt int32 OX\_DATA} & {\tt int32 CMO\_String} &{\tt int32} {\rm size} &{\tt byte} {\rm s1} & $\cdots$ &{\tt byte} {\rm ssize}\\ \hline \end{tabular} Stack after the request: \begin{tabular}{|c|} \hline {\it String s} \\ \hline \end{tabular} Output: none. //&jp CMO データの受け取りに失敗した時のみ \\ //&eg If the server fails to receive a CMO data,\\ \begin{tabular}{|c|c|c|} \hline {\tt int32 OX\_DATA} & {\tt int32 CMO\_ERROR2} & {\it CMObject} ob\\ \hline \end{tabular} \\ /*&jp をスタックへ push する. 現在のところ, ob には, \\ \centerline{ [{\sl Integer32} OX パケット番号, {\sl Integer32} エラー番号, {\sl CMObject} optional 情報] } なるリストを入れる (CMO 形式でかいてあるが, これはサーバ独自の形式でよい. CMO として送出されるときこのような形式でないといけないという意味である.) */ /*&eg is pushed onto the stack. Currently ob is a list\\ \centerline{ [{\sl Integer32} OX serial number, {\sl Integer32} error code, {\sl CMObject} optional information] } */ \item \begin{verbatim} SM_mathcap \end{verbatim} /*&jp このサーバの mathcap をもどす (termcap のまね). サーバのタイプ, サー バスタックマシンの能力を知ることができる. C 言語で実装する場合は, mathcap の構造体をシステム毎にきめるものとし,この関数はその構造体への ポインタを戻す. (open sm1 では {\tt struct mathcap} を用いている. */ /*&eg It requests a server to push the mathcap of the server. The mathcap is similar to the termcap. One can know the server type and the capability of the server from the mathcap. */ @plugin/mathcap.h) Request: \begin{tabular}{|c|c|} \hline {\tt int32 OX\_COMMAND} & {\tt int32 SM\_mathcap} \\ \hline \end{tabular} Stack after the request: \begin{tabular}{|c|c|} \hline {\tt int32 OX\_DATA} & {\sl Mathcap} mathCapOb \\ \hline \end{tabular} Output: none. \item \begin{verbatim} SM_setMathcap \end{verbatim} /*&jp 受け取った Mathcap {\tt m} を自分のシステムに設定して, 相手側が理解不 能な CMO をおくらないようにする. C 言語で実装する場合は, mathcap の構 造体をシステム毎にきめるものとし,この関数はその構造体へのポインタを引 数とする. (open sm1 では {\tt struct mathcap} を用いている. */ /*&eg It requests a server to register the peer's mathcap {\tt m} in the server. The server can avoid to send OX messages unknown to its peer. */ @plugin/mathcap.h) Request: \begin{tabular}{|c|c|} \hline {\tt int32 OX\_DATA} & {\sl Mathcap} m \\ \hline {\tt int32 OX\_COMMAND} & {\tt int32 SM\_setMathcap} \\ \hline \end{tabular} Output: none. /*&jp \noindent 注意: mathcap は一般にクライアント主体で設定する. クライアントがサーバに {\tt SM\_mathcap} をおくり, サーバ側の mathcap を得る. それを, クライアントはそのサーバに付随した mathcap として 設定する. 次に, クライアントはサーバに自分の mathcap を {\tt SM\_setMathcap} でおくり, 自分の mathcap を設定させる. */ /*&eg \noindent Remark: In general the exchange of mathcaps is triggered by a client. A client sends {\tt SM\_mathcap} to a server and obtains the server's mathcap. Then the client registers the mathcap. Finally the client sends its own mathcap by {\tt SM\_setMathcap} and the server registers it. */ \item \begin{verbatim} SM_executeStringByLocalParser \end{verbatim} /*&jp 文字列 {\tt s} を stack から pop し, その文字列をシステム固有の文法(サーバスタックマシンの組み込みローカ ル言語)にしたがったコマンドとして実行する. コマンドの実行の結 果の最後に戻り値があるときは, {\tt OperandStack} に戻り値を push する. OpenXM では, 現在のところ関数名の標準化はおこなっていない. この関数および {\tt popString} の機能を実現すれば, 最低限の open XM の サーバになれる. 実装では, まずこの二つの関数の機能を実現すべきである. */ /*&eg It requests a server to pop a character string {\tt s}, to parse it by the local parser of the stack machine, and to interpret by the local interpreter. If the execution produces a Output, it is pushed onto {\tt OperandStack}. If an error has occurred, Error2 Object is pushed onto the stack. OpenXM does not provide standard function names. If this operation and {\tt SM\_popString} is implemented, the stack machine is ready to be used as an OX server. */ Stack before the request: \\ \begin{tabular}{|c|} \hline {\it String commandString} \\ \hline \end{tabular} Request: \begin{tabular}{|c|c|} \hline {\tt int32 OX\_COMMAND}& {\tt int32 SM\_executeStringByLocalParser} \\ \hline \end{tabular} Output: none. /*&jp \noindent 参考: \ 実行前のスタックのデータは, {\it String commandString} なる local stack machine の object としてス タック上にあるが, TCP/IP の通信路では, 次のようなデータがまずながれて {\it commandName} がスタックに push される: */ /*&eg \noindent Remark: Before this request, one has to push {\it String commandString} onto the stack. It is done by sending the following OX data message. */ \begin{tabular}{|c|c|c|} \hline {\tt int32 OX\_DATA} & {\tt int32 CMO\_string} & {\it size and the string commandString} \\ \hline \end{tabular} \item \begin{verbatim} SM_executeStringByLocalParserInBatchMode \end{verbatim} /*&jp スタックに副作用がない(スタックにたいしてなんの操作もしない)ことを除き 上とまったく同じ関数である. エラーの時のみ, Error2 Object をスタック へプッシュする. */ /*&eg This is the same request as {\tt SM\_executeStringByLocalParser} except that it does not modify the stack. It pushes an Error2 Object if an error has occurred. */ \item \begin{verbatim} SM_popString \end{verbatim} /*&jp {\tt OperandStack} より Object を pop し, それを xxx の出力規則にしたがい文 字列型に変換して送信する. スタックが空のときは, {\tt (char *)NULL} を戻す. 文字列は TCP/IP stream へ CMO のデー タとして送信する. エラーの場合は {\tt CMO\_ERROR2} を戻すべきである. */ /*&eg It requests a server to pop an object from {\tt OperandStack}, to convert it into a character string according to the output format of the local system, and to send the character string via TCP/IP stream. {\tt (char *)NULL} is returned when the stack is empty. The returned strings is sent as a CMO string data. {\tt CMO\_ERROR2} should be returned if an error has occurred. */ Stack before the request: \begin{tabular}{|c|} \hline {\it Object} \\ \hline \end{tabular} Request: \begin{tabular}{|c|c|} \hline {\tt int32 OX\_COMMAND} & {\tt int32 SM\_popString} \\ \hline \end{tabular} Output: \begin{tabular}{|c|c|c|} \hline {\tt int32 OX\_DATA} & {\tt int32 CMO\_STRING} & {\it size and the string s} \\ \hline \end{tabular} \item \begin{verbatim} SM_getsp \end{verbatim} /*&jp 現在のスタックポインタの位置をもどす. スタート時点での位置は 0 であり, object が push されたばあい, 1 づつ増えるものとする. */ /*&eg It requests a server to push the current stack pointer onto the stack. The stack pointer is represented by a non-negative integer. Its initial value is 0 and a push operation increments the stack pointer by 1. */ Stack before the request: \begin{tabular}{|c|} \hline {\it Object} \\ \hline \end{tabular} Request: \begin{tabular}{|c|c|} \hline {\tt int32 OX\_COMMAND} & {\tt int32 SM\_getsp} \\ \hline \end{tabular} Stack after the request: \begin{tabular}{|c|c|c|} \hline {\tt int32 OX\_DATA} & {\tt int32 CMO\_INT32} & {\it stack pointer value} \\ \hline \end{tabular} Output: none. \item \begin{verbatim} SM_dupErrors \end{verbatim} /*&jp スタック上のエラーオブジェクトをリストにして戻す. スタック自体は変化 させない. */ /*&eg It requests a server to push a list object containing all error objects on the stack. */ Request: \begin{tabular}{|c|c|} \hline {\tt int32 OX\_COMMAND} & {\tt int32 SM\_dupErrors} \\ \hline \end{tabular} Stack after the request: \begin{tabular}{|c|c|c|} \hline {\tt int32 OX\_DATA} & {\sl CMObject} \ a list of errors\\ \hline \end{tabular} Output: none. \end{enumerate} \medbreak \noindent /*&jp {\bf 例}: \ mathcap の問い合わせに対して, {\tt ox\_sm1} は次のように答える. */ /*&eg {\bf Example}: \ {\tt ox\_sm1} returns the following data as its mathcap. */ %%Prog: [(cmoMathcap)] extension :: \begin{verbatim} Class.mathcap [ [199909080 , $Ox_system=ox_sm1.plain$ , $Version=2.990911$ , $HOSTTYPE=i386$ ] , [262 , 263 , 264 , 265 , 266 , 268 , 269 , 272 , 273 , 275 , 276 ] , [[514] , [2130706434 , 1 , 2 , 4 , 5 , 17 , 19 , 20 , 22 , 23 , 24 , 25 , 26 , 30 , 31 , 60 , 61 , 27 , 33 , 40 , 34 ]]] \end{verbatim} /*&jp mathcap は 3つの要素をもつリストである. まづ, 最初の要素を見よう. Ox\_system は openXM システム名である. 読み込むライブラリがちがって いて, 関数名(または シンボル)の意味がちがうときはこの名前もかえる. た とえば, open math の basic content dictionary 対応の関数定義マクロを読 みこんだ sm1 は, ox\_sm1\_basicCD なる名前にする. HOSTTYPE 値は, CPU の種類をあらわしunix では環境変数\verb+$HOSTTYPE+ の値である. 2 番目 の要素は 利用可能な SM コマンドをあつめたリストである. 3 番目のリスト は, 処理可能な数学データの形式, およびCMOの場合なら処理可能なCMOのタグ のリストが続く. 上の例では, 514 は {\tt OX\_DATA} をあらわし, 数学デー タのフォマットは(サイズ情報なしの) CMO であることを示す. */ /*&eg A mathcap has three components. The first one contains informations to identify the system and hosts on which the application runs. In the above example, {\tt Ox\_system} denotes the system name. {\tt HOSTTYPE} represents the OS type and taken from \verb+$HOSTTYPE+ enviroment variable. The second component consists of avaiable SM commands. The third component is a list of pairs. Each pair consists of an OX message tag and the available message tags. Again in the above example, 514 is the value of {\tt OX\_DATA} and it indicates that the server accepts CMO (without size information) as mathematical data messages. In this case the subsequent list represents available CMO tags. */ \medbreak \noindent //&jp {\bf 例}: \ //&eg {\bf Example}: \ %%Prog: (ox.sm1) run sm1connectr [(oxWatch) ox.ccc] extension %%Prog: ox.ccc (122345; ) oxsubmit ; //&jp {\tt message\_body} の実例をあげる. シリアル番号部は除いてある. //&eg We show examples of {\tt message\_body}. Serial numbers are omitted. \begin{enumerate} \item {\tt executeStringByLocalParser("12345 ;");} /*&jp は次のようなパケットに変換される. 各数字は 16進1バイトをあらわす. {\tt xx(yy)} のなかの {\tt (yy)} は対応するアスキーコードをあわらす. */ /*&eg is converted into the following packet. Each number denotes one byte in hexadecimal representation. {\tt (yy)} in {\tt xx(yy)} represents the corresponding ASCII code. */ \begin{verbatim} 0 0 2 2 0 0 0 4 0 0 0 7 31(1) 32(2) 33(3) 34(4) 35(5) 20 3b(;) 0 0 2 1 0 0 1 c \end{verbatim} /*&jp それぞれのデータの意味は次のとおりである. */ /*&eg Each data has the following meaning. */ \begin{verbatim} 0 0 2 2 (OX_DATA) 0 0 0 4 (CMO_STRING) 0 0 0 7 (size) 31(1) 32(2) 33(3) 34(4) 35(5) 20 3b(;) (data) 0 0 2 1 (OX_COMMAND) 0 0 1 c (SM_executeStringByLocalParser) \end{verbatim} //&jp これを OXexpression で表記すると次のようになる. //&eg This is expressed by OXexpression as follows. \begin{center} (OX\_DATA, (CMO\_STRING, 7, "12345 ;")) \end{center} \begin{center} (OX\_COMMAND, (SM\_executeStringByLocalParser)) \end{center} //&jp \item {\tt popString()} を要請するメッセージ: //&eg \item A message which requests {\tt SM\_popString}: \begin{verbatim} 0 0 2 1 (OX_COMMAND) 0 0 1 7 (SM_popString) \end{verbatim} //&jp OXexpression では //&eg In OXexpression it is represented as (OX\_COMMAND, (SM\_popString)). \noindent //&jp これにたいして次の返答メッセージがくる. //&eg The server returns the following reply message: \begin{verbatim} 0 0 2 2 (OX_DATA) 0 0 0 4 (CMO_STRING) 0 0 0 5 (size) 31(1) 32(2) 33(3) 34(4) 35(5) \end{verbatim} //&jp OXexpression でかくと, //&eg In OXexpression it is represented as (OX\_DATA, (CMO\_STRING, 7, "12345 ;")). \end{enumerate} //&jp \subsubsection{グループ SMobject/Basic に属するオペレータ} //&eg \subsubsection{Operators in the group SMobject/Basic} \begin{enumerate} \item \begin{verbatim} SM_pops \end{verbatim} /*&jp operand stack より, {\it n} 個の元 ({\it obj1, obj2, $\ldots$, objn} を pop して捨てる. */ /*&eg It requests a server to pop {\it n} and to discard elements {\it obj1, obj2, $\ldots$, objn}) from the stack. */ //&jp Stack before the request: \\ //&eg Stack before the request: \\ \begin{tabular}{|c|c|c|c|c|} \hline {\it obj1} & {\it obj2} & $\cdots$ & {\it objn} &{\it Integer32 n} \\ \hline \end{tabular} Request: \begin{tabular}{|c|c|} \hline {\tt int32 OX\_COMMAND} & {\tt int32 SM\_pops } \\ \hline \end{tabular} Output: none. \item \begin{verbatim} int SM_setName \end{verbatim} /*&jp {\tt OperandStack} より {\it name} を pop し, つぎに{\tt OperandStack} より {\it obj} を pop し, それを現在の名前空間で変数 {\it name} に bind する. 正常終了なら 0 を, 異常終了なら -1 をもどす. TCP/IP によ る通信では, 異常終了の時のみ, {\tt CMO\_ERROR2} をstack へ push する. */ /*&eg It requests a server to pop {\it name}, to pop {\it obj}, and to bind {\it obj} to a variable {\it name} in the current name space of the server. If an error has occurred {\tt CMO\_ERROR2} is pushed onto the stack. */ //&jp Stack before the request: //&eg Stack before the request: \begin{tabular}{|c|c|} \hline {\it obj} & {\it String name} \\ \hline \end{tabular} Request: \begin{tabular}{|c|c|} \hline {\tt int32 OX\_COMMAND} & {\tt int32 SM\_setName} \\ \hline \end{tabular} Output: none. \item \begin{verbatim} SM_evalName \end{verbatim} /*&jp 現在の名前空間で変数 {\it name} を評価する. 評価の結果 {\it OutputObj} をスタックへ戻す. 関数自体は正常終了なら 0 を, 異常終了な ら -1 をもどす. TCP/IP の場合, 異常終了の場合のみ {\tt CMO\_ERROR2} を stack へ push する. */ /*&eg It requests a server to pop {\it name} and to evaluate a variable {\it name} in the current name space. The Output of the evaluation {\it OutputObj} is pushed to the stack. If an error has occurred {\tt CMO\_ERROR2} is pushed to the stack. */ //&jp Stack before the request: //&eg Stack before the request: \begin{tabular}{|c|} \hline {\it String name} \\ \hline \end{tabular} Request: \begin{tabular}{|c|c|} \hline {\tt int32 OX\_COMMAND} & {\tt int32 SM\_evalName} \\ \hline \end{tabular} //&jp Stack after the request: //&eg Stack after the request: \begin{tabular}{|c|} \hline {\it OutputObj} \\ \hline \end{tabular} Output: none. \item \begin{verbatim} SM_executeFunction \end{verbatim} /*&jp スタックより {\it n} 個のデータを pop して, サーバのローカル関数{\it s} を実行する. エラーのときのみ {\tt CMO\_ERROR2} を stack へ push す る. */ /*&eg It requests a server to pop {\it s} as a function name, to pop {\it n} as the number of arguments and to execute a local function {\it s} with {\it n} arguments popped from the stack. If an error has occurred {\tt CMO\_ERROR2} is pushed to the stack. */ //&jp Stack before the request: \\ //&eg Stack before the request: \\ \begin{tabular}{|c|c|c|c|c|} \hline {\it objn} & $\cdots$ & {\it obj1} & {\it INT32 n} & {\it String s} \\ \hline \end{tabular} Request: \begin{tabular}{|c|c|} \hline {\tt int32 OX\_COMMAND} & {\tt int32 SM\_executeFunction} \\ \hline \end{tabular} //&jp Stack after the request: 関数実行の結果. //&eg Stack after the request: The Output of the execution. Output: none. \item \begin{verbatim} SM_popSerializedLocalObject \end{verbatim} /*&jp スタックより pop した object を local 形式で serialization して OX message として stream へ出力する. OX message tag としては, local 形式に対応したものが定義されていることが必要である. この関数はおもに, homogeneous な分散システムで用いる. */ /*&eg It requests a sever to pop an object, to convert it into a serialized form according to a local serialization scheme, and to send it to the stream as an OX message. An OX message tag corresponding to the local data format must be sent prior to the serialized data itself. This operation is used mainly on homogeneous distributed systems. */ \item \begin{verbatim} SM_popCMO \end{verbatim} /*&jp {\tt OperandStack} より object を pop し CMO 形式の serialized object を stream へ header {\tt OX\_DATA} をつけてながす. */ /*&eg It requests a server to pop an object from the stack, to convert it into a serialized form according to the standard CMO encoding scheme, and to send it to the stream with the {\tt OX\_DATA} header. */ Request: \begin{tabular}{|c|c|} \hline {\tt int32 OX\_COMMAND} & {\tt int32 OX\_popCMO} \\ \hline \end{tabular} Output: \begin{tabular}{|c|c|} \hline {\tt int32 OX\_DATA} & {\it Serialized CMO} \\ \hline \end{tabular} \end{enumerate}