2020年5月18日投稿 / 投稿者 : うつりきまぐれ (りょうたんぽ) / タグ : 投稿プログラム うつりきまぐれ ツール ライブラリ
これは SBDBG をラップして自分のプログラムから取り敢えず文字列からコンパイル・実行できるようにしたライブラリです。 OTY_SBDBG が別にダウンロードされている必要があります。SBDBGLIB には SBDBG.LIB というライブラリがあり、初期化用 DEF で別スロットに読み込みます。
また、このライブラリには私が適当に、ただ勿論便利になるよつに考えた上位互換言語 SB++ を解釈するように SBDBG を改造して読み込む機能があります。というかこちらの方がメインです。元々 SBDBG を直接改造して独自構文を組み込んでいましたが、変更点がわかりづらいのとまたアップデートに対応するため、プログラムからソースコード操作で改変する形にしました。
ところで普通に SB++ を SB にトランスパイルできないことにいま気がつきました。配布された SB++ プログラムを実行するときも SBDBGLIB と OTY_SBDBG がいるというのは鬱陶しいですね...
- LOAD ”SBDBGLIB/SBDBG.LIB”,1
- EXEC 1
- SBDBG_INIT 2,#TRUE
SBDBG_INIT の第1引数は SBDBG を読み込むスロット、第2引数は SB++ を有効にするかを示します。
- DIM SUCCESS=SBDBG_EXEC(”BEEP 70”)
SBDBG_EXEC はプログラムをコンパイルして実行します。パースかコンパイルの時点でエラーが起きた場合は #FALSE 実行が正常に終了した場合は #TRUE を返します。
DEF 式 (DEF expression) は、式中に DEF を記述できる機能です。式中の DEF が評価されると別スロットにランダムな名前の DEF が生成されて、その名前が返されます。
DEF 式は次のように使います。
- DIM FUNC=DEF HELLO
- ? ”こんにちは”
- END
ここで FUNC は文字列変数なので CALL で呼び出したり SPFUNC などに指定することができます。また DEF 式は変数に代入せずに、そのまま引数の中に記述することもできます。
ただし一部のケースでは DEF「文」として解釈されないように、それ自体を囲む括弧がないとエラーとなることがあります。下の例では SPFUNC の2番目の引数が省略されて、次に DEF「文」が続いていると構文解析の都合上解釈されてしまいます。
CALL や RETURN などや SPFUNC などの引数に直接 DEF 式を記述するときは括弧が必須です。ただし (括弧を伴う) 関数の引数に指定する場合や変数に直接代入する場合は曖昧さがないので括弧は必須ではありません。
- ’これはエラー
- SPFUNC SP,DEF
- ...
- END
- ’こうする
- SPFUNC SP,(DEF
- ...
- END)
DEF 式での名前はその内側でのみ参照できます。また、DEF 式内ではその DEF 名と同じ名前のローカルな文字列変数が、その DEF を指すようにセットされています。
また SELF という名前のローカル変数が同様にその DEF を指すため、匿名 DEF でも再帰呼び出しが可能です。( 匿名 DEF については次の項を参照 ) 従って、DEF 式内で SELF という名前の変数を宣言するとエラーとなります。
- DIM FACT=DEF F(X)
- IF X==1 THEN RETURN 1
- RETURN X*CALL(F,X−1)
- END
- ’同じ
- DIM FACT2=DEF(X)
- IF X==1 THEN RETURN 1
- RETURN X*CALL(SELF,X−1)
- END
- ?CALL(FACT,5)
再帰呼び出しの必要がなければ、DEF の直後の名前は省略できます。その場合、関数の括弧や可変長引数や OUT は DEF キーワードの直後に書きます。
- DIM F1=DEF()
- RETURN ”こんにちは”
- END
- ? CALL(F1)
- DIM SUM=DEF * OUT S
- S=0
- DIM I
- FOR I=0 TO DEFARGC()−1
- S=S+DEFARG(I)
- NEXT
- END
引数が 1 で OUT 引数が 0 の匿名 DEF 式は想定通りに動作しません。これは、引数をもたず名前をもつ DEF 式とも解釈されるあいまいな構文になるためです。
- DIM F=DEF A
- ...
- END
この場合は後者の解釈となります。A は DEF 名で、引数はありません。前者のような DEF 式は _ のようなダミーの名前をつけます。この名前は被っていても問題ないので、使用することのないダミーの名前は一律 _ で構わないと思います。
DEF 式は、DEF の外側の変数を参照できます。
- DIM NAME$=”吉野”
- DIM GREET=(DEF _ GREET$
- ? GREET$;”, ”;NAME$;”!”
- END)
- CALL GREET,”ハロー”
上の例のように DEF 式が通常の DEF 内にある場合に、その DEF 内のローカル変数を参照できます。
注意点として、キャプチャ変数が1つ以上あると DEF 式の動作が非常に重いです。タイミングを考えて使いましょう。
完全にグローバルな変数は保存されず、DEF 式の呼び出しの時点の最新の値となります。DEF 式の外のローカル変数の値は保存されて、DEF 式が呼び出されるときに復元されます。ただし、現在の実装は DEF 式が呼び出されるたびにその値が復元されるので、以下のように DEF 式の外のローカル変数を変更して、また次回の呼び出しまで保持されることを意図するプログラムは正しい動作をしません。これはバグなので後に修正します。
- DEF BATTERY()
- DIM S=100
- RETURN (DEF(X)
- S=S−X
- IF S<0 THEN
- ?”バッテリーがきれた”
- ENDIF
- RETURN S
- END)
- END
- DIM USE=BATTERY()
- ? USE(30) ’ 70
- ? USE(58) ’ 42 (!?)
- ? USE(10) ’ 90 (!?)
- ? USE(26) ’ 74 (!?)
DEF 式を直接呼び出すたびに CALL が伴うのは煩わしいですね... そこで 暗黙的な CALL (Implicit CALL) という機能があります。
これは、文字列変数が存在し、その変数が命令や関数であるかのように呼ばれている場合、自動的に CALL に変換する機能です。
- DIM HELLO=DEF
- ? ”こんにちは”
- END
- HELLO
- DIM FACT=DEF F(X)
- IF X==1 THEN RETURN 1
- RETURN X*F(X−1)
- END
- ? FACT(5)
それぞれの DEF 式の呼び出し、また再帰に暗黙的な CALL が使用されています。たとえば最後の行は ? CALL(FACT,5) に変換されます。
UFCS (Unified Function Call Syntax) とはD言語に同名の機能があります。これは FUNC(OBJ,A,B) を OBJ.FUNC(A,B) と書けるというものです。これがそのまま SB++ にあります。
- ? ”あかさたなはまやらわ!”.MID$(2).LEN().SQR()
あんまり意味のないことをしてますが、幾らでもチェーンできます。括弧のネストが減り、視線の方向と処理の流れが一致するため見やすいコードになると思います。
以下のプログラムは USE 呼び出しのたびに S が 100 にリセットされてしまいます。そのうち直します。
投票によってタイムスタンプが更新されないようにしました
この作品に対するコメントがあれば一言どうぞ~。
表示モード : [ スマホ・3DS対応表示 | クラシック表示 ]
PukiWiki 1.4.7 Copyright © 2001-2006 PukiWiki Developers Team. License is GPL. Based on "PukiWiki" 1.3 by yu-ji
ページの処理時間 : 0.115 秒 | このページの最終更新 : 2022/09/20 (火) 12:23:38 (565d) | ログイン
Copyright(C) 2011-2019 プチコンまとめWiki