@comment $OpenXM: OpenXM/src/asir-doc/parts/asir.texi,v 1.20 2020/09/08 09:16:57 noro Exp $ \BJP @node ユーザ言語 Asir,,, Top @chapter ユーザ言語 Asir \E \BEG @node User language Asir,,, Top @chapter User language @b{Asir} \E @noindent \BJP @b{Asir} の組み込み函数は, 因数分解, GCD などの計算を行うもの, ファ イル入出力を行うもの, あるいは数式の一部を取り出すものなどさまざまなもの が用意されているが, ユーザが実際に行いたいことを実行させるためには一 般にはユーザ言語によるプログラムを書く必要がある. ユーザ言語も @b{Asir} と呼ばれる. 以下では, ユーザ言語の文法規則および実際のユー ザ言語プログラムを例としたプログラムの書き方について述べる. \E \BEG @b{Asir} provides many built-in functions, which perform algebraic computations, e.g., factorization and GCD computation, file I/O, extract a part of an algebraic expression, etc. In practice, you will often encounter a specific problem for which @b{Asir} does not provide a direct solution. For such cases, you have to write a program in a certain user language. The user language for @b{Asir} is also called @b{Asir}. In the following, we describe the Syntax and then show how to write a user program by several examples. \E @menu \BJP * 文法 (C 言語との違い):: * ユーザ定義函数の書き方:: \E \BEG * Syntax (Difference from C language):: * Writing user defined functions:: \E @end menu \BJP @node 文法 (C 言語との違い),,, ユーザ言語 Asir @section 文法 (C 言語との違い) \E \BEG @node Syntax (Difference from C language),,, User language Asir @section Syntax --- Difference from C language \E @noindent \BJP @b{Asir} の文法は C 言語に準拠している. おもな相違点は次の通りである. 以下で, 変数とは @b{Asir} における プログラム用の変数, すなわち大文字で始まる文字列を意味することとする. \E \BEG The syntax of @b{Asir} is based on C language. Main differences are as follows. In this section, a variable does not mean an indeterminate, but a program variable which is written by a string which begins with a capital alphabetical letter in @b{Asir}. \E @itemize @bullet @item \JP 変数の型がない. \EG No types for variables. @* \BJP 既に説明したとおり, @b{Asir} で扱われる対象自身は全て何らかの型 を持っている. しかし, プログラム変数自体は, どのような対象でも 代入できるという意味で型がないのである. \E \BEG As is already mentioned, any object in @b{Asir} has their respective types. A program variable, however, is type-less, that is, any typed object can be assigned to it. \E @example [0] A = 1; 1 [1] type(A); 1 [2] A = [1,2,3]; [1,2,3] [3] type(A); 4 @end example @item \BJP 函数内の変数は, デフォルトでは仮引数をこめてすべて局所変数. @* ただし, @code{extern} 宣言された変数は, トップレベルにおける大域変数となる. すなわち, 変数のスコープは大域変数と局所変数の 2 種類に単純化されている. トップレベル, すなわちプロンプトに対して入力された変数は全て大域変数 として登録される. また函数内では次のいずれかとなる. \E \BEG Variables, together with formal parameters, in a function (procedure) are all local to the function by default. @* Variables can be global at the top level, if they are declared with the key word @code{extern}. Thus, the scope rule of @b{Asir} is very simple. There are only two types of variables: global variables and local variables. A name that is input to the @b{Asir}'s prompt at the top level is denotes a global variable commonly accessed at the top level. In a function (procedure) the following rules are applied. \E @enumerate @item \BJP 函数が定義されるファイルにおいて, その函数定義以前に, ある 変数が @code{extern} 宣言されている場合, 函数内のその変数も大域変数 として扱われる. \E \BEG If a variable is declared as global by an @code{extern} statement in a function, the variable used in that function denotes a global variable at the top level. Furthermore, if a variable in a function is preceded by an @code{extern} declaration outside the function but in a file where the function is defined, all the appearance of that variable in the same file denote commonly a global variable at the top level. \E @item \JP @code{extern} 宣言されていない変数はその函数に局所的となる. \BEG A variable in a function is local to that function, if it is not declared as global by an @code{extern} declaration. \E @end enumerate @example % cat afo def afo() @{ return A;@} extern A$ def bfo() @{ return A;@} end$ % asir [0] load("afo")$ [5] A = 1; 1 [6] afo(); 0 [7] bfo(); 1 @end example @item \JP プログラム変数は大文字で始まり, 不定元, 函数は小文字で始まる. \EG Program variables and algebraic indeterminates are distinguished in @b{Asir}. @* \BJP この点は, 既存の数式処理システムのほとんどと異なる点である. @b{Asir} がこの仕様を採用したのは, ユーザが不定元のつもりで使用した変数に なんらかの値が代入されていた場合に混乱を招く, という, 既存の システムにありがちな状況を避けるためである. \E \BEG The names of program variables must begin with a capital letter; while the names of indeterminates and functions must begin with a small letter. This is an unique point that differs from almost all other existing computer algebra systems. The distinction between program variables and indeterminates is adopted to avoid the possible and usual confusion that may arise in a situation where a name is used as an indeterminate but, as it was, the name has been already assigned some value. To use different type of letters, capital and small, was a matter of syntactical convention like Prolog, but it is convenient to distinguish variables and indeterminates in a program. \E @item \JP @code{switch} 文, @code{goto} がない. \EG No @code{switch} statements, and @code{goto} statements. @* \JP @code{goto} がないため, 多重ループを一度に抜けるのがやや複雑になる場合がある. \EG Lack of @code{goto} statement makes it rather bothering to exit from within multiple loops. @item \BJP コンマ式は, @code{for (A;B;C)} または, @code{while(A)} の @code{A}, @code{B}, @code{C} にのみ使うことができる. \E \BEG Comma expressions are allowed only in @code{A}, @code{B} and @code{C} of the constructs @code{for (A;B;C)} or @code{while(A)}. \E @* \JP これは, リストを正式なオブジェクトとして加えたことによる. \EG This limitation came from adopting lists as legal data objects for @b{Asir}. @end itemize @noindent \JP 以上は制限であるが, 拡張としては次の点が挙げられる. \EG The above are limitations; extensions are listed as follows. @itemize @bullet @item \JP 有理式に対する計算を, 通常の C における計算と同様にできる. \BEG Arithmetic for rational expressions can be done in the same manner as is done for numbers in C language. \E @item \JP リストが扱える. \EG Lists are available for data objects. \BJP 構造体を用いるまでもない要素の集合体を, リストで表すことができ, C で直接書く場合に比較してプログラムが短く, 読みやすく書ける. \E \BEG Lists are conveniently used to represent a certain collection of objects. Use of lists enables to write programs more easily, shorter and more comprehensible than use of structure like C programs. \E \BJP @item ユーザ定義函数における一行ヘルプ. Emacs-Lisp に類似した機能である. 詳しくは, @xref{ユーザ定義函数} を見よ. \E @item \JP ユーザ定義函数におけるオプション指定. \EG Options can be specified in calling user defined functions. \JP これに関しては, @xref{オプション指定}. \EG @xref{option}. @end itemize \BJP @noindent Asir では次の語句がキーワードとして定められている. @itemize @item C 言語に由来: @code{break}, @code{continue}, @code{do}, @code{else}, @code{extern}, @code{for}, @code{if}, @code{return}, @code{static}, @code{struct}, @code{while} @item C 言語からの拡張: @code{def}, @code{endmodule}, @code{function}, @code{global}, @code{local}, @code{localf}, @code{module} @item 函数: @code{car}, @code{cdr}, @code{getopt}, @code{newstruct}, @code{map}, @code{pari}, @code{quote}, @code{recmap}, @code{timer} @end itemize \E \BJP @node ユーザ定義函数の書き方,,, ユーザ言語 Asir @section ユーザ定義函数の書き方 \E \BEG @node Writing user defined functions,,, User language Asir @section Writing user defined functions \E @menu \BJP * ユーザ定義函数:: * 変数および不定元:: * 引数:: * コメント:: * 文:: * return 文:: * if 文:: * ループ break return continue:: * 構造体定義:: * さまざまな式:: * プリプロセッサ:: * オプション指定:: * モジュール:: \E \BEG * User defined functions:: * variables and indeterminates:: * parameters and arguments:: * comments:: * statements:: * return statement:: * if statement:: * loop break return continue:: * structure definition:: * various expressions:: * preprocessor:: * option:: * module:: \E @end menu \BJP @node ユーザ定義函数,,, ユーザ定義函数の書き方 @subsection ユーザ定義函数 \E \BEG @node User defined functions,,, Writing user defined functions @subsection User defined functions \E @noindent \BJP ユーザによる函数の定義は @samp{def} 文で行う. 文法エラーは読み込み時に ある程度チェックされ, おおよその場所が表示される. 既に(引数の個数に関係なく)同名の函数が定義されている場合には, その函数は再定義される. @code{ctrl()} 函数により @code{verbose} フラグ が on になっている場合, \E \BEG To define functions by an user himself, @samp{def} statement must be used. Syntactical errors are detected in the parsing phase of @b{Asir}, and notified with an indication of where @b{Asir} found the error. If a function with the same name is already defined (regardless to its arity,) the new definition will override the old one, and the user will be told by a message, \E @example afo() redefined. @end example @noindent \BJP というメッセージが表示される. ある函数の定義において, まだ未定義の函数 を呼び出していても, 定義時にはエラーにならない. 実行時に未定義の函数 を呼び出そうとした場合にエラーとなる. \E \BEG on the screen when a flag @code{verbose} is set to a non-zero value by @code{ctrl()}. Recursive definition, and of course, recursive use of functions are available. A call for an yet undefined function in a function definition is not detected as an error. An error will be detected at execution of the call of that yet undefined function. \E @example @tex /* $X!$ */ @end tex def f(X) @{ if ( !X ) return 1; else return X * f(X-1); @} @tex \JP /* ${_i}C_j ( 0 \le i \le N, 0 \le j \le i )$ */ \EG /* ${_i}C_j ( 0 \le i \le N, 0 \le j \le i )$ */ @end tex def c(N) @{ A = newvect(N+1); A[0] = B = newvect(1); B[0] = 1; for ( K = 1; K <= N; K++ ) @{ A[K] = B = newvect(K+1); B[0] = B[K] = 1; for ( P = A[K-1], J = 1; J < K; J++ ) B[J] = P[J-1]+P[J]; @} return A; @} @tex /* $A+B$ */ @end tex def add(A,B) "add two numbers." @{ return A+B; @} @end example @noindent \BJP 2 つ目の例では, 長さ @code{N+1} のベクトル (@code{A}とする) が返される. @code{A[I]} は長さ @code{I+1} の配列であり, そのそれぞれの要素が \E \BEG In the second example, @code{c(N)} returns a vector, say @code{A}, of length @code{N+1}. @code{A[I]} is a vector of length @code{I+1}, and each element is again a vector which contains \E @iftex @tex ${_I}C_J$ @end tex @end iftex @ifnottex ICJ @end ifnottex \JP を要素とする配列である. \EG as its elements. @noindent \BJP 3 つ目の例では, 引数並びのあとに文字列が置かれているが、これは Emacs-Lisp の関数定義に類似の機能で、ヘルプ用の文字列である。 この例の場合、@code{help(add)} によってこの文字列が出力される。 \E @table @t \JP @item 参照 \EG @item References @fref{help}. @end table @noindent \BJP 以下では, C によるプログラミングの経験がない人のために, @b{Asir} 言語 によるプログラムの書き方を解説する. \E \BEG In the following, the manner of writing @b{Asir} programs is exhibited for those who have no experience in writing C programs. \E \BJP @node 変数および不定元,,, ユーザ定義函数の書き方 @subsection 変数および不定元 \E @noindent \BJP 既に述べた通り, @b{Asir} においてはプログラム変数と不定元を明確に 区別している. \E \BEG @node variables and indeterminates,,, Writing user defined functions @subsection variables and indeterminates \E @table @b \BJP @item 変数 大文字で始まり, アルファベット, 数字, @samp{_} からなる文字列 \E \BEG @item variables (program variables) A program variable is a string that begins with a capital alphabetical letter followed by any numbers of alphabetical letters, digits and @samp{_}. \E \BJP 変数あるいはプログラム変数とは, @b{Asir} のさまざまな型の内部形式を 格納するための箱であり, 格納された内部形式が, この変数の値である. 変 数が式の要素として評価される時は, そこに収められた値に置き換えられる. すなわち, 内部形式の中にはプログラム変数は現れない. 変数は全て 0 で 初期化されている. \E \BEG A program variable is thought of a box (a carrier) which can contain @b{Asir} objects of various types. The content is called the `value' of that variable. When an expression in a program is to be evaluated, the variable appearing in the expression is first replaced by its value and then the expression is evaluated to some value and stored in the memory. Thus, no program variable appears in objects in the internal form. All the program variables are initialized to the value 0. \E @example [0] X^2+X+1; 1 [1] X=2; 2 [2] X^2+X+1; 7 @end example \BJP @item 不定元 小文字で始まり, アルファベット, 数字, @samp{_} からなる文字列, またはシングルクオートで囲まれた文字列, もしくは函数形式. 不定元とは, 多項式環を構成する際に添加される変数をいう. @b{Asir} に おいては, 不定元は値をもたない超越的な元であり, 不定元への値の代入は 許されない. \E \BEG @item indeterminates An indeterminate is a string that begins with a small alphabetical letter followed by any numbers of alphabetical letters, digits and @samp{_}. An indeterminate is a transcendental element, so-called variable, which is used to construct polynomial rings. An indeterminate cannot have any value. No assignment is allowed to it. \E @example [3] X=x; x [4] X^2+X+1; x^2+x+1 [5] A='Dx'*(x-1)+x*y-y; (y+Dx)*x-y-Dx [6] function foo(x,y); [7] B=foo(x,y)*x^2-1; foo(x,y)*x^2-1 @end example @end table \BJP @node 引数,,, ユーザ定義函数の書き方 @subsection 引数 \E \BEG @node parameters and arguments,,, Writing user defined functions @subsection parameters and arguments \E @example def sum(N) @{ for ( I = 1, S = 0; I <= N; I++ ) S += I; return S; @} @end example @noindent \BJP これは, 1 から @code{N} までの自然数の和を求める函数 @code{sum()} の 定義である. この例における @code{sum(N)} の @code{N} が引数である. この例は, 1 引数函数の例であるが, 一般に引数の個数は任意であり, 必要なだけの個数を @samp{,} で区切って指定することができる. 引数は 値が渡される. すなわち, 引数を受けとった側が, その引数の値を変更して も, 渡した側の変数は変化しない. ただし, 例外がある. それは, ベクトル, 行列を引数に渡した場合である. この場合も, 渡された変数そのものを書き 替えることは, その函数に局所的な操作であるが, 要素を書き換えた場合, それは, 呼び出し側のベクトル, 行列の要素を書き換えることになる. \E \BEG This is an example definition of a function that sums up integers from 1 to @code{N}. The @code{N} in @code{sum(N)} is called the (formal) parameter of @code{sum(N)}. The example shows a function of the single argument. In general, any number of parameters can be specified by separating by commas (@samp{,}). A (formal) parameter accepts a value given as an argument (or an actual parameter) at a function call of the function. Since the value of the argument is given to the formal parameter, any modification to the parameter does not usually affect the argument (or actual parameter). However, there are a few exceptions: vector arguments and matrix arguments. Let @code{A} be a program variable and assigned to a vector value @code{[ a, b ]}. If A is given as an actual parameter to a formal parameter, say @code{V}, of a function, then an assignment in the function to the vector element designator @code{V[1]}, say @code{V[1]=c;}, causes modification of the actual parameter @code{A} resulting @code{A} to have an altered value @code{[ a c ]}. Thus, if a vector is given to a formal parameter of a function, then its element (and subsequently the vector itself) in the calling side is modified through modification of the formal parameter by a vector element designator in the called function. The same applies to a matrix argument. Note that, even in such case where a vector (or a matrix) is given to a formal parameter, the assignment to the whole parameter itself has only a local effect within the function. \E @example def clear_vector(M) @{ /* M is expected to be a vector */ L = size(M)[0]; for ( I = 0; I < L; I++ ) M[I] = 0; @} @end example @noindent \BJP この函数は, 引数のベクトルを 0 ベクトルに初期化するための函数である. また, ベクトルを引数に渡すことにより, 複数の結果を引数のベクトルに 収納して返すことができる. 実際には, このような場合には, 結果をリスト にして返すこともできる. 状況に応じて使いわけすることが望ましい. \E \BEG This function will clear off the vector given as its argument to the formal parameter @code{M} and return a 0 vector. Passing a vector as an argument to a function enables returning multiple results by packing each result in a vector element. Another alternative to return multiple results is to use a list. Which to use depends on cases. \E \BJP @node コメント,,, ユーザ定義函数の書き方 @subsection コメント \E \BEG @node comments,,, Writing user defined functions @subsection comments \E @noindent \JP C と同様 @samp{/*} と @samp{*/} で囲まれた部分はコメントとして扱われる. \BEG The text enclosed by @samp{/*} and @samp{*/} (containing @samp{/*} and @samp{*/}) is treated as a comment and has no effect to the program execution as in C programs. \E @example /* * This is a comment. */ def afo(X) @{ @end example @noindent \BJP コメントは複数行に渡っても構わないが, 入れ子にすることはできない. @samp{/*} がいくつあっても最初のもののみが有効となり, 最初に現れた @samp{*/} でコメントは終了したと見なされる. プログラムなどで, コメント を含む可能性がある部分をコメントアウトした場合には, @code{#if 0}, @code{#endif}を使えばよい. (@xref{プリプロセッサ}.) \E \BEG A comment can span to several lines, but it cannot be nested. Only the first @samp{/*} is effective no matter how many @samp{/*}'s in the subsequent text exist, and the comment terminates at the first @samp{*/}. In order to comment out a program part that may contain comments in it, use the pair, @code{#if 0} and @code{#endif}. (@xref{preprocessor}.) \E @example #if 0 def bfo(X) @{ /* empty */ @} #endif @end example \BJP @node 文,,, ユーザ定義函数の書き方 @subsection 文 \E \BEG @node statements,,, Writing user defined functions @subsection statements \E @noindent \BJP @b{Asir} のユーザ函数は, @example def 名前(引数,引数,...,引数) @{ 文 文 ... 文 @} \E \BEG An user function of @b{Asir} is defined in the following form. @example def name(parameter, parameter,...,parameter) @{ statement statement ... statement @} \E @end example @noindent \BJP という形で定義される. このように, 文は函数の基本的構成要素であり, プロ グラムを書くためには, 文がどのようなものであるか知らなければならない. 最も単純な文として, 単文がある. これは, \E \BEG As you can see, the statement is a fundamental element of the function. Therefore, in order to write a program, you have to learn what the statement is. The simplest statement is the simple statement. One example is an expression with a terminator (@samp{;} or @samp{$}.) \E @example S = sum(N); @end example @noindent \BJP のように, 式に終端記号 (@samp{;} または @samp{$}) をつけたものである. この単文及び類似の @code{return} 文, @code{break} 文などが文の最小構成 単位となる. @code{if} 文や @code{for} 文の定義 (@ref{文法の詳細}) を見れ ばわかる通り, それらの本体は, 単なる一つの文として定義されている. 通常 は, 本体には複数の文が書けることが必要となる. このような場合, @samp{@{} と @samp{@}} で文の並びを括って, 一つの文として扱うことがで きる. これを複文と呼ぶ. \E \BEG A `@code{return} statement' and `@code{break} statement' are also primitives to construct `statements.' As you can see the syntactic definition of `@code{if} statement' and `@code{for} statement', each of their bodies consists of a single `statement.' Usually, you need several statements in such a body. To solve this contradictory requirement, you may use the `compound statement.' A `compound statement' is a sequence of `statement's enclosed by a left brace @samp{@{} and a right brace @samp{@}}. Thus, you can use multiple statement as if it were a single statement. \E @example if ( I == 0 ) @{ J = 1; K = 2; L = 3; @} @end example @noindent \BJP @samp{@}} の後ろには終端記号は必要ない. なぜなら, @samp{@{} 文並び @samp{@}}が既に文となっていて, @code{if} 文の要請を満たしているからで ある. \E \BEG No terminator symbol is necessary after @samp{@}}, because @samp{@{} statement sequence @samp{@}} already forms a statement, and it satisfies the syntactical requirement of the `@code{if} statement.' \E \BJP @node return 文,,, ユーザ定義函数の書き方 @subsection @code{return} 文 \E \BEG @node return statement,,, Writing user defined functions @subsection @code{return} statement \E @noindent \JP @code{return} 文は, \EG There are two forms of @code{return} statement. @example \JP return 式; \EG return expression; return; @end example @noindent \BJP の 2 つの形式がある. いずれも函数から抜けるための文である. 前者は 函数の値として 式 を返す. 後者では, 函数の値として何が返されるか はわからない. \E \BEG Both forms are used for exiting from a function. The former returns the value of the expression as a function value. The function value of the latter is not defined. \E \BJP @node if 文,,, ユーザ定義函数の書き方 @subsection @code{if} 文 \E \BEG @node if statement,,, Writing user defined functions @subsection @code{if} statement \E @noindent \JP @code{if} 文には \EG There are two forms of @code{if} statement. @example \BJP if ( 式 ) if ( 式 ) 文 及び 文 else 文 \E \BEG if ( expression ) if ( expression ) statement and statement else statement \E @end example @noindent \BJP の 2 種類がある. これらの動作は明らかであるが, 文の位置に @code{if} 文 が来た場合に注意を要する. 次の例を考えてみよう. \E \BEG The interpretation of these forms are obvious. However, be careful when another @code{if} statement comes at the place for `statement'. Let us examine the following example. \E @example \BJP if ( 式 ) if ( 式 ) 文 else 文 \E \BEG if ( expression1 ) if ( expression2 ) statement1 else statement2 \E @end example @noindent \BJP この場合, 字下げからは, @code{else} 以下は, 最初の @code{if} に対応する ように見えるが, パーザは, 自動的に 2 番目の @code{if} に対応すると判断する. すなわち, 2 種類の @code{if} 文を許したために, 文法に曖昧性が現れ, それを 解消するために, @code{else} 以下は, 最も近い @code{if} に対応すると いう規則が適用されるのである. 従って, この例は, \E \BEG One might guess @code{statement2} after @code{else} corresponds with the first @code{if ( expression1 )} by its appearance of indentation. But, as a matter of fact, the @code{Asir} parser decides that it correspond with the second @code{if ( expression2 )}. Ambiguity due to such two kinds of forms of @code{if} statement is thus solved by introducing a rule that a statement preceded by an @code{else} matches to the nearest preceding @code{if}. Therefore, rearrangement of the above example for improving readability according to the actual interpretation gives the following. \E @example \BJP if ( 式 ) @{ if ( 式 ) 文 else 文 @} \E \BEG if ( expression1 ) @{ if ( expression2 ) statement1 else statement2 @} \E @end example @noindent \JP という意味となる. 字下げに対応させるためには, \BEG On the other hand, in order to reflect the indentation, it must be written as the following. \E @example \BJP if ( 式 ) @{ if ( 式 ) 文 @} else 文 \E \BEG if ( expression1 ) @{ if ( expression2 ) statement1 @} else statement2 \E @end example @noindent \JP としなければならない. \BJP @noindent 関数の中でなく, top level で @code{if} 文を用いるときは @code{$} または @code{;} で終了する必要がある. これらがないと次の文がよみとばされる. \E \BEG @noindent When @code{if} is used in the top level, the @code{if} expression should be terminated with @code{$} or @code{;}. If there is no terminator, the next expression will be skipped to be evaluated. \E \BJP @node ループ break return continue,,, ユーザ定義函数の書き方 @subsection ループ, @code{break}, @code{return}, @code{continue} \E \BEG @node loop break return continue,,, Writing user defined functions @subsection @code{loop}, @code{break}, @code{return}, @code{continue} \E @noindent \BJP ループを構成する文は, @code{while} 文, @code{for} 文, @code{do} 文 の 3 種類がある. \E \BEG There are three kinds of statements for loops (repetitions): the @code{while} statement, the @code{for} statement, and the @code{do} statement. \E @itemize @bullet @item \JP @code{while} 文 \EG @code{while} statement @* \JP 形式は, \EG It has the following form. @example \JP while ( 式 ) 文 \EG while ( expression ) statement @end example @noindent \BJP で, これは, 式 を評価して, その値が 0 でない限り 文 を実行するという 意味となる. たとえば 式 が 1 ならば, 単純な無限ループとなる. \E \BEG This statement specifies that @code{statement} is repeatedly evaluated as far as the @code{expression} evaluates to a non-zero value. If the expression 1 is given to the @code{expression}, it forms an infinite loop. \E @item \JP @code{for} 文 \EG @code{for} statement @* \JP 形式は, \EG It has the following form. @example \JP for ( 式並び-1; 式; 式並び-2 ) 文 \EG for ( expr list-1; expr; expr list-2 ) statement @end example \JP で, これは \EG This is equivalent to the program @example \BJP 式並び-1 (を単文並びにしたもの) while ( 式 ) @{ 文 式並び-2 (を単文並びにしたもの) @} \E \BEG expr list-1 (transformed into a sequence of simple statement) while ( expr ) @{ statement expr list-2 (transformed into a sequence of simple statement) @} \E @end example \JP と等価である. @item \JP @code{do} 文 \EG @code{do} statement @* @example \BJP do @{ 文 @} while ( 式 ) \E \BEG do @{ statement @} while ( expression ) \E @end example \BJP は, 先に 文を実行してから条件式による判定を行う所が @code{while} 文 と異なっている. \E \BEG This statement differs from @code{while} statement by the location of the termination condition: This statement first execute the @code{statement} and then check the condition, whereas @code{while} statement does it in the reverse order. \E @end itemize @noindent \BJP ループを抜け出す手段として, @code{break} 文及び @code{return} 文がある. また, ループの制御を ある位置に移す手段として @code{continue} 文がある. \E \BEG As means for exiting from loops, there are @code{break} statement and @code{return} statement. The @code{continue} statement allows to move the control to a certain point of the loop. \E @itemize @bullet @item @code{break} @* \JP @code{break} 文は, それを囲むループを一つだけ抜ける. \EG The @code{break} statement is used to exit the inner most loop. @item @code{return} @* \BJP @code{return} 文は, 一般に函数から抜けるための文であり, ループの中からでも有効である. \E \BEG The @code{return} statement is usually used to exit from a function call and it is also effective in a loop. \E @item @code{continue} @* \BJP @code{continue} 文は, ループの本体の文の末端に制御を移す. 例えば @code{for} 文では, 最後の式並びの実行を行い, @code{while} 文では条件式の判定に移る. \E \BEG The @code{continue} statement is used to move the control to the end point of the loop body. For example, the last expression list will be evaluated in a @code{for} statement, and the termination condition will be evaluated in a @code{while} statement. \E @end itemize \BJP @node 構造体定義,,, ユーザ定義函数の書き方 @subsection 構造体定義 \E \BEG @node structure definition,,, Writing user defined functions @subsection structure definition \E \BJP 構造体とは, 各成分の要素が名前でアクセスできる固定長配列と思ってよい. 各構造体は名前で区別される. 構造体は, @code{struct} 文により宣言される. 構造体が宣言されるとき, asir は内部で構造体のそれぞれの型に固有の識別 番号をつける. この番号は, 組み込み関数 @code{struct_type} により取得 できる. ある型の構造体は, 組み込み関数 @code{newstruct} により生成される. 構造体の各メンバは, 演算子 @code{->} によりアクセスする. メンバが構造体の場合, @code{->} による指定は入れ子にできる. \E \BEG A structure data type is a fixed length array and each component of the array is accessed by its name. Each type of structure is distinguished by its name. A structure data type is declared by @code{struct} statement. A structure object is generated by a builtin function @code{newstruct}. Each member of a structure is accessed by an operatator @code{->}. If a member of a structure is again a structure, then the specification by @code{->} can be nested. \E @example [1] struct rat @{num,denom@}; 0 [2] A = newstruct(rat); @{0,0@} [3] A->num = 1; 1 [4] A->den = 2; 2 [5] A; @{1,2@} [6] struct_type(A); 1 @end example @table @t \JP @item 参照 \EG @item References @fref{newstruct}, @fref{struct_type} @end table \BJP @node さまざまな式,,, ユーザ定義函数の書き方 @subsection さまざまな式 \E \BEG @node various expressions,,, Writing user defined functions @subsection various expressions \E @noindent \JP 主な式の構成要素としては, 次のようなものがある. \EG Major elements to construct expressions are the following: @itemize @bullet @item \JP 加減乗除, 冪 \EG addition, subtraction, multiplication, division, exponentiation @* \BJP 冪は, @samp{^} により表す. 除算 @samp{/} は, 体としての演算に用いる. 例えば, @code{2/3} は有理数の @code{2/3} を表す. 整数除算, 多項式除算 (剰余を含む演算) には別途組み込み函数が用意されている. \E \BEG The exponentiation is denoted by @samp{^}. (This differs from C language.) Division denoted by @samp{/} is used to operate in a field, for example, @code{2/3} results in a rational number @code{2/3}. For integer division and polynomial division, both including remainder operation, built-in functions are provided. \E @example x+1 A^2*B*afo X/3 @end example @item \JP インデックスつきの変数 \EG programming variables with indices @* \BJP ベクトル, 行列, リストの要素はインデックスを用いることにより取り出せる. インデックスは 0 から始まることに注意する. 取り出した要素がベクトル, 行列, リストなら, さらにインデックスをつけることも有効である. \E \BEG An element of a vector, a matrix or a list can be referred to by indexing. Note that the indices begin with number 0. When the referred element is again a vector, a matrix or a list, repeated indexing is also effective. \E @example V[0] M[1][2] @end example @item \JP 比較演算 \EG comparison operation @* \BJP 等しい (@samp{==}), 等しくない (@samp{!=}), 大小 (@samp{>}, @samp{<}, @samp{>=}, @samp{<=}) の 2 項演算がある. 真ならば有理数の 1, 偽ならば 0 を値に持つ. \E \BEG There are comparison operations @samp{==} for equivalence, @samp{!=} for non-equivalence, @samp{>}, @samp{<},@samp{>=}, and @samp{<=} for larger or smaller. The results of these operations are either value 1 for the truth, or 0 for the false. \E @item \JP 論理式 \EG logical expression @* \BJP 論理積 (@samp{&&}), 論理和 (@samp{||}) の 2 項演算と, 否定 (@samp{!}) が用意されている. 値はやはり 1, 0 である. \E \BEG There are two binary logical operations @samp{&&} for logical @samp{conjunction}(and), @samp{||} for logical @samp{disjunction}(or), and one unary logical operation @samp{!} for logical @samp{negation}(not). The results of these operations are either value 1 for the truth, and 0 for the false. \E @item \JP 代入 \EG assignment @* \BJP 通常の代入は @samp{=} で行う. このほか, 算術演算子と組み合わせて 特殊な代入を行うこともできる. \E \BEG Value assignment of a program variable is usually done by @samp{=}. There are special assignments combined with arithmetic operations. \E (@samp{+=}, @samp{-=}, @samp{*=}, @samp{/=}, @samp{^=}) @example \JP A = 2 A *= 3 (これは A = A*3 と同じ; その他の演算子も同様) \EG A = 2 A *= 3 (the same as A = A*3; The others are alike.) @end example @item \JP 函数呼び出し \EG function call @* \JP 函数呼び出しも式の一種である. \EG A function call is also an expression. @item @samp{++}, @samp{--} @* \JP これらは, 変数の前後について, それぞれ次のような操作, 値を表す. \BEG These operators are attached to or before a program variable, and denote special operations and values. \E @example \BJP A++ 値は元の A の値, A = A+1 A-- 値は元の A の値, A = A-1 ++A A = A+1, 値は変化後の値 --A A = A-1, 値は変化後の値 \E \BEG A++ the expression value is the previous value of A, and A = A+1 A-- the expression value is the previous value of A, and A = A-1 ++A A = A+1, and the value is the one after increment of A --A A = A-1, and the value is the one after decrement of A \E @end example @end itemize \BJP @node プリプロセッサ,,, ユーザ定義函数の書き方 @subsection プリプロセッサ \E \BEG @node preprocessor,,, Writing user defined functions @subsection preprocessor \E @noindent \BJP @b{Asir} のユーザ言語は C 言語を模したものである. C の特徴として, プリプロセッサ @code{cpp} によるマクロ展開, ファイルのインクルード があるが, @b{Asir} においてもユーザ言語ファイルの読み込みの際 @code{cpp} を通してから読み込むこととした. これによりユーザ言語 ファイル中で @code{#include}, @code{#define}, @code{#if} などが使える. \E \BEG he @b{Asir} user language imitates C language. A typical features of C language include macro expansion and file inclusion by the preprocessor @code{cpp}. Also, @b{Asir} read in user program files through @code{cpp}. This enables @b{Asir} user to use @code{#include}, @code{#define}, @code{#if} etc. in his programs. \E @itemize @bullet @item @code{#include} @* \BJP UNIX では インクルードファイルは, Asir のライブラリディレクトリ (環境変数 @b{ASIR_LIBDIR} で指定されたディレクトリ) と @code{#include} が書かれているファイルと同じディレクトリをサーチする. UNIX 以外では @code{cpp} に特に引数を渡さないため, @code{#include} が書かれているファイルと同じディレクトリのみをサーチする. \E \BEG Include files are searched within the same directory as the file containing @code{#include} so that no arguments are passed to @code{cpp}. \E @item @code{#define} @* \JP これは, C におけるのと全く同様に用いることができる. \EG This can be used just as in C language. @item @code{#if} @* \BJP @code{/*}, @code{*/} によるコメントは入れ子にできないので, プログラム の大きな部分をコメントアウトする際に, @code{#if 0}, @code{#endif} を使うと便利である. \E \BEG This is conveniently used to comment out a large part of a user program that may contain comments by @code{/*} and @code{*/}, because such comments cannot be nested. \E @end itemize @noindent \JP 次の例は, @samp{defs.h} にあるマクロ定義である. \EG the following are the macro definitions in @samp{defs.h}. @example #define ZERO 0 #define NUM 1 #define POLY 2 #define RAT 3 #define LIST 4 #define VECT 5 #define MAT 6 #define STR 7 #define N_Q 0 #define N_R 1 #define N_A 2 #define N_B 3 #define N_C 4 #define V_IND 0 #define V_UC 1 #define V_PF 2 #define V_SR 3 #define isnum(a) (type(a)==NUM) #define ispoly(a) (type(a)==POLY) #define israt(a) (type(a)==RAT) #define islist(a) (type(a)==LIST) #define isvect(a) (type(a)==VECT) #define ismat(a) (type(a)==MAT) #define isstr(a) (type(a)==STR) #define FIRST(L) (car(L)) #define SECOND(L) (car(cdr(L))) #define THIRD(L) (car(cdr(cdr(L)))) #define FOURTH(L) (car(cdr(cdr(cdr(L))))) #define DEG(a) deg(a,var(a)) #define LCOEF(a) coef(a,deg(a,var(a))) #define LTERM(a) coef(a,deg(a,var(a)))*var(a)^deg(a,var(a)) #define TT(a) car(car(a)) #define TS(a) car(cdr(car(a))) #define MAX(a,b) ((a)>(b)?(a):(b)) @end example \BJP @noindent C のプリプロセッサを流用しているため, プリプロセッサは @code{$} を正しく処理できない. たとえば @code{LIST} が定義されていても @code{LIST$}は置換されない. @code{$} の前に空白をおいて @code{LIST $} と書かないといけない. \E \BEG @noindent Since we are utilizing the C preprocessor, it cannot properly preprocess expressions with @code{$}. For example, even if @code{LIST} is defined, @code{LIST} in the expression @code{LIST$} is not replaced. Add a blank before @code{$}, i.e., write as @code{LIST $} to make the proprocessor replace it properly. \E \BJP @node オプション指定,,, ユーザ定義函数の書き方 @subsection オプション指定 \E \BEG @node option,,, Writing user defined functions @subsection option \E \BJP ユーザ定義関数が @var{N} 変数で宣言された場合, その関数は, @var{N} 変数での呼び出しのみが許される. \E \BEG If a user defined function is declared with @var{N} arguments, then the function is callable with @var{N} arguments only. \E @example [0] def factor(A) @{ return fctr(A); @} [1] factor(x^5-1,3); evalf : argument mismatch in factor() return to toplevel @end example \BJP 不定個引数の関数をユーザ言語で記述したい場合, リスト, 配列を用いることで 可能となるが, 次のようなより分かりやすい方法も可能である. \E \BEG A function with indefinite number of arguments can be realized by using a list or an array as its argument. Another method is available as follows: \E @example % cat factor def factor(F) @{ Mod = getopt(mod); ModType = type(Mod); if ( ModType == 1 ) /* 'mod' is not specified. */ return fctr(F); else if ( ModType == 0 ) /* 'mod' is a number */ return modfctr(F,Mod); @} @end example @example [0] load("factor")$ [1] factor(x^5-1); [[1,1],[x-1,1],[x^4+x^3+x^2+x+1,1]] [2] factor(x^5-1|mod=11); [[1,1],[x+6,1],[x+2,1],[x+10,1],[x+7,1],[x+8,1]] @end example \BJP 2 番目の @code{factor()} の呼び出しにおいて, 関数定義の際に宣言された引 数 @code{x^5-1}の後ろに @code{|mod=11} が置かれている. これは, 関数実行時 に, @code{mod} という keyword に対して @code{11} という値を割り当てること を指定している. これをオプション指定と呼ぶことにする. この値は @code{getopt(mod)} で取り出すことができる. 1 番目の呼び出しのように @code{mod} に対するオプション指定がない場合には, @code{getopt(mod)} は型 識別子 -1 のオブジェクトを返す. これにより, 指定がない場合の動作を if 文 により記述できる. @samp{|} の後ろには, 任意個のオプションを, @samp{,} で区切って指定することができる. \E \BEG In the second call of @code{factor()}, @code{|mod=11} is placed after the argument @code{x^5-1}, which appears in the declaration of @code{factor()}. This means that the value @code{11} is assigned to the keyword @code{mod} when the function is executed. The value can be retrieved by @code{getopt(mod)}. We call such machinery @var{option}. If the option for @var{mod} is not specified, @code{getopt(mod)} returns an object whose type is -1. By this feature, one can describe the behaviour of the function when the option is not specified by @var{if} statements. After @samp{|} one can append any number of options seperated by @samp{,}. \E @example [100] xxx(1,2,x^2-1,[1,2,3]|proc=1,index=5); @end example \BJP さらに, オプションを @code{key1=value1,key2=value2,...} のように @samp{,} で区切って渡す代わりに, 特別なキーワード @code{option_list} とオプションリスト @code{[["key1",value1],["key2",value2],...]} を用いて渡すことも可能である. \E \BEG Optinal arguments may be given as a list with the key word @code{option_list} as @code{option_list=[["key1",value1],["key2",value2],...]}. It is equivalent to pass the optional arguments as @code{key1=value1,key2=value2,...}. \E @example [101] dp_gr_main([x^2+y^2-1,x*y-1]|option_list=[["v",[x,y]],["order",[[x,5,y,1]]]]); @end example \BJP 特に, 引数なしの @code{getopt()} はオプションリストを返すので, オプションをとる関数から, オプションをとる関数を呼び出すときには有用である. \E \BEG Since @code{getopt()} returns an option list, the optional argument @code{option_list=...} is useful when we call functions with optional arguments from a function with optional arguments to pass the all optional parameters. \E @example % cat foo.rr def foo(F) @{ OPTS=getopt(); return factor(F|option_list=OPTS); @} @end example @example [3] load("foo.rr")$ [4] foo(x^5-1|mod=11); [[1,1],[x+6,1],[x+2,1],[x+10,1],[x+7,1],[x+8,1]] @end example \BJP @node モジュール,,, ユーザ定義函数の書き方 @subsection モジュール \E \BEG @node module,,, Writing user defined functions @subsection module \E \BJP ライブラリで定義されている関数, 変数をカプセル化する仕組みが モジュール (module) である. はじめにモジュールを用いたプログラムの例をあげよう. \E \BEG Function names and variables in a library may be encapsulated by module. Let us see an example of using module \E @example module stack; static Sp $ Sp = 0$ static Ssize$ Ssize = 100$ static Stack $ Stack = newvect(Ssize)$ localf push $ localf pop $ def push(A) @{ if (Sp >= Ssize) @{print("Warning: Stack overflow\nDiscard the top"); pop();@} Stack[Sp] = A; Sp++; @} def pop() @{ local A; if (Sp <= 0) @{print("Stack underflow"); return 0;@} Sp--; A = Stack[Sp]; return A; @} endmodule; def demo() @{ stack.push(1); stack.push(2); print(stack.pop()); print(stack.pop()); @} @end example \BJP モジュールは @code{module} モジュール名 〜 @code{endmodule}で囲む. モジュールは入れ子にはできない. モジュールの中だけで使う大域変数は @code{static} で宣言する. この変数はモジュールの外からは参照もできないし変更もできない. @code{static} 変数はすべての関数定義の前に宣言しないといけない. パーサーがワンパスのため, 宣言のない変数は自動的に局所変数とみなされるからである. モジュールの外の大域変数は @code{extern} で宣言する. \E \BEG Module is encapsulated by the sentences @code{module} module name and @code{endmodule}. A variable of a module is declared with the key word @code{static}. The static variables cannot be refered nor changed out of the module, but it can be refered and changed in any functions in the module. The @code{static} variables must be declared before the definitions of functions, because the one-path parser of asir automatically assume variables as local variables if there is no declaration for them. A global variable which can be refered and changed in or out of the module is declared with the key word @code{extern}. \E \BJP モジュール内部で定義する関数は @code{localf} を用いて宣言しないといけない. 上の例では @code{push} と @code{pop} を宣言している. この宣言は必須である. \E \BEG Any function defined in a module must be declared forward with the keyword @code{localf}. In the example above, @code{push} and @code{pop} are declared. This declaration is necessary. \E \BJP モジュール @code{moduleName} で定義された関数 @code{functionName} を モジュールの外から呼ぶには @code{moduleName.functionName(引数1, 引数2, ... )} なる形式でよぶ. モジュールの中からは, 関数名のみでよい. 次の例では, モジュールの外からモジュール @code{stack} で定義された関数 @code{push}, @code{pop} を呼んでいる. \E \BEG A function @code{functionName} defined in a module @code{moduleName} can be called by the expression @code{moduleName.functioName(arg1, arg2, ...)} out of the module. Inside the module, @code{moduleName.} is not necessary. In the example below, the functions @code{push} and @code{pop} defined in the module @code{stack} are called out of the module. \E @example stack.push(2); print( stack.pop() ); 2 @end example \BJP モジュールで用いる関数名は局所的である. つまりモジュールの外や別のモジュールで定義されている関数名と同じ名前が 利用できる. \E \BEG Any function name defined in a module is local. In other words, the same function name may be used out of the module to define a different function. \E \BJP モジュール機能は大規模ライブラリの開発を想定している. ライブラリを必要に応じて分割ロードするには, 関数 @code{module_definedp} を用いるのが 便利である. デマンドロードはたとえば次のように行なえば良い. \E \BEG The module structure of asir is introduced to develop large libraries. In order to load libraries on demand, the command @code{module_definedp} will be useful. The below is an example of demand loading. \E @example if (!module_definedp("stack")) load("stack.rr") $ @end example \BJP asir では局所変数の宣言は不要であった. しかしモジュール stack の例を見れば分かるように, @code{local A;} なる形式で 局所変数を宣言できる. キーワード @code{local} を用いると, 宣言機能が有効となる. 宣言機能を有効にすると, 宣言されてない変数はロードの段階で エラーを起こす. 変数名のタイプミスによる予期しないトラブルを防ぐには, 宣言機能を有効にしてプログラムするのがよい. \E \BEG It is not necessary to declare local variables in asir. As you see in the example of the stack module, we may declare local variables by the key word @code{local}. Once this key word is used, asir requires to declare all the variables. In order to avoid some troubles to develop a large libraries, it is recommended to use @code{local} declarations. \E \BJP モジュール内の関数をそのモジュールが定義される前に 呼び出すような関数を書くときには, その関数の前でモジュールを次のように プロトタイプ宣言しておく必要がある. \E \BEG When we need to call a function in a module before the module is defined, we must make a prototype declaration as the example below. \E @example /* Prototype declaration of the module stack */ module stack; localf push $ localf pop $ endmodule; def demo() @{ print("----------------"); stack.push(1); print(stack.pop()); print("---------------"); @} module stack; /* The body of the module stack */ endmodule; @end example \BJP モジュールの中からトップレベルで定義されている関数を呼ぶには, 下の例のように @code{::} を用いる. \E \BEG In order to call functions defined in the top level from the inside of a module, we use @code{::} as in the example below. \E @example def afo() @{ S = "afo, afo"; return S; @} module abc; localf foo,afo $ def foo() @{ G = ::afo(); return G; @} def afo() @{ return "afo, afo in abc"; @} endmodule; end$ [1200] abc.foo(); afo, afo [1201] abc.afo(); afo, afo in abc @end example @table @t \JP @item 参照 \EG @item References @fref{module_list}, @fref{module_definedp}, @fref{remove_module}. @end table