list:
{exp,..,exp}
exp:
exp operator2 exp
term
term:
primary...primary
primary
primary:
literal
(exp)
identifier
identifier (exp,...,exp)
list
c.f. lisp方式
exp:
exp list
list:
{exp,...,exp}
ex.
={a, +{ *{2,x}, 1}}
内部構造はこれに近い。
compExp:
arithmetic [> < ==] arithmetic [> < ==] .... arithmetic
arithmetic:
[nul + -] exp ... [+ -] exp
mExp:
operatorExp [*/] ... [*/] operatorExp
operatorExp:
powerExp ... powerExp (右から左)
powerExp:
Exparithmetic
Exp^Exp
underscoreExp:
expsequence
exp_exp
dotExp:
term . term
コメント:
オペレータ積 l_value r_value
もしl_valueがoperatorであればoperator(r_value)が評価される。
もしl_value*r_valueが定義されていればそれになる。
A.iとA[1,2,3]の等価性はとりあえずなし。
M.iとM.sunとかの違いはどうするか。
仮にこのように決定する。
M_expはexpを評価して渡す。
M.expはexpを評価せずに渡す。
term:
INTEGER_LITERAL
FLOAT_LITERAL
IDENTIFIER
IDENTIFIER ( sequence ) function call
STRING
( exp )
list
コメント:
termには現状'[' exp ']' がある。
function( sequence )でもfunction callがなされるが
operator (sequence)でもfunction callがなされる。
さしあたりfunctionはオペレータとしても使えるし
オペレータはfunctionとしても使える。
sequence:
exp , ... , exp
exp
id_sequence:
id, ... , id
id
list:
{ sequence }
{} : const empty list
statement_squence:
statement [CR ,] ... [CR ,] statement
Statement演算子群
assignStat:
operatorExp = compExp
define identifier (id_sequence) list
while (condExp) list
if (condExp) list
if (condExp) list else list
return [nul exp stat]
break
コメント:
変数などの状態を変えるものはstatementに入る。
statementの多くには何らかの遅延評価が係っている。
assignExpの形式
id = exp : expが評価されて、変数idに代入される
id x = exp : 仮引数xは評価されない。expは、仮引数以外は評価される。
id(seq) = exp : 仮引数列をひいて関数を定義。
id.exp1 = exp: exp1の要素に代入
ex.
a = quote {
statement
statement
}
define f(x) a
define H(){
f(x)=x+1
return f
}
は無名の関数が返される。
return f(x) はローカル変数xの値をいれて評価された物が返される。
return f(x)=x+1 は式 f(x)=x+1が返される。
関数定義の3形式
define f(x){...return y}
define f(x) = x+1
f(x) = x+1
第一形式はstatement listは完全な遅延評価であり、グローバル変数などは取り込まれない。
第二形式は第一形式と同じ。第三形式は、x以外は出来るだけ評価する。
まだ決めていないこと:
新たな型の宣言、メンバ変数の隠蔽、オペレータの定義方法
新しい型のデータ構造はtype=使われていない数で中身はlist。
それぞれの演算子に(type, type, function_name)という構造のテーブルを用意する。type=nulだと何でも取り入れるということ。
たとえば、変数名、関数名は文法の知識を利用して一発で変更することができます。sedのように文字列の一部が偶然に一致しただけで置き換えられたりはしません。また、一本の数式の中の項の順番をマウスドラッグで入れ替えたり、ループのネスティングをドラッグで入れ替えたりする事ができます。
この変形支援に必要な複雑なアルゴリズムは(速度が必要な部分以外)それ自体、この言語で記述され、ユーザが拡張する事もできます。
またフロントエンドのイベントハンドリングのような速度の必要ない部分は全てこの言語自身で記述されます。
一般的なコンテナ、つまりたくさんの要素をいれるデータ構造についても
1,要素数が変動するか。
2,要素数の上限に静的な限界をもうけてよいか
3,配列の先頭や途中に要素を挿入、削除する必要があるか。
3,ランダムな読み出しは必要か
4,要素の追加と読み出しの比率はどれくらいか
5,要素の全てのデータ型は同じ型か。またバイト数は同じか。
などの要求によって千変万化なデータ型があります。たとえばC言語では静的配列、整数変数、ポインタとmalloc()を組み合わせて全ての面倒をユーザが見ることになります。そして、後から効率が悪いことが分かっても、大量のコードの書き直しが発生するために現実に書き直すことができません。またmalloc()されたメモリの管理は苦痛です。
この言語では、原始レベルで
コンテナ:リスト 配列
派生データ型: ベクトル 行列
イメージ(ピクセルマップ)
集合
構造体(識別子をインデクスにした配列)
ハッシュ表 連想記憶
時間をキーにした連続量
配列などは基本的に大きさにあらかじめ限界を設けません。また変数の型も存在しません。
しかし安全のためと、速度のために静的な修飾子をつけることはいつでもできます。また修飾子が十分な水準に達した時、自動的にマシンコードまでコンパイルする実装が許されます。
プログラマが書いたアルゴリズムはコンパイラに対してのヒントでしかなく、結果の同一性が保証される限りにおいてどのようなアルゴリズムの変形も行う権利が保留されます。ただしこれは当面実装されません。また、現実的にはアルゴリズムの変形は自動ではなくプログラマによってヒントとして与えられます。結果の同一性はシェルによって確認されます。これがアルゴリズム変形支援です。変形支援はこの言語自身で記述されます。
また例えば某OSでAPIを統一するためにハードデバイスでさえファイルにしてしまったことなども統一病の一種でしょう。
むしろ言語の核やライブラリのコード量が小さくなる方を優先します。
OSを無視した統一環境を用意しようと考えません。
OSにさわれる完全な方法を用意する。
Cのコードをプラグインとして利用できる方法を提供する。
しかしOS independentなライブラリもコードが大きくならない範囲で行う。
ライブラリ演算子
Σ
forall
∂
a= { 0 (x<1)
{ 1 (else)
ユーザレベルでのポインタは用意されない。処理系が面倒を見ているポインタをユーザに解放したらリークを始め幾らでも深刻な問題が発生するので、これは一切公開されない。
ポインタ変数の導入は本質的にtracing ガベージコレクションの実装まで行かずにはすまされない。