From 27ed6ec1f9ca50f2447b80dfeeabfd54da35f4db Mon Sep 17 00:00:00 2001 From: Mark Slee Date: Thu, 16 Aug 2007 01:26:31 +0000 Subject: [PATCH] Merging Jake Luciani's latest perl code gen fixes Reviewed By: dreiss Test Plan: Watch for any weirdness on Thrift code gen, perl specific git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@665206 13f79535-47bb-0310-9956-ffa450edef68 --- compiler/cpp/src/generate/t_perl_generator.cc | 145 +++++++++--------- compiler/cpp/src/generate/t_perl_generator.h | 4 +- compiler/cpp/src/parse/t_program.h | 12 +- compiler/cpp/src/thriftl.ll | 7 +- compiler/cpp/src/thrifty.yy | 21 ++- test/ThriftTest.thrift | 6 +- test/perl/TestClient.pl | 4 +- thrift.el | 2 +- thrift.vim | 2 +- tutorial/perl/PerlClient.pl | 4 +- tutorial/shared.thrift | 1 + tutorial/tutorial.thrift | 1 + 12 files changed, 113 insertions(+), 96 deletions(-) diff --git a/compiler/cpp/src/generate/t_perl_generator.cc b/compiler/cpp/src/generate/t_perl_generator.cc index c241a045..5f8b3792 100644 --- a/compiler/cpp/src/generate/t_perl_generator.cc +++ b/compiler/cpp/src/generate/t_perl_generator.cc @@ -20,10 +20,17 @@ void t_perl_generator::init_generator() { // Make output directory mkdir(T_PERL_DIR, S_IREAD | S_IWRITE | S_IEXEC); + string outdir(T_PERL_DIR); + std::string ns = program_->get_perl_package(); + if (ns.length() > 0) { + outdir += "/" + ns; + mkdir(outdir.c_str(), S_IREAD | S_IWRITE | S_IEXEC); + } + // Make output file - string f_types_name = string(T_PERL_DIR)+"/"+program_name_+"_types.pm"; + string f_types_name = outdir+"/Types.pm"; f_types_.open(f_types_name.c_str()); - string f_consts_name = string(T_PERL_DIR)+"/"+program_name_+"_constants.pm"; + string f_consts_name = outdir+"/Constants.pm"; f_consts_.open(f_consts_name.c_str()); // Print header @@ -47,7 +54,7 @@ string t_perl_generator::perl_includes() { inc += "use strict;\n"; inc += "use warnings;\n"; inc += "use Thrift;\n\n"; - + return inc; } @@ -88,7 +95,7 @@ void t_perl_generator::generate_enum(t_enum* tenum) { } else { ++value; } - + f_types_ << "use constant "<<(*c_iter)->get_name() << " => " << value << ";" << endl; } } @@ -359,15 +366,15 @@ void t_perl_generator::generate_perl_struct_reader(ofstream& out, indent(out) << "/^" << (*f_iter)->get_key() << "$/ && do{"; indent(out) << "if ($ftype == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl; - - indent_up(); + + indent_up(); generate_deserialize_field(out, *f_iter, "self->"); indent_down(); - + indent(out) << "} else {" << endl; - + indent(out) << " $xfer += $input->skip($ftype);" << endl; - + out << indent() << "}" << endl << indent() << "last; };" << endl; @@ -418,7 +425,7 @@ void t_perl_generator::generate_perl_struct_writer(ofstream& out, "'" << (*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, "self->"); @@ -456,9 +463,9 @@ void t_perl_generator::generate_service(t_service* tservice) { /// "package "<get_program()) << "Types;" << endl; if (tservice->get_extends() != NULL) { f_service_ << @@ -516,7 +523,7 @@ void t_perl_generator::generate_service_processor(t_service* tservice) { f_service_ << indent() << "$self->{handler} = $handler;" << endl; - + f_service_ << indent() << "return bless($self,$classname);"<$methodname($rseqid, $input, $output);" << endl << indent() << "return 1;" << endl; - + indent_down(); f_service_ << @@ -583,45 +590,45 @@ void t_perl_generator::generate_process_function(t_service* tservice, // Open function f_service_ << "sub process_" << tfunction->get_name() << "{"<get_program()) + service_name_ + "_" + tfunction->get_name() + "_args"; string resultname = perl_namespace(tservice->get_program()) + service_name_ + "_" + tfunction->get_name() + "_result"; - + f_service_ << indent() << "my $args = new " << argsname << "();" << endl << indent() << "$args->read($input);" << endl; - + f_service_ << indent() << "$input->readMessageEnd();" << endl; - + t_struct* xs = tfunction->get_xceptions(); const std::vector& xceptions = xs->get_members(); vector::const_iterator x_iter; - + // Declare result for non async function if (!tfunction->is_async()) { f_service_ << indent() << "my $result = new " << resultname << "();" << endl; } - + // Try block for a function with exceptions if (xceptions.size() > 0) { f_service_ << indent() << "eval {" << endl; indent_up(); } - + // Generate the function call t_struct* arg_struct = tfunction->get_arglist(); const std::vector& fields = arg_struct->get_members(); vector::const_iterator f_iter; - + f_service_ << indent(); if (!tfunction->is_async() && !tfunction->get_returntype()->is_void()) { f_service_ << "$result->{success} = "; @@ -638,13 +645,13 @@ void t_perl_generator::generate_process_function(t_service* tservice, f_service_ << "$args->" << (*f_iter)->get_name(); } f_service_ << ");" << endl; - + if (!tfunction->is_async() && xceptions.size() > 0) { indent_down(); for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { f_service_ << indent() << "}; if( UNIVERSAL::isa($@,'"<<(*x_iter)->get_type()->get_name()<<"') ){ "<is_async()) { indent_up(); f_service_ << @@ -673,7 +680,7 @@ void t_perl_generator::generate_process_function(t_service* tservice, indent() << "$result->write($output);" << endl << indent() << "$output->getTransport()->flush();" << endl; indent_down(); - + // Close function indent_down(); f_service_ << @@ -766,40 +773,40 @@ void t_perl_generator::generate_service_rest(t_service* tservice) { f_service_ << "package " << service_name_ << "Rest;"< $impl };"< functions = tservice->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { f_service_ << "sub " << (*f_iter)->get_name() << "{" <& args = (*f_iter)->get_arglist()->get_members(); vector::const_iterator a_iter; for (a_iter = args.begin(); a_iter != args.end(); ++a_iter) { @@ -822,7 +829,7 @@ void t_perl_generator::generate_service_rest(t_service* tservice) { indent_down(); indent(f_service_) << "}" << endl <& fields = arg_struct->get_members(); vector::const_iterator fld_iter; string funname = (*f_iter)->get_name(); - + // Open function f_service_ << "sub " << function_signature(*f_iter) << endl; - + indent_up(); - + indent(f_service_) << indent() << "$self->send_" << funname << "("; - + bool first = true; for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { if (first) { @@ -901,7 +908,7 @@ void t_perl_generator::generate_service_client(t_service* tservice) { f_service_ << "$" << (*fld_iter)->get_name(); } f_service_ << ");" << endl; - + if (!(*f_iter)->is_async()) { f_service_ << indent(); if (!(*f_iter)->get_returntype()->is_void()) { @@ -910,42 +917,42 @@ void t_perl_generator::generate_service_client(t_service* tservice) { f_service_ << "$self->recv_" << funname << "();" << endl; } - + indent_down(); - - f_service_ << "} "<get_program()) + service_name_ + "_" + (*f_iter)->get_name() + "_args"; - + // Serialize the request header f_service_ << indent() << "$self->{output}->writeMessageBegin('" << (*f_iter)->get_name() << "', TMessageType::CALL, $self->{seqid});" << endl; - + f_service_ << indent() << "my $args = new " << argsname << "();" << 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; } - + // Write to the stream f_service_ << indent() << "$args->write($self->{output});" << endl << indent() << "$self->{output}->writeMessageEnd();" << endl << indent() << "$self->{output}->getTransport()->flush();" << endl; - - + + indent_down(); - - f_service_ << "}"<is_async()) { std::string resultname = perl_namespace(tservice->get_program()) + service_name_ + "_" + (*f_iter)->get_name() + "_result"; t_struct noargs(program_); @@ -1055,7 +1062,7 @@ void t_perl_generator::generate_deserialize_field(ofstream &out, } else if (type->is_base_type() || type->is_enum()) { indent(out) << "$xfer += $input->"; - + if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { @@ -1091,7 +1098,7 @@ void t_perl_generator::generate_deserialize_field(ofstream &out, out << "readI32(\\$" << name << ");"; } out << endl; - + } else { printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n", tfield->get_name().c_str(), type->get_name().c_str()); @@ -1126,7 +1133,7 @@ void t_perl_generator::generate_deserialize_container(ofstream &out, t_field fktype(g_type_byte, ktype); t_field fvtype(g_type_byte, vtype); t_field fetype(g_type_byte, etype); - + out << indent() << "my $" << size << " = 0;" << endl; @@ -1136,27 +1143,27 @@ void t_perl_generator::generate_deserialize_container(ofstream &out, indent() << "$" << prefix << " = {};" << endl << indent() << "my $" << ktype << " = 0;" << endl << indent() << "my $" << vtype << " = 0;" << endl; - + out << indent() << "$xfer += $input->readMapBegin(" << "\\$" << ktype << ", \\$" << vtype << ", \\$" << size << ");" << endl; - + } else if (ttype->is_set()) { - + out << indent() << "$" << prefix << " = {};" << endl << indent() << "my $" << etype << " = 0;" << endl << indent() << "$xfer += $input->readSetBegin(" << "\\$" << etype << ", \\$" << size << ");" << endl; - + } else if (ttype->is_list()) { - + out << indent() << "$" << prefix << " = [];" << endl << indent() << "my $" << etype << " = 0;" << endl << indent() << "$xfer += $input->readListBegin(" << "\\$" << etype << ", \\$" << size << ");" << endl; - + } // For loop iterates over elements diff --git a/compiler/cpp/src/generate/t_perl_generator.h b/compiler/cpp/src/generate/t_perl_generator.h index c1e7820b..a0235439 100644 --- a/compiler/cpp/src/generate/t_perl_generator.h +++ b/compiler/cpp/src/generate/t_perl_generator.h @@ -141,8 +141,8 @@ class t_perl_generator : public t_oop_generator { } std::string perl_namespace(t_program* p) { - std::string ns = p->get_perl_namespace(); - return ""; //ns.size() ? (ns + "::") : ""; + std::string ns = p->get_perl_package(); + return ns.empty() ? ns : (ns + "::"); } private: diff --git a/compiler/cpp/src/parse/t_program.h b/compiler/cpp/src/parse/t_program.h index f54ed714..d516617d 100644 --- a/compiler/cpp/src/parse/t_program.h +++ b/compiler/cpp/src/parse/t_program.h @@ -149,17 +149,17 @@ class t_program : public t_doc { void set_ruby_namespace(std::string ruby_namespace) { ruby_namespace_ = ruby_namespace; } - + const std::string& get_ruby_namespace() const { return ruby_namespace_; } - void set_perl_namespace(std::string perl_namespace) { - perl_namespace_ = perl_namespace; + void set_perl_package(std::string perl_package) { + perl_package_ = perl_package; } - const std::string& get_perl_namespace() const { - return perl_namespace_; + const std::string& get_perl_package() const { + return perl_package_; } private: @@ -206,7 +206,7 @@ class t_program : public t_doc { std::string ruby_namespace_; // Perl namespace - std::string perl_namespace_; + std::string perl_package_; }; diff --git a/compiler/cpp/src/thriftl.ll b/compiler/cpp/src/thriftl.ll index 7693f335..d047acc6 100644 --- a/compiler/cpp/src/thriftl.ll +++ b/compiler/cpp/src/thriftl.ll @@ -8,7 +8,7 @@ /** * Thrift scanner. - * + * * Tokenizes a thrift definition file. * @author Mark Slee */ @@ -35,9 +35,9 @@ void thrift_reserved_keyword(char* keyword) { /** * Provides the yylineno global, useful for debugging output */ -%option lex-compat +%option lex-compat -/** +/** * Helper definitions, comments, constants, and whatnot */ @@ -72,6 +72,7 @@ sliteral ("'"[^']*"'") "cpp_type" { return tok_cpp_type; } "java_package" { return tok_java_package; } "php_namespace" { return tok_php_namespace; } +"perl_package" { return tok_perl_package; } "ruby_namespace" { return tok_ruby_namespace; } "xsd_all" { return tok_xsd_all; } "xsd_optional" { return tok_xsd_optional; } diff --git a/compiler/cpp/src/thrifty.yy b/compiler/cpp/src/thrifty.yy index e159ef05..38ca5162 100644 --- a/compiler/cpp/src/thrifty.yy +++ b/compiler/cpp/src/thrifty.yy @@ -75,6 +75,7 @@ int y_field_val = -1; %token tok_cpp_include %token tok_cpp_type %token tok_php_namespace +%token tok_perl_package %token tok_java_package %token tok_xsd_all %token tok_xsd_optional @@ -107,7 +108,7 @@ int y_field_val = -1; /** * Function modifiers - */ + */ %token tok_async /** @@ -209,8 +210,7 @@ CaptureDocText: if (g_parse_mode == PROGRAM) { $$ = g_doctext; g_doctext = NULL; - } - else { + } else { $$ = NULL; } } @@ -269,6 +269,13 @@ Header: g_program->set_php_namespace($2); } } +| tok_perl_package tok_identifier + { + pdebug("Header -> tok_perl_namespace tok_identifier"); + if (g_parse_mode == PROGRAM) { + g_program->set_perl_package($2); + } + } | tok_ruby_namespace tok_identifier { pdebug("Header -> tok_ruby_namespace tok_identifier"); @@ -294,7 +301,7 @@ Header: Include: tok_include tok_literal { - pdebug("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()) { @@ -379,7 +386,7 @@ TypeDefinition: } } | Xception - { + { pdebug("TypeDefinition -> Xception"); if (g_parse_mode == PROGRAM) { g_program->add_xception($1); @@ -536,7 +543,7 @@ ConstValue: | ConstMap { pdebug("ConstValue => ConstMap"); - $$ = $1; + $$ = $1; } ConstList: @@ -780,7 +787,7 @@ FieldRequiredness: FieldValue: '=' ConstValue { - if (g_parse_mode == PROGRAM) { + if (g_parse_mode == PROGRAM) { $$ = $2; } else { $$ = NULL; diff --git a/test/ThriftTest.thrift b/test/ThriftTest.thrift index 92a3d21f..fd0ac974 100644 --- a/test/ThriftTest.thrift +++ b/test/ThriftTest.thrift @@ -1,6 +1,7 @@ java_package thrift.test cpp_namespace thrift.test ruby_namespace Thrift.Test +perl_package ThriftTest enum Numberz { @@ -50,7 +51,7 @@ exception Xception2 { 1: i32 errorCode, 2: Xtruct struct_thing } - + struct EmptyStruct {} struct OneField { @@ -79,8 +80,7 @@ service ThriftTest map> testInsanity(1: Insanity argument), /* Multiple parameters */ - - Xtruct testMulti(byte arg0, i32 arg1, i64 arg2, map arg3, Numberz arg4, UserId arg5), + Xtruct testMulti(byte arg0, i32 arg1, i64 arg2, map arg3, Numberz arg4, UserId arg5), /* Exception specifier */ diff --git a/test/perl/TestClient.pl b/test/perl/TestClient.pl index b3c9ca3a..4e6278e5 100644 --- a/test/perl/TestClient.pl +++ b/test/perl/TestClient.pl @@ -7,7 +7,7 @@ use Data::Dumper; use Time::HiRes qw(gettimeofday); use lib '../../lib/perl/lib'; -use lib 'gen-perl'; +use lib '../gen-perl'; use Thrift; use Thrift::BinaryProtocol; @@ -15,7 +15,7 @@ use Thrift::Socket; use Thrift::BufferedTransport; use ThriftTest; -use ThriftTest_types; +use ThriftTest::Types; $|++; diff --git a/thrift.el b/thrift.el index 4abb04e3..67485cf5 100644 --- a/thrift.el +++ b/thrift.el @@ -10,7 +10,7 @@ (defconst thrift-font-lock-keywords (list '("#.*$" . font-lock-comment-face) ;; perl style comments - '("\\<\\(include\\|struct\\|exception\\|typedef\\|cpp_namespace\\|java_package\\|php_namespace\\|const\\|enum\\|service\\|extends\\|void\\|async\\|throws\\|optional\\|required\\)\\>" . font-lock-keyword-face) ;; keywords + '("\\<\\(include\\|struct\\|exception\\|typedef\\|cpp_namespace\\|java_package\\|php_namespace\\|ruby_namespace\\|perl_package\\|const\\|enum\\|service\\|extends\\|void\\|async\\|throws\\|optional\\|required\\)\\>" . font-lock-keyword-face) ;; keywords '("\\<\\(bool\\|byte\\|i16\\|i32\\|i64\\|double\\|string\\|binary\\|map\\|list\\|set\\)\\>" . font-lock-type-face) ;; built-in types '("\\<\\([0-9]+\\)\\>" . font-lock-variable-name-face) ;; ordinals '("\\<\\(\\w+\\)\\s-*(" (1 font-lock-function-name-face)) ;; functions diff --git a/thrift.vim b/thrift.vim index daec30ed..c421cf30 100644 --- a/thrift.vim +++ b/thrift.vim @@ -30,7 +30,7 @@ syn region thriftStringDouble matchgroup=None start=+"+ end=+"+ syn match thriftNumber "-\=\<\d\+\>" contained " Keywords -syn keyword thriftKeyword namespace cpp_namespace java_package php_namespace ruby_namespace +syn keyword thriftKeyword namespace cpp_namespace java_package php_namespace ruby_namespace perl_package syn keyword thriftKeyword xsd_all xsd_optional xsd_nillable xsd_namespace xsd_attrs syn keyword thriftKeyword include cpp_include cpp_type const optional required syn keyword thriftBasicTypes void bool byte i16 i32 i64 double string binary diff --git a/tutorial/perl/PerlClient.pl b/tutorial/perl/PerlClient.pl index ad9c1d60..10cb7259 100644 --- a/tutorial/perl/PerlClient.pl +++ b/tutorial/perl/PerlClient.pl @@ -12,9 +12,9 @@ use Thrift::Socket; use Thrift::BufferedTransport; use SharedService; -use shared_types; use Calculator; -use tutorial_types; +use shared::Types; +use tutorial::Types; use Data::Dumper; diff --git a/tutorial/shared.thrift b/tutorial/shared.thrift index 7596376d..1ecfb0a5 100755 --- a/tutorial/shared.thrift +++ b/tutorial/shared.thrift @@ -7,6 +7,7 @@ cpp_namespace shared java_package shared +perl_package shared struct SharedStruct { 1: i32 key diff --git a/tutorial/tutorial.thrift b/tutorial/tutorial.thrift index 1cff3435..8af016a1 100644 --- a/tutorial/tutorial.thrift +++ b/tutorial/tutorial.thrift @@ -47,6 +47,7 @@ include "shared.thrift" cpp_namespace tutorial java_package tutorial php_namespace tutorial +perl_package tutorial /** * Thrift lets you do typedefs to get pretty names for your types. Standard -- 2.17.1