protected Completion ForInOfBodyEvaluation(IForInOfInitializer lhs, Statement stmt, IteratorRecord iteratorRecord, IterationKind iterationKind, LHSKind lhsKind, List <string> labelSet, IteratorKind?iteratorKindNullable = null)
        {
            var    iteratorKind = iteratorKindNullable.GetValueOrDefault(IteratorKind.Sync);
            var    oldEnv       = Interpreter.Instance().RunningExecutionContext().LexicalEnvironment;
            IValue V            = UndefinedValue.Instance;
            // TODO assuming destructuring is false
            bool destructuring = false;

            while (true)
            {
                var nextResultComp = iteratorRecord.NextMethod.Call(iteratorRecord.Iterator);
                if (nextResultComp.IsAbrupt())
                {
                    return(nextResultComp);
                }
                var nextResult = nextResultComp.value;
                if (iteratorKind == IteratorKind.Async)
                {
                    throw new NotImplementedException("async");
                }
                if (!(nextResult is Object nextResultObject))
                {
                    return(Completion.ThrowTypeError("iterator next did not return an object."));
                }
                var doneComp = IteratorRecord.IteratorComplete(nextResultObject);
                if (doneComp.IsAbrupt())
                {
                    return(doneComp);
                }
                var done = (doneComp.value as BooleanValue) !.boolean;
                if (done)
                {
                    return(Completion.NormalCompletion(V));
                }
                var nextValueComp = IteratorRecord.IteratorValue(nextResultObject);
                if (nextValueComp.IsAbrupt())
                {
                    return(nextValueComp);
                }
                var        nextValue = nextValueComp.value !;
                Completion lhsRef    = Completion.NormalCompletion();
                if (lhsKind == LHSKind.Assignment || lhsKind == LHSKind.VarBinding)
                {
                    if (!destructuring)
                    {
                        lhsRef = lhs.Evaluate(Interpreter.Instance());
                    }
                }
                else
                {
                    if (lhsKind != LHSKind.LexicalBinding)
                    {
                        throw new InvalidOperationException("Spec 13.7.5.13 step 6hi");
                    }
                    if (!(lhs is ForDeclaration forDeclaration))
                    {
                        throw new InvalidOperationException("Spec 13.7.5.13 step 6hii");
                    }
                    var iterationEnv = oldEnv.NewDeclarativeEnvironment();
                    forDeclaration.BindingInstantiation(iterationEnv);
                    Interpreter.Instance().RunningExecutionContext().LexicalEnvironment = iterationEnv;
                    if (!destructuring)
                    {
                        lhsRef = Interpreter.Instance().ResolveBinding(forDeclaration.name, IsStrictMode);
                    }
                }
                Completion status;
                if (!destructuring)
                {
                    if (lhsRef.IsAbrupt())
                    {
                        status = lhsRef;
                    }
                    else if (lhsKind == LHSKind.LexicalBinding)
                    {
                        status = (lhsRef.value as ReferenceValue) !.InitializeReferencedBinding(nextValue);
                    }
                    else
                    {
                        status = (lhsRef.value as ReferenceValue) !.PutValue(nextValue);
                    }
                }
                else
                {
                    throw new NotImplementedException("destructuring");
                }
                if (status.IsAbrupt())
                {
                    Interpreter.Instance().RunningExecutionContext().LexicalEnvironment = oldEnv;
                    if (iteratorKind == IteratorKind.Async)
                    {
                        throw new NotImplementedException("async");
                    }
                    if (iterationKind == IterationKind.Enumerate)
                    {
                        return(status);
                    }
                    else
                    {
                        return(iteratorRecord.IteratorClose(status));
                    }
                }
                var result = stmt.Evaluate(Interpreter.Instance());
                Interpreter.Instance().RunningExecutionContext().LexicalEnvironment = oldEnv;
                if (!LoopContinues(result, labelSet))
                {
                    if (iterationKind == IterationKind.Enumerate)
                    {
                        return(result.UpdateEmpty(V));
                    }
                    else
                    {
                        status = result.UpdateEmpty(V);
                        if (iteratorKind == IteratorKind.Async)
                        {
                            throw new NotImplementedException("async");
                        }
                        return(iteratorRecord.IteratorClose(status));
                    }
                }
                if (result.value != null)
                {
                    V = result.value;
                }
            }
        }