Closed syuilo closed 1 year ago
大きな変更になるから、今までに作られたPagesをどうするか考えないといけない
Pagesにバージョンが判別できるフラグを追加して、旧と新で処理を分ける
古いPagesを移行する処理を実装する
2は必ず移行できるか分からないかも。 将来的な変更で、移行できない要素が出てくる可能性はある。
1はバージョンごとで構造を分けられれば複雑さはある程度抑えられそうに見える Pages関係の根本から全部別にするとか 共通となってる部分を変更しても影響しないほうが、今後のメンテナンスがしやすくなる
ついでにAiScriptのバージョンも上げたいことを考えると1かも
ページ変数はAiScriptと同じで順次処理に変更って認識かな
そうね
今考えてるところまでまとめた。 入力ブロック関係、その他は未検討。まだ大体の雰囲気のレベル。
ページ変数の構造データ。 AiScriptコードに変換される元データとなる。
各種コンポーネント向けに変数テーブルを公開する。
AiScript変数の内容を変数テーブル(hpml.vars)に集める。 今までページ変数で行っていたような評価は行わず、単純に変数の内容を拾う。
AiScript変数の更新を受けて、hpml.collectVarsを実行する。
ページで直接使える変数はルートスコープで定義され、且つページ変数のAttributeが付加されている変数のみ。
🆒
検討点
AiScriptは上から順に実行されるので、変数がスコープに追加されるまでの間は変数が定義されていない。 そのタイミングの変数値をページ上にどう表示するか。
思いつくのはこんな感じ:
Aはスクリプトっぽい。 Bのほうがキレイそうではある。ちょっとコンパイル言語っぽいアプローチ。初期値を静的な式として与えることもできそう(AiScript側の変更が必要かも)。
AiScript走らせ始めた後にページレンダリングするようにするのはどうだろう
AiScript走らせ始めた後にページレンダリングするようにするのはどうだろう
スクリプトの実行終わりが分からない気がする イベント処理は後からも実行されるだろうし
AiScript側にスクリプトの最後の行まで実行したことを検知できるイベント実装するとか(Pages関係なく有益そう)
良さそう。イベントを見てページレンダリングする感じでいくか
Related #5489
入力ブロックとかの仕様を考え始めてる。本当にこれでいけるかは不明。
全てのブロックはAiScript変数(hpml.scriptVars)の内容を使用してレンダリングする。
入力ブロックの値の変更時は、MkPages:updatedイベントの発火とAiScript変数(hpml.scriptVars)の再収集を行う。 エディタ上で入力ブロックが追加されると、InputVarAttrを付加したAiScript変数を自動生成する。このAttributeは入力ブロック変数として認識させるためのAttribute。 AiScriptコードのパース以降の段階で、InputVarAttrが付加された全変数に対して以下の処理を行う: ・入力ブロック変数への代入処理をMkPages:updatedイベント内に追加(判定処理を挟んで必要に応じて代入をキャンセルできることが望ましい)。
副産物として、常にAiScriptを経由して入力ブロックを扱うようになるためAiScriptだけで入力ブロックの追加を行うことができるようになる。
AiScriptだけで入力ブロックの追加はやりにくそう そもそもAiScriptではブロックの構造定義がやりにくいので、グラフィカルな操作で編集するほうが便利そう。
手間はかかるけどScratch的なビジュアルエディタだとやりやすそう
仕様案1.1
ルートスコープに、export属性を付加して変数を定義するとページで使用できるようになる。
exportが付加された変数の内、input属性が付加された変数は入力ブロックの値を保持する変数として機能する。
AiScript変数をテキストブロック等に埋め込むことができる。
AiScriptが大元の変数値を保持している。 export+input属性を付加することで変数を外部に公開し、MkPages:updatedイベントから入力ブロックの値の変化を変数に反映することで、 入力ブロックとAiScript変数が相互作用する。
今までページ変数で行っていたような評価(旧hpml.eval())は行わず、AiScriptインタプリタの実行結果から変数値を収集する。
AiScript変数に関する全ての情報はhpml.variableInfosに保持され、変数値のコピーがhpml.varsに保持される(レンダリング専用)。
全てのブロックはexportされた変数(hpml.vars)を使用してレンダリングされる。
エディタ上で入力ブロックが追加されると、exportとinput属性を付加したAiScript変数をAST上に追加する。 AiScriptコードのパース以降の段階で、export&input属性が付加された全変数に対して以下の処理を行う: ・入力ブロック変数への代入処理をMkPages:updatedイベント内に追加(判定処理を挟んで必要に応じて代入をキャンセルできることが望ましい)。
入力ブロックの値の変更時は、MkPages:updatedイベントが発行される。 AiScript側はこのMkPages:updatedをトリガとして変数の値を変更する。 変更が行われると、変数スコープのonUpdatedイベントが発行される。
AiScript変数の値は以下のタイミングで再取得(リフレッシュ)される: ・スクリプトが最後の行まで実行された時。初回取得。 ・変数スコープのonUpdatedイベントが発行された時。値が変更されると随時発行される。 ※onUpdatedイベントが発生した際に現状では更新された変数が識別できないため、hpml.refreshVars()を実行して全体のリフレッシュを行う。
ページ変数のモデルデータ。 AiScriptのASTに変換される元データとなる。
AiScriptインタプリタで実行するAST。
AiScript変数に関する全ての情報を保持する。
各種コンポーネント向けに変数テーブルを公開する。
AiScriptパーサでASTを生成。 hpml.variablesを解釈しASTを組み換える。
ASTの解析によってAiScript変数の各種情報(付加されているAttirubte等)をhpml.variableInfosに収集する。 変数値については別途hpml.refreshVars()で収集する。
インタプリタのスコープ(実行コンテキスト)からAiScript変数の値を取得し、値をvariableInfosおよびhpml.varsに収集する。 収集対象の変数はhpml.variableInfosにある変数名に限定される。
AiScriptインタプリタがASTを実行
AiScriptインタプリタの実行を中止
入力ブロックの値の変更でMkPages:updatedイベント発行→AiScriptの関数呼び出し→AiScript側で変数値を更新→onUpdatedイベント発行→hpml.varsへの反映 っていう流れが結構時間がかかりそうという懸念がある。 時間がかかるなら別のアプローチを取ることになるかも
数値入力ブロックと表示変数10個で動かしてみた。これくらいで少しカクつきはじめた。 処理にまだ改善の余地があるので、もうちょっと軽くなる見込みがある。
@syuilo おそらくかなりwipなPRを投げる感じになると思うので、upstream側に作業ブランチが欲しい。 (直接developに取り込むわけにはいかないので) よろしくお願いします。
む、ブランチって勝手に作れないっけ
権限付与した
しゅいろありがとう:pray:
処理の改善をしてみたけど、予想に反してあまり改善しなかった ボトルネックが別にある
一旦PR投げた。
Misskey Play できて動的 Pages 廃止になったからclose?
そういやまだ
乱数に関しては、各種乱数生成関数をAiScriptランタイムに提供する。
- シードを受け取り乱数を返す関数
- Pagesシードが設定済みの乱数を返す関数
- 日ごとのシードが設定済みの乱数を返す関数
が出来てない
そういやまだ
乱数に関しては、各種乱数生成関数をAiScriptランタイムに提供する。
- シードを受け取り乱数を返す関数
- Pagesシードが設定済みの乱数を返す関数
- 日ごとのシードが設定済みの乱数を返す関数
が出来てない
シードから乱数生成関数を返す関数ならすでにある(Math:gen_rng) それを利用して他のも作れそう(ただ組み込み関数はあったほうが便利かもしれない)
Summary
AiScriptとは別に、Pagesとしての変数という概念があるのは、実装が複雑になり、ユーザーの理解も難しくなる
そこで、変数機能はAiScriptのものに統一したい
とはいえ全てAiScriptで書かなければならないというのは、Pagesの「プログラムが分からなくても、グラフィカルに動的なコンテンツを作れる」という利点を失うことになるため、Pages変数を「AiScript変数をグラフィカルに定義できる機能」としたい 内部的にAiScriptにコンパイルされて、ランタイムには関わらない
乱数に関しては、各種乱数生成関数をAiScriptランタイムに提供する。
「乱数をリセット」ボタンを押した際の処理は、Pagesシードを再生成して、AiScriptランタイムのMkPages:updated関数を呼び出すようにする? もしくはそもそも乱数リセットボタン自体不要になる?