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,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