// Generated by ReScript, PLEASE EDIT WITH CARE

import * as Char from "rescript/lib/es6/char.js";
import * as List from "rescript/lib/es6/list.js";
import * as Bytes from "rescript/lib/es6/bytes.js";
import * as Curry from "rescript/lib/es6/curry.js";
import * as $$String from "rescript/lib/es6/string.js";
import * as Hashtbl from "rescript/lib/es6/hashtbl.js";
import * as Res_doc from "./res_doc.js";
import * as $$Location from "./location.js";
import * as Res_utf8 from "./res_utf8.js";
import * as Longident from "./longident.js";
import * as Res_token from "./res_token.js";
import * as Res_parens from "./res_parens.js";
import * as Res_comment from "./res_comment.js";
import * as Caml_js_exceptions from "rescript/lib/es6/caml_js_exceptions.js";
import * as Res_comments_table from "./res_comments_table.js";
import * as Res_parsetree_viewer from "./res_parsetree_viewer.js";

function convertBsExternalAttribute(x) {
  switch (x) {
    case "bs.as" :
        return "as";
    case "bs.deriving" :
        return "deriving";
    case "bs.get" :
        return "get";
    case "bs.get_index" :
        return "get_index";
    case "bs.ignore" :
        return "ignore";
    case "bs.inline" :
        return "inline";
    case "bs.int" :
        return "int";
    case "bs.meth" :
        return "meth";
    case "bs.module" :
        return "module";
    case "bs.new" :
        return "new";
    case "bs.obj" :
        return "obj";
    case "bs.optional" :
        return "optional";
    case "bs.return" :
        return "return";
    case "bs.scope" :
        return "scope";
    case "bs.send" :
        return "send";
    case "bs.set" :
        return "set";
    case "bs.set_index" :
        return "set_index";
    case "bs.string" :
        return "string";
    case "bs.this" :
        return "this";
    case "bs.uncurry" :
        return "uncurry";
    case "bs.unwrap" :
        return "unwrap";
    case "bs.val" :
        return "val";
    case "bs.splice" :
    case "bs.variadic" :
        return "variadic";
    default:
      return x;
  }
}

function convertBsExtension(x) {
  switch (x) {
    case "bs.debugger" :
        return "debugger";
    case "bs.obj" :
        return "obj";
    case "bs.external" :
    case "bs.raw" :
        return "raw";
    case "bs.re" :
        return "re";
    default:
      return x;
  }
}

function addParens(doc) {
  return Res_doc.group(Res_doc.concat({
                  hd: Res_doc.lparen,
                  tl: {
                    hd: Res_doc.indent(Res_doc.concat({
                              hd: Res_doc.softLine,
                              tl: {
                                hd: doc,
                                tl: /* [] */0
                              }
                            })),
                    tl: {
                      hd: Res_doc.softLine,
                      tl: {
                        hd: Res_doc.rparen,
                        tl: /* [] */0
                      }
                    }
                  }
                }));
}

function addBraces(doc) {
  return Res_doc.group(Res_doc.concat({
                  hd: Res_doc.lbrace,
                  tl: {
                    hd: Res_doc.indent(Res_doc.concat({
                              hd: Res_doc.softLine,
                              tl: {
                                hd: doc,
                                tl: /* [] */0
                              }
                            })),
                    tl: {
                      hd: Res_doc.softLine,
                      tl: {
                        hd: Res_doc.rbrace,
                        tl: /* [] */0
                      }
                    }
                  }
                }));
}

function getFirstLeadingComment(tbl, loc) {
  var val;
  try {
    val = Hashtbl.find(tbl.leading, loc);
  }
  catch (raw_exn){
    var exn = Caml_js_exceptions.internalToOCamlException(raw_exn);
    if (exn.RE_EXN_ID === "Not_found") {
      return ;
    }
    throw exn;
  }
  if (val) {
    return val.hd;
  }
  
}

function hasLeadingLineComment(tbl, loc) {
  var comment = getFirstLeadingComment(tbl, loc);
  if (comment !== undefined) {
    return Res_comment.isSingleLineComment(comment);
  } else {
    return false;
  }
}

function hasCommentBelow(tbl, loc) {
  var val;
  try {
    val = Hashtbl.find(tbl.trailing, loc);
  }
  catch (raw_exn){
    var exn = Caml_js_exceptions.internalToOCamlException(raw_exn);
    if (exn.RE_EXN_ID === "Not_found") {
      return false;
    }
    throw exn;
  }
  if (!val) {
    return false;
  }
  var commentLoc = Res_comment.loc(val.hd);
  return commentLoc.loc_start.pos_lnum > loc.loc_end.pos_lnum;
}

function printMultilineCommentContent(txt) {
  var indentStars = function (_lines, _acc) {
    while(true) {
      var acc = _acc;
      var lines = _lines;
      if (!lines) {
        return Res_doc.nil;
      }
      var lines$1 = lines.tl;
      var lastLine = lines.hd;
      if (lines$1) {
        var line = $$String.trim(lastLine);
        if (line !== "" && line[0] === "*") {
          var doc = Res_doc.text(" " + line);
          _acc = {
            hd: Res_doc.hardLine,
            tl: {
              hd: doc,
              tl: acc
            }
          };
          _lines = lines$1;
          continue ;
        }
        var len = txt.length;
        var trailingSpace = len > 0 && txt[len - 1 | 0] === " " ? Res_doc.space : Res_doc.nil;
        var content = Res_comment.trimSpaces(txt);
        return Res_doc.concat({
                    hd: Res_doc.text(content),
                    tl: {
                      hd: trailingSpace,
                      tl: /* [] */0
                    }
                  });
      }
      var line$1 = $$String.trim(lastLine);
      var doc$1 = Res_doc.text(" " + line$1);
      var trailingSpace$1 = line$1 === "" ? Res_doc.nil : Res_doc.space;
      return Res_doc.concat(List.rev({
                      hd: trailingSpace$1,
                      tl: {
                        hd: doc$1,
                        tl: acc
                      }
                    }));
    };
  };
  var lines = $$String.split_on_char(/* '\n' */10, txt);
  if (!lines) {
    return Res_doc.text("/* */");
  }
  var rest = lines.tl;
  var line = lines.hd;
  if (!rest) {
    return Res_doc.concat({
                hd: Res_doc.text("/* "),
                tl: {
                  hd: Res_doc.text(Res_comment.trimSpaces(line)),
                  tl: {
                    hd: Res_doc.text(" */"),
                    tl: /* [] */0
                  }
                }
              });
  }
  var firstLine = Res_comment.trimSpaces(line);
  var tmp;
  switch (firstLine) {
    case "" :
    case "*" :
        tmp = Res_doc.nil;
        break;
    default:
      tmp = Res_doc.space;
  }
  return Res_doc.concat({
              hd: Res_doc.text("/*"),
              tl: {
                hd: tmp,
                tl: {
                  hd: indentStars(rest, {
                        hd: Res_doc.hardLine,
                        tl: {
                          hd: Res_doc.text(firstLine),
                          tl: /* [] */0
                        }
                      }),
                  tl: {
                    hd: Res_doc.text("*/"),
                    tl: /* [] */0
                  }
                }
              }
            });
}

function printTrailingComment(prevLoc, nodeLoc, comment) {
  var singleLine = Res_comment.isSingleLineComment(comment);
  var txt = Res_comment.txt(comment);
  var content = singleLine ? Res_doc.text("//" + txt) : printMultilineCommentContent(txt);
  var cmtStart = Res_comment.loc(comment).loc_start;
  var diff = cmtStart.pos_lnum - prevLoc.loc_end.pos_lnum | 0;
  var isBelow = Res_comment.loc(comment).loc_start.pos_lnum > nodeLoc.loc_end.pos_lnum;
  if (diff > 0 || isBelow) {
    return Res_doc.concat({
                hd: Res_doc.breakParent,
                tl: {
                  hd: Res_doc.lineSuffix(Res_doc.concat({
                            hd: Res_doc.hardLine,
                            tl: {
                              hd: diff > 1 ? Res_doc.hardLine : Res_doc.nil,
                              tl: {
                                hd: content,
                                tl: /* [] */0
                              }
                            }
                          })),
                  tl: /* [] */0
                }
              });
  } else if (singleLine) {
    return Res_doc.lineSuffix(Res_doc.concat({
                    hd: Res_doc.space,
                    tl: {
                      hd: content,
                      tl: /* [] */0
                    }
                  }));
  } else {
    return Res_doc.concat({
                hd: Res_doc.space,
                tl: {
                  hd: content,
                  tl: /* [] */0
                }
              });
  }
}

function printLeadingComment(nextComment, comment) {
  var singleLine = Res_comment.isSingleLineComment(comment);
  var txt = Res_comment.txt(comment);
  var content = singleLine ? Res_doc.text("//" + txt) : printMultilineCommentContent(txt);
  var tmp;
  if (nextComment !== undefined) {
    var nextLoc = Res_comment.loc(nextComment);
    var currLoc = Res_comment.loc(comment);
    var diff = nextLoc.loc_start.pos_lnum - currLoc.loc_end.pos_lnum | 0;
    var nextSingleLine = Res_comment.isSingleLineComment(nextComment);
    tmp = singleLine && nextSingleLine ? (
        diff > 1 ? Res_doc.hardLine : Res_doc.nil
      ) : (
        singleLine && !nextSingleLine ? (
            diff > 1 ? Res_doc.hardLine : Res_doc.nil
          ) : (
            diff > 1 ? Res_doc.concat({
                    hd: Res_doc.hardLine,
                    tl: {
                      hd: Res_doc.hardLine,
                      tl: /* [] */0
                    }
                  }) : (
                diff === 1 ? Res_doc.hardLine : Res_doc.space
              )
          )
      );
  } else {
    tmp = Res_doc.nil;
  }
  var separator = Res_doc.concat({
        hd: singleLine ? Res_doc.concat({
                hd: Res_doc.hardLine,
                tl: {
                  hd: Res_doc.breakParent,
                  tl: /* [] */0
                }
              }) : Res_doc.nil,
        tl: {
          hd: tmp,
          tl: /* [] */0
        }
      });
  return Res_doc.concat({
              hd: content,
              tl: {
                hd: separator,
                tl: /* [] */0
              }
            });
}

function printCommentsInside(cmtTbl, loc) {
  var loop = function (_acc, _comments) {
    while(true) {
      var comments = _comments;
      var acc = _acc;
      if (!comments) {
        return Res_doc.nil;
      }
      var rest = comments.tl;
      var comment = comments.hd;
      if (rest) {
        var cmtDoc = printLeadingComment(rest.hd, comment);
        _comments = rest;
        _acc = {
          hd: cmtDoc,
          tl: acc
        };
        continue ;
      }
      var cmtDoc$1 = printLeadingComment(undefined, comment);
      return Res_doc.group(Res_doc.concat({
                      hd: Res_doc.concat(List.rev({
                                hd: cmtDoc$1,
                                tl: acc
                              })),
                      tl: /* [] */0
                    }));
    };
  };
  var comments;
  try {
    comments = Hashtbl.find(cmtTbl.inside, loc);
  }
  catch (raw_exn){
    var exn = Caml_js_exceptions.internalToOCamlException(raw_exn);
    if (exn.RE_EXN_ID === "Not_found") {
      return Res_doc.nil;
    }
    throw exn;
  }
  Hashtbl.remove(cmtTbl.inside, loc);
  return Res_doc.group(loop(/* [] */0, comments));
}

function printLeadingComments(node, tbl, loc) {
  var comments;
  try {
    comments = Hashtbl.find(tbl, loc);
  }
  catch (raw_exn){
    var exn = Caml_js_exceptions.internalToOCamlException(raw_exn);
    if (exn.RE_EXN_ID === "Not_found") {
      return node;
    }
    throw exn;
  }
  Hashtbl.remove(tbl, loc);
  var _acc = /* [] */0;
  var _comments = comments;
  while(true) {
    var comments$1 = _comments;
    var acc = _acc;
    if (!comments$1) {
      return node;
    }
    var rest = comments$1.tl;
    var comment = comments$1.hd;
    if (rest) {
      var cmtDoc = printLeadingComment(rest.hd, comment);
      _comments = rest;
      _acc = {
        hd: cmtDoc,
        tl: acc
      };
      continue ;
    }
    var cmtDoc$1 = printLeadingComment(undefined, comment);
    var diff = loc.loc_start.pos_lnum - Res_comment.loc(comment).loc_end.pos_lnum | 0;
    var separator = Res_comment.isSingleLineComment(comment) ? (
        diff > 1 ? Res_doc.hardLine : Res_doc.nil
      ) : (
        diff === 0 ? Res_doc.space : (
            diff > 1 ? Res_doc.concat({
                    hd: Res_doc.hardLine,
                    tl: {
                      hd: Res_doc.hardLine,
                      tl: /* [] */0
                    }
                  }) : Res_doc.hardLine
          )
      );
    return Res_doc.group(Res_doc.concat({
                    hd: Res_doc.concat(List.rev({
                              hd: cmtDoc$1,
                              tl: acc
                            })),
                    tl: {
                      hd: separator,
                      tl: {
                        hd: node,
                        tl: /* [] */0
                      }
                    }
                  }));
  };
}

function printTrailingComments(node, tbl, loc) {
  var loop = function (_prev, _acc, _comments) {
    while(true) {
      var comments = _comments;
      var acc = _acc;
      var prev = _prev;
      if (!comments) {
        return Res_doc.concat(List.rev(acc));
      }
      var comment = comments.hd;
      var cmtDoc = printTrailingComment(prev, loc, comment);
      _comments = comments.tl;
      _acc = {
        hd: cmtDoc,
        tl: acc
      };
      _prev = Res_comment.loc(comment);
      continue ;
    };
  };
  var comments;
  try {
    comments = Hashtbl.find(tbl, loc);
  }
  catch (raw_exn){
    var exn = Caml_js_exceptions.internalToOCamlException(raw_exn);
    if (exn.RE_EXN_ID === "Not_found") {
      return node;
    }
    throw exn;
  }
  if (!comments) {
    return node;
  }
  Hashtbl.remove(tbl, loc);
  var cmtsDoc = loop(loc, /* [] */0, comments);
  return Res_doc.concat({
              hd: node,
              tl: {
                hd: cmtsDoc,
                tl: /* [] */0
              }
            });
}

function printComments(doc, tbl, loc) {
  var docWithLeadingComments = printLeadingComments(doc, tbl.leading, loc);
  return printTrailingComments(docWithLeadingComments, tbl.trailing, loc);
}

function printList(getLoc, nodes, print, forceBreakOpt, t) {
  var forceBreak = forceBreakOpt !== undefined ? forceBreakOpt : false;
  var loop = function (_prevLoc, _acc, _nodes) {
    while(true) {
      var nodes = _nodes;
      var acc = _acc;
      var prevLoc = _prevLoc;
      if (!nodes) {
        return [
                prevLoc,
                Res_doc.concat(List.rev(acc))
              ];
      }
      var node = nodes.hd;
      var loc = Curry._1(getLoc, node);
      var comment = getFirstLeadingComment(t, loc);
      var startPos = comment !== undefined ? Res_comment.loc(comment).loc_start : loc.loc_start;
      var sep = (startPos.pos_lnum - prevLoc.loc_end.pos_lnum | 0) > 1 ? Res_doc.concat({
              hd: Res_doc.hardLine,
              tl: {
                hd: Res_doc.hardLine,
                tl: /* [] */0
              }
            }) : Res_doc.hardLine;
      var doc = printComments(Curry._2(print, node, t), t, loc);
      _nodes = nodes.tl;
      _acc = {
        hd: doc,
        tl: {
          hd: sep,
          tl: acc
        }
      };
      _prevLoc = loc;
      continue ;
    };
  };
  if (!nodes) {
    return Res_doc.nil;
  }
  var node = nodes.hd;
  var firstLoc = Curry._1(getLoc, node);
  var doc = printComments(Curry._2(print, node, t), t, firstLoc);
  var match = loop(firstLoc, {
        hd: doc,
        tl: /* [] */0
      }, nodes.tl);
  var forceBreak$1 = forceBreak || firstLoc.loc_start.pos_lnum !== match[0].loc_end.pos_lnum;
  return Res_doc.breakableGroup(forceBreak$1, match[1]);
}

function printListi(getLoc, nodes, print, forceBreakOpt, t) {
  var forceBreak = forceBreakOpt !== undefined ? forceBreakOpt : false;
  var loop = function (_i, _prevLoc, _acc, _nodes) {
    while(true) {
      var nodes = _nodes;
      var acc = _acc;
      var prevLoc = _prevLoc;
      var i = _i;
      if (!nodes) {
        return [
                prevLoc,
                Res_doc.concat(List.rev(acc))
              ];
      }
      var node = nodes.hd;
      var loc = Curry._1(getLoc, node);
      var comment = getFirstLeadingComment(t, loc);
      var startPos = comment !== undefined ? Res_comment.loc(comment).loc_start : loc.loc_start;
      var sep = (startPos.pos_lnum - prevLoc.loc_end.pos_lnum | 0) > 1 ? Res_doc.concat({
              hd: Res_doc.hardLine,
              tl: {
                hd: Res_doc.hardLine,
                tl: /* [] */0
              }
            }) : Res_doc.line;
      var doc = printComments(Curry._3(print, node, t, i), t, loc);
      _nodes = nodes.tl;
      _acc = {
        hd: doc,
        tl: {
          hd: sep,
          tl: acc
        }
      };
      _prevLoc = loc;
      _i = i + 1 | 0;
      continue ;
    };
  };
  if (!nodes) {
    return Res_doc.nil;
  }
  var node = nodes.hd;
  var firstLoc = Curry._1(getLoc, node);
  var doc = printComments(Curry._3(print, node, t, 0), t, firstLoc);
  var match = loop(1, firstLoc, {
        hd: doc,
        tl: /* [] */0
      }, nodes.tl);
  var forceBreak$1 = forceBreak || firstLoc.loc_start.pos_lnum !== match[0].loc_end.pos_lnum;
  return Res_doc.breakableGroup(forceBreak$1, match[1]);
}

function printLongidentAux(_accu, _x) {
  while(true) {
    var x = _x;
    var accu = _accu;
    switch (x.TAG | 0) {
      case /* Lident */0 :
          return {
                  hd: Res_doc.text(x._0),
                  tl: accu
                };
      case /* Ldot */1 :
          _x = x._0;
          _accu = {
            hd: Res_doc.text(x._1),
            tl: accu
          };
          continue ;
      case /* Lapply */2 :
          var d1 = Res_doc.join(Res_doc.dot, printLongidentAux(/* [] */0, x._0));
          var d2 = Res_doc.join(Res_doc.dot, printLongidentAux(/* [] */0, x._1));
          return {
                  hd: Res_doc.concat({
                        hd: d1,
                        tl: {
                          hd: Res_doc.lparen,
                          tl: {
                            hd: d2,
                            tl: {
                              hd: Res_doc.rparen,
                              tl: /* [] */0
                            }
                          }
                        }
                      }),
                  tl: accu
                };
      
    }
  };
}

function printLongident(x) {
  switch (x.TAG | 0) {
    case /* Lident */0 :
        return Res_doc.text(x._0);
    case /* Ldot */1 :
    case /* Lapply */2 :
        return Res_doc.join(Res_doc.dot, printLongidentAux(/* [] */0, x));
    
  }
}

function classifyIdentContent(allowUidentOpt, txt) {
  var allowUident = allowUidentOpt !== undefined ? allowUidentOpt : false;
  if (Res_token.isKeywordTxt(txt)) {
    return /* ExoticIdent */0;
  }
  var len = txt.length;
  var _i = 0;
  while(true) {
    var i = _i;
    if (i === len) {
      return /* NormalIdent */1;
    }
    if (i === 0) {
      var match = txt.charCodeAt(i);
      if (match > 122 || match < 95) {
        if (match > 90 || match < 65) {
          return /* ExoticIdent */0;
        }
        if (!allowUident) {
          return /* ExoticIdent */0;
        }
        _i = i + 1 | 0;
        continue ;
      }
      if (match === 96) {
        return /* ExoticIdent */0;
      }
      _i = i + 1 | 0;
      continue ;
    }
    var match$1 = txt.charCodeAt(i);
    if (match$1 >= 65) {
      if (match$1 > 96 || match$1 < 91) {
        if (match$1 >= 123) {
          return /* ExoticIdent */0;
        }
        _i = i + 1 | 0;
        continue ;
      }
      if (match$1 !== 95) {
        return /* ExoticIdent */0;
      }
      _i = i + 1 | 0;
      continue ;
    }
    if (match$1 >= 48) {
      if (match$1 >= 58) {
        return /* ExoticIdent */0;
      }
      _i = i + 1 | 0;
      continue ;
    }
    if (match$1 !== 39) {
      return /* ExoticIdent */0;
    }
    _i = i + 1 | 0;
    continue ;
  };
}

function printIdentLike(allowUident, txt) {
  var match = classifyIdentContent(allowUident, txt);
  if (match) {
    return Res_doc.text(txt);
  } else {
    return Res_doc.concat({
                hd: Res_doc.text("\\\""),
                tl: {
                  hd: Res_doc.text(txt),
                  tl: {
                    hd: Res_doc.text("\""),
                    tl: /* [] */0
                  }
                }
              });
  }
}

function unsafe_for_all_range(s, _start, finish, p) {
  while(true) {
    var start = _start;
    if (start > finish) {
      return true;
    }
    if (!Curry._1(p, s.charCodeAt(start))) {
      return false;
    }
    _start = start + 1 | 0;
    continue ;
  };
}

function for_all_from(s, start, p) {
  var len = s.length;
  return unsafe_for_all_range(s, start, len - 1 | 0, p);
}

function isValidNumericPolyvarNumber(x) {
  var len = x.length;
  if (len <= 0) {
    return false;
  }
  var a = x.charCodeAt(0);
  if (a <= 57) {
    if (len > 1) {
      if (a > 48) {
        return for_all_from(x, 1, (function (x) {
                      return !(x > 57 || x < 48);
                    }));
      } else {
        return false;
      }
    } else {
      return a >= 48;
    }
  } else {
    return false;
  }
}

function printPolyVarIdent(txt) {
  if (isValidNumericPolyvarNumber(txt)) {
    return Res_doc.text(txt);
  }
  var match = classifyIdentContent(true, txt);
  if (match && txt !== "") {
    return Res_doc.text(txt);
  } else {
    return Res_doc.concat({
                hd: Res_doc.text("\""),
                tl: {
                  hd: Res_doc.text(txt),
                  tl: {
                    hd: Res_doc.text("\""),
                    tl: /* [] */0
                  }
                }
              });
  }
}

function printLident(l) {
  var flatLidOpt = function (lid) {
    var _accu = /* [] */0;
    var _x = lid;
    while(true) {
      var x = _x;
      var accu = _accu;
      switch (x.TAG | 0) {
        case /* Lident */0 :
            return {
                    hd: x._0,
                    tl: accu
                  };
        case /* Ldot */1 :
            _x = x._0;
            _accu = {
              hd: x._1,
              tl: accu
            };
            continue ;
        case /* Lapply */2 :
            return ;
        
      }
    };
  };
  switch (l.TAG | 0) {
    case /* Lident */0 :
        return printIdentLike(undefined, l._0);
    case /* Ldot */1 :
        var txts = flatLidOpt(l._0);
        if (txts !== undefined) {
          return Res_doc.concat({
                      hd: Res_doc.join(Res_doc.dot, List.map(Res_doc.text, txts)),
                      tl: {
                        hd: Res_doc.dot,
                        tl: {
                          hd: printIdentLike(undefined, l._1),
                          tl: /* [] */0
                        }
                      }
                    });
        } else {
          return Res_doc.text("printLident: Longident.Lapply is not supported");
        }
    case /* Lapply */2 :
        return Res_doc.text("printLident: Longident.Lapply is not supported");
    
  }
}

function printLongidentLocation(l, cmtTbl) {
  var doc = printLongident(l.txt);
  return printComments(doc, cmtTbl, l.loc);
}

function printLidentPath(path, cmtTbl) {
  var doc = printLident(path.txt);
  return printComments(doc, cmtTbl, path.loc);
}

function printIdentPath(path, cmtTbl) {
  var doc = printLident(path.txt);
  return printComments(doc, cmtTbl, path.loc);
}

function printStringLoc(sloc, cmtTbl) {
  var doc = printIdentLike(undefined, sloc.txt);
  return printComments(doc, cmtTbl, sloc.loc);
}

function printStringContents(txt) {
  var lines = $$String.split_on_char(/* '\n' */10, txt);
  return Res_doc.join(Res_doc.literalLine, List.map(Res_doc.text, lines));
}

function printConstant(templateLiteralOpt, c) {
  var templateLiteral = templateLiteralOpt !== undefined ? templateLiteralOpt : false;
  switch (c.TAG | 0) {
    case /* Pconst_integer */0 :
        var suffix = c._1;
        var s = c._0;
        if (suffix !== undefined) {
          return Res_doc.text(s + Char.escaped(suffix));
        } else {
          return Res_doc.text(s);
        }
    case /* Pconst_char */1 :
        var c$1 = c._0;
        var str;
        var exit = 0;
        if (c$1 >= 40) {
          if (c$1 !== 92) {
            if (c$1 >= 127) {
              str = Res_utf8.encodeCodePoint(c$1);
            } else {
              exit = 1;
            }
          } else {
            str = "\\\\";
          }
        } else if (c$1 >= 32) {
          if (c$1 >= 39) {
            str = "\\'";
          } else {
            exit = 1;
          }
        } else if (c$1 >= 14) {
          str = Res_utf8.encodeCodePoint(c$1);
        } else {
          switch (c$1) {
            case 8 :
                str = "\\b";
                break;
            case 9 :
                str = "\\t";
                break;
            case 10 :
                str = "\\n";
                break;
            case 0 :
            case 1 :
            case 2 :
            case 3 :
            case 4 :
            case 5 :
            case 6 :
            case 7 :
            case 11 :
            case 12 :
                str = Res_utf8.encodeCodePoint(c$1);
                break;
            case 13 :
                str = "\\r";
                break;
            
          }
        }
        if (exit === 1) {
          var s$1 = [0];
          s$1[0] = c$1;
          str = Bytes.unsafe_to_string(s$1);
        }
        return Res_doc.text("'" + (str + "'"));
    case /* Pconst_string */2 :
        var prefix = c._1;
        var txt = c._0;
        if (prefix === undefined) {
          return Res_doc.concat({
                      hd: Res_doc.text("\""),
                      tl: {
                        hd: printStringContents(txt),
                        tl: {
                          hd: Res_doc.text("\""),
                          tl: /* [] */0
                        }
                      }
                    });
        }
        if (prefix === "INTERNAL_RES_CHAR_CONTENTS") {
          return Res_doc.concat({
                      hd: Res_doc.text("'"),
                      tl: {
                        hd: Res_doc.text(txt),
                        tl: {
                          hd: Res_doc.text("'"),
                          tl: /* [] */0
                        }
                      }
                    });
        }
        var match = templateLiteral ? [
            "`",
            "`"
          ] : [
            "\"",
            "\""
          ];
        return Res_doc.concat({
                    hd: prefix === "js" ? Res_doc.nil : Res_doc.text(prefix),
                    tl: {
                      hd: Res_doc.text(match[0]),
                      tl: {
                        hd: printStringContents(txt),
                        tl: {
                          hd: Res_doc.text(match[1]),
                          tl: /* [] */0
                        }
                      }
                    }
                  });
    case /* Pconst_float */3 :
        return Res_doc.text(c._0);
    
  }
}

function printStructure(s, t) {
  if (s) {
    return printList((function (s) {
                  return s.pstr_loc;
                }), s, printStructureItem, undefined, t);
  } else {
    return printCommentsInside(t, $$Location.none);
  }
}

function printStructureItem(si, cmtTbl) {
  var valueDescription = si.pstr_desc;
  switch (valueDescription.TAG | 0) {
    case /* Pstr_eval */0 :
        var expr = valueDescription._0;
        var doc = printExpressionWithComments(expr, cmtTbl);
        var braces = Res_parens.structureExpr(expr);
        var exprDoc = typeof braces === "number" ? (
            braces !== 0 ? doc : addParens(doc)
          ) : printBraces(doc, expr, braces._0);
        return Res_doc.concat({
                    hd: printAttributes(undefined, undefined, valueDescription._1, cmtTbl),
                    tl: {
                      hd: exprDoc,
                      tl: /* [] */0
                    }
                  });
    case /* Pstr_value */1 :
        var recFlag = valueDescription._0 ? Res_doc.text("rec ") : Res_doc.nil;
        return printValueBindings(recFlag, valueDescription._1, cmtTbl);
    case /* Pstr_primitive */2 :
        return printValueDescription(valueDescription._0, cmtTbl);
    case /* Pstr_type */3 :
        var recFlag$1 = valueDescription._0 ? Res_doc.text("rec ") : Res_doc.nil;
        return printTypeDeclarations(recFlag$1, valueDescription._1, cmtTbl);
    case /* Pstr_typext */4 :
        return printTypeExtension(valueDescription._0, cmtTbl);
    case /* Pstr_exception */5 :
        return printExceptionDef(valueDescription._0, cmtTbl);
    case /* Pstr_module */6 :
        return printModuleBinding(false, valueDescription._0, cmtTbl, 0);
    case /* Pstr_recmodule */7 :
        return printListi((function (mb) {
                      return mb.pmb_loc;
                    }), valueDescription._0, (function (param, param$1, param$2) {
                      return printModuleBinding(true, param, param$1, param$2);
                    }), undefined, cmtTbl);
    case /* Pstr_modtype */8 :
        return printModuleTypeDeclaration(valueDescription._0, cmtTbl);
    case /* Pstr_open */9 :
        return printOpenDescription(valueDescription._0, cmtTbl);
    case /* Pstr_class */10 :
    case /* Pstr_class_type */11 :
        return Res_doc.nil;
    case /* Pstr_include */12 :
        return printIncludeDeclaration(valueDescription._0, cmtTbl);
    case /* Pstr_attribute */13 :
        return Res_doc.concat({
                    hd: Res_doc.text("@"),
                    tl: {
                      hd: printAttribute(valueDescription._0, cmtTbl),
                      tl: /* [] */0
                    }
                  });
    case /* Pstr_extension */14 :
        return Res_doc.concat({
                    hd: printAttributes(undefined, undefined, valueDescription._1, cmtTbl),
                    tl: {
                      hd: Res_doc.concat({
                            hd: printExtension(true, valueDescription._0, cmtTbl),
                            tl: /* [] */0
                          }),
                      tl: /* [] */0
                    }
                  });
    
  }
}

function printTypeExtension(te, cmtTbl) {
  var prefix = Res_doc.text("type ");
  var name = printLidentPath(te.ptyext_path, cmtTbl);
  var typeParams = printTypeParams(te.ptyext_params, cmtTbl);
  var ecs = te.ptyext_constructors;
  var match = List.rev(ecs);
  var forceBreak;
  if (ecs && match) {
    var first = ecs.hd;
    forceBreak = first.pext_loc.loc_start.pos_lnum > te.ptyext_path.loc.loc_end.pos_lnum || first.pext_loc.loc_start.pos_lnum < match.hd.pext_loc.loc_end.pos_lnum;
  } else {
    forceBreak = false;
  }
  var match$1 = te.ptyext_private;
  var privateFlag = match$1 ? Res_doc.nil : Res_doc.concat({
          hd: Res_doc.text("private"),
          tl: {
            hd: Res_doc.line,
            tl: /* [] */0
          }
        });
  var rows = printListi((function (n) {
          return n.pext_loc;
        }), ecs, printExtensionConstructor, forceBreak, cmtTbl);
  var extensionConstructors = Res_doc.breakableGroup(forceBreak, Res_doc.indent(Res_doc.concat({
                hd: Res_doc.line,
                tl: {
                  hd: privateFlag,
                  tl: {
                    hd: rows,
                    tl: /* [] */0
                  }
                }
              })));
  return Res_doc.group(Res_doc.concat({
                  hd: printAttributes(te.ptyext_path.loc, undefined, te.ptyext_attributes, cmtTbl),
                  tl: {
                    hd: prefix,
                    tl: {
                      hd: name,
                      tl: {
                        hd: typeParams,
                        tl: {
                          hd: Res_doc.text(" +="),
                          tl: {
                            hd: extensionConstructors,
                            tl: /* [] */0
                          }
                        }
                      }
                    }
                  }
                }));
}

function printModuleBinding(isRec, moduleBinding, cmtTbl, i) {
  var prefix = i === 0 ? Res_doc.concat({
          hd: Res_doc.text("module "),
          tl: {
            hd: isRec ? Res_doc.text("rec ") : Res_doc.nil,
            tl: /* [] */0
          }
        }) : Res_doc.text("and ");
  var modExpr = moduleBinding.pmb_expr;
  var match = modExpr.pmod_desc;
  var match$1;
  match$1 = match.TAG === /* Pmod_constraint */4 ? [
      printModExpr(match._0, cmtTbl),
      Res_doc.concat({
            hd: Res_doc.text(": "),
            tl: {
              hd: printModType(match._1, cmtTbl),
              tl: /* [] */0
            }
          })
    ] : [
      printModExpr(modExpr, cmtTbl),
      Res_doc.nil
    ];
  var doc = Res_doc.text(moduleBinding.pmb_name.txt);
  var modName = printComments(doc, cmtTbl, moduleBinding.pmb_name.loc);
  var doc$1 = Res_doc.concat({
        hd: printAttributes(moduleBinding.pmb_name.loc, undefined, moduleBinding.pmb_attributes, cmtTbl),
        tl: {
          hd: prefix,
          tl: {
            hd: modName,
            tl: {
              hd: match$1[1],
              tl: {
                hd: Res_doc.text(" = "),
                tl: {
                  hd: match$1[0],
                  tl: /* [] */0
                }
              }
            }
          }
        }
      });
  return printComments(doc$1, cmtTbl, moduleBinding.pmb_loc);
}

function printModuleTypeDeclaration(modTypeDecl, cmtTbl) {
  var doc = Res_doc.text(modTypeDecl.pmtd_name.txt);
  var modName = printComments(doc, cmtTbl, modTypeDecl.pmtd_name.loc);
  var modType = modTypeDecl.pmtd_type;
  return Res_doc.concat({
              hd: printAttributes(undefined, undefined, modTypeDecl.pmtd_attributes, cmtTbl),
              tl: {
                hd: Res_doc.text("module type "),
                tl: {
                  hd: modName,
                  tl: {
                    hd: modType !== undefined ? Res_doc.concat({
                            hd: Res_doc.text(" = "),
                            tl: {
                              hd: printModType(modType, cmtTbl),
                              tl: /* [] */0
                            }
                          }) : Res_doc.nil,
                    tl: /* [] */0
                  }
                }
              }
            });
}

function printModType(modType, cmtTbl) {
  var longident = modType.pmty_desc;
  var modTypeDoc;
  switch (longident.TAG | 0) {
    case /* Pmty_ident */0 :
        var longident$1 = longident._0;
        modTypeDoc = Res_doc.concat({
              hd: printAttributes(longident$1.loc, undefined, modType.pmty_attributes, cmtTbl),
              tl: {
                hd: printLongidentLocation(longident$1, cmtTbl),
                tl: /* [] */0
              }
            });
        break;
    case /* Pmty_signature */1 :
        var signature = longident._0;
        if (signature) {
          var signatureDoc = Res_doc.breakableGroup(true, Res_doc.concat({
                    hd: Res_doc.lbrace,
                    tl: {
                      hd: Res_doc.indent(Res_doc.concat({
                                hd: Res_doc.line,
                                tl: {
                                  hd: printSignature(signature, cmtTbl),
                                  tl: /* [] */0
                                }
                              })),
                      tl: {
                        hd: Res_doc.line,
                        tl: {
                          hd: Res_doc.rbrace,
                          tl: /* [] */0
                        }
                      }
                    }
                  }));
          modTypeDoc = Res_doc.concat({
                hd: printAttributes(undefined, undefined, modType.pmty_attributes, cmtTbl),
                tl: {
                  hd: signatureDoc,
                  tl: /* [] */0
                }
              });
        } else {
          var shouldBreak = modType.pmty_loc.loc_start.pos_lnum < modType.pmty_loc.loc_end.pos_lnum;
          modTypeDoc = Res_doc.breakableGroup(shouldBreak, Res_doc.concat({
                    hd: Res_doc.lbrace,
                    tl: {
                      hd: Res_doc.indent(Res_doc.concat({
                                hd: Res_doc.softLine,
                                tl: {
                                  hd: printCommentsInside(cmtTbl, modType.pmty_loc),
                                  tl: /* [] */0
                                }
                              })),
                      tl: {
                        hd: Res_doc.softLine,
                        tl: {
                          hd: Res_doc.rbrace,
                          tl: /* [] */0
                        }
                      }
                    }
                  }));
        }
        break;
    case /* Pmty_functor */2 :
        var match = Res_parsetree_viewer.functorType(modType);
        var returnType = match[1];
        var parameters = match[0];
        var parametersDoc;
        var exit = 0;
        if (parameters) {
          var match$1 = parameters.hd;
          var match$2 = match$1[1];
          if (match$2.txt === "_") {
            var modType$1 = match$1[2];
            if (modType$1 !== undefined && !parameters.tl) {
              var loc = match$2.loc;
              var cmtLoc_loc_start = loc.loc_start;
              var cmtLoc_loc_end = modType$1.pmty_loc.loc_end;
              var cmtLoc_loc_ghost = loc.loc_ghost;
              var cmtLoc = {
                loc_start: cmtLoc_loc_start,
                loc_end: cmtLoc_loc_end,
                loc_ghost: cmtLoc_loc_ghost
              };
              var attrs = printAttributes(undefined, undefined, match$1[0], cmtTbl);
              var doc = Res_doc.concat({
                    hd: attrs,
                    tl: {
                      hd: printModType(modType$1, cmtTbl),
                      tl: /* [] */0
                    }
                  });
              parametersDoc = printComments(doc, cmtTbl, cmtLoc);
            } else {
              exit = 1;
            }
          } else {
            exit = 1;
          }
        } else {
          parametersDoc = Res_doc.nil;
        }
        if (exit === 1) {
          parametersDoc = Res_doc.group(Res_doc.concat({
                    hd: Res_doc.lparen,
                    tl: {
                      hd: Res_doc.indent(Res_doc.concat({
                                hd: Res_doc.softLine,
                                tl: {
                                  hd: Res_doc.join(Res_doc.concat({
                                            hd: Res_doc.comma,
                                            tl: {
                                              hd: Res_doc.line,
                                              tl: /* [] */0
                                            }
                                          }), List.map((function (param) {
                                              var modType = param[2];
                                              var lbl = param[1];
                                              var cmtLoc;
                                              if (modType !== undefined) {
                                                var init = lbl.loc;
                                                cmtLoc = {
                                                  loc_start: init.loc_start,
                                                  loc_end: modType.pmty_loc.loc_end,
                                                  loc_ghost: init.loc_ghost
                                                };
                                              } else {
                                                cmtLoc = lbl.loc;
                                              }
                                              var attrs = printAttributes(undefined, undefined, param[0], cmtTbl);
                                              var lblDoc;
                                              if (lbl.txt === "_" || lbl.txt === "*") {
                                                lblDoc = Res_doc.nil;
                                              } else {
                                                var doc = Res_doc.text(lbl.txt);
                                                lblDoc = printComments(doc, cmtTbl, lbl.loc);
                                              }
                                              var doc$1 = Res_doc.concat({
                                                    hd: attrs,
                                                    tl: {
                                                      hd: lblDoc,
                                                      tl: {
                                                        hd: modType !== undefined ? Res_doc.concat({
                                                                hd: lbl.txt === "_" ? Res_doc.nil : Res_doc.text(": "),
                                                                tl: {
                                                                  hd: printModType(modType, cmtTbl),
                                                                  tl: /* [] */0
                                                                }
                                                              }) : Res_doc.nil,
                                                        tl: /* [] */0
                                                      }
                                                    }
                                                  });
                                              return printComments(doc$1, cmtTbl, cmtLoc);
                                            }), parameters)),
                                  tl: /* [] */0
                                }
                              })),
                      tl: {
                        hd: Res_doc.trailingComma,
                        tl: {
                          hd: Res_doc.softLine,
                          tl: {
                            hd: Res_doc.rparen,
                            tl: /* [] */0
                          }
                        }
                      }
                    }
                  }));
        }
        var doc$1 = printModType(returnType, cmtTbl);
        var returnDoc = Res_parens.modTypeFunctorReturn(returnType) ? addParens(doc$1) : doc$1;
        modTypeDoc = Res_doc.group(Res_doc.concat({
                  hd: parametersDoc,
                  tl: {
                    hd: Res_doc.group(Res_doc.concat({
                              hd: Res_doc.text(" =>"),
                              tl: {
                                hd: Res_doc.line,
                                tl: {
                                  hd: returnDoc,
                                  tl: /* [] */0
                                }
                              }
                            })),
                    tl: /* [] */0
                  }
                }));
        break;
    case /* Pmty_with */3 :
        var modType$2 = longident._0;
        var doc$2 = printModType(modType$2, cmtTbl);
        var operand = Res_parens.modTypeWithOperand(modType$2) ? addParens(doc$2) : doc$2;
        modTypeDoc = Res_doc.group(Res_doc.concat({
                  hd: operand,
                  tl: {
                    hd: Res_doc.indent(Res_doc.concat({
                              hd: Res_doc.line,
                              tl: {
                                hd: printWithConstraints(longident._1, cmtTbl),
                                tl: /* [] */0
                              }
                            })),
                    tl: /* [] */0
                  }
                }));
        break;
    case /* Pmty_typeof */4 :
        modTypeDoc = Res_doc.concat({
              hd: Res_doc.text("module type of "),
              tl: {
                hd: printModExpr(longident._0, cmtTbl),
                tl: /* [] */0
              }
            });
        break;
    case /* Pmty_extension */5 :
        modTypeDoc = printExtension(false, longident._0, cmtTbl);
        break;
    case /* Pmty_alias */6 :
        modTypeDoc = Res_doc.concat({
              hd: Res_doc.text("module "),
              tl: {
                hd: printLongidentLocation(longident._0, cmtTbl),
                tl: /* [] */0
              }
            });
        break;
    
  }
  var match$3 = modType.pmty_desc;
  var attrsAlreadyPrinted;
  switch (match$3.TAG | 0) {
    case /* Pmty_ident */0 :
    case /* Pmty_signature */1 :
    case /* Pmty_functor */2 :
        attrsAlreadyPrinted = true;
        break;
    default:
      attrsAlreadyPrinted = false;
  }
  var doc$3 = Res_doc.concat({
        hd: attrsAlreadyPrinted ? Res_doc.nil : printAttributes(undefined, undefined, modType.pmty_attributes, cmtTbl),
        tl: {
          hd: modTypeDoc,
          tl: /* [] */0
        }
      });
  return printComments(doc$3, cmtTbl, modType.pmty_loc);
}

function printWithConstraints(withConstraints, cmtTbl) {
  var rows = List.mapi((function (i, withConstraint) {
          return Res_doc.group(Res_doc.concat({
                          hd: i === 0 ? Res_doc.text("with ") : Res_doc.text("and "),
                          tl: {
                            hd: printWithConstraint(withConstraint, cmtTbl),
                            tl: /* [] */0
                          }
                        }));
        }), withConstraints);
  return Res_doc.join(Res_doc.line, rows);
}

function printWithConstraint(withConstraint, cmtTbl) {
  switch (withConstraint.TAG | 0) {
    case /* Pwith_type */0 :
        return Res_doc.group(printTypeDeclaration(printLidentPath(withConstraint._0, cmtTbl), "=", Res_doc.nil, 0, withConstraint._1, Res_comments_table.empty));
    case /* Pwith_module */1 :
        return Res_doc.concat({
                    hd: Res_doc.text("module "),
                    tl: {
                      hd: printLongident(withConstraint._0.txt),
                      tl: {
                        hd: Res_doc.text(" ="),
                        tl: {
                          hd: Res_doc.indent(Res_doc.concat({
                                    hd: Res_doc.line,
                                    tl: {
                                      hd: printLongident(withConstraint._1.txt),
                                      tl: /* [] */0
                                    }
                                  })),
                          tl: /* [] */0
                        }
                      }
                    }
                  });
    case /* Pwith_typesubst */2 :
        return Res_doc.group(printTypeDeclaration(printLidentPath(withConstraint._0, cmtTbl), ":=", Res_doc.nil, 0, withConstraint._1, Res_comments_table.empty));
    case /* Pwith_modsubst */3 :
        return Res_doc.concat({
                    hd: Res_doc.text("module "),
                    tl: {
                      hd: printLongident(withConstraint._0.txt),
                      tl: {
                        hd: Res_doc.text(" :="),
                        tl: {
                          hd: Res_doc.indent(Res_doc.concat({
                                    hd: Res_doc.line,
                                    tl: {
                                      hd: printLongident(withConstraint._1.txt),
                                      tl: /* [] */0
                                    }
                                  })),
                          tl: /* [] */0
                        }
                      }
                    }
                  });
    
  }
}

function printSignature(signature, cmtTbl) {
  if (signature) {
    return printList((function (s) {
                  return s.psig_loc;
                }), signature, printSignatureItem, undefined, cmtTbl);
  } else {
    return printCommentsInside(cmtTbl, $$Location.none);
  }
}

function printSignatureItem(si, cmtTbl) {
  var valueDescription = si.psig_desc;
  switch (valueDescription.TAG | 0) {
    case /* Psig_value */0 :
        return printValueDescription(valueDescription._0, cmtTbl);
    case /* Psig_type */1 :
        var recFlag = valueDescription._0 ? Res_doc.text("rec ") : Res_doc.nil;
        return printTypeDeclarations(recFlag, valueDescription._1, cmtTbl);
    case /* Psig_typext */2 :
        return printTypeExtension(valueDescription._0, cmtTbl);
    case /* Psig_exception */3 :
        return printExceptionDef(valueDescription._0, cmtTbl);
    case /* Psig_module */4 :
        return printModuleDeclaration(valueDescription._0, cmtTbl);
    case /* Psig_recmodule */5 :
        return printRecModuleDeclarations(valueDescription._0, cmtTbl);
    case /* Psig_modtype */6 :
        return printModuleTypeDeclaration(valueDescription._0, cmtTbl);
    case /* Psig_open */7 :
        return printOpenDescription(valueDescription._0, cmtTbl);
    case /* Psig_include */8 :
        return printIncludeDescription(valueDescription._0, cmtTbl);
    case /* Psig_class */9 :
    case /* Psig_class_type */10 :
        return Res_doc.nil;
    case /* Psig_attribute */11 :
        return Res_doc.concat({
                    hd: Res_doc.text("@"),
                    tl: {
                      hd: printAttribute(valueDescription._0, cmtTbl),
                      tl: /* [] */0
                    }
                  });
    case /* Psig_extension */12 :
        return Res_doc.concat({
                    hd: printAttributes(undefined, undefined, valueDescription._1, cmtTbl),
                    tl: {
                      hd: Res_doc.concat({
                            hd: printExtension(true, valueDescription._0, cmtTbl),
                            tl: /* [] */0
                          }),
                      tl: /* [] */0
                    }
                  });
    
  }
}

function printRecModuleDeclarations(moduleDeclarations, cmtTbl) {
  return printListi((function (n) {
                return n.pmd_loc;
              }), moduleDeclarations, printRecModuleDeclaration, undefined, cmtTbl);
}

function printRecModuleDeclaration(md, cmtTbl, i) {
  var longident = md.pmd_type.pmty_desc;
  var body;
  if (longident.TAG === /* Pmty_alias */6) {
    body = Res_doc.concat({
          hd: Res_doc.text(" = "),
          tl: {
            hd: printLongidentLocation(longident._0, cmtTbl),
            tl: /* [] */0
          }
        });
  } else {
    var match = md.pmd_type.pmty_desc;
    var needsParens;
    needsParens = match.TAG === /* Pmty_with */3 ? true : false;
    var doc = printModType(md.pmd_type, cmtTbl);
    var modTypeDoc = needsParens ? addParens(doc) : doc;
    body = Res_doc.concat({
          hd: Res_doc.text(": "),
          tl: {
            hd: modTypeDoc,
            tl: /* [] */0
          }
        });
  }
  var prefix = i < 1 ? "module rec " : "and ";
  return Res_doc.concat({
              hd: printAttributes(md.pmd_name.loc, undefined, md.pmd_attributes, cmtTbl),
              tl: {
                hd: Res_doc.text(prefix),
                tl: {
                  hd: printComments(Res_doc.text(md.pmd_name.txt), cmtTbl, md.pmd_name.loc),
                  tl: {
                    hd: body,
                    tl: /* [] */0
                  }
                }
              }
            });
}

function printModuleDeclaration(md, cmtTbl) {
  var longident = md.pmd_type.pmty_desc;
  var body;
  body = longident.TAG === /* Pmty_alias */6 ? Res_doc.concat({
          hd: Res_doc.text(" = "),
          tl: {
            hd: printLongidentLocation(longident._0, cmtTbl),
            tl: /* [] */0
          }
        }) : Res_doc.concat({
          hd: Res_doc.text(": "),
          tl: {
            hd: printModType(md.pmd_type, cmtTbl),
            tl: /* [] */0
          }
        });
  return Res_doc.concat({
              hd: printAttributes(md.pmd_name.loc, undefined, md.pmd_attributes, cmtTbl),
              tl: {
                hd: Res_doc.text("module "),
                tl: {
                  hd: printComments(Res_doc.text(md.pmd_name.txt), cmtTbl, md.pmd_name.loc),
                  tl: {
                    hd: body,
                    tl: /* [] */0
                  }
                }
              }
            });
}

function printOpenDescription(openDescription, cmtTbl) {
  var match = openDescription.popen_override;
  return Res_doc.concat({
              hd: printAttributes(undefined, undefined, openDescription.popen_attributes, cmtTbl),
              tl: {
                hd: Res_doc.text("open"),
                tl: {
                  hd: match ? Res_doc.space : Res_doc.text("! "),
                  tl: {
                    hd: printLongidentLocation(openDescription.popen_lid, cmtTbl),
                    tl: /* [] */0
                  }
                }
              }
            });
}

function printIncludeDescription(includeDescription, cmtTbl) {
  return Res_doc.concat({
              hd: printAttributes(undefined, undefined, includeDescription.pincl_attributes, cmtTbl),
              tl: {
                hd: Res_doc.text("include "),
                tl: {
                  hd: printModType(includeDescription.pincl_mod, cmtTbl),
                  tl: /* [] */0
                }
              }
            });
}

function printIncludeDeclaration(includeDeclaration, cmtTbl) {
  var includeDoc = printModExpr(includeDeclaration.pincl_mod, cmtTbl);
  return Res_doc.concat({
              hd: printAttributes(undefined, undefined, includeDeclaration.pincl_attributes, cmtTbl),
              tl: {
                hd: Res_doc.text("include "),
                tl: {
                  hd: Res_parens.includeModExpr(includeDeclaration.pincl_mod) ? addParens(includeDoc) : includeDoc,
                  tl: /* [] */0
                }
              }
            });
}

function printValueBindings(recFlag, vbs, cmtTbl) {
  return printListi((function (vb) {
                return vb.pvb_loc;
              }), vbs, (function (param, param$1, param$2) {
                return printValueBinding(recFlag, param, param$1, param$2);
              }), undefined, cmtTbl);
}

function printValueDescription(valueDescription, cmtTbl) {
  var match = valueDescription.pval_prim;
  var isExternal = match ? true : false;
  var attrs = printAttributes(valueDescription.pval_name.loc, undefined, valueDescription.pval_attributes, cmtTbl);
  var header = isExternal ? "external " : "let ";
  return Res_doc.group(Res_doc.concat({
                  hd: attrs,
                  tl: {
                    hd: Res_doc.text(header),
                    tl: {
                      hd: printComments(printIdentLike(undefined, valueDescription.pval_name.txt), cmtTbl, valueDescription.pval_name.loc),
                      tl: {
                        hd: Res_doc.text(": "),
                        tl: {
                          hd: printTypExpr(valueDescription.pval_type, cmtTbl),
                          tl: {
                            hd: isExternal ? Res_doc.group(Res_doc.concat({
                                        hd: Res_doc.text(" ="),
                                        tl: {
                                          hd: Res_doc.indent(Res_doc.concat({
                                                    hd: Res_doc.line,
                                                    tl: {
                                                      hd: Res_doc.join(Res_doc.line, List.map((function (s) {
                                                                  return Res_doc.concat({
                                                                              hd: Res_doc.text("\""),
                                                                              tl: {
                                                                                hd: Res_doc.text(s),
                                                                                tl: {
                                                                                  hd: Res_doc.text("\""),
                                                                                  tl: /* [] */0
                                                                                }
                                                                              }
                                                                            });
                                                                }), valueDescription.pval_prim)),
                                                      tl: /* [] */0
                                                    }
                                                  })),
                                          tl: /* [] */0
                                        }
                                      })) : Res_doc.nil,
                            tl: /* [] */0
                          }
                        }
                      }
                    }
                  }
                }));
}

function printTypeDeclarations(recFlag, typeDeclarations, cmtTbl) {
  return printListi((function (n) {
                return n.ptype_loc;
              }), typeDeclarations, (function (param, param$1, param$2) {
                return printTypeDeclaration2(recFlag, param, param$1, param$2);
              }), undefined, cmtTbl);
}

function printTypeDeclaration(name, equalSign, recFlag, i, td, cmtTbl) {
  var attrs = printAttributes(td.ptype_loc, undefined, td.ptype_attributes, cmtTbl);
  var prefix = i > 0 ? Res_doc.text("and ") : Res_doc.concat({
          hd: Res_doc.text("type "),
          tl: {
            hd: recFlag,
            tl: /* [] */0
          }
        });
  var typeParams = printTypeParams(td.ptype_params, cmtTbl);
  var lds = td.ptype_kind;
  var manifestAndKind;
  if (typeof lds === "number") {
    if (lds === /* Ptype_abstract */0) {
      var typ = td.ptype_manifest;
      manifestAndKind = typ !== undefined ? Res_doc.concat({
              hd: Res_doc.concat({
                    hd: Res_doc.space,
                    tl: {
                      hd: Res_doc.text(equalSign),
                      tl: {
                        hd: Res_doc.space,
                        tl: /* [] */0
                      }
                    }
                  }),
              tl: {
                hd: printPrivateFlag(td.ptype_private),
                tl: {
                  hd: printTypExpr(typ, cmtTbl),
                  tl: /* [] */0
                }
              }
            }) : Res_doc.nil;
    } else {
      manifestAndKind = Res_doc.concat({
            hd: Res_doc.concat({
                  hd: Res_doc.space,
                  tl: {
                    hd: Res_doc.text(equalSign),
                    tl: {
                      hd: Res_doc.space,
                      tl: /* [] */0
                    }
                  }
                }),
            tl: {
              hd: printPrivateFlag(td.ptype_private),
              tl: {
                hd: Res_doc.text(".."),
                tl: /* [] */0
              }
            }
          });
    }
  } else if (lds.TAG === /* Ptype_variant */0) {
    var typ$1 = td.ptype_manifest;
    var manifest = typ$1 !== undefined ? Res_doc.concat({
            hd: Res_doc.concat({
                  hd: Res_doc.space,
                  tl: {
                    hd: Res_doc.text(equalSign),
                    tl: {
                      hd: Res_doc.space,
                      tl: /* [] */0
                    }
                  }
                }),
            tl: {
              hd: printTypExpr(typ$1, cmtTbl),
              tl: /* [] */0
            }
          }) : Res_doc.nil;
    manifestAndKind = Res_doc.concat({
          hd: manifest,
          tl: {
            hd: Res_doc.concat({
                  hd: Res_doc.space,
                  tl: {
                    hd: Res_doc.text(equalSign),
                    tl: /* [] */0
                  }
                }),
            tl: {
              hd: printConstructorDeclarations(td.ptype_private, lds._0, cmtTbl),
              tl: /* [] */0
            }
          }
        });
  } else {
    var typ$2 = td.ptype_manifest;
    var manifest$1 = typ$2 !== undefined ? Res_doc.concat({
            hd: Res_doc.concat({
                  hd: Res_doc.space,
                  tl: {
                    hd: Res_doc.text(equalSign),
                    tl: {
                      hd: Res_doc.space,
                      tl: /* [] */0
                    }
                  }
                }),
            tl: {
              hd: printTypExpr(typ$2, cmtTbl),
              tl: /* [] */0
            }
          }) : Res_doc.nil;
    manifestAndKind = Res_doc.concat({
          hd: manifest$1,
          tl: {
            hd: Res_doc.concat({
                  hd: Res_doc.space,
                  tl: {
                    hd: Res_doc.text(equalSign),
                    tl: {
                      hd: Res_doc.space,
                      tl: /* [] */0
                    }
                  }
                }),
            tl: {
              hd: printPrivateFlag(td.ptype_private),
              tl: {
                hd: printRecordDeclaration(lds._0, cmtTbl),
                tl: /* [] */0
              }
            }
          }
        });
  }
  var constraints = printTypeDefinitionConstraints(td.ptype_cstrs);
  return Res_doc.group(Res_doc.concat({
                  hd: attrs,
                  tl: {
                    hd: prefix,
                    tl: {
                      hd: name,
                      tl: {
                        hd: typeParams,
                        tl: {
                          hd: manifestAndKind,
                          tl: {
                            hd: constraints,
                            tl: /* [] */0
                          }
                        }
                      }
                    }
                  }
                }));
}

function printTypeDeclaration2(recFlag, td, cmtTbl, i) {
  var doc = printIdentLike(undefined, td.ptype_name.txt);
  var name = printComments(doc, cmtTbl, td.ptype_name.loc);
  var equalSign = "=";
  var attrs = printAttributes(td.ptype_loc, undefined, td.ptype_attributes, cmtTbl);
  var prefix = i > 0 ? Res_doc.text("and ") : Res_doc.concat({
          hd: Res_doc.text("type "),
          tl: {
            hd: recFlag,
            tl: /* [] */0
          }
        });
  var typeParams = printTypeParams(td.ptype_params, cmtTbl);
  var lds = td.ptype_kind;
  var manifestAndKind;
  if (typeof lds === "number") {
    if (lds === /* Ptype_abstract */0) {
      var typ = td.ptype_manifest;
      manifestAndKind = typ !== undefined ? Res_doc.concat({
              hd: Res_doc.concat({
                    hd: Res_doc.space,
                    tl: {
                      hd: Res_doc.text(equalSign),
                      tl: {
                        hd: Res_doc.space,
                        tl: /* [] */0
                      }
                    }
                  }),
              tl: {
                hd: printPrivateFlag(td.ptype_private),
                tl: {
                  hd: printTypExpr(typ, cmtTbl),
                  tl: /* [] */0
                }
              }
            }) : Res_doc.nil;
    } else {
      manifestAndKind = Res_doc.concat({
            hd: Res_doc.concat({
                  hd: Res_doc.space,
                  tl: {
                    hd: Res_doc.text(equalSign),
                    tl: {
                      hd: Res_doc.space,
                      tl: /* [] */0
                    }
                  }
                }),
            tl: {
              hd: printPrivateFlag(td.ptype_private),
              tl: {
                hd: Res_doc.text(".."),
                tl: /* [] */0
              }
            }
          });
    }
  } else if (lds.TAG === /* Ptype_variant */0) {
    var typ$1 = td.ptype_manifest;
    var manifest = typ$1 !== undefined ? Res_doc.concat({
            hd: Res_doc.concat({
                  hd: Res_doc.space,
                  tl: {
                    hd: Res_doc.text(equalSign),
                    tl: {
                      hd: Res_doc.space,
                      tl: /* [] */0
                    }
                  }
                }),
            tl: {
              hd: printTypExpr(typ$1, cmtTbl),
              tl: /* [] */0
            }
          }) : Res_doc.nil;
    manifestAndKind = Res_doc.concat({
          hd: manifest,
          tl: {
            hd: Res_doc.concat({
                  hd: Res_doc.space,
                  tl: {
                    hd: Res_doc.text(equalSign),
                    tl: /* [] */0
                  }
                }),
            tl: {
              hd: printConstructorDeclarations(td.ptype_private, lds._0, cmtTbl),
              tl: /* [] */0
            }
          }
        });
  } else {
    var typ$2 = td.ptype_manifest;
    var manifest$1 = typ$2 !== undefined ? Res_doc.concat({
            hd: Res_doc.concat({
                  hd: Res_doc.space,
                  tl: {
                    hd: Res_doc.text(equalSign),
                    tl: {
                      hd: Res_doc.space,
                      tl: /* [] */0
                    }
                  }
                }),
            tl: {
              hd: printTypExpr(typ$2, cmtTbl),
              tl: /* [] */0
            }
          }) : Res_doc.nil;
    manifestAndKind = Res_doc.concat({
          hd: manifest$1,
          tl: {
            hd: Res_doc.concat({
                  hd: Res_doc.space,
                  tl: {
                    hd: Res_doc.text(equalSign),
                    tl: {
                      hd: Res_doc.space,
                      tl: /* [] */0
                    }
                  }
                }),
            tl: {
              hd: printPrivateFlag(td.ptype_private),
              tl: {
                hd: printRecordDeclaration(lds._0, cmtTbl),
                tl: /* [] */0
              }
            }
          }
        });
  }
  var constraints = printTypeDefinitionConstraints(td.ptype_cstrs);
  return Res_doc.group(Res_doc.concat({
                  hd: attrs,
                  tl: {
                    hd: prefix,
                    tl: {
                      hd: name,
                      tl: {
                        hd: typeParams,
                        tl: {
                          hd: manifestAndKind,
                          tl: {
                            hd: constraints,
                            tl: /* [] */0
                          }
                        }
                      }
                    }
                  }
                }));
}

function printTypeDefinitionConstraints(cstrs) {
  if (cstrs) {
    return Res_doc.indent(Res_doc.group(Res_doc.concat({
                        hd: Res_doc.line,
                        tl: {
                          hd: Res_doc.group(Res_doc.join(Res_doc.line, List.map(printTypeDefinitionConstraint, cstrs))),
                          tl: /* [] */0
                        }
                      })));
  } else {
    return Res_doc.nil;
  }
}

function printTypeDefinitionConstraint(param) {
  return Res_doc.concat({
              hd: Res_doc.text("constraint "),
              tl: {
                hd: printTypExpr(param[0], Res_comments_table.empty),
                tl: {
                  hd: Res_doc.text(" = "),
                  tl: {
                    hd: printTypExpr(param[1], Res_comments_table.empty),
                    tl: /* [] */0
                  }
                }
              }
            });
}

function printPrivateFlag(flag) {
  if (flag) {
    return Res_doc.nil;
  } else {
    return Res_doc.text("private ");
  }
}

function printTypeParams(typeParams, cmtTbl) {
  if (typeParams) {
    return Res_doc.group(Res_doc.concat({
                    hd: Res_doc.lessThan,
                    tl: {
                      hd: Res_doc.indent(Res_doc.concat({
                                hd: Res_doc.softLine,
                                tl: {
                                  hd: Res_doc.join(Res_doc.concat({
                                            hd: Res_doc.comma,
                                            tl: {
                                              hd: Res_doc.line,
                                              tl: /* [] */0
                                            }
                                          }), List.map((function (typeParam) {
                                              var doc = printTypeParam(typeParam, cmtTbl);
                                              return printComments(doc, cmtTbl, typeParam[0].ptyp_loc);
                                            }), typeParams)),
                                  tl: /* [] */0
                                }
                              })),
                      tl: {
                        hd: Res_doc.trailingComma,
                        tl: {
                          hd: Res_doc.softLine,
                          tl: {
                            hd: Res_doc.greaterThan,
                            tl: /* [] */0
                          }
                        }
                      }
                    }
                  }));
  } else {
    return Res_doc.nil;
  }
}

function printTypeParam(param, cmtTbl) {
  var printedVariance;
  switch (param[1]) {
    case /* Covariant */0 :
        printedVariance = Res_doc.text("+");
        break;
    case /* Contravariant */1 :
        printedVariance = Res_doc.text("-");
        break;
    case /* Invariant */2 :
        printedVariance = Res_doc.nil;
        break;
    
  }
  return Res_doc.concat({
              hd: printedVariance,
              tl: {
                hd: printTypExpr(param[0], cmtTbl),
                tl: /* [] */0
              }
            });
}

function printRecordDeclaration(lds, cmtTbl) {
  var match = List.rev(lds);
  var forceBreak = lds && match ? lds.hd.pld_loc.loc_start.pos_lnum < match.hd.pld_loc.loc_end.pos_lnum : false;
  return Res_doc.breakableGroup(forceBreak, Res_doc.concat({
                  hd: Res_doc.lbrace,
                  tl: {
                    hd: Res_doc.indent(Res_doc.concat({
                              hd: Res_doc.softLine,
                              tl: {
                                hd: Res_doc.join(Res_doc.concat({
                                          hd: Res_doc.comma,
                                          tl: {
                                            hd: Res_doc.line,
                                            tl: /* [] */0
                                          }
                                        }), List.map((function (ld) {
                                            var doc = printLabelDeclaration(ld, cmtTbl);
                                            return printComments(doc, cmtTbl, ld.pld_loc);
                                          }), lds)),
                                tl: /* [] */0
                              }
                            })),
                    tl: {
                      hd: Res_doc.trailingComma,
                      tl: {
                        hd: Res_doc.softLine,
                        tl: {
                          hd: Res_doc.rbrace,
                          tl: /* [] */0
                        }
                      }
                    }
                  }
                }));
}

function printConstructorDeclarations(privateFlag, cds, cmtTbl) {
  var match = List.rev(cds);
  var forceBreak = cds && match ? cds.hd.pcd_loc.loc_start.pos_lnum < match.hd.pcd_loc.loc_end.pos_lnum : false;
  var privateFlag$1 = privateFlag ? Res_doc.nil : Res_doc.concat({
          hd: Res_doc.text("private"),
          tl: {
            hd: Res_doc.line,
            tl: /* [] */0
          }
        });
  var rows = printListi((function (cd) {
          return cd.pcd_loc;
        }), cds, (function (cd, cmtTbl, i) {
          var doc = printConstructorDeclaration2(i, cd, cmtTbl);
          return printComments(doc, cmtTbl, cd.pcd_loc);
        }), forceBreak, cmtTbl);
  return Res_doc.breakableGroup(forceBreak, Res_doc.indent(Res_doc.concat({
                      hd: Res_doc.line,
                      tl: {
                        hd: privateFlag$1,
                        tl: {
                          hd: rows,
                          tl: /* [] */0
                        }
                      }
                    })));
}

function printConstructorDeclaration2(i, cd, cmtTbl) {
  var attrs = printAttributes(undefined, undefined, cd.pcd_attributes, cmtTbl);
  var bar = i > 0 || cd.pcd_attributes !== /* [] */0 ? Res_doc.text("| ") : Res_doc.ifBreaks(Res_doc.text("| "), Res_doc.nil);
  var doc = Res_doc.text(cd.pcd_name.txt);
  var constrName = printComments(doc, cmtTbl, cd.pcd_name.loc);
  var constrArgs = printConstructorArguments(true, cd.pcd_args, cmtTbl);
  var typ = cd.pcd_res;
  var gadt = typ !== undefined ? Res_doc.indent(Res_doc.concat({
              hd: Res_doc.text(": "),
              tl: {
                hd: printTypExpr(typ, cmtTbl),
                tl: /* [] */0
              }
            })) : Res_doc.nil;
  return Res_doc.concat({
              hd: bar,
              tl: {
                hd: Res_doc.group(Res_doc.concat({
                          hd: attrs,
                          tl: {
                            hd: constrName,
                            tl: {
                              hd: constrArgs,
                              tl: {
                                hd: gadt,
                                tl: /* [] */0
                              }
                            }
                          }
                        })),
                tl: /* [] */0
              }
            });
}

function printConstructorArguments(indent, cdArgs, cmtTbl) {
  if (cdArgs.TAG === /* Pcstr_tuple */0) {
    var types = cdArgs._0;
    if (!types) {
      return Res_doc.nil;
    }
    var args = Res_doc.concat({
          hd: Res_doc.lparen,
          tl: {
            hd: Res_doc.indent(Res_doc.concat({
                      hd: Res_doc.softLine,
                      tl: {
                        hd: Res_doc.join(Res_doc.concat({
                                  hd: Res_doc.comma,
                                  tl: {
                                    hd: Res_doc.line,
                                    tl: /* [] */0
                                  }
                                }), List.map((function (typexpr) {
                                    return printTypExpr(typexpr, cmtTbl);
                                  }), types)),
                        tl: /* [] */0
                      }
                    })),
            tl: {
              hd: Res_doc.trailingComma,
              tl: {
                hd: Res_doc.softLine,
                tl: {
                  hd: Res_doc.rparen,
                  tl: /* [] */0
                }
              }
            }
          }
        });
    return Res_doc.group(indent ? Res_doc.indent(args) : args);
  }
  var args$1 = Res_doc.concat({
        hd: Res_doc.lparen,
        tl: {
          hd: Res_doc.lbrace,
          tl: {
            hd: Res_doc.indent(Res_doc.concat({
                      hd: Res_doc.softLine,
                      tl: {
                        hd: Res_doc.join(Res_doc.concat({
                                  hd: Res_doc.comma,
                                  tl: {
                                    hd: Res_doc.line,
                                    tl: /* [] */0
                                  }
                                }), List.map((function (ld) {
                                    var doc = printLabelDeclaration(ld, cmtTbl);
                                    return printComments(doc, cmtTbl, ld.pld_loc);
                                  }), cdArgs._0)),
                        tl: /* [] */0
                      }
                    })),
            tl: {
              hd: Res_doc.trailingComma,
              tl: {
                hd: Res_doc.softLine,
                tl: {
                  hd: Res_doc.rbrace,
                  tl: {
                    hd: Res_doc.rparen,
                    tl: /* [] */0
                  }
                }
              }
            }
          }
        }
      });
  if (indent) {
    return Res_doc.indent(args$1);
  } else {
    return args$1;
  }
}

function printLabelDeclaration(ld, cmtTbl) {
  var attrs = printAttributes(ld.pld_name.loc, undefined, ld.pld_attributes, cmtTbl);
  var match = ld.pld_mutable;
  var mutableFlag = match ? Res_doc.text("mutable ") : Res_doc.nil;
  var doc = printIdentLike(undefined, ld.pld_name.txt);
  var name = printComments(doc, cmtTbl, ld.pld_name.loc);
  return Res_doc.group(Res_doc.concat({
                  hd: attrs,
                  tl: {
                    hd: mutableFlag,
                    tl: {
                      hd: name,
                      tl: {
                        hd: Res_doc.text(": "),
                        tl: {
                          hd: printTypExpr(ld.pld_type, cmtTbl),
                          tl: /* [] */0
                        }
                      }
                    }
                  }
                }));
}

function printTypExpr(typExpr, cmtTbl) {
  var $$var = typExpr.ptyp_desc;
  var renderedType;
  if (typeof $$var === "number") {
    renderedType = Res_doc.text("_");
  } else {
    switch ($$var.TAG | 0) {
      case /* Ptyp_var */0 :
          renderedType = Res_doc.concat({
                hd: Res_doc.text("'"),
                tl: {
                  hd: printIdentLike(true, $$var._0),
                  tl: /* [] */0
                }
              });
          break;
      case /* Ptyp_arrow */1 :
          var match = Res_parsetree_viewer.arrowType(typExpr);
          var returnType = match[2];
          var args = match[1];
          var attrsBefore = match[0];
          var match$1 = returnType.ptyp_desc;
          var returnTypeNeedsParens;
          returnTypeNeedsParens = typeof match$1 === "number" || match$1.TAG !== /* Ptyp_alias */6 ? false : true;
          var doc = printTypExpr(returnType, cmtTbl);
          var returnDoc = returnTypeNeedsParens ? Res_doc.concat({
                  hd: Res_doc.lparen,
                  tl: {
                    hd: doc,
                    tl: {
                      hd: Res_doc.rparen,
                      tl: /* [] */0
                    }
                  }
                }) : doc;
          var match$2 = Res_parsetree_viewer.processUncurriedAttribute(attrsBefore);
          var attrs = match$2[1];
          var isUncurried = match$2[0];
          var exit = 0;
          if (args) {
            var match$3 = args.hd;
            if (match$3[0] || !(typeof match$3[1] === "number" && !(args.tl || isUncurried))) {
              exit = 1;
            } else {
              var n = match$3[2];
              var hasAttrsBefore = attrs !== /* [] */0;
              var attrs$1 = hasAttrsBefore ? printAttributes(undefined, true, attrsBefore, cmtTbl) : Res_doc.nil;
              var doc$1 = printTypExpr(n, cmtTbl);
              var match$4 = n.ptyp_desc;
              var typDoc;
              if (typeof match$4 === "number") {
                typDoc = doc$1;
              } else {
                switch (match$4.TAG | 0) {
                  case /* Ptyp_arrow */1 :
                  case /* Ptyp_tuple */2 :
                  case /* Ptyp_alias */6 :
                      typDoc = addParens(doc$1);
                      break;
                  default:
                    typDoc = doc$1;
                }
              }
              renderedType = Res_doc.group(Res_doc.concat({
                        hd: Res_doc.group(attrs$1),
                        tl: {
                          hd: Res_doc.group(hasAttrsBefore ? Res_doc.concat({
                                      hd: Res_doc.lparen,
                                      tl: {
                                        hd: Res_doc.indent(Res_doc.concat({
                                                  hd: Res_doc.softLine,
                                                  tl: {
                                                    hd: typDoc,
                                                    tl: {
                                                      hd: Res_doc.text(" => "),
                                                      tl: {
                                                        hd: returnDoc,
                                                        tl: /* [] */0
                                                      }
                                                    }
                                                  }
                                                })),
                                        tl: {
                                          hd: Res_doc.softLine,
                                          tl: {
                                            hd: Res_doc.rparen,
                                            tl: /* [] */0
                                          }
                                        }
                                      }
                                    }) : Res_doc.concat({
                                      hd: typDoc,
                                      tl: {
                                        hd: Res_doc.text(" => "),
                                        tl: {
                                          hd: returnDoc,
                                          tl: /* [] */0
                                        }
                                      }
                                    })),
                          tl: /* [] */0
                        }
                      }));
            }
          } else {
            renderedType = Res_doc.nil;
          }
          if (exit === 1) {
            var attrs$2 = printAttributes(undefined, true, attrs, cmtTbl);
            var renderedArgs = Res_doc.concat({
                  hd: attrs$2,
                  tl: {
                    hd: Res_doc.text("("),
                    tl: {
                      hd: Res_doc.indent(Res_doc.concat({
                                hd: Res_doc.softLine,
                                tl: {
                                  hd: isUncurried ? Res_doc.concat({
                                          hd: Res_doc.dot,
                                          tl: {
                                            hd: Res_doc.space,
                                            tl: /* [] */0
                                          }
                                        }) : Res_doc.nil,
                                  tl: {
                                    hd: Res_doc.join(Res_doc.concat({
                                              hd: Res_doc.comma,
                                              tl: {
                                                hd: Res_doc.line,
                                                tl: /* [] */0
                                              }
                                            }), List.map((function (tp) {
                                                return printTypeParameter(tp, cmtTbl);
                                              }), args)),
                                    tl: /* [] */0
                                  }
                                }
                              })),
                      tl: {
                        hd: Res_doc.trailingComma,
                        tl: {
                          hd: Res_doc.softLine,
                          tl: {
                            hd: Res_doc.text(")"),
                            tl: /* [] */0
                          }
                        }
                      }
                    }
                  }
                });
            renderedType = Res_doc.group(Res_doc.concat({
                      hd: renderedArgs,
                      tl: {
                        hd: Res_doc.text(" => "),
                        tl: {
                          hd: returnDoc,
                          tl: /* [] */0
                        }
                      }
                    }));
          }
          break;
      case /* Ptyp_tuple */2 :
          renderedType = printTupleType(false, $$var._0, cmtTbl);
          break;
      case /* Ptyp_constr */3 :
          var constrArgs = $$var._1;
          var longidentLoc = $$var._0;
          var exit$1 = 0;
          if (constrArgs) {
            var tuple = constrArgs.hd.ptyp_desc;
            if (typeof tuple === "number") {
              exit$1 = 1;
            } else {
              switch (tuple.TAG | 0) {
                case /* Ptyp_tuple */2 :
                    if (constrArgs.tl) {
                      exit$1 = 1;
                    } else {
                      var constrName = printLidentPath(longidentLoc, cmtTbl);
                      renderedType = Res_doc.group(Res_doc.concat({
                                hd: constrName,
                                tl: {
                                  hd: Res_doc.lessThan,
                                  tl: {
                                    hd: printTupleType(true, tuple._0, cmtTbl),
                                    tl: {
                                      hd: Res_doc.greaterThan,
                                      tl: /* [] */0
                                    }
                                  }
                                }
                              }));
                    }
                    break;
                case /* Ptyp_object */4 :
                    if (constrArgs.tl) {
                      exit$1 = 1;
                    } else {
                      var constrName$1 = printLidentPath(longidentLoc, cmtTbl);
                      renderedType = Res_doc.concat({
                            hd: constrName$1,
                            tl: {
                              hd: Res_doc.lessThan,
                              tl: {
                                hd: printObject(true, tuple._0, tuple._1, cmtTbl),
                                tl: {
                                  hd: Res_doc.greaterThan,
                                  tl: /* [] */0
                                }
                              }
                            }
                          });
                    }
                    break;
                default:
                  exit$1 = 1;
              }
            }
          } else {
            exit$1 = 1;
          }
          if (exit$1 === 1) {
            var constrName$2 = printLidentPath(longidentLoc, cmtTbl);
            renderedType = constrArgs ? Res_doc.group(Res_doc.concat({
                        hd: constrName$2,
                        tl: {
                          hd: Res_doc.lessThan,
                          tl: {
                            hd: Res_doc.indent(Res_doc.concat({
                                      hd: Res_doc.softLine,
                                      tl: {
                                        hd: Res_doc.join(Res_doc.concat({
                                                  hd: Res_doc.comma,
                                                  tl: {
                                                    hd: Res_doc.line,
                                                    tl: /* [] */0
                                                  }
                                                }), List.map((function (typexpr) {
                                                    return printTypExpr(typexpr, cmtTbl);
                                                  }), constrArgs)),
                                        tl: /* [] */0
                                      }
                                    })),
                            tl: {
                              hd: Res_doc.trailingComma,
                              tl: {
                                hd: Res_doc.softLine,
                                tl: {
                                  hd: Res_doc.greaterThan,
                                  tl: /* [] */0
                                }
                              }
                            }
                          }
                        }
                      })) : constrName$2;
          }
          break;
      case /* Ptyp_object */4 :
          renderedType = printObject(false, $$var._0, $$var._1, cmtTbl);
          break;
      case /* Ptyp_class */5 :
          renderedType = Res_doc.text("classes are not supported in types");
          break;
      case /* Ptyp_alias */6 :
          var typ = $$var._0;
          var match$5 = typ.ptyp_desc;
          var needsParens;
          needsParens = typeof match$5 === "number" || match$5.TAG !== /* Ptyp_arrow */1 ? false : true;
          var doc$2 = printTypExpr(typ, cmtTbl);
          var typ$1 = needsParens ? Res_doc.concat({
                  hd: Res_doc.lparen,
                  tl: {
                    hd: doc$2,
                    tl: {
                      hd: Res_doc.rparen,
                      tl: /* [] */0
                    }
                  }
                }) : doc$2;
          renderedType = Res_doc.concat({
                hd: typ$1,
                tl: {
                  hd: Res_doc.text(" as "),
                  tl: {
                    hd: Res_doc.concat({
                          hd: Res_doc.text("'"),
                          tl: {
                            hd: printIdentLike(undefined, $$var._1),
                            tl: /* [] */0
                          }
                        }),
                    tl: /* [] */0
                  }
                }
              });
          break;
      case /* Ptyp_variant */7 :
          var labelsOpt = $$var._2;
          var forceBreak = typExpr.ptyp_loc.loc_start.pos_lnum < typExpr.ptyp_loc.loc_end.pos_lnum;
          var printRowField = function (x) {
            if (x.TAG !== /* Rtag */0) {
              return printTypExpr(x._0, cmtTbl);
            }
            var truth = x._2;
            var attrs = x._1;
            var txt = x._0.txt;
            if (truth && !x._3) {
              return Res_doc.group(Res_doc.concat({
                              hd: printAttributes(undefined, undefined, attrs, cmtTbl),
                              tl: {
                                hd: Res_doc.concat({
                                      hd: Res_doc.text("#"),
                                      tl: {
                                        hd: printPolyVarIdent(txt),
                                        tl: /* [] */0
                                      }
                                    }),
                                tl: /* [] */0
                              }
                            }));
            }
            var doType = function (t) {
              var match = t.ptyp_desc;
              if (typeof match !== "number" && match.TAG === /* Ptyp_tuple */2) {
                return printTypExpr(t, cmtTbl);
              }
              return Res_doc.concat({
                          hd: Res_doc.lparen,
                          tl: {
                            hd: printTypExpr(t, cmtTbl),
                            tl: {
                              hd: Res_doc.rparen,
                              tl: /* [] */0
                            }
                          }
                        });
            };
            var printedTypes = List.map(doType, x._3);
            var cases = Res_doc.join(Res_doc.concat({
                      hd: Res_doc.line,
                      tl: {
                        hd: Res_doc.text("& "),
                        tl: /* [] */0
                      }
                    }), printedTypes);
            var cases$1 = truth ? Res_doc.concat({
                    hd: Res_doc.line,
                    tl: {
                      hd: Res_doc.text("& "),
                      tl: {
                        hd: cases,
                        tl: /* [] */0
                      }
                    }
                  }) : cases;
            return Res_doc.group(Res_doc.concat({
                            hd: printAttributes(undefined, undefined, attrs, cmtTbl),
                            tl: {
                              hd: Res_doc.concat({
                                    hd: Res_doc.text("#"),
                                    tl: {
                                      hd: printPolyVarIdent(txt),
                                      tl: /* [] */0
                                    }
                                  }),
                              tl: {
                                hd: cases$1,
                                tl: /* [] */0
                              }
                            }
                          }));
          };
          var docs = List.map(printRowField, $$var._0);
          var cases = Res_doc.join(Res_doc.concat({
                    hd: Res_doc.line,
                    tl: {
                      hd: Res_doc.text("| "),
                      tl: /* [] */0
                    }
                  }), docs);
          var cases$1 = docs === /* [] */0 ? cases : Res_doc.concat({
                  hd: Res_doc.ifBreaks(Res_doc.text("| "), Res_doc.nil),
                  tl: {
                    hd: cases,
                    tl: /* [] */0
                  }
                });
          var openingSymbol = $$var._1 === /* Open */1 ? Res_doc.concat({
                  hd: Res_doc.greaterThan,
                  tl: {
                    hd: Res_doc.line,
                    tl: /* [] */0
                  }
                }) : (
              labelsOpt === undefined ? Res_doc.softLine : Res_doc.concat({
                      hd: Res_doc.lessThan,
                      tl: {
                        hd: Res_doc.line,
                        tl: /* [] */0
                      }
                    })
            );
          var labels = labelsOpt !== undefined && labelsOpt ? Res_doc.concat(List.map((function (label) {
                        return Res_doc.concat({
                                    hd: Res_doc.line,
                                    tl: {
                                      hd: Res_doc.text("#"),
                                      tl: {
                                        hd: printPolyVarIdent(label),
                                        tl: /* [] */0
                                      }
                                    }
                                  });
                      }), labelsOpt)) : Res_doc.nil;
          var closingSymbol = labelsOpt !== undefined && labelsOpt ? Res_doc.text(" >") : Res_doc.nil;
          renderedType = Res_doc.breakableGroup(forceBreak, Res_doc.concat({
                    hd: Res_doc.lbracket,
                    tl: {
                      hd: Res_doc.indent(Res_doc.concat({
                                hd: openingSymbol,
                                tl: {
                                  hd: cases$1,
                                  tl: {
                                    hd: closingSymbol,
                                    tl: {
                                      hd: labels,
                                      tl: /* [] */0
                                    }
                                  }
                                }
                              })),
                      tl: {
                        hd: Res_doc.softLine,
                        tl: {
                          hd: Res_doc.rbracket,
                          tl: /* [] */0
                        }
                      }
                    }
                  }));
          break;
      case /* Ptyp_poly */8 :
          var stringLocs = $$var._0;
          renderedType = stringLocs ? Res_doc.concat({
                  hd: Res_doc.join(Res_doc.space, List.map((function (param) {
                              var doc = Res_doc.concat({
                                    hd: Res_doc.text("'"),
                                    tl: {
                                      hd: Res_doc.text(param.txt),
                                      tl: /* [] */0
                                    }
                                  });
                              return printComments(doc, cmtTbl, param.loc);
                            }), stringLocs)),
                  tl: {
                    hd: Res_doc.dot,
                    tl: {
                      hd: Res_doc.space,
                      tl: {
                        hd: printTypExpr($$var._1, cmtTbl),
                        tl: /* [] */0
                      }
                    }
                  }
                }) : printTypExpr($$var._1, cmtTbl);
          break;
      case /* Ptyp_package */9 :
          renderedType = printPackageType(true, $$var._0, cmtTbl);
          break;
      case /* Ptyp_extension */10 :
          renderedType = printExtension(false, $$var._0, cmtTbl);
          break;
      
    }
  }
  var match$6 = typExpr.ptyp_desc;
  var shouldPrintItsOwnAttributes;
  shouldPrintItsOwnAttributes = typeof match$6 === "number" || match$6.TAG !== /* Ptyp_arrow */1 ? false : true;
  var attrs$3 = typExpr.ptyp_attributes;
  var doc$3 = attrs$3 && !shouldPrintItsOwnAttributes ? Res_doc.group(Res_doc.concat({
              hd: printAttributes(undefined, undefined, attrs$3, cmtTbl),
              tl: {
                hd: renderedType,
                tl: /* [] */0
              }
            })) : renderedType;
  return printComments(doc$3, cmtTbl, typExpr.ptyp_loc);
}

function printObject(inline, fields, openFlag, cmtTbl) {
  var doc;
  if (fields) {
    var tmp;
    tmp = openFlag ? (
        fields && fields.hd.TAG !== /* Otag */0 ? Res_doc.text(".. ") : Res_doc.dotdot
      ) : Res_doc.nil;
    doc = Res_doc.concat({
          hd: Res_doc.lbrace,
          tl: {
            hd: tmp,
            tl: {
              hd: Res_doc.indent(Res_doc.concat({
                        hd: Res_doc.softLine,
                        tl: {
                          hd: Res_doc.join(Res_doc.concat({
                                    hd: Res_doc.comma,
                                    tl: {
                                      hd: Res_doc.line,
                                      tl: /* [] */0
                                    }
                                  }), List.map((function (field) {
                                      return printObjectField(field, cmtTbl);
                                    }), fields)),
                          tl: /* [] */0
                        }
                      })),
              tl: {
                hd: Res_doc.trailingComma,
                tl: {
                  hd: Res_doc.softLine,
                  tl: {
                    hd: Res_doc.rbrace,
                    tl: /* [] */0
                  }
                }
              }
            }
          }
        });
  } else {
    doc = Res_doc.concat({
          hd: Res_doc.lbrace,
          tl: {
            hd: openFlag ? Res_doc.dotdot : Res_doc.dot,
            tl: {
              hd: Res_doc.rbrace,
              tl: /* [] */0
            }
          }
        });
  }
  if (inline) {
    return doc;
  } else {
    return Res_doc.group(doc);
  }
}

function printTupleType(inline, types, cmtTbl) {
  var tuple = Res_doc.concat({
        hd: Res_doc.lparen,
        tl: {
          hd: Res_doc.indent(Res_doc.concat({
                    hd: Res_doc.softLine,
                    tl: {
                      hd: Res_doc.join(Res_doc.concat({
                                hd: Res_doc.comma,
                                tl: {
                                  hd: Res_doc.line,
                                  tl: /* [] */0
                                }
                              }), List.map((function (typexpr) {
                                  return printTypExpr(typexpr, cmtTbl);
                                }), types)),
                      tl: /* [] */0
                    }
                  })),
          tl: {
            hd: Res_doc.trailingComma,
            tl: {
              hd: Res_doc.softLine,
              tl: {
                hd: Res_doc.rparen,
                tl: /* [] */0
              }
            }
          }
        }
      });
  if (inline === false) {
    return Res_doc.group(tuple);
  } else {
    return tuple;
  }
}

function printObjectField(field, cmtTbl) {
  if (field.TAG !== /* Otag */0) {
    return Res_doc.concat({
                hd: Res_doc.dotdotdot,
                tl: {
                  hd: printTypExpr(field._0, cmtTbl),
                  tl: /* [] */0
                }
              });
  }
  var typ = field._2;
  var labelLoc = field._0;
  var doc = Res_doc.text("\"" + (labelLoc.txt + "\""));
  var lbl = printComments(doc, cmtTbl, labelLoc.loc);
  var doc$1 = Res_doc.concat({
        hd: printAttributes(labelLoc.loc, undefined, field._1, cmtTbl),
        tl: {
          hd: lbl,
          tl: {
            hd: Res_doc.text(": "),
            tl: {
              hd: printTypExpr(typ, cmtTbl),
              tl: /* [] */0
            }
          }
        }
      });
  var init = labelLoc.loc;
  var cmtLoc_loc_start = init.loc_start;
  var cmtLoc_loc_end = typ.ptyp_loc.loc_end;
  var cmtLoc_loc_ghost = init.loc_ghost;
  var cmtLoc = {
    loc_start: cmtLoc_loc_start,
    loc_end: cmtLoc_loc_end,
    loc_ghost: cmtLoc_loc_ghost
  };
  return printComments(doc$1, cmtTbl, cmtLoc);
}

function printTypeParameter(param, cmtTbl) {
  var typ = param[2];
  var lbl = param[1];
  var match = Res_parsetree_viewer.processUncurriedAttribute(param[0]);
  var uncurried = match[0] ? Res_doc.concat({
          hd: Res_doc.dot,
          tl: {
            hd: Res_doc.space,
            tl: /* [] */0
          }
        }) : Res_doc.nil;
  var attrs = printAttributes(undefined, undefined, match[1], cmtTbl);
  var label;
  label = typeof lbl === "number" ? Res_doc.nil : Res_doc.concat({
          hd: Res_doc.text("~"),
          tl: {
            hd: printIdentLike(undefined, lbl._0),
            tl: {
              hd: Res_doc.text(": "),
              tl: /* [] */0
            }
          }
        });
  var optionalIndicator;
  optionalIndicator = typeof lbl === "number" || lbl.TAG === /* Labelled */0 ? Res_doc.nil : Res_doc.text("=?");
  var match$1 = typ.ptyp_attributes;
  var match$2;
  if (match$1) {
    var match$3 = match$1.hd[0];
    if (match$3.txt === "ns.namedArgLoc") {
      var loc = match$3.loc;
      match$2 = [
        {
          loc_start: loc.loc_start,
          loc_end: typ.ptyp_loc.loc_end,
          loc_ghost: loc.loc_ghost
        },
        {
          ptyp_desc: typ.ptyp_desc,
          ptyp_loc: typ.ptyp_loc,
          ptyp_attributes: match$1.tl
        }
      ];
    } else {
      match$2 = [
        typ.ptyp_loc,
        typ
      ];
    }
  } else {
    match$2 = [
      typ.ptyp_loc,
      typ
    ];
  }
  var doc = Res_doc.group(Res_doc.concat({
            hd: uncurried,
            tl: {
              hd: attrs,
              tl: {
                hd: label,
                tl: {
                  hd: printTypExpr(match$2[1], cmtTbl),
                  tl: {
                    hd: optionalIndicator,
                    tl: /* [] */0
                  }
                }
              }
            }
          }));
  return printComments(doc, cmtTbl, match$2[0]);
}

function printValueBinding(recFlag, vb, cmtTbl, i) {
  var attrs = printAttributes(vb.pvb_pat.ppat_loc, undefined, vb.pvb_attributes, cmtTbl);
  var header = i === 0 ? Res_doc.concat({
          hd: Res_doc.text("let "),
          tl: {
            hd: recFlag,
            tl: /* [] */0
          }
        }) : Res_doc.text("and ");
  var match = vb.pvb_pat.ppat_desc;
  var exit = 0;
  if (typeof match === "number" || match.TAG !== /* Ppat_constraint */10) {
    exit = 1;
  } else {
    var patTyp = match._1;
    var tmp = patTyp.ptyp_desc;
    if (typeof tmp === "number" || tmp.TAG !== /* Ptyp_poly */8) {
      exit = 1;
    } else {
      var expr = vb.pvb_expr;
      var tmp$1 = expr.pexp_desc;
      if (typeof tmp$1 === "number" || tmp$1.TAG !== /* Pexp_newtype */31) {
        exit = 1;
      } else {
        var pattern = match._0;
        var match$1 = Res_parsetree_viewer.funExpr(expr);
        var parameters = match$1[1];
        var abstractType;
        if (parameters) {
          var match$2 = parameters.hd;
          abstractType = match$2.TAG === /* Parameter */0 || parameters.tl ? Res_doc.nil : Res_doc.concat({
                  hd: Res_doc.text("type "),
                  tl: {
                    hd: Res_doc.join(Res_doc.space, List.map((function ($$var) {
                                return Res_doc.text($$var.txt);
                              }), match$2.locs)),
                    tl: {
                      hd: Res_doc.dot,
                      tl: /* [] */0
                    }
                  }
                });
        } else {
          abstractType = Res_doc.nil;
        }
        var match$3 = match$1[2].pexp_desc;
        var exit$1 = 0;
        if (typeof match$3 === "number") {
          exit$1 = 2;
        } else {
          if (match$3.TAG === /* Pexp_constraint */19) {
            return Res_doc.group(Res_doc.concat({
                            hd: attrs,
                            tl: {
                              hd: header,
                              tl: {
                                hd: printPattern(pattern, cmtTbl),
                                tl: {
                                  hd: Res_doc.text(":"),
                                  tl: {
                                    hd: Res_doc.indent(Res_doc.concat({
                                              hd: Res_doc.line,
                                              tl: {
                                                hd: abstractType,
                                                tl: {
                                                  hd: Res_doc.space,
                                                  tl: {
                                                    hd: printTypExpr(match$3._1, cmtTbl),
                                                    tl: {
                                                      hd: Res_doc.text(" ="),
                                                      tl: {
                                                        hd: Res_doc.concat({
                                                              hd: Res_doc.line,
                                                              tl: {
                                                                hd: printExpressionWithComments(match$3._0, cmtTbl),
                                                                tl: /* [] */0
                                                              }
                                                            }),
                                                        tl: /* [] */0
                                                      }
                                                    }
                                                  }
                                                }
                                              }
                                            })),
                                    tl: /* [] */0
                                  }
                                }
                              }
                            }
                          }));
          }
          exit$1 = 2;
        }
        if (exit$1 === 2) {
          return Res_doc.group(Res_doc.concat({
                          hd: attrs,
                          tl: {
                            hd: header,
                            tl: {
                              hd: printPattern(pattern, cmtTbl),
                              tl: {
                                hd: Res_doc.text(":"),
                                tl: {
                                  hd: Res_doc.indent(Res_doc.concat({
                                            hd: Res_doc.line,
                                            tl: {
                                              hd: abstractType,
                                              tl: {
                                                hd: Res_doc.space,
                                                tl: {
                                                  hd: printTypExpr(patTyp, cmtTbl),
                                                  tl: {
                                                    hd: Res_doc.text(" ="),
                                                    tl: {
                                                      hd: Res_doc.concat({
                                                            hd: Res_doc.line,
                                                            tl: {
                                                              hd: printExpressionWithComments(expr, cmtTbl),
                                                              tl: /* [] */0
                                                            }
                                                          }),
                                                      tl: /* [] */0
                                                    }
                                                  }
                                                }
                                              }
                                            }
                                          })),
                                  tl: /* [] */0
                                }
                              }
                            }
                          }
                        }));
        }
        
      }
    }
  }
  if (exit === 1) {
    var match$4 = Res_parsetree_viewer.processBracesAttr(vb.pvb_expr);
    var expr$1 = match$4[1];
    var doc = printExpressionWithComments(vb.pvb_expr, cmtTbl);
    var braces = Res_parens.expr(vb.pvb_expr);
    var printedExpr = typeof braces === "number" ? (
        braces !== 0 ? doc : addParens(doc)
      ) : printBraces(doc, expr$1, braces._0);
    var patternDoc = printPattern(vb.pvb_pat, cmtTbl);
    if (Res_parsetree_viewer.isSinglePipeExpr(vb.pvb_expr)) {
      return Res_doc.customLayout({
                  hd: Res_doc.group(Res_doc.concat({
                            hd: attrs,
                            tl: {
                              hd: header,
                              tl: {
                                hd: patternDoc,
                                tl: {
                                  hd: Res_doc.text(" ="),
                                  tl: {
                                    hd: Res_doc.space,
                                    tl: {
                                      hd: printedExpr,
                                      tl: /* [] */0
                                    }
                                  }
                                }
                              }
                            }
                          })),
                  tl: {
                    hd: Res_doc.group(Res_doc.concat({
                              hd: attrs,
                              tl: {
                                hd: header,
                                tl: {
                                  hd: patternDoc,
                                  tl: {
                                    hd: Res_doc.text(" ="),
                                    tl: {
                                      hd: Res_doc.indent(Res_doc.concat({
                                                hd: Res_doc.line,
                                                tl: {
                                                  hd: printedExpr,
                                                  tl: /* [] */0
                                                }
                                              })),
                                      tl: /* [] */0
                                    }
                                  }
                                }
                              }
                            })),
                    tl: /* [] */0
                  }
                });
    }
    var shouldIndent;
    if (match$4[0] !== undefined) {
      shouldIndent = false;
    } else if (Res_parsetree_viewer.isBinaryExpression(expr$1)) {
      shouldIndent = true;
    } else {
      var e = vb.pvb_expr;
      var match$5 = e.pexp_desc;
      var tmp$2;
      var exit$2 = 0;
      if (typeof match$5 === "number") {
        exit$2 = 2;
      } else {
        switch (match$5.TAG | 0) {
          case /* Pexp_ifthenelse */15 :
              var match$6 = e.pexp_attributes;
              if (match$6) {
                var ifExpr = match$5._0;
                if (match$6.hd[0].txt === "ns.ternary" && !match$6.tl) {
                  tmp$2 = Res_parsetree_viewer.isBinaryExpression(ifExpr) || Res_parsetree_viewer.hasAttributes(ifExpr.pexp_attributes);
                } else {
                  exit$2 = 2;
                }
              } else {
                exit$2 = 2;
              }
              break;
          case /* Pexp_newtype */31 :
              tmp$2 = false;
              break;
          default:
            exit$2 = 2;
        }
      }
      if (exit$2 === 2) {
        tmp$2 = Res_parsetree_viewer.hasAttributes(e.pexp_attributes) || Res_parsetree_viewer.isArrayAccess(e);
      }
      shouldIndent = tmp$2;
    }
    return Res_doc.group(Res_doc.concat({
                    hd: attrs,
                    tl: {
                      hd: header,
                      tl: {
                        hd: patternDoc,
                        tl: {
                          hd: Res_doc.text(" ="),
                          tl: {
                            hd: shouldIndent ? Res_doc.indent(Res_doc.concat({
                                        hd: Res_doc.line,
                                        tl: {
                                          hd: printedExpr,
                                          tl: /* [] */0
                                        }
                                      })) : Res_doc.concat({
                                    hd: Res_doc.space,
                                    tl: {
                                      hd: printedExpr,
                                      tl: /* [] */0
                                    }
                                  }),
                            tl: /* [] */0
                          }
                        }
                      }
                    }
                  }));
  }
  
}

function printPackageType(printModuleKeywordAndParens, packageType, cmtTbl) {
  var packageConstraints = packageType[1];
  var longidentLoc = packageType[0];
  var doc = packageConstraints ? Res_doc.group(Res_doc.concat({
              hd: printLongidentLocation(longidentLoc, cmtTbl),
              tl: {
                hd: printPackageConstraints(packageConstraints, cmtTbl),
                tl: {
                  hd: Res_doc.softLine,
                  tl: /* [] */0
                }
              }
            })) : Res_doc.group(Res_doc.concat({
              hd: printLongidentLocation(longidentLoc, cmtTbl),
              tl: /* [] */0
            }));
  if (printModuleKeywordAndParens) {
    return Res_doc.concat({
                hd: Res_doc.text("module("),
                tl: {
                  hd: doc,
                  tl: {
                    hd: Res_doc.rparen,
                    tl: /* [] */0
                  }
                }
              });
  } else {
    return doc;
  }
}

function printPackageConstraints(packageConstraints, cmtTbl) {
  return Res_doc.concat({
              hd: Res_doc.text(" with"),
              tl: {
                hd: Res_doc.indent(Res_doc.concat({
                          hd: Res_doc.line,
                          tl: {
                            hd: Res_doc.join(Res_doc.line, List.mapi((function (i, pc) {
                                        var init = pc[0].loc;
                                        var cmtLoc_loc_start = init.loc_start;
                                        var cmtLoc_loc_end = pc[1].ptyp_loc.loc_end;
                                        var cmtLoc_loc_ghost = init.loc_ghost;
                                        var cmtLoc = {
                                          loc_start: cmtLoc_loc_start,
                                          loc_end: cmtLoc_loc_end,
                                          loc_ghost: cmtLoc_loc_ghost
                                        };
                                        var doc = printPackageConstraint(i, cmtTbl, pc);
                                        return printComments(doc, cmtTbl, cmtLoc);
                                      }), packageConstraints)),
                            tl: /* [] */0
                          }
                        })),
                tl: /* [] */0
              }
            });
}

function printPackageConstraint(i, cmtTbl, param) {
  var prefix = i === 0 ? Res_doc.text("type ") : Res_doc.text("and type ");
  return Res_doc.concat({
              hd: prefix,
              tl: {
                hd: printLongidentLocation(param[0], cmtTbl),
                tl: {
                  hd: Res_doc.text(" = "),
                  tl: {
                    hd: printTypExpr(param[1], cmtTbl),
                    tl: /* [] */0
                  }
                }
              }
            });
}

function printExtension(atModuleLvl, param, cmtTbl) {
  var stringLoc = param[0];
  var txt = convertBsExtension(stringLoc.txt);
  var doc = Res_doc.concat({
        hd: Res_doc.text("%"),
        tl: {
          hd: atModuleLvl ? Res_doc.text("%") : Res_doc.nil,
          tl: {
            hd: Res_doc.text(txt),
            tl: /* [] */0
          }
        }
      });
  var extName = printComments(doc, cmtTbl, stringLoc.loc);
  return Res_doc.group(Res_doc.concat({
                  hd: extName,
                  tl: {
                    hd: printPayload(param[1], cmtTbl),
                    tl: /* [] */0
                  }
                }));
}

function printPattern(p, cmtTbl) {
  var $$var = p.ppat_desc;
  var patternWithoutAttributes;
  if (typeof $$var === "number") {
    patternWithoutAttributes = Res_doc.text("_");
  } else {
    switch ($$var.TAG | 0) {
      case /* Ppat_var */0 :
          patternWithoutAttributes = printIdentLike(undefined, $$var._0.txt);
          break;
      case /* Ppat_alias */1 :
          var p$1 = $$var._0;
          var match = p$1.ppat_desc;
          var needsParens;
          if (typeof match === "number") {
            needsParens = false;
          } else {
            switch (match.TAG | 0) {
              case /* Ppat_alias */1 :
              case /* Ppat_or */9 :
                  needsParens = true;
                  break;
              default:
                needsParens = false;
            }
          }
          var p$2 = printPattern(p$1, cmtTbl);
          var renderedPattern = needsParens ? Res_doc.concat({
                  hd: Res_doc.text("("),
                  tl: {
                    hd: p$2,
                    tl: {
                      hd: Res_doc.text(")"),
                      tl: /* [] */0
                    }
                  }
                }) : p$2;
          patternWithoutAttributes = Res_doc.concat({
                hd: renderedPattern,
                tl: {
                  hd: Res_doc.text(" as "),
                  tl: {
                    hd: printStringLoc($$var._1, cmtTbl),
                    tl: /* [] */0
                  }
                }
              });
          break;
      case /* Ppat_constant */2 :
          var templateLiteral = Res_parsetree_viewer.hasTemplateLiteralAttr(p.ppat_attributes);
          patternWithoutAttributes = printConstant(templateLiteral, $$var._0);
          break;
      case /* Ppat_interval */3 :
          patternWithoutAttributes = Res_doc.concat({
                hd: printConstant(undefined, $$var._0),
                tl: {
                  hd: Res_doc.text(" .. "),
                  tl: {
                    hd: printConstant(undefined, $$var._1),
                    tl: /* [] */0
                  }
                }
              });
          break;
      case /* Ppat_tuple */4 :
          patternWithoutAttributes = Res_doc.group(Res_doc.concat({
                    hd: Res_doc.lparen,
                    tl: {
                      hd: Res_doc.indent(Res_doc.concat({
                                hd: Res_doc.softLine,
                                tl: {
                                  hd: Res_doc.join(Res_doc.concat({
                                            hd: Res_doc.text(","),
                                            tl: {
                                              hd: Res_doc.line,
                                              tl: /* [] */0
                                            }
                                          }), List.map((function (pat) {
                                              return printPattern(pat, cmtTbl);
                                            }), $$var._0)),
                                  tl: /* [] */0
                                }
                              })),
                      tl: {
                        hd: Res_doc.trailingComma,
                        tl: {
                          hd: Res_doc.softLine,
                          tl: {
                            hd: Res_doc.rparen,
                            tl: /* [] */0
                          }
                        }
                      }
                    }
                  }));
          break;
      case /* Ppat_construct */5 :
          var constrName = $$var._0;
          var match$1 = constrName.txt;
          var exit = 0;
          switch (match$1.TAG | 0) {
            case /* Lident */0 :
                switch (match$1._0) {
                  case "()" :
                      patternWithoutAttributes = Res_doc.concat({
                            hd: Res_doc.lparen,
                            tl: {
                              hd: printCommentsInside(cmtTbl, p.ppat_loc),
                              tl: {
                                hd: Res_doc.rparen,
                                tl: /* [] */0
                              }
                            }
                          });
                      break;
                  case "::" :
                      var match$2 = Res_parsetree_viewer.collectPatternsFromListConstruct(/* [] */0, p);
                      var tail = match$2[1];
                      var patterns = match$2[0];
                      var shouldHug;
                      if (patterns && !patterns.tl) {
                        var match$3 = tail.ppat_desc;
                        if (typeof match$3 === "number" || match$3.TAG !== /* Ppat_construct */5) {
                          shouldHug = false;
                        } else {
                          var match$4 = match$3._0.txt;
                          switch (match$4.TAG | 0) {
                            case /* Lident */0 :
                                shouldHug = match$4._0 === "[]" && Res_parsetree_viewer.isHuggablePattern(patterns.hd) ? true : false;
                                break;
                            case /* Ldot */1 :
                            case /* Lapply */2 :
                                shouldHug = false;
                                break;
                            
                          }
                        }
                      } else {
                        shouldHug = false;
                      }
                      var match$5 = tail.ppat_desc;
                      var tmp;
                      var exit$1 = 0;
                      if (typeof match$5 === "number" || match$5.TAG !== /* Ppat_construct */5) {
                        exit$1 = 2;
                      } else {
                        var match$6 = match$5._0.txt;
                        switch (match$6.TAG | 0) {
                          case /* Lident */0 :
                              if (match$6._0 === "[]") {
                                tmp = Res_doc.nil;
                              } else {
                                exit$1 = 2;
                              }
                              break;
                          case /* Ldot */1 :
                          case /* Lapply */2 :
                              exit$1 = 2;
                              break;
                          
                        }
                      }
                      if (exit$1 === 2) {
                        var doc = Res_doc.concat({
                              hd: Res_doc.text("..."),
                              tl: {
                                hd: printPattern(tail, cmtTbl),
                                tl: /* [] */0
                              }
                            });
                        var tail$1 = printComments(doc, cmtTbl, tail.ppat_loc);
                        tmp = Res_doc.concat({
                              hd: Res_doc.text(","),
                              tl: {
                                hd: Res_doc.line,
                                tl: {
                                  hd: tail$1,
                                  tl: /* [] */0
                                }
                              }
                            });
                      }
                      var children = Res_doc.concat({
                            hd: shouldHug ? Res_doc.nil : Res_doc.softLine,
                            tl: {
                              hd: Res_doc.join(Res_doc.concat({
                                        hd: Res_doc.text(","),
                                        tl: {
                                          hd: Res_doc.line,
                                          tl: /* [] */0
                                        }
                                      }), List.map((function (pat) {
                                          return printPattern(pat, cmtTbl);
                                        }), patterns)),
                              tl: {
                                hd: tmp,
                                tl: /* [] */0
                              }
                            }
                          });
                      patternWithoutAttributes = Res_doc.group(Res_doc.concat({
                                hd: Res_doc.text("list{"),
                                tl: {
                                  hd: shouldHug ? children : Res_doc.concat({
                                          hd: Res_doc.indent(children),
                                          tl: {
                                            hd: Res_doc.ifBreaks(Res_doc.text(","), Res_doc.nil),
                                            tl: {
                                              hd: Res_doc.softLine,
                                              tl: /* [] */0
                                            }
                                          }
                                        }),
                                  tl: {
                                    hd: Res_doc.rbrace,
                                    tl: /* [] */0
                                  }
                                }
                              }));
                      break;
                  case "[]" :
                      patternWithoutAttributes = Res_doc.concat({
                            hd: Res_doc.text("list{"),
                            tl: {
                              hd: printCommentsInside(cmtTbl, p.ppat_loc),
                              tl: {
                                hd: Res_doc.rbrace,
                                tl: /* [] */0
                              }
                            }
                          });
                      break;
                  default:
                    exit = 1;
                }
                break;
            case /* Ldot */1 :
            case /* Lapply */2 :
                exit = 1;
                break;
            
          }
          if (exit === 1) {
            var constructorArgs = $$var._1;
            var constrName$1 = printLongidentLocation(constrName, cmtTbl);
            var argsDoc;
            if (constructorArgs !== undefined) {
              var patterns$1 = constructorArgs.ppat_desc;
              var exit$2 = 0;
              if (typeof patterns$1 === "number") {
                exit$2 = 2;
              } else {
                switch (patterns$1.TAG | 0) {
                  case /* Ppat_tuple */4 :
                      var patterns$2 = patterns$1._0;
                      var exit$3 = 0;
                      if (patterns$2) {
                        var arg = patterns$2.hd;
                        var tmp$1 = arg.ppat_desc;
                        if (typeof tmp$1 === "number" || !(tmp$1.TAG === /* Ppat_tuple */4 && !patterns$2.tl)) {
                          exit$3 = 3;
                        } else {
                          argsDoc = Res_doc.concat({
                                hd: Res_doc.lparen,
                                tl: {
                                  hd: printPattern(arg, cmtTbl),
                                  tl: {
                                    hd: Res_doc.rparen,
                                    tl: /* [] */0
                                  }
                                }
                              });
                        }
                      } else {
                        argsDoc = Res_doc.concat({
                              hd: Res_doc.lparen,
                              tl: {
                                hd: Res_doc.softLine,
                                tl: {
                                  hd: printCommentsInside(cmtTbl, constructorArgs.ppat_loc),
                                  tl: {
                                    hd: Res_doc.rparen,
                                    tl: /* [] */0
                                  }
                                }
                              }
                            });
                      }
                      if (exit$3 === 3) {
                        argsDoc = Res_doc.concat({
                              hd: Res_doc.lparen,
                              tl: {
                                hd: Res_doc.indent(Res_doc.concat({
                                          hd: Res_doc.softLine,
                                          tl: {
                                            hd: Res_doc.join(Res_doc.concat({
                                                      hd: Res_doc.comma,
                                                      tl: {
                                                        hd: Res_doc.line,
                                                        tl: /* [] */0
                                                      }
                                                    }), List.map((function (pat) {
                                                        return printPattern(pat, cmtTbl);
                                                      }), patterns$2)),
                                            tl: /* [] */0
                                          }
                                        })),
                                tl: {
                                  hd: Res_doc.trailingComma,
                                  tl: {
                                    hd: Res_doc.softLine,
                                    tl: {
                                      hd: Res_doc.rparen,
                                      tl: /* [] */0
                                    }
                                  }
                                }
                              }
                            });
                      }
                      break;
                  case /* Ppat_construct */5 :
                      var match$7 = patterns$1._0.txt;
                      switch (match$7.TAG | 0) {
                        case /* Lident */0 :
                            if (match$7._0 === "()") {
                              argsDoc = Res_doc.concat({
                                    hd: Res_doc.lparen,
                                    tl: {
                                      hd: printCommentsInside(cmtTbl, constructorArgs.ppat_loc),
                                      tl: {
                                        hd: Res_doc.rparen,
                                        tl: /* [] */0
                                      }
                                    }
                                  });
                            } else {
                              exit$2 = 2;
                            }
                            break;
                        case /* Ldot */1 :
                        case /* Lapply */2 :
                            exit$2 = 2;
                            break;
                        
                      }
                      break;
                  default:
                    exit$2 = 2;
                }
              }
              if (exit$2 === 2) {
                var argDoc = printPattern(constructorArgs, cmtTbl);
                var shouldHug$1 = Res_parsetree_viewer.isHuggablePattern(constructorArgs);
                argsDoc = Res_doc.concat({
                      hd: Res_doc.lparen,
                      tl: {
                        hd: shouldHug$1 ? argDoc : Res_doc.concat({
                                hd: Res_doc.indent(Res_doc.concat({
                                          hd: Res_doc.softLine,
                                          tl: {
                                            hd: argDoc,
                                            tl: /* [] */0
                                          }
                                        })),
                                tl: {
                                  hd: Res_doc.trailingComma,
                                  tl: {
                                    hd: Res_doc.softLine,
                                    tl: /* [] */0
                                  }
                                }
                              }),
                        tl: {
                          hd: Res_doc.rparen,
                          tl: /* [] */0
                        }
                      }
                    });
              }
              
            } else {
              argsDoc = Res_doc.nil;
            }
            patternWithoutAttributes = Res_doc.group(Res_doc.concat({
                      hd: constrName$1,
                      tl: {
                        hd: argsDoc,
                        tl: /* [] */0
                      }
                    }));
          }
          break;
      case /* Ppat_variant */6 :
          var variantArgs = $$var._1;
          var label = $$var._0;
          if (variantArgs !== undefined) {
            var variantName = Res_doc.concat({
                  hd: Res_doc.text("#"),
                  tl: {
                    hd: printPolyVarIdent(label),
                    tl: /* [] */0
                  }
                });
            var argsDoc$1;
            if (variantArgs !== undefined) {
              var patterns$3 = variantArgs.ppat_desc;
              var exit$4 = 0;
              if (typeof patterns$3 === "number") {
                exit$4 = 1;
              } else {
                switch (patterns$3.TAG | 0) {
                  case /* Ppat_tuple */4 :
                      var patterns$4 = patterns$3._0;
                      var exit$5 = 0;
                      if (patterns$4) {
                        var arg$1 = patterns$4.hd;
                        var tmp$2 = arg$1.ppat_desc;
                        if (typeof tmp$2 === "number" || !(tmp$2.TAG === /* Ppat_tuple */4 && !patterns$4.tl)) {
                          exit$5 = 2;
                        } else {
                          argsDoc$1 = Res_doc.concat({
                                hd: Res_doc.lparen,
                                tl: {
                                  hd: printPattern(arg$1, cmtTbl),
                                  tl: {
                                    hd: Res_doc.rparen,
                                    tl: /* [] */0
                                  }
                                }
                              });
                        }
                      } else {
                        argsDoc$1 = Res_doc.concat({
                              hd: Res_doc.lparen,
                              tl: {
                                hd: Res_doc.softLine,
                                tl: {
                                  hd: printCommentsInside(cmtTbl, variantArgs.ppat_loc),
                                  tl: {
                                    hd: Res_doc.rparen,
                                    tl: /* [] */0
                                  }
                                }
                              }
                            });
                      }
                      if (exit$5 === 2) {
                        argsDoc$1 = Res_doc.concat({
                              hd: Res_doc.lparen,
                              tl: {
                                hd: Res_doc.indent(Res_doc.concat({
                                          hd: Res_doc.softLine,
                                          tl: {
                                            hd: Res_doc.join(Res_doc.concat({
                                                      hd: Res_doc.comma,
                                                      tl: {
                                                        hd: Res_doc.line,
                                                        tl: /* [] */0
                                                      }
                                                    }), List.map((function (pat) {
                                                        return printPattern(pat, cmtTbl);
                                                      }), patterns$4)),
                                            tl: /* [] */0
                                          }
                                        })),
                                tl: {
                                  hd: Res_doc.trailingComma,
                                  tl: {
                                    hd: Res_doc.softLine,
                                    tl: {
                                      hd: Res_doc.rparen,
                                      tl: /* [] */0
                                    }
                                  }
                                }
                              }
                            });
                      }
                      break;
                  case /* Ppat_construct */5 :
                      var match$8 = patterns$3._0.txt;
                      switch (match$8.TAG | 0) {
                        case /* Lident */0 :
                            if (match$8._0 === "()") {
                              argsDoc$1 = Res_doc.text("()");
                            } else {
                              exit$4 = 1;
                            }
                            break;
                        case /* Ldot */1 :
                        case /* Lapply */2 :
                            exit$4 = 1;
                            break;
                        
                      }
                      break;
                  default:
                    exit$4 = 1;
                }
              }
              if (exit$4 === 1) {
                var argDoc$1 = printPattern(variantArgs, cmtTbl);
                var shouldHug$2 = Res_parsetree_viewer.isHuggablePattern(variantArgs);
                argsDoc$1 = Res_doc.concat({
                      hd: Res_doc.lparen,
                      tl: {
                        hd: shouldHug$2 ? argDoc$1 : Res_doc.concat({
                                hd: Res_doc.indent(Res_doc.concat({
                                          hd: Res_doc.softLine,
                                          tl: {
                                            hd: argDoc$1,
                                            tl: /* [] */0
                                          }
                                        })),
                                tl: {
                                  hd: Res_doc.trailingComma,
                                  tl: {
                                    hd: Res_doc.softLine,
                                    tl: /* [] */0
                                  }
                                }
                              }),
                        tl: {
                          hd: Res_doc.rparen,
                          tl: /* [] */0
                        }
                      }
                    });
              }
              
            } else {
              argsDoc$1 = Res_doc.nil;
            }
            patternWithoutAttributes = Res_doc.group(Res_doc.concat({
                      hd: variantName,
                      tl: {
                        hd: argsDoc$1,
                        tl: /* [] */0
                      }
                    }));
          } else {
            patternWithoutAttributes = Res_doc.concat({
                  hd: Res_doc.text("#"),
                  tl: {
                    hd: printPolyVarIdent(label),
                    tl: /* [] */0
                  }
                });
          }
          break;
      case /* Ppat_record */7 :
          patternWithoutAttributes = Res_doc.group(Res_doc.concat({
                    hd: Res_doc.lbrace,
                    tl: {
                      hd: Res_doc.indent(Res_doc.concat({
                                hd: Res_doc.softLine,
                                tl: {
                                  hd: Res_doc.join(Res_doc.concat({
                                            hd: Res_doc.text(","),
                                            tl: {
                                              hd: Res_doc.line,
                                              tl: /* [] */0
                                            }
                                          }), List.map((function (row) {
                                              return printPatternRecordRow(row, cmtTbl);
                                            }), $$var._0)),
                                  tl: {
                                    hd: $$var._1 ? Res_doc.concat({
                                            hd: Res_doc.text(","),
                                            tl: {
                                              hd: Res_doc.line,
                                              tl: {
                                                hd: Res_doc.text("_"),
                                                tl: /* [] */0
                                              }
                                            }
                                          }) : Res_doc.nil,
                                    tl: /* [] */0
                                  }
                                }
                              })),
                      tl: {
                        hd: Res_doc.ifBreaks(Res_doc.text(","), Res_doc.nil),
                        tl: {
                          hd: Res_doc.softLine,
                          tl: {
                            hd: Res_doc.rbrace,
                            tl: /* [] */0
                          }
                        }
                      }
                    }
                  }));
          break;
      case /* Ppat_array */8 :
          var patterns$5 = $$var._0;
          patternWithoutAttributes = patterns$5 ? Res_doc.group(Res_doc.concat({
                      hd: Res_doc.text("["),
                      tl: {
                        hd: Res_doc.indent(Res_doc.concat({
                                  hd: Res_doc.softLine,
                                  tl: {
                                    hd: Res_doc.join(Res_doc.concat({
                                              hd: Res_doc.text(","),
                                              tl: {
                                                hd: Res_doc.line,
                                                tl: /* [] */0
                                              }
                                            }), List.map((function (pat) {
                                                return printPattern(pat, cmtTbl);
                                              }), patterns$5)),
                                    tl: /* [] */0
                                  }
                                })),
                        tl: {
                          hd: Res_doc.trailingComma,
                          tl: {
                            hd: Res_doc.softLine,
                            tl: {
                              hd: Res_doc.text("]"),
                              tl: /* [] */0
                            }
                          }
                        }
                      }
                    })) : Res_doc.concat({
                  hd: Res_doc.lbracket,
                  tl: {
                    hd: printCommentsInside(cmtTbl, p.ppat_loc),
                    tl: {
                      hd: Res_doc.rbracket,
                      tl: /* [] */0
                    }
                  }
                });
          break;
      case /* Ppat_or */9 :
          var orChain = Res_parsetree_viewer.collectOrPatternChain(p);
          var docs = List.mapi((function (i, pat) {
                  var patternDoc = printPattern(pat, cmtTbl);
                  var match = pat.ppat_desc;
                  var tmp;
                  tmp = typeof match === "number" || match.TAG !== /* Ppat_or */9 ? patternDoc : addParens(patternDoc);
                  return Res_doc.concat({
                              hd: i === 0 ? Res_doc.nil : Res_doc.concat({
                                      hd: Res_doc.line,
                                      tl: {
                                        hd: Res_doc.text("| "),
                                        tl: /* [] */0
                                      }
                                    }),
                              tl: {
                                hd: tmp,
                                tl: /* [] */0
                              }
                            });
                }), orChain);
          var match$9 = List.rev(orChain);
          var isSpreadOverMultipleLines = orChain && match$9 ? orChain.hd.ppat_loc.loc_start.pos_lnum < match$9.hd.ppat_loc.loc_end.pos_lnum : false;
          patternWithoutAttributes = Res_doc.breakableGroup(isSpreadOverMultipleLines, Res_doc.concat(docs));
          break;
      case /* Ppat_constraint */10 :
          var pattern = $$var._0;
          var stringLoc = pattern.ppat_desc;
          var exit$6 = 0;
          if (typeof stringLoc === "number" || stringLoc.TAG !== /* Ppat_unpack */13) {
            exit$6 = 1;
          } else {
            var match$10 = $$var._1;
            var packageType = match$10.ptyp_desc;
            if (typeof packageType === "number" || packageType.TAG !== /* Ptyp_package */9) {
              exit$6 = 1;
            } else {
              var stringLoc$1 = stringLoc._0;
              patternWithoutAttributes = Res_doc.concat({
                    hd: Res_doc.text("module("),
                    tl: {
                      hd: printComments(Res_doc.text(stringLoc$1.txt), cmtTbl, stringLoc$1.loc),
                      tl: {
                        hd: Res_doc.text(": "),
                        tl: {
                          hd: printComments(printPackageType(false, packageType._0, cmtTbl), cmtTbl, match$10.ptyp_loc),
                          tl: {
                            hd: Res_doc.rparen,
                            tl: /* [] */0
                          }
                        }
                      }
                    }
                  });
            }
          }
          if (exit$6 === 1) {
            patternWithoutAttributes = Res_doc.concat({
                  hd: printPattern(pattern, cmtTbl),
                  tl: {
                    hd: Res_doc.text(": "),
                    tl: {
                      hd: printTypExpr($$var._1, cmtTbl),
                      tl: /* [] */0
                    }
                  }
                });
          }
          break;
      case /* Ppat_type */11 :
          patternWithoutAttributes = Res_doc.concat({
                hd: Res_doc.text("#..."),
                tl: {
                  hd: printIdentPath($$var._0, cmtTbl),
                  tl: /* [] */0
                }
              });
          break;
      case /* Ppat_lazy */12 :
          var p$3 = $$var._0;
          var match$11 = p$3.ppat_desc;
          var needsParens$1;
          if (typeof match$11 === "number") {
            needsParens$1 = false;
          } else {
            switch (match$11.TAG | 0) {
              case /* Ppat_alias */1 :
              case /* Ppat_or */9 :
                  needsParens$1 = true;
                  break;
              default:
                needsParens$1 = false;
            }
          }
          var p$4 = printPattern(p$3, cmtTbl);
          var pat = needsParens$1 ? Res_doc.concat({
                  hd: Res_doc.text("("),
                  tl: {
                    hd: p$4,
                    tl: {
                      hd: Res_doc.text(")"),
                      tl: /* [] */0
                    }
                  }
                }) : p$4;
          patternWithoutAttributes = Res_doc.concat({
                hd: Res_doc.text("lazy "),
                tl: {
                  hd: pat,
                  tl: /* [] */0
                }
              });
          break;
      case /* Ppat_unpack */13 :
          var stringLoc$2 = $$var._0;
          patternWithoutAttributes = Res_doc.concat({
                hd: Res_doc.text("module("),
                tl: {
                  hd: printComments(Res_doc.text(stringLoc$2.txt), cmtTbl, stringLoc$2.loc),
                  tl: {
                    hd: Res_doc.rparen,
                    tl: /* [] */0
                  }
                }
              });
          break;
      case /* Ppat_exception */14 :
          var p$5 = $$var._0;
          var match$12 = p$5.ppat_desc;
          var needsParens$2;
          if (typeof match$12 === "number") {
            needsParens$2 = false;
          } else {
            switch (match$12.TAG | 0) {
              case /* Ppat_alias */1 :
              case /* Ppat_or */9 :
                  needsParens$2 = true;
                  break;
              default:
                needsParens$2 = false;
            }
          }
          var p$6 = printPattern(p$5, cmtTbl);
          var pat$1 = needsParens$2 ? Res_doc.concat({
                  hd: Res_doc.text("("),
                  tl: {
                    hd: p$6,
                    tl: {
                      hd: Res_doc.text(")"),
                      tl: /* [] */0
                    }
                  }
                }) : p$6;
          patternWithoutAttributes = Res_doc.group(Res_doc.concat({
                    hd: Res_doc.text("exception"),
                    tl: {
                      hd: Res_doc.line,
                      tl: {
                        hd: pat$1,
                        tl: /* [] */0
                      }
                    }
                  }));
          break;
      case /* Ppat_extension */15 :
          patternWithoutAttributes = printExtension(false, $$var._0, cmtTbl);
          break;
      case /* Ppat_open */16 :
          patternWithoutAttributes = Res_doc.nil;
          break;
      
    }
  }
  var attrs = p.ppat_attributes;
  var doc$1 = attrs ? Res_doc.group(Res_doc.concat({
              hd: printAttributes(undefined, undefined, attrs, cmtTbl),
              tl: {
                hd: patternWithoutAttributes,
                tl: /* [] */0
              }
            })) : patternWithoutAttributes;
  return printComments(doc$1, cmtTbl, p.ppat_loc);
}

function printPatternRecordRow(row, cmtTbl) {
  var longident = row[0];
  var ident = longident.txt;
  switch (ident.TAG | 0) {
    case /* Lident */0 :
        var match = row[1].ppat_desc;
        if (typeof match !== "number" && match.TAG === /* Ppat_var */0 && ident._0 === match._0.txt) {
          return printLidentPath(longident, cmtTbl);
        }
        break;
    case /* Ldot */1 :
    case /* Lapply */2 :
        break;
    
  }
  var pattern = row[1];
  var init = longident.loc;
  var locForComments_loc_start = init.loc_start;
  var locForComments_loc_end = pattern.ppat_loc.loc_end;
  var locForComments_loc_ghost = init.loc_ghost;
  var locForComments = {
    loc_start: locForComments_loc_start,
    loc_end: locForComments_loc_end,
    loc_ghost: locForComments_loc_ghost
  };
  var doc = printPattern(pattern, cmtTbl);
  var rhsDoc = Res_parens.patternRecordRowRhs(pattern) ? addParens(doc) : doc;
  var doc$1 = Res_doc.group(Res_doc.concat({
            hd: printLidentPath(longident, cmtTbl),
            tl: {
              hd: Res_doc.text(":"),
              tl: {
                hd: Res_parsetree_viewer.isHuggablePattern(pattern) ? Res_doc.concat({
                        hd: Res_doc.space,
                        tl: {
                          hd: rhsDoc,
                          tl: /* [] */0
                        }
                      }) : Res_doc.indent(Res_doc.concat({
                            hd: Res_doc.line,
                            tl: {
                              hd: rhsDoc,
                              tl: /* [] */0
                            }
                          })),
                tl: /* [] */0
              }
            }
          }));
  return printComments(doc$1, cmtTbl, locForComments);
}

function printExpressionWithComments(expr, cmtTbl) {
  var doc = printExpression(expr, cmtTbl);
  return printComments(doc, cmtTbl, expr.pexp_loc);
}

function printIfChain(pexp_attributes, ifs, elseExpr, cmtTbl) {
  var ifDocs = Res_doc.join(Res_doc.space, List.mapi((function (i, param) {
              var thenExpr = param[1];
              var ifExpr = param[0];
              var ifTxt = i > 0 ? Res_doc.text("else if ") : Res_doc.text("if ");
              if (ifExpr.TAG === /* If */0) {
                var ifExpr$1 = ifExpr._0;
                var condition;
                if (Res_parsetree_viewer.isBlockExpr(ifExpr$1)) {
                  condition = printExpressionBlock(true, ifExpr$1, cmtTbl);
                } else {
                  var doc = printExpressionWithComments(ifExpr$1, cmtTbl);
                  var braces = Res_parens.expr(ifExpr$1);
                  condition = typeof braces === "number" ? (
                      braces !== 0 ? Res_doc.ifBreaks(addParens(doc), doc) : addParens(doc)
                    ) : printBraces(doc, ifExpr$1, braces._0);
                }
                var match = Res_parsetree_viewer.processBracesAttr(thenExpr);
                var thenExpr$1 = match[0] !== undefined ? match[1] : thenExpr;
                return Res_doc.concat({
                            hd: ifTxt,
                            tl: {
                              hd: Res_doc.group(condition),
                              tl: {
                                hd: Res_doc.space,
                                tl: {
                                  hd: printExpressionBlock(true, thenExpr$1, cmtTbl),
                                  tl: /* [] */0
                                }
                              }
                            }
                          });
              }
              var conditionExpr = ifExpr._1;
              var doc$1 = printExpressionWithComments(conditionExpr, cmtTbl);
              var braces$1 = Res_parens.expr(conditionExpr);
              var conditionDoc = typeof braces$1 === "number" ? (
                  braces$1 !== 0 ? doc$1 : addParens(doc$1)
                ) : printBraces(doc$1, conditionExpr, braces$1._0);
              return Res_doc.concat({
                          hd: ifTxt,
                          tl: {
                            hd: Res_doc.text("let "),
                            tl: {
                              hd: printPattern(ifExpr._0, cmtTbl),
                              tl: {
                                hd: Res_doc.text(" = "),
                                tl: {
                                  hd: conditionDoc,
                                  tl: {
                                    hd: Res_doc.space,
                                    tl: {
                                      hd: printExpressionBlock(true, thenExpr, cmtTbl),
                                      tl: /* [] */0
                                    }
                                  }
                                }
                              }
                            }
                          }
                        });
            }), ifs));
  var elseDoc = elseExpr !== undefined ? Res_doc.concat({
          hd: Res_doc.text(" else "),
          tl: {
            hd: printExpressionBlock(true, elseExpr, cmtTbl),
            tl: /* [] */0
          }
        }) : Res_doc.nil;
  var attrs = Res_parsetree_viewer.filterFragileMatchAttributes(pexp_attributes);
  return Res_doc.concat({
              hd: printAttributes(undefined, undefined, attrs, cmtTbl),
              tl: {
                hd: ifDocs,
                tl: {
                  hd: elseDoc,
                  tl: /* [] */0
                }
              }
            });
}

function printExpression(e, cmtTbl) {
  var c = e.pexp_desc;
  var printedExpression;
  var exit = 0;
  if (typeof c === "number") {
    printedExpression = Res_doc.dot;
  } else {
    switch (c.TAG | 0) {
      case /* Pexp_ident */0 :
          printedExpression = printLidentPath(c._0, cmtTbl);
          break;
      case /* Pexp_constant */1 :
          printedExpression = printConstant(Res_parsetree_viewer.isTemplateLiteral(e), c._0);
          break;
      case /* Pexp_function */3 :
          printedExpression = Res_doc.concat({
                hd: Res_doc.text("x => switch x "),
                tl: {
                  hd: printCases(c._0, cmtTbl),
                  tl: /* [] */0
                }
              });
          break;
      case /* Pexp_fun */4 :
          if (typeof c._0 === "number" && c._1 === undefined) {
            var match = c._2.ppat_desc;
            if (typeof match === "number" || !(match.TAG === /* Ppat_var */0 && match._0.txt === "__x")) {
              exit = 1;
            } else {
              var tmp = c._3.pexp_desc;
              if (typeof tmp === "number" || tmp.TAG !== /* Pexp_apply */5) {
                exit = 1;
              } else {
                printedExpression = printExpressionWithComments(Res_parsetree_viewer.rewriteUnderscoreApply(e), cmtTbl);
              }
            }
          } else {
            exit = 1;
          }
          break;
      case /* Pexp_apply */5 :
          printedExpression = Res_parsetree_viewer.isUnaryExpression(e) ? printUnaryExpression(e, cmtTbl) : (
              Res_parsetree_viewer.isTemplateLiteral(e) ? printTemplateLiteral(e, cmtTbl) : (
                  Res_parsetree_viewer.isBinaryExpression(e) ? printBinaryExpression(e, cmtTbl) : printPexpApply(e, cmtTbl)
                )
            );
          break;
      case /* Pexp_match */6 :
          var cases = c._1;
          var expr = c._0;
          var exit$1 = 0;
          if (cases) {
            var match$1 = cases.tl;
            if (match$1 && !(match$1.tl || !Res_parsetree_viewer.isIfLetExpr(e))) {
              var match$2 = Res_parsetree_viewer.collectIfExpressions(e);
              printedExpression = printIfChain(e.pexp_attributes, match$2[0], match$2[1], cmtTbl);
            } else {
              exit$1 = 2;
            }
          } else {
            exit$1 = 2;
          }
          if (exit$1 === 2) {
            var doc = printExpressionWithComments(expr, cmtTbl);
            var braces = Res_parens.expr(expr);
            var exprDoc = typeof braces === "number" ? (
                braces !== 0 ? doc : addParens(doc)
              ) : printBraces(doc, expr, braces._0);
            printedExpression = Res_doc.concat({
                  hd: Res_doc.text("switch "),
                  tl: {
                    hd: exprDoc,
                    tl: {
                      hd: Res_doc.space,
                      tl: {
                        hd: printCases(cases, cmtTbl),
                        tl: /* [] */0
                      }
                    }
                  }
                });
          }
          break;
      case /* Pexp_try */7 :
          var expr$1 = c._0;
          var doc$1 = printExpressionWithComments(expr$1, cmtTbl);
          var braces$1 = Res_parens.expr(expr$1);
          var exprDoc$1 = typeof braces$1 === "number" ? (
              braces$1 !== 0 ? doc$1 : addParens(doc$1)
            ) : printBraces(doc$1, expr$1, braces$1._0);
          printedExpression = Res_doc.concat({
                hd: Res_doc.text("try "),
                tl: {
                  hd: exprDoc$1,
                  tl: {
                    hd: Res_doc.text(" catch "),
                    tl: {
                      hd: printCases(c._1, cmtTbl),
                      tl: /* [] */0
                    }
                  }
                }
              });
          break;
      case /* Pexp_tuple */8 :
          printedExpression = Res_doc.group(Res_doc.concat({
                    hd: Res_doc.lparen,
                    tl: {
                      hd: Res_doc.indent(Res_doc.concat({
                                hd: Res_doc.softLine,
                                tl: {
                                  hd: Res_doc.join(Res_doc.concat({
                                            hd: Res_doc.text(","),
                                            tl: {
                                              hd: Res_doc.line,
                                              tl: /* [] */0
                                            }
                                          }), List.map((function (expr) {
                                              var doc = printExpressionWithComments(expr, cmtTbl);
                                              var braces = Res_parens.expr(expr);
                                              if (typeof braces === "number") {
                                                if (braces !== 0) {
                                                  return doc;
                                                } else {
                                                  return addParens(doc);
                                                }
                                              } else {
                                                return printBraces(doc, expr, braces._0);
                                              }
                                            }), c._0)),
                                  tl: /* [] */0
                                }
                              })),
                      tl: {
                        hd: Res_doc.ifBreaks(Res_doc.text(","), Res_doc.nil),
                        tl: {
                          hd: Res_doc.softLine,
                          tl: {
                            hd: Res_doc.rparen,
                            tl: /* [] */0
                          }
                        }
                      }
                    }
                  }));
          break;
      case /* Pexp_construct */9 :
          var longidentLoc = c._0;
          var match$3 = longidentLoc.txt;
          var exit$2 = 0;
          if (Res_parsetree_viewer.hasJsxAttribute(e.pexp_attributes)) {
            printedExpression = printJsxFragment(e, cmtTbl);
          } else {
            switch (match$3.TAG | 0) {
              case /* Lident */0 :
                  switch (match$3._0) {
                    case "()" :
                        printedExpression = Res_doc.text("()");
                        break;
                    case "::" :
                        var match$4 = Res_parsetree_viewer.collectListExpressions(e);
                        var spread = match$4[1];
                        var spreadDoc;
                        if (spread !== undefined) {
                          var doc$2 = printExpressionWithComments(spread, cmtTbl);
                          var braces$2 = Res_parens.expr(spread);
                          spreadDoc = Res_doc.concat({
                                hd: Res_doc.text(","),
                                tl: {
                                  hd: Res_doc.line,
                                  tl: {
                                    hd: Res_doc.dotdotdot,
                                    tl: {
                                      hd: typeof braces$2 === "number" ? (
                                          braces$2 !== 0 ? doc$2 : addParens(doc$2)
                                        ) : printBraces(doc$2, spread, braces$2._0),
                                      tl: /* [] */0
                                    }
                                  }
                                }
                              });
                        } else {
                          spreadDoc = Res_doc.nil;
                        }
                        printedExpression = Res_doc.group(Res_doc.concat({
                                  hd: Res_doc.text("list{"),
                                  tl: {
                                    hd: Res_doc.indent(Res_doc.concat({
                                              hd: Res_doc.softLine,
                                              tl: {
                                                hd: Res_doc.join(Res_doc.concat({
                                                          hd: Res_doc.text(","),
                                                          tl: {
                                                            hd: Res_doc.line,
                                                            tl: /* [] */0
                                                          }
                                                        }), List.map((function (expr) {
                                                            var doc = printExpressionWithComments(expr, cmtTbl);
                                                            var braces = Res_parens.expr(expr);
                                                            if (typeof braces === "number") {
                                                              if (braces !== 0) {
                                                                return doc;
                                                              } else {
                                                                return addParens(doc);
                                                              }
                                                            } else {
                                                              return printBraces(doc, expr, braces._0);
                                                            }
                                                          }), match$4[0])),
                                                tl: {
                                                  hd: spreadDoc,
                                                  tl: /* [] */0
                                                }
                                              }
                                            })),
                                    tl: {
                                      hd: Res_doc.trailingComma,
                                      tl: {
                                        hd: Res_doc.softLine,
                                        tl: {
                                          hd: Res_doc.rbrace,
                                          tl: /* [] */0
                                        }
                                      }
                                    }
                                  }
                                }));
                        break;
                    case "[]" :
                        printedExpression = Res_doc.concat({
                              hd: Res_doc.text("list{"),
                              tl: {
                                hd: printCommentsInside(cmtTbl, e.pexp_loc),
                                tl: {
                                  hd: Res_doc.rbrace,
                                  tl: /* [] */0
                                }
                              }
                            });
                        break;
                    default:
                      exit$2 = 2;
                  }
                  break;
              case /* Ldot */1 :
              case /* Lapply */2 :
                  exit$2 = 2;
                  break;
              
            }
          }
          if (exit$2 === 2) {
            var args = c._1;
            var constr = printLongidentLocation(longidentLoc, cmtTbl);
            var args$1;
            if (args !== undefined) {
              var args$2 = args.pexp_desc;
              var exit$3 = 0;
              if (typeof args$2 === "number") {
                exit$3 = 3;
              } else {
                switch (args$2.TAG | 0) {
                  case /* Pexp_tuple */8 :
                      var args$3 = args$2._0;
                      var exit$4 = 0;
                      if (args$3) {
                        var arg = args$3.hd;
                        var tmp$1 = arg.pexp_desc;
                        if (typeof tmp$1 === "number" || !(tmp$1.TAG === /* Pexp_tuple */8 && !args$3.tl)) {
                          exit$4 = 4;
                        } else {
                          var doc$3 = printExpressionWithComments(arg, cmtTbl);
                          var braces$3 = Res_parens.expr(arg);
                          args$1 = Res_doc.concat({
                                hd: Res_doc.lparen,
                                tl: {
                                  hd: typeof braces$3 === "number" ? (
                                      braces$3 !== 0 ? doc$3 : addParens(doc$3)
                                    ) : printBraces(doc$3, arg, braces$3._0),
                                  tl: {
                                    hd: Res_doc.rparen,
                                    tl: /* [] */0
                                  }
                                }
                              });
                        }
                      } else {
                        exit$4 = 4;
                      }
                      if (exit$4 === 4) {
                        args$1 = Res_doc.concat({
                              hd: Res_doc.lparen,
                              tl: {
                                hd: Res_doc.indent(Res_doc.concat({
                                          hd: Res_doc.softLine,
                                          tl: {
                                            hd: Res_doc.join(Res_doc.concat({
                                                      hd: Res_doc.comma,
                                                      tl: {
                                                        hd: Res_doc.line,
                                                        tl: /* [] */0
                                                      }
                                                    }), List.map((function (expr) {
                                                        var doc = printExpressionWithComments(expr, cmtTbl);
                                                        var braces = Res_parens.expr(expr);
                                                        if (typeof braces === "number") {
                                                          if (braces !== 0) {
                                                            return doc;
                                                          } else {
                                                            return addParens(doc);
                                                          }
                                                        } else {
                                                          return printBraces(doc, expr, braces._0);
                                                        }
                                                      }), args$3)),
                                            tl: /* [] */0
                                          }
                                        })),
                                tl: {
                                  hd: Res_doc.trailingComma,
                                  tl: {
                                    hd: Res_doc.softLine,
                                    tl: {
                                      hd: Res_doc.rparen,
                                      tl: /* [] */0
                                    }
                                  }
                                }
                              }
                            });
                      }
                      break;
                  case /* Pexp_construct */9 :
                      var match$5 = args$2._0.txt;
                      switch (match$5.TAG | 0) {
                        case /* Lident */0 :
                            if (match$5._0 === "()") {
                              args$1 = Res_doc.text("()");
                            } else {
                              exit$3 = 3;
                            }
                            break;
                        case /* Ldot */1 :
                        case /* Lapply */2 :
                            exit$3 = 3;
                            break;
                        
                      }
                      break;
                  default:
                    exit$3 = 3;
                }
              }
              if (exit$3 === 3) {
                var doc$4 = printExpressionWithComments(args, cmtTbl);
                var braces$4 = Res_parens.expr(args);
                var argDoc = typeof braces$4 === "number" ? (
                    braces$4 !== 0 ? doc$4 : addParens(doc$4)
                  ) : printBraces(doc$4, args, braces$4._0);
                var shouldHug = Res_parsetree_viewer.isHuggableExpression(args);
                args$1 = Res_doc.concat({
                      hd: Res_doc.lparen,
                      tl: {
                        hd: shouldHug ? argDoc : Res_doc.concat({
                                hd: Res_doc.indent(Res_doc.concat({
                                          hd: Res_doc.softLine,
                                          tl: {
                                            hd: argDoc,
                                            tl: /* [] */0
                                          }
                                        })),
                                tl: {
                                  hd: Res_doc.trailingComma,
                                  tl: {
                                    hd: Res_doc.softLine,
                                    tl: /* [] */0
                                  }
                                }
                              }),
                        tl: {
                          hd: Res_doc.rparen,
                          tl: /* [] */0
                        }
                      }
                    });
              }
              
            } else {
              args$1 = Res_doc.nil;
            }
            printedExpression = Res_doc.group(Res_doc.concat({
                      hd: constr,
                      tl: {
                        hd: args$1,
                        tl: /* [] */0
                      }
                    }));
          }
          break;
      case /* Pexp_variant */10 :
          var args$4 = c._1;
          var variantName = Res_doc.concat({
                hd: Res_doc.text("#"),
                tl: {
                  hd: printPolyVarIdent(c._0),
                  tl: /* [] */0
                }
              });
          var args$5;
          if (args$4 !== undefined) {
            var args$6 = args$4.pexp_desc;
            var exit$5 = 0;
            if (typeof args$6 === "number") {
              exit$5 = 2;
            } else {
              switch (args$6.TAG | 0) {
                case /* Pexp_tuple */8 :
                    var args$7 = args$6._0;
                    var exit$6 = 0;
                    if (args$7) {
                      var arg$1 = args$7.hd;
                      var tmp$2 = arg$1.pexp_desc;
                      if (typeof tmp$2 === "number" || !(tmp$2.TAG === /* Pexp_tuple */8 && !args$7.tl)) {
                        exit$6 = 3;
                      } else {
                        var doc$5 = printExpressionWithComments(arg$1, cmtTbl);
                        var braces$5 = Res_parens.expr(arg$1);
                        args$5 = Res_doc.concat({
                              hd: Res_doc.lparen,
                              tl: {
                                hd: typeof braces$5 === "number" ? (
                                    braces$5 !== 0 ? doc$5 : addParens(doc$5)
                                  ) : printBraces(doc$5, arg$1, braces$5._0),
                                tl: {
                                  hd: Res_doc.rparen,
                                  tl: /* [] */0
                                }
                              }
                            });
                      }
                    } else {
                      exit$6 = 3;
                    }
                    if (exit$6 === 3) {
                      args$5 = Res_doc.concat({
                            hd: Res_doc.lparen,
                            tl: {
                              hd: Res_doc.indent(Res_doc.concat({
                                        hd: Res_doc.softLine,
                                        tl: {
                                          hd: Res_doc.join(Res_doc.concat({
                                                    hd: Res_doc.comma,
                                                    tl: {
                                                      hd: Res_doc.line,
                                                      tl: /* [] */0
                                                    }
                                                  }), List.map((function (expr) {
                                                      var doc = printExpressionWithComments(expr, cmtTbl);
                                                      var braces = Res_parens.expr(expr);
                                                      if (typeof braces === "number") {
                                                        if (braces !== 0) {
                                                          return doc;
                                                        } else {
                                                          return addParens(doc);
                                                        }
                                                      } else {
                                                        return printBraces(doc, expr, braces._0);
                                                      }
                                                    }), args$7)),
                                          tl: /* [] */0
                                        }
                                      })),
                              tl: {
                                hd: Res_doc.trailingComma,
                                tl: {
                                  hd: Res_doc.softLine,
                                  tl: {
                                    hd: Res_doc.rparen,
                                    tl: /* [] */0
                                  }
                                }
                              }
                            }
                          });
                    }
                    break;
                case /* Pexp_construct */9 :
                    var match$6 = args$6._0.txt;
                    switch (match$6.TAG | 0) {
                      case /* Lident */0 :
                          if (match$6._0 === "()") {
                            args$5 = Res_doc.text("()");
                          } else {
                            exit$5 = 2;
                          }
                          break;
                      case /* Ldot */1 :
                      case /* Lapply */2 :
                          exit$5 = 2;
                          break;
                      
                    }
                    break;
                default:
                  exit$5 = 2;
              }
            }
            if (exit$5 === 2) {
              var doc$6 = printExpressionWithComments(args$4, cmtTbl);
              var braces$6 = Res_parens.expr(args$4);
              var argDoc$1 = typeof braces$6 === "number" ? (
                  braces$6 !== 0 ? doc$6 : addParens(doc$6)
                ) : printBraces(doc$6, args$4, braces$6._0);
              var shouldHug$1 = Res_parsetree_viewer.isHuggableExpression(args$4);
              args$5 = Res_doc.concat({
                    hd: Res_doc.lparen,
                    tl: {
                      hd: shouldHug$1 ? argDoc$1 : Res_doc.concat({
                              hd: Res_doc.indent(Res_doc.concat({
                                        hd: Res_doc.softLine,
                                        tl: {
                                          hd: argDoc$1,
                                          tl: /* [] */0
                                        }
                                      })),
                              tl: {
                                hd: Res_doc.trailingComma,
                                tl: {
                                  hd: Res_doc.softLine,
                                  tl: /* [] */0
                                }
                              }
                            }),
                      tl: {
                        hd: Res_doc.rparen,
                        tl: /* [] */0
                      }
                    }
                  });
            }
            
          } else {
            args$5 = Res_doc.nil;
          }
          printedExpression = Res_doc.group(Res_doc.concat({
                    hd: variantName,
                    tl: {
                      hd: args$5,
                      tl: /* [] */0
                    }
                  }));
          break;
      case /* Pexp_record */11 :
          var spreadExpr = c._1;
          var rows = c._0;
          var spread$1;
          if (spreadExpr !== undefined) {
            var doc$7 = printExpressionWithComments(spreadExpr, cmtTbl);
            var braces$7 = Res_parens.expr(spreadExpr);
            spread$1 = Res_doc.concat({
                  hd: Res_doc.dotdotdot,
                  tl: {
                    hd: typeof braces$7 === "number" ? (
                        braces$7 !== 0 ? doc$7 : addParens(doc$7)
                      ) : printBraces(doc$7, spreadExpr, braces$7._0),
                    tl: {
                      hd: Res_doc.comma,
                      tl: {
                        hd: Res_doc.line,
                        tl: /* [] */0
                      }
                    }
                  }
                });
          } else {
            spread$1 = Res_doc.nil;
          }
          var forceBreak = e.pexp_loc.loc_start.pos_lnum < e.pexp_loc.loc_end.pos_lnum;
          var punningAllowed = spreadExpr !== undefined || !(rows && !rows.tl) ? true : false;
          printedExpression = Res_doc.breakableGroup(forceBreak, Res_doc.concat({
                    hd: Res_doc.lbrace,
                    tl: {
                      hd: Res_doc.indent(Res_doc.concat({
                                hd: Res_doc.softLine,
                                tl: {
                                  hd: spread$1,
                                  tl: {
                                    hd: Res_doc.join(Res_doc.concat({
                                              hd: Res_doc.text(","),
                                              tl: {
                                                hd: Res_doc.line,
                                                tl: /* [] */0
                                              }
                                            }), List.map((function (row) {
                                                return printRecordRow(row, cmtTbl, punningAllowed);
                                              }), rows)),
                                    tl: /* [] */0
                                  }
                                }
                              })),
                      tl: {
                        hd: Res_doc.trailingComma,
                        tl: {
                          hd: Res_doc.softLine,
                          tl: {
                            hd: Res_doc.rbrace,
                            tl: /* [] */0
                          }
                        }
                      }
                    }
                  }));
          break;
      case /* Pexp_field */12 :
          var expr$2 = c._0;
          var doc$8 = printExpressionWithComments(expr$2, cmtTbl);
          var braces$8 = Res_parens.fieldExpr(expr$2);
          var lhs = typeof braces$8 === "number" ? (
              braces$8 !== 0 ? doc$8 : addParens(doc$8)
            ) : printBraces(doc$8, expr$2, braces$8._0);
          printedExpression = Res_doc.concat({
                hd: lhs,
                tl: {
                  hd: Res_doc.dot,
                  tl: {
                    hd: printLidentPath(c._1, cmtTbl),
                    tl: /* [] */0
                  }
                }
              });
          break;
      case /* Pexp_setfield */13 :
          printedExpression = printSetFieldExpr(e.pexp_attributes, c._0, c._1, c._2, e.pexp_loc, cmtTbl);
          break;
      case /* Pexp_array */14 :
          var exprs = c._0;
          printedExpression = exprs ? Res_doc.group(Res_doc.concat({
                      hd: Res_doc.lbracket,
                      tl: {
                        hd: Res_doc.indent(Res_doc.concat({
                                  hd: Res_doc.softLine,
                                  tl: {
                                    hd: Res_doc.join(Res_doc.concat({
                                              hd: Res_doc.text(","),
                                              tl: {
                                                hd: Res_doc.line,
                                                tl: /* [] */0
                                              }
                                            }), List.map((function (expr) {
                                                var doc = printExpressionWithComments(expr, cmtTbl);
                                                var braces = Res_parens.expr(expr);
                                                if (typeof braces === "number") {
                                                  if (braces !== 0) {
                                                    return doc;
                                                  } else {
                                                    return addParens(doc);
                                                  }
                                                } else {
                                                  return printBraces(doc, expr, braces._0);
                                                }
                                              }), exprs)),
                                    tl: /* [] */0
                                  }
                                })),
                        tl: {
                          hd: Res_doc.trailingComma,
                          tl: {
                            hd: Res_doc.softLine,
                            tl: {
                              hd: Res_doc.rbracket,
                              tl: /* [] */0
                            }
                          }
                        }
                      }
                    })) : Res_doc.concat({
                  hd: Res_doc.lbracket,
                  tl: {
                    hd: printCommentsInside(cmtTbl, e.pexp_loc),
                    tl: {
                      hd: Res_doc.rbracket,
                      tl: /* [] */0
                    }
                  }
                });
          break;
      case /* Pexp_ifthenelse */15 :
          if (Res_parsetree_viewer.isTernaryExpr(e)) {
            var match$7 = Res_parsetree_viewer.collectTernaryParts(e);
            var parts = match$7[0];
            var ternaryDoc;
            if (parts) {
              var match$8 = parts.hd;
              ternaryDoc = Res_doc.group(Res_doc.concat({
                        hd: printTernaryOperand(match$8[0], cmtTbl),
                        tl: {
                          hd: Res_doc.indent(Res_doc.concat({
                                    hd: Res_doc.line,
                                    tl: {
                                      hd: Res_doc.indent(Res_doc.concat({
                                                hd: Res_doc.text("? "),
                                                tl: {
                                                  hd: printTernaryOperand(match$8[1], cmtTbl),
                                                  tl: /* [] */0
                                                }
                                              })),
                                      tl: {
                                        hd: Res_doc.concat(List.map((function (param) {
                                                    return Res_doc.concat({
                                                                hd: Res_doc.line,
                                                                tl: {
                                                                  hd: Res_doc.text(": "),
                                                                  tl: {
                                                                    hd: printTernaryOperand(param[0], cmtTbl),
                                                                    tl: {
                                                                      hd: Res_doc.line,
                                                                      tl: {
                                                                        hd: Res_doc.text("? "),
                                                                        tl: {
                                                                          hd: printTernaryOperand(param[1], cmtTbl),
                                                                          tl: /* [] */0
                                                                        }
                                                                      }
                                                                    }
                                                                  }
                                                                }
                                                              });
                                                  }), parts.tl)),
                                        tl: {
                                          hd: Res_doc.line,
                                          tl: {
                                            hd: Res_doc.text(": "),
                                            tl: {
                                              hd: Res_doc.indent(printTernaryOperand(match$7[1], cmtTbl)),
                                              tl: /* [] */0
                                            }
                                          }
                                        }
                                      }
                                    }
                                  })),
                          tl: /* [] */0
                        }
                      }));
            } else {
              ternaryDoc = Res_doc.nil;
            }
            var attrs = Res_parsetree_viewer.filterTernaryAttributes(e.pexp_attributes);
            var match$9 = Res_parsetree_viewer.filterParsingAttrs(attrs);
            var needsParens = match$9 ? true : false;
            printedExpression = Res_doc.concat({
                  hd: printAttributes(undefined, undefined, attrs, cmtTbl),
                  tl: {
                    hd: needsParens ? addParens(ternaryDoc) : ternaryDoc,
                    tl: /* [] */0
                  }
                });
          } else {
            var match$10 = Res_parsetree_viewer.collectIfExpressions(e);
            printedExpression = printIfChain(e.pexp_attributes, match$10[0], match$10[1], cmtTbl);
          }
          break;
      case /* Pexp_while */17 :
          var expr1 = c._0;
          var doc$9 = printExpressionWithComments(expr1, cmtTbl);
          var braces$9 = Res_parens.expr(expr1);
          var condition = typeof braces$9 === "number" ? (
              braces$9 !== 0 ? doc$9 : addParens(doc$9)
            ) : printBraces(doc$9, expr1, braces$9._0);
          printedExpression = Res_doc.breakableGroup(true, Res_doc.concat({
                    hd: Res_doc.text("while "),
                    tl: {
                      hd: Res_parsetree_viewer.isBlockExpr(expr1) ? condition : Res_doc.group(Res_doc.ifBreaks(addParens(condition), condition)),
                      tl: {
                        hd: Res_doc.space,
                        tl: {
                          hd: printExpressionBlock(true, c._1, cmtTbl),
                          tl: /* [] */0
                        }
                      }
                    }
                  }));
          break;
      case /* Pexp_for */18 :
          var toExpr = c._2;
          var fromExpr = c._1;
          var doc$10 = printExpressionWithComments(fromExpr, cmtTbl);
          var braces$10 = Res_parens.expr(fromExpr);
          var doc$11 = printExpressionWithComments(toExpr, cmtTbl);
          var braces$11 = Res_parens.expr(toExpr);
          printedExpression = Res_doc.breakableGroup(true, Res_doc.concat({
                    hd: Res_doc.text("for "),
                    tl: {
                      hd: printPattern(c._0, cmtTbl),
                      tl: {
                        hd: Res_doc.text(" in "),
                        tl: {
                          hd: typeof braces$10 === "number" ? (
                              braces$10 !== 0 ? doc$10 : addParens(doc$10)
                            ) : printBraces(doc$10, fromExpr, braces$10._0),
                          tl: {
                            hd: printDirectionFlag(c._3),
                            tl: {
                              hd: typeof braces$11 === "number" ? (
                                  braces$11 !== 0 ? doc$11 : addParens(doc$11)
                                ) : printBraces(doc$11, toExpr, braces$11._0),
                              tl: {
                                hd: Res_doc.space,
                                tl: {
                                  hd: printExpressionBlock(true, c._4, cmtTbl),
                                  tl: /* [] */0
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }));
          break;
      case /* Pexp_constraint */19 :
          var expr$3 = c._0;
          var modExpr = expr$3.pexp_desc;
          var exit$7 = 0;
          if (typeof modExpr === "number" || modExpr.TAG !== /* Pexp_pack */32) {
            exit$7 = 2;
          } else {
            var match$11 = c._1;
            var packageType = match$11.ptyp_desc;
            if (typeof packageType === "number" || packageType.TAG !== /* Ptyp_package */9) {
              exit$7 = 2;
            } else {
              printedExpression = Res_doc.group(Res_doc.concat({
                        hd: Res_doc.text("module("),
                        tl: {
                          hd: Res_doc.indent(Res_doc.concat({
                                    hd: Res_doc.softLine,
                                    tl: {
                                      hd: printModExpr(modExpr._0, cmtTbl),
                                      tl: {
                                        hd: Res_doc.text(": "),
                                        tl: {
                                          hd: printComments(printPackageType(false, packageType._0, cmtTbl), cmtTbl, match$11.ptyp_loc),
                                          tl: /* [] */0
                                        }
                                      }
                                    }
                                  })),
                          tl: {
                            hd: Res_doc.softLine,
                            tl: {
                              hd: Res_doc.rparen,
                              tl: /* [] */0
                            }
                          }
                        }
                      }));
            }
          }
          if (exit$7 === 2) {
            var doc$12 = printExpressionWithComments(expr$3, cmtTbl);
            var braces$12 = Res_parens.expr(expr$3);
            var exprDoc$2 = typeof braces$12 === "number" ? (
                braces$12 !== 0 ? doc$12 : addParens(doc$12)
              ) : printBraces(doc$12, expr$3, braces$12._0);
            printedExpression = Res_doc.concat({
                  hd: exprDoc$2,
                  tl: {
                    hd: Res_doc.text(": "),
                    tl: {
                      hd: printTypExpr(c._1, cmtTbl),
                      tl: /* [] */0
                    }
                  }
                });
          }
          break;
      case /* Pexp_coerce */20 :
          var typOpt = c._1;
          var docExpr = printExpressionWithComments(c._0, cmtTbl);
          var docTyp = printTypExpr(c._2, cmtTbl);
          var ofType = typOpt !== undefined ? Res_doc.concat({
                  hd: Res_doc.text(": "),
                  tl: {
                    hd: printTypExpr(typOpt, cmtTbl),
                    tl: /* [] */0
                  }
                }) : Res_doc.nil;
          printedExpression = Res_doc.concat({
                hd: Res_doc.lparen,
                tl: {
                  hd: docExpr,
                  tl: {
                    hd: ofType,
                    tl: {
                      hd: Res_doc.text(" :> "),
                      tl: {
                        hd: docTyp,
                        tl: {
                          hd: Res_doc.rparen,
                          tl: /* [] */0
                        }
                      }
                    }
                  }
                }
              });
          break;
      case /* Pexp_send */21 :
          var label = c._1;
          var parentExpr = c._0;
          var doc$13 = printExpressionWithComments(parentExpr, cmtTbl);
          var braces$13 = Res_parens.unaryExprOperand(parentExpr);
          var parentDoc = typeof braces$13 === "number" ? (
              braces$13 !== 0 ? doc$13 : addParens(doc$13)
            ) : printBraces(doc$13, parentExpr, braces$13._0);
          var memberDoc = printComments(Res_doc.text(label.txt), cmtTbl, label.loc);
          var member = Res_doc.concat({
                hd: Res_doc.text("\""),
                tl: {
                  hd: memberDoc,
                  tl: {
                    hd: Res_doc.text("\""),
                    tl: /* [] */0
                  }
                }
              });
          printedExpression = Res_doc.group(Res_doc.concat({
                    hd: parentDoc,
                    tl: {
                      hd: Res_doc.lbracket,
                      tl: {
                        hd: member,
                        tl: {
                          hd: Res_doc.rbracket,
                          tl: /* [] */0
                        }
                      }
                    }
                  }));
          break;
      case /* Pexp_new */22 :
          printedExpression = Res_doc.text("Pexp_new not impemented in printer");
          break;
      case /* Pexp_setinstvar */23 :
          printedExpression = Res_doc.text("Pexp_setinstvar not impemented in printer");
          break;
      case /* Pexp_override */24 :
          printedExpression = Res_doc.text("Pexp_override not impemented in printer");
          break;
      case /* Pexp_assert */27 :
          var expr$4 = c._0;
          var doc$14 = printExpressionWithComments(expr$4, cmtTbl);
          var braces$14 = Res_parens.lazyOrAssertExprRhs(expr$4);
          var rhs = typeof braces$14 === "number" ? (
              braces$14 !== 0 ? doc$14 : addParens(doc$14)
            ) : printBraces(doc$14, expr$4, braces$14._0);
          printedExpression = Res_doc.concat({
                hd: Res_doc.text("assert "),
                tl: {
                  hd: rhs,
                  tl: /* [] */0
                }
              });
          break;
      case /* Pexp_lazy */28 :
          var expr$5 = c._0;
          var doc$15 = printExpressionWithComments(expr$5, cmtTbl);
          var braces$15 = Res_parens.lazyOrAssertExprRhs(expr$5);
          var rhs$1 = typeof braces$15 === "number" ? (
              braces$15 !== 0 ? doc$15 : addParens(doc$15)
            ) : printBraces(doc$15, expr$5, braces$15._0);
          printedExpression = Res_doc.group(Res_doc.concat({
                    hd: Res_doc.text("lazy "),
                    tl: {
                      hd: rhs$1,
                      tl: /* [] */0
                    }
                  }));
          break;
      case /* Pexp_poly */29 :
          printedExpression = Res_doc.text("Pexp_poly not impemented in printer");
          break;
      case /* Pexp_object */30 :
          printedExpression = Res_doc.text("Pexp_object not impemented in printer");
          break;
      case /* Pexp_newtype */31 :
          exit = 1;
          break;
      case /* Pexp_pack */32 :
          printedExpression = Res_doc.group(Res_doc.concat({
                    hd: Res_doc.text("module("),
                    tl: {
                      hd: Res_doc.indent(Res_doc.concat({
                                hd: Res_doc.softLine,
                                tl: {
                                  hd: printModExpr(c._0, cmtTbl),
                                  tl: /* [] */0
                                }
                              })),
                      tl: {
                        hd: Res_doc.softLine,
                        tl: {
                          hd: Res_doc.rparen,
                          tl: /* [] */0
                        }
                      }
                    }
                  }));
          break;
      case /* Pexp_extension */34 :
          var extension = c._0;
          var exit$8 = 0;
          switch (extension[0].txt) {
            case "bs.obj" :
            case "obj" :
                exit$8 = 2;
                break;
            default:
              printedExpression = printExtension(false, extension, cmtTbl);
          }
          if (exit$8 === 2) {
            var match$12 = extension[1];
            if (match$12.TAG === /* PStr */0) {
              var match$13 = match$12._0;
              if (match$13) {
                var match$14 = match$13.hd;
                var match$15 = match$14.pstr_desc;
                if (match$15.TAG === /* Pstr_eval */0) {
                  var match$16 = match$15._0.pexp_desc;
                  if (typeof match$16 === "number" || !(match$16.TAG === /* Pexp_record */11 && !(match$15._1 || match$13.tl))) {
                    printedExpression = printExtension(false, extension, cmtTbl);
                  } else {
                    var loc = match$14.pstr_loc;
                    var forceBreak$1 = loc.loc_start.pos_lnum < loc.loc_end.pos_lnum;
                    printedExpression = Res_doc.breakableGroup(forceBreak$1, Res_doc.concat({
                              hd: Res_doc.lbrace,
                              tl: {
                                hd: Res_doc.indent(Res_doc.concat({
                                          hd: Res_doc.softLine,
                                          tl: {
                                            hd: Res_doc.join(Res_doc.concat({
                                                      hd: Res_doc.text(","),
                                                      tl: {
                                                        hd: Res_doc.line,
                                                        tl: /* [] */0
                                                      }
                                                    }), List.map((function (row) {
                                                        return printBsObjectRow(row, cmtTbl);
                                                      }), match$16._0)),
                                            tl: /* [] */0
                                          }
                                        })),
                                tl: {
                                  hd: Res_doc.trailingComma,
                                  tl: {
                                    hd: Res_doc.softLine,
                                    tl: {
                                      hd: Res_doc.rbrace,
                                      tl: /* [] */0
                                    }
                                  }
                                }
                              }
                            }));
                  }
                } else {
                  printedExpression = printExtension(false, extension, cmtTbl);
                }
              } else {
                printedExpression = printExtension(false, extension, cmtTbl);
              }
            } else {
              printedExpression = printExtension(false, extension, cmtTbl);
            }
          }
          break;
      default:
        printedExpression = printExpressionBlock(true, e, cmtTbl);
    }
  }
  if (exit === 1) {
    var match$17 = Res_parsetree_viewer.funExpr(e);
    var returnExpr = match$17[2];
    var match$18 = Res_parsetree_viewer.processUncurriedAttribute(match$17[0]);
    var match$19 = returnExpr.pexp_desc;
    var match$20;
    if (typeof match$19 === "number" || match$19.TAG !== /* Pexp_constraint */19) {
      match$20 = [
        returnExpr,
        undefined
      ];
    } else {
      var expr$6 = match$19._0;
      match$20 = [
        {
          pexp_desc: expr$6.pexp_desc,
          pexp_loc: expr$6.pexp_loc,
          pexp_attributes: List.concat({
                hd: expr$6.pexp_attributes,
                tl: {
                  hd: returnExpr.pexp_attributes,
                  tl: /* [] */0
                }
              })
        },
        match$19._1
      ];
    }
    var typConstraint = match$20[1];
    var returnExpr$1 = match$20[0];
    var hasConstraint = typConstraint !== undefined;
    var parametersDoc = printExprFunParameters(/* NoCallback */0, match$18[0], hasConstraint, match$17[1], cmtTbl);
    var match$21 = Res_parsetree_viewer.processBracesAttr(returnExpr$1);
    var match$22 = returnExpr$1.pexp_desc;
    var shouldInline;
    if (match$21[0] !== undefined) {
      shouldInline = true;
    } else if (typeof match$22 === "number") {
      shouldInline = false;
    } else {
      switch (match$22.TAG | 0) {
        case /* Pexp_construct */9 :
            shouldInline = match$22._1 !== undefined;
            break;
        case /* Pexp_tuple */8 :
        case /* Pexp_record */11 :
        case /* Pexp_array */14 :
            shouldInline = true;
            break;
        default:
          shouldInline = false;
      }
    }
    var match$23 = returnExpr$1.pexp_desc;
    var shouldIndent;
    if (typeof match$23 === "number") {
      shouldIndent = true;
    } else {
      switch (match$23.TAG | 0) {
        case /* Pexp_let */2 :
        case /* Pexp_sequence */16 :
        case /* Pexp_letmodule */25 :
        case /* Pexp_letexception */26 :
        case /* Pexp_open */33 :
            shouldIndent = false;
            break;
        default:
          shouldIndent = true;
      }
    }
    var doc$16 = printExpressionWithComments(returnExpr$1, cmtTbl);
    var braces$16 = Res_parens.expr(returnExpr$1);
    var returnDoc = typeof braces$16 === "number" ? (
        braces$16 !== 0 ? doc$16 : addParens(doc$16)
      ) : printBraces(doc$16, returnExpr$1, braces$16._0);
    var returnExprDoc = shouldInline ? Res_doc.concat({
            hd: Res_doc.space,
            tl: {
              hd: returnDoc,
              tl: /* [] */0
            }
          }) : Res_doc.group(shouldIndent ? Res_doc.indent(Res_doc.concat({
                      hd: Res_doc.line,
                      tl: {
                        hd: returnDoc,
                        tl: /* [] */0
                      }
                    })) : Res_doc.concat({
                  hd: Res_doc.space,
                  tl: {
                    hd: returnDoc,
                    tl: /* [] */0
                  }
                }));
    var typConstraintDoc;
    if (typConstraint !== undefined) {
      var doc$17 = printTypExpr(typConstraint, cmtTbl);
      var typDoc = Res_parens.arrowReturnTypExpr(typConstraint) ? addParens(doc$17) : doc$17;
      typConstraintDoc = Res_doc.concat({
            hd: Res_doc.text(": "),
            tl: {
              hd: typDoc,
              tl: /* [] */0
            }
          });
    } else {
      typConstraintDoc = Res_doc.nil;
    }
    var attrs$1 = printAttributes(undefined, undefined, match$18[1], cmtTbl);
    printedExpression = Res_doc.group(Res_doc.concat({
              hd: attrs$1,
              tl: {
                hd: parametersDoc,
                tl: {
                  hd: typConstraintDoc,
                  tl: {
                    hd: Res_doc.text(" =>"),
                    tl: {
                      hd: returnExprDoc,
                      tl: /* [] */0
                    }
                  }
                }
              }
            }));
  }
  var match$24 = e.pexp_desc;
  var shouldPrintItsOwnAttributes;
  if (typeof match$24 === "number") {
    shouldPrintItsOwnAttributes = false;
  } else {
    switch (match$24.TAG | 0) {
      case /* Pexp_match */6 :
          shouldPrintItsOwnAttributes = Res_parsetree_viewer.isIfLetExpr(e) ? true : false;
          break;
      case /* Pexp_construct */9 :
          shouldPrintItsOwnAttributes = Res_parsetree_viewer.hasJsxAttribute(e.pexp_attributes) ? true : false;
          break;
      case /* Pexp_fun */4 :
      case /* Pexp_apply */5 :
      case /* Pexp_setfield */13 :
      case /* Pexp_ifthenelse */15 :
      case /* Pexp_newtype */31 :
          shouldPrintItsOwnAttributes = true;
          break;
      default:
        shouldPrintItsOwnAttributes = false;
    }
  }
  var attrs$2 = e.pexp_attributes;
  if (attrs$2 && !shouldPrintItsOwnAttributes) {
    return Res_doc.group(Res_doc.concat({
                    hd: printAttributes(undefined, undefined, attrs$2, cmtTbl),
                    tl: {
                      hd: printedExpression,
                      tl: /* [] */0
                    }
                  }));
  } else {
    return printedExpression;
  }
}

function printPexpFun(inCallback, e, cmtTbl) {
  var match = Res_parsetree_viewer.funExpr(e);
  var returnExpr = match[2];
  var match$1 = Res_parsetree_viewer.processUncurriedAttribute(match[0]);
  var match$2 = returnExpr.pexp_desc;
  var match$3;
  if (typeof match$2 === "number" || match$2.TAG !== /* Pexp_constraint */19) {
    match$3 = [
      returnExpr,
      undefined
    ];
  } else {
    var expr = match$2._0;
    match$3 = [
      {
        pexp_desc: expr.pexp_desc,
        pexp_loc: expr.pexp_loc,
        pexp_attributes: List.concat({
              hd: expr.pexp_attributes,
              tl: {
                hd: returnExpr.pexp_attributes,
                tl: /* [] */0
              }
            })
      },
      match$2._1
    ];
  }
  var typConstraint = match$3[1];
  var returnExpr$1 = match$3[0];
  var parametersDoc = printExprFunParameters(inCallback, match$1[0], typConstraint !== undefined, match[1], cmtTbl);
  var match$4 = returnExpr$1.pexp_desc;
  var returnShouldIndent;
  if (typeof match$4 === "number") {
    returnShouldIndent = true;
  } else {
    switch (match$4.TAG | 0) {
      case /* Pexp_let */2 :
      case /* Pexp_sequence */16 :
      case /* Pexp_letmodule */25 :
      case /* Pexp_letexception */26 :
      case /* Pexp_open */33 :
          returnShouldIndent = false;
          break;
      default:
        returnShouldIndent = true;
    }
  }
  var match$5 = Res_parsetree_viewer.processBracesAttr(returnExpr$1);
  var match$6 = returnExpr$1.pexp_desc;
  var shouldInline;
  if (match$5[0] !== undefined) {
    shouldInline = true;
  } else if (typeof match$6 === "number") {
    shouldInline = false;
  } else {
    switch (match$6.TAG | 0) {
      case /* Pexp_construct */9 :
          shouldInline = match$6._1 !== undefined;
          break;
      case /* Pexp_tuple */8 :
      case /* Pexp_record */11 :
      case /* Pexp_array */14 :
          shouldInline = true;
          break;
      default:
        shouldInline = false;
    }
  }
  var doc = printExpressionWithComments(returnExpr$1, cmtTbl);
  var braces = Res_parens.expr(returnExpr$1);
  var returnDoc = typeof braces === "number" ? (
      braces !== 0 ? doc : addParens(doc)
    ) : printBraces(doc, returnExpr$1, braces._0);
  var returnExprDoc = shouldInline ? Res_doc.concat({
          hd: Res_doc.space,
          tl: {
            hd: returnDoc,
            tl: /* [] */0
          }
        }) : Res_doc.group(returnShouldIndent ? Res_doc.concat({
                hd: Res_doc.indent(Res_doc.concat({
                          hd: Res_doc.line,
                          tl: {
                            hd: returnDoc,
                            tl: /* [] */0
                          }
                        })),
                tl: {
                  hd: inCallback !== 0 ? Res_doc.softLine : Res_doc.nil,
                  tl: /* [] */0
                }
              }) : Res_doc.concat({
                hd: Res_doc.space,
                tl: {
                  hd: returnDoc,
                  tl: /* [] */0
                }
              }));
  var typConstraintDoc = typConstraint !== undefined ? Res_doc.concat({
          hd: Res_doc.text(": "),
          tl: {
            hd: printTypExpr(typConstraint, cmtTbl),
            tl: /* [] */0
          }
        }) : Res_doc.nil;
  return Res_doc.concat({
              hd: printAttributes(undefined, undefined, match$1[1], cmtTbl),
              tl: {
                hd: parametersDoc,
                tl: {
                  hd: typConstraintDoc,
                  tl: {
                    hd: Res_doc.text(" =>"),
                    tl: {
                      hd: returnExprDoc,
                      tl: /* [] */0
                    }
                  }
                }
              }
            });
}

function printTernaryOperand(expr, cmtTbl) {
  var doc = printExpressionWithComments(expr, cmtTbl);
  var braces = Res_parens.ternaryOperand(expr);
  if (typeof braces === "number") {
    if (braces !== 0) {
      return doc;
    } else {
      return addParens(doc);
    }
  } else {
    return printBraces(doc, expr, braces._0);
  }
}

function printSetFieldExpr(attrs, lhs, longidentLoc, rhs, loc, cmtTbl) {
  var doc = printExpressionWithComments(rhs, cmtTbl);
  var braces = Res_parens.setFieldExprRhs(rhs);
  var rhsDoc = typeof braces === "number" ? (
      braces !== 0 ? doc : addParens(doc)
    ) : printBraces(doc, rhs, braces._0);
  var doc$1 = printExpressionWithComments(lhs, cmtTbl);
  var braces$1 = Res_parens.fieldExpr(lhs);
  var lhsDoc = typeof braces$1 === "number" ? (
      braces$1 !== 0 ? doc$1 : addParens(doc$1)
    ) : printBraces(doc$1, lhs, braces$1._0);
  var shouldIndent = Res_parsetree_viewer.isBinaryExpression(rhs);
  var doc$2 = Res_doc.group(Res_doc.concat({
            hd: lhsDoc,
            tl: {
              hd: Res_doc.dot,
              tl: {
                hd: printLidentPath(longidentLoc, cmtTbl),
                tl: {
                  hd: Res_doc.text(" ="),
                  tl: {
                    hd: shouldIndent ? Res_doc.group(Res_doc.indent(Res_doc.concat({
                                    hd: Res_doc.line,
                                    tl: {
                                      hd: rhsDoc,
                                      tl: /* [] */0
                                    }
                                  }))) : Res_doc.concat({
                            hd: Res_doc.space,
                            tl: {
                              hd: rhsDoc,
                              tl: /* [] */0
                            }
                          }),
                    tl: /* [] */0
                  }
                }
              }
            }
          }));
  var doc$3 = attrs ? Res_doc.group(Res_doc.concat({
              hd: printAttributes(undefined, undefined, attrs, cmtTbl),
              tl: {
                hd: doc$2,
                tl: /* [] */0
              }
            })) : doc$2;
  return printComments(doc$3, cmtTbl, loc);
}

function printTemplateLiteral(expr, cmtTbl) {
  var tag = {
    contents: "js"
  };
  var walkExpr = function (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) {
              var prefix = match$1._1;
              if (prefix !== undefined) {
                tag.contents = prefix;
                return printStringContents(match$1._0);
              }
              
            }
            break;
        case /* Pexp_apply */5 :
            var match$2 = match._0.pexp_desc;
            if (typeof match$2 !== "number" && match$2.TAG === /* Pexp_ident */0) {
              var match$3 = match$2._0.txt;
              switch (match$3.TAG | 0) {
                case /* Lident */0 :
                    if (match$3._0 === "^") {
                      var match$4 = match._1;
                      if (match$4) {
                        var match$5 = match$4.hd;
                        if (typeof match$5[0] === "number") {
                          var match$6 = match$4.tl;
                          if (match$6) {
                            var match$7 = match$6.hd;
                            if (typeof match$7[0] === "number" && !match$6.tl) {
                              var lhs = walkExpr(match$5[1]);
                              var rhs = walkExpr(match$7[1]);
                              return Res_doc.concat({
                                          hd: lhs,
                                          tl: {
                                            hd: rhs,
                                            tl: /* [] */0
                                          }
                                        });
                            }
                            
                          }
                          
                        }
                        
                      }
                      
                    }
                    break;
                case /* Ldot */1 :
                case /* Lapply */2 :
                    break;
                
              }
            }
            break;
        default:
          
      }
    }
    var doc = printExpressionWithComments(expr, cmtTbl);
    return Res_doc.group(Res_doc.concat({
                    hd: Res_doc.text("${"),
                    tl: {
                      hd: Res_doc.indent(doc),
                      tl: {
                        hd: Res_doc.rbrace,
                        tl: /* [] */0
                      }
                    }
                  }));
  };
  var content = walkExpr(expr);
  return Res_doc.concat({
              hd: tag.contents === "js" ? Res_doc.nil : Res_doc.text(tag.contents),
              tl: {
                hd: Res_doc.text("`"),
                tl: {
                  hd: content,
                  tl: {
                    hd: Res_doc.text("`"),
                    tl: /* [] */0
                  }
                }
              }
            });
}

function printUnaryExpression(expr, cmtTbl) {
  var printUnaryOperator = function (op) {
    var tmp;
    switch (op) {
      case "not" :
          tmp = "!";
          break;
      case "~+" :
          tmp = "+";
          break;
      case "~+." :
          tmp = "+.";
          break;
      case "~-" :
          tmp = "-";
          break;
      case "~-." :
          tmp = "-.";
          break;
      default:
        throw {
              RE_EXN_ID: "Assert_failure",
              _1: [
                "res_printer.res",
                3472,
                13
              ],
              Error: new Error()
            };
    }
    return Res_doc.text(tmp);
  };
  var match = expr.pexp_desc;
  if (typeof match !== "number" && match.TAG === /* Pexp_apply */5) {
    var match$1 = match._0.pexp_desc;
    if (typeof match$1 !== "number" && match$1.TAG === /* Pexp_ident */0) {
      var operator = match$1._0.txt;
      switch (operator.TAG | 0) {
        case /* Lident */0 :
            var match$2 = match._1;
            if (match$2) {
              var match$3 = match$2.hd;
              if (typeof match$3[0] === "number" && !match$2.tl) {
                var operand = match$3[1];
                var doc = printExpressionWithComments(operand, cmtTbl);
                var braces = Res_parens.unaryExprOperand(operand);
                var printedOperand = typeof braces === "number" ? (
                    braces !== 0 ? doc : addParens(doc)
                  ) : printBraces(doc, operand, braces._0);
                var doc$1 = Res_doc.concat({
                      hd: printUnaryOperator(operator._0),
                      tl: {
                        hd: printedOperand,
                        tl: /* [] */0
                      }
                    });
                return printComments(doc$1, cmtTbl, expr.pexp_loc);
              }
              
            }
            break;
        case /* Ldot */1 :
        case /* Lapply */2 :
            break;
        
      }
    }
    
  }
  throw {
        RE_EXN_ID: "Assert_failure",
        _1: [
          "res_printer.res",
          3491,
          9
        ],
        Error: new Error()
      };
}

function printBinaryExpression(expr, cmtTbl) {
  var printBinaryOperator = function (inlineRhs, operator) {
    var operatorTxt;
    switch (operator) {
      case "!=" :
          operatorTxt = "!==";
          break;
      case "<>" :
          operatorTxt = "!=";
          break;
      case "=" :
          operatorTxt = "==";
          break;
      case "==" :
          operatorTxt = "===";
          break;
      case "^" :
          operatorTxt = "++";
          break;
      case "|." :
          operatorTxt = "->";
          break;
      default:
        operatorTxt = operator;
    }
    var spacingBeforeOperator = operator === "|." ? Res_doc.softLine : (
        operator === "|>" ? Res_doc.line : Res_doc.space
      );
    var spacingAfterOperator = operator === "|." ? Res_doc.nil : (
        operator === "|>" || inlineRhs ? Res_doc.space : Res_doc.line
      );
    return Res_doc.concat({
                hd: spacingBeforeOperator,
                tl: {
                  hd: Res_doc.text(operatorTxt),
                  tl: {
                    hd: spacingAfterOperator,
                    tl: /* [] */0
                  }
                }
              });
  };
  var printOperand = function (isLhs, expr, parentOperator) {
    var flatten = function (isLhs, expr, parentOperator) {
      if (Res_parsetree_viewer.isBinaryExpression(expr)) {
        var match = expr.pexp_desc;
        if (typeof match !== "number" && match.TAG === /* Pexp_apply */5) {
          var match$1 = match._0.pexp_desc;
          if (typeof match$1 !== "number" && match$1.TAG === /* Pexp_ident */0) {
            var operator = match$1._0.txt;
            switch (operator.TAG | 0) {
              case /* Lident */0 :
                  var match$2 = match._1;
                  if (match$2) {
                    var match$3 = match$2.tl;
                    if (match$3 && !match$3.tl) {
                      var right = match$3.hd[1];
                      var operator$1 = operator._0;
                      if (Res_parsetree_viewer.flattenableOperators(parentOperator, operator$1) && !Res_parsetree_viewer.hasAttributes(expr.pexp_attributes)) {
                        var leftPrinted = flatten(true, match$2.hd[1], operator$1);
                        var match$4 = Res_parsetree_viewer.partitionPrintableAttributes(right.pexp_attributes);
                        var doc = printExpressionWithComments({
                              pexp_desc: right.pexp_desc,
                              pexp_loc: right.pexp_loc,
                              pexp_attributes: match$4[1]
                            }, cmtTbl);
                        var doc$1 = Res_parens.flattenOperandRhs(parentOperator, right) ? Res_doc.concat({
                                hd: Res_doc.lparen,
                                tl: {
                                  hd: doc,
                                  tl: {
                                    hd: Res_doc.rparen,
                                    tl: /* [] */0
                                  }
                                }
                              }) : doc;
                        var printableAttrs = Res_parsetree_viewer.filterPrintableAttributes(right.pexp_attributes);
                        var doc$2 = Res_doc.concat({
                              hd: printAttributes(undefined, undefined, printableAttrs, cmtTbl),
                              tl: {
                                hd: doc$1,
                                tl: /* [] */0
                              }
                            });
                        var rightPrinted = printableAttrs ? addParens(doc$2) : doc$2;
                        var doc$3 = Res_doc.concat({
                              hd: leftPrinted,
                              tl: {
                                hd: printBinaryOperator(false, operator$1),
                                tl: {
                                  hd: rightPrinted,
                                  tl: /* [] */0
                                }
                              }
                            });
                        var doc$4 = !isLhs && Res_parens.rhsBinaryExprOperand(operator$1, expr) ? Res_doc.concat({
                                hd: Res_doc.lparen,
                                tl: {
                                  hd: doc$3,
                                  tl: {
                                    hd: Res_doc.rparen,
                                    tl: /* [] */0
                                  }
                                }
                              }) : doc$3;
                        return printComments(doc$4, cmtTbl, expr.pexp_loc);
                      }
                      var doc$5 = printExpressionWithComments({
                            pexp_desc: expr.pexp_desc,
                            pexp_loc: expr.pexp_loc,
                            pexp_attributes: /* [] */0
                          }, cmtTbl);
                      var doc$6 = Res_parens.subBinaryExprOperand(parentOperator, operator$1) || expr.pexp_attributes !== /* [] */0 && (Res_parsetree_viewer.isBinaryExpression(expr) || Res_parsetree_viewer.isTernaryExpr(expr)) ? Res_doc.concat({
                              hd: Res_doc.lparen,
                              tl: {
                                hd: doc$5,
                                tl: {
                                  hd: Res_doc.rparen,
                                  tl: /* [] */0
                                }
                              }
                            }) : doc$5;
                      return Res_doc.concat({
                                  hd: printAttributes(undefined, undefined, expr.pexp_attributes, cmtTbl),
                                  tl: {
                                    hd: doc$6,
                                    tl: /* [] */0
                                  }
                                });
                    }
                    
                  }
                  break;
              case /* Ldot */1 :
              case /* Lapply */2 :
                  break;
              
            }
          }
          
        }
        throw {
              RE_EXN_ID: "Assert_failure",
              _1: [
                "res_printer.res",
                3590,
                15
              ],
              Error: new Error()
            };
      }
      var match$5 = expr.pexp_desc;
      if (typeof match$5 !== "number") {
        switch (match$5.TAG | 0) {
          case /* Pexp_apply */5 :
              var match$6 = match$5._0.pexp_desc;
              if (typeof match$6 !== "number" && match$6.TAG === /* Pexp_ident */0) {
                var match$7 = match$6._0;
                var match$8 = match$7.txt;
                switch (match$8.TAG | 0) {
                  case /* Lident */0 :
                      switch (match$8._0) {
                        case "#=" :
                            var match$9 = match$5._1;
                            if (match$9) {
                              var match$10 = match$9.hd;
                              if (typeof match$10[0] === "number") {
                                var match$11 = match$9.tl;
                                if (match$11) {
                                  var match$12 = match$11.hd;
                                  if (typeof match$12[0] === "number" && !match$11.tl) {
                                    var rhs = match$12[1];
                                    var rhsDoc = printExpressionWithComments(rhs, cmtTbl);
                                    var lhsDoc = printExpressionWithComments(match$10[1], cmtTbl);
                                    var shouldIndent = Res_parsetree_viewer.isBinaryExpression(rhs);
                                    var doc$7 = Res_doc.group(Res_doc.concat({
                                              hd: lhsDoc,
                                              tl: {
                                                hd: Res_doc.text(" ="),
                                                tl: {
                                                  hd: shouldIndent ? Res_doc.group(Res_doc.indent(Res_doc.concat({
                                                                  hd: Res_doc.line,
                                                                  tl: {
                                                                    hd: rhsDoc,
                                                                    tl: /* [] */0
                                                                  }
                                                                }))) : Res_doc.concat({
                                                          hd: Res_doc.space,
                                                          tl: {
                                                            hd: rhsDoc,
                                                            tl: /* [] */0
                                                          }
                                                        }),
                                                  tl: /* [] */0
                                                }
                                              }
                                            }));
                                    var attrs = expr.pexp_attributes;
                                    var doc$8 = attrs ? Res_doc.group(Res_doc.concat({
                                                hd: printAttributes(undefined, undefined, attrs, cmtTbl),
                                                tl: {
                                                  hd: doc$7,
                                                  tl: /* [] */0
                                                }
                                              })) : doc$7;
                                    if (isLhs) {
                                      return addParens(doc$8);
                                    } else {
                                      return doc$8;
                                    }
                                  }
                                  
                                }
                                
                              }
                              
                            }
                            break;
                        case "^" :
                            var match$13 = match$5._1;
                            if (match$13 && typeof match$13.hd[0] === "number") {
                              var match$14 = match$13.tl;
                              if (match$14 && typeof match$14.hd[0] === "number" && !match$14.tl && match$7.loc.loc_ghost) {
                                var doc$9 = printTemplateLiteral(expr, cmtTbl);
                                return printComments(doc$9, cmtTbl, expr.pexp_loc);
                              }
                              
                            }
                            break;
                        default:
                          
                      }
                      break;
                  case /* Ldot */1 :
                  case /* Lapply */2 :
                      break;
                  
                }
              }
              break;
          case /* Pexp_setfield */13 :
              var doc$10 = printSetFieldExpr(expr.pexp_attributes, match$5._0, match$5._1, match$5._2, expr.pexp_loc, cmtTbl);
              if (isLhs) {
                return addParens(doc$10);
              } else {
                return doc$10;
              }
          default:
            
        }
      }
      var doc$11 = printExpressionWithComments(expr, cmtTbl);
      var braces = Res_parens.binaryExprOperand(isLhs, expr);
      if (typeof braces === "number") {
        if (braces !== 0) {
          return doc$11;
        } else {
          return addParens(doc$11);
        }
      } else {
        return printBraces(doc$11, expr, braces._0);
      }
    };
    return flatten(isLhs, expr, parentOperator);
  };
  var match = expr.pexp_desc;
  if (typeof match === "number") {
    return Res_doc.nil;
  }
  if (match.TAG !== /* Pexp_apply */5) {
    return Res_doc.nil;
  }
  var match$1 = match._0.pexp_desc;
  if (typeof match$1 === "number") {
    return Res_doc.nil;
  }
  if (match$1.TAG !== /* Pexp_ident */0) {
    return Res_doc.nil;
  }
  var op = match$1._0.txt;
  switch (op.TAG | 0) {
    case /* Lident */0 :
        var op$1 = op._0;
        var exit = 0;
        switch (op$1) {
          case "|." :
          case "|>" :
              exit = 2;
              break;
          default:
            
        }
        if (exit === 2) {
          var match$2 = match._1;
          if (!match$2) {
            return Res_doc.nil;
          }
          var match$3 = match$2.hd;
          if (typeof match$3[0] !== "number") {
            return Res_doc.nil;
          }
          var match$4 = match$2.tl;
          if (!match$4) {
            return Res_doc.nil;
          }
          var match$5 = match$4.hd;
          if (typeof match$5[0] !== "number") {
            return Res_doc.nil;
          }
          if (match$4.tl) {
            return Res_doc.nil;
          }
          var rhs = match$5[1];
          var lhs = match$3[1];
          if (!(Res_parsetree_viewer.isBinaryExpression(lhs) || Res_parsetree_viewer.isBinaryExpression(rhs))) {
            var lhsHasCommentBelow = hasCommentBelow(cmtTbl, lhs.pexp_loc);
            var lhsDoc = printOperand(true, lhs, op$1);
            var rhsDoc = printOperand(false, rhs, op$1);
            var tmp;
            if (lhsHasCommentBelow) {
              switch (op$1) {
                case "|." :
                    tmp = Res_doc.concat({
                          hd: Res_doc.softLine,
                          tl: {
                            hd: Res_doc.text("->"),
                            tl: /* [] */0
                          }
                        });
                    break;
                case "|>" :
                    tmp = Res_doc.concat({
                          hd: Res_doc.line,
                          tl: {
                            hd: Res_doc.text("|> "),
                            tl: /* [] */0
                          }
                        });
                    break;
                default:
                  tmp = Res_doc.nil;
              }
            } else {
              switch (op$1) {
                case "|." :
                    tmp = Res_doc.text("->");
                    break;
                case "|>" :
                    tmp = Res_doc.text(" |> ");
                    break;
                default:
                  tmp = Res_doc.nil;
              }
            }
            return Res_doc.group(Res_doc.concat({
                            hd: lhsDoc,
                            tl: {
                              hd: tmp,
                              tl: {
                                hd: rhsDoc,
                                tl: /* [] */0
                              }
                            }
                          }));
          }
          
        }
        var match$6 = match._1;
        if (!match$6) {
          return Res_doc.nil;
        }
        var match$7 = match$6.hd;
        if (typeof match$7[0] !== "number") {
          return Res_doc.nil;
        }
        var match$8 = match$6.tl;
        if (!match$8) {
          return Res_doc.nil;
        }
        var match$9 = match$8.hd;
        if (typeof match$9[0] !== "number") {
          return Res_doc.nil;
        }
        if (match$8.tl) {
          return Res_doc.nil;
        }
        var rhs$1 = match$9[1];
        var rhsDoc$1 = printOperand(false, rhs$1, op$1);
        var operatorWithRhs = Res_doc.concat({
              hd: printBinaryOperator(Res_parsetree_viewer.shouldInlineRhsBinaryExpr(rhs$1), op$1),
              tl: {
                hd: rhsDoc$1,
                tl: /* [] */0
              }
            });
        var right = Res_parsetree_viewer.shouldIndentBinaryExpr(expr) ? Res_doc.group(Res_doc.indent(operatorWithRhs)) : operatorWithRhs;
        var doc = Res_doc.group(Res_doc.concat({
                  hd: printOperand(true, match$7[1], op$1),
                  tl: {
                    hd: right,
                    tl: /* [] */0
                  }
                }));
        var bracesLoc = Res_parens.binaryExpr({
              pexp_desc: expr.pexp_desc,
              pexp_loc: expr.pexp_loc,
              pexp_attributes: List.filter(function (attr) {
                      if (attr[0].txt === "ns.braces") {
                        return false;
                      } else {
                        return true;
                      }
                    })(expr.pexp_attributes)
            });
        return Res_doc.group(Res_doc.concat({
                        hd: printAttributes(undefined, undefined, expr.pexp_attributes, cmtTbl),
                        tl: {
                          hd: typeof bracesLoc === "number" ? (
                              bracesLoc !== 0 ? doc : addParens(doc)
                            ) : printBraces(doc, expr, bracesLoc._0),
                          tl: /* [] */0
                        }
                      }));
        break;
    case /* Ldot */1 :
    case /* Lapply */2 :
        return Res_doc.nil;
    
  }
}

function printPexpApply(expr, cmtTbl) {
  var match = expr.pexp_desc;
  if (typeof match === "number") {
    throw {
          RE_EXN_ID: "Assert_failure",
          _1: [
            "res_printer.res",
            3945,
            9
          ],
          Error: new Error()
        };
  }
  if (match.TAG === /* Pexp_apply */5) {
    var callExpr = match._0;
    var lident = callExpr.pexp_desc;
    if (typeof lident !== "number" && lident.TAG === /* Pexp_ident */0) {
      var lident$1 = lident._0;
      var match$1 = lident$1.txt;
      var exit = 0;
      switch (match$1.TAG | 0) {
        case /* Lident */0 :
            switch (match$1._0) {
              case "##" :
                  var match$2 = match._1;
                  if (match$2) {
                    var match$3 = match$2.hd;
                    if (typeof match$3[0] === "number") {
                      var match$4 = match$2.tl;
                      if (match$4) {
                        var match$5 = match$4.hd;
                        if (typeof match$5[0] === "number" && !match$4.tl) {
                          var memberExpr = match$5[1];
                          var parentExpr = match$3[1];
                          var doc = printExpressionWithComments(parentExpr, cmtTbl);
                          var braces = Res_parens.unaryExprOperand(parentExpr);
                          var parentDoc = typeof braces === "number" ? (
                              braces !== 0 ? doc : addParens(doc)
                            ) : printBraces(doc, parentExpr, braces._0);
                          var lident$2 = memberExpr.pexp_desc;
                          var memberDoc;
                          memberDoc = typeof lident$2 === "number" || lident$2.TAG !== /* Pexp_ident */0 ? printExpressionWithComments(memberExpr, cmtTbl) : printComments(printLongident(lident$2._0.txt), cmtTbl, memberExpr.pexp_loc);
                          var member = Res_doc.concat({
                                hd: Res_doc.text("\""),
                                tl: {
                                  hd: memberDoc,
                                  tl: {
                                    hd: Res_doc.text("\""),
                                    tl: /* [] */0
                                  }
                                }
                              });
                          return Res_doc.group(Res_doc.concat({
                                          hd: printAttributes(undefined, undefined, expr.pexp_attributes, cmtTbl),
                                          tl: {
                                            hd: parentDoc,
                                            tl: {
                                              hd: Res_doc.lbracket,
                                              tl: {
                                                hd: member,
                                                tl: {
                                                  hd: Res_doc.rbracket,
                                                  tl: /* [] */0
                                                }
                                              }
                                            }
                                          }
                                        }));
                        }
                        exit = 2;
                      } else {
                        exit = 2;
                      }
                    } else {
                      exit = 2;
                    }
                  } else {
                    exit = 2;
                  }
                  break;
              case "#=" :
                  var match$6 = match._1;
                  if (match$6) {
                    var match$7 = match$6.hd;
                    if (typeof match$7[0] === "number") {
                      var match$8 = match$6.tl;
                      if (match$8) {
                        var match$9 = match$8.hd;
                        if (typeof match$9[0] === "number" && !match$8.tl) {
                          var rhs = match$9[1];
                          var doc$1 = printExpressionWithComments(rhs, cmtTbl);
                          var braces$1 = Res_parens.expr(rhs);
                          var rhsDoc = typeof braces$1 === "number" ? (
                              braces$1 !== 0 ? doc$1 : addParens(doc$1)
                            ) : printBraces(doc$1, rhs, braces$1._0);
                          var shouldIndent = !Res_parsetree_viewer.isBracedExpr(rhs) && Res_parsetree_viewer.isBinaryExpression(rhs);
                          var doc$2 = Res_doc.group(Res_doc.concat({
                                    hd: printExpressionWithComments(match$7[1], cmtTbl),
                                    tl: {
                                      hd: Res_doc.text(" ="),
                                      tl: {
                                        hd: shouldIndent ? Res_doc.group(Res_doc.indent(Res_doc.concat({
                                                        hd: Res_doc.line,
                                                        tl: {
                                                          hd: rhsDoc,
                                                          tl: /* [] */0
                                                        }
                                                      }))) : Res_doc.concat({
                                                hd: Res_doc.space,
                                                tl: {
                                                  hd: rhsDoc,
                                                  tl: /* [] */0
                                                }
                                              }),
                                        tl: /* [] */0
                                      }
                                    }
                                  }));
                          var attrs = expr.pexp_attributes;
                          if (attrs) {
                            return Res_doc.group(Res_doc.concat({
                                            hd: printAttributes(undefined, undefined, attrs, cmtTbl),
                                            tl: {
                                              hd: doc$2,
                                              tl: /* [] */0
                                            }
                                          }));
                          } else {
                            return doc$2;
                          }
                        }
                        exit = 2;
                      } else {
                        exit = 2;
                      }
                    } else {
                      exit = 2;
                    }
                  } else {
                    exit = 2;
                  }
                  break;
              default:
                exit = 2;
            }
            break;
        case /* Ldot */1 :
            var match$10 = match$1._0;
            switch (match$10.TAG | 0) {
              case /* Lident */0 :
                  if (match$10._0 === "Array") {
                    switch (match$1._1) {
                      case "get" :
                          var match$11 = match._1;
                          if (match$11) {
                            var match$12 = match$11.hd;
                            if (typeof match$12[0] === "number") {
                              var match$13 = match$11.tl;
                              if (match$13) {
                                var match$14 = match$13.hd;
                                if (typeof match$14[0] === "number" && !match$13.tl) {
                                  var memberExpr$1 = match$14[1];
                                  var parentExpr$1 = match$12[1];
                                  if (Res_parsetree_viewer.isRewrittenUnderscoreApplySugar(parentExpr$1)) {
                                    exit = 2;
                                  } else {
                                    var doc$3 = printExpressionWithComments(memberExpr$1, cmtTbl);
                                    var braces$2 = Res_parens.expr(memberExpr$1);
                                    var memberDoc$1 = typeof braces$2 === "number" ? (
                                        braces$2 !== 0 ? doc$3 : addParens(doc$3)
                                      ) : printBraces(doc$3, memberExpr$1, braces$2._0);
                                    var match$15 = memberExpr$1.pexp_desc;
                                    var shouldInline;
                                    if (typeof match$15 === "number") {
                                      shouldInline = false;
                                    } else {
                                      switch (match$15.TAG | 0) {
                                        case /* Pexp_ident */0 :
                                        case /* Pexp_constant */1 :
                                            shouldInline = true;
                                            break;
                                        default:
                                          shouldInline = false;
                                      }
                                    }
                                    var member$1 = shouldInline ? memberDoc$1 : Res_doc.concat({
                                            hd: Res_doc.indent(Res_doc.concat({
                                                      hd: Res_doc.softLine,
                                                      tl: {
                                                        hd: memberDoc$1,
                                                        tl: /* [] */0
                                                      }
                                                    })),
                                            tl: {
                                              hd: Res_doc.softLine,
                                              tl: /* [] */0
                                            }
                                          });
                                    var doc$4 = printExpressionWithComments(parentExpr$1, cmtTbl);
                                    var braces$3 = Res_parens.unaryExprOperand(parentExpr$1);
                                    var parentDoc$1 = typeof braces$3 === "number" ? (
                                        braces$3 !== 0 ? doc$4 : addParens(doc$4)
                                      ) : printBraces(doc$4, parentExpr$1, braces$3._0);
                                    return Res_doc.group(Res_doc.concat({
                                                    hd: printAttributes(undefined, undefined, expr.pexp_attributes, cmtTbl),
                                                    tl: {
                                                      hd: parentDoc$1,
                                                      tl: {
                                                        hd: Res_doc.lbracket,
                                                        tl: {
                                                          hd: member$1,
                                                          tl: {
                                                            hd: Res_doc.rbracket,
                                                            tl: /* [] */0
                                                          }
                                                        }
                                                      }
                                                    }
                                                  }));
                                  }
                                } else {
                                  exit = 2;
                                }
                              } else {
                                exit = 2;
                              }
                            } else {
                              exit = 2;
                            }
                          } else {
                            exit = 2;
                          }
                          break;
                      case "set" :
                          var match$16 = match._1;
                          if (match$16) {
                            var match$17 = match$16.hd;
                            if (typeof match$17[0] === "number") {
                              var match$18 = match$16.tl;
                              if (match$18) {
                                var match$19 = match$18.hd;
                                if (typeof match$19[0] === "number") {
                                  var match$20 = match$18.tl;
                                  if (match$20) {
                                    var match$21 = match$20.hd;
                                    if (typeof match$21[0] === "number" && !match$20.tl) {
                                      var targetExpr = match$21[1];
                                      var memberExpr$2 = match$19[1];
                                      var parentExpr$2 = match$17[1];
                                      var doc$5 = printExpressionWithComments(memberExpr$2, cmtTbl);
                                      var braces$4 = Res_parens.expr(memberExpr$2);
                                      var memberDoc$2 = typeof braces$4 === "number" ? (
                                          braces$4 !== 0 ? doc$5 : addParens(doc$5)
                                        ) : printBraces(doc$5, memberExpr$2, braces$4._0);
                                      var match$22 = memberExpr$2.pexp_desc;
                                      var shouldInline$1;
                                      if (typeof match$22 === "number") {
                                        shouldInline$1 = false;
                                      } else {
                                        switch (match$22.TAG | 0) {
                                          case /* Pexp_ident */0 :
                                          case /* Pexp_constant */1 :
                                              shouldInline$1 = true;
                                              break;
                                          default:
                                            shouldInline$1 = false;
                                        }
                                      }
                                      var member$2 = shouldInline$1 ? memberDoc$2 : Res_doc.concat({
                                              hd: Res_doc.indent(Res_doc.concat({
                                                        hd: Res_doc.softLine,
                                                        tl: {
                                                          hd: memberDoc$2,
                                                          tl: /* [] */0
                                                        }
                                                      })),
                                              tl: {
                                                hd: Res_doc.softLine,
                                                tl: /* [] */0
                                              }
                                            });
                                      var shouldIndentTargetExpr;
                                      if (Res_parsetree_viewer.isBracedExpr(targetExpr)) {
                                        shouldIndentTargetExpr = false;
                                      } else if (Res_parsetree_viewer.isBinaryExpression(targetExpr)) {
                                        shouldIndentTargetExpr = true;
                                      } else {
                                        var match$23 = targetExpr.pexp_desc;
                                        var tmp;
                                        var exit$1 = 0;
                                        if (typeof match$23 === "number") {
                                          exit$1 = 3;
                                        } else {
                                          switch (match$23.TAG | 0) {
                                            case /* Pexp_ifthenelse */15 :
                                                var match$24 = targetExpr.pexp_attributes;
                                                if (match$24) {
                                                  var ifExpr = match$23._0;
                                                  if (match$24.hd[0].txt === "ns.ternary" && !match$24.tl) {
                                                    tmp = Res_parsetree_viewer.isBinaryExpression(ifExpr) || Res_parsetree_viewer.hasAttributes(ifExpr.pexp_attributes);
                                                  } else {
                                                    exit$1 = 3;
                                                  }
                                                } else {
                                                  exit$1 = 3;
                                                }
                                                break;
                                            case /* Pexp_newtype */31 :
                                                tmp = false;
                                                break;
                                            default:
                                              exit$1 = 3;
                                          }
                                        }
                                        if (exit$1 === 3) {
                                          tmp = Res_parsetree_viewer.hasAttributes(targetExpr.pexp_attributes) || Res_parsetree_viewer.isArrayAccess(targetExpr);
                                        }
                                        shouldIndentTargetExpr = tmp;
                                      }
                                      var doc$6 = printExpressionWithComments(targetExpr, cmtTbl);
                                      var braces$5 = Res_parens.expr(targetExpr);
                                      var targetExpr$1 = typeof braces$5 === "number" ? (
                                          braces$5 !== 0 ? doc$6 : addParens(doc$6)
                                        ) : printBraces(doc$6, targetExpr, braces$5._0);
                                      var doc$7 = printExpressionWithComments(parentExpr$2, cmtTbl);
                                      var braces$6 = Res_parens.unaryExprOperand(parentExpr$2);
                                      var parentDoc$2 = typeof braces$6 === "number" ? (
                                          braces$6 !== 0 ? doc$7 : addParens(doc$7)
                                        ) : printBraces(doc$7, parentExpr$2, braces$6._0);
                                      return Res_doc.group(Res_doc.concat({
                                                      hd: printAttributes(undefined, undefined, expr.pexp_attributes, cmtTbl),
                                                      tl: {
                                                        hd: parentDoc$2,
                                                        tl: {
                                                          hd: Res_doc.lbracket,
                                                          tl: {
                                                            hd: member$2,
                                                            tl: {
                                                              hd: Res_doc.rbracket,
                                                              tl: {
                                                                hd: Res_doc.text(" ="),
                                                                tl: {
                                                                  hd: shouldIndentTargetExpr ? Res_doc.indent(Res_doc.concat({
                                                                              hd: Res_doc.line,
                                                                              tl: {
                                                                                hd: targetExpr$1,
                                                                                tl: /* [] */0
                                                                              }
                                                                            })) : Res_doc.concat({
                                                                          hd: Res_doc.space,
                                                                          tl: {
                                                                            hd: targetExpr$1,
                                                                            tl: /* [] */0
                                                                          }
                                                                        }),
                                                                  tl: /* [] */0
                                                                }
                                                              }
                                                            }
                                                          }
                                                        }
                                                      }
                                                    }));
                                    }
                                    exit = 2;
                                  } else {
                                    exit = 2;
                                  }
                                } else {
                                  exit = 2;
                                }
                              } else {
                                exit = 2;
                              }
                            } else {
                              exit = 2;
                            }
                          } else {
                            exit = 2;
                          }
                          break;
                      default:
                        exit = 2;
                    }
                  } else {
                    exit = 2;
                  }
                  break;
              case /* Ldot */1 :
              case /* Lapply */2 :
                  exit = 2;
                  break;
              
            }
            break;
        case /* Lapply */2 :
            exit = 2;
            break;
        
      }
      if (exit === 2 && Res_parsetree_viewer.isJsxExpression(expr)) {
        return printJsxExpression(lident$1, match._1, cmtTbl);
      }
      
    }
    var args = List.map((function (param) {
            return [
                    param[0],
                    Res_parsetree_viewer.rewriteUnderscoreApply(param[1])
                  ];
          }), match._1);
    var match$25 = Res_parsetree_viewer.processUncurriedAttribute(expr.pexp_attributes);
    var attrs$1 = match$25[1];
    var uncurried = match$25[0];
    var doc$8 = printExpressionWithComments(callExpr, cmtTbl);
    var braces$7 = Res_parens.callExpr(callExpr);
    var callExprDoc = typeof braces$7 === "number" ? (
        braces$7 !== 0 ? doc$8 : addParens(doc$8)
      ) : printBraces(doc$8, callExpr, braces$7._0);
    if (Res_parsetree_viewer.requiresSpecialCallbackPrintingFirstArg(args)) {
      var argsDoc = printArgumentsWithCallbackInFirstPosition(uncurried, args, cmtTbl);
      return Res_doc.concat({
                  hd: printAttributes(undefined, undefined, attrs$1, cmtTbl),
                  tl: {
                    hd: callExprDoc,
                    tl: {
                      hd: argsDoc,
                      tl: /* [] */0
                    }
                  }
                });
    }
    if (Res_parsetree_viewer.requiresSpecialCallbackPrintingLastArg(args)) {
      var argsDoc$1 = printArgumentsWithCallbackInLastPosition(uncurried, args, cmtTbl);
      var maybeBreakParent = Res_doc.willBreak(argsDoc$1) ? Res_doc.breakParent : Res_doc.nil;
      return Res_doc.concat({
                  hd: maybeBreakParent,
                  tl: {
                    hd: printAttributes(undefined, undefined, attrs$1, cmtTbl),
                    tl: {
                      hd: callExprDoc,
                      tl: {
                        hd: argsDoc$1,
                        tl: /* [] */0
                      }
                    }
                  }
                });
    }
    var argsDoc$2 = printArguments(uncurried, args, cmtTbl);
    return Res_doc.concat({
                hd: printAttributes(undefined, undefined, attrs$1, cmtTbl),
                tl: {
                  hd: callExprDoc,
                  tl: {
                    hd: argsDoc$2,
                    tl: /* [] */0
                  }
                }
              });
  }
  throw {
        RE_EXN_ID: "Assert_failure",
        _1: [
          "res_printer.res",
          3945,
          9
        ],
        Error: new Error()
      };
}

function printJsxExpression(lident, args, cmtTbl) {
  var name = printJsxName(lident);
  var match = printJsxProps(args, cmtTbl);
  var children = match[1];
  var isSelfClosing;
  if (children !== undefined) {
    var match$1 = children.pexp_desc;
    if (typeof match$1 === "number" || match$1.TAG !== /* Pexp_construct */9) {
      isSelfClosing = false;
    } else {
      var match$2 = match$1._0.txt;
      switch (match$2.TAG | 0) {
        case /* Lident */0 :
            isSelfClosing = match$2._0 === "[]" ? match$1._1 === undefined : false;
            break;
        case /* Ldot */1 :
        case /* Lapply */2 :
            isSelfClosing = false;
            break;
        
      }
    }
  } else {
    isSelfClosing = false;
  }
  return Res_doc.group(Res_doc.concat({
                  hd: Res_doc.group(Res_doc.concat({
                            hd: printComments(Res_doc.concat({
                                      hd: Res_doc.lessThan,
                                      tl: {
                                        hd: name,
                                        tl: /* [] */0
                                      }
                                    }), cmtTbl, lident.loc),
                            tl: {
                              hd: match[0],
                              tl: {
                                hd: isSelfClosing ? Res_doc.concat({
                                        hd: Res_doc.line,
                                        tl: {
                                          hd: Res_doc.text("/>"),
                                          tl: /* [] */0
                                        }
                                      }) : Res_doc.nil,
                                tl: /* [] */0
                              }
                            }
                          })),
                  tl: {
                    hd: isSelfClosing ? Res_doc.nil : Res_doc.concat({
                            hd: Res_doc.greaterThan,
                            tl: {
                              hd: Res_doc.indent(Res_doc.concat({
                                        hd: Res_doc.line,
                                        tl: {
                                          hd: children !== undefined ? printJsxChildren(children, cmtTbl) : Res_doc.nil,
                                          tl: /* [] */0
                                        }
                                      })),
                              tl: {
                                hd: Res_doc.line,
                                tl: {
                                  hd: Res_doc.text("</"),
                                  tl: {
                                    hd: name,
                                    tl: {
                                      hd: Res_doc.greaterThan,
                                      tl: /* [] */0
                                    }
                                  }
                                }
                              }
                            }
                          }),
                    tl: /* [] */0
                  }
                }));
}

function printJsxFragment(expr, cmtTbl) {
  var opening = Res_doc.text("<>");
  var closing = Res_doc.text("</>");
  var match = expr.pexp_desc;
  var tmp;
  var exit = 0;
  if (typeof match === "number" || match.TAG !== /* Pexp_construct */9) {
    exit = 1;
  } else {
    var match$1 = match._0.txt;
    switch (match$1.TAG | 0) {
      case /* Lident */0 :
          if (match$1._0 === "[]" && match._1 === undefined) {
            tmp = Res_doc.nil;
          } else {
            exit = 1;
          }
          break;
      case /* Ldot */1 :
      case /* Lapply */2 :
          exit = 1;
          break;
      
    }
  }
  if (exit === 1) {
    tmp = Res_doc.indent(Res_doc.concat({
              hd: Res_doc.line,
              tl: {
                hd: printJsxChildren(expr, cmtTbl),
                tl: /* [] */0
              }
            }));
  }
  return Res_doc.group(Res_doc.concat({
                  hd: opening,
                  tl: {
                    hd: tmp,
                    tl: {
                      hd: Res_doc.line,
                      tl: {
                        hd: closing,
                        tl: /* [] */0
                      }
                    }
                  }
                }));
}

function printJsxChildren(childrenExpr, cmtTbl) {
  var match = childrenExpr.pexp_desc;
  var exit = 0;
  if (typeof match === "number" || match.TAG !== /* Pexp_construct */9) {
    exit = 1;
  } else {
    var match$1 = match._0.txt;
    switch (match$1.TAG | 0) {
      case /* Lident */0 :
          if (match$1._0 === "::") {
            var match$2 = Res_parsetree_viewer.collectListExpressions(childrenExpr);
            return Res_doc.group(Res_doc.join(Res_doc.line, List.map((function (expr) {
                                  var leadingLineCommentPresent = hasLeadingLineComment(cmtTbl, expr.pexp_loc);
                                  var exprDoc = printExpressionWithComments(expr, cmtTbl);
                                  var match = Res_parens.jsxChildExpr(expr);
                                  if (typeof match === "number" && match !== 0) {
                                    return exprDoc;
                                  }
                                  var innerDoc = Res_parens.bracedExpr(expr) ? addParens(exprDoc) : exprDoc;
                                  if (leadingLineCommentPresent) {
                                    return addBraces(innerDoc);
                                  } else {
                                    return Res_doc.concat({
                                                hd: Res_doc.lbrace,
                                                tl: {
                                                  hd: innerDoc,
                                                  tl: {
                                                    hd: Res_doc.rbrace,
                                                    tl: /* [] */0
                                                  }
                                                }
                                              });
                                  }
                                }), match$2[0])));
          }
          exit = 1;
          break;
      case /* Ldot */1 :
      case /* Lapply */2 :
          exit = 1;
          break;
      
    }
  }
  if (exit === 1) {
    var leadingLineCommentPresent = hasLeadingLineComment(cmtTbl, childrenExpr.pexp_loc);
    var exprDoc = printExpressionWithComments(childrenExpr, cmtTbl);
    var match$3 = Res_parens.jsxChildExpr(childrenExpr);
    var tmp;
    var exit$1 = 0;
    if (typeof match$3 === "number" && match$3 !== 0) {
      tmp = exprDoc;
    } else {
      exit$1 = 2;
    }
    if (exit$1 === 2) {
      var innerDoc = Res_parens.bracedExpr(childrenExpr) ? addParens(exprDoc) : exprDoc;
      tmp = leadingLineCommentPresent ? addBraces(innerDoc) : Res_doc.concat({
              hd: Res_doc.lbrace,
              tl: {
                hd: innerDoc,
                tl: {
                  hd: Res_doc.rbrace,
                  tl: /* [] */0
                }
              }
            });
    }
    return Res_doc.concat({
                hd: Res_doc.dotdotdot,
                tl: {
                  hd: tmp,
                  tl: /* [] */0
                }
              });
  }
  
}

function printJsxProps(args, cmtTbl) {
  var _props = /* [] */0;
  var _args = args;
  while(true) {
    var args$1 = _args;
    var props = _props;
    if (!args$1) {
      return [
              Res_doc.nil,
              undefined
            ];
    }
    var arg = args$1.hd;
    var match = arg[0];
    if (typeof match !== "number" && match.TAG === /* Labelled */0 && match._0 === "children") {
      var match$1 = args$1.tl;
      if (match$1) {
        var match$2 = match$1.hd;
        if (typeof match$2[0] === "number") {
          var match$3 = match$2[1].pexp_desc;
          if (typeof match$3 !== "number" && match$3.TAG === /* Pexp_construct */9) {
            var match$4 = match$3._0.txt;
            switch (match$4.TAG | 0) {
              case /* Lident */0 :
                  if (match$4._0 === "()" && match$3._1 === undefined && !match$1.tl) {
                    var formattedProps = Res_doc.indent(props ? Res_doc.concat({
                                hd: Res_doc.line,
                                tl: {
                                  hd: Res_doc.group(Res_doc.join(Res_doc.line, List.rev(props))),
                                  tl: /* [] */0
                                }
                              }) : Res_doc.nil);
                    return [
                            formattedProps,
                            arg[1]
                          ];
                  }
                  break;
              case /* Ldot */1 :
              case /* Lapply */2 :
                  break;
              
            }
          }
          
        }
        
      }
      
    }
    var propDoc = printJsxProp(arg, cmtTbl);
    _args = args$1.tl;
    _props = {
      hd: propDoc,
      tl: props
    };
    continue ;
  };
}

function printJsxProp(arg, cmtTbl) {
  var lbl = arg[0];
  var exit = 0;
  var exit$1 = 0;
  if (typeof lbl === "number") {
    exit = 1;
  } else {
    var match = arg[1];
    var match$1 = match.pexp_desc;
    if (typeof match$1 === "number" || match$1.TAG !== /* Pexp_ident */0) {
      exit$1 = 2;
    } else {
      var ident = match$1._0.txt;
      switch (ident.TAG | 0) {
        case /* Lident */0 :
            var match$2 = match.pexp_attributes;
            if (match$2) {
              var match$3 = match$2.hd[0];
              var ident$1 = ident._0;
              if (match$3.txt === "ns.namedArgLoc" && !(match$2.tl || lbl._0 !== ident$1)) {
                var argLoc = match$3.loc;
                if (typeof lbl === "number") {
                  return Res_doc.nil;
                }
                if (lbl.TAG === /* Labelled */0) {
                  return printComments(printIdentLike(undefined, ident$1), cmtTbl, argLoc);
                }
                var doc = Res_doc.concat({
                      hd: Res_doc.question,
                      tl: {
                        hd: printIdentLike(undefined, ident$1),
                        tl: /* [] */0
                      }
                    });
                return printComments(doc, cmtTbl, argLoc);
              } else {
                exit = 1;
              }
            } else {
              exit$1 = 2;
            }
            break;
        case /* Ldot */1 :
        case /* Lapply */2 :
            exit = 1;
            break;
        
      }
    }
  }
  if (exit$1 === 2) {
    var match$4 = arg[1];
    var match$5 = match$4.pexp_desc;
    if (typeof match$5 === "number" || match$5.TAG !== /* Pexp_ident */0) {
      exit = 1;
    } else {
      var ident$2 = match$5._0.txt;
      switch (ident$2.TAG | 0) {
        case /* Lident */0 :
            if (match$4.pexp_attributes) {
              exit = 1;
            } else {
              var ident$3 = ident$2._0;
              if (lbl._0 === ident$3) {
                if (typeof lbl === "number") {
                  return Res_doc.nil;
                } else if (lbl.TAG === /* Labelled */0) {
                  return printIdentLike(undefined, ident$3);
                } else {
                  return Res_doc.concat({
                              hd: Res_doc.question,
                              tl: {
                                hd: printIdentLike(undefined, ident$3),
                                tl: /* [] */0
                              }
                            });
                }
              }
              exit = 1;
            }
            break;
        case /* Ldot */1 :
        case /* Lapply */2 :
            exit = 1;
            break;
        
      }
    }
  }
  if (exit === 1) {
    var expr = arg[1];
    var match$6 = expr.pexp_attributes;
    var match$7;
    if (match$6) {
      var match$8 = match$6.hd[0];
      match$7 = match$8.txt === "ns.namedArgLoc" ? [
          match$8.loc,
          {
            pexp_desc: expr.pexp_desc,
            pexp_loc: expr.pexp_loc,
            pexp_attributes: match$6.tl
          }
        ] : [
          $$Location.none,
          expr
        ];
    } else {
      match$7 = [
        $$Location.none,
        expr
      ];
    }
    var expr$1 = match$7[1];
    var argLoc$1 = match$7[0];
    var lblDoc;
    if (typeof lbl === "number") {
      lblDoc = Res_doc.nil;
    } else if (lbl.TAG === /* Labelled */0) {
      var lbl$1 = printComments(printIdentLike(undefined, lbl._0), cmtTbl, argLoc$1);
      lblDoc = Res_doc.concat({
            hd: lbl$1,
            tl: {
              hd: Res_doc.equal,
              tl: /* [] */0
            }
          });
    } else {
      var lbl$2 = printComments(printIdentLike(undefined, lbl._0), cmtTbl, argLoc$1);
      lblDoc = Res_doc.concat({
            hd: lbl$2,
            tl: {
              hd: Res_doc.equal,
              tl: {
                hd: Res_doc.question,
                tl: /* [] */0
              }
            }
          });
    }
    var leadingLineCommentPresent = hasLeadingLineComment(cmtTbl, expr$1.pexp_loc);
    var doc$1 = printExpressionWithComments(expr$1, cmtTbl);
    var match$9 = Res_parens.jsxPropExpr(expr$1);
    var exprDoc;
    var exit$2 = 0;
    if (typeof match$9 === "number" && match$9 !== 0) {
      exprDoc = doc$1;
    } else {
      exit$2 = 2;
    }
    if (exit$2 === 2) {
      var innerDoc = Res_parens.bracedExpr(expr$1) ? addParens(doc$1) : doc$1;
      exprDoc = leadingLineCommentPresent ? addBraces(innerDoc) : Res_doc.concat({
              hd: Res_doc.lbrace,
              tl: {
                hd: innerDoc,
                tl: {
                  hd: Res_doc.rbrace,
                  tl: /* [] */0
                }
              }
            });
    }
    var fullLoc_loc_start = argLoc$1.loc_start;
    var fullLoc_loc_end = expr$1.pexp_loc.loc_end;
    var fullLoc_loc_ghost = argLoc$1.loc_ghost;
    var fullLoc = {
      loc_start: fullLoc_loc_start,
      loc_end: fullLoc_loc_end,
      loc_ghost: fullLoc_loc_ghost
    };
    return printComments(Res_doc.concat({
                    hd: lblDoc,
                    tl: {
                      hd: exprDoc,
                      tl: /* [] */0
                    }
                  }), cmtTbl, fullLoc);
  }
  
}

function printJsxName(param) {
  var lident = param.txt;
  var flatten = function (_acc, _lident) {
    while(true) {
      var lident = _lident;
      var acc = _acc;
      switch (lident.TAG | 0) {
        case /* Lident */0 :
            return {
                    hd: lident._0,
                    tl: acc
                  };
        case /* Ldot */1 :
            var txt = lident._1;
            var acc$1 = txt === "createElement" ? acc : ({
                  hd: txt,
                  tl: acc
                });
            _lident = lident._0;
            _acc = acc$1;
            continue ;
        case /* Lapply */2 :
            return acc;
        
      }
    };
  };
  switch (lident.TAG | 0) {
    case /* Lident */0 :
        return Res_doc.text(lident._0);
    case /* Ldot */1 :
    case /* Lapply */2 :
        break;
    
  }
  var segments = flatten(/* [] */0, lident);
  return Res_doc.join(Res_doc.dot, List.map(Res_doc.text, segments));
}

function printArgumentsWithCallbackInFirstPosition(uncurried, args, cmtTbl) {
  var cmtTblCopy = Res_comments_table.copy(cmtTbl);
  var match;
  if (args) {
    var match$1 = args.hd;
    var expr = match$1[1];
    var lbl = match$1[0];
    var lblDoc;
    lblDoc = typeof lbl === "number" ? Res_doc.nil : (
        lbl.TAG === /* Labelled */0 ? Res_doc.concat({
                hd: Res_doc.tilde,
                tl: {
                  hd: printIdentLike(undefined, lbl._0),
                  tl: {
                    hd: Res_doc.equal,
                    tl: /* [] */0
                  }
                }
              }) : Res_doc.concat({
                hd: Res_doc.tilde,
                tl: {
                  hd: printIdentLike(undefined, lbl._0),
                  tl: {
                    hd: Res_doc.equal,
                    tl: {
                      hd: Res_doc.question,
                      tl: /* [] */0
                    }
                  }
                }
              })
      );
    var callback = Res_doc.concat({
          hd: lblDoc,
          tl: {
            hd: printPexpFun(/* FitsOnOneLine */1, expr, cmtTbl),
            tl: /* [] */0
          }
        });
    var callback$1 = printComments(callback, cmtTbl, expr.pexp_loc);
    var printedArgs = Res_doc.join(Res_doc.concat({
              hd: Res_doc.comma,
              tl: {
                hd: Res_doc.line,
                tl: /* [] */0
              }
            }), List.map((function (arg) {
                return printArgument(arg, cmtTbl);
              }), args.tl));
    match = [
      callback$1,
      printedArgs
    ];
  } else {
    throw {
          RE_EXN_ID: "Assert_failure",
          _1: [
            "res_printer.res",
            4197,
            9
          ],
          Error: new Error()
        };
  }
  var printedArgs$1 = match[1];
  var fitsOnOneLine = Res_doc.concat({
        hd: uncurried ? Res_doc.text("(. ") : Res_doc.lparen,
        tl: {
          hd: match[0],
          tl: {
            hd: Res_doc.comma,
            tl: {
              hd: Res_doc.line,
              tl: {
                hd: printedArgs$1,
                tl: {
                  hd: Res_doc.rparen,
                  tl: /* [] */0
                }
              }
            }
          }
        }
      });
  var breakAllArgs = printArguments(uncurried, args, cmtTblCopy);
  if (Res_doc.willBreak(printedArgs$1)) {
    return breakAllArgs;
  } else {
    return Res_doc.customLayout({
                hd: fitsOnOneLine,
                tl: {
                  hd: breakAllArgs,
                  tl: /* [] */0
                }
              });
  }
}

function printArgumentsWithCallbackInLastPosition(uncurried, args, cmtTbl) {
  var cmtTblCopy = Res_comments_table.copy(cmtTbl);
  var cmtTblCopy2 = Res_comments_table.copy(cmtTbl);
  var loop = function (_acc, _args) {
    while(true) {
      var args = _args;
      var acc = _acc;
      if (!args) {
        return [
                Res_doc.nil,
                Res_doc.nil,
                Res_doc.nil
              ];
      }
      var args$1 = args.tl;
      var arg = args.hd;
      var expr = arg[1];
      var lbl = arg[0];
      if (args$1) {
        var argDoc = printArgument(arg, cmtTbl);
        _args = args$1;
        _acc = {
          hd: Res_doc.line,
          tl: {
            hd: Res_doc.comma,
            tl: {
              hd: argDoc,
              tl: acc
            }
          }
        };
        continue ;
      }
      var lblDoc;
      lblDoc = typeof lbl === "number" ? Res_doc.nil : (
          lbl.TAG === /* Labelled */0 ? Res_doc.concat({
                  hd: Res_doc.tilde,
                  tl: {
                    hd: printIdentLike(undefined, lbl._0),
                    tl: {
                      hd: Res_doc.equal,
                      tl: /* [] */0
                    }
                  }
                }) : Res_doc.concat({
                  hd: Res_doc.tilde,
                  tl: {
                    hd: printIdentLike(undefined, lbl._0),
                    tl: {
                      hd: Res_doc.equal,
                      tl: {
                        hd: Res_doc.question,
                        tl: /* [] */0
                      }
                    }
                  }
                })
        );
      var pexpFunDoc = printPexpFun(/* FitsOnOneLine */1, expr, cmtTbl);
      var doc = Res_doc.concat({
            hd: lblDoc,
            tl: {
              hd: pexpFunDoc,
              tl: /* [] */0
            }
          });
      var callbackFitsOnOneLine = printComments(doc, cmtTbl, expr.pexp_loc);
      var pexpFunDoc$1 = printPexpFun(/* ArgumentsFitOnOneLine */2, expr, cmtTblCopy);
      var doc$1 = Res_doc.concat({
            hd: lblDoc,
            tl: {
              hd: pexpFunDoc$1,
              tl: /* [] */0
            }
          });
      var callbackArgumentsFitsOnOneLine = printComments(doc$1, cmtTblCopy, expr.pexp_loc);
      return [
              Res_doc.concat(List.rev(acc)),
              callbackFitsOnOneLine,
              callbackArgumentsFitsOnOneLine
            ];
    };
  };
  var match = loop(/* [] */0, args);
  var printedArgs = match[0];
  var fitsOnOneLine = Res_doc.concat({
        hd: uncurried ? Res_doc.text("(.") : Res_doc.lparen,
        tl: {
          hd: printedArgs,
          tl: {
            hd: match[1],
            tl: {
              hd: Res_doc.rparen,
              tl: /* [] */0
            }
          }
        }
      });
  var arugmentsFitOnOneLine = Res_doc.concat({
        hd: uncurried ? Res_doc.text("(.") : Res_doc.lparen,
        tl: {
          hd: printedArgs,
          tl: {
            hd: Res_doc.breakableGroup(true, match[2]),
            tl: {
              hd: Res_doc.rparen,
              tl: /* [] */0
            }
          }
        }
      });
  var breakAllArgs = printArguments(uncurried, args, cmtTblCopy2);
  if (Res_doc.willBreak(printedArgs)) {
    return breakAllArgs;
  } else {
    return Res_doc.customLayout({
                hd: fitsOnOneLine,
                tl: {
                  hd: arugmentsFitOnOneLine,
                  tl: {
                    hd: breakAllArgs,
                    tl: /* [] */0
                  }
                }
              });
  }
}

function printArguments(uncurried, args, cmtTbl) {
  if (args) {
    var match = args.hd;
    if (typeof match[0] === "number") {
      var arg = match[1];
      var match$1 = arg.pexp_desc;
      var exit = 0;
      if (typeof match$1 === "number" || match$1.TAG !== /* Pexp_construct */9) {
        exit = 2;
      } else {
        var match$2 = match$1._0.txt;
        switch (match$2.TAG | 0) {
          case /* Lident */0 :
              if (match$2._0 === "()") {
                if (!args.tl) {
                  var match$3 = arg.pexp_loc.loc_ghost;
                  if (uncurried) {
                    if (match$3) {
                      return Res_doc.text("(.)");
                    } else {
                      return Res_doc.text("(. ())");
                    }
                  } else {
                    return Res_doc.text("()");
                  }
                }
                
              } else {
                exit = 2;
              }
              break;
          case /* Ldot */1 :
          case /* Lapply */2 :
              exit = 2;
              break;
          
        }
      }
      if (exit === 2 && !args.tl && Res_parsetree_viewer.isHuggableExpression(arg)) {
        var doc = printExpressionWithComments(arg, cmtTbl);
        var braces = Res_parens.expr(arg);
        var argDoc = typeof braces === "number" ? (
            braces !== 0 ? doc : addParens(doc)
          ) : printBraces(doc, arg, braces._0);
        return Res_doc.concat({
                    hd: uncurried ? Res_doc.text("(. ") : Res_doc.lparen,
                    tl: {
                      hd: argDoc,
                      tl: {
                        hd: Res_doc.rparen,
                        tl: /* [] */0
                      }
                    }
                  });
      }
      
    }
    
  }
  return Res_doc.group(Res_doc.concat({
                  hd: uncurried ? Res_doc.text("(.") : Res_doc.lparen,
                  tl: {
                    hd: Res_doc.indent(Res_doc.concat({
                              hd: uncurried ? Res_doc.line : Res_doc.softLine,
                              tl: {
                                hd: Res_doc.join(Res_doc.concat({
                                          hd: Res_doc.comma,
                                          tl: {
                                            hd: Res_doc.line,
                                            tl: /* [] */0
                                          }
                                        }), List.map((function (arg) {
                                            return printArgument(arg, cmtTbl);
                                          }), args)),
                                tl: /* [] */0
                              }
                            })),
                    tl: {
                      hd: Res_doc.trailingComma,
                      tl: {
                        hd: Res_doc.softLine,
                        tl: {
                          hd: Res_doc.rparen,
                          tl: /* [] */0
                        }
                      }
                    }
                  }
                }));
}

function printArgument(param, cmtTbl) {
  var arg = param[1];
  var argLbl = param[0];
  if (typeof argLbl !== "number") {
    if (argLbl.TAG === /* Labelled */0) {
      var match = arg.pexp_desc;
      var lbl = argLbl._0;
      if (typeof match !== "number") {
        switch (match.TAG | 0) {
          case /* Pexp_ident */0 :
              var name = match._0.txt;
              switch (name.TAG | 0) {
                case /* Lident */0 :
                    var match$1 = arg.pexp_attributes;
                    var exit = 0;
                    if (!(match$1 && !(match$1.hd[0].txt === "ns.namedArgLoc" && !match$1.tl))) {
                      exit = 2;
                    }
                    if (exit === 2 && lbl === name._0 && !Res_parsetree_viewer.isBracedExpr(arg)) {
                      var match$2 = arg.pexp_attributes;
                      var loc;
                      if (match$2) {
                        var match$3 = match$2.hd[0];
                        loc = match$3.txt === "ns.namedArgLoc" ? match$3.loc : arg.pexp_loc;
                      } else {
                        loc = arg.pexp_loc;
                      }
                      var doc = Res_doc.concat({
                            hd: Res_doc.tilde,
                            tl: {
                              hd: printIdentLike(undefined, lbl),
                              tl: /* [] */0
                            }
                          });
                      return printComments(doc, cmtTbl, loc);
                    }
                    break;
                case /* Ldot */1 :
                case /* Lapply */2 :
                    break;
                
              }
              break;
          case /* Pexp_constraint */19 :
              var argExpr = match._0;
              var match$4 = argExpr.pexp_desc;
              if (typeof match$4 !== "number" && match$4.TAG === /* Pexp_ident */0) {
                var name$1 = match$4._0.txt;
                switch (name$1.TAG | 0) {
                  case /* Lident */0 :
                      var attrs = arg.pexp_attributes;
                      var exit$1 = 0;
                      if (!(attrs && !(attrs.hd[0].txt === "ns.namedArgLoc" && !attrs.tl))) {
                        exit$1 = 2;
                      }
                      if (exit$1 === 2 && lbl === name$1._0 && !Res_parsetree_viewer.isBracedExpr(argExpr)) {
                        var loc$1;
                        if (attrs) {
                          var match$5 = attrs.hd[0];
                          if (match$5.txt === "ns.namedArgLoc") {
                            var loc$2 = match$5.loc;
                            loc$1 = {
                              loc_start: loc$2.loc_start,
                              loc_end: arg.pexp_loc.loc_end,
                              loc_ghost: loc$2.loc_ghost
                            };
                          } else {
                            loc$1 = arg.pexp_loc;
                          }
                        } else {
                          loc$1 = arg.pexp_loc;
                        }
                        var doc$1 = Res_doc.concat({
                              hd: Res_doc.tilde,
                              tl: {
                                hd: printIdentLike(undefined, lbl),
                                tl: {
                                  hd: Res_doc.text(": "),
                                  tl: {
                                    hd: printTypExpr(match._1, cmtTbl),
                                    tl: /* [] */0
                                  }
                                }
                              }
                            });
                        return printComments(doc$1, cmtTbl, loc$1);
                      }
                      break;
                  case /* Ldot */1 :
                  case /* Lapply */2 :
                      break;
                  
                }
              }
              break;
          default:
            
        }
      }
      
    } else {
      var match$6 = arg.pexp_desc;
      if (typeof match$6 !== "number" && match$6.TAG === /* Pexp_ident */0) {
        var name$2 = match$6._0.txt;
        var lbl$1 = argLbl._0;
        switch (name$2.TAG | 0) {
          case /* Lident */0 :
              var match$7 = arg.pexp_attributes;
              var exit$2 = 0;
              if (!(match$7 && !(match$7.hd[0].txt === "ns.namedArgLoc" && !match$7.tl))) {
                exit$2 = 2;
              }
              if (exit$2 === 2 && lbl$1 === name$2._0) {
                var match$8 = arg.pexp_attributes;
                var loc$3;
                if (match$8) {
                  var match$9 = match$8.hd[0];
                  loc$3 = match$9.txt === "ns.namedArgLoc" ? match$9.loc : arg.pexp_loc;
                } else {
                  loc$3 = arg.pexp_loc;
                }
                var doc$2 = Res_doc.concat({
                      hd: Res_doc.tilde,
                      tl: {
                        hd: printIdentLike(undefined, lbl$1),
                        tl: {
                          hd: Res_doc.question,
                          tl: /* [] */0
                        }
                      }
                    });
                return printComments(doc$2, cmtTbl, loc$3);
              }
              break;
          case /* Ldot */1 :
          case /* Lapply */2 :
              break;
          
        }
      }
      
    }
  }
  var match$10 = arg.pexp_attributes;
  var match$11;
  if (match$10) {
    var match$12 = match$10.hd[0];
    match$11 = match$12.txt === "ns.namedArgLoc" ? [
        match$12.loc,
        {
          pexp_desc: arg.pexp_desc,
          pexp_loc: arg.pexp_loc,
          pexp_attributes: match$10.tl
        }
      ] : [
        arg.pexp_loc,
        arg
      ];
  } else {
    match$11 = [
      arg.pexp_loc,
      arg
    ];
  }
  var expr = match$11[1];
  var argLoc = match$11[0];
  var printedLbl;
  if (typeof argLbl === "number") {
    printedLbl = Res_doc.nil;
  } else if (argLbl.TAG === /* Labelled */0) {
    var doc$3 = Res_doc.concat({
          hd: Res_doc.tilde,
          tl: {
            hd: printIdentLike(undefined, argLbl._0),
            tl: {
              hd: Res_doc.equal,
              tl: /* [] */0
            }
          }
        });
    printedLbl = printComments(doc$3, cmtTbl, argLoc);
  } else {
    var doc$4 = Res_doc.concat({
          hd: Res_doc.tilde,
          tl: {
            hd: printIdentLike(undefined, argLbl._0),
            tl: {
              hd: Res_doc.equal,
              tl: {
                hd: Res_doc.question,
                tl: /* [] */0
              }
            }
          }
        });
    printedLbl = printComments(doc$4, cmtTbl, argLoc);
  }
  var doc$5 = printExpressionWithComments(expr, cmtTbl);
  var braces = Res_parens.expr(expr);
  var printedExpr = typeof braces === "number" ? (
      braces !== 0 ? doc$5 : addParens(doc$5)
    ) : printBraces(doc$5, expr, braces._0);
  var loc_loc_start = argLoc.loc_start;
  var loc_loc_end = expr.pexp_loc.loc_end;
  var loc_loc_ghost = argLoc.loc_ghost;
  var loc$4 = {
    loc_start: loc_loc_start,
    loc_end: loc_loc_end,
    loc_ghost: loc_loc_ghost
  };
  var doc$6 = Res_doc.concat({
        hd: printedLbl,
        tl: {
          hd: printedExpr,
          tl: /* [] */0
        }
      });
  return printComments(doc$6, cmtTbl, loc$4);
}

function printCases(cases, cmtTbl) {
  return Res_doc.breakableGroup(true, Res_doc.concat({
                  hd: Res_doc.lbrace,
                  tl: {
                    hd: Res_doc.concat({
                          hd: Res_doc.line,
                          tl: {
                            hd: printList((function (n) {
                                    var init = n.pc_lhs.ppat_loc;
                                    return {
                                            loc_start: init.loc_start,
                                            loc_end: n.pc_rhs.pexp_loc.loc_end,
                                            loc_ghost: init.loc_ghost
                                          };
                                  }), cases, printCase, undefined, cmtTbl),
                            tl: /* [] */0
                          }
                        }),
                    tl: {
                      hd: Res_doc.line,
                      tl: {
                        hd: Res_doc.rbrace,
                        tl: /* [] */0
                      }
                    }
                  }
                }));
}

function printCase($$case, cmtTbl) {
  var match = $$case.pc_rhs.pexp_desc;
  var rhs;
  var exit = 0;
  if (typeof match === "number") {
    exit = 1;
  } else {
    switch (match.TAG | 0) {
      case /* Pexp_let */2 :
      case /* Pexp_sequence */16 :
      case /* Pexp_letmodule */25 :
      case /* Pexp_letexception */26 :
      case /* Pexp_open */33 :
          exit = 2;
          break;
      default:
        exit = 1;
    }
  }
  switch (exit) {
    case 1 :
        var doc = printExpressionWithComments($$case.pc_rhs, cmtTbl);
        var match$1 = Res_parens.expr($$case.pc_rhs);
        rhs = match$1 === 0 ? addParens(doc) : doc;
        break;
    case 2 :
        rhs = printExpressionBlock(Res_parsetree_viewer.isBracedExpr($$case.pc_rhs), $$case.pc_rhs, cmtTbl);
        break;
    
  }
  var expr = $$case.pc_guard;
  var guard = expr !== undefined ? Res_doc.group(Res_doc.concat({
              hd: Res_doc.line,
              tl: {
                hd: Res_doc.text("if "),
                tl: {
                  hd: printExpressionWithComments(expr, cmtTbl),
                  tl: /* [] */0
                }
              }
            })) : Res_doc.nil;
  var match$2 = $$case.pc_rhs.pexp_desc;
  var shouldInlineRhs;
  var exit$1 = 0;
  if (typeof match$2 === "number") {
    exit$1 = 1;
  } else {
    switch (match$2.TAG | 0) {
      case /* Pexp_ident */0 :
      case /* Pexp_constant */1 :
          shouldInlineRhs = true;
          break;
      case /* Pexp_construct */9 :
          var match$3 = match$2._0.txt;
          switch (match$3.TAG | 0) {
            case /* Lident */0 :
                switch (match$3._0) {
                  case "()" :
                  case "false" :
                  case "true" :
                      shouldInlineRhs = true;
                      break;
                  default:
                    exit$1 = 1;
                }
                break;
            case /* Ldot */1 :
            case /* Lapply */2 :
                exit$1 = 1;
                break;
            
          }
          break;
      default:
        exit$1 = 1;
    }
  }
  if (exit$1 === 1) {
    shouldInlineRhs = Res_parsetree_viewer.isHuggableRhs($$case.pc_rhs) ? true : false;
  }
  var match$4 = $$case.pc_lhs.ppat_desc;
  var shouldIndentPattern;
  shouldIndentPattern = typeof match$4 === "number" || match$4.TAG !== /* Ppat_or */9 ? true : false;
  var doc$1 = printPattern($$case.pc_lhs, cmtTbl);
  var match$5 = $$case.pc_lhs.ppat_desc;
  var patternDoc;
  patternDoc = typeof match$5 === "number" || match$5.TAG !== /* Ppat_constraint */10 ? doc$1 : addParens(doc$1);
  var content = Res_doc.concat({
        hd: shouldIndentPattern ? Res_doc.indent(patternDoc) : patternDoc,
        tl: {
          hd: Res_doc.indent(guard),
          tl: {
            hd: Res_doc.text(" =>"),
            tl: {
              hd: Res_doc.indent(Res_doc.concat({
                        hd: shouldInlineRhs ? Res_doc.space : Res_doc.line,
                        tl: {
                          hd: rhs,
                          tl: /* [] */0
                        }
                      })),
              tl: /* [] */0
            }
          }
        }
      });
  return Res_doc.group(Res_doc.concat({
                  hd: Res_doc.text("| "),
                  tl: {
                    hd: content,
                    tl: /* [] */0
                  }
                }));
}

function printExprFunParameters(inCallback, uncurried, hasConstraint, parameters, cmtTbl) {
  if (parameters) {
    var match = parameters.hd;
    if (match.TAG === /* Parameter */0 && !match.attrs && typeof match.lbl === "number" && match.defaultExpr === undefined) {
      var stringLoc = match.pat.ppat_desc;
      if (typeof stringLoc === "number") {
        if (!parameters.tl && !uncurried) {
          if (hasConstraint) {
            return Res_doc.text("(_)");
          } else {
            return Res_doc.text("_");
          }
        }
        
      } else {
        switch (stringLoc.TAG | 0) {
          case /* Ppat_var */0 :
              if (!parameters.tl && !uncurried) {
                var stringLoc$1 = stringLoc._0;
                var $$var = printIdentLike(undefined, stringLoc$1.txt);
                var txtDoc = hasConstraint ? addParens($$var) : $$var;
                return printComments(txtDoc, cmtTbl, stringLoc$1.loc);
              }
              break;
          case /* Ppat_construct */5 :
              var match$1 = stringLoc._0.txt;
              switch (match$1.TAG | 0) {
                case /* Lident */0 :
                    if (match$1._0 === "()" && stringLoc._1 === undefined && !parameters.tl && !uncurried) {
                      return Res_doc.text("()");
                    }
                    break;
                case /* Ldot */1 :
                case /* Lapply */2 :
                    break;
                
              }
              break;
          default:
            
        }
      }
    }
    
  }
  var inCallback$1 = inCallback === 1;
  var lparen = uncurried ? Res_doc.text("(. ") : Res_doc.lparen;
  var shouldHug = Res_parsetree_viewer.parametersShouldHug(parameters);
  var printedParamaters = Res_doc.concat({
        hd: shouldHug || inCallback$1 ? Res_doc.nil : Res_doc.softLine,
        tl: {
          hd: Res_doc.join(Res_doc.concat({
                    hd: Res_doc.comma,
                    tl: {
                      hd: Res_doc.line,
                      tl: /* [] */0
                    }
                  }), List.map((function (p) {
                      return printExpFunParameter(p, cmtTbl);
                    }), parameters)),
          tl: /* [] */0
        }
      });
  return Res_doc.group(Res_doc.concat({
                  hd: lparen,
                  tl: {
                    hd: shouldHug || inCallback$1 ? printedParamaters : Res_doc.concat({
                            hd: Res_doc.indent(printedParamaters),
                            tl: {
                              hd: Res_doc.trailingComma,
                              tl: {
                                hd: Res_doc.softLine,
                                tl: /* [] */0
                              }
                            }
                          }),
                    tl: {
                      hd: Res_doc.rparen,
                      tl: /* [] */0
                    }
                  }
                }));
}

function printExpFunParameter(parameter, cmtTbl) {
  if (parameter.TAG !== /* Parameter */0) {
    return Res_doc.group(Res_doc.concat({
                    hd: printAttributes(undefined, undefined, parameter.attrs, cmtTbl),
                    tl: {
                      hd: Res_doc.text("type "),
                      tl: {
                        hd: Res_doc.join(Res_doc.space, List.map((function (lbl) {
                                    return printComments(printIdentLike(undefined, lbl.txt), cmtTbl, lbl.loc);
                                  }), parameter.locs)),
                        tl: /* [] */0
                      }
                    }
                  }));
  }
  var pattern = parameter.pat;
  var defaultExpr = parameter.defaultExpr;
  var lbl = parameter.lbl;
  var match = Res_parsetree_viewer.processUncurriedAttribute(parameter.attrs);
  var uncurried = match[0] ? Res_doc.concat({
          hd: Res_doc.dot,
          tl: {
            hd: Res_doc.space,
            tl: /* [] */0
          }
        }) : Res_doc.nil;
  var attrs = printAttributes(undefined, undefined, match[1], cmtTbl);
  var defaultExprDoc = defaultExpr !== undefined ? Res_doc.concat({
          hd: Res_doc.text("="),
          tl: {
            hd: printExpressionWithComments(defaultExpr, cmtTbl),
            tl: /* [] */0
          }
        }) : Res_doc.nil;
  var labelWithPattern;
  var exit = 0;
  if (typeof lbl === "number") {
    labelWithPattern = printPattern(pattern, cmtTbl);
  } else {
    var lbl$1 = lbl._0;
    var stringLoc = pattern.ppat_desc;
    if (typeof stringLoc === "number") {
      exit = 1;
    } else {
      switch (stringLoc.TAG | 0) {
        case /* Ppat_var */0 :
            var match$1 = pattern.ppat_attributes;
            var exit$1 = 0;
            if (match$1 && !(match$1.hd[0].txt === "ns.namedArgLoc" && !match$1.tl)) {
              exit = 1;
            } else {
              exit$1 = 2;
            }
            if (exit$1 === 2) {
              if (lbl$1 === stringLoc._0.txt) {
                labelWithPattern = Res_doc.concat({
                      hd: Res_doc.text("~"),
                      tl: {
                        hd: printIdentLike(undefined, lbl$1),
                        tl: /* [] */0
                      }
                    });
              } else {
                exit = 1;
              }
            }
            break;
        case /* Ppat_constraint */10 :
            var lbl$2 = lbl._0;
            var match$2 = pattern.ppat_desc;
            var match$3 = match$2._0.ppat_desc;
            if (typeof match$3 === "number" || match$3.TAG !== /* Ppat_var */0) {
              exit = 1;
            } else {
              var match$4 = pattern.ppat_attributes;
              var exit$2 = 0;
              if (match$4 && !(match$4.hd[0].txt === "ns.namedArgLoc" && !match$4.tl)) {
                exit = 1;
              } else {
                exit$2 = 2;
              }
              if (exit$2 === 2) {
                if (lbl$2 === match$3._0.txt) {
                  labelWithPattern = Res_doc.concat({
                        hd: Res_doc.text("~"),
                        tl: {
                          hd: printIdentLike(undefined, lbl$2),
                          tl: {
                            hd: Res_doc.text(": "),
                            tl: {
                              hd: printTypExpr(match$2._1, cmtTbl),
                              tl: /* [] */0
                            }
                          }
                        }
                      });
                } else {
                  exit = 1;
                }
              }
              
            }
            break;
        default:
          exit = 1;
      }
    }
  }
  if (exit === 1) {
    labelWithPattern = Res_doc.concat({
          hd: Res_doc.text("~"),
          tl: {
            hd: printIdentLike(undefined, lbl._0),
            tl: {
              hd: Res_doc.text(" as "),
              tl: {
                hd: printPattern(pattern, cmtTbl),
                tl: /* [] */0
              }
            }
          }
        });
  }
  var optionalLabelSuffix;
  optionalLabelSuffix = typeof lbl === "number" || lbl.TAG === /* Labelled */0 || defaultExpr !== undefined ? Res_doc.nil : Res_doc.text("=?");
  var doc = Res_doc.group(Res_doc.concat({
            hd: uncurried,
            tl: {
              hd: attrs,
              tl: {
                hd: labelWithPattern,
                tl: {
                  hd: defaultExprDoc,
                  tl: {
                    hd: optionalLabelSuffix,
                    tl: /* [] */0
                  }
                }
              }
            }
          }));
  var cmtLoc;
  if (defaultExpr !== undefined) {
    var match$5 = pattern.ppat_attributes;
    var startPos;
    if (match$5) {
      var match$6 = match$5.hd[0];
      startPos = match$6.txt === "ns.namedArgLoc" ? match$6.loc.loc_start : pattern.ppat_loc.loc_start;
    } else {
      startPos = pattern.ppat_loc.loc_start;
    }
    var init = pattern.ppat_loc;
    cmtLoc = {
      loc_start: startPos,
      loc_end: defaultExpr.pexp_loc.loc_end,
      loc_ghost: init.loc_ghost
    };
  } else {
    var match$7 = pattern.ppat_attributes;
    if (match$7) {
      var match$8 = match$7.hd[0];
      if (match$8.txt === "ns.namedArgLoc") {
        var loc = match$8.loc;
        cmtLoc = {
          loc_start: loc.loc_start,
          loc_end: pattern.ppat_loc.loc_end,
          loc_ghost: loc.loc_ghost
        };
      } else {
        cmtLoc = pattern.ppat_loc;
      }
    } else {
      cmtLoc = pattern.ppat_loc;
    }
  }
  return printComments(doc, cmtTbl, cmtLoc);
}

function printExpressionBlock(braces, expr, cmtTbl) {
  var collectRows = function (_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_let */2 :
              var expr2 = match._2;
              var valueBindings = match._1;
              var match$1 = List.rev(valueBindings);
              var loc;
              if (valueBindings && match$1) {
                var init = valueBindings.hd.pvb_loc;
                loc = {
                  loc_start: init.loc_start,
                  loc_end: match$1.hd.pvb_loc.loc_end,
                  loc_ghost: init.loc_ghost
                };
              } else {
                loc = $$Location.none;
              }
              var comment = getFirstLeadingComment(cmtTbl, loc);
              var loc$1;
              if (comment !== undefined) {
                var cmtLoc = Res_comment.loc(comment);
                loc$1 = {
                  loc_start: cmtLoc.loc_start,
                  loc_end: loc.loc_end,
                  loc_ghost: cmtLoc.loc_ghost
                };
              } else {
                loc$1 = loc;
              }
              var recFlag = match._0 ? Res_doc.text("rec ") : Res_doc.nil;
              var letDoc = printValueBindings(recFlag, valueBindings, cmtTbl);
              var match$2 = expr2.pexp_desc;
              var exit = 0;
              if (typeof match$2 === "number" || match$2.TAG !== /* Pexp_construct */9) {
                exit = 2;
              } else {
                var match$3 = match$2._0.txt;
                switch (match$3.TAG | 0) {
                  case /* Lident */0 :
                      if (match$3._0 === "()") {
                        return List.rev({
                                    hd: [
                                      loc$1,
                                      letDoc
                                    ],
                                    tl: acc
                                  });
                      }
                      exit = 2;
                      break;
                  case /* Ldot */1 :
                  case /* Lapply */2 :
                      exit = 2;
                      break;
                  
                }
              }
              if (exit === 2) {
                _expr = expr2;
                _acc = {
                  hd: [
                    loc$1,
                    letDoc
                  ],
                  tl: acc
                };
                continue ;
              }
              break;
          case /* Pexp_sequence */16 :
              var expr1 = match._0;
              var doc = printExpression(expr1, cmtTbl);
              var braces = Res_parens.expr(expr1);
              var exprDoc = typeof braces === "number" ? (
                  braces !== 0 ? doc : addParens(doc)
                ) : printBraces(doc, expr1, braces._0);
              var loc$2 = expr1.pexp_loc;
              _expr = match._1;
              _acc = {
                hd: [
                  loc$2,
                  exprDoc
                ],
                tl: acc
              };
              continue ;
          case /* Pexp_letmodule */25 :
              var modExpr = match._1;
              var modName = match._0;
              var doc$1 = Res_doc.text(modName.txt);
              var name = printComments(doc$1, cmtTbl, modName.loc);
              var letModuleDoc = Res_doc.concat({
                    hd: Res_doc.text("module "),
                    tl: {
                      hd: name,
                      tl: {
                        hd: Res_doc.text(" = "),
                        tl: {
                          hd: printModExpr(modExpr, cmtTbl),
                          tl: /* [] */0
                        }
                      }
                    }
                  });
              var init$1 = expr.pexp_loc;
              var loc_loc_start = init$1.loc_start;
              var loc_loc_end = modExpr.pmod_loc.loc_end;
              var loc_loc_ghost = init$1.loc_ghost;
              var loc$3 = {
                loc_start: loc_loc_start,
                loc_end: loc_loc_end,
                loc_ghost: loc_loc_ghost
              };
              _expr = match._2;
              _acc = {
                hd: [
                  loc$3,
                  letModuleDoc
                ],
                tl: acc
              };
              continue ;
          case /* Pexp_letexception */26 :
              var extensionConstructor = match._0;
              var init$2 = expr.pexp_loc;
              var loc_loc_start$1 = init$2.loc_start;
              var loc_loc_end$1 = extensionConstructor.pext_loc.loc_end;
              var loc_loc_ghost$1 = init$2.loc_ghost;
              var loc$4 = {
                loc_start: loc_loc_start$1,
                loc_end: loc_loc_end$1,
                loc_ghost: loc_loc_ghost$1
              };
              var comment$1 = getFirstLeadingComment(cmtTbl, loc$4);
              var loc$5;
              if (comment$1 !== undefined) {
                var cmtLoc$1 = Res_comment.loc(comment$1);
                loc$5 = {
                  loc_start: cmtLoc$1.loc_start,
                  loc_end: loc_loc_end$1,
                  loc_ghost: cmtLoc$1.loc_ghost
                };
              } else {
                loc$5 = loc$4;
              }
              var letExceptionDoc = printExceptionDef(extensionConstructor, cmtTbl);
              _expr = match._1;
              _acc = {
                hd: [
                  loc$5,
                  letExceptionDoc
                ],
                tl: acc
              };
              continue ;
          case /* Pexp_open */33 :
              var longidentLoc = match._1;
              var openDoc = Res_doc.concat({
                    hd: Res_doc.text("open"),
                    tl: {
                      hd: printOverrideFlag(match._0),
                      tl: {
                        hd: Res_doc.space,
                        tl: {
                          hd: printLongidentLocation(longidentLoc, cmtTbl),
                          tl: /* [] */0
                        }
                      }
                    }
                  });
              var init$3 = expr.pexp_loc;
              var loc_loc_start$2 = init$3.loc_start;
              var loc_loc_end$2 = longidentLoc.loc.loc_end;
              var loc_loc_ghost$2 = init$3.loc_ghost;
              var loc$6 = {
                loc_start: loc_loc_start$2,
                loc_end: loc_loc_end$2,
                loc_ghost: loc_loc_ghost$2
              };
              _expr = match._2;
              _acc = {
                hd: [
                  loc$6,
                  openDoc
                ],
                tl: acc
              };
              continue ;
          default:
            
        }
      }
      var doc$2 = printExpression(expr, cmtTbl);
      var braces$1 = Res_parens.expr(expr);
      var exprDoc$1 = typeof braces$1 === "number" ? (
          braces$1 !== 0 ? doc$2 : addParens(doc$2)
        ) : printBraces(doc$2, expr, braces$1._0);
      return List.rev({
                  hd: [
                    expr.pexp_loc,
                    exprDoc$1
                  ],
                  tl: acc
                });
    };
  };
  var rows = collectRows(/* [] */0, expr);
  var block = printList((function (prim) {
          return prim[0];
        }), rows, (function (param, param$1) {
          return param[1];
        }), true, cmtTbl);
  return Res_doc.breakableGroup(true, braces ? Res_doc.concat({
                    hd: Res_doc.lbrace,
                    tl: {
                      hd: Res_doc.indent(Res_doc.concat({
                                hd: Res_doc.line,
                                tl: {
                                  hd: block,
                                  tl: /* [] */0
                                }
                              })),
                      tl: {
                        hd: Res_doc.line,
                        tl: {
                          hd: Res_doc.rbrace,
                          tl: /* [] */0
                        }
                      }
                    }
                  }) : block);
}

function printBraces(doc, expr, bracesLoc) {
  var overMultipleLines = bracesLoc.loc_end.pos_lnum > bracesLoc.loc_start.pos_lnum;
  var match = expr.pexp_desc;
  if (typeof match !== "number") {
    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 doc;
      default:
        
    }
  }
  return Res_doc.breakableGroup(overMultipleLines, Res_doc.concat({
                  hd: Res_doc.lbrace,
                  tl: {
                    hd: Res_doc.indent(Res_doc.concat({
                              hd: Res_doc.softLine,
                              tl: {
                                hd: Res_parens.bracedExpr(expr) ? addParens(doc) : doc,
                                tl: /* [] */0
                              }
                            })),
                    tl: {
                      hd: Res_doc.softLine,
                      tl: {
                        hd: Res_doc.rbrace,
                        tl: /* [] */0
                      }
                    }
                  }
                }));
}

function printOverrideFlag(overrideFlag) {
  if (overrideFlag) {
    return Res_doc.nil;
  } else {
    return Res_doc.text("!");
  }
}

function printDirectionFlag(flag) {
  if (flag) {
    return Res_doc.text(" downto ");
  } else {
    return Res_doc.text(" to ");
  }
}

function printRecordRow(param, cmtTbl, punningAllowed) {
  var expr = param[1];
  var lbl = param[0];
  var init = lbl.loc;
  var cmtLoc_loc_start = init.loc_start;
  var cmtLoc_loc_end = expr.pexp_loc.loc_end;
  var cmtLoc_loc_ghost = init.loc_ghost;
  var cmtLoc = {
    loc_start: cmtLoc_loc_start,
    loc_end: cmtLoc_loc_end,
    loc_ghost: cmtLoc_loc_ghost
  };
  var match = expr.pexp_desc;
  var tmp;
  var exit = 0;
  if (typeof match === "number" || match.TAG !== /* Pexp_ident */0) {
    exit = 1;
  } else {
    var match$1 = match._0;
    var key = match$1.txt;
    switch (key.TAG | 0) {
      case /* Lident */0 :
          if (punningAllowed && Longident.last(lbl.txt) === key._0 && lbl.loc.loc_start.pos_cnum === match$1.loc.loc_start.pos_cnum) {
            tmp = printLidentPath(lbl, cmtTbl);
          } else {
            exit = 1;
          }
          break;
      case /* Ldot */1 :
      case /* Lapply */2 :
          exit = 1;
          break;
      
    }
  }
  if (exit === 1) {
    var doc = printExpressionWithComments(expr, cmtTbl);
    var braces = Res_parens.expr(expr);
    tmp = Res_doc.concat({
          hd: printLidentPath(lbl, cmtTbl),
          tl: {
            hd: Res_doc.text(": "),
            tl: {
              hd: typeof braces === "number" ? (
                  braces !== 0 ? doc : addParens(doc)
                ) : printBraces(doc, expr, braces._0),
              tl: /* [] */0
            }
          }
        });
  }
  var doc$1 = Res_doc.group(tmp);
  return printComments(doc$1, cmtTbl, cmtLoc);
}

function printBsObjectRow(param, cmtTbl) {
  var expr = param[1];
  var lbl = param[0];
  var init = lbl.loc;
  var cmtLoc_loc_start = init.loc_start;
  var cmtLoc_loc_end = expr.pexp_loc.loc_end;
  var cmtLoc_loc_ghost = init.loc_ghost;
  var cmtLoc = {
    loc_start: cmtLoc_loc_start,
    loc_end: cmtLoc_loc_end,
    loc_ghost: cmtLoc_loc_ghost
  };
  var doc = Res_doc.concat({
        hd: Res_doc.text("\""),
        tl: {
          hd: printLongident(lbl.txt),
          tl: {
            hd: Res_doc.text("\""),
            tl: /* [] */0
          }
        }
      });
  var lblDoc = printComments(doc, cmtTbl, lbl.loc);
  var doc$1 = printExpressionWithComments(expr, cmtTbl);
  var braces = Res_parens.expr(expr);
  var doc$2 = Res_doc.concat({
        hd: lblDoc,
        tl: {
          hd: Res_doc.text(": "),
          tl: {
            hd: typeof braces === "number" ? (
                braces !== 0 ? doc$1 : addParens(doc$1)
              ) : printBraces(doc$1, expr, braces._0),
            tl: /* [] */0
          }
        }
      });
  return printComments(doc$2, cmtTbl, cmtLoc);
}

function printAttributes(loc, inlineOpt, attrs, cmtTbl) {
  var inline = inlineOpt !== undefined ? inlineOpt : false;
  var attrs$1 = Res_parsetree_viewer.filterParsingAttrs(attrs);
  if (!attrs$1) {
    return Res_doc.nil;
  }
  var lineBreak;
  if (loc !== undefined) {
    var match = List.rev(attrs$1);
    lineBreak = match && loc.loc_start.pos_lnum > match.hd[0].loc.loc_end.pos_lnum ? Res_doc.hardLine : Res_doc.line;
  } else {
    lineBreak = Res_doc.line;
  }
  return Res_doc.concat({
              hd: Res_doc.group(Res_doc.join(Res_doc.line, List.map((function (attr) {
                              return printAttribute(attr, cmtTbl);
                            }), attrs$1))),
              tl: {
                hd: inline ? Res_doc.space : lineBreak,
                tl: /* [] */0
              }
            });
}

function printPayload(payload, cmtTbl) {
  switch (payload.TAG | 0) {
    case /* PStr */0 :
        var structure = payload._0;
        if (!structure) {
          return Res_doc.nil;
        }
        var si = structure.hd;
        var match = si.pstr_desc;
        switch (match.TAG | 0) {
          case /* Pstr_eval */0 :
              if (structure.tl) {
                return addParens(printStructure(structure, cmtTbl));
              }
              var attrs = match._1;
              var expr = match._0;
              var exprDoc = printExpressionWithComments(expr, cmtTbl);
              var needsParens = attrs ? true : false;
              var shouldHug = Res_parsetree_viewer.isHuggableExpression(expr);
              if (shouldHug) {
                return Res_doc.concat({
                            hd: Res_doc.lparen,
                            tl: {
                              hd: printAttributes(undefined, undefined, attrs, cmtTbl),
                              tl: {
                                hd: needsParens ? addParens(exprDoc) : exprDoc,
                                tl: {
                                  hd: Res_doc.rparen,
                                  tl: /* [] */0
                                }
                              }
                            }
                          });
              } else {
                return Res_doc.concat({
                            hd: Res_doc.lparen,
                            tl: {
                              hd: Res_doc.indent(Res_doc.concat({
                                        hd: Res_doc.softLine,
                                        tl: {
                                          hd: printAttributes(undefined, undefined, attrs, cmtTbl),
                                          tl: {
                                            hd: needsParens ? addParens(exprDoc) : exprDoc,
                                            tl: /* [] */0
                                          }
                                        }
                                      })),
                              tl: {
                                hd: Res_doc.softLine,
                                tl: {
                                  hd: Res_doc.rparen,
                                  tl: /* [] */0
                                }
                              }
                            }
                          });
              }
          case /* Pstr_value */1 :
              if (structure.tl) {
                return addParens(printStructure(structure, cmtTbl));
              } else {
                return addParens(printStructureItem(si, cmtTbl));
              }
          default:
            return addParens(printStructure(structure, cmtTbl));
        }
    case /* PSig */1 :
        return Res_doc.concat({
                    hd: Res_doc.lparen,
                    tl: {
                      hd: Res_doc.text(":"),
                      tl: {
                        hd: Res_doc.indent(Res_doc.concat({
                                  hd: Res_doc.line,
                                  tl: {
                                    hd: printSignature(payload._0, cmtTbl),
                                    tl: /* [] */0
                                  }
                                })),
                        tl: {
                          hd: Res_doc.softLine,
                          tl: {
                            hd: Res_doc.rparen,
                            tl: /* [] */0
                          }
                        }
                      }
                    }
                  });
    case /* PTyp */2 :
        return Res_doc.concat({
                    hd: Res_doc.lparen,
                    tl: {
                      hd: Res_doc.text(":"),
                      tl: {
                        hd: Res_doc.indent(Res_doc.concat({
                                  hd: Res_doc.line,
                                  tl: {
                                    hd: printTypExpr(payload._0, cmtTbl),
                                    tl: /* [] */0
                                  }
                                })),
                        tl: {
                          hd: Res_doc.softLine,
                          tl: {
                            hd: Res_doc.rparen,
                            tl: /* [] */0
                          }
                        }
                      }
                    }
                  });
    case /* PPat */3 :
        var optExpr = payload._1;
        var whenDoc = optExpr !== undefined ? Res_doc.concat({
                hd: Res_doc.line,
                tl: {
                  hd: Res_doc.text("if "),
                  tl: {
                    hd: printExpressionWithComments(optExpr, cmtTbl),
                    tl: /* [] */0
                  }
                }
              }) : Res_doc.nil;
        return Res_doc.concat({
                    hd: Res_doc.lparen,
                    tl: {
                      hd: Res_doc.indent(Res_doc.concat({
                                hd: Res_doc.softLine,
                                tl: {
                                  hd: Res_doc.text("? "),
                                  tl: {
                                    hd: printPattern(payload._0, cmtTbl),
                                    tl: {
                                      hd: whenDoc,
                                      tl: /* [] */0
                                    }
                                  }
                                }
                              })),
                      tl: {
                        hd: Res_doc.softLine,
                        tl: {
                          hd: Res_doc.rparen,
                          tl: /* [] */0
                        }
                      }
                    }
                  });
    
  }
}

function printAttribute(param, cmtTbl) {
  return Res_doc.group(Res_doc.concat({
                  hd: Res_doc.text("@"),
                  tl: {
                    hd: Res_doc.text(convertBsExternalAttribute(param[0].txt)),
                    tl: {
                      hd: printPayload(param[1], cmtTbl),
                      tl: /* [] */0
                    }
                  }
                }));
}

function printModExpr(modExpr, cmtTbl) {
  var longidentLoc = modExpr.pmod_desc;
  var doc;
  switch (longidentLoc.TAG | 0) {
    case /* Pmod_ident */0 :
        doc = printLongidentLocation(longidentLoc._0, cmtTbl);
        break;
    case /* Pmod_structure */1 :
        var structure = longidentLoc._0;
        if (structure) {
          doc = Res_doc.breakableGroup(true, Res_doc.concat({
                    hd: Res_doc.lbrace,
                    tl: {
                      hd: Res_doc.indent(Res_doc.concat({
                                hd: Res_doc.softLine,
                                tl: {
                                  hd: printStructure(structure, cmtTbl),
                                  tl: /* [] */0
                                }
                              })),
                      tl: {
                        hd: Res_doc.softLine,
                        tl: {
                          hd: Res_doc.rbrace,
                          tl: /* [] */0
                        }
                      }
                    }
                  }));
        } else {
          var shouldBreak = modExpr.pmod_loc.loc_start.pos_lnum < modExpr.pmod_loc.loc_end.pos_lnum;
          doc = Res_doc.breakableGroup(shouldBreak, Res_doc.concat({
                    hd: Res_doc.lbrace,
                    tl: {
                      hd: Res_doc.indent(Res_doc.concat({
                                hd: Res_doc.softLine,
                                tl: {
                                  hd: printCommentsInside(cmtTbl, modExpr.pmod_loc),
                                  tl: /* [] */0
                                }
                              })),
                      tl: {
                        hd: Res_doc.softLine,
                        tl: {
                          hd: Res_doc.rbrace,
                          tl: /* [] */0
                        }
                      }
                    }
                  }));
        }
        break;
    case /* Pmod_functor */2 :
        doc = printModFunctor(modExpr, cmtTbl);
        break;
    case /* Pmod_apply */3 :
        var match = Res_parsetree_viewer.modExprApply(modExpr);
        var args = match[0];
        var isUnitSugar;
        if (args) {
          var match$1 = args.hd.pmod_desc;
          isUnitSugar = match$1.TAG === /* Pmod_structure */1 && !(match$1._0 || args.tl) ? true : false;
        } else {
          isUnitSugar = false;
        }
        var shouldHug = args && args.hd.pmod_desc.TAG === /* Pmod_structure */1 && !args.tl ? true : false;
        doc = Res_doc.group(Res_doc.concat({
                  hd: printModExpr(match[1], cmtTbl),
                  tl: {
                    hd: isUnitSugar ? printModApplyArg(List.hd(args), cmtTbl) : Res_doc.concat({
                            hd: Res_doc.lparen,
                            tl: {
                              hd: shouldHug ? printModApplyArg(List.hd(args), cmtTbl) : Res_doc.indent(Res_doc.concat({
                                          hd: Res_doc.softLine,
                                          tl: {
                                            hd: Res_doc.join(Res_doc.concat({
                                                      hd: Res_doc.comma,
                                                      tl: {
                                                        hd: Res_doc.line,
                                                        tl: /* [] */0
                                                      }
                                                    }), List.map((function (modArg) {
                                                        return printModApplyArg(modArg, cmtTbl);
                                                      }), args)),
                                            tl: /* [] */0
                                          }
                                        })),
                              tl: {
                                hd: shouldHug ? Res_doc.nil : Res_doc.concat({
                                        hd: Res_doc.trailingComma,
                                        tl: {
                                          hd: Res_doc.softLine,
                                          tl: /* [] */0
                                        }
                                      }),
                                tl: {
                                  hd: Res_doc.rparen,
                                  tl: /* [] */0
                                }
                              }
                            }
                          }),
                    tl: /* [] */0
                  }
                }));
        break;
    case /* Pmod_constraint */4 :
        doc = Res_doc.concat({
              hd: printModExpr(longidentLoc._0, cmtTbl),
              tl: {
                hd: Res_doc.text(": "),
                tl: {
                  hd: printModType(longidentLoc._1, cmtTbl),
                  tl: /* [] */0
                }
              }
            });
        break;
    case /* Pmod_unpack */5 :
        var expr = longidentLoc._0;
        var match$2 = expr.pexp_desc;
        var shouldHug$1;
        if (typeof match$2 === "number") {
          shouldHug$1 = false;
        } else {
          switch (match$2.TAG | 0) {
            case /* Pexp_let */2 :
                shouldHug$1 = true;
                break;
            case /* Pexp_constraint */19 :
                var tmp = match$2._0.pexp_desc;
                if (typeof tmp === "number" || tmp.TAG !== /* Pexp_let */2) {
                  shouldHug$1 = false;
                } else {
                  var tmp$1 = match$2._1.ptyp_desc;
                  shouldHug$1 = typeof tmp$1 === "number" || tmp$1.TAG !== /* Ptyp_package */9 ? false : true;
                }
                break;
            default:
              shouldHug$1 = false;
          }
        }
        var match$3 = expr.pexp_desc;
        var match$4;
        if (typeof match$3 === "number" || match$3.TAG !== /* Pexp_constraint */19) {
          match$4 = [
            expr,
            Res_doc.nil
          ];
        } else {
          var match$5 = match$3._1;
          var packageType = match$5.ptyp_desc;
          if (typeof packageType === "number" || packageType.TAG !== /* Ptyp_package */9) {
            match$4 = [
              expr,
              Res_doc.nil
            ];
          } else {
            var doc$1 = printPackageType(false, packageType._0, cmtTbl);
            var packageDoc = printComments(doc$1, cmtTbl, match$5.ptyp_loc);
            var typeDoc = Res_doc.group(Res_doc.concat({
                      hd: Res_doc.text(":"),
                      tl: {
                        hd: Res_doc.indent(Res_doc.concat({
                                  hd: Res_doc.line,
                                  tl: {
                                    hd: packageDoc,
                                    tl: /* [] */0
                                  }
                                })),
                        tl: /* [] */0
                      }
                    }));
            match$4 = [
              match$3._0,
              typeDoc
            ];
          }
        }
        var unpackDoc = Res_doc.group(Res_doc.concat({
                  hd: printExpressionWithComments(match$4[0], cmtTbl),
                  tl: {
                    hd: match$4[1],
                    tl: /* [] */0
                  }
                }));
        doc = Res_doc.group(Res_doc.concat({
                  hd: Res_doc.text("unpack("),
                  tl: {
                    hd: shouldHug$1 ? unpackDoc : Res_doc.concat({
                            hd: Res_doc.indent(Res_doc.concat({
                                      hd: Res_doc.softLine,
                                      tl: {
                                        hd: unpackDoc,
                                        tl: /* [] */0
                                      }
                                    })),
                            tl: {
                              hd: Res_doc.softLine,
                              tl: /* [] */0
                            }
                          }),
                    tl: {
                      hd: Res_doc.rparen,
                      tl: /* [] */0
                    }
                  }
                }));
        break;
    case /* Pmod_extension */6 :
        doc = printExtension(false, longidentLoc._0, cmtTbl);
        break;
    
  }
  return printComments(doc, cmtTbl, modExpr.pmod_loc);
}

function printModFunctor(modExpr, cmtTbl) {
  var match = Res_parsetree_viewer.modExprFunctor(modExpr);
  var returnModExpr = match[1];
  var parameters = match[0];
  var match$1 = returnModExpr.pmod_desc;
  var match$2;
  if (match$1.TAG === /* Pmod_constraint */4) {
    var modType = match$1._1;
    var doc = printModType(modType, cmtTbl);
    var constraintDoc = Res_parens.modExprFunctorConstraint(modType) ? addParens(doc) : doc;
    var modConstraint = Res_doc.concat({
          hd: Res_doc.text(": "),
          tl: {
            hd: constraintDoc,
            tl: /* [] */0
          }
        });
    match$2 = [
      modConstraint,
      printModExpr(match$1._0, cmtTbl)
    ];
  } else {
    match$2 = [
      Res_doc.nil,
      printModExpr(returnModExpr, cmtTbl)
    ];
  }
  var parametersDoc;
  var exit = 0;
  if (parameters) {
    var match$3 = parameters.hd;
    var attrs = match$3[0];
    if (match$3[1].txt === "*") {
      if (match$3[2] !== undefined || parameters.tl) {
        exit = 1;
      } else {
        parametersDoc = Res_doc.group(Res_doc.concat({
                  hd: printAttributes(undefined, undefined, attrs, cmtTbl),
                  tl: {
                    hd: Res_doc.text("()"),
                    tl: /* [] */0
                  }
                }));
      }
    } else if (attrs || match$3[2] !== undefined || parameters.tl) {
      exit = 1;
    } else {
      parametersDoc = Res_doc.text(match$3[1].txt);
    }
  } else {
    exit = 1;
  }
  if (exit === 1) {
    parametersDoc = Res_doc.group(Res_doc.concat({
              hd: Res_doc.lparen,
              tl: {
                hd: Res_doc.indent(Res_doc.concat({
                          hd: Res_doc.softLine,
                          tl: {
                            hd: Res_doc.join(Res_doc.concat({
                                      hd: Res_doc.comma,
                                      tl: {
                                        hd: Res_doc.line,
                                        tl: /* [] */0
                                      }
                                    }), List.map((function (param) {
                                        return printModFunctorParam(param, cmtTbl);
                                      }), parameters)),
                            tl: /* [] */0
                          }
                        })),
                tl: {
                  hd: Res_doc.trailingComma,
                  tl: {
                    hd: Res_doc.softLine,
                    tl: {
                      hd: Res_doc.rparen,
                      tl: /* [] */0
                    }
                  }
                }
              }
            }));
  }
  return Res_doc.group(Res_doc.concat({
                  hd: parametersDoc,
                  tl: {
                    hd: match$2[0],
                    tl: {
                      hd: Res_doc.text(" => "),
                      tl: {
                        hd: match$2[1],
                        tl: /* [] */0
                      }
                    }
                  }
                }));
}

function printModFunctorParam(param, cmtTbl) {
  var optModType = param[2];
  var lbl = param[1];
  var cmtLoc;
  if (optModType !== undefined) {
    var init = lbl.loc;
    cmtLoc = {
      loc_start: init.loc_start,
      loc_end: optModType.pmty_loc.loc_end,
      loc_ghost: init.loc_ghost
    };
  } else {
    cmtLoc = lbl.loc;
  }
  var attrs = printAttributes(undefined, undefined, param[0], cmtTbl);
  var doc = lbl.txt === "*" ? Res_doc.text("()") : Res_doc.text(lbl.txt);
  var lblDoc = printComments(doc, cmtTbl, lbl.loc);
  var doc$1 = Res_doc.group(Res_doc.concat({
            hd: attrs,
            tl: {
              hd: lblDoc,
              tl: {
                hd: optModType !== undefined ? Res_doc.concat({
                        hd: Res_doc.text(": "),
                        tl: {
                          hd: printModType(optModType, cmtTbl),
                          tl: /* [] */0
                        }
                      }) : Res_doc.nil,
                tl: /* [] */0
              }
            }
          }));
  return printComments(doc$1, cmtTbl, cmtLoc);
}

function printModApplyArg(modExpr, cmtTbl) {
  var match = modExpr.pmod_desc;
  if (match.TAG === /* Pmod_structure */1 && !match._0) {
    return Res_doc.text("()");
  } else {
    return printModExpr(modExpr, cmtTbl);
  }
}

function printExceptionDef(constr, cmtTbl) {
  var longident = constr.pext_kind;
  var kind;
  if (longident.TAG === /* Pext_decl */0) {
    var args = longident._0;
    var exit = 0;
    if (args.TAG === /* Pcstr_tuple */0 && !(args._0 || longident._1 !== undefined)) {
      kind = Res_doc.nil;
    } else {
      exit = 1;
    }
    if (exit === 1) {
      var gadt = longident._1;
      var gadtDoc = gadt !== undefined ? Res_doc.concat({
              hd: Res_doc.text(": "),
              tl: {
                hd: printTypExpr(gadt, cmtTbl),
                tl: /* [] */0
              }
            }) : Res_doc.nil;
      kind = Res_doc.concat({
            hd: printConstructorArguments(false, args, cmtTbl),
            tl: {
              hd: gadtDoc,
              tl: /* [] */0
            }
          });
    }
    
  } else {
    kind = Res_doc.indent(Res_doc.concat({
              hd: Res_doc.text(" ="),
              tl: {
                hd: Res_doc.line,
                tl: {
                  hd: printLongidentLocation(longident._0, cmtTbl),
                  tl: /* [] */0
                }
              }
            }));
  }
  var name = printComments(Res_doc.text(constr.pext_name.txt), cmtTbl, constr.pext_name.loc);
  var doc = Res_doc.group(Res_doc.concat({
            hd: printAttributes(undefined, undefined, constr.pext_attributes, cmtTbl),
            tl: {
              hd: Res_doc.text("exception "),
              tl: {
                hd: name,
                tl: {
                  hd: kind,
                  tl: /* [] */0
                }
              }
            }
          }));
  return printComments(doc, cmtTbl, constr.pext_loc);
}

function printExtensionConstructor(constr, cmtTbl, i) {
  var attrs = printAttributes(undefined, undefined, constr.pext_attributes, cmtTbl);
  var bar = i > 0 ? Res_doc.text("| ") : Res_doc.ifBreaks(Res_doc.text("| "), Res_doc.nil);
  var longident = constr.pext_kind;
  var kind;
  if (longident.TAG === /* Pext_decl */0) {
    var args = longident._0;
    var exit = 0;
    if (args.TAG === /* Pcstr_tuple */0 && !(args._0 || longident._1 !== undefined)) {
      kind = Res_doc.nil;
    } else {
      exit = 1;
    }
    if (exit === 1) {
      var gadt = longident._1;
      var gadtDoc = gadt !== undefined ? Res_doc.concat({
              hd: Res_doc.text(": "),
              tl: {
                hd: printTypExpr(gadt, cmtTbl),
                tl: /* [] */0
              }
            }) : Res_doc.nil;
      kind = Res_doc.concat({
            hd: printConstructorArguments(false, args, cmtTbl),
            tl: {
              hd: gadtDoc,
              tl: /* [] */0
            }
          });
    }
    
  } else {
    kind = Res_doc.indent(Res_doc.concat({
              hd: Res_doc.text(" ="),
              tl: {
                hd: Res_doc.line,
                tl: {
                  hd: printLongidentLocation(longident._0, cmtTbl),
                  tl: /* [] */0
                }
              }
            }));
  }
  var name = printComments(Res_doc.text(constr.pext_name.txt), cmtTbl, constr.pext_name.loc);
  return Res_doc.concat({
              hd: bar,
              tl: {
                hd: Res_doc.group(Res_doc.concat({
                          hd: attrs,
                          tl: {
                            hd: name,
                            tl: {
                              hd: kind,
                              tl: /* [] */0
                            }
                          }
                        })),
                tl: /* [] */0
              }
            });
}

function printImplementation(width, s, comments) {
  var cmtTbl = Res_comments_table.make(undefined);
  Res_comments_table.walkStructure(s, cmtTbl, comments);
  var doc = printStructure(s, cmtTbl);
  return Res_doc.toString(width, doc) + "\n";
}

function printInterface(width, s, comments) {
  var cmtTbl = Res_comments_table.make(undefined);
  Res_comments_table.walkSignature(s, cmtTbl, comments);
  return Res_doc.toString(width, printSignature(s, cmtTbl)) + "\n";
}

var Doc;

var CommentTable;

var $$Comment;

var Token;

var Parens;

var ParsetreeViewer;

export {
  Doc ,
  CommentTable ,
  $$Comment ,
  Token ,
  Parens ,
  ParsetreeViewer ,
  convertBsExternalAttribute ,
  convertBsExtension ,
  addParens ,
  addBraces ,
  getFirstLeadingComment ,
  hasLeadingLineComment ,
  hasCommentBelow ,
  printMultilineCommentContent ,
  printTrailingComment ,
  printLeadingComment ,
  printCommentsInside ,
  printLeadingComments ,
  printTrailingComments ,
  printComments ,
  printList ,
  printListi ,
  printLongidentAux ,
  printLongident ,
  classifyIdentContent ,
  printIdentLike ,
  unsafe_for_all_range ,
  for_all_from ,
  isValidNumericPolyvarNumber ,
  printPolyVarIdent ,
  printLident ,
  printLongidentLocation ,
  printLidentPath ,
  printIdentPath ,
  printStringLoc ,
  printStringContents ,
  printConstant ,
  printStructure ,
  printStructureItem ,
  printTypeExtension ,
  printModuleBinding ,
  printModuleTypeDeclaration ,
  printModType ,
  printWithConstraints ,
  printWithConstraint ,
  printSignature ,
  printSignatureItem ,
  printRecModuleDeclarations ,
  printRecModuleDeclaration ,
  printModuleDeclaration ,
  printOpenDescription ,
  printIncludeDescription ,
  printIncludeDeclaration ,
  printValueBindings ,
  printValueDescription ,
  printTypeDeclarations ,
  printTypeDeclaration ,
  printTypeDeclaration2 ,
  printTypeDefinitionConstraints ,
  printTypeDefinitionConstraint ,
  printPrivateFlag ,
  printTypeParams ,
  printTypeParam ,
  printRecordDeclaration ,
  printConstructorDeclarations ,
  printConstructorDeclaration2 ,
  printConstructorArguments ,
  printLabelDeclaration ,
  printTypExpr ,
  printObject ,
  printTupleType ,
  printObjectField ,
  printTypeParameter ,
  printValueBinding ,
  printPackageType ,
  printPackageConstraints ,
  printPackageConstraint ,
  printExtension ,
  printPattern ,
  printPatternRecordRow ,
  printExpressionWithComments ,
  printIfChain ,
  printExpression ,
  printPexpFun ,
  printTernaryOperand ,
  printSetFieldExpr ,
  printTemplateLiteral ,
  printUnaryExpression ,
  printBinaryExpression ,
  printPexpApply ,
  printJsxExpression ,
  printJsxFragment ,
  printJsxChildren ,
  printJsxProps ,
  printJsxProp ,
  printJsxName ,
  printArgumentsWithCallbackInFirstPosition ,
  printArgumentsWithCallbackInLastPosition ,
  printArguments ,
  printArgument ,
  printCases ,
  printCase ,
  printExprFunParameters ,
  printExpFunParameter ,
  printExpressionBlock ,
  printBraces ,
  printOverrideFlag ,
  printDirectionFlag ,
  printRecordRow ,
  printBsObjectRow ,
  printAttributes ,
  printPayload ,
  printAttribute ,
  printModExpr ,
  printModFunctor ,
  printModFunctorParam ,
  printModApplyArg ,
  printExceptionDef ,
  printExtensionConstructor ,
  printImplementation ,
  printInterface ,
  
}
/* Location Not a pure module */
