File: reader_ext.rb

package info (click to toggle)
klayout 0.26.2-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 146,224 kB
  • sloc: cpp: 1,465,078; ruby: 35,220; xml: 19,003; python: 8,881; sh: 1,393; tcl: 210; perl: 107; makefile: 90; ansic: 42
file content (547 lines) | stat: -rw-r--r-- 11,250 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547

# 
# Copyright (C) 2006-2019 Matthias Koefferlein
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
#

class CPPObject

  # Propagate setting of the visibility down to the children 
  # (set_visibility will replace the default visibility with public or private)
  def set_visibility
  end

  # Inject scoped objects (like "class A::B { ... };") into their target 
  # scope.
  def inject_scoped
  end

  # delivers a string representation of the name or nil if the object does not have a name 
  # to contribute
  def myself
    nil
  end

  # delivers a string representation of the "weak" name or nil if the object does not have a name 
  # to contribute. "weak names" are such of second order - e.g. forward declarations.
  def myself_weak
    nil
  end

  # delivers a CPPQualifiedId representation of the object's location or nil if the object
  # does not have a location to contribute
  def myid
    nil
  end

  # sets the CPPQualifiedId
  def setid(id)
  end

  # supposed to establish the parent link
  def set_parent(p)
  end

  # removes a child from our members
  def remove(d)
  end

  # inserts a child into our members
  def insert(d)
  end

end

class CPPType
  
  def func
    i = self
    while i.respond_to?(:inner)
      if i.is_a?(CPPFunc) && (i.inner.is_a?(CPPQualifiedId) || i.inner.is_a?(CPPAnonymousId))
        return i
      end
      i = i.inner
    end
    nil
  end

  def return_type
    rt = self.dup
    f = self.func
    if f
      i = self
      idup = rt
      while i.respond_to?(:inner)
        i = i.inner
        if i == f
          idup.inner = CPPAnonymousId::new
          break
        end
        idup.inner = i.dup
        idup = idup.inner
      end
    end
    rt
  end

  def name_substituted_type(sub)
    rt = self.dup
    i = self
    idup = rt
    while i.respond_to?(:inner)
      ii = i.inner
      if ii.is_a?(CPPQualifiedId) || ii.is_a?(CPPAnonymousId)
        idup.inner = sub
        break
      end
      i = ii
      idup.inner = i.dup
      idup = idup.inner
    end
    rt
  end

  def anonymous_type
    name_substituted_type(CPPAnonymousId::new)
  end

  def renamed_type(name)
    name_substituted_type(CPPQualifiedId::new(false, [name]))
  end

  def name
    i = self
    while i.respond_to?(:inner)
      ii = i.inner
      if ii.is_a?(CPPQualifiedId)
        return ii.to_s
      end
      i = ii
    end
    nil
  end

  def is_void?
    self.concrete.is_a?(CPPPOD) && self.concrete.to_s == "void" && (self.inner.is_a?(CPPAnonymousId) || self.inner.is_a?(CPPQualifiedId))
  end

end

module QualifiedNameResolver

  attr_accessor :parent

  def global_scope
    o = self
    while o.myself && o.parent
      o = o.parent
    end
    o
  end

  # requirements
  #  - children -> must deliver a list of child objects
  #  - myself -> must deliver my name

  def set_parent(parent = nil)
    self.parent = parent
    @id2obj = {}
    self.children.each do |d|
      d.myself && (@id2obj[d.myself] = d)
    end 
    self.children.each do |d|
      d.myself_weak && (@id2obj[d.myself_weak] ||= d)
    end 
    self.children.each do |d|
      d.set_parent(self)
    end
    # Add other children, for example contributed by base classes
    if self.respond_to?(:other_children)
      self.other_children.each do |d|
        d.myself && (@id2obj[d.myself] = d)
      end
    end
  end

  def dump_ids
    @id2obj.keys.sort.each do |k|
      puts("--> #{k}")
    end
  end

  # by default the objects don't have a weak identity
  def myself_weak
    nil
  end

  # returns a list of names of child objects
  def ids
    (@id2obj || {}).keys.sort
  end

  def id2obj(id)
    @id2obj && @id2obj[id]
  end

  def resolve_qid(qid)

    qid.is_a?(CPPQualifiedId) || raise("Argument of resolve_qid must be a CPPQualifiedId object")

    obj = nil
    if qid.global && self.parent
      root = self
      while root.parent
        root = root.parent
      end
      obj = root.resolve_qid(qid)
    else
      obj = id2obj(qid.parts[0].id)
      if obj && qid.parts.size > 1
        # The part may be a typedef: resolve it in that case before we proceed
        while obj && obj.is_a?(CPPTypedef) 
          obj = obj.type.concrete.is_a?(CPPQualifiedId) && self.resolve_qid(obj.type.concrete)
        end
        if obj
          qid_new = qid.dup
          qid_new.parts = qid.parts[1 .. -1]
          obj = obj.respond_to?(:resolve_qid) && obj.resolve_qid(qid_new)
        end
      end
      if ! obj && self.parent
        obj = self.parent.resolve_qid(qid)
      end
    end

    obj

  end

  def inject_scoped

    self.children.each do |d|

      d.inject_scoped

      qid = d.myid
      if qid

        qid.is_a?(CPPQualifiedId) || raise("Argument of resolve_qid must be a CPPQualifiedId object")

        if qid.parts.size > 1

          qid = qid.dup
          while qid.parts.size > 1
            obj = id2obj(qid.parts[0].id)
            if obj
              qid.parts = qid.parts[1 .. -1]
            else
              break
            end
          end

          if obj && qid.parts.size == 1
            # This copies the visibility which is not quite correct, since the injection case
            # is usually used for providing an implementation outside a class. That does not 
            # mean the outside implementation will provide the visibility. Instead a forward
            # declaration inside the target scope will do. Since that is lost in our implementation
            # currently that is not possible.
            self.remove(d)
            d.setid(qid)
            obj.insert(d)
          end

        end

      end

    end

  end

end

class CPPDeclaration

  include QualifiedNameResolver

  def children
    []
  end

  def myself
    self.type.name 
  end

end

class CPPEnumDeclaration

  include QualifiedNameResolver

  def children
    []
  end

  def myself
    self.enum.name.to_s
  end

end

class CPPEnumSpec

  include QualifiedNameResolver

  def children
    []
  end

  def myself
    self.name.to_s
  end

end

class CPPStruct

  attr_accessor :parent

  def global_scope
    self.parent && self.parent.global_scope
  end

  def set_visibility

    (self.body_decl || []).each do |bd|
      if bd.respond_to?(:visibility) && bd.visibility == :default
        if self.kind == :struct || self.kind == :union
          bd.visibility = :public
        else 
          bd.visibility = :private
        end
      end
      bd.set_visibility
    end

  end

end

class CPPTypedef

  include QualifiedNameResolver

  def myself
    self.type.name
  end

  def children
    []
  end

end

class CPPStructDeclaration

  include QualifiedNameResolver

  def children

    # take this chance to set the parent to struct
    self.struct.parent = self
    c = self.struct.body_decl || []

    # add enum constants (CPPEnumSpec)
    (self.struct.body_decl || []).each do |bd|
      if bd.is_a?(CPPEnumDeclaration) && bd.enum && bd.enum.specs
        c += bd.enum.specs
      end
    end

    c

  end

  def remove(d)
    self.struct.body_decl && self.struct.body_decl.delete(d)
  end

  def insert(d)
    self.struct.body_decl ||= []
    self.struct.body_decl << d
  end

  def other_children

    # add base classes both as sub-namespace and individual parts
    # and add self so scoping is possible into ourself 
    c = [ self ]

    (self.struct.base_classes || []).each do |bc|
      # The parent may be null for template base classes which are 
      # forward-declared .. we're not interested in this case.
      if self.parent
        bc_obj = self.parent.resolve_qid(bc.class_id)
        # NOTE: it may look strange to test whether the base class is the class itself but
        # since we do a half-hearted job of resolving template variants, this may happen
        # if we derive a template specialization from another one (specifically 
        # "template<class T> struct is_default_constructible : is_default_constructible<> { .. }"
        if bc_obj != self && bc_obj.is_a?(CPPStructDeclaration)
          c << bc_obj
          c += bc_obj.children
          c += bc_obj.other_children
        end
      end
    end

    c

  end

  def myself_weak
    # the weak identity will also include forward declarations
    self.struct.id.to_s
  end

  def myself
    # forward declarations (struct.body_decl == nil and no base classes) don't produce a name and
    # will therefore not contribute 
    (self.struct.body_decl || self.struct.base_classes) && self.struct.id.to_s
  end

  def myid
    # forward declarations (struct.body_decl == nil and no base classes) don't produce a name and
    # will therefore not contribute 
    (self.struct.body_decl || self.struct.base_classes) && self.struct.id
  end

  def setid(id)
    self.struct.id = id
  end

  def set_visibility
    self.struct && self.struct.set_visibility
  end

end

class CPPNamespace

  include QualifiedNameResolver

  def children

    # take this opportunity to join identical namespaces
    if self.members
      new_members = []
      ns = {}
      self.members.each do |d|
        if d.is_a?(CPPNamespace)
          if !ns[d.myself]
            ns[d.myself] = d
            new_members << d
          else
            ns[d.myself].members += d.members
          end
        else
          new_members << d
        end
      end
      self.members = new_members
    end      

    self.members || []

  end

  def other_children
    # add self so scoping is possible into ourself 
    [ self ]
  end

  def myself
    self.name.to_s
  end

  def remove(d)
    self.members.delete(d)
  end

  def insert(d)
    self.members << d
  end

  def set_visibility

    (self.members || []).each do |m|
      if m.respond_to?(:visibility) && m.visibility == :default
        m.visibility = :public
      end
      m.set_visibility
    end

  end

end

class CPPModule

  include QualifiedNameResolver

  def children

    # take this opportunity to join identical namespaces
    new_decls = []
    ns = {}
    self.decls.each do |d|
      if d.is_a?(CPPNamespace)
        if !ns[d.myself]
          ns[d.myself] = d
          new_decls << d
        else
          ns[d.myself].members += d.members
        end
      else
        new_decls << d
      end
    end

    self.decls = new_decls

  end

  def remove(d)
    self.decls.delete(d)
  end

  def insert(d)
    self.decls << d
  end

  def myself
    nil
  end

  def set_visibility
    (self.decls || []).each do |d|
      if d.respond_to?(:visibility) && d.visibility == :default
        d.visibility = :public
      end
      d.set_visibility
    end
  end

end