diff --git a/CHANGELOG.md b/CHANGELOG.md
index c814152f..0df3fc63 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,8 @@
- 指定時間待機する関数`Core:sleep`を追加
- `exists 変数名` の構文で変数が存在するか判定できるように
- オブジェクトを添字で参照できるように(`object['index']`のように)
+- 「エラー型(`error`)」を導入
+- `Json:parse`がパース失敗時にエラー型の値を返すように
# 0.15.0
- Mathを強化
diff --git a/docs/get-started.md b/docs/get-started.md
index bd70436c..e20816d4 100644
--- a/docs/get-started.md
+++ b/docs/get-started.md
@@ -51,6 +51,7 @@ this is a comment
オブジェクト | obj | { foo: "bar"; a: 42; } |
null | null | null |
関数 | fn | @(x) { x } |
+ エラー | error | (TODO) |
## 変数
@@ -256,4 +257,15 @@ AiScriptファイルにメタデータを埋め込める機能です。
version: 42
keywords: ["foo" "bar" "baz"]
}
-```
\ No newline at end of file
+```
+
+## エラー型
+一部の標準関数は実行失敗時にエラー型の値を返します。
+これによりエラー処理を行うことができます。
+```
+@validate(str){
+ let v=Json:parse(str)
+ if (Core:type(v)=='error') print(v.name)
+ else print('successful')
+}
+```
diff --git a/docs/std.md b/docs/std.md
index 7d4bfe15..ed87a68e 100644
--- a/docs/std.md
+++ b/docs/std.md
@@ -33,10 +33,10 @@ AiScriptのバージョンです。
JSONを生成します。
### @Json:parse(_json_: str): value
-JSONをパースします。
+JSONをパースします。 引数がJSONとしてパース可能性でない場合、エラー型の値(`name`=`'not_json'`)を返します。
### @Json:parsable(_str_: str): bool
-文字列がJSONとしてパース可能であるかの判定を行います。
+文字列がJSONとしてパース可能であるかの判定を行います。歴史的理由により存在しています
## :: Date
@@ -236,6 +236,14 @@ _codepoint_ は 0 以上、10FFFF16 以下である必要がありま
### @Obj:copy(_v_: obj): obj
オブジェクトのコピーを生成します。
+## :: Error
+
+### @(_v_: error).name(): str
+エラーの識別子となる文字列を返します。
+
+### @(_v_: error).info(): value
+エラーに付加情報がある場合、それを返します。
+
## :: Async
### @Async:interval(_interval_: num, _callback_: fn, _immediate_?: bool): fn
diff --git a/etc/aiscript.api.md b/etc/aiscript.api.md
index 5cc949b2..f5c4ff08 100644
--- a/etc/aiscript.api.md
+++ b/etc/aiscript.api.md
@@ -1,1036 +1,1048 @@
-## API Report File for "@syuilo/aiscript"
-
-> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
-
-```ts
-
-// Warning: (ae-forgotten-export) The symbol "NodeBase" needs to be exported by the entry point index.d.ts
-//
-// @public (undocumented)
-type AddAssign = NodeBase & {
- type: 'addAssign';
- dest: Expression;
- expr: Expression;
-};
-
-// Warning: (ae-forgotten-export) The symbol "NodeBase_2" needs to be exported by the entry point index.d.ts
-//
-// @public (undocumented)
-type AddAssign_2 = NodeBase_2 & {
- type: 'addAssign';
- dest: Expression_2;
- expr: Expression_2;
-};
-
-// @public (undocumented)
-abstract class AiScriptError extends Error {
- constructor(message: string, info?: any);
- // (undocumented)
- info?: any;
-}
-
-// @public (undocumented)
-type And = NodeBase & {
- type: 'and';
- left: Expression;
- right: Expression;
-};
-
-// @public (undocumented)
-type And_2 = NodeBase_2 & {
- type: 'and';
- left: Expression_2;
- right: Expression_2;
-};
-
-// @public (undocumented)
-const ARR: (arr: VArr['value']) => VArr;
-
-// @public (undocumented)
-type Arr = NodeBase & {
- type: 'arr';
- value: Expression[];
-};
-
-// Warning: (ae-forgotten-export) The symbol "ChainProp" needs to be exported by the entry point index.d.ts
-//
-// @public (undocumented)
-type Arr_2 = NodeBase_2 & ChainProp & {
- type: 'arr';
- value: Expression_2[];
-};
-
-// @public (undocumented)
-function assertArray(val: Value | null | undefined): asserts val is VArr;
-
-// @public (undocumented)
-function assertBoolean(val: Value | null | undefined): asserts val is VBool;
-
-// @public (undocumented)
-function assertFunction(val: Value | null | undefined): asserts val is VFn;
-
-// @public (undocumented)
-function assertNumber(val: Value | null | undefined): asserts val is VNum;
-
-// @public (undocumented)
-function assertObject(val: Value | null | undefined): asserts val is VObj;
-
-// @public (undocumented)
-function assertString(val: Value | null | undefined): asserts val is VStr;
-
-// @public (undocumented)
-type Assign = NodeBase & {
- type: 'assign';
- dest: Expression;
- expr: Expression;
-};
-
-// @public (undocumented)
-type Assign_2 = NodeBase_2 & {
- type: 'assign';
- dest: Expression_2;
- expr: Expression_2;
-};
-
-declare namespace Ast {
- export {
- isStatement,
- isExpression,
- Loc,
- Node_2 as Node,
- Statement,
- Expression,
- Namespace,
- Meta,
- Definition,
- Attribute,
- Return,
- Each,
- For,
- Loop,
- Break,
- Continue,
- AddAssign,
- SubAssign,
- Assign,
- Not,
- And,
- Or,
- If,
- Fn,
- Match,
- Block,
- Exists,
- Tmpl,
- Str,
- Num,
- Bool,
- Null,
- Obj,
- Arr,
- Identifier,
- Call,
- Index,
- Prop,
- TypeSource,
- NamedTypeSource,
- FnTypeSource
- }
-}
-export { Ast }
-
-// @public (undocumented)
-type Attr_2 = {
- attr?: {
- name: string;
- value: Value;
- }[];
-};
-
-// @public (undocumented)
-type Attribute = NodeBase & {
- type: 'attr';
- name: string;
- value: Expression;
-};
-
-// @public (undocumented)
-type Attribute_2 = NodeBase_2 & {
- type: 'attr';
- name: string;
- value: Expression_2;
-};
-
-// @public (undocumented)
-type Block = NodeBase & {
- type: 'block';
- statements: (Statement | Expression)[];
-};
-
-// @public (undocumented)
-type Block_2 = NodeBase_2 & ChainProp & {
- type: 'block';
- statements: (Statement_2 | Expression_2)[];
-};
-
-// @public (undocumented)
-const BOOL: (bool: VBool['value']) => VBool;
-
-// @public (undocumented)
-type Bool = NodeBase & {
- type: 'bool';
- value: boolean;
-};
-
-// @public (undocumented)
-type Bool_2 = NodeBase_2 & ChainProp & {
- type: 'bool';
- value: boolean;
-};
-
-// @public (undocumented)
-const BREAK: () => Value;
-
-// @public (undocumented)
-type Break = NodeBase & {
- type: 'break';
-};
-
-// @public (undocumented)
-type Break_2 = NodeBase_2 & {
- type: 'break';
-};
-
-// @public (undocumented)
-function CALL(target: Call_2['target'], args: Call_2['args'], loc?: {
- start: number;
- end: number;
-}): Call_2;
-
-// @public (undocumented)
-type Call = NodeBase & {
- type: 'call';
- target: Expression;
- args: Expression[];
-};
-
-// @public (undocumented)
-type Call_2 = NodeBase_2 & {
- type: 'call';
- target: Expression_2;
- args: Expression_2[];
-};
-
-// @public (undocumented)
-type CallChain = NodeBase_2 & {
- type: 'callChain';
- args: Expression_2[];
-};
-
-// @public (undocumented)
-type ChainMember = CallChain | IndexChain | PropChain;
-
-// @public (undocumented)
-const CONTINUE: () => Value;
-
-// @public (undocumented)
-type Continue = NodeBase & {
- type: 'continue';
-};
-
-// @public (undocumented)
-type Continue_2 = NodeBase_2 & {
- type: 'continue';
-};
-
-declare namespace Cst {
- export {
- isStatement_2 as isStatement,
- isExpression_2 as isExpression,
- hasChainProp,
- CALL,
- INDEX,
- PROP,
- Node_3 as Node,
- Statement_2 as Statement,
- Expression_2 as Expression,
- Namespace_2 as Namespace,
- Meta_2 as Meta,
- Definition_2 as Definition,
- Attribute_2 as Attribute,
- Return_2 as Return,
- Each_2 as Each,
- For_2 as For,
- Loop_2 as Loop,
- Break_2 as Break,
- Continue_2 as Continue,
- AddAssign_2 as AddAssign,
- SubAssign_2 as SubAssign,
- Assign_2 as Assign,
- InfixOperator,
- Infix,
- Not_2 as Not,
- And_2 as And,
- Or_2 as Or,
- If_2 as If,
- Fn_2 as Fn,
- Match_2 as Match,
- Block_2 as Block,
- Exists_2 as Exists,
- Tmpl_2 as Tmpl,
- Str_2 as Str,
- Num_2 as Num,
- Bool_2 as Bool,
- Null_2 as Null,
- Obj_2 as Obj,
- Arr_2 as Arr,
- Identifier_2 as Identifier,
- ChainMember,
- CallChain,
- IndexChain,
- PropChain,
- Call_2 as Call,
- Index_2 as Index,
- Prop_2 as Prop,
- TypeSource_2 as TypeSource,
- NamedTypeSource_2 as NamedTypeSource,
- FnTypeSource_2 as FnTypeSource
- }
-}
-export { Cst }
-
-// @public (undocumented)
-type Definition = NodeBase & {
- type: 'def';
- name: string;
- varType?: TypeSource;
- expr: Expression;
- mut: boolean;
- attr: Attribute[];
-};
-
-// @public (undocumented)
-type Definition_2 = NodeBase_2 & {
- type: 'def';
- name: string;
- varType?: TypeSource_2;
- expr: Expression_2;
- mut: boolean;
- attr?: Attribute_2[];
-};
-
-// @public (undocumented)
-type Each = NodeBase & {
- type: 'each';
- var: string;
- items: Expression;
- for: Statement | Expression;
-};
-
-// @public (undocumented)
-type Each_2 = NodeBase_2 & {
- type: 'each';
- var: string;
- items: Expression_2;
- for: Statement_2 | Expression_2;
-};
-
-// @public (undocumented)
-function eq(a: Value, b: Value): boolean;
-
-declare namespace errors {
- export {
- AiScriptError,
- SyntaxError_2 as SyntaxError,
- TypeError_2 as TypeError,
- RuntimeError,
- IndexOutOfRangeError
- }
-}
-export { errors }
-
-// @public (undocumented)
-type Exists = NodeBase & {
- type: 'exists';
- identifier: Identifier;
-};
-
-// @public (undocumented)
-type Exists_2 = NodeBase_2 & ChainProp & {
- type: 'exists';
- identifier: Identifier_2;
-};
-
-// @public (undocumented)
-function expectAny(val: Value | null | undefined): asserts val is Value;
-
-// @public (undocumented)
-type Expression = If | Fn | Match | Block | Exists | Tmpl | Str | Num | Bool | Null | Obj | Arr | Not | And | Or | Identifier | Call | Index | Prop;
-
-// @public (undocumented)
-type Expression_2 = Infix | Not_2 | And_2 | Or_2 | If_2 | Fn_2 | Match_2 | Block_2 | Exists_2 | Tmpl_2 | Str_2 | Num_2 | Bool_2 | Null_2 | Obj_2 | Arr_2 | Identifier_2 | Call_2 | // IR
-Index_2 | // IR
-Prop_2;
-
-// @public (undocumented)
-const FALSE: {
- type: "bool";
- value: boolean;
-};
-
-// @public (undocumented)
-const FN: (args: VFn['args'], statements: VFn['statements'], scope: VFn['scope']) => VFn;
-
-// @public (undocumented)
-type Fn = NodeBase & {
- type: 'fn';
- args: {
- name: string;
- argType?: TypeSource;
- }[];
- retType?: TypeSource;
- children: (Statement | Expression)[];
-};
-
-// @public (undocumented)
-type Fn_2 = NodeBase_2 & ChainProp & {
- type: 'fn';
- args: {
- name: string;
- argType?: TypeSource_2;
- }[];
- retType?: TypeSource_2;
- children: (Statement_2 | Expression_2)[];
-};
-
-// @public (undocumented)
-const FN_NATIVE: (fn: VFn['native']) => VFn;
-
-// @public (undocumented)
-type FnTypeSource = NodeBase & {
- type: 'fnTypeSource';
- args: TypeSource[];
- result: TypeSource;
-};
-
-// @public (undocumented)
-type FnTypeSource_2 = NodeBase_2 & {
- type: 'fnTypeSource';
- args: TypeSource_2[];
- result: TypeSource_2;
-};
-
-// @public (undocumented)
-type For = NodeBase & {
- type: 'for';
- var?: string;
- from?: Expression;
- to?: Expression;
- times?: Expression;
- for: Statement | Expression;
-};
-
-// @public (undocumented)
-type For_2 = NodeBase_2 & {
- type: 'for';
- var?: string;
- from?: Expression_2;
- to?: Expression_2;
- times?: Expression_2;
- for: Statement_2 | Expression_2;
-};
-
-// @public (undocumented)
-function getLangVersion(input: string): string | null;
-
-// @public (undocumented)
-function hasChainProp(x: T): x is T & ChainProp;
-
-// @public (undocumented)
-type Identifier = NodeBase & {
- type: 'identifier';
- name: string;
-};
-
-// @public (undocumented)
-type Identifier_2 = NodeBase_2 & ChainProp & {
- type: 'identifier';
- name: string;
-};
-
-// @public (undocumented)
-type If = NodeBase & {
- type: 'if';
- cond: Expression;
- then: Statement | Expression;
- elseif: {
- cond: Expression;
- then: Statement | Expression;
- }[];
- else?: Statement | Expression;
-};
-
-// @public (undocumented)
-type If_2 = NodeBase_2 & {
- type: 'if';
- cond: Expression_2;
- then: Statement_2 | Expression_2;
- elseif: {
- cond: Expression_2;
- then: Statement_2 | Expression_2;
- }[];
- else?: Statement_2 | Expression_2;
-};
-
-// @public (undocumented)
-function INDEX(target: Index_2['target'], index: Index_2['index'], loc?: {
- start: number;
- end: number;
-}): Index_2;
-
-// @public (undocumented)
-type Index = NodeBase & {
- type: 'index';
- target: Expression;
- index: Expression;
-};
-
-// @public (undocumented)
-type Index_2 = NodeBase_2 & {
- type: 'index';
- target: Expression_2;
- index: Expression_2;
-};
-
-// @public (undocumented)
-type IndexChain = NodeBase_2 & {
- type: 'indexChain';
- index: Expression_2;
-};
-
-// @public (undocumented)
-class IndexOutOfRangeError extends RuntimeError {
- constructor(message: string, info?: any);
-}
-
-// @public (undocumented)
-type Infix = NodeBase_2 & {
- type: 'infix';
- operands: Expression_2[];
- operators: InfixOperator[];
-};
-
-// @public (undocumented)
-type InfixOperator = '||' | '&&' | '==' | '!=' | '<=' | '>=' | '<' | '>' | '+' | '-' | '*' | '^' | '/' | '%';
-
-// @public (undocumented)
-export class Interpreter {
- constructor(vars: Record, opts?: {
- in?(q: string): Promise;
- out?(value: Value): void;
- log?(type: string, params: Record): void;
- maxStep?: number;
- });
- // (undocumented)
- abort(): void;
- // (undocumented)
- static collectMetadata(script?: Ast.Node[]): Map | undefined;
- // (undocumented)
- exec(script?: Ast.Node[]): Promise;
- // (undocumented)
- execFn(fn: VFn, args: Value[]): Promise;
- // (undocumented)
- registerAbortHandler(handler: () => void): void;
- // (undocumented)
- scope: Scope;
- // (undocumented)
- stepCount: number;
- // (undocumented)
- unregisterAbortHandler(handler: () => void): void;
-}
-
-// @public (undocumented)
-function isArray(val: Value): val is VArr;
-
-// @public (undocumented)
-function isBoolean(val: Value): val is VBool;
-
-// @public (undocumented)
-function isExpression(x: Node_2): x is Expression;
-
-// @public (undocumented)
-function isExpression_2(x: Node_3): x is Expression_2;
-
-// @public (undocumented)
-function isFunction(val: Value): val is VFn;
-
-// @public (undocumented)
-function isNumber(val: Value): val is VNum;
-
-// @public (undocumented)
-function isObject(val: Value): val is VObj;
-
-// @public (undocumented)
-function isStatement(x: Node_2): x is Statement;
-
-// @public (undocumented)
-function isStatement_2(x: Node_3): x is Statement_2;
-
-// @public (undocumented)
-function isString(val: Value): val is VStr;
-
-// @public (undocumented)
-function jsToVal(val: any): Value;
-
-// @public
-type Loc = {
- start: number;
- end: number;
-};
-
-// @public (undocumented)
-type Loop = NodeBase & {
- type: 'loop';
- statements: (Statement | Expression)[];
-};
-
-// @public (undocumented)
-type Loop_2 = NodeBase_2 & {
- type: 'loop';
- statements: (Statement_2 | Expression_2)[];
-};
-
-// @public (undocumented)
-type Match = NodeBase & {
- type: 'match';
- about: Expression;
- qs: {
- q: Expression;
- a: Statement | Expression;
- }[];
- default?: Statement | Expression;
-};
-
-// @public (undocumented)
-type Match_2 = NodeBase_2 & ChainProp & {
- type: 'match';
- about: Expression_2;
- qs: {
- q: Expression_2;
- a: Statement_2 | Expression_2;
- }[];
- default?: Statement_2 | Expression_2;
-};
-
-// @public (undocumented)
-type Meta = NodeBase & {
- type: 'meta';
- name: string | null;
- value: Expression;
-};
-
-// @public (undocumented)
-type Meta_2 = NodeBase_2 & {
- type: 'meta';
- name: string | null;
- value: Expression_2;
-};
-
-// @public (undocumented)
-type NamedTypeSource = NodeBase & {
- type: 'namedTypeSource';
- name: string;
- inner?: TypeSource;
-};
-
-// @public (undocumented)
-type NamedTypeSource_2 = NodeBase_2 & {
- type: 'namedTypeSource';
- name: string;
- inner?: TypeSource_2;
-};
-
-// @public (undocumented)
-type Namespace = NodeBase & {
- type: 'ns';
- name: string;
- members: (Definition | Namespace)[];
-};
-
-// @public (undocumented)
-type Namespace_2 = NodeBase_2 & {
- type: 'ns';
- name: string;
- members: (Definition_2 | Namespace_2)[];
-};
-
-// @public (undocumented)
-type Node_2 = Namespace | Meta | Statement | Expression | TypeSource;
-
-// @public
-type Node_3 = Namespace_2 | Meta_2 | Statement_2 | Expression_2 | ChainMember | TypeSource_2;
-
-// @public (undocumented)
-type Not = NodeBase & {
- type: 'not';
- expr: Expression;
-};
-
-// @public (undocumented)
-type Not_2 = NodeBase_2 & {
- type: 'not';
- expr: Expression_2;
-};
-
-// @public (undocumented)
-const NULL: {
- type: "null";
-};
-
-// @public (undocumented)
-type Null = NodeBase & {
- type: 'null';
-};
-
-// @public (undocumented)
-type Null_2 = NodeBase_2 & ChainProp & {
- type: 'null';
-};
-
-// @public (undocumented)
-const NUM: (num: VNum['value']) => VNum;
-
-// @public (undocumented)
-type Num = NodeBase & {
- type: 'num';
- value: number;
-};
-
-// @public (undocumented)
-type Num_2 = NodeBase_2 & ChainProp & {
- type: 'num';
- value: number;
-};
-
-// @public (undocumented)
-const OBJ: (obj: VObj['value']) => VObj;
-
-// @public (undocumented)
-type Obj = NodeBase & {
- type: 'obj';
- value: Map;
-};
-
-// @public (undocumented)
-type Obj_2 = NodeBase_2 & ChainProp & {
- type: 'obj';
- value: Map;
-};
-
-// @public (undocumented)
-type Or = NodeBase & {
- type: 'or';
- left: Expression;
- right: Expression;
-};
-
-// @public (undocumented)
-type Or_2 = NodeBase_2 & {
- type: 'or';
- left: Expression_2;
- right: Expression_2;
-};
-
-// @public (undocumented)
-export class Parser {
- constructor();
- // (undocumented)
- addPlugin(type: PluginType, plugin: ParserPlugin): void;
- // (undocumented)
- static parse(input: string): Ast.Node[];
- // (undocumented)
- parse(input: string): Ast.Node[];
-}
-
-// @public (undocumented)
-export type ParserPlugin = (nodes: Cst.Node[]) => Cst.Node[];
-
-// @public (undocumented)
-export type PluginType = 'validate' | 'transform';
-
-// @public (undocumented)
-function PROP(target: Prop_2['target'], name: Prop_2['name'], loc?: {
- start: number;
- end: number;
-}): Prop_2;
-
-// @public (undocumented)
-type Prop = NodeBase & {
- type: 'prop';
- target: Expression;
- name: string;
-};
-
-// @public (undocumented)
-type Prop_2 = NodeBase_2 & {
- type: 'prop';
- target: Expression_2;
- name: string;
-};
-
-// @public (undocumented)
-type PropChain = NodeBase_2 & {
- type: 'propChain';
- name: string;
-};
-
-// @public (undocumented)
-function reprValue(value: Value, literalLike?: boolean, processedObjects?: Set