Files
quartz-research-note/content/mimiumのREPLをVMで実装.md
松浦 知也 Matsuura Tomoya 8003f8ed58
Some checks failed
Build / build (push) Has been cancelled
[obsidian] vault backup: 2025-06-30 11:47:51[
2025-06-30 11:47:51 +09:00

3.9 KiB
Raw Blame History

date
date
2025-06-27 17:10

#mimium #memo

今の所の問題点として

  • マシンが一つの結合されたコンパイル済みバイトコードしか受け付けていない

    • これを配列として複数保持する必要あり
  • 外部関数の参照インデックスのテーブルはVM上に載っているが、内部関数は一つのプログラム上の絶対位置しか参照できない

  • プログラム上で定義した内部関数を、他のプログラムでも参照できるようにする、シンボルテーブルがいる

  • またグローバル環境の評価も同様に、シンボル-(GlobalPos,型)変換のテーブルをコンパイラが持っていないとだめ

  • マシンをオーディオドライバ立ち上げとともにオーディオスレッドにMoveしてしまっているので、メインスレッドで新たにコンパイルしたプログラムを何かの方法でオーディオスレッドに送ってやらないといけない

  • シンボルテーブルもDashMapで作ってればなんとかなるのかな

  • VMの中にControllerみたいなDashMap系をArcで包んだものを用意しておいて、メインのマシンはオーディオスレッドに送ってしまい、Arcでコントローラーだけをメインスレッドに残しておく

  • ExecContextはRepl起動から終了まで次の情報を持ち続ける

    • グローバル変数のシンボルテーブル(型情報含む)
    • 内部関数のシンボルテーブル(型情報含む)
    • 外部関数のシンボルテーブル(型情報含む)

ExecContextは、起動時VMのインスタンスを作る。この時VMConrollerのArc参照がVM内に渡される。

ExecContextは、ソースコードを受け取るたびにコンパイラのインスタンスを作ってはプログラムを出力し、終了する。

出力されたプログラムはVMControllerのPrograms(DashMap)に非同期でインサートされ、シンボルテーブルも更新される

Replで送られた新しいプログラム一行だけのプログラムをどのスレッドで、いつ実行するかが問題

DSPの頭でReplで溜まった処理(無名関数のキュー)を順番に消化する?あるいは、

dsp = |l,r| ->(float,float){ ( new_process )}

こんな感じでREPLに送ると、実際には

fn repl_001(){
	| | {
		dsp = |l,r| ->(float,float){ ( new_process )}
	}@now
}

みたいなのを実行したことになるとか

これだとスケジューラープラグイン実装されてることが前提にはなるし、スケジューラーにタスクを登録するのをController越しに行える必要がある

というか、メインスレッドに相当するものを別途作る方がやっぱり良さそう

結局、今VMに乗ってるだいたいのものはShared Stateとして共有されて、スタック、ベースポインタ、StateStorageだけが独立する形になりそう


シングルスレッドの場合、REPLで実行されたものは必ずオーディオドライバのブロック頭で消化

マルチスレッド前提の場合、Shared State全般がRwLockとかで包まれることになってしまう

しかし、大概の場合グローバルな状態共有はAtomicな単一パラメーターで済む

あくまで、普通のグローバル変数宣言はスレッドローカルな扱いにして、メインスレッドと協調しないといけない場合は"shared"みたいなキーワードをつけるようにするとか(構文増やしたくないけど)

だし、これだと結局OSC送るサーバークライアント構成と実質的に変わらないかも