McCal Editorは、McCalのためのスクリプト(McCal Script)を編集するためのエディタです。Function Viewerから起動します。
McCal Editorの画面デザインは、McCal本体のそれに似せてあります。違いは上の図の右上にあるように、左右のカーソル移動ボタンに加えて上下のカーソル移動ボタンが追加されています。また、
ボタンの代わりに ボタン(改行, carriage return, ボタン)があります。McCal Editorから、読み取り専用のMcViewerやFunctionViewerを起動し、履歴、マクロ、関数などを貼り付けることができます。
McCal Scriptは、McCal Calculatorでの使用を目的に開発されたスクリプト言語です。 簡素で小さく、データ型の自動検出が特徴です。BASIC言語風のフローコントロール構文が使えます。 一行ごとに解釈されます。
McCalは、データ型として整数・浮動小数点・複素数(実部と虚部もそれぞれ整数あるいは浮動小数点の型を取ります)・文字列をサポートします。 また、これらのデータ型を要素とする配列をつかえます。演算の際は、型を自動検出し、自動的に最適な型に自動変換して演算を行います。
整数は64bit, 浮動小数点は倍精度で計算され、整数同士の演算は可能な限り整数で計算されますが、オーバーフローする時などは浮動小数点に自動的に変換されます。
文字列の場合は、演算として加算(+)のみ可能で、文字列の連結が行われます。また文字列と数の加算は、数を文字列に変換した後、連結されます。
条件判定は、評価値が0ならば「偽」0以外ならば「真」として扱われます。比較演算子は整数の0あるいは1を返します。
McCal Script は、数値、変数、演算子、関数、予約語からなります。 McCal処理プログラムは、まずMcCal Scriptを一行ずつトークン(語や記号)に分解し、数値、変数、演算子、関数、予約語を解釈します。 以下の表のように、トークンの最初の文字が解釈に重要な意味を持ちます。
タイプ | フォーマット | 例 | 数値(10進) | 整数・浮動小数点 | 100.0, 1E-8 (1×10-8を表す) | 数値(2進) | 0bで開始+[0-1]、小数点不可 | 0b10011001 | 数値(8進) | 0で開始+[0-7]、小数点不可 | 0377 | 数値(16進) | 0xで開始+[0-9A-Fa-f] | 0xFFFF, 0x7f, 0x0.1p-6 (1×16-1x2-6に等しい) | 文字列 | "で挟む | "Hello, World!" | 変数 | 英小文字一つ | a, b, z | グローバル変数 | @で始まる英数字単語 | @length, @1stName, @a | 演算子 | 特殊文字 | +, ×, >=, && | 関数 | #func(a,r,g,s), #Package.func(a) | #sin(x), #Myprog.test(10,100) | 予約語 | 大文字で始まる英文字からなる単語 | For, Print, Dim |
変数は、データ型すべてを代入することができます。変数のデータ型の宣言は必要ありません。
他の多くのプログラミング言語と異なり、変数は、英文字(半角ローマ字)の一文字だけをサポートします。また、掛け算の演算子を省略できます。 以下の例では、abcとa*b*cは、同じ値を返します
a=2; b=4; c=-2 ▶ -2 abc ▶ -16 a*b*c ▶ -16 a(b+c) ▶ 4
大文字の変数名を使うときは、隠された乗算と共に使われた時、エラーを起こすことがあります。
AB
上の例では、McCalは、"AB" というキーワードが無いとエラーを報告します。
A*B A B
'A'と'B'の間に演算子か、空白を入れることにより、変数名と認識されます。
グローバル変数のみ、'@'で始まる英数字からなる単語を使えます。
@1stName = "John"; @2ndName="Doe" ▶ "Doe" @1stName + " " + @2ndName ▶ "John Doe"
グローバル変数は、McCal Viewerで名前と値を確認できる変数でもあります。グローバル・ローカル変数は、変数のスコープで説明します。
配列は現在のところ、三次元までサポートされています。二次元の配列を数学の行列とみなし、加減算・積算の行列演算を行うことができます。
配列のサイズを前もって予約したい場合に、Dim宣言を使います。 以下の例では、それぞれ順に一次元から三次元までの配列を宣言しています。 各要素には整数のゼロが入れられます。
Dim a[100] Dim a[100][3] Dim a[100][3][2]
Dim宣言で、配列の初期化をすることができます。サイズ指定がされない場合は、初期化の値のサイズで行われます。
Dim a=[[0.5,0],[0,2]] ▶ array[2][2]
サイズ指定された場合、初期化されていない要素は整数の0がセットされます。 初期化のための値の方が配列のサイズが大きい場合は、サイズ指定の方が優先され、余分な初期化要素は捨てられます。
Dim a[100][2]=[[0.5,0],[0,2]] ▶ array[100][2] Dim a[2][2]=[[1,0,3],[0,2,4]] ▶ array[2][2]
McCal特有の演算子があり、その他は、できるだけJava, C 風の演算子に合わせてあります。またMATLAB風の、行列演算に関する豊富な演算子を備えています。
McCal 特有の演算子として、累乗(^)、階乗(!)があります。それぞれJavaなどでは、 排他的OR (exclusive OR), 論理否定(logical NOT)に使われているので、McCal Script では、排他的OR演算子に'|^’、 論理否定演算子に'!!'を使うように定義されています。
優先順位 | 演算子 | 形式 | 名称 |
---|---|---|---|
0 | () | (y) | 括弧 |
1 | () | x(y) | 関数呼出し演算子 |
[] | x[y] | 配列添字演算子 | |
2 | ! | x! | 階乗演算子 |
3 | .' | x.' | 行列転置演算子 |
' | x' | 行列複素共役転置演算子 | |
4 | ^ | x^y | 累乗演算子 |
.^ | x.^y | 行列要素累乗演算子 | |
4 | + | +x | 単項+演算子 |
- | -x | 単項-演算子 | |
!! | !!x | 論理否定演算子 | |
5 | xy | 省略された2項乗算演算子 | |
6 | * | x * y | 2項乗算演算子 |
/ | x / y | 除算演算子、行列右除算 | |
% | x % y | あまり演算子 | |
.* | x .* y | 行列要素乗算演算子 | |
./ | x ./ y | 行列要素右除算演算子 | |
.\ | x .\ y | 行列要素左除算演算子 | |
\ | x \ y | 行列左除算 | |
7 | + | x + y | 2項+演算子 |
- | x - y | 2項-演算子 | |
8 | << | x<<y | ビットシフト左 |
>> | x>>y | ビットシフト右 | |
9 | < | x < y | <比較演算子 |
<= | x <= y | <=比較演算子 | |
> | x > y | >比較演算子 | |
>= | x >= y | >=比較演算子 | |
10 | == | x == y | ==比較演算子 |
!= | x != y | !=比較演算子 | |
11 | & | x & y | ビット単位のAND演算子 |
12 | |^ | x |^ y | ビット単位の排他OR演算子 |
13 | | | x | y | ビット単位のOR演算子 |
14 | && | x && y | 論理AND演算子 |
15 | || | x || y | 論理OR演算子 |
16 | = | x = y | 単純代入演算子 |
17 | ⇒ | ⇒ y | 後置代入演算子 |
18 | , | x , y | コンマ演算子 |
関数には、McCalに備え付けられたシステム関数と、自由に定義可能なユーザ関数があります。
関数は、McCal Scriptにおいては、’#’で始まる英数字の名前と引数リストで呼び出すことができます。
複数のユーザ関数をパッケージにまとめて管理します。パッケージ名は英字大文字からはじまり、関数名は英字小文字からはじまります。
FunctionViewerでは、システム関数・ユーザ関数の選択 ⇨ パッケージの選択 ⇨ 関数の選択 と階層的に管理します。
完全な関数の名前は、パッケージ名と関数名をビリオド(.)で繋げたものです。 システム関数にはパッケージ名はありません。
次の表は、関数名の例を示しています。
関数名 | 説明 |
---|---|
#sin(x) | システム関数。リストと説明はFunctionViewerで閲覧できる |
#Pkg.fn(x) | ユーザ定義関数。パッケージ名は、大文字で始まり、関数名は小文字で始まる。 |
McCal Scriptは、BASIC言語風の条件判断、ループ制御構文をサポートしています。 複数行にまたがるこれらの構文は、ユーザ定義関数の内部のみでサポートされており、 電卓のメイン画面では使えませんので注意してください。
電卓のメイン画面では、実行制御関数にコードブロックを渡すことで繰り返しが実現できます。
If statement
If a>0 Then Print "a is positive" ElseIf a == 0 Then Print "a is zero" Else Print "a is negative" EndIf
For statement
Dim a[20] For c=0 to 19 Step 2 a[c] = "No." + c Next
Do ~ Loop While, Do ~ Until statement
Dim a[20][2] c = 0 Do a[c][0] = "square of " + c c=c+1 Loop While c < 20 c = 0 Do a[c][1] = c^2 c=c+1 Loop Untile c == 20
Do While ~ Loop, Do Until ~ Loop statement
Dim a[20][2] c = 0 Do While c < 20 a[c][0] = "square of " + c c=c+1 Loop c = 0 Do Until c == 20 a[c][1] = c^2 c=c+1 Loop
Exit statement
内側のループを脱出します。
Continue statement内側のループの最後尾までの実行を飛ばしてループの後端に実行を移します。
Return statementユーザ定義関数を脱出して、値を返します。
複数の値を戻すことができます。式をコンマで複数リストアップします。
Return a, b, c
変数のリストを使って、これらの返り値を捕捉します。
[x,y,z] = #Example.returnTest(A) [x,y] = #Example.returnTest(A) x = #Example.returnTest(A)
二番目と三番目の例では、一部の返り値は捨てています。全ての例で、変数'x' には、最初の返り値がコピーされます。
[x,y,z,a] = #Example.returnTest(A)
変数リスト中の変数の数が、返り値の数より大きい場合、エラーが報告されます。
実行制御や各種の宣言・命令につかわれる予約語のリストです。
大文字で始まる英字からなる単語がつかわれます。
予約語 | 使用例 | 説明 |
Func | Func #Pkg.fn(x,y) {...} | ユーザ定義関数の宣言 |
Dim | Dim a[100][2] | 配列のサイズ宣言。 |
Print a, a+b | 書き出し。 | |
Println | Println a, a+b | 書き出し。改行つき |
If, Then, ElseIf, Else, EndIf | If a>0 Then ... ElseIf a==0 Then ... Else ... EndIf | 条件分岐。ElseIf, Else行は省略可能 |
For, To, Step, Next | For k=1 To 10 Step 2 ... Next | For ループ。Stepは省略可能 |
Do, While, Until, Loop | (実行制御の項を参照) | While, Until ループ |
Break | Break | 内側のループからの脱出 |
Continue | Continue | 内側のループの最後へ移動 |
Return | Return 式 | 関数の実行を終えて、式の評価値を返す。 |
ユーザー定義関数の中で現れる変数は、(後述する例外を除き)ローカル変数として扱われます。 ローカル変数は、その関数内でのみデータを保持し、外部の変数には影響を与えません。また外部からはローカル変数が見えません。
どのように変数が見えるかを変数のスコープと呼び、次の図で説明します。
McCalの電卓画面で使われる変数は、グローバル変数(Global variables)として扱います。 これがMcCal Viewerの変数タブで内容を確認できる変数です。
(1) ユーザが定義した関数を呼び出すと、まず引数の値が求められます(上図では1, a+1)。
(2) 次にその関数呼び出し毎に、関数内でのみ参照できるローカル変数のための領域が確保されます(上図において、Local Variables 1)。
(3) そして関数定義での引数リストの変数a, bがこの領域内に確保され、最後に、その関数を呼び出した環境での引数の評価値がコピーされます(Call by Value)。
関数内で、ローカル変数を参照・変更できるのは、その関数内だけになります。
ある関数内からグローバル変数にアクセスすることは可能です。アクセス制御子'@'を変数名の前に付けます。関数内でこれらの変数の内容を変更した場合、実体はグローバル変数空間にありますので、グローバル変数を書き換えることが可能になります。
また、'@'の後ろに続く英数字を変数名と見なしますので、グローバル変数空間では、単語を変数名として使えるようになります。
計算結果を返すには、Return文を使う方法が一般的です。アクセス修飾子'@'を用いてグローバル変数に書き込む方法もありますが、避けたほうが良いです。
コードブロックは、局地的な変数のための領域を作らないで、呼び出し元の変数名空間が使用されます。たとえば、#times(), #sigma()などの繰り返し関数の多くは、カウンタとして変数'k'を使います。この変数kは呼び出し元の変数空間に属すると見なされますので、繰り返し関数の実行で変数kの値が変更されます。変数kの内容が必要であれば、あらかじめ別の変数に値を退避して下さい。