1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【★狂気★】自作言語RubihuruでLispが作れたので、C言語でRubihuruのVMも作った。

1
Posted at

 申し訳ありません。今回の記事も AI と一緒に書きました。最初と最後に前回の記事と同じ言葉がでているところがあるかもしれません。

プログラミング言語を自作することは、多くのエンジニアにとって一つの夢です。しかし、私はその一歩先へ進むことにしました。自分が開発したオリジナル言語「Rubihuru」を使い、その上で動くLisp系言語「Rhlisp」を実装したのです。

  • 前回記事:[自作言語Rubihuruの上で、さらにLisp(Rhlisp)を作った話]

言語の中で別の言語を作るという最高にエキサイティングな体験を経て、私の脳内にはさらなる狂気(※技術的探究心)が芽生えてしまいました。

「Rubihuruの上でRhlispが動くなら…… Rubihuruの実行エンジンをTree-walkingからバイトコードVMに変えれば、その上で動くRhlispも爆速で動くんじゃね?

構文木をそのまま愚直に走査していたインタプリタを脱却し、独自命令の「バイトコード」とそれを高速に実行する「仮想マシン(VM)」へと大改造した、頭がねじれるような新たな開発体験をここに共有します。

1. なぜ、Tree-walkingから「バイトコードVM」に変えたのか?

これまでのRubihuruは、パースした構文木(AST)を再帰的に評価する「Tree-walking」方式でした。シンプルで作りやすい反面、関数の呼び出しやループのたびにノードを探索するため、オーバーヘッドが大きいのが弱点です。

特に、Rubihuruの上でさらにLisp(Rhlisp)を動かすシステムでは、レイヤが重なりすぎて速度低下が致命的でした。
そこで、プログラムを一度「独自のバイトコード(命令列)」へとコンパイルし、C言語の高速なループ(VM)で直線的に実行する構造へ変革することにしました。

2. Rubihuru VMの設計と実装プロセス

大改造にあたり、主に以下のコンポーネントを実装していきました。

【コンパイラの構築(AST → バイトコード)】

これまでの構文木を、VMが理解できる平坦な命令列(OpCode)へと変換するフェーズです。

#define OP_CONSTANT      0
#define OP_POP           1  
#define OP_SET_ENV       2
#define OP_GET_ENV       3
#define OP_CALL          4
#define OP_BUILD_ARRAY   5
#define OP_BUILD_HASH    6
#define OP_JUMP_IF_FALSE 7
#define OP_JUMP          8
#define OP_YIELD         9
#define OP_PRIVATE      10
#define OP_BUILD_RANGE  11
#define OP_SET_IVAR     12
#define OP_GET_IVAR     13
#define OP_DEF_METHOD   14
#define OP_BUILD_LAMBDA 15
#define OP_BUILD_CLASS  16
#define OP_END_CLASS    17
#define OP_RETURN       18

【コア:Fetch-Decode-Execute ループ】

VMの心臓部です。C言語の switch-case を使い、プログラムカウンタ(PC)を進めながら命令を爆速でデコードしていきます。

struct rh_object* rh_vm_execute(struct rh_code *code, struct rh_env *env) {
    uint8_t *ip = code->bytecode; 
    struct rh_object *stack[256];
    struct rh_object **stack_top = stack;

    struct rh_class *class_save_stack[64]; // クラス定義のネスト最大64深さまで対応
    struct rh_env *env_save_stack[64];
    int save_stack_idx = 0;

    while (1) {
        int current_address = (int)(ip - code->bytecode);
        uint8_t opcode = *ip;
        //printf("[%04d] Opcode: %d | Stack Depth: %d\n", current_address, opcode, (int)(stack_top - stack));

        switch (*ip++) {
            case OP_CONSTANT: {
                int const_idx = *ip++;
                *stack_top++ = code->constants[const_idx];
                break;
            }
            case OP_POP: {
                stack_top--;
                break;
            }
// ...

この大改造を通じて、大きな快感と感動がありました。

階層を突き抜けて爆速で動いた瞬間の感動

新しく生まれ変わった「Rubihuru VM」に、前回の「Rhlisp」の評価器を読み込ませ、カッコだらけのLispコードを流し込む。
……その実行速度は、Tree-walking時代とは比較にならないほど爆速でした。レイヤを何層も重ねているにもかかわらず、バイトコードVMの力によって一瞬で計算結果が返ってくる瞬間は、筆舌に尽くしがたい快感(と感動)です。

追記(2026/5/30)の機能もそのまま加速

先日のアップデートで組み込んだ「鬼車(oniguruma)」ライブラリによる正規表現(Regex#=~String#match)などの強力な文字列処理も、VMの命令としてバインドしたことで、より洗練されたネイティブスピードで動作するようになりました。

4. まとめとこれからの展望

Tree-walkingからバイトコードVMへの変革。それは、自作言語「Rubihuru」が単なるおもちゃの枠を超え、実用的な処理系へと進化を遂げた瞬間でした。

今後はこのVMの命令セットをさらに最適化し、その上で動くRhlispとともに、さらに低レイヤの限界を突破していきたいと考えています。

1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?