/// <inheritdoc /> protected override async Task <Result <Unit, IError> > Run( IStateMonad stateMonad, CancellationToken cancellationToken) { var variableName = VariableName.Index; var from = await From.Run(stateMonad, cancellationToken); if (from.IsFailure) { return(from.ConvertFailure <Unit>()); } var to = await To.Run(stateMonad, cancellationToken); if (to.IsFailure) { return(to.ConvertFailure <Unit>()); } var increment = await Increment.Run(stateMonad, cancellationToken); if (increment.IsFailure) { return(increment.ConvertFailure <Unit>()); } var currentValue = from.Value; var setResult = await stateMonad.SetVariableAsync(variableName, currentValue, false, this); if (setResult.IsFailure) { return(setResult.ConvertFailure <Unit>()); } if (increment.Value == 0) { return(new SingleError(new ErrorLocation(this), ErrorCode.DivideByZero)); } while (increment.Value > 0 ? currentValue <= to.Value : currentValue >= to.Value) { var r = await Action.Run(stateMonad, cancellationToken); if (r.IsFailure) { return(r); } var currentValueResult = stateMonad.GetVariable <int>(variableName) .MapError(e => e.WithLocation(this)); if (currentValueResult.IsFailure) { return(currentValueResult.ConvertFailure <Unit>()); } currentValue = currentValueResult.Value; currentValue += increment.Value; var setResult2 = await stateMonad.SetVariableAsync( variableName, currentValue, false, this ); if (setResult2.IsFailure) { return(setResult.ConvertFailure <Unit>()); } } await stateMonad.RemoveVariableAsync(VariableName.Index, false, this); return(Unit.Default); }