Skip to content

Commit a9fadc7

Browse files
uzmoitakejohn
andauthored
feat: stdをインタプリタから分離 (#1022)
* stdを分離 * stdをエクスポート * Coreをstdから分離 * Update api report * changelog --------- Co-authored-by: Take-John <takejohn@takejohn.jp>
1 parent 5d4fa78 commit a9fadc7

8 files changed

Lines changed: 168 additions & 155 deletions

File tree

etc/aiscript.api.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ type Index = NodeBase & {
416416

417417
// @public (undocumented)
418418
export class Interpreter {
419-
constructor(consts: Record<string, Value>, opts?: {
419+
constructor(globals: Record<string, Value>, opts?: {
420420
in?(q: string): Promise<string>;
421421
out?(value: Value): void;
422422
err?(e: AiScriptError): void;
@@ -713,6 +713,9 @@ export class Scope {
713713
// @public (undocumented)
714714
type Statement = Definition | Return | Each | For | Loop | Break | Continue | Assign | AddAssign | SubAssign;
715715

716+
// @public (undocumented)
717+
export const std: Record<string, Value>;
718+
716719
// @public (undocumented)
717720
const STR: (str: VStr["value"]) => VStr;
718721

@@ -918,7 +921,7 @@ type VUserFn = VFnBase & {
918921

919922
// Warnings were encountered during analysis:
920923
//
921-
// src/interpreter/index.ts:49:4 - (ae-forgotten-export) The symbol "LogObject" needs to be exported by the entry point index.d.ts
924+
// src/interpreter/index.ts:50:4 - (ae-forgotten-export) The symbol "LogObject" needs to be exported by the entry point index.d.ts
922925
// src/interpreter/value.ts:47:2 - (ae-forgotten-export) The symbol "Type" needs to be exported by the entry point index.d.ts
923926

924927
// (No @packageDocumentation comment for this package)

src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//export * from './interpreter/index';
33
//export * as utils from './interpreter/util';
44
//export * as values from './interpreter/value';
5-
import { Interpreter } from './interpreter/index.js';
5+
import { Interpreter, std } from './interpreter/index.js';
66
import { Scope } from './interpreter/scope.js';
77
import * as utils from './interpreter/util.js';
88
import * as values from './interpreter/value.js';
@@ -12,7 +12,7 @@ import * as errors from './error.js';
1212
import * as Ast from './node.js';
1313
import { AISCRIPT_VERSION } from './constants.js';
1414
import type { ParserPlugin, PluginType } from './parser/index.js';
15-
export { Interpreter };
15+
export { Interpreter, std };
1616
export { Scope };
1717
export { utils };
1818
export { values };

src/interpreter/index.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,18 @@ import { AiScriptError, NonAiScriptError, AiScriptNamespaceError, AiScriptIndexO
77
import * as Ast from '../node.js';
88
import { nodeToJs } from '../utils/node-to-js.js';
99
import { Scope } from './scope.js';
10-
import { std } from './lib/std.js';
1110
import { RETURN, unWrapRet, BREAK, CONTINUE, assertValue, isControl, type Control, unWrapLabeledBreak } from './control.js';
1211
import { assertNumber, assertString, assertFunction, assertBoolean, assertObject, assertArray, eq, isObject, isArray, expectAny, reprValue, isFunction } from './util.js';
1312
import { NULL, FN_NATIVE, BOOL, NUM, STR, ARR, OBJ, FN, ERROR } from './value.js';
1413
import { getPrimProp } from './primitive-props.js';
1514
import { Variable } from './variable.js';
1615
import { Reference } from './reference.js';
16+
import { stdCore } from './lib/core.js';
1717
import type { JsValue } from './util.js';
1818
import type { Value, VFn, VUserFn } from './value.js';
1919

20+
export { std } from './lib/std.js';
21+
2022
export type LogObject = {
2123
scope?: string;
2224
var?: string;
@@ -36,12 +38,11 @@ export class Interpreter {
3638
private abortHandlers: (() => void)[] = [];
3739
private pauseHandlers: (() => void)[] = [];
3840
private unpauseHandlers: (() => void)[] = [];
39-
private vars: Record<string, Variable> = {};
4041
private irqRate: number;
4142
private irqSleep: () => Promise<void>;
4243

4344
constructor(
44-
consts: Record<string, Value>,
45+
globals: Record<string, Value>,
4546
private opts: {
4647
in?(q: string): Promise<string>;
4748
out?(value: Value): void;
@@ -67,13 +68,12 @@ export class Interpreter {
6768
}),
6869
};
6970

70-
this.vars = Object.fromEntries(Object.entries({
71-
...consts,
72-
...std,
73-
...io,
74-
}).map(([k, v]) => [k, Variable.const(v)]));
75-
76-
this.scope = new Scope([new Map(Object.entries(this.vars))]);
71+
this.scope = new Scope([
72+
new Map(
73+
Object.entries({ ...globals,...stdCore, ...io })
74+
.map(([k, v]) => [k, Variable.const(v)]),
75+
),
76+
]);
7777
this.scope.opts.log = (type, params): void => {
7878
switch (type) {
7979
case 'add': this.log('var:add', params); break;

src/interpreter/lib/core.ts

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
import { NUM, STR, FN_NATIVE, FALSE, TRUE, ARR, NULL } from '../value.js';
2+
import { assertNumber, assertString, assertBoolean, eq, expectAny, reprValue } from '../util.js';
3+
import { AiScriptUserError } from '../../error.js';
4+
import { AISCRIPT_VERSION } from '../../constants.js';
5+
import type { Value } from '../value.js';
6+
7+
export const stdCore: Record<`Core:${string}`, Value> = {
8+
'Core:v': STR(AISCRIPT_VERSION),
9+
10+
'Core:ai': STR('kawaii'),
11+
12+
'Core:not': FN_NATIVE(([a]) => {
13+
assertBoolean(a);
14+
return a.value ? FALSE : TRUE;
15+
}),
16+
17+
'Core:eq': FN_NATIVE(([a, b]) => {
18+
expectAny(a);
19+
expectAny(b);
20+
return eq(a, b) ? TRUE : FALSE;
21+
}),
22+
23+
'Core:neq': FN_NATIVE(([a, b]) => {
24+
expectAny(a);
25+
expectAny(b);
26+
return eq(a, b) ? FALSE : TRUE;
27+
}),
28+
29+
'Core:and': FN_NATIVE(([a, b]) => {
30+
assertBoolean(a);
31+
if (!a.value) return FALSE;
32+
assertBoolean(b);
33+
return b.value ? TRUE : FALSE;
34+
}),
35+
36+
'Core:or': FN_NATIVE(([a, b]) => {
37+
assertBoolean(a);
38+
if (a.value) return TRUE;
39+
assertBoolean(b);
40+
return b.value ? TRUE : FALSE;
41+
}),
42+
43+
'Core:add': FN_NATIVE(([a, b]) => {
44+
assertNumber(a);
45+
assertNumber(b);
46+
return NUM(a.value + b.value);
47+
}),
48+
49+
'Core:sub': FN_NATIVE(([a, b]) => {
50+
assertNumber(a);
51+
assertNumber(b);
52+
return NUM(a.value - b.value);
53+
}),
54+
55+
'Core:mul': FN_NATIVE(([a, b]) => {
56+
assertNumber(a);
57+
assertNumber(b);
58+
return NUM(a.value * b.value);
59+
}),
60+
61+
'Core:pow': FN_NATIVE(([a, b]) => {
62+
assertNumber(a);
63+
assertNumber(b);
64+
const res = a.value ** b.value;
65+
return NUM(res);
66+
}),
67+
68+
'Core:div': FN_NATIVE(([a, b]) => {
69+
assertNumber(a);
70+
assertNumber(b);
71+
const res = a.value / b.value;
72+
return NUM(res);
73+
}),
74+
75+
'Core:mod': FN_NATIVE(([a, b]) => {
76+
assertNumber(a);
77+
assertNumber(b);
78+
return NUM(a.value % b.value);
79+
}),
80+
81+
'Core:gt': FN_NATIVE(([a, b]) => {
82+
assertNumber(a);
83+
assertNumber(b);
84+
return a.value > b.value ? TRUE : FALSE;
85+
}),
86+
87+
'Core:lt': FN_NATIVE(([a, b]) => {
88+
assertNumber(a);
89+
assertNumber(b);
90+
return a.value < b.value ? TRUE : FALSE;
91+
}),
92+
93+
'Core:gteq': FN_NATIVE(([a, b]) => {
94+
assertNumber(a);
95+
assertNumber(b);
96+
return a.value >= b.value ? TRUE : FALSE;
97+
}),
98+
99+
'Core:lteq': FN_NATIVE(([a, b]) => {
100+
assertNumber(a);
101+
assertNumber(b);
102+
return a.value <= b.value ? TRUE : FALSE;
103+
}),
104+
105+
'Core:type': FN_NATIVE(([v]) => {
106+
expectAny(v);
107+
return STR(v.type);
108+
}),
109+
110+
'Core:to_str': FN_NATIVE(([v]) => {
111+
expectAny(v);
112+
113+
return STR(reprValue(v));
114+
}),
115+
116+
'Core:range': FN_NATIVE(([a, b]) => {
117+
assertNumber(a);
118+
assertNumber(b);
119+
if (a.value < b.value) {
120+
return ARR(Array.from({ length: (b.value - a.value) + 1 }, (_, i) => NUM(i + a.value)));
121+
} else if (a.value > b.value) {
122+
return ARR(Array.from({ length: (a.value - b.value) + 1 }, (_, i) => NUM(a.value - i)));
123+
} else {
124+
return ARR([a]);
125+
}
126+
}),
127+
128+
'Core:sleep': FN_NATIVE(async ([delay]) => {
129+
assertNumber(delay);
130+
await new Promise((r) => setTimeout(r, delay.value));
131+
return NULL;
132+
}),
133+
134+
'Core:abort': FN_NATIVE(async ([message]) => {
135+
assertString(message);
136+
throw new AiScriptUserError(message.value);
137+
}),
138+
};

0 commit comments

Comments
 (0)