-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* return,break,continueをValueと別の扱いにする * 配列や引数で最初にreturnなどが出た時点でリターン * 不正な位置のreturn文などを文法エラーに * テストの追加と実装の修正 * APIレポートの更新 * break,continueがループ内に見えても関数がより内側なら文法エラー * CHANGELOG * テンプレートリテラル内returnテスト * Control系の型や関数の秘匿と名前変更 * 使用していない関数を削除 * APIレポートの更新 * APIレポートの修正
- Loading branch information
Showing
10 changed files
with
1,098 additions
and
205 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import { AiScriptRuntimeError } from '../error.js'; | ||
import type { Reference } from './reference.js'; | ||
import type { Value } from './value.js'; | ||
|
||
export type CReturn = { | ||
type: 'return'; | ||
value: Value; | ||
}; | ||
|
||
export type CBreak = { | ||
type: 'break'; | ||
value: null; | ||
}; | ||
|
||
export type CContinue = { | ||
type: 'continue'; | ||
value: null; | ||
}; | ||
|
||
export type Control = CReturn | CBreak | CContinue; | ||
|
||
// Return文で値が返されたことを示すためのラッパー | ||
export const RETURN = (v: CReturn['value']): CReturn => ({ | ||
type: 'return' as const, | ||
value: v, | ||
}); | ||
|
||
export const BREAK = (): CBreak => ({ | ||
type: 'break' as const, | ||
value: null, | ||
}); | ||
|
||
export const CONTINUE = (): CContinue => ({ | ||
type: 'continue' as const, | ||
value: null, | ||
}); | ||
|
||
export function unWrapRet(v: Value | Control): Value { | ||
switch (v.type) { | ||
case 'return': | ||
return v.value; | ||
default: { | ||
assertValue(v); | ||
return v; | ||
} | ||
} | ||
} | ||
|
||
export function assertValue(v: Value | Control): asserts v is Value { | ||
switch (v.type) { | ||
case 'return': | ||
throw new AiScriptRuntimeError('Invalid return'); | ||
case 'break': | ||
throw new AiScriptRuntimeError('Invalid break'); | ||
case 'continue': | ||
throw new AiScriptRuntimeError('Invalid continue'); | ||
default: | ||
v satisfies Value; | ||
} | ||
} | ||
|
||
export function isControl(v: Value | Control | Reference): v is Control { | ||
switch (v.type) { | ||
case 'null': | ||
case 'bool': | ||
case 'num': | ||
case 'str': | ||
case 'arr': | ||
case 'obj': | ||
case 'fn': | ||
case 'error': | ||
case 'reference': | ||
return false; | ||
case 'return': | ||
case 'break': | ||
case 'continue': | ||
return true; | ||
} | ||
// exhaustive check | ||
v satisfies never; | ||
throw new TypeError('expected value or control'); | ||
} |
Oops, something went wrong.