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

Overview
Module Structure
Class Hierarchy
Code

Overview

Module Structure

  module: <Toplevel Module>
  module: TmDoc#10
  module: Transformer
  module: CoreIntoModule#12
  module: Evaluater#14
has properties
module method: evaluate! / 4 #25
module method: evaluate_module! / 7 #176
module method: evaluate_directive! / 6 #236
module method: evaluate_property_or_method! / 6 #295
module method: resolve_module_name! / 3 #377
module method: validate_class_consistency! / 4 #458
  class: MapOfPathToModuleFuncNames#16
includes
  Mutable ( TmStd::Lsm::Collection::Map )
inherits from
  Abstract ( TmStd::Lsm::Collection::Map )
has properties
constant: LSM_DOMAIN_CLASS #19
constant: LSM_RANGE_CLASS #20

Code

   1  # $Id: evaluater.rb,v 1.41 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 Evaluater
  15 
  16  class MapOfPathToModuleFuncNames < TmStd::Lsm::Collection::Map::Abstract
  17      include TmStd::Lsm::Collection::Map::Mutable
  18 
  19      LSM_DOMAIN_CLASS    = MMLP::AbsolutePath
  20      LSM_RANGE_CLASS     = LSM::MutableSetOfString
  21  end
  22 
  23 
  24 
  25      def self.evaluate!(
  26          mc_toplevel_module, env, map_of_path_to_module, mm_file
  27      )
  28          ASSERT.kind_of mc_toplevel_module,      MCLN::ToplevelModule
  29          ASSERT.kind_of env,                     ENV::Environment
  30          ASSERT.kind_of map_of_path_to_module,   MMLA::MapOfPathToModule
  31          ASSERT.kind_of mm_file,                 MMP::File
  32 
  33          LOG::Debug.msgout "CALLED" if env.debug?
  34 
  35          map_of_path_to_func_names = MapOfPathToModuleFuncNames.new
  36 
  37          for mc_record in mc_toplevel_module.traverse(env)
  38              mc_above_path   = mc_record.path
  39              mc_name         = mc_record.name
  40              mc_subject      = mc_record.subject
  41              line_num        = mc_subject.line_num
  42              mm_location     = MML::Location.new mm_file, line_num
  43 
  44              if env.debug?
  45                  LOG::Debug.log(
  46                      "mc_above_path: %s, mc_name: %s, mc_subject: %s",
  47                      mc_above_path.to_s, mc_name, mc_subject.to_s
  48                  )
  49 
  50                  for path in map_of_path_to_module.domains.sort
  51                      LOG::Debug.log "path: %s", path
  52                      m = map_of_path_to_module.at path
  53                      LOG::Debug.log "\tmm_module: %s", m.to_s
  54                  end
  55              end
  56 
  57              mm_above_path   = MMLP::AbsolutePath.new mc_above_path.to_a
  58              mm_above_module = map_of_path_to_module.at mm_above_path
  59              unless mm_above_module
  60                  mm_above_module = map_of_path_to_module.at(
  61                      BUILTIN_MODULE_PATH +
  62                      MMLP::RelativePath.new(mm_above_path.to_a)
  63                  )
  64              end
  65              unless mm_above_module
  66                  LOG::Error.log(
  67                      "Failed to resolve the module/class name: %s\n" +
  68                          "\tat %s in %s",
  69                      mm_above_path.to_s,
  70                          mc_subject.to_s, mm_file.to_s
  71                  )
  72                  CMD.test_sensitive_level env, LOG::Error
  73                  next
  74              end
  75              ASSERT.kind_of(
  76                  mm_above_module, MMLA::GenericModule,
  77                  "mm_above_path: %s", mm_above_path
  78              )
  79 
  80              case mc_subject
  81              when MCLA::NodeSubject
  82                  mc_node_subject = mc_subject
  83 
  84                  case mc_node_subject
  85                  when MCLN::Module
  86                      self.evaluate_module!(
  87                          mc_node_subject,    mm_location,
  88                          mm_above_path,      mm_above_module,        mc_name,
  89                          env,                map_of_path_to_module
  90                      )
  91 
  92                      mm_module_path = mm_above_path << mc_name
  93                      if mc_record.module_func_names
  94                          LOG::Debug.log(
  95                              "mc_record.module_func_names: %s -- #%d",
  96                              mc_record.module_func_names.inspect, __LINE__
  97                          ) if env.debug?
  98 
  99                          module_func_names   = map_of_path_to_func_names.at(
 100                              mm_module_path
 101                          )
 102 
 103                          if module_func_names
 104                              module_func_names.union!(
 105                                  [mc_record.module_func_names]
 106                              )
 107                          else
 108                              map_of_path_to_func_names.update!(
 109                                  mm_module_path, mc_record.module_func_names
 110                              )
 111                          end
 112                      end
 113                  when MCLN::Method
 114                      self.evaluate_property_or_method!(
 115                          mc_node_subject,    mm_location,
 116                          mm_above_path,      mm_above_module,
 117                          env,                map_of_path_to_func_names
 118                      )
 119                  else
 120                      ASSERT.abort(
 121                          "Unknown node subject: %s(%s)",
 122                          mc_node_subject.to_s, mc_node_subject.class
 123                      )
 124                  end
 125 
 126              when MCLA::LeafSubject
 127                  mc_property = mc_subject
 128 
 129                  case mc_property
 130                  when MCLA::Directive
 131                      self.evaluate_directive!(
 132                          mc_property,    mm_location,
 133                          mm_above_path,  mm_above_module,
 134                          env,            mm_file
 135                      )
 136                  when MCLL::Constant
 137                      mm_constant = MMLL::Constant.new(
 138                          mm_location, mm_above_path,
 139                          mc_property.name,
 140                          mc_property.value
 141                      )
 142 
 143                      unless mm_above_module.constants.include?(mm_constant)
 144                          mm_above_module.constants.add! mm_constant
 145                      else
 146                          LOG::Warning.log(
 147                              "Conflicted constant definiation: %s",
 148                              mm_constant.to_s(false)
 149                          )
 150                      end
 151                  when MCLA::Property
 152                      self.evaluate_property_or_method!(
 153                          mc_property,    mm_location,
 154                          mm_above_path,  mm_above_module,
 155                          env,            map_of_path_to_func_names
 156                      )
 157                  else
 158                      ASSERT.abort(
 159                          "Unknown property: %s(%s)",
 160                          mc_property.to_s, mc_property.class
 161                      )
 162                  end
 163 
 164              else
 165                  ASSERT.abort(
 166                      "Unknown subject: %s(%s)",
 167                      mc_subject.to_s, mc_subject.class
 168                  )
 169              end
 170          end
 171 
 172          nil
 173      end
 174 
 175 
 176      def self.evaluate_module!(
 177          mc_module, mm_location, mm_above_path, mm_above_module, name, env,
 178          map_of_path_to_module
 179      )
 180          ASSERT.kind_of mc_module,               MCLA::NodeSubject
 181          ASSERT.kind_of mm_location,             MML::Location
 182          ASSERT.kind_of mm_above_path,           MMLP::AbsolutePath
 183          ASSERT.kind_of mm_above_module,         MMLA::GenericModule
 184          ASSERT.kind_of name,                    String
 185          ASSERT.kind_of env,                     ENV::Environment
 186          ASSERT.kind_of map_of_path_to_module,   MMLA::MapOfPathToModule
 187 
 188          mm_module_path  = mm_above_path << name
 189 
 190          mm_module = self.resolve_module_name!(
 191              mm_module_path, env, map_of_path_to_module
 192          )
 193          if mm_module
 194              LOG::Debug.log(
 195                  "Distributed module definiation: %s",
 196                  mc_module.to_s
 197              ) if env.debug?
 198 
 199              if mm_module.kind_of?(MMLA::ChildClass)
 200                  self.validate_class_consistency!(
 201                      mc_module, mm_location, mm_module, env
 202                  )
 203              end
 204 
 205              mm_module.locations.add! mm_location
 206          else
 207              LOG::Debug.log(
 208                  "Adding module definiation: %s", mc_module.to_s
 209              ) if env.debug?
 210 
 211              mm_module = if mc_module.kind_of?(MCLN::Class)
 212                              MMLN::Class.new(
 213                                  mm_location, mm_above_path, name,
 214                                  MMLA::SetOfModule.new,
 215                                  if mc_module.inherit_path_string
 216                                      mc_module.inherit_path_string
 217                                  else
 218                                      OBJECT_CLASS_NAME
 219                                  end
 220                              )
 221                          else
 222                              MMLN::Module.new(
 223                                  mm_location, mm_above_path, name,
 224                                  MMLA::SetOfModule.new
 225                              )
 226                          end
 227              mm_above_module.add! mm_module
 228 
 229              map_of_path_to_module.update! mm_module_path, mm_module
 230          end
 231 
 232          nil
 233      end
 234 
 235 
 236      def self.evaluate_directive!(
 237          mc_directive, mm_location, mm_above_path, mm_above_module, env,
 238          mm_file
 239      )
 240          ASSERT.kind_of mc_directive,    MCLA::Directive
 241          ASSERT.kind_of mm_location,     MML::Location
 242          ASSERT.kind_of mm_above_path,   MMLP::AbsolutePath
 243          ASSERT.kind_of mm_above_module, MMLA::GenericModule
 244          ASSERT.kind_of env,             ENV::Environment
 245          ASSERT.kind_of mm_file,         MMP::File
 246 
 247          case mc_directive
 248          when MCLL::Require
 249              mm_file.require_files.add!(
 250                  MMP::RequireFile.new(
 251                      mc_directive.require_file_name, mc_directive.line_num
 252                  )
 253              )
 254 
 255          when MCLL::Extend
 256              mm_above_module.extendees.add!(
 257                  MMLL::Extend.new(
 258                      mm_location, mm_above_path,
 259                      mc_directive.seq_num,
 260                      if mc_directive.extendee_path_string
 261                          mc_directive.extendee_path_string
 262                      else
 263                          mm_above_path.to_s
 264                      end
 265                  )
 266              )
 267 
 268          when MCLL::Include
 269              mm_above_module.includees.add!(
 270                  MMLL::Include.new(
 271                      mm_location, mm_above_path,
 272                      mc_directive.seq_num,
 273                      if mc_directive.includee_path_string
 274                          mc_directive.includee_path_string
 275                      else
 276                          mm_above_path.to_s
 277                      end
 278                  )
 279              )
 280 
 281          when MCLL::ModuleFunc
 282              ;   # Nop
 283 
 284          else
 285              ASSERT.abort(
 286                  "Unknown directive: %s(%s)",
 287                  mc_directive.to_s, mc_directive.class
 288              )
 289          end
 290 
 291          nil
 292      end
 293 
 294 
 295      def self.evaluate_property_or_method!(
 296          mc_subject, mm_location, mm_above_path, mm_above_module, env,
 297          map_of_path_to_func_names
 298      )
 299          ASSERT.kind_of  mc_subject,         MCLA::Subject
 300          ASSERT.kind_of  mm_location,        MML::Location
 301          ASSERT.kind_of  mm_above_path,      MMLP::AbsolutePath
 302          ASSERT.kind_of  mm_above_module,    MMLA::GenericModule
 303          ASSERT.kind_of  env,                ENV::Environment
 304          ASSERT.kind_of(
 305                          map_of_path_to_func_names,
 306                          MapOfPathToModuleFuncNames
 307          )
 308 
 309          mm_property =
 310              case mc_subject
 311              when MCLL::Alias
 312                  MMLL::Alias.new(
 313                      mm_location, mm_above_path, mc_subject.name,
 314                      mc_subject.orig_name,
 315                      mc_subject.attach_to_instance?
 316                  )
 317 
 318              when MCLL::Attribute
 319                  MMLL::Attribute.new(
 320                      mm_location, mm_above_path, mc_subject.name,
 321                      mc_subject.seq_num, mc_subject.accessor,
 322                      mc_subject.attach_to_instance?
 323                  )
 324 
 325              when MCLN::Method
 326                  if (! mc_subject.attach_name) ||
 327                              mc_subject.attach_name == mm_above_module.name
 328                      name            = mc_subject.name
 329                      is_module_func  =
 330                          if mc_subject.module_func?
 331                              true
 332                          else
 333                              func_names = map_of_path_to_func_names.at(
 334                                  mm_above_path
 335                              )
 336                              LOG::Debug.log(
 337                                  "func_names: %s -- #%d",
 338                                  func_names.inspect, __LINE__
 339                              ) if env.debug?
 340 
 341                              if func_names && func_names.include?(name)
 342                                  true
 343                              else
 344                                  false
 345                              end
 346                          end
 347 
 348                      MMLL::Method.new(
 349                          mm_location, mm_above_path, name,
 350                          mc_subject.args,
 351                          mc_subject.attach_to_instance?,
 352                          is_module_func
 353                      )
 354                  else
 355                      LOG::Warning.log(
 356                          "I can't recognize the Id: <%s> " +
 357                                  "for module name of the unique method.\n" +
 358                              "\t-- #%d in '%s'",
 359                          mc_subject.attach_name,
 360                                  mm_location.line_num, mm_location.file_name
 361                      )
 362                      CMD.test_sensitive_level env, LOG::Warning
 363                  end
 364 
 365              else
 366                  ASSERT.abort(
 367                      "Unknown subject: %s(%s)",
 368                      mc_subject.to_s, mc_subject.class
 369                  )
 370              end
 371          mm_above_module.properties.add! mm_property
 372 
 373          nil
 374      end
 375 
 376 
 377      def self.resolve_module_name!(target_path, env, map_of_path_to_module)
 378          ASSERT.kind_of target_path,             MMLP::AbsolutePath
 379          ASSERT.kind_of env,                     ENV::Environment
 380          ASSERT.kind_of map_of_path_to_module,   MMLA::MapOfPathToModule
 381 
 382          LOG::Debug.msgout "CALLED" if env.debug?
 383 
 384          resolved_module = map_of_path_to_module.at(target_path)
 385          if resolved_module
 386              return ASSERT.kind_of resolved_module, MMLA::GenericModule
 387          end
 388 
 389          case target_path.first
 390          when 'TmDoc', 'TmStd'
 391              return nil
 392          end
 393 
 394          klass = nil
 395          begin
 396              klass = Kernel.const_get(target_path.join('::'))
 397          rescue NameError
 398              ;   # Nop
 399          end
 400          if klass
 401              resolved_path =
 402                  BUILTIN_MODULE_PATH +
 403                  MMLP::RelativePath.new(target_path.to_a)
 404              resolved_module = map_of_path_to_module.at(target_path)
 405              resolved_above_path, resolved_name = resolved_path.pop
 406 
 407              resolved_module = map_of_path_to_module.at resolved_path
 408              unless resolved_module
 409                  child_module = nil
 410 
 411                  while resolved_above_path.length > 0 && ! resolved_module
 412                      args = [nil, resolved_above_path, resolved_name]
 413                      if klass.is_a?(::Class)
 414 
 415                          # It should be resolved inheritance recursivily ...
 416 
 417                          resolved_module = MMLN::Class.new *(
 418                              args + [
 419                                  MMLA::SetOfModule.new, OBJECT_CLASS_NAME
 420                              ]
 421                          )
 422                          resolved_module.inherit_path! OBJECT_CLASS_PATH
 423                      else
 424                          resolved_module = MMLN::Module.new *args
 425                      end
 426 
 427                      if child_module
 428                          resolved_module.add! child_module
 429                      end
 430 
 431                      LOG::Debug.log(
 432                          "Add found built-in module: '%s'\n" +
 433                                              "to table: '%s'",
 434                          resolved_module.to_s,
 435                          resolved_path.to_s
 436                      ) if env.debug?
 437 
 438                      map_of_path_to_module.update!(
 439                          resolved_path.dup, resolved_module
 440                      )
 441 
 442                      child_module = resolved_module
 443 
 444                      resolved_path.pop!
 445                      resolved_above_path, resolved_name = resolved_path.pop
 446                  end
 447 
 448                  MM_BUILTIN_MODULE.add! resolved_module
 449              end
 450          else
 451              resolved_module = nil
 452          end
 453 
 454          ASSERT.opt_kind_of resolved_module, MMLA::GenericModule
 455      end
 456 
 457 
 458      def self.validate_class_consistency!(
 459          mc_my_subject, mm_my_location, mm_other_module, env
 460      )
 461          ASSERT.kind_of mc_my_subject,   MCLN::Class
 462          ASSERT.kind_of mm_my_location,  MML::Location
 463          ASSERT.kind_of mm_other_module, MMLA::GenericModule
 464          ASSERT.kind_of env,             ENV::Environment
 465 
 466          LOG::Debug.msgout "CALLED" if env.debug?
 467 
 468          my_mc_inherit_path_string =
 469              if mc_my_subject.inherit_path_string
 470                  mc_my_subject.inherit_path_string
 471              else
 472                  OBJECT_CLASS_NAME
 473              end
 474 
 475          is_consistent, my_inherit, other_inherit =
 476              if mm_other_module.inherit_path_string == OBJECT_CLASS_NAME
 477                  if my_mc_inherit_path_string == OBJECT_CLASS_NAME
 478                      [true, nil, nil]
 479                  else
 480                      [
 481                          false,
 482                          my_mc_inherit_path_string,
 483                          OBJECT_CLASS_NAME
 484                      ]
 485                  end
 486              else
 487                  if my_mc_inherit_path_string == OBJECT_CLASS_NAME
 488                      [true, nil, nil]
 489                  else
 490                      [
 491                          mm_other_module.inherit_path_string ==
 492                                                  my_mc_inherit_path_string,
 493                          my_mc_inherit_path_string,
 494                          mm_other_module.inherit_path_string
 495                      ]
 496                  end
 497              end
 498 
 499          unless is_consistent
 500              LOG::Warning.log(
 501                  "Impossible to fix " +
 502                  "class inheritance inconsistency: %s.\n" +
 503                      "\tprevious superclass: %s,\n" +
 504                      "\tbut my superclass: %s -- %s.",
 505                  mm_other_module.path.to_s,
 506                      other_inherit,
 507                      my_inherit, mm_my_location.to_s
 508              )
 509              CMD.test_sensitive_level env, LOG::Warning
 510          end
 511 
 512          nil
 513      end
 514  end
 515 
 516  end # TmDoc::Transformer::CoreIntoModule
 517 
 518  end # TmDoc