<commit_before>/**
 * Copyright (c) 2016, <NAME>
 * All rights reserved.
 */

// types

export abstract class ElmType {}

export class ElmTypeName extends ElmType {
  constructor(public name: string) {
    super();
  }
}

export class ElmTypeApp  extends ElmType {
  constructor(public name: string, public arg: ElmType) {
    super();
  }
}

export class ElmTypeRecord  extends ElmType {
  constructor(public fields: Array<ElmFieldDecl>) {
    super();
  }
}

// decls

export abstract class ElmDecl {}

export class ElmTypeDecl extends ElmDecl {
  constructor(public name: string,
              public constructors: Array<string>) {
    super();
  }
}

export class ElmTypeAliasDecl extends ElmDecl {   // todo: shouldn't this be name -> type, where type = ElmTypeRecord
  constructor(public name: string,
              public fields: Array<ElmFieldDecl>,
              public typeParams?: Array<string>) {
    super();
  }
}

export class ElmFunctionDecl extends ElmDecl {
  constructor(public name: string,
              public parameters: Array<ElmParameterDecl>,
              public returnType: ElmType,
              public body: ElmExpr) {
    super();
  }
}

export class ElmFieldDecl {
  constructor(public name: string,
              public type: ElmType) {}
}

export class ElmParameterDecl {
  constructor(public name: string,
              public type: ElmType) { }
}

// expressions

export interface ElmExpr {
  expr: string; // todo: expression trees
}

export function moduleToString(name: string, expose: Array<string>, imports: Array<string>,
                            decls: Array<ElmDecl>) {
  let warn = '{-\n    This file is automatically generated by elm-graphql. Do not modify!\n-}\n';
  return warn + 'module ' + name + ' exposing (' + expose.join(', ') + ')\n' +
    imports.map(str => '\nimport ' + str).join('') + '\n\n' +
    decls.map(declToString).join('\n\n');
}

export function declToString(decl: ElmDecl): string {
  if (decl instanceof ElmTypeDecl) {
    return typeDeclToString(decl);
  } else if (decl instanceof ElmFunctionDecl) {
    return funtionToString(decl);
  } else if (decl instanceof ElmTypeAliasDecl) {
    return typeAliasDeclToString(decl);
  } else {
    throw new Error('unexpected decl: ' + decl.constructor.name + ' ' + JSON.stringify(decl));
  }
}

export function typeDeclToString(type: ElmTypeDecl): string {
  return 'type ' + type.name + '\n' +
    '    = ' + type.constructors.join('\n    | ') + '\n';
}

export function typeAliasDeclToString(type: ElmTypeAliasDecl): string {
  if (type.fields.length == 0){
    return 'type alias ' + type.name + ' = ' + type.name + '_ {}'; // hack
  }
  let typeParams = type.typeParams ? ' ' + type.typeParams.join(' ') : '';
  let pipe = type.typeParams ? ' |' : '';
  return 'type alias ' + type.name + typeParams + ' =\n' +
    '    {' + typeParams + pipe + ' ' + type.fields.map(f => fieldToString(f, 1)).join('\n    , ') + '    }\n';
}

export function funtionToString(func: ElmFunctionDecl): string {
  let paramTypes = func.parameters.map(p => typeToString(p.type, 0)).join(' -> ');
  let paramNames = func.parameters.map(p => p.name).join(' ');
  let arrow = paramTypes.length > 0 ? ' -> ' : '';
  let space = paramTypes.length > 0 ? ' ' : '';
  return func.name + ' : ' + paramTypes + arrow + typeToString(func.returnType, 0) + '\n' +
         func.name + space + paramNames + ' =\n    ' + exprToString(func.body, 0) + '\n';
}

function fieldToString(field: ElmFieldDecl, level: number): string {
  return field.name + ' : ' + typeToString(field.type, level) + '\n';
}

export function typeToString(ty: ElmType, level: number): string {
  if (ty instanceof ElmTypeName) {
    return ty.name;
  } else if (ty instanceof ElmTypeApp) {
    return '(' + ty.name + ' ' + typeToString(ty.arg, level) + ')';  // todo: omit unneccesary parens
  } else if (ty instanceof ElmTypeRecord) {
    let indent = makeIndent(level);
    return `${indent}{ ` +
            ty.fields.map(f => fieldToString(f, level)).join(`${indent}, `) +
            `${indent}}`;
  } else {
    throw new Error('unexpected type: ' + ty.constructor.name + ' ' + JSON.stringify(ty));<commit_msg>fix: indenting bug<commit_after>/**
 * Copyright (c) 2016, <NAME>
 * All rights reserved.
 */

// types

export abstract class ElmType {}

export class ElmTypeName extends ElmType {
  constructor(public name: string) {
    super();
  }
}

export class ElmTypeApp  extends ElmType {
  constructor(public name: string, public arg: ElmType) {
    super();
  }
}

export class ElmTypeRecord  extends ElmType {
  constructor(public fields: Array<ElmFieldDecl>) {
    super();
  }
}

// decls

export abstract class ElmDecl {}

export class ElmTypeDecl extends ElmDecl {
  constructor(public name: string,
              public constructors: Array<string>) {
    super();
  }
}

export class ElmTypeAliasDecl extends ElmDecl {   // todo: shouldn't this be name -> type, where type = ElmTypeRecord
  constructor(public name: string,
              public fields: Array<ElmFieldDecl>,
              public typeParams?: Array<string>) {
    super();
  }
}

export class ElmFunctionDecl extends ElmDecl {
  constructor(public name: string,
              public parameters: Array<ElmParameterDecl>,
              public returnType: ElmType,
              public body: ElmExpr) {
    super();
  }
}

export class ElmFieldDecl {
  constructor(public name: string,
              public type: ElmType) {}
}

export class ElmParameterDecl {
  constructor(public name: string,
              public type: ElmType) { }
}

// expressions

export interface ElmExpr {
  expr: string; // todo: expression trees
}

export function moduleToString(name: string, expose: Array<string>, imports: Array<string>,
                            decls: Array<ElmDecl>) {
  let warn = '{-\n    This file is automatically generated by elm-graphql. Do not modify!\n-}\n';
  return warn + 'module ' + name + ' exposing (' + expose.join(', ') + ')\n' +
    imports.map(str => '\nimport ' + str).join('') + '\n\n' +
    decls.map(declToString).join('\n\n');
}

export function declToString(decl: ElmDecl): string {
  if (decl instanceof ElmTypeDecl) {
    return typeDeclToString(decl);
  } else if (decl instanceof ElmFunctionDecl) {
    return funtionToString(decl);
  } else if (decl instanceof ElmTypeAliasDecl) {
    return typeAliasDeclToString(decl);
  } else {
    throw new Error('unexpected decl: ' + decl.constructor.name + ' ' + JSON.stringify(decl));
  }
}

export function typeDeclToString(type: ElmTypeDecl): string {
  return 'type ' + type.name + '\n' +
    '    = ' + type.constructors.join('\n    | ') + '\n';
}

export function typeAliasDeclToString(type: ElmTypeAliasDecl): string {
  if (type.fields.length == 0){
    return 'type alias ' + type.name + ' = ' + type.name + '_ {}'; // hack
  }
  let typeParams = type.typeParams ? ' ' + type.typeParams.join(' ') : '';
  let pipe = type.typeParams ? ' |' : '';
  return 'type alias ' + type.name + typeParams + ' =\n' +
    '    {' + typeParams + pipe + ' ' + type.fields.map(f => fieldToString(f, 1)).join('\n    , ') + '    }\n';
}

export function funtionToString(func: ElmFunctionDecl): string {
  let paramTypes = func.parameters.map(p => typeToString(p.type, 1)).join(' -> ');
  let paramNames = func.parameters.map(p => p.name).join(' ');
  let arrow = paramTypes.length > 0 ? ' -> ' : '';
  let space = paramTypes.length > 0 ? ' ' : '';
  return func.name + ' : ' + paramTypes + arrow + typeToString(func.returnType, 0) + '\n' +
         func.name + space + paramNames + ' =\n    ' + exprToString(func.body, 0) + '\n';
}

function fieldToString(field: ElmFieldDecl, level: number): string {
  return field.name + ' : ' + typeToString(field.type, level) + '\n';
}

export function typeToString(ty: ElmType, level: number): string {
  if (ty instanceof ElmTypeName) {
    return ty.name;
  } else if (ty instanceof ElmTypeApp) {
    return '(' + ty.name + ' ' + typeToString(ty.arg, level) + ')';  // todo: omit unneccesary parens
  } else if (ty instanceof ElmTypeRecord) {
    let indent = makeIndent(level);
    return `${indent}{ ` +
            ty.fields.map(f => fieldToString(f, level)).join(`${indent}, `) +
            `${indent}}`;
  } else {
    throw new Error('unexpected type: ' + ty.constructor.name + ' ' + JSON.stringify(ty));
{'fraction_non_alphanumeric': 0.148401006108516, 'fraction_numerical': 0.002635046113306983, 'mean_word_length': 3.087126774351444, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 41, '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': '5731228', 'n_tokens_mistral': 2633, 'n_tokens_neox': 2616, 'n_words': 669}