OLD | NEW |
---|---|
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 from model import PropertyType | 5 from model import PropertyType |
6 import code | 6 import code |
7 import cpp_util | 7 import cpp_util |
8 import util_cc_helper | |
8 | 9 |
9 class CCGenerator(object): | 10 class CCGenerator(object): |
10 """A .cc generator for a namespace. | 11 """A .cc generator for a namespace. |
11 """ | 12 """ |
12 def __init__(self, namespace, cpp_type_generator): | 13 def __init__(self, namespace, cpp_type_generator): |
13 self._cpp_type_generator = cpp_type_generator | 14 self._cpp_type_generator = cpp_type_generator |
14 self._namespace = namespace | 15 self._namespace = namespace |
15 self._target_namespace = ( | 16 self._target_namespace = ( |
16 self._cpp_type_generator.GetCppNamespaceName(self._namespace)) | 17 self._cpp_type_generator.GetCppNamespaceName(self._namespace)) |
18 self._util_cc_helper = ( | |
19 util_cc_helper.UtilCCHelper(self._cpp_type_generator)) | |
17 | 20 |
18 def Generate(self): | 21 def Generate(self): |
19 """Generates a code.Code object with the .cc for a single namespace. | 22 """Generates a code.Code object with the .cc for a single namespace. |
20 """ | 23 """ |
21 c = code.Code() | 24 c = code.Code() |
22 (c.Append(cpp_util.CHROMIUM_LICENSE) | 25 (c.Append(cpp_util.CHROMIUM_LICENSE) |
23 .Append() | 26 .Append() |
24 .Append(cpp_util.GENERATED_FILE_MESSAGE % self._namespace.source_file) | 27 .Append(cpp_util.GENERATED_FILE_MESSAGE % self._namespace.source_file) |
25 .Append() | 28 .Append() |
26 .Append('#include "tools/json_schema_compiler/util.h"') | 29 .Append(self._util_cc_helper.GetIncludePath()) |
27 .Append('#include "%s/%s.h"' % | 30 .Append('#include "%s/%s.h"' % |
28 (self._namespace.source_file_dir, self._target_namespace)) | 31 (self._namespace.source_file_dir, self._namespace.name)) |
32 ) | |
33 includes = self._cpp_type_generator.GenerateIncludes() | |
34 if not includes.IsEmpty(): | |
35 (c.Concat(includes) | |
36 .Append() | |
37 ) | |
38 | |
39 (c.Append() | |
40 .Append('using base::Value;') | |
41 .Append('using base::DictionaryValue;') | |
42 .Append('using base::ListValue;') | |
29 .Append() | 43 .Append() |
30 .Concat(self._cpp_type_generator.GetCppNamespaceStart()) | 44 .Concat(self._cpp_type_generator.GetRootNamespaceStart()) |
45 .Concat(self._cpp_type_generator.GetNamespaceStart()) | |
31 .Append() | 46 .Append() |
32 .Append('//') | 47 .Append('//') |
33 .Append('// Types') | 48 .Append('// Types') |
34 .Append('//') | 49 .Append('//') |
35 .Append() | 50 .Append() |
36 ) | 51 ) |
37 for type_ in self._namespace.types.values(): | 52 for type_ in self._namespace.types.values(): |
38 (c.Concat(self._GenerateType(type_)) | 53 (c.Concat(self._GenerateType(type_.name, type_)) |
39 .Append() | 54 .Append() |
40 ) | 55 ) |
41 (c.Append('//') | 56 (c.Append('//') |
42 .Append('// Functions') | 57 .Append('// Functions') |
43 .Append('//') | 58 .Append('//') |
44 .Append() | 59 .Append() |
45 ) | 60 ) |
46 for function in self._namespace.functions.values(): | 61 for function in self._namespace.functions.values(): |
47 (c.Concat(self._GenerateFunction(function)) | 62 (c.Concat(self._GenerateFunction(function)) |
48 .Append() | 63 .Append() |
49 ) | 64 ) |
50 (c.Concat(self._cpp_type_generator.GetCppNamespaceEnd()) | 65 (c.Concat(self._cpp_type_generator.GetNamespaceEnd()) |
66 .Concat(self._cpp_type_generator.GetRootNamespaceEnd()) | |
51 .Append() | 67 .Append() |
52 ) | 68 ) |
53 # TODO(calamity): Events | 69 # TODO(calamity): Events |
54 return c | 70 return c |
55 | 71 |
56 def _GenerateType(self, type_): | 72 def _GenerateType(self, cpp_namespace, type_, serializable=True): |
57 """Generates the function definitions for a type. | 73 """Generates the function definitions for a type. |
58 """ | 74 """ |
75 classname = cpp_util.Classname(type_.name) | |
59 c = code.Code() | 76 c = code.Code() |
60 | 77 |
61 (c.Append('%(classname)s::%(classname)s() {}') | 78 (c.Append('%(namespace)s::%(classname)s() {}') |
62 .Append('%(classname)s::~%(classname)s() {}') | 79 .Append('%(namespace)s::~%(classname)s() {}') |
80 .Append() | |
81 .Concat(self._GenerateTypePopulate(cpp_namespace, type_)) | |
63 .Append() | 82 .Append() |
64 ) | 83 ) |
65 c.Substitute({'classname': type_.name}) | 84 if serializable: |
66 | 85 c.Concat(self._GenerateTypeToValue(cpp_namespace, type_)) |
67 c.Concat(self._GenerateTypePopulate(type_)) | |
68 c.Append() | 86 c.Append() |
69 # TODO(calamity): deal with non-serializable | 87 c.Substitute({'classname': classname, 'namespace': cpp_namespace}) |
70 c.Concat(self._GenerateTypeTovalue(type_)) | |
71 c.Append() | |
72 | 88 |
73 return c | 89 return c |
74 | 90 |
75 def _GenerateTypePopulate(self, type_): | 91 def _GenerateTypePopulate(self, cpp_namespace, type_): |
76 """Generates the function for populating a type given a pointer to it. | 92 """Generates the function for populating a type given a pointer to it. |
77 """ | 93 """ |
94 classname = cpp_util.Classname(type_.name) | |
78 c = code.Code() | 95 c = code.Code() |
79 (c.Append('// static') | 96 (c.Append('// static') |
80 .Sblock('bool %(name)s::Populate(const Value& value, %(name)s* out) {') | 97 .Sblock('bool %(namespace)s::Populate' |
98 '(const Value& value, %(name)s* out) {') | |
81 .Append('if (!value.IsType(Value::TYPE_DICTIONARY))') | 99 .Append('if (!value.IsType(Value::TYPE_DICTIONARY))') |
82 .Append(' return false;') | 100 .Append(' return false;') |
83 .Append('const DictionaryValue* dict = ' | 101 .Append('const DictionaryValue* dict = ' |
84 'static_cast<const DictionaryValue*>(&value);') | 102 'static_cast<const DictionaryValue*>(&value);') |
85 .Append() | 103 .Append() |
86 ) | 104 ) |
87 c.Substitute({'name': type_.name}) | |
88 | |
89 # TODO(calamity): this handle single PropertyType.REF properties. | |
90 # add ALL the types | |
91 for prop in type_.properties.values(): | 105 for prop in type_.properties.values(): |
92 sub = {'name': prop.name} | 106 c.Concat(self._GenerateTypePopulateProperty(prop, 'dict', 'out')) |
93 if prop.type_ == PropertyType.ARRAY: | |
94 if prop.item_type.type_ == PropertyType.REF: | |
95 if prop.optional: | |
96 (c.Append('if (!json_schema_compiler::util::' | |
97 'GetOptionalTypes<%(type)s>(*dict,') | |
98 .Append(' "%(name)s", &out->%(name)s))') | |
99 .Append(' return false;') | |
100 ) | |
101 else: | |
102 (c.Append('if (!json_schema_compiler::util::' | |
103 'GetTypes<%(type)s>(*dict,') | |
104 .Append(' "%(name)s", &out->%(name)s))') | |
105 .Append(' return false;') | |
106 ) | |
107 sub['type'] = self._cpp_type_generator.GetType(prop.item_type, | |
108 pad_for_generics=True) | |
109 elif prop.item_type.type_ == PropertyType.STRING: | |
110 if prop.optional: | |
111 (c.Append('if (!json_schema_compiler::util::GetOptionalStrings' | |
112 '(*dict, "%(name)s", &out->%(name)s))') | |
113 .Append(' return false;') | |
114 ) | |
115 else: | |
116 (c.Append('if (!json_schema_compiler::util::GetStrings' | |
117 '(*dict, "%(name)s", &out->%(name)s))') | |
118 .Append(' return false;') | |
119 ) | |
120 else: | |
121 raise NotImplementedError(prop.item_type.type_) | |
122 elif prop.type_.is_fundamental: | |
123 c.Append('if (!dict->%s)' % | |
124 cpp_util.GetFundamentalValue(prop, '&out->%s' % prop.name)) | |
125 c.Append(' return false;') | |
126 else: | |
127 raise NotImplementedError(prop.type_) | |
128 c.Substitute(sub) | |
129 (c.Append('return true;') | 107 (c.Append('return true;') |
130 .Eblock('}') | 108 .Eblock('}') |
131 ) | 109 ) |
110 c.Substitute({'namespace': cpp_namespace, 'name': classname}) | |
132 return c | 111 return c |
133 | 112 |
134 def _GenerateTypeTovalue(self, type_): | 113 def _GenerateTypePopulateProperty(self, prop, src, dst): |
114 """Generate the code to populate a single property. | |
115 | |
116 src: DictionaryValue* | |
117 dst: Type* | |
118 """ | |
119 c = code.Code() | |
120 dst_member = dst + '->' + prop.unix_name | |
121 if prop.type_ == PropertyType.ARRAY: | |
122 (c.Append('if (!%s)' % | |
123 self._util_cc_helper.GetArray(prop, src, prop.name, dst_member)) | |
124 .Append(' return false;') | |
125 ) | |
126 elif prop.type_ == PropertyType.CHOICES: | |
127 value_var = prop.unix_name + '_value' | |
128 c.Append('Value* %(value)s = NULL;') | |
129 c.Append('if (!(%(src)s->Get("%(key)s", &%(value)s)))') | |
130 if prop.optional: | |
131 c.Append(' return true;') | |
132 else: | |
133 c.Append(' return false;') | |
134 c.Append() | |
135 c.Concat(self._GeneratePopulateChoices( | |
136 prop, value_var, dst, 'return false;')) | |
137 c.Substitute({'value': value_var, 'key': prop.name, 'src': src}) | |
138 else: | |
139 if prop.optional: | |
140 if prop.type_.is_fundamental: | |
141 (c.Sblock('{') | |
142 .Append('%(type)s %(name)s_temp;') | |
143 .Append('if (%s)' % self._GeneratePopulatePropertyFunctionCall( | |
144 prop, src, '&%s_temp' % prop.unix_name)) | |
145 .Append(' out->%(name)s.reset(new %(type)s(%(name)s_temp));') | |
146 .Eblock('}') | |
147 ) | |
148 else: | |
149 raise NotImplementedError('Optional %s not implemented' % prop.type_) | |
150 else: | |
151 (c.Append('if (!%s)' % | |
152 self._GeneratePopulatePropertyFunctionCall( | |
153 prop, src, '&' + dst_member)) | |
154 .Append(' return false;') | |
155 ) | |
156 c.Substitute({ | |
157 'name': prop.unix_name, | |
158 'type': self._cpp_type_generator.GetType(prop) | |
159 }) | |
160 return c | |
161 | |
162 def _GeneratePopulatePropertyFunctionCall(self, prop, src, dst): | |
163 """Generates the function call that populates the given property. | |
164 | |
165 src: DictionaryValue* | |
166 dst: Property* or scoped_ptr<Property> | |
167 """ | |
168 if prop.type_.is_fundamental: | |
169 populate_line = cpp_util.GetFundamentalValue( | |
170 prop, src, prop.name, dst) | |
171 elif prop.type_ in (PropertyType.REF, PropertyType.OBJECT): | |
172 populate_line = '%(type)s::Populate(*%(src)s, %(dst)s)' | |
173 else: | |
174 raise NotImplementedError('%s populate is not implemented' % | |
175 prop.type_) | |
176 return populate_line | |
177 | |
178 def _GenerateTypeToValue(self, cpp_namespace, type_): | |
135 """Generates a function that serializes the type into a |DictionaryValue|. | 179 """Generates a function that serializes the type into a |DictionaryValue|. |
136 """ | 180 """ |
137 c = code.Code() | 181 c = code.Code() |
138 (c.Sblock('DictionaryValue* %s::ToValue() const {' % type_.name) | 182 (c.Sblock('scoped_ptr<DictionaryValue> %s::ToValue() const {' % cpp_namespac e) |
139 .Append('DictionaryValue* value = new DictionaryValue();') | 183 .Append('scoped_ptr<DictionaryValue> value(new DictionaryValue());') |
140 .Append() | 184 .Append() |
141 ) | 185 ) |
142 name = type_.name.lower() | |
143 for prop in type_.properties.values(): | 186 for prop in type_.properties.values(): |
144 prop_name = name + '_' + prop.name if name else prop.name | 187 c.Concat(self._CreateValueFromProperty(prop, prop.unix_name, 'value')) |
145 this_var = prop.name | |
146 c.Concat(self._CreateValueFromProperty(prop_name, prop, this_var)) | |
147 (c.Append() | 188 (c.Append() |
148 .Append('return value;') | 189 .Append('return value.Pass();') |
149 .Eblock('}') | 190 .Eblock('}') |
150 ) | 191 ) |
151 return c | 192 return c |
152 | 193 |
153 # TODO(calamity): object and choices prop types | 194 def _CreateValueFromProperty(self, prop, var, dst): |
154 def _CreateValueFromProperty(self, name, prop, var): | |
155 """Generates code to serialize a single property in a type. | 195 """Generates code to serialize a single property in a type. |
196 | |
197 prop: Property to create from | |
198 var: variable with value to create from | |
156 """ | 199 """ |
157 c = code.Code() | 200 c = code.Code() |
158 if prop.type_.is_fundamental: | 201 if prop.optional: |
159 c.Append('Value* %s_value = %s;' % | 202 c.Sblock('if (%s.get())' % var) |
160 (name, cpp_util.CreateFundamentalValue(prop, var))) | 203 if prop.type_ == PropertyType.ARRAY: |
161 elif prop.type_ == PropertyType.ARRAY: | 204 c.Append('%s;' % self._util_cc_helper.SetArray(prop, var, prop.name, dst)) |
162 if prop.item_type.type_ == PropertyType.STRING: | |
163 if prop.optional: | |
164 c.Append('json_schema_compiler::util::' | |
165 'SetOptionalStrings(%s, "%s", value);' % (var, prop.name)) | |
166 else: | |
167 c.Append('json_schema_compiler::util::' | |
168 'SetStrings(%s, "%s", value);' % (var, prop.name)) | |
169 else: | |
170 item_name = name + '_single' | |
171 (c.Append('ListValue* %(name)s_value = new ListValue();') | |
172 .Append('for (%(it_type)s::iterator it = %(var)s->begin();') | |
173 .Sblock(' it != %(var)s->end(); ++it) {') | |
174 .Concat(self._CreateValueFromProperty(item_name, prop.item_type, | |
175 '*it')) | |
176 .Append('%(name)s_value->Append(%(prop_val)s_value);') | |
177 .Eblock('}') | |
178 ) | |
179 c.Substitute( | |
180 {'it_type': self._cpp_type_generator.GetType(prop), | |
181 'name': name, 'var': var, 'prop_val': item_name}) | |
182 elif prop.type_ == PropertyType.REF: | |
183 c.Append('Value* %s_value = %s.ToValue();' % (name, var)) | |
184 else: | 205 else: |
185 raise NotImplementedError | 206 c.Append('%s->SetWithoutPathExpansion("%s", %s);' % |
207 (dst, prop.name, cpp_util.CreateValueFromSingleProperty(prop, var))) | |
186 return c | 208 return c |
187 | 209 |
188 def _GenerateFunction(self, function): | 210 def _GenerateFunction(self, function): |
189 """Generates the definitions for function structs. | 211 """Generates the definitions for function structs. |
190 """ | 212 """ |
191 classname = cpp_util.CppName(function.name) | 213 classname = cpp_util.Classname(function.name) |
192 c = code.Code() | 214 c = code.Code() |
193 | 215 |
194 # Params::Populate function | 216 # Params::Populate function |
195 if function.params: | 217 if function.params: |
218 for param in function.params: | |
219 if param.type_ == PropertyType.OBJECT: | |
220 param_namespace = '%s::Params::%s' % (classname, | |
221 cpp_util.Classname(param.name)) | |
222 c.Concat( | |
223 self._GenerateType(param_namespace, param, serializable=False)) | |
224 c.Append() | |
196 (c.Append('%(name)s::Params::Params() {}') | 225 (c.Append('%(name)s::Params::Params() {}') |
197 .Append('%(name)s::Params::~Params() {}') | 226 .Append('%(name)s::Params::~Params() {}') |
198 .Append() | 227 .Append() |
199 .Concat(self._GenerateFunctionParamsCreate(function)) | 228 .Concat(self._GenerateFunctionParamsCreate(function)) |
200 .Append() | 229 .Append() |
201 ) | 230 ) |
202 | 231 |
203 # Result::Create function | 232 # Result::Create function |
204 c.Concat(self._GenerateFunctionResultCreate(function)) | 233 c.Concat(self._GenerateFunctionResultCreate(function)) |
205 | 234 |
206 c.Substitute({'name': classname}) | 235 c.Substitute({'name': classname}) |
207 | 236 |
208 return c | 237 return c |
209 | 238 |
239 def _GenerateParamsCheck(self, function, var): | |
240 """Generates a check for the correct number of arguments when creating | |
241 Params. | |
242 """ | |
243 c = code.Code() | |
244 num_required = 0 | |
245 for param in function.params: | |
246 if not param.optional: | |
247 num_required += 1 | |
248 if num_required == len(function.params): | |
249 c.Append('if (%(var)s.GetSize() != %(total)d)') | |
250 elif not num_required: | |
251 c.Append('if (%(var)s.GetSize() > %(total)s)') | |
252 else: | |
253 c.Append('if (%(var)s.GetSize() < %(required)d' | |
254 ' || %(var)s.GetSize() > %(total)d)') | |
255 c.Append(' return scoped_ptr<Params>();') | |
256 c.Substitute({ | |
257 'var': var, | |
258 'required': num_required, | |
259 'total': len(function.params), | |
260 }) | |
261 return c | |
262 | |
210 def _GenerateFunctionParamsCreate(self, function): | 263 def _GenerateFunctionParamsCreate(self, function): |
211 """Generate function to create an instance of Params given a pointer. | 264 """Generate function to create an instance of Params given a pointer. |
212 """ | 265 """ |
213 classname = cpp_util.CppName(function.name) | 266 classname = cpp_util.Classname(function.name) |
214 c = code.Code() | 267 c = code.Code() |
215 (c.Append('// static') | 268 (c.Append('// static') |
216 .Sblock('scoped_ptr<%(classname)s::Params> %(classname)s::Params::Create' | 269 .Sblock('scoped_ptr<%(classname)s::Params> %(classname)s::Params::Create' |
217 '(const ListValue& args) {') | 270 '(const ListValue& args) {') |
218 .Append('if (args.GetSize() != %d)' % len(function.params)) | 271 .Concat(self._GenerateParamsCheck(function, 'args')) |
219 .Append(' return scoped_ptr<Params>();') | |
220 .Append() | |
221 .Append('scoped_ptr<Params> params(new Params());') | 272 .Append('scoped_ptr<Params> params(new Params());') |
222 ) | 273 ) |
223 c.Substitute({'classname': classname}) | 274 c.Substitute({'classname': classname}) |
224 | 275 |
225 # TODO(calamity): generalize, needs to move to function to do populates for | |
226 # wider variety of args | |
227 for i, param in enumerate(function.params): | 276 for i, param in enumerate(function.params): |
228 sub = {'name': param.name, 'pos': i} | 277 dst = 'params->' + param.unix_name |
278 # Any failure will cause this function to return. If any argument is | |
279 # incorrect or missing, those following it are not processed. Note that | |
280 # this is still correct in the case of multiple optional arguments as an | |
281 # optional argument at position 4 cannot exist without an argument at | |
282 # position 3. | |
283 if param.optional: | |
284 return_line = ' return params.Pass();' | |
285 else: | |
286 return_line = ' return scoped_ptr<Params>();' | |
229 c.Append() | 287 c.Append() |
230 # TODO(calamity): Make valid for not just objects | 288 param_var = param.unix_name + '_param' |
231 c.Append('DictionaryValue* %(name)s_param = NULL;') | 289 if param.type_ == PropertyType.ARRAY: |
232 c.Append('if (!args.GetDictionary(%(pos)d, &%(name)s_param))') | 290 (c.Append('ListValue* %(var)s = NULL;') |
233 c.Append(' return scoped_ptr<Params>();') | 291 .Append('if (!args.GetList(%(index)d, &%(var)s))') |
234 if param.type_ == PropertyType.REF: | 292 .Append(return_line) |
Yoyo Zhou
2012/02/10 01:49:33
I think this return_line would be different if you
calamity
2012/02/10 03:52:50
Agreed. I want to do a pretty major refactor regar
Yoyo Zhou
2012/02/10 19:43:21
Ok, just add a TODO for it.
| |
235 c.Append('if (!%(ctype)s::Populate(*%(name)s_param, ' | 293 .Append('if (!%s)' % self._util_cc_helper.GetArrayFromList( |
236 '¶ms->%(name)s))') | 294 param, param_var, dst)) |
237 c.Append(' return scoped_ptr<Params>();') | 295 .Append(return_line) |
238 sub['ctype'] = self._cpp_type_generator.GetType(param) | 296 ) |
239 elif param.type_.is_fundamental: | 297 c.Substitute({'var': param_var, 'index': i}) |
240 raise NotImplementedError('Fundamental types are unimplemented') | |
241 elif param.type_ == PropertyType.OBJECT: | |
242 c.Append('if (!%(ctype)s::Populate(*%(name)s_param, ' | |
243 '¶ms->%(name)s))') | |
244 c.Append(' return scoped_ptr<Params>();') | |
245 sub['ctype'] = self._cpp_type_generator.GetType(param) | |
246 elif param.type_ == PropertyType.CHOICES: | 298 elif param.type_ == PropertyType.CHOICES: |
247 raise NotImplementedError('Choices is unimplemented') | 299 value_var = param.unix_name + '_value' |
300 c.Append('Value* %(value)s = NULL;') | |
301 c.Append('if (!args.Get(%(index)s, &%(value)s))') | |
302 c.Append(return_line) | |
303 c.Append() | |
304 c.Concat(self._GeneratePopulateChoices(param, value_var, 'params', | |
305 'return scoped_ptr<Params>();')) | |
306 c.Substitute({'value': value_var, 'index': i}) | |
248 else: | 307 else: |
249 raise NotImplementedError(param.type_) | 308 if param.optional: |
250 c.Substitute(sub) | 309 dst = dst + '.get()' |
251 c.Append() | 310 else: |
252 c.Append('return params.Pass();') | 311 dst = '&' + dst |
312 if param.type_ in (PropertyType.REF, PropertyType.OBJECT): | |
313 (c.Append('DictionaryValue* %s = NULL;' % param_var) | |
314 .Append('if (!args.GetDictionary(%d, &%s))' % (i, param_var)) | |
315 .Append(return_line) | |
316 ) | |
317 if param.optional: | |
318 c.Append('params->%s.reset(new %s());' % | |
319 (param.unix_name, cpp_util.Classname(param.name))) | |
320 (c.Append('if (!%(ctype)s::Populate(*%(var)s, %(dst)s))' % { | |
321 'var': param_var, 'dst': dst, | |
322 'ctype': self._cpp_type_generator.GetType(param) | |
323 }) | |
324 .Append(return_line) | |
325 ) | |
326 elif param.type_.is_fundamental: | |
327 (c.Append( | |
328 'if (!%s)' % cpp_util.GetValueFromList(param, 'args', i, dst)) | |
329 .Append(return_line) | |
330 ) | |
331 (c.Append() | |
332 .Append('return params.Pass();') | |
333 .Eblock('}') | |
334 ) | |
335 | |
336 return c | |
337 | |
338 def _GeneratePopulateChoices(self, prop, value, dst, return_line): | |
339 """Generates the code to populate a PropertyType.CHOICES parameter or | |
340 property. | |
341 | |
342 value: Value* | |
343 dst: Type* or scoped_ptr<Params> | |
344 return_line: the return line on failure. Check if the property is optional | |
345 BEFORE you call this method as return_line will be used to indicate a | |
Yoyo Zhou
2012/02/10 01:49:33
Maybe s/you call/the code generated by/
calamity
2012/02/10 03:52:50
Done.
| |
346 parsing error. | |
347 """ | |
348 return_line = ' ' + return_line | |
349 type_var = '%s->%s_type' % (dst, prop.unix_name) | |
350 | |
351 c = code.Code() | |
352 c.Append('%s = %s;' % | |
353 (type_var, self._cpp_type_generator.GetChoiceEnumNoneValue(prop))) | |
354 c.Sblock('switch (%s->GetType()) {' % value) | |
355 for choice in self._cpp_type_generator.GetExpandedChoicesInParams([prop]): | |
356 current_choice = '%s->%s' % (dst, choice.unix_name) | |
357 if choice.type_.is_fundamental: | |
358 c.Sblock('case %s: {' % { | |
359 PropertyType.STRING: 'Value::TYPE_STRING', | |
Yoyo Zhou
2012/02/10 01:49:33
These "Value::..." look like they could be attribu
calamity
2012/02/10 03:52:50
I feel that this would couple the python code too
Yoyo Zhou
2012/02/10 19:43:21
Ok, makes sense.
| |
360 PropertyType.INTEGER: 'Value::TYPE_INTEGER', | |
361 PropertyType.BOOLEAN: 'Value::TYPE_BOOLEAN', | |
362 PropertyType.DOUBLE: 'Value::TYPE_DOUBLE' | |
363 }[choice.type_]) | |
364 | |
365 (c.Append('%(type)s = %(enum_value)s;') | |
366 .Append('%s.reset(new %s());' % | |
367 (current_choice, self._cpp_type_generator.GetType(choice))) | |
368 .Append('if (!%s)' % | |
369 cpp_util.GetAsFundamentalValue( | |
370 choice, value, current_choice + '.get()')) | |
371 .Append(return_line) | |
372 .Append('break;') | |
373 .Eblock('}') | |
374 ) | |
375 elif choice.type_ == PropertyType.ARRAY: | |
376 (c.Sblock('case Value::TYPE_LIST: {') | |
377 .Append('%(type)s = %(enum_value)s;') | |
378 .Append('if (!%s)' % self._util_cc_helper.GetArrayFromList( | |
379 choice, 'static_cast<ListValue*>(%s)' % value, current_choice)) | |
380 .Append(return_line) | |
381 .Append('break;') | |
382 .Eblock('}') | |
383 ) | |
384 else: | |
385 raise NotImplementedError(choice.type_) | |
386 c.Substitute({ | |
387 'type': type_var, | |
388 'enum_value': self._cpp_type_generator.GetChoiceEnumValue( | |
389 prop, choice.type_) | |
390 }) | |
391 if not prop.optional: | |
392 (c.Append('default:') | |
393 .Append(return_line) | |
394 ) | |
253 c.Eblock('}') | 395 c.Eblock('}') |
254 | |
255 return c | 396 return c |
256 | 397 |
257 def _GenerateFunctionResultCreate(self, function): | 398 def _GenerateFunctionResultCreate(self, function): |
258 """Generate function to create a Result given the return value. | 399 """Generate function to create a Result given the return value. |
259 """ | 400 """ |
260 classname = cpp_util.CppName(function.name) | 401 classname = cpp_util.Classname(function.name) |
261 c = code.Code() | 402 c = code.Code() |
262 c.Append('// static') | 403 params = function.callback.params |
263 param = function.callback.param | 404 if not params: |
264 arg = '' | 405 (c.Append('Value* %s::Result::Create() {' % classname) |
265 if param: | 406 .Append(' return Value::CreateNullValue();') |
266 if param.type_ == PropertyType.REF: | 407 .Append('}') |
267 arg = 'const %(type)s& %(name)s' | 408 ) |
268 else: | |
269 arg = 'const %(type)s %(name)s' | |
270 arg = arg % { | |
271 'type': self._cpp_type_generator.GetType(param), | |
272 'name': param.name | |
273 } | |
274 c.Sblock('Value* %(classname)s::Result::Create(%(arg)s) {') | |
275 sub = {'classname': classname, 'arg': arg} | |
276 # TODO(calamity): Choices | |
277 if not param: | |
278 c.Append('return Value::CreateNullValue();') | |
279 else: | 409 else: |
280 sub['argname'] = param.name | 410 # If there is a single parameter, this is straightforward. However, if |
281 if param.type_.is_fundamental: | 411 # the callback parameter is of 'choices', this generates a Create method |
282 c.Append('return %s;' % | 412 # for each choice. This works because only 1 choice can be returned at a |
283 cpp_util.CreateFundamentalValue(param, param.name)) | 413 # time. |
284 elif param.type_ == PropertyType.REF: | 414 for param in self._cpp_type_generator.GetExpandedChoicesInParams(params): |
Yoyo Zhou
2012/02/10 01:49:33
This logic looks somewhat duplicated between here
calamity
2012/02/10 03:52:50
Done.
| |
285 c.Append('return %(argname)s.ToValue();') | 415 if param.type_ == PropertyType.REF: |
286 elif param.type_ == PropertyType.OBJECT: | 416 arg = 'const %(type)s& %(name)s' |
287 raise NotImplementedError('Objects not implemented') | 417 else: |
288 elif param.type_ == PropertyType.ARRAY: | 418 arg = 'const %(type)s %(name)s' |
289 raise NotImplementedError('Arrays not implemented') | 419 arg %= { |
290 else: | 420 'type': self._cpp_type_generator.GetType(param, wrap_optional=True), |
291 raise NotImplementedError(param.type_) | 421 'name': param.unix_name, |
292 c.Substitute(sub) | 422 } |
293 c.Eblock('}') | 423 c.Sblock('Value* %(classname)s::Result::Create(%(arg)s) {') |
294 return c | 424 if param.type_ == PropertyType.ARRAY: |
425 (c.Append('ListValue* value = new ListValue();') | |
426 .Append('%s;' % self._util_cc_helper.SetArrayToList( | |
427 param, param.unix_name, 'value')) | |
428 .Append('return value;') | |
429 ) | |
430 else: | |
431 c.Append('return %s;' % cpp_util.CreateValueFromSingleProperty(param, | |
432 param.unix_name)) | |
433 c.Substitute({'classname': classname, 'arg': arg}) | |
434 c.Eblock('}') | |
435 | |
436 return c | |
OLD | NEW |