fOOrth 0.5.3 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/.gitignore +1 -0
 - data/README.md +9 -5
 - data/integration/array_lib_tests.rb +2 -0
 - data/integration/clone_lib_tests.rb +21 -11
 - data/integration/standard_lib_tests.rb +5 -2
 - data/integration/string_lib_tests.rb +304 -14
 - data/integration/thread_lib_tests.rb +2 -2
 - data/lib/fOOrth/compiler/process/string.rb +8 -1
 - data/lib/fOOrth/compiler/source.rb +13 -2
 - data/lib/fOOrth/compiler/source/console.rb +19 -3
 - data/lib/fOOrth/core/class.rb +2 -2
 - data/lib/fOOrth/library/array_library.rb +5 -1
 - data/lib/fOOrth/library/class_library.rb +1 -1
 - data/lib/fOOrth/library/command_library.rb +2 -2
 - data/lib/fOOrth/library/duration_library.rb +1 -1
 - data/lib/fOOrth/library/hash_library.rb +1 -1
 - data/lib/fOOrth/library/in_stream_library.rb +3 -3
 - data/lib/fOOrth/library/object_library.rb +11 -1
 - data/lib/fOOrth/library/out_stream_library.rb +6 -6
 - data/lib/fOOrth/library/procedure_library.rb +1 -1
 - data/lib/fOOrth/library/stdio_library.rb +1 -1
 - data/lib/fOOrth/library/string_library.rb +82 -33
 - data/lib/fOOrth/library/thread_library.rb +1 -1
 - data/lib/fOOrth/library/vm_library.rb +1 -1
 - data/lib/fOOrth/monkey_patch/numeric.rb +1 -1
 - data/lib/fOOrth/monkey_patch/object.rb +5 -0
 - data/lib/fOOrth/monkey_patch/string.rb +58 -1
 - data/lib/fOOrth/version.rb +1 -1
 - data/tests/monkey_patch/string_test.rb +10 -2
 - metadata +2 -2
 
| 
         @@ -71,11 +71,11 @@ class ThreadLibraryTester < Minitest::Test 
     | 
|
| 
       71 
71 
     | 
    
         
             
                foorth_run('$tmtx .lock $tmtx .unlock ')
         
     | 
| 
       72 
72 
     | 
    
         
             
                foorth_equal('$tmtx .do{{ 3 4 + }}', [7])
         
     | 
| 
       73 
73 
     | 
    
         | 
| 
       74 
     | 
    
         
            -
                foorth_run('"" val$: $tmtx_str')
         
     | 
| 
      
 74 
     | 
    
         
            +
                foorth_run('""* val$: $tmtx_str')
         
     | 
| 
       75 
75 
     | 
    
         
             
                foorth_equal('{{ $tmtx .do{{ 0 10 do $tmtx_str "@" << loop }} }} ' +
         
     | 
| 
       76 
76 
     | 
    
         
             
                             '.start drop $tmtx .do{{ $tmtx_str }} ', ["@"*10])
         
     | 
| 
       77 
77 
     | 
    
         | 
| 
       78 
     | 
    
         
            -
                foorth_run('"" val$: $tmtx_str')
         
     | 
| 
      
 78 
     | 
    
         
            +
                foorth_run('""* val$: $tmtx_str')
         
     | 
| 
       79 
79 
     | 
    
         
             
                foorth_equal('{{ Mutex .do{{ 0 10 do $tmtx_str "@" << loop }} }} ' +
         
     | 
| 
       80 
80 
     | 
    
         
             
                             '.start drop Mutex .do{{ $tmtx_str }} ', ["@"*10])
         
     | 
| 
       81 
81 
     | 
    
         
             
              end
         
     | 
| 
         @@ -12,7 +12,14 @@ module XfOOrth 
     | 
|
| 
       12 
12 
     | 
    
         
             
                #* word  - The text of the word.
         
     | 
| 
       13 
13 
     | 
    
         
             
                def string_parms(token, word)
         
     | 
| 
       14 
14 
     | 
    
         
             
                  if word.end_with?('"')
         
     | 
| 
       15 
     | 
    
         
            -
                     
     | 
| 
      
 15 
     | 
    
         
            +
                    string_value = parser.get_string.foorth_embed
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                    if parser.source.peek == '*'
         
     | 
| 
      
 18 
     | 
    
         
            +
                      parser.source.get
         
     | 
| 
      
 19 
     | 
    
         
            +
                      token.add("vm.push(StringBuffer.new(#{string_value})); ")
         
     | 
| 
      
 20 
     | 
    
         
            +
                    else
         
     | 
| 
      
 21 
     | 
    
         
            +
                      token.add("vm.push(#{string_value}.freeze); ")
         
     | 
| 
      
 22 
     | 
    
         
            +
                    end
         
     | 
| 
       16 
23 
     | 
    
         
             
                  end
         
     | 
| 
       17 
24 
     | 
    
         
             
                end
         
     | 
| 
       18 
25 
     | 
    
         | 
| 
         @@ -13,21 +13,23 @@ module XfOOrth 
     | 
|
| 
       13 
13 
     | 
    
         
             
                def initialize
         
     | 
| 
       14 
14 
     | 
    
         
             
                  reset_read_point
         
     | 
| 
       15 
15 
     | 
    
         
             
                  @eof = false
         
     | 
| 
      
 16 
     | 
    
         
            +
                  @peek_buffer = nil
         
     | 
| 
       16 
17 
     | 
    
         
             
                end
         
     | 
| 
       17 
18 
     | 
    
         | 
| 
       18 
19 
     | 
    
         
             
                #Close the source.
         
     | 
| 
       19 
20 
     | 
    
         
             
                def close
         
     | 
| 
       20 
21 
     | 
    
         
             
                  @eoln = true
         
     | 
| 
       21 
22 
     | 
    
         
             
                  @eof = true
         
     | 
| 
      
 23 
     | 
    
         
            +
                  @peek_buffer = nil
         
     | 
| 
       22 
24 
     | 
    
         
             
                end
         
     | 
| 
       23 
25 
     | 
    
         | 
| 
       24 
26 
     | 
    
         
             
                #Get the next character of input data
         
     | 
| 
       25 
27 
     | 
    
         
             
                #<br>Returns:
         
     | 
| 
       26 
28 
     | 
    
         
             
                #* The next character or nil if none are available.
         
     | 
| 
       27 
29 
     | 
    
         
             
                def get
         
     | 
| 
       28 
     | 
    
         
            -
                  return nil if @eof
         
     | 
| 
      
 30 
     | 
    
         
            +
                  return nil if (@eof && !@peek_buffer)
         
     | 
| 
       29 
31 
     | 
    
         | 
| 
       30 
     | 
    
         
            -
                  read do
         
     | 
| 
      
 32 
     | 
    
         
            +
                  @peek_buffer || read do
         
     | 
| 
       31 
33 
     | 
    
         
             
                    begin
         
     | 
| 
       32 
34 
     | 
    
         
             
                      @read_step.next.rstrip
         
     | 
| 
       33 
35 
     | 
    
         
             
                    rescue StopIteration
         
     | 
| 
         @@ -35,6 +37,15 @@ module XfOOrth 
     | 
|
| 
       35 
37 
     | 
    
         
             
                      nil
         
     | 
| 
       36 
38 
     | 
    
         
             
                    end
         
     | 
| 
       37 
39 
     | 
    
         
             
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
                ensure
         
     | 
| 
      
 41 
     | 
    
         
            +
                  @peek_buffer = nil
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                #Peek ahead by one character.
         
     | 
| 
      
 45 
     | 
    
         
            +
                #<br>Returns:
         
     | 
| 
      
 46 
     | 
    
         
            +
                #* A peek at next character or nil if none are available.
         
     | 
| 
      
 47 
     | 
    
         
            +
                def peek
         
     | 
| 
      
 48 
     | 
    
         
            +
                  @peek_buffer ||= get
         
     | 
| 
       38 
49 
     | 
    
         
             
                end
         
     | 
| 
       39 
50 
     | 
    
         | 
| 
       40 
51 
     | 
    
         
             
                #Has the source reached the end of the available data?
         
     | 
| 
         @@ -11,6 +11,8 @@ module XfOOrth 
     | 
|
| 
       11 
11 
     | 
    
         | 
| 
       12 
12 
     | 
    
         
             
                #Initialize a new console command source.
         
     | 
| 
       13 
13 
     | 
    
         
             
                def initialize
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @peek_buffer = nil
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
       14 
16 
     | 
    
         
             
                  reset_read_point
         
     | 
| 
       15 
17 
     | 
    
         | 
| 
       16 
18 
     | 
    
         
             
                  auto_src = lambda { SymbolMap.forward_map.keys.sort  }
         
     | 
| 
         @@ -22,16 +24,30 @@ module XfOOrth 
     | 
|
| 
       22 
24 
     | 
    
         
             
                                                     eoi_detect: true)
         
     | 
| 
       23 
25 
     | 
    
         
             
                end
         
     | 
| 
       24 
26 
     | 
    
         | 
| 
       25 
     | 
    
         
            -
                 
     | 
| 
       26 
     | 
    
         
            -
                 
     | 
| 
      
 27 
     | 
    
         
            +
                #Close the console source.
         
     | 
| 
      
 28 
     | 
    
         
            +
                def close
         
     | 
| 
      
 29 
     | 
    
         
            +
                  @peek_buffer = nil
         
     | 
| 
      
 30 
     | 
    
         
            +
                  reset_read_point
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                alias flush close
         
     | 
| 
       27 
34 
     | 
    
         | 
| 
       28 
35 
     | 
    
         
             
                #Get the next character of command text from the user.
         
     | 
| 
       29 
36 
     | 
    
         
             
                #<br>Returns
         
     | 
| 
       30 
37 
     | 
    
         
             
                #* The next character of user input as a string.
         
     | 
| 
       31 
38 
     | 
    
         
             
                def get
         
     | 
| 
       32 
     | 
    
         
            -
                  read do
         
     | 
| 
      
 39 
     | 
    
         
            +
                  @peek_buffer || read do
         
     | 
| 
       33 
40 
     | 
    
         
             
                    @edit.readline(prompt: prompt).rstrip
         
     | 
| 
       34 
41 
     | 
    
         
             
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
                ensure
         
     | 
| 
      
 43 
     | 
    
         
            +
                  @peek_buffer = nil
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                #Peek ahead by one character.
         
     | 
| 
      
 47 
     | 
    
         
            +
                #<br>Returns:
         
     | 
| 
      
 48 
     | 
    
         
            +
                #* A peek at next character or nil if none are available.
         
     | 
| 
      
 49 
     | 
    
         
            +
                def peek
         
     | 
| 
      
 50 
     | 
    
         
            +
                  @peek_buffer ||= get
         
     | 
| 
       35 
51 
     | 
    
         
             
                end
         
     | 
| 
       36 
52 
     | 
    
         | 
| 
       37 
53 
     | 
    
         
             
                #Has the scanning of the text reached the end of input?
         
     | 
    
        data/lib/fOOrth/core/class.rb
    CHANGED
    
    | 
         @@ -7,14 +7,14 @@ class Class 
     | 
|
| 
       7 
7 
     | 
    
         
             
              #<br>Decree!
         
     | 
| 
       8 
8 
     | 
    
         
             
              #* These are to be the only references to @_private_foorth_name!
         
     | 
| 
       9 
9 
     | 
    
         
             
              def foorth_name
         
     | 
| 
       10 
     | 
    
         
            -
                @_private_foorth_name ||= name
         
     | 
| 
      
 10 
     | 
    
         
            +
                @_private_foorth_name ||= name.freeze
         
     | 
| 
       11 
11 
     | 
    
         
             
              end
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
       13 
13 
     | 
    
         
             
              #Set the foorth name of this class.
         
     | 
| 
       14 
14 
     | 
    
         
             
              #<br>Decree!
         
     | 
| 
       15 
15 
     | 
    
         
             
              #* These are to be the only references to @_private_foorth_name!
         
     | 
| 
       16 
16 
     | 
    
         
             
              def foorth_name=(new_name)
         
     | 
| 
       17 
     | 
    
         
            -
                @_private_foorth_name = new_name
         
     | 
| 
      
 17 
     | 
    
         
            +
                @_private_foorth_name = new_name.freeze
         
     | 
| 
       18 
18 
     | 
    
         
             
              end
         
     | 
| 
       19 
19 
     | 
    
         | 
| 
       20 
20 
     | 
    
         
             
              #Access/create the class's shared fOOrth dictionary.
         
     | 
| 
         @@ -119,6 +119,10 @@ module XfOOrth 
     | 
|
| 
       119 
119 
     | 
    
         
             
              Array.create_shared_method('<<', NosSpec, [],
         
     | 
| 
       120 
120 
     | 
    
         
             
                &lambda {|vm| vm.poke(self << vm.peek); })
         
     | 
| 
       121 
121 
     | 
    
         | 
| 
      
 122 
     | 
    
         
            +
              # [ [ 3 1 2 ] n ] >> [ [ n 3 1 2 ] ]
         
     | 
| 
      
 123 
     | 
    
         
            +
              Array.create_shared_method('>>', NosSpec, [],
         
     | 
| 
      
 124 
     | 
    
         
            +
                &lambda {|vm| vm.poke(self.insert(0, vm.peek)); })
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
       122 
126 
     | 
    
         
             
              # [[3 1 2] n] + [[3 1 2 n]]
         
     | 
| 
       123 
127 
     | 
    
         
             
              Array.create_shared_method('+', NosSpec, [],
         
     | 
| 
       124 
128 
     | 
    
         
             
                &lambda {|vm| vm.poke(self + vm.peek.in_array); })
         
     | 
| 
         @@ -474,7 +478,7 @@ module XfOOrth 
     | 
|
| 
       474 
478 
     | 
    
         
             
                  end
         
     | 
| 
       475 
479 
     | 
    
         
             
                end
         
     | 
| 
       476 
480 
     | 
    
         | 
| 
       477 
     | 
    
         
            -
                vm.push(result + "]")
         
     | 
| 
      
 481 
     | 
    
         
            +
                vm.push((result + "]").freeze)
         
     | 
| 
       478 
482 
     | 
    
         
             
              })
         
     | 
| 
       479 
483 
     | 
    
         | 
| 
       480 
484 
     | 
    
         
             
              # [ l 2 3 ... n ] .strmax [ widest ]
         
     | 
| 
         @@ -11,7 +11,7 @@ module XfOOrth 
     | 
|
| 
       11 
11 
     | 
    
         
             
              #Get the class as a string.
         
     | 
| 
       12 
12 
     | 
    
         
             
              # [cls] .to_s ["cls as a string"]
         
     | 
| 
       13 
13 
     | 
    
         
             
              Class.create_shared_method('.to_s', TosSpec, [], &lambda {|vm|
         
     | 
| 
       14 
     | 
    
         
            -
                vm.push(self.foorth_name || "AnonymousClass<#{self.object_id}>")
         
     | 
| 
      
 14 
     | 
    
         
            +
                vm.push(self.foorth_name || "AnonymousClass<#{self.object_id}>".freeze)
         
     | 
| 
       15 
15 
     | 
    
         
             
              })
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
       17 
17 
     | 
    
         
             
              #The .parent_class method. Retrieves the parent class of a class.
         
     | 
| 
         @@ -117,7 +117,7 @@ module XfOOrth 
     | 
|
| 
       117 
117 
     | 
    
         
             
                  error "F50: Unable to locate file #{file_name}"
         
     | 
| 
       118 
118 
     | 
    
         
             
                end
         
     | 
| 
       119 
119 
     | 
    
         | 
| 
       120 
     | 
    
         
            -
                vm.process_file(file_name)
         
     | 
| 
      
 120 
     | 
    
         
            +
                vm.process_file(file_name.freeze)
         
     | 
| 
       121 
121 
     | 
    
         | 
| 
       122 
122 
     | 
    
         
             
                puts "Completed in #{Time.now - start_time} seconds"
         
     | 
| 
       123 
123 
     | 
    
         
             
              })
         
     | 
| 
         @@ -180,7 +180,7 @@ module XfOOrth 
     | 
|
| 
       180 
180 
     | 
    
         
             
              #List the globals defined in fOOrth.
         
     | 
| 
       181 
181 
     | 
    
         
             
              VirtualMachine.create_shared_method(')globals', VmSpec, [], &lambda {|vm|
         
     | 
| 
       182 
182 
     | 
    
         
             
                $FOORTH_GLOBALS.keys.
         
     | 
| 
       183 
     | 
    
         
            -
                  select 
     | 
| 
      
 183 
     | 
    
         
            +
                  select  {|key| !($FOORTH_GLOBALS[key].has_tag?(:class))}.
         
     | 
| 
       184 
184 
     | 
    
         
             
                  collect {|key| "#{XfOOrth::SymbolMap.unmap(key)} (#{key.to_s})"}.
         
     | 
| 
       185 
185 
     | 
    
         
             
                  foorth_pretty(vm)
         
     | 
| 
       186 
186 
     | 
    
         
             
              })
         
     | 
| 
         @@ -47,6 +47,6 @@ module XfOOrth 
     | 
|
| 
       47 
47 
     | 
    
         | 
| 
       48 
48 
     | 
    
         
             
              #Default conversion to string. See duration/formatter for formatted output.
         
     | 
| 
       49 
49 
     | 
    
         
             
              Duration.create_shared_method('.to_s', TosSpec, [], &lambda {|vm|
         
     | 
| 
       50 
     | 
    
         
            -
                vm.push("Duration instance <#{self.period.to_f} seconds>" )
         
     | 
| 
      
 50 
     | 
    
         
            +
                vm.push("Duration instance <#{self.period.to_f} seconds>".freeze )
         
     | 
| 
       51 
51 
     | 
    
         
             
              })
         
     | 
| 
       52 
52 
     | 
    
         
             
            end
         
     | 
| 
         @@ -25,13 +25,13 @@ module XfOOrth 
     | 
|
| 
       25 
25 
     | 
    
         | 
| 
       26 
26 
     | 
    
         
             
              # ["file_name", InStream] .open [an_instream]
         
     | 
| 
       27 
27 
     | 
    
         
             
              in_stream.create_exclusive_method('.open', TosSpec, [], &lambda {|vm|
         
     | 
| 
       28 
     | 
    
         
            -
                file_name = vm.pop.to_s
         
     | 
| 
      
 28 
     | 
    
         
            +
                file_name = vm.pop.to_s.freeze
         
     | 
| 
       29 
29 
     | 
    
         
             
                vm.push(XfOOrth_InStream.new(file_name))
         
     | 
| 
       30 
30 
     | 
    
         
             
              })
         
     | 
| 
       31 
31 
     | 
    
         | 
| 
       32 
32 
     | 
    
         
             
              in_stream.create_exclusive_method('.open{{', NosSpec, [], &lambda {|vm|
         
     | 
| 
       33 
33 
     | 
    
         
             
                block = vm.pop
         
     | 
| 
       34 
     | 
    
         
            -
                file_name = vm.pop.to_s
         
     | 
| 
      
 34 
     | 
    
         
            +
                file_name = vm.pop.to_s.freeze
         
     | 
| 
       35 
35 
     | 
    
         
             
                in_stream = XfOOrth_InStream.new(file_name)
         
     | 
| 
       36 
36 
     | 
    
         | 
| 
       37 
37 
     | 
    
         
             
                begin
         
     | 
| 
         @@ -71,7 +71,7 @@ module XfOOrth 
     | 
|
| 
       71 
71 
     | 
    
         
             
              # [file_name InStream] .get_all [["line 1", "line 2", ... "line n"]]
         
     | 
| 
       72 
72 
     | 
    
         
             
              in_stream.create_exclusive_method('.get_all', TosSpec, [], &lambda {|vm|
         
     | 
| 
       73 
73 
     | 
    
         
             
                begin
         
     | 
| 
       74 
     | 
    
         
            -
                  file_name = vm.pop.to_s
         
     | 
| 
      
 74 
     | 
    
         
            +
                  file_name = vm.pop.to_s.freeze
         
     | 
| 
       75 
75 
     | 
    
         
             
                  vm.push(IO.readlines(file_name).map{|line| line.chomp })
         
     | 
| 
       76 
76 
     | 
    
         
             
                rescue
         
     | 
| 
       77 
77 
     | 
    
         
             
                  error "F50: Unable to open the file #{file_name} for reading all."
         
     | 
| 
         @@ -28,7 +28,17 @@ module XfOOrth 
     | 
|
| 
       28 
28 
     | 
    
         
             
              #Get the object as a string.
         
     | 
| 
       29 
29 
     | 
    
         
             
              # [obj] .to_s ["obj as a string"]
         
     | 
| 
       30 
30 
     | 
    
         
             
              Object.create_shared_method('.to_s', TosSpec, [],
         
     | 
| 
       31 
     | 
    
         
            -
                &lambda {|vm| vm.push(self.to_s)})
         
     | 
| 
      
 31 
     | 
    
         
            +
                &lambda {|vm| vm.push(self.to_s.freeze)})
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
              #Get the object as a string.
         
     | 
| 
      
 34 
     | 
    
         
            +
              # [obj] .to_s ["obj as a string"]
         
     | 
| 
      
 35 
     | 
    
         
            +
              Object.create_shared_method('.to_s*', TosSpec, [],
         
     | 
| 
      
 36 
     | 
    
         
            +
                &lambda {|vm| vm.push(StringBuffer.new(self.to_s.dup))})
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
              #Get the object as a string.
         
     | 
| 
      
 39 
     | 
    
         
            +
              # [obj] .to_s ["obj as a string"]
         
     | 
| 
      
 40 
     | 
    
         
            +
              String.create_shared_method('.to_s*', TosSpec, [],
         
     | 
| 
      
 41 
     | 
    
         
            +
                &lambda {|vm| vm.push(StringBuffer.new(self.dup))})
         
     | 
| 
       32 
42 
     | 
    
         | 
| 
       33 
43 
     | 
    
         
             
              #Get the length of the object as a string.
         
     | 
| 
       34 
44 
     | 
    
         
             
              # [obj] .strlen [n]; the length of the object's to_s string
         
     | 
| 
         @@ -28,14 +28,14 @@ module XfOOrth 
     | 
|
| 
       28 
28 
     | 
    
         | 
| 
       29 
29 
     | 
    
         
             
              # ["file_name" OutStream] .create [an_outstream]
         
     | 
| 
       30 
30 
     | 
    
         
             
              out_stream.create_exclusive_method('.create', TosSpec, [], &lambda {|vm|
         
     | 
| 
       31 
     | 
    
         
            -
                file_name = vm.pop.to_s
         
     | 
| 
      
 31 
     | 
    
         
            +
                file_name = vm.pop.to_s.freeze
         
     | 
| 
       32 
32 
     | 
    
         
             
                vm.push(XfOOrth_OutStream.new(file_name, 'w'))
         
     | 
| 
       33 
33 
     | 
    
         
             
              })
         
     | 
| 
       34 
34 
     | 
    
         | 
| 
       35 
35 
     | 
    
         
             
              # ["file_name" OutStream] .create{{ ... }} []
         
     | 
| 
       36 
36 
     | 
    
         
             
              out_stream.create_exclusive_method('.create{{', TosSpec, [], &lambda {|vm|
         
     | 
| 
       37 
37 
     | 
    
         
             
                block = vm.pop
         
     | 
| 
       38 
     | 
    
         
            -
                file_name = vm.pop.to_s
         
     | 
| 
      
 38 
     | 
    
         
            +
                file_name = vm.pop.to_s.freeze
         
     | 
| 
       39 
39 
     | 
    
         
             
                out_stream = XfOOrth_OutStream.new(file_name, 'w')
         
     | 
| 
       40 
40 
     | 
    
         | 
| 
       41 
41 
     | 
    
         
             
                begin
         
     | 
| 
         @@ -48,7 +48,7 @@ module XfOOrth 
     | 
|
| 
       48 
48 
     | 
    
         
             
              # ["file_name" OutStream] .append{{ ... }} []
         
     | 
| 
       49 
49 
     | 
    
         
             
              out_stream.create_exclusive_method('.append{{', TosSpec, [], &lambda {|vm|
         
     | 
| 
       50 
50 
     | 
    
         
             
                block = vm.pop
         
     | 
| 
       51 
     | 
    
         
            -
                file_name = vm.pop.to_s
         
     | 
| 
      
 51 
     | 
    
         
            +
                file_name = vm.pop.to_s.freeze
         
     | 
| 
       52 
52 
     | 
    
         
             
                out_stream = XfOOrth_OutStream.new(file_name, 'a')
         
     | 
| 
       53 
53 
     | 
    
         | 
| 
       54 
54 
     | 
    
         
             
                begin
         
     | 
| 
         @@ -60,7 +60,7 @@ module XfOOrth 
     | 
|
| 
       60 
60 
     | 
    
         | 
| 
       61 
61 
     | 
    
         
             
              # ["file_name" OutStream] .append [an_outstream]
         
     | 
| 
       62 
62 
     | 
    
         
             
              out_stream.create_exclusive_method('.append', TosSpec, [], &lambda {|vm|
         
     | 
| 
       63 
     | 
    
         
            -
                file_name = vm.pop.to_s
         
     | 
| 
      
 63 
     | 
    
         
            +
                file_name = vm.pop.to_s.freeze
         
     | 
| 
       64 
64 
     | 
    
         
             
                vm.push(XfOOrth_OutStream.new(file_name, 'a'))
         
     | 
| 
       65 
65 
     | 
    
         
             
              })
         
     | 
| 
       66 
66 
     | 
    
         | 
| 
         @@ -119,7 +119,7 @@ module XfOOrth 
     | 
|
| 
       119 
119 
     | 
    
         | 
| 
       120 
120 
     | 
    
         
             
              # [text_array "file_name" OutStream] .put_all []; Write the array to file_name
         
     | 
| 
       121 
121 
     | 
    
         
             
              out_stream.create_exclusive_method('.put_all', TosSpec, [], &lambda {|vm|
         
     | 
| 
       122 
     | 
    
         
            -
                file_name = vm.pop.to_s
         
     | 
| 
      
 122 
     | 
    
         
            +
                file_name = vm.pop.to_s.freeze
         
     | 
| 
       123 
123 
     | 
    
         
             
                file_source = vm.pop
         
     | 
| 
       124 
124 
     | 
    
         
             
                out_stream = XfOOrth_OutStream.new(file_name, 'w')
         
     | 
| 
       125 
125 
     | 
    
         | 
| 
         @@ -132,7 +132,7 @@ module XfOOrth 
     | 
|
| 
       132 
132 
     | 
    
         | 
| 
       133 
133 
     | 
    
         
             
              # [text_array "file_name" OutStream] .append_all []; Append the array to file_name
         
     | 
| 
       134 
134 
     | 
    
         
             
              out_stream.create_exclusive_method('.append_all', TosSpec, [], &lambda {|vm|
         
     | 
| 
       135 
     | 
    
         
            -
                file_name = vm.pop.to_s
         
     | 
| 
      
 135 
     | 
    
         
            +
                file_name = vm.pop.to_s.freeze
         
     | 
| 
       136 
136 
     | 
    
         
             
                file_source = vm.pop
         
     | 
| 
       137 
137 
     | 
    
         
             
                out_stream = XfOOrth_OutStream.new(file_name, 'a')
         
     | 
| 
       138 
138 
     | 
    
         | 
| 
         @@ -47,7 +47,7 @@ module XfOOrth 
     | 
|
| 
       47 
47 
     | 
    
         
             
              #Get a string from the console.
         
     | 
| 
       48 
48 
     | 
    
         
             
              # [] accept"prompt" [string]; gets a string from the console.
         
     | 
| 
       49 
49 
     | 
    
         
             
              VirtualMachine.create_shared_method('accept"', VmSpec, [],
         
     | 
| 
       50 
     | 
    
         
            -
                &lambda {|vm| poke(MiniReadline.readline(peek.to_s, true)); })
         
     | 
| 
      
 50 
     | 
    
         
            +
                &lambda {|vm| poke(MiniReadline.readline(peek.to_s, true).freeze); })
         
     | 
| 
       51 
51 
     | 
    
         | 
| 
       52 
52 
     | 
    
         
             
              #Get a string from the console.
         
     | 
| 
       53 
53 
     | 
    
         
             
              # "prompt" [] .accept [string]; gets a string from the console.
         
     | 
| 
         @@ -6,13 +6,21 @@ module XfOOrth 
     | 
|
| 
       6 
6 
     | 
    
         
             
              #Connect the String class to the fOOrth class system.
         
     | 
| 
       7 
7 
     | 
    
         
             
              String.create_foorth_proxy
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
      
 9 
     | 
    
         
            +
              #Connect the StringBuffer class to the fOOrth class system.
         
     | 
| 
      
 10 
     | 
    
         
            +
              StringBuffer.create_foorth_proxy
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
       9 
12 
     | 
    
         
             
              # A no operation place holder for string literals
         
     | 
| 
       10 
13 
     | 
    
         
             
              VirtualMachine.create_shared_method('"', MacroSpec, [:macro, " "])
         
     | 
| 
       11 
14 
     | 
    
         | 
| 
      
 15 
     | 
    
         
            +
              #Is this mutable? StringBuffers are, Strings are not.
         
     | 
| 
      
 16 
     | 
    
         
            +
              # [a] .mutable? [flag]
         
     | 
| 
      
 17 
     | 
    
         
            +
              String.create_shared_method('.mutable?', TosSpec, [],
         
     | 
| 
      
 18 
     | 
    
         
            +
                &lambda {|vm| vm.push(!self.frozen?); })
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
       12 
20 
     | 
    
         
             
              # [string] .each{{ ... }} [unspecified]
         
     | 
| 
       13 
21 
     | 
    
         
             
              String.create_shared_method('.each{{', NosSpec, [], &lambda { |vm|
         
     | 
| 
       14 
22 
     | 
    
         
             
                block, idx = vm.pop, 0
         
     | 
| 
       15 
     | 
    
         
            -
                self.chars { |val| block.call(vm, val, idx); idx += 1 }
         
     | 
| 
      
 23 
     | 
    
         
            +
                self.chars { |val| block.call(vm, val.freeze, idx); idx += 1 }
         
     | 
| 
       16 
24 
     | 
    
         
             
              })
         
     | 
| 
       17 
25 
     | 
    
         | 
| 
       18 
26 
     | 
    
         
             
              #Some comparison operators
         
     | 
| 
         @@ -39,32 +47,48 @@ module XfOOrth 
     | 
|
| 
       39 
47 
     | 
    
         | 
| 
       40 
48 
     | 
    
         
             
              #Some string manipulation methods.
         
     | 
| 
       41 
49 
     | 
    
         
             
              # [n a] .ljust ['a    ']; left justify
         
     | 
| 
       42 
     | 
    
         
            -
              String.create_shared_method('.ljust', TosSpec, [],
         
     | 
| 
       43 
     | 
    
         
            -
                 
     | 
| 
      
 50 
     | 
    
         
            +
              String.create_shared_method('.ljust', TosSpec, [], &lambda {|vm|
         
     | 
| 
      
 51 
     | 
    
         
            +
                vm.poke(self.to_s.ljust(Integer.foorth_coerce(vm.peek)).freeze);
         
     | 
| 
      
 52 
     | 
    
         
            +
              })
         
     | 
| 
       44 
53 
     | 
    
         | 
| 
       45 
54 
     | 
    
         
             
              # [n a] .cjust ['  a  ']; center justify
         
     | 
| 
       46 
     | 
    
         
            -
              String.create_shared_method('.cjust', TosSpec, [],
         
     | 
| 
       47 
     | 
    
         
            -
                 
     | 
| 
      
 55 
     | 
    
         
            +
              String.create_shared_method('.cjust', TosSpec, [], &lambda {|vm|
         
     | 
| 
      
 56 
     | 
    
         
            +
                vm.poke(self.to_s.center(Integer.foorth_coerce(vm.peek)).freeze);
         
     | 
| 
      
 57 
     | 
    
         
            +
              })
         
     | 
| 
       48 
58 
     | 
    
         | 
| 
       49 
59 
     | 
    
         
             
              # [n a] .rjust ['    a']; right justify
         
     | 
| 
       50 
     | 
    
         
            -
              String.create_shared_method('.rjust', TosSpec, [],
         
     | 
| 
       51 
     | 
    
         
            -
                 
     | 
| 
      
 60 
     | 
    
         
            +
              String.create_shared_method('.rjust', TosSpec, [], &lambda {|vm|
         
     | 
| 
      
 61 
     | 
    
         
            +
                vm.poke(self.to_s.rjust(Integer.foorth_coerce(vm.peek)).freeze);
         
     | 
| 
      
 62 
     | 
    
         
            +
              })
         
     | 
| 
       52 
63 
     | 
    
         | 
| 
       53 
64 
     | 
    
         
             
              # ["  a  "] .lstrip ["a  "]; left strip
         
     | 
| 
       54 
65 
     | 
    
         
             
              String.create_shared_method('.lstrip', TosSpec, [],
         
     | 
| 
       55 
     | 
    
         
            -
                &lambda {|vm| vm.push(self.lstrip); })
         
     | 
| 
      
 66 
     | 
    
         
            +
                &lambda {|vm| vm.push(self.to_s.lstrip.freeze); })
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
              # ["  a  "*] .lstrip* []; left strip in place.
         
     | 
| 
      
 69 
     | 
    
         
            +
              StringBuffer.create_shared_method('.lstrip*', TosSpec, [],
         
     | 
| 
      
 70 
     | 
    
         
            +
                &lambda {|vm| self.lstrip! })
         
     | 
| 
       56 
71 
     | 
    
         | 
| 
       57 
72 
     | 
    
         
             
              # ["  a  "] .strip ["a"]; left and right strip
         
     | 
| 
       58 
73 
     | 
    
         
             
              String.create_shared_method('.strip', TosSpec, [],
         
     | 
| 
       59 
     | 
    
         
            -
                &lambda {|vm| vm.push(self.strip); })
         
     | 
| 
      
 74 
     | 
    
         
            +
                &lambda {|vm| vm.push(self.to_s.strip.freeze); })
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
              # ["  a  "*] .strip* []; left and right strip in place
         
     | 
| 
      
 77 
     | 
    
         
            +
              StringBuffer.create_shared_method('.strip*', TosSpec, [],
         
     | 
| 
      
 78 
     | 
    
         
            +
                &lambda {|vm| self.strip! })
         
     | 
| 
       60 
79 
     | 
    
         | 
| 
       61 
80 
     | 
    
         
             
              # ["  a  "] .rstrip ["  a"]; right strip
         
     | 
| 
       62 
81 
     | 
    
         
             
              String.create_shared_method('.rstrip', TosSpec, [],
         
     | 
| 
       63 
     | 
    
         
            -
                &lambda {|vm| vm.push(self.rstrip); })
         
     | 
| 
      
 82 
     | 
    
         
            +
                &lambda {|vm| vm.push(self.to_s.rstrip.freeze); })
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
              # ["  a  "*] .rstrip* []; right strip in place
         
     | 
| 
      
 85 
     | 
    
         
            +
              StringBuffer.create_shared_method('.rstrip*', TosSpec, [],
         
     | 
| 
      
 86 
     | 
    
         
            +
                &lambda {|vm| self.rstrip! })
         
     | 
| 
       64 
87 
     | 
    
         | 
| 
      
 88 
     | 
    
         
            +
              #The shared block for string formatting.
         
     | 
| 
       65 
89 
     | 
    
         
             
              format_action = lambda do |vm|
         
     | 
| 
       66 
90 
     | 
    
         
             
                begin
         
     | 
| 
       67 
     | 
    
         
            -
                  vm.poke(vm.peek % self.in_array)
         
     | 
| 
      
 91 
     | 
    
         
            +
                  vm.poke((vm.peek % self.in_array).freeze)
         
     | 
| 
       68 
92 
     | 
    
         
             
                rescue => err
         
     | 
| 
       69 
93 
     | 
    
         
             
                  vm.data_stack.pop
         
     | 
| 
       70 
94 
     | 
    
         
             
                  error "F40: Formating error: #{err.message}."
         
     | 
| 
         @@ -77,7 +101,14 @@ module XfOOrth 
     | 
|
| 
       77 
101 
     | 
    
         
             
              # [object_or_array] f"fmt_str" ['a formatted string']
         
     | 
| 
       78 
102 
     | 
    
         
             
              Object.create_shared_method('f"', NosSpec, [], &format_action)
         
     | 
| 
       79 
103 
     | 
    
         | 
| 
       80 
     | 
    
         
            -
              parse_action = lambda  
     | 
| 
      
 104 
     | 
    
         
            +
              parse_action = lambda do |vm|
         
     | 
| 
      
 105 
     | 
    
         
            +
                begin
         
     | 
| 
      
 106 
     | 
    
         
            +
                  vm.poke(self.sscanf(vm.peek).map{|obj| obj.foorth_string_freeze} )
         
     | 
| 
      
 107 
     | 
    
         
            +
                rescue => err
         
     | 
| 
      
 108 
     | 
    
         
            +
                  vm.data_stack.pop
         
     | 
| 
      
 109 
     | 
    
         
            +
                  error "F40: Parsing error: #{err.message}."
         
     | 
| 
      
 110 
     | 
    
         
            +
                end
         
     | 
| 
      
 111 
     | 
    
         
            +
              end
         
     | 
| 
       81 
112 
     | 
    
         | 
| 
       82 
113 
     | 
    
         
             
              # [a_str fmt_str] parse [result_array]
         
     | 
| 
       83 
114 
     | 
    
         
             
              String.create_shared_method('parse', NosSpec, [], &parse_action)
         
     | 
| 
         @@ -90,16 +121,16 @@ module XfOOrth 
     | 
|
| 
       90 
121 
     | 
    
         | 
| 
       91 
122 
     | 
    
         
             
              # [w 'abcdefgh'] .left ['ab']         // Assumes w = 2
         
     | 
| 
       92 
123 
     | 
    
         
             
              String.create_shared_method('.left', TosSpec, [],
         
     | 
| 
       93 
     | 
    
         
            -
                &lambda {|vm| vm.poke(self[0...(Integer.foorth_coerce(vm.peek))]); })
         
     | 
| 
      
 124 
     | 
    
         
            +
                &lambda {|vm| vm.poke(self.to_s[0...(Integer.foorth_coerce(vm.peek))].freeze); })
         
     | 
| 
       94 
125 
     | 
    
         | 
| 
       95 
126 
     | 
    
         
             
              # [w 'abcdefgh'] .-left ['cdefgh']    // Assumes w = 2
         
     | 
| 
       96 
127 
     | 
    
         
             
              String.create_shared_method('.-left', TosSpec, [],
         
     | 
| 
       97 
     | 
    
         
            -
                &lambda {|vm| vm.poke(self[(Integer.foorth_coerce(vm.peek))..-1]); })
         
     | 
| 
      
 128 
     | 
    
         
            +
                &lambda {|vm| vm.poke(self.to_s[(Integer.foorth_coerce(vm.peek))..-1].freeze); })
         
     | 
| 
       98 
129 
     | 
    
         | 
| 
       99 
130 
     | 
    
         
             
              # [w '123''abcdefgh'] .+left ['123cdefgh']    // Assumes w = 2
         
     | 
| 
       100 
131 
     | 
    
         
             
              String.create_shared_method('.+left', TosSpec, [], &lambda {|vm|
         
     | 
| 
       101 
132 
     | 
    
         
             
                ins = vm.pop.to_s
         
     | 
| 
       102 
     | 
    
         
            -
                vm.poke(ins + self[(Integer.foorth_coerce(vm.peek))..-1])
         
     | 
| 
      
 133 
     | 
    
         
            +
                vm.poke((ins + self[(Integer.foorth_coerce(vm.peek))..-1]).freeze)
         
     | 
| 
       103 
134 
     | 
    
         
             
              })
         
     | 
| 
       104 
135 
     | 
    
         | 
| 
       105 
136 
     | 
    
         
             
              # ['abc' 'abcdefgh'] .left? [boolean]
         
     | 
| 
         @@ -113,14 +144,14 @@ module XfOOrth 
     | 
|
| 
       113 
144 
     | 
    
         
             
              String.create_shared_method('.mid', TosSpec, [], &lambda {|vm|
         
     | 
| 
       114 
145 
     | 
    
         
             
                width = Integer.foorth_coerce(vm.pop)
         
     | 
| 
       115 
146 
     | 
    
         
             
                posn = Integer.foorth_coerce(vm.pop)
         
     | 
| 
       116 
     | 
    
         
            -
                vm.push(self[posn...(posn+width)])
         
     | 
| 
      
 147 
     | 
    
         
            +
                vm.push(self.to_s[posn...(posn+width)].freeze)
         
     | 
| 
       117 
148 
     | 
    
         
             
              })
         
     | 
| 
       118 
149 
     | 
    
         | 
| 
       119 
150 
     | 
    
         
             
              # [n w 'abcdefgh'] .-mid ['abgh']     // Assumes n = 2, w = 4
         
     | 
| 
       120 
151 
     | 
    
         
             
              String.create_shared_method('.-mid', TosSpec, [], &lambda {|vm|
         
     | 
| 
       121 
152 
     | 
    
         
             
                width = Integer.foorth_coerce(vm.pop)
         
     | 
| 
       122 
153 
     | 
    
         
             
                posn = Integer.foorth_coerce(vm.pop)
         
     | 
| 
       123 
     | 
    
         
            -
                vm.push(self[0...posn] + self[(posn+width)..-1])
         
     | 
| 
      
 154 
     | 
    
         
            +
                vm.push((self[0...posn] + self[(posn+width)..-1]).freeze)
         
     | 
| 
       124 
155 
     | 
    
         
             
              })
         
     | 
| 
       125 
156 
     | 
    
         | 
| 
       126 
157 
     | 
    
         
             
              # [n w "123" "abcdefgh"] .+mid ["ab123gh"] // Assumes n = 2, w = 4
         
     | 
| 
         @@ -128,7 +159,7 @@ module XfOOrth 
     | 
|
| 
       128 
159 
     | 
    
         
             
                ins = vm.pop.to_s
         
     | 
| 
       129 
160 
     | 
    
         
             
                width = Integer.foorth_coerce(vm.pop)
         
     | 
| 
       130 
161 
     | 
    
         
             
                posn = Integer.foorth_coerce(vm.pop)
         
     | 
| 
       131 
     | 
    
         
            -
                vm.push(self[0...posn] + ins + self[(posn+width)..-1])
         
     | 
| 
      
 162 
     | 
    
         
            +
                vm.push((self[0...posn] + ins + self[(posn+width)..-1]).freeze)
         
     | 
| 
       132 
163 
     | 
    
         
             
              })
         
     | 
| 
       133 
164 
     | 
    
         | 
| 
       134 
165 
     | 
    
         
             
              # [n 'cde' 'abcdefgh'] .mid? [true]      // Assumes n = 2
         
     | 
| 
         @@ -146,14 +177,14 @@ module XfOOrth 
     | 
|
| 
       146 
177 
     | 
    
         
             
              String.create_shared_method('.midlr', TosSpec, [], &lambda {|vm|
         
     | 
| 
       147 
178 
     | 
    
         
             
                right = Integer.foorth_coerce(vm.pop)
         
     | 
| 
       148 
179 
     | 
    
         
             
                left  = Integer.foorth_coerce(vm.pop)
         
     | 
| 
       149 
     | 
    
         
            -
                vm.push(self[left...(0-right)])
         
     | 
| 
      
 180 
     | 
    
         
            +
                vm.push(self.to_s[left...(0-right)].freeze)
         
     | 
| 
       150 
181 
     | 
    
         
             
              })
         
     | 
| 
       151 
182 
     | 
    
         | 
| 
       152 
183 
     | 
    
         
             
              # [l r 'abcdefgh'] .-midlr ['ah']     // Assumes l = 1, r = 1
         
     | 
| 
       153 
184 
     | 
    
         
             
              String.create_shared_method('.-midlr', TosSpec, [], &lambda {|vm|
         
     | 
| 
       154 
185 
     | 
    
         
             
                right = Integer.foorth_coerce(vm.pop)
         
     | 
| 
       155 
186 
     | 
    
         
             
                left  = Integer.foorth_coerce(vm.pop)
         
     | 
| 
       156 
     | 
    
         
            -
                vm.push(self[0...left] + self[((0-right))..-1])
         
     | 
| 
      
 187 
     | 
    
         
            +
                vm.push((self[0...left] + self[((0-right))..-1]).freeze)
         
     | 
| 
       157 
188 
     | 
    
         
             
              })
         
     | 
| 
       158 
189 
     | 
    
         | 
| 
       159 
190 
     | 
    
         
             
              # [l r "123" 'abcdefgh'] .+midlr ['a123h']     // Assumes l = 1, r = 1
         
     | 
| 
         @@ -161,24 +192,26 @@ module XfOOrth 
     | 
|
| 
       161 
192 
     | 
    
         
             
                ins = vm.pop.to_s
         
     | 
| 
       162 
193 
     | 
    
         
             
                right = Integer.foorth_coerce(vm.pop)
         
     | 
| 
       163 
194 
     | 
    
         
             
                left  = Integer.foorth_coerce(vm.pop)
         
     | 
| 
       164 
     | 
    
         
            -
                vm.push(self[0...left] + ins + self[((0-right))..-1])
         
     | 
| 
      
 195 
     | 
    
         
            +
                vm.push((self[0...left] + ins + self[((0-right))..-1]).freeze)
         
     | 
| 
       165 
196 
     | 
    
         
             
              })
         
     | 
| 
       166 
197 
     | 
    
         | 
| 
       167 
198 
     | 
    
         
             
              #RIGHT Group
         
     | 
| 
       168 
199 
     | 
    
         | 
| 
       169 
200 
     | 
    
         
             
              # [w 'abcdefgh'] .right ['gh']        // Assumes w = 2
         
     | 
| 
       170 
     | 
    
         
            -
              String.create_shared_method('.right', TosSpec, [],
         
     | 
| 
       171 
     | 
    
         
            -
                 
     | 
| 
      
 201 
     | 
    
         
            +
              String.create_shared_method('.right', TosSpec, [], &lambda {|vm|
         
     | 
| 
      
 202 
     | 
    
         
            +
                vm.poke(self.to_s[(0-(Integer.foorth_coerce(vm.peek)))..-1].freeze);
         
     | 
| 
      
 203 
     | 
    
         
            +
              })
         
     | 
| 
       172 
204 
     | 
    
         | 
| 
       173 
205 
     | 
    
         
             
              # [w 'abcdefgh'] .-right ['abcdef']   // Assumes w = 2
         
     | 
| 
       174 
     | 
    
         
            -
              String.create_shared_method('.-right', TosSpec, [],
         
     | 
| 
       175 
     | 
    
         
            -
                 
     | 
| 
      
 206 
     | 
    
         
            +
              String.create_shared_method('.-right', TosSpec, [], &lambda {|vm|
         
     | 
| 
      
 207 
     | 
    
         
            +
                vm.poke(self.to_s[0...(0-(Integer.foorth_coerce(vm.peek)))].freeze);
         
     | 
| 
      
 208 
     | 
    
         
            +
              })
         
     | 
| 
       176 
209 
     | 
    
         | 
| 
       177 
210 
     | 
    
         
             
              # [w "123" 'abcdefgh'] .+right ['abcdef123']   // Assumes w = 2
         
     | 
| 
       178 
211 
     | 
    
         
             
              String.create_shared_method('.+right', TosSpec, [], &lambda {|vm|
         
     | 
| 
       179 
212 
     | 
    
         
             
                ins = vm.pop.to_s
         
     | 
| 
       180 
213 
     | 
    
         
             
                width = Integer.foorth_coerce(vm.pop)
         
     | 
| 
       181 
     | 
    
         
            -
                vm.push(self[0...(0-width)] + ins)
         
     | 
| 
      
 214 
     | 
    
         
            +
                vm.push((self[0...(0-width)] + ins).freeze)
         
     | 
| 
       182 
215 
     | 
    
         
             
              })
         
     | 
| 
       183 
216 
     | 
    
         | 
| 
       184 
217 
     | 
    
         
             
              # ['fgh' 'abcdefgh'] .right? [boolean]
         
     | 
| 
         @@ -201,16 +234,20 @@ module XfOOrth 
     | 
|
| 
       201 
234 
     | 
    
         | 
| 
       202 
235 
     | 
    
         
             
              # ["b", a] + ["ba"]; "ba" is a new object, distinct from "b"
         
     | 
| 
       203 
236 
     | 
    
         
             
              String.create_shared_method('+', NosSpec, [],
         
     | 
| 
       204 
     | 
    
         
            -
                &lambda {|vm| vm.poke(self + vm.peek.to_s) 
     | 
| 
      
 237 
     | 
    
         
            +
                &lambda {|vm| vm.poke((self + vm.peek.to_s).freeze) })
         
     | 
| 
       205 
238 
     | 
    
         | 
| 
       206 
     | 
    
         
            -
              # ["b" 
     | 
| 
       207 
     | 
    
         
            -
               
     | 
| 
      
 239 
     | 
    
         
            +
              # ["b"*, a] << ["ba"*]; "ba"* is the same object as "b"*
         
     | 
| 
      
 240 
     | 
    
         
            +
              StringBuffer.create_shared_method('<<', NosSpec, [],
         
     | 
| 
       208 
241 
     | 
    
         
             
                &lambda {|vm| vm.poke(self << vm.peek.to_s); })
         
     | 
| 
       209 
242 
     | 
    
         | 
| 
      
 243 
     | 
    
         
            +
              # ["b"*, a] >> ["ab"*]; "ab"* is the same object as "b"*
         
     | 
| 
      
 244 
     | 
    
         
            +
              StringBuffer.create_shared_method('>>', NosSpec, [],
         
     | 
| 
      
 245 
     | 
    
         
            +
                &lambda {|vm| vm.poke(self.prepend(vm.peek.to_s)); })
         
     | 
| 
      
 246 
     | 
    
         
            +
             
     | 
| 
       210 
247 
     | 
    
         
             
              # ["b", n] * ["bbb..."]
         
     | 
| 
       211 
248 
     | 
    
         
             
              String.create_shared_method('*', NosSpec, [], &lambda {|vm|
         
     | 
| 
       212 
249 
     | 
    
         
             
                begin
         
     | 
| 
       213 
     | 
    
         
            -
                  vm.poke(self * Integer.foorth_coerce(vm.peek))
         
     | 
| 
      
 250 
     | 
    
         
            +
                  vm.poke((self.to_s * Integer.foorth_coerce(vm.peek)).freeze)
         
     | 
| 
       214 
251 
     | 
    
         
             
                rescue
         
     | 
| 
       215 
252 
     | 
    
         
             
                  vm.data_stack.pop
         
     | 
| 
       216 
253 
     | 
    
         
             
                  raise
         
     | 
| 
         @@ -219,15 +256,27 @@ module XfOOrth 
     | 
|
| 
       219 
256 
     | 
    
         | 
| 
       220 
257 
     | 
    
         
             
              # ["abCD"] .to_upper ["ABCD"]
         
     | 
| 
       221 
258 
     | 
    
         
             
              String.create_shared_method('.to_upper', TosSpec, [],
         
     | 
| 
       222 
     | 
    
         
            -
                &lambda {|vm| vm.push(self.upcase) 
     | 
| 
      
 259 
     | 
    
         
            +
                &lambda {|vm| vm.push(self.to_s.upcase.freeze) })
         
     | 
| 
      
 260 
     | 
    
         
            +
             
     | 
| 
      
 261 
     | 
    
         
            +
              # ["abCD"*] .to_upper* [] #Convert to upper case in place.
         
     | 
| 
      
 262 
     | 
    
         
            +
              StringBuffer.create_shared_method('.to_upper*', TosSpec, [],
         
     | 
| 
      
 263 
     | 
    
         
            +
                &lambda {|vm| self.upcase! })
         
     | 
| 
       223 
264 
     | 
    
         | 
| 
       224 
265 
     | 
    
         
             
              # ["abCD"] .to_lower ["abcd"]
         
     | 
| 
       225 
266 
     | 
    
         
             
              String.create_shared_method('.to_lower', TosSpec, [],
         
     | 
| 
       226 
     | 
    
         
            -
                &lambda {|vm| vm.push(self.downcase) 
     | 
| 
      
 267 
     | 
    
         
            +
                &lambda {|vm| vm.push(self.to_s.downcase.freeze) })
         
     | 
| 
      
 268 
     | 
    
         
            +
             
     | 
| 
      
 269 
     | 
    
         
            +
              # ["abCD"*] .to_lower* [] #Convert to lower case in place.
         
     | 
| 
      
 270 
     | 
    
         
            +
              StringBuffer.create_shared_method('.to_lower*', TosSpec, [],
         
     | 
| 
      
 271 
     | 
    
         
            +
                &lambda {|vm| self.downcase! })
         
     | 
| 
       227 
272 
     | 
    
         | 
| 
       228 
273 
     | 
    
         
             
              # ["stressed"] .reverse ["desserts"]
         
     | 
| 
       229 
274 
     | 
    
         
             
              String.create_shared_method('.reverse', TosSpec, [],
         
     | 
| 
       230 
     | 
    
         
            -
                &lambda {|vm| vm.push(self.reverse); })
         
     | 
| 
      
 275 
     | 
    
         
            +
                &lambda {|vm| vm.push(self.to_s.reverse.freeze); })
         
     | 
| 
      
 276 
     | 
    
         
            +
             
     | 
| 
      
 277 
     | 
    
         
            +
              # ["stressed"*] .reverse* [] #Reverse the string in place.
         
     | 
| 
      
 278 
     | 
    
         
            +
              StringBuffer.create_shared_method('.reverse*', TosSpec, [],
         
     | 
| 
      
 279 
     | 
    
         
            +
                &lambda {|vm| self.reverse! })
         
     | 
| 
       231 
280 
     | 
    
         | 
| 
       232 
281 
     | 
    
         
             
              # ["abc\\ndef\\n123"] .lines [["abc", "def", "123"]]
         
     | 
| 
       233 
282 
     | 
    
         
             
              String.create_shared_method('.lines', TosSpec, [],
         
     |