walker.rb

Martin Corino, 06/20/2016 06:49 pm

Download (47 KB)

 
1
#--------------------------------------------------------------------
2
# walker.rb - IDL typecode and client stubs backend walker
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 R2CORBA 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
14
  class RubyWriterBase
15
    def initialize(output = STDOUT, params = {}, indent = "  ")
16
      @output = output
17
      @params = params
18
      @indent = indent
19
      @nest = 0
20
    end
21

    
22
    def print(str);       @output << str; end
23
    def println(str="");  @output << str << "\n"; end
24
    def printi(str="");   @output << indent() << str; end
25
    def printiln(str=""); @output << indent() << str << "\n"; end
26
    def indent()
27
      @indent * @nest
28
    end
29
    def nest(in_ = 1)
30
      @nest += in_
31
      begin
32
        yield
33
      ensure
34
        @nest -= in_
35
      end
36
    end
37

    
38
    def visit_nodes(parser)
39
      pre_visit(parser)
40

    
41
      parser.walk_nodes(self)
42

    
43
      post_visit(parser)
44
    end
45
  end
46

    
47
  class RubyStubWriter < RubyWriterBase
48
    def initialize(output = STDOUT, params = {}, indent = "  ")
49
      super
50
    end
51

    
52
    def pre_visit(parser)
53
      print(
54
%Q{# -*- Ruby -*-
55
#
56
# ****  Code generated by the R2CORBA IDL Compiler ****
57
# R2CORBA has been developed by:
58
#        Remedy IT
59
#        Westervoort, GLD
60
#        The Netherlands
61
#        http://www.remedy.nl
62
#
63
})
64
      println("require 'corba'") if @params[:libinit]
65
      println()
66
      enter_module(parser.root_namespace) unless parser.root_namespace.nil?
67
      idleval = @params[:idl_eval] || false
68
      if !idleval
69
        printiln("CORBA.implement('#{@params[:idlfile]}', {}, CORBA::IDL::CLIENT_STUB) {")
70
        println()
71
      end
72
    end
73

    
74
    def post_visit(parser)
75
      idleval = @params[:idl_eval] || false
76
      if !idleval
77
        printiln("} ## end of '#{@params[:idlfile]}'")
78
      end
79
      leave_module(parser.root_namespace) unless parser.root_namespace.nil?
80
      println("# -*- END -*-")
81
    end
82

    
83
    def visit_include(node)
84
      printiln(format("require '%s'", node.filename.sub(/\.[^\.]*$/,@params[:stub_pfx])))
85
      println()
86
    end
87

    
88
    def enter_include(node)
89
      printiln("## include")
90
      printiln("CORBA.implement('#{node.filename}', {}, CORBA::IDL::CLIENT_STUB) {")
91
      println()
92
    end
93

    
94
    def leave_include(node)
95
      println()
96
      printiln("} ## end of include '#{node.filename}'")
97
      println()
98
    end
99

    
100
    def enter_module(node)
101
      printiln("module " + node.rubyname)
102
      println()
103
      @nest += 1
104
    end
105
    def leave_module(node)
106
      @nest -= 1
107
      printiln("end #of module #{node.rubyname}")
108
      println()
109
    end
110

    
111
    def declare_interface(node)
112
      name = node.rubyname
113
      if not @params[:class_interfaces].nil? and @params[:class_interfaces].include?(name)
114
        printiln("class #{name}; end  ## interface forward")
115
      else
116
        printiln("module #{name}; end  ## interface forward")
117
      end
118
    end
119
    def enter_interface(node)
120
      println
121
      name = node.rubyname
122
      if node.is_pseudo?
123
        if not @params[:class_interfaces].nil? and @params[:class_interfaces].include?(name)
124
          printiln("class #{name}  ## pseudo object interface")
125
        else
126
          printiln("module #{name}  ## pseudo object interface")
127
        end
128
        @nest += 1
129
      else
130
        if not @params[:class_interfaces].nil? and @params[:class_interfaces].include?(name)
131
          printiln("class #{node.rubyname}  ## interface")
132
        else
133
          printiln("module #{node.rubyname}  ## interface")
134
        end
135
        println()
136
        @nest += 1
137

    
138
        if node.bases.size>0
139
          node.bases.each do |n|
140
            printiln("include #{n.scoped_rubyname}")
141
          end
142
          println()
143
        end
144

    
145
        printiln(format("Id = '%s'.freeze", node.repository_id))
146
        printi("Ids = [ Id")
147
        if node.is_abstract?
148
          println(",")
149
          printi("        'IDL:omg.org/CORBA/AbstractBase:1.0'")
150
        end
151
        if node.bases.size>0
152
          node.bases.each do |n|
153
            println(",")
154
            printi("        #{n.scoped_rubyname}::Id")
155
          end
156
        end
157
        println(" ].freeze")
158

    
159
        println
160
        unless node.is_abstract?
161
          printiln(format("def %s._tc; @@tc_%s ||= CORBA::TypeCode::ObjectRef.new(Id, '%s', self); end",
162
                          node.rubyname, node.rubyname, node.rubyname))
163
        else
164
          printiln(format("def %s._tc; @@tc_%s ||= CORBA::TypeCode::AbstractInterface.new(Id, '%s', self); end",
165
                          node.rubyname, node.rubyname, node.rubyname))
166
        end
167
        printiln("self._tc  # register typecode");
168

    
169
        println
170
        printiln("def #{name}._narrow(obj)")
171
        nest {
172
          printiln('return nil if CORBA.is_nil(obj)')
173
          if node.is_local?
174
            printiln("return CORBA::Stub.create_stub(obj)._unchecked_narrow!(self)")
175
          else
176
            printiln("return CORBA::Stub.create_stub(obj)._narrow!(self)")
177
          end
178
        }
179
        printiln("end")
180
        println
181
        printiln("def #{name}._duplicate(obj)")
182
        nest {
183
          if node.is_local?
184
            printiln("obj");
185
          else
186
            printiln('return nil if CORBA.is_nil(obj)')
187
            printiln("return CORBA::Stub.create_stub(super(obj))._narrow!(self)")
188
          end
189
        }
190
        printiln("end")
191
        println
192
        printiln("def _interface_repository_id")
193
        nest {
194
          printiln("#{node.scoped_rubyname}::Id")
195
        }
196
        printiln("end")
197
      end
198
      println
199
    end
200
    def leave_interface(node)
201
      name = node.rubyname
202
      @nest -= 1
203
      printiln("end #of interface #{name}")
204
      println
205
    end
206

    
207
    private
208
    def print_valuetype_typecode(node)
209
      if node.is_a?(IDL::AST::Eventtype)
210
        println("CORBA::TypeCode::Eventtype.new('#{node.repository_id}'.freeze, '#{node.rubyname}',")
211
      else
212
        println("CORBA::TypeCode::Valuetype.new('#{node.repository_id}'.freeze, '#{node.rubyname}',")
213
      end
214
      nest(3) {
215
        printi(":#{node.modifier}, ")
216
        if node.has_concrete_base?
217
          print("#{node.bases.first.rubyname}._tc")
218
        else
219
          print('nil')
220
        end
221
        state_members_ = node.state_members
222
        unless state_members_.empty?
223
          pfx = "["
224
          state_members_.each do |m|
225
            println(",")
226
            printi(pfx)
227
            pfx = ""
228
            if m.has_incomplete_type?
229
              print("['#{m.rubyname}', ")
230
              print_valuetype_typecode(m.idltype.resolved_type.node)
231
              print(", :#{m.visibility}]")
232
            elsif m.is_recursive?
233
              print("['#{m.rubyname}', ")
234
              print("CORBA::TypeCode::Recursive.new('#{m.idltype.resolved_type.node.repository_id}')")
235
              print(", :#{m.visibility}]")
236
            else
237
              print(format("['%s', %s, :%s]", m.rubyname, get_typecode(m.idltype), m.visibility))
238
            end
239
          end
240
          print("], self)")
241
        else
242
          print(", self)")
243
        end
244
      }
245
    end
246

    
247
    public
248

    
249
    def declare_valuetype(node)
250
    end
251
    def enter_valuetype(node)
252
      println()
253
      name = node.rubyname
254
      unless node.is_abstract?
255
        printiln("class #{name}")
256
      else
257
        printiln("module #{name}")
258
      end
259
      @nest += 1
260

    
261
      unless node.is_abstract?
262
        if node.is_custom?
263
          printiln("include CORBA::Portable::CustomValueBase")
264
        else
265
          printiln("include CORBA::ValueBase")
266
        end
267
      else
268
        printiln("include CORBA::AbstractValueBase")
269
      end
270

    
271
      unless node.is_abstract?
272
        trunc_ids = node.truncatable_ids
273
        println()
274
        printi('TRUNCATABLE_IDS = [')
275
        print("'#{trunc_ids.shift}'")
276
        unless trunc_ids.empty?
277
          nest {
278
            trunc_ids.each do |trunc_id|
279
              println(",")
280
              printi("'#{trunc_id}'")
281
            end
282
          }
283
        end
284
        println(" ].freeze")
285
      end
286

    
287
      println()
288
      printiln(format("def %s._tc", node.rubyname))
289
      nest {
290
        printi("@@tc_#{node.rubyname} ||= ")
291
        print_valuetype_typecode(node)
292
        println()
293
      }
294
      printiln("end")
295
      printiln("self._tc  # register typecode")
296
    end
297

    
298
    def leave_valuetype(node)
299
      println()
300
      printiln("module Intf")
301
      nest {
302
        intfs_ = node.interfaces
303
        unless intfs_.empty?
304
          printiln('## supported interfaces')
305
          intfs_.each do |intf|
306
            printiln("include #{intf.scoped_rubyname}")
307
          end
308
          printiln("undef :_interface_repository_id")
309
        end
310

    
311
        bases_ = Array.new(node.bases)
312
        if node.has_concrete_base?
313
          printiln('## concrete base type')
314
          printiln("include #{bases_.shift.scoped_rubyname}::Intf")
315
        end
316
        unless bases_.empty?
317
          printiln('## abstract base types')
318
          bases_.each do |base|
319
            printiln("include #{base.scoped_rubyname}::Intf")
320
          end
321
        end
322

    
323
        if node.has_concrete_base?() || !bases_.empty?() || !intfs_.empty?()
324
          println
325
        end
326

    
327
        intf_members_ = node.interface_members
328
        [IDL::AST::Operation, IDL::AST::Attribute].each do |m_type|
329
          has_type = false
330
          intf_members_.each do |m|
331
            if m.is_a?(m_type)
332
              if m.is_a?(IDL::AST::Operation)
333
                printi('## operations') unless has_type
334
                visit_operation(m)
335
                has_type = true
336
              else
337
                printi('## attributes') unless has_type
338
                visit_attribute(m)
339
                has_type = true
340
              end
341
            end
342
          end
343
          println() if has_type
344
        end
345

    
346
        unless node.is_abstract?
347
          state_members_ = node.state_members
348
          has_type = false
349
          state_members_.each do |m|
350
            if m.visibility == :public
351
              printiln('## public value state') unless has_type
352
              printiln(format("attr_accessor :%s", m.rubyname))
353
              has_type = true
354
            end
355
          end
356
          println() if has_type
357
          has_type = false
358
          state_members_.each do |m|
359
            unless m.visibility == :public
360
              unless has_type
361
                printiln('## private value state')
362
                printiln('protected')
363
              end
364
              printiln(format("attr_accessor :%s", m.rubyname))
365
              has_type = true
366
            end
367
          end
368
          println() if has_type
369

    
370
          printiln('public')
371
          println()
372

    
373
          unless node.is_custom?
374
            printiln('def self.marshal(vt, __os__)')
375
            nest {
376
              printiln("#{node.bases.first.scoped_rubyname}::Intf.marshal(vt, __os__)") if node.has_concrete_base?
377
              unless state_members_.empty?
378
                printiln('vt._marshal_with(__os__) do')
379
                nest {
380
                  state_members_.each_with_index do |m, i|
381
                    printiln("__os__.write_member(#{node.scoped_rubyname}._tc.member_type(#{i}),")
382
                    printiln("                    self.#{m.rubyname})")
383
                  end
384
                }
385
                printiln('end')
386
              end
387
            }
388
            printiln('end')
389
            println()
390

    
391
            printiln('def self.unmarshal(vt, __is__)')
392
            nest {
393
              printiln("#{node.bases.first.scoped_rubyname}::Intf.unmarshal(vt, __is__)") if node.has_concrete_base?
394
              unless state_members_.empty?
395
                printiln('vt._unmarshal_with(__is__) do')
396
                nest {
397
                  state_members_.each_with_index do |m, i|
398
                    printi("self.#{m.rubyname} = ")
399
                    println("__is__.read_member(#{node.scoped_rubyname}._tc.member_type(#{i}))")
400
                  end
401
                }
402
                printiln('end')
403
              end
404
            }
405
            printiln('end')
406
            println()
407

    
408
            printiln('def marshal(os)')
409
            nest {
410
              printiln("#{node.scoped_rubyname}::Intf.marshal(self, os)")
411
            }
412
            printiln('end')
413
            println()
414

    
415
            printiln('def unmarshal(is)')
416
            nest {
417
              printiln("#{node.scoped_rubyname}::Intf.unmarshal(self, is)")
418
            }
419
            printiln('end')
420
            println()
421
          end
422
        end
423
      }
424
      printiln('end # of Intf')
425
      println
426
      printiln('include Intf')
427
      println
428

    
429
      @nest -= 1
430
      if node.is_a?(IDL::AST::Eventtype)
431
        printiln("end #of eventtype #{node.rubyname}")
432
      else
433
        printiln("end #of valuetype #{node.rubyname}")
434
      end
435

    
436
      unless node.is_abstract?
437
        println
438
        initializers = node.initializers
439
        printiln("class #{node.rubyname}Factory < CORBA::Portable::ValueFactoryBase")
440
        nest {
441
          printiln("VALUE_ID = '#{node.repository_id}'.freeze")
442
          if initializers.empty?
443
            unless node.has_operations_or_attributes?(false)
444
              # valuetype has only state, create the default factory
445
              printiln("def _create_default")
446
              nest {
447
                printiln("#{node.scoped_rubyname}.new")
448
              }
449
              printiln("end")
450
            end
451
          else
452
            println()
453
            initializers.each do |init|
454
              printiln("def #{init.rubyname}(#{init.params().collect {|p| p.rubyname}.join(',')})")
455
              nest {
456
                printiln("raise RuntimeError, 'unimplemented local operation called'")
457
              }
458
              printiln("end")
459
            end
460
          end
461
        }
462
        printiln("end # of #{node.rubyname}Factory")
463
      end
464
    end
465

    
466
    def visit_valuebox(node)
467
      println
468
      name = node.rubyname
469
      printiln("class #{name}")
470
      nest {
471
        printiln('include CORBA::Portable::BoxedValueBase')
472
        println()
473
        printiln("TRUNCATABLE_IDS = [ '#{node.repository_id}' ].freeze")
474
        println()
475
        printiln(format("def %s._tc", node.rubyname))
476
        nest {
477
          printiln(format("@@tc_%s ||= CORBA::TypeCode::Valuebox.new('%s'.freeze, '%s',",
478
                          node.rubyname, node.repository_id, node.rubyname))
479
          printiln("   #{get_typecode(node.boxed_type)}, self)")
480
        }
481
        printiln("end")
482
        printiln("self._tc  # register typecode");
483
        printiln("attr_accessor :value")
484
        printiln("def initialize(val = nil); @value = val; end")
485
      }
486
      printiln("end #of valuebox #{name}")
487
      println
488
    end
489

    
490
    def visit_const(node)
491
      #v = Expression::Value.new(node.idltype, node.value)
492
      s = node.rubyname + " = " + expression_to_s(node.expression)
493
      printiln(s)
494
    end
495

    
496
    def visit_operation(node, from_valuetype=false)
497
      _parm = node.params
498
      _in = node.in_params
499
      _out = node.out_params
500
      _intf = node.enclosure
501

    
502
      println()
503
      printi("def #{node.rubyname}(")
504
      print( _in.collect{ |p| p.rubyname }.join(", ") )
505
      if node.oneway
506
        println(")    # oneway")
507
      else
508
        println(")")
509
      end
510

    
511
      nest do
512
        if _intf.is_a?(IDL::AST::Valuetype) or from_valuetype
513
          printiln("raise RuntimeError, 'unimplemented local operation called'")
514
        elsif _intf.is_local?
515
          printiln("raise ::CORBA::NO_IMPLEMENT.new(")
516
          printiln("         'unimplemented operation on local interface',")
517
          printiln("         1, ::CORBA::COMPLETED_NO)")
518
        else
519
          ## check if this is a proper object reference
520
          printiln('raise ::CORBA::NO_IMPLEMENT unless self.respond_to?(:_invoke, true)')
521

    
522
          ##  validate data for IN/INOUT args
523
          ##
524
          if _parm.size>0
525
            _parm.each do |p|
526
              if p.attribute != IDL::AST::Parameter::OUT
527
                printiln("#{p.rubyname} = #{get_typecode(p.idltype)}.validate(#{p.rubyname})")
528
              end
529
            end
530
          end
531

    
532
          ##  invoke operation
533
          ##
534
          if not node.oneway
535
            printi("_ret = self._invoke('#{node.name}', {")
536
          else
537
            printi("self._invoke('#{node.name}', {")
538
          end
539

    
540
          newln = ""
541
          if _parm.size>0
542
            println(newln)
543
            nest do
544
              printi(":arg_list => [")
545
              nest {
546
                pfx = ""
547
                _parm.each do |p|
548
                  println(pfx)
549
                  printi("['#{p.rubyname}', #{get_arg_type(p.attribute)}, ");
550
                  print(get_typecode(p.idltype))
551
                  if p.attribute != IDL::AST::Parameter::OUT
552
                    print(", #{p.rubyname}]")
553
                  else
554
                    print("]")
555
                  end
556
                  pfx = ","
557
                end
558
                print("]")
559
              }
560
            end
561
            newln = ","
562
          end
563

    
564
          if not node.oneway
565
            println(newln)
566
            nest { printi(":result_type => #{get_typecode(node.idltype)}") }
567
            newln = ","
568
          end
569

    
570
          if node.raises.size>0
571
            println(newln)
572
            nest {
573
              printi(":exc_list => [")
574
              pfx = ""
575
              nest {
576
                node.raises.each { |ex|
577
                  println(pfx)
578
                  pfx = ","
579
                  printi(get_typecode(ex))
580
                }
581
                print("]")
582
              }
583
            }
584
          end
585

    
586
          println("})")
587

    
588
          if not node.oneway
589
            returns_void = (node.idltype.is_a? Type::Void)
590
            size = _out.size
591
            size += 1 unless returns_void
592
            printiln('_ret')
593
          end
594
        end
595
      end
596

    
597
      printiln("end #of operation #{node.rubyname}")
598
    end
599

    
600
    def visit_attribute(node, from_valuetype=false)
601
      _intf = node.enclosure
602
      println()
603
      printiln("def #{node.rubyname}()")
604
      nest do
605
        if _intf.is_a?(IDL::AST::Valuetype) or from_valuetype
606
          printiln("@#{node.name}")
607
        elsif _intf.is_local?
608
          printiln("raise ::CORBA::NO_IMPLEMENT.new(")
609
          printiln("         'unimplemented attribute on local interface',")
610
          printiln("         1, ::CORBA::COMPLETED_NO)")
611
        else
612
          ## check if this is a proper object reference
613
          printiln('raise ::CORBA::NO_IMPLEMENT unless self.respond_to?(:_invoke, true)')
614

    
615
          printiln("_ret = self._invoke('_get_#{node.name}', {")
616
          nest { printi(":result_type => #{get_typecode(node.idltype)}") }
617
          if node.get_raises.size>0
618
            println(',')
619
            nest {
620
              printi(":exc_list => [")
621
              pfx = ""
622
              nest {
623
                node.get_raises.each { |ex|
624
                  println(pfx)
625
                  pfx = ","
626
                  printi(get_typecode(ex))
627
                }
628
                print("]")
629
              }
630
            }
631
          end
632
          println("})")
633

    
634
          printiln('_ret')
635
        end
636
      end
637
      printiln("end #of attribute #{node.name} getter")
638
      if not node.readonly
639
        printiln("def #{node.rubyname}=(val)")
640
        nest do
641
          if _intf.is_a?(IDL::AST::Valuetype) or from_valuetype
642
            printiln("@#{node.name} = val")
643
          elsif _intf.is_local?
644
            printiln("raise ::CORBA::NO_IMPLEMENT.new(")
645
            printiln("         'unimplemented attribute on local interface',")
646
            printiln("         1, ::CORBA::COMPLETED_NO)")
647
          else
648
            ## check if this is a proper object reference
649
            printiln('raise ::CORBA::NO_IMPLEMENT unless self.respond_to?(:_invoke, true)')
650

    
651
            ## validate IN arg
652
            printiln("val = #{get_typecode(node.idltype)}.validate(val)")
653
            ## invoke operation
654
            printiln("self._invoke('_set_#{node.name}', {")
655
            nest {
656
              printiln(":arg_list => [")
657
              nest {
658
                printiln("['val', CORBA::ARG_IN, #{get_typecode(node.idltype)}, val]],");
659
              }
660
              printi(":result_type => CORBA._tc_void")
661
              if node.set_raises.size>0
662
                println(',')
663
                printi(":exc_list => [")
664
                pfx = ""
665
                nest {
666
                  node.set_raises.each { |ex|
667
                    println(pfx)
668
                    pfx = ","
669
                    printi(get_typecode(ex))
670
                  }
671
                  print("]")
672
                }
673
              end
674
              println("})")
675
            }
676
          end
677
        end
678
        printiln("end #of attribute #{node.name} setter")
679
      end
680
    end
681

    
682
    def get_typecode(_type)
683
      case _type
684
      when Type::Octet,
685
           Type::UShort, Type::Short,
686
           Type::ULong, Type::Long,
687
           Type::ULongLong, Type::LongLong,
688
           Type::Boolean, Type::Char, Type::WChar,
689
           Type::Float, Type::Double, Type::LongDouble,
690
           Type::Void, Type::Any
691
        s = _type.class.name.split("::") # IDL::Type::Octet -> [IDL, Type, Octet]
692
        s = s[s.length - 1]
693
        s.downcase!
694
        format("CORBA._tc_%s",s)
695

    
696
      when Type::Object
697
        "CORBA._tc_Object"
698

    
699
      when Type::String
700
        if not _type.length.nil?
701
          format("CORBA::TypeCode::String.new(%d)", _type.length)
702
        else
703
          "CORBA._tc_string"
704
        end
705

    
706
      when Type::WString
707
        if not _type.length.nil?
708
          format("CORBA::TypeCode::WString.new(%d)", _type.length)
709
        else
710
          "CORBA._tc_wstring"
711
        end
712

    
713
      when Type::ScopedName
714
        scoped_type = _type.node.idltype
715
        if scoped_type.is_a?(IDL::Type::Interface) && scoped_type.node.is_forward?()
716
          node = scoped_type.node
717
          "(CORBA::TypeCode.typecode_for_id('#{node.repository_id}') || "+
718
            "CORBA::TypeCode::ObjectRef.new('#{node.repository_id}', '#{node.rubyname}', #{node.scoped_rubyname}))"
719
        else
720
          _type.node.scoped_rubyname + '._tc'
721
        end
722

    
723
      when Type::Array
724
        sep = ""
725
        tc = "CORBA::TypeCode::Array.new(" +
726
            get_typecode(_type.basetype) + ", "
727
        _type.sizes.each do |sz|
728
          tc += "#{sep}#{sz.to_s}"
729
          sep = ", "
730
        end
731
        tc + ")"
732

    
733
      when Type::Sequence
734
        if _type.is_recursive?
735
          "CORBA::TypeCode::Sequence.new(CORBA::TypeCode::Recursive.new('#{_type.basetype.resolved_type.node.repository_id}'))"
736
        else
737
          "CORBA::TypeCode::Sequence.new(" +
738
                get_typecode(_type.basetype) +
739
                if not _type.length.nil? then format(", %d)", _type.length) else ")" end
740
        end
741

    
742
      else
743
        raise RuntimeError, "invalid type for (un)marshalling: #{_type.typename}"
744
      end
745
    end
746

    
747
    def get_arg_type(_idl_argtype)
748
      case _idl_argtype
749
      when IDL::AST::Parameter::IN
750
        "CORBA::ARG_IN"
751
      when IDL::AST::Parameter::OUT
752
        "CORBA::ARG_OUT"
753
      else
754
        "CORBA::ARG_INOUT"
755
      end
756
    end
757

    
758
    def expression_to_s(exp)
759
      case exp
760
      when Expression::Value
761
        value_to_s(exp)
762
      when Expression::Operation
763
        operation_to_s(exp)
764
      when Expression::ScopedName, Expression::Enumerator
765
        exp.node.scoped_rubyname
766
      else
767
        raise RuntimeError, "unknown expression type: #{exp.class.name}"
768
      end
769
    end
770

    
771
    def value_to_s(exp)
772
      s = nil
773
      v = exp.value
774
      case exp.idltype
775
      when Type::Void
776
        s = "nil"
777
      when Type::Char
778
        s = "'#{v.chr}'"
779
      when Type::Integer,
780
        Type::Boolean,
781
        Type::Octet,
782
        Type::Float
783
        s = v.to_s
784
      when Type::WChar
785
        s = (case v.first
786
        when :char, :esc_ch
787
          v.last.unpack('c')
788
        when :esc
789
          IDL::Scanner::ESCTBL[v.last]
790
        when :oct
791
          v.last.oct
792
        when :hex2, :hex4
793
          v.last.hex
794
        else
795
          0
796
        end).to_s
797
      when Type::Enum
798
        v = exp.idltype.narrow(v)
799
        s = exp.idltype.node.enumerators[v].scoped_rubyname
800
      when Type::String
801
        s = "'#{v.to_s}'"
802
      when Type::WString
803
        v = (v.collect do |(elt, elv)|
804
          case elt
805
          when :char, :esc_ch
806
            elv.unpack('c')
807
          when :esc
808
            IDL::Scanner::ESCTBL[elv]
809
          when :oct
810
            elv.oct
811
          when :hex2, :hex4
812
            elv.hex
813
          else
814
            nil
815
          end
816
        end).compact
817
        s = "[#{v.join(',')}]"
818
      #when Type::Fixed
819
      #when Type::Any
820
      #when Type::Object
821
      when Type::ScopedName
822
        s = value_to_s(Expression::Value.new(exp.idltype.node.idltype, v))
823
      else
824
        raise RuntimeError, "#{exp.typename}'s not been supported yet."
825
      end
826
      s
827
    end
828

    
829
    def operation_to_s(exp)
830
      s = nil
831
      op = exp.operands
832
      case exp
833
      when Expression::Operation::UnaryPlus
834
        s = expression_to_s(op[0])
835
      when Expression::Operation::UnaryMinus
836
        s = "-" + expression_to_s(op[0])
837
      when Expression::Operation::UnaryNot
838
        s = "~" + expression_to_s(op[0])
839
      when Expression::Operation::Or
840
        s = expression_to_s(op[0]) + " | " + expression_to_s(op[1])
841
      when Expression::Operation::And
842
        s = expression_to_s(op[0]) + " & " + expression_to_s(op[1])
843
      when Expression::Operation::LShift
844
        s = expression_to_s(op[0]) + " << " + expression_to_s(op[1])
845
      when Expression::Operation::RShift
846
        s = expression_to_s(op[0]) + " >> " + expression_to_s(op[1])
847
      when Expression::Operation::Add
848
        s = expression_to_s(op[0]) + " + " + expression_to_s(op[1])
849
      when Expression::Operation::Minus
850
        s = expression_to_s(op[0]) + " - " + expression_to_s(op[1])
851
      when Expression::Operation::Mult
852
        s = expression_to_s(op[0]) + " * " + expression_to_s(op[1])
853
      when Expression::Operation::Div
854
        s = expression_to_s(op[0]) + " / " + expression_to_s(op[1])
855
      when Expression::Operation::Mod
856
        s = expression_to_s(op[0]) + " % " + expression_to_s(op[1])
857
      else
858
        raise RuntimeError, "unknown operation: #{exp.type.name}"
859
      end
860
      "(" + s + ")"
861
    end
862

    
863
    def declare_struct(node)
864
    end
865
    def enter_struct(node)
866
      println()
867
      name = node.rubyname
868
      printiln("class #{name} < CORBA::Portable::Struct")
869
      @nest += 1
870
    end
871
    def leave_struct(node)
872
      tc_ = if node.is_a? IDL::AST::Exception then "Except" else "Struct" end
873
      println()
874
      printiln(format("def %s._tc", node.rubyname))
875
      struct_members_ = node.members
876
      nest {
877
        printi(format("@@tc_%s ||= CORBA::TypeCode::%s.new('%s'.freeze, '%s'",
878
                      node.rubyname, tc_, node.repository_id, node.rubyname))
879
        unless struct_members_.empty?
880
          pfx = "   ["
881
          struct_members_.each do |m|
882
            println(",")
883
            printi(pfx)
884
            pfx = "    "
885
            print(format("['%s', %s]", m.rubyname, get_typecode(m.idltype)))
886
          end
887
          println("], self)")
888
        else
889
          println(", self)")
890
        end
891
      }
892
      printiln("end")
893
      printiln("self._tc  # register typecode");
894
      struct_members_.each do |m|
895
        printiln(format("attr_accessor :%s", m.rubyname))
896
      end
897

    
898
      if struct_members_.size>0
899
        printiln('def initialize(*param_)')
900
        nest {
901
          struct_members_.each do |m|
902
            printiln("@#{m.rubyname} = param_.shift")
903
          end
904
        }
905
        printiln('end')
906
        println()
907
      end
908

    
909
      name = node.rubyname
910
      @nest -= 1
911
      printiln("end #of #{if node.is_a? IDL::AST::Exception then "exception" else "struct" end} #{name}")
912
    end
913

    
914
    def enter_exception(node)
915
      println()
916
      name = node.rubyname
917
      printiln("class #{name} < CORBA::UserException")
918
      @nest += 1
919
    end
920
    def leave_exception(node)
921
      leave_struct(node)
922
    end
923

    
924
    def declare_union(node)
925
    end
926
    def enter_union(node)
927
      println()
928
      name = node.rubyname
929
      printiln("class #{name} < CORBA::Portable::Union")
930
      @nest += 1
931
    end
932
    def leave_union(node)
933
      println()
934
      printiln(format("def %s._tc", node.rubyname))
935
      nest {
936
        printiln(format("@@tc_%s ||= CORBA::TypeCode::Union.new('%s'.freeze, '%s',",
937
                      node.rubyname, node.repository_id, node.rubyname))
938
        printi("    #{get_typecode(node.switchtype)}")
939
        if node.members.size>0
940
          pfx = "   ["
941
          node.members.each do |m|
942
            m.labels.each do |lbl|
943
              println(",")
944
              printi(pfx)
945
              pfx = "    "
946
              labeltxt = if lbl == :default then ':default'; else expression_to_s(lbl); end
947
              print(format("[%s, '%s', %s]", labeltxt, m.rubyname, get_typecode(m.idltype)))
948
            end
949
          end
950
          print("], self")
951
        else
952
          print(", self")
953
        end
954
        if (!node.has_default?) && node.default_label # has implicit default?
955
          println(", #{expression_to_s(node.default_label)})")
956
        else
957
          println(')')
958
        end
959
      }
960
      printiln("end")
961
      printiln("self._tc  # register typecode");
962
      ix = 0
963
      if node.members.size>0
964
        node.members.each do |m|
965
          printiln(format("def %s; @value; end", m.rubyname))
966
          printiln(format("def %s=(val); _set_value(%d, val); end", m.rubyname, ix))
967
          ix += m.labels.size
968
        end
969
      end
970

    
971
      if (!node.has_default?) && node.default_label # has implicit default?
972
        def_label = expression_to_s(node.default_label)
973
        printiln("def _default; @discriminator = #{def_label}; @value = nil; end")
974
      end
975

    
976
      name = node.rubyname
977
      @nest -= 1
978
      printiln("end #of union #{name}")
979
    end
980

    
981
    def visit_enum(node)
982
      printiln(format("class %s < ::Fixnum", node.rubyname))
983
      nest {
984
        printiln(format("def %s._tc", node.rubyname))
985
        nest {
986
          printi(format("@@tc_%s ||= CORBA::TypeCode::Enum.new('%s'.freeze, '%s', [",
987
                        node.rubyname, node.repository_id, node.rubyname))
988
          pfx = ""
989
          node.enumerators.each { |e|
990
            println(pfx)
991
            pfx = ","
992
            printi("    '#{e.rubyname}'")
993
          }
994
          println("])")
995
        }
996
        printiln("end")
997
        printiln("self._tc  # register typecode");
998
      }
999
      printiln(format("end # enum %s", node.rubyname))
1000
    end
1001

    
1002
    def visit_enumerator(node)
1003
      v = Expression::Value.new(node.idltype, node.value)
1004
      s = node.rubyname + " = " + expression_to_s(v)
1005
      printiln(s)
1006
    end
1007

    
1008
    def visit_typedef(node)
1009
      #tc_ = node.enclosure.rubyname + '._tc_' + node.rubyname
1010
      #typ_ = node.enclosure.rubyname + '.' + node.rubyname
1011
      case t = node.idltype
1012
      when Type::ScopedName
1013
        if Type::Interface === t.resolved_type
1014
          printiln(format("%s = %s # typedef %s", node.rubyname, t.node.scoped_rubyname, node.rubyname))
1015
        else
1016
          printiln(format("class %s < %s", node.rubyname, t.node.scoped_rubyname))
1017
          nest {
1018
            printi(format("def %s._tc; ", node.rubyname))
1019
            print(format("@@tc_%s ||= CORBA::TypeCode::Alias.new('%s', '%s',", node.rubyname, node.repository_id, node.rubyname))
1020
            println(format("%s, self); end", get_typecode(t)))
1021
          }
1022
          printiln(format("end # typedef %s", node.rubyname))
1023
        end
1024

    
1025
      when IDL::Type::Native
1026
        printiln("class #{node.rubyname}; end  ## 'native' type");
1027

    
1028
      when Type::Any, Type::Octet,
1029
          Type::UShort, Type::Short,
1030
          Type::ULong, Type::Long,
1031
          Type::ULongLong, Type::LongLong,
1032
          Type::Boolean, Type::Char, Type::WChar,
1033
          Type::Float, Type::Double, Type::LongDouble
1034
        s = t.class.name.split("::") # IDL::Type::Octet -> [IDL, Type, Octet]
1035
        s = s[s.length - 1]
1036
        s.downcase!
1037
        printiln(format("class %s < CORBA::_tc_%s.get_type", node.rubyname, s))
1038
        nest {
1039
          printiln(format("def %s._tc; @@tc_%s ||= CORBA::TypeCode::Alias.new('%s', '%s', CORBA::_tc_%s, self); end",
1040
                          node.rubyname, node.rubyname, node.repository_id, node.rubyname, s))
1041
        }
1042
        printiln(format("end # typedef %s", node.rubyname))
1043

    
1044
      when Type::String
1045
        printiln(format("class %s < String", node.rubyname))
1046
        nest {
1047
          if not t.length.nil?
1048
            printiln(format("def %s._tc; @@tc_%s ||= CORBA::TypeCode::Alias.new('%s', '%s', CORBA::TypeCode::String.new(%d), self); end",
1049
                            node.rubyname, node.rubyname, node.repository_id, node.rubyname, t.length))
1050
          else
1051
            printiln(format("def %s._tc; @@tc_%s ||= CORBA::TypeCode::Alias.new('%s', '%s', CORBA::_tc_string, self); end",
1052
                            node.rubyname, node.rubyname, node.repository_id, node.rubyname))
1053
          end
1054
        }
1055
        printiln(format("end # typedef %s", node.rubyname))
1056

    
1057
      when Type::WString
1058
        printiln(format("class %s < Array", node.rubyname))
1059
        nest {
1060
          if not t.length.nil?
1061
            printiln(format("def %s._tc; @@tc_%s ||= CORBA::TypeCode::Alias.new('%s', '%s', CORBA::TypeCode::WString.new(%d), self); end",
1062
                            node.rubyname, node.rubyname, node.repository_id, node.rubyname, t.length))
1063
          else
1064
            printiln(format("def %s._tc; @@tc_%s ||= CORBA::TypeCode::Alias.new('%s', '%s', CORBA::_tc_wstring, self); end",
1065
                            node.rubyname, node.rubyname, node.repository_id, node.rubyname))
1066
          end
1067
        }
1068
        printiln(format("end # typedef %s", node.rubyname))
1069

    
1070
      when IDL::Type::Array
1071
        printiln(format("class %s < Array", node.rubyname))
1072
        nest {
1073
          printiln(format("def %s._tc", node.rubyname))
1074
          nest {
1075
            printiln(format("@@tc_%s ||= CORBA::TypeCode::Alias.new('%s', '%s',", node.rubyname, node.repository_id, node.rubyname))
1076
            nest { printiln(format("%s, self)", get_typecode(t))) }
1077
          }
1078
          printiln("end")
1079
        }
1080
        printiln(format("end # typedef %s", node.rubyname))
1081

    
1082
      when IDL::Type::Sequence
1083
        case t.basetype.resolved_type
1084
        when IDL::Type::Char, IDL::Type::Octet
1085
          printiln(format("class %s < String", node.rubyname))
1086
        else
1087
          printiln(format("class %s < Array", node.rubyname))
1088
        end
1089
        nest {
1090
          printiln(format("def %s._tc", node.rubyname))
1091
          nest {
1092
            printiln(format("@@tc_%s ||= CORBA::TypeCode::Alias.new('%s', '%s',", node.rubyname, node.repository_id, node.rubyname))
1093
            nest { printiln(format("%s, self)", get_typecode(t))) }
1094
          }
1095
          printiln("end")
1096
        }
1097
        printiln(format("end # typedef %s", node.rubyname))
1098

    
1099
      when IDL::Type::Object
1100
        printiln(format("%s = CORBA::Object # typedef %s\n", node.rubyname, node.rubyname))
1101

    
1102
      else
1103
        raise RuntimeError, "unsupported typedef for #{t.class.name}."
1104
      end
1105
    end
1106
  end ## RubyStubWriter
1107

    
1108
  class RubyServantWriter < RubyWriterBase
1109
    def initialize(output = STDOUT, params = {}, indent = "  ")
1110
      super
1111
      @stub_root = '::'
1112
    end
1113

    
1114
    def pre_visit(parser)
1115
      print(
1116
%Q{# -*- Ruby -*-
1117
#
1118
# ****  Code generated by the R2CORBA IDL Compiler ****
1119
# R2CORBA has been developed by:
1120
#        Remedy IT
1121
#        Westervoort, GLD
1122
#        The Netherlands
1123
#        http://www.remedy.nl
1124
#
1125
})
1126
      idleval = @params[:idl_eval] || false
1127
      println("require 'corba/poa.rb'") if @params[:libinit]
1128
      if !@params[:expand_includes]
1129
        println("require '"+@params[:idlfile].sub(/\.[^\.]*$/,@params[:stub_pfx])+"'")
1130
      end
1131
      println()
1132
      printiln("module POA")
1133
      @nest += 1
1134
      if !idleval
1135
        printiln("CORBA.implement('#{@params[:idlfile]}', {}, CORBA::IDL::SERVANT_INTF) {")
1136
        println()
1137
      end
1138
      ## register explicit (*not* IDL derived) rootnamespace used for client stubs
1139
      @stub_root = "#{parser.root_namespace.rubyname}::" unless parser.root_namespace.nil?
1140
    end
1141

    
1142
    def post_visit(parser)
1143
      idleval = @params[:idl_eval] || false
1144
      if !idleval
1145
        printiln("} ## end of '#{@params[:idlfile]}'")
1146
      end
1147
      @nest -= 1
1148
      printiln("end #of module POA")
1149
      println("# -*- END -*-")
1150
    end
1151

    
1152
    def visit_include(node)
1153
      printiln(format("require '%s'", node.filename.sub(/\.[^\.]*$/,@params[:srv_pfx])))
1154
      println()
1155
    end
1156

    
1157
    def enter_include(node)
1158
      printiln("## include")
1159
      printiln("CORBA.implement('#{node.filename}', {}, CORBA::IDL::SERVANT_INTF) {")
1160
      println()
1161
    end
1162

    
1163
    def leave_include(node)
1164
      println()
1165
      printiln("} ## end of include '#{node.filename}'")
1166
      println()
1167
    end
1168

    
1169
    def enter_module(node)
1170
      printiln("module " + node.rubyname)
1171
      println()
1172
      @nest += 1
1173
    end
1174
    def leave_module(node)
1175
      @nest -= 1
1176
      printiln("end #of module #{node.rubyname}")
1177
      println()
1178
    end
1179

    
1180
    def declare_interface(node)
1181
      printiln("class #{node.rubyname} < PortableServer::Servant; end  ## servant forward")
1182
    end
1183
    def enter_interface(node)
1184
      if !node.is_local?
1185
        println
1186
        printiln("class #{node.rubyname} < PortableServer::Servant ## servant")
1187
        println()
1188
        @nest += 1
1189

    
1190
        printiln("module Intf")
1191
        @nest += 1
1192
        printiln(format("Id = '%s'.freeze", node.repository_id))
1193
        printi("Ids = [ Id")
1194
        if node.is_abstract?
1195
          print(", 'IDL:omg.org/CORBA/AbstractBase:1.0'")
1196
        end
1197
        println(' ]')
1198
        printiln("Operations = {}")
1199
        println()
1200
      end
1201
    end
1202
    def leave_interface(node)
1203
      if !node.is_local?
1204
        name = node.rubyname
1205

    
1206
        @nest -= 1
1207
        printiln("end #of Intf")
1208

    
1209
        println()
1210
        printiln("Id = Intf::Id")
1211
        println()
1212

    
1213
        if node.bases.size>0
1214
          node.bases.each do |n|
1215
            printiln("include_interface(#{n.scoped_rubyname}::Intf)")
1216
          end
1217
        else
1218
          printiln("include_interface(PortableServer::Servant::Intf)")
1219
        end
1220
        println()
1221

    
1222
        printiln("include Intf")
1223
        println()
1224

    
1225
        printiln("def _this; #{@stub_root}#{node.scoped_rubyname}._narrow(super); end")
1226

    
1227
        @nest -= 1
1228
        printiln("end #of servant #{name}")
1229
      end
1230
    end
1231

    
1232
    def declare_valuetype(node)
1233
    end
1234
    def enter_valuetype(node)
1235
      println
1236
      printiln("class #{node.rubyname} < PortableServer::Servant ## servant")
1237
      @nest += 1
1238
      printiln('## valuetype interface')
1239
      printiln("include #{@stub_root}#{node.scoped_rubyname}")
1240
      println
1241
      printiln('## object interfaces')
1242
      node.interfaces.each do |intf|
1243
        #printiln("include #{@stub_root}#{intf.scoped_rubyname}")
1244
        printiln("include #{intf.scoped_rubyname}")
1245
      end
1246
    end
1247

    
1248
    def leave_valuetype(node)
1249
      @nest -= 1
1250
      printiln("end #of servant #{node.rubyname}")
1251
    end
1252

    
1253
    def visit_valuebox(node)
1254
    end
1255

    
1256
    def visit_const(node)
1257
    end
1258

    
1259
    def visit_operation(node)
1260
      _parm = node.params
1261
      _in = node.in_params
1262
      _out = node.out_params
1263
      _intf = node.enclosure
1264

    
1265
      ## do nothing for valuetypes or local interfaces
1266
      return nil if _intf.is_a?(IDL::AST::Valuetype) || _intf.is_local?
1267

    
1268
      printi("Operations.store(:#{node.name}, {")
1269
      newln = ""
1270
      if _parm.size>0
1271
        println(newln)
1272
        nest do
1273
          printi(":arg_list => [")
1274
          nest {
1275
            pfx = ""
1276
            _parm.each do |p|
1277
              println(pfx)
1278
              printi("['#{p.rubyname}', #{get_arg_type(p.attribute)}, ");
1279
              print(get_typecode(p.idltype))
1280
              print("]")
1281
              pfx = ","
1282
            end
1283
            print("]")
1284
          }
1285
        end
1286
        newln = ","
1287
      end
1288

    
1289
      if not node.oneway
1290
        println(newln)
1291
        nest { printi(":result_type => #{get_typecode(node.idltype)}") }
1292
        newln = ","
1293
      end
1294

    
1295
      if node.raises.size>0
1296
        println(newln)
1297
        nest {
1298
          printi(":exc_list => [")
1299
          pfx = ""
1300
          nest {
1301
            node.raises.each { |ex|
1302
              println(pfx)
1303
              pfx = ","
1304
              printi(get_typecode(ex))
1305
            }
1306
            print("]")
1307
          }
1308
        }
1309
        newln = ","
1310
      end
1311

    
1312
      if node.rubyname != node.name
1313
        println(newln)
1314
        nest { printi(":op_sym => :#{node.rubyname}") }
1315
      end
1316
      println("})")
1317
      println()
1318

    
1319
      printi("def #{node.rubyname}(")
1320
      print( _in.collect{ |p| p.rubyname }.join(", ") )
1321
      if node.oneway
1322
        println(")    # oneway")
1323
      else
1324
        println(")")
1325
      end
1326
      nest {
1327
        printiln("raise ::CORBA::NO_IMPLEMENT.new(")
1328
        printiln("         'unimplemented servant operation',")
1329
        printiln("         1, ::CORBA::COMPLETED_NO)")
1330
      }
1331
      printiln("end")
1332
      println()
1333
    end
1334

    
1335
    def visit_attribute(node)
1336
      _intf = node.enclosure
1337

    
1338
      ## do nothing for valuetypes or local interfaces
1339
      return nil if _intf.is_a?(IDL::AST::Valuetype) || _intf.is_local?
1340

    
1341
      printiln("Operations.store(:_get_#{node.name}, {")
1342
      nest {
1343
        nest {
1344
          printiln(":result_type => #{get_typecode(node.idltype)},")
1345
          if node.get_raises.size>0
1346
            printi(":exc_list => [")
1347
            pfx = ""
1348
            nest {
1349
              node.get_raises.each { |ex|
1350
                println(pfx)
1351
                pfx = ","
1352
                printi(get_typecode(ex))
1353
              }
1354
              println("],")
1355
            }
1356
          end
1357
          printiln(":op_sym => :#{node.rubyname} })")
1358
        }
1359
      }
1360
      println()
1361

    
1362
      printiln("def #{node.rubyname}()")
1363
      nest {
1364
        printiln("raise ::CORBA::NO_IMPLEMENT.new(")
1365
        printiln("         'unimplemented servant attribute get',")
1366
        printiln("         1, ::CORBA::COMPLETED_NO)")
1367
      }
1368
      printiln("end #of attribute get_#{node.name}")
1369
      println()
1370

    
1371
      if not node.readonly
1372
        printiln("Operations.store(:_set_#{node.name}, {")
1373
        nest {
1374
          nest {
1375
            printiln(":arg_list => [")
1376
            nest {
1377
              printiln("['val', CORBA::ARG_IN, #{get_typecode(node.idltype)}]],");
1378
            }
1379
            printiln(":result_type => CORBA._tc_void,")
1380
            if node.set_raises.size>0
1381
              printi(":exc_list => [")
1382
              pfx = ""
1383
              nest {
1384
                node.set_raises.each { |ex|
1385
                  println(pfx)
1386
                  pfx = ","
1387
                  printi(get_typecode(ex))
1388
                }
1389
                println("],")
1390
              }
1391
            end
1392
            printiln(":op_sym => :#{node.rubyname}= })")
1393
          }
1394
        }
1395
        println()
1396

    
1397
        printiln("def #{node.rubyname}=(val)")
1398
        nest {
1399
          printiln("raise ::CORBA::NO_IMPLEMENT.new(")
1400
          printiln("         'unimplemented servant attribute set',")
1401
          printiln("         1, ::CORBA::COMPLETED_NO)")
1402
        }
1403
        printiln("end #of attribute set_#{node.name}")
1404
        println()
1405
      end
1406
    end
1407

    
1408
    def get_typecode(_type)
1409
      case _type
1410
      when Type::Octet,
1411
           Type::UShort, Type::Short,
1412
           Type::ULong, Type::Long,
1413
           Type::ULongLong, Type::LongLong,
1414
           Type::Boolean, Type::Char, Type::WChar,
1415
           Type::Float, Type::Double, Type::LongDouble,
1416
           Type::Void, Type::Any
1417
        s = _type.class.name.split("::") # IDL::Type::Octet -> [IDL, Type, Octet]
1418
        s = s[s.length - 1]
1419
        s.downcase!
1420
        format("CORBA._tc_%s",s)
1421

    
1422
      when Type::Object
1423
        "CORBA._tc_Object"
1424

    
1425
      when Type::String
1426
        if not _type.length.nil?
1427
          format("CORBA::TypeCode::String.new(%d)", _type.length)
1428
        else
1429
          "CORBA._tc_string"
1430
        end
1431

    
1432
      when Type::WString
1433
        if not _type.length.nil?
1434
          format("CORBA::TypeCode::WString.new(%d)", _type.length)
1435
        else
1436
          "CORBA._tc_wstring"
1437
        end
1438

    
1439
      when Type::ScopedName
1440
        @stub_root + _type.node.scoped_rubyname + '._tc'
1441

    
1442
      when Type::Array
1443
        sep = ""
1444
        tc = "CORBA::TypeCode::Array.new(" +
1445
            get_typecode(_type.basetype) + ", "
1446
        _type.sizes.each do |sz|
1447
          tc += "#{sep}#{sz.to_s}"
1448
          sep = ", "
1449
        end
1450
        tc + ")"
1451

    
1452
      when Type::Sequence
1453
        if _type.is_recursive?
1454
          "CORBA::TypeCode::Sequence.new(CORBA::TypeCode::Recursive.new('#{_type.basetype.resolved_type.node.repository_id}'))"
1455
        else
1456
          "CORBA::TypeCode::Sequence.new(" +
1457
                get_typecode(_type.basetype) +
1458
                if not _type.length.nil? then format(", %d)", _type.length) else ")" end +
1459
                ".freeze"
1460
        end
1461

    
1462
      else
1463
        raise RuntimeError, "invalid type for (un)marshalling: #{_type.typename}"
1464
      end
1465
    end
1466

    
1467
    def get_arg_type(_idl_argtype)
1468
      case _idl_argtype
1469
      when IDL::AST::Parameter::IN
1470
        "CORBA::ARG_IN"
1471
      when IDL::AST::Parameter::OUT
1472
        "CORBA::ARG_OUT"
1473
      else
1474
        "CORBA::ARG_INOUT"
1475
      end
1476
    end
1477

    
1478
    def expression_to_s(exp)
1479
      case exp
1480
      when Expression::Value
1481
        value_to_s(exp)
1482
      when Expression::Operation
1483
        operation_to_s(exp)
1484
      when Expression::ScopedName
1485
        @stub_root + exp.node.scoped_rubyname
1486
      else
1487
        raise RuntimeError, "unknown expression type: #{exp.class.name}"
1488
      end
1489
    end
1490

    
1491
    def value_to_s(exp)
1492
      s = nil
1493
      v = exp.value
1494
      case exp.idltype
1495
      when Type::Void
1496
        s = "nil"
1497
      when Type::Char
1498
        s = "'#{v.chr}'"
1499
      when Type::Integer,
1500
        Type::Boolean,
1501
        Type::Octet,
1502
        Type::Float,
1503
        Type::WChar
1504
        s = v.to_s
1505
      when Type::Enum
1506
        s = v.to_s
1507
      when Type::String
1508
        s = "'#{v.to_s}'"
1509
      when Type::WString
1510
        s = "[#{v.join(',')}]"
1511
      #when Type::Fixed
1512
      #when Type::Any
1513
      #when Type::Object
1514
      when Type::ScopedName
1515
        s = value_to_s(Expression::Value.new(exp.idltype.node.idltype, v))
1516
      else
1517
        raise RuntimeError, "#{exp.typename}'s not been supported yet."
1518
      end
1519
      s
1520
    end
1521

    
1522
    def operation_to_s(exp)
1523
      s = nil
1524
      op = exp.operands
1525
      case exp
1526
      when Expression::UnaryPlus
1527
        s = expression_to_s(op[0])
1528
      when Expression::UnaryMinus
1529
        s = "-" + expression_to_s(op[0])
1530
      when Expression::UnaryNot
1531
        s = "~" + expression_to_s(op[0])
1532
      when Expression::Or
1533
        s = expression_to_s(op[0]) + " | " + expression_to_s(op[1])
1534
      when Expression::And
1535
        s = expression_to_s(op[0]) + " & " + expression_to_s(op[1])
1536
      when Expression::LShift
1537
        s = expression_to_s(op[0]) + " << " + expression_to_s(op[1])
1538
      when Expression::RShift
1539
        s = expression_to_s(op[0]) + " >> " + expression_to_s(op[1])
1540
      when Expression::Add
1541
        s = expression_to_s(op[0]) + " + " + expression_to_s(op[1])
1542
      when Expression::Minus
1543
        s = expression_to_s(op[0]) + " - " + expression_to_s(op[1])
1544
      when Expression::Mult
1545
        s = expression_to_s(op[0]) + " * " + expression_to_s(op[1])
1546
      when Expression::Div
1547
        s = expression_to_s(op[0]) + " / " + expression_to_s(op[1])
1548
      when Expression::Mod
1549
        s = expression_to_s(op[0]) + " % " + expression_to_s(op[1])
1550
      else
1551
        raise RuntimeError, "unknown operation: #{exp.type.name}"
1552
      end
1553
      "(" + s + ")"
1554
    end
1555

    
1556
    def declare_struct(node)
1557
    end
1558
    def enter_struct(node)
1559
    end
1560
    def leave_struct(node)
1561
    end
1562

    
1563
    def enter_exception(node)
1564
    end
1565
    def leave_exception(node)
1566
    end
1567

    
1568
    def declare_union(node)
1569
    end
1570
    def enter_union(node)
1571
    end
1572
    def leave_union(node)
1573
    end
1574

    
1575
    def visit_enum(node)
1576
    end
1577

    
1578
    def visit_enumerator(node)
1579
    end
1580

    
1581
    def visit_typedef(node)
1582
    end
1583
  end ## RubyServantWriter
1584

    
1585
end ## module IDL