MikoScript 言語仕様

 演算子

 「演算子」は、式に対して作用します。つまり、式は、演算子の作用対象(オペランド)
になります。作用対象が1つだけの演算子を「単項演算子」と呼びます。単項演算子は、
作用対象の前または後に置きます。作用対象の前に置く演算子を「前置演算子」、後に置
く演算子を「後置演算子」と呼びます。後置演算子の中には、作用対象を省略できるもの
もあります。その場合「無項演算子」となります。作用対象が2つある演算子を「二項演
算子」と呼びます。二項演算子は、2つの作用対象の間に置きます。二項演算子の中には、
左項を省略できるものもあります。その場合、前置演算子になります。作用対象が3つあ
る特殊な三項演算子もあります。関数名や配列名等の後に置く括弧も、文法上の分類では、
演算子に含めます。これらは、引数並びを持つ特種な後置演算子になります。

●演算子一覧
 本言語で使用する演算子を、以下の一覧表に示します。

演算子 機能概要 基本用法 結合性 種類
:: グローバルスコープ規定 ::箱名 前置
. メンバースコープ規定 .箱名 前置
^ モジュールローカルスコープ規定 ^箱名 前置
$ スレッドローカルスコープ規定 $箱名 前置
@ 関数スタティックスコープ規定 @箱名 前置
:: 箱内スコープ規定(参照型) 箱名::箱名 二項
. 箱内スコープ規定(降下型) 箱名.箱名 二項
[ ] 連想名生成 箱名[ インデックス ] 特種
( ) 標準型関数コール 関数名( 引数並び ) 特種
( ) インスタンス生成 クラス名( 引数並び ) 特種
( ) 純粋配列の要素 純粋配列名( 引数並び ) 特種
+ 数値の正負維持 +式 前置
- 数値の正負反転 -式 前置
: ラベル名文字列への変換 :ラベル名 前置
' リレー型関数コール 式'関数名( 引数並び ) 二項
++ 1の加算代入(式値は演算後値) ++代入先 前置
++ 1の加算代入(式値は演算前値) 代入先++ 後置
-- 1の減算代入(式値は演算後値) --代入先 前置
-- 1の減算代入(式値は演算前値) 代入先-- 後置
! 真偽の論理否定 ! 式 前置
~ ビットの反転 ~ 式 前置
~ コマンド型関数コール 関数名~ 引数並び 特種
* 乗算 式 * 式 二項
/ 除算 式 / 式 二項
% 剰余算 式 % 式 二項
+ 加算 式 + 式 二項
- 減算 式 - 式 二項
<< ビットの左シフト 式 << 式 二項
>> ビットの右シフト(符号付) 式 >> 式 二項
& ビットの論理積 式 & 式 二項
^ ビットの排他的論理和 式 ^ 式 二項
| ビットの論理和 式 | 式 二項
< より小さいかの比較 式 < 式 二項
<= より小さいか等しいかの比較 式 <= 式 二項
> より大きいかの比較 式 > 式 二項
>= より大きいか等しいかの比較 式 >= 式 二項
== 等しいかの比較 式 == 式 二項
!= 等しくないかの比較 式 != 式 二項
&& 真偽の論理積 式 && 式 二項
|| 真偽の論理和 式 || 式 二項
? : 真偽による二者択一 式 ? 式 : 式 三項
= 複製代入(標準代入) 代入先 = 式 二項
:= 参照代入 代入先 := 式 二項
<- 移動代入 代入先 <- 式 二項
*= 乗算して代入 代入先 *= 式 二項
/= 除算して代入 代入先 /= 式 二項
%= 剰余を代入 代入先 %= 式 二項
+= 加算して代入 代入先 += 式 二項
-= 減算して代入 代入先 -= 式 二項
&= ビットの論理積を代入 代入先 &= 式 二項
|= ビットの論理和を代入 代入先 |= 式 二項
^= ビットの排他的論理を代入 代入先 ^= 式 二項
<<= ビットを左シフトして代入 代入先 <<= 式 二項
>>= ビットを右シフトして代入 代入先 >>= 式 二項
:== 代入型関数コール 関数名(引数並び):==式 二項
 この表内で、同じ枠内にある演算子は、同じ優先度を持ち、別の枠内にある演算子は、 上の方が下の方よりも高い優先度を持ちます。たとえば、乗算演算子 * は、除算演算子 / と同じ優先度ですが、加算演算子 + よりも高い優先度になります。  この表の基本用法欄には、演算子とその作用対象との用法上の基本的な関係を示してい ます。このなかで、作用対象が式であれば、文法上、任意の式が作用対象として可能であ ることを意味します。作用対象が、〜名(例えば、箱名、関数名など、但し、ラベル名は 除く)であれば、その対象は箱に限定されます。また、作用対象が代入先であれば、その 対象は代入可能な対象(箱または純粋配列の要素)に限定されます。引数並びに関しては、 別途説明します。 ●式の評価  式の値を求めることを「式を評価する」と言います。演算子を含む式は、その式内の各 演算子を作用させることによって、評価が行なわれます。演算子を含まない式、つまり、 定値や識別名だけの式では、その値自身が評価値になります。  式内に複数の演算子があると、作用対象が競合する場合があります。たとえば、 A + B * C の場合、項 B は、加算演算子 + と乗算演算子 * の両方の対象になっています。 式の評価は、競合がなければ、左から右の順に行なわれます。つまり、左側にある演算子 の方が、右側にある演算子よりも先に適用されます。 競合があれば、優先度の高い方の演算子が先に適用されます。上の例では、乗算演算子 * の方が、加算演算子 + よりも優先度が高いので、項 B は、乗算演算子 * の対象になり ます。加算演算子 + は、項 A と乗算結果を対象とすることになります。  同じ優先度の演算子どうしで競合がある場合は、演算子の結合性でどちらを優先するか が決まります。演算子が左結合なら、左の方の演算子を優先し、右結合なら、右の方の演 算子を優先します。たとえば、 A + B - C の場合、加算演算子 + と減算演算子 - は、同じ優先度で、左結合ですから、左の方の加 算演算子 + の方が優先されることになります。 次に右結合の例を示します。 A = B = C の場合、代入演算子 = は、右結合なので、まず、項 C が項 B に代入されてから、項 A に代入されることになります。なお、優先度が同じで結合性が異なる組合せはありません。  このように、式の評価順序は、演算子の優先度と結合性によって一律に決まります。こ の評価順序を変えたい場合は、丸括弧 ( ) を使います。丸括弧は、任意の式を囲うこと ができます。文法上、丸括弧で囲われた式もまた式で、演算子の作用対象になり得ます。 演算子の作用対象が丸括弧で囲われた式である場合、丸括弧内の式の評価値が、その演算 子の作用対象になります。つまり、丸括弧内の式の評価のほうが、その演算子の適用より も、先に行なわれます。たとえば、 A * ( B + C ) の場合、乗算演算子 * の右側は、丸括弧で囲われた ( B + C ) という式なので、この式 が先に評価されます。なお、この例で、もし、括弧がなければ、 A * B + C となりますが、この場合は、A * B が先に実行されます。  二項演算子では、左項と右項がともに、丸括弧で囲われた式になる場合があります。こ の場合は、左項の方が先に評価されます。たとえば、 ( A + B ) / ( C - D ) の場合、( A + B ) が先に評価され、次に ( C + D ) が評価されてから、除算演算が行 なわれます。  以下に、各演算子について、説明します。 ●算術二項演算子  算術二項演算子には、+ - * / % があります。各演算子の作用は以下の通りです。
    A + B       A と B を足した値
    A - B       A から B を引いた値
    A * B       A に B を掛けた値
    A / B       A を B で割った値
    A % B       A を B で割った余りの値(符号は A と同じ)
 算術二項演算子の作用対象は、整数値か、または、浮動小数点数値です。作用対象の二
項がともに整数値の場合、結果は整数値になり、二項のうちどちらかが浮動小数点数値の
場合、結果は浮動小数点数値になります。

 整数の算術演算は、2の補数表現の 32-bit の範囲でのみ有効で、オーバーフローとア
ンダーフローは、無視されます。浮動小数点数の算術演算で、オーバーフローが起きると
特別な値になり、アンダーフローが起きると値は0になります。いずれの場合でも、例外
は発生しません。

 加算演算子 + と減算演算子 - に関しては、文字列に対しても適用できます。
文字列A + 文字列B の結果は、文字列Aに文字列Bを連結した文字列になります。
文字列A - 文字列B の結果は、文字列Aと文字列Bを比較した結果を示す以下の整数値
になります。
    0・・・文字列Aと文字列Bは等しい
    正・・・文字列Aは文字列Bよりも、文字コードの値が大きい
    負・・・文字列Aは文字列Bよりも、文字コードの値が小さい
この場合の文字列比較は、文字コード列の単純な比較です。そのため、英字の大小等は、
区別されます。なお、もっと高度な文字列の比較を行なうには、専用の関数を使う必要が
あります。

 算術二項演算子の作用対象が、上記以外のデータ型の場合、不正演算になります。

 不正演算は、定値の場合なら、コンパイル時にエラーになりますが、そうでなければ、
実行時に例外が発生します。以降の説明で、不正演算になる場合も同様です。

●算術前置演算子
 算術前置演算子には、+ と - があります。どちらも作用対象は、整数値か、または、
浮動小数点数値に限ります。
  + 数値 の結果は、その数値と同じです。
  - 数値 の結果は、その数値の符号(正負)を反転した値になります。

単項の + と - 演算子の作用対象が、数値以外の場合、不正演算になります。

●ビット操作演算子
ビット操作演算子には、各ビットごとの論理演算を行なう
    &  |  ^  ~
と、各ビットのシフト演算を行なう
    <<  >>
があります。各ビット操作演算子の作用は、以下の通りです。
    A & B       A と B の各ビットごとの論理積を取った値
    A | B       A と B の各ビットごとの論理和を取った値
    A ^ B       A と B の各ビットごとの排他的論理和を取った値
    ~ A         A の各ビットを反転した値
    A << B      A の各ビットを B の値の回数だけ左にシフトした値
    A >> B      A の各ビットを B の値の回数だけ右にシフトした値(符号付き)
 ビット操作演算子の作用対象は、整数値に限ります。それ以外の場合は、不正演算にな
ります。

 整数値の各ビットを左にシフトすると、符号付きでも符号無しでも、最右端のビット( 
LSB )には 0 が入ります。一方、整数値の各ビットを右にシフトすると、符号付きの場合、
最左端の符号ビット( MSB )は、変わりませんが、符号無しの場合には、0 が入ります。
 演算子 >> は、符号付きの右シフトです。符号なしの右シフトを行なうには、リレー型
関数の 'shift を使います。

 なお、本言語では、ビット操作演算子 & | ^ の優先度は、比較演算子の優先度よりも
高くなっています。これは、C 言語等の優先度とは異なりますが、この方が、感覚的には
自然なので、敢えてこのようにしています。

●比較演算子
 比較演算子には、大小関係を判定する二項演算子
    <   <=   >   >=
と、等価性を判定する二項演算子
    ==   !=
があります。比較演算子の演算結果は、その演算が不正でなければ、必ず、真(1)か、偽
(0)になります。

 大小関係を判定する演算子の作用対象は、数値どうしか、または、文字列どうしに限り
ます。これ以外の場合は、不正演算になります。数値どうしの比較では、二項とも整数値
の場合、整数値の比較になり、どちらかが浮動小数点数値の場合、浮動小数点数値の比較
になります。文字列どうしの比較方法は、二項減算演算子 - の場合と同様です。

 大小関係を判定する各演算子の作用は、以下の通りです。
    A < B       A が B よりも小さければ、真(1)、さもなくば、偽(0)
    A <= B      A が B よりも小さいか等しければ、真(1)、さもなくば、偽(0)
    A > B       A が B よりも大きければ、真(1)、さもなくば、偽(0)
    A >= B      A が B よりも大きいか等しければ、真(1)、さもなくば、偽(0)
 等価性を判定する演算子の作用対象は、特に限定はなく、任意の式が可能です。等価性
を判定する各演算子の作用は、以下の通りです。
    A == B      A と B が等しければ、真(1)、さもなくば、偽(0)
    A != B      A と B が等しくなければ、真(1)、さもなくば、偽(0)
等価性の判定は、以下のように行なわれます。
    ・二項とも数値、または、二項とも文字列の場合
        大小関係の判定と同じ方法で比較して判定します。
    ・それ以外の場合
        対象の実体が同じなら等しいと判定、異なれば等しくないと判定します。
        ただし、二項とも null の場合、等しいと判定します。

たとえば、数値と文字列は、その値に関わらず、等しくないと判定されます。null は 
null 以外のものと等しいと判定されることはありません。中身が数値、文字列、空、の
どれでもない箱は、二項とも実体が同一の箱である場合に限り、等しいと判定され、実体
が異なれば、たとえ中身の構成と各値が全く同じでも、等しくないと判定されます。

●論理演算子
 論理演算子には、|| と && の二項演算子と、! の前置演算子があります。各論理演算
子の作用は、以下の通りです。
    A || B      A か B のどちらかが真ならば、真(1)、さもなくば、偽(0)
    A && B      A と B のどちらもが真ならば、真(1)、さもなくば、偽(0)
    ! A         A が真ならば、偽(0)、さもなくば、真(1)
 論理演算子の作用対象( 上記の項 A と項 B  )には、任意の式が可能です。この式の
評価値は、以下のように「真偽判定」されます。
    ・数値は、値が0でなければ真、0であれば偽
    ・文字列は、空でなければ真、空であれば偽
    ・null は、常に偽
    ・中身が数値、文字列、空、のどれでもない箱は、常に真、但し、複合箱に関しては、
     その真偽判定を行なう演算子関数が定義されていれば、その結果に従います。この
     詳細は、「演算子の多重定義」の章の以下の節に記述しています。
       ・後置演算子の多重定義

 二項論理演算では、左項の真偽判定結果が確定すれば、右項を評価しなくても、その論
理演算の結果が確定する場合があります。つまり、
    A || B は、A が真ならば、B を評価しなくても、真になり、
    A && B は、A が偽ならば、B を評価しなくても、偽になります。

このような場合、右項の評価は行なわれません。この影響は、たとえば、以下のような場
合に出ます。
    f1() || f2() で、関数 f1() の返値が真なら、関数 f2 はコールされません。
    x++ && y++ で、x の初期値が 0 なら、y の値は増えません。

 複数の二項論理演算子がある場合も、各二項論理演算子に関して、上記の規則が適用さ
れます。たとえば、
    A || B && C
では、演算子の優先度から、A || ( B && C ) となりますが、この評価は、A が真ならば、
B && C を評価しないで、真に確定され、A が偽ならば、B && C の評価に際し、B が偽な
らば、C を評価しないで、偽に確定されます。また、
    A && B && C
では、演算子の結合性から、( A && B ) && C となりますが、この評価は、A が偽ならば、
B と C を評価しないで、偽に確定され、A が真でも、B が偽ならば、C を評価しないで、
偽に確定さます。

 二項論理演算式では、このように、評価されない項がありますが、評価される項に関し
ては、どのような複雑な式でも、左側にある項(先に現れる項)のほうが、右側にある項
(後に現れる項)よりも、必ず先に評価されます。

●真偽による二者択一演算子
 真偽判定の結果に基づいて二者のうちの1つを選択する演算子があります。この演算子
の表記形式は、以下のような三項形態になります。
    C ? A : B
この表記全体で1つの式になります。この式の値は、C の評価値の真偽判定結果が、真な
らば、A の評価値になり、偽ならば、B の評価値になります。なお、この C, A, B は、
任意の式で、C の評価値の真偽判定は、論理演算子の真偽判定と同じです。

 真偽による二者択一は、この演算子を使わなくても、if-else 文でも実現できますが、
この演算子を使ったほうが、簡素に表記できます。たとえば、変数 x と変数 y の最小値
を引数にして、関数 func をコールする場合、この演算子を使うと、
    func( x <= y ? x : y );
と書けますが、これを、if-else 文で書くと、
    if( x <= y )    func( x );
    else            func( y );
のようになります。

 上記の表記形式 C ? A : B において、C の評価値の真偽判定結果が、真ならば、評価
されるのは A だけで、B は評価されません。また、偽ならば、A は評価されません。た
とえば、
    X = ( Y < 0 ) ? f1() : f2();
では、Y が負の時に、関数 f1() の返値が X に代入されます。この時、関数 f2() は、
コールされません。また、Y が負でない時、関数 f2() の返値が X に代入されます。こ
の時、関数 f1() は、コールされません。

 上記の表記形式 C ? A : B において、A の評価値のデータ型と、B の評価値のデータ
型は、必ずしも、同じである必要はありません。たとえば、
    X = ( Y > 1 ) ? 2 : "1以下";
では、Y が 1 よりも大きい時は、X に整数値 2 が代入され、Y が 1 以下の時は、X に 
"1以下" という文字列が代入されます。

●代入演算子
 代入演算子には、 =  :=  <-  の3つがあります。各代入演算子の作用の概要は、以下
の通りです。
    A = B       A に B の複製を代入する(複製代入)
    A := B      A に B の参照を代入する(参照代入)
    A <- B      A に B の実体を移動する(移動代入)
 各代入演算子の作用の違いは、主に、右辺( 上記の右項 B )の対象が箱である場合に
現れます。また、左辺( 上記の左項 A )の対象の扱いが、各代入演算子で異なります。
この詳細は後述します。まず、どの代入演算子にも共通する事項について述べます。

 どの代入演算子でも、左辺の対象、つまり、代入先は、箱、または、純粋配列の要素、
または、箱を特定する式、になります。箱を特定する評価結果にはならない定値や算術演
算式等は、代入先にはなれません。代入先が複数個ある「多重代入」も可能です。多重代
入に関しては、後に詳述します。以下に、代入先として可能な例を挙げます。
    i           デフォールトスコープ内にある i という名前の箱
    ::ABC       グローバルスコープ内にある ABC という名前の箱
    .X.Y        メンバースコープ内にある X という名前の箱の中にある
                 Y という名前の箱
    ^V[k+1]     モジュールスコープ内にある V という名前の連想配列の
                インデックス k+1 に対応する要素の箱
    @d(i)       関数スタティックスコープ内にある d という名前の純粋配列の
                インデックス i の要素
    f()         デフォールトスコープ内にある f という名前の関数が返す
                参照先の箱(箱への参照以外を返す関数は不可)
    (x,y,z)     デフォールトスコープ内にある x, y, z という名前の3つの箱
                (これは多重代入になります)
 代入先の箱は、代入前に宣言しておく必要はありません。代入時点で、
代入先の箱が存在しない場合、
    その箱は、新規に生成されて、その中身が、代入される内容に設定されます。
    この場合、代入先の箱は、そのスコープが特定されていれば、そのスコープ内に
    生成されます。デフォールトスコープの時には、現実行中の関数のローカル
    スコープ内に生成されます。
代入先の箱が存在する場合、
    その箱の中身は、代入される内容に入れ代わります。この時、もとの内容は消失
    します。箱の中身のデータ型は、固定的ではないので、代入の前後で、箱の中身
    のデータ型が変わってもまったく問題ありません。

 たとえば、グローバルスコープ内に XYZ という名前の箱が存在しないときに、
    ::XYZ = "This is XYZ";
を実行すると、グローバルスコープ内に XYZ という名前の箱が新規に生成されて、
その中身が、"This is XYZ" という文字列になります。次に、
    ::XYZ = 123;
を実行すると、もとの "This is XYZ" の文字列は破棄されて、その箱の中身は、123 と
いう整数値に変わります。
また、現実行中の関数のローカルスコープ内に P という名前の箱が無い時に、
    P.X = 45.6;
    P.Y = 78.9;
を実行すると、現実行中の関数のローカルスコープ内に P という名前の箱が、新規に生
成されて、その箱の中に、浮動小数点数値 45.6 が入った箱 X と、浮動小数点数値 78.9
 が入った箱 Y が、生成されます。この状態で、次に、
    P = 0;
を実行すると、箱 P の中にあった箱 X と箱 Y は、破棄されて、箱 P の中身は、
整数値 0 に変わります。

 代入先には、純粋配列の要素を指定できます。たとえば、
    V(i,j) = 10;
とすると、デフォールトスコープ内にある V という名前の純粋配列のインデックス
(i,j) が指す要素に、10 を代入します。

代入先が純粋配列の要素の場合、その純粋配列は、代入前に宣言しておく必要があります。
また、純粋配列の要素のデータ型は固定的で、数値以外は代入できません。純粋配列に関
しては、「純粋配列」の章で詳しく説明します。

 代入先には、箱への参照を返す関数が使えます。たとえば、グローバルスコープ内の箱
 A への参照を返す関数 F が、
    function F()    {  return ::A'ref;  }
と定義されていて、
    F() = 1;
を実行すると、箱 A に 1 が代入されます。なお、この場合、箱 A は事前に存在してい
る必要があります。

 次に、各代入演算子の作用の違いについて述べます。この主な違いは、右辺の対象が箱
である場合に現れます。以下の説明では、特に断らない限り、この場合を前提にします。

●複製代入
 複製代入では、左辺の対象が箱の場合、その箱に、右辺の箱の中身の複製が代入されま
す。その結果、左辺の箱は、右辺の箱の言わばクローンになります。つまり、左辺の箱と
右辺の箱は、中身はそっくり同じですが、実体は個別に存在します。たとえば、
    X = "This is a string.";
    Y = X;
を実行すると、"This is a string." という文字列データは、2つ存在して、1つは、箱
 X の中に、もう1つは、箱 Y の中に存在することになります。

 階層構造の箱を複製することも可能です。以下に、簡単ですが、2個の箱が入っている
箱を複製する例を示します。
    X.A = 1;
    X.B = 2;
を実行すると、箱 X の中には、整数値 1 が入った箱 A と、整数値 2 が入った箱 B が、
生成されます。次に、
    Y = X;
を実行すると、箱 Y の中には、整数値 1 が入った箱 A と、整数値 2 が入った箱 B が、
箱 X の中からコピーされます。その結果、箱 X.A と箱 Y.A は、同じ値で、各実体は、
別々に存在します。また、箱 X.B と箱 Y.B に関しても同様です。ちなみに、箱 X と箱 
Y は、中身の構成と各値は同じでも、その実体が別の構造体なので、X == Y は、偽にな
ります。

 本言語では、複製代入が標準の代入になります。そのため、複製代入を「標準代入」と
いうこともあります。どの代入演算子を使ってもその作用が同じ場合には、通常、複製代
入演算子を使います。参照代入演算子と移動代入演算子は、各固有の用途に限定して使い
ます。

●参照代入
 参照代入では、左辺の対象が箱の場合、その箱には、右辺の箱への参照が代入されます。
参照は、実体の箱への言わばポインターです。参照代入では、このポインターが設定され
るだけで、複製代入のように、箱の実体の複製が作られるわけではありません。そのため、
複製を作る必要が特になければ、参照代入を使うほうが、複製代入を使うよりも、高速で、
かつ、メモリーの節約になります。

 参照が代入された箱(その中身が他の箱への参照である箱)にアクセスすると、その実
質の対象は、その箱ではなく、その箱の参照先の箱になります。ただ、参照代入の左辺の
対象の箱に限っては、その箱自身が実質の対象になります。(参照に関しては、「参照」
の章で詳しく説明します。)たとえば、
    X = 1;      // 箱 X に整数値 1 を入れる
    Y := X;     // 箱 Y に箱 X への参照を設定する
を実行して、次に、
    Y = 2;
を実行すると、この標準代入の左辺の実質の対象は、箱 Y ではなく、箱 Y の参照先の箱
 X になり、箱 X に整数値 2 が代入されます。この時、箱 Y の中身はそのままです。

 参照代入では、右辺を、まず参照に評価しようとしますが、右辺が、箱でない場合、つ
まり、定数か、または、何らかの値が導かれる演算式のような場合には、参照にはなり得
ないので、右辺の評価値は、通常の評価値になります。したがって、この場合、左辺の箱
には、右辺の通常の評価値が代入されます。なお、この場合も、代入先は、左辺の箱自身
になります。たとえば、上例の続きで、箱 Y に箱 X への参照が設定されている時、
    Y := 3;
を実行すると、参照代入の左辺の実質の対象は、左辺の箱 Y 自身になるので、箱 Y の中
身が整数値 3 に変わります。なお、この時、箱 X の中身は変わりません。

●移動代入
 移動代入では、左辺の対象が箱の場合、その箱へ、右辺の箱が移動されます。つまり、
右辺の箱の実体の名前と所属スコープが、左辺の箱の名前と所属スコープに変わります。
たとえば、
    X = 1;
    Y <- X;
を実行すると、箱 Y に整数値 1 が入り、箱 X は実在しなくなります。これは、
    X = 1;
    Y = X;
    delete X;
を実行するのと、結果的には同じですが、移動代入では、実体が移動するだけなので、実
体の複製と削除を行なうよりも、高速に処理されます。また、実体の移動では、使用メモ
リー量は増減しません。ただし、名前とスコープの変更に伴う使用メモリー量の増減はあ
ります。

 階層構造の箱を移動することも可能です。この移動で実質的に変わるのは、根元の箱の
名前と所属スコープだけです。根元の箱よりも下位の階層にあるどの箱も、その名前と
中身は変わりません。また、上下左右の相対関係もそのまま保たれます。以下に、簡単で
すが、2個の箱が入っている箱を移動する例を示します。
    P.A = "This is A.";
    P.B = "This is B.";
    Q <- P;
を実行すると、箱 Q の中に、箱 A と箱 B が入ります。これらの箱の中身は、それぞれ、
文字列 "This is A." と "This is B." です。この時、箱 P は実存しなくなっています。

 階層構造の箱を移動する場合、その階層構造の中の箱へ、その階層構造の根元の箱を移
動することはできません。たとえば、
    X.A <- X;
は、実行エラーになります。

●多重代入
 代入式の左辺と右辺には、複数項を指定できます。複数項の表記形式は、
    ( 項, 項, ・・・ )
のように、各項をコンマで区切り、全体を丸括弧で囲みます。項の個数には特に制限はあ
りません。

 複数項を使った代入を、多重代入と呼びます。多重代入は、複製代入、参照代入、移動
代入のどの代入でも、可能です。多重代入では、左辺と右辺の複数項内で、各同順位の項
が対応します。たとえば、複製代入で、
    ( A, B ) = ( 1, 2 );
を実行すると、箱 A に 1 が代入され、箱 B に 2 が代入されます。次に、
    ( X, Y, Z ) = ( A + 1, B + 2, 3 );
を実行すると、箱 X, Y, Z には、それぞれ、2, 4, 3 が代入されます。

また、移動代入で、
    ( A, B, C ) <- ( X, Y, Z );
を実行すると、箱 A, B, C へ、それぞれ、箱 X, Y, Z の実体が移動されます。

 多重代入で、左辺の項数が、右辺の項数よりも多い場合、余った左辺の各項は、空箱に
なります。たとえば、
    ( A, B, C ) = ( 1, 2 );
を実行すると、箱 A に 1 が代入され、箱 B に 2 が代入されますが、箱 C は、空にな
ります。また、
    ( X, Y ) = 1;
を実行すると、箱 X に 1 が代入され、箱 Y は、空になります。

 多重代入で、左辺の項数が、右辺の項数よりも少ない場合、余った右辺の各項は、評価
されますが、どこにも代入されません。たとえば、
    ( A, B ) = ( 1, 2, 3 );
を実行すると、箱 A に 1 が代入され、箱 B に 2 が代入されますが、3 の項は、どこに
も代入されません。この状態から、
    X = ( A++, B++ );
を実行すると、箱 X には、1 が代入され、箱 A の中身は 2 になります。B++ の結果は
どこにも代入されませんが、評価は行なわれるので、箱 B の中身は 3 になります。

 関数が返す複数の値を、多重代入することも可能です。たとえば、
    function F()  {  return ( 10, 20, 30 );  }
という関数は、10, 20, 30 の3値を返しますが、この関数を使って、
    ( X, Y, Z ) = F();
を実行すると、箱 X, Y, Z には、それぞれ、10, 20, 30 が代入されます。

 関数が返す複数の参照先への箱に、多重代入することも可能です。たとえば、
    function G()  {  return ( ::A'ref, ::B'ref );  }
という関数は、グローバルスコープ内の箱 A と箱 B への参照を返しますが、この関数を
使って、
    G() = ( -1, -2 );
を実行すると、グローバルスコープ内の箱 A, 箱 B に、それぞれ、-1, -2 が代入されま
す。なお、この場合、グローバルスコープ内の箱 A と 箱 B は、事前に存在している必
要があります。

 多重代入でも、代入を連結できます。たとえば、
    ( A, B ) = ( X, Y ) = ( 1, 2 );
を実行すると、整数値 1, 2 は、それぞれ、まず、箱 X, Y に代入されて、次に、箱 A, 
B に代入されます。

 複数項は、複製代入、参照代入、移動代入以外の演算子には、使用できません。たとえ
ば、( A, B ) + ( X, Y ) とすることはできません。

 複数項内の項を、複数項にもできますが、結果は、複数項にしない場合と同じです。た
とえば、( A, ( B, C )) は、( A, B, C ) と同じです。

 複数項は、必ず、丸括弧で囲う必要があります。さもなければ、各項の区切りのコンマ
は、式の区切りのコンマとして解釈されます。たとえば、
    A, B = X, Y;
は、A という式と、B = X という式と、Y という式の、3つの式なら成る文として、
解釈されます。

●演算併用の代入演算子
 算術演算またはビット操作演算を併用した代入を行なう演算子が10個あります。以下
に、これらの演算子の作用を示します。
    A += B      A = A + B  と同じ
    A -= B      A = A - B  と同じ
    A *= B      A = A * B  と同じ
    A /= B      A = A / B  と同じ
    A %= B      A = A % B  と同じ
    A &= B      A = A & B  と同じ
    A |= B      A = A | B  と同じ
    A ^= B      A = A ^ B  と同じ
    A <<= B     A = A << B  と同じ
    A >>= B     A = A << B  と同じ
 これらの演算子を使うほうが、算術/ビット操作演算子と標準代入演算子を組み合わせ
て使うよりも、以下の利点があります。
    ・処理速度が速い
    ・中間コード量が少ない
    ・表記が簡素

 演算併用の代入演算子の左辺の対象、つまり、代入先は、箱、または、純粋配列の要素
になる必要があります。また、代入先は、代入前の演算で必要になるので、適切なデータ
型の値であることが必要です。これらの制約やその他の制約は、基本的に、その演算子と
同等の作用になる算術/ビット操作演算子と標準代入演算子を組み合わせて使うときの制
約と共通です。

●増減代入演算子
 増減代入演算子には、作用対象に1を加算して代入する単項演算子 ++ と、作用対象に
1を減算して代入する単項演算子 -- があります。以下に、これらの演算子の作用を示し
ます。
    ++A     A に 1 を加算した値を A に代入する      この式値は代入後の値
    A++     A に 1 を加算した値を A に代入する      この式値は代入前の値
    --A     A から 1 を減算した値を A に代入する    この式値は代入後の値
    A--     A から 1 を減算した値を A に代入する    この式値は代入前の値
 増減代入演算子は、前置演算子としても、後置演算子としても使えます。どちらの場合
でも、代入される値は同じですが、その式としての値が異なります。前置の場合、その式
値は、代入後の値になり、後置の場合、その式値は、代入前の値になります。たとえば、
    X = Y = 0;
    print ++X, Y++;
を実行すると、1, 0 とプリントされます。次に、
    print X, Y;
を実行すると、1, 1 とプリントされます。

 作用対象に単に1を加減算して代入するのは、加減算演算子と代入演算子の組み合わせ、
または、演算併用の代入演算子 += と -= でも可能ですが、増減代入演算子を使うほうが、
    ・処理速度が速い
    ・中間コード量が少ない
    ・表記が簡素
という利点があります。

 増減代入演算子の対象、つまり、代入先は、箱、または、純粋配列の要素になる必要が
あります。また、代入先が箱の場合、その中身は数値に限定されます。

●スコープ規定演算子
 スコープ規定演算子には、システムスコープを規定する5つの前置演算子
    ::  .  ^  $  @
と、一般の箱内のスコープを規定する2つの二項演算子
    ::  .
があります。

 スコープに関しては、「スコープ」の章で詳しく説明します。ここでは主に、スコープ
規定演算子の機能について述べます。

 システムスコープを規定する前置演算子と対象の箱の所属するスコープの関係を、以下
に示します。( ここで、A は任意の箱名 )
    ::A     グローバルスコープ内の箱 A
     .A     メンバースコープ内の箱 A
     ^A     モジュールローカルスコープ内の箱 A
     $A     スレッドローカルスコープ内の箱 A
     @A     関数スタティックスコープ内の箱 A
      A     デフォールトスコープ内の箱 A
 一般の箱内のスコープを規定する二項演算子は、以下のようになります。( 以下で、A
 は任意のスコープ規定式、B は任意の箱名 )
    A::B    スコープ A 内の箱 B     (参照型)
    A.B     スコープ A 内の箱 B     (降下型)
 一般に、箱 X の中に、箱 Y が入っている場合、箱 X からは直接、箱 Y が見えるので、
箱 X は、箱 Y のスコープになります。箱 X が、たとえば、デフォールトスコープ内に
あると、箱 X の中に入っている箱 Y は、デフォールトスコープから、
    X.Y
として指定できます。もし、箱 X がグローバルスコープ内にあれば、
    ::X.Y
として指定できます。

 箱 X の中にある箱 Y の中に、さらに、箱 Z が入っていると、この箱 Z は、デフォー
ルトスコープから、
    X.Y.Z
として指定できます。もし、箱 X がスレッドローカルスコープ内にあれば、
    $X.Y.Z
として指定できます。この箱 Z の中に、さらに別の箱が入っている場合も同様です。こ
のように、二項演算子「.」は、通常、箱の中のスコープを降下するのに使います。

 スコープは、参照を使っても規定できます。たとえば、上記の箱 X, Y, Z の包含関係
( デフォールトスコープ内の箱 X の中に箱 Y があり、さらに、その箱 Y の中に箱 Z 
がある場合)において、
    P := X.Y;
として、箱 X の中にある箱 Y への参照を、デフォールトスコープ内の箱 P に設定すると、
    P::Z
で、参照箱 P から、箱 X の中にある箱 Y の中にある箱 Z を指定できます。もし、この
参照を、モジュールローカルスコープ内の箱 Q に設定すると、
    ^Q::Z
で、参照箱 Q から、箱 X の中にある箱 Y の中にある箱 Z を指定できます。このように、
二項演算子「::」は、通常、参照によるスコープの指定に使います。

 慣習上、スコープの降下用には、二項演算子「.」を使い、参照によるスコープの指定
用には、二項演算子「::」を使います。しかし、機能的にその用途に限定されているわけ
ではありまん。

二項演算子「.」と「::」との本質的な違いは、それが、代入先のスコープを規定してい
て、そのスコープが存在しないか、または、不正な場合に現れます。この場合、二項演算
子「.」で規定したスコープであれば、そのスコープが強制的に形成されます。一方、二
項演算子「::」で規定したスコープであれば、例外が発生します。たとえば、デフォール
トスコープ内に、箱 S が無いか、または、箱 S があっても、スコープとして有効でない
状態で、
    S.X = 1;
を実行すると、箱 S は、強制的にスコープとして有効な箱として形成され、その中に、
箱 X が生成されて 1 が代入されます。一方、同じ状態で、
    S::X = 1;
を実行すると、例外が発生します。なお、この場合、もし、箱 S がスコープとして有効
だったら、箱 X は、代入前に存在しなくても、代入時点で自動的に生成されます。この
時、例外は発生しません。

●括弧演算子
 本言語では、丸括弧 ( ) と角括弧 [ ] を、特殊な演算子として扱います。これらをそ
れぞれ、「丸括弧演算子」「角括弧演算子」と呼ぶことにします。また、両者を総称して
「括弧演算子」と呼ぶことにします。括弧演算子は、括弧の左外側に置かれた項が、作用
対象で、括弧の内側が、引数並びになります。

●丸括弧演算子
 丸括弧演算子では、以下のような表記形態になります。
    箱名( 引数並び )
 丸括弧演算子は、作用対象の箱の中身の種類に応じて、以下の作用があります。
    ・関数の場合、その関数をコールする
    ・クラスの場合、そのクラスのインスタンスを生成する
    ・純粋配列の場合、その純粋配列の要素を特定する
いずれの場合も、括弧内の引数並びがパラメーターになります。

 引数並びは、空か、1つだけの式か、または、たとえば、
    式, 式, 式
のように、2つ以上の各式をコンマ , で区切ったリストになります。この場合の各式は、
空であっても構いません。たとえば、
    式, , 式
では、2番目の式が空になっています。引数並びに書ける式の最大個数は、現状、100 ま
でです。

 関数クラスとインスタンス純粋配列に関しては、関連各章で詳しく説明します。

●角括弧演算子
 角括弧演算子では、以下のような表記形態になります。
    箱名[ インデックス ]
 この表記は、角括弧演算子の作用対象の「箱名」の箱内にある「インデックス」に対応
する連想名の箱を特定することになります。たとえば、
    X[3,4]
は、デフォールトスコープ内の箱 X の中にある、[3,4] という連想名の箱になります。
角括弧演算子のインデックスは、丸括弧演算子の引数並びと同様です。

 角括弧演算子の作用対象の箱は、省略可能で、その場合、[ インデックス ] の連想名
の箱自身を特定することになります。たとえば、
    ["Content-Type"]
は、デフォールトスコープ内にある ["Content-Type"] という連想配列名の箱になります。

 角括弧演算子を並べて書くと、多次元の連想配列になります。たとえば、
    ::Y["C-3PO"][5]
は、グローバルスコープ内の箱 Y の中の ["C-3PO"] という連想名の箱の中の [5] という
連想名の箱になります。

 連想配列に関しては、「連想配列」の章で詳しく説明します。

●関数コール演算子(非標準型)
 本言語では、標準型の関数コール形式以外にも、以下の演算子を使った関数コール形式
があります。

リレー型関数コール演算子 '
 これは、以下のような形式で関数を呼び出す時に使います。
    式 ' 関数名( 引数並び )
 この関数コール形式の詳細は、「関数」の章の以下の節で説明しています。
  ・リレー型(後置型)の関数コール形式

代入型関数コール演算子 :==
 これは、以下のような形式で関数を呼び出す時に使います。
    関数名( 引数並び ):== 式
 この関数コール形式の詳細は、「関数」の章の以下の節で説明しています。
  ・代入型の関数コール形式

コマンド型関数コール演算子 ~
 これは、以下のような形式で関数を呼び出す時に使います。
    関数名~ 引数並び
 この関数コール形式の詳細は、「関数」の章の以下の節で説明しています。
  ・コマンド型の関数コール形式

●ラベル名演算子
 ラベル名演算子 : は、作用対象のラベル名を、文字列へ変換する前置演算子です。こ
れは、例外処理で、エラーワープ先( OnValueError, OnFuncError 等 )や、代替ラベル( 
DefLabel )に、ラベル名を設定する時などに使います。たとえば、
    OnValueError = :ErrorEntry;
を実行すると、エラーワープ先を指定する OnValueError 変数に、ErrorEntry というラ
ベル名に対応する文字列が代入されます。また、
    DefLabel = :Label[i];
を実行すると、代替ラベルを指定する DefLabel 変数に、当時点での変数 i の値におけ
る Label[i] という連想配列型のラベル名に対応する文字列が代入されます。

 ラベル名演算子の作用対象が不正な場合、その評価値は null になります。この場合、
例外は発生しません。

 なお、ラベル名を、文の前に付ける時、
    ラベル名:   文
という表記になりますが、このコロンと、ラベル名演算子のコロンとは、関連はあります
が、文法的/機能的には全く別物です。

 例外処理に関しては、「例外処理」の章で詳しく説明します。