fOOrth 0.6.6 → 0.6.11

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.
Files changed (67) hide show
  1. checksums.yaml +5 -5
  2. data/CODE_OF_CONDUCT.md +49 -0
  3. data/README.md +32 -1
  4. data/fOOrth.gemspec +3 -3
  5. data/integration/array_lib_tests.rb +10 -0
  6. data/integration/compile_lib_tests.rb +67 -1
  7. data/integration/exception_lib_tests.rb +4 -0
  8. data/integration/hash_lib_tests.rb +9 -0
  9. data/integration/numeric_lib_tests.rb +326 -321
  10. data/integration/procedure_lib_tests.rb +16 -0
  11. data/integration/queue_lib_tests.rb +2 -1
  12. data/integration/stack_lib_tests.rb +2 -1
  13. data/integration/stdio_lib_tests.rb +62 -0
  14. data/integration/string_lib_tests.rb +11 -0
  15. data/integration/thread_lib_tests.rb +19 -5
  16. data/lib/fOOrth.rb +0 -2
  17. data/lib/fOOrth/compiler/context.rb +64 -64
  18. data/lib/fOOrth/compiler/context/locals.rb +34 -34
  19. data/lib/fOOrth/compiler/context/map_name.rb +85 -74
  20. data/lib/fOOrth/compiler/context/tags.rb +60 -48
  21. data/lib/fOOrth/compiler/process/generate.rb +1 -1
  22. data/lib/fOOrth/compiler/process/procedure.rb +40 -0
  23. data/lib/fOOrth/compiler/word_specs.rb +3 -3
  24. data/lib/fOOrth/core/object.rb +1 -1
  25. data/lib/fOOrth/library.rb +3 -0
  26. data/lib/fOOrth/library/alias_library.rb +126 -0
  27. data/lib/fOOrth/library/array_library.rb +41 -21
  28. data/lib/fOOrth/library/command_library.rb +1 -1
  29. data/lib/fOOrth/library/compile_library.rb +266 -264
  30. data/lib/fOOrth/library/complex_library.rb +82 -80
  31. data/lib/fOOrth/library/float_library.rb +37 -0
  32. data/lib/fOOrth/library/formatting/array.rb +90 -0
  33. data/lib/fOOrth/library/formatting/bullets.rb +15 -79
  34. data/lib/fOOrth/library/formatting/columns.rb +20 -42
  35. data/lib/fOOrth/library/formatting/hash.rb +29 -0
  36. data/lib/fOOrth/library/formatting/nil.rb +13 -0
  37. data/lib/fOOrth/library/formatting/object.rb +18 -0
  38. data/lib/fOOrth/library/formatting/string.rb +46 -0
  39. data/lib/fOOrth/library/hash_library.rb +14 -6
  40. data/lib/fOOrth/library/introspection/class.rb +20 -18
  41. data/lib/fOOrth/library/introspection/context.rb +3 -2
  42. data/lib/fOOrth/library/introspection/object.rb +42 -20
  43. data/lib/fOOrth/library/introspection/string.rb +21 -5
  44. data/lib/fOOrth/library/introspection/vm.rb +17 -29
  45. data/lib/fOOrth/library/mutex_library.rb +8 -1
  46. data/lib/fOOrth/library/numeric_library.rb +359 -380
  47. data/lib/fOOrth/library/procedure_library.rb +69 -65
  48. data/lib/fOOrth/library/queue_library.rb +6 -1
  49. data/lib/fOOrth/library/rational_library.rb +89 -89
  50. data/lib/fOOrth/library/stack_library.rb +6 -1
  51. data/lib/fOOrth/library/stdio_library.rb +11 -8
  52. data/lib/fOOrth/library/string_library.rb +21 -6
  53. data/lib/fOOrth/library/stubs_library.rb +49 -0
  54. data/lib/fOOrth/monkey_patch/exceptions.rb +2 -6
  55. data/lib/fOOrth/monkey_patch/object.rb +7 -0
  56. data/lib/fOOrth/version.rb +1 -1
  57. data/reek.txt +1 -59
  58. data/sire.rb +0 -1
  59. data/tests/compiler/context_tests.rb +188 -177
  60. data/tests/compiler/file_source_tests.rb +130 -130
  61. data/tests/compiler/parser_tests.rb +4 -4
  62. data/tests/compiler/string_source_tests.rb +4 -4
  63. data/tests/core_tests.rb +138 -138
  64. data/tests/monkey_patch/complex_test.rb +24 -24
  65. data/tests/monkey_patch/object_test.rb +49 -49
  66. data/tests/monkey_patch/string_test.rb +61 -61
  67. metadata +20 -13
@@ -1,48 +1,60 @@
1
- # coding: utf-8
2
-
3
- #* compiler/context/tags.rb - Support tags in context.
4
- module XfOOrth
5
-
6
- #* compiler/context/tags.rb - Support tags in context.
7
- class Context
8
-
9
- #Retrieve the data value currently in effect.
10
- def [](index)
11
- @data[index] || (previous && previous[index])
12
- end
13
-
14
- #Set a data value.
15
- def []=(index,value)
16
- @data[index] = value
17
- end
18
-
19
- #Get the compile tags in effect.
20
- def tags
21
- @data[:tags] || []
22
- end
23
-
24
- #Merge in a hash of tag data.
25
- def merge(new_data)
26
- @data.merge!(new_data)
27
- end
28
-
29
- #Validate a current data value.
30
- #<br>Parameters:
31
- #* symbol - The symbol of the value to be tested.
32
- #* expect - An array of valid values.
33
- #<br>Note:
34
- #* Throws a XfOOrthError if the value is not valid.
35
- #* To check for no value, use [nil] for expect.
36
- #* Returns true to facilitate testing only.
37
- def check_set(symbol, expect)
38
- current = self[symbol]
39
-
40
- unless expect.include?(current)
41
- error "F10: Found a #{current.inspect}, excpected #{expect}"
42
- end
43
-
44
- true
45
- end
46
-
47
- end
48
- end
1
+ # coding: utf-8
2
+
3
+ #* compiler/context/tags.rb - Support tags in context.
4
+ module XfOOrth
5
+
6
+ #* compiler/context/tags.rb - Support tags in context.
7
+ class Context
8
+
9
+ #Retrieve the data value currently in effect.
10
+ def [](index)
11
+ @data[index] || (previous && previous[index])
12
+ end
13
+
14
+ #Set a data value.
15
+ def []=(index,value)
16
+ @data[index] = value
17
+ end
18
+
19
+ #Get the compile tags in effect.
20
+ def tags
21
+ @data[:tags] || []
22
+ end
23
+
24
+ #Merge in a hash of tag data.
25
+ def merge(new_data)
26
+ @data.merge!(new_data)
27
+ end
28
+
29
+ #Get the context with the specified type.
30
+ def get_context_by_ctrl(ctrl_type)
31
+ result = self
32
+
33
+ while result
34
+ return result if result[:ctrl] == ctrl_type
35
+ result = result.previous
36
+ end
37
+
38
+ error "F92: Unable to locate a context for #{ctrl_type.inspect}"
39
+ end
40
+
41
+ #Validate a current data value.
42
+ #<br>Parameters:
43
+ #* symbol - The symbol of the value to be tested.
44
+ #* expect - An array of valid values.
45
+ #<br>Note:
46
+ #* Throws a XfOOrthError if the value is not valid.
47
+ #* To check for no value, use [nil] for expect.
48
+ #* Returns true to facilitate testing only.
49
+ def check_set(symbol, expect)
50
+ current = self[symbol]
51
+
52
+ unless expect.include?(current)
53
+ error "F10: Found a #{current.inspect}, expected #{expect}"
54
+ end
55
+
56
+ true
57
+ end
58
+
59
+ end
60
+ end
@@ -11,7 +11,7 @@ module XfOOrth
11
11
  #* token - The token to receive the generated code.
12
12
  #* word - The text of the word.
13
13
  def generate_code(token, word)
14
- if (spec = @context.map(word))
14
+ if (spec = @context.map_with_defaults(word))
15
15
  token.add(spec.builds, spec.tags)
16
16
  elsif (value = word.to_foorth_n)
17
17
  token.add("vm.push(#{value.foorth_embed}); ", [:numeric])
@@ -32,6 +32,42 @@ module XfOOrth
32
32
  (_, @buffer = @buffer, save)[0]
33
33
  end
34
34
 
35
+ #The procedure used for procedure instance values
36
+ PROC_VAL = lambda {|vm|
37
+ context = vm.context.get_context_by_ctrl(:procedure)
38
+ val_name = vm.parser.get_word()
39
+
40
+ unless /^@[a-z][a-z0-9_]*$/ =~ val_name
41
+ error "F10: Invalid val name #{val_name}"
42
+ end
43
+
44
+ val_symbol = XfOOrth::SymbolMap.add_entry(val_name)
45
+ vm << "#{'@'+(val_symbol.to_s)} = vm.pop; "
46
+ vm << "self.create_exclusive_method(#{val_name.inspect}, InstanceVarSpec, []); "
47
+
48
+ context.create_local_method(val_name, LocalSpec, [:immediate], &lambda {|nvm|
49
+ nvm << "vm.push(#{'@'+(val_symbol.to_s)}); "
50
+ })
51
+ }
52
+
53
+ #The procedure used for procedure instance variables
54
+ PROC_VAR = lambda {|vm|
55
+ context = vm.context.get_context_by_ctrl(:procedure)
56
+ var_name = vm.parser.get_word()
57
+
58
+ unless /^@[a-z][a-z0-9_]*$/ =~ var_name
59
+ error "F10: Invalid val name #{var_name}"
60
+ end
61
+
62
+ var_symbol = XfOOrth::SymbolMap.add_entry(var_name)
63
+ vm << "#{'@'+(var_symbol.to_s)} = [vm.pop]; "
64
+ vm << "self.create_exclusive_method(#{var_name.inspect}, InstanceVarSpec, []); "
65
+
66
+ context.create_local_method(var_name, LocalSpec, [:immediate], &lambda {|nvm|
67
+ nvm << "vm.push(#{'@'+(var_symbol.to_s)}); "
68
+ })
69
+ }
70
+
35
71
  #Handle the opening of a procedure literal.
36
72
  def open_procedure_literal
37
73
  suspend_execute_mode("vm.push(lambda {|vm, val=nil, idx=nil| ", :procedure)
@@ -44,6 +80,10 @@ module XfOOrth
44
80
  context.create_local_method('var:', LocalSpec, [:immediate], &Local_Var_Action)
45
81
  context.create_local_method('val:', LocalSpec, [:immediate], &Local_Val_Action)
46
82
 
83
+ #Support for procedure instance data.
84
+ context.create_local_method('var@:', LocalSpec, [:immediate], &PROC_VAR)
85
+ context.create_local_method('val@:', LocalSpec, [:immediate], &PROC_VAL)
86
+
47
87
  context.create_local_method('}}', MacroSpec, [:macro, :end, "}); "])
48
88
  end
49
89
 
@@ -39,7 +39,7 @@ module XfOOrth
39
39
  #Get the default action if none is specified.
40
40
  def get_stub_action(name, symbol)
41
41
  lambda do |*_any|
42
- error "F20: A #{self.foorth_name} does not understand #{name} (#{symbol.inspect})."
42
+ f20_error(self, name, symbol)
43
43
  end
44
44
  end
45
45
 
@@ -100,7 +100,7 @@ module XfOOrth
100
100
  #be removed at this time.
101
101
  vm.data_stack.pop
102
102
 
103
- error "F20: A #{self.foorth_name} does not understand #{name} (#{symbol.inspect})."
103
+ f20_error(self, name, symbol)
104
104
  end
105
105
  end
106
106
 
@@ -175,7 +175,7 @@ module XfOOrth
175
175
  #* The last entry in the tags array is expected to be a string
176
176
  # with the text of the command macro.
177
177
  def build_builds_string(_name, _symbol)
178
- @builds = @tags.pop
178
+ @builds = @tags[-1]
179
179
  end
180
180
  end
181
181
  end
@@ -68,7 +68,7 @@ class Object
68
68
  if (stub_spec = Object.foorth_shared[symbol])
69
69
  self.instance_exec(*args, &stub_spec.does)
70
70
  else
71
- error "F20: A #{self.foorth_name} does not understand #{name} (#{symbol})."
71
+ f20_error(self, name, symbol)
72
72
  end
73
73
  else
74
74
  super
@@ -7,10 +7,13 @@ require_relative 'library/vm_library'
7
7
  require_relative 'library/data_ref_library'
8
8
  require_relative 'library/clone_library'
9
9
  require_relative 'library/compile_library'
10
+ require_relative 'library/alias_library'
11
+ require_relative 'library/stubs_library'
10
12
  require_relative 'library/ctrl_struct_library'
11
13
  require_relative 'library/stdio_library'
12
14
  require_relative 'library/numeric_library'
13
15
  require_relative 'library/integer_library'
16
+ require_relative 'library/float_library'
14
17
  require_relative 'library/rational_library'
15
18
  require_relative 'library/complex_library'
16
19
  require_relative 'library/string_library'
@@ -0,0 +1,126 @@
1
+ # coding: utf-8
2
+
3
+ #* library/alias_library.rb - Support for method aliasing in fOOrth.
4
+ module XfOOrth
5
+
6
+ VirtualMachine.create_shared_method('alias:', VmSpec, [:immediate],
7
+ &lambda {|vm|
8
+ new_name = parser.get_word().inspect
9
+ process_text("vm.create_word_alias(#{new_name}); ")
10
+ })
11
+
12
+ VirtualMachine.create_shared_method('.alias:', VmSpec, [:immediate],
13
+ &lambda {|vm|
14
+ new_name = parser.get_word().inspect
15
+ process_text("vm.create_shared_alias(#{new_name}); ")
16
+ })
17
+
18
+ VirtualMachine.create_shared_method('.alias::', VmSpec, [:immediate],
19
+ &lambda {|vm|
20
+ new_name = parser.get_word().inspect
21
+ process_text("vm.create_exclusive_alias(#{new_name}); ")
22
+ })
23
+
24
+ # Alias support methods in the VirtualMachine class.
25
+ class VirtualMachine
26
+ ALLOWED_ALIAS_TYPES = {
27
+ TosSpec => [TosSpec, SelfSpec],
28
+ SelfSpec => [TosSpec, SelfSpec],
29
+ NosSpec => [NosSpec]
30
+ }
31
+
32
+ #Create a virtual machine word method alias.
33
+ def create_word_alias(new_name)
34
+ old_name, target = pop, self.class
35
+
36
+ old_spec = get_old_shared_spec(target, old_name)
37
+
38
+ target.create_shared_method(new_name,
39
+ old_spec.class,
40
+ old_spec.tags,
41
+ &old_spec.does)
42
+ end
43
+
44
+ #Create a shared method alias
45
+ def create_shared_alias(new_name)
46
+ old_name, target = popm(2)
47
+
48
+ unless target.is_a?(Class)
49
+ error "F13: The target of .alias: must be a class"
50
+ end
51
+
52
+ old_spec = get_old_shared_spec(target, old_name)
53
+
54
+ target.create_shared_method(new_name,
55
+ get_alias_type(old_spec, new_name),
56
+ old_spec.tags,
57
+ &old_spec.does)
58
+ clear_cast
59
+ end
60
+
61
+ #Create an exclusive method alias
62
+ def create_exclusive_alias(new_name)
63
+ old_name, target = popm(2)
64
+
65
+ old_spec = get_old_exclusive_spec(target, old_name)
66
+
67
+ target.create_exclusive_method(new_name,
68
+ get_alias_type(old_spec, new_name),
69
+ old_spec.tags,
70
+ &old_spec.does)
71
+ clear_cast
72
+ end
73
+
74
+ private
75
+
76
+ #Get the shared specification of the original method.
77
+ def get_old_shared_spec(target, old_name)
78
+ old_symbol = get_old_symbol(old_name)
79
+
80
+ unless (old_spec = target.map_foorth_shared(old_symbol))
81
+ f20_error(target, old_name, old_symbol)
82
+ end
83
+
84
+ old_spec
85
+ end
86
+
87
+ #Get the exclusive specification of the original method.
88
+ def get_old_exclusive_spec(target, old_name)
89
+ old_symbol = get_old_symbol(old_name)
90
+
91
+ unless (old_spec = target.map_foorth_exclusive(old_symbol))
92
+ f20_error(target, old_name, old_symbol)
93
+ end
94
+
95
+ old_spec
96
+ end
97
+
98
+ #Get the symbol of the old method.
99
+ def get_old_symbol(old_name)
100
+ old_symbol = XfOOrth::SymbolMap.map(old_name)
101
+ error "F10: ?#{old_name}?" unless old_symbol
102
+ old_symbol
103
+ end
104
+
105
+ #Get the type of the aliased method.
106
+ def get_alias_type(old_spec, new_name)
107
+ old_type = old_spec.class
108
+ new_type = XfOOrth.name_to_type(new_name, self)
109
+ old_desc, new_desc = old_type.foorth_name, new_type.foorth_name
110
+
111
+ unless (allowed = ALLOWED_ALIAS_TYPES[old_type])
112
+ error "F13: A #{old_desc} method may not be aliased."
113
+ end
114
+
115
+ unless allowed.include?(new_type)
116
+ error "F13: A #{old_desc} method may not be aliased as a #{new_desc}"
117
+ end
118
+
119
+ XfOOrth.validate_type(self, new_type, new_name)
120
+
121
+ new_type
122
+ end
123
+
124
+ end
125
+
126
+ end
@@ -45,7 +45,7 @@ module XfOOrth
45
45
  # [array] .map{{ ... }} [mapped_array]
46
46
  Array.create_shared_method('.map{{', NosSpec, [], &lambda { |vm|
47
47
  idx, block = 0, vm.pop
48
- vm.push(self.map { |val| block.call(vm, val, idx); idx += 1; vm.pop})
48
+ vm.push(self.map{|val| block.call(vm, val, idx); idx += 1; vm.pop})
49
49
  })
50
50
 
51
51
  # [array] .select{{ ... }} [selected_array]
@@ -92,40 +92,60 @@ module XfOOrth
92
92
  # [ v i a ] .[]! []; a[i]=v
93
93
  Array.create_shared_method('.[]!', TosSpec, [], &lambda {|vm|
94
94
  value, index = vm.popm(2)
95
- self[Integer.foorth_coerce(index)] = value;
95
+ self[Integer.foorth_coerce(index)] = value
96
96
  })
97
97
 
98
98
  # [ [ 1 2 3 ] ] .reverse [ [ 3 2 1 ] ]
99
99
  Array.create_shared_method('.reverse', TosSpec, [],
100
- &lambda {|vm| vm.push(self.reverse); })
100
+ &lambda {|vm| vm.push(self.reverse) })
101
101
 
102
102
  # [ [ 3 1 2 ] ] .sort [ [ 1 2 3 ] ]
103
103
  Array.create_shared_method('.sort', TosSpec, [],
104
- &lambda {|vm| vm.push(self.sort {|va,vb| va <=> va.foorth_coerce(vb)}); })
104
+ &lambda {|vm| vm.push(self.sort {|va,vb| va <=> va.foorth_coerce(vb)}) })
105
105
 
106
106
  # [ [ 1 2 3 ] ] .shuffle [ [ x y z ] ]
107
107
  Array.create_shared_method('.shuffle', TosSpec, [],
108
- &lambda {|vm| vm.push(self.shuffle); })
108
+ &lambda {|vm| vm.push(self.shuffle) })
109
109
 
110
110
  # [ [ 3 1 2 ] ] .length [ 3 ]
111
111
  Array.create_shared_method('.length', TosSpec, [],
112
- &lambda {|vm| vm.push(self.length); })
112
+ &lambda {|vm| vm.push(self.length) })
113
113
 
114
114
  # [ an_array ] .empty? [ a_boolean ]
115
115
  Array.create_shared_method('.empty?', TosSpec, [],
116
- &lambda {|vm| vm.push(self.empty?); })
116
+ &lambda {|vm| vm.push(self.empty?) })
117
+
118
+ # [ an_array ] .present? [ a_boolean ]
119
+ Array.create_shared_method('.present?', TosSpec, [],
120
+ &lambda {|vm| vm.push(!self.empty?) })
121
+
122
+ # [ an_array ] .clear! [ ]; The array contents are removed.
123
+ Array.create_shared_method('.clear!', TosSpec, [],
124
+ &lambda {|vm| self.clear})
117
125
 
118
126
  # [ [ 3 1 2 ] n ] << [ [ 3 1 2 n ] ]
119
- Array.create_shared_method('<<', NosSpec, [],
120
- &lambda {|vm| vm.poke(self << vm.peek); })
127
+ Array.create_shared_method('<<', NosSpec, [], &lambda {|vm|
128
+ begin
129
+ vm.poke(self << vm.peek)
130
+ rescue
131
+ vm.data_stack.pop
132
+ raise
133
+ end
134
+ })
121
135
 
122
136
  # [ [ 3 1 2 ] n ] >> [ [ n 3 1 2 ] ]
123
- Array.create_shared_method('>>', NosSpec, [],
124
- &lambda {|vm| vm.poke(self.insert(0, vm.peek)); })
137
+ Array.create_shared_method('>>', NosSpec, [], &lambda {|vm|
138
+ begin
139
+ vm.poke(self.insert(0, vm.peek))
140
+ rescue
141
+ vm.data_stack.pop
142
+ raise
143
+ end
144
+ })
125
145
 
126
146
  # [[3 1 2] n] + [[3 1 2 n]]
127
147
  Array.create_shared_method('+', NosSpec, [],
128
- &lambda {|vm| vm.poke(self + vm.peek.in_array); })
148
+ &lambda {|vm| vm.poke(self + vm.peek.in_array) })
129
149
 
130
150
 
131
151
  # The LEFT group
@@ -134,7 +154,7 @@ module XfOOrth
134
154
  begin
135
155
  width = Integer.foorth_coerce(vm.peek)
136
156
  error "F41: Invalid width: #{width} in .left" if width < 0
137
- vm.poke(self.first(width));
157
+ vm.poke(self.first(width))
138
158
  rescue
139
159
  vm.data_stack.pop
140
160
  raise
@@ -146,7 +166,7 @@ module XfOOrth
146
166
  begin
147
167
  width = Integer.foorth_coerce(vm.peek)
148
168
  error "F41: Invalid width: #{width} in .-left" if width < 0
149
- vm.poke(self[width..-1]);
169
+ vm.poke(self[width..-1])
150
170
  rescue
151
171
  vm.data_stack.pop
152
172
  raise
@@ -173,7 +193,7 @@ module XfOOrth
173
193
  error "F41: Invalid width: #{width} in .^left" if width < 0
174
194
 
175
195
  vm.poke(self[width..-1])
176
- vm.push(self.first(width));
196
+ vm.push(self.first(width))
177
197
  rescue
178
198
  vm.data_stack.pop
179
199
  raise
@@ -199,7 +219,7 @@ module XfOOrth
199
219
  begin
200
220
  width = Integer.foorth_coerce(vm.peek)
201
221
  error "F41: Invalid width: #{width} in .-right" if width < 0
202
- vm.poke(self[0...(0-width)]);
222
+ vm.poke(self[0...(0-width)])
203
223
  rescue
204
224
  vm.data_stack.pop
205
225
  raise
@@ -226,7 +246,7 @@ module XfOOrth
226
246
  error "F41: Invalid width: #{width} in .^right" if width < 0
227
247
 
228
248
  vm.poke(self[0...(0-width)])
229
- vm.push(self.last(width));
249
+ vm.push(self.last(width))
230
250
  rescue
231
251
  vm.data_stack.pop
232
252
  raise
@@ -358,7 +378,7 @@ module XfOOrth
358
378
  #[ [ 1 2 3 ] ] .pop_left [ [ 2 3 ] 1 ]
359
379
  Array.create_shared_method('.pop_left', TosSpec, [], &lambda{|vm|
360
380
  error "F31: Array underflow error on .pop_left" if self.empty?
361
- vm.push(self[1..-1]);
381
+ vm.push(self[1..-1])
362
382
  vm.push(self.first)
363
383
  })
364
384
 
@@ -381,7 +401,7 @@ module XfOOrth
381
401
  #[ [ 1 2 3 ] ] .peek_left [ [ 1 2 3 ] 1 ]
382
402
  Array.create_shared_method('.peek_left', TosSpec, [], &lambda{|vm|
383
403
  error "F31: Array underflow error on .peek_left" if self.empty?
384
- vm.push(self);
404
+ vm.push(self)
385
405
  vm.push(self.first)
386
406
  })
387
407
 
@@ -396,7 +416,7 @@ module XfOOrth
396
416
  #[ [ 1 2 3 ] ] .pop_right [ [ 1 2 ] 3 ]
397
417
  Array.create_shared_method('.pop_right', TosSpec, [], &lambda{|vm|
398
418
  error "F31: Array underflow error on .pop_right" if self.empty?
399
- vm.push(self[0...-1]);
419
+ vm.push(self[0...-1])
400
420
  vm.push(self.last)
401
421
  })
402
422
 
@@ -419,7 +439,7 @@ module XfOOrth
419
439
  #[ [ 1 2 3 ] ] .peek_right [ [ 1 2 3 ] 3 ]
420
440
  Array.create_shared_method('.peek_right', TosSpec, [], &lambda{|vm|
421
441
  error "F31: Array underflow error on .peek_right" if self.empty?
422
- vm.push(self);
442
+ vm.push(self)
423
443
  vm.push(self.last)
424
444
  })
425
445