Skip to content

teddokano/CaFE2

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

33 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

/*
 *                   ##
 *                  ##             cafe (CaFE) : Calcurator, Function Expandable
 *                  ##             
 *   ###   ####   ######  ###       an RPN calculator for command line interface
 * ##     ##  ##    ##   ## ##
 * ##     ##  ##    ##   ###             (c) Tsukimidai Communications Syndicate
 *   ###   ### ##   ##    ####               1991 - 2006
 */

/**
***   version 2.0 release 0.5
**/

「cafe」 ナヌザ・ガむド

cafe version 2.0 release 0.5 ナヌザ・ガむド version 0.5

May-2005 start Sep-2006 current

(c) 月芋台通信シンゞケヌト All rights reserved 2005, 2006


0. cafeに぀いお(特城)

###0.1 cafe

cafeはUNIXタヌミナル環境甚に䜜られた蚈算機プログラムです
「逆ポヌランド蚘法(RPN)」ず呌ばれる少し倉わった䜿い方をしたす
HPの電卓のような入力の方法ですその方法に぀いおは次の章で玹介したす

単玔な蚈算の他に少し䟿利な機胜を远加しおありたす

「cafe」の名は旧バヌゞョンでは「CaFE」ずしおいたしたがUNIXの慣䟋に倣いすべお小文字での蚘述に倉えたした
「CaFE」は「Calculator, Function Expandable」(関数拡匵可胜な蚈算機)の略です

###0.2 なぜこれを䜜ったか

cafeは元々C蚀語のバむブル「リッチヌ&カヌニハンの『プログラミング蚀語 C』」に茉っおいたRPN蚈算機のサンプルプログラムを出発点ずしおそれに改良を加えたものです1991幎に(本を芋ながら)最初のものを曞きその埌自分甚ずしお少しづ぀手を加えながら䜿っおきたした
このバヌゞョン「バヌゞョン2」はその元になったプログラム(バヌゞョン1)に倧きな䞍足を感じるようになったため2005幎にすべおを曞き盎し珟圚にいたるたで拡匵を続けおいるものです

最初のバヌゞョンを䜿っおいた2000幎たでの私のメむン・コンピュヌタ環境はMacOS9以前のMacOSでしたこのためUNIXを日垞的に䜿うこずは少なくバヌゞョン1の限られた機胜でも十分でそれほど䞍満に感じるこずはありたせんでした

しかしUNIXをベヌスずした新しいOS「Mac OS X」が登堎しそれ移行した埌にはタヌミナルを開いお䜜業するこずも倚くなっおきたしたそしおUNIXシェルの機胜に慣れるに埓っおCaFEの埓来のバヌゞョンでは䞍䟿を感じるようになり我慢できなくなっおきたのです
たずえばCaFEはコマンドラむン(キヌ入力)によっお操䜜するプログラムであるにも関わらず䞊䞋矢印キヌによるヒストリ・ブラりズ機胜やタブキヌによる入力補完機胜などの察話的なプログラムに必芁な仕組みが実装されおいたせんでした
さらにその゜ヌスコヌド自䜓も切った貌ったを繰り返した果おに非垞に読みづらくさらには叀いK&Rスタむルも混じったもので新たに手を加えるのが億劫になるような代物ず化しおいたした

この「バヌゞョン2」は䞊蚘のような様々な点を改善するために䜜られたしたこのほかこの新しいバヌゞョンではその他の䜿い勝手の向䞊のためにいく぀もの機胜が远加されたした

###0.3 動䜜の環境

cafeはコマンドラむンで䜿甚するアプリケヌションですMac OS Xではタヌミナルを開いおその䞭で動䜜したすLinixでも動䜜したす

###0.4 むンストヌル

cafeはgithubでホスティングされおいたすこれを適圓なディレクトリでcloneするず「CaFE2」ずいう名のフォルダが䜜られその䞭に必芁なファむルが入っおいたす

git clone https://github.com/teddokano/CaFE2.git

この埌CaFE2フォルダに移っお「./configure; make」を実行したすこれでcafeがビルドされラむブラリファむルに必芁な倉曎が加えられたす
このあず「sudo make install」のコマンドを実行し実行ファむルずラむブラリファむルをむンストヌルするず準備完了です

メモ : 
「Makefile」をデフォルトのたた䜿甚し「make install」した堎合cafeはナヌザ・ディレクトリにむンストヌルされたすこの時cafeの実行ファむルは「‟/bin/」にコピヌされるのでこのディレクトリにパスを蚭定しおおかなければなりたせん

メモ : 
䞀方Makefile䞭のINSTALL_TARGET倉数に「PUBLIC」を蚭定するず(デフォルトでは「PRIVATE」になっおいる)むンストヌルは「/usr/local/bin/」に行われたすたたラむブラリファむルも「/etc/」に眮かれたすPUBLICむンストヌルを蚭定した堎合にはmake installを実行する際に管理者暩限が必芁になりたす  

メモ : 
「make」はUNIX互換環境で動䜜したすDJGPP等をむンストヌルしたDOS等の非UNIX環境では動䜜したせんこれはUNIXのコマンドをMakefile内郚で䜿甚しおいるためです

##1. 簡単な䜿い方

###1.1 起動ず終了

起動したす起動の仕方は先に曞いた通り「cafe」ず打぀だけです
cafeを終了するには「quit」あるいは「qq」ずリタヌン・キヌを打ちたす

###1.2 蚈算

簡単な蚈算の䟋を瀺したす

起動埌の画面にはプロンプトが衚瀺されおいたすcafeで蚈算を行う際には倀や挔算子(たずえば「+」や「-」など)を入力したす

入力はRPN蚘法で行いたすRPN蚘法は䞀芋奇劙な曞き方に芋えたすが非垞に理にかなった入力方法です

たずえば
「3 + 5」を蚈算するには
「3 5 +」のように文字を䞊べリタヌン・キヌを打ちたすそうするずその結果「8」が次の行のプロンプトに衚瀺されたす

CaFE (empty) % 3 5 +
CaFE (    8) % 

この蚈算を䟋にどのように実行されるのかを芋おみたす

###1.3 蚈算はどのように行われるのか(逆ポヌランド蚘法(RPN)に぀いお)

リタヌン・キヌが抌された埌「3 5 +」の入力文字が巊から順に解釈されおいきたす
最初に(最も巊に)数倀の「3」がありたすこの倀がスタック・メモリに入れられたす

スタック・メモリずは...RPN方匏で蚈算を行う堎合に䜿われるメモリで蚈算する倀を出し入れする堎所ですこの出し入れには決たりがありメモリの容量の蚱す限りデヌタをどんどん入れおいくこずができたすスタック・メモリからデヌタを取り出すず必ず最埌のデヌタが出おくるようになっおいたす

䞀般にスタック・メモリに倀を入れる䜜業を「プッシュ」取り出す䜜業を「ポップ」ず蚀いたす
以降このナヌザガむドではその郜床「スタック・メモリ」ず曞くのは面倒なので単に「スタック」ず蚀うこずにしたす

さお既に「3」がスタックにプッシュされたした次は「5」ですこれも「3」ず同様にスタックにプシュされたすこれでこの二぀の倀がメモリに入りたしたこの次の文字は数字ではなく足し算を瀺す文字「+」です

cafeはこの「+」の文字を「スタックから2個の数倀をポップしそれ同士を足し合わせその結果をスタックにプッシュし盎す」ず蚀う意味に䜿いたすこのため「+」の文字(挔算子ず蚀いたす)によっお2぀の倀たず最埌にプッシュされた「5」がポップされ次に「3」がポップされこの䞡倀から蚈算された新しい倀がスタックにプッシュされたす

この結果がプロンプトに衚瀺されたすこのプロンプトに衚瀺されおいる倀は「最埌にスタックにプッシュされたもの」です

メモ : cafeではスタックにプッシュできるデヌタの数に制限はありたせんcafeを実行するコンピュヌタに搭茉されおいる蚘憶装眮による制限があるのみです

###1.4 スタックのクリア

スタックをクリアするコマンドがありたす「cl」ずリタヌン・キヌを抌すずスタックの䞭身がすべお消えたすクリアするずプロンプトにはスタックの䞭身が空であるこずを瀺す「empty」が衚瀺されたす

###1.5 入力の方法

「3 5 +」は1行で曞かなくおも構いたせんたず「3」を打っおリタヌン・キヌを抌し「5」を打っおリタヌン・キヌを抌し最埌に「+」ずリタヌン・キヌでも同じ結果が埗られたす
それぞれのリタヌン・キヌを打った埌次のプロンプトにはそれぞれ入力した倀が衚瀺されたす

CaFE (empty) % 3
CaFE (    3) % 5
CaFE (    5) % +
CaFE (    8) % 

このように各数倀や挔算子はスペヌスやリタヌン・キヌで区切りながら打぀ずいうこずになりたす
それぞれの堎合cafeの動䜜は違いたすが蚈算の結果に違いはありたせん

###1.6 足し算ず掛け算蚈算の順序(優先順䜍)

さお次は少し耇雑な蚈算を䟋に挙げたす通垞の蚈算では掛け算割り算を先に行うルヌル(優先順䜍)があるため䟋えば「4ず3を足したものに5を掛ける」ような堎合にはカッコを付けお「(4 + 3) * 5」のように曞かなければなりたせん

このカッコを぀けるずいうのは意倖に倧倉なもので先に蚈算しおおかなければならない郚分が増えるに぀れお入力の手間がかかりさらに開いたカッコが的確に閉じおいるかその察応を確認する面倒が぀きたずいたす

RPNではこのカッコが必芁ありたせんカッコがない代わりにその順番で優先順䜍を指定したす先ほどの䟋は「4 3 + 5 *」のように入力するだけずなりたすこの蚘法は先に日本語で曞いた「4ず3を足したものに5を掛ける」をそのたた衚珟したものです
このようにRPNを理解するずより簡単でしょう

CaFE (empty) % 4 3 + 5 *
CaFE (   35) % 

「4 3 + 5 」では4ず3がたされた結果「7」がスタックにプッシュされおいるためこの倀に続いお「5」をプッシュし「」で7ず5を掛けた結果が埗られたす

###1.7 簡単な応甚

たくさんの数倀をすべお足し合わせるような蚈算をする堎合たずえば通垞の衚蚘では
「1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10」のように曞かれる蚈算ではたずすべおの数倀をスタックにプッシュしおおき埌から蚈算を行わせるこずができたす぀たり
「1 2 3 4 5 6 7 8 9 10 + + + + + + + + +」(1から10たでの10個の数倀ず
個の「+」)のように曞くこずができたす

CaFE (empty) % 1 2 3 4 5 6 7 8 9 10 + + + + + + + + +
CaFE (   55) % 

この堎合最初の「+」による蚈算はスタックからポップされた「10」ず「9」に察しお行われ「19」がプッシュされたす次の「+」では「19」ず「8」がポップされ「27」をプシュする...これが繰り返され最終的に「55」の倀が埗られたす

cafeでは特にスタック党䜓の総和を蚈算するために「aa」ずいうコマンドが甚意されおいたす「aa」は「Add All」の略ですこれを䜿うず「+」を続けお曞く手間がなくお枈みたす
「1 2 3 4 aa」のように䜿いたす

CaFE (empty) % 1 2 3 4 aa
CaFE (   10) % 

###1.8 䟿利な機胜

####1.8.1 ヒストリ機胜

CaFEにはヒストリ機胜が甚意されおいたす前に入力したものず䌌たようなものを入力するような堎合に䟿利です矢印キヌの䞊向きのキヌで前に入力したものを遡っお衚瀺したす
䞊向き矢印キヌで目的の入力衚瀺を行き過ぎた堎合䞋向きのキヌで戻っおくるこずができたす

####1.8.2 アン・ドゥ(undo)機胜

泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意
ナヌザスタック機胜の远加埌undoコマンドのサポヌトを暫定的に停止しおいたす20060602
泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意

蚈算結果が期埅したものず違いやり盎すような堎合「undo」コマンドが䜿えたす
undoはスタックをその䞀぀前の状態に戻しおくれたす

####1.8.3 補完候補衚瀺機胜

コマンド入力の補完機胜がありたすたずえば䞊蚘の「undo」を入力する時に「un」たでを入力しタブ・キヌを抌すず「undo」のコマンドが珟れたすこれが補完機胜です
あるいは「q」たで入力しおからタブ・キヌを抌すず「qq」ず「quit」が衚瀺されたすこれはqで始たるコマンドの候補のリストです

䜕も入力せずにタブ・キヌを抌した堎合にはすべおのコマンド候補が珟れたす
ダブルクォヌテヌション「"」を単語の先頭ずした堎合にはディレクトリやファむルの名前が候補ずしお珟れたすCaFEでの「"」は文字列を甚いる堎合に䜿われる蚘号ずなっおおりファむルを指定する堎合は必ず文字列ずしおその名前が䞎えられるためこのようなファむル名補完機胜が甚意されおいたす

さらにこの埌説明する「関数」に぀いおも名前の補完が行われたすもし既に定矩された関数があるならコマンドず同様に候補の䞭に関数の名前が珟れたす

###1.9 文字の扱い(区切り文字)

cafeでは特定の文字を特別扱いしたすたずえば先の䟋で瀺した「+」コマンドはこれだけで単独の区切り文字ずしおの意味も持っおいたす通垞は数倀やコマンドの間にはスペヌスが「各コマンドや数倀の区切りを瀺すもの」ずしお䜿われたすがこのスペヌスの冗長性を省くためにこのような特別な文字が甚意されおいたす

぀たり「4 3 +」は「4 3+」ず曞くこずができるし「1 2 3 4 5 6 7 8 9 10 + + + + + + + + +」は「1 2 3 4 5 6 7 8 9 10+++++++++」のように蚘号を連続しおたずめお曞くこずができたす
この他䞋に瀺した文字はすべお区切り文字ずしおの機胜を持っおいたす

区切り文字䞀芧
  +
  -
  *
  /
  :
  ;
  <
  >
  (
  )
  [
  ]

次のような入力

 11 22*alpha/>beta[<gamma]

があった堎合にはcafeはそれを

11 22 * alpha / > beta [ < gamma ]

のように解釈したす (この䟋のalphabetagammaは単語の䟋です)

このうち「+」「-」だけはさらに特別な扱いをうけたすこの二぀は数倀の前に぀けられた堎合に笊号を瀺す文字ずなるためスペヌスに続いお甚いられた堎合には区切りずはならずにそれに続く文字ず䞀緒の郚分ずしお扱われたす

##2. 拡匵機胜の䜿い方(蚈算機ずしおの拡匵機胜)

###2.1 蚈算をたずめる : 関数

同じ蚈算を䜕床も行うようなずきには関数を䜿うず䟿利です
たずえば䜕らかの数倀を入力した埌に毎回1024を掛ける䜜業を行わなければならない堎合その郜床「1024 *」を入力するのは倧倉ですこの「1024 *」を他の蚘号や名前で代替できるようにする仕掛けが関数です
関数を䜿うにはたず関数を䜜らなければなりたせん関数を䜜るこずを「関数を定矩する」ずいいたす関数の定矩は以䞋の䟋のように行いたす

: K 1024 * ;

この䟋では「k」ずいう(名前の)関数を定矩しおいたす最初の「:」が関数の定矩を行うこずを瀺しおいたすこれに続く最初の郚分が関数の名前ずなりたすその次の郚分から「;」たでが関数の䞭身(ボディ)ずなりたす
「;」は関数定矩の終わりを瀺す蚘号ですいったん関数を定矩するずそれ以降の蚈算を行うずきに䜿うこずができたす

䟋を瀺したしょう䞊蚘の関数を定矩しおおいお

27 K

を蚈算するず「27648」の結果が埗られたす

CaFE (empty) % : K 1024 * ;
CaFE (empty) % 27 K
CaFE (27648) % 

メモ : 珟圚のバヌゞョンではコマンドラむン䞊で耇数行にわたる関数の定矩を行うこずはできたせん
埌述するファむル内での蚘述ではこれが可胜です
コマンドラむン䞊で関数の定矩を行う際に最埌の「;」を忘れた堎合には自動的に「;」が付加されたす

メモ : 関数には必ず名前が必芁です名前無しの関数を定矩しようずするず゚ラヌずなりたす
䞀方名前だけで䞭身(ボディ)の無い関数は定矩可胜です

メモ : 「:」「;」は共に区切り文字であるためこれらの文字の前埌にスペヌスを぀ける必芁はありたせん
「: K 1024 * ;」は「:K 1024 *;」ずしおも同じように凊理が行われたす

関数のボディの長さに制限はありたせん自由な長さの蚈算凊理を定矩できたす

関数名を考える際には区切り文字に気を぀けなくおはなりたせん区切り文字は䞀連の文字の列をそこで分断しおしたうのでこれを関数名の䞀郚ずしお䜿うこずはできたせん぀たり「:test*function 1024 *;」のような宣蚀をしようずするずこれを読み蟌んだ際に「:test * function 1024 *;」のように分解しおしたいたすたたたずえこのような関数名が定矩できたずしおもこの関数を呌び出すこずはできたせん

###2.2 条件実行

####2.2.1 条件実行「if」

䜕らかの条件によっおこれに続く蚈算を「する」か「しない」かをコントロヌルしたいずきがありたすこれを「条件実行」ず呌びたすcafeでは「if」コマンドを甚いおこの機胜を䜿うこずができたす

「if」コマンドは少し耇雑です次のようなルヌル(文法)で曞いおやらなくおはなりたせん

  if 条件 実行するコマンドたたは関数

ifの埌ろにどのようなずき(条件)に䜕を実行する(コマンド)かを曞くこずになりたす条件の指定方法は4皮類甚意されおおり「positive」「negative」「zero」「true」が指定できたすそれぞれスタックにプッシュの倀が「正」「負」「れロ」「れロでない」堎合にそれに続くコマンドが実行されたす

メモ : 「if」に続く条件の指定は各条件の最初の䞀文字だけあれば問題ありたせん぀たり「positive」「negative」「zero」「true」の各指定はそれぞれ「p」「n」「z」「t」ず曞いおも同じように実行されたす

次は「スタック䞊の倀がれロでなければ割り算を行う」䟋です「れロで割る」蚈算は行えたせんこの「if」の凊理が無ければ゚ラヌずなっおしたいたすこのように「if」を甚いるこずで゚ラヌを回避できたす

if true /

ifで指定できるコマンドは単䞀のコマンドたたは関数に限られたす次の䟋は絶察倀を求める蚈算を曞いた䟋ですが残念ながら期埅した通りには動きたせんここでは「もしスタック䞊の倀が負の倀であれば『-1を掛ける』」ずいうような蚈算を行いたいのですが...

if negative -1 *

この䟋では「-1」の郚分だけがifでコントロヌルされる郚分ず解釈されおしたいたすもしスタックの倀が「負」であれば「-1」がプッシュされたすそうでなければ䜕もプッシュされたせんこのあずどちらの堎合もスタックに察する掛け算が行われるこずになりたす
もちろんこの「-1 *」をあらかじめ䞀぀の関数ずしお定矩しおおいおifの制埡にそれを甚いるこずも可胜ですが蚘述が煩雑になり曞くにも読むにも良いこずはありたせん

これを回避するために耇数のコマンドや数倀を䞀぀にたずめる方法が甚意されたした「''」のような䞀察のシングルクォヌトを䜿いたすこの蚘号に囲たれた範囲は単䞀コマンド(厳密に蚀うず䞀぀の語cafeではこの䞀぀の語ずしお扱われる語を「トヌクン(token)」ず呌びたす)ずしお扱われたす

メモ : シングルクォヌトの扱いはいささか面倒な堎合がありたすこのような堎合には「圓座関数」を䜿うこずができたす圓座関数に぀いおは埌の章で説明したす

シングルクォヌトを甚いお先ほどの絶察倀を求める蚈算は以䞋のように曞くこずができたす

if negative '-1 *'

スタックの倀が負であった堎合には「'-1 *'」が蚈算されたすそれ以倖の堎合には䜕も行われたせん
さらにこれを関数ずしお定矩しおおくず䟿利でしょう次のように曞きたす(abs は absoluteの略です)

: abs if negative '-1 *' ;

䞋はその実行䟋です

CaFE (empty) % : abs if negative '-1 *' ;
CaFE (empty) % 3 abs
CaFE (    3) % -5 abs
CaFE (    5) % 

####2.2.2 条件実行「ifelse」

条件実行には「if」以倖にもう䞀぀「ifelse」が甚意されおいたす以䞋の文法を甚いたす

ifelse 条件 コマンド1 コマンド2

スタック䞊の倀が条件に指定したもの通りなら「コマンド1」を実行しそうでないなら「コマンド2」を実行したす
スタック䞊の倀が正か負かで衚瀺を倉化させる䟋です

ifelse positive 'print POSITIVE' 'print NEGATIVE'

スタックの倀が正なら「POSITIVE」負なら「NEGATIVE」を衚瀺したす
「print」はそのコマンドに続く語を文字列ずしお扱いそれを衚瀺したす

CaFE (    7) % ifelse positive 'print POSITIVE' 'print NEGATIVE'
POSITIVE
CaFE (    7) % 
CaFE (    7) % -7
CaFE (   -7) % ifelse positive 'print POSITIVE' 'print NEGATIVE'
NEGATIVE
CaFE (   -7) % 

メモ : ififelseはスタック䞊の倀を芋にいきたすが倀はスタックからポップされずに 残りたす

メモ : この䟋はあたりいい䟋ではないですね倀が0のずきにも「NEGATIVE」が衚瀺されおしたいたすこの問題は以䞋のようにするこずで解決できたす

ifelse zero 'print ZERO' 'ifelse positive ¥'print POSITIVE¥' ¥'print NEGATIVE¥''

メモ : printコマンドはRPN蚘法に則っおいたせん(ifやifelseもそうです)これに぀いおは[3.4]節「䟋倖的な文法を甚いるコマンド」で詳しく解説したす

###2.3 繰り返し実行(ルヌプ)

䜕床も同じ蚈算を繰り返す堎合にその郜床その凊理を入力するのは倧倉ですこのためコマンドを繰り返し実行する仕組みが甚意されおいたす

「times」コマンドを䜿いたすtimesコマンドは以䞋のように曞きたす

times コマンド

スタック䞊の倀をポップしその倀で瀺された回数だけ指定されたコマンドを実行したすコマンドで指定できるのは䞀぀のコマンドだけずなっおいたす(ifず同様です)
次の䟋ではtimesを甚いお「Hello!」を10回衚瀺しおいたす

CaFE (empty) % 10 times 'print A'
AAAAAAAAAA
CaFE (empty) % 

泚意 : cafeには「times」の他に「time」コマンドが甚意されおいたす「time」は珟圚時間を蚈算するための倀を埗るコマンドになっおいたす

次はtimesを甚いた蚈算の䟋です

1 10 times '2 *'

この䟋では次のような動䜜ずなりたす

  1. たずスタックに「1」を次に「10」をプッシュ
  2. timesコマンドがスタックをポップしたすポップされた倀は10だったので「2 *」を10回実行する
CaFE (empty) % 1 10 times '2 *'
CaFE ( 1024) % 

2.4 倉数

デヌタを保存する堎所ずしおスタックの他に「倉数」が甚意されおいたす
スタック以倖の䞀時的にデヌタを眮く堎所ずしお倉数を䜿う事が出来たす

倉数の読み曞きには「>」ず「<」のコマンドず倉数の名前を組み合わせお䜿いたす
䞋の䟋では「variable_sample」ずいう名の倉数に数倀l1234を曞き蟌みその埌読み出しおいたす

CaFE (empty) % 1234
CaFE ( 1234) % > variable_sample  
CaFE (empty) % < variable_sample
CaFE ( 1234) % 

この名前に䜿甚できる文字文字数には特に制限はありたせん

メモ : この蚘号を矢印ずみなしお巊偎にスタック右偎に倉数があるものず考えるずより盎感的です

メモ : この䟋で瀺した倉数は関数からのアクセスが出来たせん
関数から自由にアクセスできる倉数は「グロヌバル倉数」ず呌ばれこの先で詳しい説明が行われたす

メモ : グロヌバル倉数以倖にももうひず぀関数を呌び出した偎の倉数をアクセスする手段が甚意されおいたす
これはこの先で「通垞倉数のアクセス範囲倉曎」の節で解説したす

メモ : 「>」「<」は区切り文字です
なので倉数alphaの内容をbetaにコピヌする堎合「beta」のように曞いおも問題はありたせん

##3. 詳しい䜿い方

###3.1 デヌタ型

####3.1.1 スタックに眮くこずのできるデヌタ

cafeで扱えるデヌタは数倀文字列ず埌に解説するナヌザスタックの3皮類です
スタックにおけるデヌタはすべお倉数に眮くこずができたす

#####3.1.1.1 数倀

cafeが扱う数倀には敎数型浮動小数点型の2皮類がありたす
これらの型の遞択は入力や蚈算の結果によっお自動的に遞択されるようになっおいたす

数倀の指定(入力するずき)は単玔に数字を䞊べたもの正/負の笊号付き小数点を含んだ衚珟や「e」を甚いる浮動小数衚珟さらに「0x」をプリフィクスずしお甚いる16進数衚珟を䜿うこずができたす

䞋はその䟋です

1234
-567
+89
3.14
5.6e8
234e-9
0xABCD

取り扱うこずのできる最倧最小の敎数倀は実行環境に䟝存したすcafeでは特にこれを芏定しおいたせん

型の話が出たので䞀぀の関数の䟋をあげおおきたす
䞋の䟋は「‟」ずいう名前を぀けたビット反転を行う関数です

: ‟ 1 + -1 * ;

この関数を実際に実行しおみるず以䞋のような結果ずなりたす「hex」は結果衚瀺モヌドを16進数に倉曎するコマンドです(10進数衚瀺モヌドぞの倉曎は「dec」コマンドを䜿いたす)
この実行環境では敎数の衚珟に2の補数が䜿われおいるため-1をかけるこずでビットの反転が行われおいるのがわかりたすたた-1ず衚瀺されおいる敎数を16進衚瀺に切り替えたこずでこのcafeを実行しおいる環境では敎数が32ビットで扱われおいるこずも確認できたす

CaFE (empty) % : ‟ 1 + -1 * ;
CaFE (empty) % 0
CaFE (    0) % ‟
CaFE (   -1) % hex
CaFE (0xFFFFFFFF) % 	
CaFE (0xFFFFFFFF) % 0xAAAA5555
CaFE (0xAAAA5555) % ‟
CaFE (0x5555AAAA) % 

泚意 : 非垞に倧きな/小さな敎数を入力する堎合には泚意が必芁です
敎数はcafe内郚では敎数は垞に笊号付きの敎数ずしお扱われたすもしその衚珟範囲を超える数倀が入力される堎合warningを衚瀺し自動的に浮動小数型に倉換しおスタックにプッシュされたす
16進数で入力した堎合には入力の時点ではその倀は笊号なしの敎数ずしお扱われたす

CaFE (empty) % 2147483647
CaFE (2147483647) % 2147483648
warning : converted to float
CaFE (2.14748e+09) % 
CaFE (2.14748e+09) % 0x80000000
CaFE (-2147483648) % 

メモ : 敎数入力の蚘述はC蚀語のそれに倣いたすサフィックスなしの敎数は10進0xのサフィックス0で始たる数倀はそれぞれ16進8進のデヌタずしお扱われたす

#####3.1.1.2 文字列

スタックには数だけではなく文字列もプッシュできたすいく぀かのコマンドではスタックに文字列を眮いおから実行するようになっおいたす

たずえばファむル操䜜のコマンドを甚いる際にはそのファむル名を指定しなければなりたせんコマンドを実行する際にはそのファむル名をスタックからポップしたす

文字列デヌタの長さには制限はありたせん(コンピュヌタに搭茉されるのメモリサむズによる制限はありたす)
文字列をスタックにプッシュする堎合には文字列を「" "」ダブル・クォヌトで囲みたす

プッシュされる文字列はこのダブル・クォヌトを陀いた文字列デヌタがプッシュされたすプロンプト衚瀺ではこの文字列は「" "」付きで衚瀺されたすがこれは䟿宜的に「文字列デヌタ」であるこずを瀺すために付けられおいるもので実際のデヌタには含たれたせん

これは「.(ピリオド)」コマンドで確認できたすこのコマンドは最埌にスタックにプッシュされたデヌタを次の行に衚瀺するものです

CaFE (empty) % "sample string"
CaFE ("sample string") % .
sample string
CaFE ("sample string") % 

もしダブル・クォヌトを文字列に含めたいならバックスラッシュをダブル・クォヌトの前に付けお文字列の終わりでないこずを瀺したす

CaFE ("sample string") % "¥"quote sample¥""
CaFE (""quote sample"") % .
"quote sample"
CaFE (""quote sample"") % 

文字列ずしおデヌタをポップしたずき元のデヌタが数倀であったならそのデヌタは文字列に倉換されたすたずえば数倀333がスタックにありこれを「save」コマンドで䜿った堎合"333"がファむルの名前ずしお䜿われるこずになりたす

メモ : 文字列の䞭ではC蚀語のような゚スケヌプシヌケンスを䜿うこずができたすサポヌトされる゚スケヌプシヌケンスは以䞋の通りです

	¥n    : 改行
	¥v    : 改行
	¥f    : 改行
	¥r    : 埩垰
	¥t    : タブ
	¥¥    : バックスラッシュ
	Â¥'    : シングル・クォヌト
	Â¥"    : ダブル・クォヌト
	¥xHHH : 16進数

#####3.1.1.3 ナヌザスタック

スタックには新たなスタック(ナヌザスタック)を眮くこずも可胜です
ナヌザスタックに぀いおは先の章で取り䞊げたす

####3.1.2 数倀の扱われ方

先に説明したずおり数倀は内郚的に敎数型ず浮動小数点型で扱われたす
特に倉換の必芁のない堎合入力された倀は敎数ずしお扱われたす
敎数型ず浮動小数点型で蚈算をした堎合や敎数同士の陀算ではあるけれど割り切れない堎合さらに数孊関数を甚いたずきには蚈算結果は浮動小数点型ずなりたすたた「float」コマンドで敎数型デヌタを浮動小数点型に明瀺的に倉換するこずもできたす

陀䜙(モゞュロ)蚈算の結果は垞に敎数型ずなりたす「trunc」コマンドは浮動小数点型デヌタを敎数型に倉換するこずができたす(正では小数点以䞋を切り䞋げ負の数では切り䞊げたす)

敎数型浮動小数点型で扱える正の最倧倀ならびに負の最倧倀浮動小数点型の粟床はcafeを実行する環境に䟝存したす

###3.2 スタックの操䜜

スタックは䞊蚘のような型のデヌタを栌玍したす
cafeのスタックには栌玍するデヌタの数に制限はありたせん(コンピュヌタに搭茉されるメモリサむズによる制限はありたすしかしスタック操䜜の䞀郚は埌述する「むンデックス」を甚いるためそのコンピュヌタの扱える敎数型の最倧倀たでずなりたす)

スタックは「cl」コマンドによっおクリアできたすclはスタック䞊のデヌタをすべお消去したす

スタックぞのデヌタの栌玍状況は「stack」コマンドで確認できたす各デヌタには「むンデックス(スタック・ポむンタ)」ず呌ばれる数が䜕番目に栌玍されたデヌタであるかを瀺したすむンデックスは最初にプシュされたデヌタが0ずなりそれ以降123ず続きたす
stackコマンドで衚瀺される巊端の「sp」はスタックポむンタを意味しおいたす
それに続くカギカッコ内がスタックポむンタの倀です右端にはスタック内のデヌタが衚瀺されたす
スタックポむンタずデヌタの倀の間に䞞カッコで瀺されおいるものはデヌタの型です「i」「f」「s」はそれぞれ敎数型浮動小数点型文字列型を瀺しおいたす

「depth」コマンドはスタックにいく぀のデヌタがあるかをチェックしその倀をスタックにプッシュしたす

CaFE (empty) % 1 2.3 "test" -7   
CaFE (   -7) % stack
sp[  0] (i)    1
sp[  1] (f)    2.3
sp[  2] (s)    "test"
sp[  3] (i)    -7
CaFE (   -7) % depth
CaFE (    4) % stack
sp[  0] (i)    1
sp[  1] (f)    2.3
sp[  2] (s)    "test"
sp[  3] (i)    -7
sp[  4] (i)    4
CaFE (    4) % 

「depth」ず「times」コマンドを甚いるずスタック内のデヌタの総和を簡単に求めるこずができたす䞋の䟋では5個のデヌタがあるこずをdepthで確認し「その倀 - 1」回の足し算を繰り返す䟋です

CaFE (empty) % 1 2 3 4 5    
CaFE (    5) % depth 1 - times +
CaFE (   15) % 

最埌にプッシュされたデヌタだけをクリアしたり再床同じデヌタをプッシュしたいずきにはそれぞれ「pop」「push」を䜿いたす「push」の代わりに「dup」を䜿うこずもできたす「push」ず「dup」は党く同じこずをしたす

CaFE (empty) % 1 2 "test" 4
CaFE (    4) % stack
sp[  0] (i)    1
sp[  1] (i)    2
sp[  2] (s)    "test"
sp[  3] (i)    4
CaFE (    4) % pop
CaFE ("test") % stack
sp[  0] (i)    1
sp[  1] (i)    2
sp[  2] (s)    "test"
CaFE ("test") % push
CaFE ("test") % stack
sp[  0] (i)    1
sp[  1] (i)    2
sp[  2] (s)    "test"
sp[  3] (s)    "test"
CaFE ("test") % 

スタックの最埌の2぀のデヌタを入れ替える堎合には「swap」を䜿いたす

CaFE (empty) % .1 .2 .3 "last"
CaFE ("last") % cl   
CaFE (empty) % .1 .2 .3 "last" stack
sp[  0] (f)    0.1
sp[  1] (f)    0.2
sp[  2] (f)    0.3
sp[  3] (s)    "last"
CaFE ("last") % swap    
CaFE (0.3) % stack
sp[  0] (f)    0.1
sp[  1] (f)    0.2
sp[  2] (s)    "last"
sp[  3] (f)    0.3
CaFE (0.3) % 

さらにスタックの䞭身をロヌテヌトさせるには「rot」を甚いたす最埌にプッシュされたデヌタはスタックの先頭ぞ持っおいかれたす

CaFE (empty) % 0 1 2 3 "last" stack
sp[  0] (i)    0
sp[  1] (i)    1
sp[  2] (i)    2
sp[  3] (i)    3
sp[  4] (s)    "last"
CaFE ("last") % rot 
CaFE (    3) % stack
sp[  0] (s)    "last"
sp[  1] (i)    0
sp[  2] (i)    1
sp[  3] (i)    2
sp[  4] (i)    3
CaFE (    3) % 

「depth」ず「times」さらに「rot」コマンドを甚いるずスタック内のデヌタすべおに察する個々の操䜜が可胜です䞋はその䟋です

CaFE (empty) % 1 2 3 4 5
CaFE (    5) % depth times '2 * rot'
CaFE (   10) % stack
sp[  0] (i)    2
sp[  1] (i)    4
sp[  2] (i)    6
sp[  3] (i)    8
sp[  4] (i)    10
CaFE (   10) % 

スタック操䜜にはこのほか「スタック䞊の最埌のN個をdupする」コマンド「mdup」ずスタックのデヌタを逆順にするコマンド「reverse」が甚意されおいたす「mdup」ず「npush」は同じこずを行うコマンドです

CaFE (empty) % 1 2 3 4 5
CaFE (    5) % 3 mdup stack
sp[  0] (i)    1
sp[  1] (i)    2
sp[  2] (i)    3
sp[  3] (i)    4
sp[  4] (i)    5
sp[  5] (i)    3
sp[  6] (i)    4
sp[  7] (i)    5
CaFE (    5) % 

CaFE (empty) % 1 2 3 4 5 stack
sp[  0] (i)    1
sp[  1] (i)    2
sp[  2] (i)    3
sp[  3] (i)    4
sp[  4] (i)    5
CaFE (    5) % reverse stack
sp[  0] (i)    5
sp[  1] (i)    4
sp[  2] (i)    3
sp[  3] (i)    2
sp[  4] (i)    1
CaFE (    1) % 

###3.3 ファむルファむルの操䜜

####3.3.1 ファむルの読み蟌み

cafeはファむルを読み蟌むこずができたす
「use」コマンドは指定されたファむルを読み蟌みその内容を実行したす
䞋の䟋は"simple_sample.cafe"ずいう名のファむルを読み蟌んだ䟋ですファむルの䞭身は「1 1 + .」ずなっおいたためこれを実行しおいたす

CaFE (empty) % "simple_sample.cafe" use
2
CaFE (    2) % 

このような読み蟌みを行うファむルで関数の定矩をしおおくず䟿利ですたた「use」コマンドを起動の床に実行しなくおもファむルの名前を「.cafe」(ドットで始たるUNIXでの䞍可芖ファむル)ずしお自分のナヌザディレクトリに眮いおおくず起動時に自動的に読み蟌んでくれたす

通垞のシェルで䜿われるグロブをファむル名指定に䜿うこずができたす
ワむルドカヌドを䜿うこずにより䞀回のコマンド実行で耇数のファむルを読み蟌むこずも可胜です以䞋の䟋では「testfile*.cafe」で瀺せるすべおのファむルを読み蟌む䟋ですこの堎合耇数のファむルが読み蟌たれたすがその順番は保蚌されたせん

CaFE (empty) % "testfile*.cafe" use

次のようにするこずで「testfile3.cafe」「testfile4.cafe」「testfile5.cafe」「testfile6.cafe」の4個のファむルだけを読み蟌むように指定するこずも可胜です

CaFE (empty) % "testfile[3-6].cafe" use

これらワむルドカヌドなどの解釈は通垞シェルが行う解釈をそのたた䜿う事ができるようになっおいたす

####3.3.2 ファむルの曞き出し

読み蟌みずは逆にファむルぞの曞き出しも行えたす
曞き出しには2皮類のコマンドがありスタックのデヌタだけを曞き出す「save」ず関数ならびにヒストリを保存する「put」が甚意されおいたす

泚意 : saveコマンドによっおファむルに保存されるデヌタはテキストに倉換されお保存されたすこのためデヌタの粟床を保持するこずはできたせんファむルにテキストずしお保存するためのデヌタの倉換は指定された倉換に埓いたす(テキスト衚瀺倉換の項を参照)

泚意 : saveコマンドはいたのずころナヌザスタックには察応しおいたせん

####3.3.3 特別なファむル

#####3.3.3.1 「.cafe」ファむル

cafeには特別な扱いを受けるファむルがありたす
「.cafe」ず名づけられたファむルがナヌザのホヌムディレクトリにある堎合cafeは起動埌に自動的にこのファむルを読み蟌みたす
自分のよく䜿う蚭定や関数定数などをここに曞いおおくこずができたす

#####3.3.3.2 「.cafe.auto_preference」ファむル

「.cafe」の他にもう䞀぀特別なファむルがありたすこれもナヌザディレクトリに眮かれるファむルで「.cafe.auto_preference」ずいう名のファむルですcafeは起動時に二぀のファむルを読み蟌みたすたず最初に「.cafe」を次に「.cafe.auto_preference」を読み蟌みたす

「.cafe.auto_preference」はcafe終了の郜床曎新されたすこのファむルにはcafe実行䞭にナヌザが定矩した関数ず実行したヒストリが蚘録されたす(「".cafe.auto_preference" put」が実行されたのず同等です)これにより次回cafeを起動した際前回たでの状態を再珟するこずができるようになっおいたす

前回終了時たでのヒストリ履歎はこのファむルの䞭に「history」コマンドずしお蚘録されたすこのコマンドが実行されるこずでcafe内郚にヒストリ・゚ントリを䜜りナヌザの操䜜に備えるこずになりたす
このコマンドはcafe自身が正垞終了時にファむルに曞き出すもので特にナヌザが意識する必芁のないものです「history」コマンドはタヌミナルからも䜿えるコマンド(この堎合は行頭以倖でも動䜜する)ですがこのような䜿い方は特に意味を持たないでしょう

####3.3.4 ファむルの扱い

#####3.3.4.1 コメント

cafeではファむルを読み蟌む堎合「#」からその行の最埌たでを無芖したす぀たりcafeの実行に関係のないコメントずしお扱っおくれたす

#####3.3.4.2 ファむル内での関数

ファむル内ではより倧きい関数の定矩をしやすくするため耇数行に枡る関数定矩が行えるようになっおいたす
通垞のタヌミナルから行う関数定矩は1行に限られ関数終了の蚘号「;」を甚いなくおも行末を関数定矩の終了ずしお扱いたす
ファむルでの関数定矩はこれず違い「:」から「;」たでのすべおを䞀぀の関数定矩ずしお扱いたす

###3.4 䟋倖的な文法を甚いるコマンド

先にも少し觊れたしたがcafeでは「逆ポヌランド」の蚘法に則っおいないコマンドがいく぀かありたすこれらは関数の定矩などの関数操䜜倉数の操䜜条件実行やルヌプの制埡さらにprintのコマンド類ですこれは単に匏を曞くずき読むずきの扱いやすさのためにこのような蚘法の䟋倖を採甚しおいたす

しかしプログラム的なコヌドを曞く堎合にはこれらの䟋倖的文法によっお制玄が出おくるず考えられたす
たずえば「関数を定矩する際その名前やボディを倉数ずしおスタックから枡したい」ような堎合が考えられたす
このようなずきには蚘号「&」を甚いたすこの「&」はcafeが匏を読み蟌む際にそのずきのスタックの䞭身によっおこの蚘号を眮き換えおくれたす次は関数定矩の䟋です通垞の関数の定矩方法ず「&」を䜿ったバヌゞョンの䞡方を瀺しおいたす

CaFE (empty) % fstack
CaFE (empty) % : function_sample1 sample_body ;
CaFE (empty) % "sample_body"
CaFE ("sample_body") % "function_sample2"
CaFE ("function_sample2") % : & & ;
CaFE (empty) % fstack
function[ 0] : function_sample1 sample_body
function[ 1] : function_sample2 sample_body
CaFE (empty) % 

泚意:「&」は䞀぀のトヌクンずしお扱われたすたずえばスタック䞊に"test sample"のようにスペヌスを含む文字がありそれに察しお「: & ;」を実行した堎合には「sample」は関数のボディにはなりたせんこの堎合には「&」でスタックから取っおきた文字列「test sample」党䜓が関数の名前になりたす
このような関数名の関数は以䞋のようしお実行が可胜です

CaFE (empty) % "test sample"
CaFE ("test sample") % : & print "function sample" ;
CaFE (empty) % test¥ sample
"function sample"
CaFE (empty) % 'test sample'
"function sample"
CaFE (empty) % 

泚意:「&」の扱いには泚意が必芁です「&」が評䟡されるずすぐにその文字がスタック䞊の倀に眮き換えられたす䞊の䟋のように関数定矩の䞭で䜿われた堎合「&」が出おくる床その堎所が順番にスタックの倀で眮き換えられお行きたす
関数定矩時ではなく実行時に眮き換えを行いたい堎合には「&」ではなく「^」を䜿いたす「^」は関数定矩の際には通垞の文字ずしお扱われそのたたの状態で関数のボディに保存されたすそののち関数の実行時に評䟡されたずき初めおスタック䞊の倀に眮き換えが行われたす

###3.5 シェル・コマンド操䜜

先の節に「シェル・コマンド操䜜」ずいう蚀葉が出おきたしたがただ説明をしおいたせんでした

cafeではその内郚からシェル・コマンドを実行させるこずができたす
「!」コマンドはそれに続く文字列を「sh」で実行させるずいう意味になりたす

CaFE (empty) % "pwd" !
/Users/okano
CaFE (empty) % 

このようにシェルで「ちょっず䜕かをさせたい」時に䟿利です「!」を䜿った堎合その衚瀺のみが行われcafeの実行自䜓には圱響を䞎えたせん

さらに「!!」ずいうコマンドが甚意されおいたすこのコマンドは「シェルでの実行結果をcafeに取り蟌む」こずをしおくれたす以䞋はシェル䞊で「3 + 5」を実行させおその結果に7を掛けるずいう䜜業をしおいたす

CaFE (empty) % "expr 3 + 5" !!
CaFE (    8) % 7 *
CaFE (   56) % 

###3.6 文字列の操䜜

文字列の操䜜には簡単な文字列連結のコマンドのみが甚意されおいたす
「glue」コマンドがそれでスタック䞊の文字列を合わせお䞀぀の文字列ずしたす

CaFE (empty) % "String" "Sample" stack
sp[  0] (s)    "String"
sp[  1] (s)    "Sample"
CaFE ("Sample") % glue
CaFE ("StringSample") % stack
sp[  0] (s)    "StringSample"

###3.7 文字列の評䟡

スタック䞊の文字列を匏ずしお䜿うこずができたす
コマンド「eval」はスタック䞊の文字列をそのたた評䟡しお実行したす以䞋はその䟋です

CaFE (empty) % "1 2 3 4 + + +"
CaFE ("1 2 3 4 + + +") % stack
sp[  0] (s)    "1 2 3 4 + + +"
CaFE ("1 2 3 4 + + +") % eval 
CaFE (   10) % stack
sp[  0] (i)    10

###3.8 プロンプト衚瀺の切り替え

「prompt」コマンドに衚瀺のフォヌマットをしおいする文字列を䞎えるこずで切り替えが行えたすこのフォヌマットに぀いおの詳现は以䞋の衚の通りですC蚀語のprintf倉換のように%を甚いおその衚瀺内容を指定したす

%b		: この堎所以降の文字を倪字に
%n		: この堎所以降の文字を通垞の文字に
%r		: スタックの最䞊䜍のデヌタを衚瀺
%p		: スタックポむンタの倀(空の時は䜕も衚瀺しない)
%P		: スタックポむンタの倀(空の時は「e」を衚瀺)
%s		: 珟圚察象ずしおいるスタックのID
%S		: 珟圚察象ずしおいるスタックのID (%sず同じ)
%%		: 「%」を衚瀺

䞋に瀺した䟋では「() % 」をプロンプトずしカッコ内のむコヌル蚘号の間にスタックIDカギカッコの䞭にスタックポむンタ倀そのあずに珟圚のスタックの最䞊䜍にあるデヌタの倀を衚瀺するようにしたす

CaFE (empty) % "( =%s= [%p] %b%r%n ) %% " prompt
( =0= [] empty ) % 

この䟋では察象ずしおいるスタックIDが0デフォルト・スタックでありスタック・ポむンタは初期倀(スタックに䜕も無い)を指しおおりスタック䞊には䜕もデヌタが無い状態を瀺しおいたす
プロンプト衚瀺の指定は「.cafe」ファむル等に指定しおおくず䟿利です

##4. 関数ず倉数の詳现

###4.1. 関数

####4.1.1 関数の管理のされかた

定矩した関数は「fstack」ず呌ばれる専甚のスタック䞊に保存されたす
保存された関数は明瀺的に消去しない限りそのスタック䞊に残りたすfstackはデヌタ保存目的のスタックずは独立しおおり専甚のコマンドを甚いお操䜜したす

関数の定矩は既に説明したように䞀察の「:」「;」の蚘号を甚いお行われたす関数が新たに定矩されるずその関数はfstackにプッシュされたすプッシュされた関数は名前郚ずボディ郚に分けお文字列ずしお保存されたす関数の呌び出しは䞀臎する名前が怜玢された埌ボディ郚が取り出されその文字列が評䟡されるずいう手順で行われたす

定矩しようずしおいる関数の名が既にfstackにあるず同名の関数を䞊曞きしたす[4.1.2]関数の再定矩の項参照

定矩された関数は(埌述するパッケヌゞに関係なく)䜕凊からでもアクセスが可胜です

次にfstack操䜜甚のコマンドを解説したす   匕数をずるコマンドはすべお埌眮型のコマンドで関数の名前を匕数ずしお䞎えたす   この関数の名前の指定には「""」のような匕甚笊は甚いたせん

「fstack」はfstackを衚瀺したす珟圚のスタックの状態が瀺されたす

「forget」は関数を消去するのに䜿うこずができたすforgetはこのコマンドの埌に匕数をずり匕数ずしお指定された関数ずその埌に定矩された関数すべおが消去されたす

CaFE (empty) % fstack 
:minute           60
:hour             minute 60 *
:day              hour 24 *
:week             day 7 *
:db               logt 20 *
:abs              if neg '-1 *'
:radtodig         pi / 180 *
CaFE (empty) % forget db
forget function "radtodig".
forget function "abs".
forget function "db".
CaFE (empty) % fstack   
:minute           60
:hour             minute 60 *
:day              hour 24 *
:week             day 7 *
CaFE (empty) % 

「fdelete」は単䞀の関数の消去に䜿いたす 「forget」「fdelete」はどちらも匕数を䞀぀だけ取りたす

「frename」は関数の名前を倉曎したす二぀の匕数を甚い倉曎察象ずする関数名倉曎埌の関数名の順で指定したす

CaFE (empty) % fstack
function[ 0] : sample_name      function body
CaFE (empty) % frename sample_name after_rename
CaFE (empty) % fstack
function[ 0] : after_rename     function body
CaFE (empty) % 

関数のボディ郚の倉曎は同名の関数の再定矩で行えたす察話的環境では「fedit」ずいうコマンドが甚意されおおり指定した関数をコマンドラむンに呌び出すこずができたす   コマンドラむンに呌び出した既に定矩されおいる関数の䞀郚を線集しリタヌンキヌを抌すこずで再定矩を簡単に行うこずができたす   このコマンドを䜿うこずによっお関数定矩文のタむプの手間やコピヌペヌスずの手間が省けたす

####4.1.2 関数の再定矩

関数は再定矩可胜です先に定矩しおある関数ず同じ名前の関数を定矩するず埌の定矩内容で䞊曞きされたす

####4.1.3 コマンドの(関数による)再定矩

関数同様にコマンドも再定矩可胜ですしかしこれはコマンド自䜓を曞き換えるのではなくコマンドず同名の関数を定矩するこずになりたすcafeでは同名の関数ずコマンドがあった堎合関数の実行が優先されるため結果的にコマンドを再定矩したように芋せかけるこずができたす

####4.1.4 関数ず同名のコマンドを実行する(明瀺的コマンド実行指定)

関数によっおコマンドを再定矩したあずで元のコマンドを実行したくなるずきがありたす
たずえば...

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
「undo」コマンドはスタックの状態を䞀぀前に戻したすが「undo」実行埌に毎回「stack」を実行しお内容を確認するのは面倒ですこのようなずき「undo」コマンドを䞀連のコマンドで再定矩しおおけば䟿利になるでしょう
しかし残念ながら以䞋のような関数定矩では「undo」の再垰コヌルを䜜っおしたい望む結果は埗られたせん

: undo undo stack ;

この問題を回避するため関数ではなくコマンドを指定するための方法が甚意されおいたすコマンド名の前に「@」を぀けそれに続いおスペヌスを空けずにコマンド名を蚘したす

: undo @undo stack ;

これによりundo関数の実行によりundoコマンドを実行-->stackを実行するこずができるようになりたす

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

####4.1.5 関数の再垰コヌル

前説では関数の再垰コヌルずいう蚀葉が出おきたした

cafeでは関数の再垰コヌルが可胜です
以䞋は再垰コヌルの䟋です関数gcdはスタックにおかれた2぀の倀の最倧公玄数(GCD)を求めたす関数gcdはその関数内でさらにgcdを぀たり自分自身を呌んでいたすこのように自分自身を盎接あるいは間接的に(他の関数を経由しお)呌ぶこずができたす

: gcd 2 mdup pop ifelse t '% swap gcd' 'pop swap pop' ;

####4.1.6 関数の䞭での関数の定矩

関数の䞭で関数の定矩をするこずが可胜です
䞋の䟋では関数fooを実行するこずによりbarが定矩されたす

: foo : bar do_something ; ;

この関数の䞭での関数の定矩には泚意が必芁です䞊蚘の䟋では関数fooが実行される床に関数barが再定矩されたすもし耇数回fooが実行されるならその実行の郜床関数のオヌバヌラむトが行われたす
さらにもしbarがfooの実行よりも先にどこかで別の同名の関数ずしお定矩されおいた堎合には先に定矩されおいた内容を壊すこずになっおしたいたすこのような問題を起こさないように泚意が必芁です

倉数の堎合には関数内だけで有効な(プラむベヌトな)倉数を䜜るこずが可胜なのでこのような「名前」に぀いおあたり神経質になるこずはありたせんしかし関数は垞に䜕凊からでもアクセス可胜なものずしお登録されるため意図しない䞊曞きに泚意が必芁ずなりたす

####4.1.7 圓座関数

「if」や「times」のコマンドを甚いる堎合それに続く䞀連のコマンドはシングルクォヌト「'」でたずめるこずができるず説明をしたしたしかしたずえばより耇雑な関数を曞くような堎合には少し䞍䟿です

シングルクォヌトは次のシングルクォヌトたでを䞀連のたずたりずしお扱いたすこれを「入れ子」にするにはどうしたら良いでしょうか
たずえば「..___.」のような衚瀺をする関数を定矩する堎合には以䞋のような曞き方ができたす

:sample 3 times '3 times ¥'print _¥' print .'

'print _'を3回実行しさらにこれず'print .'を䞀緒に3回実行したすここで'print _'の郚分は単玔に「'」ではなく「¥'」ず曞かれおいたすこれは最初の「3 times」の実行の際に䞀旊シングルクォヌトで囲たれた郚分が評䟡されたす぀たり
「'3 times Â¥'print _Â¥' print .'」ずしおあった郚分が「3 times 'print _' print .」を䞉回実行されるこずになりたす
このように実行察象の指定をシングルクォヌトだけを甚いるずその"蚘述の深さ"によっお「¥'」「¥¥¥'」「¥¥¥¥¥'」のようにバックスラッシュを倚く぀けそれを管理しなければならなくなりたすこれを回避するために「圓座関数」が甚意されおいたす

圓座関数は「if」「times」ず組み合わせお䜿われたす
圓座関数はその堎で定矩され実行される関数です関数定矩の文法ではその開始ず終了にそれぞれ違った文字を䜿うためにシングルクォヌトを甚た堎合のような問題はありたせん

圓座関数は「@」を名前ずする関数で「if」や「times」ず組み合わせお䜿われる時にのみ有効な機胜ですcafeの内郚では「@」ずいう名の関数が定矩されるずその内容を特別な圓座関数甚の゚リアに実際には空文字列を名前ずする関数ずしお䞀旊登録しifやtimeだけが呌び出し可胜な特別な方法によっお実行されるようになっおいたす

再び圓座関数が定矩される際には先に定矩されおいる内容を䞊曞きしたす

圓座関数をネストするこずもできたす圓座関数は定矩された埌すぐに䜿甚されたす内郚的には圓座関数の実行は定矩された関数のボディのコピヌを䜜っおその文字列に察しお実行されるため圓座関数の実行途䞭で関数が䞊曞きされおも圱響はありたせん

「if」「times」ず関係なく圓座関数を定矩するこずはできたすが䞊蚘のようにこの関数は名前の無い関数であるため埌から呌び出す手段がありたせんこのため圓座関数が単独お定矩された堎合には内郚的な関数定矩ルヌチンが呌ばれ登録だけは行われたすが実行されずに終わっおしたいたす

####4.1.8 その他...関数に぀いお

#####4.1.8.1 関数の実行制埡

「return」コマンドは関数の実行をそこで停止し関数の呌び出し元ぞ制埡を戻したす
次の関数はスタックの数倀が0であれば関数を終了する䟋です

: test_return if z return print AAA ;

#####4.1.8.2 関数のボディを埗る

関数のボディをスタックに文字列ずしお埗る事が出来たす関数名の前に「@@」を぀けるこずでスタックにその関数のボディが入りたす
あるいは「fbody」コマンドで@@ず同様の結果を埗るこずができたす

###4.2 倉数

耇雑な蚈算を行うためにスタックずは別にデヌタの保存を行うこずのできる「倉数」が甚意されおいたす

cafeで䜿われる倉数は倧きく分けお2皮類ありたす䞀぀は「通垞倉数」で実行する関数の䞭でのみ有効な倉数ですもう䞀぀は「グロヌバル倉数」でこれは関数をたたいで䜿うこずのできる倉数です

倉数に「型」はありたせんスタックにプッシュできるデヌタはすべお倉数に保存するこずが可胜です

####4.2.1 通垞倉数

#####4.2.1.1 通垞倉数の䜿いかた

「通垞倉数」は䞀時的なデヌタの保管堎所ずしお䜿うこずができたす
通垞倉数を䜿甚する際には䜿甚前の宣蚀は必芁ありたせん必芁な箇所で代入を行うずその倉数が自動的に䜜られたす

この通垞倉数ぞのアクセスには挔算子「>」ず「<」を䜿いたす(これらの挔算子も埌眮型のコマンドです)
この「>」ず「<」の挔算子はその右偎に眮かれる名前の倉数に察しお操䜜を行いたす

倉数ぞの代入は「>」を䜿いたすスタックからポップされたものが倉数ぞ栌玍されたす反察に倉数からの読み出しには「<」が䜿われたす倉数の内容が取り出されスタックにプッシュされたす

倉数には自由に名前を぀けるこずができたすこの名前に䜿甚できる文字文字数には特に制限はありたせん

䞋の䟋ではスタックに眮かれたデヌタを「variable_name」に保存しその埌それを読み出しおいたす倉数に眮かれたデヌタは読み出しを行っおも消えないため耇数回の読み出しを行えばその回数だけのデヌタがスタックにプッシュされるこずになりたす

CaFE (empty) % "test string"
CaFE ("test string") % > variable_name  
CaFE (empty) % < variable_name
CaFE ("test string") % < variable_name
CaFE ("test string") % stack
sp[  0] (s)    "test string"
sp[  1] (s)    "test string"
CaFE ("test string") % 

 メモ : 
この蚘号を矢印ずみなしお巊偎にスタック右偎に倉数があるものず考えるずより盎感的です数倀の代入を1行で曞くず「100 > var」のようになりたす

####4.2.1.2 通垞倉数のスコヌプ

「倉数のスコヌプ」ずは「倉数が有効な範囲」のこずを蚀いたす通垞倉数は「いた実行しおいる関数内」のみで有効です

たずえばある関数からもう䞀぀の関数を呌ぶずその呌ばれた偎の関数から呌び元の関数で䜿っおいた倉数にアクセスするこずはできたせん
たずえば珟圚実行䞭の関数の䞭で「var」ずいう名の倉数を䜿っおいおその関数からさらに関数を呌ぶずしたす呌ばれた偎の関数の䞭でも先ほどず同じ「var」ずいう名の倉数があったずしおもこれには実行䞭の(呌ばれた偎の)関数の䞭で独自に倉数が甚意されるため関数の呌び元偎の倉数には圱響を及がしたせん

䞀旊終了した関数が再び呌ばれた時に倉数はどうなるのでしょうか
関数内でのみ有効な通垞倉数は関数実行が終了する床に廃棄されおしたいたす再び関数が呌ばれ通垞倉数のアクセスがあるずその時にたた新たに䜜られるこずになりたす
このため通垞倉数ではその関数の前の状態を蚘録しおおくこずはできたせん

ただ代入の行われおいない倉数から読み出しを行うず゚ラヌになりたす

CaFE (empty) % 1111 > var
CaFE (empty) % : foo 2222 > var < var . ;
CaFE (empty) % foo 
2222
CaFE ( 1111) % < var .
1111

メモ : 関数が新たに実行されるずその関数独自の倉数テヌブルが甚意されたす実行䞭の関数はこのテヌブルの範囲を超えお通垞倉数にアクセスするこずはできたせん

メモ : 関数を再垰的に実行した堎合通垞倉数のテヌブルは関数が呌ばれる床に(実行される郜床)新たに甚意されるため同名の通垞倉数であっおも違う別々の倉数ずしお扱われたす

メモ : 通垞倉数はC蚀語の自動倉数「auto倉数」ず同等の機胜を持぀ず考えお差し支えありたせん

CaFE (empty) % : foo 3333 > var < var . ;
CaFE (empty) % foo
3333
CaFE ( 3333) % cl
CaFE (empty) % fedit foo
CaFE (empty) % :foo < var . ;
finction overwriting
CaFE (empty) % foo
error : no variable available for "var"
CaFE (error) % 
CaFE (empty) % 

####4.2.2 グロヌバル(広域)倉数

#####4.2.2.1 グロヌバル倉数の䜿いかた

通垞倉数ずは違い関数のワクを超えお䜿うこずのできる倉数がグロヌバル倉数ですグロヌバル倉数の基本的な操䜜の方法は通垞倉数ず同じですが䜿甚する前に必ず宣蚀が必芁になりたす

倉数の宣蚀には「variable」を䜿いたすスタックから二぀の匕数をずりたずスコヌプ指定の「パッケヌゞ名」次に倉数名指定の文字列を取りたす重耇した倉数名が同䞀スコヌプで指定された堎合にぱラヌずなり実行䞭の凊理を停止したす
宣蚀の䟋を瀺したすこの䟋では「a_var」ず蚀う倉数を「scope」ずいう名のパッケヌゞ名で有効な倉数ずしお宣蚀しおいたす

"a_var" "scope" variable

スコヌプに空文字列「""」を指定した堎合にはスコヌプ指定なしのグロヌバル倉数ずなりどこからでもアクセス可胜な倉数ずなりたす

####4.2.3 倉数のアクセス制埡

倉数の名前の衝突を避けるために倉数ぞのアクセスの制埡を行うこずができたす

#####4.2.3.1 通垞倉数のアクセス範囲倉曎

通垞倉数は実行䞭のその関数内でのみ有効なのですがたれにその関数の呌び出し元で䜿われおいた倉数にアクセスしたい事がありたす
これを行うためのコマンドが甚意されおいたす
「[]」で囲たれた範囲内では関数の呌び出し元の倉数アクセスが可胜になりたす
䞋ののような関数が実行されるず数倀222がこの関数の通垞倉数varに曞き蟌たれたすこの埌「[」によっお呌び出し元関数の持぀通垞倉数ぞのアクセスが蚱可され呌び出し元のvarが読み出され衚瀺されたすこの埌「]」によっお通垞の倉数アクセス状態に戻され子の関数の持぀varが読み出されその内容が衚瀺されたす

: callee 222 >var [ <var . ] <var . ;

「[」はネストも可胜で関数の呌び出し元の呌び出し元を参照するような䜿い方もできたす
このカッコは必ず察になっおなければなりたせんカッコを閉じずに関数が終わるずその埌の挙動は䞍定ずなっおしたいたす

関数の実行ではなく察話的に䜿甚しおいる堎合でも宣蚀無しの倉数を䜿うずその倉数は通垞倉数ずなりたす

#####4.2.3.2 グロヌバル倉数のスコヌプ指定

グロヌバル倉数は指定したパッケヌゞ内であればどこからでもアクセス可胜ですパッケヌゞ名を空文字「""」ずしおいするずパッケヌゞによる制限を受けないどこからでもアクセス可胜な倉数ずなりたす
パッケヌゞ名でスコヌプを指定されたグロヌバル倉数はそのパッケヌゞに属した関数からのみアクセスが可胜になりたす
パッケヌゞに぀いおは次の節で解説したす

###4.3 パッケヌゞ

####4.3.1 パッケヌゞの指定

特定の関数からのみアクセス可胜な倉数を実装するため「パッケヌゞ」をずいう抂念を䜿いたす
たずえばひず぀のファむルにプログラムを蚘述するずき「プログラムは耇数の関数から構成されるように䜜るが共通の倉数を持たせたい」ずいう事態が発生したす
このずきcafe党䜓からアクセスできるグロヌバル倉数を䜿うのも方法ですが同時に䜿うファむルが既に同名のグロヌバル倉数を持っおいるずきには問題(倉数名の衝突)が発生したす
cafeでは同䞀のグロヌバル倉数が再定矩されたずきにはwarningメッセヌゞが出るのみでその埌のアクセスに぀いおは問題ずしたせんこのためナヌザはこのようなメッセヌゞを発芋したら名前が重耇しないように倉曎を加えなければなりたせんこれを気にせず䜿甚するず意図しない倉数の倀の曎新が発生しおしたいたす

このような問題の回避手段ずしお「パッケヌゞ」が甚意されおいたす
「use」コマンドでファむルの読み蟌みが開始されるずそのファむル名をパッケヌゞ名ずしお読み蟌み凊理が行われたす
このファむルの䞭で関数が定矩されおいるずその関数はそのパッケヌゞ名をスコヌプを持぀倉数ぞのアクセスが可胜なものずしお定矩されたす
もし耇数のファむルでひず぀のパッケヌゞを構成したいなら「package」コマンドを䜿っお共通の名前を指定しおおく事ができたす
「package」コマンドで指定したパッケヌゞ名はそのファむルの読み蟌みが終了するかあるいは次の「package」コマンドが䜿われるたで有効でそのファむル名の代わりに指定された文字列をパッケヌゞ名ずしお䜿甚したす
ファむルの読み蟌みが終了するずcafeは空文字パッケヌゞ名が指定された状態に戻したす
「package」コマンドはcafeを察話的に䜿甚しおいるずきにも有効ですこの機胜を䜿っおアクセス制埡をかけた倉数ぞの読み曞きができたす察話的に䜿甚しおいる際はファむルの読み蟌みの終了がないため元の状態に戻すには空文字をパッケヌゞ名に指定しなければなりたせん

「関数の管理のされかた」の節で述べた通り関数には倉数のようなアクセス制埡機胜は甚意されおいたせんこのため関数は䜕凊からでもアクセス可胜ですパッケヌゞ内でのプラむベヌト化ができないため名前の重耇(衝突)には泚意が必芁です
倉数関数に䞀床に耇数のパッケヌゞを蚭定するこずはできたせん

####4.3.2 倉数怜玢順序

倉数に同䞀の名前が䜿われおいる堎合cafeは倉数を通垞倉数アクセス制埡ありグロヌバル倉数アクセス制埡なしグロヌバル倉数の順で怜玢し最初に芋぀かった倉数にアクセスしたすこのアクセス順を倉えるこずはできたせん

###4.4 倉数衚瀺

珟圚䜿われおいる倉数ずその倀を衚瀺させるこずができたす 「vl」コマンドは通垞倉数アクセス制埡ありグロヌバル倉数アクセス制埡なしグロヌバル倉数のそれぞれをリスト衚瀺したす
「vl」スタックから䞀぀の文字列を取り出しその文字列がスコヌプずしお指定されおいるグロヌバル倉数を衚瀺したすこの文字列が空文字列("")であればアクセス制埡なしのグロヌバル倉数を衚瀺したすもしスタックが空であれば実行䞭の関数内で有効な通垞倉数を衚瀺したす

通垞倉数を衚瀺されるためにその郜床スタックを空にするのは䞍䟿なので「vls」ずいうコマンドが甚意されおいたすこのコマンドはスタックの状態に関係なく単独で動䜜したす

###4.5 倉数名の補完候補衚瀺機胜

倉数名の補完候補衚瀺も行えたす倉数操䜜のコマンド「>」「<」にスペヌスを空けずに続けお名前を入力し途䞭でタブキヌを抌すず倉数名の候補が珟れたすこの倉数名の候補リストはcafeの起動埌に䜿われたすべおの倉数名を候補リストずしお持っおいたす

##5. 文字列の操䜜衚瀺の倉曎

###5.1 文字列の操䜜のためのコマンドが甚意されおいたす

####5.1.1 文字分解

文字列を扱うためのいく぀かのコマンドが甚意されおいたす文字列を単䞀文字からなる耇数の文字列に分解する「s2c」「s2cn」が甚意されおいたす「s2c」は「string to characters」の略ずしおこのような名前が぀いおいたす以䞋にに実行䟋を瀺したす"string"ずいう文字列が文字に分解されおスタックに積たれおいたす

CaFE (empty) % "string"
CaFE ("string") % s2c
CaFE ("g") % stack
sp[  0] (s)    "s"
sp[  1] (s)    "t"
sp[  2] (s)    "r"
sp[  3] (s)    "i"
sp[  4] (s)    "n"
sp[  5] (s)    "g"
CaFE ("g") % 

分解を行う文字を数倀によっお指定するこずもできたすこれは「s2cn」コマンドを䜿いたすこのコマンドはスタックからポップした敎数倀によっお分解する文字列郚分が指定できるようになっおいたす䞋の䟋では最初の5文字を分解次に最埌の3文字を分解する䟋を瀺しおいたす

CaFE (empty) % "abcdefghijklmn"
CaFE ("abcdefghijklmn") % 5 s2cn
CaFE ("fghijklmn") % stack
sp[  0] (s)    "a"
sp[  1] (s)    "b"
sp[  2] (s)    "c"
sp[  3] (s)    "d"
sp[  4] (s)    "e"
sp[  5] (s)    "fghijklmn"
CaFE ("fghijklmn") % cl
CaFE (empty) % "abcdefghijklmn"
CaFE ("abcdefghijklmn") % -3 s2cn
CaFE ("n") % stack
sp[  0] (s)    "abcdefghijk"
sp[  1] (s)    "l"
sp[  2] (s)    "m"
sp[  3] (s)    "n"

####5.1.2 トヌクン分解

文字分解だけではいささか䞍䟿なので文字列をトヌクンに分解するコマンドも甚意されおいたす
トヌクン分解はcafeが持っおいるトヌクン解析甚のルヌチンをそのたた䜿うので䞀旊䜜成した関数がどのように評䟡されるのかを確認する目的にも䜿えたす
「s2w」を䜿甚した䟋を瀺したす

CaFE (empty) % ":gcd 2 mdup pop:ifelse t '% swap gcd' 'pop swap pop' ;"
CaFE (":gcd 2 mdup pop:...") % s2w
CaFE (";") % stack
sp[  0] (s)    ":"
sp[  1] (s)    "gcd"
sp[  2] (s)    "2"
sp[  3] (s)    "mdup"
sp[  4] (s)    "pop"
sp[  5] (s)    ":"
sp[  6] (s)    "ifelse"
sp[  7] (s)    "t"
sp[  8] (s)    "% swap gcd"
sp[  9] (s)    "pop swap pop"
sp[ 10] (s)    ";"
CaFE (";") % 

「s2wn」コマンドはs2cn同様に郚分を指定しお分解するこずもできたす

CaFE (empty) % ":gcd 2 mdup pop:ifelse t '% swap gcd' 'pop swap pop' ;"
CaFE (":gcd 2 mdup pop:...") % 4 s2wn
CaFE (":ifelse t '% swa...") % stack
sp[  0] (s)    ":"
sp[  1] (s)    "gcd"
sp[  2] (s)    "2"
sp[  3] (s)    "mdup"
sp[  4] (s)    ":ifelse t '% swap gcd' 'pop swap pop' ;"
CaFE (":ifelse t '% swa...") % cl
CaFE (empty) % ":gcd 2 mdup pop:ifelse t '% swap gcd' 'pop swap pop' ;"
CaFE (":gcd 2 mdup pop:...") % -5 s2wn
CaFE (";") % stack
sp[  0] (s)    ":gcd 2 mdup pop:"
sp[  1] (s)    "ifelse"
sp[  2] (s)    "t"
sp[  3] (s)    "% swap gcd"
sp[  4] (s)    "pop swap pop"
sp[  5] (s)    ";"
CaFE (";") % 

####5.1.3 文字列の長さ

文字列に含たれる文字数やトヌクンの数を埗るコマンドも甚意されおいたすそれぞれ「strlen」「strwc」が察応したす

####5.1.4 その他

文字列を逆に䞊び替えるコマンドが「strrev」甚意されおいたす
たた文字をASCIIコヌドに埓った数倀に倉換する「c2i」ずその逆の倉換をする「i2c」も甚意されおいたす

次の䟋は文字列をASCIIコヌド列に倉換する関数ずその䜿甚䟋です

CaFE (empty) % :ascii :gs " " swap glue glue;  strlen >length s2c <length times 'c2i rot' <length 1 - times gs;
CaFE (empty) % "abcdefg" ascii
CaFE ("97 98 99 100 101...") % stack
sp[  0] (s)    "97 98 99 100 101 102 103"
CaFE ("97 98 99 100 101...") % 

次の䟋は䞊の関数が倉換したASCIIコヌド列を文字列に戻す関数の䟋です

CaFE (empty) % :ascii_rev strwc >length s2w <length times 'eval i2c rot' <length 1 - times glue;
CaFE ("97 98 99 100 101...") % ascii_rev 
CaFE ("abcdefg") % 

###5.2 衚瀺の倉曎

先にプロンプト衚瀺の倉曎に぀いおの説明を行いたしたがここでは敎数や浮動小数点衚瀺の倉曎方法を解説したす

敎数浮動小数点のそれぞれが画面に衚瀺されたりやファむルに曞き出される際の衚瀺圢匏を倉曎すすこずができたす「format_int」「format_float」のそれぞれのコマンドがこれにあたりたす

「format_int」コマンドは敎数を衚瀺する際の衚瀺圢匏「format_float」は浮動小数点の衚瀺圢匏を決定したすこれらのコマンドはスタックから文字列を䞀぀ポップしそれを衚瀺の際のフォヌマットそしお䜿甚したすこのフォヌマット文字列はcafeの内郚でprintf関数にそのたた枡されるためprintf倉換のそれに倣った蚘述である必芁がありたす

䞋に䜿甚䟋を瀺したす

CaFE (empty) % 0xabcd
CaFE (43981) % "0x%X" format_int
CaFE (0xABCD) % "%Xh" format_int
CaFE (ABCDh) % stack
sp[  0] (i)    ABCDh
CaFE (ABCDh) % 10 3 /
CaFE (3.33333) % "%.10lf" format_float 
CaFE (3.3333333333) % stack
sp[  0] (i)    ABCDh
sp[  1] (f)    3.3333333333
CaFE (3.3333333333) % 

どちらのコマンドの堎合もフォヌマットずしお空文字列を指定するこずでデフォルトの状態に戻すこずができたす

CaFE (3.3333333333) % "" format_float 
CaFE (3.33333) % 

##6. ナヌザ・スタック

###6.1 ナヌザ・スタック

泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意
この機胜が远加されたためundoコマンドを暫定的にサポヌトしおたせん20060602
泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意泚意

通垞のスタック(デフォルト・スタック)ずは別にスタックを別に甚意するこずが可胜です
新しいスタックを宣蚀するず珟圚のスタックの䞊に新しいスタックが䜜られたすこのようにしおスタックの䞊に子スタックさらに孫スタックを䜜っおいくこずができたす

新しいスタックが䜜られるずそのスタックには固有のID番号が割り振られたすデフォルトスタックのIDは0ずなっおおりナヌザによっお䜜成されたスタックは1番から順番に数字が぀けられおいきたすスタックのID番号はナヌザの利䟿性のために蚭けられたものであり実際の操䜜にこの番号を䜿うこずはありたせん

「=new」コマンドが新しいスタックを䜜りたすこのスタックはデフォルトスタックず党く同じように䜿うこずができたす

スタック自䜓を操䜜するコマンドはすべお「=」蚘号で始たりたす(デヌタの積み重なった「スタック」をむメヌゞしおいたす)
「=new」コマンドを実行した埌に珟圚のスタックを芋おみるず「=1=」のようにむコヌルで挟たれた数字が衚瀺されたすこれが新しく䜜られたスタックです

メモ :  
	スタックは䞀床䜜られるず参照元が存圚する限りその内容が保持されたすスタック自䜓がどこからも参照されなくなった時に消されたすたずえばナヌザ・スタックがその芪のスタックから消されおも倉数に保存されおいればその内容を保持しおいたす

メモ :  
	スタックのIDはcafeの起動埌の最初の䜜成で1が割り振られ以降䜜成される郜床234のように順番に番号が぀けられおいきたす

新しく䜜成したスタック䞊で蚈算を行うには「=target」コマンドを甚いお察象(タヌゲット)ずするスタックを指定したす=targetコマンドは珟圚のスタックの最䞊䜍が指しおいるスタックぞその察象を切り替えたすいたたで䜿っおいたプロンプト衚瀺ではどのスタックを察象ずしおいるかがわからないのでここで切り替えおおきたしょう

CaFE (empty) % "( =%s= [%p] %b%r%n ) %% " prompt
( =0= [] empty ) % 

###6.2 スタックの切り替え

䞊蚘のプロンプト衚瀺の状態で先に説明したスタックの䜜成切り替えを説明したす

( =0= [] empty ) % 1 2 3
( =0= [2] 3 ) % =new
( =0= [3] =1= ) % stack
sp[  0] (i)    1
sp[  1] (i)    2
sp[  2] (i)    3
sp[  3] (=)    =1=
( =0= [3] =1= ) % =target 
( =1= [] empty ) % stack
( =1= [] empty ) % 

この䟋では新しく䜜られたスタックが珟圚のスタック䞊にどのように眮かれるかを説明するため仮に「1」「2」「3」のデヌタを眮いおみおいたすこのあずの=newによっお䜜られたスタックにはID番号1が䞎えられ先ほどのスタックのデヌタの埌にプッシュされおいたすこの状態で=targetコマンドを発行するず蚈算察象スタックがデフォルト・スタックからID1のスタックに切り替わりたす
これはプロンプト衚瀺を蚭定しおおくずそこで確認できたす新しく䜜られたスタックは垞に空ですここでもID1のスタックが空なのがわかりたす

泚意 :   
	スタック䞊に眮かれたナヌザスタックはその実䜓が眮かれおいるわけではなく「参照先」が指定されおいるだけです
	
メモ :  
	タヌゲット・スタックずなりえるのは垞に䞀぀だけですこれたでに説明したスタック操䜜のコマンド以倖はすべおこのタヌゲットずしおいるスタックに察しおのみ有効ですたずえば「cl」はスタックをクリアする目的で甚意されたコマンドず説明したしたがこのコマンドもその時点でタヌゲットずしおいるスタックに察しおのみ有効です子や孫スタックをタヌゲットずしおいる堎合にはそのスタックの䞭身だけがクリアされたす

=newコマンドで䜜られるスタックは珟圚のスタックの「子」ずなりたす =new=targetコマンドを繰り返すこずで子孫曟孫のようにスタックの䞊にさらにスタックを䜜るこずが可胜です

子スタックから芪スタックを参照するには「=parent」コマンドを䜿いたす=parentコマンドは珟圚の蚈算察象ずしおいるスタックに「芪」スタックを眮いおくれたす(先の「泚意」で述べた通り実䜓ではなく参照先ずしお眮かれたす)ここで=targetを実行するず芪スタックぞの切り替えが行われたすもし=targetがスタック以倖に実行された堎合にはなにも起こりたせん

###6.3 スタック䞊のスタック(参照先ずしおのデヌタ)

先にスタック䞊のスタックは参照先ずしおのデヌタであるこずを述べたしたがもう少し詳しく説明したす
=newコマンドが実行されるず新しくスタックが䜜られたすこのスタックは実䜓が珟圚のスタックの䞊に䜜られるわけではなく別の堎所に実際のデヌタの眮き堎所が䜜られたす䜜成した元のスタックにはIDが衚瀺されたすがこれはあくたでこのスタックを指しおいるIDに過ぎたせん
実隓しおみたしょう

( =0= [] empty ) % =new 
( =0= [0] =1= ) % dup
( =0= [1] =1= ) % stack
sp[  0] (=)    =1=
sp[  1] (=)    =1=
( =0= [1] =1= ) % 

最初に=newコマンドでスタックを䜜りdupコマンドを実行したすdupコマンドによっおできるのはID2のスタックではなくID1のスタックがコピヌされおいたすここたでの操䜜に匕き続いお=targetコマンドを䜿っおID1のスタックを操䜜しおみたす

( =0= [1] =1= ) % =target 
( =1= [] empty ) % 1 2 3
( =1= [2] 3 ) % =parent =target
( =0= [1] =1= ) % stack
sp[  0] (=)    =1=
sp[  1] (=)    =1=
( =0= [1] =1= ) % pop
( =0= [0] =1= ) % stack
sp[  0] (=)    =1=
( =0= [0] =1= ) % =target 
( =1= [2] 3 ) % stack
sp[  0] (i)    1
sp[  1] (i)    2
sp[  2] (i)    3
( =1= [2] 3 ) % 

元のスタックの最䞊䜍にあったID1のスタックを蚈算察象ずするため=targetを実行したした 次にID1のスタックに「1」「2」「3」のデヌタを積んでいたす
その埌=parent に続いお =target を実行し蚈算察象を芪スタックに切り替え元に戻しおいたすたす
stackコマンドを実行するず先ほどず同じように=1=が二぀存圚したすこのうち先ほどスタックを操䜜した䞊䜍偎の方のスタックを珟スタックから消去したす
残った偎のスタックを蚈算察象にしおスタックの内容を確認するず先ほどの内容が残っおいるのがわかりたす぀たりID1のスタックは同じものでありそこぞの参照を䞀぀消しおも内容はそのたた保持されおいるこずがわかりたした

スタックの実䜓は参照されおいる限り残りたす参照ずはたずえばあるスタック䞊にそのスタックが存圚しおいる状態や倉数に保存されおいる状態にあたりたす

###6.4 =targetコマンドの挙動

=target コマンドの実行埌のスタックの状態は䞀定ではありたせん

  • 蚈算察象ずしお子スタックが指定された堎合には芪スタックにはその子スタックが残されたす

  • 蚈算察象ずしお芪スタックが指定された堎合には珟スタックにはその芪スタックぞの参照は残されたせん

    これは=parentが=targetの盎前に実行された堎合ばかりでなく間接的に参照された堎合も適甚されたす
    

子スタックが芪スタックぞの参照を持ちそのスタックぞ子スタックの䞋぀たり孫スタックずしお芪にアクセスするのは埪環参照ずなるため望たしくありたせんこのような理由で芪スタックぞの参照を䞊蚘のように実装しおありたす
たたさらに自身をタヌゲトにする堎合にも

  • 珟スタック自身を明瀺的に指定した堎合にはその参照は残されたす
  • 珟スタック自身を明瀺的に指定しなかった堎合にはスタックの倀は消されたす

###6.5 スタックのコピヌ

先ほどのdupコマンドによる操䜜ではスタックの参照が増えただけでした実䜓は同じもののため片方の内容が倉曎されるずもう䞀方の内容も倉曎されおしたいたす
独立したスタックのコピヌは「=copy」コマンドで䜜るこずができたす=copyコマンドはスタックから二぀の匕数を取りたす最初にポップされたデヌタをコピヌ先埌からポップされた方をコピヌ元ずしたす䞋に䜿甚䟋を瀺したす

( =0= [] empty ) % =new =target
( =1= [] empty ) % 1 2 3 4 5
( =1= [4] 5 ) % =parent =target 
( =0= [0] =1= ) % stack
sp[  0] (=)    =1=
( =0= [0] =1= ) % =new
( =0= [1] =2= ) % stack
sp[  0] (=)    =1=
sp[  1] (=)    =2=
( =0= [1] =2= ) % =target stack
( =2= [] empty ) % =parent =target 
( =0= [1] =2= ) % =copy
( =0= [1] =2= ) % =target stack   
sp[  0] (i)    1
sp[  1] (i)    2
sp[  2] (i)    3
sp[  3] (i)    4
sp[  4] (i)    5
( =2= [4] 5 ) % 

ID1のスタックを䜜成しその䞭に「1」「2」「3」「4」「5」をセットしおいたす
その埌芪スタックに戻り新しい子スタックID2を䜜成その䞭身を確認するず空になっおいたす
=copyを実行したすID1からID2ぞスタックの内容がコピヌされその内容を確認しおいたす

ID1の内容がすべおID2のスタックにコピヌされたした
もし既にID2のスタックにデヌタが存圚した堎合にはID1のデヌタがその埌に远加される圢になりたす

=copyコマンドは子スタックばかりではなく芪スタックや自分自身をその察象に指定できたす
=targetコマンドず同様に自分自身を参照する堎合にはその匕数ずしお非スタックデヌタを指定したす

##7. cafeを制埡する

###7.1 パラメヌタ蚭定

cafeの挙動を決定するパラメヌタはあらかじめ定矩されおいる倉数ぞのアクセスずしお制埡できたす
パラメヌタずしお定矩されおいる倉数はすべお「$$」で始たる名前を持ちたす

たずえばナヌザが意識しおおかないずいけないものに「再垰コヌルの制限」がありたす実行時の䞍甚意なメモリのオヌバヌフロヌを防のが目的です再垰コヌルの制限は「$$RECURSIVE_LIMIT」倉数で蚭定されたす
デフォルト倀は2000です
再垰コヌルの制限倀を倉曎するのは自由ですがプログラムのクラッシュの危険を垞に考えおおかなくおはなりたせん

この倀の倉曎は以䞋のように行いたす

CaFE (empty) % 1000 > $$RECURSIVE_LIMIT
CaFE (empty) %

珟圚の倀をスタックに埗るには反察の䞍等号蚘号を䜿いたす

CaFE (empty) % < $$RECURSIVE_LIMIT
CaFE (1000) %

実際に$$RECURSIVE_LIMITの倀を蚭定する際には「䜕回たで匏を再垰的に評䟡可胜にするか」を蚭定するこずずなるためこの倀が盎接「再垰コヌルの限界数」ずなるわけではありたせん
たずえば最倧公玄数を求める関数「gcd」の䟋では...

1. ifelseの条件が真であれば'% swap gcd'をトヌクンずしお
   評䟡する
2. '% swap gcd'には「gcd」が関数ずしお存圚するのでそのgcdを
   さらに評䟡する

次の再垰コヌルが行われるたでに匏が2回評䟡されたすこのため実際の再垰コヌルは「1000 > $$RECURSIVE_LIMIT」ずした堎合には499回たでずいう制限ずなりたす(500でないのは最初の匏評䟡も1぀めず考えるためです)

操䜜可胜なパラメヌタ倉数の䞀芧を埗るこずもできたすこの時には「>」たたは「<」コマンドに続き「$$」(ドル蚘号2぀のみで名前無し)の倉数を指定するこずで衚瀺されたす

CaFE (empty) % < $$
current mode status
  $$INTERACTIVE_MODE             : 1
  $$GET_STDIN                    : 0
  $$USE_PREFERENCE               : 1
  $$USE_HISTORY                  : 1
  $$PUT_HISTORY                  : 1
  $$RECURSIVE_LIMIT              : 2000
  $$ERROR_DETECTED               : 0
  $$N_HISTORY                    : 500
  $$QUIT                         : 0
  $$FUNC_EXE_ABORT               : 0
  $$FORCE_FUNCTION_RTN           : 0
CaFE (empty) % 

たずえば

1 > $$QUIT

ずするずcafeは終了したす

メモ : これらのパラメヌタの名前を毎回正確に曞くのは面倒なので倉数名の補完機胜を䜿うず䟿利です

###7.2 コマンンドラむンから䜿う

ここたではcafeを察話的に䜿う方法を説明しおきたしたこの節ではcafeを非察話モヌドで䜿甚する方法を説明したす

####7.2.1 コマンドラむン䞊で蚈算を行う

cafeをコマンドラむンで䜿甚する方法を玹介したしょうcafeコマンドに続いお蚈算匏を入力したすこの方法を䜿う堎合にはプロンプトは珟れないのでその結果の衚瀺を明瀺的に指瀺する必芁がありたす

alice:‟ % cafe 3 4 5 - + .
2

最埌のピリオドは結果を衚瀺させるコマンドですcafeを非察話モヌド䜿う堎合にはプロンプトは衚瀺されたせんこのためでピリオド無しでは䜕も衚瀺されずに終了しおしたいたす(ピリオドはスタックの䞀番䞊に眮かれおいる倀を衚瀺するコマンドです)

掛け算を行う際には泚意が必芁ですこのように蚈算匏を曞く堎合にはシェルがアスタリスクを展開しおしたうためcafeに「」が枡らなくなっおしたいたすこのような問題を避けるためには「」を「¥*」ず曞いおやらなくおはなりたせん

alice:‟ % cafe 3 4 5 Â¥* + .
23

####7.2.2 暙準入力を䜿っおファむルから入力

暙準入力を䜿うずファむル入力で蚈算をさせるこずができたすcafeを非察話モヌドで起動するために「-B」オプションを䜿甚したす

alice:‟ % echo '3 4 5 * + .' > test.txt
alice:‟ % cat test.txt
3 4 5 * + .
alice:‟ % cafe -B < test.txt
23

cafeの起動に(オプションスむッチ以倖の)2぀以䞊の匕数がを甚いるず-Bオプションを甚いなくおも自動的に非察話モヌドでの起動ずなりたす[5.2.1]節の䟋ではcafeに䞎えた蚈算匏の各文字が匕数であり合蚈6個の匕数があったために-Bが必芁なかったのです

####7.2.3 ファむルを凊理する

「-f」オプションを甚いおcafeの起動時にファむルを読み蟌たせるこずができたすcafeは起動埌通垞動䜜ずしお「‟/.cafe」ず「‟/.cafe.autopreference」を読み蟌みその埌「-f」オプションで指定されたファむルを読み蟌みたす察話モヌドでは起動埌に「use」コマンドを䜿っおファむルを読み蟌むのず同等です
「-f」オプションは察話モヌドず非察話モヌドのどちらでも䜿うこずができたす非察話モヌドで䜿甚する際は匕数の数に泚意しおください-fオプションの埌に指定されるファむル名はこのオプションスむッチの匕数ずなりcafeの匕数の数にはカりントされたせんこのため-fオプションを甚いおcafeを非察話モヌドで起動する時には-Bを䜿甚した方が安党です

-fオプションは耇数䜿甚するこずができたす-fをファむル名を繰り返し曞くこずで耇数のファむルを読み蟌むこずができたす読み蟌む順序はコマンドラむンに曞かれた逆順右から巊ぞずなりたす
䞋は非察話モヌドで耇数のファむルを凊理する䟋です-Bオプションで非察話モヌドで起動しおいたす

alice:‟ % cat function.txt
: process 22 * ;
alice:‟ % cat test.txt
3 4 5 * + . process .
alice:‟ % cafe -B -f test.txt -f function.txt
23
506

この䟋ではcafeは非察話モヌドで起動はされおいるのですがファむル凊理をの埌に自動的に終了しおくれたせん非察話モヌドを䜿っおも入力を暙準入力から埗るこずを期埅しおいるためファむルの読み蟌み埌暙準入力からEOF(「Control-D」)を入力しなければ察話モヌドず同じようにプログラムが埅っおいる状態になりたす
-fオプションを䜿い暙準入力からはなにも入力しない堎合にはそれをオプション「-!」によっお指定しおやらなければなりたせん䞊蚘のような堎合にはcafeを「cafe -! -B -f test.txt -f function.txt」のように起動したす

####7.2.4 入力の組み合わせ凊理

䞊蚘で説明したようにcafeを非察話モヌドで起動する際にはオプションの指定によっおいく぀かの入力を同時に指定するこずができたす
a. 匕数ずしおの入力
b. 暙準入力
c. -fオプションを甚いたファむル入力
これらはそれぞれ単独で䜿甚するこずも組み合わせお䜿甚するこずもできたす組み合わせお䜿甚する堎合には次のような仕組みで動くようになっおいたす

ステップ1. 起動埌に-fオプション指定のファむルを順番に読み蟌む
ステップ2. ステップ1終了埌匕数ずしお指定された匏をロヌドする
ステップ3. 暙準入力を1行づ぀読み蟌みステップ2でロヌドされた匏を行末に付け足しお蚈算凊理を行う

alice:‟/coding/CaFE2 % cat average.txt
:avg depth >dp aa <dp /;
alice:‟/coding/CaFE2 % cat multiline.txt
5 5 5 5 5 5 6 5 5 5
32 43 54 42 23 32 23 2 54 12 45 11 53
1 2 3 4 5 6 7 8 9 9 9 9 9 9 9 9 9 9 9 9

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1
2 2 2 3 4 5 5 5 5 5 4 3 3 2 1 2 3 4 4 5 5 6 2
alice:‟/coding/CaFE2 % cafe 'avg . cl' -f average.txt < multiline.txt
5.1
32.7692
7.2

1.04167
3.56522
alice:‟/coding/CaFE2 %                 

##8. デバッガ

###8.1 デバッガの起動

関数の振る舞いを怜蚌するためにデバッガが甚意されおいたす
デバッガ機胜の起動には以䞋の二぀の方法がありたす

䞀぀は関数を実行する前に「debugger_enable」コマンドを実行しおおく方法もう䞀぀は関数内に「pause」コマンドを甚意しおおく方法ですこれらのコマンドは実質的にどちらも同じですが「pause」ではデバッガモヌドに入ったメッセヌゞが衚瀺されたす

ここで䟋を瀺しお説明したすたず最初に「test」ずいう名の関数を甚意しその関数をステップ実行しおみたす

CaFE (empty) % :test 10 times 'print A';
CaFE (empty) % debugger_enable 
CaFE (empty) % test
<< in function ""  [prev:"debugger_enable"]  [next:"test"]  [d/r:1/1] [faf=0] >>
debug > 

最初に「test」関数を定矩した埌「debugger_enable」コマンドを実行しおデバッガモヌドを蚭定しおいたすこの埌「test」を実行するずデバッグ・プロンプトが衚瀺され実行が䞀時停止状態ずなっおいたす
このデバッグ・プロンプト衚瀺がされおいる時に「?」キヌを抌すずヘルプが衚瀺されたす

CaFE (empty) % test
<< in function ""  [prev:"debugger_enable"]  [next:"test"]  [d/r:1/1] [faf=0] >>
debug > 
	n        : execute next command
	[return] : execute next command
	[space]  : execute next command
	i        : step into function
	o        : step out from function
	g        : go to next breakpoint
	s        : show stack
	q        : abort from debug mode
	e        : evaluate key input
debug > 

このヘルプ衚瀺はデバッグ・プロンプトで䜿うこずのできるデバッグ・コマンドです
関数の内郚をステップ実行するには「n」リタヌンスペヌスのいずれかのキヌを抌せば良いこずがわかりたす
「g」は実行を続行したす関数内にpauseのコマンドが存圚しなければ関数をすべお実行しお終了したす
「s」は珟圚のスタックの状態を瀺したす
「q」はデバッグモヌドの䞭止cafeの内郚的な゚ラヌを発生させお関数の実行を打ち切りたす
「e」はナヌザのコマンド入力を可胜にしたす

デバッグ・プロンプトの䞊の行には実行状態が衚瀺されおいたすたず「<<」の蚘号に続いお珟圚䞀時停止しおいる関数の名前次に盎前に実行したトヌクン文字列その右暪には次に実行されるトヌクンさらに珟圚の関数実行レベル最埌に関数の実行䞭止フラグです

この䞭の「関数実行レベル」ずは実際に関数をどのレベルで停止させるかずいう倀ず珟圚はどのレベルなのかずいう倀の二぀の数倀から成っおいたす

cafeでは関数が関数を呌ぶこずが蚱されおいたす関数から呌び出す関数は他の関数でも自分自身でも構いたせん呌び出された関数はさらに関数を呌び出すこずができたすここでは関数からさらに呌ばれる関数をより「深い」関数ず呌ぶこずにしたす
関数実行レベルの倀はこの「深さ」を瀺すものです実行レベルの倀が倧きいほどその関数は深い所で実行されおいたす

cafeがナヌザのコマンドを受け付けおコマンドあるいは関数の実行が始たったずき実行レベルは1ずなりたすそこから関数が呌ばれるずその関数は実行レベル2で実行されさらにその関数の䞭から呌ばれた関数は実行レベル3で実行されたす
実行レベル3の関数が終了するず実行は元の関数に戻り実行レベルは2にその関数の実行も終了するず実行レベルは1に順に戻っおいきたす

より深い関数を順次呌び出しながら実行しおいく仕組みをデバッグする際すべおの深さの関数の実行たで監芖するようなこずはあたりないでしょう通垞ある凊理を行う堎合にはその凊理を现かい郚品にわけお共通するものを関数化しお動䜜を確認しその関数をより倧きな関数から呌び出しお䜿うようにしたすすでに実行に問題ないこずが確認されおいる関数を䜿うのであればその内郚の動䜜たでは監芖する必芁はありたせん

デバッグ䜜業のある時点で実行停止䞭に次に実行する関数の内郚たで監芖する必芁があるかあるいは単に䞀぀のコマンドのように実行させるかを遞択できなければ関数を積み重ねた凊理を怜蚌するこずは非垞に難しくなっおしたいたす

このような関数の深さず実行をどの深さの関数で止めるのかを制埡するためにこのような「実行レベル」が䜜られおいたす次のような関数の実行を䟋に芋おみたしょう

CaFE (empty) % :a 0 1+;
CaFE (empty) % :b 2+;
CaFE (empty) % :c 3+;
CaFE (empty) % :d 4+;
CaFE (empty) % :abcd a b c d;

この䟋ではa, b, c, d, abcdの5個の関数が定矩されおいたすここでデバッガモヌドをセットしおabcdずいく぀かのコマンドを実行しおみたす

CaFE (empty) % debugger_enable 
CaFE (empty) % abcd . print ¥nend¥n
<< in function ""  [prev:"debugger_enable"]  [next:"abcd"]  [d/r:1/1] [faf=0] >>
debug > 

次に実行するコマンド/関数が「abcd」ずなっおいる状態でデバッガが埅機しおいたすこの状態で実行レベルは「1/1」になっおいおデバッガに指定された実行を停止レベルが1珟圚のレベルが1ずいうこずを意味しおいたすこの状態で「n」「return」「space」のいずれかのキヌを抌すず「abcd」はその内郚では停止せず実行されおしたいたすabcdが実行された埌には次のトヌクン「.」を凊理する手前で䞀旊停止したす

<< in function ""  [prev:"+"]  [next:"."]  [d/r:1/1] [faf=0] >>
debug > 

これでは関数abcdの内郚の動䜜を芋るこずができたせんこのような時に停止させる深さを䞀぀進めるこずでabcdの関数実行の内郚を芗くこずができるようになりたす先ほどの「.」コマンドの実行を埅぀デバッガの状態から通垞状態ぞ抜けるために「q」キヌを抌しお実行を砎棄通垞のプロンプトに戻りたしょう

メモ : 「q」キヌによる実行の砎棄は関数/コマンドの実行を䞭断し通垞のプロンプト状態に戻すだけで途䞭たで実行した凊理によるスタックや倉数関数定矩等の圱響はそのたた残されたす

<< in function ""  [prev:"+"]  [next:"."]  [d/r:1/1] [faf=0] >>
debug > error : error condition has been thrown to quit from the debugging mode.

10
CaFE (error) % 

先ほどず同じ凊理をデバッガを起動しお実行したす

CaFE (empty) % debugger_enable 
CaFE (empty) % abcd . print ¥nend¥n
<< in function ""  [prev:"debugger_enable"]  [next:"abcd"]  [d/r:1/1] [faf=0] >>
debug > 

先の䟋では「n」「return」「space」でステップ実行をさせたずころでその代わりにステップ・むン・コマンドの「i」を抌しおみたすこうするこずで関数を停止させる深さの指定をを䞀぀進めるこずになりたすこの埌関数abcdが実行されるわけですが停止の指定が2そしお実行レベル2であるこずを認識し実行は関数に入った所で停止したす
その埌ステップ実行を繰り返しおいくず関数abcdの䞭で呌び出される関数が実行レベル2で順次実行されおいくのが芋えたす
関数abcdが終了するず実行レベル1に戻っおくるこずが確認できたす

<< in function "abcd"  [prev:"abcd"]  [next:"a"]  [d/r:2/2] [faf=0] >>
debug > 
<< in function "abcd"  [prev:"+"]  [next:"b"]  [d/r:2/2] [faf=0] >>
debug > 
<< in function "abcd"  [prev:"+"]  [next:"c"]  [d/r:2/2] [faf=0] >>
debug > 
<< in function "abcd"  [prev:"+"]  [next:"d"]  [d/r:2/2] [faf=0] >>
debug > 
<< in function ""  [prev:"+"]  [next:"."]  [d/r:1/1] [faf=0] >>
debug > 

関数実行を途䞭たで監芖しその埌その関数の動䜜を芋る必芁がなくなった時には「o」キヌによるステップ・アりト・コマンドで1段階浅い実行レベルに戻るこずができるようになっおいたす

これから曞く






##APPENDIX

###A1. むテレヌタ

ルヌプ凊理の䞭身をルヌプの倖郚で定矩しお䜿うこずができたす
次の関数は文字列䞭の各文字を数倀ずしお操䜜する関数ですがその䞭で䜿われるルヌプ内の凊理を実行時に指定できるようにしおありたすこの関数は2぀の文字列を取り1぀目は操䜜する文字列2぀目は操䜜する内容を指定したす

:hal >calculation

strlen >length 
s2c 
<length 
times 
'
	c2i <calculation eval i2c rot
' 

<length 1- 
times glue

;

䞋はその実行䟋です

CaFE (empty) % :hal >calculation strlen >length s2c <length times 'c2i <calculation eval i2c rot' <length 1- times glue;
CaFE (empty) % "IBM"
CaFE ("IBM") % "1 -" hal
CaFE ("HAL") % "1 +" hal
CaFE ("IBM") % 

halの䞭身を芋るずスタック䞊の最初のデヌタをcalculationに保存しおいたすここにはどのような蚈算を行うかを指定する文字列が入れられたすその埌その次にスタックに残っおいる文字列の凊理を始めたすが文字列が各文字に分解され凊理が行われる際にcalculationの䞭に保存しおおいた文字列を取り出しその内容に埓っお操䜜が行われたす「"IBM" "1 -" hal」ずするず"IBM"の各文字が1文字づ぀アルファベット順のAの方向にシフトされたす

さらにこれから曞くもの






コマンド䞀芧
倧文字小文字の扱い
割り蟌み(実行の停止)

グロヌバル倉数ずナヌザむンタヌフェヌス実行䞭の通垞倉数の違い
スコヌプ指定したグロヌバル倉数は関数のなかからのみアクセス可胜

About

An RPN calculator

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages