File: cpp_classes.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 (654 lines) | stat: -rw-r--r-- 18,677 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
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
# 
# 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 Module
  def def_initializer(*args)
    self.class_eval <<END
      def initialize(#{args.join(", ")})
        #{args.map { |arg| "@#{arg} = #{arg}" }.join("\n")}
      end
      def initialize_copy(other)
        # TODO: is there a better way to check whether dup can be used?
        # Implement Hash?
        #{args.map { |arg| "a = other.#{arg}\n"+
                           "if a.is_a?(TrueClass) || a.is_a?(FalseClass) || a.is_a?(NilClass) || a.is_a?(Fixnum) || a.is_a?(Float) || a.is_a?(Symbol)\n"+
                           "  @#{arg} = a\n"+
                           "elsif a.is_a?(Array)\n"+
                           "  @#{arg} = a.collect { |aa| aa.dup }\n"+
                           "else\n"+
                           "  @#{arg} = a.dup\n"+
                           "end"
                   }.join("\n")}
      end
END
  end
end

# @brief The base class for all CPP objects
class CPPObject
end

# @brief Denotes type nesting wrappers
# Type nesting provide a modification the renders a different type
# for the inner "user" of the type. For example:
# "int **x" starts with "int", adds a pointer, adds another pointer and
# ends at "x" (the symbol). "int" is the "concrete type", the two 
# pointers are type wrappers and "x" is the innermost elements. 
# The type s read from the inside out: "x" is a pointer to a pointer to an int.
class CPPOuterType < CPPObject
end

# @brief An array specification
# @attribute inner The inner type (the type which makes use of the array)
# "inner" is either another CPPOuterType or a CPPQualifiedId (the innermost)
# part.
class CPPArray < CPPOuterType

  attr_accessor :inner
  def_initializer :inner 

  def to_s
    if self.inner.is_a?(CPPPointer) 
      "(" + self.inner.to_s + ") []"
    else
      self.inner.to_s + " []"
    end
  end

  def dump(i)
    i + "CPPArray\n" + i + " inner:\n" + self.inner.dump(i + "  ")
  end

end

# @brief A function specification
# @attribute inner The inner type (which makes use of the function)
# @attribute args The function arguments
# @attribute cv A const/voilatile specification if the function is a method (:const, :volatile)
# "inner" is either another CPPOuterType or a CPPQualifiedId (the innermost)
# part.
# "args" is an array of CPPType or CPPInitializedType objects, optionally terminated with 
# a CPPEllipsis.
# "cv" is a CPPCV object.
class CPPFunc < CPPOuterType

  attr_accessor :inner, :args, :cv
  def_initializer :inner, :args, :cv 

  def to_s
    a = self.args
    a ||= []
    if !a.is_a?(Array)
      a = [a]
    end
    self.inner.to_s + " (" + a.join(", ") + ")" + (self.cv ? " " + self.cv.to_s : "") 
  end

  def dump(i)
    i + "CPPFunc\n" + i + " inner:\n" + self.inner.dump(i + "  ") + "\n" + 
    i + " cv: " + self.cv.to_s + "\n" + 
    i + " args:\n" + (self.args || []).collect { |f| f.dump(i + "  ") }.join("\n")
  end

end

# @brief A pointer declaration
# @attribute inner The inner type which sees the outer type converted into a pointer
# "inner" is either another CPPOuterType or a CPPQualifiedId (the innermost)
# part.
class CPPPointer < CPPOuterType

  attr_accessor :inner
  def_initializer :inner

  def to_s
    "* " + self.inner.to_s
  end

  def dump(i)
    i + "CPPPointer\n" + i + " inner:\n" + self.inner.dump(i + "  ")
  end

end

# @brief A reference declaration
# @attribute inner The inner type which sees the outer type converted into a reference
# "inner" is either another CPPOuterType or a CPPQualifiedId (the innermost)
# part.
class CPPReference < CPPOuterType

  attr_accessor :inner
  def_initializer :inner

  def to_s
    "& " + self.inner.to_s
  end

  def dump(i)
    i + "CPPReference\n" + i + " inner:\n" + self.inner.dump(i + "  ")
  end

end

# @brief A member/method pointer declaration
# @attribute qid The class of which a member/method is addressed (a CPPQualifiedId object)
# @attribute inner The inner type which sees the outer type converted into a member/method pointer
# @attribute cv A CPPCV object describing whether the method is a const or volatile one
# Functions are converted to method pointers, plain type into member pointers.
# "inner" is either another CPPOuterType or a CPPQualifiedId (the innermost)
# part.
class CPPMemberPointer < CPPOuterType

  attr_accessor :qid, :inner, :cv
  def_initializer :qid, :inner, :cv

  def to_s
    self.qid.to_s + "::* " + self.inner.to_s + (self.cv ? " " + self.cv.to_s : "")
  end

  def dump(i)
    i + "CPPMemberPointer\n" + i + " inner:\n" + self.inner.dump(i + "  ") + 
    i + " cv:\n" + self.cv.dump(i + "  ") + 
    i + " qid: " + self.qid.to_s
  end

end

# @param Adds const or volatile declaration 
# @attribute cv :const or :volatile
# @attribute inner The inner expression which sees the const/volatile declaration
class CPPCV < CPPOuterType

  attr_accessor :cv, :inner
  def_initializer :cv, :inner

  def to_s
    (self.cv ? (self.cv.to_s + " ") : "") + self.inner.to_s
  end

  def dump(i)
    i + "CPPCV\n" + 
    i + " cv: " + self.cv.to_s + "\n" +
    i + " inner:\n" + self.inner.dump(i + "  ")
  end

end

def CPPCV::wrap(cv, inner)
  cv ? CPPCV::new(cv, inner) : inner
end

# @brief A constant uses as a template instance argument
# @attribute value A string giving the value
class CPPConst < CPPObject

  attr_accessor :value
  def_initializer :value

  def to_s
    self.value
  end

  def dump(i)
    i + "CPPConst\n" + i + " value: " + self.value.to_s
  end

end

# @brief A class the template instance arguments
# @attribute args An array of CPPConst (for constants) or CPPType objects (for types)
# This class is used for both template instances or declarations.
class CPPTemplateArgs < CPPObject

  attr_accessor :args
  def_initializer :args

  def to_s
    self.args.collect { |a| a.to_s }.join(", ")
  end

  def dump(i)
    i + "CPPTemplateArgs\n" +
    i + " args:\n" + (self.args || []).collect { |a| a.dump(i + "  ") }.join("\n")
  end

end

# @brief An class or namespace name, optionally with template arguments
# @attribute id The basic id (a string)
# @attribute template_args A CPPTemplateArgs object describing the template arguments or nil, if it does not describe a template instance or declaration
class CPPId < CPPObject

  attr_accessor :id, :template_args
  def_initializer :id, :template_args

  def to_s
    ta = self.template_args.to_s
    if ta =~ />$/
      ta += " "
    end
    self.id + (self.template_args ? ( "<" + ta + ">" ) : "")
  end

  def dump(i)
    i + "CPPId\n" +
    i + " id: " + self.id.to_s + 
    i + " template_args:\n" + self.template_args.dump(i + "  ")
  end

end

# @brief An anonymous ID
# This object is used in place of CPPQualifiedId if no name is given
class CPPAnonymousId < CPPObject

  def to_s
    "" 
  end

  def dump(i)
    i + "CPPAnonymousId"
  end

end

# @brief An id, optionally qualified by a namespace
# @attribute global If true, the Id is rooted in the global namespace
# @attribute parts A sequence of CPPId objects forming the namespace sequence
class CPPQualifiedId < CPPObject

  attr_accessor :global, :parts
  def_initializer :global, :parts

  def to_s
    (self.global ? "::" : "") + (self.parts || []).collect { |p| p.to_s }.join("::")
  end

  def dump(i)
    n = (self.global ? "::" : "") + (self.parts || []).collect { |p| "[" + p.to_s + "]" }.join("::")
    i + "CPPQualifiedId (" + n + ")"
  end

end

# @brief A "plain old type" (double, float, int, char, ...)
# @attribute signed Is nil, :signed or :unsigned (for the types supporting that)
# @attribute length Is nil, :short, :long or :longlong for the types supporting that
# @attribute type The basic type (:int, :char, :bool, :float, :double)
class CPPPOD < CPPObject

  attr_accessor :signed, :length, :type
  def_initializer :signed, :length, :type

  def to_s
    
    s = ""
    if self.signed == :signed
      s += "signed "
    elsif self.signed == :unsigned
      s += "unsigned "
    end
    if self.length == :short
      s += "short "
    elsif self.length == :long
      s += "long "
    elsif self.length == :longlong
      s += "long long "
    end

    s + self.type.to_s

  end

  def dump(i)
    i + "CPPPOD (" + self.to_s + ")"
  end

end

# @brief A base class declarations
# @attribute visibility :default, :public, :private or :protected
# @attribute virtual Is true, if the class is a virtual base class
# @attribute class_id A CPPQualifiedId object pointing to the base class
class CPPBaseClass < CPPObject

  attr_accessor :visibility, :virtual, :class_id
  def_initializer :visibility, :virtual, :class_id

  def to_s
    (self.visibility ? self.visibility.to_s + " " : "") + (self.virtual ? "virtual " : "") + self.class_id.to_s
  end

  def dump(i)
    i + "CPPBaseClass\n" + 
    i + " visibility: " + self.visibility.to_s + 
    i + " virtual:\n" + self.virtual.to_s + 
    i + " class_id:\n" + self.class_id.to_s  
  end

end

# @brief Describes a structure, class or union
# @attribute kind :struct, :class or :union
# @attribute id The name of the struct, class or union
# @attribute base_classes The base class declarations (an array of CPPBaseClass objects)
# @attribute body_decl An array or CPPUsingSpec, CPPFriendDecl, CPPTypedef, CPPEnumDeclaration, CPPStructDeclaration or CPPDeclaration objects 
# "body_decl" forms the body of the class. It contains friend declarations, using specs, typedef's, enum's,
# nested struct's or method and member declarations.
class CPPStruct < CPPObject

  attr_accessor :kind, :id, :base_classes, :body_decl
  def_initializer :kind, :id, :base_classes, :body_decl

  def to_s
    self.kind.to_s + " " + self.id.to_s
  end

  def dump(i)
    l = i + self.kind.to_s + ": " + self.id.to_s + "\n"
    l += (self.base_classes || []).collect { |b| i + "  < " + b.to_s + "\n" }.join("")
    l += (self.body_decl || []).collect { |b| b.dump(i + "  ") }.join("\n")
  end

end

# @param Describes a type derived with "__typeof"
# @attribute what The object from which the type is derived (a CPPQualifiedId)
class CPPTypeOf < CPPObject

  attr_accessor :what
  def_initializer :what

  def to_s
    "__typeof(" + what.to_s + ")"
  end

  def dump(i)
    i + "CPPTypeOf\n" + 
    i + " what: " + self.what.to_s  
  end

end

# @param Describes an ellipsis inside a function argument list
class CPPEllipsis < CPPObject

  def to_s
    "..."
  end

  def dump(i)
    i + "CPPEllipsis"  
  end

end

# @brief A general type definition
# @attribute concrete The concrete part of the type: a CPPPOD, CPPStruct, CPPEnum, CPPTypeof or CPPQualifiedId object)
# @attribute inner The "inner part": one of the CPPOuterType-derived classes or CPPQualifiedId
# @attribute init A string indicating the initialization expression
# If the concrete type is a class, struct, union, enum or typedef, a CPPQualifiedId is used for the 
# attribute, describing the initial type (which can be complex already in the case of a typedef).
# The "inner" declarations add pointers, references, arrays of functions and finally the identifier.
# Without any further qualification, "inner" is a CPPQualifiedId object.
class CPPType < CPPObject

  attr_accessor :concrete, :inner, :init
  def_initializer :concrete, :inner, :init

  def to_s
    i = self.inner.to_s
    s = self.concrete.to_s + " " + i
    # nicen:
    s.gsub(/\s+/, " ").sub(/^\s*/, "").sub(/\s*$/, "").gsub(/ \(/, "(").gsub(/\* /, "*").gsub(/& /, "&")
  end

  def dump(i)
    i + "CPPType\n" + 
    i + " init: " + (self.init ? self.init.to_s : "nil") + "\n" + 
    i + " concrete:\n" + (self.concrete ? self.concrete.dump(i + "  ") : i + "  nil") + "\n" + 
    i + " inner:\n" + self.inner.dump(i + "  ")
  end

end

# @brief A "using" instruction
# @attribute qid The qualified Id of the using specification
# @attribute visibility :default, :public, :private or :protected
class CPPUsingSpec < CPPObject

  attr_accessor :qid, :visibility
  def_initializer :qid, :visibility

  def dump(i)
    i + "using [" + self.visibility.to_s + "]: " + self.qid.to_s
  end

end

# @brief A typedef instruction
# @attribute type The declared type (a CPPType object, the inner name is the name of the defined type)
# @attribute visibility :default, :public, :private or :protected
class CPPTypedef < CPPObject

  attr_accessor :type, :visibility
  def_initializer :type, :visibility

  def dump(i)
    i + "typedef [" + self.visibility.to_s + "]: " + self.type.to_s
  end

end

# @brief A friend declaration 
# @attribute decl An array of friend types (an array of CPPType objects)
class CPPFriendDecl < CPPObject

  attr_accessor :decl
  def_initializer :decl

  def dump(i)
    self.decl.collect { |d| i + "friend: " + d.to_s }.join("\n")
  end

end

# @brief A type template argument (with an optional initializer)
# @attribute id The name of the argument (a string)
# @attribute def_type The default type (nil or a CPPType object) 
class CPPClassTemplateArg < CPPObject

  attr_accessor :id, :def_type
  def_initializer :id, :def_type

  def to_s
    self.id + (self.def_type ? ("=" + self.def_type.to_s) : "")
  end

end

# @brief A value template argument (with an optional initializer)
# @attribute type A CPPType object describing the type
# @attribute def_expr The initializer expression (a string) or nil if no initializer is given
class CPPDirectTemplateArg < CPPObject

  attr_accessor :type, :def_expr
  def_initializer :type, :def_expr

  def to_s
    self.type.to_s + (self.def_expr ? ("=" + self.def_expr.to_s) : "")
  end

end

# @brief A template declaration
# @attribute parts An array of CPPClassTemplateArg or CPPDirectTemplateArg objects
# CPPClassTemplateArg objects describe type arguments while CPPDirectTemplateArg objects
# describe value arguments (i.e. int).
class CPPTemplateDecl < CPPObject

  attr_accessor :parts
  def_initializer :parts

  def to_s
    (self.parts || []).collect { |p| p.to_s }.join(", ")
  end

end

# @brief An internal object, does not appear in the final parsed tree
class CPPAttr < CPPObject
  attr_accessor :attr
  def_initializer :attr
end

# @brief An struct/class/union declaration inside a namespace or class
# @attribute struct The CPPStruct object describing the class, struct or union
# @attribute template_decl nil or a CPPTemplateDecl object if the declaration is a template declaration
# @attribute visibility :default, :public, :private or :protected
class CPPStructDeclaration < CPPObject

  attr_accessor :struct, :template_decl, :visibility
  def_initializer :struct, :template_decl, :visibility

  def dump(i)
    l = i + self.struct.kind.to_s + "_decl [" + self.visibility.to_s + "]: "
    if self.template_decl
      l += "template<" + self.template_decl.to_s + ">"
    end
    l += "\n"
    l += self.struct.dump(i + "  ")
  end

end

# @brief An enum declaration inside a namespace or class
# @attribute enum The CPPEnum object describing the enum
# @attribute visibility :default, :public, :private or :protected
class CPPEnumDeclaration < CPPObject

  attr_accessor :enum, :visibility
  def_initializer :enum, :visibility

  def dump(i)
    i + "enum_decl [" + self.visibility.to_s + "]:\n" + self.enum.dump(i + "  ")
  end

end

# @brief A declaration of either a function, a type, a member or a method
# @attribute type the declared type: a CPPType object
# @attribute template_decl nil or a CPPTemplateDecl object if the declaration is a template declaration
# @attribute visibility :default, :public, :private or :protected
# @attribute storage_class nil, :extern or :static
# @attribute virtual Is true for virtual methods
# @attribute inline Is true for inline declarations
class CPPDeclaration < CPPObject

  attr_accessor :type, :template_decl, :visibility, :storage_class, :virtual, :inline
  def_initializer :type, :template_decl, :visibility, :storage_class, :virtual, :inline

  def dump(i)
    l = i
    l += "decl [" + self.visibility.to_s + "]: "
    if self.storage_class
      l += self.storage_class.to_s + " "
    end
    if self.virtual
      l += "virtual "
    end
    if self.inline
      l += "inline "
    end
    if self.template_decl
      l += "template<" + self.template_decl.to_s + "> "
    end
    if self.type.respond_to?(:to_s)
      l += self.type.to_s
    else
      l += self.type.dump(i + "  ")
    end
    l += " #" + self.myself.to_s
    l
  end

end

# @brief A namespace
# @attribute name The namespace name (a string)
# @attribute members The content of the namespace: an array of CPPTypedef, CPPNamespace (nested namespaces), CPPStructDeclaration, CPPEnumDeclaration or CPPDeclaration objects
class CPPNamespace < CPPObject

  attr_accessor :name, :members
  def_initializer :name, :members

  def dump(i)
    l = i + "namespace #{self.name} {\n"
    l += (self.members || []).collect { |m| m.dump(i + "  ") }.join("\n")
    l += i + "}"
  end

end

# @brief Describes a single enum constant
# @attribute name The name of the enum constant
# @attribute init The initalizer (not parsed - just a string)
class CPPEnumSpec < CPPObject

  attr_accessor :name, :init
  def_initializer :name, :init

  def to_s
    self.name + (self.init ? "=" + self.init : "")
  end

end

# @brief Describes an enum declaration
# @attribute name The name of the enum (a string)
# @attribute specs the enum members (an array of CPPEnumSpec objects)
class CPPEnum < CPPObject

  attr_accessor :name, :specs
  def_initializer :name, :specs

  def to_s
    "enum " + (self.name || "")
  end

  def dump(i)
    l = i + self.to_s + " {\n"
    l += (self.specs || []).collect { |s| i + "  " + s.to_s + "\n" }.join("")
    l += i + "}"
  end
  
end

# @brief The root object of the declaration tree
# @attribute decls The content of the module: an array of CPPTypedef, CPPNamespace (nested namespaces), CPPStructDeclaration, CPPEnumDeclaration or CPPDeclaration objects
class CPPModule < CPPObject

  attr_accessor :decls
  def_initializer :decls

  def dump
    (self.decls || []).collect { |d| d.dump("") }.join("\n")
  end

end