Skip to content

Commit 9dc3321

Browse files
uzmoikakkokari-gtyih
andauthoredJan 8, 2025··
playgroundにバージョン切り替えを追加 (#17)
* バージョンを切り替えるUIを追加 * runnerをクラスに切り出す * add versions * runnerの切り替えを実装 * refactor * fix type * tweak design * tweak design * 不要なガード節を削除 --------- Co-authored-by: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com>
1 parent a6b6a15 commit 9dc3321

File tree

12 files changed

+580
-64
lines changed

12 files changed

+580
-64
lines changed
 

Diff for: ‎.vitepress/pages/Playground.vue

+89-64
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,14 @@
22
<div :class="$style.playgroundRoot">
33
<div :class="$style.playgroundHeader">
44
<div :class="$style.playgroundHeaderInner">
5-
<div>Playground <small>(v{{ AISCRIPT_VERSION }})</small></div>
6-
<div :class="$style.playgroundOptions"></div>
5+
<div>Playground <small>(v{{ runner?.version ?? "???" }})</small></div>
6+
<div :class="$style.playgroundOptions">
7+
<select :class="$style.playgroundSelect" v-model="version">
8+
<option v-for="version in versionModules.keys()" :value="version">
9+
{{ version === latestVersion ? `${version} (latest)` : version }}
10+
</option>
11+
</select>
12+
</div>
713
</div>
814
</div>
915
<div :class="[$style.playgroundPaneRoot, $style.playgroundEditorPane]">
@@ -83,14 +89,15 @@
8389
</template>
8490

8591
<script setup lang="ts">
86-
import { AISCRIPT_VERSION, Parser, Interpreter, utils, errors, type Ast } from '@syuilo/aiscript';
8792
import { inBrowser } from 'vitepress';
8893
import { ref, computed, useTemplateRef, nextTick, onMounted, watch, onUnmounted } from 'vue';
8994
import { createHighlighterCore } from 'shiki/core';
9095
import type { HighlighterCore, LanguageRegistration } from 'shiki/core';
9196
import { createOnigurumaEngine } from 'shiki/engine/oniguruma';
9297
import lzString from 'lz-string';
9398
import { useThrottle } from '../scripts/throttle';
99+
import type { Runner } from '../scripts/runner';
100+
import { latestVersion, versionModules } from '../scripts/versions';
94101
95102
// lz-stringがCommonJSモジュールだったみたいなので
96103
const { compressToEncodedURIComponent, decompressFromEncodedURIComponent } = lzString;
@@ -166,8 +173,10 @@ function replaceWithFizzbuzz() {
166173
//#endregion
167174
168175
//#region Runner
169-
let parser: Parser | null = null;
170-
let interpreter: Interpreter | null = null;
176+
let RunnerConstructor: new (...args: ConstructorParameters<typeof Runner>) => Runner;
177+
const runner = ref<Runner>();
178+
179+
const version = ref(latestVersion);
171180
172181
const isRunning = ref(false);
173182
@@ -179,7 +188,7 @@ const logEl = useTemplateRef('logEl');
179188
180189
const isSyntaxError = ref(false);
181190
182-
const ast = ref<Ast.Node[] | null>(null);
191+
const ast = ref<unknown>(null);
183192
const astHtml = ref('');
184193
185194
const metadata = ref<unknown>(null);
@@ -188,16 +197,16 @@ const metadataHtml = ref('');
188197
function parse() {
189198
isSyntaxError.value = false;
190199
191-
if (parser != null) {
200+
if (runner.value == null) {
201+
ast.value = null;
202+
} else {
192203
try {
193-
const _ast = parser.parse(code.value);
204+
const [ast_, metadata_] = runner.value.parse(code.value);
194205
logs.value = [];
195-
ast.value = _ast;
196-
197-
const meta = Interpreter.collectMetadata(_ast);
198-
metadata.value = meta?.get(null) ?? null;
206+
ast.value = ast_;
207+
metadata.value = metadata_?.get(null) ?? null;
199208
} catch (err) {
200-
if (err instanceof errors.AiScriptError) {
209+
if (runner.value.isAiScriptError(err)) {
201210
logs.value = [{
202211
text: `[SyntaxError] ${err.name}: ${err.message}`,
203212
type: 'error',
@@ -207,30 +216,15 @@ function parse() {
207216
ast.value = null;
208217
metadata.value = null;
209218
}
210-
} else {
211-
ast.value = null;
212219
}
213220
}
214221
215222
function initAiScriptEnv() {
216-
if (parser == null) {
217-
parser = new Parser();
218-
}
219-
if (interpreter != null) {
220-
interpreter.abort();
221-
}
222-
interpreter = new Interpreter({}, {
223-
out: (value) => {
224-
logs.value.push({
225-
text: value.type === 'num' ? value.value.toString() : value.type === 'str' ? `"${value.value}"` : JSON.stringify(utils.valToJs(value), null, 2) ?? '',
226-
});
227-
},
228-
log: (type, params) => {
229-
if (type === 'end' && params.val != null && 'type' in params.val) {
230-
logs.value.push({
231-
text: utils.valToString(params.val, true),
232-
});
233-
}
223+
runner.value?.dispose();
224+
225+
runner.value = new RunnerConstructor({
226+
print(text) {
227+
logs.value.push({ text });
234228
},
235229
});
236230
}
@@ -244,10 +238,10 @@ async function run() {
244238
isRunning.value = true;
245239
246240
parse();
247-
if (ast.value != null && interpreter !== null) {
241+
if (ast.value != null && runner.value != null) {
248242
try {
249243
const execStartTime = performance.now();
250-
await interpreter.exec(ast.value);
244+
await runner.value.exec(ast.value);
251245
const execEndTime = performance.now();
252246
logs.value.push({
253247
text: `[Playground] Execution Completed in ${Math.round(execEndTime - execStartTime)}ms`,
@@ -259,21 +253,8 @@ async function run() {
259253
});
260254
}
261255
} catch (err) {
262-
if (err instanceof errors.AiScriptError) {
263-
let errorName = 'AiScriptError';
264-
265-
if (err instanceof errors.AiScriptSyntaxError) {
266-
errorName = 'SyntaxError';
267-
} else if (err instanceof errors.AiScriptTypeError) {
268-
errorName = 'TypeError';
269-
} else if (err instanceof errors.AiScriptRuntimeError) {
270-
errorName = 'RuntimeError';
271-
} else if (err instanceof errors.AiScriptIndexOutOfRangeError) {
272-
errorName = 'IndexOutOfRangeError';
273-
} else if (err instanceof errors.AiScriptUserError) {
274-
errorName = 'UserError';
275-
}
276-
256+
if (runner.value.isAiScriptError(err)) {
257+
const errorName = runner.value.getErrorName(err);
277258
logs.value.push({
278259
text: `[${errorName}] ${err.name}: ${err.message}`,
279260
type: 'error',
@@ -291,8 +272,8 @@ async function run() {
291272
}
292273
293274
function abort() {
294-
if (interpreter != null) {
295-
interpreter.abort();
275+
if (runner.value != null) {
276+
runner.value.dispose();
296277
logs.value.push({
297278
text: '[Playground] Execution Aborted',
298279
type: 'info',
@@ -309,7 +290,7 @@ function clearLog() {
309290
//#region Permalink with hash
310291
type HashData = {
311292
code: string;
312-
// TODO: バージョン情報(マルチバージョン対応の際に必要。なければ最新にフォールバック)
293+
version?: string;
313294
};
314295
const hash = ref<string | null>(inBrowser ? window.location.hash.slice(1) || localStorage.getItem('ais:playground') : null);
315296
const hashData = computed<HashData | null>(() => {
@@ -332,16 +313,38 @@ onMounted(async () => {
332313
const loadStartedAt = Date.now();
333314
334315
await init();
335-
initAiScriptEnv();
336316
337-
if (hashData.value != null && hashData.value.code != null) {
338-
code.value = hashData.value.code;
317+
if (hashData.value != null) {
318+
if (hashData.value.code != null) {
319+
code.value = hashData.value.code;
320+
}
321+
if (hashData.value.version != null) {
322+
version.value = hashData.value.version;
323+
}
339324
}
340-
watch([code], () => {
341-
updateHash({ code: code.value });
325+
326+
watch(version, async () => {
327+
editorLoading.value = true;
328+
329+
const import_ = versionModules.get(version.value);
330+
if (import_ == null) return;
331+
332+
const module = await import_();
333+
RunnerConstructor = module.default;
334+
335+
initAiScriptEnv();
336+
337+
editorLoading.value = false;
342338
}, { immediate: true });
343339
344-
watch(code, async (newCode) => {
340+
watch([code, version], () => {
341+
updateHash({
342+
code: code.value,
343+
version: version.value,
344+
});
345+
}, { immediate: true });
346+
347+
watch([code, runner], ([newCode]) => {
345348
parse();
346349
if (highlighter) {
347350
editorHtml.value = highlighter.codeToHtml(newCode, {
@@ -399,9 +402,7 @@ onMounted(async () => {
399402
});
400403
401404
onUnmounted(() => {
402-
if (interpreter != null) {
403-
interpreter.abort();
404-
}
405+
runner.value?.dispose();
405406
});
406407
</script>
407408

@@ -420,8 +421,10 @@ onUnmounted(() => {
420421
421422
.playgroundHeaderInner {
422423
margin: 0 auto;
423-
padding: 0.5em 36px;
424+
padding: 0 36px;
425+
min-height: 40px;
424426
display: flex;
427+
align-items: center;
425428
}
426429
427430
.playgroundOptions {
@@ -629,14 +632,36 @@ onUnmounted(() => {
629632
background-color: var(--vp-button-brand-hover-bg);
630633
}
631634
635+
.playgroundSelect {
636+
background-color: var(--vp-button-alt-bg);
637+
transition: background-color 0.25s;
638+
padding: 3px 36px 3px 16px;
639+
border-radius: 8px;
640+
font-family: var(--vp-font-family-base);
641+
font-size: 80%;
642+
643+
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
644+
background-repeat: no-repeat;
645+
background-position: right .75em center;
646+
background-size: 16px 12px;
647+
}
648+
649+
:global(html.dark) .playgroundSelect {
650+
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23fffff5db' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
651+
}
652+
653+
.playgroundSelect:hover {
654+
background-color: var(--vp-button-alt-hover-bg);
655+
}
656+
632657
@media (max-width: 768px) {
633658
.playgroundEditorScroller,
634659
.playgroundEditorTextarea {
635660
padding: 24px 24px;
636661
}
637662
638663
.playgroundHeaderInner {
639-
padding: 0.5em 24px;
664+
padding: 0 24px;
640665
}
641666
642667
.playgroundResultActionsLeft {

Diff for: ‎.vitepress/scripts/runner.ts

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
export abstract class Runner {
2+
abstract version: string;
3+
4+
protected print: (text: string) => void;
5+
constructor({ print }: {
6+
print(text: string): void;
7+
}) {
8+
this.print = print;
9+
}
10+
11+
abstract parse(code: string): readonly [unknown, Map<string | null, unknown> | undefined];
12+
abstract exec(node: unknown): Promise<void>;
13+
abstract isAiScriptError(error: unknown): error is Error;
14+
abstract getErrorName(error: Error): string | undefined;
15+
abstract dispose(): void;
16+
}

Diff for: ‎.vitepress/scripts/versions/0.14.1.ts

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { Parser, Interpreter, utils, errors, type Ast, values } from 'aiscript0_14';
2+
import { Runner } from '../runner';
3+
4+
export default class extends Runner {
5+
version = '0.14.1';
6+
7+
parse(code: string) {
8+
const ast = Parser.parse(code);
9+
const metadata = Interpreter.collectMetadata(ast);
10+
return [ast, metadata] as const;
11+
}
12+
13+
private interpreter = new Interpreter({}, {
14+
out: (value: values.Value) => {
15+
this.print(
16+
value.type === 'num' ? value.value.toString()
17+
: value.type === 'str' ? `"${value.value}"`
18+
: JSON.stringify(utils.valToJs(value), null, 2) ?? '',
19+
);
20+
},
21+
log: (type: string, params: { val?: values.Value }) => {
22+
if (type === 'end' && params.val != null && 'type' in params.val) {
23+
this.print(utils.valToString(params.val, true));
24+
}
25+
},
26+
});
27+
async exec(node: unknown): Promise<void> {
28+
await this.interpreter.exec(node as Ast.Node[]);
29+
}
30+
isAiScriptError(error: unknown): error is errors.AiScriptError {
31+
return error instanceof errors.AiScriptError;
32+
}
33+
getErrorName(error: errors.AiScriptError): string | undefined {
34+
if (error instanceof errors.SyntaxError) {
35+
return 'SyntaxError';
36+
}
37+
if (error instanceof errors.TypeError) {
38+
return 'TypeError';
39+
}
40+
if (error instanceof errors.RuntimeError) {
41+
return 'RuntimeError';
42+
}
43+
if (error instanceof errors.IndexOutOfRangeError) {
44+
return 'IndexOutOfRangeError';
45+
}
46+
return 'AiScriptError';
47+
}
48+
dispose() {
49+
this.interpreter.abort();
50+
}
51+
}

Diff for: ‎.vitepress/scripts/versions/0.15.0.ts

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { Parser, Interpreter, values, utils, errors, type Ast } from 'aiscript0_15';
2+
import { Runner } from '../runner';
3+
4+
export default class extends Runner {
5+
version = '0.15.0';
6+
7+
parse(code: string) {
8+
const ast = Parser.parse(code);
9+
const metadata = Interpreter.collectMetadata(ast);
10+
return [ast, metadata] as const;
11+
}
12+
13+
private interpreter = new Interpreter({}, {
14+
out: (value: values.Value) => {
15+
this.print(
16+
value.type === 'num' ? value.value.toString()
17+
: value.type === 'str' ? `"${value.value}"`
18+
: JSON.stringify(utils.valToJs(value), null, 2) ?? '',
19+
);
20+
},
21+
log: (type: string, params: { val?: values.Value }) => {
22+
if (type === 'end' && params.val != null && 'type' in params.val) {
23+
this.print(utils.valToString(params.val, true));
24+
}
25+
},
26+
});
27+
async exec(node: unknown): Promise<void> {
28+
await this.interpreter.exec(node as Ast.Node[]);
29+
}
30+
isAiScriptError(error: unknown): error is errors.AiScriptError {
31+
return error instanceof errors.AiScriptError;
32+
}
33+
getErrorName(error: errors.AiScriptError): string | undefined {
34+
if (error instanceof errors.SyntaxError) {
35+
return 'SyntaxError';
36+
}
37+
if (error instanceof errors.TypeError) {
38+
return 'TypeError';
39+
}
40+
if (error instanceof errors.RuntimeError) {
41+
return 'RuntimeError';
42+
}
43+
if (error instanceof errors.IndexOutOfRangeError) {
44+
return 'IndexOutOfRangeError';
45+
}
46+
return 'AiScriptError';
47+
}
48+
dispose() {
49+
this.interpreter.abort();
50+
}
51+
}

Diff for: ‎.vitepress/scripts/versions/0.16.0.ts

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { Parser, Interpreter, utils, errors, type Ast } from 'aiscript0_16/index.js';
2+
import { Runner } from '../runner';
3+
4+
export default class extends Runner {
5+
version = '0.16.0';
6+
7+
parse(code: string) {
8+
const ast = Parser.parse(code);
9+
const metadata = Interpreter.collectMetadata(ast);
10+
return [ast, metadata] as const;
11+
}
12+
13+
private interpreter = new Interpreter({}, {
14+
out: (value) => {
15+
this.print(
16+
value.type === 'num' ? value.value.toString()
17+
: value.type === 'str' ? `"${value.value}"`
18+
: JSON.stringify(utils.valToJs(value), null, 2) ?? '',
19+
);
20+
},
21+
log: (type, params) => {
22+
if (type === 'end' && params.val != null && 'type' in params.val) {
23+
this.print(utils.valToString(params.val, true));
24+
}
25+
},
26+
});
27+
async exec(node: unknown): Promise<void> {
28+
await this.interpreter.exec(node as Ast.Node[]);
29+
}
30+
isAiScriptError(error: unknown): error is errors.AiScriptError {
31+
return error instanceof errors.AiScriptError;
32+
}
33+
getErrorName(error: errors.AiScriptError): string | undefined {
34+
if (error instanceof errors.AiScriptSyntaxError) {
35+
return 'SyntaxError';
36+
}
37+
if (error instanceof errors.AiScriptTypeError) {
38+
return 'TypeError';
39+
}
40+
if (error instanceof errors.AiScriptRuntimeError) {
41+
return 'RuntimeError';
42+
}
43+
if (error instanceof errors.AiScriptIndexOutOfRangeError) {
44+
return 'IndexOutOfRangeError';
45+
}
46+
return 'AiScriptError';
47+
}
48+
dispose() {
49+
this.interpreter.abort();
50+
}
51+
}

Diff for: ‎.vitepress/scripts/versions/0.17.0.ts

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { AISCRIPT_VERSION, Parser, Interpreter, utils, errors, type Ast } from 'aiscript0_17';
2+
import { Runner } from '../runner';
3+
4+
export default class extends Runner {
5+
version = AISCRIPT_VERSION;
6+
7+
parse(code: string) {
8+
const ast = Parser.parse(code);
9+
const metadata = Interpreter.collectMetadata(ast);
10+
return [ast, metadata] as const;
11+
}
12+
13+
private interpreter = new Interpreter({}, {
14+
out: (value) => {
15+
this.print(
16+
value.type === 'num' ? value.value.toString()
17+
: value.type === 'str' ? `"${value.value}"`
18+
: JSON.stringify(utils.valToJs(value), null, 2) ?? '',
19+
);
20+
},
21+
log: (type, params) => {
22+
if (type === 'end' && params.val != null && 'type' in params.val) {
23+
this.print(utils.valToString(params.val, true));
24+
}
25+
},
26+
});
27+
async exec(node: unknown): Promise<void> {
28+
await this.interpreter.exec(node as Ast.Node[]);
29+
}
30+
isAiScriptError(error: unknown): error is errors.AiScriptError {
31+
return error instanceof errors.AiScriptError;
32+
}
33+
getErrorName(error: errors.AiScriptError): string | undefined {
34+
if (error instanceof errors.AiScriptSyntaxError) {
35+
return 'SyntaxError';
36+
}
37+
if (error instanceof errors.AiScriptTypeError) {
38+
return 'TypeError';
39+
}
40+
if (error instanceof errors.AiScriptRuntimeError) {
41+
return 'RuntimeError';
42+
}
43+
if (error instanceof errors.AiScriptIndexOutOfRangeError) {
44+
return 'IndexOutOfRangeError';
45+
}
46+
return 'AiScriptError';
47+
}
48+
dispose() {
49+
this.interpreter.abort();
50+
}
51+
}

Diff for: ‎.vitepress/scripts/versions/0.18.0.ts

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { AISCRIPT_VERSION, Parser, Interpreter, utils, errors, type Ast } from 'aiscript0_18';
2+
import { Runner } from '../runner';
3+
4+
export default class extends Runner {
5+
version = AISCRIPT_VERSION;
6+
7+
parse(code: string) {
8+
const ast = Parser.parse(code);
9+
const metadata = Interpreter.collectMetadata(ast);
10+
return [ast, metadata] as const;
11+
}
12+
13+
private interpreter = new Interpreter({}, {
14+
out: (value) => {
15+
this.print(
16+
value.type === 'num' ? value.value.toString()
17+
: value.type === 'str' ? `"${value.value}"`
18+
: JSON.stringify(utils.valToJs(value), null, 2) ?? '',
19+
);
20+
},
21+
log: (type, params) => {
22+
if (type === 'end' && params.val != null && 'type' in params.val) {
23+
this.print(utils.valToString(params.val, true));
24+
}
25+
},
26+
});
27+
async exec(node: unknown): Promise<void> {
28+
await this.interpreter.exec(node as Ast.Node[]);
29+
}
30+
isAiScriptError(error: unknown): error is errors.AiScriptError {
31+
return error instanceof errors.AiScriptError;
32+
}
33+
getErrorName(error: errors.AiScriptError): string | undefined {
34+
if (error instanceof errors.AiScriptSyntaxError) {
35+
return 'SyntaxError';
36+
}
37+
if (error instanceof errors.AiScriptTypeError) {
38+
return 'TypeError';
39+
}
40+
if (error instanceof errors.AiScriptRuntimeError) {
41+
return 'RuntimeError';
42+
}
43+
if (error instanceof errors.AiScriptIndexOutOfRangeError) {
44+
return 'IndexOutOfRangeError';
45+
}
46+
if (error instanceof errors.AiScriptUserError) {
47+
return 'UserError';
48+
}
49+
return 'AiScriptError';
50+
}
51+
dispose() {
52+
this.interpreter.abort();
53+
}
54+
}

Diff for: ‎.vitepress/scripts/versions/0.19.0.ts

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { AISCRIPT_VERSION, Parser, Interpreter, utils, errors, type Ast } from 'aiscript0_19';
2+
import { Runner } from '../runner';
3+
4+
export default class extends Runner {
5+
version = AISCRIPT_VERSION;
6+
7+
parse(code: string) {
8+
const ast = Parser.parse(code);
9+
const metadata = Interpreter.collectMetadata(ast);
10+
return [ast, metadata] as const;
11+
}
12+
13+
private interpreter = new Interpreter({}, {
14+
out: (value) => {
15+
this.print(
16+
value.type === 'num' ? value.value.toString()
17+
: value.type === 'str' ? `"${value.value}"`
18+
: JSON.stringify(utils.valToJs(value), null, 2) ?? '',
19+
);
20+
},
21+
log: (type, params) => {
22+
if (type === 'end' && params.val != null && 'type' in params.val) {
23+
this.print(utils.valToString(params.val, true));
24+
}
25+
},
26+
});
27+
async exec(node: unknown): Promise<void> {
28+
await this.interpreter.exec(node as Ast.Node[]);
29+
}
30+
isAiScriptError(error: unknown): error is errors.AiScriptError {
31+
return error instanceof errors.AiScriptError;
32+
}
33+
getErrorName(error: errors.AiScriptError): string | undefined {
34+
if (error instanceof errors.AiScriptSyntaxError) {
35+
return 'SyntaxError';
36+
}
37+
if (error instanceof errors.AiScriptTypeError) {
38+
return 'TypeError';
39+
}
40+
if (error instanceof errors.AiScriptRuntimeError) {
41+
return 'RuntimeError';
42+
}
43+
if (error instanceof errors.AiScriptIndexOutOfRangeError) {
44+
return 'IndexOutOfRangeError';
45+
}
46+
if (error instanceof errors.AiScriptUserError) {
47+
return 'UserError';
48+
}
49+
return 'AiScriptError';
50+
}
51+
dispose() {
52+
this.interpreter.abort();
53+
}
54+
}

Diff for: ‎.vitepress/scripts/versions/dev.ts

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { AISCRIPT_VERSION, Parser, Interpreter, utils, errors, type Ast } from '@syuilo/aiscript';
2+
import { Runner } from '../runner';
3+
4+
export default class extends Runner {
5+
version = AISCRIPT_VERSION;
6+
7+
parse(code: string) {
8+
const ast = Parser.parse(code);
9+
const metadata = Interpreter.collectMetadata(ast);
10+
return [ast, metadata] as const;
11+
}
12+
13+
private interpreter = new Interpreter({}, {
14+
out: (value) => {
15+
this.print(
16+
value.type === 'num' ? value.value.toString()
17+
: value.type === 'str' ? `"${value.value}"`
18+
: JSON.stringify(utils.valToJs(value), null, 2) ?? '',
19+
);
20+
},
21+
log: (type, params) => {
22+
if (type === 'end' && params.val != null && 'type' in params.val) {
23+
this.print(utils.valToString(params.val, true));
24+
}
25+
},
26+
});
27+
async exec(node: unknown): Promise<void> {
28+
await this.interpreter.exec(node as Ast.Node[]);
29+
}
30+
isAiScriptError(error: unknown): error is errors.AiScriptError {
31+
return error instanceof errors.AiScriptError;
32+
}
33+
getErrorName(error: errors.AiScriptError): string | undefined {
34+
if (error instanceof errors.AiScriptSyntaxError) {
35+
return 'SyntaxError';
36+
}
37+
if (error instanceof errors.AiScriptTypeError) {
38+
return 'TypeError';
39+
}
40+
if (error instanceof errors.AiScriptRuntimeError) {
41+
return 'RuntimeError';
42+
}
43+
if (error instanceof errors.AiScriptIndexOutOfRangeError) {
44+
return 'IndexOutOfRangeError';
45+
}
46+
if (error instanceof errors.AiScriptUserError) {
47+
return 'UserError';
48+
}
49+
return 'AiScriptError';
50+
}
51+
dispose() {
52+
this.interpreter.abort();
53+
}
54+
}

Diff for: ‎.vitepress/scripts/versions/index.ts

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { Runner } from '../runner';
2+
3+
interface VersionModule {
4+
default: new (...args: ConstructorParameters<typeof Runner>) => Runner;
5+
}
6+
7+
export const versionModules = new Map<string, () => Promise<VersionModule>>([
8+
['dev', () => import('./dev')],
9+
['0.19.0', () => import('./0.19.0')],
10+
['0.18.0', () => import('./0.18.0')],
11+
['0.17.0', () => import('./0.17.0')],
12+
['0.16.0', () => import('./0.16.0')],
13+
['0.15.0', () => import('./0.15.0')],
14+
['0.14.1', () => import('./0.14.1')],
15+
]);
16+
17+
export const latestVersion = [...versionModules.keys()][1]!;

Diff for: ‎package.json

+6
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@
99
"packageManager": "pnpm@9.14.3",
1010
"devDependencies": {
1111
"@syuilo/aiscript": "dev",
12+
"aiscript0_19": "npm:@syuilo/aiscript@0.19.0",
13+
"aiscript0_18": "npm:@syuilo/aiscript@0.18.0",
14+
"aiscript0_17": "npm:@syuilo/aiscript@0.17.0",
15+
"aiscript0_16": "npm:@syuilo/aiscript@0.16.0",
16+
"aiscript0_15": "npm:@syuilo/aiscript@0.15.0",
17+
"aiscript0_14": "npm:@syuilo/aiscript@0.14.1",
1218
"aiscript-vscode": "github:aiscript-dev/aiscript-vscode#v0.1.15",
1319
"lz-string": "^1.5.0",
1420
"markdown-it-mathjax3": "^4.3.2",

Diff for: ‎pnpm-lock.yaml

+86
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
Please sign in to comment.