fOOrth 0.5.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 +7 -0
- data/.gitignore +21 -0
- data/.rdoc_options +17 -0
- data/Gemfile +4 -0
- data/README.md +67 -0
- data/bin/fOOrth +8 -0
- data/demo.rb +24 -0
- data/fOOrth.gemspec +40 -0
- data/fOOrth.reek +109 -0
- data/integration/README.md +12 -0
- data/integration/_FILE_test.foorth +5 -0
- data/integration/array_lib_tests.rb +360 -0
- data/integration/class_lib_tests.rb +116 -0
- data/integration/clone_lib_tests.rb +108 -0
- data/integration/comparison_tests.rb +132 -0
- data/integration/compile_lib_tests.rb +190 -0
- data/integration/ctrl_struct_lib_tests.rb +80 -0
- data/integration/data_ref_lib_tests.rb +43 -0
- data/integration/exception_lib_tests.rb +86 -0
- data/integration/fiber_bundle_tests.rb +380 -0
- data/integration/hash_lib_tests.rb +120 -0
- data/integration/in_stream_test_1.txt +4 -0
- data/integration/load_test_one.foorth +6 -0
- data/integration/load_test_two.foorth +4 -0
- data/integration/numeric_lib_tests.rb +321 -0
- data/integration/object_lib_tests.rb +38 -0
- data/integration/procedure_lib_tests.rb +40 -0
- data/integration/queue_lib_tests.rb +66 -0
- data/integration/stack_lib_tests.rb +70 -0
- data/integration/standard_lib_tests.rb +208 -0
- data/integration/stdio_lib_tests.rb +52 -0
- data/integration/stream_lib_tests.rb +196 -0
- data/integration/string_lib_tests.rb +217 -0
- data/integration/support/foorth_testing.rb +135 -0
- data/integration/thread_lib_tests.rb +83 -0
- data/integration/time_lib_tests.rb +791 -0
- data/integration/vm_lib_tests.rb +38 -0
- data/lib/fOOrth.rb +57 -0
- data/lib/fOOrth/compiler.rb +78 -0
- data/lib/fOOrth/compiler/context.rb +49 -0
- data/lib/fOOrth/compiler/context/locals.rb +34 -0
- data/lib/fOOrth/compiler/context/map_name.rb +92 -0
- data/lib/fOOrth/compiler/context/tags.rb +48 -0
- data/lib/fOOrth/compiler/modes.rb +32 -0
- data/lib/fOOrth/compiler/modes/compiled.rb +41 -0
- data/lib/fOOrth/compiler/modes/deferred.rb +57 -0
- data/lib/fOOrth/compiler/modes/delayed.rb +40 -0
- data/lib/fOOrth/compiler/modes/nested.rb +34 -0
- data/lib/fOOrth/compiler/modes/suspend.rb +32 -0
- data/lib/fOOrth/compiler/parser.rb +26 -0
- data/lib/fOOrth/compiler/parser/get_string.rb +71 -0
- data/lib/fOOrth/compiler/parser/normal.rb +53 -0
- data/lib/fOOrth/compiler/parser/skip.rb +50 -0
- data/lib/fOOrth/compiler/parser/special.rb +42 -0
- data/lib/fOOrth/compiler/process.rb +47 -0
- data/lib/fOOrth/compiler/process/generate.rb +24 -0
- data/lib/fOOrth/compiler/process/get_token.rb +23 -0
- data/lib/fOOrth/compiler/process/procedure.rb +55 -0
- data/lib/fOOrth/compiler/process/string.rb +20 -0
- data/lib/fOOrth/compiler/source.rb +51 -0
- data/lib/fOOrth/compiler/source/console.rb +70 -0
- data/lib/fOOrth/compiler/source/file_source.rb +37 -0
- data/lib/fOOrth/compiler/source/read_point.rb +46 -0
- data/lib/fOOrth/compiler/source/string_source.rb +28 -0
- data/lib/fOOrth/compiler/token.rb +37 -0
- data/lib/fOOrth/compiler/word_specs.rb +178 -0
- data/lib/fOOrth/core.rb +27 -0
- data/lib/fOOrth/core/class.rb +116 -0
- data/lib/fOOrth/core/object.rb +78 -0
- data/lib/fOOrth/core/virtual_machine.rb +28 -0
- data/lib/fOOrth/debug.rb +13 -0
- data/lib/fOOrth/debug/context_dump.rb +31 -0
- data/lib/fOOrth/debug/dbg_puts.rb +17 -0
- data/lib/fOOrth/debug/display_abort.rb +37 -0
- data/lib/fOOrth/debug/vm_dump.rb +27 -0
- data/lib/fOOrth/initialize.rb +83 -0
- data/lib/fOOrth/interpreter.rb +24 -0
- data/lib/fOOrth/interpreter/add_to_hash.rb +17 -0
- data/lib/fOOrth/interpreter/data_stack.rb +125 -0
- data/lib/fOOrth/interpreter/do_loop.rb +55 -0
- data/lib/fOOrth/interpreter/squash.rb +25 -0
- data/lib/fOOrth/library.rb +38 -0
- data/lib/fOOrth/library/array_library.rb +577 -0
- data/lib/fOOrth/library/bundle_library.rb +112 -0
- data/lib/fOOrth/library/class_library.rb +90 -0
- data/lib/fOOrth/library/clone_library.rb +72 -0
- data/lib/fOOrth/library/command_library.rb +205 -0
- data/lib/fOOrth/library/compile_library.rb +181 -0
- data/lib/fOOrth/library/complex_library.rb +81 -0
- data/lib/fOOrth/library/ctrl_struct_library.rb +116 -0
- data/lib/fOOrth/library/data_ref_library.rb +100 -0
- data/lib/fOOrth/library/duration/arithmetic.rb +114 -0
- data/lib/fOOrth/library/duration/formatter.rb +152 -0
- data/lib/fOOrth/library/duration/intervals.rb +233 -0
- data/lib/fOOrth/library/duration/make.rb +75 -0
- data/lib/fOOrth/library/duration_library.rb +52 -0
- data/lib/fOOrth/library/fiber_library.rb +120 -0
- data/lib/fOOrth/library/hash_library.rb +203 -0
- data/lib/fOOrth/library/in_stream_library.rb +81 -0
- data/lib/fOOrth/library/integer_library.rb +104 -0
- data/lib/fOOrth/library/mutex_library.rb +31 -0
- data/lib/fOOrth/library/numeric_library.rb +380 -0
- data/lib/fOOrth/library/object_library.rb +80 -0
- data/lib/fOOrth/library/other_value_types_library.rb +96 -0
- data/lib/fOOrth/library/out_stream_library.rb +146 -0
- data/lib/fOOrth/library/procedure_library.rb +65 -0
- data/lib/fOOrth/library/queue_library.rb +47 -0
- data/lib/fOOrth/library/rational_library.rb +90 -0
- data/lib/fOOrth/library/stack_library.rb +56 -0
- data/lib/fOOrth/library/stdio_library.rb +56 -0
- data/lib/fOOrth/library/string_library.rb +285 -0
- data/lib/fOOrth/library/stubs.rb +76 -0
- data/lib/fOOrth/library/sync_bundle_library.rb +50 -0
- data/lib/fOOrth/library/thread_library.rb +73 -0
- data/lib/fOOrth/library/time_library.rb +302 -0
- data/lib/fOOrth/library/vm_library.rb +105 -0
- data/lib/fOOrth/main.rb +125 -0
- data/lib/fOOrth/monkey_patch.rb +14 -0
- data/lib/fOOrth/monkey_patch/complex.rb +30 -0
- data/lib/fOOrth/monkey_patch/exceptions.rb +154 -0
- data/lib/fOOrth/monkey_patch/false.rb +11 -0
- data/lib/fOOrth/monkey_patch/float.rb +22 -0
- data/lib/fOOrth/monkey_patch/integer.rb +22 -0
- data/lib/fOOrth/monkey_patch/nil.rb +11 -0
- data/lib/fOOrth/monkey_patch/numeric.rb +33 -0
- data/lib/fOOrth/monkey_patch/object.rb +43 -0
- data/lib/fOOrth/monkey_patch/rational.rb +31 -0
- data/lib/fOOrth/monkey_patch/string.rb +51 -0
- data/lib/fOOrth/symbol_map.rb +82 -0
- data/lib/fOOrth/version.rb +7 -0
- data/license.txt +21 -0
- data/rakefile.rb +65 -0
- data/reek.txt +1 -0
- data/sire.rb +132 -0
- data/t.txt +3 -0
- data/test.foorth +5 -0
- data/tests/compiler/context_tests.rb +180 -0
- data/tests/compiler/file_source_test_one.txt +1 -0
- data/tests/compiler/file_source_test_three.txt +3 -0
- data/tests/compiler/file_source_test_two.txt +3 -0
- data/tests/compiler/file_source_tests.rb +130 -0
- data/tests/compiler/mode_tests.rb +45 -0
- data/tests/compiler/parser_tests.rb +116 -0
- data/tests/compiler/spec_tests.rb +113 -0
- data/tests/compiler/string_source_tests.rb +128 -0
- data/tests/core_tests.rb +138 -0
- data/tests/interpreter/data_stack_tests.rb +119 -0
- data/tests/monkey_patch/coerce_test.rb +131 -0
- data/tests/monkey_patch/complex_test.rb +25 -0
- data/tests/monkey_patch/numeric_test.rb +62 -0
- data/tests/monkey_patch/object_test.rb +49 -0
- data/tests/monkey_patch/rational_test.rb +57 -0
- data/tests/monkey_patch/string_test.rb +53 -0
- data/tests/symbol_map_tests.rb +53 -0
- metadata +366 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
require_relative 'interpreter/data_stack'
|
|
4
|
+
require_relative 'interpreter/do_loop'
|
|
5
|
+
require_relative 'interpreter/squash'
|
|
6
|
+
require_relative 'interpreter/add_to_hash'
|
|
7
|
+
|
|
8
|
+
#* interpreter.rb - The run time interpreter portion of the fOOrth language system.
|
|
9
|
+
module XfOOrth
|
|
10
|
+
|
|
11
|
+
#* interpreter.rb - The run time interpreter portion of the fOOrth language system.
|
|
12
|
+
class VirtualMachine
|
|
13
|
+
|
|
14
|
+
#The fOOrth timer anchor point. Used to assist in benchmarking etc.
|
|
15
|
+
attr_accessor :start_time
|
|
16
|
+
|
|
17
|
+
#Reset the state of the fOOrth inner interpreter.
|
|
18
|
+
def interpreter_reset
|
|
19
|
+
@data_stack = Array.new
|
|
20
|
+
self
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
#* interpreter/add_to_hash.rb - The fOOrth language hash literal support module.
|
|
4
|
+
module XfOOrth
|
|
5
|
+
|
|
6
|
+
#* interpreter/add_to_hash.rb - The fOOrth language hash literal support module.
|
|
7
|
+
class VirtualMachine
|
|
8
|
+
|
|
9
|
+
#Add the key and value to the hash being constructed.
|
|
10
|
+
def add_to_hash
|
|
11
|
+
key, value = popm(2)
|
|
12
|
+
peek(1)[key] = value
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
#* interpreter/data_stack.rb - The fOOrth language system data stack.
|
|
4
|
+
module XfOOrth
|
|
5
|
+
|
|
6
|
+
#* interpreter/data_stack.rb - The fOOrth language system data stack.
|
|
7
|
+
class VirtualMachine
|
|
8
|
+
#The fOOrth data stack. This is the primary means used to hold data
|
|
9
|
+
#for processing.
|
|
10
|
+
attr_accessor :data_stack
|
|
11
|
+
|
|
12
|
+
#Add an entry to the data stack.
|
|
13
|
+
#<br>Parameters:
|
|
14
|
+
#* datum - The data to be added to the data stack.
|
|
15
|
+
def push(datum)
|
|
16
|
+
@data_stack << datum
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
#Add some entries to the data stack.
|
|
20
|
+
#<br>Parameters:
|
|
21
|
+
#* datum - An array of data to be mass added to the data stack.
|
|
22
|
+
def pushm(datum)
|
|
23
|
+
@data_stack += datum
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
#Remove the "top" entry from the data stack.
|
|
27
|
+
#<br>Returns:
|
|
28
|
+
#* The "top" element of the data stack.
|
|
29
|
+
#<br>Note:
|
|
30
|
+
#* If the stack is empty this will raise an XfOOrthError exception.
|
|
31
|
+
def pop
|
|
32
|
+
error "F30: Data Stack Underflow: pop" if @data_stack.empty?
|
|
33
|
+
@data_stack.pop
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
#Remove multiple entries from the "top" of the data stack.
|
|
37
|
+
#<br>Parameters:
|
|
38
|
+
#* count - the number of elements to be returned.
|
|
39
|
+
#<br>Returns:
|
|
40
|
+
#* An array containing the "top" count elements of the data stack.
|
|
41
|
+
#<br>Note:
|
|
42
|
+
#* Raises an XfOOrthError exception if the stack has too few data.
|
|
43
|
+
def popm(count)
|
|
44
|
+
begin
|
|
45
|
+
error "F30: Data Stack Underflow: popm" if @data_stack.length < count
|
|
46
|
+
@data_stack.pop(count)
|
|
47
|
+
rescue
|
|
48
|
+
@data_stack = []
|
|
49
|
+
raise
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
#Remove the "top" entry from the data stack as a boolean.
|
|
54
|
+
#<br>Returns:
|
|
55
|
+
#* The "top" element of the data stack as a boolean
|
|
56
|
+
#<br>Note:
|
|
57
|
+
#* If the stack is empty this will raise an XfOOrthError exception.
|
|
58
|
+
def pop?
|
|
59
|
+
pop.to_foorth_b
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
#Read an entry from the data stack without modify that stack.
|
|
63
|
+
#<br>Parameters:
|
|
64
|
+
#* index - The (optional) entry to be retrieved. 1 corresponds to the
|
|
65
|
+
# "top" of the stack, 2 the next element, etc.
|
|
66
|
+
# This parameter defaults to 1.
|
|
67
|
+
#<br>Returns:
|
|
68
|
+
#* The element specified from the data stack.
|
|
69
|
+
#<br>Note:
|
|
70
|
+
#* Attempting to access an element deeper than the number of elements
|
|
71
|
+
# on the stack will fail with an XfOOrthError exception.
|
|
72
|
+
def peek(index=1)
|
|
73
|
+
unless @data_stack.length >= index && index > 0
|
|
74
|
+
error "F30: Data Stack Underflow: peek"
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
@data_stack[-index]
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
#Overwrite the TOS with the supplied data.
|
|
81
|
+
#<br>Parameters:
|
|
82
|
+
#* datum - The data to be placed in the data stack.
|
|
83
|
+
#<br>Note:
|
|
84
|
+
#* Attempting to poke an empty stack will fail with an XfOOrthError exception.
|
|
85
|
+
def poke(datum)
|
|
86
|
+
error "F30: Data Stack Underflow: poke" if @data_stack.empty?
|
|
87
|
+
@data_stack[-1] = datum
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
#Read an entry from the data stack as a boolean without modify that stack.
|
|
91
|
+
#<br>Parameters:
|
|
92
|
+
#* index - The (optional) entry to be retrieved. 1 corresponds to the "top"
|
|
93
|
+
# of the stack, 2 the next element, etc. This parameter defaults to 1.
|
|
94
|
+
#<br>Returns:
|
|
95
|
+
#* The element specified from the data stack as a boolean.
|
|
96
|
+
#<br>Note:
|
|
97
|
+
#* Attempting to access an element deeper than the number of elements on
|
|
98
|
+
# the stack will fail with an XfOOrthError exception.
|
|
99
|
+
def peek?(index=1)
|
|
100
|
+
peek(index).to_foorth_b
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
#A special operation to support dyadic operators. Swap then pop.
|
|
104
|
+
#<br>Returns:
|
|
105
|
+
#* The second element from the data stack.
|
|
106
|
+
#<br>Note:
|
|
107
|
+
#* If the stack has less than 2 elements, this will raise an
|
|
108
|
+
# XfOOrthError exception.
|
|
109
|
+
def swap_pop
|
|
110
|
+
begin
|
|
111
|
+
unless @data_stack.length >= 2
|
|
112
|
+
error "F30: Data Stack Underflow: swap_pop"
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
nos, tos = @data_stack.pop(2)
|
|
116
|
+
@data_stack << tos
|
|
117
|
+
nos
|
|
118
|
+
rescue
|
|
119
|
+
@data_stack = []
|
|
120
|
+
raise
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
end
|
|
125
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
#* interpreter/do_loop.rb - The fOOrth language do loop support module.
|
|
4
|
+
module XfOOrth
|
|
5
|
+
|
|
6
|
+
#* interpreter/do_loop.rb - The fOOrth language do loop support module.
|
|
7
|
+
class VirtualMachine
|
|
8
|
+
|
|
9
|
+
#The runtime implementation of the "do" word.
|
|
10
|
+
#<br>Parameters:
|
|
11
|
+
#* jloop - An optional outer loop value.
|
|
12
|
+
#* block - A block of code to be executed as the do loop body.
|
|
13
|
+
#<br>Block Parameters:
|
|
14
|
+
#* iloop - The stack frame of the current loop counter. This
|
|
15
|
+
# corresponds to the fOOrth 'i' value.
|
|
16
|
+
#* jloop - The stack frame of any containing loop counter. This corresponds
|
|
17
|
+
# to the fOOrth 'j' value. If there is no containing loop, this
|
|
18
|
+
# will always be a zero frame ie: [0, 0, 0].
|
|
19
|
+
#<br>Note:
|
|
20
|
+
#* Nested loops must be in the same compiler context in order to use this
|
|
21
|
+
# mechanism. Otherwise, loop index counters must be passed in explicitly.
|
|
22
|
+
#<br>Endemic Code Smells
|
|
23
|
+
#* :reek:FeatureEnvy -- false positive
|
|
24
|
+
def vm_do(jloop = [0, 0, 0], &block)
|
|
25
|
+
#Pop the start and ending values from the stack.
|
|
26
|
+
start_index, end_index = popm(2)
|
|
27
|
+
|
|
28
|
+
#Construct the loop data frame.
|
|
29
|
+
iloop = [start_index, end_index - 1, start_index + end_index - 1]
|
|
30
|
+
|
|
31
|
+
#Loop until done!
|
|
32
|
+
while iloop[0] <= iloop[1]
|
|
33
|
+
#Yield to the loop.
|
|
34
|
+
yield iloop, jloop
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
#The runtime implementation of the "+loop" word.
|
|
39
|
+
def vm_do_increment
|
|
40
|
+
inc_raw = self.pop
|
|
41
|
+
|
|
42
|
+
unless (inc_value = inc_raw.to_foorth_n)
|
|
43
|
+
error "F40: Cannot convert a #{inc_raw.foorth_name} to a Numeric instance"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
if inc_value > 0
|
|
47
|
+
inc_value
|
|
48
|
+
else
|
|
49
|
+
error "F41: Invalid loop increment value: #{inc_value}"
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
#* interpreter/squash.rb - The fOOrth language array literal support module.
|
|
4
|
+
module XfOOrth
|
|
5
|
+
|
|
6
|
+
#* interpreter/squash.rb - The fOOrth language do loop support module.
|
|
7
|
+
class VirtualMachine
|
|
8
|
+
|
|
9
|
+
#Compress the entire data stack into a single entry.
|
|
10
|
+
def squash
|
|
11
|
+
@data_stack = [@data_stack]
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
#Compress all the added entries into a single entry and revive the previous
|
|
15
|
+
#contents of the data stack.
|
|
16
|
+
def unsquash
|
|
17
|
+
previous = @data_stack[0]
|
|
18
|
+
data = @data_stack[1..-1]
|
|
19
|
+
@data_stack = previous
|
|
20
|
+
push(data)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
require_relative 'library/stubs'
|
|
4
|
+
require_relative 'library/object_library'
|
|
5
|
+
require_relative 'library/class_library'
|
|
6
|
+
require_relative 'library/vm_library'
|
|
7
|
+
require_relative 'library/data_ref_library'
|
|
8
|
+
require_relative 'library/clone_library'
|
|
9
|
+
require_relative 'library/compile_library'
|
|
10
|
+
require_relative 'library/ctrl_struct_library'
|
|
11
|
+
require_relative 'library/stdio_library'
|
|
12
|
+
require_relative 'library/numeric_library'
|
|
13
|
+
require_relative 'library/integer_library'
|
|
14
|
+
require_relative 'library/rational_library'
|
|
15
|
+
require_relative 'library/complex_library'
|
|
16
|
+
require_relative 'library/string_library'
|
|
17
|
+
require_relative 'library/duration_library'
|
|
18
|
+
require_relative 'library/time_library'
|
|
19
|
+
require_relative 'library/array_library'
|
|
20
|
+
require_relative 'library/hash_library'
|
|
21
|
+
require_relative 'library/procedure_library'
|
|
22
|
+
require_relative 'library/thread_library'
|
|
23
|
+
require_relative 'library/fiber_library'
|
|
24
|
+
require_relative 'library/bundle_library'
|
|
25
|
+
require_relative 'library/sync_bundle_library'
|
|
26
|
+
require_relative 'library/other_value_types_library'
|
|
27
|
+
require_relative 'library/command_library'
|
|
28
|
+
require_relative 'library/in_stream_library'
|
|
29
|
+
require_relative 'library/out_stream_library'
|
|
30
|
+
require_relative 'library/queue_library'
|
|
31
|
+
require_relative 'library/stack_library'
|
|
32
|
+
require_relative 'library/mutex_library'
|
|
33
|
+
|
|
34
|
+
#* library.rb - The word library portion of the fOOrth language system.
|
|
35
|
+
module XfOOrth
|
|
36
|
+
|
|
37
|
+
end
|
|
38
|
+
|
|
@@ -0,0 +1,577 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
#* library/array_library.rb - Array support for the fOOrth library.
|
|
4
|
+
module XfOOrth
|
|
5
|
+
|
|
6
|
+
#Connect the Array class to the fOOrth class system.
|
|
7
|
+
Array.create_foorth_proxy
|
|
8
|
+
|
|
9
|
+
# [] Array .new [[]]; create an empty array.
|
|
10
|
+
# The default implementation from Object is used for this.
|
|
11
|
+
|
|
12
|
+
# [n] Array .new_size [[0,0,...0]]; create an array of n zeros.
|
|
13
|
+
Array.create_exclusive_method('.new_size', TosSpec, [], &lambda {|vm|
|
|
14
|
+
begin
|
|
15
|
+
vm.poke(self.new(Integer.foorth_coerce(vm.peek), 0));
|
|
16
|
+
rescue
|
|
17
|
+
vm.data_stack.pop
|
|
18
|
+
raise
|
|
19
|
+
end
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
# [v] Array .new_value [[v]]; create an array of a single value.
|
|
23
|
+
Array.create_exclusive_method('.new_value', TosSpec, [],
|
|
24
|
+
&lambda {|vm| vm.poke(self.new(1, vm.peek)); })
|
|
25
|
+
|
|
26
|
+
# [v n] Array .new_values [[v,v,...v]]; create an array of a n values.
|
|
27
|
+
Array.create_exclusive_method('.new_values', TosSpec, [], &lambda {|vm|
|
|
28
|
+
begin
|
|
29
|
+
count = Integer.foorth_coerce(vm.pop)
|
|
30
|
+
vm.poke(self.new(count, vm.peek))
|
|
31
|
+
rescue
|
|
32
|
+
vm.data_stack.pop
|
|
33
|
+
raise
|
|
34
|
+
end
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
# [n] Array .new{{ ... }} [[array]]; create an array of a n computed values.
|
|
38
|
+
Array.create_exclusive_method('.new{{', NosSpec, [], &lambda {|vm|
|
|
39
|
+
block = vm.pop
|
|
40
|
+
count = Integer.foorth_coerce(vm.pop)
|
|
41
|
+
|
|
42
|
+
vm.push(Array.new(count) { |idx| block.call(vm, nil, idx); vm.pop})
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
# [array] .map{{ ... }} [mapped_array]
|
|
46
|
+
Array.create_shared_method('.map{{', NosSpec, [], &lambda { |vm|
|
|
47
|
+
idx, block = 0, vm.pop
|
|
48
|
+
vm.push(self.map { |val| block.call(vm, val, idx); idx += 1; vm.pop})
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
# [array] .select{{ ... }} [selected_array]
|
|
52
|
+
Array.create_shared_method('.select{{', NosSpec, [], &lambda { |vm|
|
|
53
|
+
idx, block = 0, vm.pop
|
|
54
|
+
vm.push(self.select { |val| block.call(vm, val, idx); idx += 1; vm.pop})
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
# [] [ v1 v2 ... vn ] [[v1,v2,...vn]]; an array literal value
|
|
58
|
+
VirtualMachine.create_shared_method('[', VmSpec, [:immediate], &lambda { |vm|
|
|
59
|
+
vm.nest_mode('vm.squash; ', :array_literal)
|
|
60
|
+
|
|
61
|
+
vm.context.create_local_method(']', LocalSpec, [:immediate],
|
|
62
|
+
&lambda {|vm| vm.unnest_mode('vm.unsquash; ', [:array_literal]) })
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
# [array] .each{{ ... }} [unspecified]
|
|
66
|
+
Array.create_shared_method('.each{{', NosSpec, [], &lambda { |vm|
|
|
67
|
+
block = vm.pop
|
|
68
|
+
self.each_with_index { |val, idx| block.call(vm, val, idx) }
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
# Some basic data access words.
|
|
72
|
+
# [a] @ [a[0]]
|
|
73
|
+
Array.create_shared_method('@', TosSpec, [], &lambda { |vm|
|
|
74
|
+
vm.push(self[0])
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
# [ v a ] ! [], a[0] = v
|
|
78
|
+
Array.create_shared_method('!', TosSpec, [], &lambda { |vm|
|
|
79
|
+
self[0] = vm.pop
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
# [ i a ] .[]@ [ a[i] ]
|
|
83
|
+
Array.create_shared_method('.[]@', TosSpec, [], &lambda {|vm|
|
|
84
|
+
begin
|
|
85
|
+
vm.poke(self[Integer.foorth_coerce(vm.peek)])
|
|
86
|
+
rescue
|
|
87
|
+
vm.data_stack.pop
|
|
88
|
+
raise
|
|
89
|
+
end
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
# [ v i a ] .[]! []; a[i]=v
|
|
93
|
+
Array.create_shared_method('.[]!', TosSpec, [], &lambda {|vm|
|
|
94
|
+
value, index = vm.popm(2)
|
|
95
|
+
self[Integer.foorth_coerce(index)] = value;
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
# [ [ 1 2 3 ] ] .reverse [ [ 3 2 1 ] ]
|
|
99
|
+
Array.create_shared_method('.reverse', TosSpec, [],
|
|
100
|
+
&lambda {|vm| vm.push(self.reverse); })
|
|
101
|
+
|
|
102
|
+
# [ [ 3 1 2 ] ] .sort [ [ 1 2 3 ] ]
|
|
103
|
+
Array.create_shared_method('.sort', TosSpec, [],
|
|
104
|
+
&lambda {|vm| vm.push(self.sort {|va,vb| va <=> va.foorth_coerce(vb)}); })
|
|
105
|
+
|
|
106
|
+
# [ [ 1 2 3 ] ] .shuffle [ [ x y z ] ]
|
|
107
|
+
Array.create_shared_method('.shuffle', TosSpec, [],
|
|
108
|
+
&lambda {|vm| vm.push(self.shuffle); })
|
|
109
|
+
|
|
110
|
+
# [ [ 3 1 2 ] ] .length [ 3 ]
|
|
111
|
+
Array.create_shared_method('.length', TosSpec, [],
|
|
112
|
+
&lambda {|vm| vm.push(self.length); })
|
|
113
|
+
|
|
114
|
+
# [ an_array ] .empty? [ a_boolean ]
|
|
115
|
+
Array.create_shared_method('.empty?', TosSpec, [],
|
|
116
|
+
&lambda {|vm| vm.push(self.empty?); })
|
|
117
|
+
|
|
118
|
+
# [ [ 3 1 2 ] n ] << [ [ 3 1 2 n ] ]
|
|
119
|
+
Array.create_shared_method('<<', NosSpec, [],
|
|
120
|
+
&lambda {|vm| vm.poke(self << vm.peek); })
|
|
121
|
+
|
|
122
|
+
# [[3 1 2] n] + [[3 1 2 n]]
|
|
123
|
+
Array.create_shared_method('+', NosSpec, [],
|
|
124
|
+
&lambda {|vm| vm.poke(self + vm.peek.in_array); })
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
# The LEFT group
|
|
128
|
+
# [w [ 3 1 2 ] ] .left [ [ 3 1 ] ]; assumes w = 2
|
|
129
|
+
Array.create_shared_method('.left', TosSpec, [], &lambda {|vm|
|
|
130
|
+
begin
|
|
131
|
+
width = Integer.foorth_coerce(vm.peek)
|
|
132
|
+
error "F41: Invalid width: #{width} in .left" if width < 0
|
|
133
|
+
vm.poke(self.first(width));
|
|
134
|
+
rescue
|
|
135
|
+
vm.data_stack.pop
|
|
136
|
+
raise
|
|
137
|
+
end
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
# [w [ 3 1 2 ] ] .-left [ 2 ] // Assumes w = 2
|
|
141
|
+
Array.create_shared_method('.-left', TosSpec, [], &lambda {|vm|
|
|
142
|
+
begin
|
|
143
|
+
width = Integer.foorth_coerce(vm.peek)
|
|
144
|
+
error "F41: Invalid width: #{width} in .-left" if width < 0
|
|
145
|
+
vm.poke(self[width..-1]);
|
|
146
|
+
rescue
|
|
147
|
+
vm.data_stack.pop
|
|
148
|
+
raise
|
|
149
|
+
end
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
# [w [ 0 8 9 ] [ 1 2 3 4 ] ] .+left [ [ 0 8 9 3 4 ] ] // Assumes w = 2
|
|
153
|
+
Array.create_shared_method('.+left', TosSpec, [], &lambda {|vm|
|
|
154
|
+
begin
|
|
155
|
+
ins = vm.pop.in_array
|
|
156
|
+
width = Integer.foorth_coerce(vm.peek)
|
|
157
|
+
error "F41: Invalid width: #{width} in .+left" if width < 0
|
|
158
|
+
vm.poke(ins + self[width..-1])
|
|
159
|
+
rescue
|
|
160
|
+
vm.data_stack.pop
|
|
161
|
+
raise
|
|
162
|
+
end
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
# [w [ 1 2 3 4 ] ] .^left [ [ 3 4 ] [ 1 2 ] ]; assumes w = 2
|
|
166
|
+
Array.create_shared_method('.^left', TosSpec, [], &lambda {|vm|
|
|
167
|
+
begin
|
|
168
|
+
width = Integer.foorth_coerce(vm.peek)
|
|
169
|
+
error "F41: Invalid width: #{width} in .^left" if width < 0
|
|
170
|
+
|
|
171
|
+
vm.poke(self[width..-1])
|
|
172
|
+
vm.push(self.first(width));
|
|
173
|
+
rescue
|
|
174
|
+
vm.data_stack.pop
|
|
175
|
+
raise
|
|
176
|
+
end
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
#The RIGHT group
|
|
181
|
+
# [w [ 3 1 2 ] ] .right [ [ 1 2 ] ]; assumes w = 2
|
|
182
|
+
Array.create_shared_method('.right', TosSpec, [], &lambda {|vm|
|
|
183
|
+
begin
|
|
184
|
+
width = Integer.foorth_coerce(vm.peek)
|
|
185
|
+
error "F41: Invalid width: #{width} in .right" if width < 0
|
|
186
|
+
vm.poke(self.last(width))
|
|
187
|
+
rescue
|
|
188
|
+
vm.data_stack.pop
|
|
189
|
+
raise
|
|
190
|
+
end
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
# [w [ 3 1 2 ] ] .-right [ [ 3 ] ] // Assumes w = 2
|
|
194
|
+
Array.create_shared_method('.-right', TosSpec, [], &lambda {|vm|
|
|
195
|
+
begin
|
|
196
|
+
width = Integer.foorth_coerce(vm.peek)
|
|
197
|
+
error "F41: Invalid width: #{width} in .-right" if width < 0
|
|
198
|
+
vm.poke(self[0...(0-width)]);
|
|
199
|
+
rescue
|
|
200
|
+
vm.data_stack.pop
|
|
201
|
+
raise
|
|
202
|
+
end
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
# [w [ 0 8 9 ] [ 1 2 3 4 ] ] .+right [ [ 1 2 0 8 9 ] ] // Assumes w = 2
|
|
206
|
+
Array.create_shared_method('.+right', TosSpec, [], &lambda {|vm|
|
|
207
|
+
begin
|
|
208
|
+
ins = vm.pop.in_array
|
|
209
|
+
width = Integer.foorth_coerce(vm.peek)
|
|
210
|
+
error "F41: Invalid width: #{width} in .+right" if width < 0
|
|
211
|
+
vm.poke(self[0...(0-width)] + ins)
|
|
212
|
+
rescue
|
|
213
|
+
vm.data_stack.pop
|
|
214
|
+
raise
|
|
215
|
+
end
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
# [w [ 1 2 3 4 ] ] .^right [ [ 1 2 ] [ 3 4 ] ]; assumes w = 2
|
|
219
|
+
Array.create_shared_method('.^right', TosSpec, [], &lambda {|vm|
|
|
220
|
+
begin
|
|
221
|
+
width = Integer.foorth_coerce(vm.peek)
|
|
222
|
+
error "F41: Invalid width: #{width} in .^right" if width < 0
|
|
223
|
+
|
|
224
|
+
vm.poke(self[0...(0-width)])
|
|
225
|
+
vm.push(self.last(width));
|
|
226
|
+
rescue
|
|
227
|
+
vm.data_stack.pop
|
|
228
|
+
raise
|
|
229
|
+
end
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
# The MID group
|
|
234
|
+
# [n w [ 1 2 3 4 5 6 7 8 ] ] .mid [ [ 3 4 5 6 ] ] // Assumes n = 2, w = 4
|
|
235
|
+
Array.create_shared_method('.mid', TosSpec, [], &lambda {|vm|
|
|
236
|
+
begin
|
|
237
|
+
width = Integer.foorth_coerce(vm.pop)
|
|
238
|
+
posn = Integer.foorth_coerce(vm.peek)
|
|
239
|
+
error "F41: Invalid index: #{posn} in .mid" if posn < 0
|
|
240
|
+
error "F41: Invalid width: #{width} in .mid" if width < 0
|
|
241
|
+
vm.poke(self[posn...(posn+width)])
|
|
242
|
+
rescue
|
|
243
|
+
vm.data_stack.pop
|
|
244
|
+
raise
|
|
245
|
+
end
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
# [n w [ 1 2 3 4 5 6 7 8 ] ] .-mid [ [ 1 2 7 8 ] ] // Assumes n = 2, w = 4
|
|
249
|
+
Array.create_shared_method('.-mid', TosSpec, [], &lambda {|vm|
|
|
250
|
+
begin
|
|
251
|
+
width = Integer.foorth_coerce(vm.pop)
|
|
252
|
+
posn = Integer.foorth_coerce(vm.peek)
|
|
253
|
+
error "F41: Invalid index: #{posn} in .-mid" if posn < 0
|
|
254
|
+
error "F41: Invalid width: #{width} in .-mid" if width < 0
|
|
255
|
+
vm.poke(self[0...posn] + self[(posn+width)..-1])
|
|
256
|
+
rescue
|
|
257
|
+
vm.data_stack.pop
|
|
258
|
+
raise
|
|
259
|
+
end
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
# [n w [ 0 8 9 ] [ 1 2 3 4 5 6 7 8 ] ] .+mid [ [ 1 2 0 8 9 7 8 ] ] // Assumes n=2, w=4
|
|
263
|
+
Array.create_shared_method('.+mid', TosSpec, [], &lambda {|vm|
|
|
264
|
+
begin
|
|
265
|
+
ins = vm.pop.in_array
|
|
266
|
+
width = Integer.foorth_coerce(vm.pop)
|
|
267
|
+
posn = Integer.foorth_coerce(vm.peek)
|
|
268
|
+
error "F41: Invalid index: #{posn} in .+mid" if posn < 0
|
|
269
|
+
error "F41: Invalid width: #{width} in .+mid" if width < 0
|
|
270
|
+
vm.poke(self[0...posn] + ins + self[(posn+width)..-1])
|
|
271
|
+
rescue
|
|
272
|
+
vm.data_stack.pop
|
|
273
|
+
raise
|
|
274
|
+
end
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
# [n w [ 1 2 3 4 5 6 7 8 ] ] .^mid [ [ 1 2 7 8 ] [ 3 4 5 6 ] ] // For n=2, w=4
|
|
278
|
+
Array.create_shared_method('.^mid', TosSpec, [], &lambda {|vm|
|
|
279
|
+
begin
|
|
280
|
+
width = Integer.foorth_coerce(vm.pop)
|
|
281
|
+
posn = Integer.foorth_coerce(vm.peek)
|
|
282
|
+
error "F41: Invalid index: #{posn} in .^mid" if posn < 0
|
|
283
|
+
error "F41: Invalid width: #{width} in .^mid" if width < 0
|
|
284
|
+
vm.poke(self[0...posn] + self[(posn+width)..-1])
|
|
285
|
+
vm.push(self[posn...(posn+width)])
|
|
286
|
+
rescue
|
|
287
|
+
vm.data_stack.pop
|
|
288
|
+
raise
|
|
289
|
+
end
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
# The MIDLR group
|
|
294
|
+
# [l r [ 1 2 3 4 5 6 7 8 ] ] .midlr [ [ 2 3 4 5 6 7 ] ] // Assumes l=1, r=1
|
|
295
|
+
Array.create_shared_method('.midlr', TosSpec, [], &lambda {|vm|
|
|
296
|
+
begin
|
|
297
|
+
right = Integer.foorth_coerce(vm.pop)
|
|
298
|
+
left = Integer.foorth_coerce(vm.peek)
|
|
299
|
+
error "F41: Invalid left width: #{left} in .midlr" if left < 0
|
|
300
|
+
error "F41: Invalid right width: #{right} in .midlr" if right < 0
|
|
301
|
+
vm.poke(self[left..(0-right-1)])
|
|
302
|
+
rescue
|
|
303
|
+
vm.data_stack.pop
|
|
304
|
+
raise
|
|
305
|
+
end
|
|
306
|
+
})
|
|
307
|
+
|
|
308
|
+
# [l r [ 1 2 3 4 5 6 7 8 ] ] .-midlr [ [ 1 8 ] ] // Assumes l = 1, r = 1
|
|
309
|
+
Array.create_shared_method('.-midlr', TosSpec, [], &lambda {|vm|
|
|
310
|
+
begin
|
|
311
|
+
right = Integer.foorth_coerce(vm.pop)
|
|
312
|
+
left = Integer.foorth_coerce(vm.peek)
|
|
313
|
+
error "F41: Invalid left width: #{left} in .-midlr" if left < 0
|
|
314
|
+
error "F41: Invalid right width: #{right} in .-midlr" if right < 0
|
|
315
|
+
vm.poke(self.first(left) + self.last(right))
|
|
316
|
+
rescue
|
|
317
|
+
vm.data_stack.pop
|
|
318
|
+
raise
|
|
319
|
+
end
|
|
320
|
+
})
|
|
321
|
+
|
|
322
|
+
# [l r [ 0 8 9 ] [ 1 2 3 4 5 6 7 8 ] ] .+midlr [ [ 1 0 8 9 8 ] ] // Assumes l = 1, r = 1
|
|
323
|
+
Array.create_shared_method('.+midlr', TosSpec, [], &lambda {|vm|
|
|
324
|
+
begin
|
|
325
|
+
ins = vm.pop.in_array
|
|
326
|
+
right = Integer.foorth_coerce(vm.pop)
|
|
327
|
+
left = Integer.foorth_coerce(vm.peek)
|
|
328
|
+
error "F41: Invalid left width: #{left} in .-midlr" if left < 0
|
|
329
|
+
error "F41: Invalid right width: #{right} in .-midlr" if right < 0
|
|
330
|
+
vm.poke(self.first(left) + ins + self.last(right))
|
|
331
|
+
rescue
|
|
332
|
+
vm.data_stack.pop
|
|
333
|
+
raise
|
|
334
|
+
end
|
|
335
|
+
})
|
|
336
|
+
|
|
337
|
+
# [l r [ 1 2 3 4 5 ] ] .midlr [ [ 1 5 ] [ 2 3 4 ] ] // Assumes l=1, r=1
|
|
338
|
+
Array.create_shared_method('.^midlr', TosSpec, [], &lambda {|vm|
|
|
339
|
+
begin
|
|
340
|
+
right = Integer.foorth_coerce(vm.pop)
|
|
341
|
+
left = Integer.foorth_coerce(vm.peek)
|
|
342
|
+
error "F41: Invalid left width: #{left} in .midlr" if left < 0
|
|
343
|
+
error "F41: Invalid right width: #{right} in .midlr" if right < 0
|
|
344
|
+
vm.poke(self.first(left) + self.last(right))
|
|
345
|
+
vm.push(self[left..(0-right-1)])
|
|
346
|
+
rescue
|
|
347
|
+
vm.data_stack.pop
|
|
348
|
+
raise
|
|
349
|
+
end
|
|
350
|
+
})
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
#The DEQUEUE LEFT group
|
|
354
|
+
#[ [ 1 2 3 ] ] .pop_left [ [ 2 3 ] 1 ]
|
|
355
|
+
Array.create_shared_method('.pop_left', TosSpec, [], &lambda{|vm|
|
|
356
|
+
error "F31: Array underflow error on .pop_left" if self.empty?
|
|
357
|
+
vm.push(self[1..-1]);
|
|
358
|
+
vm.push(self.first)
|
|
359
|
+
})
|
|
360
|
+
|
|
361
|
+
#[ [ 1 2 3 ] ] .pop_left! [ 1 ]; Mutates original array.
|
|
362
|
+
Array.create_shared_method('.pop_left!', TosSpec, [], &lambda{|vm|
|
|
363
|
+
error "F31: Array underflow error on .pop_left!" if self.empty?
|
|
364
|
+
vm.push(self.delete_at(0))
|
|
365
|
+
})
|
|
366
|
+
|
|
367
|
+
#[ 0 [ 1 2 3 ] ] .push_left [ [ 0 1 2 3 ] ]
|
|
368
|
+
Array.create_shared_method('.push_left', TosSpec, [], &lambda{|vm|
|
|
369
|
+
vm.poke([ vm.peek ] + self)
|
|
370
|
+
})
|
|
371
|
+
|
|
372
|
+
#[ 0 [ 1 2 3 ] ] .push_left! [ ]; Mutates original array.
|
|
373
|
+
Array.create_shared_method('.push_left!', TosSpec, [], &lambda{|vm|
|
|
374
|
+
self.insert(0, vm.pop)
|
|
375
|
+
})
|
|
376
|
+
|
|
377
|
+
#[ [ 1 2 3 ] ] .peek_left [ [ 1 2 3 ] 1 ]
|
|
378
|
+
Array.create_shared_method('.peek_left', TosSpec, [], &lambda{|vm|
|
|
379
|
+
error "F31: Array underflow error on .peek_left" if self.empty?
|
|
380
|
+
vm.push(self);
|
|
381
|
+
vm.push(self.first)
|
|
382
|
+
})
|
|
383
|
+
|
|
384
|
+
#[ [ 1 2 3 ] ] .peek_left! [ 1 ]
|
|
385
|
+
Array.create_shared_method('.peek_left!', TosSpec, [], &lambda{|vm|
|
|
386
|
+
error "F31: Array underflow error on .peek_left!" if self.empty?
|
|
387
|
+
vm.push(self.first)
|
|
388
|
+
})
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
#The DEQUEUE RIGHT group
|
|
392
|
+
#[ [ 1 2 3 ] ] .pop_right [ [ 1 2 ] 3 ]
|
|
393
|
+
Array.create_shared_method('.pop_right', TosSpec, [], &lambda{|vm|
|
|
394
|
+
error "F31: Array underflow error on .pop_right" if self.empty?
|
|
395
|
+
vm.push(self[0...-1]);
|
|
396
|
+
vm.push(self.last)
|
|
397
|
+
})
|
|
398
|
+
|
|
399
|
+
#[ [ 1 2 3 ] ] .pop_right! [ 3 ]; Mutates original array.
|
|
400
|
+
Array.create_shared_method('.pop_right!', TosSpec, [], &lambda{|vm|
|
|
401
|
+
error "F31: Array underflow error on .pop_right!" if self.empty?
|
|
402
|
+
vm.push(self.pop)
|
|
403
|
+
})
|
|
404
|
+
|
|
405
|
+
#[ 4 [ 1 2 3 ] ] .push_right [ [ 1 2 3 4 ] ]
|
|
406
|
+
Array.create_shared_method('.push_right', TosSpec, [], &lambda{|vm|
|
|
407
|
+
vm.poke(self + [ vm.peek ])
|
|
408
|
+
})
|
|
409
|
+
|
|
410
|
+
#[ 4 [ 1 2 3 ] ] .push_right! [ ]; Mutates original array.
|
|
411
|
+
Array.create_shared_method('.push_right!', TosSpec, [], &lambda{|vm|
|
|
412
|
+
self << vm.pop
|
|
413
|
+
})
|
|
414
|
+
|
|
415
|
+
#[ [ 1 2 3 ] ] .peek_right [ [ 1 2 3 ] 3 ]
|
|
416
|
+
Array.create_shared_method('.peek_right', TosSpec, [], &lambda{|vm|
|
|
417
|
+
error "F31: Array underflow error on .peek_right" if self.empty?
|
|
418
|
+
vm.push(self);
|
|
419
|
+
vm.push(self.last)
|
|
420
|
+
})
|
|
421
|
+
|
|
422
|
+
#[ [ 1 2 3 ] ] .peek_right! [ [ 1 2 3 ] 3 ]
|
|
423
|
+
Array.create_shared_method('.peek_right!', TosSpec, [], &lambda{|vm|
|
|
424
|
+
error "F31: Array underflow error on .peek_right!" if self.empty?
|
|
425
|
+
vm.push(self.last)
|
|
426
|
+
})
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
# [ a ] .min [ smallest_element ]
|
|
430
|
+
Array.create_shared_method('.min', TosSpec, [], &lambda {|vm|
|
|
431
|
+
result = self[0]
|
|
432
|
+
|
|
433
|
+
self.each do |value|
|
|
434
|
+
other = result.foorth_coerce(value)
|
|
435
|
+
result = other if result > other
|
|
436
|
+
end
|
|
437
|
+
|
|
438
|
+
vm.push(result)
|
|
439
|
+
})
|
|
440
|
+
|
|
441
|
+
# [ a ] .max [ largest_element ]
|
|
442
|
+
Array.create_shared_method('.max', TosSpec, [], &lambda {|vm|
|
|
443
|
+
result = self[0]
|
|
444
|
+
|
|
445
|
+
self.each do |value|
|
|
446
|
+
other = result.foorth_coerce(value)
|
|
447
|
+
result = other if result < other
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
vm.push(result)
|
|
451
|
+
})
|
|
452
|
+
|
|
453
|
+
# [ array ] .split [ a0 a1 ... aN ]
|
|
454
|
+
Array.create_shared_method('.split', TosSpec, [], &lambda {|vm|
|
|
455
|
+
vm.pushm(self)
|
|
456
|
+
})
|
|
457
|
+
|
|
458
|
+
# [ a1 a2 aN N ] .join [ [ a1 a2 ... aN ] ]
|
|
459
|
+
Integer.create_shared_method('.join', TosSpec, [], &lambda {|vm|
|
|
460
|
+
error "F30: Invalid array size: .join" if self < 0
|
|
461
|
+
vm.push(vm.popm(self))
|
|
462
|
+
})
|
|
463
|
+
|
|
464
|
+
# [ array ] .to_s [ string ]
|
|
465
|
+
Array.create_shared_method('.to_s', TosSpec, [], &lambda {|vm|
|
|
466
|
+
result = "[ "
|
|
467
|
+
|
|
468
|
+
self.each do |value|
|
|
469
|
+
if value.is_a?(String)
|
|
470
|
+
result << value.inspect + " "
|
|
471
|
+
else
|
|
472
|
+
value.to_foorth_s(vm)
|
|
473
|
+
result << (vm.pop || value.inspect) + " "
|
|
474
|
+
end
|
|
475
|
+
end
|
|
476
|
+
|
|
477
|
+
vm.push(result + "]")
|
|
478
|
+
})
|
|
479
|
+
|
|
480
|
+
# [ l 2 3 ... n ] .strmax [ widest ]
|
|
481
|
+
Array.create_shared_method('.strmax', TosSpec, [], &lambda {|vm|
|
|
482
|
+
result = 0
|
|
483
|
+
|
|
484
|
+
self.each {|item|
|
|
485
|
+
item.foorth_strlen(vm)
|
|
486
|
+
temp = vm.pop
|
|
487
|
+
result = result > temp ? result : temp
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
vm.push(result)
|
|
491
|
+
})
|
|
492
|
+
|
|
493
|
+
#[ array ] .scatter [ a0 a1 ... aN ]
|
|
494
|
+
Array.create_shared_method('.scatter', TosSpec, [], &lambda {|vm|
|
|
495
|
+
vm.data_stack += self
|
|
496
|
+
})
|
|
497
|
+
|
|
498
|
+
#[ x0 x1 ... xN] gather [ array ]
|
|
499
|
+
VirtualMachine.create_shared_method('gather', VmSpec, [], &lambda{|vm|
|
|
500
|
+
@data_stack = [@data_stack]
|
|
501
|
+
})
|
|
502
|
+
|
|
503
|
+
#[ x0 x1 ... xN N] .gather [ array ]
|
|
504
|
+
Integer.create_shared_method('.gather', TosSpec, [], &lambda {|vm|
|
|
505
|
+
error "F30: Invalid .gather count value." unless self > 0
|
|
506
|
+
error "F30: Data stack underflow." unless self <= vm.data_stack.length
|
|
507
|
+
|
|
508
|
+
temp = vm.data_stack.pop(self)
|
|
509
|
+
vm.data_stack << temp
|
|
510
|
+
})
|
|
511
|
+
|
|
512
|
+
#[ an_array ] .to_a [ an_array ]
|
|
513
|
+
Array.create_shared_method('.to_a', TosSpec, [],
|
|
514
|
+
&lambda {|vm| vm.push(self) })
|
|
515
|
+
|
|
516
|
+
#[ an_array ] .to_h [ a_hash ]
|
|
517
|
+
Array.create_shared_method('.to_h', TosSpec, [], &lambda {|vm|
|
|
518
|
+
result = {}
|
|
519
|
+
self.each_with_index { |val, idx| result[idx] = val }
|
|
520
|
+
vm.push(result)
|
|
521
|
+
})
|
|
522
|
+
|
|
523
|
+
#[ an_array ] .values [ an_array ]
|
|
524
|
+
Array.create_shared_method('.values', TosSpec, [],
|
|
525
|
+
&lambda {|vm| vm.push(self) })
|
|
526
|
+
|
|
527
|
+
#[ an_array ] .keys [ an_array ]
|
|
528
|
+
Array.create_shared_method('.keys', TosSpec, [],
|
|
529
|
+
&lambda {|vm| vm.push((0...self.length).to_a) })
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
$fcpl = 80 #fOOrth Character Per Line
|
|
533
|
+
$flpp = 25 #fOOrth Lines Per Page
|
|
534
|
+
|
|
535
|
+
# [ l 2 3 ... n ] .pp []; pretty print the array!
|
|
536
|
+
Array.create_shared_method('.pp', TosSpec, [], &lambda {|vm|
|
|
537
|
+
self.foorth_strmax(vm)
|
|
538
|
+
width = vm.pop + 1
|
|
539
|
+
cols = (width <= $fcpl) ? ($fcpl / width) : 1
|
|
540
|
+
full_rows = ((cols * width) % $fcpl) == 0
|
|
541
|
+
rows_left = (self.length + cols - 1) / cols
|
|
542
|
+
pages = (rows_left + $flpp - 1) / $flpp
|
|
543
|
+
page_capacity = $flpp * cols
|
|
544
|
+
|
|
545
|
+
(0...pages).each do |page|
|
|
546
|
+
offset = page * page_capacity
|
|
547
|
+
rows_this_page = (rows_left >= $flpp) ? $flpp : rows_left
|
|
548
|
+
|
|
549
|
+
(0...rows_this_page).each do |row|
|
|
550
|
+
(0...cols).each do |col|
|
|
551
|
+
self[offset + col*rows_this_page + row].to_foorth_s(vm)
|
|
552
|
+
|
|
553
|
+
if cols > 1
|
|
554
|
+
print vm.pop.ljust(width)
|
|
555
|
+
else
|
|
556
|
+
print vm.pop
|
|
557
|
+
end
|
|
558
|
+
end
|
|
559
|
+
|
|
560
|
+
puts unless full_rows
|
|
561
|
+
end
|
|
562
|
+
|
|
563
|
+
rows_left -= $flpp
|
|
564
|
+
puts "\n"
|
|
565
|
+
end
|
|
566
|
+
})
|
|
567
|
+
|
|
568
|
+
#Show the page length.
|
|
569
|
+
VirtualMachine.create_shared_method(')pl', MacroSpec,
|
|
570
|
+
[:macro, 'puts "Page Length = #{$flpp}"; '])
|
|
571
|
+
|
|
572
|
+
|
|
573
|
+
#Set/show the page length.
|
|
574
|
+
VirtualMachine.create_shared_method(')set_pl', MacroSpec,
|
|
575
|
+
[:macro, 'puts "New Page Length = #{$flpp = vm.pop.to_i}"; '])
|
|
576
|
+
|
|
577
|
+
end
|