サンプル言語「crowbar」

crowbarとは

今回作成する言語の名前は、「crowbar」とします。

crowbarというのは、四葉のを見つけるといいことがある植物のことではなく (それはclover)、こんな形をした工具のことです。

命名の由来ですが、今回作る言語は、解析木を作成しそれを実行する、 という点において、Perlと似たような位置付けにある言語です。

というわけで、つまりアレです。ニュースなんかでよく聞く、

パールのようなもの

ということでcrowbarと名付けました。あっ、石を投げないでっっ!!

現時点のcrowbar(Ver.0.1)では、変数が使え、 条件分岐、ループ等が記述できますが、 データ型は整数型、実数型、文字列型だけで、 配列もなければ、正規表現による文字列処理の機能も、 オブジェクト指向な機能もありません。

こんなのでPerlのようなものとか言ったら怒られそうですが ――ごもっともです。すみません。ネタを思いついちゃったもので。

私自身、crowbarを「すごく画期的で、使いやすくて、 生産性の高い言語」だとか思っているわけではありませんし、 将来的にそうするつもりもさほどありません。 crowbarはあくまでサンプル言語です ※1。 興味を持たれた方は、 crowbarのソースをベースに「俺言語」を作ってみてはいかがかと (改造も再配布も自由です。ライセンスを参照のこと)。

crowbarの文法は、この記事を読む人が慣れた言語ということで、 ある程度Cを踏襲するようにしました。

私としては、代入演算子はやっぱり:=だよね、とか思わなくもないのですが (こういう問題は、実際にはほとんど「慣れ」 の問題でしかないとも思っていますが)、 crowbarにおいてはそういう「こだわり」は控えたつもりです。 ――それにしちゃ、if文とかの( )がないのはかなりアレですが。 近い将来直すかも。

Ver.0.1における機能の概要

データ型

crowbarで使用可能なデータ型は、以下のとおりです。

現時点では、配列や連想配列やクラスやオブジェクトはありません。

また、論理型もないので、整数型で代用しています。 整数型の0が偽、それ以外の整数は真となります。 if文の条件式など、論理型が必要なところに、 整数型以外の式を書くとエラーになります。

変数

crowbarは、Perl, Rubyなどと同じく、 静的な型付けのない(変数に型がない)言語です。

いやその私自身は、 どちらかというと「 型なし言語逝ってよし!」的な立場に立つものですが、 今回はサンプルということで、 あえて意に沿わない方の言語を作ってみました (^^;

crowbarでは変数宣言は不要であり、最初の代入が宣言を兼ねます(Rubyを真似ました)。 代入されていない変数をいきなり参照するとエラーになります。

変数の字句規則は、Cなどと同様で、 英字で始まり2文字目以降には英数字が使えます。 アンダースコアは英字と同様に使えます。 Perl等とは異なり、先頭に$等を付ける必要はありません。

また、関数内で初めて代入された変数は、ローカル変数になります。 ローカル変数の寿命は、その関数を抜けるまでです。

関数内で、新しいローカル変数を作るつもりで「a = 0」のように書いても、 同名のグローバル変数が存在していると、 単なる「グローバル変数aへの代入」とみなされますから注意してください ※2

ローカル変数のスコープは「ブロック」ではなく「関数」です。 また、変数は代入が実行された時点で宣言されるので、 以下のような例では、

  if a == 10 {
      b = 10;
  }
  print("b.." + b);  

aが10の時だけbが宣言され、printで表示可能です。 もしaが10でなければ、未定義変数エラーになります ※3

crowbarには、Cなどと同じく、if文、while文、for文等があります。

C, C++, Javaといった言語と大きく異なるのは、以下の点です。

具体的には、以下のような体裁になります。

  # if文の例
  if a == 10 {
      # a == 10の時に実行される
  } elsif a == 11 {
      # a == 11の時に実行される。
  } else {
      # a が10でも11でもない時に実行される。
  }

  # while文の例
  while i < 10 {
      # i が10より小さい間、ここを繰り返す。
  }

  # for文の例
  for i = 0; i < 10; i = i + 1 {
      # ここを10回繰り返す。
  }

――正直、中括弧の使用を強制するところまではともかく、 ( )まで無くしてしまったことで、 CやらJavaやらに慣れた人(私を含む) には違和感ありまくりの言語になってしまった気もします。 まあ、ifやwhileなら、条件式を()で囲んでも同じ意味になるからよいですが、 forはそれもできませんし。

中括弧の使用を強制している以上、構文的にこの場所の( )は無駄です。 だったら取ってしまった方がすっきりして良いじゃないか、 と思うわけですが、実際には「慣れ」の要素も大きいようです。 あるプログラミング言語が世間で広く使われるかどうか、 なんてことには、こんなことが結構強く影響しているようにも思います。

また、crowbarでは、以下の文を使うこともできます。意味はCと同じです。

breakやcontinueには、 Javaのようにラベルを付けられるようにしようかとも思ったのですが、 面倒なのでまだやってません。簡単にできるはずですが。

まず、crowbarでは以下の定数式を記述できます。

また、変数も式です。

これらを演算子で結合して式を構築します。 当然ですが括弧も使えます。

crowbarで使える演算子は以下の通りです (優先順位順に並べてあります)。

(単項の)-符号の反転
* / %乗算、除算、剰余
+ -加算、減算
> >= < <=大小比較
== !=同値比較
&&論理AND
||論理OR
=代入

%は、実数に対しても適用可能で、その場合内部的にfmod()が呼び出されます。

また、==, !=, >, >=, <, <= といった類の演算子は、 条件が真であった場合は整数の1を、偽であった場合は0を返します。

Cなどでもそうですが、crowbarにも、負の数を表現する定数はありません。 負の数を使いたい場合には、単項演算子「-」を使います。 Cなどと違い、&&, ||は短絡演算子にはなっていません。 これも単なる手抜きの結果です。

関数定義

関数定義は、以下のような形式になります。

function hoge(a, b) {
    c = a + b;
    print("a+b.." + c + "\n");

    return c;
}

関数定義は、プログラム中、文の途中でさえなければどこに書いても構いません。

関数にreturn文が存在しない場合、 その関数は特別な定数であるnullを返します。 nullは、今のところ、比較に使えるわけでもなく、何の役にも立ちませんが、 いずれ参照型を導入する際に使おうと思っています。

組み込み関数

crowbarには最初から用意されている組み込み関数があります。 一覧は以下の通りです。

print(arg) argを表示する。argの型は、整数、実数、文字列のいずれでも可。

以上!

って、ひとつしかないのに「一覧」もクソもないですな。

その他

crowbarでは、#から行末まではコメントです。 Cに似せるなら/*〜*/かとも思うんですが、やっぱりスクリプト言語ですしねえ。

crowbarの実行

crowbarインタプリタは、ひとつの実行形式だけで動作しますので、 PATHの通ったところに実行形式を配置してもらえれば、 それだけで実行可能です。

実行は、以下のようにして行ないます(%はプロンプトだと思ってください)。

  % crowbar hoge.crb

「hoge.crb」が、crowbarによるプログラムが記述されたファイルです。

今のところ、crowbarには対話的な実行モードはありません。

Cとの連携

ここで書くべきことかどうかは疑問ですが、 crowbarはもともとアプリケーション組み込み言語としての用途をそれなりに 考えているつもりなので、Cとの連携方法について書いておきます。

Cからcrowbarを呼び出す

crowbarインタプリタは、Cのプログラムから呼び出すことができます。

以下は、現状のmain.cの記述とほぼ同等なコード片です。 これらの関数を呼び出すためには、CRB.hを#includeする必要があります。

  CRB_Interpreter	*interpreter;
  FILE *fp;
  /* 中略 */

  /* crowbarインタプリタを生成 */
  interpreter = CRB_create_interpreter();

  /* FILE* を引数に渡して解析木にコンパイル */
  CRB_compile(interpreter, fp);

  /* 実行 */
  CRB_interpret(interpreter);

  /* 実行が終わったらインタプリタを破棄 */
  CRB_dispose_interpreter(interpreter);

crowbarのソースからmain.cを抜いて、適当にリンクすればよいはずです。

crowbarからCを呼び出す

crowbarには現状で組み込み関数がひとつしかありませんが、 crowbarから呼び出せるようなC関数を書くのは比較的容易です。

まず、組み込み関数作成者向けのヘッダファイルCRB_dev.hを#include した上で、以下のような形式の関数を書きます。

CRB_Value hoge_func(CRB_Interpreter *interpreter,
                    int arg_count, CRB_Value *args)
{
    …
}

ここで、arg_countが引数の数、argsは引数を格納した可変長配列です。 CRB_Valueの定義については、CRB_dev.hを参照してください。

そして、この関数を、CRB_add_native_function()関数により、 インタプリタに登録します。 具体的な方法については、interface.cを参照してください ※4



前のページ | 次のページ | ひとつ上のページに戻る | トップページに戻る