<commit_before>import TemplateVisitor, { Action } from './template-visitor';
import JavaScriptCompiler, { Template } from './javascript-compiler';
import { assert, Option } from '@glimmer/util';
import { AST, isLiteral, SyntaxError } from '@glimmer/syntax';
import { getAttrNamespace } from './utils';
import { Opaque } from '@glimmer/interfaces';
import { SymbolAllocator, InOp as SymbolInOp, OutOp as SymbolOutOp } from './allocate-symbols';
import { PathHead } from './compiler-ops';

export interface CompileOptions {
  meta: Opaque;
  customizeComponentName?(tag: string): string;
}

function isTrustedValue(value: any) {
  return value.escaped !== undefined && !value.escaped;
}

export const THIS = 0;

export default class TemplateCompiler {
  static compile(ast: AST.Program, options?: CompileOptions): Template {
    let templateVisitor = new TemplateVisitor();
    templateVisitor.visit(ast);

    let compiler = new TemplateCompiler();
    let opcodes: SymbolInOp[] = compiler.process(templateVisitor.actions);
    let symbols: SymbolOutOp[] = new SymbolAllocator(opcodes).process();

    return JavaScriptCompiler.process(symbols, ast['symbols'], options);
  }

  private templateId = 0;
  private templateIds: number[] = [];
  private opcodes: SymbolInOp[] = [];
  private includeMeta = false;

  process(actions: Action[]): SymbolInOp[] {
    actions.forEach(([name, ...args]) => {
      if (!this[name]) {
        throw new Error(`Unimplemented ${name} on TemplateCompiler`);
      }
      (this[name] as any)(...args);
    });
    return this.opcodes;
  }

  startProgram([program]: [AST.Program]) {
    this.opcode(['startProgram', program], program);
  }

  endProgram() {
    this.opcode(['endProgram', null], null);
  }

  startBlock([program]: [AST.Program]) {
    this.templateId++;
    this.opcode(['startBlock', program], program);
  }

  endBlock() {
    this.templateIds.push(this.templateId - 1);
    this.opcode(['endBlock', null], null);
  }

  text([action]: [AST.TextNode]) {
    this.opcode(['text', action.chars], action);
  }

  comment([action]: [AST.CommentStatement]) {
    this.opcode(['comment', action.value], action);
  }

  openElement([action]: [AST.ElementNode]) {
    let attributes = action.attributes;
    let hasSplat;

    for (let i = 0; i < attributes.length; i++) {
      let attr = attributes[i];
      if (attr.name === '...attributes') {
        hasSplat = attr;
        break;
      }
    }

    if (isDynamicComponent(action)) {
      let head: PathHead, rest: string[];
      [head, ...rest] = action.tag.split('.');
      if (head === 'this') {
        head = 0;
      }
      this.opcode(['get', [head, rest]]);
      this.opcode(['openComponent', action], action);
    } else if (isComponent(action)) {
      this.opcode(['openComponent', action], action);
    } else if (hasSplat) {
      this.opcode(['openSplattedElement', action], action);
    } else {
      this.opcode(['openElement', action], action);
    }

    let typeAttr: Option<AST.AttrNode> = null;
    let attrs = action.attributes;
    for (let i = 0; i < attrs.length; i++) {
      if (attrs[i].name === 'type') {
        typeAttr = attrs[i];
        continue;
      }
      this.attribute([attrs[i]]);
    }

    if (typeAttr) {
      this.attribute([typeAttr]);
    }

    this.opcode(['flushElement', action], null);
  }

  closeElement([action]: [AST.ElementNode]) {
    if (isDynamicComponent(action)) {
      this.opcode(['closeDynamicComponent', action], action);
    } else if (isComponent(action)) {
      this.opcode(['closeComponent', action], action);
    } else if (action.modifiers.length > 0) {
      for (let i = 0; i < action.modifiers.length; i++) {
        this.modifier([action.modifiers[i]]);
      }
      this.opcode(['closeElement', action], action);
    } else {
      this.opcode(['closeElement', action], action);
    }
  }

  attribute([action]: [AST.AttrNode]) {
    let { name, value } = action;

    let namespace = getAttrNamespace(name);

    let isStatic = this.prepareAttributeValue(value);

    if (name.charAt(0) === '@') {
      // Arguments
      if (isStatic) {
        this.opcode(['staticArg', name], action);
      } else if (action.value.type === 'MustacheStatement') {
        this.opcode(['dynamicArg', name], action);
      } else {
        this.opcode(['dynamicArg', name], action);
      }
    } else {
      let isTrusting = isTrustedValue(value);

      if (isStatic && name === '...attributes') {
        this.opcode(['attrSplat', null], action);
      } else if (isStatic) {
        this.opcode(['staticAttr', [name, namespace]], action);
      } else if (isTrusting) {
        this.opcode(['trustingAttr', [name, namespace]], action);
      } else if (action.value.type === 'MustacheStatement') {
        this.opcode(['dynamicAttr', [name, null]], action);
      } else {
        this.opcode(['dynamicAttr', [name, namespace]], action);
      }
    }
  }

  modifier([action]: [AST.ElementModifierStatement]) {
    assertIsSimplePath(action.path, action.loc, 'modifier');

    let {
      path: { parts },
    } = action;

    this.prepareHelper(action);
    this.opcode(['modifier', parts[0]], action);
  }

  mustache([action]: [AST.MustacheStatement]) {<commit_msg>set namespace for dynamicArg<commit_after>import TemplateVisitor, { Action } from './template-visitor';
import JavaScriptCompiler, { Template } from './javascript-compiler';
import { assert, Option } from '@glimmer/util';
import { AST, isLiteral, SyntaxError } from '@glimmer/syntax';
import { getAttrNamespace } from './utils';
import { Opaque } from '@glimmer/interfaces';
import { SymbolAllocator, InOp as SymbolInOp, OutOp as SymbolOutOp } from './allocate-symbols';
import { PathHead } from './compiler-ops';

export interface CompileOptions {
  meta: Opaque;
  customizeComponentName?(tag: string): string;
}

function isTrustedValue(value: any) {
  return value.escaped !== undefined && !value.escaped;
}

export const THIS = 0;

export default class TemplateCompiler {
  static compile(ast: AST.Program, options?: CompileOptions): Template {
    let templateVisitor = new TemplateVisitor();
    templateVisitor.visit(ast);

    let compiler = new TemplateCompiler();
    let opcodes: SymbolInOp[] = compiler.process(templateVisitor.actions);
    let symbols: SymbolOutOp[] = new SymbolAllocator(opcodes).process();

    return JavaScriptCompiler.process(symbols, ast['symbols'], options);
  }

  private templateId = 0;
  private templateIds: number[] = [];
  private opcodes: SymbolInOp[] = [];
  private includeMeta = false;

  process(actions: Action[]): SymbolInOp[] {
    actions.forEach(([name, ...args]) => {
      if (!this[name]) {
        throw new Error(`Unimplemented ${name} on TemplateCompiler`);
      }
      (this[name] as any)(...args);
    });
    return this.opcodes;
  }

  startProgram([program]: [AST.Program]) {
    this.opcode(['startProgram', program], program);
  }

  endProgram() {
    this.opcode(['endProgram', null], null);
  }

  startBlock([program]: [AST.Program]) {
    this.templateId++;
    this.opcode(['startBlock', program], program);
  }

  endBlock() {
    this.templateIds.push(this.templateId - 1);
    this.opcode(['endBlock', null], null);
  }

  text([action]: [AST.TextNode]) {
    this.opcode(['text', action.chars], action);
  }

  comment([action]: [AST.CommentStatement]) {
    this.opcode(['comment', action.value], action);
  }

  openElement([action]: [AST.ElementNode]) {
    let attributes = action.attributes;
    let hasSplat;

    for (let i = 0; i < attributes.length; i++) {
      let attr = attributes[i];
      if (attr.name === '...attributes') {
        hasSplat = attr;
        break;
      }
    }

    if (isDynamicComponent(action)) {
      let head: PathHead, rest: string[];
      [head, ...rest] = action.tag.split('.');
      if (head === 'this') {
        head = 0;
      }
      this.opcode(['get', [head, rest]]);
      this.opcode(['openComponent', action], action);
    } else if (isComponent(action)) {
      this.opcode(['openComponent', action], action);
    } else if (hasSplat) {
      this.opcode(['openSplattedElement', action], action);
    } else {
      this.opcode(['openElement', action], action);
    }

    let typeAttr: Option<AST.AttrNode> = null;
    let attrs = action.attributes;
    for (let i = 0; i < attrs.length; i++) {
      if (attrs[i].name === 'type') {
        typeAttr = attrs[i];
        continue;
      }
      this.attribute([attrs[i]]);
    }

    if (typeAttr) {
      this.attribute([typeAttr]);
    }

    this.opcode(['flushElement', action], null);
  }

  closeElement([action]: [AST.ElementNode]) {
    if (isDynamicComponent(action)) {
      this.opcode(['closeDynamicComponent', action], action);
    } else if (isComponent(action)) {
      this.opcode(['closeComponent', action], action);
    } else if (action.modifiers.length > 0) {
      for (let i = 0; i < action.modifiers.length; i++) {
        this.modifier([action.modifiers[i]]);
      }
      this.opcode(['closeElement', action], action);
    } else {
      this.opcode(['closeElement', action], action);
    }
  }

  attribute([action]: [AST.AttrNode]) {
    let { name, value } = action;

    let namespace = getAttrNamespace(name);

    let isStatic = this.prepareAttributeValue(value);

    if (name.charAt(0) === '@') {
      // Arguments
      if (isStatic) {
        this.opcode(['staticArg', name], action);
      } else if (action.value.type === 'MustacheStatement') {
        this.opcode(['dynamicArg', name], action);
      } else {
        this.opcode(['dynamicArg', name], action);
      }
    } else {
      let isTrusting = isTrustedValue(value);

      if (isStatic && name === '...attributes') {
        this.opcode(['attrSplat', null], action);
      } else if (isStatic) {
        this.opcode(['staticAttr', [name, namespace]], action);
      } else if (isTrusting) {
        this.opcode(['trustingAttr', [name, namespace]], action);
      } else if (action.value.type === 'MustacheStatement') {
        this.opcode(['dynamicAttr', [name, namespace]], action);
      } else {
        this.opcode(['dynamicAttr', [name, namespace]], action);
      }
    }
  }

  modifier([action]: [AST.ElementModifierStatement]) {
    assertIsSimplePath(action.path, action.loc, 'modifier');

    let {
      path: { parts },
    } = action;

    this.prepareHelper(action);
    this.opcode(['modifier', parts[0]], action);
  }

  mustache([action]: [AST.MustacheStatement]) {
{'fraction_non_alphanumeric': 0.1682189697776088, 'fraction_numerical': 0.0019007793195210036, 'mean_word_length': 3.1757936507936506, 'pattern_counts': {'":': 0, '<': 11, '<?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': '1080698', 'n_tokens_mistral': 3203, 'n_tokens_neox': 3178, 'n_words': 719}