4 ポイント 投稿者 GN⁺ 2023-10-09 | 1件のコメント | WhatsAppで共有
  • Berryは低性能な組み込みデバイス向けの動的型付きスクリプト言語で、ARM Cortex M4基準でインタープリタコアは40KiB未満、4KiB未満のヒープでも実行可能
  • ランタイムはワンパスコンパイラとレジスタベースVMで構成され、コード全体はANSI C99で書かれているため既存の組み込みコードに組み込みやすい
  • 性能のために int、real、boolean、string はクラスオブジェクトにせず、list、map、range のみをクラスオブジェクトとして扱う
  • 言語機能は命令型・オブジェクト指向・関数型プログラミングをあわせてサポートし、GC、FFI、例外処理、バイトコードファイル、拡張モジュールを含む
  • コンパイル時のオブジェクト構成とflash固定機能により、コード・クラス・モジュールのRAM使用量を削減でき、メモリ制約の大きい環境に適している

組み込み環境を狙ったランタイム

  • Berryはマイクロプロセッサのような低性能の組み込みデバイスで使うための動的型付きスクリプト言語
    • ARM Cortex M4 CPU、Thumb ISA、ARMCC compiler 基準でインタープリタコアのコードサイズは40KiB未満
    • 同じ条件で4KiB未満のヒープで実行可能
  • インタープリタはANSI C99で書かれており、ワンパスのバイトコードコンパイラとレジスタベースの仮想マシンを含む
  • 型設計は実行性能を優先し、値型とオブジェクト型を区別する
    • クラスオブジェクトではない型: int、real、boolean、string
    • クラスオブジェクトである型: list、map、range
  • コンパイル時のオブジェクト構成では、ほとんどの定数オブジェクトを読み取り専用のコードデータセグメントに保存し、インタープリタ起動時のRAM使用量を抑える

言語機能と実行モデル

  • 基本型には nil、boolean、integer、real、string、class、instance、module、list、map、range が含まれる
  • 式と演算子は代入、関係、論理、算術、ビット、フィールド、添字、文字列連結、条件演算子、括弧、bytes buffer をサポートする
  • 制御構造は if elif else endwhileforbreakcontinue を提供する
  • 関数機能にはローカル変数とブロックスコープ、return文、入れ子関数定義、Upvalue ベースのクロージャ、無名関数、ラムダ式まで含まれる
  • クラスは公開単一継承のみをサポートし、メソッドと演算子オーバーロード、コンストラクタメソッド、デストラクタメソッドを提供する
  • GCはMark-Sweep GCを使用する
  • 例外処理では raise 文で任意の例外値を投げられ、複数の catch モードをサポートする
  • バイトコードファイル機能により、関数をバイトコードファイルとしてエクスポートして再ロードし、実行できる

モジュール、C連携、例

  • モジュール管理は組み込みモジュールと拡張モジュールの両方をサポートする
    • 拡張モジュールにはスクリプトモジュール、バイトコードファイルモジュール、*.so*.dll のような共有ライブラリモジュールが含まれる
    • コード、クラス、モジュールを flash に固定して RAM 使用量を削減できる
    • オプションの Regex サポートとオプションの LVGL mapping を提供する
  • Native C インターフェースにより既存コードへライブラリのように組み込め、Tasmota のようなコードが例として挙げられている
    • Berry から C コードを呼び出すためのオプションの easy mapping を提供する
  • 文法例ではリスト走査、map 作成とキー走査、class 宣言、: 演算子による単一継承を示している
  • 追加のサンプルコードは GitHub で確認できる

1件のコメント

 
GN⁺ 2023-10-09
Hacker News のコメント
  • 40KB のランタイムにしては機能が驚くほど豊富。ガベージコレクション付きの VM 上で Python/Ruby に似た言語が動き、手続き型・オブジェクト指向・関数型スタイルをサポートしている
    ざっと見ただけでも、かなり書きやすそうに見える。特に定数オブジェクトを事前に作って大部分を ROM に置き、RAM は実際に変更可能なデータだけに使う機能が目を引く。私の知る限り MicroPython や Lua にはない方式で、ROM/フラッシュは十分あるが RAM が不足しがちな MCU では大きな差になる

    • MicroPython でもモジュールを freeze してフラッシュに保存でき、その場合フラッシュには事前コンパイル済みのバイトコードだけが入る
      モジュールに文字列や bytes() のような不変オブジェクト形式の保存データがある場合、RAM に先にコピーせずフラッシュから直接読み出す。ただし freeze を行うには、デスクトップコンピューター上でコードを一度実行する必要がある
      https://docs.micropython.org/en/latest/reference/constrained...
    • 説明を読んでからあらためてサイトを見に行ったが、ホームページよりずっと包括的で魅力的に感じた
    • @snops が説明しているように、MicroPython は frozen code という形でフラッシュからコードを実行できる。その結果、ファームウェアバイナリにコンパイルして組み込む必要があり、MicroPython の通常の高速な開発サイクルが遅くなる
      そのため便利な流れとしては、コードベースが安定するか製品化段階に近づくまではランタイムにデプロイし、その時点でコードをファームウェアに freeze する、という方法になる。より便利なモデルとして mapfs サポートの提案があり、フラッシュの一部をコード保存用に割り当てたうえで Python をバイトコードにコンパイル(mpy_cross)し、その領域へアップロードしてランタイムに実行できるようにする。概念実証はすでに出ているが、メインラインに入る前に整理すべき細部が残っている
      https://github.com/micropython/micropython/pull/8381
    • かなり興味深く見えるし、多くの点で Lua に似ているように見えるが、目立つ違いもある。ちなみに eLua でも、一部のデータを透過的に ROM に置く取り組みがあった
      https://eluaproject.net/doc/v0.9/en_arch_ltr.html の rotables を見るとよい
  • Berry は Tasmota で使われている: https://tasmota.github.io/docs/Berry/

    • Tasmota は面白そうに見える。使ったことがある、あるいは toit/jaguar と比較したことがあるなら、感想を聞いてみたい
  • 本当に良さそう。個人的には、これまで見たドキュメントの中でも最上級のドキュメントに近いと思う
    熟練した開発者が言語の感覚をすばやくつかめるようにしてくれる「short manual」が特に良い。Tasmota は以前は知らなかったが、プロジェクトで試す口実を探すことになりそう

  • いちばん気になるのは、Lua と比べた性能とメモリ使用量がどうなのか、そしてサンドボックス化がどの程度可能なのかという点
    信頼できないコードを実行できるのかも気になる

    • Lua との比較がいちばん興味深い。私が働いていた会社の多くは Python を雑なプロキシや CLI ツールのように使っていたが、Lua はメタテーブルベースのオブジェクト指向が分かりにくく、勧めにくかった
      この言語が単純な構造体と基本的なコンストラクターを備えた有効な代替になるなら、Python スクリプトとその依存関係を取り除く用途で勧められそう
    • 基本的にコードはファイルシステムを開いたり書き込んだりできるため、信頼できないコードをそのまま実行することはできない
      サンドボックス化はアプリケーション側が責任を持つ必要がある。サンドボックス化には WebAssembly が良い代替案になる
    • async キーワードのあるネイティブスレッド管理が入れば、ゲームエンジン用途では Lua と明確に差別化できそう
  • これとほぼ同じようなものだが、パラダイムはもっと少なく、静的型付けなら、設定言語として本当に良さそう
    複雑な設定が必要な複数のプロジェクトで、数百行の YAML を書かせる代わりに Lua や Starlark/Python を使わせるケースがあったが、ずっと良く感じた。ただ、いつも自動補完とリフレクションが物足りない。この用途にぴったりの候補はなかなか見当たらず、小さく組み込めるスクリプト言語はほとんどが動的型付けだ

    • 似た方向を考えてきたが、静的型付けというよりは強く検証される設定に近い。設定全体を読み込んだあとに問題の一覧を生成できるほうが望ましく、きちんと作れば優れたエディターサポートも可能であるべき
      ただし https://dhall-lang.org/ は、多くの設定を静的型で扱えることと、その利点が大きいことを示している。複数の言語にプログラム的に埋め込めるようだ
      https://docs.dhall-lang.org/howtos/How-to-integrate-Dhall.ht...
  • 良さそう。それでも今のところはまだ uLisphttp://www.ulisp.com)のほうにかなり心が傾いているが、こういうものが出てくるのはうれしい

  • 言語の雰囲気をつかむためにまずコード例を見るタイプなら、examples ディレクトリを見るとよい: https://github.com/berry-lang/berry/tree/master/examples

  • 他言語向けのバインディングを提供してくれるととても良い。私たちは Rust から quickjs を使っているが、かなりうまく動いている
    VM に必要なものだけを提供できるので、信頼できないコードも実行できる

  • 組み込み用途に最適化された言語のように見える。設計とドキュメントがよくできていて、奇妙だったり予想外だったりする挙動はしないようだ
    文法も心地よいほどミニマルで好みに合う。次の ESP32 プロジェクトでは必ず念頭に置くと思う

    • すぐに試すつもり。光るハロウィン飾りを作ろうと思って ESP-32 開発キットをいじっていたところで、これを試すのが楽しみだ
      このニッチ領域には本当に合っていそうで、特に他の言語には対応物がすぐには思い浮かばないようなことをしている点が良い
  • ネイティブのスタックトレースで、スタックフレームにスクリプト関数名を表示する標準的なアプローチがあるのか気になる
    クラッシュしたときや CPU プロファイラーを使うときに、ネイティブのスタックトレースとスクリプトのスタックトレースを混ぜて表示できるのか知りたい