use :node;

var Node = module.require('./Node').Node;

fn Program(body)

extends Node {

this.type = 'Program';
this.body = body;

for statement, i in body {
  if statement? {
    statement.parent = this;
  } else {
    body[i] = { type: 'EmptyStatement' };
  }
}

this.definedIdentifiers = Program.prototype.generateIdentifiers(
  'Infinity',
  'NaN',
  'eval',
  'uneval',
  'isFinite',
  'isNaN',
  'parseFloat',
  'parseInt',
  'decodeURI',
  'decodeURIComponent',
  'encodeURI',
  'encodeURIComponent',
  'escape',
  'unescape',
  'Object',
  'Function',
  'Boolean',
  'Symbol',
  'Error',
  'EvalError',
  'InternalError',
  'RangeError',
  'ReferenceError',
  'StopIteration',
  'SyntaxError',
  'TypeError',
  'URIError', 
  'Number',
  'Math',
  'Date',
  'String',
  'RegExp',
  'Array',
  'Int8Array',
  'Uint8Array',
  'Uint8ClampedArray',
  'Int16Array',
  'Uint16Array',
  'Int32Array',
  'Uint32Array',
  'Float32Array',
  'Float64Array',
  'Map',
  'Set',
  'WeakMap',
  'WeakSet',
  'ArrayBuffer',
  'DataView',
  'JSON',
  'Iterator',
  'Generator',
  'Promise',
  'arguments');

}

Program.prototype.codegen = () -> {

if !super.codegen() {
  return;
}

var i = 0;
while (i < this.body.length) {
  var statement = this.body[i];

  if !statement || statement.codeGenerated {
    i++;
    continue;
  }

  if statement.codegen && statement.codegen() {
    this.body[this.body.indexOf(statement)] = statement;
    i++;
  } else {
    this.body.splice(i, 1);
  }
}

return this;

};

Program.prototype.generateIdentifiers = (identifiers…) -> {

return identifiers.map((id) -> {
  return {
    "type": "Identifier",
    "name": id
  };
});

};

exports.Program = Program;