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