// Generated by ReScript, PLEASE EDIT WITH CARE

import * as List from "rescript/lib/es6/list.js";

function arrowType(ct) {
  var $$process = function (attrsBefore, _acc, _typ) {
    while(true) {
      var typ = _typ;
      var acc = _acc;
      var match = typ.ptyp_desc;
      if (typeof match === "number") {
        return [
                attrsBefore,
                List.rev(acc),
                typ
              ];
      }
      if (match.TAG !== /* Ptyp_arrow */1) {
        return [
                attrsBefore,
                List.rev(acc),
                typ
              ];
      }
      var lbl = match._0;
      if (typeof lbl === "number") {
        var attrs = typ.ptyp_attributes;
        var typ2 = match._2;
        var typ1 = match._1;
        if (attrs) {
          if (attrs.hd[0].txt === "bs" && !attrs.tl) {
            var arg = [
              attrs,
              lbl,
              typ1
            ];
            _typ = typ2;
            _acc = {
              hd: arg,
              tl: acc
            };
            continue ;
          }
          
        } else {
          var arg$1 = [
            /* [] */0,
            lbl,
            typ1
          ];
          _typ = typ2;
          _acc = {
            hd: arg$1,
            tl: acc
          };
          continue ;
        }
        var args = List.rev(acc);
        return [
                attrsBefore,
                args,
                typ
              ];
      }
      var arg_0 = typ.ptyp_attributes;
      var arg_2 = match._1;
      var arg$2 = [
        arg_0,
        lbl,
        arg_2
      ];
      _typ = match._2;
      _acc = {
        hd: arg$2,
        tl: acc
      };
      continue ;
    };
  };
  var match = ct.ptyp_desc;
  if (typeof match === "number" || !(match.TAG === /* Ptyp_arrow */1 && typeof match._0 === "number")) {
    return $$process(/* [] */0, /* [] */0, ct);
  } else {
    return $$process(ct.ptyp_attributes, /* [] */0, {
                ptyp_desc: ct.ptyp_desc,
                ptyp_loc: ct.ptyp_loc,
                ptyp_attributes: /* [] */0
              });
  }
}

function functorType(modtype) {
  var _acc = /* [] */0;
  var _modtype = modtype;
  while(true) {
    var modtype$1 = _modtype;
    var acc = _acc;
    var match = modtype$1.pmty_desc;
    if (match.TAG !== /* Pmty_functor */2) {
      return [
              List.rev(acc),
              modtype$1
            ];
    }
    var arg_0 = modtype$1.pmty_attributes;
    var arg_1 = match._0;
    var arg_2 = match._1;
    var arg = [
      arg_0,
      arg_1,
      arg_2
    ];
    _modtype = match._2;
    _acc = {
      hd: arg,
      tl: acc
    };
    continue ;
  };
}

function processUncurriedAttribute(attrs) {
  var _uncurriedSpotted = false;
  var _acc = /* [] */0;
  var _attrs = attrs;
  while(true) {
    var attrs$1 = _attrs;
    var acc = _acc;
    var uncurriedSpotted = _uncurriedSpotted;
    if (!attrs$1) {
      return [
              uncurriedSpotted,
              List.rev(acc)
            ];
    }
    var attr = attrs$1.hd;
    if (attr[0].txt === "bs") {
      _attrs = attrs$1.tl;
      _uncurriedSpotted = true;
      continue ;
    }
    _attrs = attrs$1.tl;
    _acc = {
      hd: attr,
      tl: acc
    };
    continue ;
  };
}

function collectListExpressions(expr) {
  var _acc = /* [] */0;
  var _expr = expr;
  while(true) {
    var expr$1 = _expr;
    var acc = _acc;
    var match = expr$1.pexp_desc;
    if (typeof match !== "number" && match.TAG === /* Pexp_construct */9) {
      var match$1 = match._0.txt;
      switch (match$1.TAG | 0) {
        case /* Lident */0 :
            switch (match$1._0) {
              case "::" :
                  var match$2 = match._1;
                  if (match$2 !== undefined) {
                    var match$3 = match$2.pexp_desc;
                    if (typeof match$3 !== "number" && match$3.TAG === /* Pexp_tuple */8) {
                      var match$4 = match$3._0;
                      if (match$4) {
                        var match$5 = match$4.tl;
                        if (match$5 && !match$5.tl) {
                          _expr = match$5.hd;
                          _acc = {
                            hd: match$4.hd,
                            tl: acc
                          };
                          continue ;
                        }
                        
                      }
                      
                    }
                    
                  }
                  break;
              case "[]" :
                  return [
                          List.rev(acc),
                          undefined
                        ];
              default:
                
            }
            break;
        case /* Ldot */1 :
        case /* Lapply */2 :
            break;
        
      }
    }
    return [
            List.rev(acc),
            expr$1
          ];
  };
}

function rewriteUnderscoreApply(expr) {
  var match = expr.pexp_desc;
  if (typeof match === "number") {
    return expr;
  }
  if (match.TAG !== /* Pexp_fun */4) {
    return expr;
  }
  if (typeof match._0 !== "number") {
    return expr;
  }
  if (match._1 !== undefined) {
    return expr;
  }
  var match$1 = match._2.ppat_desc;
  if (typeof match$1 === "number") {
    return expr;
  }
  if (match$1.TAG !== /* Ppat_var */0) {
    return expr;
  }
  if (match$1._0.txt !== "__x") {
    return expr;
  }
  var e = match._3;
  var match$2 = e.pexp_desc;
  if (typeof match$2 === "number") {
    return expr;
  }
  if (match$2.TAG !== /* Pexp_apply */5) {
    return expr;
  }
  var newArgs = List.map((function (arg) {
          var argExpr = arg[1];
          var lid = argExpr.pexp_desc;
          if (typeof lid === "number") {
            return arg;
          }
          if (lid.TAG !== /* Pexp_ident */0) {
            return arg;
          }
          var lid$1 = lid._0;
          var match = lid$1.txt;
          switch (match.TAG | 0) {
            case /* Lident */0 :
                if (match._0 === "__x") {
                  return [
                          arg[0],
                          {
                            pexp_desc: {
                              TAG: /* Pexp_ident */0,
                              _0: {
                                txt: {
                                  TAG: /* Lident */0,
                                  _0: "_"
                                },
                                loc: lid$1.loc
                              }
                            },
                            pexp_loc: argExpr.pexp_loc,
                            pexp_attributes: argExpr.pexp_attributes
                          }
                        ];
                } else {
                  return arg;
                }
            case /* Ldot */1 :
            case /* Lapply */2 :
                return arg;
            
          }
        }), match$2._1);
  return {
          pexp_desc: {
            TAG: /* Pexp_apply */5,
            _0: match$2._0,
            _1: newArgs
          },
          pexp_loc: e.pexp_loc,
          pexp_attributes: e.pexp_attributes
        };
}

function funExpr(expr) {
  var collectNewTypes = function (_acc, _returnExpr) {
    while(true) {
      var returnExpr = _returnExpr;
      var acc = _acc;
      var match = returnExpr.pexp_desc;
      if (typeof match === "number") {
        return [
                List.rev(acc),
                returnExpr
              ];
      }
      if (match.TAG !== /* Pexp_newtype */31) {
        return [
                List.rev(acc),
                returnExpr
              ];
      }
      if (returnExpr.pexp_attributes) {
        return [
                List.rev(acc),
                returnExpr
              ];
      }
      _returnExpr = match._1;
      _acc = {
        hd: match._0,
        tl: acc
      };
      continue ;
    };
  };
  var collect = function (attrsBefore, _acc, _expr) {
    while(true) {
      var expr = _expr;
      var acc = _acc;
      var match = expr.pexp_desc;
      if (typeof match !== "number") {
        switch (match.TAG | 0) {
          case /* Pexp_fun */4 :
              var lbl = match._0;
              var exit = 0;
              var exit$1 = 0;
              if (typeof lbl === "number" && match._1 === undefined) {
                var match$1 = match._2.ppat_desc;
                if (typeof match$1 === "number" || !(match$1.TAG === /* Ppat_var */0 && match$1._0.txt === "__x")) {
                  exit$1 = 3;
                } else {
                  var tmp = match._3.pexp_desc;
                  if (typeof tmp === "number") {
                    exit$1 = 3;
                  } else {
                    if (tmp.TAG === /* Pexp_apply */5) {
                      return [
                              attrsBefore,
                              List.rev(acc),
                              rewriteUnderscoreApply(expr)
                            ];
                    }
                    exit$1 = 3;
                  }
                }
              } else {
                exit$1 = 3;
              }
              if (exit$1 === 3) {
                var attrs = expr.pexp_attributes;
                var returnExpr = match._3;
                var pattern = match._2;
                var defaultExpr = match._1;
                if (attrs) {
                  if (attrs.hd[0].txt === "bs" && !attrs.tl) {
                    var parameter = {
                      TAG: /* Parameter */0,
                      attrs: attrs,
                      lbl: lbl,
                      defaultExpr: defaultExpr,
                      pat: pattern
                    };
                    _expr = returnExpr;
                    _acc = {
                      hd: parameter,
                      tl: acc
                    };
                    continue ;
                  }
                  exit = 2;
                } else {
                  var parameter$1 = {
                    TAG: /* Parameter */0,
                    attrs: /* [] */0,
                    lbl: lbl,
                    defaultExpr: defaultExpr,
                    pat: pattern
                  };
                  _expr = returnExpr;
                  _acc = {
                    hd: parameter$1,
                    tl: acc
                  };
                  continue ;
                }
              }
              if (exit === 2 && typeof lbl !== "number") {
                var parameter_0 = expr.pexp_attributes;
                var parameter_2 = match._1;
                var parameter_3 = match._2;
                var parameter$2 = {
                  TAG: /* Parameter */0,
                  attrs: parameter_0,
                  lbl: lbl,
                  defaultExpr: parameter_2,
                  pat: parameter_3
                };
                _expr = match._3;
                _acc = {
                  hd: parameter$2,
                  tl: acc
                };
                continue ;
              }
              break;
          case /* Pexp_newtype */31 :
              var match$2 = collectNewTypes({
                    hd: match._0,
                    tl: /* [] */0
                  }, match._1);
              var param_0 = expr.pexp_attributes;
              var param_1 = match$2[0];
              var param = {
                TAG: /* NewTypes */1,
                attrs: param_0,
                locs: param_1
              };
              _expr = match$2[1];
              _acc = {
                hd: param,
                tl: acc
              };
              continue ;
          default:
            
        }
      }
      return [
              attrsBefore,
              List.rev(acc),
              expr
            ];
    };
  };
  var match = expr.pexp_desc;
  if (typeof match === "number" || !(match.TAG === /* Pexp_fun */4 && typeof match._0 === "number")) {
    return collect(/* [] */0, /* [] */0, expr);
  } else {
    return collect(expr.pexp_attributes, /* [] */0, {
                pexp_desc: expr.pexp_desc,
                pexp_loc: expr.pexp_loc,
                pexp_attributes: /* [] */0
              });
  }
}

function processBracesAttr(expr) {
  var match = expr.pexp_attributes;
  if (!match) {
    return [
            undefined,
            expr
          ];
  }
  var attr = match.hd;
  if (attr[0].txt === "ns.braces") {
    return [
            attr,
            {
              pexp_desc: expr.pexp_desc,
              pexp_loc: expr.pexp_loc,
              pexp_attributes: match.tl
            }
          ];
  } else {
    return [
            undefined,
            expr
          ];
  }
}

function filterParsingAttrs(attrs) {
  return List.filter(function (attr) {
                switch (attr[0].txt) {
                  case "bs" :
                  case "ns.braces" :
                  case "ns.iflet" :
                  case "ns.namedArgLoc" :
                  case "ns.ternary" :
                  case "res.template" :
                      return false;
                  default:
                    return true;
                }
              })(attrs);
}

function isBlockExpr(expr) {
  var match = expr.pexp_desc;
  if (typeof match === "number") {
    return false;
  }
  switch (match.TAG | 0) {
    case /* Pexp_let */2 :
    case /* Pexp_sequence */16 :
    case /* Pexp_letmodule */25 :
    case /* Pexp_letexception */26 :
    case /* Pexp_open */33 :
        return true;
    default:
      return false;
  }
}

function isBracedExpr(expr) {
  var match = processBracesAttr(expr);
  return match[0] !== undefined;
}

function isMultilineText(txt) {
  var len = txt.length;
  var _i = 0;
  while(true) {
    var i = _i;
    if (i >= len) {
      return false;
    }
    var c = txt.charCodeAt(i);
    if (c > 13 || c < 10) {
      if (c !== 92) {
        _i = i + 1 | 0;
        continue ;
      }
      if ((i + 2 | 0) === len) {
        return false;
      }
      _i = i + 2 | 0;
      continue ;
    }
    if (!(c === 12 || c === 11)) {
      return true;
    }
    _i = i + 1 | 0;
    continue ;
  };
}

function isHuggableExpression(expr) {
  var match = expr.pexp_desc;
  if (typeof match !== "number") {
    switch (match.TAG | 0) {
      case /* Pexp_constant */1 :
          var match$1 = match._0;
          if (match$1.TAG === /* Pconst_string */2 && match$1._1 !== undefined) {
            return true;
          }
          break;
      case /* Pexp_construct */9 :
          var match$2 = match._0.txt;
          switch (match$2.TAG | 0) {
            case /* Lident */0 :
                switch (match$2._0) {
                  case "::" :
                  case "[]" :
                      return true;
                  default:
                    
                }
                break;
            case /* Ldot */1 :
            case /* Lapply */2 :
                break;
            
          }
          break;
      case /* Pexp_tuple */8 :
      case /* Pexp_record */11 :
      case /* Pexp_array */14 :
          return true;
      case /* Pexp_extension */34 :
          switch (match._0[0].txt) {
            case "bs.obj" :
            case "obj" :
                return true;
            default:
              
          }
          break;
      default:
        
    }
  }
  if (isBlockExpr(expr)) {
    return true;
  }
  if (isBracedExpr(expr)) {
    return true;
  }
  if (typeof match === "number") {
    return false;
  }
  if (match.TAG !== /* Pexp_constant */1) {
    return false;
  }
  var match$3 = match._0;
  if (match$3.TAG === /* Pconst_string */2 && isMultilineText(match$3._0)) {
    return true;
  } else {
    return false;
  }
}

function isHuggableRhs(expr) {
  var match = expr.pexp_desc;
  if (typeof match !== "number") {
    switch (match.TAG | 0) {
      case /* Pexp_construct */9 :
          var match$1 = match._0.txt;
          switch (match$1.TAG | 0) {
            case /* Lident */0 :
                switch (match$1._0) {
                  case "::" :
                  case "[]" :
                      return true;
                  default:
                    
                }
                break;
            case /* Ldot */1 :
            case /* Lapply */2 :
                break;
            
          }
          break;
      case /* Pexp_tuple */8 :
      case /* Pexp_record */11 :
      case /* Pexp_array */14 :
          return true;
      case /* Pexp_extension */34 :
          switch (match._0[0].txt) {
            case "bs.obj" :
            case "obj" :
                return true;
            default:
              
          }
          break;
      default:
        
    }
  }
  if (isBracedExpr(expr)) {
    return true;
  } else {
    return false;
  }
}

function isHuggablePattern(pattern) {
  var match = pattern.ppat_desc;
  if (typeof match === "number") {
    return false;
  }
  switch (match.TAG | 0) {
    case /* Ppat_tuple */4 :
    case /* Ppat_construct */5 :
    case /* Ppat_variant */6 :
    case /* Ppat_record */7 :
    case /* Ppat_array */8 :
        return true;
    default:
      return false;
  }
}

function operatorPrecedence(operator) {
  switch (operator) {
    case "&&" :
        return 3;
    case "**" :
        return 7;
    case "*" :
    case "*." :
    case "/" :
    case "/." :
        return 6;
    case ":=" :
        return 1;
    case "+" :
    case "+." :
    case "-" :
    case "-." :
    case "^" :
        return 5;
    case "#" :
    case "##" :
    case "|." :
        return 8;
    case "!=" :
    case "!==" :
    case "<" :
    case "<=" :
    case "<>" :
    case "=" :
    case "==" :
    case ">" :
    case ">=" :
    case "|>" :
        return 4;
    case "||" :
        return 2;
    default:
      return 0;
  }
}

function isUnaryOperator(operator) {
  switch (operator) {
    case "not" :
    case "~+" :
    case "~+." :
    case "~-" :
    case "~-." :
        return true;
    default:
      return false;
  }
}

function isUnaryExpression(expr) {
  var match = expr.pexp_desc;
  if (typeof match === "number") {
    return false;
  }
  if (match.TAG !== /* Pexp_apply */5) {
    return false;
  }
  var match$1 = match._0.pexp_desc;
  if (typeof match$1 === "number") {
    return false;
  }
  if (match$1.TAG !== /* Pexp_ident */0) {
    return false;
  }
  var operator = match$1._0.txt;
  switch (operator.TAG | 0) {
    case /* Lident */0 :
        var match$2 = match._1;
        if (match$2 && typeof match$2.hd[0] === "number" && !(match$2.tl || !isUnaryOperator(operator._0))) {
          return true;
        } else {
          return false;
        }
    case /* Ldot */1 :
    case /* Lapply */2 :
        return false;
    
  }
}

function isBinaryOperator(operator) {
  switch (operator) {
    case "!=" :
    case "!==" :
    case "&&" :
    case "*" :
    case "**" :
    case "*." :
    case "+" :
    case "+." :
    case "-" :
    case "-." :
    case "/" :
    case "/." :
    case ":=" :
    case "<" :
    case "<=" :
    case "<>" :
    case "=" :
    case "==" :
    case ">" :
    case ">=" :
    case "^" :
    case "|." :
    case "|>" :
    case "||" :
        return true;
    default:
      return false;
  }
}

function isBinaryExpression(expr) {
  var match = expr.pexp_desc;
  if (typeof match === "number") {
    return false;
  }
  if (match.TAG !== /* Pexp_apply */5) {
    return false;
  }
  var match$1 = match._0.pexp_desc;
  if (typeof match$1 === "number") {
    return false;
  }
  if (match$1.TAG !== /* Pexp_ident */0) {
    return false;
  }
  var match$2 = match$1._0;
  var operator = match$2.txt;
  switch (operator.TAG | 0) {
    case /* Lident */0 :
        var match$3 = match._1;
        if (!match$3) {
          return false;
        }
        if (typeof match$3.hd[0] !== "number") {
          return false;
        }
        var match$4 = match$3.tl;
        if (!match$4) {
          return false;
        }
        if (typeof match$4.hd[0] !== "number") {
          return false;
        }
        if (match$4.tl) {
          return false;
        }
        var operator$1 = operator._0;
        if (isBinaryOperator(operator$1)) {
          return !(match$2.loc.loc_ghost && operator$1 === "^");
        } else {
          return false;
        }
    case /* Ldot */1 :
    case /* Lapply */2 :
        return false;
    
  }
}

function isEqualityOperator(operator) {
  switch (operator) {
    case "!=" :
    case "<>" :
    case "=" :
    case "==" :
        return true;
    default:
      return false;
  }
}

function flattenableOperators(parentOperator, childOperator) {
  var precParent = operatorPrecedence(parentOperator);
  var precChild = operatorPrecedence(childOperator);
  if (precParent === precChild) {
    return !(isEqualityOperator(parentOperator) && isEqualityOperator(childOperator));
  } else {
    return false;
  }
}

function hasIfLetAttribute(_attrs) {
  while(true) {
    var attrs = _attrs;
    if (!attrs) {
      return false;
    }
    if (attrs.hd[0].txt === "ns.iflet") {
      return true;
    }
    _attrs = attrs.tl;
    continue ;
  };
}

function isIfLetExpr(expr) {
  var tmp = expr.pexp_desc;
  if (typeof tmp === "number" || !(tmp.TAG === /* Pexp_match */6 && hasIfLetAttribute(expr.pexp_attributes))) {
    return false;
  } else {
    return true;
  }
}

function hasAttributes(attrs) {
  return List.exists((function (attr) {
                switch (attr[0].txt) {
                  case "bs" :
                  case "ns.braces" :
                  case "ns.iflet" :
                  case "ns.ternary" :
                  case "res.template" :
                      return false;
                  case "warning" :
                      var match = attr[1];
                      if (match.TAG !== /* PStr */0) {
                        return true;
                      }
                      var match$1 = match._0;
                      if (!match$1) {
                        return true;
                      }
                      var match$2 = match$1.hd.pstr_desc;
                      if (match$2.TAG !== /* Pstr_eval */0) {
                        return true;
                      }
                      var match$3 = match$2._0.pexp_desc;
                      if (typeof match$3 === "number") {
                        return true;
                      }
                      if (match$3.TAG !== /* Pexp_constant */1) {
                        return true;
                      }
                      var match$4 = match$3._0;
                      if (match$4.TAG === /* Pconst_string */2 && match$4._0 === "-4" && !(match$4._1 !== undefined || match$1.tl)) {
                        return !hasIfLetAttribute(attrs);
                      } else {
                        return true;
                      }
                  default:
                    return true;
                }
              }), attrs);
}

function isArrayAccess(expr) {
  var match = expr.pexp_desc;
  if (typeof match === "number") {
    return false;
  }
  if (match.TAG !== /* Pexp_apply */5) {
    return false;
  }
  var match$1 = match._0.pexp_desc;
  if (typeof match$1 === "number") {
    return false;
  }
  if (match$1.TAG !== /* Pexp_ident */0) {
    return false;
  }
  var match$2 = match$1._0.txt;
  switch (match$2.TAG | 0) {
    case /* Ldot */1 :
        var match$3 = match$2._0;
        switch (match$3.TAG | 0) {
          case /* Lident */0 :
              if (match$3._0 !== "Array") {
                return false;
              }
              if (match$2._1 !== "get") {
                return false;
              }
              var match$4 = match._1;
              if (!match$4) {
                return false;
              }
              if (typeof match$4.hd[0] !== "number") {
                return false;
              }
              var match$5 = match$4.tl;
              if (match$5 && typeof match$5.hd[0] === "number" && !match$5.tl) {
                return true;
              } else {
                return false;
              }
          case /* Ldot */1 :
          case /* Lapply */2 :
              return false;
          
        }
    case /* Lident */0 :
    case /* Lapply */2 :
        return false;
    
  }
}

function collectIfExpressions(expr) {
  var _acc = /* [] */0;
  var _expr = expr;
  while(true) {
    var expr$1 = _expr;
    var acc = _acc;
    var match = expr$1.pexp_desc;
    if (typeof match !== "number") {
      switch (match.TAG | 0) {
        case /* Pexp_match */6 :
            var match$1 = match._1;
            if (match$1) {
              var match$2 = match$1.hd;
              if (match$2.pc_guard === undefined) {
                var match$3 = match$1.tl;
                if (match$3) {
                  var elseExpr = match$3.hd.pc_rhs;
                  var match$4 = elseExpr.pexp_desc;
                  var thenExpr = match$2.pc_rhs;
                  var pattern = match$2.pc_lhs;
                  var condition = match._0;
                  var exit = 0;
                  if (typeof match$4 === "number" || match$4.TAG !== /* Pexp_construct */9) {
                    exit = 2;
                  } else {
                    var match$5 = match$4._0.txt;
                    switch (match$5.TAG | 0) {
                      case /* Lident */0 :
                          if (match$5._0 === "()") {
                            if (!match$3.tl) {
                              if (isIfLetExpr(expr$1)) {
                                var ifs = List.rev({
                                      hd: [
                                        {
                                          TAG: /* IfLet */1,
                                          _0: pattern,
                                          _1: condition
                                        },
                                        thenExpr
                                      ],
                                      tl: acc
                                    });
                                return [
                                        ifs,
                                        undefined
                                      ];
                              }
                              exit = 2;
                            }
                            
                          } else {
                            exit = 2;
                          }
                          break;
                      case /* Ldot */1 :
                      case /* Lapply */2 :
                          exit = 2;
                          break;
                      
                    }
                  }
                  if (exit === 2 && !match$3.tl && isIfLetExpr(expr$1)) {
                    _expr = elseExpr;
                    _acc = {
                      hd: [
                        {
                          TAG: /* IfLet */1,
                          _0: pattern,
                          _1: condition
                        },
                        thenExpr
                      ],
                      tl: acc
                    };
                    continue ;
                  }
                  
                }
                
              }
              
            }
            break;
        case /* Pexp_ifthenelse */15 :
            var elseExpr$1 = match._2;
            var thenExpr$1 = match._1;
            var ifExpr = match._0;
            if (elseExpr$1 !== undefined) {
              _expr = elseExpr$1;
              _acc = {
                hd: [
                  {
                    TAG: /* If */0,
                    _0: ifExpr
                  },
                  thenExpr$1
                ],
                tl: acc
              };
              continue ;
            }
            var ifs$1 = List.rev({
                  hd: [
                    {
                      TAG: /* If */0,
                      _0: ifExpr
                    },
                    thenExpr$1
                  ],
                  tl: acc
                });
            return [
                    ifs$1,
                    elseExpr$1
                  ];
        default:
          
      }
    }
    return [
            List.rev(acc),
            expr$1
          ];
  };
}

function hasTernaryAttribute(_attrs) {
  while(true) {
    var attrs = _attrs;
    if (!attrs) {
      return false;
    }
    if (attrs.hd[0].txt === "ns.ternary") {
      return true;
    }
    _attrs = attrs.tl;
    continue ;
  };
}

function isTernaryExpr(expr) {
  var tmp = expr.pexp_desc;
  if (typeof tmp === "number" || !(tmp.TAG === /* Pexp_ifthenelse */15 && hasTernaryAttribute(expr.pexp_attributes))) {
    return false;
  } else {
    return true;
  }
}

function collectTernaryParts(expr) {
  var _acc = /* [] */0;
  var _expr = expr;
  while(true) {
    var expr$1 = _expr;
    var acc = _acc;
    var match = expr$1.pexp_desc;
    if (typeof match === "number") {
      return [
              List.rev(acc),
              expr$1
            ];
    }
    if (match.TAG !== /* Pexp_ifthenelse */15) {
      return [
              List.rev(acc),
              expr$1
            ];
    }
    var alternate = match._2;
    if (alternate === undefined) {
      return [
              List.rev(acc),
              expr$1
            ];
    }
    if (!hasTernaryAttribute(expr$1.pexp_attributes)) {
      return [
              List.rev(acc),
              expr$1
            ];
    }
    _expr = alternate;
    _acc = {
      hd: [
        match._0,
        match._1
      ],
      tl: acc
    };
    continue ;
  };
}

function parametersShouldHug(parameters) {
  if (!parameters) {
    return false;
  }
  var match = parameters.hd;
  if (match.TAG === /* Parameter */0 && !(match.attrs || !(typeof match.lbl === "number" && !(match.defaultExpr !== undefined || parameters.tl || !isHuggablePattern(match.pat))))) {
    return true;
  } else {
    return false;
  }
}

function filterTernaryAttributes(attrs) {
  return List.filter(function (attr) {
                if (attr[0].txt === "ns.ternary") {
                  return false;
                } else {
                  return true;
                }
              })(attrs);
}

function filterFragileMatchAttributes(attrs) {
  return List.filter(function (attr) {
                if (attr[0].txt !== "warning") {
                  return true;
                }
                var match = attr[1];
                if (match.TAG !== /* PStr */0) {
                  return true;
                }
                var match$1 = match._0;
                if (!match$1) {
                  return true;
                }
                var match$2 = match$1.hd.pstr_desc;
                if (match$2.TAG !== /* Pstr_eval */0) {
                  return true;
                }
                var match$3 = match$2._0.pexp_desc;
                if (typeof match$3 === "number") {
                  return true;
                }
                if (match$3.TAG !== /* Pexp_constant */1) {
                  return true;
                }
                var match$4 = match$3._0;
                if (match$4.TAG === /* Pconst_string */2 && match$4._0 === "-4" && !match$1.tl) {
                  return false;
                } else {
                  return true;
                }
              })(attrs);
}

function isJsxExpression(expr) {
  var match = expr.pexp_desc;
  if (typeof match === "number" || match.TAG !== /* Pexp_apply */5) {
    return false;
  } else {
    var _attrs = expr.pexp_attributes;
    while(true) {
      var attrs = _attrs;
      if (!attrs) {
        return false;
      }
      if (attrs.hd[0].txt === "JSX") {
        return true;
      }
      _attrs = attrs.tl;
      continue ;
    };
  }
}

function hasJsxAttribute(attributes) {
  var _attrs = attributes;
  while(true) {
    var attrs = _attrs;
    if (!attrs) {
      return false;
    }
    if (attrs.hd[0].txt === "JSX") {
      return true;
    }
    _attrs = attrs.tl;
    continue ;
  };
}

function shouldIndentBinaryExpr(expr) {
  var samePrecedenceSubExpression = function (operator, subExpression) {
    var match = subExpression.pexp_desc;
    if (typeof match === "number") {
      return true;
    }
    if (match.TAG !== /* Pexp_apply */5) {
      return true;
    }
    var match$1 = match._0.pexp_desc;
    if (typeof match$1 === "number") {
      return true;
    }
    if (match$1.TAG !== /* Pexp_ident */0) {
      return true;
    }
    var subOperator = match$1._0.txt;
    switch (subOperator.TAG | 0) {
      case /* Lident */0 :
          var match$2 = match._1;
          if (!match$2) {
            return true;
          }
          if (typeof match$2.hd[0] !== "number") {
            return true;
          }
          var match$3 = match$2.tl;
          if (!match$3) {
            return true;
          }
          if (typeof match$3.hd[0] !== "number") {
            return true;
          }
          if (match$3.tl) {
            return true;
          }
          var subOperator$1 = subOperator._0;
          if (isBinaryOperator(subOperator$1)) {
            return flattenableOperators(operator, subOperator$1);
          } else {
            return true;
          }
      case /* Ldot */1 :
      case /* Lapply */2 :
          return true;
      
    }
  };
  var match = expr.pexp_desc;
  if (typeof match === "number") {
    return false;
  }
  if (match.TAG !== /* Pexp_apply */5) {
    return false;
  }
  var match$1 = match._0.pexp_desc;
  if (typeof match$1 === "number") {
    return false;
  }
  if (match$1.TAG !== /* Pexp_ident */0) {
    return false;
  }
  var operator = match$1._0.txt;
  switch (operator.TAG | 0) {
    case /* Lident */0 :
        var match$2 = match._1;
        if (!match$2) {
          return false;
        }
        var match$3 = match$2.hd;
        if (typeof match$3[0] !== "number") {
          return false;
        }
        var match$4 = match$2.tl;
        if (!match$4) {
          return false;
        }
        if (typeof match$4.hd[0] !== "number") {
          return false;
        }
        if (match$4.tl) {
          return false;
        }
        var operator$1 = operator._0;
        if (isBinaryOperator(operator$1)) {
          if (isEqualityOperator(operator$1) || !samePrecedenceSubExpression(operator$1, match$3[1])) {
            return true;
          } else {
            return operator$1 === ":=";
          }
        } else {
          return false;
        }
    case /* Ldot */1 :
    case /* Lapply */2 :
        return false;
    
  }
}

function shouldInlineRhsBinaryExpr(rhs) {
  var match = rhs.pexp_desc;
  if (typeof match === "number") {
    return false;
  }
  switch (match.TAG | 0) {
    case /* Pexp_constant */1 :
    case /* Pexp_let */2 :
    case /* Pexp_try */7 :
    case /* Pexp_record */11 :
    case /* Pexp_array */14 :
    case /* Pexp_ifthenelse */15 :
    case /* Pexp_sequence */16 :
    case /* Pexp_while */17 :
    case /* Pexp_for */18 :
    case /* Pexp_letmodule */25 :
    case /* Pexp_letexception */26 :
    case /* Pexp_open */33 :
        return true;
    default:
      return false;
  }
}

function isPrintableAttribute(attr) {
  switch (attr[0].txt) {
    case "JSX" :
    case "bs" :
    case "ns.braces" :
    case "ns.iflet" :
    case "ns.ternary" :
    case "res.template" :
        return false;
    default:
      return true;
  }
}

function hasPrintableAttributes(attrs) {
  return List.exists(isPrintableAttribute, attrs);
}

function filterPrintableAttributes(attrs) {
  return List.filter(isPrintableAttribute)(attrs);
}

function partitionPrintableAttributes(attrs) {
  return List.partition(isPrintableAttribute, attrs);
}

function requiresSpecialCallbackPrintingLastArg(args) {
  var _args = args;
  while(true) {
    var args$1 = _args;
    if (!args$1) {
      return false;
    }
    var tmp = args$1.hd[1].pexp_desc;
    if (typeof tmp === "number") {
      _args = args$1.tl;
      continue ;
    }
    switch (tmp.TAG | 0) {
      case /* Pexp_fun */4 :
      case /* Pexp_newtype */31 :
          if (args$1.tl) {
            return false;
          } else {
            return true;
          }
      default:
        _args = args$1.tl;
        continue ;
    }
  };
}

function requiresSpecialCallbackPrintingFirstArg(args) {
  if (!args) {
    return false;
  }
  var tmp = args.hd[1].pexp_desc;
  if (typeof tmp === "number") {
    return false;
  }
  switch (tmp.TAG | 0) {
    case /* Pexp_fun */4 :
    case /* Pexp_newtype */31 :
        break;
    default:
      return false;
  }
  var rest = args.tl;
  if (rest) {
    var _args = rest;
    while(true) {
      var args$1 = _args;
      if (!args$1) {
        return true;
      }
      var tmp$1 = args$1.hd[1].pexp_desc;
      if (typeof tmp$1 === "number") {
        _args = args$1.tl;
        continue ;
      }
      switch (tmp$1.TAG | 0) {
        case /* Pexp_fun */4 :
        case /* Pexp_newtype */31 :
            return false;
        default:
          _args = args$1.tl;
          continue ;
      }
    };
  } else {
    return false;
  }
}

function modExprApply(modExpr) {
  var _acc = /* [] */0;
  var _modExpr = modExpr;
  while(true) {
    var modExpr$1 = _modExpr;
    var acc = _acc;
    var match = modExpr$1.pmod_desc;
    if (match.TAG !== /* Pmod_apply */3) {
      return [
              acc,
              modExpr$1
            ];
    }
    _modExpr = match._0;
    _acc = {
      hd: match._1,
      tl: acc
    };
    continue ;
  };
}

function modExprFunctor(modExpr) {
  var _acc = /* [] */0;
  var _modExpr = modExpr;
  while(true) {
    var modExpr$1 = _modExpr;
    var acc = _acc;
    var match = modExpr$1.pmod_desc;
    if (match.TAG !== /* Pmod_functor */2) {
      return [
              List.rev(acc),
              modExpr$1
            ];
    }
    var param_0 = modExpr$1.pmod_attributes;
    var param_1 = match._0;
    var param_2 = match._1;
    var param = [
      param_0,
      param_1,
      param_2
    ];
    _modExpr = match._2;
    _acc = {
      hd: param,
      tl: acc
    };
    continue ;
  };
}

function collectPatternsFromListConstruct(_acc, _pattern) {
  while(true) {
    var pattern = _pattern;
    var acc = _acc;
    var match = pattern.ppat_desc;
    if (typeof match === "number") {
      return [
              List.rev(acc),
              pattern
            ];
    }
    if (match.TAG !== /* Ppat_construct */5) {
      return [
              List.rev(acc),
              pattern
            ];
    }
    var match$1 = match._0.txt;
    switch (match$1.TAG | 0) {
      case /* Lident */0 :
          if (match$1._0 !== "::") {
            return [
                    List.rev(acc),
                    pattern
                  ];
          }
          var match$2 = match._1;
          if (match$2 === undefined) {
            return [
                    List.rev(acc),
                    pattern
                  ];
          }
          var match$3 = match$2.ppat_desc;
          if (typeof match$3 === "number") {
            return [
                    List.rev(acc),
                    pattern
                  ];
          }
          if (match$3.TAG !== /* Ppat_tuple */4) {
            return [
                    List.rev(acc),
                    pattern
                  ];
          }
          var match$4 = match$3._0;
          if (!match$4) {
            return [
                    List.rev(acc),
                    pattern
                  ];
          }
          var match$5 = match$4.tl;
          if (!match$5) {
            return [
                    List.rev(acc),
                    pattern
                  ];
          }
          if (match$5.tl) {
            return [
                    List.rev(acc),
                    pattern
                  ];
          }
          _pattern = match$5.hd;
          _acc = {
            hd: match$4.hd,
            tl: acc
          };
          continue ;
      case /* Ldot */1 :
      case /* Lapply */2 :
          return [
                  List.rev(acc),
                  pattern
                ];
      
    }
  };
}

function hasTemplateLiteralAttr(attrs) {
  return List.exists((function (attr) {
                if (attr[0].txt === "res.template") {
                  return true;
                } else {
                  return false;
                }
              }), attrs);
}

function isTemplateLiteral(expr) {
  var match = expr.pexp_desc;
  if (typeof match === "number") {
    return false;
  }
  switch (match.TAG | 0) {
    case /* Pexp_constant */1 :
        var match$1 = match._0;
        if (match$1.TAG === /* Pconst_string */2) {
          var match$2 = match$1._1;
          if (match$2 === "") {
            return true;
          }
          
        }
        if (hasTemplateLiteralAttr(expr.pexp_attributes)) {
          return true;
        } else {
          return false;
        }
    case /* Pexp_apply */5 :
        var match$3 = match._0.pexp_desc;
        if (typeof match$3 === "number") {
          return false;
        }
        if (match$3.TAG !== /* Pexp_ident */0) {
          return false;
        }
        var match$4 = match$3._0.txt;
        switch (match$4.TAG | 0) {
          case /* Lident */0 :
              if (match$4._0 !== "^") {
                return false;
              }
              var match$5 = match._1;
              if (!match$5) {
                return false;
              }
              if (typeof match$5.hd[0] !== "number") {
                return false;
              }
              var match$6 = match$5.tl;
              if (match$6 && typeof match$6.hd[0] === "number" && !(match$6.tl || !hasTemplateLiteralAttr(expr.pexp_attributes))) {
                return true;
              } else {
                return false;
              }
          case /* Ldot */1 :
          case /* Lapply */2 :
              return false;
          
        }
    default:
      return false;
  }
}

function collectOrPatternChain(pat) {
  var _pattern = pat;
  var _chain = /* [] */0;
  while(true) {
    var chain = _chain;
    var pattern = _pattern;
    var match = pattern.ppat_desc;
    if (typeof match === "number") {
      return {
              hd: pattern,
              tl: chain
            };
    }
    if (match.TAG !== /* Ppat_or */9) {
      return {
              hd: pattern,
              tl: chain
            };
    }
    _chain = {
      hd: match._1,
      tl: chain
    };
    _pattern = match._0;
    continue ;
  };
}

function isSinglePipeExpr(expr) {
  var isPipeExpr = function (expr) {
    var match = expr.pexp_desc;
    if (typeof match === "number") {
      return false;
    }
    if (match.TAG !== /* Pexp_apply */5) {
      return false;
    }
    var match$1 = match._0.pexp_desc;
    if (typeof match$1 === "number") {
      return false;
    }
    if (match$1.TAG !== /* Pexp_ident */0) {
      return false;
    }
    var match$2 = match$1._0.txt;
    switch (match$2.TAG | 0) {
      case /* Lident */0 :
          switch (match$2._0) {
            case "|." :
            case "|>" :
                break;
            default:
              return false;
          }
          var match$3 = match._1;
          if (!match$3) {
            return false;
          }
          if (typeof match$3.hd[0] !== "number") {
            return false;
          }
          var match$4 = match$3.tl;
          if (match$4 && typeof match$4.hd[0] === "number" && !match$4.tl) {
            return true;
          } else {
            return false;
          }
          break;
      case /* Ldot */1 :
      case /* Lapply */2 :
          return false;
      
    }
  };
  var match = expr.pexp_desc;
  if (typeof match === "number") {
    return false;
  }
  if (match.TAG !== /* Pexp_apply */5) {
    return false;
  }
  var match$1 = match._0.pexp_desc;
  if (typeof match$1 === "number") {
    return false;
  }
  if (match$1.TAG !== /* Pexp_ident */0) {
    return false;
  }
  var match$2 = match$1._0.txt;
  switch (match$2.TAG | 0) {
    case /* Lident */0 :
        switch (match$2._0) {
          case "|." :
          case "|>" :
              break;
          default:
            return false;
        }
        var match$3 = match._1;
        if (!match$3) {
          return false;
        }
        var match$4 = match$3.hd;
        if (typeof match$4[0] !== "number") {
          return false;
        }
        var match$5 = match$3.tl;
        if (match$5 && typeof match$5.hd[0] === "number" && !match$5.tl) {
          return !isPipeExpr(match$4[1]);
        } else {
          return false;
        }
        break;
    case /* Ldot */1 :
    case /* Lapply */2 :
        return false;
    
  }
}

function isUnderscoreApplySugar(expr) {
  var match = expr.pexp_desc;
  if (typeof match === "number") {
    return false;
  }
  if (match.TAG !== /* Pexp_fun */4) {
    return false;
  }
  if (typeof match._0 !== "number") {
    return false;
  }
  if (match._1 !== undefined) {
    return false;
  }
  var match$1 = match._2.ppat_desc;
  if (typeof match$1 === "number") {
    return false;
  }
  if (match$1.TAG !== /* Ppat_var */0) {
    return false;
  }
  if (match$1._0.txt !== "__x") {
    return false;
  }
  var tmp = match._3.pexp_desc;
  if (typeof tmp === "number" || tmp.TAG !== /* Pexp_apply */5) {
    return false;
  } else {
    return true;
  }
}

function isRewrittenUnderscoreApplySugar(expr) {
  var match = expr.pexp_desc;
  if (typeof match === "number") {
    return false;
  }
  if (match.TAG !== /* Pexp_ident */0) {
    return false;
  }
  var match$1 = match._0.txt;
  switch (match$1.TAG | 0) {
    case /* Lident */0 :
        if (match$1._0 === "_") {
          return true;
        } else {
          return false;
        }
    case /* Ldot */1 :
    case /* Lapply */2 :
        return false;
    
  }
}

export {
  arrowType ,
  functorType ,
  processUncurriedAttribute ,
  collectListExpressions ,
  rewriteUnderscoreApply ,
  funExpr ,
  processBracesAttr ,
  filterParsingAttrs ,
  isBlockExpr ,
  isBracedExpr ,
  isMultilineText ,
  isHuggableExpression ,
  isHuggableRhs ,
  isHuggablePattern ,
  operatorPrecedence ,
  isUnaryOperator ,
  isUnaryExpression ,
  isBinaryOperator ,
  isBinaryExpression ,
  isEqualityOperator ,
  flattenableOperators ,
  hasIfLetAttribute ,
  isIfLetExpr ,
  hasAttributes ,
  isArrayAccess ,
  collectIfExpressions ,
  hasTernaryAttribute ,
  isTernaryExpr ,
  collectTernaryParts ,
  parametersShouldHug ,
  filterTernaryAttributes ,
  filterFragileMatchAttributes ,
  isJsxExpression ,
  hasJsxAttribute ,
  shouldIndentBinaryExpr ,
  shouldInlineRhsBinaryExpr ,
  isPrintableAttribute ,
  hasPrintableAttributes ,
  filterPrintableAttributes ,
  partitionPrintableAttributes ,
  requiresSpecialCallbackPrintingLastArg ,
  requiresSpecialCallbackPrintingFirstArg ,
  modExprApply ,
  modExprFunctor ,
  collectPatternsFromListConstruct ,
  hasTemplateLiteralAttr ,
  isTemplateLiteral ,
  collectOrPatternChain ,
  isSinglePipeExpr ,
  isUnderscoreApplySugar ,
  isRewrittenUnderscoreApplySugar ,
  
}
/* No side effect */
