PageRenderTime 15ms CodeModel.GetById 2ms app.highlight 5ms RepoModel.GetById 1ms app.codeStats 0ms

/src/tools/liberty_universe.e

http://github.com/tybor/Liberty
Specman e | 1353 lines | 1207 code | 126 blank | 20 comment | 46 complexity | ff46476357431ba4f89d4e8e520646dd MD5 | raw file
   1-- This file is part of Liberty Eiffel.
   2--
   3-- Liberty Eiffel is free software: you can redistribute it and/or modify
   4-- it under the terms of the GNU General Public License as published by
   5-- the Free Software Foundation, version 3 of the License.
   6--
   7-- Liberty Eiffel is distributed in the hope that it will be useful,
   8-- but WITHOUT ANY WARRANTY; without even the implied warranty of
   9-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10-- GNU General Public License for more details.
  11--
  12-- You should have received a copy of the GNU General Public License
  13-- along with Liberty Eiffel.  If not, see <http://www.gnu.org/licenses/>.
  14--
  15class LIBERTY_UNIVERSE
  16
  17insert
  18   LIBERTY_ERROR_LEVELS
  19      undefine is_equal
  20      end
  21   LIBERTY_AST_HANDLER
  22      undefine is_equal
  23      end
  24   LIBERTY_ERROR_LEVELS
  25      undefine is_equal
  26      end
  27   SINGLETON
  28   LOGGING
  29      undefine is_equal
  30      end
  31
  32create {ANY}
  33   make
  34
  35feature {ANY}
  36   get_type (cluster: LIBERTY_CLUSTER; position: LIBERTY_POSITION; class_name: FIXED_STRING; effective_type_parameters: TRAVERSABLE[LIBERTY_ACTUAL_TYPE]): LIBERTY_ACTUAL_TYPE is
  37      require
  38         position /= Void
  39      do
  40         Result := do_get_type(cluster, position, class_name, effective_type_parameters)
  41      ensure
  42         Result.name.is_equal(class_name)
  43         same_parameters(Result.parameters, effective_type_parameters)
  44      end
  45
  46   parse_expression (a_expression: STRING; when_error: PROCEDURE[TUPLE[PARSE_ERROR]]): LIBERTY_AST_EXPRESSION is
  47      require
  48         a_expression /= Void
  49         when_error /= Void
  50      do
  51         Result ::= partial_parse(a_expression, once "Expression", when_error)
  52      end
  53
  54   parse_instruction (a_instruction: STRING; when_error: PROCEDURE[TUPLE[PARSE_ERROR]]): LIBERTY_AST_INSTRUCTION is
  55      require
  56         a_instruction /= Void
  57         when_error /= Void
  58      do
  59         Result ::= partial_parse(a_instruction, once "Instruction", when_error)
  60      end
  61
  62   build_types (root_type: LIBERTY_ACTUAL_TYPE; root_feature_name: LIBERTY_FEATURE_NAME; target_type: LIBERTY_ACTUAL_TYPE) is
  63      require
  64         target_type /= Void
  65      local
  66         flame: LIBERTY_FLAME
  67         incubator: like types_incubator
  68      do
  69         if not target_type.is_built then
  70            create incubator.with_capacity(1024, 0) --|TODO optim: replace by an attribute
  71            from
  72            until
  73               types_incubator.is_empty or else target_type.is_built
  74            loop
  75               flame := torch.flame
  76               build_to_incubator(incubator, target_type)
  77               mark_reachable_code(root_type, root_feature_name)
  78               resolve_delayed_types
  79               if types_incubator.is_empty then
  80                  incubator := check_flame_and_swap_incubator(flame, incubator)
  81               end
  82            end
  83            if not incubator.is_empty then
  84               -- don't lose work
  85               types_incubator.append_traversable(incubator)
  86            end
  87            debug ("type.building")
  88               debug_types(types_incubator)
  89               if target_type.is_built then
  90                  log.trace.put_string(once "Type is ready: ")
  91                  log.trace.put_line(target_type.full_name)
  92               else
  93                  log.trace.put_string(once "Type is NOT READY: ")
  94                  log.trace.put_line(target_type.full_name)
  95                  breakpoint
  96               end
  97            end
  98         end
  99      ensure
 100         target_type.is_built
 101      end
 102
 103feature {ANY} -- Kernel types
 104   type_any: LIBERTY_ACTUAL_TYPE is
 105      require
 106         not errors.has_error
 107      once
 108         Result := kernel_type("ANY".intern, visit_type_any)
 109      end
 110
 111   type_arguments: LIBERTY_ACTUAL_TYPE is
 112      require
 113         not errors.has_error
 114      once
 115         Result := kernel_type("ARGUMENTS".intern, visit_type_arguments)
 116      end
 117
 118   type_platform: LIBERTY_ACTUAL_TYPE is
 119      require
 120         not errors.has_error
 121      once
 122         Result := kernel_type("PLATFORM".intern, visit_type_platform)
 123      end
 124
 125   type_pointer: LIBERTY_ACTUAL_TYPE is
 126      require
 127         not errors.has_error
 128      once
 129         Result := kernel_type("POINTER".intern, visit_type_pointer)
 130      end
 131
 132   type_integer_64: LIBERTY_ACTUAL_TYPE is
 133      require
 134         not errors.has_error
 135      once
 136         Result := kernel_type("INTEGER_64".intern, visit_type_integer_64)
 137         Result.add_converter(type_real_128, convert_integer_64_real_128)
 138         Result.add_converter(type_real_80, convert_integer_64_real_80)
 139         Result.set_may_promote_current
 140      end
 141
 142   type_integer, type_integer_32: LIBERTY_ACTUAL_TYPE is
 143      require
 144         not errors.has_error
 145      once
 146         Result := kernel_type("INTEGER_32".intern, visit_type_integer_32)
 147         Result.add_converter(type_integer_64, convert_integer_32_64)
 148         Result.add_converter(type_real_128, convert_integer_32_real_128)
 149         Result.add_converter(type_real_80, convert_integer_32_real_80)
 150         Result.add_converter(type_real_64, convert_integer_32_real_64)
 151         Result.set_may_promote_current
 152      end
 153
 154   type_integer_16: LIBERTY_ACTUAL_TYPE is
 155      require
 156         not errors.has_error
 157      once
 158         Result := kernel_type("INTEGER_16".intern, visit_type_integer_16)
 159         Result.add_converter(type_integer_32, convert_integer_16_32)
 160         Result.add_converter(type_integer_64, convert_integer_16_64)
 161         Result.add_converter(type_real_128, convert_integer_16_real_128)
 162         Result.add_converter(type_real_80, convert_integer_16_real_80)
 163         Result.add_converter(type_real_64, convert_integer_16_real_64)
 164         Result.add_converter(type_real_32, convert_integer_16_real_32)
 165         Result.set_may_promote_current
 166      end
 167
 168   type_integer_8: LIBERTY_ACTUAL_TYPE is
 169      require
 170         not errors.has_error
 171      once
 172         Result := kernel_type("INTEGER_8".intern, visit_type_integer_8)
 173         Result.add_converter(type_integer_16, convert_integer_8_16)
 174         Result.add_converter(type_integer_32, convert_integer_8_32)
 175         Result.add_converter(type_integer_64, convert_integer_8_64)
 176         Result.add_converter(type_real_128, convert_integer_8_real_128)
 177         Result.add_converter(type_real_80, convert_integer_8_real_80)
 178         Result.add_converter(type_real_64, convert_integer_8_real_64)
 179         Result.add_converter(type_real_32, convert_integer_8_real_32)
 180         Result.set_may_promote_current
 181      end
 182
 183   type_real_128: LIBERTY_ACTUAL_TYPE is
 184      require
 185         not errors.has_error
 186      once
 187         Result := kernel_type("REAL_128".intern, visit_type_real_128)
 188         Result.set_may_promote_current
 189      end
 190
 191   type_real_80: LIBERTY_ACTUAL_TYPE is
 192      require
 193         not errors.has_error
 194      once
 195         Result := kernel_type("REAL_80".intern, visit_type_real_80)
 196         Result.add_converter(type_real_128, convert_real_80_128)
 197         Result.set_may_promote_current
 198      end
 199
 200   type_real, type_real_64: LIBERTY_ACTUAL_TYPE is
 201      require
 202         not errors.has_error
 203      once
 204         Result := kernel_type("REAL_64".intern, visit_type_real_64)
 205         Result.add_converter(type_real_80, convert_real_64_80)
 206         Result.add_converter(type_real_128, convert_real_64_128)
 207         Result.set_may_promote_current
 208      end
 209
 210   type_real_32: LIBERTY_ACTUAL_TYPE is
 211      require
 212         not errors.has_error
 213      once
 214         Result := kernel_type("REAL_32".intern, visit_type_real_32)
 215         Result.add_converter(type_real_64, convert_real_32_64)
 216         Result.add_converter(type_real_80, convert_real_32_80)
 217         Result.add_converter(type_real_128, convert_real_32_128)
 218         Result.set_may_promote_current
 219      end
 220
 221   type_character: LIBERTY_ACTUAL_TYPE is
 222      require
 223         not errors.has_error
 224      once
 225         Result := kernel_type("CHARACTER".intern, visit_type_character)
 226      end
 227
 228   type_string: LIBERTY_ACTUAL_TYPE is
 229      require
 230         not errors.has_error
 231      once
 232         Result := kernel_type("STRING".intern, visit_type_string)
 233      end
 234
 235   type_boolean: LIBERTY_ACTUAL_TYPE is
 236      require
 237         not errors.has_error
 238      once
 239         Result := kernel_type("BOOLEAN".intern, visit_type_boolean)
 240      end
 241
 242   type_native_array (effective_generics: TRAVERSABLE[LIBERTY_TYPE]; position: LIBERTY_POSITION): LIBERTY_ACTUAL_TYPE is
 243      require
 244         not errors.has_error
 245      local
 246         td: LIBERTY_TYPE_DESCRIPTOR
 247         ast: LIBERTY_AST_ONE_CLASS
 248      do
 249         create td.make(native_array_class_descriptor, effective_generics)
 250         Result := types.reference_at(td)
 251         if Result = Void then
 252            ast := parse_class(td.cluster, td.name, Void)
 253            create Result.make(td, standard_generics_checker, ast, visit_type_native_array)
 254            start_to_build_type(Result)
 255         end
 256      ensure
 257         Result /= Void
 258      end
 259
 260   type_tuple (effective_generics: TRAVERSABLE[LIBERTY_TYPE]; position: LIBERTY_POSITION): LIBERTY_ACTUAL_TYPE is
 261      require
 262         effective_generics /= Void
 263         not errors.has_error
 264      local
 265         td: LIBERTY_TYPE_DESCRIPTOR
 266         tuple_ast: LIBERTY_AST_CLASSES
 267         ast: LIBERTY_AST_ONE_CLASS
 268         tuple_count: INTEGER
 269      do
 270         tuple_count := effective_generics.count
 271         create td.make(tuple_class_descriptor, effective_generics)
 272         Result := types.reference_at(td)
 273         if Result = Void then
 274            tuple_ast := parse_tuple_classes(Void)
 275            check tuple_ast.classes.lower = 0 end
 276            if tuple_count > tuple_ast.classes.upper then
 277               errors.add_position(position)
 278               errors.set(level_fatal_error, "TUPLE does not support more than " + tuple_ast.classes.upper.out
 279                          + " generic parameters.%NYou might want a named class with named attributes instead.")
 280            end
 281            ast ::= tuple_ast.classes.item(tuple_count)
 282            create Result.make(td, tuple_generics_checker, ast, visit_type_tuple)
 283            start_to_build_type(Result)
 284         end
 285      ensure
 286         Result /= Void
 287      end
 288
 289   type_routine (effective_generics: TRAVERSABLE[LIBERTY_TYPE]; position: LIBERTY_POSITION): LIBERTY_ACTUAL_TYPE is
 290      require
 291         effective_generics /= Void
 292      do
 293         Result := agent_type(routine_class_descriptor, {FAST_ARRAY[LIBERTY_TYPE] << type_tuple(effective_generics, position) >> }, position, visit_type_routine)
 294      end
 295
 296   type_procedure (effective_generics: TRAVERSABLE[LIBERTY_TYPE]; position: LIBERTY_POSITION): LIBERTY_ACTUAL_TYPE is
 297      require
 298         effective_generics /= Void
 299      do
 300         Result := agent_type(procedure_class_descriptor, {FAST_ARRAY[LIBERTY_TYPE] << type_tuple(effective_generics, position) >> }, position, visit_type_procedure)
 301      end
 302
 303   type_function (effective_generics: TRAVERSABLE[LIBERTY_TYPE]; result_type: LIBERTY_TYPE; position: LIBERTY_POSITION): LIBERTY_ACTUAL_TYPE is
 304      require
 305         effective_generics /= Void
 306         result_type /= Void
 307      do
 308         Result := agent_type(function_class_descriptor, {FAST_ARRAY[LIBERTY_TYPE] << type_tuple(effective_generics, position), result_type >> }, position, visit_type_function)
 309      end
 310
 311   type_predicate (effective_generics: TRAVERSABLE[LIBERTY_TYPE]; position: LIBERTY_POSITION): LIBERTY_ACTUAL_TYPE is
 312      require
 313         effective_generics /= Void
 314      do
 315         Result := agent_type(predicate_class_descriptor, {FAST_ARRAY[LIBERTY_TYPE] << type_tuple(effective_generics, position) >> }, position, visit_type_predicate)
 316      end
 317
 318feature {} -- Partial parsing of command-line buffer (for the debugger and REPL)
 319   partial_parse (a_entry, a_root_atom_name: STRING; when_error: PROCEDURE[TUPLE[PARSE_ERROR]]): LIBERTY_AST_NON_TERMINAL_NODE is
 320      require
 321         a_entry /= Void
 322         when_error /= Void
 323      local
 324         evaled: BOOLEAN
 325      do
 326         parser_buffer.initialize_with(a_entry)
 327         eiffel.reset
 328         evaled := parser.eval(parser_buffer, eiffel.table, a_root_atom_name)
 329         if evaled then
 330            if parser.error /= Void then
 331               when_error.call([parser.error])
 332            else
 333               Result ::= eiffel.root_node
 334            end
 335         end
 336      end
 337
 338feature {}
 339   reachable_counter: COUNTER is
 340      once
 341         create Result
 342      end
 343
 344   mark_reachable_code (root_type: LIBERTY_ACTUAL_TYPE; root_feature_name: LIBERTY_FEATURE_NAME) is
 345      local
 346         root_feature: LIBERTY_FEATURE_DEFINITION
 347      do
 348         reachable_counter.increment
 349         root_type.set_reachable(reachable_counter.value)
 350         if root_type.has_loaded_features then
 351            if not root_type.has_feature(root_feature_name) then
 352               errors.set(level_fatal_error,
 353                          "Am I blind or what? I cannot find any method '" + root_feature_name.name
 354                          + "' feature in the type " + root_type.full_name + "!")
 355               die_with_code(1)
 356            end
 357            root_feature := root_type.feature_definition(root_feature_name)
 358            reachable_counter.increment
 359            debug ("mark.reachable")
 360               log.trace.put_string(once " +++ Marking reachable code (")
 361               log.trace.put_integer(reachable_counter.value)
 362               log.trace.put_line(once ")...")
 363            end
 364            root_feature.set_reachable(reachable_counter.value)
 365            debug ("mark.reachable")
 366               log.trace.put_line(once "     Reachable code marked.")
 367            end
 368         end
 369      end
 370
 371   resolve_delayed_types is
 372      local
 373         delayed_types: COLLECTION[LIBERTY_DELAYED_TYPE]
 374         delayed_type: LIBERTY_DELAYED_TYPE
 375         i, n: INTEGER; more: BOOLEAN
 376      do
 377         delayed_types := type_lookup.resolver.delayed_types
 378         from
 379            more := True
 380         until
 381            not more or else delayed_types.is_empty
 382         loop
 383            more := False
 384            from
 385               n := delayed_types.count
 386            until
 387               n = 0
 388            loop
 389               delayed_type := delayed_types.first
 390               delayed_types.remove_first
 391               check
 392                  not delayed_type.is_known
 393               end
 394               if delayed_type.can_resolve then
 395                  delayed_type.resolve
 396                  debug ("type.resolution")
 397                     log.trace.put_string(once " ===> resolved ")
 398                     log.trace.put_line(delayed_type.out)
 399                  end
 400                  more := True
 401               else
 402                  delayed_types.add_last(delayed_type)
 403               end
 404               n := n - 1
 405            end
 406         end
 407         debug ("type.resolution")
 408            log.trace.put_line(once "======================================================================")
 409            from
 410               i := delayed_types.lower
 411            until
 412               i > delayed_types.upper
 413            loop
 414               log.trace.put_line(delayed_types.item(i).out)
 415               i := i + 1
 416            end
 417            log.trace.put_string(once " === ")
 418            log.trace.put_integer(delayed_types.count)
 419            if delayed_types.count = 1 then
 420               log.trace.put_line(once " delayed type yet to be resolved.")
 421            else
 422               log.trace.put_line(once " delayed types yet to be resolved.")
 423            end
 424         end
 425      end
 426
 427   build_to_incubator (incubator: like types_incubator; target_type: LIBERTY_ACTUAL_TYPE) is
 428      require
 429         not types_incubator.is_empty
 430         not target_type.is_built
 431      local
 432         type: LIBERTY_ACTUAL_TYPE
 433      do
 434         from
 435         until
 436            types_incubator.is_empty or else target_type.is_built
 437         loop
 438            target_type.build_more
 439            type := types_incubator.first
 440            types_incubator.remove_first
 441            if not type.is_built then
 442               type.build_more
 443               if not type.is_built then
 444                  incubator.add_last(type)
 445               end
 446            end
 447         end
 448      end
 449
 450   check_flame_and_swap_incubator (flame: LIBERTY_FLAME; incubator: like types_incubator): like types_incubator is
 451      require
 452         types_incubator.is_empty
 453      do
 454         if not torch.still_burns(flame) then
 455            clean_unreachable_types(incubator)
 456            if not incubator.is_empty then
 457               debug ("error")
 458                  debug_types(incubator)
 459               end
 460               errors.set(level_system_error, once "It looks like I miss some data but the hell if I know what.")
 461               check
 462                  dead: False
 463               end
 464            end
 465         end
 466         Result := types_incubator
 467         types_incubator := incubator
 468         debug
 469            log.trace.put_line(once "Swapped incubator")
 470         end
 471      ensure
 472         types_incubator = incubator
 473         Result = old types_incubator
 474      end
 475
 476   clean_unreachable_types (incubator: like types_incubator) is
 477      local
 478         i: INTEGER
 479      do
 480         clean_unreachable_types_from_incubator(incubator)
 481         from
 482            i := types.lower
 483         until
 484            i > types.upper
 485         loop
 486            if not types.item(i).is_reachable then
 487               types.fast_remove(types.key(i))
 488            else
 489               i := i + 1
 490            end
 491         end
 492      end
 493
 494   clean_unreachable_types_from_incubator (incubator: like types_incubator) is
 495      local
 496         i: INTEGER
 497      do
 498         from
 499            i := incubator.lower
 500         until
 501            i > incubator.upper
 502         loop
 503            if not incubator.item(i).is_reachable then
 504               debug
 505                  log.trace.put_string(once "Removing ")
 506                  log.trace.put_string(incubator.item(i).full_name)
 507                  log.trace.put_line(once ": not reachable")
 508               end
 509               incubator.remove(i)
 510            else
 511               i := i + 1
 512            end
 513         end
 514      end
 515
 516feature {} -- debug
 517   debug_types (incubator: like types_incubator) is
 518      local
 519         i: INTEGER
 520         all_types: FAST_ARRAY[LIBERTY_ACTUAL_TYPE]
 521         c: COMPARATOR_COLLECTION_SORTER[LIBERTY_ACTUAL_TYPE]
 522      do
 523         from
 524            create all_types.with_capacity(types.count)
 525            c.set_comparator(agent debug_compare_type_names)
 526            i := types.lower
 527         until
 528            i > types.upper
 529         loop
 530            c.add(all_types, types.item(i))
 531            i := i + 1
 532         end
 533         check
 534            all_types.count = types.count
 535         end
 536         log.trace.put_line(once "--8<--------")
 537         from
 538            i := all_types.lower
 539         until
 540            i > all_types.upper
 541         loop
 542            log.trace.put_integer(i - all_types.lower + 1)
 543            log.trace.put_string(once ": ")
 544            all_types.item(i).debug_display(log.trace, False)
 545            i := i + 1
 546         end
 547         log.trace.put_line(once "-------->8--")
 548         if incubator.is_empty then
 549            log.trace.put_integer(all_types.count)
 550            log.trace.put_line(once " types (total), incubator is empty")
 551         else
 552            log.trace.put_integer(all_types.count)
 553            log.trace.put_string(once " types (total), including ")
 554            log.trace.put_integer(incubator.count)
 555            log.trace.put_line(once " types in incubator:")
 556            log.trace.put_line(once "--8<--------")
 557            from
 558               i := incubator.lower
 559            until
 560               i > incubator.upper
 561            loop
 562               log.trace.put_integer(i - incubator.lower + 1)
 563               log.trace.put_string(once ": ")
 564               incubator.item(i).debug_display(log.trace, False)
 565               i := i + 1
 566            end
 567            log.trace.put_line(once "-------->8--")
 568         end
 569      end
 570
 571   debug_compare_type_names (t1, t2: LIBERTY_ACTUAL_TYPE): BOOLEAN is
 572      do
 573         Result := t1.full_name < t2.full_name
 574      end
 575
 576feature {}
 577   start_to_build_type (type: LIBERTY_ACTUAL_TYPE) is
 578      require
 579         not types.has(type.descriptor)
 580      do
 581         types.add(type, type.descriptor)
 582         type.start_build(Current)
 583         if not type.is_built then
 584            types_incubator.add_last(type)
 585         end
 586         torch.burn
 587      end
 588
 589   native_array_class_descriptor: LIBERTY_CLASS_DESCRIPTOR is
 590      local
 591         cluster: LIBERTY_CLUSTER
 592      once
 593         cluster := root.find("NATIVE_ARRAY".intern)
 594         create Result.make(cluster, "NATIVE_ARRAY".intern, Void)
 595      end
 596
 597   tuple_class_descriptor: LIBERTY_CLASS_DESCRIPTOR is
 598      local
 599         cluster: LIBERTY_CLUSTER
 600      once
 601         cluster := root.find("TUPLE".intern)
 602         create Result.make(cluster, "TUPLE".intern, Void)
 603      end
 604
 605   routine_class_descriptor: LIBERTY_CLASS_DESCRIPTOR is
 606      local
 607         cluster: LIBERTY_CLUSTER
 608      once
 609         cluster := root.find("ROUTINE".intern)
 610         create Result.make(cluster, "ROUTINE".intern, Void)
 611      end
 612
 613   procedure_class_descriptor: LIBERTY_CLASS_DESCRIPTOR is
 614      local
 615         cluster: LIBERTY_CLUSTER
 616      once
 617         cluster := root.find("PROCEDURE".intern)
 618         create Result.make(cluster, "PROCEDURE".intern, Void)
 619      end
 620
 621   function_class_descriptor: LIBERTY_CLASS_DESCRIPTOR is
 622      local
 623         cluster: LIBERTY_CLUSTER
 624      once
 625         cluster := root.find("FUNCTION".intern)
 626         create Result.make(cluster, "FUNCTION".intern, Void)
 627      end
 628
 629   predicate_class_descriptor: LIBERTY_CLASS_DESCRIPTOR is
 630      local
 631         cluster: LIBERTY_CLUSTER
 632      once
 633         cluster := root.find("PREDICATE".intern)
 634         create Result.make(cluster, "PREDICATE".intern, Void)
 635      end
 636
 637   kernel_type (class_name: FIXED_STRING; visit: PROCEDURE[TUPLE[LIBERTY_TYPE_VISITOR, LIBERTY_ACTUAL_TYPE]]): LIBERTY_ACTUAL_TYPE is
 638         -- Called only once per kernel type
 639      require
 640         not errors.has_error
 641      local
 642         cd: LIBERTY_CLASS_DESCRIPTOR; td: LIBERTY_TYPE_DESCRIPTOR
 643         ast: LIBERTY_AST_ONE_CLASS
 644         cluster: LIBERTY_CLUSTER
 645      do
 646         cluster := root.find(class_name)
 647         if cluster = Void then
 648            errors.set(level_fatal_error, "What's that installation of yours? I cannot even find the kernel class " + class_name + "!")
 649         end
 650         create cd.make(cluster, class_name.intern, Void)
 651         create td.make(cd, no_parameters)
 652         Result := types.reference_at(td)
 653         if Result = Void then
 654            ast := parse_class(cluster, class_name, Void)
 655            create Result.make(td, standard_generics_checker, ast, visit)
 656            start_to_build_type(Result)
 657         end
 658      ensure
 659         Result /= Void
 660      end
 661
 662   agent_type (class_descriptor: LIBERTY_CLASS_DESCRIPTOR; agent_generics: TRAVERSABLE[LIBERTY_TYPE]; position: LIBERTY_POSITION;
 663               visit: PROCEDURE[TUPLE[LIBERTY_TYPE_VISITOR, LIBERTY_ACTUAL_TYPE]]): LIBERTY_ACTUAL_TYPE is
 664      require
 665         class_descriptor /= Void
 666         agent_generics /= Void
 667      local
 668         td: LIBERTY_TYPE_DESCRIPTOR
 669         ast: LIBERTY_AST_ONE_CLASS
 670      do
 671         create td.make(class_descriptor, agent_generics)
 672         Result := types.reference_at(td)
 673         if Result = Void then
 674            ast := parse_class(td.cluster, td.name, position)
 675            create Result.make(td, agent_generics_checker, ast, visit)
 676            start_to_build_type(Result)
 677         end
 678      end
 679
 680feature {LIBERTY_TYPE_RESOLVER}
 681   get_type_from_descriptor (descriptor: LIBERTY_TYPE_DESCRIPTOR): LIBERTY_ACTUAL_TYPE is
 682      require
 683         not errors.has_error
 684      do
 685         Result := do_get_type_from_descriptor(descriptor)
 686      ensure
 687         Result.cluster.is_equal(descriptor.cluster)
 688         Result.name.is_equal(descriptor.name)
 689         same_parameters(Result.parameters, descriptor.parameters)
 690      end
 691
 692   get_type_from_type_definition (type_definition: LIBERTY_AST_TYPE_DEFINITION; cluster: LIBERTY_CLUSTER): LIBERTY_ACTUAL_TYPE is
 693      require
 694         not type_definition.is_anchor
 695         not errors.has_error
 696      local
 697         class_name: STRING
 698         parameters: TRAVERSABLE[LIBERTY_TYPE]
 699      do
 700         class_name := type_definition.type_name.image.image
 701         inspect
 702            class_name
 703         when "INTEGER" then
 704            Result := type_integer
 705         when "INTEGER_64" then
 706            Result := type_integer_64
 707         when "INTEGER_32" then
 708            Result := type_integer_32
 709         when "INTEGER_16" then
 710            Result := type_integer_16
 711         when "INTEGER_8" then
 712            Result := type_integer_8
 713         when "ANY" then
 714            Result := type_any
 715         when "ARGUMENTS" then
 716            Result := type_arguments
 717         when "PLATFORM" then
 718            Result := type_platform
 719         when "REAL" then
 720            Result := type_real
 721         when "REAL_32" then
 722            Result := type_real_32
 723         when "REAL_64" then
 724            Result := type_real_64
 725         when "REAL_80" then
 726            Result := type_real_80
 727         when "REAL_128" then
 728            Result := type_real_128
 729         when "POINTER" then
 730            Result := type_pointer
 731         when "CHARACTER" then
 732            Result := type_character
 733         when "STRING" then
 734            Result := type_string
 735         when "BOOLEAN" then
 736            Result := type_boolean
 737         when "NATIVE_ARRAY" then
 738            parameters := get_parameters(type_definition.type_parameters)
 739            Result := type_native_array(parameters, type_lookup.resolver.position(type_definition))
 740         when "TUPLE" then
 741            parameters := get_parameters(type_definition.type_parameters)
 742            Result := type_tuple(parameters, type_lookup.resolver.position(type_definition))
 743         when "ROUTINE" then
 744            parameters := get_parameters(type_definition.type_parameters)
 745            check
 746               parameters.count = 1
 747               parameters.first.is_known
 748            end
 749            Result := type_routine(parameters.first.known_type.parameters, type_lookup.resolver.position(type_definition))
 750         when "PROCEDURE" then
 751            parameters := get_parameters(type_definition.type_parameters)
 752            check
 753               parameters.count = 1
 754               parameters.first.is_known
 755            end
 756            Result := type_procedure(parameters.first.known_type.parameters, type_lookup.resolver.position(type_definition))
 757         when "PREDICATE" then
 758            parameters := get_parameters(type_definition.type_parameters)
 759            check
 760               parameters.count = 1
 761               parameters.first.is_known
 762            end
 763            Result := type_predicate(parameters.first.known_type.parameters, type_lookup.resolver.position(type_definition))
 764         when "FUNCTION" then
 765            parameters := get_parameters(type_definition.type_parameters)
 766            check
 767               parameters.count = 2
 768               parameters.first.is_known
 769            end
 770            Result := type_function(parameters.first.known_type.parameters, parameters.last, type_lookup.resolver.position(type_definition))
 771         else
 772            parameters := get_parameters(type_definition.type_parameters)
 773            Result := do_get_type(cluster, type_lookup.resolver.position(type_definition), class_name.intern, parameters)
 774         end
 775      end
 776
 777feature {}
 778   do_get_type (cluster: LIBERTY_CLUSTER; position: LIBERTY_POSITION; class_name: FIXED_STRING; effective_type_parameters: TRAVERSABLE[LIBERTY_TYPE]): LIBERTY_ACTUAL_TYPE is
 779      require
 780         position /= Void
 781      local
 782         descriptor: LIBERTY_TYPE_DESCRIPTOR
 783         c: like cluster
 784      do
 785         if cluster = Void then
 786            c := root.find(class_name)
 787         else
 788            c := cluster.find(class_name)
 789         end
 790         if c = Void then
 791            errors.add_position(position)
 792            errors.set(level_fatal_error, "Looks like some configuration is missing, or you mistyped something. Anyway I cannot find the class named " + class_name + ".")
 793         end
 794         create descriptor.make(create {LIBERTY_CLASS_DESCRIPTOR}.make(c, class_name.intern, position), effective_type_parameters)
 795         Result := do_get_type_from_descriptor(descriptor)
 796      ensure
 797         Result.name.is_equal(class_name)
 798         same_parameters(Result.parameters, effective_type_parameters)
 799      end
 800
 801   do_get_type_from_descriptor (descriptor: LIBERTY_TYPE_DESCRIPTOR): LIBERTY_ACTUAL_TYPE is
 802      require
 803         not errors.has_error
 804      local
 805         ast: LIBERTY_AST_ONE_CLASS
 806      do
 807         Result := types.reference_at(descriptor)
 808         if Result = Void then
 809            ast := parse_class(descriptor.cluster, descriptor.name, descriptor.position)
 810            create Result.make(descriptor, standard_generics_checker, ast, visit_user_type)
 811            start_to_build_type(Result)
 812         end
 813      ensure
 814         Result.cluster.is_equal(descriptor.cluster)
 815         Result.name.is_equal(descriptor.name)
 816         same_parameters(Result.parameters, descriptor.parameters)
 817      end
 818
 819feature {}
 820   same_parameters (params1, params2: TRAVERSABLE[LIBERTY_TYPE]): BOOLEAN is
 821         -- Simply doing "params1.is_equal(params2)" does not always work because one or both may actually be
 822         -- a TRAVERSABLE[LIBERTY_ACTUAL_TYPE] - and is_equal has a postcondition that requires the same
 823         -- actual runtime type for both the target and the parameter.
 824      require
 825         params1 /= Void
 826         params2 /= Void
 827      local
 828         i: INTEGER
 829      do
 830         if params1.count = params2.count then
 831            check
 832               params1.lower = params2.lower
 833            end
 834            from
 835               Result := True
 836               i := params1.lower
 837            until
 838               not Result or else i > params1.upper
 839            loop
 840               if params1.item(i) /= params2.item(i) then
 841                  Result := params1.item(i).is_known and then params2.item(i).is_known
 842                     and then params1.item(i).known_type = params2.item(i).known_type
 843               end
 844               i := i + 1
 845            end
 846         end
 847      end
 848
 849feature {} -- Type parameters fetching
 850   get_parameters (type_parameters: LIBERTY_AST_EFFECTIVE_TYPE_PARAMETERS): COLLECTION[LIBERTY_TYPE] is
 851      local
 852         type_parameter: LIBERTY_AST_EFFECTIVE_TYPE_PARAMETER
 853         type_definition: LIBERTY_AST_TYPE_DEFINITION
 854         type: LIBERTY_TYPE
 855         i: INTEGER
 856      do
 857         if type_parameters.list_is_empty then
 858            Result := no_parameters
 859         else
 860            create {FAST_ARRAY[LIBERTY_TYPE]} Result.with_capacity(type_parameters.list_count)
 861            from
 862               i := type_parameters.list_lower
 863            until
 864               i > type_parameters.list_upper
 865            loop
 866               type_parameter := type_parameters.list_item(i)
 867               type_definition := type_parameter.type_definition
 868               type := type_lookup.resolver.type(type_definition)
 869               Result.add_last(type)
 870               i := i + 1
 871            end
 872         end
 873      end
 874
 875   no_parameters: COLLECTION[LIBERTY_TYPE] is
 876      once
 877         create {FAST_ARRAY[LIBERTY_TYPE]} Result.with_capacity(0)
 878      end
 879
 880feature {LIBERTY_TYPE_RESOLVER_IN_TYPE}
 881   parse_class (cluster: LIBERTY_CLUSTER; class_name: FIXED_STRING; pos: LIBERTY_POSITION): LIBERTY_AST_ONE_CLASS is
 882      require
 883         cluster /= Void
 884         class_name /= Void
 885      local
 886         code: STRING; class_descriptor: LIBERTY_CLASS_DESCRIPTOR
 887         ast: LIBERTY_AST_CLASS; actual_cluster: LIBERTY_CLUSTER
 888         evaled: BOOLEAN
 889      do
 890         actual_cluster := cluster.find(class_name)
 891         if actual_cluster = Void then
 892            errors.set(level_fatal_error,
 893                       "Looks like some configuration is missing, or you mistyped something. Anyway I cannot find the class named " + class_name + ".")
 894            check
 895               dead: False
 896            end
 897         end
 898         create class_descriptor.make(actual_cluster, class_name, pos)
 899         Result := classes.reference_at(class_descriptor)
 900         if Result = Void then
 901            log.info.put_string(once "Parsing ")
 902            log.info.put_string(cluster.name)
 903            log.info.put_character('.')
 904            log.info.put_line(class_name)
 905
 906            code := once ""
 907            code.clear_count
 908            read_file_in(class_descriptor, code)
 909            parser_buffer.initialize_with(code)
 910
 911            eiffel.reset
 912            evaled := parser.eval(parser_buffer, eiffel.table, once "Class")
 913            if not evaled then
 914               errors.add_position(errors.syntax_position(code.upper, code, class_descriptor.file.intern))
 915               errors.set(level_fatal_error,
 916                          "I'm afraid you need to use a bit more those fingers of yours. The code of the class " + class_name
 917                          +" is incomplete.")
 918                errors.emit
 919               check
 920                  dead: False
 921               end
 922            end
 923            if parser.error /= Void then
 924               errors.emit_syntax_error(parser.error, code, class_descriptor.file.intern)
 925               die_with_code(1)
 926            end
 927            ast ::= eiffel.root_node
 928            Result := ast.one_class
 929            classes.put(Result, class_descriptor)
 930
 931            log.trace.put_string(cluster.name)
 932            log.trace.put_character('.')
 933            log.trace.put_string(class_name)
 934            log.trace.put_line(once " parsed.")
 935         end
 936      ensure
 937         Result /= Void
 938      end
 939
 940feature {} -- AST building
 941   read_file_in (descriptor: LIBERTY_CLASS_DESCRIPTOR; code: STRING) is
 942      require
 943         descriptor /= Void
 944         code.is_empty
 945      local
 946         file: FIXED_STRING
 947      do
 948         file := descriptor.file
 949         parser_file.connect_to(file)
 950         if not parser_file.is_connected then
 951            std_error.put_string(" *** Could not read file " + file)
 952            die_with_code(1)
 953         end
 954
 955         from
 956            parser_file.read_line
 957         until
 958            parser_file.end_of_input
 959         loop
 960            code.append(parser_file.last_string)
 961            code.extend('%N')
 962            parser_file.read_line
 963         end
 964         code.append(parser_file.last_string)
 965         parser_file.disconnect
 966      end
 967
 968   parse_tuple_classes (pos: LIBERTY_POSITION): LIBERTY_AST_CLASSES is
 969      local
 970         code: STRING; class_descriptor: LIBERTY_CLASS_DESCRIPTOR
 971         tuple_cluster: LIBERTY_CLUSTER
 972         i: INTEGER; file: FIXED_STRING
 973         one_class: LIBERTY_AST_ONE_CLASS
 974         evaled: BOOLEAN
 975      once
 976         log.info.put_line(once "Parsing TUPLE")
 977
 978         tuple_cluster := root.find("TUPLE".intern)
 979         if tuple_cluster = Void then
 980            errors.set(level_fatal_error, "What's that installation of yours? I cannot even find the kernel class TUPLE!")
 981         end
 982         create class_descriptor.make(tuple_cluster, "TUPLE".intern, pos)
 983         code := once ""
 984         code.clear_count
 985         read_file_in(class_descriptor, code)
 986         parser_buffer.initialize_with(code)
 987
 988         eiffel.reset
 989         evaled := parser.eval(parser_buffer, eiffel.table, once "Classes")
 990         if not evaled then
 991            errors.add_position(errors.syntax_position(code.upper, code, class_descriptor.file.intern))
 992            errors.set(level_fatal_error,
 993                       "The code of the class TUPLE is incomplete. Maybe you could try installing Liberty again?")
 994             errors.emit
 995            check
 996               dead: False
 997            end
 998         end
 999         if parser.error /= Void then
1000            errors.emit_syntax_error(parser.error, code, class_descriptor.file.intern)
1001            die_with_code(1)
1002         end
1003         Result ::= eiffel.root_node
1004         file := class_descriptor.file.intern
1005         from
1006            i := Result.classes.lower
1007            check i = 0 end
1008         until
1009            i > Result.classes.upper
1010         loop
1011            one_class ::= Result.classes.item(i)
1012            check_tuple_class(one_class, i, Result, file)
1013            i := i + 1
1014         end
1015
1016         log.trace.put_line(once "TUPLE parsed.")
1017      ensure
1018         Result /= Void
1019      end
1020
1021   check_tuple_class (a_tuple_class: LIBERTY_AST_ONE_CLASS; generics_count: INTEGER; ast: LIBERTY_AST_CLASSES; file: FIXED_STRING) is
1022         -- minimal integrity check
1023      local
1024         classname: STRING
1025         gencount: INTEGER
1026      do
1027         classname := a_tuple_class.class_header.class_name.image.image
1028         if not classname.is_equal(once "TUPLE") then
1029            errors.add_position(errors.semantics_position(a_tuple_class.class_header.class_name.image.index, ast, file))
1030            errors.set(level_fatal_error, "Invalid TUPLE class text: strangely enough it does not contain TUPLE. Maybe you could try installing Liberty again?")
1031         end
1032         gencount := a_tuple_class.class_header.type_parameters.list_count
1033         if gencount /= generics_count then
1034            errors.add_position(errors.semantics_position(a_tuple_class.class_header.class_name.image.index, ast, file))
1035            if generics_count = 1 then
1036               errors.set(level_fatal_error,
1037                          "Invalid TUPLE class text: expected 1 generic parameter but got " + gencount.out
1038                          + ". Maybe you could try installing Liberty again?")
1039            else
1040               errors.set(level_fatal_error,
1041                          "Invalid TUPLE class text: expected " + generics_count.out + " generic parameters but got " + gencount.out
1042                          + ". Maybe you could try installing Liberty again)?")
1043            end
1044         end
1045      ensure
1046         not errors.has_error
1047      end
1048
1049   parser_file: TEXT_FILE_READ is
1050      once
1051         create Result.make
1052      end
1053
1054   parser_buffer: MINI_PARSER_BUFFER is
1055      once
1056         create Result
1057      end
1058
1059   parser: DESCENDING_PARSER is
1060      once
1061         create Result.make
1062      end
1063
1064   eiffel: EIFFEL_GRAMMAR is
1065      once
1066         create Result.make(create {LIBERTY_NODE_FACTORY}.make)
1067      end
1068
1069feature {}
1070   default_type_capacity: INTEGER is 4096
1071
1072   make is
1073      local
1074         tr: LIBERTY_TYPE_RESOLVER_IN_UNIVERSE
1075      do
1076         type_lookup.set_universe(Current)
1077         create root.make_root
1078         create {HASHED_DICTIONARY[LIBERTY_AST_ONE_CLASS, LIBERTY_CLASS_DESCRIPTOR]} classes.with_capacity(default_type_capacity)
1079         create {HASHED_DICTIONARY[LIBERTY_ACTUAL_TYPE, LIBERTY_TYPE_DESCRIPTOR]} types.with_capacity(default_type_capacity)
1080         create types_incubator.with_capacity(default_type_capacity, 0)
1081         create tr.make(Current)
1082         type_lookup.push(tr)
1083      end
1084
1085   root: LIBERTY_CLUSTER
1086
1087   classes: DICTIONARY[LIBERTY_AST_ONE_CLASS, LIBERTY_CLASS_DESCRIPTOR]
1088   types: DICTIONARY[LIBERTY_ACTUAL_TYPE, LIBERTY_TYPE_DESCRIPTOR]
1089
1090   types_incubator: RING_ARRAY[LIBERTY_ACTUAL_TYPE]
1091
1092   errors: LIBERTY_ERRORS
1093   torch: LIBERTY_ENLIGHTENING_THE_WORLD
1094   type_lookup: LIBERTY_TYPE_LOOKUP
1095
1096   standard_generics_checker: LIBERTY_GENERICS_CONFORMANCE_CHECKER is
1097      once
1098         create {LIBERTY_STANDARD_GENERICS_CONFORMANCE_CHECKER} Result.make
1099      end
1100
1101   tuple_generics_checker: LIBERTY_GENERICS_CONFORMANCE_CHECKER is
1102      once
1103         create {LIBERTY_TUPLE_CONFORMANCE_CHECKER} Result.make
1104      end
1105
1106   agent_generics_checker: LIBERTY_GENERICS_CONFORMANCE_CHECKER is
1107      once
1108         create {LIBERTY_AGENT_CONFORMANCE_CHECKER} Result.make
1109      end
1110
1111feature {}
1112   visit_type_any: PROCEDURE[TUPLE[LIBERTY_TYPE_VISITOR, LIBERTY_ACTUAL_TYPE]] is
1113      once
1114         Result := agent {LIBERTY_TYPE_VISITOR}.visit_type_any
1115      end
1116
1117   visit_type_arguments: PROCEDURE[TUPLE[LIBERTY_TYPE_VISITOR, LIBERTY_ACTUAL_TYPE]] is
1118      once
1119         Result := agent {LIBERTY_TYPE_VISITOR}.visit_type_arguments
1120      end
1121
1122   visit_type_platform: PROCEDURE[TUPLE[LIBERTY_TYPE_VISITOR, LIBERTY_ACTUAL_TYPE]] is
1123      once
1124         Result := agent {LIBERTY_TYPE_VISITOR}.visit_type_platform
1125      end
1126
1127   visit_type_pointer: PROCEDURE[TUPLE[LIBERTY_TYPE_VISITOR, LIBERTY_ACTUAL_TYPE]] is
1128      once
1129         Result := agent {LIBERTY_TYPE_VISITOR}.visit_type_pointer
1130      end
1131
1132   visit_type_integer_64: PROCEDURE[TUPLE[LIBERTY_TYPE_VISITOR, LIBERTY_ACTUAL_TYPE]] is
1133      once
1134         Result := agent {LIBERTY_TYPE_VISITOR}.visit_type_integer_64
1135      end
1136
1137   visit_type_integer_32: PROCEDURE[TUPLE[LIBERTY_TYPE_VISITOR, LIBERTY_ACTUAL_TYPE]] is
1138      once
1139         Result := agent {LIBERTY_TYPE_VISITOR}.visit_type_integer_32
1140      end
1141
1142   visit_type_integer_16: PROCEDURE[TUPLE[LIBERTY_TYPE_VISITOR, LIBERTY_ACTUAL_TYPE]] is
1143      once
1144         Result := agent {LIBERTY_TYPE_VISITOR}.visit_type_integer_16
1145      end
1146
1147   visit_type_integer_8: PROCEDURE[TUPLE[LIBERTY_TYPE_VISITOR, LIBERTY_ACTUAL_TYPE]] is
1148      once
1149         Result := agent {LIBERTY_TYPE_VISITOR}.visit_type_integer_8
1150      end
1151
1152   visit_type_real_64: PROCEDURE[TUPLE[LIBERTY_TYPE_VISITOR, LIBERTY_ACTUAL_TYPE]] is
1153      once
1154         Result := agent {LIBERTY_TYPE_VISITOR}.visit_type_real_64
1155      end
1156
1157   visit_type_real_32: PROCEDURE[TUPLE[LIBERTY_TYPE_VISITOR, LIBERTY_ACTUAL_TYPE]] is
1158      once
1159         Result := agent {LIBERTY_TYPE_VISITOR}.visit_type_real_32
1160      end
1161
1162   visit_type_real_80: PROCEDURE[TUPLE[LIBERTY_TYPE_VISITOR, LIBERTY_ACTUAL_TYPE]] is
1163      once
1164         Result := agent {LIBERTY_TYPE_VISITOR}.visit_type_real_80
1165      end
1166
1167   visit_type_real_128: PROCEDURE[TUPLE[LIBERTY_TYPE_VISITOR, LIBERTY_ACTUAL_TYPE]] is
1168      once
1169         Result := agent {LIBERTY_TYPE_VISITOR}.visit_type_real_128
1170      end
1171
1172   visit_type_character: PROCEDURE[TUPLE[LIBERTY_TYPE_VISITOR, LIBERTY_ACTUAL_TYPE]] is
1173      once
1174         Result := agent {LIBERTY_TYPE_VISITOR}.visit_type_character
1175      end
1176
1177   visit_type_string: PROCEDURE[TUPLE[LIBERTY_TYPE_VISITOR, LIBERTY_ACTUAL_TYPE]] is
1178      once
1179         Result := agent {LIBERTY_TYPE_VISITOR}.visit_type_string
1180      end
1181
1182   visit_type_boolean: PROCEDURE[TUPLE[LIBERTY_TYPE_VISITOR, LIBERTY_ACTUAL_TYPE]] is
1183      once
1184         Result := agent {LIBERTY_TYPE_VISITOR}.visit_type_boolean
1185      end
1186
1187   visit_type_native_array: PROCEDURE[TUPLE[LIBERTY_TYPE_VISITOR, LIBERTY_ACTUAL_TYPE]] is
1188      once
1189         Result := agent {LIBERTY_TYPE_VISITOR}.visit_type_native_array
1190      end
1191
1192   visit_type_tuple: PROCEDURE[TUPLE[LIBERTY_TYPE_VISITOR, LIBERTY_ACTUAL_TYPE]] is
1193      once
1194         Result := agent {LIBERTY_TYPE_VISITOR}.visit_type_tuple
1195      end
1196
1197   visit_type_routine: PROCEDURE[TUPLE[LIBERTY_TYPE_VISITOR, LIBERTY_ACTUAL_TYPE]] is
1198      once
1199         Result := agent {LIBERTY_TYPE_VISITOR}.visit_type_routine
1200      end
1201
1202   visit_type_procedure: PROCEDURE[TUPLE[LIBERTY_TYPE_VISITOR, LIBERTY_ACTUAL_TYPE]] is
1203      once
1204         Result := agent {LIBERTY_TYPE_VISITOR}.visit_type_procedure
1205      end
1206
1207   visit_type_function: PROCEDURE[TUPLE[LIBERTY_TYPE_VISITOR, LIBERTY_ACTUAL_TYPE]] is
1208      once
1209         Result := agent {LIBERTY_TYPE_VISITOR}.visit_type_function
1210      end
1211
1212   visit_type_predicate: PROCEDURE[TUPLE[LIBERTY_TYPE_VISITOR, LIBERTY_ACTUAL_TYPE]] is
1213      once
1214         Result := agent {LIBERTY_TYPE_VISITOR}.visit_type_predicate
1215      end
1216
1217   visit_user_type: PROCEDURE[TUPLE[LIBERTY_TYPE_VISITOR, LIBERTY_ACTUAL_TYPE]] is
1218      once
1219         Result := agent {LIBERTY_TYPE_VISITOR}.visit_user_type
1220      end
1221
1222feature {}
1223   convert_integer_8_16: PROCEDURE[TUPLE[LIBERTY_TYPE_CONVERTER]] is
1224      once
1225         Result := agent {LIBERTY_TYPE_CONVERTER}.convert_integer_8_16
1226      end
1227
1228   convert_integer_8_32: PROCEDURE[TUPLE[LIBERTY_TYPE_CONVERTER]] is
1229      once
1230         Result := agent {LIBERTY_TYPE_CONVERTER}.convert_integer_8_32
1231      end
1232
1233   convert_integer_8_64: PROCEDURE[TUPLE[LIBERTY_TYPE_CONVERTER]] is
1234      once
1235         Result := agent {LIBERTY_TYPE_CONVERTER}.convert_integer_8_64
1236      end
1237
1238   convert_integer_16_32: PROCEDURE[TUPLE[LIBERTY_TYPE_CONVERTER]] is
1239      once
1240         Result := agent {LIBERTY_TYPE_CONVERTER}.convert_integer_16_32
1241      end
1242
1243   convert_integer_16_64: PROCEDURE[TUPLE[LIBERTY_TYPE_CONVERTER]] is
1244      once
1245         Result := agent {LIBERTY_TYPE_CONVERTER}.convert_integer_16_64
1246      end
1247
1248   convert_integer_32_64: PROCEDURE[TUPLE[LIBERTY_TYPE_CONVERTER]] is
1249      once
1250         Result := agent {LIBERTY_TYPE_CONVERTER}.convert_integer_32_64
1251      end
1252
1253   convert_real_32_64: PROCEDURE[TUPLE[LIBERTY_TYPE_CONVERTER]] is
1254      once
1255         Result := agent {LIBERTY_TYPE_CONVERTER}.convert_real_32_64
1256      end
1257
1258   convert_real_32_80: PROCEDURE[TUPLE[LIBERTY_TYPE_CONVERTER]] is
1259      once
1260         Result := agent {LIBERTY_TYPE_CONVERTER}.convert_real_32_80
1261      end
1262
1263   convert_real_32_128: PROCEDURE[TUPLE[LIBERTY_TYPE_CONVERTER]] is
1264      once
1265         Result := agent {LIBERTY_TYPE_CONVERTER}.convert_real_32_128
1266      end
1267
1268   convert_real_64_80: PROCEDURE[TUPLE[LIBERTY_TYPE_CONVERTER]] is
1269      once
1270         Result := agent {LIBERTY_TYPE_CONVERTER}.convert_real_64_80
1271      end
1272
1273   convert_real_64_128: PROCEDURE[TUPLE[LIBERTY_TYPE_CONVERTER]] is
1274      once
1275         Result := agent {LIBERTY_TYPE_CONVERTER}.convert_real_64_128
1276      end
1277
1278   convert_real_80_128: PROCEDURE[TUPLE[LIBERTY_TYPE_CONVERTER]] is
1279      once
1280         Result := agent {LIBERTY_TYPE_CONVERTER}.convert_real_80_128
1281      end
1282
1283   convert_integer_64_real_128: PROCEDURE[TUPLE[LIBERTY_TYPE_CONVERTER]] is
1284      once
1285         Result := agent {LIBERTY_TYPE_CONVERTER}.convert_integer_64_real_128
1286      end
1287
1288   convert_integer_64_real_80: PROCEDURE[TUPLE[LIBERTY_TYPE_CONVERTER]] is
1289      once
1290         Result := agent {LIBERTY_TYPE_CONVERTER}.convert_integer_64_real_80
1291      end
1292
1293   convert_integer_32_real_128: PROCEDURE[TUPLE[LIBERTY_TYPE_CONVERTER]] is
1294      once
1295         Result := agent {LIBERTY_TYPE_CONVERTER}.convert_integer_32_real_128
1296      end
1297
1298   convert_integer_32_real_80: PROCEDURE[TUPLE[LIBERTY_TYPE_CONVERTER]] is
1299      once
1300         Result := agent {LIBERTY_TYPE_CONVERTER}.convert_integer_32_real_80
1301      end
1302
1303   convert_integer_32_real_64: PROCEDURE[TUPLE[LIBERTY_TYPE_CONVERTER]] is
1304      once
1305         Result := agent {LIBERTY_TYPE_CONVERTER}.convert_integer_32_real_64
1306      end
1307
1308   convert_integer_16_real_128: PROCEDURE[TUPLE[LIBERTY_TYPE_CONVERTER]] is
1309      once
1310         Result := agent {LIBERTY_TYPE_CONVERTER}.convert_integer_16_real_128
1311      end
1312
1313   convert_integer_16_real_80: PROCEDURE[TUPLE[LIBERTY_TYPE_CONVERTER]] is
1314      once
1315         Result := agent {LIBERTY_TYPE_CONVERTER}.convert_integer_16_real_80
1316      end
1317
1318   convert_integer_16_real_64: PROCEDURE[TUPLE[LIBERTY_TYPE_CONVERTER]] is
1319      once
1320         Result := agent {LIBERTY_TYPE_CONVERTER}.convert_integer_16_real_64
1321      end
1322
1323   convert_integer_16_real_32: PROCEDURE[TUPLE[LIBERTY_TYPE_CONVERTER]] is
1324      once
1325         Result := agent {LIBERTY_TYPE_CONVERTER}.convert_integer_16_real_32
1326      end
1327
1328   convert_integer_8_real_128: PROCEDURE[TUPLE[LIBERTY_TYPE_CONVERTER]] is
1329      once
1330         Result := agent {LIBERTY_TYPE_CONVERTER}.convert_integer_8_real_128
1331      end
1332
1333   convert_integer_8_real_80: PROCEDURE[TUPLE[LIBERTY_TYPE_CONVERTER]] is
1334      once
1335         Result := agent {LIBERTY_TYPE_CONVERTER}.convert_integer_8_real_80
1336      end
1337
1338   convert_integer_8_real_64: PROCEDURE[TUPLE[LIBERTY_TYPE_CONVERTER]] is
1339      once
1340         Result := agent {LIBERTY_TYPE_CONVERTER}.convert_integer_8_real_64
1341      end
1342
1343   convert_integer_8_real_32: PROCEDURE[TUPLE[LIBERTY_TYPE_CONVERTER]] is
1344      once
1345         Result := agent {LIBERTY_TYPE_CONVERTER}.convert_integer_8_real_32
1346      end
1347
1348invariant
1349   types /= Void
1350   classes /= Void
1351   types_incubator /= Void
1352
1353end