blob: 86363144bf0126d158e172760b4470740de5fa6f [file] [log] [blame]
Mark Sleee9ce01c2007-05-16 02:29:53 +00001// Copyright (c) 2006- Facebook
2// Distributed under the Thrift Software License
3//
4// See accompanying file LICENSE or visit the Thrift site at:
5// http://developers.facebook.com/thrift/
6
Mark Slee31985722006-05-24 21:45:31 +00007#ifndef T_GENERATOR_H
8#define T_GENERATOR_H
9
10#include <string>
11#include <iostream>
Mark Sleee8540632006-05-30 09:24:40 +000012#include <sstream>
Mark Slee31985722006-05-24 21:45:31 +000013#include "parse/t_program.h"
Mark Slee0e0ff7e2007-01-18 22:59:59 +000014#include "globals.h"
Mark Slee31985722006-05-24 21:45:31 +000015
16/**
17 * Base class for a thrift code generator. This class defines the basic
18 * routines for code generation and contains the top level method that
19 * dispatches code generation across various components.
20 *
21 * @author Mark Slee <mcslee@facebook.com>
22 */
23class t_generator {
24 public:
Mark Sleef0712dc2006-10-25 19:03:57 +000025 t_generator(t_program* program) {
Mark Sleef5377b32006-10-10 01:42:59 +000026 tmp_ = 0;
Mark Sleef0712dc2006-10-25 19:03:57 +000027 indent_ = 0;
28 program_ = program;
29 program_name_ = get_program_name(program);
Mark Sleef5377b32006-10-10 01:42:59 +000030 }
31
Mark Slee31985722006-05-24 21:45:31 +000032 virtual ~t_generator() {}
33
34 /**
35 * Framework generator method that iterates over all the parts of a program
36 * and performs general actions. This is implemented by the base class and
David Reissb4d7b892008-03-27 21:40:01 +000037 * should not normally be overwritten in the subclasses.
Mark Slee31985722006-05-24 21:45:31 +000038 */
David Reissb4d7b892008-03-27 21:40:01 +000039 virtual void generate_program();
Mark Slee31985722006-05-24 21:45:31 +000040
kholst76f2c882008-01-16 02:47:41 +000041 const t_program* get_program() const { return program_; }
42
Mark Slee31985722006-05-24 21:45:31 +000043 protected:
Mark Sleef5377b32006-10-10 01:42:59 +000044
45 /**
46 * Optional methods that may be imlemented by subclasses to take necessary
47 * steps at the beginning or end of code generation.
48 */
Mark Sleee8540632006-05-30 09:24:40 +000049
Mark Sleef0712dc2006-10-25 19:03:57 +000050 virtual void init_generator() {}
51 virtual void close_generator() {}
Mark Slee31985722006-05-24 21:45:31 +000052
Mark Sleeaa7671d2006-11-29 03:19:31 +000053 virtual void generate_consts(std::vector<t_const*> consts);
54
Mark Sleef5377b32006-10-10 01:42:59 +000055 /**
56 * Pure virtual methods implemented by the generator subclasses.
57 */
Mark Sleee8540632006-05-30 09:24:40 +000058
Mark Slee9cb7c612006-09-01 22:17:45 +000059 virtual void generate_typedef (t_typedef* ttypedef) = 0;
60 virtual void generate_enum (t_enum* tenum) = 0;
Mark Sleeaa7671d2006-11-29 03:19:31 +000061 virtual void generate_const (t_const* tconst) {}
Mark Slee9cb7c612006-09-01 22:17:45 +000062 virtual void generate_struct (t_struct* tstruct) = 0;
Mark Sleef5377b32006-10-10 01:42:59 +000063 virtual void generate_service (t_service* tservice) = 0;
Mark Slee9cb7c612006-09-01 22:17:45 +000064 virtual void generate_xception (t_struct* txception) {
Mark Sleef5377b32006-10-10 01:42:59 +000065 // By default exceptions are the same as structs
Mark Slee9cb7c612006-09-01 22:17:45 +000066 generate_struct(txception);
67 }
Mark Slee31985722006-05-24 21:45:31 +000068
Mark Sleef5377b32006-10-10 01:42:59 +000069 /**
70 * Method to get the program name, may be overridden
71 */
Mark Sleee8540632006-05-30 09:24:40 +000072 virtual std::string get_program_name(t_program* tprogram) {
73 return tprogram->get_name();
74 }
75
Mark Sleef5377b32006-10-10 01:42:59 +000076 /**
77 * Method to get the service name, may be overridden
78 */
Mark Sleee8540632006-05-30 09:24:40 +000079 virtual std::string get_service_name(t_service* tservice) {
80 return tservice->get_name();
81 }
82
Mark Sleef5377b32006-10-10 01:42:59 +000083 /**
dweatherford65b70752007-10-31 02:18:14 +000084 * Get the current output directory
85 */
86 virtual std::string get_out_dir() const {
87 return program_->get_out_path() + out_dir_base_ + "/";
88 }
89
90 /**
Mark Sleef5377b32006-10-10 01:42:59 +000091 * Creates a unique temporary variable name, which is just "name" with a
92 * number appended to it (i.e. name35)
93 */
Mark Sleee8540632006-05-30 09:24:40 +000094 std::string tmp(std::string name) {
95 std::ostringstream out;
96 out << name << tmp_++;
97 return out.str();
98 }
99
Mark Sleef5377b32006-10-10 01:42:59 +0000100 /**
101 * Indentation level modifiers
102 */
Mark Sleee8540632006-05-30 09:24:40 +0000103
Mark Sleef5377b32006-10-10 01:42:59 +0000104 void indent_up(){
105 ++indent_;
106 }
Mark Slee31985722006-05-24 21:45:31 +0000107
Mark Sleef5377b32006-10-10 01:42:59 +0000108 void indent_down() {
109 --indent_;
110 }
111
112 /**
113 * Indentation print function
114 */
Mark Slee31985722006-05-24 21:45:31 +0000115 std::string indent() {
116 std::string ind = "";
117 int i;
118 for (i = 0; i < indent_; ++i) {
119 ind += " ";
120 }
121 return ind;
122 }
123
Mark Sleef5377b32006-10-10 01:42:59 +0000124 /**
125 * Indentation utility wrapper
126 */
Mark Slee31985722006-05-24 21:45:31 +0000127 std::ostream& indent(std::ostream &os) {
128 return os << indent();
129 }
David Reiss3429b6a2007-08-15 00:55:41 +0000130
iproctor9a41a0c2007-07-16 21:59:24 +0000131 /**
132 * Capitalization helpers
133 */
134 std::string capitalize(std::string in) {
135 in[0] = toupper(in[0]);
136 return in;
137 }
138 std::string decapitalize(std::string in) {
139 in[0] = tolower(in[0]);
140 return in;
141 }
Mark Sleee02ab332007-11-28 04:17:49 +0000142 std::string lowercase(std::string in) {
143 for (size_t i = 0; i < in.size(); ++i) {
144 in[i] = tolower(in[i]);
145 }
146 return in;
147 }
Mark Slee31985722006-05-24 21:45:31 +0000148
David Reiss3429b6a2007-08-15 00:55:41 +0000149 /**
150 * Get the true type behind a series of typedefs.
151 */
152 static t_type* get_true_type(t_type* type) {
153 while (type->is_typedef()) {
154 type = ((t_typedef*)type)->get_type();
155 }
156 return type;
157 }
158
Mark Sleee8540632006-05-30 09:24:40 +0000159 protected:
Mark Sleef5377b32006-10-10 01:42:59 +0000160 /**
Mark Sleef0712dc2006-10-25 19:03:57 +0000161 * The program being generated
162 */
163 t_program* program_;
164
165 /**
Mark Sleef5377b32006-10-10 01:42:59 +0000166 * Quick accessor for formatted program name that is currently being
167 * generated.
168 */
Mark Sleee8540632006-05-30 09:24:40 +0000169 std::string program_name_;
170
Mark Sleef5377b32006-10-10 01:42:59 +0000171 /**
172 * Quick accessor for formatted service name that is currently being
173 * generated.
174 */
Mark Sleee8540632006-05-30 09:24:40 +0000175 std::string service_name_;
176
dweatherford65b70752007-10-31 02:18:14 +0000177 /**
178 * Output type-specifc directory name ("gen-*")
179 */
180 std::string out_dir_base_;
181
Mark Slee31985722006-05-24 21:45:31 +0000182 private:
Mark Sleef5377b32006-10-10 01:42:59 +0000183 /**
184 * Current code indentation level
185 */
Mark Slee31985722006-05-24 21:45:31 +0000186 int indent_;
187
Mark Sleef5377b32006-10-10 01:42:59 +0000188 /**
189 * Temporary variable counter, for making unique variable names
190 */
Mark Sleee8540632006-05-30 09:24:40 +0000191 int tmp_;
Mark Slee31985722006-05-24 21:45:31 +0000192};
193
David Reissbd0db882008-02-27 01:54:51 +0000194
195/**
196 * A factory for producing generator classes of a particular language.
197 *
198 * This class is also responsible for:
199 * - Registering itself with the generator registry.
200 * - Providing documentation for the generators it produces.
201 */
202class t_generator_factory {
203 public:
204 t_generator_factory(const std::string& short_name,
205 const std::string& long_name,
206 const std::string& documentation);
207
208 virtual ~t_generator_factory() {}
209
210 virtual t_generator* get_generator(
211 // The program to generate.
212 t_program* program,
213 // Note: parsed_options will not exist beyond the call to get_generator.
214 const std::map<std::string, std::string>& parsed_options,
215 // Note: option_string might not exist beyond the call to get_generator.
216 const std::string& option_string)
217 = 0;
218
219 std::string get_short_name() { return short_name_; }
220 std::string get_long_name() { return long_name_; }
221 std::string get_documentation() { return documentation_; }
222
223 private:
224 std::string short_name_;
225 std::string long_name_;
226 std::string documentation_;
227};
228
229template <typename generator>
230class t_generator_factory_impl : public t_generator_factory {
231 public:
232 t_generator_factory_impl(const std::string& short_name,
233 const std::string& long_name,
234 const std::string& documentation)
235 : t_generator_factory(short_name, long_name, documentation)
236 {}
237
238 virtual t_generator* get_generator(
239 t_program* program,
240 const std::map<std::string, std::string>& parsed_options,
241 const std::string& option_string) {
242 return new generator(program, parsed_options, option_string);
243 }
244};
245
246class t_generator_registry {
247 public:
248 static void register_generator(t_generator_factory* factory);
249
250 static t_generator* get_generator(t_program* program,
251 const std::string& options);
252
253 typedef std::map<std::string, t_generator_factory*> gen_map_t;
254 static gen_map_t& get_generator_map();
255
256 private:
257 t_generator_registry();
258 t_generator_registry(const t_generator_registry&);
259};
260
261#define THRIFT_REGISTER_GENERATOR(language, long_name, doc) \
262 class t_##language##_generator_factory_impl \
263 : public t_generator_factory_impl<t_##language##_generator> \
264 { \
265 public: \
266 t_##language##_generator_factory_impl() \
267 : t_generator_factory_impl<t_##language##_generator>( \
268 #language, long_name, doc) \
269 {} \
270 }; \
271 static t_##language##_generator_factory_impl _registerer;
272
Mark Slee31985722006-05-24 21:45:31 +0000273#endif