<commit_before>import * as ast from '../ast';
import { ASTVisit, ast_visit, complete_visit } from '../visit';
import { INT, FLOAT, Type, OverloadedType, FunType } from '../type';
import { Proc, Prog, Variant, CompilerIR } from '../compile/ir'
import * as llvm from '../../node_modules/llvmc/src/wrapped';

///////////////////////////////////////////////////////////////////
// Begin Emit Functions & Redundant Funcs
///////////////////////////////////////////////////////////////////

/**
 * Like `emitter.Emitter`, but for generating LLVM code instead of strings.
 */
interface LLVMEmitter {
  /**
   * The LLVM IRBuilder object used to generate code.
   */
  builder: llvm.Builder;

  /**
   * Map from id's to Alloca ptr's
   */
  namedValues: {[id:string] : llvm.Value};

  /**
   * Program we are compiling
   */
  ir: CompilerIR;

  // These are copies of `emitter.Emitter`'s `emit_` functions, except for
  // generating LLVM IR constructs.
  emit_expr: (tree: ast.SyntaxNode, emitter: LLVMEmitter) => llvm.Value;
  emit_proc: (emitter: LLVMEmitter, proc: Proc) => llvm.Value;
  emit_prog: (emitter: LLVMEmitter, prog: Prog) => llvm.Value;
  emit_prog_variant: (emitter: LLVMEmitter, variant: Variant, prog: Prog) =>
    llvm.Value;
}

// Copy of emitutils.ts function
function varsym(defid: number) {
  return 'v' + defid;
}

// Copy of js.ts function
function _is_fun_type(type: Type): boolean {
  if (type instanceof FunType) {
    return true;
  } else if (type instanceof OverloadedType) {
    return _is_fun_type(type.types[0]);
  } else {
    return false;
  }
}

function emit_extern(name: string, type: Type): llvm.Value {
  if (_is_fun_type(type)) {
    // The extern is a function. Wrap it in the clothing of our closure
    // format (with no environment).
    // TODO
    throw "Not implemented yet";
  } else {
    // An ordinary value. Just look it up by name.
    // TODO
    throw "Not implemented yet";
  }
}

function emit_assign(emitter: LLVMEmitter, tree: ast.AssignNode, get_varsym=varsym): llvm.Value {
  let defid = emitter.ir.defuse[tree.id!];
  let extern = emitter.ir.externs[defid];

  if (extern !== undefined) {
    // Extern assignment.
    // TODO
    throw "not implemented yet";
  } else {
    // Ordinary variable assignment.
    let jsvar = get_varsym(defid);
    let val: llvm.Value; // = emit(emitter, tree.expr)
    // TODO
  }
}

function emit_lookup(emitter: LLVMEmitter, emit_extern: (name: string, type: Type) => llvm.Value, tree: ast.LookupNode, get_varsym=varsym): llvm.Value {
  let defid = emitter.ir.defuse[tree.id!];
  let name = emitter.ir.externs[defid];

  if (name !== undefined) {
    // extern
    let [type, _] = emitter.ir.type_table[tree.id!];
    return emit_extern(name, type);
  } else {
    // An ordinary variable lookup
    let id = get_varsym(defid);

    // look up the pointer
    if (!emitter.namedValues.hasOwnProperty(id))
      throw "Unknown variable name";
    let ptr: llvm.Value = emitter.namedValues[id];

    // load value
    return emitter.builder.buildLoad(ptr, id);
  }
}

// copy of emitter function
function emit(emitter: LLVMEmitter, tree: ast.SyntaxNode): llvm.Value {
  return emitter.emit_expr(tree, emitter);
}

///////////////////////////////////////////////////////////////////
// End Emit Functions & Redundant Funcs
///////////////////////////////////////////////////////////////////

let compile_rules: ASTVisit<LLVMEmitter, llvm.Value> = {
  visit_literal(tree: ast.LiteralNode, emitter: LLVMEmitter): llvm.Value {
    if (tree.type === "int")
      return llvm.ConstInt.create(<number>tree.value, llvm.Type.int32());
    else if (tree.type === "float")
      return llvm.ConstFloat.create(<number>tree.value, llvm.Type.double());
    else if (tree.type === "string")
      return llvm.ConstString.create(<string>tree.value, true); // TODO: Null terminate? In Context?
    else
      throw "Unrecognized Type";
  },

  visit_seq(tree: ast.SeqNode, emitter: LLVMEmitter): llvm.Value {
    throw "not implemented";
  },

  visit_let(tree: ast.LetNode, emitter: LLVMEmitter): llvm.Value {
    let jsvar: string = varsym(tree.id!);
    let val: llvm.Value = emit(emitter, tree.expr)
    throw "not implemented";
  },

  visit_assign(tree: ast.AssignNode, emitter: LLVMEmitter): llvm.Value {
    throw "not implemented";
  },

  visit_lookup(tree: ast.LookupNode, emitter: LLVMEmitter): llvm.Value {
    return emit_lookup(emitter, emit_extern, tree);
  },
<commit_msg>Write function for creating entry block allocas<commit_after>import * as ast from '../ast';
import { ASTVisit, ast_visit, complete_visit } from '../visit';
import { INT, FLOAT, Type, OverloadedType, FunType } from '../type';
import { Proc, Prog, Variant, CompilerIR } from '../compile/ir'
import * as llvm from '../../node_modules/llvmc/src/wrapped';

///////////////////////////////////////////////////////////////////
// Begin Emit Functions & Redundant Funcs
///////////////////////////////////////////////////////////////////

/**
 * Like `emitter.Emitter`, but for generating LLVM code instead of strings.
 */
interface LLVMEmitter {
  /**
   * The LLVM IRBuilder object used to generate code.
   */
  builder: llvm.Builder;

  /**
   * Map from id's to Alloca ptr's
   */
  namedValues: {[id:string] : llvm.Value};

  /**
   * Program we are compiling
   */
  ir: CompilerIR;

  // These are copies of `emitter.Emitter`'s `emit_` functions, except for
  // generating LLVM IR constructs.
  emit_expr: (tree: ast.SyntaxNode, emitter: LLVMEmitter) => llvm.Value;
  emit_proc: (emitter: LLVMEmitter, proc: Proc) => llvm.Value;
  emit_prog: (emitter: LLVMEmitter, prog: Prog) => llvm.Value;
  emit_prog_variant: (emitter: LLVMEmitter, variant: Variant, prog: Prog) =>
    llvm.Value;
}

// Copy of emitutils.ts function
function varsym(defid: number) {
  return 'v' + defid;
}

// Copy of js.ts function
function _is_fun_type(type: Type): boolean {
  if (type instanceof FunType) {
    return true;
  } else if (type instanceof OverloadedType) {
    return _is_fun_type(type.types[0]);
  } else {
    return false;
  }
}

function emit_extern(name: string, type: Type): llvm.Value {
  if (_is_fun_type(type)) {
    // The extern is a function. Wrap it in the clothing of our closure
    // format (with no environment).
    // TODO
    throw "Not implemented yet";
  } else {
    // An ordinary value. Just look it up by name.
    // TODO
    throw "Not implemented yet";
  }
}

function emit_fun(name: string | null, argnames: string[], localnames: string[], body: string): llvm.Value {
  throw "not implemented yet"
}

function emit_assign(emitter: LLVMEmitter, tree: ast.AssignNode, get_varsym=varsym): llvm.Value {
  let defid = emitter.ir.defuse[tree.id!];
  let extern = emitter.ir.externs[defid];

  if (extern !== undefined) {
    // Extern assignment.
    // TODO
    throw "not implemented yet";
  } else {
    // Ordinary variable assignment.
    let jsvar = get_varsym(defid);
    let val: llvm.Value; // = emit(emitter, tree.expr)
    // TODO
  }
}

function emit_lookup(emitter: LLVMEmitter, emit_extern: (name: string, type: Type) => llvm.Value, tree: ast.LookupNode, get_varsym=varsym): llvm.Value {
  let defid = emitter.ir.defuse[tree.id!];
  let name = emitter.ir.externs[defid];

  if (name !== undefined) {
    // extern
    let [type, _] = emitter.ir.type_table[tree.id!];
    return emit_extern(name, type);
  } else {
    // An ordinary variable lookup
    let id = get_varsym(defid);

    // look up the pointer
    if (!emitter.namedValues.hasOwnProperty(id))
      throw "Unknown variable name";
    let ptr: llvm.Value = emitter.namedValues[id];

    // load value
    return emitter.builder.buildLoad(ptr, id);
  }
}

// copy of emitter function
function emit(emitter: LLVMEmitter, tree: ast.SyntaxNode): llvm.Value {
  return emitter.emit_expr(tree, emitter);
}

///////////////////////////////////////////////////////////////////
// End Emit Functions & Redundant Funcs
///////////////////////////////////////////////////////////////////

/**
 * Create an alloca with the provided name in the entry block of the provided function
 */
function createEntryBlockAlloca(func: llvm.Function, type: llvm.Type, name: string): llvm.Value {
  let builder: llvm.Builder = llvm.Builder.create();
  let bb: llvm.BasicBlock = func.getEntryBlock();
  let instr: llvm.Value = bb.getFirstInstr();

  builder.positionAfter(bb, instr);
  return builder.buildAlloca(type, name);
}

let compile_rules: ASTVisit<LLVMEmitter, llvm.Value> = {
  visit_literal(tree: ast.LiteralNode, emitter: LLVMEmitter): llvm.Value {
    if (tree.type === "int")
      return llvm.ConstInt.create(<number>tree.value, llvm.Type.int32());
    else if (tree.type === "float")
      return llvm.ConstFloat.create(<number>tree.value, llvm.Type.double());
    else if (tree.type === "string")
      return llvm.ConstString.create(<string>tree.value, true); // TODO: Null terminate? In Context?
    else
      throw "Unrecognized Type";
  },

  visit_seq(tree: ast.SeqNode, emitter: LLVMEmitter): llvm.Value {
    throw "not implemented";
  },

  visit_let(tree: ast.LetNode, emitter: LLVMEmitter): llvm.Value {
    let jsvar: string = varsym(tree.id!);
    let val: llvm.Value = emit(emitter, tree.expr)
    throw "not implemented";
  },

  visit_assign(tree: ast.AssignNode, emitter: LLVMEmitter): llvm.Value {
    throw "not implemented";
  },

  visit_lookup(tree: ast.LookupNode, emitter: LLVMEmitter): llvm.Value {
    return emit_lookup(emitter, emit_extern, tree);
  },

{'fraction_non_alphanumeric': 0.18415529905561384, 'fraction_numerical': 0.0006295907660020986, 'mean_word_length': 2.7303326810176127, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 21, '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': '3584365', 'n_tokens_mistral': 3072, 'n_tokens_neox': 2971, 'n_words': 823}