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.
Files changed (155) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.rdoc_options +17 -0
  4. data/Gemfile +4 -0
  5. data/README.md +67 -0
  6. data/bin/fOOrth +8 -0
  7. data/demo.rb +24 -0
  8. data/fOOrth.gemspec +40 -0
  9. data/fOOrth.reek +109 -0
  10. data/integration/README.md +12 -0
  11. data/integration/_FILE_test.foorth +5 -0
  12. data/integration/array_lib_tests.rb +360 -0
  13. data/integration/class_lib_tests.rb +116 -0
  14. data/integration/clone_lib_tests.rb +108 -0
  15. data/integration/comparison_tests.rb +132 -0
  16. data/integration/compile_lib_tests.rb +190 -0
  17. data/integration/ctrl_struct_lib_tests.rb +80 -0
  18. data/integration/data_ref_lib_tests.rb +43 -0
  19. data/integration/exception_lib_tests.rb +86 -0
  20. data/integration/fiber_bundle_tests.rb +380 -0
  21. data/integration/hash_lib_tests.rb +120 -0
  22. data/integration/in_stream_test_1.txt +4 -0
  23. data/integration/load_test_one.foorth +6 -0
  24. data/integration/load_test_two.foorth +4 -0
  25. data/integration/numeric_lib_tests.rb +321 -0
  26. data/integration/object_lib_tests.rb +38 -0
  27. data/integration/procedure_lib_tests.rb +40 -0
  28. data/integration/queue_lib_tests.rb +66 -0
  29. data/integration/stack_lib_tests.rb +70 -0
  30. data/integration/standard_lib_tests.rb +208 -0
  31. data/integration/stdio_lib_tests.rb +52 -0
  32. data/integration/stream_lib_tests.rb +196 -0
  33. data/integration/string_lib_tests.rb +217 -0
  34. data/integration/support/foorth_testing.rb +135 -0
  35. data/integration/thread_lib_tests.rb +83 -0
  36. data/integration/time_lib_tests.rb +791 -0
  37. data/integration/vm_lib_tests.rb +38 -0
  38. data/lib/fOOrth.rb +57 -0
  39. data/lib/fOOrth/compiler.rb +78 -0
  40. data/lib/fOOrth/compiler/context.rb +49 -0
  41. data/lib/fOOrth/compiler/context/locals.rb +34 -0
  42. data/lib/fOOrth/compiler/context/map_name.rb +92 -0
  43. data/lib/fOOrth/compiler/context/tags.rb +48 -0
  44. data/lib/fOOrth/compiler/modes.rb +32 -0
  45. data/lib/fOOrth/compiler/modes/compiled.rb +41 -0
  46. data/lib/fOOrth/compiler/modes/deferred.rb +57 -0
  47. data/lib/fOOrth/compiler/modes/delayed.rb +40 -0
  48. data/lib/fOOrth/compiler/modes/nested.rb +34 -0
  49. data/lib/fOOrth/compiler/modes/suspend.rb +32 -0
  50. data/lib/fOOrth/compiler/parser.rb +26 -0
  51. data/lib/fOOrth/compiler/parser/get_string.rb +71 -0
  52. data/lib/fOOrth/compiler/parser/normal.rb +53 -0
  53. data/lib/fOOrth/compiler/parser/skip.rb +50 -0
  54. data/lib/fOOrth/compiler/parser/special.rb +42 -0
  55. data/lib/fOOrth/compiler/process.rb +47 -0
  56. data/lib/fOOrth/compiler/process/generate.rb +24 -0
  57. data/lib/fOOrth/compiler/process/get_token.rb +23 -0
  58. data/lib/fOOrth/compiler/process/procedure.rb +55 -0
  59. data/lib/fOOrth/compiler/process/string.rb +20 -0
  60. data/lib/fOOrth/compiler/source.rb +51 -0
  61. data/lib/fOOrth/compiler/source/console.rb +70 -0
  62. data/lib/fOOrth/compiler/source/file_source.rb +37 -0
  63. data/lib/fOOrth/compiler/source/read_point.rb +46 -0
  64. data/lib/fOOrth/compiler/source/string_source.rb +28 -0
  65. data/lib/fOOrth/compiler/token.rb +37 -0
  66. data/lib/fOOrth/compiler/word_specs.rb +178 -0
  67. data/lib/fOOrth/core.rb +27 -0
  68. data/lib/fOOrth/core/class.rb +116 -0
  69. data/lib/fOOrth/core/object.rb +78 -0
  70. data/lib/fOOrth/core/virtual_machine.rb +28 -0
  71. data/lib/fOOrth/debug.rb +13 -0
  72. data/lib/fOOrth/debug/context_dump.rb +31 -0
  73. data/lib/fOOrth/debug/dbg_puts.rb +17 -0
  74. data/lib/fOOrth/debug/display_abort.rb +37 -0
  75. data/lib/fOOrth/debug/vm_dump.rb +27 -0
  76. data/lib/fOOrth/initialize.rb +83 -0
  77. data/lib/fOOrth/interpreter.rb +24 -0
  78. data/lib/fOOrth/interpreter/add_to_hash.rb +17 -0
  79. data/lib/fOOrth/interpreter/data_stack.rb +125 -0
  80. data/lib/fOOrth/interpreter/do_loop.rb +55 -0
  81. data/lib/fOOrth/interpreter/squash.rb +25 -0
  82. data/lib/fOOrth/library.rb +38 -0
  83. data/lib/fOOrth/library/array_library.rb +577 -0
  84. data/lib/fOOrth/library/bundle_library.rb +112 -0
  85. data/lib/fOOrth/library/class_library.rb +90 -0
  86. data/lib/fOOrth/library/clone_library.rb +72 -0
  87. data/lib/fOOrth/library/command_library.rb +205 -0
  88. data/lib/fOOrth/library/compile_library.rb +181 -0
  89. data/lib/fOOrth/library/complex_library.rb +81 -0
  90. data/lib/fOOrth/library/ctrl_struct_library.rb +116 -0
  91. data/lib/fOOrth/library/data_ref_library.rb +100 -0
  92. data/lib/fOOrth/library/duration/arithmetic.rb +114 -0
  93. data/lib/fOOrth/library/duration/formatter.rb +152 -0
  94. data/lib/fOOrth/library/duration/intervals.rb +233 -0
  95. data/lib/fOOrth/library/duration/make.rb +75 -0
  96. data/lib/fOOrth/library/duration_library.rb +52 -0
  97. data/lib/fOOrth/library/fiber_library.rb +120 -0
  98. data/lib/fOOrth/library/hash_library.rb +203 -0
  99. data/lib/fOOrth/library/in_stream_library.rb +81 -0
  100. data/lib/fOOrth/library/integer_library.rb +104 -0
  101. data/lib/fOOrth/library/mutex_library.rb +31 -0
  102. data/lib/fOOrth/library/numeric_library.rb +380 -0
  103. data/lib/fOOrth/library/object_library.rb +80 -0
  104. data/lib/fOOrth/library/other_value_types_library.rb +96 -0
  105. data/lib/fOOrth/library/out_stream_library.rb +146 -0
  106. data/lib/fOOrth/library/procedure_library.rb +65 -0
  107. data/lib/fOOrth/library/queue_library.rb +47 -0
  108. data/lib/fOOrth/library/rational_library.rb +90 -0
  109. data/lib/fOOrth/library/stack_library.rb +56 -0
  110. data/lib/fOOrth/library/stdio_library.rb +56 -0
  111. data/lib/fOOrth/library/string_library.rb +285 -0
  112. data/lib/fOOrth/library/stubs.rb +76 -0
  113. data/lib/fOOrth/library/sync_bundle_library.rb +50 -0
  114. data/lib/fOOrth/library/thread_library.rb +73 -0
  115. data/lib/fOOrth/library/time_library.rb +302 -0
  116. data/lib/fOOrth/library/vm_library.rb +105 -0
  117. data/lib/fOOrth/main.rb +125 -0
  118. data/lib/fOOrth/monkey_patch.rb +14 -0
  119. data/lib/fOOrth/monkey_patch/complex.rb +30 -0
  120. data/lib/fOOrth/monkey_patch/exceptions.rb +154 -0
  121. data/lib/fOOrth/monkey_patch/false.rb +11 -0
  122. data/lib/fOOrth/monkey_patch/float.rb +22 -0
  123. data/lib/fOOrth/monkey_patch/integer.rb +22 -0
  124. data/lib/fOOrth/monkey_patch/nil.rb +11 -0
  125. data/lib/fOOrth/monkey_patch/numeric.rb +33 -0
  126. data/lib/fOOrth/monkey_patch/object.rb +43 -0
  127. data/lib/fOOrth/monkey_patch/rational.rb +31 -0
  128. data/lib/fOOrth/monkey_patch/string.rb +51 -0
  129. data/lib/fOOrth/symbol_map.rb +82 -0
  130. data/lib/fOOrth/version.rb +7 -0
  131. data/license.txt +21 -0
  132. data/rakefile.rb +65 -0
  133. data/reek.txt +1 -0
  134. data/sire.rb +132 -0
  135. data/t.txt +3 -0
  136. data/test.foorth +5 -0
  137. data/tests/compiler/context_tests.rb +180 -0
  138. data/tests/compiler/file_source_test_one.txt +1 -0
  139. data/tests/compiler/file_source_test_three.txt +3 -0
  140. data/tests/compiler/file_source_test_two.txt +3 -0
  141. data/tests/compiler/file_source_tests.rb +130 -0
  142. data/tests/compiler/mode_tests.rb +45 -0
  143. data/tests/compiler/parser_tests.rb +116 -0
  144. data/tests/compiler/spec_tests.rb +113 -0
  145. data/tests/compiler/string_source_tests.rb +128 -0
  146. data/tests/core_tests.rb +138 -0
  147. data/tests/interpreter/data_stack_tests.rb +119 -0
  148. data/tests/monkey_patch/coerce_test.rb +131 -0
  149. data/tests/monkey_patch/complex_test.rb +25 -0
  150. data/tests/monkey_patch/numeric_test.rb +62 -0
  151. data/tests/monkey_patch/object_test.rb +49 -0
  152. data/tests/monkey_patch/rational_test.rb +57 -0
  153. data/tests/monkey_patch/string_test.rb +53 -0
  154. data/tests/symbol_map_tests.rb +53 -0
  155. metadata +366 -0
@@ -0,0 +1,196 @@
1
+ # coding: utf-8
2
+
3
+ require_relative '../lib/fOOrth'
4
+ require_relative 'support/foorth_testing'
5
+ gem 'minitest'
6
+ require 'minitest/autorun'
7
+ require 'minitest_visible'
8
+
9
+ #Test the standard fOOrth library.
10
+ class InOutStreamLibraryTester < Minitest::Test
11
+
12
+ include XfOOrthTestExtensions
13
+
14
+ #Track mini-test progress.
15
+ include MinitestVisible
16
+
17
+ # **** In Streams ****
18
+
19
+ $isfn = '"integration/in_stream_test_1.txt" '
20
+
21
+ def test_that_class_exists
22
+ foorth_equal('InStream', [XfOOrth::XfOOrth_InStream])
23
+ foorth_equal('InStream .name', ['InStream'])
24
+ end
25
+
26
+ def test_that_new_is_a_stub
27
+ foorth_raises('InStream .new')
28
+ end
29
+
30
+ def test_opening_and_reading_a_character
31
+ foorth_equal($isfn + 'InStream .open dup .getc swap .close', ['T'])
32
+ end
33
+
34
+ def test_opening_and_reading_a_line
35
+ foorth_equal($isfn + 'InStream .open dup .gets swap .close', ['Test 1 2 3'])
36
+ end
37
+
38
+ def test_open_block_and_reading_a_character
39
+ foorth_equal($isfn + 'InStream .open{{ ~getc }}', ['T'])
40
+ end
41
+
42
+ def test_open_block_and_reading_a_line
43
+ foorth_equal($isfn + 'InStream .open{{ ~gets }}', ['Test 1 2 3'])
44
+ end
45
+
46
+ def test_opening_and_reading_all_lines
47
+ all_lines = ["Test 1 2 3",
48
+ "Test 4 5 6",
49
+ "ABCDEFG",
50
+ "Eric the Half a Bee"]
51
+
52
+ foorth_equal($isfn + 'InStream .get_all', [all_lines])
53
+ end
54
+
55
+ # **** Out Streams ****
56
+
57
+ $osfn = '"integration/out_stream_test_1.txt" '
58
+
59
+ def test_that_class_exists
60
+ foorth_equal('OutStream', [XfOOrth::XfOOrth_OutStream])
61
+ foorth_equal('OutStream .name', ['OutStream'])
62
+ end
63
+
64
+ def test_that_new_is_a_stub
65
+ foorth_raises('OutStream .new')
66
+ end
67
+
68
+
69
+ def test_that_we_can_write
70
+ foorth_equal($osfn + 'OutStream .create .close')
71
+ assert(File.exists?($osfn[1...-2]))
72
+ do_cleanup
73
+ end
74
+
75
+ def test_that_we_can_write_block
76
+ foorth_equal($osfn + 'OutStream .create{{ }}')
77
+ assert(File.exists?($osfn[1...-2]))
78
+ do_cleanup
79
+ end
80
+
81
+
82
+ def test_that_we_can_write_stuff
83
+ foorth_equal($osfn + 'OutStream .create dup 42 swap . .close')
84
+ assert_equal(["42"], IO.readlines($osfn[1...-2]))
85
+ do_cleanup
86
+ end
87
+
88
+ def test_that_we_can_write_block_stuff
89
+ foorth_equal($osfn + 'OutStream .create{{ 42 ~ }}')
90
+ assert_equal(["42"], IO.readlines($osfn[1...-2]))
91
+ do_cleanup
92
+ end
93
+
94
+
95
+ def test_that_we_can_write_stuff_too
96
+ foorth_run($osfn + 'OutStream .create dup .with{{ ~"Hello World" }} .close')
97
+ assert_equal(["Hello World"], IO.readlines($osfn[1...-2]))
98
+ do_cleanup
99
+ end
100
+
101
+ def test_that_we_can_write_block_stuff_too
102
+ foorth_equal($osfn + 'OutStream .create{{ ~"Hello World" }}')
103
+ assert_equal(["Hello World"], IO.readlines($osfn[1...-2]))
104
+ do_cleanup
105
+ end
106
+
107
+
108
+ def test_that_we_can_write_a_character
109
+ foorth_equal($osfn + 'OutStream .create 65 over .emit .close')
110
+ assert_equal(["A"], IO.readlines($osfn[1...-2]))
111
+ do_cleanup
112
+ end
113
+
114
+ def test_that_we_can_write_block_a_character
115
+ foorth_equal($osfn + 'OutStream .create{{ 65 ~emit }}')
116
+ assert_equal(["A"], IO.readlines($osfn[1...-2]))
117
+ do_cleanup
118
+ end
119
+
120
+
121
+ def test_that_we_can_write_out_lines
122
+ foorth_run($osfn + 'OutStream .create .with{{ ~"Hello" ~cr ~"World" self .close }}')
123
+ assert_equal(["Hello\n", "World"], IO.readlines($osfn[1...-2]))
124
+ do_cleanup
125
+ end
126
+
127
+ def test_that_we_can_block_write_out_lines
128
+ foorth_equal($osfn + 'OutStream .create{{ ~"Hello" ~cr ~"World" }}', [])
129
+ assert_equal(["Hello\n", "World"], IO.readlines($osfn[1...-2]))
130
+ do_cleanup
131
+ end
132
+
133
+
134
+ def test_that_we_can_write_out_a_space
135
+ foorth_run($osfn + 'OutStream .create .with{{ ~"Hello" self .space ~"World" self .close }}')
136
+ assert_equal(["Hello World"], IO.readlines($osfn[1...-2]))
137
+ do_cleanup
138
+ end
139
+
140
+ def test_that_we_can_block_write_out_a_space
141
+ foorth_equal($osfn + 'OutStream .create{{ ~"Hello" ~space ~"World" }}', [])
142
+ assert_equal(["Hello World"], IO.readlines($osfn[1...-2]))
143
+ do_cleanup
144
+ end
145
+
146
+
147
+ def test_that_we_can_write_out_spaces
148
+ foorth_run($osfn + 'OutStream .create .with{{ ~"Hello" 3 self .spaces ~"World" self .close }}')
149
+ assert_equal(["Hello World"], IO.readlines($osfn[1...-2]))
150
+ do_cleanup
151
+ end
152
+
153
+ def test_that_we_can_block_write_out_spaces
154
+ foorth_equal($osfn + 'OutStream .create{{ ~"Hello" 3 ~spaces ~"World" }}', [])
155
+ assert_equal(["Hello World"], IO.readlines($osfn[1...-2]))
156
+ do_cleanup
157
+ end
158
+
159
+
160
+ def test_that_we_can_append_a_character
161
+ foorth_equal($osfn + 'OutStream .create 65 over .emit .close')
162
+ assert_equal(["A"], IO.readlines($osfn[1...-2]))
163
+
164
+ foorth_equal($osfn + 'OutStream .append 66 over .emit .close')
165
+ assert_equal(["AB"], IO.readlines($osfn[1...-2]))
166
+
167
+ do_cleanup
168
+ end
169
+
170
+ def test_that_we_can_block_append_a_character
171
+ foorth_equal($osfn + 'OutStream .create 65 over .emit .close')
172
+ assert_equal(["A"], IO.readlines($osfn[1...-2]))
173
+
174
+ foorth_equal($osfn + 'OutStream .append{{ 66 ~emit }} ')
175
+ assert_equal(["AB"], IO.readlines($osfn[1...-2]))
176
+
177
+ do_cleanup
178
+ end
179
+
180
+ def test_put_and_append_all
181
+ foorth_equal('[ "A" "B" "C" ] ' + $osfn + 'OutStream .put_all')
182
+ assert_equal(["A\n", "B\n", "C\n"], IO.readlines($osfn[1...-2]))
183
+
184
+ foorth_equal('[ "D" "E" "F" ] ' + $osfn + 'OutStream .append_all')
185
+ assert_equal(["A\n", "B\n", "C\n", "D\n", "E\n", "F\n"], IO.readlines($osfn[1...-2]))
186
+
187
+ do_cleanup
188
+ end
189
+
190
+
191
+ def do_cleanup
192
+ name = $osfn[1...-2]
193
+ system("rm #{name}")
194
+ end
195
+
196
+ end
@@ -0,0 +1,217 @@
1
+ # coding: utf-8
2
+
3
+ require_relative '../lib/fOOrth'
4
+ require_relative 'support/foorth_testing'
5
+ gem 'minitest'
6
+ require 'minitest/autorun'
7
+ require 'minitest_visible'
8
+
9
+ #Test the standard fOOrth library.
10
+ class StringLibraryTester < Minitest::Test
11
+
12
+ include XfOOrthTestExtensions
13
+
14
+ #Track mini-test progress.
15
+ include MinitestVisible
16
+
17
+ def test_string_literals
18
+ foorth_equal(' "" ', [""])
19
+ foorth_equal(' "\"" ', ["\""])
20
+ foorth_equal(' "\"hello\"" ', ["\"hello\""])
21
+ foorth_equal(' "abc" ', ["abc"])
22
+ foorth_equal(' "a\\\\c" ', ["a\\c"])
23
+ foorth_equal(' "a\\nb" ', ["a\nb"])
24
+
25
+ test_src1 = <<-'ONE'
26
+ "abc\
27
+ def"
28
+ ONE
29
+
30
+ assert_equal(" \"abc\\\n def\"\n", test_src1)
31
+ foorth_equal(test_src1, ["abcdef"])
32
+
33
+ test_src2 = <<-'TWO'
34
+ "abc
35
+ TWO
36
+
37
+ assert_equal(" \"abc\n", test_src2)
38
+ foorth_equal(test_src2, ["abc"])
39
+
40
+ foorth_equal(' "a\\x55b" ', ["aUb"])
41
+ foorth_equal(' "a\\u5555b" ', ["a\u5555b"])
42
+ end
43
+
44
+ def test_file_loading
45
+ foorth_equal('"integration/load_test_one.foorth" .load ', [42])
46
+ foorth_equal('4 double ', [8])
47
+ foorth_equal('"integration/load_test_one" .load ', [42])
48
+
49
+ foorth_equal('load"integration/load_test_one.foorth"', [42])
50
+ foorth_equal('load"integration/load_test_one"', [42])
51
+
52
+ #foorth_equal(')load"integration/load_test_one.foorth"', [42])
53
+ #foorth_equal(')load"integration/load_test_one"', [42])
54
+ end
55
+
56
+ def test_split_strings
57
+ foorth_equal('load"integration/load_test_two"', ["foo "])
58
+ end
59
+
60
+ def test_for_lines
61
+ foorth_equal(' "abc\\ndef\\n123" .lines ', [["abc", "def", "123"]])
62
+ end
63
+
64
+ def test_for_split
65
+ foorth_equal(' "abc def 123" .split ', [["abc", "def", "123"]])
66
+ end
67
+
68
+ def test_for_call
69
+ foorth_equal(' " 5 " .call ', [5])
70
+ end
71
+
72
+ def test_some_string_basics
73
+ foorth_equal('String .new', [""])
74
+ foorth_equal('"abcdefg" .length ', [7])
75
+ end
76
+
77
+ def test_left_justification
78
+ foorth_equal('5 "a" .ljust ', ['a '])
79
+ foorth_equal('5 "too long" .ljust ', ['too long'])
80
+ end
81
+
82
+ def test_center_justification
83
+ foorth_equal('5 "a" .cjust ', [' a '])
84
+ foorth_equal('5 "too long" .cjust ', ['too long'])
85
+ end
86
+
87
+ def test_right_justification
88
+ foorth_equal('5 "a" .rjust ', [' a'])
89
+ foorth_equal('5 "too long" .rjust ', ['too long'])
90
+ end
91
+
92
+ def test_left_strip
93
+ foorth_equal('" a " .lstrip ', ["a "])
94
+ end
95
+
96
+ def test_center_strip
97
+ foorth_equal('" a " .strip ', ["a"])
98
+ end
99
+
100
+ def test_right_strip
101
+ foorth_equal('" a " .rstrip ', [" a"])
102
+ end
103
+
104
+ def test_formatted_strings
105
+ foorth_equal('5 "%03d" format ', ['005'])
106
+ foorth_equal('5 f"%03d" ', ['005'])
107
+ end
108
+
109
+ def test_left_copy_paste_and_cut
110
+ foorth_equal('2 "abcdefgh" .left ', ['ab'])
111
+ foorth_equal('2 "123" "abcdefgh" .+left ', ['123cdefgh'])
112
+ foorth_equal('2 "abcdefgh" .-left ', ['cdefgh'])
113
+ foorth_equal('"abc" "abcdefgh" .left? ', [true])
114
+ foorth_equal('"abx" "abcdefgh" .left? ', [false])
115
+ end
116
+
117
+ def test_right_copy_paste_and_cut
118
+ foorth_equal('2 "abcdefgh" .right ', ['gh'])
119
+ foorth_equal('2 "123" "abcdefgh" .+right ', ['abcdef123'])
120
+ foorth_equal('2 "abcdefgh" .-right ', ['abcdef'])
121
+ foorth_equal('"fgh" "abcdefgh" .right? ', [true])
122
+ foorth_equal('"fgx" "abcdefgh" .right? ', [false])
123
+ end
124
+
125
+ def test_mid_copy_paste_and_cut
126
+ foorth_equal('2 4 "abcdefgh" .mid ', ['cdef'])
127
+ foorth_equal('2 4 "abcdefgh" .-mid ', ['abgh'])
128
+ foorth_equal('2 4 "123" "abcdefgh" .+mid ', ['ab123gh'])
129
+ foorth_equal('2 0 "123" "abcdefgh" .+mid ', ['ab123cdefgh'])
130
+ end
131
+
132
+ def test_mid_find
133
+ foorth_equal('2 "cde" "abcdefgh" .mid? ', [true])
134
+ foorth_equal('3 "cde" "abcdefgh" .mid? ', [false])
135
+ end
136
+
137
+ def test_midlr_copy_paste_and_cut
138
+ foorth_equal('2 2 "abcdefgh" .midlr ', ['cdef'])
139
+ foorth_equal('2 2 "abcdefgh" .-midlr ', ['abgh'])
140
+ foorth_equal('2 2 "123" "abcdefgh" .+midlr ', ['ab123gh'])
141
+ end
142
+
143
+ def test_string_contains
144
+ foorth_equal('"cde" "abcdefgh" .contains? ', [true])
145
+ foorth_equal('"cdx" "abcdefgh" .contains? ', [false])
146
+ end
147
+
148
+ def test_string_posn
149
+ foorth_equal('"cde" "abcdefgh" .posn ', [2])
150
+ foorth_equal('"cdx" "abcdefgh" .posn ', [nil])
151
+ end
152
+
153
+ def test_replication
154
+ foorth_equal('"abc" 0 *', [''])
155
+ foorth_equal('"abc" 1 *', ['abc'])
156
+ foorth_equal('"abc" 2 *', ['abcabc'])
157
+ foorth_equal('"abc" 3 *', ['abcabcabc'])
158
+ end
159
+
160
+ def test_concatenation
161
+ foorth_equal('"abc" 0 +', ['abc0'])
162
+ foorth_equal('"abc" "def" + ', ['abcdef'])
163
+
164
+ foorth_equal('"abc" 0 <<', ['abc0'])
165
+ foorth_equal('"abc" "def" << ', ['abcdef'])
166
+
167
+ foorth_equal('"abc" dup "def" + distinct?', [true])
168
+ foorth_equal('"abc" dup "def" << distinct?', [false])
169
+ end
170
+
171
+ def test_case_changing
172
+ foorth_equal('"abcDEF" .to_upper', ['ABCDEF'])
173
+ foorth_equal('"abcDEF" .to_lower', ['abcdef'])
174
+ end
175
+
176
+ def test_reversing
177
+ foorth_equal('"stressed" .reverse', ['desserts'])
178
+ end
179
+
180
+ def test_the_each
181
+ foorth_equal('"abc" .each{{ v x 1+ * }} ', ['a', 'bb', 'ccc'])
182
+ end
183
+
184
+ def test_calling_a_string
185
+ foorth_equal('"1 2 +" .call ', [3])
186
+ end
187
+
188
+ def test_capturing_shell_output
189
+ foorth_equal('"ls" .shell_out .class ', [String])
190
+ end
191
+
192
+ def test_parsing_some_strings
193
+ foorth_equal('"1 2 3" p"%d %d %d"', [[1,2,3]])
194
+ foorth_equal('"1 2 3" "%d %d %d" parse', [[1,2,3]])
195
+
196
+ foorth_equal('"12 34 -56" p"%d %2d %4d"', [[12, 34, -56]])
197
+ foorth_equal('"255 0b11111111 0377 0xFF 0 " p"%i %i %i %i %i"', [[255, 255, 255, 255, 0]])
198
+ foorth_equal('"7 10 377" p"%o %o %o"', [[7, 8, 255]])
199
+ foorth_equal('"10 10011 11110000" p"%b %b %b"',[[2, 19, 240]])
200
+ foorth_equal('"0 F FF FFF FFFF" p"%x %x %x %x %x"', [[0, 15, 255, 4095, 65535]])
201
+ foorth_equal('"Hello Silly World" p"%s %*s %s"', [["Hello", "World"]])
202
+ foorth_equal('"Hello Silly World" p"%5c %*5c %5c"', [["Hello", "World"]])
203
+ foorth_equal('"42 The secret is X" p"%i %-1c"', [[42, "The secret is X"]])
204
+ foorth_equal('"42 The secret is X" p"%i %-2c%c"', [[42, "The secret is ", "X"]])
205
+ foorth_equal('"42 The secret is X" p"%i %*-2c%c"', [[42, "X"]])
206
+ foorth_equal('"9.99 1.234e56 -1e100" p"%f %f %f"', [[9.99, 1.234e56, -1e100]])
207
+ foorth_equal('"85% 75%" p"%f%% %f%%"', [[85, 75]])
208
+ foorth_equal('"12 34 -56" p"%u %u %u"', [[12, 34]])
209
+ foorth_equal('"1/2 3/4r -5/6" p"%r %r %r"', [['1/2'.to_r, '3/4'.to_r, '-5/6'.to_r]])
210
+ foorth_equal('"1+2i 3+4j -5e10-6.2i" p"%j %j %j"',
211
+ [[Complex('1+2i'), Complex('3+4j'), Complex('-5e10-6.2i')]])
212
+ s = "\"'quote' 'silly' \\\"un quote\\\" 'a \\\\'' \" p\"%q %*q %q %q\" "
213
+ foorth_equal(s, [["quote", "un quote", "a '"]])
214
+ foorth_equal('"a b c" p"%[a] %[b] %[c]"', [["a", "b", "c"]])
215
+ end
216
+
217
+ end
@@ -0,0 +1,135 @@
1
+ # coding: utf-8
2
+
3
+ #A small group of extensions to facilitate testing in fOOrth.
4
+ module XfOOrthTestExtensions
5
+
6
+ #When the source is executed, does it raise err?
7
+ #<br>Parameters:
8
+ #* source - A string containing fOOrth source code to execute.
9
+ #* err - The type of exception expected during execution.
10
+ #* debug - Set to true to display debug info.
11
+ def foorth_run(source, debug=false)
12
+ vm = Thread.current[:vm]
13
+ vm.debug = debug
14
+ vm.process_string(source)
15
+ ensure
16
+ vm.debug = false
17
+ vm.interpreter_reset
18
+ vm.compiler_reset
19
+ end
20
+
21
+ #When the source is executed, is the stack as expected?
22
+ #<br>Parameters:
23
+ #* source - A string containing fOOrth source code to execute.
24
+ #* remainder - An array with the expected stack contents after execution.
25
+ #* debug - Set to true to display debug info.
26
+ def foorth_equal(source, remainder=[], debug=false)
27
+ self.assertions += 1
28
+ vm = Thread.current[:vm]
29
+ vm.debug = debug
30
+ vm.process_string(source)
31
+
32
+ unless remainder == vm.data_stack
33
+ msg = "Expected: #{remainder.inspect}\n Actual: #{vm.data_stack.inspect}"
34
+ raise MiniTest::Assertion, msg, caller
35
+ end
36
+ ensure
37
+ vm.debug = false
38
+ vm.interpreter_reset
39
+ vm.compiler_reset
40
+ end
41
+
42
+ #When the source is executed, does it raise err?
43
+ #<br>Parameters:
44
+ #* source - A string containing fOOrth source code to execute.
45
+ #* err - The type of exception expected during execution.
46
+ #* debug - Set to true to display debug info.
47
+ def foorth_raises(source, err=XfOOrth::XfOOrthError, debug=false)
48
+ self.assertions += 1
49
+ vm = Thread.current[:vm]
50
+ vm.debug = debug
51
+ failed, msg = false, ""
52
+
53
+ begin
54
+ vm.process_string(source)
55
+ msg = "Expected: #{err}\n Actual: No exception raised."
56
+ failed = true
57
+
58
+ rescue Exception => e
59
+ unless e.class == err
60
+ msg = "Expected: #{err}\n Actual: #{e.class}"
61
+ failed = true
62
+ end
63
+ end
64
+
65
+ raise MiniTest::Assertion, msg, caller if failed
66
+
67
+ ensure
68
+ vm.debug = false
69
+ vm.interpreter_reset
70
+ vm.compiler_reset
71
+ end
72
+
73
+ #When the source is executed, does the stdout match?
74
+ #<br>Parameters:
75
+ #* source - A string containing fOOrth source code to execute.
76
+ #* expected - A string with the expected console output.
77
+ def foorth_output(source, expected)
78
+ self.assertions += 1
79
+ failed, msg = false, ""
80
+ vm = Thread.current[:vm]
81
+
82
+ actual, _nc = capture_io do
83
+ vm.process_string(source)
84
+ end
85
+
86
+ if expected != actual
87
+ msg = "Expected: #{expected.inspect}\n Actual: #{actual.inspect}"
88
+ raise MiniTest::Assertion, msg, caller
89
+ end
90
+
91
+ ensure
92
+ vm.interpreter_reset
93
+ vm.compiler_reset
94
+ end
95
+
96
+ #Copied here for study
97
+ def capture_foorth_io
98
+ require 'stringio'
99
+
100
+ orig_stdout = $stdout
101
+
102
+ (s_o = StringIO.new).set_encoding 'UTF-8'
103
+ captured_stdout = s_o
104
+ $stdout = captured_stdout
105
+
106
+ yield
107
+
108
+ return captured_stdout.string.bytes.to_a
109
+ ensure
110
+ $stdout = orig_stdout
111
+ end
112
+
113
+ #When the source is executed, does the stdout match? Forces UTF-8 encoding.
114
+ #<br>Parameters:
115
+ #* source - A string containing fOOrth source code to execute.
116
+ #* expected - An array of bytes expected for the console.
117
+ def foorth_utf8_output(source, expected)
118
+ self.assertions += 1
119
+ vm = Thread.current[:vm]
120
+
121
+ actual = capture_foorth_io do
122
+ vm.process_string(source)
123
+ end
124
+
125
+ if expected != actual
126
+ msg = "Expected: #{expected.inspect}\n Actual: #{actual.inspect}"
127
+ raise MiniTest::Assertion, msg, caller
128
+ end
129
+
130
+ ensure
131
+ vm.interpreter_reset
132
+ vm.compiler_reset
133
+ end
134
+
135
+ end