@node プリミティブ, 索引, 基本言語仕様, Top
@chapter プリミティブ
インタプリタ初期化時に、環境にデフォルトで組み込まれる変数とその値をプリミティブと呼ぶ。そのうち値は固定的であり、Cなどのインタプリタを記述する言語で書かれている。そのうち、あらゆるXLでいつでも使える関数を汎用プリミティブとよぶ。また、データベース検索など何らかの高機能な目的のために拡張するために組み込まれるものを拡張プリミティブと呼ぶ。拡張プリミティブについては、ここの仕様では定義しない。

@menu
* システム関数::                
* GetSet関連関数::              
* 制御関数::                    
* 環境操作関数::                
* 構造型操作関数::              
* 算術演算関数::                
* 論理演算関数::                
* ネットワーク関数::            
* セッション管理関数::          
* サーバ・認証命令::            
* 文字列操作関数::              
* ロックサーバー命令::          
@end menu


@node システム関数, GetSet関連関数, プリミティブ, プリミティブ
@section システム関数

@primitivea {ErrHandler , Nomal Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(ErrHandler exp)
@b{XML型式}
<ErrHandler> exp </ErroHandler>
@b{C言語宣言}
XLtype * cErrHandler(XLtype * exp);
@end example
@end cartouche

@sp 1

@primitiveMid
エラーをとらえることの出来る特殊なEvalを使って、expを評価する。評価の結果、expがエラー型でないばあいはそのままexpを戻り値とする。 exp がエラー型であった場合は、これを分解し、以下のような構造型に変形して、それを戻り値とする。

@sp 1

LISP形式
@example
(Error シーケンス番号 エラー発生サイトURL
　エラー発生ファイル名　エラー発生関数 エラーコード exp)
@end example

@sp 1

XML形式
@example
<Error>
        シーケンス番号 \
        エラー発生サイトURL \
        エラー発生ファイル名 \
        エラーコード \
        exp
</Error>
@end example

@sp 1
もし、エラーが発生していない場合は、
@sp 1

LISP形式

@example
(Error シーケンス番号 サイトURL　ファイル名　"ErrHandler" 0 exp)
@end example

@sp 1

XML形式

@example
<Error>
        シーケンス番号
        サイトURL
        ファイル名
        ErrHandler
        0
        exp
</Error>
@end example

@sp 1

となる。基本的にはエラー型の値の内容がErrorから始まる、構造型に変化したものである。こうすることにより、インタープリタはこれをエラー型とは認識しなくなるので、普通の構造型と同様に処理できるようになる。たとえば、以下のように使う。

@sp 1

@example
        (define c (ErrHandler (/ a b)))
        <If> (Not (= (GetElement c 4) 0))
                <Then> ゼロ割に関する処理 </Then>
                <Else> 通常処理 </Else>
        </If>
@end example
@primitiveEnd

@primitivea{InvokeError, Normal Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式(1)}
(InvokeError シーケンス番号 サイトURL ファイル名 関数名 エラーコード exp)
@b{LISP型式(2)}
(InvokeError exp)
@b{XML型式(1)}
<InvokeError>
        シーケンス番号 
        サイトURL 
        ファイル名 
        関数名 
        エラーコード 
        exp
</InvokeError>
@b{XML型式(2)}
<InvokeError>exp</InvokeError>
@end example
@end cartouche

@sp 1

@primitiveMid
与えられた情報のエラーを返す。(1)において、シーケンス番号を-1とすると、@code{InvokeError}のある行をその値にする。サイトURLを文字列ではなく()とすると、このスクリプトが実行されているサイトdomainの値が入る。ファイル名は、同様に()とすると現在動いているインタプリタに指定されているファイル名となる。関数名と、エラーコード、@code{exp}は省略出来ない。@code{exp}はどんな値でも良い。

@sp 1

(2)は、

@example
<Error> シーケンス番号 サイトURL ファイル名 関数名 エラーコード exp </Error> 
@end example

という値を@code{exp}として与える。シーケンス番号などの意味は(1)の場合と同じ。

@primitiveEnd 


@primitivea{Arg,Applicative Order / LEVEL: 1}

@cartouche
@example
@b{LISP型式}
(Arg integer-exp)
@b{XML型式}
<Arg>integer-exp</Arg>
@b{C関数宣言}
XLtype * xl_Arg(XLtype * exp)
@end example
@end cartouche

@sp 1

@primitiveMid
シェルのコマンドラインからエージェントが呼び出されたときの @code{integer-exp} 番目の引数を返す。ただし、コマンドラインの引数の中で@samp{/}の位置を0番目と見なし、それより前の引数を負の値で、それより後の引数を正の値で順番を指定する。

@primitiveEnd

@primitivea {GetVariable,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(GetVariable string-exp)
@b{XML型式}
<GetVariable> string-exp </GetVariable>
@b{C関数宣言}
XLtype * xl_GetVariable(XLtype * exp);
@end example
@end cartouche

@sp 1

@primitiveMid
@code{string-exp}で与えられたシェルの環境変数をアクセスする。戻り値は文字列型である。

@primitiveEnd

@primitivea {Getlid,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(GetIid)
@b{XML型式}
<GetIid>
@end example
@end cartouche

@sp 1

@primitiveMid
この関数を評価したインタプリタのIIDを返す。

@primitiveEnd

@primitivea {SetMainInterpreter,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(SetMainInterpreter integer-exp(iid))
@b{C関数宣言}
XLtype * xl_SetMainInterpreter(XLtype * exp);
@end example
@end cartouche

@sp 1

@primitiveMid
メイン・インタプリタを変更する。-1を与えると、メイン・インタプリタは未指定となる。

メイン・インタプリタを指定すると、このインタプリタが終了した時点でエージェントは全て終了する。また、サーバの認証の際に、GetUserInfoはこのメイン・インタプリタをたどることによって、ルート・エージェントの認証を行う。 

@primitiveEnd

@primitivea {WaitInterpreter,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(WaitInterpreter integer-exp(iid))
@end example
@end cartouche

@sp 1

@primitiveMid
与えられた、IIDのインタプリタが終了するのを待つ。 

@primitiveEnd


@primitiveb {Env0,Env1,Symbol Order / LEVEL: 0}
@c @primitivx {Env1,Symbol Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
Env0, Env1
@b{XML型式}
^Env0, ^Env1
@end example
@end cartouche

@sp 1

@primitiveMid
レベル0の関数、シンボルが定義されている環境が@code{Env0}である。レベル1の関数、シンボルが定義されている環境が@code{Env1}である。@code{Env1}の親環境は@code{Env0}である。またエージェント立ち上げ時に動くインタプリタは、@code{Env1}がエントリ環境となる。 

@primitiveEnd

@primitivea {OpenInterpreter,Applicative Order / LEVEL: 1}

@cartouche
@example
@b{LISP型式}
OpenInterpreter "stdio/socket/ipc" env-exp option )
@b{XML型式}
<OpenInterpreter>
        stdio/accept/connect/ipc/file
        env-exp
        option
</OpenInterpreter>
@end example
@end cartouche

@sp 1

@primitiveMid
インタプリタの受け口を定義する。受け口の接続元を、@code{stdio},@code{accept},@code{connect},@code{ipc}の中から指定する。また、最初のエントリ環境を@code{env-exp}に指定する。@code{option}は以下の通り。

@sp 1



@multitable @columnfractions .30 .30 .30
@item @emph{LISP型式} @tab @emph{XML型式} @tab @emph{説明}

@item (FormatMode "lisp/xml/html")
@tab <FormatMode> lisp/xml/html </FormatMode>
@tab インタプリタの結果出力形式の指定

@item (FormatIndent string-exp)
@tab <FormatIndent> string-exp </FormatIndent>
@tab インデントの設定1がインデントあり。

@item (Port integer-exp)
@tab <Port> integer-exp </Port>
@tab ソケットまたはIPCのアクセプト・ポート番号

@item MaxConnection integer-exp)
@tab <MaxConnection> integer-exp </MaxConnection>
@tab 最大ソケット/IPC接続数の指定

@item (InputFileName string-exp)
@tab <InputFileName> string-exp </InputFileName>
@tab 接続元の入力ストリームとなるファイル名

@item (OutputFileName string-exp)
@tab <OutputFileName> string-exp </FileName>
@tab 接続元の出力ストリームとなるファイル名

@item (MaxConnectionTime integer-exp)
@tab <MaxConnectionTime> integer-exp </MaxConnectionTime>
@tab 最大コネクション時間の指定（秒）

@item (MaxSilentTime integer-exp)
@tab <MaxSilentTime> integer-exp </MaxSilentTime>
@tab 最大停止時間の指定（秒）

@item (Environment "new/thisone")
@tab <Environment> new/thisone </Environment>
@tab "thisone"を指定すると、与えられたenv-expをそのままエントリ環境とする。"new"を指定すると新しい環境を生成し、その親をenv-expとする。

@item (HostName string-exp)
@tab <HostName> string-exp </HostName>
@tab connect 先のホスト名を指定する

@item (Result integer-exp)
@tab <Result> integer-exp </Result>
@tab 1を指定すると、@code{<Result>}タグで結果を囲う。0を指定すると囲わない。connect先のIPアドレスを指定する。

@item (IP string-exp)
@tab <IP> string-exp </IP>
@tab connect先のIPアドレスを指定する。

@item (Permission exp(login mode) allow/deny ...)
@tab <IP> exp(login mode) allow/deny ... </IP>
@tab accept 可能な接続元の指定。

@end multitable

@sp 1

@multitable @columnfractions .20 .35 .35
@item 命令 @tab 対象となる入力ストリームの種類 @tab デフォルト値

@item @code{FormatMode} @tab stdio/file/connect/ipc @tab lisp

@item @code{FormatIndent} @tab stdio/file/connect/ipc @tab 0

@item @code{Port} @tab connect/ipc @tab 9090

@item @code{MaxConnection} @tab connect/ipc @tab 10

@item @code{InputFileName} @tab file @tab なし。指定しないとエラー

@item @code{OutputFileName} @tab file @tab なし。指定しないと出力されない。

@item @code{MaxConnectionTime} @tab stdio/connect/ipc/file @tab 無限大(-1)

@item @code{MaxSilentTime} @tab stdio/connect/ipc/file @tab 無限大(-1)

@item @code{Environment} @tab stdio/connect/ipc/file @tab thisone

@item @code{HostName} @tab connect @tab HostName または IP のどちらかを指定しないとエラー 

@item @code{Result} @tab すべて。 @tab 1

@item @code{IP} @tab connect @tab HostName または IP のどちらかを指定しないとエラー 

@item @code{Permission} @tab connect @tab 全ての接続を拒絶

@end multitable

@sp 1

Permission はApplicative 関数であり、その指定方法は、以下の通りである。

@sp 1

@example
<Permission>
        <list> string-exp .... </list>
        <Allow/Deny> ... </Allow/Deny>
        ....
</Permission>
@end example

@sp 1

そしてAllow/Denyの指定方法は以下の通りである。Denyも同じである。

@enumerate
@item
<Allow>ip string-exp(ipアドレス) string-exp(ipアドレスマスク) </Allow>

@item
<Allow>domain string-exp</Allow>

@item
<Allow>all</Allow>
@end enumerate



@sp 1

ip で始まる物は、接続を許可するipアドレスを指定する。domainで始まる物は、接続を許可するdomainを指定する。allは全てを許可するという意味である。Denyは同様に拒絶するアドレスを指定する。

@sp 1

接続を要求するクライアントがあった場合、Permissionの第二引数より、順番にチェックしていき、初めてマッチした要素がAllowであれば、接続許可、Denyであれば、接続拒絶となる。接続が許可された場合は、使用可能な接続モードが最初のリストに指定されている接続モードである。

@sp 1

さらに、Permissionは複数指定することが出来る。クライアントから接続要求があると、始めに現れたPermissionからチェックし、最初にAllowとなったパーミッションの接続モードが使用可能な接続モードとなる。すべてのPermissionがDenyであると、接続拒絶である。

@primitiveEnd


@primitivea {CloseInterpreter,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(CloseInterpreter integer-exp)
@b{C関数宣言}
int xl_CloseInterpreter(int integer_exp);
@end example
@end cartouche

@sp 1

@primitiveMid
@code{integer-exp}で示されるインタプリタ識別子で示されるインタプリタを終了し、ストリームも解放する。

@primitiveEnd

@node GetSet関連関数, 制御関数, システム関数, プリミティブ
@comment  node-name,  next,  previous,  up
@section GetSet関連関数

@primitivea {Get,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(Get string-exp)
@b{XML型式}
<Get> string-exp </Get>
@end example
@end cartouche

@sp 1

@primitiveMid
Getの引数の仕様はエージェントごとに異なる。それぞれの定義はそれぞれのエージェント仕様を見ること。ここでは、標準のエージェントxlのGetの定義を述べる。

@sp 1

string-expで示されるURLのファイルの内容を返す。このファイルの拡張子は、 SetPrefixModeで定義されていなければならない。また、xldocsのファイルかxlsys のファイルかはSetPrefixModeの指定に従う。Getには、拡張しごとにアクセスするモードがある。たとえば、.jpgはrawモードでアクセスし、.xmlはxlモードでアクセスする。このモードのし亭もSetPrefixModeで行う。

@primitiveEnd

@primitivea {Set,Applicative Order / LEVEL: 0}
@primitiveMid
Setはエージェントごとに異なり標準が存在しない。各エージェントの説明を参照のこと。

@primitiveEnd

@primitivea {SetThisAgentName,Applicative Order / LEVEL: 1}

@cartouche
@example
@b{LISP型式}
(ThisAgentName string-exp)
@b{XML型式}
<ThisAgentName> string-exp </ThisAgentName>
@b{C言語宣言}
XLtype * xl_ThisAgentName(XLenv * ,XLtype *);
@end example
@end cartouche

@sp 1

@primitiveMid
string-expで示される名前を現在実行中のエージェントの名前とする。
@primitiveEnd

@primitivea {DatabasePath,Applicative Order / LEVEL: 1}

@cartouche
@example
@b{LISP型式}
(DatabasePath string-exp1 [string-exp2]
@b{XML型式}
<DatabasePath> string-exp1 [string-exp2] </DatabasePath>
@end example
@end cartouche

@sp 1

@primitiveMid
string-exp1で示されるパスをxldocsパスとし、string-exp2で示されるパスを xlsysパスとする。xlsysパスは省略可能。

@primitiveEnd

@primitivea {SetPrefixMode,Applicative Order / LEVEL: 1}

@cartouche
@example
@b{LISP型式}
([SetPrefixMode 
xldocs="precedence/only" xlsys="precedence/only" 
lock="part/full/off"]	 
prefix(string-exp) agent(string-exp) 
mode(string-exp) function(string-exp) .... )
@b{XML型式}
<SetPrefixMode 
xldocs="precedence/*only" 
xlsys="precedence/only" lock="part/full/*off">
prefix(string-exp) agent(string-exp) 
mode(string-exp) function(string-exp) .... 
</SetPrefixMode>
@end example
@end cartouche

@sp 1

@primitiveMid
PrefixMode を定義する。xldocs,xlsys は、それぞれのパスの参照の優先順位を指定する。 precedenceはそのパスを優先し、その後で他方を見るという意味。onlyはそのパスしか見ないということ。xldocs,xlsysを両方指定してはならない。lockはアクセス時にロックするかどうかを指定する。partは、Getに指定するURLのファイルパス部分をロックの名前としてロックする。fullはそのファイルへのフルパスでロックする。offはロックしない。

@sp 1

prefixはアクセス可能とするファイルの拡張子を指定する。拡張子はどっとから入れること。つまり、.jpg というように指定する。agentはその拡張子のファイルをゲット出来るエージェントの名前。modeはそのGetを実行するモード。標準のGetではxlとrawがある。functionは複数指定可能で、このファイルをアクセスできる関数を示す。通常はGetを指定する。

@sp 1

一つの拡張子に複数のエージェントが定義できる

@primitiveEnd

@primitivea {GetPrefixMode,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(GetPrefixMode prefix(string-exp))
@b{XML型式}
<GetPrefixMode> prefix(string-exp) </GetPrefixMode>
@end example
@end cartouche

@sp 1

@primitiveMid
設定されている拡張子モードを取り出す。戻り値は、エージェントごとのリストで以下の形式となる。

@sp 1

@example
((agent mode flag function ...) ...) 
@end example

@sp 1

agent mode function は上述SetPrefixModeで定義した値であり、flagは xldocs,xlsysなどの属性値をフラグ化した実数が入っている。一つの拡張子に対して複数のエージェントが定義できるので、このようにリストとなっている。 

@primitiveEnd

@node 制御関数, 環境操作関数, GetSet関連関数, プリミティブ
@comment  node-name,  next,  previous,  up
@section 制御関数

@primitivea {Eval,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(Eval exp exp)
@b{XML型式}
<Eval> exp exp </Eval>
@b{C関数宣言}
XLtype * cEval(XLenv * e, XLsturct * exp);
@end example
@end cartouche

@sp 1

@primitiveMid
環境変数と、もう一つ値を受け取り、その値を評価し、結果を返す。

@primitiveEnd

@primitivea {Lambda,Normal Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(1)
   ([Lambda Order="Normal"] (Arguments symbol ....) exp)
(2)
   ([Lambda Order="Applicative"] env-exp (Arguments symbol ....) exp)
(3)
   ([Lambda Order="Normal"] symbol exp)
(4)
   ([Lambda Order="Applicative"] env-exp symbol exp)
@end example
@end cartouche
@cartouche
@example
@b{XML型式}
(1)
   <Lambda Order="Normal">
           <Arguments>
                   ^symbol
                   ^symbol
                   ....
           </Arguments>
           exp
   </Lambda>

(2)
   <Lambda Order="Applicative">
           env-exp
           <Arguments>
                   ^symbol
                   ^symbol
                   ....
           </Arguments>
           exp
   </Lambda>

(3)
   <Lambda Order="Normal">
           ^symbol
           exp
   </Lambda>

(4)
   <Lambda Order="Applicative">
           env-exp
           ^symbol
           exp
   </Lambda>
@b{C関数宣言}
XLtype *
cLambda(char * order,XLtype * (*)());
(プリミティブ関数の定義用)
@end example
@end cartouche

@sp 1

@primitiveMid
評価順序(Order)には、引数の評価方法としてNormal か Applicative のいずれかを指定する。Normal の場合は引数はすべて評価されずに、そのまま関数に渡される。環境は新たに生成され、そこに引数、属性情報などが記憶される。 Applicative の場合は、引数はすべて評価され関数に渡される。関数はexpを評価し、その戻り値を関数の戻り値とする。引数の評価の時に使用する環境は、 env-expで指定される。env-exp = () とすると評価時のカレント環境で引数を評価する。

@sp 1

Lambdaの戻り値は関数である。この戻り値をEvalによって評価すると、まず、与えられた環境で、この関数の属性に従って引数を評価する。次に、与えられた環境を親に持つ環境を生成し、その環境に、シンボルリストで定義されたシンボルと先の値の対応を記憶し、この環境をもって、expを評価する。評価結果を、この関数の戻り値とする。

@sp 1

(1)の場合、引数の指定された順番と、Argumentのシンボルの順番を照らし合わせ、対応するシンボルに引数を対応させる。一方、(2)は関数呼び出し時の構造型全体をシンボルsymbolに対応させる。

@primitiveEnd

@primitivea {Define,Normal Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(1)
   (Define symbol exp)

(2)
   ([Define Order="Normal"] 
           symbol1
           (Argmnets symbol2 ....) 
           exp)

(3)
   ([Define Order="Applicative"] 
           symbol1 
           env-exp 
           (Argmnets symbol2 ....) 
           exp)

(4)
   ([Define Order="Normal"] 
           symbol1 symbol2 exp)

(5)
   ([Define Order="Applicative"] 
           symbol1 env-exp symbol2 exp)
@end example
@end cartouche
@cartouche
@example
@b{XML型式}
(1)
   <Define> ^symbol1 exp </Define>

(2)
   <Define Order="Normal">
           ^symbol1
           <Argmnets>
                   ^symbol2
                   ....
           </Argments>
           exp
   </Define>

(3)
   <Define Order="Applicative">
           ^symbol1
           env-exp
           <Argmnets>
                   ^symbol2
                   ....
           </Argments>
           exp
   </Define>

(4)
   <Define Order="Normal"> 
           ^symbol1
           ^symbol2
           exp
   </Define>

(5)
   <Define Order="Applicative"> 
           ^symbol1
           ^symbol2
           env-exp
           exp
   </Define>
@b{C関数宣言}
XLtype *
cDefine(XLenv * e,char * symbol,XLtype * exp);
@end example
@end cartouche

@sp 1

@primitiveMid
(1) はカレント環境において、symbol1と、expの評価結果を対応させる。もし、 symbolのエントリがすでにあった場合は、その値を書き換える。

@sp 1

(2)(3) は (Define symbol1 (Lambda (Argments ....) exp) の略記形。

@sp 1

(4)(5) は (Define symbol1(Lambda symbol exp) の略記形。 

@primitiveEnd


@primitivea {DeleteDefine,Normal Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(DeleteDefine symbol-exp)
@b{XML型式}
<DeleteDefine symbol-exp </DeleteDefine>
@end example
@end cartouche

@sp 1

@primitiveMid
与えられたシンボルをカレントディレクトリから削除する。

@primitiveEnd


@primitivea {MoveDefine,Normal Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(MoveDefine symbol-exp from-env to-env)
@b{XML型式}
<MoveDefine symbol-exp from-env to-env </MoveDefine>
@end example
@end cartouche

@sp 1

@primitiveMid
与えられたシンボルを環境from-envから環境to-envへ移動する。

@primitiveEnd


@primitivea {If,Normal Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(If exp (Then exp) (Else exp))
@b{XML型式}
<If>
        exp
        <Then> exp </Then>
        <Else> exp </Else>
</If>
@end example
@end cartouche

@sp 1

@primitiveMid
最初のexp を評価し、0だったら、の中のexpを評価し、その結果を、戻り値とする。0以外だったら、 の中のexpを評価し、その結果を戻り値とする。

@primitiveEnd

@primitivea {Switch,Normal Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(Switch
        (Case integer-exp(condition)
                exp ...)
        (Case integer-exp(condition)
                exp ...)
        ....
        )
@b{XML型式}
<Switch>
        <Case> integer-exp(condition)
                exp ...
        </Case>
        <Case> integer-exp(condition)
                exp ...
        </Case>
        ....
</Switch>
@end example
@end cartouche

@sp 1

@primitiveMid
最初のCase要素から順番に条件をチェックし最初に真になった要素のexpを評価し、最後のexpの評価の結果を返す。

@primitiveEnd


@primitivea {Sequence,Normal Order / LEVEL: 0}

@cartouche
@example
@b{LISP形式}
(Sequence exp ..)
@b{XML形式}
<Sequence>
        exp
        ..
</Sequence>
@end example
@end cartouche

@sp 1

@primitiveMid
現在のカレント環境を親環境とする新しい環境を生成し、それをカレント環境とする。そのカレント環境のもとで、expを順番に評価し、最後のexpの戻り値をSequenceの戻り値とする。途中でエラーが発生した場合は、その時点でそのエラーを戻り値とする。 

@primitiveEnd


@primitivea {For,Normal Order / LEVEL: 0}

@cartouche
@example
@b{LISP形式}
(For exp1 exp2)
@b{XML形式}
<For>
        exp1
        exp2
</For>
@end example
@end cartouche

@sp 1

@primitiveMid
exp1を最初に評価し、結果が0であれば、0を返す。結果が0以外であれば、exp2を評価し、もう一度exp1を評価する。exp1の評価が0以外になるまでこれを繰り返し、0以外になったときに一番最後のexp2の評価の値を戻り値とする。 

@primitiveEnd


@primitivea {While,Normal Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(While exp1 exp2)
@b{XML形式}
<While>
        exp1
        exp2
</While>
@end example
@end cartouche

@sp 1

@primitiveMid
Forと反対に、まず、exp2を評価する。その評価結果をいったん保存し、exp1を評価する。exp1の評価結果が0であれば、保存されたexp2の保存結果を戻り値として返す。もし、exp1の評価結果が0以外であれば、再びexp2を評価する。 

@primitiveEnd


@primitivea {Break,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(Break exp1)
@b{XML形式}
<Break>
        exp1
</Break>
@end example
@end cartouche

@sp 1

@primitiveMid
For,Whileの中で使用可能。この関数が実行されると、For,Whileは強制的に終了する。そのときの戻り値がexp1の評価結果となる。

@primitiveEnd


@primitivea {Continue,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(Continue)
@b{XML形式}
<Continue/>
@end example
@end cartouche

@sp 1

@primitiveMid
For,Whileの中で使用可能。この関数が実行されると、For,Whileはもう一度exp1を評価し直す。

@primitiveEnd

@node 環境操作関数, 構造型操作関数, 制御関数, プリミティブ
@comment  node-name,  next,  previous,  up
@section 環境操作関数

@primitivea {NewEnvironment,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(NewEnvironment env-exp)
@b{XML形式}
<NewEnvironment> env-exp env-exp</NewEnvironment>
@end example
@end cartouche

@sp 1

@primitiveMid
env-expを親環境ととした環境を生成する。

@primitiveEnd


@primitivea {GetParentEnvironment,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(GetParentEnvironment env-exp)
@b{XML形式}
<GetParentEnvironment> 
         env-exp 
</GetParentEnvironment>
@end example
@end cartouche

@sp 1

@primitiveMid
env-expの親環境を返す。親環境が無い場合は、()を返す。

@primitiveEnd


@primitivea {SetParentEnvironment,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP形式}
(SetParentEnvironment env-exp1 env-exp2)
@b{XML形式}
<SetParentEnvironment>
        env-exp
        env-exp
</SetParentEnvironment>
@b{C関数宣言}
int SetParentEnvironment
        (XLenv * env_exp1,XLenv * env_exp2);
@end example
@end cartouche

@sp 1

@primitiveMid
env-exp2をenv-exp1の親環境としてセットする。戻り値は()

@primitiveEnd


@primitivea {CurrentEnvironment,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP形式}
(CurrentEnvironment)
@b{XML形式}
<CurrentEnvironment/>
@end example
@end cartouche

@sp 1

@primitiveMid
現在のカレント環境を返す。

@primitiveEnd

@node 構造型操作関数, 算術演算関数, 環境操作関数, プリミティブ
@comment  node-name,  next,  previous,  up
@section 構造型操作関数


@primitivea {quote,Normal Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(quote exp)
@b{XML形式}
<quote> exp </quote>
@end example
@end cartouche

@sp 1

@primitiveMid
expを評価しないでそのまま返す。

@sp 1

ただし、expの中で($ exp) を発見した場合は、expを評価し、($ exp)のある位置に挿入した結果を返す。また、[symbol attr="$sym"] のように$から始まるアトリビュートを発見した場合は、symをシンボルとして評価し、その結果をアトリビュートに挿入する。

@primitiveEnd


@primitivea {GetElement,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP形式}
(1)
   (GetElement exp integer)
(2)
   (GetElement exp symbol)
@b{XML形式}
(1)
   <GetElement>
           exp
           integer
   </GetElement>
(2)
   <GetElement>
           exp
           ^symbol
   <GetElement>
@b{C関数宣言}
XLtype *
cGetElement(XLtype * exp,int integer);
@end example
@end cartouche

@sp 1

@primitiveMid
説明 (1)は、expで与えられた値が構造型であった場合、integer番目の要素を返す。(2)はsymbolで示される要素を検索し返す。

@primitiveEnd


@primitivea {Next,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP形式}
(Next exp)
@b{XML形式}
<Next>
        exp
</Next>
@b{C関数宣言}
XLtype * cNext(XLtype * exp);
@end example
@end cartouche

@sp 1

@primitiveMid
expで与えられた値が構造型であった場合、一番目の要素を除いた残りの構造型の値を返す。

@primitiveEnd


@primitivea {CutOut,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP形式}
(CutOut exp integer1 integer2)
@b{XML型式}
<CutOut>
        exp \
        integer1 \
        integer2
</CutOut>
@b{C関数宣言}
XLtype * CutOut(XLtype * exp,int integer1,int integer2);
@end example
@end cartouche

@sp 1

@primitiveMid
expで与えられた値が構造型であった場合、そのinteger1からinteger2番目の部分を切り出した構造型の値を返す。

@primitiveEnd


@primitivea {Append,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(Append exp1 exp2)
@b{XML型式}
<Append>
        exp1
        exp2
</Append>
@b{C関数宣言}
XLtype * cAppend(XLtype * exp1,XLtype * exp2);
@end example
@end cartouche

@sp 1

@primitiveMid
exp1 exp2で与えられた値が構造型であった場合、exp1とexp2をつなげた構造型の値を返す。

@sp 1

exp1とexp2の最初の要素がシンボルで、exp2のシンボルも属性情報を持っていたとすると、exp2の属性情報は、exp1の属性情報へ上書きされる。exp2のシンボルの属性情報は消える。

@sp 1

exp1の最初がシンボルでない場合は、exp2のシンボルの属性情報が消えるのみ。

@sp 1

exp1 exp2が構造型で無かった場合はtype missmatchエラーを返す。 

@primitiveEnd


@primitivea {List,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(List exp ....)
@b{XML型式}
<List>exp ....</List>
@b{C関数宣言}
XLtype * cList(XLtype * exp,...);
可変引数の最終点は、0ポインタとする。
@end example
@end cartouche

@sp 1

@primitiveMid
exp ....をこの順番で構造型に含めた値を返す。

@primitiveEnd



@primitivea {ListLength,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(ListLnegth exp)
@b{XML型式}
<ListLength>exp</ListLength>
@end example
@end cartouche

@sp 1

@primitiveMid
expが構造型であった場合、その要素の個数を返す。構造型でなかった場合は、-1 を返す。

@primitiveEnd


@primitivea {AttouchAttribute,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(AtouchAttribute exp1 string-exp2 string-exp3)
@b{XML型式}
<AttouchAttribute>
        exp1
        string-exp2
        string-exp3
</Append>
@b{C関数宣言}
XLtype * cAtouchAttribute(
        XLtype * exp1,
        char * string_exp2,
        char * string_exp3);
@end example
@end cartouche

@sp 1

@primitiveMid
exp1 が、構造型で最初の要素がシンボルであった場合、ここに、 string-exp2=string-exp3という属性情報を追加する。

@sp 1

string-exp2,string-exp3は文字列で無ければならないが、string-exp3=()のときには、string-exp2で示される属性情報を取り除くという意味に解釈される。 

@primitiveEnd


@primitivea {Sort,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(Sort data-exp func-exp)
@b{XML型式}
<Sort> struct-exp func-exp </Sort>
@end example
@end cartouche

@sp 1

@primitiveMid
struct-expの内容の順番を、ソートする。その大小関係はfunc-expによって決める。

@sp 1

@example
<func-exp> ^a ^b </func-exp> 
@end example

@sp 1

a,bにstruct-expを構成する一つ一つの要素が代入されたときに、

@sp 1

@example
a < b
@end example

@sp 1
ならば、 -1、
@sp 1

@example
a > b
@end example

@sp 1
ならば1を返し、
@sp 1

@example
a = b
@end example

@sp 1
ならば0を返すようにfunc-expを定義する。こうしたときに、Sortの結果は、小さい順にソートされる。

@primitiveEnd

@node 算術演算関数, 論理演算関数, 構造型操作関数, プリミティブ
@comment  node-name,  next,  previous,  up
@section 算術演算関数


@primitived {*,+,mul,add,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(* exp exp ....)
(+ exp exp ....)
@b{XML型式}
<mul>
        exp
        exp
        ....
</mul>
<add>
        exp
        exp
        ....
</add>
@end example
@end cartouche

@sp 1

@primitiveMid
*,+はXMLのタグの中で使うことが出来ないので、mul addを全く同じ関数として定義している。

@sp 1

*はかけ算、+は足し算を引数要素のexpに対して施し、結果を返す。expとして、取ることの出来る型は、Integer,FloatingPointである。+に関してはString も取ることが出来る。

@sp 1

IntegerとFloatingPointが混在していると、まずは、IntegerをFloatingPointにキャストしてから演算を行う。+の場合、全てがStringであれば、それを引数の順番でつなぎ合わせた物を戻り値とする。

@primitiveEnd


@primitivef {/,%,-,div,rem,sub,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(- exp1 exp2)
(/ exp1 exp2)
(% exp1 exp2)
@b{XML型式}
<sub> exp1 exp2 </sub>
<div> exp1 exp2 </div>
<rem> exp1 exp2 </rem>
@end example
@end cartouche

@sp 1

@primitiveMid
説明 引き算、わり算、わり算の余り。exp1からexp2を引く（割る、余りを求める）。ただし、/,-についてはString型は扱えない。%については整数型のみ。

@primitiveEnd


@primitivec {and,or,xor,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(and exp1 exp2 ....)
(or exp1 exp2 ....)
(xor exp1 exp2 ....)
@b{XML型式}
<and> exp1 exp2 ....</and>
<or> exp1 exp2 ....</or>
<xor> exp1 exp2 ....</xor>
@end example
@end cartouche

@sp 1

@primitiveMid
exp1 exp2 は整数で、これらのビットごとのand,or,xor を取って戻り値とする。

@primitiveEnd

@primitivea {not,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(not exp)
@b{XML型式}
<not> exp1 </not>
@end example
@end cartouche

@sp 1

@primitiveMid
expが整数のとき、これのビットごとのnot を取って戻り値とする。

@primitiveEnd

@node 論理演算関数, ネットワーク関数, 算術演算関数, プリミティブ
@comment  node-name,  next,  previous,  up
@section 論理演算関数

@primitivec {And,Or,Xor,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(And exp1 exp2 ....)
(Or exp1 exp2 ....)
(Xor exp1 exp2 ....)
@b{XML型式}
<And> exp1 exp2 ....</And>
<Or> exp1 exp2 ....</Or>
<Xor> exp1 exp2 ....</Xor>
@end example
@end cartouche

@sp 1

@primitiveMid
exp1 exp2 ....のAnd,Or,Xor を取って戻り値とする。真偽値は、Integerまたは FloatingPoint型で、0が偽、それ以外は真と解釈する。

@primitiveEnd


@primitivea {Not,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(Not exp)
@b{XML型式}
<Not> exp1 </Not>
@end example
@end cartouche

@sp 1

@primitiveMid
expのNot を取って戻り値とする。真偽値は、IntegerまたはFloatingPoint型で、 0が偽、それ以外は真と解釈する。 

@primitiveEnd


@primitiveg {=,Equ,Neq,Lt,Gt,Lteq,Gteq,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(= exp1 exp2)
(Equ exp1 exp2)
(Neq exp1 exp2)
(Lt exp1 exp2)
(Gt exp1 exp2)
(Lteq exp1 exp2)
(Gteq exp1 exp2)
@b{XML型式}
<Equ> exp1 exp2</Equ>
<Neq> exp1 exp2</Neq>
<Lt> exp1 exp2</Lt>
<Gt> exp1 exp2</Gt>
<Lteq> exp1 exp2</Lteq>
<Gteq> exp1 exp2</Gteq>
@b{C関数宣言}
int cEqu(XLtype * exp1,XLtype * exp2);
@end example
@end cartouche

@sp 1

@primitiveMid
exp1とexp2が等しければ0,exp1 > exp2 ならば1、その他ならば-1
を返す。大小が分からないが、等しくない場合は-2を返す。

@sp 1

exp1 exp2の比較を取って戻り値とする。真偽値は、Integerで、0が偽、それ以外は真と解釈する。

@sp 1

@multitable @columnfractions .20 .40
@item @code{=,Equ}
@tab
等しくないとき真
@item @code{Neq}
@tab
等しくないとき真
@item @code{Lt}
@tab
小なり。exp1が小さいとき真
@item @code{Gt}
@tab
大なり。exp1が大きいとき真
@item @code{Lteq}
@tab
(Or (= exp1 exp2) (Lt exp1 exp2)) と等価
@item @code{Gteq}
@tab
(Or (= exp1 exp2) (Gt exp1 exp2)) と等価
@end multitable

@primitiveEnd


@node ネットワーク関数, セッション管理関数, 論理演算関数, プリミティブ
@comment  node-name,  next,  previous,  up
@section ネットワーク関数

@primitivea {SetAgent,Applicative Order / LEVEL: 1 サーバーのみの特殊関数 }

@cartouche
@example
@b{LISP型式}
(1)
   (SetAgent string-exp)
(2)
   (SetAgent string-exp (User string-exp) (Passwd string-exp))
@b{XML形式}
(1)
   <SetAgent> string-exp </SetAgent>
(2)
   <SetAgent> string-exp
           <User> string-exp </User>
           <Passwd> string-exp </Passwd>
   </SetAgent>
@b{C関数宣言}
int cSetAgent(char * string_exp,char * user,char * passwd);
@end example
@end cartouche

@sp 1

@primitiveMid
string-exp で示される、URL のデータベースを呼び出す。成功するとデータベースのアクセス権が戻る。"read" "write" "root"　その他。

@primitiveEnd


@primitivea {Sync,Applicative Order / LEVEL: 0 サーバのみの特殊関数}

@cartouche
@example
@b{LISP型式}
([Sync type="on/off"])
@b{XML型式}
<Sync type="on/off"/>
@end example
@end cartouche

@sp 1

@primitiveMid
サーバがSetAgentエージェントを起動するときに、一時的にコネクションがサーバ側とエージェント側の両方が保持している状態が生じる。この時にクライアント側がコマンドを送り込むと、両方が取り合い、両方が返事する可能性があり、混乱を招く。そのため、SetAgentの実行の中で、クライアントに次の命令を送らないように同期をとるキャラクタを送る処理を行っている。この処理をonするかoffするかを指定する。デフォルトはonである。

@sp 1

ところが、この処理は、特殊なエスケープコードを使っているので、クライアントとしてtelnetで接続した場合は、逆に文字化けを起こしてしまう。これを防ぐために、telnet接続時はSetAgentを実行する前にこのを実行する必要がある。 

@primitiveEnd


@primitivea {Remote,Normal Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(Remote integer-exp exp)
@b{XML型式}
<Remote>
        integer-exp
        exp
</Remote>
@b{C関数宣言}
XLtype * cRemote(int integer_exp,XLtype * exp);
@end example
@end cartouche

@sp 1

@primitiveMid
integer-expはConnectで得られた識別子。Integer-expは先に評価される。識別子の示すコネクション先に、expをそのまま送信する。expは先方のインタープリタで評価され、結果が<Result>で返される。その結果値(Resultを参照)をRemote の戻り値とする。

@primitiveEnd


@primitivea {Local,Normal Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(Local exp)
@b{XML型式}
<Local> exp </Local>
@b{C関数宣言}
XLtype * cLocal(XLtype * exp);
@end example
@end cartouche

@sp 1

@primitiveMid
どこからかのコネクション先でこの関数が評価されたとき、expをコネクションもとのインタープリタへ送り、コネクションもとの環境で評価する。評価結果はコネクション先へ<Result>を使って送り返される。Resultの結果値がLocalの戻り値となる。 

@primitiveEnd


@primitivea {Result,Normal Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(Result integer-exp exp)
@b{XML型式}
<Result> integer-exp exp</Result>
@b{C関数宣言}
int cResult(int integer_exp,XLtype * exp);
@end example
@end cartouche

@sp 1

@primitiveMid
標準入力、あるは、ネットワークから入力など入力ストリームから入力された関数の評価結果をResultで返す。integer-expは入力ストリームに送り込まれた関数の先頭の行番号、expは評価結果、これを結果値と呼ぶ。

@sp 1

入力ストリームから15行目に、

@sp 1

@example
<If> (= a b)
        <Then>  .... </Then>
        <Else>  .... </Else>
</If>
@end example

@sp 1

これに対応するResultの第2引数のinteger-exp は15となる。 expは関数の評価結果である。

@sp 1

たとえば、上述Ifの戻り値は次のように表現される。

@sp 1

@example
<Result>15
        (1.2 3)
</Result>
@end example

@sp 1

二つのインタープリタがつながっており、一方のストリーム出力が片方のストリーム入力となっている場合は、<Result>を受けたインタープリタはこれを評価する。<Result>を受けるインタープリタは、自身の出力ストリームに向かって以前に関数を送り込んだインタプリタを検索する。（上記の例では<If>[[>を発行したインタプリタ）検索されたインタプリタは、 <![CDATA[<Remote>や<Local>を発行し、結果待ちの状態になっているはずである。 Resultはinteger-exp(評価しない) に対応するRemote/Local を探しだし、その Remote/Localへ結果値を受け渡し、結果待ちのインタプリタを起こす。

@sp 1

<Result>の評価結果は常に@code{ErrDonPrint}。また、 <Result>を評価するインタプリタがなにかを評価していて、ビジーの状態である場合もあるので、現在のインプリメントでは、フロントスレッドが、 Resultだけ特別に評価するという仕組みになっている。 

@primitiveEnd


@primitivea {Cancel,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(Cancel)
@b{XML型式}
<Cancel/>
@b{C関数宣言}
int cCancel(int integer_exp,XLtype * exp);
@end example
@end cartouche

@sp 1

@primitiveMid
この命令をあるインタプリタの入力ストリームへ送り込むと、現在そのインタプリタが実行している関数を即座に終了し、キャンセルエラーを返す。

@primitiveEnd


@primitivea {GetLocalHostName,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(GetLocalHostName)
@b{XML型式}
<GetLocalHostName/>
@end example
@end cartouche

@sp 1

@primitiveMid
実行中のエージェントの動作しているローカルホストの名前を返す。

@primitiveEnd


@primitivea {GetLocalHostIP,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(GetLocalHostIP)
@b{XML型式}
<GetLocalHostIP/>
@end example
@end cartouche

@sp 1

@primitiveMid
実行中のエージェントの動作しているローカルホストのIPを返す。

@primitiveEnd

@node セッション管理関数, サーバ・認証命令, ネットワーク関数, プリミティブ
@comment  node-name,  next,  previous,  up
@section セッション管理関数


@primitivea {OpenSession,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(OpenSession)
@b{XML型式}
<OpenSession/>
@end example
@end cartouche

@sp 1

@primitiveMid
セッションを開き、そのセッションIDを返す。

@sp 1

セッションとは、与えられたいくつかのURL,URIに従って、複数のXLサーバにコネクションし、エージェントを駆動し、データをGetしたりSetしたり、またはその他のコマンドを発行する一連の作業を言う。

@sp 1

たとえば、URLを与え、そのファイルをGetするためには、まず、URLを分解し、コネクションすべきサーバを特定する。このサーバに接続し、まずは、 @code{GetPrefixMode}を発行し、URLの拡張子に対する駆動すべきエージェントを特定する。得られたエージェントを@code{SetAgent}によって駆動する。そして、最後に@code{Get}を発行しファイルを得る。

@sp 1

一度駆動されたエージェントはタイムリミットの中で何回も使えるので、@code{Get}したい別のファイルが同じエージェントの条件を備えて入ればこのエージェントへコマンドを送ることによってゲットできる。

@sp 1

セッション管理はこのようなエージェント共有、タイムアウトで一度切れてしまったコネクションの復活など、煩雑な作業を透明化するものである。

@code{OpenSession}によって、一つのセッションを開き@code{RemoteSession}によって、いろいろな　URL,URIに接続し、この@code{RemoteSession}に与えたコマンドを対応するエージェントに送り込む。同一セッションで、@code{RemoteSession}はURL,URIを変更して何度も発行できる。最後に@code{CloseSession}でセッションを閉じる。

@sp 1

同一のサイトの同一のエージェントを示すURL,URIの要求が会った場合は、このエージェントを共有することになる。異なるセッションであっても共有される。

@primitiveEnd


@primitivea {RemoteSession,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(RemoteSession integer-exp [option-command ... ] exp ....)

option-command =
(URL string-exp)
(Command string-exp)
(Agent string-exp)
(LoginType string-exp)
@b{XML形式}
<RemoteSession> integer-exp
        [option-command ....]
        exp ....
</RemoteSession>

option-command =
<URL> string-exp </URL>
<Command> string-exp </Command>
<Agent> string-exp </Agent>
<LoginType> string-exp </LoginType>
@end example
@end cartouche

@sp 1

@primitiveMid
指定されたURLに指定された@code{Command}を使うという前提で接続し、エージェント上げる。すでに接続されている場合は、そのエージェントを使う。URLは省略不可能。 @code{Command}は省略するとGetとなる。@code{Agent}は接続するエージェントを明示的に指定するために使う。@code{LoginType}は@code{LoginType}を指定する。省略するとuserとなる。

@sp 1

URLに相対パスを指定すると、前回の@code{RemoteSession}で指定したURLからの相対パスとなる。前回の@code{RemoteSession}が無い場合はエラーである。この前回から引き継がれるパスを@code{Session}の環境パスと呼ぶ。

@sp 1

@code{RemoteSession}は、URLの実際にアクセスする先の絶対パスをカレント環境の@code{SessionPath}に、アクセスする先のファイル名を@code{SessionResource}に文字列型のデータとして記録する。 

@primitiveEnd


@primitivea {ForkSession,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(ForkSession integer-exp)
@b{XML型式}
<ForkSession> integer-exp </ForkSession>
@end example
@end cartouche

@sp 1

@primitiveMid
integer-expで指定されたセッションと同じ環境パスを引継、別のセッションを開き、そのIDを返す。

@primitiveEnd


@primitivea {CloseSession,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(CloseSession integer-exp)
@b{XML型式}
<CloseSession> integer-exp </CloseSession>
@end example
@end cartouche

@sp 1

@primitiveMid
セッションを閉じる。

@primitiveEnd


@node サーバ・認証命令, 文字列操作関数, セッション管理関数, プリミティブ
@comment  node-name,  next,  previous,  up
@section サーバ・認証命令

@primitivea {GetUserInfo,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(GetUserInfo
        string-exp(group)
        string-exp(login mode)
        "user"または"passwd")
@b{XML型式}
<GetUserInfo>
        string-exp(group)
        string-exp(login mode)
        "user"または"passwd"
</GetUserInfo>
@end example
@end cartouche

@sp 1

@primitiveMid
サーバの@code{SetAgent}を呼び出すと、サーバはクライアントから求められているエージェントを駆動するのにどの様な認証が必要かを判定する。認証が必要と認められたときに、サーバは、クライアント側に@code{GetUserInfo}を使用してuser名と、パスワードを求める。

@sp 1

必要な認証は@code{SetAgent}を受けたサーバに直接に接続をかけてきたサーバの認証ではなく、カスケードを介して、このサーバに接続をかけてきたおおもとのエージェントの認証である。そこで@code{GetUserInfo}を受け取ったエージェントのメインインタプリタの入力ストリームがソケットの場合は、このソケットへ@code{GetUserInfo}をリレーする。この場合@code{GetUserInfo}は@code{Result}などと同様にフロント・スレッドで処理され、これの定義を変更することは出来ない。一方、@code{GetUserInfo}を受け取ったエージェントのメインインタプリタの入力ストリームがソケット以外である場合、このエージェントはルート・エージェントであると見なされ、ここで、ユーザ定義の@code{GetUserInfo}が呼び出される。

@sp 1

@code{GetUserInfo}には、user名、パスワードの指定ともに、group、 login mode の組が渡される。login mode は@code{SetAgent}に渡されたものである。一方、group はagent名と login modeからサーバのデータベースより検索された、ユーザ名、パスワードの有効範囲となるグループ名を表す。

@sp 1

エージェントひとつひとつに、ユーザを定義するのではなく、あるまとまったエージェントのグループにユーザを定義し、認証するときに役に立つ。たとえば、nichibun.ac.jpと group を定義し、このドメイン内のエージェントには同じユーザを定義するという形で用いる。 

@primitiveEnd


@primitivea {Permission,Applicative Order / LEVEL: -} 

@cartouche
@example
@b{LISP型式}
(Permission string-exp)
@b{XML型式}
<Permission> string-exp </Permission>
@end example
@end cartouche

@sp 1

@primitiveMid
サーバにコネクションがはられたときに、サーバ側からクライアント側へまず最初に、この要素が送られる。

@sp 1

string-exp = "Allow" のときには、ネットワークアドレスの認証に成功し、接続が成立したことを示す。

@sp 1

string-exp = "Deny" のときは、ネットワークアドレスの認証に失敗し、接続が失敗したことを示す。直後にソケットは切断される。

@sp 1

クライアントはこの情報を@code{OpenInterpreter}へ返す。成功時には、@code{OpenInterpreter}はIIDを返し、失敗の時には、Permission Denied のエラーを返す。


@primitiveEnd


@primitivea {Agent,Applicative Order / LEVEL: 1}

@cartouche
@example
@b{LISP型式}
([Agent passwd="required/anonymous" dircheck="on/off"]
        string-exp(group)
        string-exp(agent)
        string-exp(login mode)
        env-exp
        func-exp)
@b{XML型式}
<Agent passwd="required/anonymous" dircheck="on/off">
        string-exp(group)
        string-exp(agent)
        string-exp(login mode)
        env-exp
        func-exp
</Agent>
@end example
@end cartouche

@sp 1

@primitiveMid
サーバのみで使用可能な命令。@code{SetAgent}によって認証、駆動されるエージェントの情報を設定する。

@sp 1

エージェントのホストパスと、エージェント名、ログインモードを指定し、駆動時の環境と駆動方法を示した関数を指定する。

@sp 1

フィールド指定のpasswdはパスワードが必要か否かを指定する。requiredを指定すると、必要であるという意味になる。anonymousは必要ないことを示す。デフォルトはrequired である。dircheckをonにすると、agentはディレクトリ名あるいは、パス名であると見なし、認証時に、親ディレクトリを参照したり、見えないディレクトリを参照するなどの不正参照がないかをチェックする機能をONにする。

@sp 1

func-exp()に指定されている状態で認証に成功すると、@code{SetAgent}を含むルート要素の実行終了時に、カレントディレクトリをenv-expへ変更する。func-expに関数が指定されている状態で認証に成功すると、env-expをカレント環境としてfunc-expが実行される。

@sp 1

func-expの引数は、(func-exp group agent login-mode user) という形で、いずれも文字列型である。


@primitiveEnd


@primitivea {Account,Applicative Order / LEVEL: 1}

@cartouche
@example
@b{LISP型式}
(Account
        string-exp(group)
        string-exp(login mode)
        string-exp(user)
        string-exp(passwd) )
@b{XML型式}
<Account>
        string-exp(group)
        string-exp(login mode)
        string-exp(user)
        string-exp(passwd)
</Account>
@end example
@end cartouche

@sp 1

@primitiveMid
サーバのみで使用可能な命令。@code{SetAgent}によってエージェントを駆動可能なユーザとパスワードを指定する。パスワード名、ユーザ名は、group ごとに定義することが出来る。 

@primitiveEnd


@node 文字列操作関数, ロックサーバー命令, サーバ・認証命令, プリミティブ
@comment  node-name,  next,  previous,  up
@section 文字列操作関数

@primitivea {Parse,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(Parse string-exp)
@b{XML型式}
<Parse>
        string-exp
</Parse>
@b{C関数宣言}
XLtype * cParse(char * string_exp);
@end example
@end cartouche

@sp 1

@primitiveMid
string-expで与えられた文字列を構造型に置き換える。

@primitiveEnd


@primitivea {Print,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(Print exp)
@b{XML形式}
<Print>
        exp
</Print>
@b{C関数宣言}
int cPrint(XLtype * exp);
@end example
@end cartouche

@sp 1

@primitiveMid
expで与えられる構造型を文字列に変換する。

@primitiveEnd


@primitivea {CutString,Applicative Order / LEVEL: 0} 

@cartouche
@example
@b{LISP型式}
(CutString string-exp integer-exp1 integer-exp2)
@b{XML型式}
<CutString>
        string-exp
</CutString>
@end example
@end cartouche

@sp 1

@primitiveMid
string-expで与えられる文字列のinteger-exp1文字目からinteger-exp2文字を切り出す。ただし、文字列の先頭の文字は0文字目と数える。integer-exp1 + integer-exp2が文字列の長さより長い場合は、存在している文字数のところまでの文字列を返す。

@primitiveEnd


@primitivea {StringLength,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(StringLength string-exp)
@b{XML型式}
<StringLength>
        string-exp
</StringLength>
@end example
@end cartouche

@sp 1

@primitiveMid
string-expで与えられた文字列の長さを返す。

@primitiveEnd


@primitivea {GetChar,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(GetChar string-exp integer-exp)
@b{XML型式}
<GetChar>
        string-exp integer-exp
</GetChar>
@end example
@end cartouche

@sp 1

@primitiveMid
string-expで与えられた文字列のinteger-exp番目の内部文字コードを返す。 

@primitiveEnd


@primitivea {SetChar,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(SetChar integer-exp)
@b{XML型式}
<SetChar>
        integer-exp
</SetChar>
@end example
@end cartouche

@sp 1

@primitiveMid
intrger-expで与えられた文字コードの文字一字からなる文字列を返す。

@primitiveEnd


@primitivea {DivideString,Applicative Order / LEVEL: 0} 

@cartouche
@example
@b{LISP型式}
(DivideString exp string-exp)
@b{XML型式}
<DivideString>
        exp string-exp
</DivideString>
@end example
@end cartouche

@sp 1

@primitiveMid
expの中に存在する文字列をstring-expを区切りとして分解する。分解された文字列はリストにして、文字列のあった位置に埋め込む。以下の例参照。

@sp 1

@example
<DivideString> 
(quote ("abcdEFghij" (("123EF5EF" "zxcEFiii") "jofEFrEFddd" "dfgh"))) 
</DivideString> 
@end example

@sp 1

の結果は、

@sp 1

@example
(("abcd" "ghij") ((("123" "5 "") ("zxc" "iii")) ("jof" "r" "ddd") ("dfgh"))) 
@end example

@primitiveEnd


@node ロックサーバー命令,  , 文字列操作関数, プリミティブ
@comment  node-name,  next,  previous,  up
@section ロックサーバー命令
(ロックサーバーのみ)

@primitivea {Lock,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(Lock string-exp)
@b{XML型式}
<Lock type="read/write"> string-exp </Lock>
@end example
@end cartouche

@sp 1

@primitiveMid
string-expを名前とするロックを生成し、ロックする。すでに、コマンドを発行したコネクションによってLockされている場合は、ロックのカウントを1増やす。

@sp 1

すでに他のコネクションによってロックされている場合は、そのコネクションとこのコネクションが両方ともtype="read"でロックしている場合以外は、このコネクションの@code{Lock}関数の処理はロックされる。ロックしているコネクションが@code{Unlock}を発行した時点で処理が先にすすむ。

@sp 1

ロックしているコネクションが切れると自動的にロックは解除される。

@sp 1

ロックサーバへのアクセスは、同一サイト内からのみに限定することを奨励する。なぜならば、ロックしているコネクションが、物理レイヤ、ネットワーク・レイヤで接続が切れた場合、TCPコネクションは永遠に残ることになり、ロックされ続けることになる。これを解消するために、サーバへの接続のタイムリミットを設定することも出来るが、こんどは、ロックが勝手に解除されるおそれがある。この問題はネットワークを介する以上避けられない問題である。 

@primitiveEnd



@primitivea {Unlock,Applicative Order / LEVEL: 0}

@cartouche
@example
@b{LISP型式}
(Unlock string-exp)
@b{XML型式}
<Unlock type="read/write"> string-exp </Unlock>
@end example
@end cartouche

@sp 1

@primitiveMid
ロックを解放する。複数回ロックしている場合は、その数だけUnlockを発行する必要がある。

@primitiveEnd
