fOOrth 0.6.6 → 0.6.11

Sign up to get free protection for your applications and to get access to all the features.
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