File: transformer/core-into-module/resolver.rb

Overview
Module Structure
Code

Overview

Module Structure

  module: <Toplevel Module>
  module: TmDoc#10
  module: Transformer
  module: CoreIntoModule#12
  module: Resolver#14
has properties
module method: resolve! / 3 #15
module method: resolve_path! / 5 #191
module method: resolve_absolute_path! / 5 #227
module method: resolve_relative_path! / 5 #380
module method: update_module! / 7 #540

Code

   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