Skip to content

Instantly share code, notes, and snippets.

@TimothyGu
Created September 25, 2018 08:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TimothyGu/93a41838d1f069ab312f131785ae65be to your computer and use it in GitHub Desktop.
Save TimothyGu/93a41838d1f069ab312f131785ae65be to your computer and use it in GitHub Desktop.
From adafabcd57702bd2a73207962f81bdc94d5278de Mon Sep 17 00:00:00 2001
From: Timothy Gu <timothygu99@gmail.com>
Date: Tue, 25 Sep 2018 00:01:16 -0700
Subject: [PATCH] for-in loop
engine262/src/runtime-semantics/ForStatement.mjs
149:7 error 'BindingInstantiation_ForDeclaration' is not defined no-undef
169:18 error 'DestructuringAssignmentEvaluation_AssignmentPattern' is not defined no-undef
---
src/ast.mjs | 45 ++++-
src/evaluator.mjs | 13 +-
src/runtime-semantics/BindingInitialization.mjs | 23 +++
src/runtime-semantics/BlockStatement.mjs | 4 +-
src/runtime-semantics/BreakableStatement.mjs | 60 ++++++
src/runtime-semantics/EvaluateBody.mjs | 14 +-
src/runtime-semantics/ForStatement.mjs | 242 +++++++++++++++++++++---
src/runtime-semantics/all.mjs | 3 +-
src/static-semantics/IsDestructuring.mjs | 26 +++
src/static-semantics/all.mjs | 1 +
10 files changed, 388 insertions(+), 43 deletions(-)
create mode 100644 src/runtime-semantics/BreakableStatement.mjs
create mode 100644 src/static-semantics/IsDestructuring.mjs
diff --git a/src/ast.mjs b/src/ast.mjs
index 7169a50..665bf7b 100644
--- a/src/ast.mjs
+++ b/src/ast.mjs
@@ -591,24 +591,62 @@ export function isIterationStatement(node) {
|| node.type === 'ForOfStatement';
}
+// Used in #prod-IterationStatement
+export function isDoWhileStatement(node) {
+ return node.type === 'DoWhileStatement';
+}
+
+// Used in #prod-IterationStatement
+export function isWhileStatement(node) {
+ return node.type === 'WhileStatement';
+}
+
+// Used in #prod-IterationStatement
export function isForStatement(node) {
return node.type === 'ForStatement';
}
+// Used in #prod-IterationStatement
export function isForStatementWithExpression(node) {
return isForStatement(node) && isExpression(node.init);
}
+// Used in #prod-IterationStatement
export function isForStatementWithVariableStatement(node) {
return isForStatement(node) && isVariableStatement(node.init);
}
+// Used in #prod-IterationStatement
export function isForStatementWithLexicalDeclaration(node) {
return isForStatement(node) && isLexicalDeclaration(node.init);
}
-export function isForBinding() {
- return false;
+// Used in #prod-IterationStatement
+export function isForInStatement(node) {
+ return node.type === 'ForInStatement';
+}
+
+// Used in #prod-IterationStatement
+// This covers cases like for ({ a } of b), in which case the { a } is in fact
+// parsed as an ObjectLiteral per spec.
+export function isForInStatementWithExpression(node) {
+ return isForInStatement(node) && node.left.type !== 'VariableDeclaration';
+}
+
+// Used in #prod-IterationStatement
+export function isForInStatementWithVarForBinding(node) {
+ return isForInStatement(node) && isVariableStatement(node.left)
+ && !node.left.declarations[0].init;
+}
+
+// Used in #prod-IterationStatement
+export function isForInStatementWithForDeclaration(node) {
+ return isForInStatement(node) && isForDeclaration(node.left);
+}
+
+// #prod-ForBinding
+export function isForBinding(node) {
+ return isBindingIdentifier(node) || isBindingPattern(node);
}
// #prod-SwitchStatement
@@ -740,6 +778,9 @@ export function isLexicalDeclaration(node) {
return node.type === 'VariableDeclaration' && (node.kind === 'let' || node.kind === 'const');
}
+// #prod-ForDeclaration
+export const isForDeclaration = isLexicalDeclaration;
+
// #prod-LexicalBinding
export function isLexicalBinding(node) {
return node.type === 'VariableDeclarator';
diff --git a/src/evaluator.mjs b/src/evaluator.mjs
index 58adb24..df5be2b 100644
--- a/src/evaluator.mjs
+++ b/src/evaluator.mjs
@@ -27,9 +27,9 @@ import {
isArrowFunction,
isBlockStatement,
isBreakStatement,
+ isBreakableStatement,
isExpressionStatement,
isExpressionWithComma,
- isForStatement,
isFunctionDeclaration,
isFunctionExpression,
isIdentifierReference,
@@ -39,7 +39,6 @@ import {
isLiteral,
isObjectLiteral,
isReturnStatement,
- isSwitchStatement,
isTemplateLiteral,
isThis,
isThrowStatement,
@@ -63,12 +62,12 @@ import {
Evaluate_BinaryBitwiseExpression,
Evaluate_BlockStatement,
Evaluate_BreakStatement,
+ Evaluate_BreakableStatement,
Evaluate_CallExpression,
Evaluate_ConditionalExpression,
Evaluate_EqualityExpression,
Evaluate_ExponentiationExpression,
Evaluate_ExpressionWithComma,
- Evaluate_ForStatement,
Evaluate_FunctionDeclaration,
Evaluate_FunctionExpression,
Evaluate_Identifier,
@@ -84,7 +83,6 @@ import {
Evaluate_RelationalExpression,
Evaluate_ReturnStatement,
Evaluate_ShiftExpression,
- Evaluate_SwitchStatement,
Evaluate_TemplateLiteral,
Evaluate_ThisExpression,
Evaluate_ThrowStatement,
@@ -155,8 +153,8 @@ function Evaluate_StatementListItem(StatementListItem) {
case isIfStatement(StatementListItem):
return Evaluate_IfStatement(StatementListItem);
- case isForStatement(StatementListItem):
- return Evaluate_ForStatement(StatementListItem);
+ case isBreakableStatement(StatementListItem):
+ return Evaluate_BreakableStatement(StatementListItem);
// case isContinueStatement(StatementListItem):
// return Evaluate_ContinueStatement(StatementListItem);
@@ -170,9 +168,6 @@ function Evaluate_StatementListItem(StatementListItem) {
case isWithStatement(StatementListItem):
return Evaluate_WithStatement(StatementListItem);
- case isSwitchStatement(StatementListItem):
- return Evaluate_SwitchStatement(StatementListItem);
-
case isThrowStatement(StatementListItem):
return Evaluate_ThrowStatement(StatementListItem.argument);
diff --git a/src/runtime-semantics/BindingInitialization.mjs b/src/runtime-semantics/BindingInitialization.mjs
index 6dd664c..601fff5 100644
--- a/src/runtime-semantics/BindingInitialization.mjs
+++ b/src/runtime-semantics/BindingInitialization.mjs
@@ -77,6 +77,23 @@ export function BindingInitialization_BindingPattern(BindingPattern, value, envi
}
}
+// (implicit)
+// ForBinding :
+// BindingIdentifier
+// BindingPattern
+export function BindingInitialization_ForBinding(ForBinding, value, environment) {
+ switch (true) {
+ case isBindingIdentifier(ForBinding):
+ return BindingInitialization_BindingIdentifier(ForBinding, value, environment);
+
+ case isBindingPattern(ForBinding):
+ return BindingInitialization_BindingPattern(ForBinding, value, environment);
+
+ default:
+ throw outOfRange('BindingInitialization_ForBinding', ForBinding);
+ }
+}
+
// #sec-destructuring-binding-patterns-runtime-semantics-bindinginitialization
// ObjectBindingPattern :
// `{` `}`
@@ -121,3 +138,9 @@ export function BindingInitialization_CatchParameter(CatchParameter, value, envi
throw outOfRange('BindingInitialization_CatchParameter', CatchParameter);
}
}
+
+// #sec-for-in-and-for-of-statements-runtime-semantics-bindinginitialization
+// ForDeclaration : LetOrConst ForBinding
+export function BindingInitialization_ForDeclaration(ForDeclaration, value, environment) {
+ return BindingInitialization_ForBinding(ForDeclaration.declarations[0].id, value, environment);
+}
diff --git a/src/runtime-semantics/BlockStatement.mjs b/src/runtime-semantics/BlockStatement.mjs
index d755831..1212ef0 100644
--- a/src/runtime-semantics/BlockStatement.mjs
+++ b/src/runtime-semantics/BlockStatement.mjs
@@ -39,9 +39,9 @@ export function BlockDeclarationInstantiation(code, env) {
for (const d of declarations) {
for (const dn of BoundNames_Declaration(d).map(NewValue)) {
if (IsConstantDeclaration(d)) {
- X(envRec.CreateImmutableBinding(dn, NewValue(true)));
+ X(envRec.CreateImmutableBinding(dn, true));
} else {
- X(envRec.CreateMutableBinding(dn, NewValue(false)));
+ X(envRec.CreateMutableBinding(dn, false));
}
if (isFunctionDeclaration(d) || isGeneratorDeclaration(d)
|| isAsyncFunctionDeclaration(d) || isAsyncGeneratorDeclaration(d)) {
diff --git a/src/runtime-semantics/BreakableStatement.mjs b/src/runtime-semantics/BreakableStatement.mjs
new file mode 100644
index 0000000..4fd2e92
--- /dev/null
+++ b/src/runtime-semantics/BreakableStatement.mjs
@@ -0,0 +1,60 @@
+import {
+ isIterationStatement,
+ isSwitchStatement,
+} from '../ast.mjs';
+import {
+ Completion,
+ NormalCompletion,
+} from '../completion.mjs';
+import { outOfRange } from '../helpers.mjs';
+import { New as NewValue } from '../value.mjs';
+import {
+ Evaluate_SwitchStatement,
+ LabelledEvaluation_IterationStatement,
+} from './all.mjs';
+
+// #sec-statement-semantics-runtime-semantics-evaluation
+// BreakableStatement :
+// IterationStatement
+// SwitchStatement
+export function Evaluate_BreakableStatement(BreakableStatement) {
+ const newLabelSet = [];
+ return LabelledEvaluation_BreakableStatement(BreakableStatement, newLabelSet);
+}
+
+// #sec-statement-semantics-runtime-semantics-labelledevaluation
+// BreakableStatement : IterationStatement
+function LabelledEvaluation_BreakableStatement(BreakableStatement, labelSet) {
+ switch (true) {
+ case isIterationStatement(BreakableStatement): {
+ let stmtResult = LabelledEvaluation_IterationStatement(BreakableStatement, labelSet);
+ if (stmtResult.Type === 'break') {
+ if (stmtResult.Target === undefined) {
+ if (stmtResult.Value === undefined) {
+ stmtResult = new NormalCompletion(NewValue(undefined));
+ } else {
+ stmtResult = new NormalCompletion(stmtResult.Value);
+ }
+ }
+ }
+ return Completion(stmtResult);
+ }
+
+ case isSwitchStatement(BreakableStatement): {
+ let stmtResult = Evaluate_SwitchStatement(BreakableStatement, labelSet);
+ if (stmtResult.Type === 'break') {
+ if (stmtResult.Target === undefined) {
+ if (stmtResult.Value === undefined) {
+ stmtResult = new NormalCompletion(NewValue(undefined));
+ } else {
+ stmtResult = new NormalCompletion(stmtResult.Value);
+ }
+ }
+ }
+ return Completion(stmtResult);
+ }
+
+ default:
+ throw outOfRange('LabelledEvaluation_BreakableStatement', BreakableStatement);
+ }
+}
diff --git a/src/runtime-semantics/EvaluateBody.mjs b/src/runtime-semantics/EvaluateBody.mjs
index ed4d6a3..fd8918d 100644
--- a/src/runtime-semantics/EvaluateBody.mjs
+++ b/src/runtime-semantics/EvaluateBody.mjs
@@ -105,7 +105,7 @@ export function FunctionDeclarationInstantiation(func, argumentsList) {
for (const paramName of parameterNames) {
const alreadyDeclared = envRec.HasBinding(paramName);
if (alreadyDeclared.isFalse()) {
- X(envRec.CreateMutableBinding(paramName, NewValue(false)));
+ X(envRec.CreateMutableBinding(paramName, false));
if (hasDuplicates === true) {
X(envRec.InitializeBinding(paramName, NewValue(undefined)));
}
@@ -121,9 +121,9 @@ export function FunctionDeclarationInstantiation(func, argumentsList) {
ao = CreateMappedArgumentsObject(func, formals, argumentsList, envRec);
}
if (strict) {
- X(envRec.CreateImmutableBinding(NewValue('arguments'), NewValue(false)));
+ X(envRec.CreateImmutableBinding(NewValue('arguments'), false));
} else {
- X(envRec.CreateMutableBinding(NewValue('arguments'), NewValue(false)));
+ X(envRec.CreateMutableBinding(NewValue('arguments'), false));
}
envRec.InitializeBinding(NewValue('arguments'), ao);
parameterBindings = [...parameterNames, NewValue('arguments')];
@@ -145,7 +145,7 @@ export function FunctionDeclarationInstantiation(func, argumentsList) {
for (const n of varNames) {
if (!instantiatedVarNames.includes(n)) {
instantiatedVarNames.push(n);
- X(envRec.CreateMutableBinding(n, NewValue(false)));
+ X(envRec.CreateMutableBinding(n, false));
envRec.InitializeBinding(n, NewValue(undefined));
}
}
@@ -159,7 +159,7 @@ export function FunctionDeclarationInstantiation(func, argumentsList) {
for (const n of varNames) {
if (!instantiatedVarNames.includes(n)) {
instantiatedVarNames.push(n);
- X(varEnvRec.CreateMutableBinding(n, NewValue(false)));
+ X(varEnvRec.CreateMutableBinding(n, false));
let initialValue;
if (!parameterBindings.includes(n) || functionNames.includes(n)) {
initialValue = NewValue(undefined);
@@ -190,9 +190,9 @@ export function FunctionDeclarationInstantiation(func, argumentsList) {
for (const d of lexDeclarations) {
for (const dn of BoundNames_LexicalDeclaration.map(NewValue)) {
if (IsConstantDeclaration(d)) {
- X(lexEnvRec.CreateImmutableBinding(dn, NewValue(true)));
+ X(lexEnvRec.CreateImmutableBinding(dn, true));
} else {
- X(lexEnvRec.CreateMutableBinding(dn, NewValue(false)));
+ X(lexEnvRec.CreateMutableBinding(dn, false));
}
}
}
diff --git a/src/runtime-semantics/ForStatement.mjs b/src/runtime-semantics/ForStatement.mjs
index 5d66882..8ef3a27 100644
--- a/src/runtime-semantics/ForStatement.mjs
+++ b/src/runtime-semantics/ForStatement.mjs
@@ -2,14 +2,23 @@ import { surroundingAgent } from '../engine.mjs';
import { Type, New as NewValue } from '../value.mjs';
import {
Assert,
+ Call,
+ GetIterator,
GetValue,
- ToBoolean,
+ IteratorClose,
+ IteratorValue,
LoopContinues,
+ PutValue,
+ ToBoolean,
+ ToObject,
+ ResolveBinding,
+ InitializeReferencedBinding,
} from '../abstract-ops/all.mjs';
import {
Q, X, ReturnIfAbrupt,
Completion,
AbruptCompletion,
+ BreakCompletion,
NormalCompletion,
UpdateEmpty,
} from '../completion.mjs';
@@ -17,11 +26,23 @@ import {
isForStatementWithExpression,
isForStatementWithVariableStatement,
isForStatementWithLexicalDeclaration,
+ isForInStatementWithExpression,
+ isForInStatementWithForDeclaration,
+ isForInStatementWithVarForBinding,
+ isForDeclaration,
+ isForBinding,
} from '../ast.mjs';
import {
IsConstantDeclaration,
BoundNames_LexicalDeclaration,
+ BoundNames_ForDeclaration,
+ IsDestructuring_ForDeclaration,
+ IsDestructuring_ForBinding,
} from '../static-semantics/all.mjs';
+import {
+ BindingInitialization_ForBinding,
+ BindingInitialization_ForDeclaration,
+} from './all.mjs';
import { Evaluate_Expression, Evaluate_Statement } from '../evaluator.mjs';
import { NewDeclarativeEnvironment } from '../environment.mjs';
import { outOfRange } from '../helpers.mjs';
@@ -36,7 +57,7 @@ function CreatePerIterationEnvironment(perIterationBindings) {
const thisIterationEnv = NewDeclarativeEnvironment(outer);
const thisIterationEnvRec = thisIterationEnv.EnvironmentRecord;
for (const bn of perIterationBindings) {
- X(thisIterationEnvRec.CreateMutableBinding(bn, NewValue(false)));
+ X(thisIterationEnvRec.CreateMutableBinding(bn, false));
const lastValue = Q(lastIterationEnvRec.GetBindingValue(bn, NewValue(true)));
thisIterationEnvRec.InitializeBinding(bn, lastValue);
}
@@ -72,49 +93,226 @@ function ForBodyEvaluation(test, increment, stmt, perIterationBindings, labelSet
}
}
+function ForInOfHeadEvaluation(TDZnames, expr, iterationKind) {
+ const oldEnv = surroundingAgent.runningExecutionContext.LexicalEnvironment;
+ if (TDZnames.length > 0) {
+ Assert(new Set(TDZnames).size === TDZnames.length);
+ const TDZ = NewDeclarativeEnvironment(oldEnv);
+ const TDZEnvRec = TDZ.EnvironmentRecord;
+ for (const name of TDZnames) {
+ X(TDZEnvRec.CreateMutableBinding(name, false));
+ }
+ surroundingAgent.runningExecutionContext.LexicalEnvironment = TDZ;
+ }
+ const exprRef = Evaluate_Expression(expr);
+ surroundingAgent.runningExecutionContext.LexicalEnvironment = oldEnv;
+ const exprValue = Q(GetValue(exprRef));
+ if (iterationKind === 'enumerate') {
+ if (Type(exprValue) === 'Undefined' || Type(exprValue) === 'Null') {
+ return new BreakCompletion(undefined);
+ }
+ const obj = X(ToObject(exprValue));
+ return Q(EnumerateObjectProperties(obj));
+ } else {
+ Assert(iterationKind === 'iterate' || iterationKind === 'async-iterate');
+ const iteratorHint = iterationKind === 'async-iterate' ? 'async' : 'hint';
+ return Q(GetIterator(exprValue, iteratorHint));
+ }
+}
+
+function ForInOfBodyEvaluation(lhs, stmt, iteratorRecord, iterationKind, lhsKind, labelSet/* , iteratorKind = 'sync' */) {
+ const oldEnv = surroundingAgent.runningExecutionContext.LexicalEnvironment;
+ let V = NewValue(undefined);
+ const destructuring = lhs.type === 'VariableDeclaration'
+ ? IsDestructuring_ForDeclaration(lhs) : IsDestructuring_ForBinding(lhs);
+ let assignmentPattern;
+ if (destructuring && lhsKind === 'assignment') {
+ assignmentPattern = lhs;
+ }
+ while (true) {
+ const nextResult = Q(Call(iteratorRecord.NextMethod, iteratorRecord.Iterator, []));
+ // if (iteratorKind === 'async')
+ if (Type(nextResult) !== 'Object') {
+ return surroundingAgent.Throw('TypeError');
+ }
+ const nextValue = Q(IteratorValue(nextResult));
+ let iterationEnv;
+ let lhsRef;
+ if (lhsKind === 'assignment' || lhsKind === 'varBinding') {
+ if (!destructuring) {
+ lhsRef = Evaluate_Expression(lhs);
+ }
+ } else {
+ Assert(lhsKind === 'lexicalBinding');
+ Assert(isForDeclaration(lhs));
+ iterationEnv = NewDeclarativeEnvironment(oldEnv);
+ BindingInstantiation_ForDeclaration(lhs, iterationEnv);
+ surroundingAgent.runningExecutionContext.LexicalEnvironment = iterationEnv;
+ if (!destructuring) {
+ const lhsNames = BoundNames_ForDeclaration(lhs);
+ Assert(lhsNames.length === 1);
+ const [lhsName] = lhsNames;
+ lhsRef = X(ResolveBinding(lhsName));
+ }
+ }
+ let status;
+ if (!destructuring) {
+ if (lhsRef instanceof AbruptCompletion) {
+ status = lhsRef;
+ } else if (lhsKind === 'lexicalBinding') {
+ status = InitializeReferencedBinding(lhsRef, nextValue);
+ } else {
+ status = PutValue(lhsRef, nextValue);
+ }
+ } else {
+ if (lhsKind === 'assignment') {
+ status = DestructuringAssignmentEvaluation_AssignmentPattern(assignmentPattern, nextValue);
+ } else if (lhsKind === 'varBinding') {
+ Assert(isForBinding(lhs));
+ status = BindingInitialization_ForBinding(lhs, nextValue, NewValue(undefined));
+ } else {
+ Assert(lhsKind === 'lexicalBinding');
+ Assert(isForDeclaration(lhs));
+ status = BindingInitialization_ForDeclaration(lhs, nextValue, iterationEnv);
+ }
+ }
+ if (status instanceof AbruptCompletion) {
+ surroundingAgent.runningExecutionContext.LexicalEnvironment = oldEnv;
+ // if (iteratorKind === 'async') {
+ // return Q(AsyncIteratorClose(iteratorRecord, status));
+ // }
+ if (iterationKind === 'enumerate') {
+ return status;
+ } else {
+ Assert(iterationKind === 'iterate');
+ return Q(IteratorClose(iteratorRecord, status));
+ }
+ }
+ const result = Evaluate_Statement(stmt);
+ surroundingAgent.runningExecutionContext.LexicalEnvironment = oldEnv;
+ if (LoopContinues(result, labelSet).isFalse()) {
+ if (iterationKind === 'enumerate') {
+ return Completion(UpdateEmpty(result, V));
+ } else {
+ Assert(iterationKind === 'iterate');
+ status = UpdateEmpty(result, V);
+ // if (iteratorKind === 'async') {
+ // return Q(AsyncIteratorClose(iteratorRecord, status));
+ // }
+ return Q(IteratorClose(iteratorRecord, status));
+ }
+ }
+ if (result.Value !== undefined) {
+ V = result.Value;
+ }
+ }
+}
+
+// #sec-do-while-statement-runtime-semantics-labelledevaluation
+// IterationStatement : `do` Statement `while` `(` Expression `)` `;`
+//
+// #sec-while-statement-runtime-semantics-labelledevaluation
+// IterationStatement : `while` `(` Expression `)` Statement
+//
// #sec-for-statement-runtime-semantics-labelledevaluation
-// IterationStatement :
-// `for` `(` Expression `;` Expression `;` Expression `)` Statement
-// `for` `(` `var` VariableDeclarationList `;` Expression `;` Expression `)` Statement
-// `for` `(` LexicalDeclarationExpression `;` Expression `)` Statement
-export function Evaluate_ForStatement(ForStatement, labelSet = []) {
+// IterationStatement :
+// `for` `(` Expression `;` Expression `;` Expression `)` Statement
+// `for` `(` `var` VariableDeclarationList `;` Expression `;` Expression `)` Statement
+// `for` `(` LexicalDeclarationExpression `;` Expression `)` Statement
+//
+// #sec-for-in-and-for-of-statements-runtime-semantics-labelledevaluation
+// IterationStatement :
+// `for` `(` LeftHandSideExpression `in` Expression `)` Statement
+// `for` `(` `var` ForBinding `in` Expression `)` Statement
+// `for` `(` ForDeclaration `in` Expression `)` Statement
+// `for` `(` LeftHandSideExpression `of` AssignmentExpression `)` Statement
+// `for` `(` `var` ForBinding `of` AssignmentExpression `)` Statement
+// `for` `(` ForDeclaration `of` AssignmentExpression `)` Statement
+// `for` `await` `(` LeftHandSideExpression `of` AssignmentExpression `)` Statement
+// `for` `await` `(` `var` ForBinding `of` AssignmentExpression `)` Statement
+// `for` `await` `(` ForDeclaration `of` AssignmentExpression `)` Statement
+export function LabelledEvaluation_IterationStatement(IterationStatement, labelSet) {
switch (true) {
- case isForStatementWithExpression(ForStatement):
- if (ForStatement.init) {
- const exprRef = Evaluate_Expression(ForStatement.init);
+ // case isDoWhileStatement(IterationStatement):
+
+ // case isWhileStatement(IterationStatement):
+
+ case isForStatementWithExpression(IterationStatement):
+ if (IterationStatement.init) {
+ const exprRef = Evaluate_Expression(IterationStatement.init);
Q(GetValue(exprRef));
}
- return Q(ForBodyEvaluation(ForStatement.test, ForStatement.update, ForStatement.body, [], labelSet));
- case isForStatementWithVariableStatement(ForStatement): {
- let varDcl = Evaluate_Statement(ForStatement.init);
+ return Q(ForBodyEvaluation(IterationStatement.test, IterationStatement.update, IterationStatement.body, [], labelSet));
+
+ case isForStatementWithVariableStatement(IterationStatement): {
+ let varDcl = Evaluate_Statement(IterationStatement.init);
ReturnIfAbrupt(varDcl);
- return Q(ForBodyEvaluation(ForStatement.test, ForStatement.update, ForStatement.body, [], labelSet));
+ return Q(ForBodyEvaluation(IterationStatement.test, IterationStatement.update, IterationStatement.body, [], labelSet));
}
- case isForStatementWithLexicalDeclaration(ForStatement): {
+
+ case isForStatementWithLexicalDeclaration(IterationStatement): {
const oldEnv = surroundingAgent.runningExecutionContext.LexicalEnvironment;
const loopEnv = NewDeclarativeEnvironment(oldEnv);
const loopEnvRec = loopEnv.EnvironmentRecord;
- const isConst = IsConstantDeclaration(ForStatement.init);
- const boundNames = BoundNames_LexicalDeclaration(ForStatement.init).map(NewValue);
+ const isConst = IsConstantDeclaration(IterationStatement.init);
+ const boundNames = BoundNames_LexicalDeclaration(IterationStatement.init).map(NewValue);
for (const dn of boundNames) {
if (isConst) {
- X(loopEnvRec.CreateImmutableBinding(dn, NewValue(true)));
+ X(loopEnvRec.CreateImmutableBinding(dn, true));
} else {
- X(loopEnvRec.CreateMutableBinding(dn, NewValue(true)));
+ X(loopEnvRec.CreateMutableBinding(dn, true));
}
}
surroundingAgent.runningExecutionContext.LexicalEnvironment = loopEnv;
- const forDcl = Evaluate_Statement(ForStatement.init);
+ const forDcl = Evaluate_Statement(IterationStatement.init);
if (forDcl instanceof AbruptCompletion) {
surroundingAgent.runningExecutionContext.LexicalEnvironment = oldEnv;
return Completion(forDcl);
}
const perIterationLets = isConst ? [] : boundNames;
- const bodyResult = ForBodyEvaluation(ForStatement.test, ForStatement.update, ForStatement.body, perIterationLets, labelSet);
+ const bodyResult = ForBodyEvaluation(IterationStatement.test, IterationStatement.update, IterationStatement.body, perIterationLets, labelSet);
surroundingAgent.runningExecutionContext.LexicalEnvironment = oldEnv;
return Completion(bodyResult);
}
+
+ case isForInStatementWithExpression(IterationStatement): {
+ const {
+ left: LeftHandSideExpression,
+ right: Expression,
+ body: Statement,
+ } = IterationStatement;
+ const keyResult = Q(ForInOfHeadEvaluation([], Expression, 'enumerate'));
+ return Q(ForInOfBodyEvaluation(LeftHandSideExpression, Statement, keyResult, 'enumerate', 'assignment', labelSet));
+ }
+
+ case isForInStatementWithVarForBinding(IterationStatement): {
+ const {
+ left: {
+ declarations: [{ id: ForBinding }],
+ },
+ right: Expression,
+ body: Statement,
+ } = IterationStatement;
+ const keyResult = Q(ForInOfHeadEvaluation([], Expression, 'enumerate'));
+ return Q(ForInOfBodyEvaluation(ForBinding, Statement, keyResult, 'enumerate', 'varBinding', labelSet));
+ }
+
+ case isForInStatementWithForDeclaration(IterationStatement): {
+ const {
+ left: ForDeclaration,
+ right: Expression,
+ body: Statement,
+ } = IterationStatement;
+ const keyResult = Q(ForInOfHeadEvaluation(BoundNames_ForDeclaration(ForDeclaration), Expression, 'enumerate'));
+ return Q(ForInOfBodyEvaluation(ForDeclaration, Statement, keyResult, 'enumerate', 'lexicalBinding', labelSet));
+ }
+
default:
- throw outOfRange('Evaluate_ForStatement', ForStatement);
+ throw outOfRange('LabelledEvaluation_IterationStatement', IterationStatement);
}
}
+
+// #sec-enumerate-object-properties
+function EnumerateObjectProperties(O) {
+ Assert(Type(O) === 'Object');
+}
diff --git a/src/runtime-semantics/all.mjs b/src/runtime-semantics/all.mjs
index e865edf..a0d193a 100644
--- a/src/runtime-semantics/all.mjs
+++ b/src/runtime-semantics/all.mjs
@@ -7,6 +7,7 @@ export * from './BindingInitialization.mjs';
export * from './BitwiseOperators.mjs';
export * from './BlockStatement.mjs';
export * from './BreakStatement.mjs';
+export * from './BreakableStatement.mjs';
export * from './CallExpression.mjs';
export * from './ConditionalExpression.mjs';
export * from './EqualityExpression.mjs';
@@ -33,8 +34,8 @@ export * from './NewExpression.mjs';
export * from './ObjectLiteral.mjs';
export * from './PropertyBindingInitialization.mjs';
export * from './RelationalOperators.mjs';
-export * from './ReturnStatement.mjs';
export * from './RestBindingInitialization.mjs';
+export * from './ReturnStatement.mjs';
export * from './ShiftExpression.mjs';
export * from './SwitchStatement.mjs';
export * from './TemplateLiteral.mjs';
diff --git a/src/static-semantics/IsDestructuring.mjs b/src/static-semantics/IsDestructuring.mjs
new file mode 100644
index 0000000..cc0387e
--- /dev/null
+++ b/src/static-semantics/IsDestructuring.mjs
@@ -0,0 +1,26 @@
+import { outOfRange } from '../helpers.mjs';
+import {
+ isBindingIdentifier,
+ isBindingPattern,
+} from '../ast.mjs';
+
+// #sec-for-in-and-for-of-statements-static-semantics-isdestructuring
+// ForDeclaration : LetOrConst ForBinding
+export function IsDestructuring_ForDeclaration(ForDeclaration) {
+ return IsDestructuring_ForBinding(ForDeclaration.declarations[0].id);
+}
+
+// #sec-for-in-and-for-of-statements-static-semantics-isdestructuring
+// ForBinding :
+// BindingIdentifier
+// BindingPattern
+export function IsDestructuring_ForBinding(ForBinding) {
+ switch (true) {
+ case isBindingIdentifier(ForBinding):
+ return false;
+ case isBindingPattern(ForBinding):
+ return true;
+ default:
+ throw outOfRange('IsDestructuring_ForBinding', ForBinding);
+ }
+}
diff --git a/src/static-semantics/all.mjs b/src/static-semantics/all.mjs
index e6a825c..80ae6f7 100644
--- a/src/static-semantics/all.mjs
+++ b/src/static-semantics/all.mjs
@@ -4,6 +4,7 @@ export * from './ContainsUseStrict.mjs';
export * from './DeclarationPart.mjs';
export * from './ExpectedArgumentCount.mjs';
export * from './HasInitializer.mjs';
+export * from './IsDestructuring.mjs';
export * from './LexicallyDeclaredNames.mjs';
export * from './LexicallyScopedDeclarations.mjs';
export * from './TopLevelLexicallyDeclaredNames.mjs';
--
2.11.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment