言語仕様

文字コード

外部I/OではUTF-8、内部ではUTF-16で扱う。基本多言語面のみサポートし、第1面以降の拡張領域はサポートしない。
サロゲートペアは無視する。

プログラム中の単語の種類

プログラム内で用いる単語は識別子とリテラルの2種類に大別される。
識別子はプログラム内で命令、変数、定数、ラベル、予約語として使用される。
リテラルはプログラム内の数値データやテキストデータを表すために使用される。

識別子

識別子は英字またはアンダースコアで始まる任意長の英数字またはアンダースコアの並び。(正規表現では[_A-Z][_A-Z0-9]+)大文字小文字は区別しない。
識別子末尾に%,#,$のいずれかの記号が付く事がある。この記号を型サフィックスと呼ぶ。

予約語

次の識別子は予約語と言われ、言語機能に使用するため変数名、命令名、関数名には使用できない。

IF THEN ELSE ELSEIF ENDIF CASE WHEN OTHERWISE ENDCASE GOTO GOSUB RETURN ON LOOP ENDLOOP FOR NEXT WHILE WEND REPEAT UNTIL BREAK CONTINUE
DEF END DEFOUT VAR DIM AND OR XOR NOT DATA READ RESTORE PRINT TPRINT INPUT LINPUT CALL SWAP OUT COMMON EXEC

ラベル

識別子の先頭に'@'が付いた単語をラベルと呼び、プログラム中の位置を表すために使用される。

ラベルが通常の文字列式中に現れた場合は、そのラベル自体が入った文字列値として扱われる。

定数

識別子の先頭に'#'がついた単語を定数と呼び、定数毎に対応する数値または文字列が決まっている。式中に定数が現れた場合、対応する値に置換される。

リテラル

SmileBASICが扱う基本データには大きく分けて数値型と文字列型の2種類があるが、基本データを表した単語をリテラルと呼ぶ。
数値リテラルは整数リテラルと実数リテラルに別れる。
整数リテラルは0から‭2147483647‬までの10進数の数値、もしくは先頭に&Hをつけた16進数の値、もしくは先頭に&Bをつけた2進数の値となる。
実数リテラルは小数点または指数表記が含まれた数値となる。
文字列リテラルはダブルクォーテーション " で囲われたテキストとなる。

SmileBASICで扱うデータの基本単位を値と呼ぶ。
値の種類として、数値型(整数型、実数型)、文字列型、配列型、空白型がある。

整数型

32bit 符号あり。-2147483648~2147483647までの値を表現できる。

実数型

倍精度実数(64bit。IEEE754倍精度)

文字列型

文字単位がUTF-16で構成された任意の長さの文字の並び。最大長は2^31(メモリ空き容量に依存)

配列型

整数型、実数型、文字列型を複数個格納できる。
最大要素数は2^31(メモリ空き容量に依存)
最大次元は4次元。
2次元以上の配列はすべて1次元配列のサブセットで、1次元配列としても参照できる。

空白型

「値が入っていない」事を示すための型。デフォルト型とも呼ばれる。
空白型を使った演算はすべてエラーとなる

値の型変換

整数型と実数型間で値を交換する場合はすべて暗黙で値が変換される。
また、整数型と実数型の混じった演算を行う場合、整数計算を行う演算子かどうかで扱いが変わる。
整数計算を行う演算子の場合は、実数型は暗黙で整数型に変換され、結果も整数型となる。
実数計算を行う演算子の場合は、暗黙で整数型が実数型に変換され、結果も実数型となる。
上記以外の演算子の場合、2項演算子で左辺右辺のいずれかが実数型の場合、また両辺整数型で計算結果が整数型の値域を超える場合実数型となる。
演算子が整数計算・実数計算を行うかどうかは、後述の演算子の説明を参照。

参照型について

・値には参照型という特性を持った型があります
・文字列型と全ての配列型は参照型です
・数値型はある変数Aから別の変数Bに代入するとA→Bと値がコピーされますが、それぞれ全く別の値として扱われ、元の変数の中身を変更しても代入先の変数の値は変わりません
・参照型の値は、データ本体と参照用情報の2つに分かれており、変数に入るのは参照用情報のみで、データ本体は入りません
・参照型の値が入った変数Aから別の変数Bへ代入すると、数値型と同じようにA→Bと値がコピーされますが、この時コピーされるのは参照用情報のみで、データ本体はコピーされません
・結果、同じデータ本体を参照する異なる変数A,Bができあがります
・この状態でAの文字列を操作する命令を使用すると、Bの中身まで変わったように見えてしまいます
・このような状態を避けるにはCOPY命令を使ってデータ本体もコピーして下さい。ただし上記の特性を理解できれば、COPY命令を使う必要がある場面はそれほど多くはない事に気付くと思います

参照型の例

A$="ABC"     '初期値ABCのメモリーを確保
B$=A$        '変数は別だが参照しているデータ本体は同じ
?A$,B$       'ABCとABCと表示
A$[1]="Z"    'データ本体を書き換える
?A$,B$       'AZC AZCと表示

B$=B$+"X"    '文字列+文字列では、別な文字列が作成される
?A$,B$       'AZC AZCXと表示
C$=B$        '変数は異なるが参照先は同じメモリー
?A$,B$,C$    'AZC AZCX AZCXと表示
PUSH C$,"W"  'C$のデータ本体参照先に対してWを加算
?A$,B$,C$    'AZC AZCXW AZCXWと表示

A$="ABC" 
B$=COPY(A$)  'COPY関数を使うと別な文字列となる 
A$[1]="Z" 
?A$,B$       '最初の例と違い、AZC ABCと表示

変数

変数は任意の値を格納するための箱に相当する物である。

変数の初期値は変数名につく型サフィックスにより決定する。

なし デフォルト型値
$ 空文字列(長さゼロの文字列)
% ゼロ(整数)
# ゼロ(実数)

デフォルト型値は、通常時は実数のゼロ、OPTION DEFINT 指定時には整数のゼロとなる。

変数自体は型を持たず、直前に入っている値の型に関係なく任意の型の値を格納できる。

変数スコープ

変数スコープはグローバルとローカルの2種類存在する。
グローバル変数はユーザー定義命令・関数外で定義される変数で、プログラム内のどこからでも参照できる。
ローカル変数はユーザー定義命令・関数内で定義される変数で、定義したユーザー定義命令・関数内でのみ参照できる。

名前空間

変数、定数、命令・関数、ラベルはそれぞれ別の名前空間に分かれており、それぞれ同じ名前を使用してもエラーにならない。
組み込み命令・関数にもこのルールは適用される。

言語要素の実行時参照

SmileBASICの言語要素のうち、ラベル、変数、命令・関数は実行時に文字列から検索・使用ができる。

ラベルの実行時参照

GOTO / GOSUB の飛び先、またRESTOREの引数として、文字列を指定できる。
文字列を指定した場合実行時に飛び先を検索し、そこにジャンプする。
飛び先が見つからなかった場合は Undefined label エラーが発生する。
文字列の先頭に"数字:"というプレフィクスがついている場合、指定プログラムスロットのラベルを検索する。

変数の実行時参照

VAR ("変数名") と記述する事で、実行時に変数を検索し使用する事ができる。
例えば VAR ("FOO") = 3 は FOO = 3 と同じ意味となる。
変数が見つからなかった場合はUndefined variableエラーが発生する。
文字列の先頭に"数字:"というプレフィクスがついている場合、指定プログラムスロットの変数を検索する。

命令・関数の実行時参照

CALL キーワードを使用する事で、実行時に命令や関数を検索し呼び出す事ができる。

命令・関数が見つからなかった場合は Undefined functionエラーが発生する。
命令・関数は組み込み、ユーザー定義に関わらず参照できるが、PRINT と INPUT は言語要素として組み込まれているため参照できない。
文字列の先頭に"数字:"というプレフィクスがついている場合、指定プログラムスロットの命令・関数を検索する。