<commit_before>// patterns.js : Powerful pattern matching for Javascript
// <NAME> <<EMAIL>>

var parser = require("./parser");
var compiler = require("./compiler");
var Matcher = require("./matcher").Matcher;

// Cache slice
var slice = Array.prototype.slice;

// Internal cache of all patterns
var patterns = {};

// Internal cache of all unique, normalized patterns
var normalized = {};

// Creates a pattern matching function given a string and a fn to execute.
function pattern () {
  var args = slice.call(arguments);

  // types
  var targ0 = typeof args[0];
  var targ1 = typeof args[1];
  var targ2 = typeof args[2];

  // Shared vars
  var matcherFn, patternObj, patternFn, patternStr, successFn, chain, tree, last;

  // pattern(matcherFn, chain)
  if (targ0 == "function" && (targ1 == "undefined" || targ1 == "object")) { 
    matcherFn = args[0];
    chain = args[1];

    // Throw an error if the supplied function does not have a match chain.
    if (!matcherFn.__matchChain) throw new Error("Not a matcher function");

    // Splice the chains together.
    if (chain) {
      chain = chain.clone();
      chain.last().next = matcherFn.__matchChain.clone();
    } else {
      chain = matcherFn.__matchChain.clone();
    }

    last = chain.pop();
    return matcher(last.patternFn, last.successFn, chain);
  }

  // pattern(patternObj, chain)
  else if (targ0 == "object" && (targ1 == "undefined" || targ1 == "object")) {
    patternObj = args[0];
    chain = args[1] ? args[1].clone() : null;
    for (patternStr in patternObj) {
      matcherFn = pattern(patternStr, patternObj[patternStr], chain);
      chain = matcherFn.__matchChain;
    }
    return matcherFn;
  }

  // pattern(patternFn, successFn, chain)
  else if (targ0 == "function" && targ1 == "function") {
    chain = args[2] ? args[2].clone() : null;
    return matcher(args[0], args[1], chain);
  }

  // pattern(patternStr, successFn, chain)
  else {
    patternStr = args[0];
    successFn = args[1];
    chain = args[2] ? args[2].clone() : null;
    tree = parser.parse(patternStr);

    // Check if we've already compiled a pattern function for the normalized
    // pattern. If so, just use that and don't bother compiling.
    if (tree.pattern in normalized) {
      patternFn = (patterns[patternStr] = normalized[tree.pattern]);
    }

    // Compile the pattern function and cache it.
    else {
      patternFn = compiler.compile(tree);
      patternFn.pattern = tree.pattern;
      patterns[patternStr] = patternFn;
      normalized[tree.pattern] = patternFn;
    }

    return matcher(patternFn, successFn, chain);
  }
}

// Creates a function that tries a match and executes the given fn if
// successful. If not it tries subsequent patterns.
function matcher (patternFn, successFn, chain) {
  var matcherObj = new Matcher(patternFn, successFn);

  if (chain) {
    chain.last().next = matcherObj;
  } else {
    chain = matcherObj;
  }

  var fn = function () {
    var args = slice.call(arguments);
    return chain.match(args, this);
  };

  fn.alt = function () {
    var args = slice.call(arguments);
    args.push(chain);<commit_msg>Lookup pattern string in cache before attempting to parse<commit_after>// patterns.js : Powerful pattern matching for Javascript
// <NAME> <<EMAIL>>

var parser = require("./parser");
var compiler = require("./compiler");
var Matcher = require("./matcher").Matcher;

// Cache slice
var slice = Array.prototype.slice;

// Internal cache of all patterns
var patterns = {};

// Internal cache of all unique, normalized patterns
var normalized = {};

// Creates a pattern matching function given a string and a fn to execute.
function pattern () {
  var args = slice.call(arguments);

  // types
  var targ0 = typeof args[0];
  var targ1 = typeof args[1];
  var targ2 = typeof args[2];

  // Shared vars
  var matcherFn, patternObj, patternFn, patternStr, successFn, chain, tree, last;

  // pattern(matcherFn, chain)
  if (targ0 == "function" && (targ1 == "undefined" || targ1 == "object")) { 
    matcherFn = args[0];
    chain = args[1];

    // Throw an error if the supplied function does not have a match chain.
    if (!matcherFn.__matchChain) throw new Error("Not a matcher function");

    // Splice the chains together.
    if (chain) {
      chain = chain.clone();
      chain.last().next = matcherFn.__matchChain.clone();
    } else {
      chain = matcherFn.__matchChain.clone();
    }

    last = chain.pop();
    return matcher(last.patternFn, last.successFn, chain);
  }

  // pattern(patternObj, chain)
  else if (targ0 == "object" && (targ1 == "undefined" || targ1 == "object")) {
    patternObj = args[0];
    chain = args[1] ? args[1].clone() : null;
    for (patternStr in patternObj) {
      matcherFn = pattern(patternStr, patternObj[patternStr], chain);
      chain = matcherFn.__matchChain;
    }
    return matcherFn;
  }

  // pattern(patternFn, successFn, chain)
  else if (targ0 == "function" && targ1 == "function") {
    chain = args[2] ? args[2].clone() : null;
    return matcher(args[0], args[1], chain);
  }

  // pattern(patternStr, successFn, chain)
  else {
    patternStr = args[0];
    successFn = args[1];
    chain = args[2] ? args[2].clone() : null;

    // Check if we've already compiled the same patternStr before.
    if (patternStr in patterns) {
      patternFn = patterns[patternStr];
    }

    else {
      tree = parser.parse(patternStr);

      // Check if we've already compiled a pattern function for the normalized
      // pattern. If so, just use that and don't bother compiling.
      if (tree.pattern in normalized) {
        patternFn = (patterns[patternStr] = normalized[tree.pattern]);
      }

      // Compile the pattern function and cache it.
      else {
        patternFn = compiler.compile(tree);
        patternFn.pattern = tree.pattern;
        patterns[patternStr] = patternFn;
        normalized[tree.pattern] = patternFn;
      }
    }

    return matcher(patternFn, successFn, chain);
  }
}

// Creates a function that tries a match and executes the given fn if
// successful. If not it tries subsequent patterns.
function matcher (patternFn, successFn, chain) {
  var matcherObj = new Matcher(patternFn, successFn);

  if (chain) {
    chain.last().next = matcherObj;
  } else {
    chain = matcherObj;
  }

  var fn = function () {
    var args = slice.call(arguments);
    return chain.match(args, this);
  };

  fn.alt = function () {
    var args = slice.call(arguments);
    args.push(chain);
{'fraction_non_alphanumeric': 0.1331079003996311, 'fraction_numerical': 0.008300030740854596, 'mean_word_length': 3.041614906832298, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, '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': '3567605', 'n_tokens_mistral': 2009, 'n_tokens_neox': 1961, 'n_words': 609}