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,50 @@
1
+ # coding: utf-8
2
+
3
+ #* library/sync_bundle_library.rb - The fOOrth SyncBundle class library.
4
+ module XfOOrth
5
+
6
+ #Define the SyncBundle class.
7
+ XfOOrth_Bundle.create_foorth_subclass('SyncBundle').new_class
8
+
9
+ #The fOOrth Synchronized Bundle class. A bundle contains multiple fibers.
10
+ class XfOOrth_SyncBundle < XfOOrth_Bundle
11
+
12
+ #Build up the synchronized bundle instance
13
+ def initialize(fibers=[])
14
+ @sync = Mutex.new
15
+ super(fibers)
16
+ end
17
+
18
+ #Add the fibers to this bundle.
19
+ def add_fibers(fibers)
20
+ @sync.synchronize{super(fibers)}
21
+ end
22
+
23
+ #What is the status of this bundle?
24
+ def status
25
+ @sync.synchronize{super}
26
+ end
27
+
28
+ #how many fibers in this bundle?
29
+ def length
30
+ @sync.synchronize{super}
31
+ end
32
+
33
+ #Let the fiber run for one step
34
+ def step(vm)
35
+ @sync.synchronize{super(vm)}
36
+ end
37
+
38
+ end
39
+
40
+ #[an_array_of_procs_fibers_or_bundles] .to_bundle [a_sync_bundle]
41
+ Array.create_shared_method('.to_sync_bundle', TosSpec, [], &lambda{|vm|
42
+ vm.push(XfOOrth_SyncBundle.new(self))
43
+ })
44
+
45
+ #[a_proc] .to_bundle [a_bundle]
46
+ Proc.create_shared_method('.to_sync_bundle', TosSpec, [], &lambda{|vm|
47
+ vm.push(XfOOrth_SyncBundle.new(self))
48
+ })
49
+
50
+ end
@@ -0,0 +1,73 @@
1
+ # coding: utf-8
2
+
3
+ #* library/thread_library.rb - The thread support fOOrth library.
4
+ module XfOOrth
5
+
6
+ #Connect the Thread class to the fOOrth class system.
7
+ Thread.create_foorth_proxy
8
+
9
+ #Class Methods
10
+
11
+ Thread.create_exclusive_method('.new', TosSpec, [:stub])
12
+
13
+ # [name Thread] .new{{ ... }} [a_thread]
14
+ Thread.create_exclusive_method('.new{{', NosSpec, [], &lambda {|vm|
15
+ block = vm.pop
16
+ name = vm.pop.to_s
17
+ vm.push(block.do_thread_start(vm, name))
18
+ })
19
+
20
+ # [Thread] .current [the current thread]
21
+ Thread.create_exclusive_method('.current', TosSpec, [], &lambda {|vm|
22
+ vm.push(Thread.current)
23
+ })
24
+
25
+ # [Thread] .main [the main thread]
26
+ Thread.create_exclusive_method('.main', TosSpec, [], &lambda {|vm|
27
+ vm.push(Thread.main)
28
+ })
29
+
30
+ # [Thread] .list [[threads]]
31
+ Thread.create_exclusive_method('.list', TosSpec, [], &lambda {|vm|
32
+ vm.push(Thread.list)
33
+ })
34
+
35
+ #Instance Methods
36
+ # [a thread] .vm [the vm of the thread or nil]
37
+ Thread.create_shared_method('.vm', TosSpec, [], &lambda {|vm|
38
+ vm.push(self[:vm])
39
+ })
40
+
41
+ #Pause the current thread.
42
+ VirtualMachine.create_shared_method('pause', MacroSpec,
43
+ [:macro, 'Thread.pass; '])
44
+
45
+ #Put the current thread to sleep for the specified number of seconds.
46
+ Numeric.create_shared_method('.sleep', TosSpec, [], &lambda {|vm|
47
+ sleep(Float.foorth_coerce(self))
48
+ })
49
+
50
+ #Wait for a thread to finish.
51
+ #[a_thread] .join []
52
+ Thread.create_shared_method('.join', TosSpec, [], &lambda {|vm|
53
+ self.join
54
+ })
55
+
56
+ #Is the thread sill alive?
57
+ #[a_thread] .alive? [a_boolean]
58
+ Thread.create_shared_method('.alive?', TosSpec, [], &lambda {|vm|
59
+ vm.push(self.alive?)
60
+ })
61
+
62
+ #What is the status of this thread?
63
+ #[a_thread] .status ["a_status_string"]
64
+ Thread.create_shared_method('.status', TosSpec, [], &lambda {|vm|
65
+ vm.push(self.status || 'dead')
66
+ })
67
+
68
+ #Terminate the given thread.
69
+ Thread.create_shared_method('.exit', TosSpec, [], &lambda {|vm|
70
+ self.exit
71
+ })
72
+
73
+ end
@@ -0,0 +1,302 @@
1
+ # coding: utf-8
2
+
3
+ require 'time' # Get extended time support.
4
+
5
+ #* library/time_library.rb - The time support fOOrth library.
6
+ module XfOOrth
7
+
8
+ #Connect the Time class to the fOOrth class system
9
+ Time.create_foorth_proxy
10
+
11
+ #Class Methods
12
+
13
+ #Stub out .new
14
+ Time.create_exclusive_method('.new', TosSpec, [:stub])
15
+
16
+ # [] now [Time.now]
17
+ VirtualMachine.create_shared_method('now', MacroSpec,
18
+ [:macro, "vm.push(Time.now); "])
19
+
20
+ VirtualMachine.create_shared_method('local_offset', MacroSpec,
21
+ [:macro, "vm.push(Time.now.utc_offset); "])
22
+
23
+
24
+ #Instance Methods
25
+
26
+ #Helper Methods .to_t and .to_t!
27
+
28
+ #[object] .to_t [a_time]
29
+ Numeric.create_shared_method('.to_t', TosSpec, [], &lambda {|vm|
30
+ begin
31
+ vm.push(Time.at(self))
32
+ rescue
33
+ vm.push(nil)
34
+ end
35
+ })
36
+
37
+ Numeric.create_shared_method('.to_t!', TosSpec, [], &lambda {|vm|
38
+ begin
39
+ vm.push(Time.at(self))
40
+ rescue
41
+ error "F40: Cannot convert #{self.to_s} to a Time instance"
42
+ end
43
+ })
44
+
45
+ Complex.create_shared_method('.to_t', TosSpec, [:stub])
46
+ Complex.create_shared_method('.to_t!', TosSpec, [:stub])
47
+
48
+ String.create_shared_method('.to_t', TosSpec, [], &lambda {|vm|
49
+ begin
50
+ vm.push(Time.parse(self))
51
+ rescue
52
+ vm.push(nil)
53
+ end
54
+ })
55
+
56
+ String.create_shared_method('.to_t!', TosSpec, [], &lambda {|vm|
57
+ begin
58
+ vm.push(Time.parse(self))
59
+ rescue
60
+ error "F40: Cannot convert \"#{self.to_s}\" to a Time instance"
61
+ end
62
+ })
63
+
64
+ Time.create_shared_method('.to_t', TosSpec, [], &lambda {|vm|
65
+ vm.push(self.clone)
66
+ })
67
+
68
+ Time.create_shared_method('.to_t!', TosSpec, [], &lambda {|vm|
69
+ vm.push(self.clone)
70
+ })
71
+
72
+ Array.create_shared_method('.to_t', TosSpec, [], &lambda {|vm|
73
+ begin
74
+ vm.push(Time.new(*self))
75
+ rescue
76
+ vm.push(nil)
77
+ end
78
+ })
79
+
80
+ Array.create_shared_method('.to_t!', TosSpec, [], &lambda {|vm|
81
+ begin
82
+ vm.push(Time.new(*self))
83
+ rescue
84
+ error "F40: Cannot convert #{self.to_s} to a Time instance"
85
+ end
86
+ })
87
+
88
+
89
+ #Turn a Time value into an Array
90
+
91
+ #[time] .to_a [string]
92
+ Time.create_shared_method('.to_a', TosSpec, [], &lambda {|vm|
93
+ vm.push([self.year,
94
+ self.month,
95
+ self.day,
96
+ self.hour,
97
+ self.min,
98
+ self.sec + self.subsec.to_f,
99
+ self.utc_offset])
100
+ })
101
+
102
+
103
+ #Methods to access various attributes of a Time object.
104
+
105
+ Time.create_shared_method('.year', TosSpec, [], &lambda {|vm|
106
+ vm.push(self.year)
107
+ })
108
+
109
+ Time.create_shared_method('.month', TosSpec, [], &lambda {|vm|
110
+ vm.push(self.month)
111
+ })
112
+
113
+ Time.create_shared_method('.day', TosSpec, [], &lambda {|vm|
114
+ vm.push(self.day)
115
+ })
116
+
117
+ Time.create_shared_method('.hour', TosSpec, [], &lambda {|vm|
118
+ vm.push(self.hour)
119
+ })
120
+
121
+ Time.create_shared_method('.minute', TosSpec, [], &lambda {|vm|
122
+ vm.push(self.min)
123
+ })
124
+
125
+ Time.create_shared_method('.second', TosSpec, [], &lambda {|vm|
126
+ vm.push(self.sec)
127
+ })
128
+
129
+ Time.create_shared_method('.fraction', TosSpec, [], &lambda {|vm|
130
+ vm.push(self.subsec.to_f)
131
+ })
132
+
133
+ Time.create_shared_method('.sec_frac', TosSpec, [], &lambda {|vm|
134
+ vm.push(self.sec + self.subsec.to_f)
135
+ })
136
+
137
+ Time.create_shared_method('.offset', TosSpec, [], &lambda {|vm|
138
+ vm.push(self.utc_offset)
139
+ })
140
+
141
+
142
+ #Time zone control
143
+
144
+ #[a_time] .utc? [a boolean]
145
+ Time.create_shared_method('.utc?', TosSpec, [], &lambda {|vm|
146
+ vm.push(self.utc_offset == 0)
147
+ })
148
+
149
+ #[a_time] .as_utc [a_time]
150
+ Time.create_shared_method('.as_utc', TosSpec, [], &lambda {|vm|
151
+ vm.push(self.clone.localtime(0))
152
+ })
153
+
154
+ #[a_time] .as_local [a_time]
155
+ Time.create_shared_method('.as_local', TosSpec, [], &lambda {|vm|
156
+ vm.push(self.clone.localtime)
157
+ })
158
+
159
+ #[offset a_time] .as_zone [a_time]
160
+ Time.create_shared_method('.as_zone', TosSpec, [], &lambda {|vm|
161
+ offset = Integer.foorth_coerce(vm.pop)
162
+ vm.push(self.clone.localtime(offset))
163
+ })
164
+
165
+
166
+ #Turn Time values to/from strings
167
+
168
+ #[a_time] .time_s [string]
169
+ Time.create_shared_method('.time_s', TosSpec, [], &lambda {|vm|
170
+ vm.push(self.asctime)
171
+ })
172
+
173
+ format_action = lambda {|vm|
174
+ begin
175
+ vm.poke(self.strftime(vm.peek));
176
+ rescue
177
+ vm.data_stack.pop
178
+ raise
179
+ end
180
+ }
181
+
182
+ # [a_time a_string] format [a_string]
183
+ Time.create_shared_method('format', NosSpec, [], &format_action)
184
+
185
+ # [a_time] f"string" [a_string]
186
+ Time.create_shared_method('f"', NosSpec, [], &format_action)
187
+
188
+ parse_action = lambda do |vm|
189
+ fmt = vm.pop
190
+ src = vm.pop
191
+
192
+ begin
193
+ vm.push(Time.strptime(src, fmt));
194
+ rescue
195
+ vm.push(nil)
196
+ end
197
+ end
198
+
199
+ # [a_string Time a_string] parse [a_time or nil]
200
+ Time.create_exclusive_method('parse', NosSpec, [], &parse_action)
201
+
202
+ # [a_string Time] p"string" [a_time or nil]
203
+ Time.create_exclusive_method('p"', NosSpec, [], &parse_action)
204
+
205
+ parse_bang_action = lambda do |vm|
206
+ fmt = vm.pop
207
+ src = vm.pop
208
+
209
+ begin
210
+ vm.push(Time.strptime(src, fmt));
211
+ rescue
212
+ error "F40: Cannot parse \"#{src.to_s}\" into a Time instance"
213
+ end
214
+ end
215
+
216
+ # [a_string Time a_string] parse [a_time or nil]
217
+ Time.create_exclusive_method('parse!', NosSpec, [], &parse_bang_action)
218
+
219
+ # [a_string Time] p"str" [a_time or nil]
220
+ Time.create_exclusive_method('p!"', NosSpec, [], &parse_bang_action)
221
+
222
+
223
+ #Time comparison operations
224
+
225
+ Time.create_shared_method('>', NosSpec, [], &lambda {|vm|
226
+ begin
227
+ vm.poke(self.to_f > Float.foorth_coerce(vm.peek))
228
+ rescue
229
+ vm.data_stack.pop
230
+ raise
231
+ end
232
+ })
233
+
234
+ Time.create_shared_method('>=', NosSpec, [], &lambda {|vm|
235
+ begin
236
+ vm.poke(self.to_f >= Float.foorth_coerce(vm.peek))
237
+ rescue
238
+ vm.data_stack.pop
239
+ raise
240
+ end
241
+ })
242
+
243
+ Time.create_shared_method('<', NosSpec, [], &lambda {|vm|
244
+ begin
245
+ vm.poke(self.to_f < Float.foorth_coerce(vm.peek))
246
+ rescue
247
+ vm.data_stack.pop
248
+ raise
249
+ end
250
+ })
251
+
252
+ Time.create_shared_method('<=', NosSpec, [], &lambda {|vm|
253
+ begin
254
+ vm.poke(self.to_f <= Float.foorth_coerce(vm.peek))
255
+ rescue
256
+ vm.data_stack.pop
257
+ raise
258
+ end
259
+ })
260
+
261
+ Time.create_shared_method('<=>', NosSpec, [], &lambda {|vm|
262
+ begin
263
+ vm.poke(self.to_f <=> Float.foorth_coerce(vm.peek))
264
+ rescue
265
+ vm.data_stack.pop
266
+ raise
267
+ end
268
+ })
269
+
270
+ #Temporal mathematics, no Tardis required.
271
+
272
+ #[a_time a_float] + [a_time]
273
+ Time.create_shared_method('+', NosSpec, [], &lambda {|vm|
274
+ begin
275
+ other = vm.peek
276
+ vm.poke(self + other.to_foorth_r)
277
+ rescue TypeError
278
+ vm.data_stack.pop
279
+ error "F40: Unable to add a Time instance and a #{other.foorth_name}"
280
+ rescue
281
+ vm.data_stack.pop
282
+ raise
283
+ end
284
+ })
285
+
286
+ #[a_time a_float] - [a_time]
287
+ #[a_time a_time] - [a_float]
288
+ Time.create_shared_method('-', NosSpec, [], &lambda {|vm|
289
+ begin
290
+ other = vm.peek
291
+ result = self - (other.is_a?(Time) ? other : other.to_foorth_r)
292
+ vm.poke(result.is_a?(Time) ? result : Duration.new(result.rationalize))
293
+ rescue TypeError
294
+ vm.data_stack.pop
295
+ error "F40: Unable to subtract a Time instance and a #{other.foorth_name}"
296
+ rescue
297
+ vm.data_stack.pop
298
+ raise
299
+ end
300
+ })
301
+
302
+ end
@@ -0,0 +1,105 @@
1
+ # coding: utf-8
2
+
3
+ #* library/class_library.rb - The fOOrth Class class library.
4
+ module XfOOrth
5
+
6
+ #Get the VM as a string.
7
+ # [vm] .to_s ["vm as a string"]
8
+ VirtualMachine.create_shared_method('.to_s', TosSpec, [],
9
+ &lambda {|vm| vm.push(self.foorth_name)})
10
+
11
+ #Create a macro to get at the current virtual machine instance.
12
+ # [] vm [the_current_vm]
13
+ VirtualMachine.create_shared_method('vm', MacroSpec,
14
+ [:macro, "vm.push(vm); "])
15
+
16
+ # [vm] .vm_name ['name']
17
+ VirtualMachine.create_shared_method('.vm_name', TosSpec, [],
18
+ &lambda {|vm| vm.push(self.name); })
19
+
20
+ # [vm] .dump []
21
+ VirtualMachine.create_shared_method('.dump', TosSpec, [],
22
+ &lambda {|vm| self.debug_dump; })
23
+
24
+ # Some stack manipulation words.
25
+ # [a] drop []
26
+ VirtualMachine.create_shared_method('drop', MacroSpec,
27
+ [:macro, "vm.pop(); "])
28
+
29
+ # [a, b] 2drop []
30
+ VirtualMachine.create_shared_method('2drop', MacroSpec,
31
+ [:macro, "vm.popm(2); "])
32
+
33
+ # Some stack manipulation words.
34
+ # [unspecified] clear [];
35
+ VirtualMachine.create_shared_method('clear', VmSpec, [], &lambda {|vm|
36
+ vm.data_stack.clear
37
+ })
38
+
39
+ # [a] dup [a, a]
40
+ VirtualMachine.create_shared_method('dup', MacroSpec,
41
+ [:macro, "vm.push(vm.peek()); "])
42
+
43
+ # [a, b] 2dup [a, b, a, b]
44
+ VirtualMachine.create_shared_method('2dup', MacroSpec,
45
+ [:macro, "vm.push(vm.peek(2)); vm.push(vm.peek(2));"])
46
+
47
+ # [a] ?dup if a is true then [a,a] else [a]
48
+ VirtualMachine.create_shared_method('?dup', VmSpec, [],
49
+ &lambda {|vm| if peek?() then push(peek()); end; })
50
+
51
+ # [b,a] swap [a,b]
52
+ VirtualMachine.create_shared_method('swap', VmSpec, [],
53
+ &lambda {|vm| vb,va = popm(2); push(va); push(vb); })
54
+
55
+ # [c,b,a] rot [b,a,c]
56
+ VirtualMachine.create_shared_method('rot', VmSpec, [],
57
+ &lambda {|vm| vc,vb,va = popm(3); push(vb); push(va); push(vc); })
58
+
59
+ # [b,a] over [b,a,b]
60
+ VirtualMachine.create_shared_method('over', MacroSpec,
61
+ [:macro, "vm.push(vm.peek(2)); "])
62
+
63
+ # [di,..d2,d1,i] pick [di,..d2,d1,di]
64
+ VirtualMachine.create_shared_method('pick', MacroSpec,
65
+ [:macro, "vm.push(vm.peek(Integer.foorth_coerce(vm.pop()))); "])
66
+
67
+ # [b,a] nip [a]
68
+ VirtualMachine.create_shared_method('nip', MacroSpec,
69
+ [:macro, "vm.swap_pop(); "])
70
+
71
+ # [b,a] tuck [a,b,a]
72
+ VirtualMachine.create_shared_method('tuck', VmSpec, [],
73
+ &lambda {|vm| vb,va = popm(2); push(va); push(vb); push(va); })
74
+
75
+ #Get the VM timer start time.
76
+ #[] .start [start_time]
77
+ VirtualMachine.create_shared_method('.start_time', TosSpec, [], &lambda {|vm|
78
+ vm.push(vm.start_time)
79
+ })
80
+
81
+ #Reset the VM timer start time.
82
+ #[] .restart []
83
+ VirtualMachine.create_shared_method('.restart_timer', TosSpec, [], &lambda {|vm|
84
+ vm.start_time = Time.now
85
+ })
86
+
87
+ #Get the elapsed time.
88
+ #[] .elapsed [elapsed_time_in_seconds]
89
+ VirtualMachine.create_shared_method('.elapsed_time', TosSpec, [], &lambda {|vm|
90
+ vm.push(Time.now - vm.start_time)
91
+ })
92
+
93
+ #Get the name of the code source.
94
+ #[] _FILE_ [a_string]
95
+ VirtualMachine.create_shared_method('_FILE_', VmSpec, [:immediate], &lambda{|vm|
96
+ file_name = @parser.source.file_name
97
+
98
+ if execute_mode?
99
+ vm.push(file_name)
100
+ else
101
+ vm << "vm.push(#{file_name.inspect})"
102
+ end
103
+ })
104
+
105
+ end