Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

制御構文の変更 #859

Open
wants to merge 22 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 31 additions & 18 deletions etc/aiscript.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,16 +145,20 @@ declare namespace Ast {
Statement,
Definition,
Attribute,
Return,
AddAssign,
SubAssign,
Assign,
Expression,
ControlFlow,
If,
Match,
Block,
Each,
For,
Loop,
Break,
Continue,
AddAssign,
SubAssign,
Assign,
Expression,
Return,
Plus,
Minus,
Not,
Expand All @@ -172,10 +176,7 @@ declare namespace Ast {
Neq,
And,
Or,
If,
Fn,
Match,
Block,
Exists,
Tmpl,
Str,
Expand Down Expand Up @@ -213,6 +214,7 @@ type Attribute = NodeBase & {
// @public (undocumented)
type Block = NodeBase & {
type: 'block';
label?: string;
statements: (Statement | Expression)[];
};

Expand All @@ -228,6 +230,8 @@ type Bool = NodeBase & {
// @public (undocumented)
type Break = NodeBase & {
type: 'break';
label?: string;
expr?: Expression;
};

// @public (undocumented)
Expand All @@ -240,8 +244,12 @@ type Call = NodeBase & {
// @public (undocumented)
type Continue = NodeBase & {
type: 'continue';
label?: string;
};

// @public (undocumented)
type ControlFlow = If | Match | Block | Each | For | Loop;

// @public (undocumented)
type Definition = NodeBase & {
type: 'def';
Expand All @@ -262,9 +270,10 @@ type Div = NodeBase & {
// @public (undocumented)
type Each = NodeBase & {
type: 'each';
label?: string;
var: Expression;
items: Expression;
for: Statement | Expression;
for: Block;
};

// @public (undocumented)
Expand Down Expand Up @@ -306,7 +315,7 @@ type Exists = NodeBase & {
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 | Plus | Minus | Not | Pow | Mul | Div | Rem | Add | Sub | Lt | Lteq | Gt | Gteq | Eq | Neq | And | Or | Identifier | Call | Index | Prop;
type Expression = ControlFlow | Return | Break | Continue | Fn | Exists | Tmpl | Str | Num | Bool | Null | Obj | Arr | Plus | Minus | Not | Pow | Mul | Div | Rem | Add | Sub | Lt | Lteq | Gt | Gteq | Eq | Neq | And | Or | Identifier | Call | Index | Prop;

// @public (undocumented)
const FALSE: {
Expand Down Expand Up @@ -343,11 +352,12 @@ type FnTypeSource = NodeBase & {
// @public (undocumented)
type For = NodeBase & {
type: 'for';
label?: string;
var?: string;
from?: Expression;
to?: Expression;
times?: Expression;
for: Statement | Expression;
for: Block;
};

// @public (undocumented)
Expand Down Expand Up @@ -376,13 +386,14 @@ type Identifier = NodeBase & {
// @public (undocumented)
type If = NodeBase & {
type: 'if';
label?: string;
cond: Expression;
then: Statement | Expression;
then: Block;
elseif: {
cond: Expression;
then: Statement | Expression;
then: Block;
}[];
else?: Statement | Expression;
else?: Block;
};

// @public (undocumented)
Expand Down Expand Up @@ -475,6 +486,7 @@ type Loc = {
// @public (undocumented)
type Loop = NodeBase & {
type: 'loop';
label?: string;
statements: (Statement | Expression)[];
};

Expand All @@ -495,12 +507,13 @@ type Lteq = NodeBase & {
// @public (undocumented)
type Match = NodeBase & {
type: 'match';
label?: string;
about: Expression;
qs: {
q: Expression;
a: Statement | Expression;
a: Expression;
}[];
default?: Statement | Expression;
default?: Expression;
};

// @public (undocumented)
Expand Down Expand Up @@ -651,7 +664,7 @@ function reprValue(value: Value, literalLike?: boolean, processedObjects?: Set<o
// @public (undocumented)
type Return = NodeBase & {
type: 'return';
expr: Expression;
expr?: Expression;
};

// @public (undocumented)
Expand Down Expand Up @@ -681,7 +694,7 @@ export class Scope {
}

// @public (undocumented)
type Statement = Definition | Return | Each | For | Loop | Break | Continue | Assign | AddAssign | SubAssign;
type Statement = Definition | Assign | AddAssign | SubAssign;

// @public (undocumented)
const STR: (str: VStr["value"]) => VStr;
Expand Down
34 changes: 29 additions & 5 deletions src/interpreter/control.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { AiScriptRuntimeError } from '../error.js';
import { NULL, type Value } from './value.js';

Check warning on line 2 in src/interpreter/control.ts

View workflow job for this annotation

GitHub Actions / lint

'NULL' is defined but never used. Allowed unused vars must match /^_/u
import type { Reference } from './reference.js';
import type { Value } from './value.js';

export type CReturn = {
type: 'return';
Expand All @@ -9,11 +9,13 @@

export type CBreak = {
type: 'break';
value: null;
label?: string;
value: Value;
};

export type CContinue = {
type: 'continue';
label?: string;
value: null;
};

Expand All @@ -25,13 +27,15 @@
value: v,
});

export const BREAK = (): CBreak => ({
export const BREAK = (v: CBreak['value'], label?: string): CBreak => ({
type: 'break' as const,
value: null,
label,
value: v,
});

export const CONTINUE = (): CContinue => ({
export const CONTINUE = (label?: string): CContinue => ({
type: 'continue' as const,
label,
value: null,
});

Expand All @@ -46,6 +50,26 @@
}
}

/**
* 値がbreakで、ラベルが指定されていないまたは一致する場合のみ、その中身を取り出します。
*/
export function unWrapBreak(v: Value | Control, label: string | undefined): Value | Control {
if (v.type === 'break' && (v.label == null || v.label === label)) {
return v.value;
}
return v;
}

/**
* 値がbreakで、ラベルが一致する場合のみ、その中身を取り出します。
*/
export function unWrapLabeledBreak(v: Value | Control, label: string | undefined): Value | Control {
if (v.type === 'break' && v.label != null && v.label === label) {
return v.value;
}
return v;
}

export function assertValue(v: Value | Control): asserts v is Value {
switch (v.type) {
case 'return':
Expand Down
Loading
Loading