var classes = new Object();

function MemberInfo(name) {
  this.initialized_members = [];
  this.members = undefined;
  this.name = name;
}

MemberInfo.prototype.addUsage = function(decl, members) {
  this.initialized_members.push({decl:decl, members:members});
}

MemberInfo.prototype.addMembers = function(members) {
  this.members = members
}

MemberInfo.prototype.checkInits = function () {
  if(!this.members)
    return
  for each(var init in this.initialized_members) {
      if(init.members.length != this.members.length) 
	print("Constructor declared at "+init.decl+" is not initializing everything")
  }
}

function process(vars, state) {
  // Step one. When entering a function there is a special variable
  // describing a function. Check if the function is actually a constructor.
  // Then save the class name & statically initialized members
  if(!state) {
    var constructor = /class ([^ ]+)/(vars[0].constructor);
    if(constructor) {
      // record initializers if in constructor 
      state = {class:constructor[1], decl: vars[0].decl,
	       members:vars[0].inits.map(function(x) {return x.name})}
      return state
    }
  }
  // return if we arent in a constructor
  if(!state)
    return;
  // This function looks into decomposed expressions
  // looking for {name:"member", fieldOf{name:this, type:"class Name *"}} 
  // pattern. If class Name matches the class in state, save the "member" as an
  // initialized one 
  function process_v(v) {
    if(!(v.assign && v.fieldOf && v.fieldOf.name == "this"))
      return;
    var type = /class ([^ ]+) \*/(v.fieldOf.type);
    if(!(type && type[1] == state.class))
      return;
    if(state.members.indexOf(v.name) == -1)
      state.members.push(v.name);
    //print(type[1] + "." +v.name);
  }
  //print(vars)
  iter(process_v, vars)
  return state;  
}

function path_end(state) {
  if(!state)
    return
  var class = classes[state.class];
  if(!class) {
    class = classes[state.class] = new MemberInfo();
  }
  class.addUsage(state.decl, state.members)
}

function process_class(c) {
  var ls = [];
  for each (var m in c.members) {
    if(/\(\)\(\)$/(m.type)) continue;
    ls.push(m.name)
  }
  var class = classes[c.name];
  if(!class)
    class = classes[c.name] = new MemberInfo(c.name);
  class.members = ls
}

function input_end() {
  for each (var class in classes) {
      class.checkInits()
  }
}
