<commit_before>module.exports = Compiler;

function Compiler(node, opts) {
  this.opts = opts = opts || {};
  this.node = node;
}

Compiler.prototype.compile = function() {
  var ast = this.visit(this.node);
  return 'return ' + JSON.stringify(ast) + ';';
};

Compiler.prototype.visit = function(node) {
  if (!node || !node.type) return undefined;
  return this['visit' + node.type](node);
};

Compiler.prototype.visitCase = function(node) {
  return {
    type: 'switch',
    expression: node.expr,
    children: this.visit(node.block),
    line: node.line,
    filename: node.filename,
    buffer: true
  }
};

Compiler.prototype.visitWhen = function(node) {
  return {
    type: node.expr === 'default' ? 'default' : 'case',
    expression: node.expr !== 'default' ? node.expr : undefined,
    children: this.visit(node.block),
    line: node.line,
    filename: node.filename,
    buffer: true
  };
};

Compiler.prototype.visitLiteral = function(node) {
  return {
    type: 'expression',
    expression: node.str,
    buffer: node.buffer,
    escape: node.escape,
    line: node.line,
    filename: node.filename
  };
};

Compiler.prototype.visitBlock = function(node) {
  var length = node.nodes.length;

  var ast = [];

  for (var i = 0; i < length; ++i) {
    var out = this.visit(node.nodes[i]);
    if (out) ast.push(out);
  }
  return ast;
};

Compiler.prototype.visitMixinBlock = function(node, ast) {
  // TODO
  throw errorAtNode(node, new Error('Mixins are not supported at this time'));
};

Compiler.prototype.visitDoctype = function(node, ast) {
  // TODO
  throw errorAtNode(node, new Error('Doctypes are not supported at this time'));
};

Compiler.prototype.visitMixin = function(node, ast) {
  // TODO
  throw errorAtNode(node, new Error('Mixins are not supported at this time'));
};

Compiler.prototype.visitTag = function(node, ast) {
  var self = this;
  var name = node.name;

  if (node.selfClosing &&
      node.block &&
      !(node.block.type === 'Block' && node.block.nodes.length === 0) &&
      node.block.nodes.some(function(tag) {
        return tag.type !== 'Text' || !/^\s*$/.test(tag.val)
      })) {
    throw errorAtNode(node, new Error(name + ' is self closing and should not have content.'));
  }

  if (name === 't') return self.visitTranslation(node, ast);
  if (name === 'import') return self.visitImport(node, ast);
  if (name === 'var') return self.visitVar(node, ast);
  if (name === 'export') return self.visitExport(node, ast);

  var attrs = node.attrs.slice();

  var children = (node.block && node.block.nodes.length && node.block.nodes || (node.code ? [node.code] : [])).reduce(function(acc, child) {
    if (child.type !== 'Block' || !child.name) acc.push(self.visit(child));
    else attrs.push({name: child.name, val: self.visit(child), block: true, args: child.args});
    return acc;
  }, []);

  var el = {
    type: 'tag',
    name: name,
    props: this.visitAttributes(attrs, node.attributeBlocks),
    children: children,
    line: node.line,
    filename: node.filename,
    buffer: true
  };

  return el;
};

Compiler.prototype.visitImport = function(node, ast) {
  return {
    type: 'import',
    expression: node.block.nodes[0].val,
    line: node.line,
    filename: node.filename
  };
};

Compiler.prototype.visitExport = function(node, ast) {
  return {
    type: 'export',
    expression: node.block.nodes.map(function(node) {
      return node.val;
    }).join('\n'),
    line: node.line,
    filename: node.filename
  }
};

Compiler.prototype.visitVar = function(node, ast) {
  return {
    type: 'var',
    expression: node.block.nodes[0].val,
    line: node.line,
    filename: node.filename
  };
};

Compiler.prototype.visitFilter = function(node, ast) {
  // TODO
  throw errorAtNode(node, new Error('Filters are not supported at this time'));
};

Compiler.prototype.visitText = function(node, ast) {
  if (!node.val) return false;
  // TODO interpolation
  // TODO unescape html expressions
  return {
    type: 'text',
    expression: JSON.stringify(node.val),
    line: node.line,
    filename: node.filename,
    buffer: true
  };
};

Compiler.prototype.visitTranslation = function(node, ast) {
  var self = this;
  var attrs = node.attrs.slice();

  var children = (node.block && node.block.nodes.length && node.block.nodes || (node.code ? [node.code] : [])).map(function(child) {
    if (child.type !== 'Block') throw errorAtNode(node, new Error('Invalid child for translation'));
    var name = child.name;
    if (!name) throw errorAtNode(node, new Error('Block missing name'));

    attrs.push({
      name: name,
      val: self.visit(child),
      block: true
    });
  });

  var el = {<commit_msg>set key property on translation blocks<commit_after>module.exports = Compiler;

function Compiler(node, opts) {
  this.opts = opts = opts || {};
  this.node = node;
}

Compiler.prototype.compile = function() {
  var ast = this.visit(this.node);
  return 'return ' + JSON.stringify(ast) + ';';
};

Compiler.prototype.visit = function(node) {
  if (!node || !node.type) return undefined;
  return this['visit' + node.type](node);
};

Compiler.prototype.visitCase = function(node) {
  return {
    type: 'switch',
    expression: node.expr,
    children: this.visit(node.block),
    line: node.line,
    filename: node.filename,
    buffer: true
  }
};

Compiler.prototype.visitWhen = function(node) {
  return {
    type: node.expr === 'default' ? 'default' : 'case',
    expression: node.expr !== 'default' ? node.expr : undefined,
    children: this.visit(node.block),
    line: node.line,
    filename: node.filename,
    buffer: true
  };
};

Compiler.prototype.visitLiteral = function(node) {
  return {
    type: 'expression',
    expression: node.str,
    buffer: node.buffer,
    escape: node.escape,
    line: node.line,
    filename: node.filename
  };
};

Compiler.prototype.visitBlock = function(node) {
  var length = node.nodes.length;

  var ast = [];

  for (var i = 0; i < length; ++i) {
    var out = this.visit(node.nodes[i]);
    if (out) ast.push(out);
  }
  return ast;
};

Compiler.prototype.visitMixinBlock = function(node, ast) {
  // TODO
  throw errorAtNode(node, new Error('Mixins are not supported at this time'));
};

Compiler.prototype.visitDoctype = function(node, ast) {
  // TODO
  throw errorAtNode(node, new Error('Doctypes are not supported at this time'));
};

Compiler.prototype.visitMixin = function(node, ast) {
  // TODO
  throw errorAtNode(node, new Error('Mixins are not supported at this time'));
};

Compiler.prototype.visitTag = function(node, ast) {
  var self = this;
  var name = node.name;

  if (node.selfClosing &&
      node.block &&
      !(node.block.type === 'Block' && node.block.nodes.length === 0) &&
      node.block.nodes.some(function(tag) {
        return tag.type !== 'Text' || !/^\s*$/.test(tag.val)
      })) {
    throw errorAtNode(node, new Error(name + ' is self closing and should not have content.'));
  }

  if (name === 't') return self.visitTranslation(node, ast);
  if (name === 'import') return self.visitImport(node, ast);
  if (name === 'var') return self.visitVar(node, ast);
  if (name === 'export') return self.visitExport(node, ast);

  var attrs = node.attrs.slice();

  var children = (node.block && node.block.nodes.length && node.block.nodes || (node.code ? [node.code] : [])).reduce(function(acc, child) {
    if (child.type !== 'Block' || !child.name) acc.push(self.visit(child));
    else attrs.push({name: child.name, val: self.visit(child), block: true, args: child.args});
    return acc;
  }, []);

  var el = {
    type: 'tag',
    name: name,
    props: this.visitAttributes(attrs, node.attributeBlocks),
    children: children,
    line: node.line,
    filename: node.filename,
    buffer: true
  };

  return el;
};

Compiler.prototype.visitImport = function(node, ast) {
  return {
    type: 'import',
    expression: node.block.nodes[0].val,
    line: node.line,
    filename: node.filename
  };
};

Compiler.prototype.visitExport = function(node, ast) {
  return {
    type: 'export',
    expression: node.block.nodes.map(function(node) {
      return node.val;
    }).join('\n'),
    line: node.line,
    filename: node.filename
  }
};

Compiler.prototype.visitVar = function(node, ast) {
  return {
    type: 'var',
    expression: node.block.nodes[0].val,
    line: node.line,
    filename: node.filename
  };
};

Compiler.prototype.visitFilter = function(node, ast) {
  // TODO
  throw errorAtNode(node, new Error('Filters are not supported at this time'));
};

Compiler.prototype.visitText = function(node, ast) {
  if (!node.val) return false;
  // TODO interpolation
  // TODO unescape html expressions
  return {
    type: 'text',
    expression: JSON.stringify(node.val),
    line: node.line,
    filename: node.filename,
    buffer: true
  };
};

Compiler.prototype.visitTranslation = function(node, ast) {
  var self = this;
  var attrs = node.attrs.slice();

  var children = (node.block && node.block.nodes.length && node.block.nodes || (node.code ? [node.code] : [])).map(function(child) {
    if (child.type !== 'Block') throw errorAtNode(node, new Error('Invalid child for translation'));
    var name = child.name;
    if (!name) throw errorAtNode(node, new Error('Block missing name'));

    var visited = self.visit(child);

    if (visited.length === 1) visited[0].props.key = {name: name, expression: JSON.stringify(name)};

    attrs.push({
      name: name,
      val: visited,
      block: true
    });
  });

  var el = {
{'fraction_non_alphanumeric': 0.162139486103828, 'fraction_numerical': 0.001048767697954903, 'mean_word_length': 3.3306085376930064, 'pattern_counts': {'":': 0, '<': 5, '<?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': '5764407', 'n_tokens_mistral': 3093, 'n_tokens_neox': 3069, 'n_words': 758}