mruby/c ソースツリー　ウォーキングツアー

[しまねソフト研究開発センター](https://www.s-itoc.jp)（略称 ITOC）にいます、東です。
これは [mrubyファミリー Advent Calendar 2023](https://qiita.com/advent-calendar/2023/mruby-family) の記事です。

私は、ITOCで軽量Ruby言語の1種類である、mruby/c を開発しています。mruby/c は、既存のC言語プロジェクトに楽にインポートできることを前提として、ソースツリーを設計しています。その辺りの設計意図も含め、ディレクトリ及び各ソースファイルの役割について説明します。

# ソースツリー

mruby/c は、github でソースコードベースで提供しています。
https://github.com/mrubyc/mrubyc
以下の説明は、[mruby/c のバージョン（リリース） 3.2](https://github.com/mrubyc/mrubyc/releases/tag/release3.2) を使います。

# まずはディレクトリ

```
mrubyc-release3.2
├── doc
├── mrblib
├── sample_c
├── src
├── support
└── test
```

<dl>
<dt>doc</dt>
  <dd>ドキュメント。</dd>
<dt>mrblib</dt>
  <dd>rubyで書いたクラスライブラリ群</dd>
<dt>sample_c</dt>
  <dd>C言語からのVM利用サンプル</dd>
<dt>src</dt>
  <dd>VM (mruby/c 実行部) のソースコード</dd>
<dt>support</dt>
  <dd>VMソースコードに対する自動生成ツールなど</dd>
<dt>test</dt>
  <dd>自動テストコード</dd>
</dl>

利用者から見て重要なのは、`src` ディレクトリです。ここには、VMを構成する全てのC言語ソースファイル、ヘッダファイル等が入っています。先に説明した既存のC言語プロジェクトにインポートして使う方法では、この`src` ディレクトリをまるごと既存プロジェクトのソースツリーへコピーして使うことができます。

既存のC言語プロジェクトにインポートして使うとは言いましたが、コマンドラインで動作させるサンプルも用意しています。それらを、`sample_c` ディレクトリに置いています。

`mrblib` ディレクトリには、rubyで書いたライブラリを入れています。これらはリリース時点でC言語にコンパイル済のものが、`src` ディレクトリへ `mrblib.c` として入れてありますので、利用者が直接このディレクトリ下のファイルを利用することは少ないかもしれません。

`support` ディレクトリは、シンボルテーブルなどを自動生成するためのツールを入れています。ここも利用者が直接使うことは少ないと思います。

`test` は、自動テスト （Unit Test) 用のスクリプトが入っています。


# src ディレクトリ内の各ファイルたち

```
Makefile                        class.h
VERSION                         console.c
_autogen_builtin_symbol.h       console.h
_autogen_class_array.h          error.c
_autogen_class_exception.h      error.h
_autogen_class_float.h          global.c
_autogen_class_hash.h           global.h
_autogen_class_integer.h        hal_esp32
_autogen_class_math.h           hal_pic24
_autogen_class_object.h         hal_posix
_autogen_class_range.h          hal_psoc5lp
_autogen_class_string.h         hal_rp2040
_autogen_class_symbol.h         hal_selector.h
alloc.c                         hal_selector.mk
alloc.h                         keyvalue.c
c_array.c                       keyvalue.h
c_array.h                       load.c
c_hash.c                        load.h
c_hash.h                        mrblib.c
c_math.c                        mrubyc.h
c_math.h                        opcode.h
c_numeric.c                     rrt0.c
c_numeric.h                     rrt0.h
c_object.c                      symbol.c
c_object.h                      symbol.h
c_range.c                       value.c
c_range.h                       value.h
c_string.c                      vm.c
c_string.h                      vm.h
class.c                         vm_config.h
```

通常使う上では、ひとつひとつのファイルについて理解する必要はありません。VM本体に機能を追加したい場合や、構造の理解のために必要になる最低限の説明をします。

## Virtual Machine

### vm.[ch]

VM (Virtual Machine) の本体。
mrubyコンパイラが出力したバイトコードを解釈して、実行する関数などを定義しています。

### opcode.h

mruby バイトコードのオペコードとそれに対応する数値を定義しています。


## Class Libraries

### c_array.[ch]

Array クラスとそのメソッドを定義しています。

### c_hash.[ch]

Hash クラスとそのメソッドを定義しています。
なお、現在の実装では実質 Array と同じ実装（リニアサーチ）としており、ハッシュ値を使った探索は行っていません。

### c_math.[ch]

Math クラスとそのメソッドを定義しています。mruby/c は、module をサポートしていませんので、Math は、モジュールではなくクラスになっています。
このクラスを使うには、プリプロセッサマクロ `MRBC_USE_MATH` に 1 に定義する必要があります。vm_config.h を編集することでも定義できます。

### c_numeric.[ch]

Integer クラスと Float クラス、及びそのメソッドを定義しています。

### c_object.[ch]

Object, Proc, Nil, True, False クラスとそのメソッドを定義しています。

### c_range.[ch]

Range クラスとそのメソッドを定義しています。

### c_string.[ch]

String クラスとそのメソッドを定義しています。

### error.[ch]

例外クラスとそのメソッドを定義しています。


## 各機能やデータ構造のためのファイル

### class.[ch]

クラス定義に関する内部表現や、クラスを定義するための関数を実装しています。

### value.[ch]

rubyの変数に関する内部表現や定数、サブルーチンなどを実装しています。

### symbol.[ch]

シンボルを扱うための、内部的なサブルーチンなどを実装しています。

### global.[ch]

グローバル変数と定数の機能を実装しています。

### keyvalue.[ch]

内部的に使用するキーバリューストアのサブルーチンです。

### load.[ch]

バイトコード (mrbファイル) を実行前にパースして、実行のための準備をする関数を実装しています。

### console.[ch]

コンソール出力をサポートします。
puts, p, printf などのメソッドについて、mruby/c では特別扱いして独自実装している部分があり、それらのサポート関数を実装しています。

### alloc.[ch]

メモリ管理モジュール。
rubyは、実行時にとても短期間にメモリを動的に確保(malloc)・解放(free) を行います。マイコン向けのmalloc,free の実装は簡易的な実装になっているケースがあり、実行速度を考えた場合に不利になるので、mruby/c は標準で独自にメモリ管理を行います。


## スケジューラとHAL

### rrt0.[ch]

複数のプログラムをタイムスライスによって同時実行する機能をまとめたスケジューラを定義しています。mruby/c の特徴の一つです。
VMへは強く依存していますが、逆にVMはスケジューラにほとんど依存していませんので、アプリケーションによっては、このスケジューラを使わないというカスタマイズすることもできます。

### hal_*

ハードウェア抽象化レイヤー (Hardware abstraction layer) を、マイコンごとに定義しています。


## そのほか

### mrblib.c

mrblib ディレクトリに置いてある Ruby で記述したクラスやメソッドを、事前にコンパイルしてC言語の配列で表現したものです。

### _autogen*

`support` ディレクトリに配置したツールによって自動生成したファイル群です。

### mrubyc.h

利用者が、C言語で独自クラス、独自メソッドを書く場合に、インクルードするヘッダファイルです。

### vm_config.h

VM　をユーザーニーズや利用するマイコンに合わせてカスタマイズするための定数を定義しています。
よく使うであろう値をいくつか列挙します。

| 定義 | 説明 |
|-|-|
| MAX\_VM\_COUNT | 一度に実行するプログラムの数 |
| MRBC\_USE\_FLOAT　| Rubyプログラムで浮動小数点を使うかどうか |
| MRBC\_BIG\_ENDIAN | ビッグエンディアンのマイコンを使う場合 |
| MRBC\_REQUIRE\_32BIT\_ALIGNMENT | メモリアクセスに32bitアライメントを必要とするマイコンを使う場合 |
| MRBC\_ALLOC\_LIBC | 処理系標準の malloc を使う |
| MRBC\_CONVERT\_CRLF | consoleへの出力で、LFを、CRLFに変換しながら出力する |


# おわり

長くなったので、一旦ここで終わります。
別記事で、PC上でコンパイルして試すことなどを説明しようと思います。

では、Happy Holidays!