mirror of
https://github.com/facebookarchive/prepack.git
synced 2024-09-19 19:17:25 +03:00
Partial evaluator for block (#695)
This commit is contained in:
parent
4ac76366e9
commit
8a55a231af
@ -12,7 +12,7 @@
|
||||
import type { LexicalEnvironment } from "../environment.js";
|
||||
import type { PropertyKeyValue } from "../types.js";
|
||||
import type { Realm } from "../realm.js";
|
||||
import { ThrowCompletion, ReturnCompletion, AbruptCompletion, NormalCompletion, PossiblyNormalCompletion, IntrospectionThrowCompletion } from "../completions.js";
|
||||
import { Completion, ThrowCompletion, ReturnCompletion, AbruptCompletion, NormalCompletion, PossiblyNormalCompletion, IntrospectionThrowCompletion } from "../completions.js";
|
||||
import { ExecutionContext } from "../realm.js";
|
||||
import { GlobalEnvironmentRecord, ObjectEnvironmentRecord, Reference } from "../environment.js";
|
||||
import { Value, BoundFunctionValue, EmptyValue, FunctionValue, ObjectValue, StringValue, SymbolValue, NumberValue } from "../values/index.js";
|
||||
@ -1060,6 +1060,62 @@ export function EvaluateStatements(
|
||||
|
||||
}
|
||||
|
||||
export function PartiallyEvaluateStatements(
|
||||
body: Array<BabelNodeStatement>, blockValue: void | NormalCompletion | Value,
|
||||
strictCode: boolean, blockEnv: LexicalEnvironment, realm: Realm
|
||||
): [Completion | Value, Array<BabelNodeStatement>] {
|
||||
let statementAsts = [];
|
||||
for (let node of body) {
|
||||
if (node.type !== "FunctionDeclaration") {
|
||||
let [res, nast, nio] = blockEnv.partiallyEvaluateCompletionDeref(node, strictCode);
|
||||
for (let ioAst of nio) statementAsts.push(ioAst);
|
||||
statementAsts.push((nast: any));
|
||||
if (!(res instanceof EmptyValue)) {
|
||||
if (blockValue === undefined || blockValue instanceof Value) {
|
||||
if (res instanceof AbruptCompletion)
|
||||
return [UpdateEmpty(realm, res, blockValue || realm.intrinsics.empty), statementAsts];
|
||||
invariant(res instanceof NormalCompletion || res instanceof Value);
|
||||
blockValue = res;
|
||||
} else {
|
||||
invariant(blockValue instanceof PossiblyNormalCompletion);
|
||||
if (res instanceof AbruptCompletion) {
|
||||
let e = realm.getCapturedEffects();
|
||||
invariant(e !== undefined);
|
||||
realm.stopEffectCapture();
|
||||
let [_c, _g, b, p, _o] = e;
|
||||
_c; _g; _o;
|
||||
realm.restoreBindings(b);
|
||||
realm.restoreProperties(p);
|
||||
if (res instanceof IntrospectionThrowCompletion) {
|
||||
realm.applyEffects(e);
|
||||
throw res;
|
||||
}
|
||||
invariant(blockValue instanceof PossiblyNormalCompletion);
|
||||
e[0] = res;
|
||||
let joined_effects = joinPossiblyNormalCompletionWithAbruptCompletion(realm, blockValue, res, e);
|
||||
realm.applyEffects(joined_effects);
|
||||
let jres = joined_effects[0];
|
||||
invariant(jres instanceof Value || jres instanceof Completion);
|
||||
return [jres, statementAsts];
|
||||
} else {
|
||||
if (res instanceof Value)
|
||||
blockValue.value = res;
|
||||
else {
|
||||
invariant(blockValue instanceof PossiblyNormalCompletion);
|
||||
invariant(res instanceof PossiblyNormalCompletion);
|
||||
blockValue = composePossiblyNormalCompletions(realm, blockValue, res);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 7. Return blockValue.
|
||||
return [blockValue || realm.intrinsics.empty, statementAsts];
|
||||
|
||||
}
|
||||
|
||||
// ECMA262 9.2.5
|
||||
export function FunctionCreate(realm: Realm, kind: "normal" | "arrow" | "method", ParameterList: Array<BabelNodeLVal>, Body: BabelNodeBlockStatement, Scope: LexicalEnvironment, Strict: boolean, prototype?: ObjectValue) {
|
||||
// 1. If the prototype argument was not passed, then
|
||||
|
@ -13,13 +13,46 @@ import type { BabelNodeBlockStatement, BabelNodeStatement } from "babel-types";
|
||||
import type { Realm } from "../realm.js";
|
||||
import type { LexicalEnvironment } from "../environment.js";
|
||||
|
||||
import { AbruptCompletion } from "../completions.js";
|
||||
import { Value } from "../values/index.js";
|
||||
import { Completion, NormalCompletion } from "../completions.js";
|
||||
import { EmptyValue, StringValue, Value } from "../values/index.js";
|
||||
import { BlockDeclarationInstantiation, NewDeclarativeEnvironment, PartiallyEvaluateStatements } from "../methods/index.js";
|
||||
|
||||
import invariant from "../invariant.js";
|
||||
import * as t from "babel-types";
|
||||
|
||||
// ECMA262 13.2.13
|
||||
export default function (
|
||||
ast: BabelNodeBlockStatement, strictCode: boolean, env: LexicalEnvironment, realm: Realm
|
||||
): [AbruptCompletion | Value, BabelNodeBlockStatement, Array<BabelNodeStatement>] {
|
||||
let result = env.evaluateCompletionDeref(ast, strictCode);
|
||||
return [result, ast, []];
|
||||
): [Completion | Value, BabelNodeStatement, Array<BabelNodeStatement>] {
|
||||
// 1. Let oldEnv be the running execution context's LexicalEnvironment.
|
||||
let oldEnv = realm.getRunningContext().lexicalEnvironment;
|
||||
|
||||
// 2. Let blockEnv be NewDeclarativeEnvironment(oldEnv).
|
||||
let blockEnv = NewDeclarativeEnvironment(realm, oldEnv);
|
||||
|
||||
// 3. Perform BlockDeclarationInstantiation(StatementList, blockEnv).
|
||||
BlockDeclarationInstantiation(realm, strictCode, ast.body, blockEnv);
|
||||
|
||||
// 4. Set the running execution context's LexicalEnvironment to blockEnv.
|
||||
realm.getRunningContext().lexicalEnvironment = blockEnv;
|
||||
|
||||
try {
|
||||
// 5. Let blockValue be the result of evaluating StatementList.
|
||||
let blockValue: void | NormalCompletion | Value;
|
||||
|
||||
if (ast.directives) {
|
||||
for (let directive of (ast.directives)) {
|
||||
blockValue = new StringValue(realm, directive.value.value);
|
||||
}
|
||||
}
|
||||
|
||||
let [res, bAst] = PartiallyEvaluateStatements(ast.body, blockValue, strictCode, blockEnv, realm);
|
||||
invariant(bAst.length > 0 || res instanceof EmptyValue);
|
||||
if (bAst.length === 0) return [res, t.emptyStatement(), []];
|
||||
let rAst = t.blockStatement(bAst, ast.directives);
|
||||
return [res, rAst, []];
|
||||
} finally {
|
||||
// 6. Set the running execution context's LexicalEnvironment to oldEnv.
|
||||
realm.getRunningContext().lexicalEnvironment = oldEnv;
|
||||
}
|
||||
}
|
||||
|
1
test/residual/block.js
Normal file
1
test/residual/block.js
Normal file
@ -0,0 +1 @@
|
||||
{let __result = 1;}
|
Loading…
Reference in New Issue
Block a user