# NLL

## 製作

坂井弘亮 (KOZOSプロジェクト)

## 概要

NLL(New Learning Language)は学習向け簡易言語HOBBYのNLUX版実装です．

NLUXのreadline(nlline)やlibc(nllibc)と組み合わせることで，システム標準の
ライブラリを一切使わずにビルドすることができます．
(このため極小サイズの実行ファイルを生成可能です)

## チュートリアル

### ダイレクトモード

起動すると，以下のようにコマンドラインが開きます．

	nll> 

ここからいろんなコマンドを入力することで，操作します．

プログラムを書いたり実行したりも，ここからできます．

ここでプログラムを入力することで，即時実行されます．

まずは簡単なプログラムを書いて，実行してみます．

「10」という数値を出すだけのプログラムは，「P.10」と書けます．

Pは表示コマンドです．

つまりこれは「10という値を表示しろ」という意味のプログラムです．

プログラムをnllに入力して，実行してみましょう．

	nll> 

ここに，入力していきます．

まずは「P.10」と入力してEnterキーを押してみます．

これでプログラムが入力され，実行されます．

「P」は，Shiftキーを押しながら「P」のキーを押すと，出てきます．
「.」は，キーボードの右下のほうにあります．

打ち間違えたら，「Back Space」というキーを押すと，戻ります．

	nll> P.11	※打ち間違えたら「Back Space」を押すと戻る
	
	nll> P.1	※１文字，戻った
	
	nll> P.10	※続けて「0」を押すと，修正できる

もしくは矢印キーの「←」や「→」を押すと，入力する位置を変えられます．

「←」「→」「Back Space」をいろいろ押すことで，入力行の内容を変更できます．

Enterキーを押すまでは確定しないので，いろいろ，変更してみてください．

そして「P.10」と入力できたら，Enterキーを押してみます．

	nll> P.10	※「P.10」と入力したらEnterキーを押す
	10
	nll> 

プログラムが実行され，10と表示されました．

これをダイレクトモードと呼びます．

ダイレクトモードでは，プログラムは保存されず，入力したらすぐに実行されます．

### プログラムモード(入力)

プログラムを入力して実行する方法には，プログラムモードというのもあります．

これは，プログラムを入力したら一旦保存して，あとで実行するという方法です．

先頭に行番号を追加して入力すると，入力した行がプログラムとして保存されます．

行番号を10として，「P.100」というプログラムを保存してみます．

「100という値を表示する」というプログラムです．

	nll> 10 P.100	※入力したらEnterキーを押す
	nll> 

これでプログラムが保存されました．

プログラムを保存しただけで，実行はされていません．
(「100」と表示されていません)

これをプログラムモードと呼びます．

LS.で，保存されているプログラムを表示できます．

	nll> LS.
	1 P.100
	nll> 

「P.100」というプログラムが保存されているようです．

しかし行番号は10としていたはずなのに，行番号が1になってしまっています．

行番号は，プログラムの保存や編集のために便宜上つけているものです．

次の説明は，よくわからなければ，後で例を出して説明するので
読み飛ばしても大丈夫です．

- プログラムの保存時には，行番号は保存されません．
- ただし，指定した行番号の順番で保存されます．
- プログラムの表示時には，各行に1から順の行番号が割り当てられます．
- つまり行番号を10として入力してもその行番号は保存はされていません．
- そしてLSで表示するときに，行番号が1から割り当てられます．

### 行入力

入力した行は，保存されています．

上向き矢印のキー(「↑」)を押すと，以前に入力された行の内容が出てきます．

何度も押すと，ずっと遡って出てきます．

	nll> 		※ここで「↑」を押す
	nll> LS.	※以前に入力された行の内容が出てくる
	nll> 10 P.100	※「↑」をもっと押すと，もっと以前の行の内容が出てくる

出てきた行の内容は，左向き・右向き矢印のキー(「←」「→」)によって
カーソルを移動させて編集できます．

これを利用すると，一度入力した行の内容を，入力し直さなくても済ませられます．

これは「ヒストリ」という機能です．

### プログラムモード(実行)

プログラムを入力して保存したので，次はそのプログラムを実行してみましょう．

R.で保存されたプログラムが実行されます．

	nll> R.
	100
	nll> 

プログラムが実行され，「100」と表示されました．

このように，プログラムの入力と実行を別々に行なうのが，プログラムモードです．

### プログラムモード(追加)

実行したプログラムに，さらにプログラムを追加してみましょう．

行番号を指定して入力すると，その行にプログラムが挿入されます．

	nll> LS.
	1 P.100
	nll> 2 P.300	※2行目に追加
	nll> LS.
	1 P.100
	2 P.300		※2行目に追加されました
	nll> 2 P.200	※さらに2行目に追加
	nll> LS.
	1 P.100
	2 P.200		※2行目に追加されました
	3 P.300		※もともとあった2行目は，3行目になりました
	nll> 

プログラムは，上の行から下の行に向かって，順番に実行されていきます．

上の例だと，1行目，2行目，3行目の順に実行されます．

つまりこれは，「100」「200」「300」という数値を順に表示するプログラムです．

実行してみましょう．

	nll> R.
	100
	200
	300
	nll>

「100」「200」「300」という数値が，順番に表示されています．

### プログラムモード(削除)

行番号だけ入力すると，その行が削除されます．

行番号は，削除後にやはり1から順に割り当てられます．

	nll> LS.
	1 P.100
	2 P.200
	3 P.300
	nll> 2		※2行目を削除
	nll> LS.
	1 P.100
	2 P.300		※2行目が削除され，3行目が2行目になりました
	nll> 

実行してみましょう．

	nll> R.
	100
	300
	nll>

「200」を表示する行は削除されたので，「200」は表示されません．

なので，「100」「300」が表示されています．

### プログラムモード(最終行への追加)

行番号を0として入力すると，最終行に追加されます．

	nll> LS
	1 P.100
	2 P.300
	nll> 0 P.200	※行番号を0として入力
	nll> LS.
	1 P.100
	2 P.300
	3 P.200		※ここに追加されました
	nll> 

ちょうど，「200」と「300」を表示する行が入れ替わったことになります．

プログラムは上から順に実行されます．

なので，実行される順番も入れ替わることになります．

実行してみましょう．

	nll> R.
	100
	300
	200
	nll>

「100」「300」「200」という順番で表示されています．

「200」と「300」が表示される順番が，入れ替わっています．

### プログラムモード(変更)

同じ行番号を２つ連続で書いて続けてプログラムを書くと，その行が変更されます．

	nll> LS.
	1 P.100
	2 P.300
	3 P.200
	nll> 1 1 P.150	※1行目を「P.150」に変更
	nll> LS.
	1 P.150		※変更された
	2 P.300
	3 P.200
	nll> 

Eコマンドを使うと，変更したい行がヒストリに格納されます．

これを利用すると，変更したい行を入力し直さなくても済みます．

	nll> E.1	※1行目の内容がヒストリに追加される
	nll> 		※ここで「↑」を押す
	
	nll> 1 1 P.150	※「↑」を押すと，1行目の内容が表示される
	
	nll> 1 1 P.100	※「←」でカーソルを移動し，150を100に修正しEnterを押す
	nll> LS.
	1 P.100		※変更された
	2 P.300
	3 P.200
	nll> 

### プログラムモード(移動)

行番号を２つ連続で書くことで，行を移動できます．

	nll> LS.
	1 P.100
	2 P.300
	3 P.200
	nll> 2 4	※2行目を4行目(つまり，3行目の後)に移動
	nll> LS.
	1 P.100
	2 P.200
	3 P.300		※ここに移動した
	nll> 

移動先の行番号を0にすると，最後の行に移動します．

	nll> 1 0	※1行目を最終行に移動
	nll> LS.
	1 P.200
	2 P.300
	3 P.100		※ここに移動した
	nll> 

※ 行番号に負の値を指定すると，末尾からの位置になります

行番号を２つ連続で書いて，続けてプログラムを書くことで，変更して移動します．

	nll> 3 1 P.150	※3行目を1行目に移動して，さらに「P 150」に変更
	nll> LS.
	1 P.150		※ここに移動して，さらに変更された
	2 P.200
	3 P.300
	nll> 

最後に，nllを終了して終わりです．

nllはEX.で終了します．

	nll> EX.

### プログラムの実行方法

以下は，0から9まで表示するプログラムです．

まずは，以下のように入力してみます．

	nll> 1 L. I,0
	nll> 2 .MAIN
	nll> 3 P. I
	nll> 4 L. I,I+1
	nll> 5 W.
	nll> 6 I<10: G. MAIN
	nll> 7 EN.
	nll> 

プログラムの意味は後で説明します．

まずはプログラムを実行してみましょう．

Rで，保存してあるプログラムが実行されます．

	nll> R.
	0
	1
	2
	...		※１秒おきに表示されていきます

１秒おきに数字が表示され，9まで出ると終了します．

	nll> R.
	0
	1
	2
	...
	9
	nll>

プログラムは保存されているので，何度でも実行できます．

	nll> R.
	0
	1
	2
	...		※再度，実行されています

実行中にCtrl＋Cを押すと，実行を中断します．

Ctrl＋Cというのは，Ctrlキーを押しながらCのキーを押します．

	nll> R.
	0
	1
	2
	3
				※ここでCtrl＋Cを押しました
	Break at: I<10: G. MAIN	※この行で実行を中断しました
	nll>

3が表示されたときに，Ctrl+Cを押して実行を中断しました．

中断時にも，変数の値などをダイレクトモードで確認できます．

	nll> P. I
	4
	nll> 

変数Iが4になっているところで，実行が中断されたようです．

Sで１命令ずつ実行を進められます．これをステップ実行といいます．

	nll> S.			※実行を１命令進める
	
	Step break at: .MAIN	※「MAIN」の位置に実行が戻り，実行が中断
	nll> S.			※さらに実行を１命令進める
	
	Step break at:  P. I	※１命令を実行したところで，実行が中断
	nll> S.			※さらに実行を１命令進める
	4			※「P I」が実行され，Iの値が表示される
	
	Step break at:  L. I,I+1
	nll> S.			※さらに実行を１命令進める
	
	Step break at:  W.
	nll> P. I
	5
	nll>			※Iが1増えて，5になっている

Cで実行を再開できます．

	nll> C.
	5
	6
	7
	8
	9
	nll> 

5が表示されるところから実行を再開し，9まで表示されました．

それでは，プログラムの意味を説明します．

プログラムを表示させてみましょう．

	nll> LS.
	1 L. I,0		※変数Iに0を代入する
	2 .MAIN			※ジャンプ先のラベル(目印なので実行されない)
	3 P. I			※変数Iの値を表示
	4 L. I,I+1		※変数IにI+1の結果を代入(つまり変数Iが1増える)
	5 W.			※１秒待つ
	6 I<10: G. MAIN		※変数Iが10より小さければMAINに戻る(ジャンプ)
	7 EN.			※実行を終了する
	nll> 

プログラムは，行番号の順に，上から順に実行されます．

上のプログラムの場合は，以下のような順番で実行されます．

1. まず，変数Iに0が入る
2. ラベルは実行されないのでそのまま進む
3. 変数Iの値を表示する
4. 変数Iの値が1増える
5. １秒待つ
6. 変数Iが10より小さければ2に戻る．そうでなければ7に進む
7. プログラムの実行を終わる

6のところで変数Iの値によって，2に戻ります．

このため，2から6の間を何度も実行することになります．

変数Iの値が10になったら，2に戻らずに7に進んで，実行を終了します．

## 文法事項

### コマンドの省略表記

コマンドは省略表記ができます．
省略表記の際には，終端に「.」を付加します．

	L. I, 1	※ LET I, 1 と同じ
	P. I	※ PRINT I と同じ

### コマンドの連結

「;」でコマンドを連結できます

	L. I, 0; .MAIN; P. I; L. I, I + 1; I < 10: G. MAIN

### 空白文字

変数名などが判別できる範囲で，空白文字(スペースやタブ文字)は省略できます

	L.I,0;.MAIN;P.I;L.I,I+1;I<10:G.MAIN

※ LET I を LETI のようにすることはできません(変数名と区別できなくなるため)
※ L. I を L.I のようにすることはできます．

### 変数名・ラベル名

変数名とラベル名は32文字までです．

先頭は英字，２文字目以降は英数字です．(A, AB, B0, BC1, CD12 など)

※ 変数名・ラベル名には日本語も利用できますが，文字コードの変換は行われません．
このため文字コード違いによる混乱の原因になるため，推奨しません

### 大文字・小文字

小文字は大文字に変換されて保存・実行されます．(文字列はそのままです)

このため，小文字と大文字の区別はありません．
(「print abc」や「Print Abc」のような表記は，「PRINT ABC」に変換されます)

### LETでの演算

LETでは，変数への代入ができます．

以下はB+Cの結果を変数Aに代入します．

	LET A, B + C

LETには演算式を書くことができます．さらに「=」は代入の演算なので，以下のように
することでも，変数Aに値を代入することができます．

	LET A = B + C

LETを省略して，以下のように演算式のみを書くこともできます．

	A = 1
	B = 2
	C = A + B

これらは，以下のように書くこともできます．

	LET A, 1
	LET B = 2
	LET C = A + B

### 条件プレフィックス

コマンドには以下のようにコロンで区切って，条件式を記述できます．

	(I > 0): LET A, I

条件式がある場合には，その条件を満たすときのみ実行されます．

例えば以下は，Iの値が10未満のときのみ，MAINにジャンプします．

	(I < 10): GOTO MAIN

LETと組み合わせることで，様々な数式や関数を実行することができます．

	(I < 10): LET A = B + C		※I<10 のときにA=B+Cを実行
	(I < 10): LET FPRINT(I)		※I<10 のときにFPRINT(I)を実行
	(I < 10): LET (I = 0, J = 0)	※I<10 のときにI=0とJ=0を実行

これは，以下のようにLETを省略して書くこともできます．
※ 条件式後のコマンドを省略すると，ARGSコマンドがあるとみなされます．
ARGSコマンドは与えられた式を演算するだけのコマンドです．

	(I < 10): A = B + C		※I<10 のときにA=B+Cを実行
	(I < 10): FPRINT(I)		※I<10 のときにFPRINT(I)を実行
	(I < 10): (I = 0, J = 0)	※I<10 のときにI=0とJ=0を実行

他のコマンドと組み合わせることで，以下のようなことができます．

	(I>10): END			※I>10 のときに実行終了
	(I>10): STOP			※I>10 のときに実行停止

### ループ

ループはLOOP/LOOPENDで行なうことができます．

	1 LOOP I, 10	※変数Iの値を変えながら10回ループして繰り返し
	2 P. I
	3 LOOPEND I	※LOOPからここまでを繰り返す

以下のようにすると，変数Iの値を細かく指定できます．

	1 LOOP I, 100, 10, 2	※10から始まり，2ずつ増やしながら100回繰り返し
	2 P. I
	3 LOOPEND I

FOR/NEXTでもループができます．こちらはループ継続の条件式などを書くことが
できます．

	1 FOR I=0, I<10, ++I	※最初にI=0を実行，++IをしながらI<10となっている間だけループ
	2 P. I
	3 NEXT

FORの条件式などは省略できます．またNEXTには繰り返し時に実行する式を書けます．

	1 I=0
	2 FOR ,I<10,	※I<10の間だけ繰り返し
	3 P.I
	4 NEXT ++I	※繰り返すたびにIを1ずつ増やす

### ラベルへのジャンプ

ラベルは先頭に「.」を付けて配置します．
GOTO等でラベルにジャンプできます．

	1 GOTO SUBR	※SUBRにジャンプ
	2 P. "NG"	※ここは実行されない
	3 .SUBR		※ここにジャンプ
	4 END

	1 I = 0		※Iを0にする
	2 .SUBR
	3 P. I
	4 ++I		※Iを1増やす
	5 GOTO SUBR	※Iを1ずつ増やしながらSUBRにジャンプ(無限ループ)

### サブルーチン

GOSUB/RETURNでラベルをサブルーチン呼び出しすることができます．

	1 GOSUB SUBR	※RETURNでの戻り先を保存してSUBRにジャンプ
	2 P. "end"	※RETURNされるとここに戻る
	3 END		※実行を終了
	4 .SUBR		※サブルーチンのラベル
	5 P. "subr"
	6 RETURN	※GOSUBの次の命令に戻る

### 引数渡しと戻り値

GOTO/GOSUBでのラベルへのジャンプ時に，引数を渡すことができます．

	1 GOTO MAIN,1		※SUBRに引数として1を渡す
	2 END
	3 .MAIN X		※引数をXで受け取る(Xは1となる)
	4 P.X

RETURNで戻るときに値を返すことができます．

	1 GOSUB SUBR, 1, A	※SUBRに１を渡し，返り値をAで受け取る
	2 P.A			※返り値はAで受け取るため，AはX+1となる
	3 END
	4 .SUBR X		※引数をXで受け取る(Xは1となる)
	5 P.X
	6 RETURN X+1		※返り値としてX+1を渡す

値を()でくくることで，複数の値を渡せます．

	1 GOTO MAIN, (1,2,3)
	2 END
	3 .MAIN(X,Y,Z)		※X=1,Y=2,Z=3になる
	4 P.X; P.Y; P.Z

RETURNで複数の値を返すこともできます．

	1 GOSUB SUBR, (1,2,3), (A,B,C)	※1,2,3を渡し，返り値をA,B,Cで受け取る
	2 P.A; P.B; P.C		※A=2,B=3,C=4が返る
	3 END
	4 .SUBR(X,Y,Z)		※X=1,Y=2,Z=3になる
	5 P.X; P.Y; P.Z
	6 RETURN (X+1,Y+1,Z+1)	※2,3,4を返す

なお変数はすべてグローバル変数で，スコープというものはありません．
このため上の変数A,B,Cは，サブルーチンの中からも参照できますし，
変数X,Y,Zはサブルーチンの外からも参照できます．
(そもそもサブルーチンには，その中や外という区別はありません)

### サブルーチンの関数呼び出し

サブルーチンは関数として，式の中から呼び出して戻り値を利用することができます．

例えば以下は，加算を行うサブルーチンを関数として呼び出す例です．

	1 A = 10; B = 20
	2 C = SUBR(A, B)	※サブルーチンを関数として呼び出し戻り値を受け取る
	3 PRINT C
	4 END
	5 .SUBR(X, Y)
	6 RETURN X + Y

戻り値を複数返すこともできます．以下は割算の商と余りを返す例です．

	1 A = 123; B = 10
	2 (C, D) = SUBR(A, B)
	3 PRINT C; PRINT D
	4 END
	5 .SUBR(X, Y)
	6 RETURN (X / Y, X % Y)

引数を与えない場合には，空の引数を指定します．
(以下の「()」を省略することはできません)

	A = SUBR()

ただし関数呼び出しされたサブルーチンの内部では，ステップ実行や実行中断，
CONTINUEによる実行再開，EXITによる実行終了などができません．
(関数呼び出しは基本として１つの演算として扱われるため，その中で実行中断したり
実行再開したりすることはできず，関数呼び出しから返った後で実行中断されます)

これが不都合ある場合には，GOSUBによってサブルーチン呼び出ししてください．
(GOSUBによる呼び出しでは，そのような制限はありません)

### サブルーチンの関数呼び出しでのローカル変数

変数はすべてグローバル変数で，スコープはありません．
また，関数に関数内や関数外の区別は無いので，関数内のみ使えるローカル変数と
いうものはありません．

ローカル変数のような扱いをしたい場合には，以下のようにPUSHを使うことで，変数の
値をスタックに保存して，関数内のみのローカル変数のように扱うことができます．

	1 A=1
	2 GOSUB SUBR
	3 P.A
	4 END
	5 .SUBR
	6 PUSH A	※ Aの値をスタックに保存
	7 A = 10	※ Aの値を書き換える
	8 P.A
	9 POP A		※ Aの値をスタックから復旧
	10 RETURN

関数の引数は，以下のように+/-で保存と復旧ができます．

	1 A=1; B=2
	2 (D, C) = SUBR(10, 20)
	3 P.A; P.B		※ A,Bは復旧して1,2が表示される
	4 P.C; P.D		※ 変更された値の11,21が返ってきている
	5 END
	6 .SUBR(A+, B+)	※ A,Bの値をスタックに保存
	7 A++; B++		※ A,Bの値を変更
	8 P.A; P.B		※ 11,21が表示される
	9 RETURN (B-, A-)	※ A,Bの値をスタックから復旧

### ラベル無しでのジャンプ

GONEXTを利用することで，ラベル無しでジャンプすることができます．

GONEXTで次の行の先頭にジャンプします．GONEXT 0 で現在の行の先頭に戻ります．
GONEXT 2 で２行先の先頭にジャンプします．
GONEXT -1 でひとつ前の行に戻ります．

	(I>10): GONEXT; P.A; P.B; P.C	※I>10のときは後続コマンドを実行しない
	P.I; I=I+1; (I<10): GONEXT 0	※Iが10になるまでループ

GONEXT 2,3 のようにすると，2行先の3つ目のコマンドにジャンプします．
(行末に達した場合には，さらに次の行に繰り越してジャンプします)

GONEXT ,3 のようにすると，現在のコマンド(GONEXT)の3つ先のコマンドにジャンプ
します．

	P.0; GONEXT 0,3; P.1; P.2; P.3	※ P.2の位置にジャンプ(行先頭から数えて3番目)
	P.0; GONEXT ,2; P.1; P.2; P.3	※ P.2の位置にジャンプ(GONEXTから数えて2番目)

	1 P.0; GONEXT 1,5; P.1; P.2	※ P.8の位置にジャンプ(1行先の先頭から数えて5番目)
	2 P.3; P.4; P.5; P.6
	3 P.7; P.8; P.9

	GONEXT,0			※ GONEXT自身にジャンプ(無限ループ)

GONEXTで，条件分岐で複数のコマンドを実行するようなこともできます．
以下はI>10を満たすときはD,E,Fを表示し，満たさないときはA,B,Cを表示します．

	1 (I>10): GONEXT; P.A; P.B; P.C; GONEXT 2
	2 P.D; P.E; P.F

### ループ／サブルーチンからの抜け出し

LOOP/FORによるループやGOSUBによるサブルーチン呼び出しでは，
LOOPEND/NEXT/RETURNでの戻り先を保存します．(スタック構造で保存します)

このため，以下のようにしてLOOPENDによる終了をせずにLOOPの途中から抜け出すと，
戻り先が残ってしまいます．

	1 LOOP I, 10
	2 (I == 5): GOTO MAINEND
	3 LOOPEND
	4 .MAINEND
	...

これにより，LOOPENDやNEXTによるループの対応がうまくとれなくなります．

	1 LOOP I, 100; P. I
	2 LOOP J, 10; GONEXT; LOOPEND
	3 LOOPEND		※ Iに対するLOOPENDが，Jに対して行なわれる

これを防ぐには，以下のようにしてDISCARDを呼び出すことで，保存している戻り先を
破棄します．

	1 LOOP I, 10
	2 (I == 5): DISCARD
	3 (I == 5): GOTO MAINEND
	4 LOOPEND
	5 .MAINEND
	...

GOSUBにも，以下のように同様に使えます．

	1 GOSUB SUBR
	2 END
	3 .SUBR
	4 (I == 10): RETURN
	5 DISCARD
	...

DISCARDに個数を指定すると，指定した個数の戻り先を破棄します．

これを利用して，２重ループ等から抜け出すこともできます．

	1 LOOP I, 10; LOOP J, 20
	2 (A[I][J] == 1): LET FOUND = 1
	3 FOUND: GOTO MAINEND
	4 LOOPEND J; LOOPEND I
	5 .MAINEND
	6 FOUND: DISCARD 2	※ LOOP I / LOOP J の２つの戻り先を削除
	...

### データの読み込み

DATAでデータを定義し，DREADで読み込むことができます．

	1 FOR I=0, I<10, I++
	2 DREAD A
	3 PRINT A
	4 NEXT
	5 DATA 1,2,3,4
	6 DATA 5,6,7,8
	7 DATA 9,10

DFROMで，読み込む位置を指定できます．

	1 DFROM DATA0; DREAD A,B,C; PRINT A,B,C
	2 DFROM DATA1; DREAD A,B,C; PRINT A,B,C
	3 .DATA0
	4 DATA 1,2,3
	5 .DATA1
	6 DATA 4,5,6

## 演算表記

### 数値の表現

数値は通常は10進数ですが，0で始めると8進数，0xで始めると16進数，0bで始めると
2進数になります．

	A = 0x10	※ Aに16(16進数の10)が格納される
	A = 0b10000	※ Aに16(2進数の10000)が格納される

1文字の文字は，''でくくることで表現します．この型は整数になります．

	C = 0x41	※ Cに0x41が格納される
	C = 'A'		※ Cに'A'のASCIIコードの0x41が格納される

### 演算子

以下の演算子が使えます．
※ 一覧は DUMP L_OPERATOR コマンドで参照できます

- 単項の演算

	I	Iが0でない場合に満たされる
	!I	Iが0の場合に満たされる
	++I	インクリメント(1増やす)
	--I	デクリメント(1減らす)
	I++	ポストインクリメント(演算後に1増やす)
	I--	ポストデクリメント(演算後に1減らす)
	+I	プラス符号
	-I	マイナス符号
	I+	スタックに保存
	I-	スタックから復旧
	~I	ビット反転
	#I	サイズ(文字列では文字列長，ベクトル値では要素数など)
	(1,%(2,3),4)	ベクトル値を展開
	?I	真偽値(値が0のとき0，0以外のとき1)
	(),{}	括弧内を優先的に演算
	(1,2,3)	ベクトル値(要素数が１なら通常の値)
	{1,2,3}	ベクトル値(要素数が１でもベクトル化)

- ２項の演算

	A + B	足し算
	A - B	引き算
	A * B	かけ算
	A / B	割算
	A % B	割算の余り
	A << B	左シフト
	A >> B	右シフト
	A += B	足し算して代入
	A -= B	引き算して代入
	A *= B	かけ算して代入
	A /= B	割算して代入
	A %= B	割算の余りを代入
	A <<= B	左シフトして代入
	A >>= B	右シフトして代入
	(I==0) && (J==0)	論理積(左辺の値に限らず，右辺は演算されます)
	(I==0) || (J==0)	論理和(左辺の値に限らず，右辺は演算されます)
	(I==0) &> (++J>0)	論理積(左辺の値が真のときに右辺は演算されます)
	(I==0) |> (++J>0)	論理和(左辺の値が偽のときに右辺は演算されます)
	(I==0) ! I++		条件実行(左辺の値が真のときに右辺は演算されます)
	A=0,B=0	連続して実行

- 比較

	A < B	比較
	A > B	比較
	A <= B	比較
	A >= B	比較
	A == B	比較
	A != B	比較
	A <> B	比較
	A === B	ベクトル値の比較
	A !== B	ベクトル値の比較

- ビット演算

	A ^ B	ビットXOR
	A & B	ビットAND
	A | B	ビットOR
	A ^= B	ビットXORして代入
	A &= B	ビットANDして代入
	A |= B	ビットORして代入

- 特殊な演算

	A ? (B,C)	Aが0でない場合にBに，0の場合にCになる
	A ? (++I,++J)	Aが0でない場合に++Iが，0の場合に++Jが行われる(指定された要素のみ評価される)
	A ? {++I,++J}	Aが0でない場合に１つ目の値，0の場合に２つ目の値になる(すべての要素が評価される)
	A ? FARGS(B,C)	Aが0でない場合に1個目の戻り値，0の場合に2個目の戻り値になる
	A @ (B,C,D)	Aが0のときはB，1のときはC，2のときはDになる
	A @ (++I,++J,++K)	Aが0のときは++Iが，1のときは++Jが，...行われる(指定された要素のみ評価される)
	A @ {++I,++J,++K}	Aが0のときは１つ目の値，1のときは２つ目の値，...になる(すべての要素が評価される)
	A @ FARGS(B,C,D)	Aが0のときは1個目の戻り値，1のときは2個目の戻り値，...になる
	(A,B,C).N	Nが0のときはA，1のときはB，2のときはCになる(A,B,Cはすべて評価される)

- 整数・文字列・配列・ポインタに使える演算

	B ?= A	代入し型を固定
	B @= A	エイリアス
	A = B	代入

- 文字列に対する演算

	S	文字列が空でない場合に満たされる
	!S	文字列が空の場合に満たされる
	S + T	文字列の連結
	S += T	文字列を連結して代入
	S < T	比較(辞書順)
	S > T	比較(辞書順)
	S <= T	比較(辞書順)
	S >= T	比較(辞書順)
	S == T	比較(辞書順)
	S != T	比較(辞書順)
	S <> T	比較(辞書順)

- 配列に対する演算

	++A	インクリメント(1増やす)
	--A	デクリメント(1減らす)
	A++	ポストインクリメント(演算後に1増やす)
	A--	ポストデクリメント(演算後に1減らす)
	A + 1	配列加算
	A - 1	配列減算
	A += I	配列加算して代入
	A -= I	配列減算して代入
	A[B]	配列参照
	A < B	配列比較
	A > B	配列比較
	A <= B	配列比較
	A >= B	配列比較
	A == B	配列比較
	A != B	配列比較
	A <> B	配列比較

- ポインタに対する演算

	++P	インクリメント(1増やす)
	--P	デクリメント(1減らす)
	P++	ポストインクリメント(演算後に1増やす)
	P--	ポストデクリメント(演算後に1減らす)
	P + 1	ポインタ加算
	P - 1	ポインタ減算
	P += I	ポインタ加算して代入
	P -= I	ポインタ減算して代入
	*P	ポインタ参照
	P->N	ポインタの指す先がベクトル値の場合，ベクトル値のN番目の要素
	&I	ポインタ値
	A < B	ポインタ比較
	A > B	ポインタ比較
	A <= B	ポインタ比較
	A >= B	ポインタ比較
	A == B	ポインタ比較
	A != B	ポインタ比較
	A <> B	ポインタ比較

- 浮動小数に対する演算

	F	Fが0.0でない場合に満たされる
	!F	Fが0.0の場合に満たされる
	++F	インクリメント(1.0増やす)
	--F	デクリメント(1.0減らす)
	F++	ポストインクリメント(演算後に1.0増やす)
	F--	ポストデクリメント(演算後に1.0減らす)
	+F	プラス符号
	-F	マイナス符号
	F + G	足し算
	F - G	引き算
	F * G	かけ算
	F / G	割算
	F += G	足し算して代入
	F -= G	引き算して代入
	F *= G	かけ算して代入
	F /= G	割算して代入
	F < G	比較
	F > G	比較
	F <= G	比較
	F >= G	比較
	F == G	比較
	F != G	比較
	F <> G	比較

### 連続した代入

AとBとCをすべて０にしたい場合には，以下のように書けます．
(代入式の演算結果は，代入した値になるためです)

	A = B = C = 0

### ベクトル値

複数の式を()でくくってカンマで区切ると，複数の値によるベクトル値になります．

例えば以下は，XとYに1と2を代入します．

	(X,Y) = (1,2)

以下のようにすることで，値の入れ換えができます．

	(X,Y) = (Y,X)

値を複数返す関数は，以下のようにして値を受け取ることができます．

	(X,Y) = GETPOS()

以下のような演算もできます．

	(A,B) = (X,Y) + (1,2)	※ A = X + 1, B = Y + 2 と等価
	++(X,Y)			※ ++X, ++Y と等価
	(X,Y) = ((COS(R)*X+SIN(R)*Y), (COS(R)*Y-SIN(R)*X))	※ 回転変換

### 式の条件実行

複数の式を!や&>で連続して書くと，左の演算の結果が真(0以外)のときのみ，
右の演算をします．

例えば以下は，Iが10未満のときのみJに20を代入します．

	(I < 10) ! (J = 20)
	(I < 10) &> (J = 20)

これは，以下のように書くこともできます．
(ただしわかりにくくなるので，カッコでくくることを推奨します)

	I < 10 ! (J = 20)

ベクトル値を用いることで複数の式を書けるため，以下のように組み合わせることで
条件を満たしたときに複数の処理を実行することができます．

	(I < 10) ! (I = 10, J = 20)

&>はベクトル値の場合には要素ごと，!はベクトル値はベクトル値として演算します．
以下はIが10未満のときに，IとJを表示します．

	(I < 10) ! (FPRINT(I), FPRINT(J))

以下はIが0以外のときにIを表示，Jが0以外のときにJを表示します．
(IとJが要素ごとに演算されます)

	(I, J) &> (FPRINT(I), FPRINT(J))

これを関数と組み合わせて利用すると，特定の条件のときのみ関数を呼び出すような
ことができます．

以下は，Iが10未満のときのみIの値を表示します．

	(I < 10) ! FPRINT(I)

以下は，Iが10未満のときに++Jを行い，さらにJが20未満のときのみIとJの値を表示
します．

	(I < 10) ! (++J < 20) ! FPRINT(I,J)

### 変数のエイリアス

以下のようにすると，変数Bは変数Aと同じ実体になります．
つまり変数Bは，変数Aの別名(エイリアス)となります．

	B @= A

変数Bへの代入や演算は，変数Aに対するものと同じようになります．

	A = 10
	B @= A
	B = 20		※ 変数Aに20が代入される
	P. A		※ 20が表示される

### 組み込み変数

以下の変数は固定値を持つものとして，値が組み込まれています．
(利用すると自動的にその固定値になります)
※ 以下は一部です．一覧は DUMP L_CONST コマンドで参照できます

例えば以下のように利用することで，円周率が利用できます．

	RAD = DEG * 2.0 * M_PI / 360.0

- 標準的に利用されるもの

	ARGC		nll起動時のコマンドライン引数の数
	ARGV[n]		nll起動時のコマンドライン引数
	VERSION		バージョン情報
	UNDEF		未定義(Undefined)の値
	NULL		NULL値
	NULLSTR		NULL文字列
	NULLARRAY	NULL配列
	NULLMEM		NULL領域
	NULLPTR		NULLポインタ
	NULLFUNC	NULL関数
	NULLLABEL	NULLラベル

	T_UNDEFINED	未指定
	T_NULL		NULL型
	T_VALUE		参照型
	T_VECTOR	ベクトル型
	T_INTEGER	整数型
	T_STRING	文字列型
	T_FLOAT		浮動小数型
	T_ARRAY		配列型
	T_AREA		領域型
	T_POINTER	ポインタ型
	T_FUNCTION	関数型
	T_LABEL		ラベル型

- ファイル関連

	O_RDONLY	ファイルオープン時のモード(読み込みのみ)
	O_WRONLY	ファイルオープン時のモード(書き込みのみ)
	O_RDWR		ファイルオープン時のモード(読み書き)
	O_ACCMODE	ファイルモードのマスク
	O_APPEND	ファイル終端に追加
	O_CREAT		ファイルを新規作成
	O_TRUNC		ファイルを空にする
	O_TEXT		テキストモード(Windows版のみ)
	O_BINARY	バイナリモード(Windows版のみ)
	SEEK_SET	ファイル位置
	SEEK_CUR	ファイルの現在位置からの相対位置
	SEEK_END	ファイル終端からの相対位置

- 数学関連

	M_E		logの底のe
	M_PI		円周率

- ネットワーク関連

	INADDR_ANY		0.0.0.0
	INADDR_BROADCAST	255.255.255.255
	INADDR_LOOPBACK		127.0.0.1
	IN6ADDR_ANY		::
	IN6ADDR_LOOPBACK	::1

- ソケット関連

	AF_UNIX		socket()オープン時のドメイン
	AF_INET		socket()オープン時のドメイン
	AF_INET6	socket()オープン時のドメイン
	SOCK_STREAM	socket()オープン時のタイプ
	SOCK_DGRAM	socket()オープン時のタイプ
	SHUT_RD		shutdown()の引数
	SHUT_WR		shutdown()の引数
	SHUT_RDWR	shutdown()の引数

## 整数以外の型

### 文字列

文字列は""でくくることで表現します．

	PRINT "TEST"

\Nや\nは改行になります．

	PRINT "TEST\N"

文字列は変数に代入できます．

	S = "TEST"
	PRINT S

文字列は「+」で連結できます．

	A = "ABC"
	B = "DEF"
	PRINT A + B

文字列は「==」や「>」で比較できます．
(「==」の場合は文字列の一致，「>」「<」などの場合は辞書順での比較をします)

文字列の長さは65536文字までです．

### 変数の型

変数は，代入することで型が決まります．
新たな型を代入しなおすと型は変更されます．
配列の場合は，要素ごとに型が決まります．

例えば以下の場合は，変数Aは整数型になり，その後に文字列型になります．

	1 A = 1		※Aは整数型になる
	2 A = "STR"	※Aは整数型から文字列型に変更される

NEWで変数を初期化できます．

	1 A = 1		※Aは整数型になる
	2 NEW A		※Aが初期化される(型は未定義になる)
	3 A = "STR"	※Aは文字列型になる

「?=」で代入するとそのときの型に固定され，他の型を代入できなくなります．
(NEWで初期化することで，再代入できるようになります)

	1 A = 1
	2 A ?= 10	※Aは整数型に固定される
	3 A = "STR"	※Aは整数型に固定されているので，この代入はエラー

RUNによる実行開始時には，すべての変数は初期化されます．

RUN 0 とすると，初期化のみ行います．

### 浮動小数

小数点を付けることで，浮動小数を扱えます．

	1 F = 1.5
	2 F2 = 1.25
	3 PRINT F * F2
	4 PRINT SIN(F)

### 配列

配列はDIMで作成します．

以下はA[0]〜A[9]が利用可能になります．
(A[0]を先頭として要素数10の配列を獲得するので，A[0]〜A[9]となります)

	DIM A, 10

以下はA[0][0]〜A[10][20]の２次元配列が利用可能になります．

	DIM A, 10, 20

以下のようにすると，部分的に配列を作成することができます．

	1 DIM A, 10
	2 DIM A[2], 20	※A[2][0]〜A[2][19]が利用可能になります

以下のようにすると，４次元以上の配列が作成できます．

	1 DIM A, 2, 2, 2
	2 LOOP I, 2; LOOP J, 2; LOOP K, 2
	3 DIM A[I][J][K], 2
	4 LOOPEND; LOOPEND; LOOPEND

配列を代入した場合には，内容はコピーされずに同じ配列を指すものになります．

	1 DIM A, 10
	2 B = A
	3 A[0] = 10
	4 PRINT B[0]	※BとAは同じ実体なので「10」が表示される

配列を加算・減算すると，その位置からの配列になります．
(配列どうしを減算すると，位置の差分になります)

	1 DIM A, 10
	2 B = A + 3
	3 B[0] = 10
	4 PRINT A[3]	※B[0]とA[3]は同じ実体なので「10」が表示される
	5 PRINT B - A	※BとAの差分の「3」が表示される

配列は以下で解放されます．

	NEW A		※配列Aをすべて解放
	NEW A[10]	※配列Aの，A[10]以降の要素を部分的に解放

配列は各要素が別の型になっても構いません．例えば以下のように，整数と文字列が
混在しても構いません．

	1 DIM A, 10
	2 A[0] = 1	※A[0]は数値
	3 A[1] = "test"	※A[1]は文字列
	4 DIM A[2], 20	※A[2]は２次元配列
	5 A[2][0] = 10	※A[2][0]は数値

### ポインタ

ポインタ(他の値を指すことができる型)を定義できます．

	1 A = 10
	2 P = &A	※ PはAを指す型になる
	3 *P = 20	※ Pの指す先(つまり，A)に20が代入される
	4 P. A		※ 20が表示される

配列に対してポインタを設定することもできます．

	1 DIM A, 5; LOOP I, 5; A[I] = I+1; LOOPEND
	2 P = &A
	3 P. *P		※ 配列全体が表示される
	4 P++		※ ポインタを加算する
	5 P. (*P)[0]	※ ２つ目の「2」が表示される

ポインタに対して以下のような演算もできます．

	++P		※ ポインタPを１進める
	P = P + 3	※ ポインタPを３進める
	P = P - 1	※ ポインタPを１戻す
	D = P1 - P0	※ ポインタP1とP0の差をDに格納する
	(P1 > P0): GN.	※ ポインタP1がP0より先にあるなら次の行にジャンプ

### NULL値

以下のようにNULLを代入すると，何も指さない値(NULL値)になります．

	1 P = NULL

以下のような演算もできます．

	(P==NULL): GN.	※ PがNULL値なら次の行にジャンプ

### ベクトル値

変数にはベクトル値を保存できます．
(１次元のベクトル値はスカラー値として扱われます)

	1 A = (1,2,3)		※ 変数Aに(1,2,3)というベクトル値を代入
	2 PRINT A		※ 「(1,2,3)」が表示される

ベクトル値の中にベクトル値を入れることもできます．

	1 A = (1,2,3)
	2 B = (4,A,5)
	3 PRINT B		※ 「(4,(1,2,3),5)」が表示される

ベクトル値の中のベクトル値を展開することもできます．

	1 A = (1,2,3)
	2 B = (4,%A,5)
	3 PRINT B		※ 「(4,1,2,3,5)」が表示される

ベクトル値に対して通常の演算をすると，要素ごとの演算になります．

	1 A = (1,2,3)
	2 B = (4,5,6)
	3 PRINT A+B		※ 「(5,7,9)」が表示される

以下のようにすることで，ベクトル値の指定した位置の要素を取り出せます．

	1 A = (1,2,3)
	2 PRINT 0@A		※ 「1」が表示される
	3 PRINT 2@A		※ 「3」が表示される

以下のようにすることで，ベクトル値の特定の次元数までを切り出せます．
(負の値を指定すると，終端から切り出します)

	1 A = (1,2,3)
	2 PRINT A#2		※ 「(1,2)」が表示される

関数やサブルーチンの関数呼び出しでも，戻り値の次元数を明示できます．

	PRINT COPY(1,2,3,4)	※ 「1234」が表示される
	PRINT COPY(1,2,3,4)#2	※ 「12」が表示される(戻り値は２次元となるため)
	PRINT SUBR(A, B)#3	※ サブルーチンの関数呼び出しでも同様

一部の関数(主に，１つの値を変換して返す関数)は，複数の引数を与えると，
引数ぶんの変換を行ってベクトル値で返します．

	1 A = ASCII("A","B","C")
	2 B = CHAR(A)
	3 PRINT A		※ 「(65,66,67)」が表示される
	4 PRINT B		※ 「(A,B,C)」が表示される

### 構造体

構造体は扱えませんが，ベクトル値は要素ごとに異なる型を持てるため，
構造体のように扱えます．

	S = (10, "NAME", (1,2,3))

またベクトル値は「.」を用いることで，指定した位置の要素を取り出すことが
できます．

	S = (10, "NAME", (1,2,3))
	LOOP I, 3; PRINT S.I; LOOPEND

位置を変数にすることで，各要素を構造体のように読み書きすることができます．

	S = (10, "NAME", (1,2,3))
	NUM = 0; NAME = 1; VEC = 2
	PRINT S.NUM
	PRINT S.NAME
	PRINT S.VEC

### 構造体へのポインタ

ポインタはベクトル値を指すこともできます．

	S = (10, "NAME", (1,2,3))
	P = &S
	PRINT *P

ベクトル値を指すポインタは，「->」を用いることで，指定した位置の要素を
取り出すことができます．

	S = (10, "NAME", (1,2,3))
	P = &S
	LOOP I, 3; PRINT P->I; LOOPEND

位置を変数にすることで，各要素を構造体のように読み書きすることができます．

	S = (10, "NAME", (1,2,3))
	P = &S
	NUM = 0; NAME = 1; VEC = 2
	PRINT P->NUM
	PRINT P->NAME
	PRINT P->VEC

ベクトル値はポインタ値を要素として持つこともできるため，構造体のチェイン構造を
作ることもできます．(NEXTはコマンドで予約されているため，LETで代入しています)

	S1 = (NULL, 20, "NAME2", (4,5,6))
	S0 = (&S1, 10, "NAME", (1,2,3))
	P = &S0
	LET NEXT = 0; NUM = 1; NAME = 2; VEC = 3
	PRINT P->NAME
	P = P->NEXT
	PRINT P->NAME

配列を利用してポインタで各要素を繋げることで，リンクリスト構造を作ることも
できます．

	1 DIM S, 10
	2 P = NULL
	3 LOOP I, 10; S[I] = (P, I, "NAME" + ITOA(I)); P = &S[I]; LOOPEND
	4 LET NEXT = 0; NUM = 1; NAME = 2
	5 FOR P = &S[9], P, P = P->NEXT; PRINT P->NUM, P->NAME; NEXT

### メモリ領域

MEMORYでメモリ領域を作成できます．FMEMORY()関数でも作成できます．

	MEMORY M, 256	※ 256バイトのメモリ領域を作成
	M = FMEMORY(256)	※ 上と同じ動作

メモリ領域はPEEK()/POKE()/MREAD()/MWRITE()で読み書きできます．

	C = PEEK(M, 0, 1)	※ 先頭から0の位置から1バイトを読み込み
	POKE(M, 0, 1, 'A')	※ 先頭から1バイトの'A'を書き込み

	V = PEEK(M, 16, 4)	※ 先頭から16の位置から4バイトを読み込み
	POKE(M, 16, 4, V)	※ 先頭から16の位置に4バイトを書き込み

	S = MREAD(M, 1, 5)	※ 5文字を文字列として読み込み
	MWRITE(M, 3, 4, "DEFG")	※ 4文字を文字列として書き込み

	MCOPY(M0, 0, M1, 0, 4)	※ M1からM0に4バイトをコピー

メモリ領域を代入した際には，新たな領域が作成されたりコピーされたりするのでは
なく，同じ領域を指します．別々にしたい場合には新たに領域作成し，MCOPY()で
コピーします．

	1 MEMORY M, 10
	2 M2 = M		※ M2はMと同じ領域を指す
	3 POKE(M2, 0, 4, V)	※ Mに対する書き込みと同じになる

### キュー／スタック

データ格納用のキューを作成し，キューやスタックとして利用することができます．

	1 Q = QOPEN()		※ キューを作成
	2 QPUSH(Q, 1, 2, 3)
	3 PRINT QPOP(Q)
	4 PRINT QPOP(Q)
	5 PRINT QPOP(Q)
	6 QCLOSE(Q)

QPUSHF()/QPUSH()/QPOPL()/QPOP()でキューの先頭，
QPUSHL()/QPOPF()でキューの末尾に対してデータの入出力をします．

QPUSHL()→QPOPF()(もしくはQPUSH()→QPOP())のように呼び出せばスタック(LIFO)，
QPUSHF()→QPOPF()のように呼び出せばキュー(FIFO)として動作します．

## デバッグ技法

### 実行中断と実行再開

実行はCtrl+Cで実行中断されます．

	nll> LS.
	1 I=0; .LOOP; P.++I; WAIT 100; G.LOOP	※ 数値を順に表示するサンプル
	nll> RUN
	1
	2			※ 2まで表示した
	※ ここでCtrl+Cを押す
	Break at: G.LOOP	※ 実行中断した
	nll> 

実行中断時に，STEPでステップ実行，CONTINUEで実行再開ができます．

	nll> STEP		※ １命令ずつ実行を進める
	
	Step break at: .LOOP; P.++I; WAIT 100; G.LOOP
	nll> STEP
	
	Step break at: P.++I; WAIT 100; G.LOOP
	nll> STEP
	3			※ 3が表示された
	
	Step break at: WAIT 100; G.LOOP
	nll> CONTINUE		※ 中断位置から実行再開
	4			※ 実行再開され，4から表示される
	5

STEPに引数を指定すると，指定した数だけステップ実行します．

	nll> CONTINUE
	4
	5
	
	Break at: G.LOOP
	nll> STEP 3		※ 命令を3つ実行する
	6			※ 6が表示された
	
	Step break at: WAIT 100; G.LOOP
	nll>

### 中断時の変数書き換えやプログラム編集

実行中断時に変数の値を書き換えて，実行再開することができます．

	nll> PRINT I
	6			※ Iの値は6になっている
	nll> I=10		※ Iを10に書き換え
	nll> PRINT I
	10
	nll> CONTINUE		※ 実行再開
	11			※ Iが10になって実行再開される
	12

実行中断時にプログラムを編集し，実行再開することもできます．
ただし中断箇所の行が編集された場合には，実行再開できません．

またLOOP/FOR/GOSUBの呼び出し後の実行中断時にそれらの行が編集された場合には，
対となっているLOOPEND/NEXT/RETURNの実行でエラー終了します．
(スタック上に保存されている戻り先が，行編集時に無効化されるためです)

### STOPによる実行中断

STOPで明示的に実行中断することができます．

	nll> LS.
	1 I=0; .LOOP; STOP; P.++I; WAIT 100; G.LOOP	※ 表示前に実行中断
	nll> RUN
	
	Break at: P.++I; WAIT 100; G.LOOP	※ STOPの位置で実行中断した

引数が指定されている際には，その値を表示します．

	STOP "Stopped."				※ 「Stopped」と表示して実行中断

STOPでの実行中断後，STEPによるステップ実行やCONTINUEによる実行再開もできます．

	nll> STEP				※ ステップ実行で実行を進める
	1					※ 1が表示された
	
	Step break at: WAIT 100; G.LOOP
	nll>

条件プレフィックスを組み合わせることで，決まった条件のときのみ実行を中断する
ことができます．

	(R < 0): STOP

### ブレークポイント

BREAKでブレークポイントを設定できます．

	nll> BREAK		※ ブレークポイントの削除
	nll> BREAK 10		※ 10行目の先頭にブレークポイントを設定

BREAKでは行番号とコマンド位置を数値で指定します．

	nll> BREAK 10 2		※ 10行目3番目のコマンドにブレークポイント設定

ブレークポイントでの実行中断後に，STEPのステップ実行やCONTINUEでの実行再開を
することもできます．

### エラー中断

実行時にエラーが発生した場合には，エラー箇所で実行中断します．

	nll> LS.
	1 A = = 1		※ A = 1 の間違い．実行時にエラーになる
	2 PRINT A
	3 PRINT A + 1
	nll> RUN
	Invalid parameter: A = = 1	※ エラー箇所で実行中断した
	nll>

### エラー箇所のスキップ

エラーによる実行中断時に，STEPやCONTINUEをしても，エラー箇所が再度実行されて
再度エラーになり，実行は進みません．

	nll> CONTINUE
	Invalid parameter: A = = 1
	nll>

しかしエラーが発生した行を修正しようとして編集すると，CONTINUEによる実行継続が
できなくなってしまいます．

SKIPで命令を無視して実行を進めることができます．これによりエラー箇所をスキップ
し，CONTINUEで実行継続できます．

	nll> SKIP		※ エラー箇所をスキップする
	nll> CONTINUE		※ 実行再開
				※ ただしAの設定が行なわれていないため非表示
	Invalid value type: PRINT A + 1	※ Aが未設定のため演算エラーとなる
	nll>

以下のように修正後の行を新たに追加してからエラー行をスキップすることで，
エラー発生時にエラー箇所を修正して，実行継続することができます．

	nll> LS.
	1 A = = 1			※ この行でエラーになる
	2 PRINT A
	3 PRINT A + 1
	nll> RUN
	Invalid parameter: A = = 1	※ エラーで実行中断
	nll> 2 A = 1			※ エラー行の直後に修正した行を追加
	nll> LS.
	1 A = = 1			※ 修正前の行(現在はここで実行中断)
	2 A = 1				※ 修正後の行
	3 PRINT A
	4 PRINT A + 1
	nll> SKIP			※ エラー行のスキップを指定
	nll> STEP			※ ステップ実行で処理を進める
	
	Step break at: PRINT A		※ 修正後の行が実行された
	nll> PRINT A
	1				※ 修正後の行が実行されている
	nll> 1				※ 修正前の行を削除
	nll> LS.
	1 A = 1
	2 PRINT A
	3 PRINT A + 1
	nll> CONTINUE			※ 実行再開
	1
	2
	nll>

### 関数呼び出ししているサブルーチンの内部での動作

サブルーチンを関数呼び出しした際には，関数呼び出しを1つの演算として扱うため，
基本的に内部で実行中断し再開するようなことはできません．

(GOSUBによる呼び出し時にはこのようなことは無く，サブルーチン内部での実行中断・
再開ができますので，これが問題あればGOSUBを使うことを推奨します)

サブルーチンの関数呼び出し時の挙動は，具体的には以下のようになります．

- Ctrl+Cでの実行中断

	- 関数呼び出しの内部では実行中断はされません
	- 関数呼び出しの終了後に実行中断します
	- ただしCtrl+Cを繰り返し何度も押すと，強制中断します(関数内部で無限ループ等になった場合の対策です)
	- 強制中断の場合は，その関数呼び出しがエラーになります
	- よってその後にCONTINUEで実行再開した場合には，関数呼び出ししたコマンドが再実行されます

- ステップ実行

	- 関数呼び出しは1つの演算として扱われます
	- このため関数呼び出しの内部ではステップ実行はされず，まとめてステップ実行されます

- STOPでの実行中断

	- Ctrl+Cでの実行中断と同様に扱われます

- ブレークポイントとエラー中断

	- 関数内部のブレークポイントで実行中断した場合には，その関数呼び出しがエラーになります
	- 関数内部でエラー中断した場合には，その関数呼び出しがエラーになります
	- よってその後にCONTINUEで実行再開した場合には，関数呼び出ししたコマンドが再実行されます

- 関数内部でのNEW

	- 関数内部でのNEWによるプログラム消去は，エラーとなりますが消去はされます

- 関数内部でのEXIT/END

	- 関数内部でのEXITは，その関数呼び出しがエラーとなります
	- 関数内部でのENDやプログラム末尾での実行終了は，RETURNと等価です

## リファレンス

### 基本コマンド例

	コマンド例	意味
	
	# COMMENT	コメント
	L. A,10		変数Aに10を代入
	L. A=10		変数Aに10を代入
	L. A,B+C	変数Aに，B+C の結果を代入
	L. A=B+C+D	変数Aに，B+C+D の結果を代入
	P. A		変数Aの値を表示
	P. B+C		B+C の結果を表示
	
	.LABEL		ラベルの定義
	G. LABEL	ラベルの位置に実行をジャンプ
	A<10: G. LABEL	変数Aが10未満のときにラベルにジャンプ(条件分岐)

	LP. I,10,0,1	LP〜LEの間を10回繰り返す(変数Iが0から9まで1ずつ変化)
	LE.		LPによる繰り返しの終端
	
	GS. SUBR	サブルーチンにジャンプ(RETURNで次の命令に戻る)
	RT.		サブルーチンからのリターン
	
	LS.		保存してあるプログラムを表示
	R.		保存してあるプログラムを実行
	EN.		プログラムの実行を終了
	EX.		nllを終了

### コマンド一覧

ここまでで説明したコマンドは，省略表記になっています．

正式表記は以下ですが，省略表記で利用することもできます．(どちらでも構いません)

省略表記として，(他のコマンドと区別できれば)コマンド名の一部分でも構いません．
(たとえばPRINTコマンドは，P,PR,PRI,PRINのいずれかでも構いません)
※ 一覧は DUMP L_COMMAND コマンドで参照できます

	正式表記	省略表記	意味
	RUN		R.,RN.		保存してあるプログラムの実行
	EDIT		E.,ET.		保存してあるプログラムの編集
	END		EN.		プログラムの実行を終了
	EXIT		EX.		nllを終了
	QUIT		Q.,QT.		nllを終了
	BREAK		B.,BK.		ブレークポイントを設定(CONTINUEで再開)
	STEP		S.,SE.		ステップ実行
	STOP		SP.		プログラムの実行を中断(CONTINUEで再開)
	SKIP		SK.		命令をスキップし実行しない(CONTINUEで再開)
	CONTINUE	C.,CN.		中断したプログラムの実行を再開
	ARGS		A.,AG.		式の演算
	LET		L.,LT.		変数への値の代入
	PRINT		P.,PT.		式の値を表示
	GOTO		G.,GT.		ラベルにジャンプ
	GONEXT		GN.		次の行にジャンプ
	GOSUB		GS.		サブルーチンにジャンプ(RETURNで戻る)
	RETURN		RE.,RT.		サブルーチンから戻る
	IF		I.		条件評価
	ELSE		EL.,ES.		条件評価が偽の場合
	ENDIF		EI.		条件評価の終了
	LOOPEND		LO.,LE.		LOOP〜LOOPENDの間をループ
	LOOP		LP.		LOOP〜LOOPENDの間をループ
	FOR		F.,FR.		FOR〜NEXTの間をループ
	NEXT		N.,NX.		FOR〜NEXTの間をループ
	DIM		D.,DM.		配列の作成
	MEMORY		M.,MM.		メモリ領域の作成
	PUSH		PU.,PS.		値のスタックへの保存
	POP		PO.,PP.		値のスタックからの復旧
	DFROM		DF.,FM.		データの定義の位置
	DREAD		DR.,RD.		定義されたデータの読み込み
	DATA		DA.,DT.		データの定義
	DISCARD		DC.		FOR/GOSUBの戻り先保存スタックを破棄
	NEW		NW.		保存してあるプログラムを削除，または変数を初期化
	LIST		LI.,LS.		保存してあるプログラムを表示
	SAVE		SA.,SV.		保存してあるプログラムをファイルに保存
	LOAD		LD.		ファイルからプログラムを読み込み
	STDIN		SI.		入力先を切替え
	STDOUT		SO.		出力先を切替え
	EVAL		EV.		指定した文字列をプログラムとして実行
	EVALF		EF.		指定したファイルの内容をプログラムとして実行
	WAIT		W.,WT.		指定した時間，実行を停止
	DUMP		DU.,DP.		各種内部情報の表示

### コマンドリファレンス

変数... Aのような変数を記述できます
式... 10のような数値，Aのような変数，A+1のような数式を記述できます

- {}内の引数は省略可能，末尾のカンマは省略可能
    - 例えば第２引数が無く，第３引数がある場合には，以下のように書けます
        - LOOP I,,1
    - 例えばLOOPで第３引数と第４引数が無い場合には，以下のように書けます
        - LOOP I,100    (LOOP I,100,, のような末尾のカンマは不要です)

- 変数は実際には式なので，式を記述することもできます

- RUN {<式1>},{<式2>}			実行開始．式1がある場合はその値の番号の行から実行．RUN 0 で実行前の初期化のみ行う．式2はARGV[]をベクトル値で指定
- EDIT {<式>}				行の編集．式は編集行．式未指定，0指定時は最終行
- END {<式>}				プログラムの実行を終了．式指定時は終了ステータス
- EXIT {<式>}				nllを終了．式指定時は終了ステータス
- QUIT {<式>}				EXITと同様
- BREAK {<式1>},{<式2>}			ブレークポイント指定．式1の未指定時はブレークポイント削除，式1は行，式2はコマンド位置(先頭が0)
- STEP {<式>}				ステップ実行．式はステップ回数(未指定時は1)
- SKIP {<式>}				命令を実行しない．式は回数(未指定時は1)．エラー発生でのブレーク時に，その命令を無視して実行を進めることができる
- STOP {<式1>},{<式2>},{<式3>},{<式4>}	強制ブレーク(式の指定時には，内容を表示する)
- CONTINUE				ブレーク時の実行再開
- ARGS {<式1>},{<式2>},{<式3>...}	式の演算
- LET {<式1>},{<式2>},{<式3>...}	式の演算．式1が変数の場合は式2を代入
- PRINT {<式1>},{<式2>},{<式3>},{<式4>}	式の値を表示(未指定時は改行表示)
- GOTO <ラベル>,{<式1>},{<式2>},{<式3>}	ラベルにジャンプ．式1の指定時はその値を引数として渡す．式2の指定時にはジャンプ時に演算．式3の指定時にはDISCARD相当を実施
- GONEXT {<式1>},{<式2>},{<式3>},{<式4>}	次の行にジャンプ．式1の指定時はその行数をスキップ(0の指定時は現在行の先頭にジャンプ，負の値は前の行にジャンプ)．式2の指定時はそのコマンドの位置にジャンプ(0で先頭コマンド)．式3の指定時にはジャンプ時に演算．式4の指定時にはDISCARD相当を実施
- GOSUB <ラベル>,{<式1>},{<変数>}	ラベルをサブルーチン呼び出し(RETURNで戻る)．式1の指定時はその値を引数として渡す．変数の指定時はRETURNから戻り値として受け取る
- RETURN {<式1>},{<式2>},{<式3>}	GOSUBによってジャンプした次の命令に戻る．式1の指定時はその値を戻り値として返す．式2の指定時にはRETURN時に演算．式3の指定時にはDISCARD相当を実施
- IF {<式1>},{<式2>},{<式3>}		式1の真偽によってIF〜ELSE〜ENDIFを条件実行．実行の可否によって式2/式3を実行
- ELSE {<式1>},{<式2>},{<式3>}		式1の真偽によってIF〜ELSE〜ENDIFを条件実行．実行の可否によって式2/式3を実行
- ENDIF					IF〜ELSE〜ENDIFの条件実行を終了
- LOOP {<変数>},{<式1>},{<式2>},{<式3>}	変数でループ．式1はループ回数(未指定時は無限ループ)，式2は変数の初期値(未指定時は0)，式3は変数の増分(未指定時は1)
- LOOPEND {<変数>},{<式>}		LOOPによるループの終端．変数指定時にはLOOPで指定した変数との対応をチェックする．式の指定時には繰り返し時に演算
- FOR {<式1>},{<式2>},{<式3>}		変数でループ．式1は初回に実行，式2は満たされた場合にループ継続(未指定時は無限ループ)，式3はNEXT時に実行
- NEXT {<式>}				FORによるループの終端．式指定時には繰り返し時に演算
- DIM {<変数>},{<式1>},{<式2>...}	配列の確保．式1の値の個数を確保する．式2以降がある場合は２次元／３次元配列
- MEMORY {<変数>},{<式>}		式の値のサイズのメモリ領域を作成
- PUSH {<式>...}			式の値をスタックに保存する
- POP {<変数>...}			スタックから値を変数に復旧する
- DFROM <ラベル>			データの位置を指定
- DREAD {<式>...}			定義されたデータを読み込み式に代入
- DATA {<式>...}			式の値をデータとして定義
- DISCARD {<式>}			LOOP/FOR/IF/GOSUBの保存スタックを破棄．式がある場合はその値の個数を破棄(未指定時は1)
- NEW {<変数>...}			変数が指定された場合は変数の初期化．未指定の場合はプログラムの削除と初期化
- LIST {<式1>},{<式2>}			プログラムの表示．式1は先頭行，式2は終端行，未指定時は全体表示
- SAVE {<式1>},{<式2>},{<式3>}		プログラムのファイルへの保存．式1はファイル名(未指定時は"sample.nll")．式2は先頭行，式3は終端行，未指定時は全体保存
- LOAD {<式1>}				プログラムのファイルからの読み込み．式1はファイル名(未指定時は"sample.nll")
- STDIN {<式1>}				入力先を切替え．式1はファイル名(未指定時は標準入力に戻す)
- STDOUT {<式1>}			出力先を切替え．式1はファイル名(未指定時は標準出力に戻す)
- EVAL {<式1>},{<式2>}			式1で指定した文字列をプログラム実行し，結果を式2に格納する．結果は実行プログラム内からRETURNで返す
- EVALF {<式1>},{<式2>}			式1で指定したファイルの内容をプログラム実行し，結果を式2に格納する．結果は実行プログラム内からRETURNで返す
- WAIT {<式1>},{<式2>},{<式3>},{<式4>}	ウエイト．式1はウエイト時間(1/100秒)，未指定時は１秒．式2はウエイト時間(1/10000秒)．式3はウエイト時間(マイクロ秒)．式4はウエイト時間(1秒)
- DUMP {<式1>},{<式2>},{<式3>},{<式4>}	内部情報のダンプ．全式未指定，もしくはD_ALLで全ダンプ，D_VARIABLEで変数情報，D_STRINGで文字列情報，D_LABELでラベル情報，D_LINEで行情報，D_STACKでスタック情報，D_POSITIONでLOOP/FOR/IF/GOSUB/EVALの保存スタック情報，L_COMMANDでコマンド一覧，L_FUNCTIONで関数一覧，L_CONSTで定数値一覧，L_OPERATORで演算子一覧．|で繋げることで複数表示

## 関数

様々な関数があります．
※ 一覧は DUMP L_FUNCTION コマンドで参照できます

関数の引数は，すべて演算されます．
(例えばCOND(I,++A,++B)としたとき，Iの値によらずに++Aと++Bが行われます)

### 入出力

	FPRINT(I, "ABC", F)	※表示(引数を連続して表示する)
	PRINTF("%d %s %02x\n", I, S, X)	※表示(printfフォーマットで書式指定)
	PRINTM(I, X, Y, FG, BG)	※座標と色を指定して表示(座標・色は省略可能)
	S = INPUT("name? ")	※入力(引数をプロンプトとして表示する)
	N = INPUTN("num? ")	※数値の入力(引数をプロンプトとして表示する)

(printfフォーマットの表記)

	%<数値>	桁数指定
	%c	文字
	%s	文字列
	%l	long
	%q	quad
	%d	10進数
	%u	unsigned
	%b	2進数
	%o	8進数
	%x	16進数(小文字)
	%X	16進数(大文字)
	%f	浮動小数値
	%%	%

### 値

	PRINT TYPEOF(I)	※型を返す
	PRINT TYPENAME(I)	※型の名称を表示
	PRINT SIZEOF(I)	※サイズを表示(文字列では文字列長，ベクトル値では要素数など)
	I = NZERO(A,B,C...)	※ゼロ以外の値の存在チェック(存在すれば1，しなければ0)
	I = CMP(A,B,C...)	※A,B,...の値を比較(一致で0，不一致で1)
	V = REP(N,A,B,...)	※A,B,...の値をN回繰り返し
	V = INSERT(I,N,A,B,...)	※IをA,B,...のN番目に挿入(Nが負で末尾からカウント)
	V = DELETE(N,A,B,...)	※A,B,...のN番目を削除(Nが負で末尾からカウント)

### 型の変換

	S = ITOC(I)	※数値をASCIIコード表の文字に変換(別名:CHAR())
	I = CTOI(C)	※文字をASCIIコード表の数値に変換(別名:ASCII())
	S = ITOA(123)	※整数値を文字列に変換(別名:STR())
	I = ATOI("123")	※文字列を整数値に変換(別名:VAL())
	F = ITOF(I)	※整数値を浮動小数値に変換
	I = FTOI(F)	※浮動小数値を整数値に変換	
	F = ATOF("1.23")	※文字列を浮動小数値に変換
	S = FTOA(1.23)	※浮動小数値を文字列に変換	

### 数値

	(A,B,C) = FARGS(1,2,3)	※引数をリスト値としてそのまま返す(別名:VALUE())
	(A,B,C) = COPY(1,2,3)	※引数をコピーしてそのまま返す
	B = TRUE(I,J)	※必ず1を返す
	B = FALSE(I,J)	※必ず0を返す
	B = ARGNUM(I,J)	※引数の個数
	B = BOOLEAN(I,J)	※真偽値
	B = COND(I,A,B)	※Iが0以外の場合はA，0の場合はBを返す
	B = AT(I,A,B,C)	※Iが0の場合はA，1の場合はB，2の場合はCを返す
	B = FPUSH(A,B,C)	※値のスタックへの保存(別名:LOCAL())
	(C,B,A) = FPOP(3)	※値のスタックからの復旧(引数の個数ぶん復旧する)(別名:RESTORE())
	N = STACKNUM()	※スタックに格納されている値の個数
	SRAND(N)	※乱数系列をNで初期化(0の場合は現在時刻で初期化)
	R = RAND(I)	※0〜I-1までの乱数値(別名:RND())
	I = INT(I)	※整数値
	I = ABS(I)	※絶対値
	I = SIGN(I)	※符号(-1, 0, 1)(別名:SGN())
	I = MAX(A,B,C)	※最大値
	I = MIN(A,B,C)	※最小値
	S = ABS2SUM(A,B,C)	※２乗の和

### 文字列

	S = SPRINTF("%d %s %02x\n", I, S, X)	※printfフォーマットで文字列生成
	PRINT ISALNUM("a", "0")		※アルファベット・数字かどうか
	PRINT ISALPHA("a")		※アルファベットかどうか
	PRINT ISASCII("a")		※アスキー文字かどうか
	PRINT ISCNTRL("\x00")		※制御文字かどうか
	PRINT ISDIGIT("0")		※数字かどうか
	PRINT ISGRAPH("!")		※空白文字を除く表示可能文字かどうか
	PRINT ISLOWER("a")		※小文字かどうか
	PRINT ISPRINT("a")		※表示可能文字かどうか
	PRINT ISPUNCT("!")		※記号かどうか
	PRINT ISSPACE(" ", "\n")	※空白文字かどうか
	PRINT ISUPPER("A")		※大文字かどうか
	PRINT ISXDIGIT("a")		※16進数での数字かどうか
	PRINT TOLOWER("abcABC")		※小文字に変換
	PRINT TOUPPER("abcABC")		※大文字に変換
	PRINT LEFT("ABCDE", 3)		※文字列の左側を切り出し
	PRINT RIGHT("ABCDE", 3)		※文字列の右側を切り出し
	PRINT MID("ABCDE", 3, 1)	※文字列の中央を切り出し
	PRINT MID("ABCDE", 3)		※文字列の途中から終端まで切り出し
	PRINT INSTR("ABCDE", "CD")	※文字列中の文字列の位置を検索
	PRINT STRLEN("123")		※文字列の長さ
	PRINT STRCPY("ABCD", 3, "def")	※文字列中に別の文字列をコピー
	PRINT SPLIT(",:", "ABC,DEF:GHI")	※文字列の分割
	PRINT SPLITS(" \t", "ABC   DEF   GHI")	※文字列の分割
	PRINT CHOMP(" \t\n", " ABC ", " DEF ")	※文字列の前後から指定した文字を削除
	PRINT LCHOMP(" \t\n", " ABC", " DEF")	※文字列の前から指定した文字を削除
	PRINT RCHOMP(" \t\n", "ABC ", "DEF ")	※文字列の後から指定した文字を削除

### 実行

	VAL = FEVAL("RETURN 10")	※文字列として与えられた命令の実行(戻り値はRETURNで返す)
	VAL = FEVALF("sample.nll")	※ファイルの内容を実行(戻り値はRETURNで返す)

### システム

	FWAIT(SEC,MSEC)			※ウエイト(秒，ミリ秒)
	(SEC,MSEC)=TIMER(SEC,MSEC)	※タイマ(引数無しで現在時刻を設定，正の引数で設定時刻からの差分だけウエイト，ゼロもしくは負の引数で設定時刻からの差分を返す，戻り値は設定時刻からの差分)
	NOSYSTEM()			※-no-system指定と同様に，システム系の機能を無効にする(解除不可)
	NOSYSCALL()			※-no-syscall指定と同様に，システムコール機能を無効にする(解除不可)
	NONETWORK()			※-no-network指定と同様に，ネットワーク機能を無効にする(解除不可)
	VAL = SYSTEM(COMMAND)		※system()によるホストコマンドの実行
	VAL = SYSCALL(NO,ARG1,ARG2,...)	※システムコールの実行(引数には整数，文字列，メモリ領域を指定可能)

### 時刻

	(SEC,MSEC) = TIME()	※現在時刻(秒，ミリ秒)
	PRINT DATE()	※現在時刻(文字列)

### 数学関数

	I = INT(F)	※浮動小数を整数値に変換(底の値)
	F = ABS(F)	※絶対値
	F = SGN(F)	※符号(-1.0, 0.0, 1.0)
	F = PI()	※円周率(引数がある場合はその値をかけた値)
	RAD = RADIAN(DEG)	※角度(degree)→角度(radian)の変換
	DEG = DEGREE(RAD)	※角度(radian)→角度(degree)の変換
	F = SIN(F)	※サイン
	F = COS(F)	※コサイン
	F = TAN(F)	※タンジェント
	F = ASIN(F)	※アークサイン
	F = ACOS(F)	※アークコサイン
	F = ATAN(F)	※アークタンジェント
	F = SINH(F)	※ハイパボリック・サイン
	F = COSH(F)	※ハイパボリック・コサイン
	F = TANH(F)	※ハイパボリック・タンジェント
	F = EXP(F)	※eの累乗
	F = LOG(F)	※対数(底はe)
	F = LOG10(F)	※対数(底は10)
	F = SQRT(F)	※平方根(別名:SQR())
	F = ATAN2(Y,X)	※アークタンジェント
	F = POW(X,Y)	※XのY乗
	F = FMOD(X,Y)	※剰余
	F = INFINITY()	※無限大(別名:INF())
	F = NAN()	※非数(Not a Number)
	I = ISFINITE(F)	※有限数の判定
	I = ISINF(F)	※無限大の判定
	I = ISNAN(F)	※非数(Not a Number)の判定
	I = ISNORMAL(F)	※ゼロ以外の判定

### 配列

	A = FDIM(2,3,4)		※配列の作成(引数が複数の場合には多次元配列)

### メモリ管理

	M = FMEMORY(256)	※メモリ領域の作成
	C = PEEK(M,OFFSET,SIZE)	※メモリ領域の読み出し
	POKE(M,OFFSET,SIZE,VAL)	※メモリ領域の書き込み
	S = MREAD(M,OFFSET,SIZE)	※メモリ領域の読み出し(文字列)
	MWRITE(M,OFFSET,SIZE,"ABC")	※メモリ領域の書き込み(文字列)
	MCOPY(M0,OFFSET0,M1,OFFSET1,SIZE)	※メモリ領域のコピー(M1→M0)

### ファイル操作用システムコール

	RENAME("from.txt","to.txt")	※ファイル名の変更
	UNLINK("file.txt")	※ファイルの削除
	TRUNCATE("file.txt",LENGTH)	※ファイルの短縮
	MKDIR("dir")	※ディレクトリ作成
	RMDIR("dir")	※ディレクトリ削除
	CHDIR("dir")	※カレントディレクトリ移動
	FD = OPEN("file.txt", O_RDONLY)	※ファイルのオープン
	CLOSE(FD)		※ファイルのクローズ
	READ(FD,M,OFFSET,SIZE)	※メモリ領域の指定位置への入力
	WRITE(FD,M,OFFSET,SIZE)	※メモリ領域の指定位置の出力
	LSEEK(FD,OFFSET,WHENCE)	※ファイル位置の変更
	FTRUNCATE(FD,LENGTH)	※ファイルの短縮
	FDS=ISREADABLE(TIMEOUT,FD0,FD1,FD2,...)	※ファイルの読み込み可能の確認
	FDS=ISWRITABLE(TIMEOUT,FD0,FD1,FD2,...)	※ファイルの書き込み可能の確認

### ファイル操作

	FP = FOPEN("file.txt", "r")	※ファイルのオープン
	FP = FDOPEN(FD, "r")	※OPEN()でオープンしたファイルのオープン
	FCLOSE(FP)		※ファイルのクローズ
	FD = FILENO(FP)		※ファイルディスクリプタの取得
	FEOF(FP)		※ファイル終端の検査
	FERROR(FP)		※ファイルエラーの検査
	C = FGETC(FP)		※ファイルからの1文字入力
	FPUTC(FP, C)		※ファイルへの1文字出力
	S = FGETS(FP)		※ファイルからの1行入力
	FPUTS(FP, "ABC\n")	※ファイルへの出力
	FPRINTF(FP, "%d %s %02x\n", I, S, X)	※ファイルへの出力(printfフォーマットで書式指定)
	FREAD(FP,M,OFFSET,SIZE)	※メモリ領域の指定位置への入力
	FWRITE(FP,M,OFFSET,SIZE)	※メモリ領域の指定位置の出力
	FSEEK(FP,OFFSET,WHENCE)	※ファイル位置の変更

### キュー操作

	Q = QOPEN()	※キューを作成
	QCLOSE(Q)	※キューを削除
	QLENGTH(Q)	※キューの要素数
	QPUSHF(Q,A,B,C)	※値をキューの先頭に挿入(別名:QPUSH())
	(A,B,C) = QPOPL(Q,3)	※値をキューの先頭から取得(別名:QPOP())
	QPUSHL(Q,A,B,C)	※値をキューの末尾に挿入
	(A,B,C) = QPOPF(Q,3)	※値をキューの末尾から取得

### ネットワーク

	ADDR = SOCKADDR(AF_INET,"192.168.1.1",10000)	※アドレスの作成
	S = SOCKET(AF_INET,SOCK_STREAM,0)	※ソケットのオープン
	BIND(S,ADDR)		※ソケットのbind()
	LISTEN(S,5)		※ソケットのlisten()
	S=ACCEPT(S,ADDR)	※ソケットのaccept()
	CONNECT(S,ADDR)		※ソケットのconnect()
	SHUTDOWN(S,HOW)		※ソケットのshutdown()
	SIZE=RECV(S,M,OFFSET,SIZE,FLAGS)	※ソケットのrecv()
	SIZE=SEND(S,M,OFFSET,SIZE,FLAGS)	※ソケットのsend()
	SIZE=RECVFROM(S,M,OFFSET,SIZE,FLAGS,ADDR)	※ソケットのrecvfrom()
	SIZE=SENDTO(S,M,OFFSET,SIZE,FLAGS,ADDR)	※ソケットのsendto()

### キー関連

	PRINT KEYNAME(KEY_A, KEY_0)	※キーコード→キー名称への変換
	PRINT KEYCODE("a","0")	※キー名称→キーコードへの変換

### テキスト画面制御

	SCREEN(FLAGS,WIDTH,HEIGHT)	※描画切替え．FLAGSはF_DISABLE(通常表示)，F_ENABLE(バッファリング表示．適切な動作を自動指定・推奨動作)，F_BUFFER(テキストバッファ表示)，F_FLUSH(自動フラッシュ)，F_CURSOR(カーソル表示)，F_CURSES(curses利用)，F_FORCE(強制フラッシュ)(フラグ未指定時は初回は表示有効化，次回以降は前回値継続)
	(F,W,H) = SCRSTAT()	※現在の描画フラグ，横幅，縦幅
	FLUSH(FLAGS)		※画面フラッシュ(テキストバッファ利用時)．FLAGSはF_FORCE(強制フラッシュ)
	(FG,BG) = GETCOLOR()	※描画色の取得
	FG = GETFGCOLOR()	※フォアグラウンドの描画色の取得
	BG = GETBGCOLOR()	※バックグラウンドの描画色の取得
	SETCOLOR(FG,BG)		※描画色の設定(C_BLACK:黒，C_RED:赤，C_GREEN:緑，C_YELLOW:黄，C_BLUE:青，C_MAGENTA:紫，C_CYAN:水色，C_WHITE:白)
	ATTR = GETATTR()	※描画属性の取得
	SETATTR(ATTR)		※描画属性の設定(A_RESET:初期化，A_BOLD:太字，A_FAINT:薄字，A_ITALIC:斜字，A_UNDERLINE:下線，A_BLINK:点滅，A_RAPIDBLINK:高速点滅，A_INVERSE:反転，A_INVISIBLE:非表示，A_CROSSOUT:取消)
	(X,Y) = GETPOS()	※現在のカーソル位置(テキストバッファが必要)
	MOVE(X,Y,DX,DY)		※カーソル位置を移動(DX,DYは増分)
	CH = GETCH(X,Y)		※指定位置の文字(未指定でカーソル位置)(テキストバッファが必要)
	CLEAR(CH,FLAGS)		※画面クリア(クリア文字)．FLAGSはF_FLUSH(自動フラッシュ)，F_FORCE(強制フラッシュ)
	SCROLL(X,Y,CH)		※X桁/Y行スクロール(負の値の場合は逆スクロール)(X方向はテキストバッファが必要)
	LINE(X0,Y0,X1,Y1,"*")	※直線の描画(座標未指定でカーソル位置)
	BOX(X0,Y0,X1,Y1,"*",FLAGS)	※長方形の描画(座標未指定でカーソル位置)(FLAGSにF_FILL指定で塗りつぶし)
	K = INKEY()		※キー入力(別名:KEY())

### グラフィック画面制御

	GSCREEN(FLAGS,WIDTH,HEIGHT,INDEX)	※描画切替え．FLAGSはG_DISABLE(グラフィック未使用)，G_ENABLE(グラフィック利用．適切な動作を自動指定・推奨動作)，G_DIRECT(直接描画)，G_BUFFER(バッファリング動作)，G_RENDERER(レンダリング利用)，G_FORCE(強制フラッシュ)，G_FLUSH(自動フラッシュ)，G_ROUGH(減色高速化)，G_HROUGH(さらに減色)(フラグ未指定時は初回は表示有効化，次回以降は前回値継続)，INDEXは描画画像
	(F,W,H,INDEX) = GSCRSTAT()	※現在の描画フラグ，横幅，縦幅，描画画像
	C = GCOLOR(R,G,B)	※RGB値から色の数値を生成(RGBは0〜255)
	(R,G,B) = GRGB(C)	※色の数値からRGB値を生成
	GSYNC()			※画面同期
	GFLUSH(FLAGS)		※画面フラッシュ．FLAGSはG_FORCE(強制フラッシュ)，G_ROUGH(減色高速化)，G_HROUGH(さらに減色)，G_SYNC(フラッシュ後に画面同期)
	GGETMAINIMG(INDEX)	※メイン画像の取得(この画像を画面に描画する)
	GSETMAINIMG(INDEX)	※メイン画像の指定(この画像を画面に描画する)
	(W,H) = GGETSIZE(INDEX)	※画像サイズの取得(INDEXはGDOTと同様)
	(X,Y,W,H,MX,MY) = GGETRANGE(INDEX)	※描画範囲の取得(INDEXはGDOTと同様)
	GSETRANGE(X,Y,W,H,MX,MY,INDEX)	※描画範囲の設定(INDEXはGDOTと同様)
	(X,Y) = GGETOFFSET(INDEX)	※描画時のオフセット位置の取得(INDEXはGDOTと同様)
	GSETOFFSET(X,Y,INDEX)	※描画時のオフセット位置の設定(INDEXはGDOTと同様)
	(MX,MY,DX,DY) = GGETSCALE(INDEX)	※描画時のスケーリングの取得(INDEXはGDOTと同様)
	GSETSCALE(MX,MY,DX,DY,INDEX)	※描画時のスケーリングの設定(INDEXはGDOTと同様)
	(X,Y) = GGETDOTOFFSET(INDEX)	※描画時のドットオフセットの取得(INDEXはGDOTと同様)
	GSETDOTOFFSET(X,Y,INDEX)	※描画時のドットオフセットの設定(INDEXはGDOTと同様)
	(W,H) = GGETDOTSIZE(INDEX)	※描画時のドットサイズの取得(INDEXはGDOTと同様)
	GSETDOTSIZE(W,H,INDEX)	※描画時のドットサイズの設定(INDEXはGDOTと同様)
	(C,FG,BG,F,T) = GGETCOLOR(INDEX)	※描画色の取得(Cは標準色，FGは描画色，BGは背景色，F,Tは変換する色，INDEXはGDOTと同様)
	GSETCOLOR(C,FG,BG,F,T,FLAGS,INDEX)	※描画色の設定(C,FG,BG,F,TはGGETCOLORと同様，FLAGS,INDEXはGDOTと同様)
	C = GGETPIXEL(X,Y,INDEX)	※指定座標の色の取得(INDEXはGDOTと同様)
	GCLEAR(C,FLAGS,INDEX)	※画面クリア(指定色でクリア．FLAGS,INDEXはGDOTと同様)
	GSCROLL(X,Y,C,FLAGS,INDEX)	※N行スクロール(負の値の場合は逆スクロール．CはGCLEARと同様，FLAGS,INDEXはGDOTと同様)
	GDOT(X,Y,C,FLAGS,INDEX)	※点の描画(座標未指定で描画の最終座標)(Cで色指定，FLAGSはG_SET:通常描画，G_AND,G_OR,G_XOR:現在の色とそれぞれの論理で描画，G_FLUSH(描画時フラッシュ)，G_ROUGH:減色高速化,G_HROUGH:さらに減色，INDEXは画像番号(省略時もしくはG_MAINIMGはメイン画像))(別名:GPOINT())
	GLINE(X0,Y0,X1,Y1,C,FLAGS,INDEX)	※直線の描画(座標,C,FLAGS,INDEXはGDOTと同様)
	GBOX(X0,Y0,X1,Y1,C,FLAGS,INDEX)	※長方形の描画(座標,C,FLAGS,INDEXはGDOTと同様，FLAGSにG_FILL指定で塗りつぶし)
	GCIRCLE(X,Y,RX,RY,C,FLAGS,INDEX)	※円・楕円の描画(座標,C,FLAGS,INDEXはGBOXと同様，FLAGSにG_EVENPOS指定で座標点の間を中心とする)(RY未指定で円)
	GPAINT(X,Y,C,BORDER,FLAGS,INDEX)	※塗りつぶし(BORDER未指定で指定座標の色範囲を塗りつぶし)(座標,C,FLAGS,INDEXはGBOXと同様)(G_AND,G_OR,G_XORは無効)
	GCOPY(X0,Y0,W0,H0,SOURCE,X,Y,W,H,FLAGS,INDEX)	※画像の張り付け(X0,Y0,W0,H0は張り付け先の領域，SOURCEは張り付け元の画像番号，X,Y,W,Hは張り付け元の領域，FLAGS,INDEXはGDOTと同様)
	GROTATE(X,Y,W,H,CX,CY,NUM,C,FLAGS,INDEX)	※画像の回転(X,Y,W,Hは回転する領域，CX,CYは回転の中心，NUMは角度(時計回りに90度単位)，CはGCLEARと同様，FLAGS,INDEXはGDOTと同様，FLAGSにG_ODDPOS指定で座標点を中心とする)
	GCHAR(X,Y,W,H,CH,TYPE,FLAGS,INDEX)	※文字の描画(X,Y,W,Hは描画先の領域，CHは描画文字，TYPEはGCHARSETと同様，FLAGS,INDEXはGDOTと同様)
	GPRINT(X,Y,W,H,S,TYPE,XGRID,YGRID,FLAGS,INDEX)	※文字列の描画(X,Y,W,H,TYPE,FLAGS,INDEXはGCHARと同様，Sは描画文字列，XGRID,YGRIDは文字列の方向)
	K = GINKEY()		※キー入力(別名:GKEY())
	(S0,S1,...) = GKEYSTAT("a","b",...)	※キーの押下状態の取得(GINKEY()で得られる文字列を指定)
	(X,Y) = GMOUSEPOS()	※マウスカーソルの位置
	(K,X,Y) = GINMOUSE()		※マウスボタン入力と入力時座標
	(S0,S1,...) = GMOUSESTAT("LEFT","MIDDLE",...)	※マウスボタンの押下状態の取得(GINMOUSE()で得られる文字列を指定)
	INDEX = GALLOCIMAGE(WIDTH,HEIGHT,FLAGS)	※画像の作成(サイズ未指定時はGSCREENで指定したサイズ．FLAGSはG_FULLCOLOR(フルカラー)，G_MONOCOLOR(モノクロ色)，G_ROUGHCOLOR(低階調色)，G_GRAYCOLOR(グレースケール)，G_HALFCOLOR(16ビットカラー)，G_AUTOCOLOR(自動選択)(フラグ未指定時はフルカラー))
	GFREEIMAGE(INDEX)	※画像の解放(INDEXはGDOTと同様)
	(INDEX,W,H) = GLOADIMAGE("sample.bmp",FLAGS)	※BMP画像のロード(FLAGSはGALLOCIMAGEと同様)
	GSAVEIMAGE("sample.bmp",INDEX,X,Y,W,H,FLAGS)	※画像のセーブ(BMP形式．X,Y,W,Hは保存位置とサイズ(未指定時は画像全体)．FLAGSはG_HALFCOLOR(16ビットBMP)，G_FULLCOLOR(32ビットBMP)，G_AUTOCOLOR(自動選択)(フラグ未指定時はパレット有無を自動選択))
	R = GCMPIMAGE(X0,Y0,W0,H0,SOURCE,X,Y,W,H,FLAGS,INDEX)	※画像の比較(X0,Y0,W0,H0は比較先の領域，SOURCEは比較元の画像番号，X,Y,W,Hは比較元の領域，INDEXはGDOTと同様)
	(INDEX,W,H,NUM) = GCHARSET(TYPE,FLAGS)	※キャラクタセットのロード(TYPEは文字種指定(G_FONT8X8:8x8フォント，G_FONT16X16:16x16フォント，G_CHARA:キャラクタ画像，G_CHARA2:キャラクタ画像２，G_CHARA3:キャラクタ画像３))

### オーディオ

	ASTOP()			※演奏中の演奏の停止
	ACLEAR(UNITSET)		※音源ユニットのクリア
	ASOUND(SAMPLEFREQ)	※サウンド設定．SAMPLEFREQはサンプリング周波数(未指定でデフォルト値の44100)
	SAMPLEFREQ = ASNDSTAT()	※現在のサウンド設定
	N = APLAYNUM()		※演奏中の演奏の数
	AWAIT()			※演奏の終了を待つ
	AUNITSET(UNITSET)	※音源ユニットのセットのデフォルト値
	INDEX = AUNIT(OUTPUT,AMP,FLAGS,UNITSET)	※音源ユニットの作成
	AOSC(INDEX,AMP,FREQ,PHASE,TYPE,MOD,FLAGS,UNITSET)	※発信器の設定
	AADDOUT(INDEX,OUTPUT,AMP,FLAGS,UNITSET)	※音源ユニットへの出力の追加
	AENVPOINT(INDEX,N,STEP,AMP,FLAGS,UNITSET)	※エンベロープ点の追加
	AENVCOPY(INDEX,SOURCE,FLAGS,UNITSET)	※エンベロープのコピー
	AFILPOINT(INDEX,TYPE,N,AMP,FLAGS,UNITSET)	※フィルタの設定
	AFILCOPY(INDEX,SOURCE,FLAGS,UNITSET)	※フィルタのコピー
	APLAY("CDEFGAB",FLAGS,UNITSET,FILENAME)	※音声を鳴らす
	(INDEX,LENGTH)=AOPEN("sample.wav",FLAGS)	※ファイルをオープン．LENGTHは音声の長さ(ミリ秒)
	ACLOSE(INDEX)		※ファイルをクローズ

## 起動

### 起動時の引数の指定

	$ nll [<起動オプション>...] [<ファイル名>|-|{--|stdin} [<ARGV[1]> [<ARGV[2]> [...]]]]

### 起動時動作

- 起動時にファイル名を指定すると，そのファイルを読み込みます．
- ファイル名は起動オプションの後に指定します．
- ファイル名に-を指定すると無視されます．
- ファイル名に--もしくはstdinを指定すると，標準入力から読み込みます．
- ファイル読み込みは，nllのコマンドラインでの入力と同等に行われます．
- このためファイル読み込み時には，行番号無しの行は，ダイレクトモードで実行されます．
- -numberを指定すると，行番号無しのプログラムはプログラムモードで読み込みされます．(行頭に$を付加するとダイレクトモードで読み込みされます)
- ファイルの読み込み後は，自動実行されます．-no-runを指定すると自動実行されません．
- -quitを指定すると，ファイルの自動実行後にnllを終了します．
- -eで，実行コマンドを起動オプションから指定できます．ワンライナー実行ができます．

### 起動オプション

- -help,-h	ヘルプを出力
- -version,-v	バージョン情報を出力
- -quit,-q	ファイル実行後に自動終了
- -number,-n	入力ファイルの各行をプログラムモードで入力
- -no-run,-nr	ファイルを自動実行しない(標準では指定したファイルを自動実行)
- -no-argv,-na	ARGV[]を渡さない
- -no-system,-ns	システム系の機能を無効にする(FOPEN()やSYSTEM()など)
- -no-syscall,-nc	システムコール機能を無効にする(SYSCALL()関数)
- -no-network,-nn	ネットワーク機能を無効にする(SOCKET()など)
- -no-fixed,-nf	定数どうしの演算を毎回行う(標準では初回のみ行う．低速になるが，演算結果のデバッグ用)
- -e <command>	指定したコマンドをダイレクトモードで実行
- -		ファイル名を無視
- --,stdin	標準入力からプログラムを読み込み

### 起動例

	$ nll sample.nll	※ sample.nllを読み込んで起動し実行
	$ nll -nr sample.nll	※ sample.nllを読み込んで起動(実行しない)
	$ nll - abc def		※ ARGV[1]に"abc",ARGV[2]に"def"を渡して起動
	$ echo "abc" | nll -e 'S=FGETS(0);FPUTS(0,S)'	※ワンライナー実行

## nllを改造する

### コマンドの追加

コマンドの追加手順は以下です．
実際の詳細は，他のコマンドを参考にしてください．
(LETのような，簡単なコマンドを参考にするといいと思います)

- command.hのcommand_type_tに，コマンド番号を追加する
- command.cのopecodesに，コマンド名を追加する
- nll.cのnll_parse()内のswitch文に，コマンドの引数解析を追加する
- nll.cのnll_proc()内のswitch文に，コマンドの実行処理を追加する

### 関数の追加

関数の追加手順は以下です．
実際の詳細は，他の関数を参考にしてください．
(TRUE()やITOA()のような，簡単な関数を参考にするといいと思います)

多くのことが関数で実現できます．
また，コマンド追加よりも関数追加のほうが，簡単だと思います．
このため機能追加の際には，コマンドよりも関数による実装を推奨します．

- function.hのfunction_type_tに，関数番号を追加する
- function.cに，他の関数を参考にして，関数処理のプロトタイプ宣言を追加する
- function.cのfunctions[]に，関数名を追加する
- function.cに，関数の処理を追加する

## 算数への応用

### □に入る数値

- 15 ＋ 21 − □ ＋ 11 − 4 ＝ 10	(答えは33)

	1 LOOP I,100
	2 (15 + 21 - I + 11 - 4 == 10): GOTO FOUND
	3 LOOPEND
	4 .FOUND; PRINT I

- 12 × (□ ÷ 3 − 15) ＋ 21 ＝ 165	(答えは81)

	1 LOOP I,100
	2 (12 * (I / 3 - 15) + 21 == 165): GOTO FOUND
	3 LOOPEND
	4 .FOUND; PRINT I

### 数当て

- その数は，4桁です
- その数は，17の倍数です
- その数は，１の位の数と百の位の数が同じです
- その数は，１の位の数と千の位の数を入れ換えると19の倍数になります
- その数は何でしょう？(答えは7191,7565,7939,9010)

	1 LOOP I, 9000, 1000
	2 LET I0, (I % 10)
	3 LET I1, ((I / 10) % 10)
	4 LET I2, ((I / 100) % 10)
	5 LET I3, ((I / 1000) % 10)
	6 I % 17 != 0: GOTO NOT
	7 I0 != I2: GOTO NOT
	8 (I0 * 1000 + I2 * 100 + I1 * 10 + I3) % 19 != 0: GOTO NOT
	9 PRINT I
	10 .NOT; LOOPEND

### 足し算九九

	1 LOOP I,9,1
	2 LOOP J,9,1
	3 PRINTF("%3d",I+J)
	4 LOOPEND J
	5 PRINT
	6 LOOPEND I

### かけ算九九

	1 LOOP I,9,1
	2 LOOP J,9,1
	3 PRINTF("%3d",I*J)
	4 LOOPEND J
	5 PRINT
	6 LOOPEND I

### かけ算	(答えは28782)

	1 LET A, 123
	2 LET B, 234
	3 LET C, 0
	4 LOOP I, A
	5 LET C, C + B
	6 LOOPEND
	7 PRINT C

### 割算	(答えは123余り10)

	1 LET A, 28792
	2 LET B, 234
	3 LET C, 0
	4 .MAIN
	5 LET C, C + 1
	6 LET A, A - B
	7 A >= B: GOTO MAIN
	8 PRINT C
	9 PRINT A

### 最大公約数	(答えは6)

	1 LET A,30
	2 LET B,42
	3 LET I,30
	4 .MAIN
	5 LET I,I-1
	6 (A%I)!=0:GOTO MAIN
	7 (B%I)!=0:GOTO MAIN
	8 PRINT I

### 最小公倍数	(答えは210と9594)

	1 LET A,30
	2 LET B,42
	3 LET I,0
	4 .MAIN
	5 LET I,I+1
	6 (I%A)!=0:GOTO MAIN
	7 (I%B)!=0:GOTO MAIN
	8 PRINT I

	1 LET A,123
	2 LET B,234
	3 LET I,0
	4 .MAIN
	5 LET I,I+1
	6 (I%A)!=0:GOTO MAIN
	7 (I%B)!=0:GOTO MAIN
	8 PRINT I

### 円周率(モンテカルロ法)

	1 N = 10000; R = 10000
	2 LET S, 0
	3 LOOP I, N
	4 X = RAND(R*2+1)-R; Y = RAND(R*2+1)-R
	5 (X*X+Y*Y <= R*R): ++S
	6 LOOPEND I
	7 PRINT 4.0 * ITOF(S) / ITOF(N)

### サイコロを３つ振ってすべて１になる確率(1/(6^3) == 0.0046296...)

	1 SRAND(1)
	2 LET N, 100000
	3 LET S, 0
	4 LOOP I, N
	5 (RAND(6)+1 == 1) &> (RAND(6)+1 == 1) &> (RAND(6)+1 == 1): ++S
	6 LOOPEND
	7 PRINT ITOF(S) / ITOF(N)

### サイコロを３つ振って１，２，３が出る確率(1/2 * 1/3 * 1/6 == 0.027777...)

	1 SRAND(1)
	2 LET N, 10000
	3 LET S, 0
	4 LOOP I, N
	5 LET A, RAND(6)+1
	6 LET B, RAND(6)+1
	7 LET C, RAND(6)+1
	8 (A==1) && (B==2) && (C==3): ++S
	9 (A==1) && (B==3) && (C==2): ++S
	10 (A==2) && (B==1) && (C==3): ++S
	11 (A==2) && (B==3) && (C==1): ++S
	12 (A==3) && (B==1) && (C==2): ++S
	13 (A==3) && (B==2) && (C==1): ++S
	14 LOOPEND
	15 PRINT ITOF(S) / ITOF(N)

### バブルソート

	1 DIM A, 10
	2 LOOP I, 10; A[I] = RAND(100); P.A[I]; LOOPEND
	3 P. "----"
	4 .MAIN; FOUND = 0
	5 LOOP I, 9
	6 (A[I] > A[I+1]):LET ((A[I],A[I+1]) = (A[I+1],A[I]), FOUND = 1)
	7 LOOPEND
	8 FOUND:GOTO MAIN
	9 LOOP I, 10; P.A[I]; LOOPEND

### 数のカウント

	1 LIMIT = VAL(INPUT("limit? "))
	2 LOOP I, LIMIT
	3 PRINT I; WAIT ,1
	4 LOOPEND

### 掛け合わせると2になる数(√2)

	1 LET R, 1.0
	2 LET DIV, 1.0
	3 LET N, 0
	4 CLEAR(); .MAIN
	5 LET DELTA, 2.0 - R*R
	6 (ABS(DELTA) < 0.00001):GOTO END
	7 R = R + DIV * SIGN(DELTA)
	8 DIV = DIV * 0.99
	9 PRINTM("*", N / 10, (R-1.0) * 20)
	10 LET N, N+1
	11 GOTO MAIN
	12 .END; PRINT R

### サイコロを３つ振ってすべて１になる確率をグラフ化

	1 SRAND(1); CLEAR()
	2 LET N, 100
	3 LOOP NUM, 50
	4 LET S, 0
	5 LOOP I, N
	6 (RAND(6)+1 == 1) &> (RAND(6)+1 == 1) &> (RAND(6)+1 == 1): ++S
	7 LOOPEND
	8 PRINTM("*", NUM, ITOF(S) / ITOF(N) * 1000)
	9 N = FTOI((ITOF(N) * 1.2))
	10 LOOPEND NUM

### 回転変換による円の描画

	1 SCREEN(F_ENABLE|F_FLUSH)
	2 LET R, 1.0 * PI(2) / 360
	3 (X, Y) = (9.0, 0.0)
	4 LOOP I, 360
	5 PRINTM("*", X*2+21, Y+11)
	6 (X, Y) = ((COS(R)*X+SIN(R)*Y), (COS(R)*Y-SIN(R)*X))
	7 WAIT 1; LOOPEND

### マンデルブロ集合

	1 R=12; M=1.4
	2 LOOP X, R*2+1, -R
	3 LOOP Y, R*2+1, -R
	4 (ZX, ZY) = (0.0, 0.0)
	5 LOOP I, 100
	6 (CX, CY) = (ITOF(X), ITOF(Y)) * (M/ITOF(R), M/ITOF(R))
	7 (ZX, ZY) = (ZX*ZX - ZY*ZY, ZX*ZY + ZY*ZX) + (CX, CY)
	8 LOOPEND
	9 D = ZX*ZX + ZY*ZY
	10 C = (D <= 4.0) ? ("##", "  ")
	11 PRINTM(C, (X + R)*2, Y + R)
	12 LOOPEND Y; LOOPEND X

### 障害物ゲーム

	1 LET X, 10
	2 SCREEN(); CLEAR(); FLUSH()
	3 .MAIN
	4 LET K, INKEY(0)
	5 ((K=="j") || (K=="LEFT" )) && (X >  0): --X
	6 ((K=="l") || (K=="RIGHT")) && (X < 19): ++X
	7 SCROLL(,1)
	8 (GETCH(X, 0) == "*"):GOTO END
	9 PRINTM("V", X, 0, 9)
	10 PRINTM("*", RAND(20), 19, RAND(7) + 1)
	11 FLUSH()
	12 WAIT 10
	13 GOTO MAIN
	14 .END

## ビルド

- ビルド前に以下の設定を行ないます．

	- トップディレクトリのMakefileのBUILDを環境に合わせて設定
	- トップディレクトリのMakefileのARCHを環境に合わせて設定
	- もしくはmake時に，make BUILD=XXX ARCH=XXXのように指定してビルドする

- 行入力のライブラリを，以下から選択できます．
	- libedit (Makefile で USE_LIBEDIT/USE_CURSES を有効にする)
	- editline (Makefile で USE_EDITLINE を有効にする)
	- readline (Makefile で USE_READLINE/USE_CURSES を有効にする)
	- nlline (Makefile で USE_NLLINE を有効にする)
		- 独自のreadlineライブラリのサブセットです
	- getline() による入力 (Makefile で USE_GETLINE を有効にする)
	- fgets() による入力 (Makefile で USE_FGETS を有効にする)
	- ライブラリ内でcursesライブラリが利用されている場合には，USE_CURSESで有効化する必要があります

	make install.nll			※nllineを利用してビルド
	make READLINE=libedit USE_CURSES=yes install.nll	※libeditを利用してビルド
	make READLINE=readline USE_CURSES=yes install.nll	※readlineを利用してビルド
	make READLINE=editline install.nll	※editlineを利用してビルド
	make READLINE=getline install.nll	※getlineを利用してビルド
	make READLINE=fgets install.nll		※fgetsを利用してビルド

- 標準ライブラリ(いわゆるlibc)無しでビルド可能です．
	- Makefile で USE_NLLIBC / USE_NLTERM / USE_NLCRT を有効にします
	- nllibc / nlcrt という独自の標準ライブラリとスタートアップを持っています
	- 現時点では nlline との併用が必要です
	- nllibcは数学ライブラリをサポートしていないため，無効化が必要です

	make BUILD=nllibc USE_NLLIBC=yes USE_NLTERM=yes USE_NLCRT=yes \
		USE_MATHLIB= install.nll

- Windows用の実行ファイルは，MinGWを利用して以下でビルドできます．
	- readlineライブラリは，nllineで代用できます(うまくビルドできない場合は，READLINE=fgets を指定してfgets()を利用してください)
	- MinGW用のSDL(SDL2-devel-2.XX.X-mingw.zip)が必要です．ダウンロード・展開し，展開場所をSDLDIRで指定します(以下の例を参考にしてください)
	- SDLを利用しない(グラフィックとオーディオが限定機能のみ)場合には，USE_SDL1とUSE_SDL2を空に指定します
	- SDL利用時での実行時にSDL2.dllが必要になる場合(通常は不要です)は，SDL2-2.XX.X-win32-x86.zipをダウンロードし，nll.exeと同一フォルダに配置します
	- SDLはここからダウンロードできます

	https://www.libsdl.org/

	- SDL2-2.26.5以降だとオーディオ関連の浮動小数演算のライブラリ不足でリンクエラーになるようです．SDL2-devel-2.26.4-mingw.zipが以下からダウンロードできます

	https://kozos.jp/nll/archive/SDL2-devel-2.26.4-mingw.zip

	- 通常のビルド(MinGW用のcursesライブラリが必要です．通常はこちらでOKですが，cursesライブラリが利用できない場合には以下を参考に無効化してください)

	make MINGW=mingw32 CCOMPILER=gcc \
		SDLDIR=../../SDL2-2.26.4/i686-w64-mingw32 \
		LINK_STATIC=yes install.nll

	- CURSES未使用・SDL未使用(グラフィックとオーディオが限定機能のみ)

	make MINGW=mingw32 CCOMPILER=gcc USE_CURSES= USE_SDL1= USE_SDL2= \
		LINK_STATIC=yes install.nll

- Android用の実行ファイルは，クロスコンパイラを使って以下でビルドできます．
	- ライブラリとしてnllibcとnllineを利用するため，それらを先にビルドします
	- nllibcが浮動小数(表示等)と数学ライブラリに未対応のため，それらを無効化します

(ARM機種(32ビットARM)の場合)
	make STDCHEADERS=nllibc \
		CROSS=arm-none-eabi CCOMPILER=gcc OSDEF=__linux__ OSABI=none \
		GOPTFLAGS="-march=armv7-a -mfpu=vfp -mfloat-abi=soft -Wa,-meabi=5" \
		install.nllibc
	make STDCHEADERS=nllibc \
		CROSS=arm-none-eabi CCOMPILER=gcc OSDEF=__linux__ OSABI=none \
		GOPTFLAGS="-march=armv7-a -mfpu=vfp -mfloat-abi=soft -Wa,-meabi=5" \
		USE_NLLIBC=yes USE_NLTERM=yes \
		install.nlline
	make STDCHEADERS=nllibc \
		CROSS=arm-none-eabi CCOMPILER=gcc OSDEF=__linux__ OSABI=none \
		GOPTFLAGS="-march=armv7-a -mfpu=vfp -mfloat-abi=soft -Wa,-meabi=5" \
		USE_NLLIBC=yes USE_NLTERM=yes USE_NLCRT=yes NLLDSCR=arm LINK_STATIC=yes \
		USE_FLOATING_POINT= USE_MATHLIB= \
		USE_CURSES= USE_SDL1= USE_SDL2= USE_NETWORK_FUNCTION= \
		install.nll

ここまで
