<commit_before>package thx.promise;

import haxe.ds.Option;

import thx.Either;
import thx.Error;
import thx.Nil;
import thx.Result;
import thx.Tuple;
import thx.fp.Functions.const;

using thx.Arrays;
using thx.Functions;
using thx.Options;

typedef PromiseValue<T> = Result<T, Error>;

@:forward(hasValue, mapAsync, state, then)
abstract Promise<T>(Future<Result<T, Error>>) to Future<Result<T, Error>> {
  inline private function new(future: Future<Result<T, Error>>)
    this = future;

  public static function fromFuture<T>(future : Future<T>) : Promise<T>
    return new Promise(future.map(function(v) return (Right(v) : PromiseValue<T>)));

  // Note: this can be a static var again, when the issue #19 with promise reuse is fixed
  //public static var nil(default, null) : Promise<Nil> = Promise.value(Nil.nil);
  public static var nil(get, null) : Promise<Nil>;
  static function get_nil() : Promise<Nil> return Promise.value(Nil.nil);

  @:deprecated("Use Promise.sequence instead; since Promise construction is eager there is no difference between the two.")
  public static function all<T>(arr : Array<Promise<T>>) : Promise<Array<T>> {
    return if (arr.length == 0) Promise.value([])
    else Promise.create(
      function(resolve, reject) {
        var results  = [],
            counter  = 0,
            hasError = false;

        // For each element of the array, mutate the results completion. When
        // all results have been included, or an error is encountered, resolve
        // the resulting promise.
        for (i in 0...arr.length) {
          arr[i].either(
            function(v) {
              if (!hasError) {
                results[i] = v;
                counter++;

                if(counter == arr.length) resolve(results);
              }
            },
            function(err) {
              if (!hasError) {
                hasError = true;
                reject(err);
              }
            }
          );
        }
      }
    );
  }

  public static function afterAll(arr : Array<Promise<Dynamic>>) : Promise<Nil>
    return sequence(arr).map(const(Nil.nil));

  public static function sequence<T>(arr : Array<Promise<T>>) : Promise<Array<T>> {
    return arr.reduce(
      function(acc: Promise<Array<T>>, p: Promise<T>) return acc.flatMap(
        function(arr: Array<T>) return p.map(function(t) return arr.concat([t]))
      ),
      Promise.value([])
    );
  }

  @:deprecated("Use Promise.sequence instead.")
  public static function allSequence<T>(arr : Array<Promise<T>>) : Promise<Array<T>>
    return sequence(arr);

  public static function create<T>(callback : (T -> Void) -> (Error -> Void) -> Void) : Promise<T>
    return new Promise(
      Future.create(function(cb : PromiseValue<T> -> Void) {
        try {
          callback(
            function(v : T)     cb((Right(v) : PromiseValue<T>)),
            function(e : Error) cb((Left(e) : PromiseValue<T>))
          );
        } catch(e : Dynamic) {
          cb((Left(Error.fromDynamic(e)) : PromiseValue<T>));
        }
      })
    );

  public static function createUnsafe<T>(callback : (T -> Void) -> (Error -> Void) -> Void) : Promise<T>
    return new Promise(
      Future.create(function(cb : PromiseValue<T> -> Void) {
        callback(
          function(v : T)     cb((Right(v) : PromiseValue<T>)),
          function(e : Error) cb((Left(e) : PromiseValue<T>))
        );
      })
    );

  public static function createFulfill<T>(callback : (PromiseValue<T> -> Void) -> Void) : Promise<T>
    return new Promise(Future.create(function(cb) {
      try callback(cb) catch(e : Dynamic) cb(Left(Error.fromDynamic(e)));
    }));

  public static function fail<T>(message : String, ?pos : haxe.PosInfos) : Promise<T>
    return error(new thx.Error(message, pos));

  public static function error<T>(err : Error) : Promise<T>
    return Promise.create(function(_, reject) reject(err));

  public static function value<T>(v : T) : Promise<T>
    return Promise.create(function(resolve, _) resolve(v));

  public function always(handler : Void -> Void) : Promise<T>
    return new Promise(
      Future.create(function(cb : PromiseValue<T> -> Void) {
        this.then(function(v) {
          try {
            handler();
            cb(v);
          } catch(e : Dynamic) {
            cb(Left(Error.fromDynamic(e)));
          }
        });
      })
    );

  public function either(success : T -> Void, failure : Error -> Void) : Promise<T>
    return Promise.createUnsafe(function(resolve : T -> Void, reject : Error -> Void) {
      this.then(function(r) {
        try {
          switch r {
            case Right(v):
              success(v);
              resolve(v);
            case Left(e):
              failure(e);
              reject(e);
          }
        } catch(e : Dynamic) {
          reject(Error.fromDynamic(e));
        }
      });
    });

#if (js || flash)
  public function delay(?delayms : Int) : Promise<T>
    return new Promise(this.delay(delayms));
#end

  public function isFailure() : Bool
    return switch this.state {
      case None, Some(Right(_)): false;
      case _: true;
    };

  public function isResolved() : Bool
    return switch this.state {
      case None, Some(Left(_)): false;
      case _: true;
    };
<commit_msg>Add check for pending promise<commit_after>package thx.promise;

import haxe.ds.Option;

import thx.Either;
import thx.Error;
import thx.Nil;
import thx.Result;
import thx.Tuple;
import thx.fp.Functions.const;

using thx.Arrays;
using thx.Functions;
using thx.Options;

typedef PromiseValue<T> = Result<T, Error>;

@:forward(hasValue, mapAsync, state, then)
abstract Promise<T>(Future<Result<T, Error>>) to Future<Result<T, Error>> {
  inline private function new(future: Future<Result<T, Error>>)
    this = future;

  public static function fromFuture<T>(future : Future<T>) : Promise<T>
    return new Promise(future.map(function(v) return (Right(v) : PromiseValue<T>)));

  // Note: this can be a static var again, when the issue #19 with promise reuse is fixed
  //public static var nil(default, null) : Promise<Nil> = Promise.value(Nil.nil);
  public static var nil(get, null) : Promise<Nil>;
  static function get_nil() : Promise<Nil> return Promise.value(Nil.nil);

  @:deprecated("Use Promise.sequence instead; since Promise construction is eager there is no difference between the two.")
  public static function all<T>(arr : Array<Promise<T>>) : Promise<Array<T>> {
    return if (arr.length == 0) Promise.value([])
    else Promise.create(
      function(resolve, reject) {
        var results  = [],
            counter  = 0,
            hasError = false;

        // For each element of the array, mutate the results completion. When
        // all results have been included, or an error is encountered, resolve
        // the resulting promise.
        for (i in 0...arr.length) {
          arr[i].either(
            function(v) {
              if (!hasError) {
                results[i] = v;
                counter++;

                if(counter == arr.length) resolve(results);
              }
            },
            function(err) {
              if (!hasError) {
                hasError = true;
                reject(err);
              }
            }
          );
        }
      }
    );
  }

  public static function afterAll(arr : Array<Promise<Dynamic>>) : Promise<Nil>
    return sequence(arr).map(const(Nil.nil));

  public static function sequence<T>(arr : Array<Promise<T>>) : Promise<Array<T>> {
    return arr.reduce(
      function(acc: Promise<Array<T>>, p: Promise<T>) return acc.flatMap(
        function(arr: Array<T>) return p.map(function(t) return arr.concat([t]))
      ),
      Promise.value([])
    );
  }

  @:deprecated("Use Promise.sequence instead.")
  public static function allSequence<T>(arr : Array<Promise<T>>) : Promise<Array<T>>
    return sequence(arr);

  public static function create<T>(callback : (T -> Void) -> (Error -> Void) -> Void) : Promise<T>
    return new Promise(
      Future.create(function(cb : PromiseValue<T> -> Void) {
        try {
          callback(
            function(v : T)     cb((Right(v) : PromiseValue<T>)),
            function(e : Error) cb((Left(e) : PromiseValue<T>))
          );
        } catch(e : Dynamic) {
          cb((Left(Error.fromDynamic(e)) : PromiseValue<T>));
        }
      })
    );

  public static function createUnsafe<T>(callback : (T -> Void) -> (Error -> Void) -> Void) : Promise<T>
    return new Promise(
      Future.create(function(cb : PromiseValue<T> -> Void) {
        callback(
          function(v : T)     cb((Right(v) : PromiseValue<T>)),
          function(e : Error) cb((Left(e) : PromiseValue<T>))
        );
      })
    );

  public static function createFulfill<T>(callback : (PromiseValue<T> -> Void) -> Void) : Promise<T>
    return new Promise(Future.create(function(cb) {
      try callback(cb) catch(e : Dynamic) cb(Left(Error.fromDynamic(e)));
    }));

  public static function fail<T>(message : String, ?pos : haxe.PosInfos) : Promise<T>
    return error(new thx.Error(message, pos));

  public static function error<T>(err : Error) : Promise<T>
    return Promise.create(function(_, reject) reject(err));

  public static function value<T>(v : T) : Promise<T>
    return Promise.create(function(resolve, _) resolve(v));

  public function always(handler : Void -> Void) : Promise<T>
    return new Promise(
      Future.create(function(cb : PromiseValue<T> -> Void) {
        this.then(function(v) {
          try {
            handler();
            cb(v);
          } catch(e : Dynamic) {
            cb(Left(Error.fromDynamic(e)));
          }
        });
      })
    );

  public function either(success : T -> Void, failure : Error -> Void) : Promise<T>
    return Promise.createUnsafe(function(resolve : T -> Void, reject : Error -> Void) {
      this.then(function(r) {
        try {
          switch r {
            case Right(v):
              success(v);
              resolve(v);
            case Left(e):
              failure(e);
              reject(e);
          }
        } catch(e : Dynamic) {
          reject(Error.fromDynamic(e));
        }
      });
    });

#if (js || flash)
  public function delay(?delayms : Int) : Promise<T>
    return new Promise(this.delay(delayms));
#end

  public function isFailure() : Bool
    return switch this.state {
      case None, Some(Right(_)): false;
      case _: true;
    };

  public function isResolved() : Bool
    return switch this.state {
      case None, Some(Left(_)): false;
      case _: true;
    };

  public function isPending() : Bool
    return switch this.state {
      case Some(_): false;
      case None: true;
    };

{'fraction_non_alphanumeric': 0.14109002976190477, 'fraction_numerical': 0.0009300595238095238, 'mean_word_length': 2.412567438908283, 'pattern_counts': {'":': 0, '<': 127, '<?xml version=': 0, '>': 163, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '785132', 'n_tokens_mistral': 3278, 'n_tokens_neox': 3168, 'n_words': 823}