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, [],
|