fOOrth 0.6.10 → 0.6.11

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 (42) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +13 -2
  3. data/fOOrth.gemspec +2 -2
  4. data/integration/array_lib_tests.rb +10 -0
  5. data/integration/exception_lib_tests.rb +4 -0
  6. data/integration/hash_lib_tests.rb +9 -0
  7. data/integration/numeric_lib_tests.rb +326 -321
  8. data/integration/procedure_lib_tests.rb +16 -0
  9. data/integration/queue_lib_tests.rb +2 -1
  10. data/integration/stack_lib_tests.rb +2 -1
  11. data/integration/string_lib_tests.rb +11 -0
  12. data/integration/thread_lib_tests.rb +11 -8
  13. data/lib/fOOrth/compiler/context.rb +64 -64
  14. data/lib/fOOrth/compiler/context/locals.rb +34 -34
  15. data/lib/fOOrth/compiler/context/map_name.rb +85 -85
  16. data/lib/fOOrth/compiler/context/tags.rb +60 -48
  17. data/lib/fOOrth/compiler/process/procedure.rb +40 -0
  18. data/lib/fOOrth/library.rb +1 -0
  19. data/lib/fOOrth/library/array_library.rb +41 -21
  20. data/lib/fOOrth/library/command_library.rb +1 -1
  21. data/lib/fOOrth/library/compile_library.rb +266 -266
  22. data/lib/fOOrth/library/complex_library.rb +82 -80
  23. data/lib/fOOrth/library/float_library.rb +37 -0
  24. data/lib/fOOrth/library/hash_library.rb +14 -6
  25. data/lib/fOOrth/library/mutex_library.rb +4 -2
  26. data/lib/fOOrth/library/numeric_library.rb +359 -380
  27. data/lib/fOOrth/library/procedure_library.rb +69 -65
  28. data/lib/fOOrth/library/queue_library.rb +6 -1
  29. data/lib/fOOrth/library/rational_library.rb +89 -89
  30. data/lib/fOOrth/library/stack_library.rb +6 -1
  31. data/lib/fOOrth/library/string_library.rb +18 -6
  32. data/lib/fOOrth/monkey_patch/exceptions.rb +2 -6
  33. data/lib/fOOrth/version.rb +1 -1
  34. data/tests/compiler/context_tests.rb +188 -177
  35. data/tests/compiler/file_source_tests.rb +130 -130
  36. data/tests/compiler/parser_tests.rb +4 -4
  37. data/tests/compiler/string_source_tests.rb +4 -4
  38. data/tests/core_tests.rb +138 -138
  39. data/tests/monkey_patch/complex_test.rb +24 -24
  40. data/tests/monkey_patch/object_test.rb +49 -49
  41. data/tests/monkey_patch/string_test.rb +61 -61
  42. metadata +10 -10
@@ -1,65 +1,69 @@
1
- # coding: utf-8
2
-
3
- #* library/procedure_library.rb - Proc support for the fOOrth library.
4
- module XfOOrth
5
-
6
- #Connect the Proc class to the fOOrth class system.
7
- Proc.create_foorth_proxy('Procedure')
8
-
9
- # A no operation place holder for procedure literals
10
- VirtualMachine.create_shared_method('{{', MacroSpec, [:macro, " "])
11
-
12
- # [procedure] .call [unspecified]
13
- Proc.create_shared_method('.call', TosSpec, [],
14
- &lambda {|vm| self.call(vm); })
15
-
16
- # [owner procedure] .call_with [unspecified]
17
- Proc.create_shared_method('.call_with', TosSpec, [],
18
- &lambda {|vm| vm.pop.instance_exec(vm, &self); })
19
-
20
- # [v procedure] .call_v [unspecified]
21
- Proc.create_shared_method('.call_v', TosSpec, [],
22
- &lambda {|vm| value = vm.pop; self.call(vm, value); })
23
-
24
- # [x procedure] .call_x [unspecified]
25
- Proc.create_shared_method('.call_x', TosSpec, [],
26
- &lambda {|vm| index = vm.pop; self.call(vm, nil, index); })
27
-
28
- # [v x procedure] .call_vx [unspecified]
29
- Proc.create_shared_method('.call_vx', TosSpec, [],
30
- &lambda {|vm| value, index = vm.popm(2); self.call(vm, value, index); })
31
-
32
- # [procedure] .start [a_thread]
33
- Proc.create_shared_method('.start', TosSpec, [], &lambda {|vm|
34
- vm.push(self.do_thread_start(vm, '-'))
35
- })
36
-
37
- # [name procedure] .start_named [a_thread]
38
- Proc.create_shared_method('.start_named', TosSpec, [], &lambda {|vm|
39
- vm.push(self.do_thread_start(vm, vm.pop.to_s.freeze))
40
- })
41
-
42
- end
43
-
44
- #A helper method in the Proc class for fOOrth threads.
45
- class Proc
46
- #Do the mechanics of starting a thread.
47
- def do_thread_start(vm, vm_name)
48
- block, interlock = self, Queue.new
49
-
50
- result = Thread.new(vm.foorth_copy(vm_name)) do |vm_copy|
51
-
52
- begin
53
- self.foorth_init(vm_copy.compiler_reset.connect_vm_to_thread)
54
- ensure
55
- interlock.push(:ready)
56
- end
57
-
58
- vm_copy.instance_exec(vm_copy, &block)
59
- end
60
-
61
- interlock.pop
62
- result
63
- end
64
- end
65
-
1
+ # coding: utf-8
2
+
3
+ #* library/procedure_library.rb - Proc support for the fOOrth library.
4
+ module XfOOrth
5
+
6
+ #Connect the Proc class to the fOOrth class system.
7
+ Proc.create_foorth_proxy('Procedure')
8
+
9
+ # A no operation place holder for procedure literals. This may seem odd but
10
+ # works because any word ending in '{{' is assumed to have a procedure literal
11
+ # attached to it. This is handled in compiler/process/procedure.rb. This code
12
+ # handles compiling the procedure and pushing a reference to it on the stack.
13
+ # Once this is done, this word need do nothing further so is a no-op.
14
+ VirtualMachine.create_shared_method('{{', MacroSpec, [:macro, " "])
15
+
16
+ # [procedure] .call [unspecified]
17
+ Proc.create_shared_method('.call', TosSpec, [],
18
+ &lambda {|vm| self.call(vm); })
19
+
20
+ # [owner procedure] .call_with [unspecified]
21
+ Proc.create_shared_method('.call_with', TosSpec, [],
22
+ &lambda {|vm| vm.pop.instance_exec(vm, &self); })
23
+
24
+ # [v procedure] .call_v [unspecified]
25
+ Proc.create_shared_method('.call_v', TosSpec, [],
26
+ &lambda {|vm| value = vm.pop; self.call(vm, value); })
27
+
28
+ # [x procedure] .call_x [unspecified]
29
+ Proc.create_shared_method('.call_x', TosSpec, [],
30
+ &lambda {|vm| index = vm.pop; self.call(vm, nil, index); })
31
+
32
+ # [v x procedure] .call_vx [unspecified]
33
+ Proc.create_shared_method('.call_vx', TosSpec, [],
34
+ &lambda {|vm| value, index = vm.popm(2); self.call(vm, value, index); })
35
+
36
+ # [procedure] .start [a_thread]
37
+ Proc.create_shared_method('.start', TosSpec, [], &lambda {|vm|
38
+ vm.push(self.do_thread_start(vm, '-'))
39
+ })
40
+
41
+ # [name procedure] .start_named [a_thread]
42
+ Proc.create_shared_method('.start_named', TosSpec, [], &lambda {|vm|
43
+ vm.push(self.do_thread_start(vm, vm.pop.to_s.freeze))
44
+ })
45
+
46
+ end
47
+
48
+ #A helper method in the Proc class for fOOrth threads.
49
+ class Proc
50
+ #Do the mechanics of starting a thread.
51
+ def do_thread_start(vm, vm_name)
52
+ block, interlock = self, Queue.new
53
+
54
+ result = Thread.new(vm.foorth_copy(vm_name)) do |vm_copy|
55
+
56
+ begin
57
+ self.foorth_init(vm_copy.compiler_reset.connect_vm_to_thread)
58
+ ensure
59
+ interlock.push(:ready)
60
+ end
61
+
62
+ vm_copy.instance_exec(vm_copy, &block)
63
+ end
64
+
65
+ interlock.pop
66
+ result
67
+ end
68
+ end
69
+
@@ -34,13 +34,18 @@ module XfOOrth
34
34
  vm.push(self.empty?)
35
35
  })
36
36
 
37
+ # [queue] .present? [a_boolean]
38
+ Queue.create_shared_method('.present?', TosSpec, [], &lambda {|vm|
39
+ vm.push(!self.empty?)
40
+ })
41
+
37
42
  # [queue] .length [an_integer]
38
43
  Queue.create_shared_method('.length', TosSpec, [], &lambda {|vm|
39
44
  vm.push(self.length)
40
45
  })
41
46
 
42
47
  # [queue] .clear []
43
- Queue.create_shared_method('.clear', TosSpec, [], &lambda {|vm|
48
+ Queue.create_shared_method('.clear!', TosSpec, [], &lambda {|vm|
44
49
  self.clear
45
50
  })
46
51
 
@@ -1,90 +1,90 @@
1
- # coding: utf-8
2
-
3
- #* library/rational_library.rb - Numeric support for the fOOrth library.
4
- module XfOOrth
5
-
6
- #Connect the Rational class to the fOOrth class system.
7
- Rational.create_foorth_proxy
8
-
9
- # Some conversion words.
10
- # [n d] rational [n/d]
11
- VirtualMachine.create_shared_method('rational', VmSpec, [], &lambda {|vm|
12
- num,den = popm(2)
13
-
14
- begin
15
- push(Rational(num.to_foorth_r, den.to_foorth_r))
16
- rescue
17
- push(nil)
18
- end
19
- })
20
-
21
- # Some conversion words.
22
- # [n d] rational! [n/d]
23
- VirtualMachine.create_shared_method('rational!', VmSpec, [], &lambda {|vm|
24
- num,den = popm(2)
25
-
26
- begin
27
- push(Rational(num.to_foorth_r, den.to_foorth_r))
28
- rescue
29
- error "F40: Cannot coerce a #{num.foorth_name}, #{den.foorth_name} to a Rational"
30
- end
31
- })
32
-
33
- # [err_limit float] .rationalize_to [rational]
34
- Numeric.create_shared_method('.rationalize_to', TosSpec, [], &lambda {|vm|
35
- err_limit = Float.foorth_coerce(vm.pop)
36
-
37
- vm.push(self.rationalize(err_limit))
38
- })
39
-
40
- Complex.create_shared_method('.rationalize_to', TosSpec, [:stub])
41
-
42
- # [rational] .split [numerator, denominator]
43
- Rational.create_shared_method('.split', TosSpec, [],
44
- &lambda {|vm| vm.push(self.numerator); vm.push(self.denominator); })
45
-
46
- # [a] .to_r [n/d]
47
- Object.create_shared_method('.to_r', TosSpec, [], &lambda {|vm|
48
- begin
49
- vm.push(Rational(self))
50
- rescue
51
- vm.push(nil)
52
- end
53
- })
54
-
55
- # [a] .to_r! [n/d]
56
- Object.create_shared_method('.to_r!', TosSpec, [], &lambda {|vm|
57
- begin
58
- vm.push(Rational(self))
59
- rescue
60
- error "F40: Cannot convert a #{self.foorth_name} to a Rational instance"
61
- end
62
- })
63
-
64
- # [a_float] .to_r [n/d]
65
- Float.create_shared_method('.to_r', TosSpec, [], &lambda {|vm|
66
- begin
67
- vm.push(self.rationalize)
68
- rescue
69
- vm.push(nil)
70
- end
71
- })
72
-
73
- # [a_float] .to_r! [n/d]
74
- Float.create_shared_method('.to_r!', TosSpec, [], &lambda {|vm|
75
- begin
76
- vm.push(self.rationalize)
77
- rescue
78
- error "F40: Cannot convert a #{self.foorth_name} to a Rational instance"
79
- end
80
- })
81
-
82
- # [n/d] .numerator [n]
83
- Numeric.create_shared_method('.numerator', TosSpec, [],
84
- &lambda {|vm| vm.push(self.numerator); })
85
-
86
- # [n/d] .denominator [d]
87
- Numeric.create_shared_method('.denominator', TosSpec, [],
88
- &lambda {|vm| vm.push(self.denominator); })
89
-
1
+ # coding: utf-8
2
+
3
+ #* library/rational_library.rb - Numeric support for the fOOrth library.
4
+ module XfOOrth
5
+
6
+ #Connect the Rational class to the fOOrth class system.
7
+ Rational.create_foorth_proxy
8
+
9
+ # Some conversion words.
10
+ # [n d] rational [n/d]
11
+ VirtualMachine.create_shared_method('rational', VmSpec, [], &lambda {|vm|
12
+ num,den = popm(2)
13
+
14
+ begin
15
+ push(Rational(num.to_foorth_r, den.to_foorth_r))
16
+ rescue
17
+ push(nil)
18
+ end
19
+ })
20
+
21
+ # Some conversion words.
22
+ # [n d] rational! [n/d]
23
+ VirtualMachine.create_shared_method('rational!', VmSpec, [], &lambda {|vm|
24
+ num,den = popm(2)
25
+
26
+ begin
27
+ push(Rational(num.to_foorth_r, den.to_foorth_r))
28
+ rescue
29
+ error "F40: Cannot coerce a #{num.foorth_name}, #{den.foorth_name} to a Rational"
30
+ end
31
+ })
32
+
33
+ # [err_limit float] .rationalize_to [rational]
34
+ Numeric.create_shared_method('.rationalize_to', TosSpec, [], &lambda {|vm|
35
+ err_limit = Float.foorth_coerce(vm.pop)
36
+
37
+ vm.push(self.rationalize(err_limit))
38
+ })
39
+
40
+ Complex.create_shared_method('.rationalize_to', TosSpec, [:stub])
41
+
42
+ # [rational] .split [numerator, denominator]
43
+ Rational.create_shared_method('.split', TosSpec, [],
44
+ &lambda {|vm| vm.push(self.numerator); vm.push(self.denominator); })
45
+
46
+ # [a] .to_r [n/d]
47
+ Object.create_shared_method('.to_r', TosSpec, [], &lambda {|vm|
48
+ begin
49
+ vm.push(Rational(self))
50
+ rescue
51
+ vm.push(nil)
52
+ end
53
+ })
54
+
55
+ # [a] .to_r! [n/d]
56
+ Object.create_shared_method('.to_r!', TosSpec, [], &lambda {|vm|
57
+ begin
58
+ vm.push(Rational(self))
59
+ rescue
60
+ error "F40: Cannot convert a #{self.foorth_name} to a Rational instance"
61
+ end
62
+ })
63
+
64
+ # [a_float] .to_r [n/d]
65
+ Float.create_shared_method('.to_r', TosSpec, [], &lambda {|vm|
66
+ begin
67
+ vm.push(self.rationalize)
68
+ rescue
69
+ vm.push(nil)
70
+ end
71
+ })
72
+
73
+ # [a_float] .to_r! [n/d]
74
+ Float.create_shared_method('.to_r!', TosSpec, [], &lambda {|vm|
75
+ begin
76
+ vm.push(self.rationalize)
77
+ rescue
78
+ error "F40: Cannot convert a #{self.foorth_name} to a Rational instance"
79
+ end
80
+ })
81
+
82
+ # [n/d] .numerator [n]
83
+ Numeric.create_shared_method('.numerator', TosSpec, [],
84
+ &lambda {|vm| vm.push(self.numerator); })
85
+
86
+ # [n/d] .denominator [d]
87
+ Numeric.create_shared_method('.denominator', TosSpec, [],
88
+ &lambda {|vm| vm.push(self.denominator); })
89
+
90
90
  end
@@ -14,7 +14,7 @@ module XfOOrth
14
14
  })
15
15
 
16
16
  #Clear the Stack object.
17
- stack.create_shared_method('.clear', TosSpec, [], &lambda {|vm|
17
+ stack.create_shared_method('.clear!', TosSpec, [], &lambda {|vm|
18
18
  @data.clear
19
19
  })
20
20
 
@@ -46,6 +46,11 @@ module XfOOrth
46
46
  vm.push(@data.empty?)
47
47
  })
48
48
 
49
+ #[stack] .present? [a_boolean]
50
+ stack.create_shared_method('.present?', TosSpec, [], &lambda {|vm|
51
+ vm.push(!@data.empty?)
52
+ })
53
+
49
54
  #[stack] .length [an_integer]
50
55
  stack.create_shared_method('.length', TosSpec, [], &lambda {|vm|
51
56
  vm.push(@data.length)
@@ -211,22 +211,34 @@ module XfOOrth
211
211
 
212
212
  # ['fgh' 'abcdefgh'] .right? [boolean]
213
213
  String.create_shared_method('.right?', TosSpec, [],
214
- &lambda {|vm| vm.poke(self.end_with?(vm.peek)); })
214
+ &lambda {|vm| vm.poke(self.end_with?(vm.peek)) })
215
215
 
216
216
  #Other String Methods
217
217
 
218
218
  # ['cde' 'abcdefgh'] .contains? [boolean]
219
219
  String.create_shared_method('.contains?', TosSpec, [],
220
- &lambda {|vm| vm.poke(self.index(vm.peek).to_foorth_b); })
220
+ &lambda {|vm| vm.poke(self.index(vm.peek).to_foorth_b) })
221
221
 
222
222
  # ['cde' 'abcdefgh'] .posn [position or nil]
223
223
  String.create_shared_method('.posn', TosSpec, [],
224
- &lambda {|vm| vm.poke(self.index(vm.peek)); })
224
+ &lambda {|vm| vm.poke(self.index(vm.peek)) })
225
225
 
226
226
  # ["a"] .length [n]
227
227
  String.create_shared_method('.length', TosSpec, [],
228
228
  &lambda {|vm| vm.push(self.length); })
229
229
 
230
+ # ["a"] .empty? [a_boolean]
231
+ String.create_shared_method('.empty?', TosSpec, [],
232
+ &lambda {|vm| vm.push(self.empty?) })
233
+
234
+ # ["a"] .present? [a_boolean]
235
+ String.create_shared_method('.present?', TosSpec, [],
236
+ &lambda {|vm| vm.push(!self.empty?) })
237
+
238
+ # ["a"] .clear! [a_boolean]
239
+ StringBuffer.create_shared_method('.clear!', TosSpec, [],
240
+ &lambda {|vm| self.clear })
241
+
230
242
  # ["b", a] + ["ba"]; "ba" is a new object, distinct from "b"
231
243
  String.create_shared_method('+', NosSpec, [],
232
244
  &lambda {|vm| vm.poke((self + vm.peek.to_s).freeze) })
@@ -240,7 +252,7 @@ module XfOOrth
240
252
 
241
253
  # ["b"*, a] >> ["ab"*]; "ab"* is the same object as "b"*
242
254
  StringBuffer.create_shared_method('>>', NosSpec, [],
243
- &lambda {|vm| vm.poke(self.prepend(vm.peek.to_s)); })
255
+ &lambda {|vm| vm.poke(self.prepend(vm.peek.to_s)) })
244
256
 
245
257
  # ["b", n] * ["bbb..."]
246
258
  String.create_shared_method('*', NosSpec, [], &lambda {|vm|
@@ -270,7 +282,7 @@ module XfOOrth
270
282
 
271
283
  # ["stressed"] .reverse ["desserts"]
272
284
  String.create_shared_method('.reverse', TosSpec, [],
273
- &lambda {|vm| vm.push(self.to_s.reverse.freeze); })
285
+ &lambda {|vm| vm.push(self.to_s.reverse.freeze) })
274
286
 
275
287
  # ["stressed"*] .reverse* [] #Reverse the string in place.
276
288
  StringBuffer.create_shared_method('.reverse*', TosSpec, [],
@@ -321,7 +333,7 @@ module XfOOrth
321
333
 
322
334
  # [a_string] .shell []
323
335
  String.create_shared_method('.shell', TosSpec, [], &lambda {|vm|
324
- system(self)
336
+ system(self.chomp + "\n")
325
337
  })
326
338
 
327
339
  # [a_string] .shell_out [a_string]
@@ -108,13 +108,9 @@ end
108
108
  #Extensions to the RunTimeError to support fOOrth
109
109
  class RuntimeError
110
110
 
111
- #Massage the messages a bit
112
- #<br>Endemic Code Smells
113
- #* :reek:FeatureEnvy
111
+ #Massage the messages a bit.
114
112
  def message
115
- msg = super
116
- msg["frozen"] && msg["frozen"] = "protected"
117
- msg
113
+ super.gsub(/frozen/, "protected")
118
114
  end
119
115
 
120
116
  end
@@ -3,5 +3,5 @@
3
3
  #* version.rb - The version string for fOOrth.
4
4
  module XfOOrth
5
5
  #The version string for fOOrth.
6
- VERSION = "0.6.10"
6
+ VERSION = "0.6.11"
7
7
  end
@@ -1,177 +1,188 @@
1
- # coding: utf-8
2
-
3
- $exclude_fOOrth_library = true
4
- require_relative '../../lib/fOOrth'
5
- gem 'minitest'
6
- require 'minitest/autorun'
7
- require 'minitest_visible'
8
-
9
- class MockClass
10
- def initialize; @data = {}; end
11
- def []=(index, value); @data[index] = value; end
12
- def map_foorth_shared(index); @data[index]; end
13
- end
14
-
15
- class MockObject
16
- def initialize; @data = {}; end
17
- def []=(index, value); @data[index] = value; end
18
- def map_foorth_exclusive(index); @data[index]; end
19
- end
20
-
21
- #Test the monkey patches applied to the Object class.
22
- class ContextTester < Minitest::Test
23
-
24
- #Track mini-test progress.
25
- include MinitestVisible
26
-
27
- def test_data_store
28
- context = XfOOrth::Context.new(45, stuff: 'buy', price: :plenty)
29
-
30
- assert_equal(context.previous, 45)
31
- assert_equal(context[:stuff], 'buy')
32
- assert_equal(context[:price], :plenty)
33
-
34
- context[:stuff] = 'sell'
35
- assert_equal(context[:stuff], 'sell')
36
- assert_equal(context[:price], :plenty)
37
-
38
- context[:price] = 9.95
39
- assert_equal(context[:stuff], 'sell')
40
- assert_equal(context[:price], 9.95)
41
- end
42
-
43
- #Test level counting
44
- def test_level_tracking
45
- context = XfOOrth::Context.new(nil, stuff: 'buy')
46
- assert_equal(context.depth, 1)
47
-
48
- context = XfOOrth::Context.new(context, stuff: 'other')
49
- assert_equal(context.depth, 2)
50
-
51
- context = XfOOrth::Context.new(context, stuff: 'more')
52
- assert_equal(context.depth, 3)
53
-
54
- context = context.previous
55
- assert_equal(context.depth, 2)
56
-
57
- context = context.previous
58
- assert_equal(context.depth, 1)
59
-
60
- context = context.previous
61
- assert_equal(context, nil)
62
- end
63
-
64
- def test_the_nesting_of_scopes
65
- context = XfOOrth::Context.new(nil, stuff: 'buy')
66
- assert_equal(context[:foo], nil)
67
- assert_equal(context[:jelly], nil)
68
- assert_equal(context[:stuff], 'buy')
69
- context[:foo] = 1
70
- context[:jelly] = 'donut'
71
- assert_equal(context[:jelly], 'donut')
72
- assert_equal(context[:stuff], 'buy')
73
- assert_equal(context[:foo], 1)
74
-
75
- context = XfOOrth::Context.new(context, stuff: 'other')
76
- assert_equal(context[:foo], 1)
77
- assert_equal(context[:jelly], 'donut')
78
- assert_equal(context[:stuff], 'other')
79
- context[:foo] = 2
80
- assert_equal(context[:jelly], 'donut')
81
- assert_equal(context[:stuff], 'other')
82
- assert_equal(context[:foo], 2)
83
-
84
- context = XfOOrth::Context.new(context, stuff: 'more')
85
- assert_equal(context[:foo], 2)
86
- assert_equal(context[:jelly], 'donut')
87
- assert_equal(context[:stuff], 'more')
88
- context[:foo] = 3
89
- context[:jelly] = 'Berliner'
90
- assert_equal(context[:jelly], 'Berliner')
91
- assert_equal(context[:stuff], 'more')
92
- assert_equal(context[:foo], 3)
93
-
94
- context = context.previous
95
- assert_equal(context[:foo], 2)
96
- assert_equal(context[:jelly], 'donut')
97
- assert_equal(context[:stuff], 'other')
98
-
99
- context = context.previous
100
- assert_equal(context[:foo], 1)
101
- assert_equal(context[:jelly], 'donut')
102
- assert_equal(context[:stuff], 'buy')
103
- end
104
-
105
- def test_the_local_mapping_of_symbols
106
- context = XfOOrth::Context.new(nil)
107
-
108
- name = 'b'
109
- sym = XfOOrth::SymbolMap.add_entry(name)
110
- context[sym] = XfOOrth::VmSpec.new(name, sym, [])
111
- spec = context.map_with_defaults(name)
112
- assert(spec.is_a?(XfOOrth::VmSpec))
113
- end
114
-
115
- def test_the_class_mapping_of_symbols
116
- mk = MockClass.new
117
- context = XfOOrth::Context.new(nil, cls: mk)
118
-
119
- name = '.c'
120
- sym = XfOOrth::SymbolMap.add_entry(name)
121
- mk[sym] = XfOOrth::TosSpec.new(name, sym, [])
122
- spec = context.map_with_defaults(name)
123
- assert(spec.is_a?(XfOOrth::TosSpec))
124
- end
125
-
126
- def test_the_exclusive_mapping_of_symbols
127
- mk = MockObject.new
128
- context = XfOOrth::Context.new(nil, obj: mk)
129
-
130
- name = '.d'
131
- sym = XfOOrth::SymbolMap.add_entry(name)
132
- mk[sym] = XfOOrth::TosSpec.new(name, sym, [])
133
- spec = context.map_with_defaults(name)
134
- assert(spec.is_a?(XfOOrth::TosSpec))
135
- end
136
-
137
- def test_that_it_verifies_sets
138
- context = XfOOrth::Context.new(nil, mode: :Execute, ctrl: :colon)
139
-
140
- assert(context.check_set(:mode, [:Execute, :Compile]))
141
-
142
- assert_raises(XfOOrth::XfOOrthError) do
143
- context.check_set(:mode, [:Compile, :Deferred])
144
- end
145
-
146
- assert(context.check_set(:stuff, [nil]))
147
- end
148
-
149
- def test_the_locating_of_the_receiver
150
- context = XfOOrth::Context.new(nil, vm: 'vm_sample')
151
- assert_equal('vm_sample', context.target)
152
-
153
- context = XfOOrth::Context.new(context, cls: 'cls_sample')
154
- assert_equal('cls_sample', context.target)
155
-
156
- context = XfOOrth::Context.new(context, obj: 'obj_sample')
157
- assert_equal('obj_sample', context.target)
158
-
159
- context = XfOOrth::Context.new(nil)
160
- assert_raises(XfOOrth::XfOOrthError) { context.target }
161
- end
162
-
163
- def test_adding_and_removing_local_methods
164
- context = XfOOrth::Context.new(nil, vm: 'vm_sample')
165
- name = 'lm'
166
- sym = XfOOrth::SymbolMap.add_entry(name)
167
- spec = context.create_local_method(name, XfOOrth::LocalSpec, [])
168
-
169
- assert_equal(spec, context[sym])
170
-
171
- context.remove_local_method(name)
172
-
173
- assert_equal(nil, context[sym])
174
-
175
- end
176
-
177
- end
1
+ # coding: utf-8
2
+
3
+ $exclude_fOOrth_library = true
4
+ require_relative '../../lib/fOOrth'
5
+ gem 'minitest'
6
+ require 'minitest/autorun'
7
+ require 'minitest_visible'
8
+
9
+ class MockClass
10
+ def initialize; @data = {}; end
11
+ def []=(index, value); @data[index] = value; end
12
+ def map_foorth_shared(index); @data[index]; end
13
+ end
14
+
15
+ class MockObject
16
+ def initialize; @data = {}; end
17
+ def []=(index, value); @data[index] = value; end
18
+ def map_foorth_exclusive(index); @data[index]; end
19
+ end
20
+
21
+ #Test the monkey patches applied to the Object class.
22
+ class ContextTester < Minitest::Test
23
+
24
+ #Track mini-test progress.
25
+ include MinitestVisible
26
+
27
+ def test_data_store
28
+ context = XfOOrth::Context.new(45, stuff: 'buy', price: :plenty)
29
+
30
+ assert_equal(context.previous, 45)
31
+ assert_equal(context[:stuff], 'buy')
32
+ assert_equal(context[:price], :plenty)
33
+
34
+ context[:stuff] = 'sell'
35
+ assert_equal(context[:stuff], 'sell')
36
+ assert_equal(context[:price], :plenty)
37
+
38
+ context[:price] = 9.95
39
+ assert_equal(context[:stuff], 'sell')
40
+ assert_equal(context[:price], 9.95)
41
+ end
42
+
43
+ #Test level counting
44
+ def test_level_tracking
45
+ context = XfOOrth::Context.new(nil, stuff: 'buy')
46
+ assert_equal(context.depth, 1)
47
+
48
+ context = XfOOrth::Context.new(context, stuff: 'other')
49
+ assert_equal(context.depth, 2)
50
+
51
+ context = XfOOrth::Context.new(context, stuff: 'more')
52
+ assert_equal(context.depth, 3)
53
+
54
+ context = context.previous
55
+ assert_equal(context.depth, 2)
56
+
57
+ context = context.previous
58
+ assert_equal(context.depth, 1)
59
+
60
+ context = context.previous
61
+ assert_nil(context)
62
+ end
63
+
64
+ def test_the_nesting_of_scopes
65
+ context = XfOOrth::Context.new(nil, stuff: 'buy')
66
+ assert_nil(context[:foo])
67
+ assert_nil(context[:jelly])
68
+ assert_equal(context[:stuff], 'buy')
69
+ context[:foo] = 1
70
+ context[:jelly] = 'donut'
71
+ assert_equal(context[:jelly], 'donut')
72
+ assert_equal(context[:stuff], 'buy')
73
+ assert_equal(context[:foo], 1)
74
+
75
+ context = XfOOrth::Context.new(context, stuff: 'other')
76
+ assert_equal(context[:foo], 1)
77
+ assert_equal(context[:jelly], 'donut')
78
+ assert_equal(context[:stuff], 'other')
79
+ context[:foo] = 2
80
+ assert_equal(context[:jelly], 'donut')
81
+ assert_equal(context[:stuff], 'other')
82
+ assert_equal(context[:foo], 2)
83
+
84
+ context = XfOOrth::Context.new(context, stuff: 'more')
85
+ assert_equal(context[:foo], 2)
86
+ assert_equal(context[:jelly], 'donut')
87
+ assert_equal(context[:stuff], 'more')
88
+ context[:foo] = 3
89
+ context[:jelly] = 'Berliner'
90
+ assert_equal(context[:jelly], 'Berliner')
91
+ assert_equal(context[:stuff], 'more')
92
+ assert_equal(context[:foo], 3)
93
+
94
+ context = context.previous
95
+ assert_equal(context[:foo], 2)
96
+ assert_equal(context[:jelly], 'donut')
97
+ assert_equal(context[:stuff], 'other')
98
+
99
+ context = context.previous
100
+ assert_equal(context[:foo], 1)
101
+ assert_equal(context[:jelly], 'donut')
102
+ assert_equal(context[:stuff], 'buy')
103
+ end
104
+
105
+ def test_getting_context_with_a_specific_tag
106
+ c1 = XfOOrth::Context.new(nil, ctrl: :procedure)
107
+ c2 = XfOOrth::Context.new(c1, ctrl: :if)
108
+ c3 = XfOOrth::Context.new(c2, ctrl: :loop)
109
+
110
+ assert_equal(c1, c3.get_context_by_ctrl(:procedure))
111
+ assert_equal(c2, c3.get_context_by_ctrl(:if))
112
+ assert_equal(c3, c3.get_context_by_ctrl(:loop))
113
+ assert_raises(XfOOrth::XfOOrthError) { c3.get_context_by_ctrl(:wrong) }
114
+ end
115
+
116
+ def test_the_local_mapping_of_symbols
117
+ context = XfOOrth::Context.new(nil)
118
+
119
+ name = 'b'
120
+ sym = XfOOrth::SymbolMap.add_entry(name)
121
+ context[sym] = XfOOrth::VmSpec.new(name, sym, [])
122
+ spec = context.map_with_defaults(name)
123
+ assert(spec.is_a?(XfOOrth::VmSpec))
124
+ end
125
+
126
+ def test_the_class_mapping_of_symbols
127
+ mk = MockClass.new
128
+ context = XfOOrth::Context.new(nil, cls: mk)
129
+
130
+ name = '.c'
131
+ sym = XfOOrth::SymbolMap.add_entry(name)
132
+ mk[sym] = XfOOrth::TosSpec.new(name, sym, [])
133
+ spec = context.map_with_defaults(name)
134
+ assert(spec.is_a?(XfOOrth::TosSpec))
135
+ end
136
+
137
+ def test_the_exclusive_mapping_of_symbols
138
+ mk = MockObject.new
139
+ context = XfOOrth::Context.new(nil, obj: mk)
140
+
141
+ name = '.d'
142
+ sym = XfOOrth::SymbolMap.add_entry(name)
143
+ mk[sym] = XfOOrth::TosSpec.new(name, sym, [])
144
+ spec = context.map_with_defaults(name)
145
+ assert(spec.is_a?(XfOOrth::TosSpec))
146
+ end
147
+
148
+ def test_that_it_verifies_sets
149
+ context = XfOOrth::Context.new(nil, mode: :Execute, ctrl: :colon)
150
+
151
+ assert(context.check_set(:mode, [:Execute, :Compile]))
152
+
153
+ assert_raises(XfOOrth::XfOOrthError) do
154
+ context.check_set(:mode, [:Compile, :Deferred])
155
+ end
156
+
157
+ assert(context.check_set(:stuff, [nil]))
158
+ end
159
+
160
+ def test_the_locating_of_the_receiver
161
+ context = XfOOrth::Context.new(nil, vm: 'vm_sample')
162
+ assert_equal('vm_sample', context.target)
163
+
164
+ context = XfOOrth::Context.new(context, cls: 'cls_sample')
165
+ assert_equal('cls_sample', context.target)
166
+
167
+ context = XfOOrth::Context.new(context, obj: 'obj_sample')
168
+ assert_equal('obj_sample', context.target)
169
+
170
+ context = XfOOrth::Context.new(nil)
171
+ assert_raises(XfOOrth::XfOOrthError) { context.target }
172
+ end
173
+
174
+ def test_adding_and_removing_local_methods
175
+ context = XfOOrth::Context.new(nil, vm: 'vm_sample')
176
+ name = 'lm'
177
+ sym = XfOOrth::SymbolMap.add_entry(name)
178
+ spec = context.create_local_method(name, XfOOrth::LocalSpec, [])
179
+
180
+ assert_equal(spec, context[sym])
181
+
182
+ context.remove_local_method(name)
183
+
184
+ assert_nil(context[sym])
185
+
186
+ end
187
+
188
+ end