Skip to content

Commit 591c438

Browse files
AiScriptを外部アプリに実装する際の概要について記載
1 parent 41e9c82 commit 591c438

File tree

3 files changed

+213
-0
lines changed

3 files changed

+213
-0
lines changed

.vitepress/config/en.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { defineConfig, type DefaultTheme } from 'vitepress';
33
const guideNav: DefaultTheme.SidebarItem[] = [
44
{ text: 'Introduction', link: 'get-started' },
55
{ text: 'Execution', link: 'execution' },
6+
{ text: 'Implement to Your App', link: 'implementation' },
67
];
78

89
const referenceNav: DefaultTheme.SidebarItem[] = [

.vitepress/config/ja.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const guideNav: DefaultTheme.SidebarItem[] = [
1111
items: [
1212
{ text: 'はじめに', link: 'get-started' },
1313
{ text: '実行方法', link: 'execution' },
14+
{ text: 'アプリに組み込む', link: 'implementation' },
1415
],
1516
},
1617
{ text: 'リファレンス', base: '/ja/references/', link: 'syntax' },

docs/ja/guides/implementation.md

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
# アプリに組み込む
2+
3+
このガイドでは、既存のWebアプリにAiScriptを組み込む方法をご紹介します。
4+
5+
## 1. AiScriptのインストール
6+
7+
まずは、AiScriptをインストールします。
8+
9+
```sh
10+
# npm
11+
npm i @syuilo/aiscript
12+
13+
# yarn
14+
yarn add @syuilo/aiscript
15+
16+
# pnpm
17+
pnpm add @syuilo/aiscript
18+
```
19+
20+
## 2. AiScriptの読み込み・設定
21+
22+
今回は、このようにテキストベースで渡されたAiScriptを実行するまでの手順を説明します。
23+
24+
```ts
25+
const program = "<: \"Hello, World!\"";
26+
```
27+
28+
AiScriptを読み込みます。
29+
30+
```ts
31+
import { Parser, Interpreter, utils } from '@syuilo/aiscript'; // [!code ++]
32+
33+
const program = "<: \"Hello, World!\"";
34+
```
35+
36+
AiScriptは、まず`Parser`でASTと呼ばれるオブジェクトに変換し、その後`Interpreter`で実行します。
37+
38+
AiScriptを実行する際に呼び出すJavascript関数を用意しましょう。\
39+
AiScriptインタプリタの実行は非同期で行われますので、`async function`を使用します。
40+
41+
```ts
42+
import { Parser, Interpreter, utils } from '@syuilo/aiscript';
43+
44+
const program = "<: \"Hello, World!\"";
45+
46+
async function run() { // [!code ++]
47+
// 処理を追加していく // [!code ++]
48+
} // [!code ++]
49+
// [!code ++]
50+
run(); // [!code ++]
51+
```
52+
53+
次に、`Parser``Interpreter`を初期化します。それぞれは再使用が可能なので、関数の外で宣言しておくとよいでしょう。
54+
55+
```ts
56+
import { Parser, Interpreter, utils } from '@syuilo/aiscript';
57+
58+
const program = "<: \"Hello, World!\"";
59+
60+
let parser: Parser; // [!code ++]
61+
let interpreter: Interpreter; // [!code ++]
62+
63+
async function run() {
64+
parser = new Parser(); // [!code ++]
65+
interpreter = new Interpreter(); // [!code ++]
66+
}
67+
68+
run();
69+
```
70+
71+
`Interpreter`には、AiScriptにグローバル定数や関数を注入できるオプションと、入出力のためのハンドラがあります。
72+
73+
今回は、`Interpreter`の出力ハンドラから`console.log`を利用して、AiScriptからの出力をコンソールに表示するようにします。
74+
75+
AiScriptインタプリタとのやり取りでは生のJavascriptの値は使われず、すべてValueというオブジェクトを介しています。今回は簡単のために、`utils.valueToJs`を使ってValueをJavascriptの値に変換しています。
76+
77+
```ts
78+
import { Parser, Interpreter, utils } from '@syuilo/aiscript';
79+
80+
const program = "<: \"Hello, World!\"";
81+
82+
let parser: Parser;
83+
let interpreter: Interpreter;
84+
85+
async function run() {
86+
parser = new Parser();
87+
interpreter = new Interpreter({}, { // ←第1引数で注入する値を指定できる // [!code ++]
88+
out: (value) => { // [!code ++]
89+
console.log(utils.valueToJs(value)); // [!code ++]
90+
}, // [!code ++]
91+
}); // [!code ++]
92+
}
93+
94+
run();
95+
```
96+
97+
これで`Parser``Interpreter`の準備は完了です。実際に`program`を実行してみましょう。
98+
99+
```ts
100+
import { Parser, Interpreter, utils } from '@syuilo/aiscript';
101+
102+
const program = "<: \"Hello, World!\"";
103+
104+
let parser: Parser;
105+
let interpreter: Interpreter;
106+
107+
async function run() {
108+
parser = new Parser();
109+
interpreter = new Interpreter({}, {
110+
out: (value) => {
111+
console.log(utils.valueToJs(value));
112+
},
113+
});
114+
115+
const ast = parser.parse(program); // [!code ++]
116+
await interpreter.exec(ast); // [!code ++]
117+
}
118+
119+
run();
120+
```
121+
122+
お疲れ様でした!コンソールに`Hello, World!`と表示されるはずです。
123+
124+
:::warning 注意
125+
実際の運用では、`parser.parse`および`interpreter.exec`にエラーハンドリングを追加してください。
126+
:::
127+
128+
## 3. 独自の値を注入する
129+
130+
先ほど説明した通り、`Interpreter`の第1引数にはAiScriptからアクセス可能なグローバル定数や関数を注入できます。
131+
132+
今回は、以下のような関数を注入してみましょう。
133+
134+
- `APP_VERSION`: アプリケーションのバージョンの定数
135+
- `App:showAlert(message: string)`: アラートを表示する関数
136+
137+
そして、これらを組み合わせて、バージョン番号を含むアラートを表示するプログラムを実行してみます。
138+
139+
```aiscript
140+
App:showAlert(`You are running MyApp Version {APP_VERSION}`)
141+
```
142+
143+
ステップ2のコードをそのまま流用して、AiScriptプログラムだけを変更したのが以下のものです。
144+
145+
```ts
146+
import { Parser, Interpreter, utils } from '@syuilo/aiscript';
147+
148+
const program = `App:showAlert(\`You are running MyApp Version {APP_VERSION}\`)`; // [!code ++]
149+
150+
let parser: Parser;
151+
let interpreter: Interpreter;
152+
153+
async function run() {
154+
parser = new Parser();
155+
interpreter = new Interpreter({}, {
156+
out: (value) => {
157+
console.log(utils.valueToJs(value));
158+
},
159+
});
160+
161+
const ast = parser.parse(program);
162+
await interpreter.exec(ast);
163+
}
164+
165+
run();
166+
```
167+
168+
ここで、`APP_VERSION``App:showAlert`を注入します。
169+
170+
```ts
171+
import { Parser, Interpreter, utils, values } from '@syuilo/aiscript'; // [!code ++]
172+
import { alert } from '@/ui'; // お使いの環境に合わせて変更してください // [!code ++]
173+
174+
const program = `App:showAlert(\`You are running MyApp Version {APP_VERSION}\`)`;
175+
176+
let parser: Parser;
177+
let interpreter: Interpreter;
178+
179+
async function run() {
180+
parser = new Parser();
181+
interpreter = new Interpreter({
182+
APP_VERSION: values.STR('1.0.0'), // [!code ++]
183+
'App:showAlert': values.FN_NATIVE(([message]) => { // [!code ++]
184+
utils.assertString(message); // [!code ++]
185+
alert(message.value); // [!code ++]
186+
return values.NULL; // [!code ++]
187+
}), // [!code ++]
188+
}, {
189+
out: (value) => {
190+
console.log(utils.valueToJs(value));
191+
},
192+
});
193+
194+
const ast = parser.parse(program);
195+
await interpreter.exec(ast);
196+
}
197+
198+
run();
199+
```
200+
201+
`Interpreter`の第1引数に、注入したい値を**AiScriptの値に変換して**渡します。すべての値は`values`オブジェクトを通じて生成できます。もちろん文字列だけでなく、数値・配列・オブジェクトなども注入することができます。
202+
203+
また、関数の引数もAiScriptの値として渡されます。`utils`に含まれている`assert*`系の関数を使って、型アサーションを行うとともに、不正な値が含まれていた場合はエラーを返すことができます。
204+
205+
:::tip ヒント
206+
207+
既存の関数群との衝突を避けるためにも、名前空間を意識して関数名を指定することをお勧めします。
208+
209+
独自関数を多数実装している[Misskeyの独自関数のリファレンス](https://misskey-hub.net/docs/for-developers/plugin/plugin-api-reference/)や、[実際に独自関数を実装している部分のコード](https://github.com/misskey-dev/misskey/blob/develop/packages/frontend/src/scripts/aiscript/api.ts)が参考になるでしょう。
210+
211+
:::

0 commit comments

Comments
 (0)