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.
@@ -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
+