fOOrth 0.5.0

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