1 # $Id: logical.rb,v 1.26 2012/01/25 10:06:01 machan Exp $
2
3
4 require 'tmdoc/tmstd'
5 require 'tmdoc/tmstd/treeable'
6 require 'tmdoc/constant'
7
8
9 module TmDoc
10
11 module Model::Module::Logical
12
13 module Path
14
15 class AbsolutePath < Model::Abstraction::Path::Absolute
16 include TmStd::Lsm::Collection::Sequence::Mutable
17
18 LSM_ELEMENT_CLASS = String
19 PATH_SEPARATOR_STRING = '::'
20 end
21
22
23
24 class RelativePath < Model::Abstraction::Path::Relative
25 include TmStd::Lsm::Collection::Sequence::Mutable
26
27 LSM_ELEMENT_CLASS = String
28 PATH_SEPARATOR_STRING = '::'
29 ABSOLUTE_PATH_CLASS = AbsolutePath
30 end
31
32
33
34 class SetOfPath < Model::Abstraction::Path::SetOfPath
35 include TmStd::Lsm::Collection::Set::Mutable
36
37 LSM_ELEMENT_CLASS = Path::AbsolutePath
38 end
39
40 end
41
42
43
44 module Abstraction
45
46 class Subject < Model::Abstraction::Subject::LogicalSubject; end
47
48
49 class SeqOfSubject < Model::Abstraction::Subject::SeqOfLogicalSubject
50 LSM_ELEMENT_CLASS = Subject
51 end
52
53
54 class SetOfSubject < Model::Abstraction::Subject::SetOfLogicalSubject
55 include TmStd::Lsm::Collection::Set::Mutable
56
57 LSM_ELEMENT_CLASS = Subject
58 end
59
60
61
62 class LeafSubject < Subject
63 def initialize(location, above_path, name = nil, seq_num = 0)
64 ASSERT.opt_kind_of location, Location
65 ASSERT.kind_of above_path, Path::AbsolutePath
66 ASSERT.opt_kind_of name, String
67 ASSERT.kind_of seq_num, Integer
68
69 super(location, above_path, name, seq_num)
70 end
71
72
73 def to_s(label, opt_str = nil)
74 str = format("%s %s%s%s%s%s",
75 label,
76
77 self.above_path.to_s,
78
79 if self.name
80 ' ' + self.name
81 else
82 ''
83 end,
84
85 if self.seq_num >= 1
86 format(" [#%d]", self.seq_num)
87 else
88 ''
89 end,
90
91 if opt_str
92 ' ' + opt_str
93 else
94 ''
95 end,
96
97 if self.location
98 format(" -- %s", self.location.to_s)
99 else
100 ''
101 end
102 )
103
104 ASSERT.kind_of str, String
105 end
106 end
107
108 class SeqOfLeafSubject < SeqOfSubject
109 LSM_ELEMENT_CLASS = LeafSubject
110 end
111
112 class SetOfLeafSubject < SetOfSubject
113 LSM_ELEMENT_CLASS = LeafSubject
114 end
115
116
117
118 class PairOfUniqueNumber < TmStd::Lsm::Product::Abstract
119 attr_reader :num,
120 :max_num
121
122
123 def initialize(num, max_num)
124 ASSERT.kind_of num, Integer
125 ASSERT.kind_of max_num, Integer
126
127 @num = num
128 @max_num = max_num
129 end
130 end
131
132 UNIQUE_PAIR_OF_UNIQUE_NUMBER = PairOfUniqueNumber.new(0, 0)
133
134
135
136 class MapOfPropertyToUniqueNumber < TmStd::Lsm::Collection::Map::Abstract
137 LSM_DOMAIN_CLASS = LeafSubject
138 LSM_RANGE_CLASS = PairOfUniqueNumber
139 end
140
141 EMPTY_MAP_OF_PROPERTY_TO_UNIQUE_NUMBER = MapOfPropertyToUniqueNumber.new
142
143
144
145 class Directive < LeafSubject
146 attr_reader :value
147
148
149 def initialize(location, above_path, seq_num, value)
150 ASSERT.kind_of location, Location
151 ASSERT.kind_of above_path, Path::AbsolutePath
152 ASSERT.kind_of seq_num, Integer
153 ASSERT.kind_of value, String
154
155 super(location, above_path, nil, seq_num)
156
157 @value = value
158 end
159
160
161 def path
162 p = self.above_path << self.label
163
164 ASSERT.kind_of p, Path::Absolute
165 end
166
167
168 def to_s(label)
169 str = super label, format(" '%s'", self.value)
170
171 ASSERT.kind_of str, String
172 end
173 end
174
175
176
177 class Property < LeafSubject
178 attr_reader :value, :does_attach_to_instance
179
180 alias attach_to_instance? does_attach_to_instance
181
182
183 def initialize(
184 location, above_path, name, seq_num,
185 value = nil, does_attach_to_instance = false
186 )
187 ASSERT.kind_of location, Location
188 ASSERT.kind_of above_path, Path::AbsolutePath
189 ASSERT.kind_of seq_num, Integer
190 ASSERT.kind_of name, String
191 ASSERT.opt_kind_of value, String
192 ASSERT.boolean does_attach_to_instance
193
194 super(location, above_path, name, seq_num)
195
196 @value = value
197 @does_attach_to_instance = does_attach_to_instance
198 end
199
200
201 def path
202 p = self.above_path << self.label
203
204 ASSERT.kind_of p, Path::Absolute
205 end
206
207
208 def to_s(label, opt_str = nil)
209 ASSERT.opt_kind_of opt_str, String
210
211 str = super(
212 label,
213
214 format("%s%s%s",
215 if self.attach_to_instance?
216 ' [I]'
217 else
218 ''
219 end,
220
221 if self.value
222 format(" '%s'", self.value)
223 else
224 ''
225 end,
226
227 if opt_str
228 ' ' + opt_str
229 else
230 ''
231 end
232 )
233 )
234
235 ASSERT.kind_of str, String
236 end
237 end
238
239 class SetOfProperty < TmStd::Lsm::Collection::Set::Abstract
240 include TmStd::Lsm::Collection::Set::Mutable
241
242 LSM_ELEMENT_CLASS = Property
243 end
244
245
246
247 class GenericModule < Subject
248 include TmStd::Treeable
249
250 attr_reader :locations,
251 :below_modules,
252 :constants,
253 :properties,
254 :extendees,
255 :extendee_module_paths,
256 :includees,
257 :includee_module_paths
258
259
260 def initialize(
261 location,
262 above_path,
263 name,
264 below_modules = SetOfModule.new
265 )
266 ASSERT.opt_kind_of location, Location
267 ASSERT.kind_of above_path, Path::AbsolutePath
268 ASSERT.kind_of name, String
269 ASSERT.kind_of below_modules, SetOfModule
270
271 super nil, above_path, name
272
273 @locations = SetOfLocation.new(
274 if location then [location] else [] end
275 )
276
277 @constants = MMLL::SetOfConstant.new
278 @properties = MMLA::SetOfProperty.new
279 @extendees = MMLL::SetOfExtend.new
280 @includees = MMLL::SetOfInclude.new
281
282 @below_modules = below_modules
283 for below_module in below_modules
284 if below_module.kind_of?(ChildModule)
285 below_module.an_above_module! self
286 end
287 end
288
289 @extendee_module_paths = Path::SetOfPath.new
290 @includee_module_paths = Path::SetOfPath.new
291 end
292
293
294 def to_s(label = 'module', opt_str = nil)
295 ASSERT.kind_of label, String
296 ASSERT.opt_kind_of opt_str, String
297
298 str = format("%s %s(%s)%s",
299 label,
300
301 self.name,
302
303 self.above_path.to_s,
304
305 if opt_str then opt_str else '' end
306 )
307
308 ASSERT.kind_of str, String
309 end
310
311
312 def print(indent)
313 ASSERT.kind_of indent, Integer
314
315 super
316
317 is = "\t" * indent
318 is1 = "\t" * (indent + 1)
319
320 unless self.locations.empty?
321 LOG::Debug.log "%slocations:", is
322 for loc in self.locations.sort
323 LOG::Debug.log "%s%s", is1, loc.to_s
324 end
325 end
326
327 cos = self.constants
328 unless cos.empty?
329 LOG::Debug.log "%sconstants:", is
330 for co in cos.sort
331 LOG::Debug.log "%s%s", is1, co.to_s
332 end
333 end
334
335 prs = self.properties
336 unless prs.empty?
337 LOG::Debug.log "%sproperties:", is
338 for pr in prs.sort
339 LOG::Debug.log "%s%s", is1, pr.to_s
340 end
341 end
342
343 bms = self.below_modules
344 unless bms.empty?
345 LOG::Debug.log "%sbelow_modules:", is
346 for bm in bms.sort
347 LOG::Debug.log "%s%s", is1, bm.to_s
348 end
349 end
350
351 emes = self.extendees
352 unless emes.empty?
353 LOG::Debug.log "%sextendees:", is
354 for eme in emes.sort
355 LOG::Debug.log "%s%s", is1, eme.to_s
356 end
357 end
358
359 emps = self.extendee_module_paths
360 unless emps.empty?
361 LOG::Debug.log "%sextendee_module_paths:", is
362 for emp in emps.sort
363 LOG::Debug.log "%s%s", is1, emp.to_s
364 end
365 end
366
367 imes = self.includees
368 unless imes.empty?
369 LOG::Debug.log "%sincludees:", is
370 for ime in imes.sort
371 LOG::Debug.log "%s%s", is1, ime.to_s
372 end
373 end
374
375 imps = self.includee_module_paths
376 unless imps.empty?
377 LOG::Debug.log "%sincludee_module_paths:", is
378 for imp in imps.sort
379 LOG::Debug.log "%s%s", is1, imp.to_s
380 end
381 end
382
383 nil
384 end
385
386
387 def location
388 loc = unless self.locations.empty?
389 self.locations.sort.first
390 else
391 nil
392 end
393
394 ASSERT.opt_kind_of loc, MML::Location
395 end
396
397
398 def each(&block)
399 self.below_modules.sort.each(&block)
400
401 nil
402 end
403
404
405 def children
406 belows = self.below_modules.sort
407
408 ASSERT.kind_of belows, Array
409 end
410
411
412 def empty?
413 result = self.below_modules.empty?
414
415 ASSERT.boolean result
416 end
417
418
419 def add!(below_module)
420 ASSERT.kind_of below_module, ChildModule
421
422 ASSERT.assert(
423 !(self.below_modules.include?(below_module)),
424 "Duplicated module: '%s' is adding to '%s'.\n",
425 below_module.to_s, self.to_s
426 )
427
428 below_module.an_above_module! self
429 self.below_modules.add! below_module
430
431 nil
432 end
433
434
435 def map_of_property_to_uniq_num
436
437 map = self.properties.inject({}) {
438 |hash_of_name_to_properties, property|
439
440 hash_of_name_to_properties.merge(
441 property.name => [property]
442 ) { |_, self_properties, other_properties|
443
444 self_properties + other_properties
445 }
446 }.values.inject(
447 Abstraction::EMPTY_MAP_OF_PROPERTY_TO_UNIQUE_NUMBER
448 ) { |map_of_property_to_uniq_num, properties|
449 max_uniq_num = properties.length
450
451 map_of_property_to_uniq_num.merge(
452 if max_uniq_num <= 1
453 Abstraction::MapOfPropertyToUniqueNumber.new(
454 properties.first =>
455 Abstraction::UNIQUE_PAIR_OF_UNIQUE_NUMBER
456 )
457 else
458 MMLA::SeqOfLeafSubject.new(
459 properties.sort
460 ).map_with_index { |property, index|
461 [property, index]
462 }.inject(
463 Abstraction::EMPTY_MAP_OF_PROPERTY_TO_UNIQUE_NUMBER
464 ) { |map, pair|
465 ASSERT.tuple_of(
466 pair,
467 [Abstraction::LeafSubject, Integer]
468 )
469 property, index = pair
470
471 map.update(
472 property,
473 Abstraction::PairOfUniqueNumber.new(
474 index + 1, max_uniq_num
475 )
476 )
477 }
478 end
479 )
480 }
481
482 ASSERT.kind_of map, Abstraction::MapOfPropertyToUniqueNumber
483 end
484 end
485
486
487 class SetOfModule < SetOfSubject
488 LSM_ELEMENT_CLASS = GenericModule
489 end
490
491
492
493 class MapOfPathToModule < TmStd::Lsm::Collection::Map::Abstract
494 include TmStd::Lsm::Collection::Map::Mutable
495
496 LSM_DOMAIN_CLASS = Path::AbsolutePath
497 LSM_RANGE_CLASS = GenericModule
498 end
499
500
501
502 class RootModule < GenericModule
503 def initialize(
504 above_path,
505 name,
506 below_modules = SetOfModule.new
507 )
508 ASSERT.kind_of above_path, Path::AbsolutePath
509 ASSERT.kind_of name, String
510 ASSERT.kind_of below_modules, SetOfModule
511
512 super(nil, above_path, name, below_modules)
513 end
514 end
515
516
517
518 class ChildModule < GenericModule
519 attr_reader :an_above_module
520
521
522 def initialize(
523 location,
524 above_path,
525 name,
526 below_modules = SetOfModule.new
527 )
528 ASSERT.opt_kind_of location, Location
529 ASSERT.kind_of above_path, Path::AbsolutePath
530 ASSERT.kind_of name, String
531 ASSERT.kind_of below_modules, SetOfModule
532
533 super
534
535 @an_above_module = nil
536 end
537
538
539 def an_above_module!(an_above_module)
540 ASSERT.kind_of an_above_module, Abstraction::GenericModule
541
542 ASSERT.assert(
543 (! @an_above_module),
544 "Duplicated setting, '%s' is above of '%s'.\n",
545 @an_above_module.to_s, an_above_module.to_s
546 )
547
548 @an_above_module = an_above_module
549
550 nil
551 end
552
553
554 def print(indent)
555 ASSERT.kind_of indent, Integer
556
557 super
558
559 is = "\t" * indent
560
561 am = self.an_above_module
562 if am
563 LOG::Debug.log "%san_above_module: %s", is, am.to_s
564 end
565
566 nil
567 end
568 end
569
570
571
572 class GenericClass < ChildModule
573 def to_s(opt_str = nil)
574 str = super('class', opt_str)
575
576 ASSERT.kind_of str, String
577 end
578 end
579
580
581
582 class ChildClass < GenericClass
583 attr_reader :inherit_path_string, :inherit_path
584
585
586 def initialize(
587 location, above_path, name, below_modules, inherit_path_string
588 )
589 ASSERT.opt_kind_of location, Location
590 ASSERT.kind_of above_path, Path::AbsolutePath
591 ASSERT.kind_of name, String
592 ASSERT.kind_of below_modules, SetOfModule
593 ASSERT.kind_of inherit_path_string, String, name
594
595 super(location, above_path, name, below_modules)
596
597 @inherit_path_string = inherit_path_string
598 @inherit_path = nil
599 end
600
601
602 def to_s
603 str = super(' < ' + self.inherit_path_string)
604
605 ASSERT.kind_of str, String
606 end
607
608
609 def print(indent)
610 ASSERT.kind_of indent, Integer
611
612 super
613
614 is = "\t" * indent
615
616 LOG::Debug.log(
617 "%sinherit_path_string: %s", is, self.inherit_path_string
618 )
619
620 ip = self.inherit_path
621 if ip
622 LOG::Debug.log "%sinherit_path: %s", is, ip.to_s
623 end
624
625 nil
626 end
627
628
629 def inherit_path_string!(new_str)
630 ASSERT.kind_of new_str, String
631
632 @inherit_path_string = new_str
633
634 nil
635 end
636
637
638 def inherit_path!(path)
639 ASSERT.kind_of path, Path::AbsolutePath
640
641 @inherit_path = path
642
643 nil
644 end
645 end
646
647 end # TmDoc::Model::Module::Abstraction
648
649
650
651 module Leaf
652
653 class Constant < Abstraction::LeafSubject
654 attr_reader :value
655 attr_reader :hash
656
657
658 def initialize(location, above_path, name, value)
659 ASSERT.kind_of location, Location
660 ASSERT.kind_of above_path, Path::AbsolutePath
661 ASSERT.kind_of name, String
662 ASSERT.kind_of value, String
663
664 super(location, above_path, name)
665
666 @hash = format("%s %s", above_path.to_s, name).hash
667
668 @value = value
669 end
670
671
672 def eql?(other)
673 result = if Constant >= other.class then true else false end &&
674 self.above_path == other.above_path &&
675 self.name == other.name
676
677 ASSERT.boolean result
678 end
679
680
681 def to_s(show_value = true)
682 ASSERT.boolean show_value
683
684 value_str = if show_value
685 format(" = %s", self.value)
686 else
687 nil
688 end
689
690 str = super 'constant', value_str
691
692 ASSERT.kind_of str, String
693 end
694 end
695
696
697 class SetOfConstant < Abstraction::SetOfLeafSubject
698 LSM_ELEMENT_CLASS = Constant
699 end
700
701
702
703 class Alias < Abstraction::Property
704 alias orig_name value
705
706
707 def initialize(
708 location, above_path, name, orig_name,
709 does_attach_to_instance
710 )
711 ASSERT.kind_of location, Location
712 ASSERT.kind_of above_path, Path::AbsolutePath
713 ASSERT.kind_of name, String
714 ASSERT.kind_of orig_name, String
715 ASSERT.boolean does_attach_to_instance
716
717 super(
718 location, above_path, name, 0,
719 orig_name, does_attach_to_instance
720 )
721 end
722
723
724 def to_s
725 str = super 'alias'
726
727 ASSERT.kind_of str, String
728 end
729 end
730
731
732
733 class Attribute < Abstraction::Property
734 attr_reader :accessor
735
736
737 def initialize(
738 location, above_path, name, seq_num, accessor,
739 does_attach_to_instance
740 )
741 ASSERT.kind_of location, Location
742 ASSERT.kind_of above_path, Path::AbsolutePath
743 ASSERT.kind_of name, String
744 ASSERT.kind_of seq_num, Integer
745 ASSERT.kind_of accessor, Symbol
746 ASSERT.boolean does_attach_to_instance
747
748 super(
749 location, above_path, name, seq_num,
750 nil, does_attach_to_instance
751 )
752
753 @accessor = accessor
754 end
755
756
757 def to_s
758 str = super 'attribute', format("[%s]", self.accessor)
759
760 ASSERT.kind_of str, String
761 end
762 end
763
764
765
766 class Method < Abstraction::Property
767 attr_reader :args, :is_module_func
768
769 alias module_func? is_module_func
770
771
772 def initialize(
773 location, above_path, name, args,
774 does_attach_to_instance, is_module_func
775 )
776 ASSERT.kind_of location, Location
777 ASSERT.kind_of above_path, Path::AbsolutePath
778 ASSERT.kind_of name, String
779 ASSERT.kind_of args, LSM::SeqOfString
780 ASSERT.boolean does_attach_to_instance
781 ASSERT.boolean is_module_func
782
783 super(location, above_path, name, 0, nil, does_attach_to_instance)
784
785 @args = args
786 @is_module_func = is_module_func
787 end
788
789
790 def to_s
791 str = super(
792 'method',
793
794 [
795 unless self.args.empty?
796 format "(%s)", self.args.join(', ')
797 else
798 ''
799 end,
800
801 if self.module_func?
802 '[F]'
803 else
804 ''
805 end
806 ].join(' ')
807 )
808
809 ASSERT.kind_of str, String
810 end
811 end
812
813
814
815 class Extend < Abstraction::Directive
816 alias extendee_path value
817
818
819 def to_s
820 str = super 'extend'
821
822 ASSERT.kind_of str, String
823 end
824 end
825
826
827 class SetOfExtend < Abstraction::SetOfLeafSubject
828 LSM_ELEMENT_CLASS = Extend
829 end
830
831
832
833 class Include < Abstraction::Directive
834 alias includee_path value
835
836
837 def to_s
838 str = super 'include'
839
840 ASSERT.kind_of str, String
841 end
842 end
843
844
845 class SetOfInclude < Abstraction::SetOfLeafSubject
846 LSM_ELEMENT_CLASS = Include
847 end
848
849 end # TmDoc::Model::Module::Logical::Leaf
850
851
852
853 module Node
854
855 class ToplevelModule < Abstraction::RootModule; end
856
857
858
859 class BuiltinModule < Abstraction::RootModule; end
860
861
862
863 class UnknownModule < Abstraction::RootModule; end
864
865
866
867 class Module < Abstraction::ChildModule; end
868
869
870
871 class Object < Abstraction::GenericClass
872 def initialize(above_path, name)
873 ASSERT.kind_of above_path, Path::AbsolutePath
874 ASSERT.kind_of name, String
875
876 super(nil, above_path, name)
877 end
878 end
879
880
881
882 class Class < Abstraction::ChildClass; end
883
884
885
886 class UnknownClass < Node::Class
887 def initialize(above_path, name, inherit_path_string)
888 ASSERT.kind_of above_path, Path::AbsolutePath
889 ASSERT.kind_of name, String
890 ASSERT.kind_of inherit_path_string, String
891
892 super(
893 nil,
894 above_path,
895 name,
896 Abstraction::SetOfModule.new,
897 inherit_path_string
898 )
899 end
900 end
901
902 end # TmDoc::Model::Module::Logical::Node
903
904
905
906 class Location < Model::Abstraction::Location
907 def initialize(file, line_num)
908 ASSERT.kind_of file, MMP::File
909 ASSERT.kind_of line_num, Integer
910
911 super(file, line_num)
912 end
913 end
914
915
916
917 class SetOfLocation < Model::Abstraction::SetOfLocation
918 include TmStd::Lsm::Collection::Set::Mutable
919
920 LSM_ELEMENT_CLASS = Location
921 end
922
923 end # TmDoc::Model::Module::Logical
924
925 end # TmDoc