Update thrift compiler for new syntax, generate new form of C++ code

Reviewed By: wayne, he loves less warnings


git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664840 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/compiler/cpp/src/generate/t_cpp_generator.cc b/compiler/cpp/src/generate/t_cpp_generator.cc
index 28c9913..c59112c 100644
--- a/compiler/cpp/src/generate/t_cpp_generator.cc
+++ b/compiler/cpp/src/generate/t_cpp_generator.cc
@@ -10,7 +10,7 @@
  *
  * @param tprogram The program to generate
  */
-void t_cpp_generator::init_generator(t_program* tprogram) {
+void t_cpp_generator::init_generator() {
   // Make output directory
   mkdir(T_CPP_DIR, S_IREAD | S_IWRITE | S_IEXEC);
 
@@ -40,14 +40,31 @@
     "#include <transport/TTransport.h>" << endl <<
     endl;
 
+  // Include other Thrift includes
+  const vector<t_program*>& includes = program_->get_includes();
+  for (size_t i = 0; i < includes.size(); ++i) {
+    f_types_ <<
+      "#include \"" << includes[i]->get_name() << "_types.h\"" << endl;
+  }
+  f_types_ << endl;
+
+  // Include custom headers
+  const vector<string>& cpp_includes = program_->get_cpp_includes();
+  for (size_t i = 0; i < cpp_includes.size(); ++i) {
+    f_types_ <<
+      "#include \"" << cpp_includes[i] << "\"" << endl;
+  }
+  f_types_ <<
+    endl;
+  
   // Include the types file
   f_types_impl_ <<
-    "#include \"" << program_name_ <<"_types.h\"" << endl <<
+    "#include \"" << program_name_ << "_types.h\"" << endl <<
     endl;
 
   // Open namespace
-  ns_open_ = namespace_open(tprogram->get_namespace());
-  ns_close_ = namespace_close(tprogram->get_namespace());
+  ns_open_ = namespace_open(program_->get_cpp_namespace());
+  ns_close_ = namespace_close(program_->get_cpp_namespace());
 
   f_types_ <<
     ns_open_ << endl <<
@@ -61,7 +78,7 @@
 /**
  * Closes the output files.
  */
-void t_cpp_generator::close_generator(t_program* tprogram) {
+void t_cpp_generator::close_generator() {
   // Close namespace
   f_types_ <<
     ns_close_ << endl <<
@@ -171,8 +188,9 @@
         indent(out) <<
           tstruct->get_name() << "() : ";
         out << (*m_iter)->get_name() << "(0)";
-      } else
+      } else {
         out << ", " << (*m_iter)->get_name() << "(0)";
+      }
     }
   }
   if (init_ctor) {
@@ -219,8 +237,8 @@
 
   out <<
     endl <<
-    indent() << "uint32_t read(boost::shared_ptr<const facebook::thrift::protocol::TProtocol> iprot, boost::shared_ptr<facebook::thrift::transport::TTransport> itrans);" << endl <<
-    indent() << "uint32_t write(boost::shared_ptr<const facebook::thrift::protocol::TProtocol> oprot, boost::shared_ptr<facebook::thrift::transport::TTransport> otrans) const;" << endl <<
+    indent() << "uint32_t read(boost::shared_ptr<facebook::thrift::protocol::TProtocol> iprot);" << endl <<
+    indent() << "uint32_t write(boost::shared_ptr<facebook::thrift::protocol::TProtocol> oprot) const;" << endl <<
     endl;
 
   indent_down(); 
@@ -238,7 +256,7 @@
 void t_cpp_generator::generate_struct_reader(ofstream& out,
                                              t_struct* tstruct) {
   indent(out) <<
-    "uint32_t " << tstruct->get_name() << "::read(boost::shared_ptr<const facebook::thrift::protocol::TProtocol> iprot, boost::shared_ptr<facebook::thrift::transport::TTransport> itrans) {" << endl;
+    "uint32_t " << tstruct->get_name() << "::read(boost::shared_ptr<facebook::thrift::protocol::TProtocol> iprot) {" << endl;
   indent_up();
 
   const vector<t_field*>& fields = tstruct->get_members();
@@ -252,7 +270,7 @@
     indent() << "facebook::thrift::protocol::TType ftype;" << endl <<
     indent() << "int16_t fid;" << endl <<
     endl <<
-    indent() << "xfer += iprot->readStructBegin(itrans, fname);" << endl <<
+    indent() << "xfer += iprot->readStructBegin(fname);" << endl <<
     endl;
   
   // Loop over reading in fields
@@ -262,7 +280,7 @@
     
     // Read beginning field marker
     indent(out) <<
-      "xfer += iprot->readFieldBegin(itrans, fname, ftype, fid);" << endl;
+      "xfer += iprot->readFieldBegin(fname, ftype, fid);" << endl;
     
     // Check for field STOP marker
     out <<
@@ -291,20 +309,20 @@
       // In the default case we skip the field
       out <<
         indent() << "default:" << endl <<
-        indent() << "  xfer += iprot->skip(itrans, ftype);" << endl <<
+        indent() << "  xfer += iprot->skip(ftype);" << endl <<
         indent() << "  break;" << endl;
       
       scope_down(out);
 
     // Read field end marker
     indent(out) <<
-      "xfer += iprot->readFieldEnd(itrans);" << endl;
+      "xfer += iprot->readFieldEnd();" << endl;
 
     scope_down(out);
 
   out <<
     endl <<
-    indent() << "xfer += iprot->readStructEnd(itrans);" << endl <<
+    indent() << "xfer += iprot->readStructEnd();" << endl <<
     indent() <<"return xfer;" << endl;
 
   indent_down();
@@ -325,18 +343,18 @@
   vector<t_field*>::const_iterator f_iter;
 
   indent(out) <<
-    "uint32_t " << tstruct->get_name() << "::write(boost::shared_ptr<const facebook::thrift::protocol::TProtocol> oprot, boost::shared_ptr<facebook::thrift::transport::TTransport> otrans) const {" << endl;
+    "uint32_t " << tstruct->get_name() << "::write(boost::shared_ptr<facebook::thrift::protocol::TProtocol> oprot) const {" << endl;
   indent_up();
 
   out <<
     indent() << "uint32_t xfer = 0;" << endl;
 
   indent(out) <<
-    "xfer += oprot->writeStructBegin(otrans, \"" << name << "\");" << endl;
+    "xfer += oprot->writeStructBegin(\"" << name << "\");" << endl;
   for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
     // Write field header
     out <<
-      indent() << "xfer += oprot->writeFieldBegin(otrans, " <<
+      indent() << "xfer += oprot->writeFieldBegin(" <<
       "\"" << (*f_iter)->get_name() << "\", " <<
       type_to_enum((*f_iter)->get_type()) << ", " <<
       (*f_iter)->get_key() << ");" << endl;
@@ -344,12 +362,12 @@
     generate_serialize_field(out, *f_iter, "this->");
     // Write field closer
     indent(out) <<
-      "xfer += oprot->writeFieldEnd(otrans);" << endl;
+      "xfer += oprot->writeFieldEnd();" << endl;
   }
   // Write the struct map
   out <<
-    indent() << "xfer += oprot->writeFieldStop(otrans);" << endl <<
-    indent() << "xfer += oprot->writeStructEnd(otrans);" << endl <<
+    indent() << "xfer += oprot->writeFieldStop();" << endl <<
+    indent() << "xfer += oprot->writeStructEnd();" << endl <<
     indent() << "return xfer;" << endl;
 
   indent_down();
@@ -373,7 +391,7 @@
   vector<t_field*>::const_iterator f_iter;
 
   indent(out) <<
-    "uint32_t " << tstruct->get_name() << "::write(boost::shared_ptr<const facebook::thrift::protocol::TProtocol> oprot, boost::shared_ptr<facebook::thrift::transport::TTransport> otrans) const {" << endl;
+    "uint32_t " << tstruct->get_name() << "::write(boost::shared_ptr<facebook::thrift::protocol::TProtocol> oprot) const {" << endl;
   indent_up();
 
   out <<
@@ -382,7 +400,7 @@
     endl;
 
   indent(out) <<
-    "xfer += oprot->writeStructBegin(otrans, \"" << name << "\");" << endl;
+    "xfer += oprot->writeStructBegin(\"" << name << "\");" << endl;
 
   bool first = true;
   for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
@@ -402,14 +420,14 @@
 
     // Write field header
     out <<
-      indent() << "xfer += oprot->writeFieldBegin(otrans, " <<
+      indent() << "xfer += oprot->writeFieldBegin(" <<
       "\"" << (*f_iter)->get_name() << "\", " <<
       type_to_enum((*f_iter)->get_type()) << ", " <<
       (*f_iter)->get_key() << ");" << endl;
     // Write field contents
     generate_serialize_field(out, *f_iter, "this->");
     // Write field closer
-    indent(out) << "xfer += oprot->writeFieldEnd(otrans);" << endl;
+    indent(out) << "xfer += oprot->writeFieldEnd();" << endl;
 
     indent_down();
     indent(out) << "}";
@@ -418,8 +436,8 @@
   // Write the struct map
   out <<
     endl <<
-    indent() << "xfer += oprot->writeFieldStop(otrans);" << endl <<
-    indent() << "xfer += oprot->writeStructEnd(otrans);" << endl <<
+    indent() << "xfer += oprot->writeFieldStop();" << endl <<
+    indent() << "xfer += oprot->writeStructEnd();" << endl <<
     indent() << "return xfer;" << endl;
 
   indent_down();
@@ -451,7 +469,14 @@
     "#define " << svcname << "_H" << endl <<
     endl <<
     "#include <TProcessor.h>" << endl <<
-    "#include \"" << program_name_ << "_types.h\"" << endl <<
+    "#include \"" << program_name_ << "_types.h\"" << endl;
+
+  if (tservice->get_extends() != NULL) {
+    f_header_ <<
+      "#include \"" << tservice->get_extends()->get_name() << ".h\"" << endl;
+  }
+
+  f_header_ <<
     endl <<
     ns_open_ << endl <<
     endl;
@@ -471,8 +496,9 @@
   generate_service_interface(tservice);
   generate_service_helpers(tservice);
   generate_service_client(tservice);
-  generate_service_server(tservice);
+  generate_service_processor(tservice);
   generate_service_multiface(tservice);
+  generate_service_skeleton(tservice);
 
   // Close the namespace
   f_service_ <<
@@ -513,8 +539,12 @@
  * @param tservice The service to generate a header definition for
  */
 void t_cpp_generator::generate_service_interface(t_service* tservice) {
+  string extends = "";
+  if (tservice->get_extends() != NULL) {
+    extends = " : virtual public " + type_name(tservice->get_extends()) + "If";
+  }
   f_header_ <<
-    "class " << service_name_ << "If {" << endl <<
+    "class " << service_name_ << "If" << extends << " {" << endl <<
     " public: " << endl;
   indent_up(); 
   f_header_ <<
@@ -542,16 +572,33 @@
   vector<t_function*> functions = tservice->get_functions();
   vector<t_function*>::iterator f_iter; 
 
+  string extends = "";
+  string extends_multiface = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    extends_multiface = ", public " + extends + "Multiface";
+  }
+
   string list_type = string("std::vector<boost::shared_ptr<") + service_name_ + "If> >";
 
   // Generate the header portion
   f_header_ <<
     "class " << service_name_ << "Multiface : " <<
-    "public " << service_name_ << "If {" << endl <<
+    "virtual public " << service_name_ << "If" <<
+    extends_multiface << " {" << endl <<
     " public: " << endl;
   indent_up();
   f_header_ << 
-    indent() << service_name_ << "Multiface(" << list_type << "& ifaces) : _ifaces(ifaces) {}" << endl <<
+    indent() << service_name_ << "Multiface(" << list_type << "& ifaces) : ifaces_(ifaces) {" << endl;
+  if (!extends.empty()) {
+    f_header_ <<
+      indent() << "  std::vector<boost::shared_ptr<" + service_name_ + "If> >::iterator iter;" << endl <<
+      indent() << "  for (iter = ifaces.begin(); iter != ifaces.end(); ++iter) {" << endl <<
+      indent() << "    " << extends << "Multiface::add(*iter);" << endl <<
+      indent() << "  }" << endl;
+  }
+  f_header_ <<
+    indent() << "}" << endl <<
     indent() << "virtual ~" << service_name_ << "Multiface() {}" << endl;
   indent_down();
 
@@ -560,7 +607,16 @@
     " protected:" << endl;
   indent_up();
   f_header_ <<
-    indent() << list_type << "& _ifaces;" << endl;
+    indent() << list_type << " ifaces_;" << endl <<
+    indent() << service_name_ << "Multiface() {}" << endl <<
+    indent() << "void add(boost::shared_ptr<" << service_name_ << "If> iface) { " << endl;
+  if (!extends.empty()) {
+    f_header_ <<
+      indent() << "  " << extends << "Multiface::add(iface);" << endl;
+  }
+  f_header_ <<
+    indent() << "  ifaces_.push_back(iface);" << endl <<
+    indent() << "}" << endl;
   indent_down();
 
   f_header_ <<
@@ -572,7 +628,7 @@
     const vector<t_field*>& args = arglist->get_members();
     vector<t_field*>::const_iterator a_iter;
 
-    string call = string("_ifaces[i]->") + (*f_iter)->get_name() + "(";
+    string call = string("ifaces_[i]->") + (*f_iter)->get_name() + "(";
     bool first = true;
     for (a_iter = args.begin(); a_iter != args.end(); ++a_iter) {
       if (first) {
@@ -588,7 +644,7 @@
       indent() << function_signature(*f_iter) << " {" << endl;
     indent_up();
     f_header_ <<
-      indent() << "uint32_t sz = _ifaces.size();" << endl <<
+      indent() << "uint32_t sz = ifaces_.size();" << endl <<
       indent() << "for (uint32_t i = 0; i < sz; ++i) {" << endl;
     if (!(*f_iter)->get_returntype()->is_void()) {
       f_header_ <<
@@ -623,37 +679,53 @@
  * @param tservice The service to generate a server for.
  */
 void t_cpp_generator::generate_service_client(t_service* tservice) {
+  string extends = "";
+  string extends_client = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    extends_client = ", public " + extends + "Client";
+  }
+
   // Generate the header portion
   f_header_ <<
     "class " << service_name_ << "Client : " <<
-    "public " << service_name_ << "If {" << endl <<
+    "virtual public " << service_name_ << "If" <<
+    extends_client << " {" << endl <<
     " public:" << endl; 
 
   indent_up();
   f_header_ <<
-    indent() << service_name_ << "Client(boost::shared_ptr<facebook::thrift::transport::TTransport> trans, boost::shared_ptr<const facebook::thrift::protocol::TProtocol> prot) : " << endl <<
-    indent() << "  _itrans(trans)," << endl <<
-    indent() << "  _otrans(trans)," << endl <<
-    indent() << "  _iprot(prot)," << endl <<
-    indent() << "  _oprot(prot) {}" << endl;
+    indent() << service_name_ << "Client(boost::shared_ptr<facebook::thrift::protocol::TProtocol> prot) : " << endl;
+  if (extends.empty()) {
+    f_header_ <<
+      indent() << "  iprot_(prot)," << endl <<
+      indent() << "  oprot_(prot) {}" << endl;
+  } else {
+    f_header_ <<
+      indent() << "  " << extends << "Client(prot, prot) {}" << endl;
+  }
 
   f_header_ <<
-    indent() << service_name_ << "Client(boost::shared_ptr<facebook::thrift::transport::TTransport> itrans, boost::shared_ptr<facebook::thrift::transport::TTransport> otrans, boost::shared_ptr<const facebook::thrift::protocol::TProtocol> iprot, boost::shared_ptr<const facebook::thrift::protocol::TProtocol> oprot) : " << endl <<
-    indent() << "  _itrans(itrans)," << endl <<
-    indent() << "  _otrans(otrans)," << endl <<
-    indent() << "  _iprot(iprot)," << endl <<
-    indent() << "  _oprot(oprot) {}" << endl;
+    indent() << service_name_ << "Client(boost::shared_ptr<facebook::thrift::protocol::TProtocol> iprot, boost::shared_ptr<facebook::thrift::protocol::TProtocol> oprot) : " << endl;
+  if (extends.empty()) {
+    f_header_ <<
+      indent() << "  iprot_(iprot)," << endl <<
+      indent() << "  oprot_(oprot) {}" << endl;
+  } else {
+    f_header_ <<
+      indent() << "  " << extends << "Client(iprot, oprot) {}" << endl;
+  }
 
   vector<t_function*> functions = tservice->get_functions();
   vector<t_function*>::const_iterator f_iter; 
   for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    t_function send_function(g_program->get_void_type(),
+    t_function send_function(g_type_void,
                              string("send_") + (*f_iter)->get_name(),
                              (*f_iter)->get_arglist());
     indent(f_header_) << function_signature(*f_iter) << ";" << endl;
     indent(f_header_) << function_signature(&send_function) << ";" << endl;
     if (!(*f_iter)->is_async()) {
-      t_struct noargs;
+      t_struct noargs(program_);
       t_function recv_function((*f_iter)->get_returntype(),
                                string("recv_") + (*f_iter)->get_name(),
                                &noargs);
@@ -662,15 +734,15 @@
   }
   indent_down();
   
-  f_header_ <<
-    " protected:" << endl;
-  indent_up();
-  f_header_ <<
-    indent() << "boost::shared_ptr<facebook::thrift::transport::TTransport> _itrans;" << endl <<
-    indent() << "boost::shared_ptr<facebook::thrift::transport::TTransport> _otrans;" << endl <<
-    indent() << "boost::shared_ptr<const facebook::thrift::protocol::TProtocol>  _iprot;"  << endl <<
-    indent() << "boost::shared_ptr<const facebook::thrift::protocol::TProtocol>  _oprot;"  << endl;
-  indent_down();  
+  if (extends.empty()) {
+    f_header_ <<
+      " protected:" << endl;
+    indent_up();
+    f_header_ <<
+      indent() << "boost::shared_ptr<facebook::thrift::protocol::TProtocol> iprot_;"  << endl <<
+      indent() << "boost::shared_ptr<facebook::thrift::protocol::TProtocol> oprot_;"  << endl;
+    indent_down();  
+  }
 
   f_header_ <<
     "};" << endl <<
@@ -718,7 +790,7 @@
     f_service_ << endl;
 
     // Function for sending
-    t_function send_function(g_program->get_void_type(),
+    t_function send_function(g_type_void,
                              string("send_") + (*f_iter)->get_name(),
                              (*f_iter)->get_arglist());
 
@@ -734,27 +806,27 @@
     // Serialize the request
     f_service_ <<
       indent() << "int32_t cseqid = 0;" << endl <<
-      indent() << "_oprot->writeMessageBegin(_otrans, \"" << (*f_iter)->get_name() << "\", facebook::thrift::protocol::T_CALL, cseqid);" << endl <<
+      indent() << "oprot_->writeMessageBegin(\"" << (*f_iter)->get_name() << "\", facebook::thrift::protocol::T_CALL, cseqid);" << endl <<
       endl <<
-      indent() << argsname << " __args;" << endl;
+      indent() << argsname << " args;" << endl;
     
     for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
       f_service_ <<
-        indent() << "__args." << (*fld_iter)->get_name() << " = " << (*fld_iter)->get_name() << ";" << endl;
+        indent() << "args." << (*fld_iter)->get_name() << " = " << (*fld_iter)->get_name() << ";" << endl;
     }
       
     f_service_ <<
-      indent() << "__args.write(_oprot, _otrans);" << endl <<
+      indent() << "args.write(oprot_);" << endl <<
       endl <<
-      indent() << "_oprot->writeMessageEnd(_otrans);" << endl <<
-      indent() << "_otrans->flush();" << endl;
+      indent() << "oprot_->writeMessageEnd();" << endl <<
+      indent() << "oprot_->getOutputTransport()->flush();" << endl;
        
     scope_down(f_service_);
     f_service_ << endl;
 
     // Generate recv function only if not an async function
     if (!(*f_iter)->is_async()) {
-      t_struct noargs;
+      t_struct noargs(program_);
       t_function recv_function((*f_iter)->get_returntype(),
                                string("recv_") + (*f_iter)->get_name(),
                                &noargs);
@@ -769,7 +841,7 @@
         indent() << "std::string fname;" << endl <<
         indent() << "facebook::thrift::protocol::TMessageType mtype;" << endl <<
         endl <<
-        indent() << "_iprot->readMessageBegin(_itrans, fname, mtype, rseqid);" << endl <<
+        indent() << "iprot_->readMessageBegin(fname, mtype, rseqid);" << endl <<
         indent() << "if (mtype != facebook::thrift::protocol::T_REPLY || fname.compare(\"" << (*f_iter)->get_name() << "\") != 0) {" << endl;
       indent_up();
         f_service_ <<
@@ -778,16 +850,16 @@
 
       f_service_ <<
         indent() << "}" << endl <<
-        indent() << resultname << " __result;" << endl <<
-        indent() << "__result.read(_iprot, _itrans);" << endl <<
-        indent() << "_iprot->readMessageEnd(_itrans);" << endl <<
+        indent() << resultname << " result;" << endl <<
+        indent() << "result.read(iprot_);" << endl <<
+        indent() << "iprot_->readMessageEnd();" << endl <<
         endl;
 
       // Careful, only look for _result if not a void function
       if (!(*f_iter)->get_returntype()->is_void()) {
         f_service_ <<
-          indent() << "if (__result.__isset.success) {" << endl <<
-          indent() << "  return __result.success;" << endl <<
+          indent() << "if (result.__isset.success) {" << endl <<
+          indent() << "  return result.success;" << endl <<
           indent() << "}" << endl;
       }
 
@@ -796,8 +868,8 @@
       vector<t_field*>::const_iterator x_iter;
       for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
         f_service_ <<
-          indent() << "if (__result.__isset." << (*x_iter)->get_name() << ") {" << endl <<
-          indent() << "  throw __result." << (*x_iter)->get_name() << ";" << endl <<
+          indent() << "if (result.__isset." << (*x_iter)->get_name() << ") {" << endl <<
+          indent() << "  throw result." << (*x_iter)->get_name() << ";" << endl <<
           indent() << "}" << endl;
       }
 
@@ -822,43 +894,53 @@
  *
  * @param tservice The service to generate a server for.
  */
-void t_cpp_generator::generate_service_server(t_service* tservice) {
+void t_cpp_generator::generate_service_processor(t_service* tservice) {
   // Generate the dispatch methods
   vector<t_function*> functions = tservice->get_functions();
   vector<t_function*>::iterator f_iter; 
 
+  string extends = "";
+  string extends_processor = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    extends_processor = ", public " + extends + "Processor";
+  }
+
   // Generate the header portion
   f_header_ <<
     "class " << service_name_ << "Processor : " <<
-    "public facebook::thrift::TProcessor {" << endl;
+    "virtual public facebook::thrift::TProcessor" << 
+    extends_processor << " {" << endl;
 
   // Protected data members
   f_header_ <<
     " protected:" << endl;
   indent_up();
   f_header_ <<
-    indent() << "boost::shared_ptr<" << service_name_ << "If> _iface;" << endl <<
-    indent() << "boost::shared_ptr<const facebook::thrift::protocol::TProtocol> _iprot;" << endl <<
-    indent() << "boost::shared_ptr<const facebook::thrift::protocol::TProtocol> _oprot;" << endl <<
-    indent() << "std::map<std::string, void (" << service_name_ << "Processor::*)(int32_t, boost::shared_ptr<facebook::thrift::transport::TTransport>, boost::shared_ptr<facebook::thrift::transport::TTransport>)> _processMap;" << endl;
+    indent() << "boost::shared_ptr<" << service_name_ << "If> iface_;" << endl;
+  f_header_ <<
+    indent() << "virtual bool process_fn(boost::shared_ptr<facebook::thrift::protocol::TProtocol> iprot, boost::shared_ptr<facebook::thrift::protocol::TProtocol> oprot, std::string& fname, int32_t seqid);" << endl;
   indent_down();
 
   // Process function declarations
   f_header_ <<
     " private:" << endl;
   indent_up();
+  f_header_ <<
+    indent() << "std::map<std::string, void (" << service_name_ << "Processor::*)(int32_t, boost::shared_ptr<facebook::thrift::protocol::TProtocol>, boost::shared_ptr<facebook::thrift::protocol::TProtocol>)> processMap_;" << endl;
   for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
     indent(f_header_) <<
-      "void process_" << (*f_iter)->get_name() << "(int32_t seqid, boost::shared_ptr<facebook::thrift::transport::TTransport> _itrans, boost::shared_ptr<facebook::thrift::transport::TTransport> _otrans);" << endl;
+      "void process_" << (*f_iter)->get_name() << "(int32_t seqid, boost::shared_ptr<facebook::thrift::protocol::TProtocol> iprot, boost::shared_ptr<facebook::thrift::protocol::TProtocol> oprot);" << endl;
   }
   indent_down();
 
   indent_up();
   string declare_map = "";
   indent_up();
+
   for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
     declare_map += indent();
-    declare_map += "_processMap[\"";
+    declare_map += "processMap_[\"";
     declare_map += (*f_iter)->get_name();
     declare_map += "\"] = &";
     declare_map += service_name_;
@@ -870,20 +952,20 @@
 
   f_header_ << 
     " public: " << endl <<
-    indent() << service_name_ << "Processor(boost::shared_ptr<" << service_name_ << "If> iface, boost::shared_ptr<const facebook::thrift::protocol::TProtocol> prot) :" << endl <<
-    indent() << "  _iface(iface)," << endl <<
-    indent() << "  _iprot(prot)," << endl <<
-    indent() << "  _oprot(prot) {" << endl <<
-    declare_map <<
-    indent() << "}" << endl <<
-    indent() << service_name_ << "Processor(boost::shared_ptr<" << service_name_ << "If> iface, boost::shared_ptr<const facebook::thrift::protocol::TProtocol> iprot, boost::shared_ptr<const facebook::thrift::protocol::TProtocol> oprot) :" << endl <<
-    indent() << "  _iface(iface)," << endl <<
-    indent() << "  _iprot(iprot)," << endl <<
-    indent() << "  _oprot(oprot) {" << endl <<
+    indent() << service_name_ << "Processor(boost::shared_ptr<" << service_name_ << "If> iface) :" << endl;
+  if (extends.empty()) {
+    f_header_ <<
+      indent() << "  iface_(iface) {" << endl;
+  } else {
+    f_header_ <<
+      indent() << "  " << extends << "Processor(iface)," << endl <<
+      indent() << "  iface_(iface) {" << endl;
+  }
+  f_header_ <<
     declare_map <<
     indent() << "}" << endl <<
     endl <<
-    indent() << "bool process(boost::shared_ptr<facebook::thrift::transport::TTransport> _itrans, boost::shared_ptr<facebook::thrift::transport::TTransport> _otrans);" << endl <<
+    indent() << "virtual bool process(boost::shared_ptr<facebook::thrift::protocol::TProtocol> iprot, boost::shared_ptr<facebook::thrift::protocol::TProtocol> oprot);" << endl <<
     indent() << "virtual ~" << service_name_ << "Processor() {}" << endl;
   indent_down();
   f_header_ <<
@@ -891,7 +973,7 @@
 
   // Generate the server implementation
   f_service_ <<
-    "bool " << service_name_ << "Processor::process(boost::shared_ptr<facebook::thrift::transport::TTransport> itrans, boost::shared_ptr<facebook::thrift::transport::TTransport> otrans) {" << endl;
+    "bool " << service_name_ << "Processor::process(boost::shared_ptr<facebook::thrift::protocol::TProtocol> iprot, boost::shared_ptr<facebook::thrift::protocol::TProtocol> oprot) {" << endl;
   indent_up();
 
   f_service_ <<
@@ -900,21 +982,39 @@
     indent() << "facebook::thrift::protocol::TMessageType mtype;" << endl <<
     indent() << "int32_t seqid;" << endl <<
     endl <<
-    indent() << "_iprot->readMessageBegin(itrans, fname, mtype, seqid);" << endl <<
+    indent() << "iprot->readMessageBegin(fname, mtype, seqid);" << endl <<
     endl <<
     indent() << "if (mtype != facebook::thrift::protocol::T_CALL) {" << endl <<
     indent() << "  throw facebook::thrift::Exception(\"Unexpected message type\");" << endl <<
     indent() << "}" << endl <<
+    endl <<
+    indent() << "return process_fn(iprot, oprot, fname, seqid);" <<
     endl;
 
+  indent_down();
+  f_service_ <<
+    indent() << "}" << endl <<
+    endl;
+
+  f_service_ <<
+    "bool " << service_name_ << "Processor::process_fn(boost::shared_ptr<facebook::thrift::protocol::TProtocol> iprot, boost::shared_ptr<facebook::thrift::protocol::TProtocol> oprot, std::string& fname, int32_t seqid) {" << endl;
+  indent_up();
+    
   // HOT: member function pointer map
   f_service_ <<
-    indent() << "std::map<std::string, void (" << service_name_ << "Processor::*)(int32_t, boost::shared_ptr<facebook::thrift::transport::TTransport>, boost::shared_ptr<facebook::thrift::transport::TTransport>)>::iterator pfn;" << endl <<
-    indent() << "pfn = _processMap.find(fname);" << endl <<
-    indent() << "if (pfn == _processMap.end()) {" << endl <<
-    indent() << "  throw facebook::thrift::Exception(\"Unknown function name: '\"+fname+\"'\");" << endl <<
+    indent() << "std::map<std::string, void (" << service_name_ << "Processor::*)(int32_t, boost::shared_ptr<facebook::thrift::protocol::TProtocol>, boost::shared_ptr<facebook::thrift::protocol::TProtocol>)>::iterator pfn;" << endl <<
+    indent() << "pfn = processMap_.find(fname);" << endl <<
+    indent() << "if (pfn == processMap_.end()) {" << endl;
+  if (extends.empty()) {
+    f_service_ <<
+      indent() << "  throw facebook::thrift::Exception(\"Unknown function name: '\"+fname+\"'\");" << endl;
+  } else {
+    f_service_ <<
+      indent() << "  return " << extends << "Processor::process_fn(iprot, oprot, fname, seqid);" << endl;
+  }
+  f_service_ <<
     indent() << "} else {" << endl <<
-    indent() << "  (this->*(pfn->second))(seqid, itrans, otrans);" << endl <<
+    indent() << "  (this->*(pfn->second))(seqid, iprot, oprot);" << endl <<
     indent() << "}" << endl;  
 
   // Read end of args field, the T_STOP, and the struct close
@@ -942,7 +1042,7 @@
     return;
   }
 
-  t_struct result(tfunction->get_name() + "_result");
+  t_struct result(program_, tfunction->get_name() + "_result");
   t_field success(tfunction->get_returntype(), "success", 0);
   if (!tfunction->get_returntype()->is_void()) {
     result.append(&success);
@@ -971,17 +1071,17 @@
   f_service_ <<
     "void " << tservice->get_name() << "Processor::" <<
     "process_" << tfunction->get_name() <<
-    "(int32_t seqid, boost::shared_ptr<facebook::thrift::transport::TTransport> itrans, boost::shared_ptr<facebook::thrift::transport::TTransport> otrans)" << endl;
+    "(int32_t seqid, boost::shared_ptr<facebook::thrift::protocol::TProtocol> iprot, boost::shared_ptr<facebook::thrift::protocol::TProtocol> oprot)" << endl;
   scope_up(f_service_);
 
   string argsname = tfunction->get_name() + "_args";
   string resultname = tfunction->get_name() + "_result";
 
   f_service_ <<
-    indent() << argsname << " __args;" << endl <<
-    indent() << "__args.read(_iprot, itrans);" << endl <<
-    indent() << "_iprot->readMessageEnd(itrans);" << endl <<
-    indent() << "itrans->readEnd();" << endl <<
+    indent() << argsname << " args;" << endl <<
+    indent() << "args.read(iprot);" << endl <<
+    indent() << "iprot->readMessageEnd();" << endl <<
+    indent() << "iprot->getInputTransport()->readEnd();" << endl <<
     endl;
 
   t_struct* xs = tfunction->get_xceptions();
@@ -991,7 +1091,7 @@
   // Declare result
   if (!tfunction->is_async()) {
     f_service_ <<
-      indent() << resultname << " __result;" << endl;
+      indent() << resultname << " result;" << endl;
   }
 
   // Try block for functions with exceptions
@@ -1008,10 +1108,10 @@
 
   f_service_ << indent();
   if (!tfunction->is_async() && !tfunction->get_returntype()->is_void()) {
-    f_service_ << "__result.success = ";    
+    f_service_ << "result.success = ";    
   }
   f_service_ <<
-    "_iface->" << tfunction->get_name() << "(";
+    "iface_->" << tfunction->get_name() << "(";
   bool first = true;
   for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
     if (first) {
@@ -1019,14 +1119,14 @@
     } else {
       f_service_ << ", ";
     }
-    f_service_ << "__args." << (*f_iter)->get_name();
+    f_service_ << "args." << (*f_iter)->get_name();
   }
   f_service_ << ");" << endl;
 
   // Set isset on success field
   if (!tfunction->is_async() && !tfunction->get_returntype()->is_void()) {
     f_service_ <<
-      indent() << "__result.__isset.success = true;" << endl;
+      indent() << "result.__isset.success = true;" << endl;
   }
 
   if (!tfunction->is_async() && xceptions.size() > 0) {
@@ -1037,8 +1137,8 @@
       if (!tfunction->is_async()) {
         indent_up();
         f_service_ <<
-          indent() << "__result." << (*x_iter)->get_name() << " = " << (*x_iter)->get_name() << ";" << endl <<
-          indent() << "__result.__isset." << (*x_iter)->get_name() << " = true;" << endl;
+          indent() << "result." << (*x_iter)->get_name() << " = " << (*x_iter)->get_name() << ";" << endl <<
+          indent() << "result.__isset." << (*x_iter)->get_name() << " = true;" << endl;
         indent_down();
         f_service_ << indent() << "}";
       } else {
@@ -1061,11 +1161,11 @@
   // Serialize the result into a struct
   f_service_ <<
     endl <<
-    indent() << "_oprot->writeMessageBegin(otrans, \"" << tfunction->get_name() << "\", facebook::thrift::protocol::T_REPLY, seqid);" << endl <<
-    indent() << "__result.write(_oprot, otrans);" << endl <<
-    indent() << "_oprot->writeMessageEnd(otrans);" << endl <<
-    indent() << "otrans->flush();" << endl <<
-    indent() << "otrans->writeEnd();" << endl;
+    indent() << "oprot->writeMessageBegin(\"" << tfunction->get_name() << "\", facebook::thrift::protocol::T_REPLY, seqid);" << endl <<
+    indent() << "result.write(oprot);" << endl <<
+    indent() << "oprot->writeMessageEnd();" << endl <<
+    indent() << "oprot->getOutputTransport()->flush();" << endl <<
+    indent() << "oprot->getOutputTransport()->writeEnd();" << endl;
     
   // Close function
   scope_down(f_service_);
@@ -1073,6 +1173,92 @@
 }
 
 /**
+ * Generates a skeleton file of a server
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_cpp_generator::generate_service_skeleton(t_service* tservice) {
+  string svcname = tservice->get_name();
+  
+  // Service implementation file includes
+  string f_skeleton_name = string(T_CPP_DIR)+"/"+svcname+"_server.skeleton.cpp";
+
+  string ns = namespace_prefix(tservice->get_program()->get_cpp_namespace());
+
+  ofstream f_skeleton;
+  f_skeleton.open(f_skeleton_name.c_str());
+  f_skeleton <<
+    "// This autogenerated skeleton file illustrates how to build a server." << endl <<
+    "// You should copy it to another filename to avoid overwriting it." << endl <<
+    endl <<
+    "#include \"" << svcname << ".h\"" << endl << 
+    "#include <protocol/TBinaryProtocol.h>" << endl <<
+    "#include <server/TSimpleServer.h>" << endl <<
+    "#include <transport/TServerSocket.h>" << endl <<
+    "#include <transport/TBufferedTransportFactory.h>" << endl <<
+    endl <<
+    "using namespace facebook::thrift;" << endl <<
+    "using namespace facebook::thrift::protocol;" << endl <<
+    "using namespace facebook::thrift::transport;" << endl <<
+    "using namespace facebook::thrift::server;" << endl <<
+    endl;
+  
+  if (!ns.empty()) {
+    f_skeleton <<
+      "using namespace " << string(ns, 0, ns.size()-2) << ";" << endl <<
+      endl;
+  }
+
+  f_skeleton <<
+    "class " << svcname << "Handler : public " << svcname << "If {" << endl <<
+    " public:" << endl;
+  indent_up();
+  f_skeleton <<
+    indent() << svcname << "Handler() {" << endl <<
+    indent() << "  // Your initialization goes here" << endl <<
+    indent() << "}" << endl <<
+    endl;
+
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    f_skeleton <<
+      indent() << function_signature(*f_iter) << " {" << endl <<
+      indent() << "  // Your implementation goes here" << endl <<
+      indent() << "  printf(\"" << (*f_iter)->get_name() << "\\n\");" << endl <<
+      indent() << "}" << endl <<
+      endl;
+  }
+
+  indent_down();
+  f_skeleton <<
+    "};" << endl <<
+    endl;
+
+  f_skeleton <<
+    indent() << "int main(int argc, char **argv) {" << endl;
+  indent_up();
+  f_skeleton <<
+    indent() << "int port = 9090;" << endl <<
+    indent() << "shared_ptr<" << svcname << "Handler> handler(new " << svcname << "Handler());" << endl <<
+    indent() << "shared_ptr<TProcessor> processor(new " << svcname << "Processor(handler));" << endl <<
+    indent() << "shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));" << endl <<
+    indent() << "shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());" << endl <<
+    indent() << "shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());" << endl <<
+    endl <<
+    indent() << "TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);" << endl <<
+    indent() << "server.serve();" << endl <<
+    indent() << "return 0;" << endl;
+  indent_down();
+  f_skeleton <<
+    "}" << endl <<
+    endl;
+  
+  // Close the files
+  f_skeleton.close();
+}
+
+/**
  * Deserializes a field of any type.
  */
 void t_cpp_generator::generate_deserialize_field(ofstream& out,
@@ -1106,31 +1292,31 @@
           name;
         break;
       case t_base_type::TYPE_STRING:
-        out << "readString(itrans, " << name << ");";
+        out << "readString(" << name << ");";
         break;
       case t_base_type::TYPE_BOOL:
-        out << "readBool(itrans, " << name << ");";
+        out << "readBool(" << name << ");";
         break;
       case t_base_type::TYPE_BYTE:
-        out << "readByte(itrans, " << name << ");";
+        out << "readByte(" << name << ");";
         break;
       case t_base_type::TYPE_I16:
-        out << "readI16(itrans, " << name << ");";
+        out << "readI16(" << name << ");";
         break;
       case t_base_type::TYPE_I32:
-        out << "readI32(itrans, " << name << ");";
+        out << "readI32(" << name << ");";
         break;
       case t_base_type::TYPE_I64:
-        out << "readI64(itrans, " << name << ");";
+        out << "readI64(" << name << ");";
         break;
       case t_base_type::TYPE_DOUBLE:
-        out << "readDouble(itrans, " << name << ");";
+        out << "readDouble(" << name << ");";
         break;
       default:
         throw "compiler error: no C++ reader for base type " + tbase + name;
       }
     } else if (type->is_enum()) {
-      out << "readI32(itrans, (int32_t&)" << name << ");";
+      out << "readI32((int32_t&)" << name << ");";
     }
     out <<
       endl;
@@ -1150,7 +1336,7 @@
                                                   t_struct* tstruct,
                                                   string prefix) {
   indent(out) <<
-    "xfer += " << prefix << ".read(iprot, itrans);" << endl;
+    "xfer += " << prefix << ".read(iprot);" << endl;
 }
 
 void t_cpp_generator::generate_deserialize_container(ofstream& out,
@@ -1171,17 +1357,17 @@
     out <<
       indent() << "facebook::thrift::protocol::TType " << ktype << ";" << endl <<
       indent() << "facebook::thrift::protocol::TType " << vtype << ";" << endl <<
-      indent() << "iprot->readMapBegin(itrans, " <<
+      indent() << "iprot->readMapBegin(" <<
                    ktype << ", " << vtype << ", " << size << ");" << endl;
   } else if (ttype->is_set()) {
     out <<
       indent() << "facebook::thrift::protocol::TType " << etype << ";" << endl <<
-      indent() << "iprot->readSetBegin(itrans, " <<
+      indent() << "iprot->readSetBegin(" <<
                    etype << ", " << size << ");" << endl;
   } else if (ttype->is_list()) {
     out <<
       indent() << "facebook::thrift::protocol::TType " << etype << ";" << endl <<
-      indent() << "iprot->readListBegin(itrans, " <<
+      indent() << "iprot->readListBegin(" <<
                    etype << ", " << size << ");" << endl;
   }
 
@@ -1206,11 +1392,11 @@
 
   // Read container end
   if (ttype->is_map()) {
-    indent(out) << "iprot->readMapEnd(itrans);" << endl;
+    indent(out) << "iprot->readMapEnd();" << endl;
   } else if (ttype->is_set()) {
-    indent(out) << "iprot->readSetEnd(itrans);" << endl;
+    indent(out) << "iprot->readSetEnd();" << endl;
   } else if (ttype->is_list()) {
-    indent(out) << "iprot->readListEnd(itrans);" << endl;
+    indent(out) << "iprot->readListEnd();" << endl;
   }
 
   scope_down(out);
@@ -1312,31 +1498,31 @@
           "compiler error: cannot serialize void field in a struct: " + name;
         break;
       case t_base_type::TYPE_STRING:
-        out << "writeString(otrans, " << name << ");";
+        out << "writeString(" << name << ");";
         break;
       case t_base_type::TYPE_BOOL:
-        out << "writeBool(otrans, " << name << ");";
+        out << "writeBool(" << name << ");";
         break;
       case t_base_type::TYPE_BYTE:
-        out << "writeByte(otrans, " << name << ");";
+        out << "writeByte(" << name << ");";
         break;
       case t_base_type::TYPE_I16:
-        out << "writeI16(otrans, " << name << ");";
+        out << "writeI16(" << name << ");";
         break;
       case t_base_type::TYPE_I32:
-        out << "writeI32(otrans, " << name << ");";
+        out << "writeI32(" << name << ");";
         break;
       case t_base_type::TYPE_I64:
-        out << "writeI64(otrans, " << name << ");";
+        out << "writeI64(" << name << ");";
         break;
       case t_base_type::TYPE_DOUBLE:
-        out << "writeDouble(otrans, " << name << ");";
+        out << "writeDouble(" << name << ");";
         break;
       default:
         throw "compiler error: no C++ writer for base type " + tbase + name;
       }
     } else if (type->is_enum()) {
-      out << "writeI32(otrans, (int32_t)" << name << ");";
+      out << "writeI32((int32_t)" << name << ");";
     }
     out << endl;
   } else {
@@ -1357,7 +1543,7 @@
                                                 t_struct* tstruct,
                                                 string prefix) {
   indent(out) <<
-    "xfer += " << prefix << ".write(oprot, otrans);" << endl;
+    "xfer += " << prefix << ".write(oprot);" << endl;
 }
 
 void t_cpp_generator::generate_serialize_container(ofstream& out,
@@ -1367,18 +1553,18 @@
   
   if (ttype->is_map()) {
     indent(out) <<
-      "xfer += oprot->writeMapBegin(otrans, " <<
+      "xfer += oprot->writeMapBegin(" <<
       type_to_enum(((t_map*)ttype)->get_key_type()) << ", " <<
       type_to_enum(((t_map*)ttype)->get_val_type()) << ", " <<
       prefix << ".size());" << endl;
   } else if (ttype->is_set()) {
     indent(out) <<
-      "xfer += oprot->writeSetBegin(otrans, " <<
+      "xfer += oprot->writeSetBegin(" <<
       type_to_enum(((t_set*)ttype)->get_elem_type()) << ", " <<
       prefix << ".size());" << endl;
   } else if (ttype->is_list()) {
     indent(out) <<
-      "xfer += oprot->writeListBegin(otrans, " <<
+      "xfer += oprot->writeListBegin(" <<
       type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " <<
       prefix << ".size());" << endl;
   }
@@ -1399,13 +1585,13 @@
     
   if (ttype->is_map()) {
     indent(out) <<
-      "xfer += oprot->writeMapEnd(otrans);" << endl;
+      "xfer += oprot->writeMapEnd();" << endl;
   } else if (ttype->is_set()) {
     indent(out) <<
-      "xfer += oprot->writeSetEnd(otrans);" << endl;
+      "xfer += oprot->writeSetEnd();" << endl;
   } else if (ttype->is_list()) {
     indent(out) <<
-      "xfer += oprot->writeListEnd(otrans);" << endl;
+      "xfer += oprot->writeListEnd();" << endl;
   }
 
   scope_down(out);  
@@ -1446,6 +1632,29 @@
 }
 
 /**
+ * Makes a :: prefix for a namespace
+ *
+ * @param ns The namepsace, w/ periods in it
+ * @return Namespaces
+ */
+string t_cpp_generator::namespace_prefix(string ns) {
+  if (ns.size() == 0) {
+    return "";
+  }
+  string result = "";
+  string::size_type loc;
+  while ((loc = ns.find(".")) != string::npos) {
+    result += ns.substr(0, loc);
+    result += "::";
+    ns = ns.substr(loc+1);
+  }
+  if (ns.size() > 0) {
+    result += ns + "::";
+  }
+  return result;  
+}
+
+/**
  * Opens namespace.
  *
  * @param ns The namepsace, w/ periods in it
@@ -1523,6 +1732,14 @@
     return "std::vector<" + type_name(tlist->get_elem_type()) + "> ";
   }
 
+  // Check if it needs to be namespaced
+  t_program* program = ttype->get_program();
+  if (program != NULL && program != program_) {
+    return
+      namespace_prefix(program->get_cpp_namespace()) +
+      ttype->get_name();
+  }
+
   return ttype->get_name();
 }
 
diff --git a/compiler/cpp/src/generate/t_cpp_generator.h b/compiler/cpp/src/generate/t_cpp_generator.h
index 37c36a1..45cbdac 100644
--- a/compiler/cpp/src/generate/t_cpp_generator.h
+++ b/compiler/cpp/src/generate/t_cpp_generator.h
@@ -18,14 +18,15 @@
  */
 class t_cpp_generator : public t_oop_generator {
  public:
-  t_cpp_generator() {}
+  t_cpp_generator(t_program* program) :
+    t_oop_generator(program) {}
 
   /**
    * Init and close methods
    */
 
-  void init_generator(t_program *tprogram);
-  void close_generator(t_program *tprogram);
+  void init_generator();
+  void close_generator();
 
   /**
    * Program-level generation functions
@@ -49,7 +50,8 @@
   void generate_service_multiface (t_service* tservice);
   void generate_service_helpers   (t_service* tservice);
   void generate_service_client    (t_service* tservice);
-  void generate_service_server    (t_service* tservice);
+  void generate_service_processor (t_service* tservice);
+  void generate_service_skeleton  (t_service*  tservice);
   void generate_process_function  (t_service* tservice, t_function* tfunction);
   void generate_function_helpers  (t_function* tfunction);
 
@@ -109,6 +111,7 @@
    * Helper rendering functions
    */
 
+  std::string namespace_prefix(std::string ns);
   std::string namespace_open(std::string ns);
   std::string namespace_close(std::string ns);
   std::string type_name(t_type* ttype);
diff --git a/compiler/cpp/src/generate/t_generator.cc b/compiler/cpp/src/generate/t_generator.cc
index dc09ba1..30830d6 100644
--- a/compiler/cpp/src/generate/t_generator.cc
+++ b/compiler/cpp/src/generate/t_generator.cc
@@ -9,43 +9,40 @@
  * @param program The thrift program to compile into C++ source
  * @author Mark Slee <mcslee@facebook.com>
  */
-void t_generator::generate_program(t_program *tprogram) {
-  // Set program name
-  program_name_ = get_program_name(tprogram);
-
+void t_generator::generate_program() {
   // Initialize the generator
-  init_generator(tprogram);
+  init_generator();
 
   // Generate typedefs
-  vector<t_typedef*> typedefs = tprogram->get_typedefs();
+  vector<t_typedef*> typedefs = program_->get_typedefs();
   vector<t_typedef*>::iterator td_iter;
   for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) {
     generate_typedef(*td_iter);
   }
 
   // Generate enums
-  vector<t_enum*> enums = tprogram->get_enums();
+  vector<t_enum*> enums = program_->get_enums();
   vector<t_enum*>::iterator en_iter;
   for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) {
     generate_enum(*en_iter);
   }
 
   // Generate structs
-  vector<t_struct*> structs = tprogram->get_structs();
+  vector<t_struct*> structs = program_->get_structs();
   vector<t_struct*>::iterator st_iter;
   for (st_iter = structs.begin(); st_iter != structs.end(); ++st_iter) {
     generate_struct(*st_iter);
   }
 
   // Generate xceptions
-  vector<t_struct*> xceptions = tprogram->get_xceptions();
+  vector<t_struct*> xceptions = program_->get_xceptions();
   vector<t_struct*>::iterator x_iter;
   for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
     generate_xception(*x_iter);
   }
 
   // Generate services
-  vector<t_service*> services = tprogram->get_services();
+  vector<t_service*> services = program_->get_services();
   vector<t_service*>::iterator sv_iter;
   for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) {
     service_name_ = get_service_name(*sv_iter);
@@ -53,5 +50,5 @@
   }
 
   // Close the generator
-  close_generator(tprogram);
+  close_generator();
 }
diff --git a/compiler/cpp/src/generate/t_generator.h b/compiler/cpp/src/generate/t_generator.h
index 07eaf38..18a2247 100644
--- a/compiler/cpp/src/generate/t_generator.h
+++ b/compiler/cpp/src/generate/t_generator.h
@@ -15,8 +15,11 @@
  */
 class t_generator {
  public:
-  t_generator() {
+  t_generator(t_program* program) {
     tmp_ = 0;
+    indent_ = 0;
+    program_ = program;
+    program_name_ = get_program_name(program);
   }
 
   virtual ~t_generator() {}
@@ -26,7 +29,7 @@
    * and performs general actions. This is implemented by the base class and
    * should not be overwritten in the subclasses.
    */
-  void generate_program  (t_program*  tprogram);
+  void generate_program();
 
  protected:
 
@@ -35,8 +38,8 @@
    * steps at the beginning or end of code generation.
    */
 
-  virtual void init_generator    (t_program*  tprogram) {}
-  virtual void close_generator   (t_program*  tprogram) {}
+  virtual void init_generator() {}
+  virtual void close_generator() {}
 
   /**
    * Pure virtual methods implemented by the generator subclasses.
@@ -108,6 +111,11 @@
 
  protected:
   /**
+   * The program being generated
+   */
+  t_program* program_;
+
+  /**
    * Quick accessor for formatted program name that is currently being
    * generated.
    */
diff --git a/compiler/cpp/src/generate/t_java_generator.cc b/compiler/cpp/src/generate/t_java_generator.cc
index b99c748..1c43fdb 100644
--- a/compiler/cpp/src/generate/t_java_generator.cc
+++ b/compiler/cpp/src/generate/t_java_generator.cc
@@ -10,10 +10,10 @@
  *
  * @param tprogram The program to generate
  */
-void t_java_generator::init_generator(t_program* tprogram) {
+void t_java_generator::init_generator() {
   // Make output directory
   mkdir(T_JAVA_DIR, S_IREAD | S_IWRITE | S_IEXEC);
-  package_name_ = tprogram->get_namespace();
+  package_name_ = program_->get_java_package();
 }
 
 /**
@@ -22,7 +22,10 @@
  * @return String of the package, i.e. "package com.facebook.thriftdemo;"
  */
 string t_java_generator::java_package() {
-  return string("package ") + package_name_ + ";\n\n";
+  if (!package_name_.empty()) {
+    return string("package ") + package_name_ + ";\n\n";
+  }
+  return "";
 }
 
 /**
@@ -54,7 +57,7 @@
 /**
  * Nothing in Java
  */
-void t_java_generator::close_generator(t_program *tprogram) {}
+void t_java_generator::close_generator() {}
 
 /**
  * Generates a typedef. This is not done in Java, since it does
@@ -163,7 +166,7 @@
                                                        bool is_exception,
                                                        bool in_class,
                                                        bool is_result) {
-  out <<
+  indent(out) <<
     "public " << (in_class ? "static " : "") << "class " << tstruct->get_name() << " ";
   
   if (is_exception) {
@@ -441,8 +444,15 @@
  * @param tservice The service to generate a header definition for
  */
 void t_java_generator::generate_service_interface(t_service* tservice) {
+  string extends = "";
+  string extends_iface = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    extends_iface = " extends " + extends + ".Iface";
+  }
+
   f_service_ <<
-    indent() << "public interface Iface {" << endl;
+    indent() << "public interface Iface" << extends_iface << " {" << endl;
   indent_up();
   vector<t_function*> functions = tservice->get_functions();
   vector<t_function*>::iterator f_iter; 
@@ -477,8 +487,15 @@
  * @param tservice The service to generate a server for.
  */
 void t_java_generator::generate_service_client(t_service* tservice) {
-  f_service_ <<
-    "public static class Client implements Iface {" << endl;
+  string extends = "";
+  string extends_client = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    extends_client = " extends " + extends + ".Client";
+  }
+
+  indent(f_service_) <<
+    "public static class Client" << extends_client << " implements Iface {" << endl;
   indent_up();
 
   indent(f_service_) <<
@@ -493,22 +510,29 @@
     "public Client(TTransport itrans, TTransport otrans," <<
     " TProtocol iprot, TProtocol oprot)" << endl;
   scope_up(f_service_);
-  f_service_ <<
-    indent() << "_itrans = itrans;" << endl <<
-    indent() << "_otrans = otrans;" << endl <<
-    indent() << "_iprot = iprot;" << endl <<
-    indent() << "_oprot = oprot;" << endl;
+  if (extends.empty()) {
+    f_service_ <<
+      indent() << "_itrans = itrans;" << endl <<
+      indent() << "_otrans = otrans;" << endl <<
+      indent() << "_iprot = iprot;" << endl <<
+      indent() << "_oprot = oprot;" << endl;
+  } else {
+    f_service_ <<
+      indent() << "super(itrans, otrans, iprot, oprot);" << endl;
+  }
   scope_down(f_service_);
   f_service_ << endl;
  
-  f_service_ <<
-    indent() << "private TTransport _itrans;" << endl <<
-    indent() << "private TTransport _otrans;" << endl <<
-    indent() << "private TProtocol  _iprot;"  << endl <<
-    indent() << "private TProtocol  _oprot;"  << endl <<
-    endl <<
-    indent() << "private int _seqid;" << endl <<
-    endl;
+  if (extends.empty()) {
+    f_service_ <<
+      indent() << "protected TTransport _itrans;" << endl <<
+      indent() << "protected TTransport _otrans;" << endl <<
+      indent() << "protected TProtocol  _iprot;"  << endl <<
+      indent() << "protected TProtocol  _oprot;"  << endl <<
+      endl <<
+      indent() << "protected int _seqid;" << endl <<
+      endl;
+  }
 
   // Generate client method implementations
   vector<t_function*> functions = tservice->get_functions();
@@ -551,7 +575,7 @@
     scope_down(f_service_);
     f_service_ << endl;
       
-    t_function send_function(g_program->get_void_type(),
+    t_function send_function(g_type_void,
                              string("send_") + (*f_iter)->get_name(),
                              (*f_iter)->get_arglist());
 
@@ -583,7 +607,7 @@
     if (!(*f_iter)->is_async()) {
       string resultname = (*f_iter)->get_name() + "_result";
 
-      t_struct noargs;
+      t_struct noargs(program_);
       t_function recv_function((*f_iter)->get_returntype(),
                                string("recv_") + (*f_iter)->get_name(),
                                &noargs,
@@ -635,7 +659,7 @@
   }
 
   indent_down();
-  f_service_ <<
+  indent(f_service_) <<
     "}" << endl;
 }
 
@@ -649,9 +673,17 @@
   vector<t_function*> functions = tservice->get_functions();
   vector<t_function*>::iterator f_iter; 
 
+  // Extends stuff
+  string extends = "";
+  string extends_processor = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    extends_processor = " extends " + extends + ".Processor";
+  }
+
   // Generate the header portion
-  f_service_ <<
-    "public static class Processor implements TProcessor {" << endl;
+  indent(f_service_) <<
+    "public static class Processor" << extends_processor << " implements TProcessor {" << endl;
   indent_up();
 
   indent(f_service_) <<
@@ -665,17 +697,48 @@
   indent(f_service_) <<
     "public Processor(Iface iface, TProtocol iprot, TProtocol oprot)" << endl;
   scope_up(f_service_);
+  if (extends.empty()) {
+    f_service_ <<
+      indent() << "_iprot = iprot;" << endl <<
+      indent() << "_oprot = oprot;" << endl;
+  } else {
+    f_service_ <<
+      indent() << "super(iface, iprot, oprot);" << endl;
+  }
   f_service_ <<
-    indent() << "_iface = iface;" << endl <<
-    indent() << "_iprot = iprot;" << endl <<
-    indent() << "_oprot = oprot;" << endl;
+    indent() << "_iface = iface;" << endl;
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    f_service_ <<
+      indent() << "_processMap.put(\"" << (*f_iter)->get_name() << "\", new " << (*f_iter)->get_name() << "());" << endl;
+  }
+  
   scope_down(f_service_);
   f_service_ << endl;
- 
+  
+  if (extends.empty()) {
+    f_service_ <<
+      indent() << "private static interface ProcessFunction {" << endl <<
+      indent() << "  public void process(int seqid, TTransport _itrans, TTransport _otrans) throws TException;" << endl <<
+      indent() << "}" << endl <<
+      endl;
+  }
+
   f_service_ <<
-    indent() << "private Iface _iface;" << endl <<
-    indent() << "private TProtocol _iprot;" << endl <<
-    indent() << "private TProtocol _oprot;" << endl << endl;
+    indent() << "private Iface _iface;" << endl;
+
+  if (extends.empty()) {
+    f_service_ <<
+      indent() << "protected final HashMap<String,ProcessFunction> _processMap = new HashMap<String,ProcessFunction>();" << endl;
+  }
+
+  if (extends.empty()) {
+    f_service_ <<
+      indent() << "protected TProtocol _iprot;" << endl <<
+      indent() << "protected TProtocol _oprot;" << endl;
+  }
+  
+  f_service_ << endl;
   
   // Generate the server implementation
   indent(f_service_) <<
@@ -683,34 +746,17 @@
   scope_up(f_service_);
 
   f_service_ <<
-    indent() << "TMessage _msg = _iprot.readMessageBegin(_itrans);" << endl;
+    indent() << "TMessage msg = _iprot.readMessageBegin(_itrans);" << endl;
 
   // TODO(mcslee): validate message, was the seqid etc. legit?
 
-  bool first = true;
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    if (!first) {
-      f_service_ << " else ";
-    } else {
-      f_service_ << indent();
-      first = false;
-    }
-    f_service_ <<
-      "if (_msg.name.equals(\"" << (*f_iter)->get_name() <<"\")) {" << endl;
-    indent_up();
-    indent(f_service_) <<
-      "process_" << (*f_iter)->get_name() << "(_msg.seqid, _itrans, _otrans);" << endl;
-    indent_down();
-    indent(f_service_) << "}";
-  }
   f_service_ <<
-    " else {" << endl;
-  indent_up();
-  indent(f_service_) <<
-    "System.err.println(\"Unknown function: '\" + _msg.name + \"'\");" << endl;
-  indent_down();
-  indent(f_service_) <<
-    "}" << endl;
+    indent() << "ProcessFunction fn = _processMap.get(msg.name);" << endl <<
+    indent() << "if (fn == null) {" << endl <<
+    indent() << "  System.err.println(\"Unknown function: '\" + msg.name + \"'\");" << endl <<
+    indent() << "} else {" << endl <<
+    indent() << "  fn.process(msg.seqid, _itrans, _otrans);" << endl <<
+    indent() << "}" << endl;
   
   // Read end of args field, the T_STOP, and the struct close
   f_service_ <<
@@ -725,7 +771,7 @@
   }
 
   indent_down();
-  f_service_ <<
+  indent(f_service_) <<
     "}" << endl <<
     endl;
 }
@@ -740,7 +786,7 @@
     return;
   }
 
-  t_struct result(tfunction->get_name() + "_result");
+  t_struct result(program_, tfunction->get_name() + "_result");
   t_field success(tfunction->get_returntype(), "success", 0);
   if (!tfunction->get_returntype()->is_void()) {
     result.append(&success);
@@ -763,9 +809,14 @@
  */
 void t_java_generator::generate_process_function(t_service* tservice,
                                                  t_function* tfunction) {
+  // Open class
+  indent(f_service_) <<
+    "private class " << tfunction->get_name() << " implements ProcessFunction {" << endl;
+  indent_up();
+
   // Open function
   indent(f_service_) <<
-    "private void process_" << tfunction->get_name() << "(int seqid, TTransport _itrans, TTransport _otrans) throws TException" << endl;
+    "public void process(int seqid, TTransport _itrans, TTransport _otrans) throws TException" << endl;
   scope_up(f_service_);
 
   string argsname = tfunction->get_name() + "_args";
@@ -859,6 +910,12 @@
   // Close function
   scope_down(f_service_);
   f_service_ << endl;
+
+  // Close class
+  indent_down();
+  f_service_ <<
+    indent() << "}" << endl <<
+    endl;
 }
 
 /**
@@ -942,7 +999,7 @@
                                                    t_struct* tstruct,
                                                    string prefix) {
   out <<
-    indent() << prefix << " = new " << tstruct->get_name() << "();" << endl <<
+    indent() << prefix << " = new " << type_name(tstruct) << "();" << endl <<
     indent() << prefix << ".read(_iprot, _itrans);" << endl;
 }
 
@@ -1296,9 +1353,18 @@
   } else if (ttype->is_list()) {
     t_list* tlist = (t_list*) ttype;
     return "ArrayList<" + type_name(tlist->get_elem_type(), true) + ">";
-  } else {
-    return ttype->get_name();
   }
+
+  // Check for namespacing
+  t_program* program = ttype->get_program();
+  if (program != NULL && program != program_) {
+    string package = program->get_java_package();
+    if (!package.empty()) {
+      return package + "." + ttype->get_name();
+    }
+  }
+
+  return ttype->get_name();
 }
 
 /**
diff --git a/compiler/cpp/src/generate/t_java_generator.h b/compiler/cpp/src/generate/t_java_generator.h
index e528c34..2b60e73 100644
--- a/compiler/cpp/src/generate/t_java_generator.h
+++ b/compiler/cpp/src/generate/t_java_generator.h
@@ -18,14 +18,15 @@
  */
 class t_java_generator : public t_oop_generator {
  public:
-  t_java_generator() {}
+  t_java_generator(t_program* program) :
+    t_oop_generator(program) {}
 
   /**
    * Init and close methods
    */
 
-  void init_generator(t_program *tprogram);
-  void close_generator(t_program *tprogram);
+  void init_generator();
+  void close_generator();
 
   /**
    * Program-level generation functions
diff --git a/compiler/cpp/src/generate/t_oop_generator.h b/compiler/cpp/src/generate/t_oop_generator.h
index fc47bc6..d0d2946 100644
--- a/compiler/cpp/src/generate/t_oop_generator.h
+++ b/compiler/cpp/src/generate/t_oop_generator.h
@@ -12,6 +12,8 @@
  */
 class t_oop_generator : public t_generator {
  public:
+  t_oop_generator(t_program* program) :
+    t_generator(program) {}
 
   /**
    * Scoping, using curly braces!
diff --git a/compiler/cpp/src/generate/t_php_generator.cc b/compiler/cpp/src/generate/t_php_generator.cc
index 61df589..5a6b8ac 100644
--- a/compiler/cpp/src/generate/t_php_generator.cc
+++ b/compiler/cpp/src/generate/t_php_generator.cc
@@ -10,7 +10,7 @@
  *
  * @param tprogram The program to generate
  */
-void t_php_generator::init_generator(t_program* tprogram) {
+void t_php_generator::init_generator() {
   // Make output directory
   mkdir(T_PHP_DIR, S_IREAD | S_IWRITE | S_IEXEC);
 
@@ -36,7 +36,7 @@
 /**
  * Close up (or down) some filez.
  */
-void t_php_generator::close_generator(t_program *tprogram) {
+void t_php_generator::close_generator() {
   // Close types file
   f_types_ << "?>" << endl;
   f_types_.close();
@@ -80,7 +80,6 @@
   // We're also doing it this way to see how it performs. It's more legible
   // code but you can't do things like an 'extract' on it, which is a bit of
   // a downer.
-
   f_types_ <<
     "final class " << tenum->get_name() << " {" << endl;
   indent_up();
@@ -97,6 +96,10 @@
       "const " << (*c_iter)->get_name() << " = " << value << ";" << endl;
   }
 
+  // Prevent instantiation of this class
+  f_types_ <<
+    indent() << "private function __construct() {}" << endl;
+
   indent_down();
   f_types_ << "}" << endl << endl;
 }
@@ -201,8 +204,8 @@
     
     // Read beginning field marker
     if (binary_inline_) {
-      t_field fftype(g_program->get_byte_type(), "ftype");
-      t_field ffid(g_program->get_i16_type(), "fid");
+      t_field fftype(g_type_byte, "ftype");
+      t_field ffid(g_type_i16, "fid");
       generate_deserialize_field(out, &fftype);
       out <<
         indent() << "if ($ftype == TType::STOP) {" << endl <<
@@ -364,7 +367,15 @@
     php_includes();
 
   f_service_ <<
-    "include_once $GLOBALS['THRIFT_ROOT'].'/packages/" << program_name_ << "/" << program_name_ << "_types.php';" << endl << endl;
+    "include_once $GLOBALS['THRIFT_ROOT'].'/packages/" << program_name_ << "/" << program_name_ << "_types.php';" << endl;
+
+  if (tservice->get_extends() != NULL) {
+    f_service_ <<
+      "include_once $GLOBALS['THRIFT_ROOT'].'/packages/" << tservice->get_extends()->get_program()->get_name() << "/" << tservice->get_extends()->get_name() << ".php';" << endl;
+  }
+  
+  f_service_ <<
+    endl;
 
   // Generate the three main parts of the service (well, two for now in PHP)
   generate_service_interface(tservice);
@@ -387,32 +398,55 @@
   vector<t_function*> functions = tservice->get_functions();
   vector<t_function*>::iterator f_iter; 
 
+  string extends = "";
+  string extends_processor = "";
+  if (tservice->get_extends() != NULL) {
+    extends = tservice->get_extends()->get_name();
+    extends_processor = " extends " + extends + "Processor";
+  }
+
   // Generate the header portion
   f_service_ <<
-    "class " << service_name_ << "Processor {" << endl;
+    "class " << service_name_ << "Processor" << extends_processor << " {" << endl;
   indent_up();
 
-  f_service_ <<
-    indent() << "private $_handler = null;" << endl;
-  if (!binary_inline_) {
-    f_service_ << 
-      indent() << "private $_iprot = null;" << endl <<
-      indent() << "private $_oprot = null;" << endl <<
-      endl;
+  if (extends.empty()) {
+    f_service_ <<
+      indent() << "protected $_handler = null;" << endl;
+    if (!binary_inline_) {
+      f_service_ << 
+        indent() << "protected $_iprot = null;" << endl <<
+        indent() << "protected $_oprot = null;" << endl <<
+        endl;
+    }
   }
 
   if (binary_inline_) {
     f_service_ <<
-      indent() << "public function __construct($handler) {" << endl << 
-      indent() << "  $this->_handler = $handler;" << endl <<
+      indent() << "public function __construct($handler) {" << endl;
+    if (extends.empty()) {
+      f_service_ <<
+        indent() << "  $this->_handler = $handler;" << endl;
+    } else {
+      f_service_ <<
+        indent() << "  parent::__construct($handler);" << endl;
+    }
+    f_service_ <<
       indent() << "}" << endl <<
       endl;
   } else {
     f_service_ <<
-      indent() << "public function __construct($handler, $iprot, $oprot=null) {" << endl << 
-      indent() << "  $this->_handler = $handler;" << endl <<
-      indent() << "  $this->_iprot = $iprot;" << endl <<
-      indent() << "  $this->_oprot = $oprot ? $oprot : $iprot;" << endl <<
+      indent() << "public function __construct($handler, $iprot, $oprot=null) {" << endl;
+    if (extends.empty()) {
+      f_service_ <<
+        indent() << "  $this->_handler = $handler;" << endl <<
+        indent() << "  $this->_iprot = $iprot;" << endl <<
+        indent() << "  $this->_oprot = $oprot ? $oprot : $iprot;" << endl;
+    } else {
+      f_service_ <<
+        indent() << "  parent::__construct($handler, $iprot, $oprot);" << endl;
+    }
+    f_service_ <<
       indent() << "}" << endl <<
       endl;
   }
@@ -429,9 +463,9 @@
     endl;
 
   if (binary_inline_) {
-    t_field ffname(g_program->get_string_type(), "fname");
-    t_field fmtype(g_program->get_byte_type(), "mtype");
-    t_field fseqid(g_program->get_i32_type(), "rseqid");
+    t_field ffname(g_type_string, "fname");
+    t_field fmtype(g_type_byte, "mtype");
+    t_field fseqid(g_type_i32, "rseqid");
     generate_deserialize_field(f_service_, &ffname, "", true);
     generate_deserialize_field(f_service_, &fmtype, "", true);
     generate_deserialize_field(f_service_, &fseqid, "", true);
@@ -602,7 +636,7 @@
  * @param tfunction The function
  */
 void t_php_generator::generate_php_function_helpers(t_function* tfunction) {
-  t_struct result(service_name_ + "_" + tfunction->get_name() + "_result");
+  t_struct result(program_, service_name_ + "_" + tfunction->get_name() + "_result");
   t_field success(tfunction->get_returntype(), "success", 0);
   if (!tfunction->get_returntype()->is_void()) {
     result.append(&success);
@@ -624,14 +658,20 @@
  * @param tservice The service to generate a header definition for
  */
 void t_php_generator::generate_service_interface(t_service* tservice) {
+  string extends = "";
+  string extends_if = "";
+  if (tservice->get_extends() != NULL) {
+    extends = " extends " + tservice->get_extends()->get_name();
+    extends_if = " extends " + tservice->get_extends()->get_name() + "If";
+  }
   f_service_ <<
-    "abstract class " << service_name_ << "If {" << endl;
+    "interface " << service_name_ << "If" << extends_if << " {" << endl;
   indent_up();
   vector<t_function*> functions = tservice->get_functions();
   vector<t_function*>::iterator f_iter; 
   for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
     indent(f_service_) <<
-      "public abstract function " << function_signature(*f_iter) << ";" << endl;
+      "public function " << function_signature(*f_iter) << ";" << endl;
   }
   indent_down();
   f_service_ <<
@@ -644,53 +684,59 @@
  * @param tservice The service to generate a server for.
  */
 void t_php_generator::generate_service_client(t_service* tservice) {
-  f_service_ <<
-    "class " << service_name_ << "Client " <<
-    "extends " << service_name_ << "If {" << endl;
-  indent_up();
-
-  // Private members
-  f_service_ <<
-    indent() << "private $_itrans = null;" << endl <<
-    indent() << "private $_otrans = null;" << endl <<
-    endl;
-
-  if (!binary_inline_) {
-    f_service_ <<
-      indent() << "private $_iprot = null;" << endl <<
-      indent() << "private $_oprot = null;" << endl <<
-      endl;
+  string extends = "";
+  string extends_client = "";
+  if (tservice->get_extends() != NULL) {
+    extends = tservice->get_extends()->get_name();
+    extends_client = " extends " + extends + "Client";
   }
 
   f_service_ <<
-    indent() << "private $_seqid = 0;" << endl <<
-    endl;
+    "class " << service_name_ << "Client" << extends_client << " implements " << service_name_ << "If {" << endl;
+  indent_up();
+
+  // Private members
+  if (extends.empty()) {
+    f_service_ <<
+      indent() << "protected $_itrans = null;" << endl <<
+      indent() << "protected $_otrans = null;" << endl <<
+      endl;
+    if (!binary_inline_) {
+      f_service_ <<
+        indent() << "protected $_iprot = null;" << endl <<
+        indent() << "protected $_oprot = null;" << endl <<
+        endl;
+    }
+    f_service_ <<
+      indent() << "protected $_seqid = 0;" << endl <<
+      endl;
+  }
 
   // Constructor function
   f_service_ <<
-    indent() << "public function __construct() {" << endl <<
-    indent() << "  $argv = func_get_args();" << endl <<
-    indent() << "  $argc = count($argv);" << endl;
-
-  if (binary_inline_) {
+    indent() << "public function __construct() {" << endl;
+  f_service_ <<
+    indent() << "  $argv = func_get_args();" << endl;
+  if (!extends.empty()) {
     f_service_ <<
-      indent() << "  if ($argc == 1) {" << endl <<
-      indent() << "    $this->_itrans = $this->_otrans = $argv[0];" << endl <<
-      indent() << "  } else if ($argc == 2) {" << endl <<
-      indent() << "    $this->_itrans = $argv[0];" << endl <<
-      indent() << "    $this->_otrans = $argv[1];" << endl <<
-      indent() << "  }" << endl;
+      indent() << "  parent::__construct($argv[0], $argv[1], $argv[2], $argv[3]);" << endl;
   } else {
-    f_service_ <<
-      indent() << "  if ($argc == 2) {" << endl <<
-      indent() << "    $this->_itrans = $this->_otrans = $argv[0];" << endl <<
-      indent() << "    $this->_iprot = $this->_oprot = $argv[1];" << endl <<
-      indent() << "  } else if ($argc == 4) {" << endl <<
-      indent() << "    $this->_itrans = $argv[0];" << endl <<
-      indent() << "    $this->_otrans = $argv[1];" << endl <<
-      indent() << "    $this->_iprot = $argv[2];" << endl <<
-      indent() << "    $this->_oprot = $argv[3];" << endl <<
-      indent() << "  }" << endl;
+    if (binary_inline_) {
+      f_service_ <<
+        indent() << "  $this->_itrans = $this->_otrans = $argv[0];" << endl <<
+        indent() << "  if ($argv[1]) {" << endl <<
+        indent() << "    $this->_otrans = $argv[1];" << endl <<
+        indent() << "  }" << endl;
+    } else {
+      f_service_ <<
+        indent() << "  $this->_itrans = $this->_otrans = $argv[0];" << endl <<
+        indent() << "  $this->_iprot = $this->_oprot = $argv[1];" << endl <<
+        indent() << "  if ($argv[2]) {" << endl <<
+        indent() << "    $this->_otrans = $argv[1];" << endl <<
+        indent() << "    $this->_iprot = $argv[2];" << endl <<
+        indent() << "    $this->_oprot = $argv[3];" << endl <<
+        indent() << "  }" << endl;
+    }
   }
   f_service_ <<
     indent() << "}" << endl << endl;   
@@ -780,7 +826,7 @@
 
     if (!(*f_iter)->is_async()) {
       std::string resultname = service_name_ + "_" + (*f_iter)->get_name() + "_result";
-      t_struct noargs;
+      t_struct noargs(program_);
       
       t_function recv_function((*f_iter)->get_returntype(),
                                string("recv_") + (*f_iter)->get_name(),
@@ -798,9 +844,9 @@
         endl;
 
       if (binary_inline_) {
-        t_field ffname(g_program->get_string_type(), "fname");
-        t_field fmtype(g_program->get_byte_type(), "mtype");
-        t_field fseqid(g_program->get_i32_type(), "rseqid");
+        t_field ffname(g_type_string, "fname");
+        t_field fmtype(g_type_byte, "mtype");
+        t_field fseqid(g_type_i32, "rseqid");
         generate_deserialize_field(f_service_, &ffname, "", true);
         generate_deserialize_field(f_service_, &fmtype, "", true);
         generate_deserialize_field(f_service_, &fseqid, "", true);
@@ -1046,10 +1092,10 @@
   string vtype = tmp("_vtype");
   string etype = tmp("_etype");
   
-  t_field fsize(g_program->get_i32_type(), size);
-  t_field fktype(g_program->get_byte_type(), ktype);
-  t_field fvtype(g_program->get_byte_type(), vtype);
-  t_field fetype(g_program->get_byte_type(), etype);
+  t_field fsize(g_type_i32, size);
+  t_field fktype(g_type_byte, ktype);
+  t_field fvtype(g_type_byte, vtype);
+  t_field fetype(g_type_byte, etype);
 
   out <<
     indent() << "$" << prefix << " = array();" << endl <<
diff --git a/compiler/cpp/src/generate/t_php_generator.h b/compiler/cpp/src/generate/t_php_generator.h
index 0e6869b..609cbae 100644
--- a/compiler/cpp/src/generate/t_php_generator.h
+++ b/compiler/cpp/src/generate/t_php_generator.h
@@ -15,8 +15,9 @@
  */
 class t_php_generator : public t_oop_generator {
  public:
-  t_php_generator(bool binary_inline=false) {
-    binary_inline_ = binary_inline;
+  t_php_generator(t_program* program, bool binary_inline=false) :
+    t_oop_generator(program),
+    binary_inline_(binary_inline) {
     if (binary_inline_) {
       T_PHP_DIR = "gen-phpi";
     } else {
@@ -28,8 +29,8 @@
    * Init and close methods
    */
 
-  void init_generator(t_program *tprogram);
-  void close_generator(t_program *tprogram);
+  void init_generator();
+  void close_generator();
 
   /**
    * Program-level generation functions
diff --git a/compiler/cpp/src/generate/t_py_generator.cc b/compiler/cpp/src/generate/t_py_generator.cc
index 9838df6..6398f11 100644
--- a/compiler/cpp/src/generate/t_py_generator.cc
+++ b/compiler/cpp/src/generate/t_py_generator.cc
@@ -11,7 +11,7 @@
  *
  * @param tprogram The program to generate
  */
-void t_py_generator::init_generator(t_program* tprogram) {
+void t_py_generator::init_generator() {
   // Make output directory
   mkdir(T_PY_DIR, S_IREAD | S_IWRITE | S_IEXEC);
 
@@ -23,7 +23,22 @@
   f_types_ <<
     py_autogen_comment() << endl <<
     py_imports() << endl <<
-    endl;
+    render_includes() << endl;
+}
+
+/**
+ * Renders all the imports necessary for including another Thrift program
+ */
+string t_py_generator::render_includes() {
+  const vector<t_program*>& includes = program_->get_includes();
+  string result = "";
+  for (size_t i = 0; i < includes.size(); ++i) {
+    result += "import " + includes[i]->get_name() + "_types\n";
+  }
+  if (includes.size() > 0) {
+    result += "\n";
+  }
+  return result;
 }
 
 /**
@@ -50,7 +65,7 @@
 /**
  * Closes the type files
  */
-void t_py_generator::close_generator(t_program *tprogram) {
+void t_py_generator::close_generator() {
   // Close types file
   f_types_.close();
 }
@@ -307,6 +322,11 @@
     py_autogen_comment() << endl <<
     py_imports() << endl;
 
+  if (tservice->get_extends() != NULL) {
+    f_service_ <<
+      "import " << tservice->get_extends()->get_name() << endl;
+  }
+
   f_service_ <<
     "from " << program_name_ << "_types import *" << endl << 
     "from thrift.Thrift import TProcessor" << endl <<
@@ -315,8 +335,8 @@
   // Generate the three main parts of the service (well, two for now in PHP)
   generate_service_interface(tservice);
   generate_service_client(tservice);
-  generate_service_helpers(tservice);
   generate_service_server(tservice);
+  generate_service_helpers(tservice);
   generate_service_remote(tservice);
 
   // Close service file
@@ -349,7 +369,7 @@
  * @param tfunction The function
  */
 void t_py_generator::generate_py_function_helpers(t_function* tfunction) {
-  t_struct result(tfunction->get_name() + "_result");
+  t_struct result(program_, tfunction->get_name() + "_result");
   t_field success(tfunction->get_returntype(), "success", 0);
   if (!tfunction->get_returntype()->is_void()) {
     result.append(&success);
@@ -370,8 +390,15 @@
  * @param tservice The service to generate a header definition for
  */
 void t_py_generator::generate_service_interface(t_service* tservice) {
+  string extends = "";
+  string extends_if = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    extends_if = "(" + extends + ".Iface)";
+  }
+
   f_service_ <<
-    "class Iface:" << endl;
+    "class Iface" << extends_if << ":" << endl;
   indent_up();
   vector<t_function*> functions = tservice->get_functions();
   vector<t_function*>::iterator f_iter; 
@@ -391,25 +418,39 @@
  * @param tservice The service to generate a server for.
  */
 void t_py_generator::generate_service_client(t_service* tservice) {
+  string extends = "";
+  string extends_client = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    extends_client = extends + ".Client, ";
+  }
+
   f_service_ <<
-    "class Client(Iface):" << endl;
+    "class Client(" << extends_client << "Iface):" << endl;
   indent_up();
 
   // Constructor function
   f_service_ <<
-    indent() << "def __init__(self, one, two, three=None, four=None):" << endl <<
-    indent() << "  if three == None or four == None:" << endl <<
-    indent() << "    self.__otrans = one" << endl <<
-    indent() << "    self.__itrans = one" << endl <<
-    indent() << "    self.__iprot = two" << endl <<
-    indent() << "    self.__oprot = two" << endl <<
-    indent() << "  else:" << endl <<
-    indent() << "    self.__otrans = one" << endl <<
-    indent() << "    self.__itrans = two" << endl <<
-    indent() << "    self.__iprot = three" << endl <<
-    indent() << "    self.__oprot = four" << endl <<
-    indent() << "  self.__seqid = 0" << endl <<
-    endl;
+    indent() << "def __init__(self, one, two, three=None, four=None):" << endl;
+  if (extends.empty()) {
+    f_service_ <<
+      indent() << "  if three == None or four == None:" << endl <<
+      indent() << "    self._otrans = one" << endl <<
+      indent() << "    self._itrans = one" << endl <<
+      indent() << "    self._iprot = two" << endl <<
+      indent() << "    self._oprot = two" << endl <<
+      indent() << "  else:" << endl <<
+      indent() << "    self._otrans = one" << endl <<
+      indent() << "    self._itrans = two" << endl <<
+      indent() << "    self._iprot = three" << endl <<
+      indent() << "    self._oprot = four" << endl <<
+      indent() << "  self._seqid = 0" << endl <<
+      endl;
+  } else {
+    f_service_ <<
+      indent() << "  " << extends << ".Client.__init__(self, one, two, three, four)" << endl <<
+      endl;
+  }
 
   // Generate client method implementations
   vector<t_function*> functions = tservice->get_functions();
@@ -457,7 +498,7 @@
 
       // Serialize the request header
       f_service_ <<
-        indent() << "self.__oprot.writeMessageBegin(self.__otrans, '" << (*f_iter)->get_name() << "', TMessageType.CALL, self.__seqid)" << endl;
+        indent() << "self._oprot.writeMessageBegin(self._otrans, '" << (*f_iter)->get_name() << "', TMessageType.CALL, self._seqid)" << endl;
       
       f_service_ <<
         indent() << "__args = " << argsname << "()" << endl;
@@ -469,16 +510,16 @@
            
       // Write to the stream
       f_service_ <<
-        indent() << "__args.write(self.__oprot, self.__otrans)" << endl <<
-        indent() << "self.__oprot.writeMessageEnd(self.__otrans)" << endl <<
-        indent() << "self.__otrans.flush()" << endl;
+        indent() << "__args.write(self._oprot, self._otrans)" << endl <<
+        indent() << "self._oprot.writeMessageEnd(self._otrans)" << endl <<
+        indent() << "self._otrans.flush()" << endl;
 
     indent_down();
       
 
     if (!(*f_iter)->is_async()) {
       std::string resultname = (*f_iter)->get_name() + "_result";
-      t_struct noargs;
+      t_struct noargs(program_);
       
       t_function recv_function((*f_iter)->get_returntype(),
                                string("recv_") + (*f_iter)->get_name(),
@@ -490,14 +531,14 @@
       indent_up();
 
       f_service_ <<
-        indent() << "(fname, mtype, rseqid) = self.__iprot.readMessageBegin(self.__itrans)" << endl;
+        indent() << "(fname, mtype, rseqid) = self._iprot.readMessageBegin(self._itrans)" << endl;
 
       // TODO(mcslee): Validate message reply here, seq ids etc.
 
       f_service_ <<
         indent() << "__result = " << resultname << "()" << endl <<
-        indent() << "__result.read(self.__iprot, self.__otrans)" << endl <<
-        indent() << "self.__iprot.readMessageEnd(self.__itrans)" << endl;
+        indent() << "__result.read(self._iprot, self._otrans)" << endl <<
+        indent() << "self._iprot.readMessageEnd(self._itrans)" << endl;
 
       // Careful, only return _result if not a void function
       if (!(*f_iter)->get_returntype()->is_void()) {
@@ -645,7 +686,7 @@
       "    sys.exit(1)" << endl <<
       "  pp.pprint(client." << (*f_iter)->get_name() << "(";
     for (int i = 0; i < num_args; ++i) {
-      if (args[i]->get_type() == g_program->get_string_type()) {
+      if (args[i]->get_type() == g_type_string) {
         f_remote << "args[" << i << "],";
       } else {
         f_remote << "eval(args[" << i << "]),";
@@ -682,29 +723,35 @@
   vector<t_function*> functions = tservice->get_functions();
   vector<t_function*>::iterator f_iter; 
 
+  string extends = "";
+  string extends_processor = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    extends_processor = extends + ".Processor, ";
+  }
+
   // Generate the header portion
   f_service_ <<
-    "class Processor(Iface, TProcessor):" << endl;
+    "class Processor(" << extends_processor << "Iface, TProcessor):" << endl;
   indent_up();
 
   indent(f_service_) <<
     "def __init__(self, handler, iprot, oprot=None):" << endl;
   indent_up();
-  f_service_ <<
-    indent() << "self.__handler = handler" << endl <<
-    indent() << "self.__iprot = iprot" << endl <<
-    indent() << "if oprot == None:" << endl <<
-    indent() << "  self.__oprot = iprot" << endl <<
-    indent() << "else:" << endl <<
-    indent() << "  self.__oprot = oprot" << endl <<
-    indent() << "self.__processMap = {" << endl;
+  if (extends.empty()) {
+    f_service_ <<
+      indent() << "self._handler = handler" << endl <<
+      indent() << "self._iprot = iprot" << endl <<
+      indent() << "if oprot == None:" << endl <<
+      indent() << "  self._oprot = iprot" << endl <<
+      indent() << "else:" << endl <<
+      indent() << "  self._oprot = oprot" << endl <<
+      indent() << "self._processMap = {}" << endl;
+  }
   for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
     f_service_ <<
-      indent() << "  \"" << (*f_iter)->get_name() << "\" : Processor.process_" << (*f_iter)->get_name() << "," << endl;
-  }
-  f_service_ <<
-    indent() << "}" << endl;
-  
+      indent() << "self._processMap[\"" << (*f_iter)->get_name() << "\"] = Processor.process_" << (*f_iter)->get_name() << endl;
+  } 
   indent_down();
   f_service_ << endl;
  
@@ -714,16 +761,16 @@
   indent_up();
 
   f_service_ <<
-    indent() << "(name, type, seqid)  = self.__iprot.readMessageBegin(itrans)" << endl;
+    indent() << "(name, type, seqid)  = self._iprot.readMessageBegin(itrans)" << endl;
 
   // TODO(mcslee): validate message
 
   // HOT: dictionary function lookup
   f_service_ <<
-    indent() << "if name not in self.__processMap:" << endl <<
+    indent() << "if name not in self._processMap:" << endl <<
     indent() << "  print 'Unknown function %s' % (name)" << endl <<
     indent() << "else:" << endl <<
-    indent() << "  self.__processMap[name](self, seqid, itrans, otrans)" << endl;
+    indent() << "  self._processMap[name](self, seqid, itrans, otrans)" << endl;
 
   // Read end of args field, the T_STOP, and the struct close
   f_service_ <<
@@ -759,8 +806,8 @@
 
   f_service_ <<
     indent() << "__args = " << argsname << "()" << endl <<
-    indent() << "__args.read(self.__iprot, itrans)" << endl <<
-    indent() << "self.__iprot.readMessageEnd(itrans)" << endl;
+    indent() << "__args.read(self._iprot, itrans)" << endl <<
+    indent() << "self._iprot.readMessageEnd(itrans)" << endl;
 
   t_struct* xs = tfunction->get_xceptions();
   const std::vector<t_field*>& xceptions = xs->get_members();
@@ -789,7 +836,7 @@
     f_service_ << "__result.success = ";
   }
   f_service_ <<
-    "self.__handler." << tfunction->get_name() << "(";
+    "self._handler." << tfunction->get_name() << "(";
   bool first = true;
   for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
     if (first) {
@@ -828,9 +875,9 @@
   }
 
   f_service_ <<
-    indent() << "self.__oprot.writeMessageBegin(otrans, \"" << tfunction->get_name() << "\", TMessageType.REPLY, seqid)" << endl <<
-    indent() << "__result.write(self.__oprot, otrans)" << endl <<
-    indent() << "self.__oprot.writeMessageEnd(otrans)" << endl <<
+    indent() << "self._oprot.writeMessageBegin(otrans, \"" << tfunction->get_name() << "\", TMessageType.REPLY, seqid)" << endl <<
+    indent() << "__result.write(self._oprot, otrans)" << endl <<
+    indent() << "self._oprot.writeMessageEnd(otrans)" << endl <<
     indent() << "otrans.flush()" << endl;
 
   // Close function
@@ -916,7 +963,7 @@
                                                   t_struct* tstruct,
                                                   string prefix) {
   out <<
-    indent() << prefix << " = " << tstruct->get_name() << "()" << endl <<
+    indent() << prefix << " = " << type_name(tstruct) << "()" << endl <<
     indent() << prefix << ".read(iprot, itrans)" << endl;
 }
 
@@ -932,10 +979,10 @@
   string vtype = tmp("_vtype");
   string etype = tmp("_etype");
   
-  t_field fsize(g_program->get_i32_type(), size);
-  t_field fktype(g_program->get_byte_type(), ktype);
-  t_field fvtype(g_program->get_byte_type(), vtype);
-  t_field fetype(g_program->get_byte_type(), etype);
+  t_field fsize(g_type_i32, size);
+  t_field fktype(g_type_byte, ktype);
+  t_field fvtype(g_type_byte, vtype);
+  t_field fetype(g_type_byte, etype);
 
   // Declare variables, read header
   if (ttype->is_map()) {
@@ -991,13 +1038,6 @@
   t_field fkey(tmap->get_key_type(), key);
   t_field fval(tmap->get_val_type(), val);
 
-  /*
-  indent(out) <<
-    declare_field(&fkey, true, true) << endl;
-  indent(out) <<
-    declare_field(&fval, true, true) << endl;
-  */
-
   generate_deserialize_field(out, &fkey);
   generate_deserialize_field(out, &fval);
 
@@ -1264,7 +1304,7 @@
       }
     } else if (type->is_struct() || type->is_xception()) {
       if (obj) {
-        result += " = " + type->get_name() + "()";
+        result += " = " + type_name((t_struct*)type) + "()";
       } else {
         result += " = None";
       }
@@ -1307,6 +1347,18 @@
   return result;
 }
 
+string t_py_generator::type_name(t_type* ttype) {
+  t_program* program = ttype->get_program();
+  if (program != NULL && program != program_) {
+    if (ttype->is_service()) {
+      return ttype->get_name();
+    } else {
+      return program->get_name() + "_types." + ttype->get_name();
+    }
+  }
+  return ttype->get_name();
+}
+
 /**
  * Converts the parse type to a Python tyoe
  */
diff --git a/compiler/cpp/src/generate/t_py_generator.h b/compiler/cpp/src/generate/t_py_generator.h
index 238d10e..9cbc4a6 100644
--- a/compiler/cpp/src/generate/t_py_generator.h
+++ b/compiler/cpp/src/generate/t_py_generator.h
@@ -17,14 +17,15 @@
  */
 class t_py_generator : public t_oop_generator {
  public:
-  t_py_generator() {}
+  t_py_generator(t_program* program) :
+    t_oop_generator(program) {}
 
   /**
    * Init and close methods
    */
 
-  void init_generator(t_program *tprogram);
-  void close_generator(t_program *tprogram);
+  void init_generator();
+  void close_generator();
 
   /**
    * Program-level generation functions
@@ -117,7 +118,9 @@
 
   std::string py_autogen_comment();
   std::string py_imports();
+  std::string render_includes();
   std::string declare_field(t_field* tfield, bool init=false, bool obj=false);
+  std::string type_name(t_type* ttype);
   std::string function_signature(t_function* tfunction, std::string prefix="");
   std::string argument_list(t_struct* tstruct);
   std::string type_to_enum(t_type* ttype);
diff --git a/compiler/cpp/src/globals.h b/compiler/cpp/src/globals.h
index 7385565..51502c7 100644
--- a/compiler/cpp/src/globals.h
+++ b/compiler/cpp/src/globals.h
@@ -1,7 +1,39 @@
 #ifndef T_GLOBALS_H
 #define T_GLOBALS_H
 
+#include <set>
+#include <queue>
+#include <stack>
+#include <vector>
+#include <string>
+
+/**
+ * This module contains all the global variables (slap on the wrist) that are
+ * shared throughout the program. The reason for this is to facilitate simple
+ * interaction between the parser and the rest of the program. Before calling
+ * yyparse(), the main.cc program will make necessary adjustments to these
+ * global variables such that the parser does the right thing and puts entries
+ * into the right containers, etc.
+ *
+ * @author Mark Slee <mcslee@facebook.com>
+ */
+
+/**
+ * Hooray for forward declaration of types!
+ */
+
 class t_program;
+class t_scope;
+class t_type;
+
+/**
+ * Parsing mode, two passes up in this gin rummy!
+ */
+
+enum PARSE_MODE {
+  INCLUDES = 1,
+  PROGRAM = 2
+};
 
 /**
  * The master program parse tree. This is accessed from within the parser code
@@ -10,9 +42,37 @@
 extern t_program* g_program;
 
 /**
- * Global debug state
+ * Global types for the parser to be able to reference
  */
-extern int g_debug;
+
+extern t_type* g_type_void;
+extern t_type* g_type_string;
+extern t_type* g_type_bool;
+extern t_type* g_type_byte;
+extern t_type* g_type_i16;
+extern t_type* g_type_i32;
+extern t_type* g_type_i64;
+extern t_type* g_type_double;
+
+/**
+ * The scope that we are currently parsing into
+ */
+extern t_scope* g_scope;
+
+/**
+ * The parent scope to also load symbols into
+ */
+extern t_scope* g_parent_scope;
+
+/**
+ * The prefix for the parent scope entries
+ */
+extern std::string g_parent_prefix;
+
+/**
+ * The parsing pass that we are on. We do different things on each pass.
+ */
+extern PARSE_MODE g_parse_mode;
 
 /**
  * Global time string, used in formatting error messages etc.
diff --git a/compiler/cpp/src/main.cc b/compiler/cpp/src/main.cc
index 9a8e29e..aee89ae 100644
--- a/compiler/cpp/src/main.cc
+++ b/compiler/cpp/src/main.cc
@@ -13,12 +13,15 @@
 #include <stdio.h>
 #include <stdarg.h>
 #include <string>
+#include <sys/types.h>
+#include <sys/stat.h>
 
-// Careful: must include globals first here for extern/global definitions
+// Careful: must include globals first for extern definitions
 #include "globals.h"
 
 #include "main.h"
 #include "parse/t_program.h"
+#include "parse/t_scope.h"
 #include "generate/t_cpp_generator.h"
 #include "generate/t_java_generator.h"
 #include "generate/t_php_generator.h"
@@ -32,16 +35,79 @@
 t_program* g_program;
 
 /**
+ * Global types
+ */
+
+t_type* g_type_void;
+t_type* g_type_string;
+t_type* g_type_bool;
+t_type* g_type_byte;
+t_type* g_type_i16;
+t_type* g_type_i32;
+t_type* g_type_i64;
+t_type* g_type_double;
+
+/**
+ * Global scope
+ */
+t_scope* g_scope;
+
+/**
+ * Parent scope to also parse types
+ */
+t_scope* g_parent_scope;
+
+/**
+ * Prefix for putting types in parent scope
+ */
+string g_parent_prefix;
+
+/**
+ * Parsing pass
+ */
+PARSE_MODE g_parse_mode;
+
+/**
+ * Current directory of file being parsed
+ */
+string g_curdir;
+
+/**
+ * Current file being parsed
+ */
+string g_curpath;
+
+/**
  * Global debug state
  */
 int g_debug = 0;
 
 /**
+ * Warning level
+ */
+int g_warn = 1;
+
+/**
+ * Verbose output
+ */
+int g_verbose = 0;
+
+/**
  * Global time string
  */
 char* g_time_str;
 
 /**
+ * Flags to control code generation
+ */
+bool gen_cpp = false;
+bool gen_java = false;
+bool gen_py = false;
+bool gen_php = false;
+bool gen_phpi = false;
+bool gen_recurse = false;
+
+/**
  * Report an error to the user. This is called yyerror for historical
  * reasons (lex and yacc expect the error reporting routine to be called
  * this). Call this function to report any errors to the user.
@@ -52,10 +118,10 @@
 void yyerror(char* fmt, ...) {
   va_list args;
   fprintf(stderr,
-          "\n!!! Error: line %d (last token was '%s')",
+          "[ERROR:%s:%d] (last token was '%s')\n",
+          g_curpath.c_str(),
           yylineno,
           yytext);
-  fprintf(stderr, "\n!!! ");
 
   va_start(args, fmt);
   vfprintf(stderr, fmt, args);
@@ -74,7 +140,39 @@
     return;
   }
   va_list args;
-  printf("[Parse] ");
+  printf("[PARSE] ");
+  va_start(args, fmt);
+  vprintf(fmt, args);
+  va_end(args);
+  printf("\n");
+}
+
+/**
+ * Prints a verbose output mode message
+ *
+ * @param fmt C format string followed by additional arguments
+ */
+void pverbose(char* fmt, ...) {
+  if (g_verbose == 0) {
+    return;
+  }
+  va_list args;
+  va_start(args, fmt);
+  vprintf(fmt, args);
+  va_end(args);
+}
+
+/**
+ * Prints a warning message
+ *
+ * @param fmt C format string followed by additional arguments
+ */
+void pwarning(int level, char* fmt, ...) {
+  if (g_warn < level) {
+    return;
+  }
+  va_list args;
+  printf("[WARNING:%s:%d] ", g_curpath.c_str(), yylineno);
   va_start(args, fmt);
   vprintf(fmt, args);
   va_end(args);
@@ -88,7 +186,7 @@
  */
 void failure(char* fmt, ...) {
   va_list args; 
-  fprintf(stderr, "\n!!! Failure: ");
+  fprintf(stderr, "[FAILURE:%s:%d] ", g_curpath.c_str(), yylineno);
   va_start(args, fmt);
   vfprintf(stderr, fmt, args);
   va_end(args);
@@ -97,38 +195,201 @@
 }
 
 /**
+ * Converts a string filename into a thrift program name
+ */
+string program_name(string filename) {
+  string::size_type slash = filename.rfind("/");
+  if (slash != string::npos) {
+    filename = filename.substr(slash+1);
+  }
+  string::size_type dot = filename.rfind(".");
+  if (dot != string::npos) {
+    filename = filename.substr(0, dot);
+  }
+  return filename;
+}
+
+/**
+ * Gets the directory path of a filename
+ */
+string directory_name(string filename) {
+  string::size_type slash = filename.rfind("/");
+  // No slash, just use the current directory
+  if (slash == string::npos) {
+    return ".";
+  }
+  return filename.substr(0, slash);
+}
+
+/**
+ * Finds the appropriate file path for the given filename
+ */
+string include_file(string filename) {
+  // Absolute path? Just try that
+  if (filename[0] != '/') {
+    filename = g_curdir + "/" + filename;
+  }
+
+  // Realpath!
+  char rp[PATH_MAX];
+  if (realpath(filename.c_str(), rp) == NULL) {
+    pwarning(0, "Cannot open include file %s\n", filename.c_str());
+    return std::string();
+  }
+  
+  // Stat this files
+  struct stat finfo;
+  if (stat(rp, &finfo) == 0) {
+    return rp;
+  }
+
+  // Uh oh
+  pwarning(0, "Could not find include file %s\n", filename.c_str());
+  return std::string();
+}
+
+/**
  * Diplays the usage message and then exits with an error code.
  */
 void usage() {
   fprintf(stderr, "Usage: thrift [options] file\n");
   fprintf(stderr, "Options:\n");
-  fprintf(stderr, "  --cpp    Generate C++ output files\n");
-  fprintf(stderr, "  --java   Generate Java output files\n");
-  fprintf(stderr, "  --php    Generate PHP output files\n");
-  fprintf(stderr, "  --phpi   Generate PHP inlined files\n");
-  fprintf(stderr, "  --py     Generate Python output files\n");
-  fprintf(stderr, "  --debug  Print parse debugging to standard output\n");
+  fprintf(stderr, "  --cpp        Generate C++ output files\n");
+  fprintf(stderr, "  --java       Generate Java output files\n");
+  fprintf(stderr, "  --php        Generate PHP output files\n");
+  fprintf(stderr, "  --phpi       Generate PHP inlined files\n");
+  fprintf(stderr, "  --py         Generate Python output files\n");
+  fprintf(stderr, "  --nowarn     Suppress all compiler warnings (BAD!)\n");
+  fprintf(stderr, "  --strict     Strict compiler warnings on\n");
+  fprintf(stderr, "  --v[erbose]  Verbose mode\n");
+  fprintf(stderr, "  --r[ecurse]  Also generate included files\n");
+  fprintf(stderr, "  --debug      Parse debug trace to stdout\n");
   exit(1);
 }
 
 /**
+ * Parses a program
+ */
+void parse(t_program* program, t_program* parent_program) {  
+  // Get scope file path
+  string path = program->get_path();
+  
+  // Set current dir global, which is used in the include_file function
+  g_curdir = directory_name(path);
+  g_curpath = path;
+
+  // Open the file
+  yyin = fopen(path.c_str(), "r");
+  if (yyin == 0) {
+    failure("Could not open input file: \"%s\"", path.c_str());
+  }
+
+  // Create new scope and scan for includes
+  pverbose("Scanning %s for includes\n", path.c_str());
+  g_parse_mode = INCLUDES; 
+  g_program = program;
+  g_scope = program->scope();
+  if (yyparse() != 0) {
+    failure("Parser error during include pass.");
+  }
+  fclose(yyin);
+
+  // Recursively parse all the include programs
+  vector<t_program*>& includes = program->get_includes();
+  vector<t_program*>::iterator iter;
+  for (iter = includes.begin(); iter != includes.end(); ++iter) {
+    parse(*iter, program);
+  }
+
+  // Parse the program the file
+  g_parse_mode = PROGRAM;
+  g_program = program;
+  g_scope = program->scope();
+  g_parent_scope = (parent_program != NULL) ? parent_program->scope() : NULL;
+  g_parent_prefix = program->get_name() + ".";
+  g_curpath = path;
+  yyin = fopen(path.c_str(), "r");
+  if (yyin == 0) {
+    failure("Could not open input file: \"%s\"", path.c_str());
+  }
+  pverbose("Parsing %s for types\n", path.c_str());
+  if (yyparse() != 0) {
+    failure("Parser error during types pass.");
+  }
+  fclose(yyin);
+}
+
+/**
+ * Generate code
+ */
+void generate(t_program* program) {
+  // Oooohh, recursive code generation, hot!!
+  if (gen_recurse) {
+    const vector<t_program*>& includes = program->get_includes();
+    for (size_t i = 0; i < includes.size(); ++i) {
+      generate(includes[i]);
+    }
+  }
+
+  // Generate code!
+  try {
+    pverbose("Program: %s\n", program->get_path().c_str());
+
+    if (gen_cpp) {
+      pverbose("Generating C++\n");
+      t_cpp_generator* cpp = new t_cpp_generator(program);
+      cpp->generate_program();
+      delete cpp;
+    }
+
+    if (gen_java) {
+      pverbose("Generating Java\n");
+      t_java_generator* java = new t_java_generator(program);
+      java->generate_program();
+      delete java;
+    }
+
+    if (gen_php) {
+      pverbose("Generating PHP\n");
+      t_php_generator* php = new t_php_generator(program, false);
+      php->generate_program();
+      delete php;
+    }
+
+    if (gen_phpi) {
+      pverbose("Generating PHP-inline\n");
+      t_php_generator* phpi = new t_php_generator(program, true);
+      phpi->generate_program();
+      delete phpi;
+    }
+
+    if (gen_py) {
+      pverbose("Generating Python\n");
+      t_py_generator* py = new t_py_generator(program);
+      py->generate_program();
+      delete py;
+    }
+  } catch (string s) {
+    printf("Error: %s\n", s.c_str());
+  } catch (const char* exc) {
+    printf("Error: %s\n", exc);
+  }
+
+}
+
+/**
  * Parse it up.. then spit it back out, in pretty much every language. Alright
  * not that many languages, but the cool ones that we care about.
  */
 int main(int argc, char** argv) {
   int i;
 
-  bool gen_cpp = false;
-  bool gen_java = false;
-  bool gen_py = false;
-  bool gen_php = false;
-  bool gen_phpi = false;
-
   // Setup time string
   time_t now = time(NULL);
   g_time_str = ctime(&now);
 
-  // Check for necessary arguments
+  // Check for necessary arguments, you gotta have at least a filename and
+  // an output language flag
   if (argc < 2) {
     usage();
   }
@@ -140,6 +401,14 @@
     while (arg != NULL) {
       if (strcmp(arg, "--debug") == 0) {
         g_debug = 1;
+      } else if (strcmp(arg, "--nowarn") == 0) {
+        g_warn = 0;
+      } else if (strcmp(arg, "--strict") == 0) {
+        g_warn = 2;
+      } else if (strcmp(arg, "--v") == 0 || strcmp(arg, "--verbose") == 0 ) {
+        g_verbose = 1;
+      } else if (strcmp(arg, "--r") == 0 || strcmp(arg, "--recurse") == 0 ) {
+        gen_recurse = true;
       } else if (strcmp(arg, "--cpp") == 0) {
         gen_cpp = true;
       } else if (strcmp(arg, "--java") == 0) {
@@ -160,77 +429,51 @@
     }
   }
   
+  // You gotta generate something!
   if (!gen_cpp && !gen_java && !gen_php && !gen_phpi && !gen_py) {
     fprintf(stderr, "!!! No output language(s) specified\n\n");
     usage();
   }
-  
-  // Open input file
-  char* input_file = argv[i];
-  yyin = fopen(input_file, "r");
-  if (yyin == 0) {
-    failure("Could not open input file: \"%s\"", input_file);
+
+  // Real-pathify it
+  char rp[PATH_MAX];
+  if (realpath(argv[i], rp) == NULL) {
+    failure("Could not open input file: %s", argv[i]);
   }
-  
-  // Extract program name by dropping directory and .thrift from filename
-  string name = input_file;
-  string::size_type slash = name.rfind("/");
-  if (slash != string::npos) {
-    name = name.substr(slash+1);
-  }
-  string::size_type dot = name.find(".");
-  if (dot != string::npos) {
-    name = name.substr(0, dot);
-  }
-  
+  string input_file(rp);
+
   // Instance of the global parse tree
-  g_program = new t_program(name);
+  t_program* program = new t_program(input_file);
+
+  // Initialize global types
+  g_type_void   = new t_base_type("void",   t_base_type::TYPE_VOID);
+  g_type_string = new t_base_type("string", t_base_type::TYPE_STRING);
+  g_type_bool   = new t_base_type("bool",   t_base_type::TYPE_BOOL);
+  g_type_byte   = new t_base_type("byte",   t_base_type::TYPE_BYTE);
+  g_type_i16    = new t_base_type("i16",    t_base_type::TYPE_I16);
+  g_type_i32    = new t_base_type("i32",    t_base_type::TYPE_I32);
+  g_type_i64    = new t_base_type("i64",    t_base_type::TYPE_I64);
+  g_type_double = new t_base_type("double", t_base_type::TYPE_DOUBLE);
 
   // Parse it!
-  if (yyparse() != 0) {
-    failure("Parser error.");
-  }
+  parse(program, NULL);
 
-  // Generate code
-  try {
-    if (gen_cpp) {
-      t_cpp_generator* cpp = new t_cpp_generator();
-      cpp->generate_program(g_program);
-      delete cpp;
-    }
+  // Generate it!
+  generate(program);
 
-    if (gen_java) {
-      t_java_generator* java = new t_java_generator();
-      java->generate_program(g_program);
-      delete java;
-    }
+  // Clean up. Who am I kidding... this program probably orphans heap memory
+  // all over the place, but who cares because it is about to exit and it is
+  // all referenced and used by this wacky parse tree up until now anyways.
 
-    if (gen_php) {
-      t_php_generator* php = new t_php_generator(false);
-      php->generate_program(g_program);
-      delete php;
-    }
-
-    if (gen_phpi) {
-      t_php_generator* phpi = new t_php_generator(true);
-      phpi->generate_program(g_program);
-      delete phpi;
-    }
-
-    if (gen_py) {
-      t_py_generator* py = new t_py_generator();
-      py->generate_program(g_program);
-      delete py;
-    }
-
-  } catch (string s) {
-    printf("Error: %s\n", s.c_str());
-  } catch (const char* exc) {
-    printf("Error: %s\n", exc);
-  }
-
-  // Clean up
-  delete g_program;
+  delete program;
+  delete g_type_void;
+  delete g_type_string;
+  delete g_type_bool;
+  delete g_type_byte;
+  delete g_type_i16;
+  delete g_type_i32;
+  delete g_type_i64;
+  delete g_type_double;
 
   // Finished
   return 0;
diff --git a/compiler/cpp/src/main.h b/compiler/cpp/src/main.h
index 1281cc9..9a3a81e 100644
--- a/compiler/cpp/src/main.h
+++ b/compiler/cpp/src/main.h
@@ -1,22 +1,50 @@
 #ifndef T_MAIN_H
 #define T_MAIN_H
 
+#include <string>
+
 /**
  * Defined in the flex library
  */
 
-extern int yylex(void);
-extern int yyparse(void);
+int yylex(void);
+
+int yyparse(void);
 
 /**
  * Expected to be defined by Flex/Bison
  */
-extern void yyerror(char* fmt, ...);
+void yyerror(char* fmt, ...);
 
 /**
- * Parse debugging output, used to print warnings etc.
+ * Parse debugging output, used to print helpful info
  */
-extern void pdebug(char* fmt, ...);
+void pdebug(char* fmt, ...);
+
+/**
+ * Parser warning
+ */
+void pwarning(int level, char* fmt, ...);
+
+/**
+ * Failure!
+ */
+void failure(char* fmt, ...);
+
+/**
+ * Converts a string filename into a thrift program name
+ */
+std::string program_name(std::string filename);
+
+/**
+ * Gets the directory path of a filename
+ */
+std::string directory_name(std::string filename);
+
+/**
+ * Get the absolute path for an include file
+ */
+std::string include_file(std::string filename);
 
 /**
  * Flex utilities
diff --git a/compiler/cpp/src/parse/t_enum.h b/compiler/cpp/src/parse/t_enum.h
index 4b6fe36..002ca82 100644
--- a/compiler/cpp/src/parse/t_enum.h
+++ b/compiler/cpp/src/parse/t_enum.h
@@ -11,7 +11,8 @@
  */
 class t_enum : public t_type {
  public:
-  t_enum() {}
+  t_enum(t_program* program) :
+    t_type(program) {}
 
   void set_name(std::string name) {
     name_ = name;
diff --git a/compiler/cpp/src/parse/t_function.h b/compiler/cpp/src/parse/t_function.h
index 3d07171..6f06abe 100644
--- a/compiler/cpp/src/parse/t_function.h
+++ b/compiler/cpp/src/parse/t_function.h
@@ -22,7 +22,7 @@
     name_(name),
     arglist_(arglist),
     async_(async) {
-    xceptions_ = new t_struct;
+    xceptions_ = new t_struct(NULL);
   }
 
   t_function(t_type* returntype,
diff --git a/compiler/cpp/src/parse/t_program.h b/compiler/cpp/src/parse/t_program.h
index 5e58654..a3270ad 100644
--- a/compiler/cpp/src/parse/t_program.h
+++ b/compiler/cpp/src/parse/t_program.h
@@ -5,6 +5,10 @@
 #include <string>
 #include <vector>
 
+// For program_name()
+#include "main.h"
+
+#include "t_scope.h"
 #include "t_base_type.h"
 #include "t_typedef.h"
 #include "t_enum.h"
@@ -30,38 +34,26 @@
  */
 class t_program {
  public:
-  t_program(std::string name) :
-    name_(name),
-    namespace_() {
-    type_void   = new t_base_type("void",   t_base_type::TYPE_VOID);
-    type_string = new t_base_type("string", t_base_type::TYPE_STRING);
-    type_bool   = new t_base_type("bool",   t_base_type::TYPE_BOOL);
-    type_byte   = new t_base_type("byte",   t_base_type::TYPE_BYTE);
-    type_i16    = new t_base_type("i16",    t_base_type::TYPE_I16);
-    type_i32    = new t_base_type("i32",    t_base_type::TYPE_I32);
-    type_i64    = new t_base_type("i64",    t_base_type::TYPE_I64);
-    type_double = new t_base_type("double", t_base_type::TYPE_DOUBLE);
+  t_program(std::string path, std::string name) :
+    path_(path), 
+    name_(name) {
+    scope_ = new t_scope();
   }
 
-  ~t_program() {
-    delete type_string;
-    delete type_bool;
-    delete type_byte;
-    delete type_i16;
-    delete type_i32;
-    delete type_i64;
-    delete type_double;
+  t_program(std::string path) :
+    path_(path) {
+    name_ = program_name(path);
+    scope_ = new t_scope();
   }
 
+  // Path accessor   
+  const std::string& get_path() const { return path_; }
+
   // Name accessor
-  const std::string& get_name() const {
-    return name_;
-  }
+  const std::string& get_name() const { return name_; }
 
   // Namespace
-  const std::string& get_namespace() const {
-    return namespace_;
-  }
+  const std::string& get_namespace() const { return namespace_; }
 
   // Accessors for program elements
   const std::vector<t_typedef*>& get_typedefs()  const { return typedefs_;  }
@@ -70,57 +62,67 @@
   const std::vector<t_struct*>&  get_xceptions() const { return xceptions_; }
   const std::vector<t_service*>& get_services()  const { return services_;  }
 
-  // Accessors for global types
-  t_type* get_void_type()   const { return type_void;   }
-  t_type* get_string_type() const { return type_string; }
-  t_type* get_bool_type()   const { return type_bool;   }
-  t_type* get_byte_type()   const { return type_byte;   }
-  t_type* get_i16_type()    const { return type_i16;    }
-  t_type* get_i32_type()    const { return type_i32;    }
-  t_type* get_i64_type()    const { return type_i64;    }
-  t_type* get_double_type() const { return type_double; }
+  // Program elements
+  void add_typedef  (t_typedef* td) { typedefs_.push_back(td);  }
+  void add_enum     (t_enum*    te) { enums_.push_back(te);     }
+  void add_struct   (t_struct*  ts) { structs_.push_back(ts);   }
+  void add_xception (t_struct*  tx) { xceptions_.push_back(tx); }
+  void add_service  (t_service* ts) { services_.push_back(ts);  }
 
-  // Custom data type lookup
-  t_type* get_custom_type(std::string name) {
-    return custom_types_[name];
-  }
+  // Programs to include
+  const std::vector<t_program*>& get_includes() const { return includes_; }
 
-  // New program element addition
-
+  // Scoping and namespacing
   void set_namespace(std::string name) {
     namespace_ = name;
   }
 
-  void add_typedef(t_typedef* td) {
-    typedefs_.push_back(td);
-    add_custom_type(td->get_symbolic(), td);
+  // Scope accessor
+  t_scope* scope() {
+    return scope_;
   }
 
-  void add_enum(t_enum* te) {
-    enums_.push_back(te);
-    add_custom_type(te->get_name(), te);
+  // Includes
+
+  void add_include(std::string path) {
+    includes_.push_back(new t_program(path));
   }
 
-  void add_struct(t_struct* ts) {
-    structs_.push_back(ts);
-    add_custom_type(ts->get_name(), ts);
+  std::vector<t_program*>& get_includes() {
+    return includes_;
   }
 
-  void add_xception(t_struct* tx) {
-    xceptions_.push_back(tx);
-    add_custom_type(tx->get_name(), tx);
+  // Language specific namespace / packaging
+
+  void set_cpp_namespace(std::string cpp_namespace) {
+    cpp_namespace_ = cpp_namespace;
   }
 
-  void add_service(t_service* ts) {
-    services_.push_back(ts);
+  const std::string& get_cpp_namespace() const {
+    return cpp_namespace_;
   }
 
+  void add_cpp_include(std::string path) {
+    cpp_includes_.push_back(path);
+  }
+
+  const std::vector<std::string>& get_cpp_includes() {
+    return cpp_includes_;
+  }
+
+  void set_java_package(std::string java_package) {
+    java_package_ = java_package;
+  }
+
+  const std::string& get_java_package() const {
+    return java_package_;
+  }
+
+
  private:
 
-  // Add custom type for lookup
-  void add_custom_type(std::string name, t_type* type) {
-    custom_types_[name] = type;
-  }
+  // File path
+  std::string path_;
 
   // Name
   std::string name_;
@@ -128,25 +130,28 @@
   // Namespace
   std::string namespace_;
 
-  // Components
-  std::vector<t_typedef*>  typedefs_;
-  std::vector<t_enum*>     enums_;
-  std::vector<t_struct*>   structs_;
-  std::vector<t_struct*>   xceptions_;
-  std::vector<t_service*>  services_;
+  // Included programs
+  std::vector<t_program*> includes_;
 
-  // Type map
-  std::map<std::string, t_type*> custom_types_;
+  // Identifier lookup scope
+  t_scope* scope_;
 
-  // Global base types
-  t_type* type_void;
-  t_type* type_string;
-  t_type* type_bool;
-  t_type* type_byte;
-  t_type* type_i16;
-  t_type* type_i32;
-  t_type* type_i64;
-  t_type* type_double;
+  // Components to generate code for
+  std::vector<t_typedef*> typedefs_;
+  std::vector<t_enum*>    enums_;
+  std::vector<t_struct*>  structs_;
+  std::vector<t_struct*>  xceptions_;
+  std::vector<t_service*> services_;
+
+  // C++ namespace
+  std::string cpp_namespace_;
+
+  // C++ extra includes
+  std::vector<std::string> cpp_includes_;
+
+  // Java package
+  std::string java_package_;
+
 };
 
 #endif
diff --git a/compiler/cpp/src/parse/t_scope.h b/compiler/cpp/src/parse/t_scope.h
new file mode 100644
index 0000000..504393b
--- /dev/null
+++ b/compiler/cpp/src/parse/t_scope.h
@@ -0,0 +1,57 @@
+#ifndef T_SCOPE_H
+#define T_SCOPE_H
+
+#include <map>
+#include <string>
+
+#include "t_type.h"
+#include "t_service.h"
+
+/**
+ * This represents a variable scope used for looking up predefined types and
+ * services. Typically, a scope is associated with a t_program. Scopes are not
+ * used to determine code generation, but rather to resolve identifiers at
+ * parse time.
+ *
+ * @author Mark Slee <mcslee@facebook.com>
+ */
+class t_scope {
+ public:
+  t_scope() {}
+
+  void add_type(std::string name, t_type* type) {
+    types_[name] = type;
+  }
+
+  t_type* get_type(std::string name) {
+    return types_[name];
+  }
+
+  void add_service(std::string name, t_service* service) {
+    services_[name] = service;
+  }
+
+  t_service* get_service(std::string name) {
+    return services_[name];
+  }
+
+  void print() {
+    std::map<std::string, t_type*>::iterator iter;
+    for (iter = types_.begin(); iter != types_.end(); ++iter) {
+      printf("%s => %s\n",
+             iter->first.c_str(),
+             iter->second->get_name().c_str());
+    }
+  }
+
+ private:
+  
+  // Map of names to types
+  std::map<std::string, t_type*> types_;
+
+  // Map of names to services
+  std::map<std::string, t_service*> services_; 
+ 
+};
+
+#endif
diff --git a/compiler/cpp/src/parse/t_service.h b/compiler/cpp/src/parse/t_service.h
index 6bb5e5d..52280a4 100644
--- a/compiler/cpp/src/parse/t_service.h
+++ b/compiler/cpp/src/parse/t_service.h
@@ -4,34 +4,42 @@
 #include "t_function.h"
 #include <vector>
 
+class t_program;
+
 /**
  * A service consists of a set of functions.
  *
  * @author Mark Slee <mcslee@facebook.com>
  */
-class t_service {
+class t_service : public t_type {
  public:
-  t_service() {}
+  t_service(t_program* program) :
+    t_type(program),
+    extends_(NULL) {}
 
-  void set_name(std::string name) {
-    name_ = name;
+  bool is_service() const {
+    return true;
+  }
+
+  void set_extends(t_service* extends) {
+    extends_ = extends;
   }
 
   void add_function(t_function* func) {
     functions_.push_back(func);
   }
 
-  const std::string& get_name() const {
-    return name_;
-  }
-
   const std::vector<t_function*>& get_functions() const {
     return functions_;
   }
 
+  t_service* get_extends() {
+    return extends_;
+  }
+
  private:
-  std::string name_;
   std::vector<t_function*> functions_;
+  t_service* extends_;
 };
 
 #endif
diff --git a/compiler/cpp/src/parse/t_struct.h b/compiler/cpp/src/parse/t_struct.h
index 8768c5f..ce5f752 100644
--- a/compiler/cpp/src/parse/t_struct.h
+++ b/compiler/cpp/src/parse/t_struct.h
@@ -7,6 +7,9 @@
 #include "t_type.h"
 #include "t_field.h"
 
+// Forward declare that puppy
+class t_program;
+
 /**
  * A struct is a container for a set of member fields that has a name. Structs
  * are also used to implement exception types.
@@ -15,11 +18,12 @@
  */
 class t_struct : public t_type {
  public:
-  t_struct() :
+  t_struct(t_program* program) :
+    t_type(program),
     is_xception_(false) {}
 
-  t_struct(const std::string& name) :
-    t_type(name),
+  t_struct(t_program* program, const std::string& name) :
+    t_type(program, name),
     is_xception_(false) {}
 
   void set_name(const std::string& name) {
diff --git a/compiler/cpp/src/parse/t_type.h b/compiler/cpp/src/parse/t_type.h
index 1d0a2ed..9589f02 100644
--- a/compiler/cpp/src/parse/t_type.h
+++ b/compiler/cpp/src/parse/t_type.h
@@ -3,6 +3,8 @@
 
 #include <string>
 
+class t_program;
+
 /**
  * Generic representation of a thrift type. These objects are used by the
  * parser module to build up a tree of object that are all explicitly typed.
@@ -16,7 +18,13 @@
  public:
   virtual ~t_type() {}
 
-  virtual const std::string& get_name() const { return name_; }
+  virtual void set_name(std::string name) {
+    name_ = name;
+  }
+
+  virtual const std::string& get_name() const {
+    return name_;
+  }
 
   virtual bool is_void()      const { return false; }
   virtual bool is_base_type() const { return false; }
@@ -28,13 +36,26 @@
   virtual bool is_list()      const { return false; }
   virtual bool is_set()       const { return false; }
   virtual bool is_map()       const { return false; }
+  virtual bool is_service()   const { return false; }
+
+  t_program* get_program() {
+    return program_;
+  }
 
  protected:
   t_type() {}
 
-  t_type(std::string name) :
+  t_type(t_program* program) :
+    program_(program) {}
+
+  t_type(t_program* program, std::string name) :
+    program_(program),
     name_(name) {}
 
+  t_type(std::string name) :
+    name_(name) {}
+    
+  t_program* program_;
   std::string name_;
 };
 
diff --git a/compiler/cpp/src/parse/t_typedef.h b/compiler/cpp/src/parse/t_typedef.h
index 8973201..cc7f25c 100644
--- a/compiler/cpp/src/parse/t_typedef.h
+++ b/compiler/cpp/src/parse/t_typedef.h
@@ -14,8 +14,8 @@
  */
 class t_typedef : public t_type {
  public:
-  t_typedef(t_type* type, std::string symbolic) :
-    t_type(symbolic),
+  t_typedef(t_program* program, t_type* type, std::string symbolic) :
+    t_type(program, symbolic),
     type_(type),
     symbolic_(symbolic) {}
 
diff --git a/compiler/cpp/src/thrift.l b/compiler/cpp/src/thrift.l
index e72565e..839060e 100644
--- a/compiler/cpp/src/thrift.l
+++ b/compiler/cpp/src/thrift.l
@@ -33,8 +33,8 @@
 multicomm    ("/*""/"*([^*/]|[^*]"/"|"*"[^/])*"*"*"*/")
 comment      ("//"[^\n]*)
 unixcomment  ("#"[^\n]*)
-symbol       ([\,\{\}\(\)\=<>])
-cpptype      ("[cpp:".*"]")
+symbol       ([:\,\{\}\(\)\=<>\[\]])
+literal      ("\""[^"]*"\"")
 
 %%
 
@@ -45,41 +45,47 @@
 
 {symbol}      { return yytext[0]; }
 
-"namespace"   { return tok_namespace; }
-"void"        { return tok_void;      }
-"bool"        { return tok_bool;      }
-"byte"        { return tok_byte;      }
-"i16"         { return tok_i16;       }
-"i32"         { return tok_i32;       }
-"i64"         { return tok_i64;       }
-"double"      { return tok_double;    }
-"string"      { return tok_string;    }
-"map"         { return tok_map;       }
-"list"        { return tok_list;      }
-"set"         { return tok_set;       }
-"async"       { return tok_async;     }
-"typedef"     { return tok_typedef;   }
-"struct"      { return tok_struct;    }
-"exception"   { return tok_xception;  }
-"throws"      { return tok_throws;    }
-"service"     { return tok_service;   }
-"enum"        { return tok_enum;      }
+"namespace"     { return tok_namespace;     }
+"cpp_namespace" { return tok_cpp_namespace; }
+"cpp_include"   { return tok_cpp_include;   }
+"cpp_type"      { return tok_cpp_type;      }
+"java_package"  { return tok_java_package;  }
+"include"       { return tok_include;       }
+
+"void"          { return tok_void;          }
+"bool"          { return tok_bool;          }
+"byte"          { return tok_byte;          }
+"i16"           { return tok_i16;           }
+"i32"           { return tok_i32;           }
+"i64"           { return tok_i64;           }
+"double"        { return tok_double;        }
+"string"        { return tok_string;        }
+"map"           { return tok_map;           }
+"list"          { return tok_list;          }
+"set"           { return tok_set;           }
+"async"         { return tok_async;         }
+"typedef"       { return tok_typedef;       }
+"struct"        { return tok_struct;        }
+"exception"     { return tok_xception;      }
+"extends"       { return tok_extends;       }
+"throws"        { return tok_throws;        }
+"service"       { return tok_service;       }
+"enum"          { return tok_enum;          }
 
 {intconstant} {
   yylval.iconst = atoi(yytext);
   return tok_int_constant;
 }
 
-{cpptype} {
-  yylval.id = strdup(yytext+5);
-  yylval.id[strlen(yylval.id)-1] = '\0';
-  return tok_cpptype;
-}
-
 {identifier} {
   yylval.id = strdup(yytext);
   return tok_identifier;
 }
 
+{literal} {
+  yylval.id = strdup(yytext+1);
+  yylval.id[strlen(yylval.id)-1] = '\0';
+  return tok_literal;
+}
 
 %%
diff --git a/compiler/cpp/src/thrift.y b/compiler/cpp/src/thrift.y
index 3bf8b53..7d1ba1e 100644
--- a/compiler/cpp/src/thrift.y
+++ b/compiler/cpp/src/thrift.y
@@ -12,6 +12,7 @@
 #include "main.h"
 #include "globals.h"
 #include "parse/t_program.h"
+#include "parse/t_scope.h"
 
 /**
  * This global variable is used for automatic numbering of field indices etc.
@@ -44,7 +45,7 @@
  * Strings identifier
  */
 %token<id>     tok_identifier
-%token<id>     tok_cpptype
+%token<id>     tok_literal
 
 /**
  * Integer constant value
@@ -52,9 +53,14 @@
 %token<iconst> tok_int_constant
 
 /**
- * Namespace keyword
+ * Header keywoards
  */
+%token tok_include
 %token tok_namespace
+%token tok_cpp_namespace
+%token tok_cpp_include
+%token tok_cpp_type
+%token tok_java_package
 
 /**
  * Base datatype keywords
@@ -87,6 +93,7 @@
 %token tok_struct
 %token tok_xception
 %token tok_throws
+%token tok_extends
 %token tok_service
 %token tok_enum
 
@@ -94,14 +101,14 @@
  * Grammar nodes
  */
 
-%type<id>        Namespace
-
 %type<ttype>     BaseType
 %type<ttype>     ContainerType
 %type<ttype>     MapType
 %type<ttype>     SetType
 %type<ttype>     ListType
 
+%type<ttype>     TypeDefinition
+
 %type<ttypedef>  Typedef
 %type<ttype>     DefinitionType
 
@@ -122,6 +129,7 @@
 %type<tservice>  FunctionList
 
 %type<tstruct>   ThrowsOptional
+%type<tservice>  ExtendsOptional
 %type<tbool>     AsyncOptional
 %type<id>        CppTypeOptional
 
@@ -136,10 +144,67 @@
  */
 
 Program:
-  DefinitionList
-  {
-    pdebug("Program -> DefinitionList");
-  }
+  HeaderList DefinitionList
+    {
+      pdebug("Program -> Headers DefinitionList");
+    }
+
+HeaderList:
+  HeaderList Header
+    {
+      pdebug("HeaderList -> HeaderList Header");
+    }
+|
+    {
+      pdebug("HeaderList -> ");
+    }
+
+Header:
+  Include
+    {
+      pdebug("Header -> Include");
+    }
+| tok_namespace tok_identifier
+    {
+      pwarning(1, "'namespace' is deprecated. Use 'cpp_namespace' and/or 'java_package' instead");
+      if (g_parse_mode == PROGRAM) {
+        g_program->set_cpp_namespace($2);
+        g_program->set_java_package($2);
+      }
+    }
+| tok_cpp_namespace tok_identifier
+    {
+      pdebug("Header -> tok_cpp_namespace tok_identifier");
+      if (g_parse_mode == PROGRAM) {
+        g_program->set_cpp_namespace($2);
+      }
+    }
+| tok_cpp_include tok_literal
+    {
+      pdebug("Header -> tok_cpp_include tok_literal");
+      if (g_parse_mode == PROGRAM) {
+        g_program->add_cpp_include($2);
+      }
+    }
+| tok_java_package tok_identifier
+    {
+      pdebug("Header -> tok_java_package tok_identifier");
+      if (g_parse_mode == PROGRAM) {
+        g_program->set_java_package($2);
+      }
+    }
+
+Include:
+  tok_include tok_literal
+    {
+      pdebug("Include -> tok_include tok_literal");     
+      if (g_parse_mode == INCLUDES) {
+        std::string path = include_file(std::string($2));
+        if (!path.empty()) {
+          g_program->add_include(path);
+        }
+      }
+    }
 
 DefinitionList:
   DefinitionList Definition
@@ -152,49 +217,63 @@
     }
 
 Definition:
-  Namespace
+  TypeDefinition
     {
-      pdebug("Definition -> Namespace");
-      g_program->set_namespace($1);
-    }
-| Typedef
-    {
-      pdebug("Definition -> Typedef");
-      g_program->add_typedef($1);
-    }
-| Enum
-    {
-      pdebug("Definition -> Enum");
-      g_program->add_enum($1);
-    }
-| Struct
-    {
-      pdebug("Definition -> Struct");
-      g_program->add_struct($1);
-    }
-| Xception
-    { 
-      pdebug("Definition -> Xception");
-      g_program->add_xception($1);     
+      pdebug("Definition -> TypeDefinition");
+      if (g_parse_mode == PROGRAM) {
+        g_scope->add_type($1->get_name(), $1);
+        if (g_parent_scope != NULL) {
+          g_parent_scope->add_type(g_parent_prefix + $1->get_name(), $1);
+        }
+      }
     }
 | Service
     {
       pdebug("Definition -> Service");
-      g_program->add_service($1);
+      if (g_parse_mode == PROGRAM) {
+        g_scope->add_service($1->get_name(), $1);
+        if (g_parent_scope != NULL) {
+          g_parent_scope->add_service(g_parent_prefix + $1->get_name(), $1);
+        }
+        g_program->add_service($1);
+      }
     }
 
-Namespace:
-  tok_namespace tok_identifier
+TypeDefinition:
+  Typedef
     {
-      pdebug("Namespace -> tok_namespace tok_identifier");
-      $$ = $2;
+      pdebug("TypeDefinition -> Typedef");
+      if (g_parse_mode == PROGRAM) {
+        g_program->add_typedef($1);
+      }
+    }
+| Enum
+    {
+      pdebug("TypeDefinition -> Enum");
+      if (g_parse_mode == PROGRAM) {
+        g_program->add_enum($1);
+      }
+    }
+| Struct
+    {
+      pdebug("TypeDefinition -> Struct");
+      if (g_parse_mode == PROGRAM) {
+        g_program->add_struct($1);
+      }
+    }
+| Xception
+    { 
+      pdebug("TypeDefinition -> Xception");
+      if (g_parse_mode == PROGRAM) {
+        g_program->add_xception($1);
+      }
     }
 
 Typedef:
   tok_typedef DefinitionType tok_identifier
     {
       pdebug("TypeDef -> tok_typedef DefinitionType tok_identifier");
-      t_typedef *td = new t_typedef($2, $3);
+      t_typedef *td = new t_typedef(g_program, $2, $3);
       $$ = td;
     }
 
@@ -216,13 +295,13 @@
 | EnumDef
     {
       pdebug("EnumDefList -> EnumDef");
-      $$ = new t_enum;
+      $$ = new t_enum(g_program);
       $$->append($1);
     }
 |
     {
       pdebug("EnumDefList -> ");
-      $$ = new t_enum;
+      $$ = new t_enum(g_program);
     }
 
 EnumDef:
@@ -230,7 +309,7 @@
     {
       pdebug("EnumDef => tok_identifier = tok_int_constant");
       if ($3 < 0) {
-        printf("WARNING (%d): Negative value supplied for enum %s.\n", yylineno, $1);
+        pwarning(1, "Negative value supplied for enum %s.\n", $1);
       }
       $$ = new t_constant($1, $3);
     }
@@ -261,11 +340,30 @@
     }
 
 Service:
-  tok_service tok_identifier '{' FunctionList '}'
+  tok_service tok_identifier ExtendsOptional '{' FunctionList '}'
     {
       pdebug("Service -> tok_service tok_identifier { FunctionList }");
-      $$ = $4;
+      $$ = $5;
       $$->set_name($2);
+      $$->set_extends($3);
+    }
+
+ExtendsOptional:
+  tok_extends tok_identifier
+    {
+      pdebug("ExtendsOptional -> tok_extends tok_identifier");
+      $$ = NULL;
+      if (g_parse_mode == PROGRAM) {
+        $$ = g_scope->get_service($2);
+        if ($$ == NULL) {
+          yyerror("Service \"%s\" has not been defined.", $2);
+          exit(1);
+        }
+      }
+    }
+|
+    {
+      $$ = NULL;
     }
 
 FunctionList:
@@ -278,7 +376,7 @@
 |
     {
       pdebug("FunctionList -> ");
-      $$ = new t_service;
+      $$ = new t_service(g_program);
     }
 
 CommaOptional:
@@ -308,11 +406,12 @@
 ThrowsOptional:
   tok_throws '(' FieldList ')'
     {
+      pdebug("ThrowsOptional -> tok_throws ( FieldList )");
       $$ = $3;
     }
 |
     {
-      $$ = new t_struct;
+      $$ = new t_struct(g_program);
     }
 
 FieldList:
@@ -325,31 +424,41 @@
 | Field
     {
       pdebug("FieldList -> Field");
-      $$ = new t_struct;
+      $$ = new t_struct(g_program);
       $$->append($1);
     }
 |
     {
       pdebug("FieldList -> ");
-      $$ = new t_struct;
+      $$ = new t_struct(g_program);
     }
 
 Field:
-  FieldType tok_identifier '=' tok_int_constant
+  tok_int_constant ':' FieldType tok_identifier
     {
-      pdebug("Field -> FieldType tok_identifier = tok_int_constant");
-      if ($4 <= 0) {
-        printf("WARNING (%d): Nonpositive value (%d) not allowed as a field key for '%s'.\n", yylineno, $4, $2);
-        $4 = y_field_val--;
+      pdebug("tok_int_constant : Field -> FieldType tok_identifier");
+      if ($1 <= 0) {
+        pwarning(1, "Nonpositive value (%d) not allowed as a field key for '%s'.\n", $1, $4);
+        $1 = y_field_val--;
       }
-      $$ = new t_field($1, $2, $4);
+      $$ = new t_field($3, $4, $1);
     }
 | FieldType tok_identifier
     {
       pdebug("Field -> FieldType tok_identifier");
-      printf("WARNING (%d): No field key specified for '%s', resulting protocol may have conflicts or not be backwards compatible!\n", yylineno, $2);
+      pwarning(2, "No field key specified for '%s', resulting protocol may have conflicts or not be backwards compatible!\n", $2);
       $$ = new t_field($1, $2, y_field_val--);
     }
+| FieldType tok_identifier '=' tok_int_constant
+    {
+      pwarning(1, "Trailing = id notation is deprecated. Use 'Id: Type Name' notatio instead"); 
+      pdebug("Field -> FieldType tok_identifier = tok_int_constant");
+      if ($4 <= 0) {
+        pwarning(1, "Nonpositive value (%d) not allowed as a field key for '%s'.\n", $4, $2);
+        $4 = y_field_val--;
+      }
+      $$ = new t_field($1, $2, $4);
+    }
 
 DefinitionType:
   BaseType
@@ -372,17 +481,23 @@
 | tok_void
     {
       pdebug("FunctionType -> tok_void");
-      $$ = g_program->get_void_type();
+      $$ = g_type_void;
     }
 
 FieldType:
   tok_identifier
     {
       pdebug("FieldType -> tok_identifier");
-      $$ = g_program->get_custom_type($1);
-      if ($$ == NULL) {
-        yyerror("Type \"%s\" has not been defined.", $1);
-        exit(1);
+      if (g_parse_mode == INCLUDES) {
+        // Ignore identifiers in include mode
+        $$ = NULL;
+      } else {
+        // Lookup the identifier in the current scope
+        $$ = g_scope->get_type($1);
+        if ($$ == NULL) {
+          yyerror("Type \"%s\" has not been defined.", $1);
+          exit(1);
+        }
       }
     }
 | BaseType
@@ -400,37 +515,37 @@
   tok_string
     {
       pdebug("BaseType -> tok_string");
-      $$ = g_program->get_string_type();
+      $$ = g_type_string;
     }
 | tok_bool
     {
       pdebug("BaseType -> tok_bool");
-      $$ = g_program->get_bool_type();
+      $$ = g_type_bool;
     }
 | tok_byte
     {
       pdebug("BaseType -> tok_byte");
-      $$ = g_program->get_byte_type();
+      $$ = g_type_byte;
     }
 | tok_i16
     {
       pdebug("BaseType -> tok_i16");
-      $$ = g_program->get_i16_type();
+      $$ = g_type_i16;
     }
 | tok_i32
     {
       pdebug("BaseType -> tok_i32");
-      $$ = g_program->get_i32_type();
+      $$ = g_type_i32;
     }
 | tok_i64
     {
       pdebug("BaseType -> tok_i64");
-      $$ = g_program->get_i64_type();
+      $$ = g_type_i64;
     }
 | tok_double
     {
       pdebug("BaseType -> tok_double");
-      $$ = g_program->get_double_type();
+      $$ = g_type_double;
     }
 
 ContainerType:
@@ -471,19 +586,19 @@
     }
 
 ListType:
-  tok_list CppTypeOptional '<' FieldType '>'
+  tok_list '<' FieldType '>' CppTypeOptional
     {
       pdebug("ListType -> tok_list<FieldType>");
-      $$ = new t_list($4);
-      if ($2 != NULL) {
-        ((t_container*)$$)->set_cpp_name(std::string($2));
+      $$ = new t_list($3);
+      if ($5 != NULL) {
+        ((t_container*)$$)->set_cpp_name(std::string($5));
       }
     }
 
 CppTypeOptional:
-  tok_cpptype
+  '[' tok_cpp_type tok_literal ']'
     {
-      $$ = $1;
+      $$ = $3;
     }
 |
     {