msgpack-idl 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/AUTHORS +1 -0
- data/ChangeLog +5 -0
- data/README +22 -0
- data/bin/msgpack-idl +3 -0
- data/lib/msgpack/idl/ast.rb +251 -0
- data/lib/msgpack/idl/command/example.rb +135 -0
- data/lib/msgpack/idl/command/idl.rb +262 -0
- data/lib/msgpack/idl/error.rb +60 -0
- data/lib/msgpack/idl/evaluator.rb +616 -0
- data/lib/msgpack/idl/generator.rb +58 -0
- data/lib/msgpack/idl/ir.rb +403 -0
- data/lib/msgpack/idl/module.rb +45 -0
- data/lib/msgpack/idl/parser/rule.rb +499 -0
- data/lib/msgpack/idl/parser/transform.rb +260 -0
- data/lib/msgpack/idl/parser.rb +84 -0
- data/lib/msgpack/idl/version.rb +7 -0
- metadata +111 -0
@@ -0,0 +1,60 @@
|
|
1
|
+
#
|
2
|
+
# MessagePack IDL Processor
|
3
|
+
#
|
4
|
+
# Copyright (C) 2011 FURUHASHI Sadayuki
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
module MessagePack
|
19
|
+
module IDL
|
20
|
+
|
21
|
+
|
22
|
+
class IDLError < StandardError
|
23
|
+
end
|
24
|
+
|
25
|
+
class IncludeError < IDLError
|
26
|
+
end
|
27
|
+
|
28
|
+
class SyntaxError < IDLError
|
29
|
+
end
|
30
|
+
|
31
|
+
class SemanticsError < IDLError
|
32
|
+
end
|
33
|
+
|
34
|
+
class NameError < SemanticsError
|
35
|
+
end
|
36
|
+
|
37
|
+
class InvlaidNameError < NameError
|
38
|
+
end
|
39
|
+
|
40
|
+
class NameNotFoundError < NameError
|
41
|
+
end
|
42
|
+
|
43
|
+
class InvalidNameError < NameError
|
44
|
+
end
|
45
|
+
|
46
|
+
class DuplicatedNameError < NameError
|
47
|
+
end
|
48
|
+
|
49
|
+
class TypeError < SemanticsError
|
50
|
+
end
|
51
|
+
|
52
|
+
class InheritanceError < IDLError
|
53
|
+
end
|
54
|
+
|
55
|
+
class GeneratorError < IDLError
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,616 @@
|
|
1
|
+
#
|
2
|
+
# MessagePack IDL Processor
|
3
|
+
#
|
4
|
+
# Copyright (C) 2011 FURUHASHI Sadayuki
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
module MessagePack
|
19
|
+
module IDL
|
20
|
+
|
21
|
+
|
22
|
+
class Evaluator
|
23
|
+
include ProcessorModule
|
24
|
+
|
25
|
+
class Template
|
26
|
+
def initialize(generic_type, nullable=false)
|
27
|
+
@name = generic_type.name
|
28
|
+
@params = generic_type.type_params
|
29
|
+
@generic_type = generic_type
|
30
|
+
@nullable = nullable
|
31
|
+
end
|
32
|
+
attr_reader :generic_type, :nullable
|
33
|
+
|
34
|
+
def nullable?
|
35
|
+
@nullable
|
36
|
+
end
|
37
|
+
|
38
|
+
def match_all(name, array)
|
39
|
+
if @name != name
|
40
|
+
return nil
|
41
|
+
end
|
42
|
+
if array.size != @params.size
|
43
|
+
return nil
|
44
|
+
end
|
45
|
+
resolved_params = @params.zip(array).map {|a,b|
|
46
|
+
if b.class == IR::TypeParameterSymbol
|
47
|
+
return nil
|
48
|
+
end
|
49
|
+
if a.class != IR::TypeParameterSymbol && a != b
|
50
|
+
return nil
|
51
|
+
end
|
52
|
+
b
|
53
|
+
}
|
54
|
+
resolved_params
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def initialize
|
59
|
+
@names = {} # name:String => AST::Element
|
60
|
+
|
61
|
+
@types = {} # name:String => AST::Type
|
62
|
+
@generic_types = [] # Template
|
63
|
+
|
64
|
+
@global_namespace = "" # Namespace
|
65
|
+
@lang_namespace = {} # lang:String => scope:Namespace
|
66
|
+
|
67
|
+
@services = [] # name:String => IR::Service
|
68
|
+
|
69
|
+
init_built_in
|
70
|
+
|
71
|
+
@ir_types = []
|
72
|
+
@ir_services = []
|
73
|
+
@ir_applications = []
|
74
|
+
end
|
75
|
+
|
76
|
+
def evaluate(ast)
|
77
|
+
ast.each {|e|
|
78
|
+
evaluate_one(e)
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
82
|
+
def evaluate_one(e)
|
83
|
+
case e
|
84
|
+
when AST::Namespace
|
85
|
+
add_namespace(e)
|
86
|
+
|
87
|
+
when AST::Exception
|
88
|
+
check_name(e.name, e)
|
89
|
+
if e.super_class
|
90
|
+
super_message = resolve_type(e.super_class)
|
91
|
+
if !super_message.is_a?(IR::Exception)
|
92
|
+
raise InvalidNameError, "`#{e.super_class}' is not a #{IR::Exception} but a #{super_message.class}"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
new_fields = resolve_fields(e.fields, super_message)
|
96
|
+
add_exception(e.name, super_message, new_fields)
|
97
|
+
|
98
|
+
when AST::Message
|
99
|
+
check_name(e.name, e)
|
100
|
+
if e.super_class
|
101
|
+
super_message = resolve_type(e.super_class)
|
102
|
+
if !super_message.is_a?(IR::Message)
|
103
|
+
raise InvalidNameError, "`#{e.super_class}' is not a #{IR::Message} but a #{super_message.class}"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
new_fields = resolve_fields(e.fields, super_message)
|
107
|
+
add_message(e.name, super_message, new_fields)
|
108
|
+
|
109
|
+
when AST::Enum
|
110
|
+
check_name(e.name, e)
|
111
|
+
fields = resolve_enum_fields(e.fields)
|
112
|
+
add_enum(e.name, fields)
|
113
|
+
|
114
|
+
when AST::Service
|
115
|
+
v = e.version || 0
|
116
|
+
s = check_service_version(e.name, v)
|
117
|
+
funcs = resolve_funcs(e.funcs)
|
118
|
+
add_service_version(s, e.name, v, funcs)
|
119
|
+
|
120
|
+
when AST::Application
|
121
|
+
check_name(e.name, e)
|
122
|
+
scopes = resolve_scopes(e.scopes)
|
123
|
+
add_application(e.name, scopes)
|
124
|
+
|
125
|
+
else
|
126
|
+
raise SemanticsError, "Unknown toplevel AST element `#{e.class}': #{e.inspect}"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def evaluate_inheritance
|
131
|
+
@services.each {|s|
|
132
|
+
super_versions = []
|
133
|
+
s.versions = s.versions.sort_by {|sv| sv.version }
|
134
|
+
s.versions.each do |sv|
|
135
|
+
|
136
|
+
sv.functions.each {|f|
|
137
|
+
f.super_version = nil
|
138
|
+
f.super_func = nil
|
139
|
+
super_versions.reverse_each do |ssv|
|
140
|
+
if sf = ssv.functions.find {|sf| sf.name == f.name }
|
141
|
+
if f.args == sf.args && f.return_type == sf.return_type
|
142
|
+
f.super_version = ssv.version
|
143
|
+
f.super_func = sf
|
144
|
+
end
|
145
|
+
break
|
146
|
+
end
|
147
|
+
end
|
148
|
+
}
|
149
|
+
|
150
|
+
super_versions << sv
|
151
|
+
end
|
152
|
+
}
|
153
|
+
@ir_services = @services
|
154
|
+
self
|
155
|
+
end
|
156
|
+
|
157
|
+
def evaluate_spec(lang)
|
158
|
+
lang = lang.to_s
|
159
|
+
ns = spec_namespace(lang)
|
160
|
+
types = spec_types(lang)
|
161
|
+
services = spec_services(lang)
|
162
|
+
applications = spec_applications(lang)
|
163
|
+
IR::Spec.new(ns, types, services, applications)
|
164
|
+
end
|
165
|
+
|
166
|
+
private
|
167
|
+
def spec_namespace(lang)
|
168
|
+
if ns = @lang_namespace[lang]
|
169
|
+
return ns
|
170
|
+
else
|
171
|
+
@global_namespace
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def spec_types(lang)
|
176
|
+
@ir_types
|
177
|
+
end
|
178
|
+
|
179
|
+
def spec_services(lang)
|
180
|
+
@ir_services
|
181
|
+
end
|
182
|
+
|
183
|
+
def spec_applications(lang)
|
184
|
+
@ir_applications
|
185
|
+
end
|
186
|
+
|
187
|
+
def check_name(name, e)
|
188
|
+
if ee = @names[name]
|
189
|
+
raise DuplicatedNameError, "duplicated name `#{name}': #{e.inspect}"
|
190
|
+
end
|
191
|
+
@names[name] = e
|
192
|
+
end
|
193
|
+
|
194
|
+
|
195
|
+
def resolve_simple_type(e)
|
196
|
+
type = @types[e.name]
|
197
|
+
unless type
|
198
|
+
raise NameNotFoundError, "type not found: #{e.name}"
|
199
|
+
end
|
200
|
+
if e.nullable? && !type.is_a?(IR::NullableType)
|
201
|
+
IR::NullableType.new(type)
|
202
|
+
else
|
203
|
+
type
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def resolve_generic_type(e)
|
208
|
+
query = e.type_params.map {|v|
|
209
|
+
resolve_type(v)
|
210
|
+
}
|
211
|
+
resolved_types = nil
|
212
|
+
template = nil
|
213
|
+
@generic_types.find {|tmpl|
|
214
|
+
if resolved_types = tmpl.match_all(e.name, query)
|
215
|
+
template = tmpl
|
216
|
+
true
|
217
|
+
end
|
218
|
+
}
|
219
|
+
unless resolved_types
|
220
|
+
raise NameNotFoundError, "generic type not matched: #{e.name}"
|
221
|
+
end
|
222
|
+
type = IR::ParameterizedType.new(resolved_types, template.generic_type)
|
223
|
+
if template.nullable || e.nullable?
|
224
|
+
IR::NullableType.new(type)
|
225
|
+
else
|
226
|
+
type
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
def resolve_type(e)
|
231
|
+
if e.is_a?(AST::GenericType)
|
232
|
+
resolve_generic_type(e)
|
233
|
+
else
|
234
|
+
resolve_simple_type(e)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
def resolve_fields(fields, super_message)
|
239
|
+
used_ids = []
|
240
|
+
used_names = {}
|
241
|
+
super_used_names = {}
|
242
|
+
super_used_ids = []
|
243
|
+
|
244
|
+
if super_message
|
245
|
+
super_message.all_fields.each {|f|
|
246
|
+
super_used_ids[f.id] = true
|
247
|
+
super_used_names[f.name] = true
|
248
|
+
}
|
249
|
+
end
|
250
|
+
|
251
|
+
new_fields = fields.map {|e|
|
252
|
+
if e.id == 0
|
253
|
+
raise InvalidNameError, "field id 0 is invalid"
|
254
|
+
end
|
255
|
+
if e.id < 0
|
256
|
+
raise InvalidNameError, "field id < 0 is invalid"
|
257
|
+
end
|
258
|
+
if n = used_ids[e.id]
|
259
|
+
raise DuplicatedNameError, "duplicated field id #{e.id}: #{n}, #{e.name}"
|
260
|
+
end
|
261
|
+
if used_names[e.name]
|
262
|
+
raise DuplicatedNameError, "duplicated field name: #{e.name}"
|
263
|
+
end
|
264
|
+
if super_used_ids[e.id]
|
265
|
+
raise InheritanceError, "field id is duplicated with super class: #{e.is}"
|
266
|
+
end
|
267
|
+
if super_used_names[e.name]
|
268
|
+
raise InheritanceError, "field name is duplicated with super class: #{e.name}"
|
269
|
+
end
|
270
|
+
|
271
|
+
used_ids[e.id] = e.name
|
272
|
+
used_names[e.name] = e.name
|
273
|
+
|
274
|
+
type = resolve_type(e.type)
|
275
|
+
if e.modifier == AST::FIELD_OPTIONAL
|
276
|
+
option = IR::FIELD_OPTIONAL
|
277
|
+
else
|
278
|
+
option = IR::FIELD_REQUIRED
|
279
|
+
end
|
280
|
+
|
281
|
+
if e.is_a?(AST::ValueAssignedField)
|
282
|
+
v = resolve_initial_value(type, e.value)
|
283
|
+
else
|
284
|
+
v = resolve_implicit_value(type)
|
285
|
+
end
|
286
|
+
|
287
|
+
IR::Field.new(e.id, type, e.name, option, v)
|
288
|
+
}.sort_by {|f|
|
289
|
+
f.id
|
290
|
+
}
|
291
|
+
|
292
|
+
return new_fields
|
293
|
+
end
|
294
|
+
|
295
|
+
BUILT_IN_LITERAL = {
|
296
|
+
'BYTE_MAX' => AST::IntLiteral.new((2**7)-1),
|
297
|
+
'SHORT_MAX' => AST::IntLiteral.new((2**15)-1),
|
298
|
+
'INT_MAX' => AST::IntLiteral.new((2**31)-1),
|
299
|
+
'LONG_MAX' => AST::IntLiteral.new((2**63)-1),
|
300
|
+
'UBYTE_MAX' => AST::IntLiteral.new((2**8)-1),
|
301
|
+
'USHORT_MAX' => AST::IntLiteral.new((2**16)-1),
|
302
|
+
'UINT_MAX' => AST::IntLiteral.new((2**32)-1),
|
303
|
+
'ULONG_MAX' => AST::IntLiteral.new((2**64)-1),
|
304
|
+
'BYTE_MIN' => AST::IntLiteral.new(-(2**7)),
|
305
|
+
'SHORT_MIN' => AST::IntLiteral.new(-(2**15)),
|
306
|
+
'INT_MIN' => AST::IntLiteral.new(-(2**31)),
|
307
|
+
'LONG_MIN' => AST::IntLiteral.new(-(2**63)),
|
308
|
+
}
|
309
|
+
|
310
|
+
def resolve_initial_value(type, e)
|
311
|
+
if e.is_a?(AST::ConstLiteral)
|
312
|
+
e = BUILT_IN_LITERAL[e.name] || e
|
313
|
+
end
|
314
|
+
v = case e
|
315
|
+
when AST::NilLiteral
|
316
|
+
IR::NilValue.nil
|
317
|
+
|
318
|
+
when AST::TrueLiteral
|
319
|
+
IR::BoolValue.true
|
320
|
+
|
321
|
+
when AST::FalseLiteral
|
322
|
+
IR::BoolValue.false
|
323
|
+
|
324
|
+
when AST::IntLiteral
|
325
|
+
IR::IntValue.new(e.value)
|
326
|
+
|
327
|
+
when AST::EnumLiteral
|
328
|
+
enum = resolve_type(e.name)
|
329
|
+
if !enum.is_a?(IR::Enum)
|
330
|
+
raise NameNotFoundError, "not a enum type: #{e.name}"
|
331
|
+
end
|
332
|
+
f = enum.fields.find {|f|
|
333
|
+
f.name == e.field
|
334
|
+
}
|
335
|
+
if !f
|
336
|
+
raise NameNotFoundError, "no such field in enum `#{e.name}': #{e.field}"
|
337
|
+
end
|
338
|
+
IR::EnumValue.new(enum, f)
|
339
|
+
|
340
|
+
when AST::ConstLiteral
|
341
|
+
raise NameNotFoundError, "unknown constant: #{name}"
|
342
|
+
|
343
|
+
else
|
344
|
+
raise SemanticsError, "Unknown literal type: #{e.class}"
|
345
|
+
end
|
346
|
+
|
347
|
+
check_assignable(type, v)
|
348
|
+
v
|
349
|
+
end
|
350
|
+
|
351
|
+
def check_assignable(type, v)
|
352
|
+
if type.nullable_type? && v != IR::NilValue.nil
|
353
|
+
raise TypeError, "not-nullable value for nullable type is not allowed"
|
354
|
+
end
|
355
|
+
|
356
|
+
case v
|
357
|
+
when IR::NilValue
|
358
|
+
unless type.nullable_type?
|
359
|
+
raise TypeError, "nullable is expected: #{type}"
|
360
|
+
end
|
361
|
+
|
362
|
+
when IR::IntValue
|
363
|
+
unless IR::Primitive::INT_TYPES.include?(type)
|
364
|
+
raise TypeError, "integer type is expected: #{type}"
|
365
|
+
end
|
366
|
+
# TODO overflow
|
367
|
+
|
368
|
+
when IR::BoolValue
|
369
|
+
if type != IR::Primitive::bool
|
370
|
+
raise TypeError, "bool type is expected: #{type}"
|
371
|
+
end
|
372
|
+
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
def resolve_implicit_value(t)
|
377
|
+
if t.nullable_type?
|
378
|
+
return IR::NilValue.nil
|
379
|
+
end
|
380
|
+
|
381
|
+
if IR::Primitive::INT_TYPES.include?(t)
|
382
|
+
IR::IntValue.new(0)
|
383
|
+
|
384
|
+
elsif t == IR::Primitive.bool
|
385
|
+
IR::BoolValue.false
|
386
|
+
|
387
|
+
elsif t.is_a?(IR::Enum)
|
388
|
+
if t.fields.empty?
|
389
|
+
raise TypeError, "empty enum: #{t.name}"
|
390
|
+
end
|
391
|
+
IR::EnumValue.new(t, t.fields.first)
|
392
|
+
|
393
|
+
else
|
394
|
+
IR::EmptyValue.new
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
398
|
+
def resolve_enum_fields(fields)
|
399
|
+
used_ids = []
|
400
|
+
used_names = {}
|
401
|
+
|
402
|
+
fields = fields.map {|e|
|
403
|
+
if e.id < 0
|
404
|
+
raise InvalidNameError, "enum id < 0 is invalid"
|
405
|
+
end
|
406
|
+
if n = used_ids[e.id]
|
407
|
+
raise DuplicatedNameError, "duplicated enum id #{e.id}: #{n}, #{e.name}"
|
408
|
+
end
|
409
|
+
if used_names[e.name]
|
410
|
+
raise DuplicatedNameError, "duplicated field name: #{e.name}"
|
411
|
+
end
|
412
|
+
|
413
|
+
used_ids[e.id] = e.name
|
414
|
+
used_names[e.name] = e.name
|
415
|
+
|
416
|
+
IR::EnumField.new(e.id, e.name)
|
417
|
+
}.sort_by {|f|
|
418
|
+
f.id
|
419
|
+
}
|
420
|
+
|
421
|
+
return fields
|
422
|
+
end
|
423
|
+
|
424
|
+
def check_service_version(name, version)
|
425
|
+
s = @services.find {|s|
|
426
|
+
s.name == name
|
427
|
+
}
|
428
|
+
if s
|
429
|
+
s.versions.each {|sv|
|
430
|
+
if sv.version == version
|
431
|
+
raise DuplicatedNameError, "duplicated version #{version}"
|
432
|
+
end
|
433
|
+
}
|
434
|
+
else
|
435
|
+
check_name(name, nil)
|
436
|
+
end
|
437
|
+
s
|
438
|
+
end
|
439
|
+
|
440
|
+
def resolve_funcs(funcs)
|
441
|
+
used_names = {}
|
442
|
+
|
443
|
+
funcs = funcs.map {|e|
|
444
|
+
if used_names[e.name]
|
445
|
+
raise DuplicatedNameError, "duplicated function name: #{e.name}"
|
446
|
+
end
|
447
|
+
|
448
|
+
used_names[e.name] = true
|
449
|
+
|
450
|
+
args = resolve_args(e.args)
|
451
|
+
if e.return_type.name == "void"
|
452
|
+
return_type = IR::Primitive.void
|
453
|
+
else
|
454
|
+
return_type = resolve_type(e.return_type)
|
455
|
+
end
|
456
|
+
|
457
|
+
IR::Function.new(e.name, return_type, args, nil, nil)
|
458
|
+
}.sort_by {|f|
|
459
|
+
f.name
|
460
|
+
}
|
461
|
+
|
462
|
+
return funcs
|
463
|
+
end
|
464
|
+
|
465
|
+
def resolve_args(args)
|
466
|
+
used_ids = []
|
467
|
+
used_names = {}
|
468
|
+
|
469
|
+
args = args.map {|e|
|
470
|
+
if e.id == 0
|
471
|
+
raise InvalidNameError, "argument id 0 is invalid"
|
472
|
+
end
|
473
|
+
if e.id < 0
|
474
|
+
raise InvalidNameError, "argument id < 0 is invalid"
|
475
|
+
end
|
476
|
+
if n = used_ids[e.id]
|
477
|
+
raise DuplicatedNameError, "duplicated argument id #{e.id}: #{n}, #{e.name}"
|
478
|
+
end
|
479
|
+
if used_names[e.name]
|
480
|
+
raise DuplicatedNameError, "duplicated argument name: #{e.name}"
|
481
|
+
end
|
482
|
+
|
483
|
+
used_ids[e.id] = e.name
|
484
|
+
used_names[e.name] = e.name
|
485
|
+
|
486
|
+
type = resolve_type(e.type)
|
487
|
+
if e.modifier == AST::FIELD_OPTIONAL
|
488
|
+
option = IR::FIELD_OPTIONAL
|
489
|
+
else
|
490
|
+
option = IR::FIELD_REQUIRED
|
491
|
+
end
|
492
|
+
|
493
|
+
if e.is_a?(AST::ValueAssignedField)
|
494
|
+
v = resolve_initial_value(type, e.value)
|
495
|
+
else
|
496
|
+
v = resolve_implicit_value(type)
|
497
|
+
end
|
498
|
+
|
499
|
+
IR::Argument.new(e.id, type, e.name, option, v)
|
500
|
+
}.sort_by {|a|
|
501
|
+
a.id
|
502
|
+
}
|
503
|
+
|
504
|
+
return args
|
505
|
+
end
|
506
|
+
|
507
|
+
def resolve_scopes(scopes)
|
508
|
+
ds = scopes.find_all {|e|
|
509
|
+
e.default?
|
510
|
+
}
|
511
|
+
if ds.size > 1
|
512
|
+
raise DuplicatedNameError, "multiple default scope: #{ds.map {|e| e.name}.join(', ')}"
|
513
|
+
end
|
514
|
+
|
515
|
+
if ds.empty?
|
516
|
+
default_scope = scopes.first.name
|
517
|
+
else
|
518
|
+
default_scope = ds.first.name
|
519
|
+
end
|
520
|
+
|
521
|
+
used_names = {}
|
522
|
+
|
523
|
+
scopes = scopes.map {|e|
|
524
|
+
if used_names[e.name]
|
525
|
+
raise DuplicatedNameError, "duplicated scope name: #{e.name}"
|
526
|
+
end
|
527
|
+
|
528
|
+
s = @services.find {|s|
|
529
|
+
s.name == e.service
|
530
|
+
}
|
531
|
+
unless s
|
532
|
+
raise NameNotFoundError, "no such service: #{e.name}"
|
533
|
+
end
|
534
|
+
|
535
|
+
sv = s.versions.find {|sv|
|
536
|
+
sv.version == e.version
|
537
|
+
}
|
538
|
+
unless sv
|
539
|
+
raise NameNotFoundError, "no such service version: #{e.service}:#{s.version}"
|
540
|
+
end
|
541
|
+
|
542
|
+
used_names[e.name] = true
|
543
|
+
|
544
|
+
default = default_scope == e.name
|
545
|
+
|
546
|
+
IR::Scope.new(e.name, s, e.version, default)
|
547
|
+
}
|
548
|
+
|
549
|
+
return scopes
|
550
|
+
end
|
551
|
+
|
552
|
+
|
553
|
+
def add_namespace(e)
|
554
|
+
if e.lang
|
555
|
+
@lang_namespace[e.lang] = IR::Namespace.new(e.scopes)
|
556
|
+
else
|
557
|
+
@global_namespace = IR::Namespace.new(e.scopes)
|
558
|
+
end
|
559
|
+
end
|
560
|
+
|
561
|
+
def add_message(name, super_message, fields)
|
562
|
+
m = IR::Message.new(name, super_message, fields)
|
563
|
+
@types[name] = m
|
564
|
+
@ir_types << m
|
565
|
+
m
|
566
|
+
end
|
567
|
+
|
568
|
+
def add_exception(name, super_message, fields)
|
569
|
+
e = IR::Exception.new(name, super_message, fields)
|
570
|
+
@types[name] = e
|
571
|
+
@ir_types << e
|
572
|
+
e
|
573
|
+
end
|
574
|
+
|
575
|
+
def add_enum(name, fields)
|
576
|
+
e = IR::Enum.new(name, fields)
|
577
|
+
@types[name] = e
|
578
|
+
@ir_types << e
|
579
|
+
e
|
580
|
+
end
|
581
|
+
|
582
|
+
def add_service_version(s, name, version, funcs)
|
583
|
+
sv = IR::ServiceVersion.new(version, funcs)
|
584
|
+
if s
|
585
|
+
s.versions << sv
|
586
|
+
else
|
587
|
+
s = IR::Service.new(name, [sv])
|
588
|
+
@services << s
|
589
|
+
end
|
590
|
+
sv
|
591
|
+
end
|
592
|
+
|
593
|
+
def add_application(name, scopes)
|
594
|
+
app = IR::Application.new(name, scopes)
|
595
|
+
@ir_applications << app
|
596
|
+
app
|
597
|
+
end
|
598
|
+
|
599
|
+
|
600
|
+
def init_built_in
|
601
|
+
%w[byte short int long ubyte ushort uint ulong float double bool raw string].each {|name|
|
602
|
+
check_name(name, nil)
|
603
|
+
@types[name] = IR::Primitive.send(name)
|
604
|
+
}
|
605
|
+
check_name('list', nil)
|
606
|
+
@generic_types << Template.new(IR::Primitive.list)
|
607
|
+
check_name('map', nil)
|
608
|
+
@generic_types << Template.new(IR::Primitive.map)
|
609
|
+
#check_name('nullable', nil)
|
610
|
+
#@generic_types << Template.new(IR::Primitive.nullable)
|
611
|
+
end
|
612
|
+
end
|
613
|
+
|
614
|
+
|
615
|
+
end
|
616
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
#
|
2
|
+
# MessagePack IDL Processor
|
3
|
+
#
|
4
|
+
# Copyright (C) 2011 FURUHASHI Sadayuki
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
module MessagePack
|
19
|
+
module IDL
|
20
|
+
|
21
|
+
|
22
|
+
class GeneratorModule
|
23
|
+
include ProcessorModule
|
24
|
+
|
25
|
+
def self.generate(ir, out)
|
26
|
+
new(ir, out).generate!
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
class Generator
|
32
|
+
include ProcessorModule
|
33
|
+
|
34
|
+
GENERATORS = {}
|
35
|
+
|
36
|
+
def self.register(lang, impl)
|
37
|
+
GENERATORS[lang.to_s] = impl
|
38
|
+
end
|
39
|
+
|
40
|
+
def initialize
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.available?(lang)
|
44
|
+
GENERATORS.has_key?(lang)
|
45
|
+
end
|
46
|
+
|
47
|
+
def generate(lang, ir, outdir)
|
48
|
+
gen = GENERATORS[lang]
|
49
|
+
unless gen
|
50
|
+
raise IDLError, "generator not found: #{lang}"
|
51
|
+
end
|
52
|
+
gen.generate(ir, outdir)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|