ridl 2.2.4
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.
- checksums.yaml +7 -0
- data/LICENSE +49 -0
- data/README.rdoc +42 -0
- data/lib/idl/BiDirPolicy.pidl +28 -0
- data/lib/idl/CosNaming.idl +260 -0
- data/lib/idl/IOP.pidl +98 -0
- data/lib/idl/Messaging.pidl +152 -0
- data/lib/idl/PortableServer.pidl +371 -0
- data/lib/idl/TimeBase.pidl +40 -0
- data/lib/idl/orb.idl +200 -0
- data/lib/ridl/backend.rb +124 -0
- data/lib/ridl/delegate.rb +740 -0
- data/lib/ridl/expression.rb +276 -0
- data/lib/ridl/genfile.rb +220 -0
- data/lib/ridl/node.rb +2818 -0
- data/lib/ridl/optparse_ext.rb +357 -0
- data/lib/ridl/parser.diff +42 -0
- data/lib/ridl/parser.rb +3836 -0
- data/lib/ridl/parser.ry +933 -0
- data/lib/ridl/require.rb +18 -0
- data/lib/ridl/ridl.rb +44 -0
- data/lib/ridl/runner.rb +304 -0
- data/lib/ridl/scanner.rb +1238 -0
- data/lib/ridl/type.rb +507 -0
- data/lib/ridl/version.rb +22 -0
- metadata +74 -0
data/lib/ridl/node.rb
ADDED
@@ -0,0 +1,2818 @@
|
|
1
|
+
#--------------------------------------------------------------------
|
2
|
+
# node.rb - IDL nodes
|
3
|
+
#
|
4
|
+
# Author: Martin Corino
|
5
|
+
#
|
6
|
+
# This program is free software; you can redistribute it and/or
|
7
|
+
# modify it under the terms of the RIDL LICENSE which is
|
8
|
+
# included with this program.
|
9
|
+
#
|
10
|
+
# Copyright (c) Remedy IT Expertise BV
|
11
|
+
# Chamber of commerce Rotterdam nr.276339, The Netherlands
|
12
|
+
#--------------------------------------------------------------------
|
13
|
+
module IDL::AST
|
14
|
+
|
15
|
+
REPO_ID_XCHARS = ['.', '-', '_']
|
16
|
+
REPO_ID_RE = /^[#{('a'..'z').to_a.join}#{('A'..'Z').to_a.join}#{('0'..'9').to_a.join}\.\-_\/]+$/
|
17
|
+
|
18
|
+
class Annotation
|
19
|
+
def initialize(id, fields = {})
|
20
|
+
@id = id.to_sym
|
21
|
+
# copy field map transforming all keys to symbols and
|
22
|
+
# detecting nested annotation objects
|
23
|
+
@fields = fields.inject({}) do |m,(k,v)|
|
24
|
+
m[k.to_sym] = case v
|
25
|
+
when Array
|
26
|
+
v.collect { |ve| Hash === ve ? Annotation.new(*ve.to_a.first) : ve }
|
27
|
+
when Hash
|
28
|
+
Annotation.new(*v.to_a.first)
|
29
|
+
else
|
30
|
+
v
|
31
|
+
end
|
32
|
+
m
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
attr_reader :id, :fields
|
37
|
+
|
38
|
+
def is_marker?
|
39
|
+
@fields.empty?
|
40
|
+
end
|
41
|
+
|
42
|
+
def [](fieldid)
|
43
|
+
@fields[(fieldid || '').to_sym]
|
44
|
+
end
|
45
|
+
|
46
|
+
def each(&block)
|
47
|
+
@fields.each(&block)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class Annotations
|
52
|
+
def initialize(stack = [], index = {})
|
53
|
+
@index = index
|
54
|
+
@stack = stack
|
55
|
+
end
|
56
|
+
|
57
|
+
def empty?
|
58
|
+
@stack.empty?
|
59
|
+
end
|
60
|
+
|
61
|
+
def [](annid)
|
62
|
+
(@index[annid] || []).collect { |ix| @stack[ix] }
|
63
|
+
end
|
64
|
+
|
65
|
+
def <<(ann)
|
66
|
+
(@index[ann.id] ||= []) << @stack.size
|
67
|
+
@stack << ann
|
68
|
+
end
|
69
|
+
|
70
|
+
def each(&block)
|
71
|
+
@stack.each(&block)
|
72
|
+
end
|
73
|
+
|
74
|
+
def each_for_id(annid, &block)
|
75
|
+
self[annid].each(&block)
|
76
|
+
end
|
77
|
+
|
78
|
+
def clear
|
79
|
+
@index.clear
|
80
|
+
@stack.clear
|
81
|
+
end
|
82
|
+
|
83
|
+
def concat(anns)
|
84
|
+
(anns || []).each {|_ann| self << _ann }
|
85
|
+
end
|
86
|
+
|
87
|
+
def dup
|
88
|
+
self.class.new(@stack.dup, @index.dup)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class Leaf
|
93
|
+
attr_reader :name, :intern
|
94
|
+
attr_reader :lm_name
|
95
|
+
attr_accessor :enclosure
|
96
|
+
attr_reader :scopes
|
97
|
+
attr_reader :prefix
|
98
|
+
attr_reader :annotations
|
99
|
+
|
100
|
+
def typename
|
101
|
+
self.class.name
|
102
|
+
end
|
103
|
+
|
104
|
+
def initialize(_name, _enclosure)
|
105
|
+
_name ||= ''
|
106
|
+
_name = IDL::Scanner::Identifier.new(_name, _name) unless IDL::Scanner::Identifier === _name
|
107
|
+
@name = _name
|
108
|
+
@lm_name = self.class.mk_name(_name.checked_name, _enclosure.nil? ? false : _enclosure.scopes.size>0).freeze
|
109
|
+
@intern = _name.rjust(1).downcase.intern
|
110
|
+
@enclosure = _enclosure
|
111
|
+
@scopes = if @enclosure.nil? then [] else (@enclosure.scopes.dup << self) end
|
112
|
+
@prefix = ''
|
113
|
+
@repo_id = nil
|
114
|
+
@repo_ver = nil
|
115
|
+
@annotations = Annotations.new
|
116
|
+
end
|
117
|
+
|
118
|
+
def parsed_name_scope
|
119
|
+
(@enclosure ? @enclosure.parsed_name_scope : '') + '::' + @name
|
120
|
+
end
|
121
|
+
|
122
|
+
def lm_name_for_scope
|
123
|
+
lm_name
|
124
|
+
end
|
125
|
+
|
126
|
+
def scoped_name
|
127
|
+
@scoped_name ||= @scopes.collect{|s| s.name}.join("::").freeze
|
128
|
+
end
|
129
|
+
|
130
|
+
def scoped_lm_name
|
131
|
+
@scoped_lm_name ||= @scopes.collect{|s| s.lm_name_for_scope }.join("::").freeze
|
132
|
+
end
|
133
|
+
|
134
|
+
def marshal_dump
|
135
|
+
[@name, @lm_name, @intern, @enclosure, @scopes, @prefix, @repo_id, @repo_ver, @annotations]
|
136
|
+
end
|
137
|
+
|
138
|
+
def marshal_load(vars)
|
139
|
+
@name, @lm_name, @intern, @enclosure, @scopes, @prefix, @repo_id, @repo_ver, @annotations = vars
|
140
|
+
@scoped_name = nil
|
141
|
+
@scoped_lm_name = nil
|
142
|
+
end
|
143
|
+
|
144
|
+
def repo_scopes
|
145
|
+
@repo_scopes ||= (@enclosure.nil? ? [] : (@enclosure.repo_scopes.dup << self))
|
146
|
+
end
|
147
|
+
|
148
|
+
def is_template?
|
149
|
+
@enclosure && @enclosure.is_template?
|
150
|
+
end
|
151
|
+
|
152
|
+
def instantiate(_context, _enclosure, _params = {})
|
153
|
+
(_context[self] = self.class.new(self.name, _enclosure, _params)).copy_from(self, _context)
|
154
|
+
end
|
155
|
+
|
156
|
+
def set_repo_id(id)
|
157
|
+
if @repo_id
|
158
|
+
if id != @repo_id
|
159
|
+
raise RuntimeError,
|
160
|
+
"#{self.scoped_name} already has a different repository ID assigned: #{@repo_id}"
|
161
|
+
end
|
162
|
+
end
|
163
|
+
id_arr = id.split(':')
|
164
|
+
if @repo_ver
|
165
|
+
if id_arr.first != 'IDL' or id_arr.last != @repo_ver
|
166
|
+
raise RuntimeError,
|
167
|
+
"supplied repository ID (#{id}) does not match previously assigned repository version for #{self.scoped_name} = #{@repo_ver}"
|
168
|
+
end
|
169
|
+
end
|
170
|
+
# check validity of IDL format repo IDs
|
171
|
+
if id_arr.first == 'IDL'
|
172
|
+
id_arr.shift
|
173
|
+
id_str = id_arr.shift.to_s
|
174
|
+
raise RuntimeError, 'ID identifiers should not start or end with \'/\'' if id_str[0,1]=='/' or id_str[-1, 1]=='/'
|
175
|
+
raise RuntimeError, "ID identifiers should not start with one of '#{REPO_ID_XCHARS.join("', '")}'" if REPO_ID_XCHARS.include?(id_str[0,1])
|
176
|
+
raise RuntimeError, 'Invalid ID! Only a..z, A..Z, 0..9, \'.\', \'-\', \'_\' or \'\/\' allowed for identifiers' unless REPO_ID_RE =~ id_str
|
177
|
+
end
|
178
|
+
@repo_id = id
|
179
|
+
end
|
180
|
+
|
181
|
+
def set_repo_version(ma, mi)
|
182
|
+
ver = "#{ma}.#{mi}"
|
183
|
+
if @repo_ver
|
184
|
+
if ver != @repo_ver
|
185
|
+
raise RuntimeError,
|
186
|
+
"#{self.scoped_name} already has a repository version assigned: #{@repo_ver}"
|
187
|
+
end
|
188
|
+
end
|
189
|
+
if @repo_id
|
190
|
+
l = @repo_id.split(':')
|
191
|
+
if l.last != ver
|
192
|
+
raise RuntimeError,
|
193
|
+
"supplied repository version (#{ver}) does not match previously assigned repository ID for #{self.scoped_name}: #{@repo_id}"
|
194
|
+
end
|
195
|
+
end
|
196
|
+
@repo_ver = ver
|
197
|
+
end
|
198
|
+
|
199
|
+
def prefix=(pfx)
|
200
|
+
unless pfx.to_s.empty?
|
201
|
+
raise RuntimeError, 'ID prefix should not start or end with \'/\'' if pfx[0,1]=='/' or pfx[-1, 1]=='/'
|
202
|
+
raise RuntimeError, "ID prefix should not start with one of '#{REPO_ID_XCHARS.join("', '")}'" if REPO_ID_XCHARS.include?(pfx[0,1])
|
203
|
+
raise RuntimeError, 'Invalid ID prefix! Only a..z, A..Z, 0..9, \'.\', \'-\', \'_\' or \'\/\' allowed' unless REPO_ID_RE =~ pfx
|
204
|
+
end
|
205
|
+
self._set_prefix(pfx)
|
206
|
+
end
|
207
|
+
|
208
|
+
def replace_prefix(pfx)
|
209
|
+
self.prefix = pfx
|
210
|
+
end
|
211
|
+
|
212
|
+
def _set_prefix(pfx)
|
213
|
+
@prefix = pfx.to_s
|
214
|
+
end
|
215
|
+
|
216
|
+
def repository_id
|
217
|
+
if @repo_id.nil?
|
218
|
+
@repo_ver = "1.0" unless @repo_ver
|
219
|
+
format("IDL:%s%s:%s",
|
220
|
+
if @prefix.empty? then "" else @prefix+"/" end,
|
221
|
+
self.repo_scopes.collect{|s| s.name}.join("/"),
|
222
|
+
@repo_ver)
|
223
|
+
else
|
224
|
+
@repo_id
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
def has_annotations?()
|
229
|
+
!@annotations.empty?
|
230
|
+
end
|
231
|
+
|
232
|
+
def resolve(_name)
|
233
|
+
nil
|
234
|
+
end
|
235
|
+
|
236
|
+
def is_local?
|
237
|
+
false
|
238
|
+
end
|
239
|
+
|
240
|
+
protected
|
241
|
+
def copy_from(_template, _context)
|
242
|
+
@prefix = _template.instance_variable_get(:@prefix)
|
243
|
+
@repo_id = _template.instance_variable_get(:@repo_id)
|
244
|
+
@repo_ver = _template.instance_variable_get(:@repo_ver)
|
245
|
+
@annotations = _template.instance_variable_get(:@annotations)
|
246
|
+
self
|
247
|
+
end
|
248
|
+
end # Leaf
|
249
|
+
|
250
|
+
class Node < Leaf
|
251
|
+
def initialize(name, enclosure)
|
252
|
+
super
|
253
|
+
@introduced = Hash.new
|
254
|
+
@children = []
|
255
|
+
introduce(self)
|
256
|
+
end
|
257
|
+
|
258
|
+
def marshal_dump
|
259
|
+
super() << @children << @introduced
|
260
|
+
end
|
261
|
+
|
262
|
+
def marshal_load(vars)
|
263
|
+
@introduced = vars.pop
|
264
|
+
@children = vars.pop
|
265
|
+
super(vars)
|
266
|
+
end
|
267
|
+
|
268
|
+
def introduce(node)
|
269
|
+
n = (@introduced[node.intern] ||= node)
|
270
|
+
raise RuntimeError,
|
271
|
+
"#{node.name} is already introduced as a #{n.scoped_name} of #{n.typename}." if n != node
|
272
|
+
end
|
273
|
+
|
274
|
+
def undo_introduction(node)
|
275
|
+
@introduced.delete(node.intern)
|
276
|
+
end
|
277
|
+
|
278
|
+
def redefine(node, params)
|
279
|
+
raise RuntimeError, "\"#{node.name}\" is already defined."
|
280
|
+
end
|
281
|
+
|
282
|
+
def is_definable?(_type)
|
283
|
+
self.class::DEFINABLE.any? do |target|
|
284
|
+
_type.ancestors.include? target
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
def define(_type, _name, params = Hash.new)
|
289
|
+
if not is_definable?(_type)
|
290
|
+
raise RuntimeError,
|
291
|
+
"#{_type.to_s} is not definable in #{self.typename}."
|
292
|
+
end
|
293
|
+
node = search_self(_name)
|
294
|
+
if node.nil?
|
295
|
+
node = _type.new(_name, self, params)
|
296
|
+
node.annotations.concat(params[:annotations])
|
297
|
+
node.prefix = @prefix
|
298
|
+
introduce(node)
|
299
|
+
@children << node
|
300
|
+
else
|
301
|
+
if _type != node.class
|
302
|
+
raise RuntimeError,
|
303
|
+
"#{_name} is already defined as a type of #{node.typename}"
|
304
|
+
end
|
305
|
+
node = redefine(node, params)
|
306
|
+
end
|
307
|
+
node
|
308
|
+
end
|
309
|
+
|
310
|
+
def resolve(_name)
|
311
|
+
node = search_enclosure(_name)
|
312
|
+
@introduced[node.intern] = node unless node.nil?
|
313
|
+
node
|
314
|
+
end
|
315
|
+
|
316
|
+
def walk_members(&block)
|
317
|
+
@children.each { |c| yield(c) }
|
318
|
+
end
|
319
|
+
|
320
|
+
def match_members(&block)
|
321
|
+
!(@children.find { |c| yield(c) }).nil?
|
322
|
+
end
|
323
|
+
|
324
|
+
def replace_prefix(pfx)
|
325
|
+
super
|
326
|
+
walk_members { |m| m.replace_prefix(pfx) }
|
327
|
+
end
|
328
|
+
|
329
|
+
protected
|
330
|
+
def children
|
331
|
+
@children
|
332
|
+
end
|
333
|
+
|
334
|
+
def search_self(_name)
|
335
|
+
key = _name.downcase.intern
|
336
|
+
node = @introduced[key]
|
337
|
+
if not node.nil? and node.name != _name
|
338
|
+
raise RuntimeError, "\"#{_name}\" clashed with \"#{node.name}\"."
|
339
|
+
end
|
340
|
+
node
|
341
|
+
end
|
342
|
+
|
343
|
+
def search_enclosure(_name)
|
344
|
+
node = search_self(_name)
|
345
|
+
if node.nil? and not @enclosure.nil?
|
346
|
+
node = @enclosure.search_enclosure(_name)
|
347
|
+
end
|
348
|
+
node
|
349
|
+
end
|
350
|
+
|
351
|
+
def walk_members_for_copy(&block)
|
352
|
+
self.walk_members(&block)
|
353
|
+
end
|
354
|
+
|
355
|
+
def copy_from(_template, _context)
|
356
|
+
super
|
357
|
+
_template.__send__(:walk_members_for_copy) do |child|
|
358
|
+
_child_copy = child.instantiate(_context, self)
|
359
|
+
@children << _child_copy
|
360
|
+
# introduce unless already introduced (happens with module chains)
|
361
|
+
@introduced[_child_copy.intern] = _child_copy unless @introduced.has_key?(_child_copy.intern)
|
362
|
+
end
|
363
|
+
self
|
364
|
+
end
|
365
|
+
end # Node
|
366
|
+
|
367
|
+
# Forward declarations
|
368
|
+
|
369
|
+
class Module < Node; end
|
370
|
+
class Include < Module; end
|
371
|
+
class TemplateParam < Leaf; end
|
372
|
+
class TemplateModule < Module; end
|
373
|
+
class TemplateModuleReference < Leaf; end
|
374
|
+
class Derivable < Node; end
|
375
|
+
class Interface < Derivable; end
|
376
|
+
class ComponentBase < Derivable; end
|
377
|
+
class Connector < ComponentBase; end
|
378
|
+
class Component < ComponentBase; end
|
379
|
+
class Porttype < Node; end
|
380
|
+
class Port < Leaf; end
|
381
|
+
class Home < ComponentBase; end
|
382
|
+
class Valuebox < Leaf; end
|
383
|
+
class Valuetype < Derivable; end
|
384
|
+
class Typedef < Leaf; end
|
385
|
+
class Const < Leaf; end
|
386
|
+
class Operation < Node; end
|
387
|
+
class Attribute < Leaf; end
|
388
|
+
class Parameter < Leaf; end
|
389
|
+
class StateMember < Leaf; end
|
390
|
+
class Initializer < Leaf; end
|
391
|
+
class Finder < Initializer; end
|
392
|
+
class Struct < Node; end
|
393
|
+
class Member < Leaf; end
|
394
|
+
class Union < Node; end
|
395
|
+
class UnionMember < Member; end
|
396
|
+
class Enum < Leaf; end
|
397
|
+
class Enumerator < Leaf; end
|
398
|
+
|
399
|
+
class Module < Node
|
400
|
+
NAMETYPE = :class
|
401
|
+
DEFINABLE = [
|
402
|
+
IDL::AST::Module, IDL::AST::Interface, IDL::AST::Valuebox, IDL::AST::Valuetype, IDL::AST::Const, IDL::AST::Struct,
|
403
|
+
IDL::AST::Union, IDL::AST::Enum, IDL::AST::Enumerator, IDL::AST::Typedef, IDL::AST::Include,
|
404
|
+
IDL::AST::Home, IDL::AST::Porttype, IDL::AST::Component, IDL::AST::Connector
|
405
|
+
]
|
406
|
+
attr_reader :anchor, :next
|
407
|
+
def initialize(_name, _enclosure, params)
|
408
|
+
super(_name, _enclosure)
|
409
|
+
@anchor = params[:anchor]
|
410
|
+
@prefix = params[:prefix] || @prefix
|
411
|
+
@not_in_repo_id = params[:not_in_repo_id]
|
412
|
+
@next = nil
|
413
|
+
end
|
414
|
+
|
415
|
+
def has_anchor?
|
416
|
+
!@anchor.nil?
|
417
|
+
end
|
418
|
+
|
419
|
+
def annotations
|
420
|
+
(has_anchor? ? self.anchor : self).get_annotations
|
421
|
+
end
|
422
|
+
|
423
|
+
def marshal_dump
|
424
|
+
super() << @anchor << @next
|
425
|
+
end
|
426
|
+
|
427
|
+
def marshal_load(vars)
|
428
|
+
@next = vars.pop
|
429
|
+
@anchor = vars.pop
|
430
|
+
super(vars)
|
431
|
+
end
|
432
|
+
|
433
|
+
def instantiate(_context, _enclosure)
|
434
|
+
super(_context, _enclosure, {})
|
435
|
+
end
|
436
|
+
|
437
|
+
def repo_scopes
|
438
|
+
@repo_scopes ||= (@enclosure.nil? ? [] : (@not_in_repo_id ? @enclosure.repo_scopes.dup : (@enclosure.repo_scopes.dup << self)))
|
439
|
+
end
|
440
|
+
|
441
|
+
def redefine(node, params)
|
442
|
+
case node
|
443
|
+
when IDL::AST::Include
|
444
|
+
if node.enclosure == self
|
445
|
+
return node
|
446
|
+
else
|
447
|
+
_inc = IDL::AST::Include.new(node.name, self, params)
|
448
|
+
_inc.annotations.concat(params[:annotations])
|
449
|
+
@children << _inc
|
450
|
+
return _inc
|
451
|
+
end
|
452
|
+
when IDL::AST::Module
|
453
|
+
# Module reopening
|
454
|
+
_anchor = node.has_anchor? ? node.anchor : node
|
455
|
+
_anchor.annotations.concat(params[:annotations])
|
456
|
+
_last = _anchor.find_last
|
457
|
+
_params = { :anchor => _anchor, :prefix => node.prefix }
|
458
|
+
_next = IDL::AST::Module.new(node.name, self, _params)
|
459
|
+
_last.set_next(_next)
|
460
|
+
@children << _next
|
461
|
+
return _next
|
462
|
+
when IDL::AST::Interface
|
463
|
+
node.annotations.concat(params[:annotations])
|
464
|
+
return node if params[:forward]
|
465
|
+
if node.is_defined?
|
466
|
+
raise RuntimeError, "#{node.typename} \"#{node.name}\" is already defined."
|
467
|
+
end
|
468
|
+
if (node.is_abstract? != params[:abstract]) || (node.is_local? != params[:local]) || (node.is_pseudo? != params[:pseudo])
|
469
|
+
raise RuntimeError, "\"attributes are not the same: \"#{node.name}\"."
|
470
|
+
end
|
471
|
+
|
472
|
+
_intf = IDL::AST::Interface.new(node.name, self, params)
|
473
|
+
_intf.annotations.concat(node.annotations)
|
474
|
+
_intf.prefix = node.prefix
|
475
|
+
_intf.instance_variable_set(:@repo_ver, node.instance_variable_get(:@repo_ver))
|
476
|
+
_intf.instance_variable_set(:@repo_id, node.instance_variable_get(:@repo_id))
|
477
|
+
|
478
|
+
@children << _intf
|
479
|
+
# replace forward node registration
|
480
|
+
node.enclosure.undo_introduction(node)
|
481
|
+
introduce(_intf)
|
482
|
+
|
483
|
+
return _intf
|
484
|
+
when IDL::AST::Valuetype
|
485
|
+
node.annotations.concat(params[:annotations])
|
486
|
+
return node if params[:forward]
|
487
|
+
if node.is_defined?
|
488
|
+
raise RuntimeError, "#{node.typename} \"#{node.name}\" is already defined."
|
489
|
+
end
|
490
|
+
if (node.is_abstract? != params[:abstract])
|
491
|
+
raise RuntimeError, "\"attributes are not the same: \"#{node.name}\"."
|
492
|
+
end
|
493
|
+
|
494
|
+
_new_node = node.class.new(node.name, self, params)
|
495
|
+
_new_node.annotations.concat(node.annotations)
|
496
|
+
_new_node.prefix = node.prefix
|
497
|
+
_new_node.instance_variable_set(:@repo_ver, node.instance_variable_get(:@repo_ver))
|
498
|
+
_new_node.instance_variable_set(:@repo_id, node.instance_variable_get(:@repo_id))
|
499
|
+
|
500
|
+
@children << _new_node
|
501
|
+
# replace forward node registration
|
502
|
+
node.enclosure.undo_introduction(node)
|
503
|
+
introduce(_new_node)
|
504
|
+
|
505
|
+
return _new_node
|
506
|
+
when IDL::AST::Struct, IDL::AST::Union
|
507
|
+
node.annotations.concat(params[:annotations])
|
508
|
+
return node if params[:forward]
|
509
|
+
if node.is_defined?
|
510
|
+
raise RuntimeError, "#{node.typename} \"#{node.name}\" is already defined."
|
511
|
+
end
|
512
|
+
|
513
|
+
_new_node = node.class.new(node.name, self, params)
|
514
|
+
_new_node.annotations.concat(node.annotations)
|
515
|
+
_new_node.prefix = node.prefix
|
516
|
+
_new_node.instance_variable_set(:@repo_ver, node.instance_variable_get(:@repo_ver))
|
517
|
+
_new_node.instance_variable_set(:@repo_id, node.instance_variable_get(:@repo_id))
|
518
|
+
|
519
|
+
node.switchtype = params[:switchtype] if node.is_a?(IDL::AST::Union)
|
520
|
+
|
521
|
+
@children << _new_node
|
522
|
+
# replace forward node registration
|
523
|
+
node.enclosure.undo_introduction(node)
|
524
|
+
introduce(_new_node)
|
525
|
+
|
526
|
+
return _new_node
|
527
|
+
end
|
528
|
+
raise RuntimeError,
|
529
|
+
"#{node.name} is already introduced as #{node.typename} #{node.scoped_name}."
|
530
|
+
end
|
531
|
+
|
532
|
+
def undo_introduction(node)
|
533
|
+
_mod = (@anchor || self)
|
534
|
+
while _mod
|
535
|
+
_mod._undo_link_introduction(node)
|
536
|
+
_mod = _mod.next
|
537
|
+
end
|
538
|
+
end
|
539
|
+
|
540
|
+
def replace_prefix(pfx)
|
541
|
+
self.prefix = pfx # handles validation
|
542
|
+
if @anchor.nil?
|
543
|
+
self.replace_prefix_(pfx)
|
544
|
+
else
|
545
|
+
@anchor.replace_prefix_(pfx)
|
546
|
+
end
|
547
|
+
end
|
548
|
+
|
549
|
+
def _set_prefix(pfx)
|
550
|
+
if @anchor.nil?
|
551
|
+
self._set_prefix_(pfx)
|
552
|
+
else
|
553
|
+
@anchor._set_prefix_(pfx)
|
554
|
+
end
|
555
|
+
end
|
556
|
+
|
557
|
+
protected
|
558
|
+
|
559
|
+
def get_annotations
|
560
|
+
@annotations
|
561
|
+
end
|
562
|
+
|
563
|
+
def copy_from(_template, _context)
|
564
|
+
super
|
565
|
+
if _template.has_anchor?
|
566
|
+
# module anchor is first to be copied/instantiated and
|
567
|
+
# should be registered in _context
|
568
|
+
@anchor = IDL::AST::TemplateParam.concrete_param(_context, _template.anchor)
|
569
|
+
# link ourself into module chain
|
570
|
+
@anchor.find_last.set_next(self)
|
571
|
+
end
|
572
|
+
@next = nil # to be sure
|
573
|
+
self
|
574
|
+
end
|
575
|
+
|
576
|
+
def replace_prefix_(pfx)
|
577
|
+
walk_members { |m| m.replace_prefix(pfx) }
|
578
|
+
# propagate along chain using fast method
|
579
|
+
@next.replace_prefix_(pfx) unless @next.nil?
|
580
|
+
end
|
581
|
+
|
582
|
+
def _set_prefix_(pfx)
|
583
|
+
@prefix = pfx
|
584
|
+
# propagate along chain
|
585
|
+
self.next._set_prefix_(pfx) unless self.next.nil?
|
586
|
+
end
|
587
|
+
|
588
|
+
def search_self(_name)
|
589
|
+
(@anchor || self).search_links(_name)
|
590
|
+
end
|
591
|
+
|
592
|
+
def search_links(_name)
|
593
|
+
_key = _name.downcase.intern
|
594
|
+
node = @introduced[_key]
|
595
|
+
if not node.nil? and node.name != _name
|
596
|
+
raise RuntimeError, "\"#{_name}\" clashed with \"#{node.name}\"."
|
597
|
+
end
|
598
|
+
if node.nil? && @next
|
599
|
+
node = @next.search_links(_name)
|
600
|
+
end
|
601
|
+
node
|
602
|
+
end
|
603
|
+
|
604
|
+
def _undo_link_introduction(node)
|
605
|
+
@introduced.delete(node.intern)
|
606
|
+
end
|
607
|
+
|
608
|
+
def set_next(mod)
|
609
|
+
@next = mod
|
610
|
+
end
|
611
|
+
|
612
|
+
def find_last
|
613
|
+
if @next.nil?
|
614
|
+
self
|
615
|
+
else
|
616
|
+
@next.find_last
|
617
|
+
end
|
618
|
+
end
|
619
|
+
end # Module
|
620
|
+
|
621
|
+
class TemplateParam < Leaf
|
622
|
+
NAMETYPE = :class
|
623
|
+
attr_reader :idltype, :concrete
|
624
|
+
def initialize(_name, _enclosure, params)
|
625
|
+
super(_name, _enclosure)
|
626
|
+
@idltype = params[:type]
|
627
|
+
@concrete = nil
|
628
|
+
end
|
629
|
+
|
630
|
+
def marshal_dump
|
631
|
+
super() << @idltype
|
632
|
+
end
|
633
|
+
|
634
|
+
def marshal_load(vars)
|
635
|
+
@idltype = vars.pop
|
636
|
+
super(vars)
|
637
|
+
end
|
638
|
+
|
639
|
+
def is_template?
|
640
|
+
true
|
641
|
+
end
|
642
|
+
|
643
|
+
def set_concrete_param(_param)
|
644
|
+
@concrete = _param
|
645
|
+
end
|
646
|
+
|
647
|
+
def self.concrete_param(_context, _node)
|
648
|
+
if _node.is_template?
|
649
|
+
_cnode = if _node.is_a?(IDL::AST::TemplateParam)
|
650
|
+
_node.concrete
|
651
|
+
else
|
652
|
+
# referenced template node should have been instantiated already and available through context
|
653
|
+
_context[_node]
|
654
|
+
end
|
655
|
+
raise RuntimeError, "cannot resolve concrete node for template #{_node.typename} #{_node.scoped_lm_name}" unless _cnode
|
656
|
+
_cnode
|
657
|
+
else
|
658
|
+
_node
|
659
|
+
end
|
660
|
+
end
|
661
|
+
end
|
662
|
+
|
663
|
+
class TemplateModule < Module
|
664
|
+
NAMETYPE = :class
|
665
|
+
DEFINABLE = [
|
666
|
+
IDL::AST::Include, IDL::AST::Module, IDL::AST::Interface, IDL::AST::Valuebox, IDL::AST::Valuetype,
|
667
|
+
IDL::AST::Const, IDL::AST::Struct, IDL::AST::Union, IDL::AST::Enum, IDL::AST::Enumerator, IDL::AST::Typedef,
|
668
|
+
IDL::AST::Home, IDL::AST::Porttype, IDL::AST::Component, IDL::AST::Connector,
|
669
|
+
IDL::AST::TemplateParam, IDL::AST::TemplateModuleReference
|
670
|
+
]
|
671
|
+
attr_reader :idltype
|
672
|
+
def initialize(_name, _enclosure, _params)
|
673
|
+
super(_name, _enclosure, {})
|
674
|
+
@idltype = IDL::Type::TemplateModule.new(self)
|
675
|
+
@template_params = []
|
676
|
+
end
|
677
|
+
|
678
|
+
def define(*args)
|
679
|
+
child = super(*args)
|
680
|
+
@template_params << child if child.is_a?(IDL::AST::TemplateParam)
|
681
|
+
child
|
682
|
+
end
|
683
|
+
|
684
|
+
def is_template?
|
685
|
+
true
|
686
|
+
end
|
687
|
+
|
688
|
+
def instantiate(_module_instance, _concrete_params, _context = {})
|
689
|
+
# process concrete parameters
|
690
|
+
@template_params.each_with_index do |_tp, _ix|
|
691
|
+
raise RuntimeError,
|
692
|
+
"missing template parameter for #{typename} #{scoped_lm_name}: #{_tp.name}" unless _ix < _concrete_params.size
|
693
|
+
_cp = _concrete_params[_ix]
|
694
|
+
if _cp.is_a?(IDL::Type)
|
695
|
+
raise RuntimeError, "anonymous type definitions are not allowed!" if _cp.is_anonymous?
|
696
|
+
# parameter should be a matching IDL::Type
|
697
|
+
unless _tp.idltype.is_a?(IDL::Type::Any) || _tp.idltype.class === _cp.resolved_type
|
698
|
+
raise RuntimeError, "mismatched instantiation parameter \##{_ix} #{_cp.typename} for #{typename} #{scoped_lm_name}: expected #{_tp.idltype.typename} for #{_tp.name}"
|
699
|
+
end
|
700
|
+
# verify concrete parameter
|
701
|
+
case _tp.idltype
|
702
|
+
when IDL::Type::Any # 'typename'
|
703
|
+
# no further checks
|
704
|
+
when IDL::Type::Interface, # 'interface'
|
705
|
+
IDL::Type::Eventtype, # 'eventtype'
|
706
|
+
IDL::Type::Valuetype, # 'valuetype'
|
707
|
+
IDL::Type::Struct, # 'struct'
|
708
|
+
IDL::Type::Union, # 'union'
|
709
|
+
IDL::Type::Exception, # 'exception'
|
710
|
+
IDL::Type::Enum # 'enum'
|
711
|
+
# no further checks
|
712
|
+
when IDL::Type::Sequence # 'sequence' or 'sequence<...>'
|
713
|
+
_tptype = _tp.idltype
|
714
|
+
unless _tptype.basetype.is_a?(IDL::Type::Void) # 'sequence'
|
715
|
+
# check basetype
|
716
|
+
unless _tptype.basetype.is_a?(IDL::Type::ScopedName) &&
|
717
|
+
_tptype.basetype.is_node?(IDL::AST::TemplateParam) &&
|
718
|
+
_tptype.basetype.node.concrete &&
|
719
|
+
_tptype.basetype.node.concrete.idltype.resolved_type == _cp.resolved_type.basetype.resolved_type
|
720
|
+
raise RuntimeError, "invalid sequence type as instantiation parameter for #{typename} #{scoped_lm_name}: expected #{_tp.idltype.typename} for #{_tp.name}"
|
721
|
+
end
|
722
|
+
end
|
723
|
+
end
|
724
|
+
elsif _cp.is_a?(IDL::Expression)
|
725
|
+
# template param should be 'const <const_type>'
|
726
|
+
unless _tp.idltype.is_a?(IDL::Type::Const)
|
727
|
+
raise RuntimeError, "unexpected expression as instantiation parameter for #{typename} #{scoped_lm_name}: expected #{_tp.idltype.typename} for #{_tp.name}"
|
728
|
+
end
|
729
|
+
# match constant type
|
730
|
+
_tp.idltype.narrow(_cp.value)
|
731
|
+
else
|
732
|
+
raise RuntimeError, "invalid instantiation parameter for #{typename} #{scoped_lm_name}: #{_cp.class.name}"
|
733
|
+
end
|
734
|
+
# if we get here all is well -> store concrete param
|
735
|
+
_tp.set_concrete_param(_cp.is_a?(IDL::Type::ScopedName) ? _cp.node : _cp)
|
736
|
+
end
|
737
|
+
# instantiate template by copying template module state to module instance
|
738
|
+
_module_instance.copy_from(self, _context)
|
739
|
+
end
|
740
|
+
|
741
|
+
protected
|
742
|
+
|
743
|
+
def walk_members_for_copy(&block)
|
744
|
+
@children.each { |c| yield(c) unless c.is_a?(IDL::AST::TemplateParam) }
|
745
|
+
end
|
746
|
+
end # TemplateModule
|
747
|
+
|
748
|
+
class TemplateModuleReference < Leaf
|
749
|
+
NAMETYPE = :class
|
750
|
+
def initialize(_name, _enclosure, _params)
|
751
|
+
super(_name, _enclosure)
|
752
|
+
unless _params[:tpl_type].is_a?(IDL::Type::ScopedName) && _params[:tpl_type].is_node?(IDL::AST::TemplateModule)
|
753
|
+
raise RuntimeError, "templated module reference type required for #{typename} #{scoped_lm_name}: got #{_params[:tpl_type].typename}"
|
754
|
+
end
|
755
|
+
@template = _params[:tpl_type].resolved_type.node
|
756
|
+
_params[:tpl_params].each do |p|
|
757
|
+
unless (p.is_a?(IDL::Type::ScopedName) || p.is_a?(IDL::Expression::ScopedName)) && p.is_node?(IDL::AST::TemplateParam)
|
758
|
+
raise RuntimeError, "invalid template module parameter for template module reference #{typename} #{scoped_lm_name}: #{p.typename}"
|
759
|
+
end
|
760
|
+
end
|
761
|
+
@params = _params[:tpl_params].collect { |p| p.resolved_node }
|
762
|
+
end
|
763
|
+
|
764
|
+
def marshal_dump
|
765
|
+
super() << @template << @params
|
766
|
+
end
|
767
|
+
|
768
|
+
def marshal_load(vars)
|
769
|
+
@params = vars.pop
|
770
|
+
@template = vars.pop
|
771
|
+
super(vars)
|
772
|
+
end
|
773
|
+
|
774
|
+
def instantiate(_context, _enclosure)
|
775
|
+
mod_inst = IDL::AST::Module.new(self.name, _enclosure, {})
|
776
|
+
inst_params = @params.collect do |tp|
|
777
|
+
# concrete objects are either Expression or Node; latter needs to be repacked as IDL::Type::ScopedName
|
778
|
+
# as that is what the TemplateModule#instantiate expects
|
779
|
+
tp.concrete.is_a?(IDL::Expression) ? tp.concrete : IDL::Type::ScopedName.new(tp.concrete)
|
780
|
+
end
|
781
|
+
@template.instantiate(mod_inst, inst_params, _context)
|
782
|
+
mod_inst
|
783
|
+
end
|
784
|
+
|
785
|
+
def resolve(_name)
|
786
|
+
@template.resolve(_name)
|
787
|
+
end
|
788
|
+
end # TemplateModuleReference
|
789
|
+
|
790
|
+
class Include < Module
|
791
|
+
attr_reader :filename
|
792
|
+
def initialize(_name, _enclosure, params)
|
793
|
+
super(_name, _enclosure, params)
|
794
|
+
@filename = params[:filename]
|
795
|
+
@defined = params[:defined] || false
|
796
|
+
@preprocessed = params[:preprocessed] || false
|
797
|
+
#overrule
|
798
|
+
@scopes = @enclosure.scopes
|
799
|
+
@scoped_name = @scopes.collect{|s| s.name}.join("::")
|
800
|
+
@scoped_lm_name = @scopes.collect{|s| s.lm_name}.join("::")
|
801
|
+
end
|
802
|
+
|
803
|
+
def marshal_dump
|
804
|
+
super() << @filename << @defined << @preprocessed
|
805
|
+
end
|
806
|
+
|
807
|
+
def marshal_load(vars)
|
808
|
+
@preprocessed = vars.pop
|
809
|
+
@defined = vars.pop
|
810
|
+
@filename = vars.pop
|
811
|
+
super(vars)
|
812
|
+
#overrule
|
813
|
+
@scopes = @enclosure.scopes || []
|
814
|
+
@scoped_name = @scopes.collect{|s| s.name}.join("::")
|
815
|
+
@scoped_lm_name = @scopes.collect{|s| s.lm_name}.join("::")
|
816
|
+
end
|
817
|
+
|
818
|
+
def is_defined?; @defined; end
|
819
|
+
def is_preprocessed?; @preprocessed; end
|
820
|
+
|
821
|
+
def repo_scopes
|
822
|
+
@repo_scopes ||= (@enclosure.nil? ? [] : @enclosure.repo_scopes.dup)
|
823
|
+
end
|
824
|
+
|
825
|
+
def introduce(node)
|
826
|
+
@enclosure.introduce(node) unless node == self
|
827
|
+
end
|
828
|
+
|
829
|
+
def undo_introduction(node)
|
830
|
+
@enclosure.undo_introduction(node) unless node == self
|
831
|
+
end
|
832
|
+
|
833
|
+
def resolve(_name)
|
834
|
+
@enclosure.resolve(_name)
|
835
|
+
end
|
836
|
+
|
837
|
+
protected
|
838
|
+
def copy_from(_template, _context)
|
839
|
+
super
|
840
|
+
@filename = _template.filename
|
841
|
+
@defined = _template.is_defined?
|
842
|
+
@preprocessed = _template.is_preprocessed?
|
843
|
+
#overrule
|
844
|
+
@scopes = @enclosure.scopes
|
845
|
+
@scoped_name = @scopes.collect{|s| s.name}.join("::")
|
846
|
+
@scoped_lm_name = @scopes.collect{|s| s.lm_name}.join("::")
|
847
|
+
self
|
848
|
+
end
|
849
|
+
|
850
|
+
def search_self(_name)
|
851
|
+
@enclosure.search_self(_name)
|
852
|
+
end
|
853
|
+
end # Include
|
854
|
+
|
855
|
+
class Derivable < Node
|
856
|
+
|
857
|
+
alias :search_self_before_derived :search_self
|
858
|
+
def search_self(_name)
|
859
|
+
node = search_self_before_derived(_name)
|
860
|
+
node = search_ancestors(_name) if node.nil?
|
861
|
+
node
|
862
|
+
end
|
863
|
+
|
864
|
+
def has_ancestor?(n)
|
865
|
+
self.has_base?(n) || resolved_bases.any? { |b| b.has_ancestor?(n) }
|
866
|
+
end
|
867
|
+
|
868
|
+
protected
|
869
|
+
|
870
|
+
def resolved_bases
|
871
|
+
[]
|
872
|
+
end
|
873
|
+
|
874
|
+
def each_ancestors(visited = [], &block)
|
875
|
+
resolved_bases.each do |p|
|
876
|
+
next if visited.include? p
|
877
|
+
yield(p)
|
878
|
+
visited.push p
|
879
|
+
p.each_ancestors(visited, &block)
|
880
|
+
end
|
881
|
+
end
|
882
|
+
|
883
|
+
# search inherited interfaces.
|
884
|
+
def search_ancestors(_name)
|
885
|
+
results = []
|
886
|
+
self.each_ancestors do |interface|
|
887
|
+
node = interface.search_self(_name)
|
888
|
+
results.push(node) unless node.nil?
|
889
|
+
end
|
890
|
+
if results.size > 1
|
891
|
+
# check if the matched name resulted in multiple different nodes or all the same
|
892
|
+
r_one = results.shift
|
893
|
+
unless results.all? {|r| r_one == r || (r_one.class == r.class && r_one.scoped_name == r.scoped_name) }
|
894
|
+
s = results.inject([r_one]) {|l,r| l << r unless l.include?(r); l }.collect{ |n| n.scoped_name }.join(", ")
|
895
|
+
raise RuntimeError, "\"#{_name}\" is ambiguous. " + s
|
896
|
+
end
|
897
|
+
end
|
898
|
+
results.first
|
899
|
+
end
|
900
|
+
|
901
|
+
# recursively collect operations from bases
|
902
|
+
def base_operations(traversed)
|
903
|
+
traversed.push self
|
904
|
+
ops = []
|
905
|
+
resolved_bases.each do |base|
|
906
|
+
base = base.idltype.resolved_type.node if base.is_a?(IDL::AST::Typedef)
|
907
|
+
ops.concat(base.operations(true, traversed)) unless traversed.include?(base)
|
908
|
+
end
|
909
|
+
ops
|
910
|
+
end
|
911
|
+
|
912
|
+
# recursively collect attributes from bases
|
913
|
+
def base_attributes(traversed)
|
914
|
+
traversed.push self
|
915
|
+
atts = []
|
916
|
+
resolved_bases.each do |base|
|
917
|
+
base = base.idltype.resolved_type.node if base.is_a?(IDL::AST::Typedef)
|
918
|
+
atts.concat(base.attributes(true, traversed)) unless traversed.include?(base)
|
919
|
+
end
|
920
|
+
atts
|
921
|
+
end
|
922
|
+
end # Derivable
|
923
|
+
|
924
|
+
class Interface < Derivable
|
925
|
+
NAMETYPE = :class
|
926
|
+
DEFINABLE = [IDL::AST::Const, IDL::AST::Operation, IDL::AST::Attribute,
|
927
|
+
IDL::AST::Struct, IDL::AST::Union, IDL::AST::Typedef, IDL::AST::Enum, IDL::AST::Enumerator]
|
928
|
+
attr_reader :bases
|
929
|
+
attr_reader :idltype
|
930
|
+
|
931
|
+
def initialize(_name, _enclosure, params)
|
932
|
+
super(_name, _enclosure)
|
933
|
+
@bases = []
|
934
|
+
@resolved_bases = []
|
935
|
+
@defined = !params[:forward]
|
936
|
+
@abstract = params[:abstract]
|
937
|
+
@pseudo = params[:pseudo]
|
938
|
+
@local = params[:local]
|
939
|
+
@idltype = IDL::Type::Interface.new(self)
|
940
|
+
add_bases(params[:inherits] || [])
|
941
|
+
end
|
942
|
+
|
943
|
+
def marshal_dump
|
944
|
+
super() << @bases << @resolved_bases << @defined << @abstract << @local << @pseudo << @idltype
|
945
|
+
end
|
946
|
+
|
947
|
+
def marshal_load(vars)
|
948
|
+
@idltype = vars.pop
|
949
|
+
@pseudo = vars.pop
|
950
|
+
@local = vars.pop
|
951
|
+
@abstract = vars.pop
|
952
|
+
@defined = vars.pop
|
953
|
+
@resolved_bases = vars.pop
|
954
|
+
@bases = vars.pop
|
955
|
+
super(vars)
|
956
|
+
end
|
957
|
+
|
958
|
+
def instantiate(_context, _enclosure)
|
959
|
+
_params = {
|
960
|
+
:forward => self.is_forward?,
|
961
|
+
:abstract => self.is_abstract?,
|
962
|
+
:pseudo => self.is_pseudo?,
|
963
|
+
:local => self.is_local?,
|
964
|
+
:inherits => self.concrete_bases(_context)
|
965
|
+
}
|
966
|
+
# instantiate concrete interface def and validate
|
967
|
+
# concrete bases
|
968
|
+
super(_context, _enclosure, _params)
|
969
|
+
end
|
970
|
+
|
971
|
+
def is_abstract?; @abstract; end
|
972
|
+
def is_local?; @local; end
|
973
|
+
def is_pseudo?; @pseudo; end
|
974
|
+
def is_defined?; @defined; end
|
975
|
+
def is_forward?; not @defined; end
|
976
|
+
|
977
|
+
def add_bases(inherits_)
|
978
|
+
inherits_.each do |tc|
|
979
|
+
unless tc.is_a?(IDL::Type::ScopedName) && tc.is_node?(IDL::AST::TemplateParam)
|
980
|
+
unless (tc.is_a?(IDL::Type::ScopedName) && tc.is_node?(IDL::AST::Interface))
|
981
|
+
raise RuntimeError,
|
982
|
+
"invalid inheritance identifier for #{typename} #{scoped_lm_name}: #{tc.typename}"
|
983
|
+
end
|
984
|
+
rtc = tc.resolved_type
|
985
|
+
if rtc.node.has_ancestor?(self)
|
986
|
+
raise RuntimeError,
|
987
|
+
"circular inheritance detected for #{typename} #{scoped_lm_name}: #{tc.node.scoped_lm_name} is descendant"
|
988
|
+
end
|
989
|
+
if not rtc.node.is_defined?
|
990
|
+
raise RuntimeError,
|
991
|
+
"#{typename} #{scoped_lm_name} cannot inherit from forward declared #{tc.node.typename} #{tc.node.scoped_lm_name}"
|
992
|
+
end
|
993
|
+
if rtc.node.is_local? and not self.is_local?
|
994
|
+
raise RuntimeError,
|
995
|
+
"#{typename} #{scoped_lm_name} cannot inherit from 'local' #{tc.node.typename} #{tc.node.scoped_lm_name}"
|
996
|
+
end
|
997
|
+
if rtc.node.is_pseudo? and not self.is_pseudo?
|
998
|
+
raise RuntimeError,
|
999
|
+
"#{typename} #{scoped_lm_name} cannot inherit from 'pseudo' #{tc.node.typename} #{tc.node.scoped_lm_name}"
|
1000
|
+
end
|
1001
|
+
if self.is_abstract? and not rtc.node.is_abstract?
|
1002
|
+
raise RuntimeError,
|
1003
|
+
"'abstract' #{typename} #{scoped_lm_name} cannot inherit from non-'abstract' #{tc.node.typename} #{tc.node.scoped_lm_name}"
|
1004
|
+
end
|
1005
|
+
if self.is_local? and rtc.node.is_abstract?
|
1006
|
+
raise RuntimeError,
|
1007
|
+
"'local' #{typename} #{scoped_lm_name} cannot inherit from 'abstract' #{tc.node.typename} #{tc.node.scoped_lm_name}"
|
1008
|
+
end
|
1009
|
+
if self.has_base?(rtc.node)
|
1010
|
+
raise RuntimeError,
|
1011
|
+
"#{typename} #{scoped_lm_name} cannot inherit from #{tc.node.typename} #{tc.node.scoped_lm_name} multiple times"
|
1012
|
+
end
|
1013
|
+
# check if we indirectly derive from this base multiple times (which is ok; no further need to check)
|
1014
|
+
unless @resolved_bases.any? { |b| b.has_ancestor?(rtc.node) }
|
1015
|
+
# this is a new base so we need to check for member redefinition/ambiguity
|
1016
|
+
new_op_att_ = []
|
1017
|
+
rtc.node.walk_members do |m|
|
1018
|
+
new_op_att_ << m if m.is_a?(IDL::AST::Operation) || m.is_a?(IDL::AST::Attribute)
|
1019
|
+
end
|
1020
|
+
if new_op_att_.any? {|n| n_ = self.search_self(n.name); n_.is_a?(IDL::AST::Operation) || n_.is_a?(IDL::AST::Attribute) }
|
1021
|
+
raise RuntimeError,
|
1022
|
+
"#{typename} #{scoped_lm_name} cannot inherit from #{tc.node.typename} #{tc.node.scoped_lm_name} because of duplicated operations/attributes"
|
1023
|
+
end
|
1024
|
+
# no need to check for duplicate member names; this inheritance is ok
|
1025
|
+
end
|
1026
|
+
@resolved_bases << rtc.node
|
1027
|
+
end
|
1028
|
+
@bases << tc.node
|
1029
|
+
end
|
1030
|
+
end
|
1031
|
+
|
1032
|
+
def has_base?(_base)
|
1033
|
+
@resolved_bases.any? { |b| b == _base.idltype.resolved_type.node }
|
1034
|
+
end
|
1035
|
+
|
1036
|
+
def ancestors
|
1037
|
+
@resolved_bases
|
1038
|
+
end
|
1039
|
+
|
1040
|
+
def operations(include_bases=false,traversed=nil)
|
1041
|
+
ops = @children.find_all { |c| c.is_a?(IDL::AST::Operation) }
|
1042
|
+
ops.concat(base_operations(traversed || [])) if include_bases
|
1043
|
+
ops
|
1044
|
+
end
|
1045
|
+
|
1046
|
+
def attributes(include_bases=false,traversed=nil)
|
1047
|
+
atts = @children.find_all { |c| c.is_a?(IDL::AST::Attribute) }
|
1048
|
+
atts.concat(base_attributes(traversed || [])) if include_bases
|
1049
|
+
atts
|
1050
|
+
end
|
1051
|
+
|
1052
|
+
def redefine(node, params)
|
1053
|
+
if node.enclosure == self
|
1054
|
+
case node
|
1055
|
+
when IDL::AST::Struct, IDL::AST::Union
|
1056
|
+
if node.is_defined?
|
1057
|
+
raise RuntimeError, "#{node.typename} \"#{node.name}\" is already defined."
|
1058
|
+
end
|
1059
|
+
node.annotations.concat(params[:annotations])
|
1060
|
+
|
1061
|
+
_new_node = node.class.new(node.name, self, params)
|
1062
|
+
_new_node.annotations.concat(node.annotations)
|
1063
|
+
_new_node.prefix = node.prefix
|
1064
|
+
_new_node.instance_variable_set(:@repo_ver, node.instance_variable_get(:@repo_ver))
|
1065
|
+
_new_node.instance_variable_set(:@repo_id, node.instance_variable_get(:@repo_id))
|
1066
|
+
|
1067
|
+
node.switchtype = params[:switchtype] if node.is_a?(IDL::AST::Union)
|
1068
|
+
|
1069
|
+
@children << _new_node
|
1070
|
+
# replace forward node registration
|
1071
|
+
node.enclosure.undo_introduction(node)
|
1072
|
+
introduce(_new_node)
|
1073
|
+
|
1074
|
+
return _new_node
|
1075
|
+
else
|
1076
|
+
raise RuntimeError, "#{node.typename} \"#{node.name}\" is already defined."
|
1077
|
+
end
|
1078
|
+
end
|
1079
|
+
|
1080
|
+
case node
|
1081
|
+
when IDL::AST::Operation, IDL::AST::Attribute
|
1082
|
+
raise RuntimeError, "#{node.typename} '#{node.scoped_lm_name}' cannot be overridden."
|
1083
|
+
else
|
1084
|
+
newnode = node.class.new(node.name, self, params)
|
1085
|
+
newnode.annotations.concat(params[:annotations])
|
1086
|
+
introduce(newnode)
|
1087
|
+
@children << newnode # add overriding child
|
1088
|
+
return newnode
|
1089
|
+
end
|
1090
|
+
end
|
1091
|
+
|
1092
|
+
protected
|
1093
|
+
|
1094
|
+
def concrete_bases(_context)
|
1095
|
+
# collect all bases and resolve any template param types
|
1096
|
+
@bases.collect do |_base|
|
1097
|
+
IDL::Type::ScopedName.new(IDL::AST::TemplateParam.concrete_param(_context, _base))
|
1098
|
+
end
|
1099
|
+
end
|
1100
|
+
|
1101
|
+
def resolved_bases
|
1102
|
+
@resolved_bases
|
1103
|
+
end
|
1104
|
+
end # Interface
|
1105
|
+
|
1106
|
+
class ComponentBase < Derivable
|
1107
|
+
NAMETYPE = :class
|
1108
|
+
DEFINABLE = []
|
1109
|
+
attr_reader :base
|
1110
|
+
attr_reader :interfaces
|
1111
|
+
attr_reader :idltype
|
1112
|
+
|
1113
|
+
def initialize(_name, _enclosure, params)
|
1114
|
+
super(_name, _enclosure)
|
1115
|
+
@base = nil
|
1116
|
+
@resolved_base = nil
|
1117
|
+
@interfaces = []
|
1118
|
+
@resolved_interfaces = []
|
1119
|
+
set_base(params[:base]) if params[:base]
|
1120
|
+
add_interfaces(params[:supports] || [])
|
1121
|
+
end
|
1122
|
+
|
1123
|
+
def marshal_dump
|
1124
|
+
super() << @base << @resolved_base << @interfaces << @resolved_interfaces << @idltype
|
1125
|
+
end
|
1126
|
+
|
1127
|
+
def marshal_load(vars)
|
1128
|
+
@idltype = vars.pop
|
1129
|
+
@resolved_interfaces = vars.pop
|
1130
|
+
@interfaces = vars.pop
|
1131
|
+
@resolved_base = vars.pop
|
1132
|
+
@base = vars.pop
|
1133
|
+
super(vars)
|
1134
|
+
end
|
1135
|
+
|
1136
|
+
def instantiate(_context, _enclosure, _params = {})
|
1137
|
+
_params.merge!({
|
1138
|
+
:base => @base ? IDL::Type::ScopedName.new(IDL::AST::TemplateParam.concrete_param(_context, @base)) : @base,
|
1139
|
+
:supports => self.concrete_interfaces(_context)
|
1140
|
+
})
|
1141
|
+
# instantiate concrete def and validate
|
1142
|
+
super(_context, _enclosure, _params)
|
1143
|
+
end
|
1144
|
+
|
1145
|
+
def set_base(parent)
|
1146
|
+
unless parent.is_a?(IDL::Type::ScopedName) && parent.is_node?(IDL::AST::TemplateParam)
|
1147
|
+
unless (parent.is_a?(IDL::Type::ScopedName) && parent.is_node?(self.class))
|
1148
|
+
raise RuntimeError,
|
1149
|
+
"invalid inheritance identifier for #{typename} #{scoped_lm_name}: #{parent.typename}"
|
1150
|
+
end
|
1151
|
+
if parent.resolved_type.node.has_base?(self)
|
1152
|
+
raise RuntimeError,
|
1153
|
+
"circular inheritance detected for #{typename} #{scoped_lm_name}: #{parent.node.scoped_lm_name} is descendant"
|
1154
|
+
end
|
1155
|
+
@resolved_base = parent.resolved_type.node
|
1156
|
+
end
|
1157
|
+
@base = parent.node
|
1158
|
+
end
|
1159
|
+
|
1160
|
+
def has_base?(n)
|
1161
|
+
@resolved_base && (@resolved_base == n.idltype.resolved_type.node) # || @resolved_base.has_base?(n))
|
1162
|
+
end
|
1163
|
+
|
1164
|
+
def ancestors
|
1165
|
+
resolved_bases
|
1166
|
+
end
|
1167
|
+
|
1168
|
+
def add_interfaces(intfs)
|
1169
|
+
intfs.each do |tc|
|
1170
|
+
unless tc.is_a?(IDL::Type::ScopedName) && tc.is_node?(IDL::AST::TemplateParam)
|
1171
|
+
unless (tc.is_a?(IDL::Type::ScopedName) && tc.is_node?(IDL::AST::Interface))
|
1172
|
+
raise RuntimeError,
|
1173
|
+
"invalid inheritance identifier for #{typename} #{scoped_lm_name}: #{tc.typename}"
|
1174
|
+
end
|
1175
|
+
rtc = tc.resolved_type
|
1176
|
+
if not rtc.node.is_defined?
|
1177
|
+
raise RuntimeError,
|
1178
|
+
"#{typename} #{scoped_lm_name} cannot support forward declared #{tc.node.typename} #{tc.node.scoped_lm_name}"
|
1179
|
+
end
|
1180
|
+
## TODO : is this legal?
|
1181
|
+
if rtc.node.is_local?
|
1182
|
+
raise RuntimeError,
|
1183
|
+
"#{typename} #{scoped_lm_name} cannot support 'local' #{tc.node.typename} #{tc.node.scoped_lm_name}"
|
1184
|
+
end
|
1185
|
+
if rtc.node.is_pseudo?
|
1186
|
+
raise RuntimeError,
|
1187
|
+
"#{typename} #{scoped_lm_name} cannot support 'pseudo' #{tc.node.typename} #{tc.node.scoped_lm_name}"
|
1188
|
+
end
|
1189
|
+
## TODO : is this legal?
|
1190
|
+
#if tc.node.is_abstract?
|
1191
|
+
# raise RuntimeError,
|
1192
|
+
# "'abstract' #{typename} #{scoped_lm_name} cannot support 'abstract' #{tc.node.typename} #{tc.node.scoped_lm_name}"
|
1193
|
+
#end
|
1194
|
+
if self.has_support?(rtc.node)
|
1195
|
+
raise RuntimeError,
|
1196
|
+
"#{typename} #{scoped_lm_name} cannot support #{tc.node.typename} #{tc.node.scoped_lm_name} multiple times"
|
1197
|
+
end
|
1198
|
+
# check if we indirectly support this base multiple times (which is ok; no further need to check)
|
1199
|
+
unless @resolved_interfaces.any? { |b| b.has_ancestor?(rtc.node) }
|
1200
|
+
# this is a new support interface so we need to check for member redefinition/ambiguity
|
1201
|
+
new_op_att_ = []
|
1202
|
+
rtc.node.walk_members do |m|
|
1203
|
+
new_op_att_ << m if m.is_a?(IDL::AST::Operation) || m.is_a?(IDL::AST::Attribute)
|
1204
|
+
end
|
1205
|
+
if new_op_att_.any? {|n| n_ = self.search_self(n.name); n_.is_a?(IDL::AST::Operation) || n_.is_a?(IDL::AST::Attribute) }
|
1206
|
+
raise RuntimeError,
|
1207
|
+
"#{typename} #{scoped_lm_name} cannot support #{tc.node.typename} #{tc.node.scoped_lm_name} because of duplicated operations/attributes"
|
1208
|
+
end
|
1209
|
+
# no need to check for duplicate member names; this support is ok
|
1210
|
+
end
|
1211
|
+
@resolved_interfaces << rtc.node
|
1212
|
+
end
|
1213
|
+
@interfaces << tc.node
|
1214
|
+
end
|
1215
|
+
end
|
1216
|
+
|
1217
|
+
def has_support?(intf)
|
1218
|
+
@resolved_interfaces.any? { |b| b == intf.idltype.resolved_type.node }
|
1219
|
+
end
|
1220
|
+
|
1221
|
+
def supports?(intf)
|
1222
|
+
self.has_support?(intf) || (@resolved_base && @resolved_base.supports?(intf)) || @resolved_interfaces.any? { |base_i| i.has_ancestor?(intf) }
|
1223
|
+
end
|
1224
|
+
|
1225
|
+
def redefine(node, params)
|
1226
|
+
if node.enclosure == self
|
1227
|
+
case node
|
1228
|
+
when IDL::AST::Struct, IDL::AST::Union
|
1229
|
+
if node.is_defined?
|
1230
|
+
raise RuntimeError, "#{node.typename} \"#{node.name}\" is already defined."
|
1231
|
+
end
|
1232
|
+
node.annotations.concat(params[:annotations])
|
1233
|
+
|
1234
|
+
_new_node = node.class.new(node.name, self, params)
|
1235
|
+
_new_node.annotations.concat(node.annotations)
|
1236
|
+
_new_node.prefix = node.prefix
|
1237
|
+
_new_node.instance_variable_set(:@repo_ver, node.instance_variable_get(:@repo_ver))
|
1238
|
+
_new_node.instance_variable_set(:@repo_id, node.instance_variable_get(:@repo_id))
|
1239
|
+
|
1240
|
+
node.switchtype = params[:switchtype] if node.is_a?(IDL::AST::Union)
|
1241
|
+
|
1242
|
+
@children << _new_node
|
1243
|
+
# replace forward node registration
|
1244
|
+
node.enclosure.undo_introduction(node)
|
1245
|
+
introduce(_new_node)
|
1246
|
+
|
1247
|
+
return _new_node
|
1248
|
+
else
|
1249
|
+
raise RuntimeError, "#{node.typename} \"#{node.name}\" is already defined."
|
1250
|
+
end
|
1251
|
+
end
|
1252
|
+
|
1253
|
+
case node
|
1254
|
+
when IDL::AST::Operation, IDL::AST::Attribute
|
1255
|
+
raise RuntimeError, "#{node.typename} '#{node.scoped_lm_name}' cannot be overridden."
|
1256
|
+
else
|
1257
|
+
newnode = node.class.new(node.name, self, params)
|
1258
|
+
newnode.annotations.concat(params[:annotations])
|
1259
|
+
introduce(newnode)
|
1260
|
+
@children << newnode # add overriding child
|
1261
|
+
return newnode
|
1262
|
+
end
|
1263
|
+
end
|
1264
|
+
|
1265
|
+
protected
|
1266
|
+
|
1267
|
+
def resolved_bases
|
1268
|
+
(@resolved_base ? [@resolved_base] : []).concat(@resolved_interfaces)
|
1269
|
+
end
|
1270
|
+
|
1271
|
+
def concrete_interfaces(_context)
|
1272
|
+
# collect all bases and resolve any template param types
|
1273
|
+
@interfaces.collect do |_intf|
|
1274
|
+
IDL::Type::ScopedName.new(IDL::AST::TemplateParam.concrete_param(_context, _intf))
|
1275
|
+
end
|
1276
|
+
end
|
1277
|
+
end # ComponentBase
|
1278
|
+
|
1279
|
+
class Home < ComponentBase
|
1280
|
+
NAMETYPE = :class
|
1281
|
+
DEFINABLE = [IDL::AST::Const, IDL::AST::Operation, IDL::AST::Attribute, IDL::AST::Initializer, IDL::AST::Finder,
|
1282
|
+
IDL::AST::Struct, IDL::AST::Union, IDL::AST::Typedef, IDL::AST::Enum, IDL::AST::Enumerator]
|
1283
|
+
attr_reader :component
|
1284
|
+
attr_reader :primarykey
|
1285
|
+
|
1286
|
+
def initialize(_name, _enclosure, params)
|
1287
|
+
@component = nil
|
1288
|
+
@resolved_comp = nil
|
1289
|
+
@primarykey = nil
|
1290
|
+
@resolved_pk = nil
|
1291
|
+
@idltype = IDL::Type::Home.new(self)
|
1292
|
+
super(_name, _enclosure, params)
|
1293
|
+
set_component_and_key(params[:component], params[:primarykey])
|
1294
|
+
end
|
1295
|
+
|
1296
|
+
def marshal_dump
|
1297
|
+
super() << @component << @resolved_comp << @primarykey << @resolved_pk
|
1298
|
+
end
|
1299
|
+
|
1300
|
+
def marshal_load(vars)
|
1301
|
+
@resolved_pk = vars.pop
|
1302
|
+
@primarykey = vars.pop
|
1303
|
+
@resolved_comp = vars.pop
|
1304
|
+
@component = vars.pop
|
1305
|
+
super(vars)
|
1306
|
+
end
|
1307
|
+
|
1308
|
+
def instantiate(_context, _enclosure)
|
1309
|
+
_params = {
|
1310
|
+
:component => IDL::Type::ScopedName.new(IDL::AST::TemplateParam.concrete_param(_context, @component)),
|
1311
|
+
:primarykey => @primarykey ? IDL::Type::ScopedName.new(IDL::AST::TemplateParam.concrete_param(_context, @primarykey)) : @primarykey
|
1312
|
+
}
|
1313
|
+
# instantiate concrete home def and validate
|
1314
|
+
super(_context, _enclosure, _params)
|
1315
|
+
end
|
1316
|
+
|
1317
|
+
def set_component_and_key(comp, key)
|
1318
|
+
unless comp && comp.is_a?(IDL::Type::ScopedName) && comp.is_node?(IDL::AST::TemplateParam)
|
1319
|
+
unless comp && comp.is_a?(IDL::Type::ScopedName) && comp.is_node?(IDL::AST::Component)
|
1320
|
+
raise RuntimeError,
|
1321
|
+
(comp ?
|
1322
|
+
"invalid managed component for #{typename} #{scoped_lm_name}: #{comp.typename}" :
|
1323
|
+
"missing managed component specification for #{typename} #{scoped_lm_name}")
|
1324
|
+
end
|
1325
|
+
unless comp.resolved_type.node.is_defined?
|
1326
|
+
raise RuntimeError,
|
1327
|
+
"#{scoped_lm_name}: #{comp.typename} cannot manage forward declared component #{comp.node.scoped_lm_name}"
|
1328
|
+
end
|
1329
|
+
@resolved_comp = comp.resolved_type.node
|
1330
|
+
end
|
1331
|
+
unless key && key.is_a?(IDL::Type::ScopedName) && key.is_node?(IDL::AST::TemplateParam)
|
1332
|
+
## TODO : add check for Components::PrimaryKeyBase base type
|
1333
|
+
unless key.nil? || (key.is_a?(IDL::Type::ScopedName) && key.is_node?(IDL::AST::Valuetype))
|
1334
|
+
raise RuntimeError,
|
1335
|
+
"invalid primary key for #{typename} #{scoped_lm_name}: #{key.typename}"
|
1336
|
+
end
|
1337
|
+
@resolved_pk = key.resolved_type.node if key
|
1338
|
+
end
|
1339
|
+
@component = comp.node
|
1340
|
+
@primarykey = key.node if key
|
1341
|
+
end
|
1342
|
+
|
1343
|
+
def operations(include_bases=false,traversed=nil)
|
1344
|
+
ops = @children.find_all { |c| c.is_a?(IDL::AST::Operation) }
|
1345
|
+
ops.concat(base_operations(traversed || [])) if include_bases
|
1346
|
+
ops
|
1347
|
+
end
|
1348
|
+
|
1349
|
+
def attributes(include_bases=false,traversed=nil)
|
1350
|
+
atts = @children.find_all { |c| c.is_a?(IDL::AST::Attribute) }
|
1351
|
+
atts.concat(base_attributes(traversed || [])) if include_bases
|
1352
|
+
atts
|
1353
|
+
end
|
1354
|
+
|
1355
|
+
end # Home
|
1356
|
+
|
1357
|
+
class Connector < ComponentBase
|
1358
|
+
NAMETYPE = :class
|
1359
|
+
DEFINABLE = [IDL::AST::Attribute, IDL::AST::Port]
|
1360
|
+
|
1361
|
+
def initialize(_name, _enclosure, params)
|
1362
|
+
@idltype = IDL::Type::Component.new(self)
|
1363
|
+
super(_name, _enclosure, params)
|
1364
|
+
end
|
1365
|
+
|
1366
|
+
def marshal_dump
|
1367
|
+
super()
|
1368
|
+
end
|
1369
|
+
|
1370
|
+
def marshal_load(vars)
|
1371
|
+
super(vars)
|
1372
|
+
end
|
1373
|
+
|
1374
|
+
def instantiate(_context, _enclosure)
|
1375
|
+
# instantiate concrete connector def and validate
|
1376
|
+
super(_context, _enclosure, {})
|
1377
|
+
end
|
1378
|
+
|
1379
|
+
def is_defined?; true; end
|
1380
|
+
def is_forward?; false; end
|
1381
|
+
|
1382
|
+
def add_interfaces(intfs)
|
1383
|
+
raise RuntimeError, "interface support not allowed for #{typename} #{scoped_lm_name}" if intfs && !intfs.empty?
|
1384
|
+
end
|
1385
|
+
|
1386
|
+
def set_base(parent)
|
1387
|
+
unless parent.is_a?(IDL::Type::ScopedName) && parent.is_node?(IDL::AST::TemplateParam)
|
1388
|
+
if not (parent.is_a?(IDL::Type::ScopedName) && parent.is_node?(self.class))
|
1389
|
+
raise RuntimeError,
|
1390
|
+
"invalid inheritance identifier for #{typename} #{scoped_lm_name}: #{parent.typename}"
|
1391
|
+
end
|
1392
|
+
@resolved_base = parent.resolved_type.node
|
1393
|
+
if @resolved_base.has_base?(self)
|
1394
|
+
raise RuntimeError,
|
1395
|
+
"circular inheritance detected for #{typename} #{scoped_lm_name}: #{parent.node.scoped_lm_name} is descendant"
|
1396
|
+
end
|
1397
|
+
end
|
1398
|
+
@base = parent.node
|
1399
|
+
end
|
1400
|
+
|
1401
|
+
def ports(include_bases=false,traversed=nil)
|
1402
|
+
ports = @children.inject([]) do |lst, c|
|
1403
|
+
lst.concat(c.ports) if IDL::AST::Port === c
|
1404
|
+
lst
|
1405
|
+
end
|
1406
|
+
ports.concat(base_ports(traversed || [])) if include_bases
|
1407
|
+
ports
|
1408
|
+
end
|
1409
|
+
|
1410
|
+
def attributes(include_bases=false,traversed=nil)
|
1411
|
+
atts = @children.inject([]) do |lst, c|
|
1412
|
+
if IDL::AST::Port === c
|
1413
|
+
lst.concat(c.attributes)
|
1414
|
+
else
|
1415
|
+
lst << c
|
1416
|
+
end
|
1417
|
+
lst
|
1418
|
+
end
|
1419
|
+
atts.concat(base_attributes(traversed || [])) if include_bases
|
1420
|
+
atts
|
1421
|
+
end
|
1422
|
+
|
1423
|
+
protected
|
1424
|
+
|
1425
|
+
# recursively collect ports from bases
|
1426
|
+
def base_ports(traversed)
|
1427
|
+
traversed.push self
|
1428
|
+
ports = []
|
1429
|
+
if (base = @resolved_base)
|
1430
|
+
base = base.idltype.resolved_type.node if base.is_a?(IDL::AST::Typedef)
|
1431
|
+
ports = base.ports(true, traversed) unless traversed.include?(base)
|
1432
|
+
end
|
1433
|
+
ports
|
1434
|
+
end
|
1435
|
+
|
1436
|
+
end # Connector
|
1437
|
+
|
1438
|
+
class Component < ComponentBase
|
1439
|
+
NAMETYPE = :class
|
1440
|
+
DEFINABLE = [IDL::AST::Attribute, IDL::AST::Port]
|
1441
|
+
|
1442
|
+
def initialize(_name, _enclosure, params)
|
1443
|
+
@idltype = IDL::Type::Component.new(self)
|
1444
|
+
super(_name, _enclosure, params)
|
1445
|
+
@defined = !params[:forward]
|
1446
|
+
end
|
1447
|
+
|
1448
|
+
def marshal_dump
|
1449
|
+
super() << @defined
|
1450
|
+
end
|
1451
|
+
|
1452
|
+
def marshal_load(vars)
|
1453
|
+
@defined = vars.pop
|
1454
|
+
super(vars)
|
1455
|
+
end
|
1456
|
+
|
1457
|
+
def instantiate(_context, _enclosure)
|
1458
|
+
# instantiate concrete component def and validate
|
1459
|
+
super(_context, _enclosure, { :forward => self.is_forward? })
|
1460
|
+
end
|
1461
|
+
|
1462
|
+
def is_defined?; @defined; end
|
1463
|
+
def is_forward?; not @defined; end
|
1464
|
+
|
1465
|
+
def set_base(parent)
|
1466
|
+
unless parent.is_a?(IDL::Type::ScopedName) && parent.is_node?(IDL::AST::TemplateParam)
|
1467
|
+
if not (parent.is_a?(IDL::Type::ScopedName) && parent.is_node?(self.class))
|
1468
|
+
raise RuntimeError,
|
1469
|
+
"invalid inheritance identifier for #{typename} #{scoped_lm_name}: #{parent.typename}"
|
1470
|
+
end
|
1471
|
+
@resolved_base = parent.resolved_type.node
|
1472
|
+
if not @resolved_base.is_defined?
|
1473
|
+
raise RuntimeError,
|
1474
|
+
"#{typename} #{scoped_lm_name} cannot inherit from forward declared #{parent.node.typename} #{parent.node.scoped_lm_name}"
|
1475
|
+
end
|
1476
|
+
if @resolved_base.has_base?(self)
|
1477
|
+
raise RuntimeError,
|
1478
|
+
"circular inheritance detected for #{typename} #{scoped_lm_name}: #{parent.node.scoped_lm_name} is descendant"
|
1479
|
+
end
|
1480
|
+
end
|
1481
|
+
@base = parent.node
|
1482
|
+
end
|
1483
|
+
|
1484
|
+
def ports(include_bases=false,traversed=nil)
|
1485
|
+
ports = @children.inject([]) do |lst, c|
|
1486
|
+
lst.concat(c.ports) if IDL::AST::Port === c
|
1487
|
+
lst
|
1488
|
+
end
|
1489
|
+
ports.concat(base_ports(traversed || [])) if include_bases
|
1490
|
+
ports
|
1491
|
+
end
|
1492
|
+
|
1493
|
+
def operations(include_bases=false,traversed=nil)
|
1494
|
+
include_bases ? base_operations(traversed || []) : []
|
1495
|
+
end
|
1496
|
+
|
1497
|
+
def attributes(include_bases=false,traversed=nil)
|
1498
|
+
atts = @children.inject([]) do |lst, c|
|
1499
|
+
if IDL::AST::Port === c
|
1500
|
+
lst.concat(c.attributes)
|
1501
|
+
else
|
1502
|
+
lst << c
|
1503
|
+
end
|
1504
|
+
lst
|
1505
|
+
end
|
1506
|
+
atts.concat(base_attributes(traversed || [])) if include_bases
|
1507
|
+
atts
|
1508
|
+
end
|
1509
|
+
|
1510
|
+
protected
|
1511
|
+
|
1512
|
+
# recursively collect ports from bases
|
1513
|
+
def base_ports(traversed)
|
1514
|
+
traversed.push self
|
1515
|
+
ports = []
|
1516
|
+
if (base = @resolved_base)
|
1517
|
+
base = base.idltype.resolved_type.node if base.is_a?(IDL::AST::Typedef)
|
1518
|
+
ports = base.ports(true, traversed) unless traversed.include?(base)
|
1519
|
+
end
|
1520
|
+
ports
|
1521
|
+
end
|
1522
|
+
|
1523
|
+
end # Component
|
1524
|
+
|
1525
|
+
class Porttype < Node
|
1526
|
+
NAMETYPE = :class
|
1527
|
+
DEFINABLE = [IDL::AST::Attribute, IDL::AST::Port]
|
1528
|
+
attr_reader :idltype
|
1529
|
+
def initialize(_name, _enclosure, params)
|
1530
|
+
super(_name, _enclosure)
|
1531
|
+
@idltype = IDL::Type::Porttype.new(self)
|
1532
|
+
end
|
1533
|
+
|
1534
|
+
def ports
|
1535
|
+
@children.select {|c| IDL::AST::Port === c}
|
1536
|
+
end
|
1537
|
+
|
1538
|
+
def attributes
|
1539
|
+
@children.select {|c| IDL::AST::Attribute === c}
|
1540
|
+
end
|
1541
|
+
|
1542
|
+
def instantiate(_context, _enclosure)
|
1543
|
+
super(_context, _enclosure, {})
|
1544
|
+
end
|
1545
|
+
end # Porttype
|
1546
|
+
|
1547
|
+
class Port < Leaf
|
1548
|
+
NAMETYPE = :member
|
1549
|
+
PORTTYPES = [:facet, :receptacle, :emitter, :publisher, :consumer, :port, :mirrorport]
|
1550
|
+
PORT_MIRRORS = {:facet => :receptacle, :receptacle => :facet}
|
1551
|
+
EXTPORTDEF_ANNOTATION = 'ExtendedPortDef'
|
1552
|
+
attr_reader :idltype
|
1553
|
+
attr_reader :porttype
|
1554
|
+
def initialize(_name, _enclosure, params)
|
1555
|
+
super(_name, _enclosure)
|
1556
|
+
@idltype = params[:type]
|
1557
|
+
@porttype = params[:porttype]
|
1558
|
+
raise RuntimeError, "unknown porttype for #{typename} #{scoped_lm_name}: #{@porttype}" unless PORTTYPES.include?(@porttype)
|
1559
|
+
case @porttype
|
1560
|
+
when :facet, :receptacle
|
1561
|
+
unless @idltype.is_a?(IDL::Type::Object) ||
|
1562
|
+
(@idltype.is_a?(IDL::Type::ScopedName) && (@idltype.is_node?(IDL::AST::Interface) || @idltype.is_node?(IDL::AST::TemplateParam)))
|
1563
|
+
raise RuntimeError, "invalid type for #{typename} #{scoped_lm_name}: #{@idltype.typename}"
|
1564
|
+
end
|
1565
|
+
when :port, :mirrorport
|
1566
|
+
unless @idltype.is_a?(IDL::Type::ScopedName) && (@idltype.is_node?(IDL::AST::Porttype) || @idltype.is_node?(IDL::AST::TemplateParam))
|
1567
|
+
raise RuntimeError, "invalid type for #{typename} #{scoped_lm_name}: #{@idltype.typename}"
|
1568
|
+
end
|
1569
|
+
else
|
1570
|
+
unless @idltype.is_a?(IDL::Type::ScopedName) && (@idltype.is_node?(IDL::AST::Eventtype) || @idltype.is_node?(IDL::AST::TemplateParam))
|
1571
|
+
raise RuntimeError, "invalid type for #{typename} #{scoped_lm_name}: #{@idltype.typename}"
|
1572
|
+
end
|
1573
|
+
end
|
1574
|
+
@multiple = params[:multiple] ? true : false
|
1575
|
+
end
|
1576
|
+
|
1577
|
+
def instantiate(_context, _enclosure)
|
1578
|
+
_params = {
|
1579
|
+
:type => @idltype.instantiate(_context),
|
1580
|
+
:porttype => @porttype,
|
1581
|
+
:multiple => @multiple
|
1582
|
+
}
|
1583
|
+
super(_context, _enclosure, _params)
|
1584
|
+
end
|
1585
|
+
|
1586
|
+
def multiple?
|
1587
|
+
@multiple
|
1588
|
+
end
|
1589
|
+
|
1590
|
+
def expanded_copy(name_pfx, enc)
|
1591
|
+
p = IDL::AST::Port.new("#{name_pfx}_#{self.name}", enc, {:type => @idltype, :porttype => @porttype})
|
1592
|
+
p.annotations << Annotation.new(EXTPORTDEF_ANNOTATION, { :extended_port_name => name_pfx, :base_name => self.name, :mirror => false })
|
1593
|
+
p # return expanded copy
|
1594
|
+
end
|
1595
|
+
|
1596
|
+
def expanded_mirror_copy(name_pfx, enc)
|
1597
|
+
p = IDL::AST::Port.new("#{name_pfx}_#{self.name}", enc, {:type => @idltype, :porttype => PORT_MIRRORS[@porttype]})
|
1598
|
+
p.annotations << Annotation.new(EXTPORTDEF_ANNOTATION, { :extended_port_name => name_pfx, :base_name => self.name, :mirror => true })
|
1599
|
+
p # return expanded copy
|
1600
|
+
end
|
1601
|
+
|
1602
|
+
def ports
|
1603
|
+
case @porttype
|
1604
|
+
when :port
|
1605
|
+
@idltype.resolved_type.node.ports.collect {|p| p.expanded_copy(self.name, self.enclosure) }
|
1606
|
+
when :mirrorport
|
1607
|
+
@idltype.resolved_type.node.ports.collect {|p| p.expanded_mirror_copy(self.name, self.enclosure) }
|
1608
|
+
else
|
1609
|
+
[self]
|
1610
|
+
end
|
1611
|
+
end
|
1612
|
+
|
1613
|
+
def attributes
|
1614
|
+
case @porttype
|
1615
|
+
when :port, :mirrorport
|
1616
|
+
@idltype.resolved_type.node.attributes.collect {|att|
|
1617
|
+
exp_a = att.expanded_copy(self.name, self.enclosure)
|
1618
|
+
exp_a.annotations << Annotation.new(EXTPORTDEF_ANNOTATION, { :extended_port_name => self.name, :base_name => att.name, :mirror => (@porttype == :mirrorport) })
|
1619
|
+
exp_a # return expanded copy
|
1620
|
+
}
|
1621
|
+
else
|
1622
|
+
[]
|
1623
|
+
end
|
1624
|
+
end
|
1625
|
+
end # Port
|
1626
|
+
|
1627
|
+
class Valuebox < Leaf
|
1628
|
+
NAMETYPE = :class
|
1629
|
+
attr_reader :idltype, :boxed_type
|
1630
|
+
def initialize(_name, _enclosure, params)
|
1631
|
+
super(_name, _enclosure)
|
1632
|
+
@idltype = IDL::Type::Valuebox.new(self)
|
1633
|
+
@boxed_type = params[:type]
|
1634
|
+
unless @boxed_type.is_a?(IDL::Type::ScopedName) && @boxed_type.is_node?(IDL::AST::TemplateParam)
|
1635
|
+
if @boxed_type.resolved_type.is_a?(IDL::Type::Valuetype)
|
1636
|
+
raise RuntimeError,
|
1637
|
+
"boxing valuetype #{@boxed_type.scoped_lm_name} in Valuebox #{scoped_lm_name} not allowed"
|
1638
|
+
end
|
1639
|
+
end
|
1640
|
+
end
|
1641
|
+
|
1642
|
+
def is_local?(recurstk = [])
|
1643
|
+
boxed_type.is_local?(recurstk)
|
1644
|
+
end
|
1645
|
+
|
1646
|
+
def marshal_dump
|
1647
|
+
super() << @idltype << @boxed_type
|
1648
|
+
end
|
1649
|
+
|
1650
|
+
def marshal_load(vars)
|
1651
|
+
@boxed_type = vars.pop
|
1652
|
+
@idltype = vars.pop
|
1653
|
+
super(vars)
|
1654
|
+
end
|
1655
|
+
|
1656
|
+
def instantiate(_context, _enclosure)
|
1657
|
+
_params = {
|
1658
|
+
:type => @boxed_type.instantiate(_context)
|
1659
|
+
}
|
1660
|
+
super(_context, _enclosure, _params)
|
1661
|
+
end
|
1662
|
+
end # Valuebox
|
1663
|
+
|
1664
|
+
class Valuetype < Derivable
|
1665
|
+
NAMETYPE = :class
|
1666
|
+
DEFINABLE = [IDL::AST::Include, IDL::AST::Const, IDL::AST::Operation, IDL::AST::Attribute, IDL::AST::StateMember, IDL::AST::Initializer,
|
1667
|
+
IDL::AST::Struct, IDL::AST::Union, IDL::AST::Typedef, IDL::AST::Enum, IDL::AST::Enumerator]
|
1668
|
+
attr_reader :bases, :interfaces
|
1669
|
+
attr_reader :idltype
|
1670
|
+
|
1671
|
+
def initialize(_name, _enclosure, params)
|
1672
|
+
super(_name, _enclosure)
|
1673
|
+
@bases = []
|
1674
|
+
@resolved_bases = []
|
1675
|
+
@interfaces = []
|
1676
|
+
@resolved_interfaces = []
|
1677
|
+
@defined = false
|
1678
|
+
@recursive = false
|
1679
|
+
@forward = params[:forward] ? true : false
|
1680
|
+
@abstract = params[:abstract]
|
1681
|
+
@idltype = IDL::Type::Valuetype.new(self)
|
1682
|
+
complete_definition(params)
|
1683
|
+
end
|
1684
|
+
|
1685
|
+
def complete_definition(params)
|
1686
|
+
unless params[:forward]
|
1687
|
+
@custom = params[:custom] || false
|
1688
|
+
_inherits = params[:inherits] || {}
|
1689
|
+
_base = _inherits[:base] || {}
|
1690
|
+
@truncatable = _base[:truncatable] || false
|
1691
|
+
if @custom && @truncatable
|
1692
|
+
raise RuntimeError,
|
1693
|
+
"'truncatable' attribute *not* allowed for 'custom' #{typename} #{scoped_lm_name}"
|
1694
|
+
end
|
1695
|
+
add_bases(_base[:list] || [])
|
1696
|
+
add_interfaces(_inherits[:supports] || [])
|
1697
|
+
end
|
1698
|
+
end
|
1699
|
+
|
1700
|
+
def marshal_dump
|
1701
|
+
super() << @bases << @resolved_bases <<
|
1702
|
+
@interfaces << @resolved_interfaces <<
|
1703
|
+
@defined << @recursive <<
|
1704
|
+
@forward << @abstract <<
|
1705
|
+
@custom << @truncatable << @idltype
|
1706
|
+
end
|
1707
|
+
|
1708
|
+
def marshal_load(vars)
|
1709
|
+
@idltype = vars.pop
|
1710
|
+
@truncatable = vars.pop
|
1711
|
+
@custom = vars.pop
|
1712
|
+
@abstract = vars.pop
|
1713
|
+
@forward = vars.pop
|
1714
|
+
@recursive = vars.pop
|
1715
|
+
@defined = vars.pop
|
1716
|
+
@resolved_interfaces = vars.pop
|
1717
|
+
@interfaces = vars.pop
|
1718
|
+
@resolved_bases = vars.pop
|
1719
|
+
@bases = vars.pop
|
1720
|
+
super(vars)
|
1721
|
+
end
|
1722
|
+
|
1723
|
+
def instantiate(_context, _enclosure)
|
1724
|
+
_params = {
|
1725
|
+
:forward => self.is_forward?,
|
1726
|
+
:abstract => self.is_abstract?,
|
1727
|
+
:custom => self.is_custom?,
|
1728
|
+
:inherits => {
|
1729
|
+
:base => {
|
1730
|
+
:truncatable => self.is_truncatable?,
|
1731
|
+
:list => self.concrete_bases(_context)
|
1732
|
+
},
|
1733
|
+
:supports => self.concrete_interfaces(_context)
|
1734
|
+
}
|
1735
|
+
}
|
1736
|
+
inst = super(_context, _enclosure, _params)
|
1737
|
+
inst.defined = true
|
1738
|
+
inst
|
1739
|
+
end
|
1740
|
+
|
1741
|
+
def is_abstract?; @abstract; end
|
1742
|
+
def is_custom?; @custom; end
|
1743
|
+
def is_truncatable?; @truncatable; end
|
1744
|
+
def is_defined?; @defined; end
|
1745
|
+
def defined=(f); @defined = f; end
|
1746
|
+
def is_forward?; @forward; end
|
1747
|
+
def is_recursive?; @recursive end
|
1748
|
+
def recursive=(f); @recursive = f end
|
1749
|
+
|
1750
|
+
def is_local?(recurstk = [])
|
1751
|
+
# not local if forward decl or recursion detected
|
1752
|
+
return false if is_forward? || recurstk.include?(self)
|
1753
|
+
recurstk.push self # track root node to detect recursion
|
1754
|
+
ret = state_members.any? { |m| m.is_local?(recurstk) }
|
1755
|
+
recurstk.pop
|
1756
|
+
ret
|
1757
|
+
end
|
1758
|
+
|
1759
|
+
def modifier
|
1760
|
+
if is_abstract?
|
1761
|
+
:abstract
|
1762
|
+
elsif is_custom?
|
1763
|
+
:custom
|
1764
|
+
elsif is_truncatable?
|
1765
|
+
:truncatable
|
1766
|
+
else
|
1767
|
+
:none
|
1768
|
+
end
|
1769
|
+
end
|
1770
|
+
|
1771
|
+
def has_concrete_base?
|
1772
|
+
(not @resolved_bases.empty?) and (not @resolved_bases.first.is_abstract?)
|
1773
|
+
end
|
1774
|
+
|
1775
|
+
def supports_concrete_interface?
|
1776
|
+
!(@resolved_interfaces.empty? || @resolved_interfaces.first.is_abstract?)
|
1777
|
+
end
|
1778
|
+
|
1779
|
+
def supports_abstract_interface?
|
1780
|
+
@resolved_interfaces.any? { |intf| intf.is_abstract? }
|
1781
|
+
end
|
1782
|
+
|
1783
|
+
def truncatable_ids
|
1784
|
+
ids = [self.repository_id()]
|
1785
|
+
ids.concat(@resolved_bases.first().truncatable_ids()) if self.has_concrete_base?() && self.is_truncatable?()
|
1786
|
+
ids
|
1787
|
+
end
|
1788
|
+
|
1789
|
+
def add_bases(inherits_)
|
1790
|
+
inherits_.each do |tc|
|
1791
|
+
unless tc.is_a?(IDL::Type::ScopedName) && tc.is_node?(IDL::AST::TemplateParam)
|
1792
|
+
if not (tc.is_a?(IDL::Type::ScopedName) && tc.is_node?(IDL::AST::Valuetype))
|
1793
|
+
raise RuntimeError,
|
1794
|
+
"invalid inheritance identifier for #{typename} #{scoped_lm_name}: #{tc.typename}"
|
1795
|
+
end
|
1796
|
+
rtc = tc.resolved_type
|
1797
|
+
if rtc.node.has_ancestor?(self)
|
1798
|
+
raise RuntimeError,
|
1799
|
+
"circular inheritance detected for #{typename} #{scoped_lm_name}: #{tc.node.scoped_lm_name} is descendant"
|
1800
|
+
end
|
1801
|
+
if not rtc.node.is_defined?
|
1802
|
+
raise RuntimeError,
|
1803
|
+
"#{typename} #{scoped_lm_name} cannot inherit from forward declared #{tc.node.typename} #{tc.node.scoped_lm_name}"
|
1804
|
+
end
|
1805
|
+
if self.is_abstract? and not rtc.node.is_abstract?
|
1806
|
+
raise RuntimeError,
|
1807
|
+
"'abstract' #{typename} #{scoped_lm_name} cannot inherit from non-'abstract' #{tc.node.typename} #{tc.node.scoped_lm_name}"
|
1808
|
+
end
|
1809
|
+
if (not self.is_custom?) and rtc.node.is_custom?
|
1810
|
+
raise RuntimeError,
|
1811
|
+
"non-'custom' #{typename} #{scoped_lm_name} cannot inherit from 'custom' #{tc.node.typename} #{tc.node.scoped_lm_name}"
|
1812
|
+
end
|
1813
|
+
if @resolved_bases.include?(rtc.node)
|
1814
|
+
raise RuntimeError,
|
1815
|
+
"#{typename} #{scoped_lm_name} cannot inherit from #{tc.node.typename} #{tc.node.scoped_lm_name} multiple times"
|
1816
|
+
end
|
1817
|
+
if (not rtc.node.is_abstract?) and @bases.size > 0
|
1818
|
+
raise RuntimeError,
|
1819
|
+
"concrete basevalue #{tc.node.typename} #{tc.node.scoped_lm_name} MUST "+
|
1820
|
+
"be first and only non-abstract in inheritance list for #{typename} #{scoped_lm_name}"
|
1821
|
+
end
|
1822
|
+
@resolved_bases << rtc.node
|
1823
|
+
end
|
1824
|
+
@bases << tc.node
|
1825
|
+
end
|
1826
|
+
end
|
1827
|
+
|
1828
|
+
def add_interfaces(iflist_)
|
1829
|
+
iflist_.each do |if_|
|
1830
|
+
unless if_.is_a?(IDL::Type::ScopedName) && if_.is_node?(IDL::AST::TemplateParam)
|
1831
|
+
if not (if_.is_a?(IDL::Type::ScopedName) && if_.is_node?(IDL::AST::Interface))
|
1832
|
+
raise RuntimeError,
|
1833
|
+
"invalid support identifier for #{typename} #{scoped_lm_name}: #{if_.typename}"
|
1834
|
+
end
|
1835
|
+
rif_ = if_.resolved_type
|
1836
|
+
### @@TODO@@ further validation
|
1837
|
+
if (not rif_.node.is_abstract?) and @interfaces.size > 0
|
1838
|
+
raise RuntimeError,
|
1839
|
+
"concrete interface #{tc.node.typename} #{tc.node.scoped_lm_name} MUST be first and only in supports list for #{typename} #{scoped_lm_name}"
|
1840
|
+
end
|
1841
|
+
if (not rif_.node.is_abstract?) && (not is_interface_compatible?(rif_.node))
|
1842
|
+
raise RuntimeError,
|
1843
|
+
"#{typename} #{scoped_lm_name} cannot support #{tc.node.typename} #{tc.node.scoped_lm_name} because it does not derive from inherited interfaces"
|
1844
|
+
end
|
1845
|
+
@resolved_interfaces << rif_.node
|
1846
|
+
end
|
1847
|
+
@interfaces << if_.node
|
1848
|
+
end
|
1849
|
+
end
|
1850
|
+
|
1851
|
+
def has_ancestor?(n)
|
1852
|
+
@resolved_bases.include?(n.idltype.resolved_type.node) || @resolved_bases.any? { |b| b.has_ancestor?(n) }
|
1853
|
+
end
|
1854
|
+
|
1855
|
+
def is_interface_compatible?(n)
|
1856
|
+
if @resolved_interfaces.empty? || @resolved_interfaces.first.is_abstract?
|
1857
|
+
@resolved_bases.all? { |b| b.is_interface_compatible?(n) }
|
1858
|
+
else
|
1859
|
+
n.idltype.resolved_type.node.has_ancestor?(@interfaces.first)
|
1860
|
+
end
|
1861
|
+
end
|
1862
|
+
|
1863
|
+
def define(_type, _name, *args)
|
1864
|
+
if self.is_abstract? && [IDL::AST::StateMember, IDL::AST::Initializer].include?(_type)
|
1865
|
+
raise RuntimeError, "cannot define statemember #{_name} on abstract #{typename} #{scoped_lm_name}"
|
1866
|
+
end
|
1867
|
+
super(_type, _name, *args)
|
1868
|
+
end
|
1869
|
+
|
1870
|
+
def walk_members(&block)
|
1871
|
+
@children.each { |c| yield(c) unless c.is_a?(IDL::AST::StateMember) or
|
1872
|
+
c.is_a?(IDL::AST::Operation) or
|
1873
|
+
c.is_a?(IDL::AST::Attribute) or
|
1874
|
+
c.is_a?(IDL::AST::Initializer)
|
1875
|
+
}
|
1876
|
+
end
|
1877
|
+
|
1878
|
+
def state_members
|
1879
|
+
@children.find_all { |c| c.is_a?(IDL::AST::StateMember) }
|
1880
|
+
end
|
1881
|
+
|
1882
|
+
def interface_members
|
1883
|
+
@children.find_all { |c| c.is_a?(IDL::AST::Operation) or c.is_a?(IDL::AST::Attribute) }
|
1884
|
+
end
|
1885
|
+
|
1886
|
+
def initializers
|
1887
|
+
@children.find_all { |c| c.is_a?(IDL::AST::Initializer) }
|
1888
|
+
end
|
1889
|
+
|
1890
|
+
def has_operations_or_attributes?(include_intf = true)
|
1891
|
+
@children.any? { |c| c.is_a?(IDL::AST::Operation) || c.is_a?(IDL::AST::Attribute) } ||
|
1892
|
+
@resolved_bases.any? { |b| b.has_operations_or_attributes? } ||
|
1893
|
+
(include_intf &&
|
1894
|
+
@resolved_interfaces.any? { |intf| !intf.operations(true).empty? || !intf.attributes(true).empty? })
|
1895
|
+
end
|
1896
|
+
|
1897
|
+
def redefine(node, params)
|
1898
|
+
if node.enclosure == self
|
1899
|
+
case node
|
1900
|
+
when IDL::AST::Struct, IDL::AST::Union
|
1901
|
+
if node.is_defined?
|
1902
|
+
raise RuntimeError, "#{node.typename} \"#{node.name}\" is already defined."
|
1903
|
+
end
|
1904
|
+
node.annotations.concat(params[:annotations])
|
1905
|
+
|
1906
|
+
_new_node = node.class.new(node.name, self, params)
|
1907
|
+
_new_node.annotations.concat(node.annotations)
|
1908
|
+
_new_node.prefix = node.prefix
|
1909
|
+
_new_node.instance_variable_set(:@repo_ver, node.instance_variable_get(:@repo_ver))
|
1910
|
+
_new_node.instance_variable_set(:@repo_id, node.instance_variable_get(:@repo_id))
|
1911
|
+
|
1912
|
+
node.switchtype = params[:switchtype] if node.is_a?(IDL::AST::Union)
|
1913
|
+
|
1914
|
+
@children << _new_node
|
1915
|
+
# replace forward node registration
|
1916
|
+
node.enclosure.undo_introduction(node)
|
1917
|
+
introduce(_new_node)
|
1918
|
+
|
1919
|
+
return _new_node
|
1920
|
+
else
|
1921
|
+
raise RuntimeError, "#{node.typename} \"#{node.name}\" is already defined."
|
1922
|
+
end
|
1923
|
+
end
|
1924
|
+
|
1925
|
+
case node
|
1926
|
+
when IDL::AST::Operation, IDL::AST::Attribute, IDL::AST::StateMember, IDL::AST::Initializer
|
1927
|
+
raise RuntimeError, "#{node.typename} '#{node.scoped_lm_name}' cannot be overridden."
|
1928
|
+
else
|
1929
|
+
newnode = node.class.new(node.name, self, params)
|
1930
|
+
newnode.annotations.concat(params[:annotations])
|
1931
|
+
introduce(newnode)
|
1932
|
+
return newnode
|
1933
|
+
end
|
1934
|
+
end
|
1935
|
+
|
1936
|
+
protected
|
1937
|
+
|
1938
|
+
def walk_members_for_copy(&block)
|
1939
|
+
@children.each { |c| yield(c) }
|
1940
|
+
end
|
1941
|
+
|
1942
|
+
def resolved_bases
|
1943
|
+
@resolved_bases
|
1944
|
+
end
|
1945
|
+
|
1946
|
+
def concrete_bases(_context)
|
1947
|
+
# collect all bases and resolve any template param types
|
1948
|
+
@bases.collect do |_base|
|
1949
|
+
IDL::Type::ScopedName.new(IDL::AST::TemplateParam.concrete_param(_context, _base))
|
1950
|
+
end
|
1951
|
+
end
|
1952
|
+
|
1953
|
+
def concrete_interfaces(_context)
|
1954
|
+
@interfaces.collect do |_intf|
|
1955
|
+
IDL::Type::ScopedName.new(IDL::AST::TemplateParam.concrete_param(_context, _intf))
|
1956
|
+
end
|
1957
|
+
end
|
1958
|
+
end # Valuetype
|
1959
|
+
|
1960
|
+
class Eventtype < Valuetype
|
1961
|
+
def initialize(_name, _enclosure, params)
|
1962
|
+
super(_name, _enclosure, params)
|
1963
|
+
# overrule
|
1964
|
+
@idltype = IDL::Type::Eventtype.new(self)
|
1965
|
+
end
|
1966
|
+
end # Eventtype
|
1967
|
+
|
1968
|
+
class StateMember < Leaf
|
1969
|
+
NAMETYPE = :member
|
1970
|
+
attr_reader :idltype, :visibility
|
1971
|
+
def initialize(_name, _enclosure, params)
|
1972
|
+
@is_recursive = false
|
1973
|
+
@has_incomplete_type = false
|
1974
|
+
super(_name, _enclosure)
|
1975
|
+
@idltype = params[:type]
|
1976
|
+
@visibility = (params[:visibility] == :public ? :public : :private)
|
1977
|
+
unless @idltype.is_a?(IDL::Type::ScopedName) && @idltype.is_node?(IDL::AST::TemplateParam)
|
1978
|
+
raise RuntimeError, "Anonymous type definitions are not allowed!" if params[:type].is_anonymous?
|
1979
|
+
## check for use of incomplete types
|
1980
|
+
if !@idltype.is_complete?
|
1981
|
+
## verify type is used in sequence
|
1982
|
+
if @idltype.resolved_type.is_a?(IDL::Type::Sequence)
|
1983
|
+
## find the (non-sequence) elementtype
|
1984
|
+
seq_ = @idltype.resolved_type
|
1985
|
+
mtype = seq_.basetype
|
1986
|
+
while mtype.resolved_type.is_a? IDL::Type::Sequence
|
1987
|
+
seq_ = mtype.resolved_type
|
1988
|
+
mtype = seq_.basetype
|
1989
|
+
end
|
1990
|
+
## is it an incomplete struct, union or valuetype?
|
1991
|
+
if mtype.is_a? IDL::Type::ScopedName
|
1992
|
+
case mtype.resolved_type
|
1993
|
+
when IDL::Type::Struct, IDL::Type::Union, IDL::Type::Valuetype
|
1994
|
+
if !mtype.node.is_defined?
|
1995
|
+
## check if incomplete struct/union/valuetype is contained within definition of self
|
1996
|
+
enc = _enclosure
|
1997
|
+
while enc.is_a?(IDL::AST::Struct) || enc.is_a?(IDL::AST::Union) || enc.is_a?(IDL::AST::Valuetype)
|
1998
|
+
if enc.scoped_name == mtype.node.scoped_name
|
1999
|
+
## mark enclosure as recursive
|
2000
|
+
enc.recursive = true
|
2001
|
+
## mark sequence as recursive type !!! DEPRECATED !!!; leave till R2CORBA updated
|
2002
|
+
seq_.recursive = true
|
2003
|
+
return
|
2004
|
+
end
|
2005
|
+
enc = enc.enclosure
|
2006
|
+
end
|
2007
|
+
end
|
2008
|
+
end
|
2009
|
+
if mtype.resolved_type.is_a?(IDL::Type::Valuetype)
|
2010
|
+
# mark member as using an incomplete valuetype; allowed but needs special care
|
2011
|
+
@has_incomplete_type = true
|
2012
|
+
return
|
2013
|
+
end
|
2014
|
+
end
|
2015
|
+
elsif @idltype.resolved_type.is_a?(IDL::Type::Valuetype)
|
2016
|
+
mtype = @idltype.resolved_type
|
2017
|
+
enc = _enclosure
|
2018
|
+
while enc.is_a?(IDL::AST::Struct) || enc.is_a?(IDL::AST::Union) || enc.is_a?(IDL::AST::Valuetype)
|
2019
|
+
if enc.is_a?(IDL::AST::Valuetype) && enc.scoped_name == mtype.node.scoped_name
|
2020
|
+
## statemember using recursive valuetype
|
2021
|
+
## is enclosed in valuetype itself as part of constructed type
|
2022
|
+
## which is allowed and not a problem
|
2023
|
+
@is_recursive = true
|
2024
|
+
## mark enclosure as recursive
|
2025
|
+
enc.recursive = true
|
2026
|
+
return
|
2027
|
+
end
|
2028
|
+
enc = enc.enclosure
|
2029
|
+
end
|
2030
|
+
# mark member as using an incomplete valuetype; allowed but needs special care
|
2031
|
+
@has_incomplete_type = true
|
2032
|
+
return
|
2033
|
+
end
|
2034
|
+
raise RuntimeError, "Incomplete type #{@idltype.typename} not allowed here!"
|
2035
|
+
end
|
2036
|
+
end
|
2037
|
+
end
|
2038
|
+
|
2039
|
+
def marshal_dump
|
2040
|
+
super() << @idltype << @visibility << @is_recursive << @has_incomplete_type
|
2041
|
+
end
|
2042
|
+
|
2043
|
+
def marshal_load(vars)
|
2044
|
+
@has_incomplete_type = vars.pop
|
2045
|
+
@is_recursive = vars.pop
|
2046
|
+
@visibility = vars.pop
|
2047
|
+
@idltype = vars.pop
|
2048
|
+
super(vars)
|
2049
|
+
end
|
2050
|
+
|
2051
|
+
def instantiate(_context, _enclosure)
|
2052
|
+
_params = {
|
2053
|
+
:type => @idltype.instantiate(_context),
|
2054
|
+
:visibility => self.visibility
|
2055
|
+
}
|
2056
|
+
super(_context, _enclosure, _params)
|
2057
|
+
end
|
2058
|
+
|
2059
|
+
def is_local?(recurstk)
|
2060
|
+
idltype.is_local?(recurstk)
|
2061
|
+
end
|
2062
|
+
|
2063
|
+
def is_public?
|
2064
|
+
@visibility == :public
|
2065
|
+
end
|
2066
|
+
|
2067
|
+
def is_recursive?
|
2068
|
+
@is_recursive
|
2069
|
+
end
|
2070
|
+
|
2071
|
+
def has_incomplete_type?
|
2072
|
+
@has_incomplete_type
|
2073
|
+
end
|
2074
|
+
end # StateMember
|
2075
|
+
|
2076
|
+
class Initializer < Leaf
|
2077
|
+
NAMETYPE = :member
|
2078
|
+
attr_reader :raises, :params
|
2079
|
+
def initialize(_name, _enclosure, params)
|
2080
|
+
super(_name, _enclosure)
|
2081
|
+
@params = (params[:params] || []).collect do |(ptype, pname)|
|
2082
|
+
IDL::AST::Parameter.new(pname, self, {:attribute => :in, :type => ptype})
|
2083
|
+
end
|
2084
|
+
@raises = []
|
2085
|
+
self.raises = params[:raises]
|
2086
|
+
end
|
2087
|
+
|
2088
|
+
def raises=(exlist)
|
2089
|
+
exlist.each do |extype|
|
2090
|
+
unless extype.is_a?(IDL::Type::ScopedName) &&
|
2091
|
+
(extype.is_node?(IDL::AST::Exception) || extype.is_node?(IDL::AST::TemplateParam) || extype.resolved_type.is_a?(IDL::Type::Native))
|
2092
|
+
raise RuntimeError, 'Only IDL Exception types allowed in raises declaration.'
|
2093
|
+
end
|
2094
|
+
@raises << extype
|
2095
|
+
end
|
2096
|
+
end
|
2097
|
+
|
2098
|
+
def marshal_dump
|
2099
|
+
super() << @params << @raises
|
2100
|
+
end
|
2101
|
+
|
2102
|
+
def marshal_load(vars)
|
2103
|
+
@raises = vars.pop
|
2104
|
+
@params = vars.pop
|
2105
|
+
super(vars)
|
2106
|
+
end
|
2107
|
+
|
2108
|
+
def instantiate(_context, _enclosure)
|
2109
|
+
_params = {
|
2110
|
+
:raises => self.concrete_raises(_context)
|
2111
|
+
}
|
2112
|
+
_init = super(_context, _enclosure, _params)
|
2113
|
+
_init.set_concrete_parameters(_context, @params)
|
2114
|
+
_init
|
2115
|
+
end
|
2116
|
+
|
2117
|
+
protected
|
2118
|
+
|
2119
|
+
def concrete_raises(_context)
|
2120
|
+
@raises.collect do |ex|
|
2121
|
+
ex.instantiate(_context)
|
2122
|
+
end
|
2123
|
+
end
|
2124
|
+
|
2125
|
+
def set_concrete_parameters(_context, parms)
|
2126
|
+
@params = parms.collect do |parm|
|
2127
|
+
IDL::AST::Parameter.new(parm.name, self,
|
2128
|
+
{ :attribute => :in,
|
2129
|
+
:type => parm.idltype.instantiate(_context) })
|
2130
|
+
end
|
2131
|
+
end
|
2132
|
+
|
2133
|
+
end # Initializer
|
2134
|
+
|
2135
|
+
class Finder < Initializer
|
2136
|
+
end # Finder
|
2137
|
+
|
2138
|
+
class Const < Leaf
|
2139
|
+
NAMETYPE = :class
|
2140
|
+
attr_reader :idltype, :expression, :value
|
2141
|
+
def initialize(_name, _enclosure, params)
|
2142
|
+
super(_name, _enclosure)
|
2143
|
+
@idltype = params[:type]
|
2144
|
+
@expression = params[:expression]
|
2145
|
+
@value = nil
|
2146
|
+
unless @idltype.is_a?(IDL::Type::ScopedName) && @idltype.is_node?(IDL::AST::TemplateParam)
|
2147
|
+
raise RuntimeError, "Anonymous type definitions are not allowed!" if @idltype.is_anonymous?
|
2148
|
+
raise RuntimeError,
|
2149
|
+
"Incomplete type #{@idltype.typename} not allowed here!" if !@idltype.is_complete?
|
2150
|
+
unless @expression.is_a?(IDL::Expression::ScopedName) && @expression.is_node?(IDL::AST::TemplateParam)
|
2151
|
+
@value = @idltype.narrow(@expression.value)
|
2152
|
+
end
|
2153
|
+
end
|
2154
|
+
end
|
2155
|
+
|
2156
|
+
def marshal_dump
|
2157
|
+
super() << @idltype << @expression
|
2158
|
+
end
|
2159
|
+
|
2160
|
+
def marshal_load(vars)
|
2161
|
+
@expression = vars.pop
|
2162
|
+
@idltype = vars.pop
|
2163
|
+
super(vars)
|
2164
|
+
unless @idltype.is_a?(IDL::Type::ScopedName) && @idltype.is_node?(IDL::AST::TemplateParam)
|
2165
|
+
unless @expression.is_a?(IDL::Expression::ScopedName) && @expression.is_node?(IDL::AST::TemplateParam)
|
2166
|
+
@value = @idltype.narrow(@expression.value)
|
2167
|
+
end
|
2168
|
+
end
|
2169
|
+
end
|
2170
|
+
|
2171
|
+
def instantiate(_context, _enclosure)
|
2172
|
+
_params = {
|
2173
|
+
:type => @idltype.instantiate(_context),
|
2174
|
+
:expression => @expression.instantiate(_context)
|
2175
|
+
}
|
2176
|
+
super(_context, _enclosure, _params)
|
2177
|
+
end
|
2178
|
+
end # Const
|
2179
|
+
|
2180
|
+
class Parameter < Leaf
|
2181
|
+
NAMETYPE = :member
|
2182
|
+
IN, OUT, INOUT = 0, 1, 2
|
2183
|
+
ATTRIBUTE_MAP = {
|
2184
|
+
:in => IN,
|
2185
|
+
:out => OUT,
|
2186
|
+
:inout => INOUT
|
2187
|
+
}
|
2188
|
+
attr_reader :idltype
|
2189
|
+
def initialize(_name, _enclosure, params)
|
2190
|
+
super(_name, _enclosure)
|
2191
|
+
@idltype = params[:type]
|
2192
|
+
@attribute = params[:attribute]
|
2193
|
+
unless ATTRIBUTE_MAP.has_key?(@attribute)
|
2194
|
+
raise RuntimeError,
|
2195
|
+
"invalid attribute for parameter: #{params[:attribute]}"
|
2196
|
+
end
|
2197
|
+
unless @idltype.is_a?(IDL::Type::ScopedName) && @idltype.is_node?(IDL::AST::TemplateParam)
|
2198
|
+
raise RuntimeError, "Anonymous type definitions are not allowed!" if params[:type].is_anonymous?
|
2199
|
+
if @idltype.is_local?
|
2200
|
+
if _enclosure.enclosure.is_a?(IDL::AST::Interface) && !_enclosure.enclosure.is_local?
|
2201
|
+
raise RuntimeError, "Local type #{@idltype.typename} not allowed for operation on unrestricted interface"
|
2202
|
+
end
|
2203
|
+
## IDL_Valuetype: no problem as valuetype operations are local
|
2204
|
+
end
|
2205
|
+
if !@idltype.is_complete?
|
2206
|
+
if _enclosure.enclosure.is_a?(IDL::AST::Interface)
|
2207
|
+
raise RuntimeError, "Incomplete type #{@idltype.typename} not allowed here!"
|
2208
|
+
end
|
2209
|
+
## IDL_Valuetype: no problem as valuetype operations are local
|
2210
|
+
end
|
2211
|
+
end
|
2212
|
+
end
|
2213
|
+
|
2214
|
+
def attribute
|
2215
|
+
ATTRIBUTE_MAP[@attribute]
|
2216
|
+
end
|
2217
|
+
|
2218
|
+
def marshal_dump
|
2219
|
+
super() << @idltype << @attribute
|
2220
|
+
end
|
2221
|
+
|
2222
|
+
def marshal_load(vars)
|
2223
|
+
@attribute = vars.pop
|
2224
|
+
@idltype = vars.pop
|
2225
|
+
super(vars)
|
2226
|
+
end
|
2227
|
+
|
2228
|
+
def instantiate(_context, _enclosure)
|
2229
|
+
_params = {
|
2230
|
+
:type => @idltype.instantiate(_context),
|
2231
|
+
:attribute => @attribute
|
2232
|
+
}
|
2233
|
+
super(_context, _enclosure, _params)
|
2234
|
+
end
|
2235
|
+
end # Parameter
|
2236
|
+
|
2237
|
+
class Operation < Node
|
2238
|
+
NAMETYPE = :member
|
2239
|
+
DEFINABLE = [IDL::AST::Parameter]
|
2240
|
+
attr_reader :idltype, :oneway, :raises
|
2241
|
+
attr_accessor :context
|
2242
|
+
|
2243
|
+
def initialize(_name, _enclosure, params)
|
2244
|
+
super(_name, _enclosure)
|
2245
|
+
@idltype = params[:type]
|
2246
|
+
@oneway = (params[:oneway] == true)
|
2247
|
+
@in = []
|
2248
|
+
@out = []
|
2249
|
+
@raises = []
|
2250
|
+
@context = nil
|
2251
|
+
unless @idltype.is_a?(IDL::Type::ScopedName) && @idltype.is_node?(IDL::AST::TemplateParam)
|
2252
|
+
raise RuntimeError, "Anonymous type definitions are not allowed!" if params[:type].is_anonymous?
|
2253
|
+
if @idltype.is_local?
|
2254
|
+
if _enclosure.is_a?(IDL::AST::Interface) && !_enclosure.is_local?
|
2255
|
+
raise RuntimeError, "Local type #{@idltype.typename} not allowed for operation on unrestricted interface"
|
2256
|
+
end
|
2257
|
+
## IDL_Valuetype: no problem as valuetype operations are local
|
2258
|
+
end
|
2259
|
+
if !@idltype.is_complete?
|
2260
|
+
if _enclosure.is_a?(IDL::AST::Interface)
|
2261
|
+
raise RuntimeError, "Incomplete type #{@idltype.typename} not allowed here!"
|
2262
|
+
end
|
2263
|
+
## IDL_Valuetype: no problem as valuetype operations are local
|
2264
|
+
end
|
2265
|
+
end
|
2266
|
+
end
|
2267
|
+
|
2268
|
+
def marshal_dump
|
2269
|
+
super() << @idltype << @oneway << @in << @out << @raises << @context
|
2270
|
+
end
|
2271
|
+
|
2272
|
+
def marshal_load(vars)
|
2273
|
+
@context = vars.pop
|
2274
|
+
@raises = vars.pop
|
2275
|
+
@out = vars.pop
|
2276
|
+
@in = vars.pop
|
2277
|
+
@oneway = vars.pop
|
2278
|
+
@idltype = vars.pop
|
2279
|
+
super(vars)
|
2280
|
+
end
|
2281
|
+
|
2282
|
+
def instantiate(_context, _enclosure)
|
2283
|
+
_params = {
|
2284
|
+
:type => @idltype.instantiate(_context),
|
2285
|
+
:oneway => @oneway,
|
2286
|
+
}
|
2287
|
+
_op = super(_context, _enclosure, _params)
|
2288
|
+
_op.raises = self.concrete_raises(_context)
|
2289
|
+
_op.context = @context
|
2290
|
+
_op
|
2291
|
+
end
|
2292
|
+
|
2293
|
+
def raises=(exlist)
|
2294
|
+
exlist.each do |extype|
|
2295
|
+
unless extype.is_a?(IDL::Type::ScopedName) &&
|
2296
|
+
(extype.is_node?(IDL::AST::Exception) || extype.is_node?(IDL::AST::TemplateParam) || extype.resolved_type.is_a?(IDL::Type::Native))
|
2297
|
+
raise RuntimeError, 'Only IDL Exception or Native types allowed in raises declaration.'
|
2298
|
+
end
|
2299
|
+
@raises << extype
|
2300
|
+
end
|
2301
|
+
end
|
2302
|
+
|
2303
|
+
def define(*args)
|
2304
|
+
param = super(*args)
|
2305
|
+
case param.attribute
|
2306
|
+
when Parameter::IN
|
2307
|
+
@in << param
|
2308
|
+
when Parameter::OUT
|
2309
|
+
@out << param
|
2310
|
+
when Parameter::INOUT
|
2311
|
+
@in << param
|
2312
|
+
@out << param
|
2313
|
+
end
|
2314
|
+
param
|
2315
|
+
end
|
2316
|
+
|
2317
|
+
def in_params
|
2318
|
+
@in
|
2319
|
+
end
|
2320
|
+
def out_params
|
2321
|
+
@out
|
2322
|
+
end
|
2323
|
+
def params
|
2324
|
+
self.children
|
2325
|
+
end
|
2326
|
+
|
2327
|
+
protected
|
2328
|
+
|
2329
|
+
def concrete_raises(_context)
|
2330
|
+
@raises.collect do |ex|
|
2331
|
+
ex.instantiate(_context)
|
2332
|
+
end
|
2333
|
+
end
|
2334
|
+
|
2335
|
+
def copy_from(_template, _context)
|
2336
|
+
super
|
2337
|
+
self.walk_members do |param|
|
2338
|
+
case param.attribute
|
2339
|
+
when Parameter::IN
|
2340
|
+
@in << param
|
2341
|
+
when Parameter::OUT
|
2342
|
+
@out << param
|
2343
|
+
when Parameter::INOUT
|
2344
|
+
@in << param
|
2345
|
+
@out << param
|
2346
|
+
end
|
2347
|
+
end
|
2348
|
+
self
|
2349
|
+
end
|
2350
|
+
end # Operation
|
2351
|
+
|
2352
|
+
class Attribute < Leaf
|
2353
|
+
attr_reader :idltype, :readonly
|
2354
|
+
attr_reader :get_raises, :set_raises
|
2355
|
+
NAMETYPE = :member
|
2356
|
+
def initialize(_name, _enclosure, params)
|
2357
|
+
super(_name, _enclosure)
|
2358
|
+
@idltype = params[:type]
|
2359
|
+
@get_raises = []
|
2360
|
+
@set_raises = []
|
2361
|
+
unless @idltype.is_a?(IDL::Type::ScopedName) && @idltype.is_node?(IDL::AST::TemplateParam)
|
2362
|
+
raise RuntimeError, "Anonymous type definitions are not allowed!" if @idltype.is_anonymous?
|
2363
|
+
if @idltype.is_local?
|
2364
|
+
if _enclosure.is_a?(IDL::AST::Interface) && !_enclosure.is_local?
|
2365
|
+
raise RuntimeError, "Local type #{@idltype.typename} not allowed for operation on unrestricted interface"
|
2366
|
+
end
|
2367
|
+
## IDL_Valuetype: no problem as valuetype operations are local
|
2368
|
+
end
|
2369
|
+
if !@idltype.is_complete?
|
2370
|
+
if _enclosure.is_a?(IDL::AST::Interface)
|
2371
|
+
raise RuntimeError, "Incomplete type #{@idltype.typename} not allowed here!"
|
2372
|
+
end
|
2373
|
+
## IDL_Valuetype: no problem as valuetype operations are local
|
2374
|
+
end
|
2375
|
+
end
|
2376
|
+
@readonly = params[:readonly]
|
2377
|
+
end
|
2378
|
+
|
2379
|
+
def marshal_dump
|
2380
|
+
super() << @idltype << @readonly << @get_raises << @set_raises
|
2381
|
+
end
|
2382
|
+
|
2383
|
+
def marshal_load(vars)
|
2384
|
+
@set_raises = vars.pop
|
2385
|
+
@get_raises = vars.pop
|
2386
|
+
@readonly = vars.pop
|
2387
|
+
@idltype = vars.pop
|
2388
|
+
super(vars)
|
2389
|
+
end
|
2390
|
+
|
2391
|
+
def instantiate(_context, _enclosure)
|
2392
|
+
_params = {
|
2393
|
+
:type => @idltype.instantiate(_context),
|
2394
|
+
:readonly => @readonly
|
2395
|
+
}
|
2396
|
+
_att = super(_context, _enclosure, _params)
|
2397
|
+
_att.get_raises = self.concrete_get_raises(_context)
|
2398
|
+
_att.set_raises = self.concrete_set_raises(_context)
|
2399
|
+
_att
|
2400
|
+
end
|
2401
|
+
|
2402
|
+
def get_raises=(exlist)
|
2403
|
+
exlist.each do |extype|
|
2404
|
+
unless extype.is_a?(IDL::Type::ScopedName) &&
|
2405
|
+
(extype.is_node?(IDL::AST::Exception) || extype.is_node?(IDL::AST::TemplateParam) || extype.resolved_type.is_a?(IDL::Type::Native))
|
2406
|
+
raise RuntimeError, 'Only IDL Exception types allowed in raises declaration.' unless extype.resolved_type.node.is_a?(IDL::AST::Exception)
|
2407
|
+
end
|
2408
|
+
@get_raises << extype
|
2409
|
+
end
|
2410
|
+
end
|
2411
|
+
|
2412
|
+
def set_raises=(exlist)
|
2413
|
+
exlist.each do |extype|
|
2414
|
+
unless extype.is_a?(IDL::Type::ScopedName) &&
|
2415
|
+
(extype.is_node?(IDL::AST::Exception) || extype.is_node?(IDL::AST::TemplateParam) || extype.resolved_type.is_a?(IDL::Type::Native))
|
2416
|
+
raise RuntimeError, 'Only IDL Exception types allowed in raises declaration.' unless extype.resolved_type.node.is_a?(IDL::AST::Exception)
|
2417
|
+
end
|
2418
|
+
@set_raises << extype
|
2419
|
+
end
|
2420
|
+
end
|
2421
|
+
|
2422
|
+
def expanded_copy(name_pfx, enc)
|
2423
|
+
att = IDL::AST::Attribute.new("#{name_pfx}_#{self.name}", enc, {:type => @idltype, :readonly => @readonly})
|
2424
|
+
att.get_raises = @get_raises unless @get_raises.empty?
|
2425
|
+
att.set_raises = @set_raises unless @set_raises.empty?
|
2426
|
+
att
|
2427
|
+
end
|
2428
|
+
|
2429
|
+
protected
|
2430
|
+
|
2431
|
+
def concrete_get_raises(_context)
|
2432
|
+
@get_raises.collect do |ex|
|
2433
|
+
ex.instantiate(_context)
|
2434
|
+
end
|
2435
|
+
end
|
2436
|
+
|
2437
|
+
def concrete_set_raises(_context)
|
2438
|
+
@set_raises.collect do |ex|
|
2439
|
+
ex.instantiate(_context)
|
2440
|
+
end
|
2441
|
+
end
|
2442
|
+
end # Attribute
|
2443
|
+
|
2444
|
+
class Struct < Node
|
2445
|
+
NAMETYPE = :class
|
2446
|
+
DEFINABLE = [IDL::AST::Member, IDL::AST::Struct, IDL::AST::Union, IDL::AST::Enum, IDL::AST::Enumerator]
|
2447
|
+
attr_reader :idltype
|
2448
|
+
def initialize(_name, _enclosure, params)
|
2449
|
+
@defined = false
|
2450
|
+
@recursive = false
|
2451
|
+
@forward = params[:forward] ? true : false
|
2452
|
+
super(_name, _enclosure)
|
2453
|
+
@idltype = IDL::Type::Struct.new(self)
|
2454
|
+
end
|
2455
|
+
|
2456
|
+
def is_defined?; @defined end
|
2457
|
+
def defined=(f); @defined = f end
|
2458
|
+
def is_forward?; @forward end
|
2459
|
+
def is_recursive?; @recursive end
|
2460
|
+
def recursive=(f); @recursive = f end
|
2461
|
+
|
2462
|
+
def walk_members(&block)
|
2463
|
+
@children.each { |m| yield(m) if not m.is_a? IDL::AST::Member }
|
2464
|
+
end
|
2465
|
+
|
2466
|
+
def members
|
2467
|
+
@children.find_all { |c| c.is_a? IDL::AST::Member }
|
2468
|
+
end
|
2469
|
+
|
2470
|
+
def is_local?(recurstk = [])
|
2471
|
+
# not local if forward decl or recursion detected
|
2472
|
+
return false if is_forward? || recurstk.include?(self)
|
2473
|
+
recurstk.push self # track root node to detect recursion
|
2474
|
+
ret = members.any? { |m| m.is_local?(recurstk) }
|
2475
|
+
recurstk.pop
|
2476
|
+
ret
|
2477
|
+
end
|
2478
|
+
|
2479
|
+
def marshal_dump
|
2480
|
+
super() << @idltype << @defined << @recursive << @forward
|
2481
|
+
end
|
2482
|
+
|
2483
|
+
def marshal_load(vars)
|
2484
|
+
@forward = vars.pop
|
2485
|
+
@recursive = vars.pop
|
2486
|
+
@defined = vars.pop
|
2487
|
+
@idltype = vars.pop
|
2488
|
+
super(vars)
|
2489
|
+
end
|
2490
|
+
|
2491
|
+
def instantiate(_context, _enclosure)
|
2492
|
+
_params = {
|
2493
|
+
:forward => @forward
|
2494
|
+
}
|
2495
|
+
_s = super(_context, _enclosure, _params)
|
2496
|
+
_s.defined = self.is_defined?
|
2497
|
+
_s
|
2498
|
+
end
|
2499
|
+
|
2500
|
+
protected
|
2501
|
+
|
2502
|
+
def walk_members_for_copy(&block)
|
2503
|
+
@children.each { |c| yield(c) }
|
2504
|
+
end
|
2505
|
+
end # Struct
|
2506
|
+
|
2507
|
+
class Exception < IDL::AST::Struct
|
2508
|
+
DEFINABLE = [IDL::AST::Member, IDL::AST::Struct, IDL::AST::Union, IDL::AST::Enum, IDL::AST::Enumerator]
|
2509
|
+
def initialize(_name, _enclosure, params)
|
2510
|
+
super(_name, _enclosure, params)
|
2511
|
+
@idltype = IDL::Type::Exception.new(self)
|
2512
|
+
end
|
2513
|
+
end # Exception
|
2514
|
+
|
2515
|
+
class Member < Leaf
|
2516
|
+
attr_reader :idltype
|
2517
|
+
NAMETYPE = :member
|
2518
|
+
def initialize(_name, _enclosure, params)
|
2519
|
+
super(_name, _enclosure)
|
2520
|
+
@idltype = params[:type]
|
2521
|
+
unless @idltype.is_a?(IDL::Type::ScopedName) && @idltype.is_node?(IDL::AST::TemplateParam)
|
2522
|
+
raise RuntimeError, "Anonymous type definitions are not allowed!" if @idltype.is_anonymous?
|
2523
|
+
## check for use of incomplete types
|
2524
|
+
if !@idltype.is_complete?
|
2525
|
+
## verify type is used in sequence
|
2526
|
+
if @idltype.resolved_type.is_a? IDL::Type::Sequence
|
2527
|
+
## find the (non-sequence) elementtype
|
2528
|
+
seq_ = @idltype.resolved_type
|
2529
|
+
mtype = seq_.basetype
|
2530
|
+
while mtype.resolved_type.is_a? IDL::Type::Sequence
|
2531
|
+
seq_ = mtype.resolved_type
|
2532
|
+
mtype = seq_.basetype
|
2533
|
+
end
|
2534
|
+
## is it an incomplete struct, union or valuetype?
|
2535
|
+
if mtype.is_a? IDL::Type::ScopedName
|
2536
|
+
case mtype.resolved_type
|
2537
|
+
when IDL::Type::Struct, IDL::Type::Union, IDL::Type::Valuetype
|
2538
|
+
if !mtype.node.is_defined?
|
2539
|
+
## check if incomplete struct/union is contained within definition of self
|
2540
|
+
enc = _enclosure
|
2541
|
+
while enc.is_a?(IDL::AST::Struct) || enc.is_a?(IDL::AST::Union) || enc.is_a?(IDL::AST::Valuetype)
|
2542
|
+
if enc.scoped_name == mtype.node.scoped_name
|
2543
|
+
## mark enclosure as recursive
|
2544
|
+
enc.recursive = true
|
2545
|
+
## mark sequence as recursive type !!! DEPRECATED !!!; leave till R2CORBA updated
|
2546
|
+
seq_.recursive = true
|
2547
|
+
return
|
2548
|
+
end
|
2549
|
+
enc = enc.enclosure
|
2550
|
+
end
|
2551
|
+
end
|
2552
|
+
return # incomplete types in sequences allowed
|
2553
|
+
end
|
2554
|
+
end
|
2555
|
+
end
|
2556
|
+
raise RuntimeError, "Incomplete type #{@idltype.typename} not allowed here!"
|
2557
|
+
end
|
2558
|
+
end
|
2559
|
+
end
|
2560
|
+
|
2561
|
+
def is_local?(recurstk)
|
2562
|
+
idltype.is_local?(recurstk)
|
2563
|
+
end
|
2564
|
+
|
2565
|
+
def marshal_dump
|
2566
|
+
super() << @idltype
|
2567
|
+
end
|
2568
|
+
|
2569
|
+
def marshal_load(vars)
|
2570
|
+
@idltype = vars.pop
|
2571
|
+
super(vars)
|
2572
|
+
end
|
2573
|
+
|
2574
|
+
def instantiate(_context, _enclosure, _params = {})
|
2575
|
+
_params.merge!({
|
2576
|
+
:type => @idltype.instantiate(_context),
|
2577
|
+
})
|
2578
|
+
super(_context, _enclosure, _params)
|
2579
|
+
end
|
2580
|
+
end # Member
|
2581
|
+
|
2582
|
+
class Union < Node
|
2583
|
+
NAMETYPE = :class
|
2584
|
+
DEFINABLE = [IDL::AST::UnionMember, IDL::AST::Struct, IDL::AST::Union, IDL::AST::Enum, IDL::AST::Enumerator]
|
2585
|
+
attr_reader :idltype
|
2586
|
+
attr_accessor :switchtype
|
2587
|
+
def initialize(_name, _enclosure, params)
|
2588
|
+
@defined = false
|
2589
|
+
@recursive = false
|
2590
|
+
@forward = params[:forward] ? true : false
|
2591
|
+
@switchtype = nil
|
2592
|
+
super(_name, _enclosure)
|
2593
|
+
@idltype = IDL::Type::Union.new(self)
|
2594
|
+
end
|
2595
|
+
|
2596
|
+
def set_switchtype(_switchtype)
|
2597
|
+
@switchtype = _switchtype
|
2598
|
+
end
|
2599
|
+
|
2600
|
+
def is_defined?; @defined; end
|
2601
|
+
def defined=(f); @defined = f; end
|
2602
|
+
def is_forward?; @forward; end
|
2603
|
+
def is_recursive?; @recursive end
|
2604
|
+
def recursive=(f); @recursive = f end
|
2605
|
+
|
2606
|
+
def walk_members(&block)
|
2607
|
+
@children.each { |m| yield(m) if not m.is_a? IDL::AST::UnionMember }
|
2608
|
+
end
|
2609
|
+
|
2610
|
+
def members
|
2611
|
+
@children.find_all { |c| c.is_a? IDL::AST::UnionMember }
|
2612
|
+
end
|
2613
|
+
|
2614
|
+
def is_local?(recurstk = [])
|
2615
|
+
# not local if forward decl or recursion detected
|
2616
|
+
return false if is_forward? || recurstk.include?(self)
|
2617
|
+
recurstk.push self # track root node to detect recursion
|
2618
|
+
ret = members.any? { |m| m.is_local?(recurstk) }
|
2619
|
+
recurstk.pop
|
2620
|
+
ret
|
2621
|
+
end
|
2622
|
+
|
2623
|
+
def has_default?
|
2624
|
+
members.any? { |m| m.labels.include?(:default) }
|
2625
|
+
end
|
2626
|
+
|
2627
|
+
def default_label
|
2628
|
+
swtype = @switchtype.resolved_type
|
2629
|
+
lbls = members.collect { |m| m.labels.include?(:default) ? [] : m.labels.collect { |l| l.value } }.flatten
|
2630
|
+
lbls = lbls.sort unless IDL::Type::Boolean === swtype ## work around bug in Ruby 1.9.2
|
2631
|
+
def_lbl = swtype.min
|
2632
|
+
while swtype.in_range?(def_lbl)
|
2633
|
+
return IDL::Expression::Value.new(@switchtype, def_lbl) unless lbls.include?(def_lbl)
|
2634
|
+
return nil if def_lbl == swtype.max
|
2635
|
+
def_lbl = swtype.next(def_lbl)
|
2636
|
+
end
|
2637
|
+
nil
|
2638
|
+
end
|
2639
|
+
|
2640
|
+
def validate_labels
|
2641
|
+
return if self.is_template?
|
2642
|
+
labelvals = []
|
2643
|
+
default_ = false
|
2644
|
+
members.each { |m|
|
2645
|
+
## check union case labels for validity
|
2646
|
+
m.labels.each { |lbl|
|
2647
|
+
if lbl == :default
|
2648
|
+
raise RuntimeError,
|
2649
|
+
"duplicate case label 'default' for #{typename} #{lm_name}" if default_
|
2650
|
+
default_ = true
|
2651
|
+
else
|
2652
|
+
# correct type
|
2653
|
+
lv = @switchtype.resolved_type.narrow(lbl.value)
|
2654
|
+
# doubles
|
2655
|
+
if labelvals.include? lv
|
2656
|
+
raise RuntimeError,
|
2657
|
+
"duplicate case label #{lv.to_s} for #{typename} #{lm_name}"
|
2658
|
+
end
|
2659
|
+
labelvals << lv
|
2660
|
+
end
|
2661
|
+
}
|
2662
|
+
}
|
2663
|
+
## check if default allowed if defined
|
2664
|
+
if default_
|
2665
|
+
if @switchtype.resolved_type.range_length == labelvals.size
|
2666
|
+
raise RuntimeError,
|
2667
|
+
"'default' case label superfluous for #{typename} #{lm_name}"
|
2668
|
+
end
|
2669
|
+
end
|
2670
|
+
end
|
2671
|
+
|
2672
|
+
def marshal_dump
|
2673
|
+
super() << @defined << @recursive << @forward << @idltype << @switchtype
|
2674
|
+
end
|
2675
|
+
|
2676
|
+
def marshal_load(vars)
|
2677
|
+
@switchtype = vars.pop
|
2678
|
+
@idltype = vars.pop
|
2679
|
+
@forward = vars.pop
|
2680
|
+
@recursive = vars.pop
|
2681
|
+
@defined = vars.pop
|
2682
|
+
super(vars)
|
2683
|
+
end
|
2684
|
+
|
2685
|
+
def instantiate(_context, _enclosure)
|
2686
|
+
_params = {
|
2687
|
+
:forward => @forward
|
2688
|
+
}
|
2689
|
+
_u = super(_context, _enclosure, _params)
|
2690
|
+
_u.set_switchtype(@switchtype.instantiate(_context))
|
2691
|
+
_u.validate_labels
|
2692
|
+
_u.defined = self.is_defined?
|
2693
|
+
_u
|
2694
|
+
end
|
2695
|
+
|
2696
|
+
protected
|
2697
|
+
|
2698
|
+
def walk_members_for_copy(&block)
|
2699
|
+
@children.each { |c| yield(c) }
|
2700
|
+
end
|
2701
|
+
end # Union
|
2702
|
+
|
2703
|
+
class UnionMember < Member
|
2704
|
+
NAMETYPE = :member
|
2705
|
+
attr_reader :labels
|
2706
|
+
def initialize(_name, _enclosure, params)
|
2707
|
+
super(_name, _enclosure, params)
|
2708
|
+
## if any of the labels is 'default' forget about the others
|
2709
|
+
if params[:labels].include?(:default)
|
2710
|
+
@labels = [ :default ]
|
2711
|
+
else
|
2712
|
+
@labels = params[:labels]
|
2713
|
+
end
|
2714
|
+
end
|
2715
|
+
|
2716
|
+
def marshal_dump
|
2717
|
+
super() << @labels
|
2718
|
+
end
|
2719
|
+
|
2720
|
+
def marshal_load(vars)
|
2721
|
+
@labels = vars.pop
|
2722
|
+
super(vars)
|
2723
|
+
end
|
2724
|
+
|
2725
|
+
def instantiate(_context, _enclosure)
|
2726
|
+
_params = {
|
2727
|
+
:labels => @labels.collect { |l| l == :default ? l : l.instantiate(_context) },
|
2728
|
+
}
|
2729
|
+
super(_context, _enclosure, _params)
|
2730
|
+
end
|
2731
|
+
end # UnionMember
|
2732
|
+
|
2733
|
+
class Enum < Leaf
|
2734
|
+
NAMETYPE = :class
|
2735
|
+
attr_reader :idltype
|
2736
|
+
def initialize(_name, _enclosure, params)
|
2737
|
+
super(_name, _enclosure)
|
2738
|
+
@enums = []
|
2739
|
+
@idltype = IDL::Type::Enum.new(self)
|
2740
|
+
end
|
2741
|
+
|
2742
|
+
def marshal_dump
|
2743
|
+
super() << @idltype << @enums
|
2744
|
+
end
|
2745
|
+
|
2746
|
+
def marshal_load(vars)
|
2747
|
+
@enums = vars.pop
|
2748
|
+
@idltype = vars.pop
|
2749
|
+
super(vars)
|
2750
|
+
end
|
2751
|
+
|
2752
|
+
def enumerators
|
2753
|
+
@enums
|
2754
|
+
end
|
2755
|
+
|
2756
|
+
def add_enumerator(n)
|
2757
|
+
@enums << n
|
2758
|
+
end
|
2759
|
+
|
2760
|
+
def instantiate(_context, _enclosure)
|
2761
|
+
super(_context, _enclosure, {})
|
2762
|
+
end
|
2763
|
+
end # Enum
|
2764
|
+
|
2765
|
+
class Enumerator < Leaf
|
2766
|
+
NAMETYPE = :class
|
2767
|
+
attr_reader :idltype, :enum, :value
|
2768
|
+
def initialize(_name, _enclosure, params)
|
2769
|
+
super(_name, _enclosure)
|
2770
|
+
@idltype = IDL::Type::ULong.new
|
2771
|
+
@enum = params[:enum]
|
2772
|
+
@value = params[:value]
|
2773
|
+
@enum.add_enumerator(self)
|
2774
|
+
end
|
2775
|
+
|
2776
|
+
def marshal_dump
|
2777
|
+
super() << @idltype << @enum << @value
|
2778
|
+
end
|
2779
|
+
|
2780
|
+
def marshal_load(vars)
|
2781
|
+
@value = vars.pop
|
2782
|
+
@enum = vars.pop
|
2783
|
+
@idltype = vars.pop
|
2784
|
+
super(vars)
|
2785
|
+
end
|
2786
|
+
|
2787
|
+
def instantiate(_context, _enclosure)
|
2788
|
+
super(_context, _enclosure, { :enum => @enum, :value => @value })
|
2789
|
+
end
|
2790
|
+
end # Enumerator
|
2791
|
+
|
2792
|
+
class Typedef < Leaf
|
2793
|
+
attr_reader :idltype
|
2794
|
+
NAMETYPE = :class
|
2795
|
+
def initialize(_name, _enclosure, params)
|
2796
|
+
super(_name, _enclosure)
|
2797
|
+
@idltype = params[:type]
|
2798
|
+
end
|
2799
|
+
|
2800
|
+
def is_local?(recurstk = [])
|
2801
|
+
@idltype.is_local?(recurstk)
|
2802
|
+
end
|
2803
|
+
|
2804
|
+
def marshal_dump
|
2805
|
+
super() << @idltype
|
2806
|
+
end
|
2807
|
+
|
2808
|
+
def marshal_load(vars)
|
2809
|
+
@idltype = vars.pop
|
2810
|
+
super(vars)
|
2811
|
+
end
|
2812
|
+
|
2813
|
+
def instantiate(_context, _enclosure)
|
2814
|
+
super(_context, _enclosure, { :type => @idltype.instantiate(_context) })
|
2815
|
+
end
|
2816
|
+
end # Typedef
|
2817
|
+
end
|
2818
|
+
|