fOOrth 0.6.10 → 0.6.11

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