+void ProgramCompiler::UnusedVariableLocator::visit(FunctionDeclaration &func)
+{
+ variables.push_back(BlockVariableMap());
+
+ {
+ SetForScope<bool> set(global_scope, false);
+ for(vector<RefPtr<VariableDeclaration> >::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
+ (*i)->visit(*this);
+ func.body.visit(*this);
+ }
+
+ BlockVariableMap &block_variables = variables.back();
+ for(BlockVariableMap::iterator i=block_variables.begin(); i!=block_variables.end(); ++i)
+ i->second.conditionally_assigned = true;
+ for(vector<RefPtr<VariableDeclaration> >::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
+ block_variables[i->get()].referenced = true;
+ merge_down_variables();
+}
+
+void ProgramCompiler::UnusedVariableLocator::merge_down_variables()
+{
+ BlockVariableMap &parent_variables = variables[variables.size()-2];
+ BlockVariableMap &block_variables = variables.back();
+ for(BlockVariableMap::iterator i=block_variables.begin(); i!=block_variables.end(); ++i)
+ {
+ if(i->second.local)
+ {
+ if(!i->second.referenced)
+ unused_nodes.insert(i->first);
+ clear_assignments(i->second, true);
+ continue;
+ }
+
+ BlockVariableMap::iterator j = parent_variables.find(i->first);
+ if(j==parent_variables.end())
+ parent_variables.insert(*i);
+ else
+ {
+ if(i->second.referenced || !i->second.conditionally_assigned)
+ clear_assignments(j->second, !i->second.referenced);
+ j->second.conditionally_assigned = i->second.conditionally_assigned;
+ j->second.referenced |= i->second.referenced;
+ j->second.assignments.insert(j->second.assignments.end(), i->second.assignments.begin(), i->second.assignments.end());
+ }
+ }
+ variables.pop_back();
+}
+
+void ProgramCompiler::UnusedVariableLocator::visit(Conditional &cond)
+{
+ cond.condition->visit(*this);
+ variables.push_back(BlockVariableMap());
+ cond.body.visit(*this);
+
+ BlockVariableMap if_variables;
+ swap(variables.back(), if_variables);
+ cond.else_body.visit(*this);
+
+ BlockVariableMap &else_variables = variables.back();
+ for(BlockVariableMap::iterator i=else_variables.begin(); i!=else_variables.end(); ++i)
+ {
+ BlockVariableMap::iterator j = if_variables.find(i->first);
+ if(j!=if_variables.end())
+ {
+ i->second.assignments.insert(i->second.assignments.end(), j->second.assignments.begin(), j->second.assignments.end());
+ i->second.conditionally_assigned |= j->second.conditionally_assigned;
+ if_variables.erase(j);
+ }
+ else
+ i->second.conditionally_assigned = true;
+ }
+
+ for(BlockVariableMap::iterator i=if_variables.begin(); i!=if_variables.end(); ++i)
+ {
+ i->second.conditionally_assigned = true;
+ else_variables.insert(*i);
+ }
+
+ merge_down_variables();
+}
+
+void ProgramCompiler::UnusedVariableLocator::visit(Iteration &iter)
+{
+ variables.push_back(BlockVariableMap());
+ TraversingVisitor::visit(iter);
+
+ BlockVariableMap &block_variables = variables.back();
+ for(BlockVariableMap::iterator i=block_variables.begin(); i!=block_variables.end(); ++i)
+ if(!i->second.local && i->second.referenced)
+ i->second.assignments.clear();
+
+ merge_down_variables();
+}
+
+
+ProgramCompiler::UnusedVariableLocator::VariableInfo::VariableInfo():
+ local(false),
+ conditionally_assigned(false),
+ referenced(false)
+{ }
+
+
+void ProgramCompiler::UnusedFunctionLocator::visit(FunctionCall &call)
+{
+ TraversingVisitor::visit(call);
+
+ unused_nodes.erase(call.declaration);
+ if(call.declaration && call.declaration->definition!=call.declaration)
+ used_definitions.insert(call.declaration->definition);
+}
+
+void ProgramCompiler::UnusedFunctionLocator::visit(FunctionDeclaration &func)
+{
+ TraversingVisitor::visit(func);
+
+ if((func.name!="main" || func.body.body.empty()) && !used_definitions.count(&func))
+ unused_nodes.insert(&func);
+}
+
+
+ProgramCompiler::NodeRemover::NodeRemover(const set<Node *> &r):
+ to_remove(r)
+{ }