From 52f643df7c069228a799f19ae4b58a6ab8c05275 Mon Sep 17 00:00:00 2001 From: Mark Slee Date: Wed, 9 Aug 2006 00:03:43 +0000 Subject: [PATCH] Thrift compiler support for inline PHP client code Summary: Option to generate inline PHP code, as well as support for the async modifier keyword and the abstraction of function calls into a send and recv component git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664740 13f79535-47bb-0310-9956-ffa450edef68 --- compiler/Makefile | 4 +- compiler/src/generate/t_cpp_generator.cc | 113 ++++- compiler/src/generate/t_java_generator.cc | 223 ++++++--- compiler/src/generate/t_java_generator.h | 4 +- compiler/src/generate/t_php_generator.cc | 556 +++++++++++++++------- compiler/src/generate/t_php_generator.h | 10 +- compiler/src/main.cc | 8 +- compiler/src/parse/t_function.h | 15 +- compiler/src/thrift.l | 3 +- compiler/src/thrift.y | 18 +- 10 files changed, 668 insertions(+), 286 deletions(-) diff --git a/compiler/Makefile b/compiler/Makefile index 26a8b319..6b12853f 100644 --- a/compiler/Makefile +++ b/compiler/Makefile @@ -35,9 +35,9 @@ BIN_DIR = bin/ # Source files SRC_FILES = main.cc \ generate/t_generator.cc \ + generate/t_php_generator.cc \ generate/t_cpp_generator.cc \ - generate/t_java_generator.cc \ - generate/t_php_generator.cc + generate/t_java_generator.cc # Autogenerated files GEN_FILES = thrift.tab.hh \ diff --git a/compiler/src/generate/t_cpp_generator.cc b/compiler/src/generate/t_cpp_generator.cc index b4ad1352..6014e5f4 100644 --- a/compiler/src/generate/t_cpp_generator.cc +++ b/compiler/src/generate/t_cpp_generator.cc @@ -220,7 +220,18 @@ void t_cpp_generator::generate_service_client(t_service* tservice) { vector functions = tservice->get_functions(); vector::const_iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { + t_function send_function(g_program->get_void_type(), + 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_function recv_function((*f_iter)->get_returntype(), + string("recv_") + (*f_iter)->get_name(), + &noargs); + indent(f_header_) << function_signature(&recv_function) << ";" << endl; + } } indent_down(); @@ -245,8 +256,47 @@ void t_cpp_generator::generate_service_client(t_service* tservice) { string funname = (*f_iter)->get_name(); // Open function - f_service_ << - function_signature(*f_iter, scope) << "" << endl; + indent(f_service_) << + function_signature(*f_iter, scope) << endl; + scope_up(f_service_); + indent(f_service_) << + "send_" << funname << "("; + + // Get the struct of function call params + t_struct* arg_struct = (*f_iter)->get_arglist(); + + // Declare the function arguments + const vector& fields = arg_struct->get_members(); + vector::const_iterator fld_iter; + bool first = true; + for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { + if (first) { + first = false; + } else { + f_service_ << ", "; + } + f_service_ << (*fld_iter)->get_name(); + } + f_service_ << ");" << endl; + + if (!(*f_iter)->is_async()) { + f_service_ << indent(); + if (!(*f_iter)->get_returntype()->is_void()) { + f_service_ << "return "; + } + f_service_ << + "recv_" << funname << "();" << endl; + } + scope_down(f_service_); + f_service_ << endl; + + t_function send_function(g_program->get_void_type(), + string("send_") + (*f_iter)->get_name(), + (*f_iter)->get_arglist()); + + // Open function + indent(f_service_) << + function_signature(&send_function, scope) << endl; scope_up(f_service_); // Serialize the request @@ -273,33 +323,48 @@ void t_cpp_generator::generate_service_client(t_service* tservice) { // Flush the request indent(f_service_) << "_otrans->flush();" << endl; + + scope_down(f_service_); + f_service_ << endl; - // Read the response - t_struct result_struct((*f_iter)->get_name() + "_result"); - t_field result_field((*f_iter)->get_returntype(), "_result"); - - // Add a field to the return struct if non void - if (!(*f_iter)->get_returntype()->is_void()) { + if (!(*f_iter)->is_async()) { + t_struct noargs; + t_function recv_function((*f_iter)->get_returntype(), + string("recv_") + (*f_iter)->get_name(), + &noargs); + // Open function indent(f_service_) << - type_name((*f_iter)->get_returntype()) << " _result;" << endl; - result_struct.append(&result_field); - } - - // Deserialize response struct - generate_deserialize_struct(&result_struct); + function_signature(&recv_function, scope) << endl; + scope_up(f_service_); - // Careful, only return _result if not a void function - if (!(*f_iter)->get_returntype()->is_void()) { - indent(f_service_) << - "return _result;" << endl; - } else { - indent(f_service_) << - "return;" << endl; + // Read the response + t_struct result_struct((*f_iter)->get_name() + "_result"); + t_field result_field((*f_iter)->get_returntype(), "_result"); + + // Add a field to the return struct if non void + if (!(*f_iter)->get_returntype()->is_void()) { + indent(f_service_) << + type_name((*f_iter)->get_returntype()) << " _result;" << endl; + result_struct.append(&result_field); + } + + // Deserialize response struct + generate_deserialize_struct(&result_struct); + + // Careful, only return _result if not a void function + if (!(*f_iter)->get_returntype()->is_void()) { + indent(f_service_) << + "return _result;" << endl; + } else { + indent(f_service_) << + "return;" << endl; + } + + // Close function + scope_down(f_service_); + f_service_ << endl; } - // Close function - scope_down(f_service_); - indent(f_service_) << endl; } } diff --git a/compiler/src/generate/t_java_generator.cc b/compiler/src/generate/t_java_generator.cc index e4236fc7..13b50220 100644 --- a/compiler/src/generate/t_java_generator.cc +++ b/compiler/src/generate/t_java_generator.cc @@ -33,7 +33,6 @@ string t_java_generator::java_type_imports() { "import java.util.HashMap;\n" + "import java.util.HashSet;\n" + "import com.facebook.thrift.*;\n" + - "import com.facebook.thrift.types.*;\n" + "import com.facebook.thrift.protocol.TString;\n\n"; } @@ -73,8 +72,7 @@ void t_java_generator::generate_enum(t_enum* tenum) { f_enum << autogen_comment() << - java_package() << - "import com.facebook.thrift.types.Int32;" << endl << endl; + java_package() << endl; f_enum << "public class " << tenum->get_name() << " "; @@ -91,8 +89,8 @@ void t_java_generator::generate_enum(t_enum* tenum) { } indent(f_enum) << - "public static final Int32 " << (*c_iter)->get_name() << - " = new Int32(" << value << ");" << endl; + "public static final int " << (*c_iter)->get_name() << + " = " << value << ";" << endl; } scope_down(f_enum); @@ -236,6 +234,45 @@ void t_java_generator::generate_service_client(t_service* tservice) { indent(f_service_) << "public " << function_signature(*f_iter) << " throws TException" << endl; scope_up(f_service_); + indent(f_service_) << + "send_" << funname << "("; + + // Get the struct of function call params + t_struct* arg_struct = (*f_iter)->get_arglist(); + + // Declare the function arguments + const vector& fields = arg_struct->get_members(); + vector::const_iterator fld_iter; + bool first = true; + for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { + if (first) { + first = false; + } else { + f_service_ << ", "; + } + f_service_ << (*fld_iter)->get_name(); + } + f_service_ << ");" << endl; + + if (!(*f_iter)->is_async()) { + f_service_ << indent(); + if (!(*f_iter)->get_returntype()->is_void()) { + f_service_ << "return "; + } + f_service_ << + "recv_" << funname << "();" << endl; + } + scope_down(f_service_); + f_service_ << endl; + + t_function send_function(g_program->get_void_type(), + string("send_") + (*f_iter)->get_name(), + (*f_iter)->get_arglist()); + + // Open function + indent(f_service_) << + "public " << function_signature(&send_function) << " throws TException" << endl; + scope_up(f_service_); // Serialize the request f_service_ << @@ -247,7 +284,7 @@ void t_java_generator::generate_service_client(t_service* tservice) { "new TField(\"name\", TType.STRING, 0));" << endl << indent() << "_oprot.writeString(_otrans, " << - "new TString(\"" << funname << "\"));" << endl << + "\"" << funname << "\");" << endl << indent() << "_oprot.writeFieldEnd(_otrans);" << endl << indent() << @@ -266,32 +303,46 @@ void t_java_generator::generate_service_client(t_service* tservice) { indent(f_service_) << "_otrans.flush();" << endl; - // Read the response - t_struct result_struct((*f_iter)->get_name() + "_result"); - t_field result_field((*f_iter)->get_returntype(), "_result"); - - // Add a field to the return struct if non void - if (!(*f_iter)->get_returntype()->is_void()) { - indent(f_service_) << - declare_field(&result_field, true) << endl; - result_struct.append(&result_field); - } - - // Deserialize response struct - generate_deserialize_struct(&result_struct); + scope_down(f_service_); + f_service_ << endl; - // Careful, only return _result if not a void function - if (!(*f_iter)->get_returntype()->is_void()) { + if (!(*f_iter)->is_async()) { + t_struct noargs; + t_function recv_function((*f_iter)->get_returntype(), + string("recv_") + (*f_iter)->get_name(), + &noargs); + // Open function indent(f_service_) << - "return _result;" << endl; - } else { - indent(f_service_) << - "return;" << endl; + "public " << function_signature(&recv_function) << " throws TException" << endl; + scope_up(f_service_); + + // Read the response + t_struct result_struct((*f_iter)->get_name() + "_result"); + t_field result_field((*f_iter)->get_returntype(), "_result"); + + // Add a field to the return struct if non void + if (!(*f_iter)->get_returntype()->is_void()) { + indent(f_service_) << + declare_field(&result_field, true) << endl; + result_struct.append(&result_field); + } + + // Deserialize response struct + generate_deserialize_struct(&result_struct); + + // Careful, only return _result if not a void function + if (!(*f_iter)->get_returntype()->is_void()) { + indent(f_service_) << + "return _result;" << endl; + } else { + indent(f_service_) << + "return;" << endl; + } + + // Close function + scope_down(f_service_); + f_service_ << endl; } - - // Close function - scope_down(f_service_); - f_service_ << endl; } indent_down(); @@ -356,21 +407,21 @@ void t_java_generator::generate_service_server(t_service* tservice) { f_service_ << indent() << - "TString _fname = new TString();" << endl << + "String _fname;" << endl << indent() << - "TStruct _struct = new TStruct();" << endl << + "TStruct _struct;" << endl << indent() << - "TField _field = new TField();" << endl << + "TField _field;" << endl << indent() << - "_iprot.readStructBegin(_itrans, _struct);" << endl << + "_struct = _iprot.readStructBegin(_itrans);" << endl << indent() << - "_iprot.readFieldBegin(_itrans, _field);" << endl << + "_field = _iprot.readFieldBegin(_itrans);" << endl << indent() << - "_iprot.readString(_itrans, _fname);" << endl << + "_fname = _iprot.readString(_itrans);" << endl << indent() << "_iprot.readFieldEnd(_itrans);" << endl << indent() << - "_iprot.readFieldBegin(_itrans, _field);" << endl; + "_field = _iprot.readFieldBegin(_itrans);" << endl; bool first = true; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { @@ -381,7 +432,7 @@ void t_java_generator::generate_service_server(t_service* tservice) { first = false; } f_service_ << - "if (_fname.value.equals(\"" << (*f_iter)->get_name() <<"\")) {" << endl; + "if (_fname.equals(\"" << (*f_iter)->get_name() <<"\")) {" << endl; indent_up(); indent(f_service_) << "process_" << (*f_iter)->get_name() << @@ -404,7 +455,7 @@ void t_java_generator::generate_service_server(t_service* tservice) { indent() << "_iprot.readFieldEnd(_itrans);" << endl << indent() << - "_iprot.readFieldBegin(_itrans, _field);" << endl << + "_field = _iprot.readFieldBegin(_itrans);" << endl << indent() << "_iprot.readStructEnd(_itrans);" << endl << indent() << @@ -514,7 +565,7 @@ void t_java_generator::generate_deserialize_field(t_field* tfield, } else if (type->is_base_type() || type->is_enum()) { indent(f_service_) << - "_iprot."; + name << " = _iprot."; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); @@ -524,28 +575,28 @@ void t_java_generator::generate_deserialize_field(t_field* tfield, name; break; case t_base_type::TYPE_STRING: - f_service_ << "readString(_itrans, " << name << ");"; + f_service_ << "readString(_itrans);"; break; case t_base_type::TYPE_BYTE: - f_service_ << "readByte(_itrans, " << name << ");"; + f_service_ << "readByte(_itrans);"; break; case t_base_type::TYPE_I32: - f_service_ << "readI32(_itrans, " << name << ");"; + f_service_ << "readI32(_itrans);"; break; case t_base_type::TYPE_U32: - f_service_ << "readU32(_itrans, " << name << ");"; + f_service_ << "readU32(_itrans);"; break; case t_base_type::TYPE_I64: - f_service_ << "readI64(_itrans, " << name << ");"; + f_service_ << "readI64(_itrans);"; break; case t_base_type::TYPE_U64: - f_service_ << "readU64(_itrans, " << name << ");"; + f_service_ << "readU64(_itrans);"; break; default: throw "compiler error: no C++ name for base type " + tbase; } } else if (type->is_enum()) { - f_service_ << "readI32(_itrans, " << name << ");"; + f_service_ << "readI32(_itrans);"; } f_service_ << endl; @@ -574,9 +625,8 @@ void t_java_generator::generate_deserialize_struct(t_struct* tstruct, // Declare stack tmp variables f_service_ << - indent() << "TStruct " << _struct << " = new TStruct();" << endl << - indent() << "TField " << _field << " = new TField();" << endl << - indent() << "_iprot.readStructBegin(_itrans, " << _struct << ");" << endl; + indent() << "TField " << _field << ";" << endl << + indent() << "TStruct " << _struct << " = _iprot.readStructBegin(_itrans);" << endl; // Loop over reading in fields indent(f_service_) << @@ -586,11 +636,11 @@ void t_java_generator::generate_deserialize_struct(t_struct* tstruct, // Read beginning field marker indent(f_service_) << - "_iprot.readFieldBegin(_itrans, " << _field << ");" << endl; + _field << " = _iprot.readFieldBegin(_itrans);" << endl; // Check for field STOP marker and break indent(f_service_) << - "if (" << _field << ".type.equals(TType.STOP)) { " << endl; + "if (" << _field << ".type == TType.STOP) { " << endl; indent_up(); indent(f_service_) << "break;" << endl; @@ -600,7 +650,7 @@ void t_java_generator::generate_deserialize_struct(t_struct* tstruct, // Switch statement on the field we are reading indent(f_service_) << - "switch ((int)" << _field << ".id.get())" << endl; + "switch ((int)" << _field << ".id)" << endl; scope_up(f_service_); @@ -656,16 +706,13 @@ void t_java_generator::generate_deserialize_container(t_type* ttype, // Declare variables, read header if (ttype->is_map()) { f_service_ << - indent() << "TMap " << obj << " = new TMap();" << endl << - indent() << "_iprot.readMapBegin(_itrans, " << obj << ");" << endl; + indent() << "TMap " << obj << " = _iprot.readMapBegin(_itrans);" << endl; } else if (ttype->is_set()) { f_service_ << - indent() << "TSet " << obj << " = new TSet();" << endl << - indent() << "_iprot.readSetBegin(_itrans, " << obj << ");" << endl; + indent() << "TSet " << obj << " = _iprot.readSetBegin(_itrans);" << endl; } else if (ttype->is_list()) { f_service_ << - indent() << "TList " << obj << " = new TList();" << endl << - indent() << "_iprot.readListBegin(_itrans, " << obj << ");" << endl; + indent() << "TList " << obj << " = _iprot.readListBegin(_itrans);" << endl; } @@ -673,7 +720,7 @@ void t_java_generator::generate_deserialize_container(t_type* ttype, string i = tmp("_i"); indent(f_service_) << "for (int " << i << " = 0; " << - i << " < " << obj << ".size.get()" << "; " << + i << " < " << obj << ".size" << "; " << "++" << i << ")" << endl; scope_up(f_service_); @@ -853,7 +900,7 @@ void t_java_generator::generate_serialize_struct(t_struct* tstruct, indent() << _field << ".type = " << type_to_enum((*f_iter)->get_type()) << ";" << endl << indent() << - _field << ".id.set(" << (*f_iter)->get_key() << ");" << endl << + _field << ".id = " << (*f_iter)->get_key() << ";" << endl << indent() << "_oprot.writeFieldBegin(_otrans, " << _field << ");" << endl; // Write field contents @@ -975,28 +1022,29 @@ void t_java_generator::generate_serialize_list_element(t_list* tlist, * Returns a Java type name * * @param ttype The type + * @param container Is the type going inside a container? */ -string t_java_generator::type_name(t_type* ttype) { +string t_java_generator::type_name(t_type* ttype, bool in_container) { // In Java typedefs are just resolved to their real type while (ttype->is_typedef()) { ttype = ((t_typedef*)ttype)->get_type(); } if (ttype->is_base_type()) { - return base_type_name(((t_base_type*)ttype)->get_base()); + return base_type_name(((t_base_type*)ttype)->get_base(), in_container); } else if (ttype->is_enum()) { - return "Int32"; + return (in_container ? "Integer" : "int"); } else if (ttype->is_map()) { t_map* tmap = (t_map*) ttype; return "HashMap<" + - type_name(tmap->get_key_type()) + "," + - type_name(tmap->get_val_type()) + ">"; + type_name(tmap->get_key_type(), true) + "," + + type_name(tmap->get_val_type(), true) + ">"; } else if (ttype->is_set()) { t_set* tset = (t_set*) ttype; - return "HashSet<" + type_name(tset->get_elem_type()) + ">"; + return "HashSet<" + type_name(tset->get_elem_type(), true) + ">"; } else if (ttype->is_list()) { t_list* tlist = (t_list*) ttype; - return "ArrayList<" + type_name(tlist->get_elem_type()) + ">"; + return "ArrayList<" + type_name(tlist->get_elem_type(), true) + ">"; } else { return ttype->get_name(); } @@ -1006,23 +1054,23 @@ string t_java_generator::type_name(t_type* ttype) { * Returns the C++ type that corresponds to the thrift type. * * @param tbase The base type + * @param container Is it going in a Java container? */ -string t_java_generator::base_type_name(t_base_type::t_base tbase) { +string t_java_generator::base_type_name(t_base_type::t_base tbase, + bool in_container) { switch (tbase) { case t_base_type::TYPE_VOID: return "void"; case t_base_type::TYPE_STRING: - return "TString"; + return "String"; case t_base_type::TYPE_BYTE: - return "UInt8"; + return "byte"; case t_base_type::TYPE_I32: - return "Int32"; case t_base_type::TYPE_U32: - return "UInt32"; + return (in_container ? "Integer" : "int"); case t_base_type::TYPE_I64: - return "Int64"; case t_base_type::TYPE_U64: - return "UInt64"; + return (in_container ? "Long" : "long"); default: throw "compiler error: no C++ name for base type " + tbase; } @@ -1037,7 +1085,32 @@ string t_java_generator::declare_field(t_field* tfield, bool init) { // TODO(mcslee): do we ever need to initialize the field? string result = type_name(tfield->get_type()) + " " + tfield->get_name(); if (init) { - result += " = new " + type_name(tfield->get_type()) + "()"; + t_type* ttype = tfield->get_type(); + while (ttype->is_typedef()) { + ttype = ((t_typedef*)ttype)->get_type(); + } + if (ttype->is_base_type()) { + t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base(); + switch (tbase) { + case t_base_type::TYPE_VOID: + throw "NO T_VOID CONSTRUCT"; + case t_base_type::TYPE_STRING: + result += " = \"\""; + break; + case t_base_type::TYPE_BYTE: + case t_base_type::TYPE_I32: + case t_base_type::TYPE_U32: + case t_base_type::TYPE_I64: + case t_base_type::TYPE_U64: + result += " = 0"; + break; + } + + } else if (ttype->is_enum()) { + result += " = 0"; + } else { + result += " = new " + type_name(tfield->get_type()) + "()"; + } } return result + ";"; } diff --git a/compiler/src/generate/t_java_generator.h b/compiler/src/generate/t_java_generator.h index ae96252f..3dd4dbd2 100644 --- a/compiler/src/generate/t_java_generator.h +++ b/compiler/src/generate/t_java_generator.h @@ -84,8 +84,8 @@ class t_java_generator : public t_oop_generator { std::string java_package(); std::string java_type_imports(); std::string java_thrift_imports(); - std::string type_name(t_type* ttype); - std::string base_type_name(t_base_type::t_base tbase); + std::string type_name(t_type* ttype, bool in_container=false); + std::string base_type_name(t_base_type::t_base tbase, bool in_container=false); std::string declare_field(t_field* tfield, bool init=false); std::string function_signature(t_function* tfunction, std::string prefix=""); std::string argument_list(t_struct* tstruct); diff --git a/compiler/src/generate/t_php_generator.cc b/compiler/src/generate/t_php_generator.cc index d7185acd..09a39a65 100644 --- a/compiler/src/generate/t_php_generator.cc +++ b/compiler/src/generate/t_php_generator.cc @@ -145,7 +145,7 @@ void t_php_generator::generate_service(t_service* tservice) { php_includes(); f_service_ << - "require_once '" << service_name_ << "Types.php';" << endl << endl; + "require_once dirname(__FILE__).'/" << service_name_ << "Types.php';" << endl << endl; // Generate the three main parts of the service (well, two for now in PHP) generate_service_interface(tservice); @@ -191,24 +191,41 @@ void t_php_generator::generate_service_client(t_service* tservice) { // Private members f_service_ << indent() << "private $_itrans = null;" << endl << - indent() << "private $_otrans = null;" << endl << - indent() << "private $_iprot = null;" << endl << - indent() << "private $_oprot = null;" << endl << endl; + indent() << "private $_otrans = null;" << endl << endl; + + if (!binary_inline_) { + f_service_ << + indent() << "private $_iprot = null;" << endl << + indent() << "private $_oprot = null;" << endl << endl; + } // Constructor function f_service_ << indent() << "public function __construct() {" << endl << indent() << " $argv = func_get_args();" << endl << - indent() << " $argc = count($argv);" << endl << - 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 << + indent() << " $argc = count($argv);" << endl; + + if (binary_inline_) { + 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; + } 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; + } + f_service_ << indent() << "}" << endl << endl; // Generate client method implementations @@ -222,27 +239,40 @@ void t_php_generator::generate_service_client(t_service* tservice) { "public function " << function_signature(*f_iter) << endl; scope_up(f_service_); - // Serialize the request - f_service_ << - indent() << - "$this->_oprot->writeStructBegin($this->_otrans, 'function');" << endl << - indent() << - "$this->_oprot->writeFieldBegin($this->_otrans, 'name', TType::STRING, 0);" << endl << - indent() << - "$this->_oprot->writeString($this->_otrans, '" << funname << "');" << endl << - indent() << - "$this->_oprot->writeFieldEnd($this->_otrans);" << endl << - indent() << - "$this->_oprot->writeFieldBegin($this->_otrans, 'args', TType::STRUCT, 1);" << endl; + // Serialize the request header + if (binary_inline_) { + f_service_ << + indent() << "$_output = '';" << endl << + indent() << "$_output .= pack('c', TType::STRING);" << endl << + indent() << "$_output .= strrev(pack('l', 0));" << endl << + indent() << "$_output .= strrev(pack('l', strlen('" << funname << "')));" << endl << + indent() << "$_output .= '" << funname << "';" << endl << + indent() << "$_output .= pack('c', TType::STRUCT);" << endl << + indent() << "$_output .= strrev(pack('l', 1));" << endl; + } else { + f_service_ << + indent() << "$this->_oprot->writeStructBegin($this->_otrans, 'function');" << endl << + indent() << "$this->_oprot->writeFieldBegin($this->_otrans, 'name', TType::STRING, 0);" << endl << + indent() << "$this->_oprot->writeString($this->_otrans, '" << funname << "');" << endl << + indent() << "$this->_oprot->writeFieldEnd($this->_otrans);" << endl << + indent() << "$this->_oprot->writeFieldBegin($this->_otrans, 'args', TType::STRUCT, 1);" << endl; + } + + // Serialize request arguments generate_serialize_struct((*f_iter)->get_arglist()); - f_service_ << - indent() << - "$this->_oprot->writeFieldEnd($this->_otrans);" << endl << - indent() << - "$this->_oprot->writeFieldStop($this->_otrans);" << endl << - indent() << - "$this->_oprot->writeStructEnd($this->_otrans);" << endl; - + + // Write to the stream + if (binary_inline_) { + f_service_ << + indent() << "$_output .= pack('c', TType::STOP);" << endl << + indent() << "$this->_otrans->write($_output);" << endl; + } else { + f_service_ << + indent() << "$this->_oprot->writeFieldEnd($this->_otrans);" << endl << + indent() << "$this->_oprot->writeFieldStop($this->_otrans);" << endl << + indent() << "$this->_oprot->writeStructEnd($this->_otrans);" << endl; + } + // Flush the request indent(f_service_) << "$this->_otrans->flush();" << endl; @@ -305,46 +335,99 @@ void t_php_generator::generate_deserialize_field(t_field* tfield, generate_deserialize_container(tfield->get_type(), name); } else if (type->is_base_type() || type->is_enum()) { - indent(f_service_) << - "$this->_iprot->"; - - if (type->is_base_type()) { - t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); - switch (tbase) { - case t_base_type::TYPE_VOID: - throw "compiler error: cannot serialize void field in a struct: " + - name; - break; - case t_base_type::TYPE_STRING: - f_service_ << "readString($this->_itrans, $" << name << ");"; - break; - case t_base_type::TYPE_BYTE: - f_service_ << "readByte($this->_itrans, $" << name << ");"; - break; - case t_base_type::TYPE_I32: + if (binary_inline_) { + if (type->is_base_type()) { + t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); + switch (tbase) { + case t_base_type::TYPE_VOID: + throw "compiler error: cannot serialize void field in a struct: " + + name; + break; + case t_base_type::TYPE_STRING: + f_service_ << + indent() << "$_len = unpack('l', strrev($this->_itrans->readAll(4)));" << endl << + indent() << "$_len = $_len[1];" << endl << + indent() << "$" << name << " = $this->_itrans->readAll($_len);" << endl; + break; + case t_base_type::TYPE_BYTE: + f_service_ << + indent() << "$" << name << " = unpack('c', $this->_itrans->readAll(1));" << endl << + indent() << "$" << name << " = $" << name << "[1];" << endl; + break; + case t_base_type::TYPE_I32: + f_service_ << + indent() << "$" << name << " = unpack('l', strrev($this->_itrans->readAll(4)));" << endl << + indent() << "$" << name << " = $" << name << "[1];" << endl; + break; + case t_base_type::TYPE_U32: + f_service_ << "readU32($this->_itrans, $" << name << ");"; + break; + case t_base_type::TYPE_I64: + f_service_ << + indent() << "$_arr = unpack('N2', $this->_itrans->readAll(8));" << endl << + indent() << "if ($_arr[1] & 0x80000000) {" << endl << + indent() << " $_arr[1] = $_arr[1] ^ 0xFFFFFFFF;" << endl << + indent() << " $_arr[2] = $_arr[2] ^ 0xFFFFFFFF;" << endl << + indent() << " $" << name << " = 0 - $_arr[1]*4294967296 - $_arr[2] - 1;" << endl << + indent() << "} else {" << endl << + indent() << " $" << name << " = $_arr[1]*4294967296 + $_arr[2];" << endl << + indent() << "}" << endl; + break; + case t_base_type::TYPE_U64: + f_service_ << "readU64($this->_itrans, $" << name << ");"; + break; + default: + throw "compiler error: no C++ name for base type " + tbase; + } + } else if (type->is_enum()) { + f_service_ << + indent() << "$" << name << " = unpack('l', strrev($this->_itrans->readAll(4)));" << endl << + indent() << "$" << name << " = $" << name << "[1];" << endl; + } + + } else { + + indent(f_service_) << + "$this->_iprot->"; + + if (type->is_base_type()) { + t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); + switch (tbase) { + case t_base_type::TYPE_VOID: + throw "compiler error: cannot serialize void field in a struct: " + + name; + break; + case t_base_type::TYPE_STRING: + f_service_ << "readString($this->_itrans, $" << name << ");"; + break; + case t_base_type::TYPE_BYTE: + f_service_ << "readByte($this->_itrans, $" << name << ");"; + break; + case t_base_type::TYPE_I32: + f_service_ << "readI32($this->_itrans, $" << name << ");"; + break; + case t_base_type::TYPE_U32: + f_service_ << "readU32($this->_itrans, $" << name << ");"; + break; + case t_base_type::TYPE_I64: + f_service_ << "readI64($this->_itrans, $" << name << ");"; + break; + case t_base_type::TYPE_U64: + f_service_ << "readU64($this->_itrans, $" << name << ");"; + break; + default: + throw "compiler error: no C++ name for base type " + tbase; + } + } else if (type->is_enum()) { f_service_ << "readI32($this->_itrans, $" << name << ");"; - break; - case t_base_type::TYPE_U32: - f_service_ << "readU32($this->_itrans, $" << name << ");"; - break; - case t_base_type::TYPE_I64: - f_service_ << "readI64($this->_itrans, $" << name << ");"; - break; - case t_base_type::TYPE_U64: - f_service_ << "readU64($this->_itrans, $" << name << ");"; - break; - default: - throw "compiler error: no C++ name for base type " + tbase; } - } else if (type->is_enum()) { - f_service_ << "readI32($this->_itrans, $" << name << ");"; + f_service_ << endl; } - f_service_ << - endl; + } else { printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n", tfield->get_name().c_str(), type_name(type).c_str()); - } + } } /** @@ -365,13 +448,20 @@ void t_php_generator::generate_deserialize_struct(t_struct* tstruct, string ftype = tmp("_ftype"); string fname = tmp("_name"); - // Declare stack tmp variables + t_field ffid(g_program->get_i32_type(), fid); + t_field fftype(g_program->get_byte_type(), ftype); + f_service_ << indent() << "$" << fname << " = null;" << endl << indent() << "$" << ftype << " = null;" << endl << - indent() << "$" << fid << " = 0;" << endl << - indent() << "$this->_iprot->readStructBegin($this->_itrans, $" << fname << ");" << endl; - + indent() << "$" << fid << " = 0;" << endl; + + // Declare stack tmp variables + if (!binary_inline_) { + f_service_ << + indent() << "$this->_iprot->readStructBegin($this->_itrans, $" << fname << ");" << endl; + } + // Loop over reading in fields indent(f_service_) << "while (true)" << endl; @@ -379,20 +469,30 @@ void t_php_generator::generate_deserialize_struct(t_struct* tstruct, scope_up(f_service_); // Read beginning field marker - indent(f_service_) << - "$this->_iprot->readFieldBegin($this->_itrans, " << - "$" << fname << ", $" << ftype << ", $" << fid << ");" << endl; - - // Check for field STOP marker and break - indent(f_service_) << - "if ($" << ftype << " == TType::STOP) { " << endl; - indent_up(); - indent(f_service_) << - "break;" << endl; - indent_down(); - indent(f_service_) << - "}" << endl; + if (binary_inline_) { + generate_deserialize_field(&fftype); + f_service_ << + indent() << "if ($" << ftype << " == TType::STOP) {" << endl << + indent() << " break;" << endl << + indent() << "}" << endl; + generate_deserialize_field(&ffid); + } else { + indent(f_service_) << + "$this->_iprot->readFieldBegin($this->_itrans, " << + "$" << fname << ", $" << ftype << ", $" << fid << ");" << endl; + + // Check for field STOP marker and break + indent(f_service_) << + "if ($" << ftype << " == TType::STOP) {" << endl; + indent_up(); + indent(f_service_) << + "break;" << endl; + indent_down(); + indent(f_service_) << + "}" << endl; + } + // Switch statement on the field we are reading indent(f_service_) << "switch ($" << fid << ")" << endl; @@ -417,15 +517,19 @@ void t_php_generator::generate_deserialize_struct(t_struct* tstruct, indent() << " break;" << endl; scope_down(f_service_); - - // Read field end marker - indent(f_service_) << - "$this->_iprot->readFieldEnd($this->_itrans);" << endl; + + if (!binary_inline_) { + // Read field end marker + indent(f_service_) << + "$this->_iprot->readFieldEnd($this->_itrans);" << endl; + } scope_down(f_service_); - - indent(f_service_) << - "$this->_iprot->readStructEnd($this->_itrans);" << endl; + + if (!binary_inline_) { + indent(f_service_) << + "$this->_iprot->readStructEnd($this->_itrans);" << endl; + } scope_down(f_service_); } @@ -439,6 +543,11 @@ void t_php_generator::generate_deserialize_container(t_type* ttype, 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); + indent(f_service_) << "$" << size << " = 0;" << endl; @@ -446,19 +555,36 @@ void t_php_generator::generate_deserialize_container(t_type* ttype, if (ttype->is_map()) { f_service_ << indent() << "$" << ktype << " = 0;" << endl << - indent() << "$" << vtype << " = 0;" << endl << - indent() << "$this->_iprot->readMapBegin($this->_itrans, " << - "$" << ktype << ", $" << vtype << ", $" << size << ");" << endl; + indent() << "$" << vtype << " = 0;" << endl; + if (binary_inline_) { + generate_deserialize_field(&fktype); + generate_deserialize_field(&fvtype); + generate_deserialize_field(&fsize); + } else { + f_service_ << + indent() << "$this->_iprot->readMapBegin($this->_itrans, " << + "$" << ktype << ", $" << vtype << ", $" << size << ");" << endl; + } } else if (ttype->is_set()) { - f_service_ << - indent() << "$" << etype << " = 0;" << endl << - indent() << "$this->_iprot->readSetBegin($this->_itrans, " << - "$" << etype << ", $" << size << ");" << endl; + if (binary_inline_) { + generate_deserialize_field(&fetype); + generate_deserialize_field(&fsize); + } else { + f_service_ << + indent() << "$" << etype << " = 0;" << endl << + indent() << "$this->_iprot->readSetBegin($this->_itrans, " << + "$" << etype << ", $" << size << ");" << endl; + } } else if (ttype->is_list()) { - f_service_ << - indent() << "$" << etype << " = 0;" << endl << - indent() << "$this->_iprot->readListBegin($this->_itrans, " << - "$" << etype << ", $" << size << ");" << endl; + if (binary_inline_) { + generate_deserialize_field(&fetype); + generate_deserialize_field(&fsize); + } else { + f_service_ << + indent() << "$" << etype << " = 0;" << endl << + indent() << "$this->_iprot->readListBegin($this->_itrans, " << + "$" << etype << ", $" << size << ");" << endl; + } } // For loop iterates over elements @@ -479,13 +605,15 @@ void t_php_generator::generate_deserialize_container(t_type* ttype, scope_down(f_service_); - // Read container end - if (ttype->is_map()) { - indent(f_service_) << "$this->_iprot->readMapEnd($this->_itrans);" << endl; - } else if (ttype->is_set()) { - indent(f_service_) << "$this->_iprot->readSetEnd($this->_itrans);" << endl; - } else if (ttype->is_list()) { - indent(f_service_) << "$this->_iprot->readListEnd($this->_itrans);" << endl; + if (!binary_inline_) { + // Read container end + if (ttype->is_map()) { + indent(f_service_) << "$this->_iprot->readMapEnd($this->_itrans);" << endl; + } else if (ttype->is_set()) { + indent(f_service_) << "$this->_iprot->readSetEnd($this->_itrans);" << endl; + } else if (ttype->is_list()) { + indent(f_service_) << "$this->_iprot->readListEnd($this->_itrans);" << endl; + } } scope_down(f_service_); @@ -571,41 +699,84 @@ void t_php_generator::generate_serialize_field(t_field* tfield, } else if (type->is_base_type() || type->is_enum()) { string name = prefix + tfield->get_name(); - indent(f_service_) << - "$this->_oprot->"; - - if (type->is_base_type()) { - t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); - switch (tbase) { - case t_base_type::TYPE_VOID: - throw - "compiler error: cannot serialize void field in a struct: " + name; - break; - case t_base_type::TYPE_STRING: - f_service_ << "writeString($this->_otrans, $" << name << ");"; - break; - case t_base_type::TYPE_BYTE: - f_service_ << "writeByte($this->_otrans, $" << name << ");"; - break; - case t_base_type::TYPE_I32: + + if (binary_inline_) { + if (type->is_base_type()) { + t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); + switch (tbase) { + case t_base_type::TYPE_VOID: + throw + "compiler error: cannot serialize void field in a struct: " + name; + break; + case t_base_type::TYPE_STRING: + f_service_ << + indent() << "$_output .= strrev(pack('l', strlen($" << name << ")));" << endl << + indent() << "$_output .= $" << name << ";" << endl; + break; + case t_base_type::TYPE_BYTE: + f_service_ << + indent() << "$_output .= pack('c', $" << name << ");" << endl; + break; + case t_base_type::TYPE_I32: + f_service_ << + indent() << "$_output .= strrev(pack('l', $" << name << "));" << endl; + break; + case t_base_type::TYPE_U32: + f_service_ << + indent() << "writeU32($this->_otrans, $" << name << ");" << endl; + break; + case t_base_type::TYPE_I64: + f_service_ << + indent() << "$_output .= pack('N2', $" << name << " >> 32, $" << name << " & 0xFFFFFFFF);" << endl; + break; + case t_base_type::TYPE_U64: + f_service_ << "writeU64($this->_otrans, $" << name << ");"; + break; + default: + throw "compiler error: no C++ name for base type " + tbase; + } + } else if (type->is_enum()) { + f_service_ << + indent() << "$_output .= strrev(pack('l', $" << name << "));" << endl; + } + } else { + + indent(f_service_) << + "$this->_oprot->"; + + if (type->is_base_type()) { + t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); + switch (tbase) { + case t_base_type::TYPE_VOID: + throw + "compiler error: cannot serialize void field in a struct: " + name; + break; + case t_base_type::TYPE_STRING: + f_service_ << "writeString($this->_otrans, $" << name << ");"; + break; + case t_base_type::TYPE_BYTE: + f_service_ << "writeByte($this->_otrans, $" << name << ");"; + break; + case t_base_type::TYPE_I32: + f_service_ << "writeI32($this->_otrans, $" << name << ");"; + break; + case t_base_type::TYPE_U32: + f_service_ << "writeU32($this->_otrans, $" << name << ");"; + break; + case t_base_type::TYPE_I64: + f_service_ << "writeI64($this->_otrans, $" << name << ");"; + break; + case t_base_type::TYPE_U64: + f_service_ << "writeU64($this->_otrans, $" << name << ");"; + break; + default: + throw "compiler error: no C++ name for base type " + tbase; + } + } else if (type->is_enum()) { f_service_ << "writeI32($this->_otrans, $" << name << ");"; - break; - case t_base_type::TYPE_U32: - f_service_ << "writeU32($this->_otrans, $" << name << ");"; - break; - case t_base_type::TYPE_I64: - f_service_ << "writeI64($this->_otrans, $" << name << ");"; - break; - case t_base_type::TYPE_U64: - f_service_ << "writeU64($this->_otrans, $" << name << ");"; - break; - default: - throw "compiler error: no C++ name for base type " + tbase; } - } else if (type->is_enum()) { - f_service_ << "writeI32($this->_otrans, $" << name << ");"; + f_service_ << endl; } - f_service_ << endl; } else { printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n", prefix.c_str(), @@ -627,25 +798,46 @@ void t_php_generator::generate_serialize_struct(t_struct* tstruct, vector::const_iterator f_iter; scope_up(f_service_); - indent(f_service_) << - "$this->_oprot->writeStructBegin($this->_otrans, '" << name << "');" << endl; + + if (!binary_inline_) { + indent(f_service_) << + "$this->_oprot->writeStructBegin($this->_otrans, '" << name << "');" << endl; + } + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { // Write field header - indent(f_service_) << - "$this->_oprot->writeFieldBegin($this->_otrans, " << - "'" << (*f_iter)->get_name() << "', " << - type_to_enum((*f_iter)->get_type()) << ", " << - (*f_iter)->get_key() << ");" << endl; + if (binary_inline_) { + f_service_ << + indent() << "$_output .= pack('c', " << type_to_enum((*f_iter)->get_type()) << ");" << endl << + indent() << "$_output .= strrev(pack('l', " << (*f_iter)->get_key() << "));" << endl; + } else { + indent(f_service_) << + "$this->_oprot->writeFieldBegin($this->_otrans, " << + "'" << (*f_iter)->get_name() << "', " << + type_to_enum((*f_iter)->get_type()) << ", " << + (*f_iter)->get_key() << ");" << endl; + } + // Write field contents generate_serialize_field(*f_iter, prefix); + // Write field closer - indent(f_service_) << - "$this->_oprot->writeFieldEnd($this->_otrans);" << endl; + if (binary_inline_) { + } else { + indent(f_service_) << + "$this->_oprot->writeFieldEnd($this->_otrans);" << endl; + } + } + + if (binary_inline_) { + f_service_ << + indent() << "$_output .= pack('c', TType::STOP);" << endl; + } else { + // Write the struct map + f_service_ << + indent() << "$this->_oprot->writeFieldStop($this->_otrans);" << endl << + indent() << "$this->_oprot->writeStructEnd($this->_otrans);" << endl; } - // Write the struct map - f_service_ << - indent() << "$this->_oprot->writeFieldStop($this->_otrans);" << endl << - indent() << "$this->_oprot->writeStructEnd($this->_otrans);" << endl; scope_down(f_service_); } @@ -655,21 +847,42 @@ void t_php_generator::generate_serialize_container(t_type* ttype, scope_up(f_service_); if (ttype->is_map()) { - indent(f_service_) << - "$this->_oprot->writeMapBegin($this->_otrans, " << - type_to_enum(((t_map*)ttype)->get_key_type()) << ", " << - type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << - "count($" << prefix << "));" << endl; + if (binary_inline_) { + f_service_ << + indent() << "$_output .= pack('c', " << type_to_enum(((t_map*)ttype)->get_key_type()) << ");" << endl << + indent() << "$_output .= pack('c', " << type_to_enum(((t_map*)ttype)->get_val_type()) << ");" << endl << + indent() << "$_output .= strrev(pack('l', count($" << prefix << ")));" << endl; + } else { + indent(f_service_) << + "$this->_oprot->writeMapBegin($this->_otrans, " << + type_to_enum(((t_map*)ttype)->get_key_type()) << ", " << + type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << + "count($" << prefix << "));" << endl; + } } else if (ttype->is_set()) { - indent(f_service_) << - "$this->_oprot->writeSetBegin($this->_otrans, " << - type_to_enum(((t_set*)ttype)->get_elem_type()) << ", " << - "count($" << prefix << "));" << endl; + if (binary_inline_) { + f_service_ << + indent() << "$_output .= pack('c', " << type_to_enum(((t_set*)ttype)->get_elem_type()) << ");" << endl << + indent() << "$_output .= strrev(pack('l', count($" << prefix << ")));" << endl; + + } else { + indent(f_service_) << + "$this->_oprot->writeSetBegin($this->_otrans, " << + type_to_enum(((t_set*)ttype)->get_elem_type()) << ", " << + "count($" << prefix << "));" << endl; + } } else if (ttype->is_list()) { - indent(f_service_) << - "$this->_oprot->writeListBegin($this->_otrans, " << - type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " << - "count($" << prefix << "));" << endl; + if (binary_inline_) { + f_service_ << + indent() << "$_output .= pack('c', " << type_to_enum(((t_list*)ttype)->get_elem_type()) << ");" << endl << + indent() << "$_output .= strrev(pack('l', count($" << prefix << ")));" << endl; + + } else { + indent(f_service_) << + "$this->_oprot->writeListBegin($this->_otrans, " << + type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " << + "count($" << prefix << "));" << endl; + } } scope_up(f_service_); @@ -699,6 +912,10 @@ void t_php_generator::generate_serialize_container(t_type* ttype, scope_down(f_service_); } + + scope_down(f_service_); + + if (!binary_inline_) { if (ttype->is_map()) { indent(f_service_) << "$this->_oprot->writeMapEnd($this->_otrans);" << endl; @@ -709,8 +926,7 @@ void t_php_generator::generate_serialize_container(t_type* ttype, indent(f_service_) << "$this->_oprot->writeListEnd($this->_otrans);" << endl; } - - scope_down(f_service_); + } scope_down(f_service_); } diff --git a/compiler/src/generate/t_php_generator.h b/compiler/src/generate/t_php_generator.h index d01acd20..e5fb30cf 100644 --- a/compiler/src/generate/t_php_generator.h +++ b/compiler/src/generate/t_php_generator.h @@ -18,7 +18,10 @@ */ class t_php_generator : public t_oop_generator { public: - t_php_generator() {} + t_php_generator(bool binary_inline=false) { + binary_inline_ = binary_inline; + } + ~t_php_generator() {} /** Init and close methods */ @@ -93,6 +96,11 @@ class t_php_generator : public t_oop_generator { std::ofstream f_types_; std::ofstream f_service_; + + /** Generate protocol-independent template? Or Binary inline code? */ + + bool binary_inline_; + }; #endif diff --git a/compiler/src/main.cc b/compiler/src/main.cc index 87833093..6a7faf8c 100644 --- a/compiler/src/main.cc +++ b/compiler/src/main.cc @@ -98,6 +98,7 @@ void usage() { 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, " -python Generate Python output files\n"); fprintf(stderr, " -d Print parse debugging to standard output\n"); exit(1); @@ -111,6 +112,7 @@ int main(int argc, char** argv) { bool gen_cpp = false; bool gen_java = false; bool gen_php = false; + bool php_inline = false; // Setup time string time_t now = time(NULL); @@ -130,6 +132,10 @@ int main(int argc, char** argv) { gen_java = true; } else if (strcmp(argv[i], "-php") == 0) { gen_php = true; + php_inline = false; + } else if (strcmp(argv[i], "-phpi") == 0) { + gen_php = true; + php_inline = true; } else { fprintf(stderr, "!!! Unrecognized option: %s\n", argv[i]); usage(); @@ -181,7 +187,7 @@ int main(int argc, char** argv) { } if (gen_php) { - t_php_generator* php = new t_php_generator(); + t_php_generator* php = new t_php_generator(php_inline); php->generate_program(g_program); delete php; } diff --git a/compiler/src/parse/t_function.h b/compiler/src/parse/t_function.h index b248db7c..9e6c56a2 100644 --- a/compiler/src/parse/t_function.h +++ b/compiler/src/parse/t_function.h @@ -7,26 +7,33 @@ /** * Representation of a function. Key parst are return type, function name, - * optional modifiers, and an argument list. Each function also has a - * hash signature that is used in the network protocol. + * optional modifiers, and an argument list. * * @author Mark Slee */ class t_function { public: - t_function(t_type* returntype, std::string name, t_struct* arglist) : - returntype_(returntype), name_(name), arglist_(arglist) {} + t_function(t_type* returntype, + std::string name, + t_struct* arglist, + bool async=false) : + returntype_(returntype), + name_(name), + arglist_(arglist), + async_(async) {} ~t_function() {} t_type* get_returntype() const { return returntype_; } const std::string& get_name() const { return name_; } t_struct* get_arglist() const { return arglist_; } + bool is_async() const { return async_; } private: t_type* returntype_; std::string name_; t_struct* arglist_; + bool async_; }; #endif diff --git a/compiler/src/thrift.l b/compiler/src/thrift.l index 33cbda84..9d2944ac 100644 --- a/compiler/src/thrift.l +++ b/compiler/src/thrift.l @@ -33,6 +33,7 @@ symbol ([\,\{\}\(\)\=<>]) {symbol} { return yytext[0]; } +"void" { return tok_void; } "byte" { return tok_byte; } "string" { return tok_string; } "i32" { return tok_i32; } @@ -44,7 +45,6 @@ symbol ([\,\{\}\(\)\=<>]) "list" { return tok_list; } "set" { return tok_set; } -"void" { return tok_void; } "async" { return tok_async; } "typedef" { return tok_typedef; } @@ -52,6 +52,7 @@ symbol ([\,\{\}\(\)\=<>]) "service" { return tok_service; } "enum" { return tok_enum; } + {intconstant} { yylval.iconst = atoi(yytext) ; return tok_int_constant; } {identifier} { yylval.id = strdup(yytext); return tok_identifier; } diff --git a/compiler/src/thrift.y b/compiler/src/thrift.y index 269d1632..d0882ff7 100644 --- a/compiler/src/thrift.y +++ b/compiler/src/thrift.y @@ -20,6 +20,7 @@ int y_field_val = 0; %union { char* id; int iconst; + bool tbool; t_type* ttype; t_typedef* ttypedef; t_enum* tenum; @@ -82,10 +83,11 @@ int y_field_val = 0; %type Service %type Function -%type FunctionModifiers %type FunctionType %type FunctionList +%type AsyncOptional + %% /** Thrift Grammar */ @@ -210,17 +212,21 @@ FunctionList: } Function: - FunctionType FunctionModifiers tok_identifier '(' FieldList ')' + FunctionType AsyncOptional tok_identifier '(' FieldList ')' { $5->set_name(std::string($3) + "_args"); - $$ = new t_function($1, $3, $5); + $$ = new t_function($1, $3, $5, $2); y_field_val = 0; } -FunctionModifiers: +AsyncOptional: + tok_async + { + $$ = true; + } +| { - /** TODO(mcslee): implement async modifier, etc. */ - $$ = 0; + $$ = false; } FieldList: -- 2.17.1