1 # $Id: resolver.rb,v 1.19 2012/04/17 02:49:40 machan Exp $
2
3 require 'tmdoc/tmstd'
4 require 'tmdoc/constant'
5 require 'tmdoc/environment'
6 require 'tmdoc/model/module'
7 require 'tmdoc/transformer/core-into-module/constant'
8
9
10 module TmDoc
11
12 module Transformer::CoreIntoModule
13
14 module Resolver
15 def self.resolve!(
16 mm_module, env, map_of_path_to_module
17 )
18 ASSERT.kind_of mm_module, MMLA::GenericModule
19 ASSERT.kind_of env, ENV::Environment
20 ASSERT.kind_of map_of_path_to_module, MMLA::MapOfPathToModule
21
22 LOG::Debug.msgout "CALLED" if env.debug?
23
24 for mm_extendee in mm_module.extendees
25 LOG::Debug.log(
26 "Resolving extend-directive: %s in %s",
27 mm_extendee.to_s, mm_module.to_s
28 ) if env.debug?
29
30 resolved_path = self.resolve_path!(
31 mm_extendee.extendee_path,
32 env,
33 :in_extending,
34 mm_module.above_path,
35 map_of_path_to_module
36 )
37 ASSERT.kind_of resolved_path, MMLP::AbsolutePath
38 LOG::Debug.log(
39 "Resolved extend module path: %s", resolved_path.to_s
40 ) if env.debug?
41 resolved_module = map_of_path_to_module.at resolved_path
42
43 unless resolved_module
44 LOG::Warning.log(
45 "I can't resolve extend-path: %s\n" +
46 "\t-- %s",
47 resolved_path.to_s, mm_extendee.to_s
48 )
49 CMD.test_sensitive_level env, LOG::Warning
50
51 next
52 end
53
54 if resolved_module.kind_of?(MMLA::GenericClass)
55 LOG::Warning.log(
56 "The extend-directive was expected path to module,\n" +
57 "\tbut actual is: %s\n\t-- %s",
58 resolved_module.to_s, mm_extendee.to_s
59 )
60 CMD.test_sensitive_level env, LOG::Warning
61
62 next
63 end
64
65 extendee_module_paths = mm_module.extendee_module_paths
66 if extendee_module_paths.include?(resolved_path)
67 LOG::Notice.log(
68 "Duplicated extend-path: %s\n\t-- %s",
69 resolved_path.to_s, mm_extendee.to_s
70 )
71 CMD.test_sensitive_level env, LOG::Notice
72
73 next
74 end
75
76 mm_module.extendee_module_paths.add! resolved_path
77 end
78
79 for mm_includee in mm_module.includees
80 LOG::Debug.log(
81 "Resolving include directive: %s in %s",
82 mm_includee.to_s, mm_module.to_s
83 ) if env.debug?
84
85 resolved_path = self.resolve_path!(
86 mm_includee.includee_path,
87 env,
88 :in_including,
89 mm_module.above_path,
90 map_of_path_to_module
91 )
92 ASSERT.kind_of resolved_path, MMLP::AbsolutePath
93 LOG::Debug.log(
94 "Resolved include module path: %s", resolved_path.to_s
95 ) if env.debug?
96 resolved_module = map_of_path_to_module.at resolved_path
97
98 unless resolved_module
99 LOG::Warning.log(
100 "I can't resolve include-path: %s\n" +
101 "\t-- %s",
102 resolved_path.to_s, mm_includee.to_s
103 )
104 CMD.test_sensitive_level env, LOG::Warning
105
106 next
107 end
108
109 if resolved_module.kind_of?(MMLA::GenericClass)
110 LOG::Warning.log(
111 "The include-directive was expected path to module,\n" +
112 "\tbut actual is: %s\n\t-- %s",
113 resolved_module.to_s, mm_includee.to_s
114 )
115 CMD.test_sensitive_level env, LOG::Warning
116
117 next
118 end
119
120 includee_module_paths = mm_module.includee_module_paths
121 if includee_module_paths.include?(resolved_path)
122 LOG::Notice.log(
123 "Duplicated include-path: %s\n\t-- %s",
124 resolved_path.to_s, mm_includee.to_s
125 )
126 CMD.test_sensitive_level env, LOG::Notice
127
128 next
129 end
130
131 mm_module.includee_module_paths.add! resolved_path
132 end
133
134 if mm_module.kind_of?(MMLA::ChildClass)
135 mm_class = mm_module
136 inherit_path_string = mm_class.inherit_path_string
137
138 if inherit_path_string
139 LOG::Debug.log(
140 "Resolving inherit class path: %s in %s",
141 inherit_path_string, mm_class.to_s
142 ) if env.debug?
143
144 resolved_path = self.resolve_path!(
145 inherit_path_string,
146 env,
147 :in_inheriting,
148 mm_class.above_path,
149 map_of_path_to_module
150 )
151 ASSERT.kind_of resolved_path, MMLP::AbsolutePath
152 LOG::Debug.log(
153 "Resolved inherit class path: %s", resolved_path.to_s
154 ) if env.debug?
155 resolved_class = map_of_path_to_module.at resolved_path
156
157 inherit_path =
158 if resolved_class
159 if resolved_class.kind_of?(MMLA::GenericClass)
160 resolved_path
161 else
162 LOG::Warning.log(
163 "The inherit-path was expected " +
164 "to class,\n" +
165 "\tbut actual is: %s\n\t-- %s",
166 resolved_class.to_s, mm_class.to_s
167 )
168 CMD.test_sensitive_level env, LOG::Warning
169
170 UNKNOWN_CLASS_PATH
171 end
172 else
173 LOG::Warning.log(
174 "I can't resolve inherit-path: %s\n" +
175 "\t-- %s",
176 resolved_path.to_s, mm_class.to_s
177 )
178 CMD.test_sensitive_level env, LOG::Warning
179
180 UNKNOWN_CLASS_PATH
181 end
182
183 mm_class.inherit_path! inherit_path
184 end
185 end
186
187 nil
188 end
189
190
191 def self.resolve_path!(
192 target_path_string,
193 env,
194 context_type,
195 context_path,
196 map_of_path_to_module
197 )
198 ASSERT.kind_of target_path_string, String
199 ASSERT.kind_of env, ENV::Environment
200 ASSERT.kind_of context_type, Symbol
201 ASSERT.kind_of context_path, MMLP::AbsolutePath
202 ASSERT.kind_of map_of_path_to_module, MMLA::MapOfPathToModule
203
204 resolved_path =
205 if /^::(.+)/ =~ target_path_string
206 self.resolve_absolute_path!(
207 MMLP::AbsolutePath.new($1.split(/::/)),
208 env,
209 context_type,
210 context_path,
211 map_of_path_to_module
212 )
213 else
214 self.resolve_relative_path!(
215 MMLP::RelativePath.new(target_path_string.split(/::/)),
216 env,
217 context_type,
218 context_path,
219 map_of_path_to_module
220 )
221 end
222
223 ASSERT.kind_of resolved_path, MMLP::AbsolutePath
224 end
225
226
227 def self.resolve_absolute_path!(
228 target_path,
229 env,
230 context_type,
231 context_path,
232 map_of_path_to_module
233 )
234 ASSERT.kind_of target_path, MMLP::AbsolutePath
235 ASSERT.kind_of env, ENV::Environment
236 ASSERT.kind_of context_type, Symbol
237 ASSERT.kind_of context_path, MMLP::AbsolutePath
238 ASSERT.kind_of map_of_path_to_module, MMLA::MapOfPathToModule
239
240 LOG::Debug.msgout "CALLED" if env.debug?
241
242 target_above_path, target_name = target_path.pop
243
244
245 # Case (1): The target is toplevel module.
246
247 if target_path.empty?
248 return ASSERT.kind_of target_path, MMLP::AbsolutePath
249 end
250
251
252 # Case (2): The target was found on searching path.
253
254 # Nop
255
256
257 # Case (3): The target was found in mapping table.
258
259 if map_of_path_to_module.at(target_path)
260 return ASSERT.kind_of target_path, MMLP::AbsolutePath
261 end
262
263 [
264 BUILTIN_MODULE_PATH,
265 UNKNOWN_MODULE_PATH
266 ].each { |special_path|
267 target_path_in_special =
268 special_path + MMLP::RelativePath.new(target_path.to_a)
269 if map_of_path_to_module.at(target_path_in_special)
270 LOG::Debug.log(
271 "Found the path: %s", target_path_in_special
272 ) if env.debug?
273
274 return ASSERT.kind_of(
275 target_path_in_special, MMLP::AbsolutePath
276 )
277 end
278 }
279
280
281 # Case (4): The target wasn't found, it may be a built-in object.
282
283 klass = nil
284 begin
285 klass = eval(target_path.join('::'))
286 rescue NameError
287 ; # nop
288 rescue SyntaxError => exception
289 LOG::Debug.log(
290 "Fail to eval: '%s' by %s",
291 target_path.to_s, exception.inspect
292 ) if env.debug?
293 end
294 if klass
295 resolved_path =
296 BUILTIN_MODULE_PATH +
297 MMLP::RelativePath.new(target_path.to_a)
298 resolved_above_path, resolved_name = resolved_path.pop
299
300 resolved_module = map_of_path_to_module.at resolved_path
301 unless resolved_module
302 args = [nil, resolved_above_path, resolved_name]
303 resolved_module =
304 if klass.kind_of?(::Class)
305 resolved_class = MMLN::Class.new *(
306 args + [
307 MMLA::SetOfModule.new, OBJECT_CLASS_NAME
308 ]
309 )
310 else
311 MMLN::Module.new *args
312 end
313
314 self.update_module!(
315 target_path,
316 resolved_module,
317 env,
318 context_type,
319 context_path,
320 map_of_path_to_module,
321 MM_BUILTIN_MODULE
322 )
323 end
324
325 return ASSERT.kind_of(
326 BUILTIN_MODULE_PATH +
327 MMLP::RelativePath.new(target_path.to_a),
328 MMLP::AbsolutePath
329 )
330 end
331
332
333 # Case (5): The target wasn't found, I see it as a unknown object.
334
335 resolved_path =
336 UNKNOWN_MODULE_PATH + MMLP::RelativePath.new(target_path.to_a)
337 resolved_above_path, resolved_name = resolved_path.pop
338
339 resolved_module = map_of_path_to_module.at resolved_path
340 unless resolved_module
341 args = [
342 nil, resolved_above_path, resolved_name,
343 MMLA::SetOfModule.new
344 ]
345 resolved_module =
346 case context_type
347 when :in_including, :in_extending
348 MMLN::Module.new(*args)
349 when :in_inheriting
350 resolved_class = MMLN::Class.new(
351 *(args << UNKNOWN_CLASS_NAME)
352 )
353 resolved_class.inherit_path! UNKNOWN_CLASS_PATH
354
355 resolved_class
356 else
357 ASSERT.abort(
358 "Unknown context_type_type: '%s'", context.to_s
359 )
360 end
361
362 self.update_module!(
363 target_path,
364 resolved_module,
365 env,
366 context_type,
367 context_path,
368 map_of_path_to_module,
369 MM_UNKNOWN_MODULE
370 )
371 end
372
373 ASSERT.kind_of(
374 UNKNOWN_MODULE_PATH + MMLP::RelativePath.new(target_path.to_a),
375 MMLP::AbsolutePath
376 )
377 end
378
379
380 def self.resolve_relative_path!(
381 target_path,
382 env,
383 context_type,
384 context_path,
385 map_of_path_to_module
386 )
387 ASSERT.kind_of target_path, MMLP::RelativePath
388 ASSERT.kind_of env, ENV::Environment
389 ASSERT.kind_of context_type, Symbol
390 ASSERT.kind_of context_path, MMLP::AbsolutePath
391 ASSERT.kind_of map_of_path_to_module, MMLA::MapOfPathToModule
392
393 LOG::Debug.msgout "CALLED" if env.debug?
394
395 target_above_path, target_name = target_path.pop
396
397
398 # Case (1): The target is toplevel module.
399
400 if target_path.empty?
401 return ASSERT.kind_of(
402 target_path.to_absolute, MMLP::AbsolutePath
403 )
404 end
405
406
407 # Case (2): The target was found on searching path.
408
409 testing_path = context_path.dup
410 until testing_path.empty?
411 resolved_path = testing_path + target_path
412 if map_of_path_to_module.at(resolved_path)
413 return ASSERT.kind_of resolved_path, MMLP::AbsolutePath
414 end
415
416 testing_path.pop!
417 end
418
419
420 # Case (3): The target was found in mapping table.
421
422 if map_of_path_to_module.at(target_path.to_absolute)
423 return ASSERT.kind_of(
424 target_path.to_absolute, MMLP::AbsolutePath
425 )
426 end
427
428 [
429 BUILTIN_MODULE_PATH,
430 UNKNOWN_MODULE_PATH
431 ].each { |special_path|
432 target_path_in_special = special_path + target_path
433 if map_of_path_to_module.at(target_path_in_special)
434 LOG::Debug.log(
435 "Found the path: %s", target_path_in_special
436 ) if env.debug?
437
438 return ASSERT.kind_of(
439 target_path_in_special, MMLP::AbsolutePath
440 )
441 end
442 }
443
444
445 # Case (4): The target wasn't found, it may be a built-in object.
446
447 klass = nil
448 begin
449 klass = eval('::' + target_path.join('::'))
450 rescue NameError
451 ; # nop
452 rescue SyntaxError => exception
453 LOG::Debug.log(
454 "Fail to eval: '%s' by %s",
455 target_path.to_s, exception.inspect
456 ) if env.debug?
457 end
458 if klass
459 resolved_path = BUILTIN_MODULE_PATH + target_path
460 resolved_above_path, resolved_name = resolved_path.pop
461
462 resolved_module = map_of_path_to_module.at resolved_path
463 unless resolved_module
464 args = [nil, resolved_above_path, resolved_name]
465 resolved_module =
466 if klass.kind_of?(::Class)
467 resolved_class = MMLN::Class.new *(
468 args + [
469 MMLA::SetOfModule.new, OBJECT_CLASS_NAME
470 ]
471 )
472 else
473 MMLN::Module.new *args
474 end
475
476 self.update_module!(
477 target_path,
478 resolved_module,
479 env,
480 context_type,
481 context_path,
482 map_of_path_to_module,
483 MM_BUILTIN_MODULE
484 )
485 end
486
487 return ASSERT.kind_of(
488 BUILTIN_MODULE_PATH + target_path,
489 MMLP::AbsolutePath
490 )
491 end
492
493
494 # Case (5): The target wasn't found, I see it as a unknown object.
495
496 resolved_path = UNKNOWN_MODULE_PATH + target_path
497 resolved_above_path, resolved_name = resolved_path.pop
498
499 resolved_module = map_of_path_to_module.at resolved_path
500 unless resolved_module
501 args = [
502 nil, resolved_above_path, resolved_name,
503 MMLA::SetOfModule.new
504 ]
505 resolved_module =
506 case context_type
507 when :in_including, :in_extending
508 MMLN::Module.new(*args)
509 when :in_inheriting
510 resolved_class = MMLN::Class.new(
511 *(args << UNKNOWN_CLASS_NAME)
512 )
513 resolved_class.inherit_path! UNKNOWN_CLASS_PATH
514
515 resolved_class
516 else
517 ASSERT.abort(
518 "Unknown context_type_type: '%s'", context.to_s
519 )
520 end
521
522 self.update_module!(
523 target_path,
524 resolved_module,
525 env,
526 context_type,
527 context_path,
528 map_of_path_to_module,
529 MM_UNKNOWN_MODULE
530 )
531 end
532
533
534 ASSERT.kind_of(
535 UNKNOWN_MODULE_PATH + target_path, MMLP::AbsolutePath
536 )
537 end
538
539
540 def self.update_module!(
541 target_path,
542 mm_module,
543 env,
544 context_type,
545 context_path,
546 map_of_path_to_module,
547 mm_root_module
548 )
549 ASSERT.kind_of(
550 target_path, Model::Abstraction::Path::Abstract
551 )
552 ASSERT.kind_of mm_module, MMLA::GenericModule
553 ASSERT.kind_of env, ENV::Environment
554 ASSERT.kind_of context_type, Symbol
555 ASSERT.kind_of context_path, MMLP::AbsolutePath
556 ASSERT.kind_of map_of_path_to_module, MMLA::MapOfPathToModule
557 ASSERT.kind_of mm_root_module, MMLA::RootModule
558
559 LOG::Debug.msgout "CALLED" if env.debug?
560
561 target_above_path, target_name = target_path.pop
562
563 LOG::Debug.log(
564 "[BEGIN TO RESOLVE] target above path: '%s' of\n" +
565 "\tmodule: '%s'",
566 target_above_path.to_s, mm_module.to_s
567 ) if env.debug?
568 resolved_above_module =
569 if target_above_path.empty?
570 mm_root_module
571 else
572 work_above_path =
573 if target_above_path.kind_of?(MMLP::AbsolutePath)
574 target_above_path
575 else
576 # Recursive calling !!
577 self.resolve_relative_path!(
578 target_above_path,
579 env,
580 context_type,
581 context_path,
582 map_of_path_to_module
583 )
584 end
585 map_of_path_to_module.at work_above_path
586 end
587 unless resolved_above_module.kind_of?(MMLA::GenericModule)
588 LOG::Notice.log(
589 "Unexpected name resolving fail: %s", target_above_path.to_s
590 ) if env.debug?
591
592 return nil
593 end
594 ASSERT.kind_of(resolved_above_module, MMLA::GenericModule,
595 "resolved_above_module: %s<%s>, target_above_path: %s",
596 if resolved_above_module.respond_to?(:to_s)
597 resolved_above_module.to_s
598 else
599 ''
600 end,
601 resolved_above_module.class.to_s,
602 target_above_path.to_s
603 )
604
605 LOG::Debug.log(
606 "[END TO RESOLVE] above module: '%s' of\n" +
607 "\ttarget above path: '%s'",
608 resolved_above_module.to_s, target_above_path.to_s
609 ) if env.debug?
610
611 unless resolved_above_module.below_modules.include?(
612 mm_module
613 ) || map_of_path_to_module.include?(
614 mm_module.path
615 )
616 LOG::Debug.log(
617 "Add found module: '%s' in '%s'",
618 mm_module.to_s, context_path.to_s
619 ) if env.debug?
620
621 resolved_above_module.add! mm_module
622 map_of_path_to_module.update!(
623 mm_module.path, mm_module
624 )
625 else
626 LOG::Debug.log(
627 "Duplcated module: '%s' in '%s'",
628 mm_module.to_s, context_path.to_s
629 ) if env.debug?
630 end
631
632
633 if mm_module.kind_of?(MMLA::GenericClass)
634 mm_class = mm_module
635
636 LOG::Debug.log(
637 "[BEGIN TO RESOLVE] target class: '%s'", mm_class.to_s
638 ) if env.debug?
639
640 mm_class_path = mm_class.path
641 get_path_str =
642 case mm_class_path.first
643 when 'TmDoc', 'TmStd'
644 nil
645 when BUILTIN_MODULE_NAME, UNKNOWN_MODULE_NAME
646 array = mm_class_path.to_a.dup
647 array.shift
648
649 '::' + array.join('::')
650 else
651 mm_class_path.to_s
652 end
653 klass = nil
654 if get_path_str
655 begin
656 klass = eval(get_path_str)
657 LOG::Debug.log(
658 "Success to eval: '%s'", get_path_str
659 ) if env.debug?
660 rescue NameError, SyntaxError => exception
661 LOG::Debug.log(
662 "Fail to eval: '%s' by %s",
663 get_path_str, exception.inspect
664 ) if env.debug?
665 end
666 end
667
668 resolved_superclass =
669 if klass
670 ASSERT.kind_of klass, ::Class
671
672 superklass = klass.superclass
673 if superklass == ::Object
674 MM_OBJECT_CLASS
675 else
676 # Recursive calling !!
677 work_superclass_path =
678 self.resolve_relative_path!(
679 MMLP::RelativePath.new(
680 superklass.name.split(/::/)
681 ),
682 env,
683 context_type,
684 TOPLEVEL_MODULE_PATH,
685 map_of_path_to_module
686 )
687 map_of_path_to_module.at work_superclass_path
688 end
689 else
690 MM_UNKNOWN_CLASS
691 end
692
693 ASSERT.kind_of resolved_superclass, MMLA::GenericClass
694 LOG::Debug.log(
695 "[END TO RESOLVE] superclass: '%s' of\n" +
696 "\ttarget class path: '%s'",
697 resolved_superclass.to_s, mm_class.path.to_s
698 ) if env.debug?
699
700 unless mm_class.inherit_path
701 mm_class.inherit_path_string! resolved_superclass.name
702 mm_class.inherit_path! resolved_superclass.path
703 end
704 end
705
706 nil
707 end
708 end
709
710 end # TmDoc::Transformer::CoreIntoModule
711
712 end # TmDoc