<commit_before>Ibis.Inferer = (function () {
  var Type = Ibis.Type;
  var Env = Ibis.Env;
  var IbisError = Ibis.IbisError;
  
  var exports = function () {
    return {
      infer: polyInfer
    };
  };
  
  function polyInfer(ctxt, env, variants, expr) {
    var freeVars = [];
    var inferredType = infer(ctxt, env, variants, expr);
    var unwrappedType = unwrapVar(inferredType, freeVars);
    return Type.createTypeSchema(freeVars, unwrappedType);
  }
  
  function infer(ctxt, env, variants, expr) {
    switch (expr.tag) {
    case "Const":
      switch (expr.value.tag) {
      case "Unit":
        return Type.Unit;
      case "Int":
        return Type.Int;
      case "True":
      case "False":
        return Type.Bool;
      }
    case "Var":
      var typeSchema = Env.find(ctxt, expr.varName);
      if (!typeSchema) {
        throw new IbisError("undefined variable: " + expr.varName);
      }
      return createAlphaEquivalent(typeSchema).bodyType;
    case "Abs":
      var paramType = Type.createVar(null);
      var newCtxt = Env.createLocal({}, ctxt);
      Env.add(newCtxt, expr.varName, Type.createTypeSchema([], paramType));
      var retType = infer(newCtxt, env, variants, expr.bodyExpr);
      return Type.createFun(paramType, retType);
    case "App":
      var funType = infer(ctxt, env, variants, expr.funExpr);
      var argType = infer(ctxt, env, variants, expr.argExpr);
      var retType = Type.createVar(null);
      unify(funType, Type.createFun(argType, retType));
      return retType;
    case "Let":
      var inferredType = infer(ctxt, env, variants, expr.valueExpr);
      var typeSchema = createPolyType(inferredType);
      Env.add(ctxt, expr.varName, typeSchema);
      return createAlphaEquivalent(typeSchema).bodyType;
    case "LetRec":
      var varType = Type.createVar(null);
      var newCtxt = Env.createLocal({}, ctxt);
      Env.add(newCtxt, expr.varName, Type.createTypeSchema([], varType));
      var inferredType = infer(newCtxt, env, variants, expr.valueExpr);
      var typeSchema = createPolyType(inferredType);
      Env.add(ctxt, expr.varName, typeSchema);
      return createAlphaEquivalent(typeSchema).bodyType;
    case "LetTuple":
      var inferredType = infer(ctxt, env, variants, expr.valueExpr);
      if (inferredType.tag != "Tuple") {
        throw new IbisError("tuple required, but got: " + inferredType);
      }
      var varNames = expr.varNames;
      var inferredTypeArray = inferredType.typeArray;
      if (inferredTypeArray.length != varNames.length) {
        throw new IbisError(varNames.length + "-tuple required, but got: " + inferredType);
      }
      var newTypeArray = [];
      for (var i in varNames) {
        var typeSchema = createPolyType(inferredTypeArray[i]);
        Env.add(ctxt, varNames[i], typeSchema);
        newTypeArray.push(createAlphaEquivalent(typeSchema).bodyType);
      }
      return Type.createTuple(newTypeArray);
    case "If":
      unify(infer(ctxt, env, variants, expr.condExpr), Type.Bool);<commit_msg>Bug fix: inferer.js: Add unification to let-rec<commit_after>Ibis.Inferer = (function () {
  var Type = Ibis.Type;
  var Env = Ibis.Env;
  var IbisError = Ibis.IbisError;
  
  var exports = function () {
    return {
      infer: polyInfer
    };
  };
  
  function polyInfer(ctxt, env, variants, expr) {
    var freeVars = [];
    var inferredType = infer(ctxt, env, variants, expr);
    var unwrappedType = unwrapVar(inferredType, freeVars);
    return Type.createTypeSchema(freeVars, unwrappedType);
  }
  
  function infer(ctxt, env, variants, expr) {
    switch (expr.tag) {
    case "Const":
      switch (expr.value.tag) {
      case "Unit":
        return Type.Unit;
      case "Int":
        return Type.Int;
      case "True":
      case "False":
        return Type.Bool;
      }
    case "Var":
      var typeSchema = Env.find(ctxt, expr.varName);
      if (!typeSchema) {
        throw new IbisError("undefined variable: " + expr.varName);
      }
      return createAlphaEquivalent(typeSchema).bodyType;
    case "Abs":
      var paramType = Type.createVar(null);
      var newCtxt = Env.createLocal({}, ctxt);
      Env.add(newCtxt, expr.varName, Type.createTypeSchema([], paramType));
      var retType = infer(newCtxt, env, variants, expr.bodyExpr);
      return Type.createFun(paramType, retType);
    case "App":
      var funType = infer(ctxt, env, variants, expr.funExpr);
      var argType = infer(ctxt, env, variants, expr.argExpr);
      var retType = Type.createVar(null);
      unify(funType, Type.createFun(argType, retType));
      return retType;
    case "Let":
      var inferredType = infer(ctxt, env, variants, expr.valueExpr);
      var typeSchema = createPolyType(inferredType);
      Env.add(ctxt, expr.varName, typeSchema);
      return createAlphaEquivalent(typeSchema).bodyType;
    case "LetRec":
      var varType = Type.createVar(null);
      var newCtxt = Env.createLocal({}, ctxt);
      Env.add(newCtxt, expr.varName, Type.createTypeSchema([], varType));
      var inferredType = infer(newCtxt, env, variants, expr.valueExpr);
      unify(varType, inferredType);
      var typeSchema = createPolyType(inferredType);
      Env.add(ctxt, expr.varName, typeSchema);
      return createAlphaEquivalent(typeSchema).bodyType;
    case "LetTuple":
      var inferredType = infer(ctxt, env, variants, expr.valueExpr);
      if (inferredType.tag != "Tuple") {
        throw new IbisError("tuple required, but got: " + inferredType);
      }
      var varNames = expr.varNames;
      var inferredTypeArray = inferredType.typeArray;
      if (inferredTypeArray.length != varNames.length) {
        throw new IbisError(varNames.length + "-tuple required, but got: " + inferredType);
      }
      var newTypeArray = [];
      for (var i in varNames) {
        var typeSchema = createPolyType(inferredTypeArray[i]);
        Env.add(ctxt, varNames[i], typeSchema);
        newTypeArray.push(createAlphaEquivalent(typeSchema).bodyType);
      }
      return Type.createTuple(newTypeArray);
    case "If":
      unify(infer(ctxt, env, variants, expr.condExpr), Type.Bool);
{'fraction_non_alphanumeric': 0.12296151337247227, 'fraction_numerical': 0.0, 'mean_word_length': 3.0269205515430073, 'pattern_counts': {'":': 24, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6836555', 'n_tokens_mistral': 1932, 'n_tokens_neox': 1918, 'n_words': 451}