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,31 @@
1
+ # coding: utf-8
2
+
3
+ #Extensions to the \Rational class required by the fOOrth language system.
4
+ class Rational
5
+ #Convert this rational number to a form suitable for embedding in a source string.
6
+ #<br>Returns
7
+ #* An embeddable form of this rational number as a string.
8
+ def foorth_embed
9
+ "'#{self.to_s}'.to_r"
10
+ end
11
+
12
+ #Convert this object to a rational. Returns self.
13
+ def to_foorth_r
14
+ self
15
+ end
16
+
17
+ #Argument coercion methods.
18
+
19
+ #Coerce the argument to match my type.
20
+ def self.foorth_coerce(arg)
21
+ arg.to_foorth_r || (error "F40: Cannot coerce a #{arg.foorth_name} to a Rational")
22
+ end
23
+
24
+ #Coerce the argument to match my type.
25
+ #<br>Endemic Code Smells
26
+ #* :reek:FeatureEnvy -- false positive
27
+ def foorth_coerce(arg)
28
+ arg.to_foorth_r || (error "F40: Cannot coerce a #{arg.foorth_name} to a Rational")
29
+ end
30
+
31
+ end
@@ -0,0 +1,51 @@
1
+ # coding: utf-8
2
+
3
+ #Extensions to the \String class required by the fOOrth language system.
4
+ class String
5
+ #Convert this String to a form suitable for embedding in a source string.
6
+ #<br>Returns
7
+ #* An embeddable form of this string as a string.
8
+ def foorth_embed
9
+ self.inspect
10
+ end
11
+
12
+ #Coerce the argument to match my type.
13
+ #<br>Endemic Code Smells
14
+ #* :reek:FeatureEnvy -- false positive
15
+ def foorth_coerce(arg)
16
+ arg.to_s
17
+ rescue
18
+ error "F40: Cannot coerce a #{arg.foorth_name} to an String instance"
19
+ end
20
+
21
+ #Convert this string to a single character string.
22
+ def to_foorth_c
23
+ self[0]
24
+ end
25
+
26
+ #Convert this string to a numeric. Return a number or nil on fail.
27
+ def to_foorth_n
28
+ if /\di$/ =~ self #Check for a trailing '<digit>i'.
29
+ #Check for the internal '+' or '-'sign.
30
+ if /(?<=\d)[+-]/ =~ self
31
+ Complex(($PREMATCH).to_foorth_n, ($MATCH + $POSTMATCH).chop.to_foorth_n)
32
+ else
33
+ Complex(0, self.chop.to_foorth_n)
34
+ end
35
+ elsif /\d\/\d/ =~ self #Check for an embedded '<digit>/<digit>'.
36
+ Rational(self)
37
+ elsif /\d\.\d/ =~ self #Check for an embedded '<digit>.<digit>'.
38
+ Float(self)
39
+ else #For the rest, assume an integer.
40
+ Integer(self)
41
+ end
42
+ rescue
43
+ nil
44
+ end
45
+
46
+ #Convert this string to a rational. Return a number or nil on fail.
47
+ def to_foorth_r
48
+ self.to_foorth_n.to_foorth_r
49
+ end
50
+
51
+ end
@@ -0,0 +1,82 @@
1
+ # coding: utf-8
2
+
3
+ #* symbol_map.rb - The name mangler for the foorth Language System.
4
+ module XfOOrth
5
+
6
+ #A module used to map strings to unique symbols
7
+ module SymbolMap
8
+
9
+ class << self
10
+ #Access to the mapping of names to symbols.
11
+ attr_reader :forward_map
12
+
13
+ #Access to the mapping of symbols to names.
14
+ attr_reader :reverse_map
15
+ end
16
+
17
+ @sync = Mutex.new
18
+ @incrementer = '_000'
19
+ @forward_map = Hash.new
20
+ @reverse_map = Hash.new
21
+
22
+ #Add a global mapping for a string to a symbol that will not collide with
23
+ #existing symbols.
24
+ #<br>Parameters:
25
+ #* name - The string to be mapped.
26
+ #* presym - A pre-assigned symbol value or nil to generate a symbol.
27
+ #<br>Returns:
28
+ #* The symbol that corresponds to the name.
29
+ #<br>Endemic Code Smells
30
+ #* :reek:ControlParameter -- false positive
31
+ def self.add_entry(name, presym=nil)
32
+ @sync.synchronize do
33
+ unless (symbol = @forward_map[name])
34
+ symbol = presym || (@incrementer.succ!).to_sym
35
+ connect(name, symbol)
36
+ else
37
+ error "F90: Attempt to redefine #{name}." if presym && presym != symbol
38
+ end
39
+
40
+ symbol
41
+ end
42
+ end
43
+
44
+ #Get the entry for the mapping string. Return nil if there is no entry.
45
+ #<br>Parameters:
46
+ #* name - The string to be looked up.
47
+ #<br>Returns:
48
+ #* A symbol or nil if the symbol is not in the map.
49
+ def self.map(name)
50
+ @forward_map[name]
51
+ end
52
+
53
+ #Get the entry for the mapping symbol. Return nil if there is no entry.
54
+ #<br>Parameters:
55
+ #* mapped - The mapping of the desired symbol.
56
+ #<br>Returns:
57
+ #* The name or nil if the symbol is not in the map.
58
+ def self.unmap(mapped)
59
+ @reverse_map[mapped]
60
+ end
61
+
62
+ #Reset the incrementer to the given string. This used for testing only.
63
+ #<br>Parameters:
64
+ #* start - The new starting point of the generated symbols.
65
+ #<br>Note:
66
+ #* FOR TESTING ONLY.
67
+ def self.restart(start)
68
+ @incrementer = start
69
+ end
70
+
71
+ #Set up the internal workings of the mapping hashes.
72
+ private
73
+ def self.connect(name, symbol)
74
+ if (old = @reverse_map[symbol]) && (old != name)
75
+ error "F90: Attempt to redefine #{name}."
76
+ end
77
+
78
+ @reverse_map[symbol] = name
79
+ @forward_map[name] = symbol
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,7 @@
1
+ # coding: utf-8
2
+
3
+ #* version.rb - The version string for fOOrth.
4
+ module XfOOrth
5
+ #The version string for fOOrth.
6
+ VERSION = "0.5.0"
7
+ end
@@ -0,0 +1,21 @@
1
+ === The MIT License (MIT).
2
+
3
+ Copyright (c) 2014 Peter Camilleri
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env rake
2
+ # coding: utf-8
3
+
4
+ require 'rake/testtask'
5
+ require 'rdoc/task'
6
+ require "bundler/gem_tasks"
7
+
8
+ #Generate internal documentation with rdoc.
9
+ RDoc::Task.new do |rdoc|
10
+ rdoc.rdoc_dir = "rdoc"
11
+
12
+ #List out all the files to be documented.
13
+ rdoc.rdoc_files.include("lib/**/*.rb", "license.txt", "README.md")
14
+
15
+ #Make all access levels visible.
16
+ rdoc.options << '--visibility' << 'private'
17
+ #rdoc.options << '--verbose'
18
+ #rdoc.options << '--coverage-report'
19
+
20
+ #Set a title.
21
+ rdoc.options << '--title' << 'fOOrth Language Internals'
22
+
23
+ end
24
+
25
+ #Run the fOOrth unit test suite.
26
+ Rake::TestTask.new do |t|
27
+ #List out all the test files.
28
+ t.test_files = FileList['tests/**/*.rb']
29
+ t.verbose = false
30
+ end
31
+
32
+ #Run the fOOrth integration test suite.
33
+ Rake::TestTask.new(:integration) do |t|
34
+ #List out all the test files.
35
+ t.test_files = FileList['integration/*.rb']
36
+ end
37
+
38
+ desc "Run a scan for smelly code!"
39
+ task :reek do |t|
40
+ `reek --no-color lib > reek.txt`
41
+ end
42
+
43
+ desc "Fire up an IRB session with fOOrth preloaded."
44
+ task :console do
45
+ require 'irb'
46
+ require 'irb/completion'
47
+ require './lib/fOOrth'
48
+ puts "Starting an IRB console for fOOrth."
49
+ ARGV.clear
50
+ IRB.start
51
+ end
52
+
53
+ desc "Run an Interactive fOOrth Session."
54
+ task :run do
55
+ require './lib/fOOrth'
56
+ ARGV.clear
57
+ XfOOrth::main
58
+ end
59
+
60
+ desc "What version of fOOrth is this?"
61
+ task :vers do |t|
62
+ puts
63
+ puts "fOOrth version = #{XfOOrth::VERSION}"
64
+ end
65
+
@@ -0,0 +1 @@
1
+ 0 total warnings
data/sire.rb ADDED
@@ -0,0 +1,132 @@
1
+ # coding: utf-8
2
+ # A Simple Interactive Ruby Environment
3
+
4
+ $no_alias_read_line_module = true
5
+ require 'mini_readline'
6
+ require 'pp'
7
+
8
+ if ARGV[0] == 'local'
9
+ require_relative 'lib/fOOrth'
10
+ puts "\nOption(local) Loaded fOOrth from the local code folder."
11
+ elsif defined?(XfOOrth)
12
+ puts "The fOOrth system is already loaded."
13
+ else
14
+ begin
15
+ require 'fOOrth'
16
+ puts "\nLoaded fOOrth from the system gem."
17
+ rescue LoadError
18
+ require_relative 'lib/fOOrth'
19
+ puts "\nLoaded fOOrth from the local code folder."
20
+ end
21
+ end
22
+
23
+ puts "fOOrth version = #{XfOOrth::VERSION}"
24
+ puts
25
+
26
+ class Object
27
+ #Generate the class lineage of the object.
28
+ def classes
29
+ begin
30
+ result = ""
31
+ klass = self.instance_of?(Class) ? self : self.class
32
+
33
+ begin
34
+ result << klass.to_s
35
+ klass = klass.superclass
36
+ result << " < " if klass
37
+ end while klass
38
+
39
+ result
40
+ end
41
+ end
42
+ end
43
+
44
+ class SIRE
45
+ #Set up the interactive session.
46
+ def initialize
47
+ @_done = false
48
+ @_edit = MiniReadline::Readline.new(history: true,
49
+ auto_complete: true,
50
+ auto_source: MiniReadline::QuotedFileFolderSource,
51
+ eoi_detect: true)
52
+
53
+ puts "Welcome to a Simple Interactive Ruby Environment\n"
54
+ puts
55
+ puts "Local commands:"
56
+ puts " q - quit SIRE."
57
+ puts " r - run fOOrth."
58
+ puts " v - version manifest"
59
+ puts "obj classes - show the obj's class heritage."
60
+ puts
61
+ end
62
+
63
+ #Quit the interactive session.
64
+ def q
65
+ @_done = true
66
+ puts
67
+ "Bye bye for now!"
68
+ end
69
+
70
+ def r
71
+ ARGV.clear
72
+ XfOOrth::main.data_stack
73
+ end
74
+
75
+ def v
76
+ puts "Version Manifest"
77
+ mods = ObjectSpace.each_object(Module).select{|c| c.const_defined?("VERSION")}
78
+ width = (mods.max_by{|m| m.to_s.length}).to_s.length
79
+ list = mods.map {|m| "#{m.to_s.ljust(width)} #{m.const_get(:VERSION)}" }
80
+ list.sort
81
+ end
82
+
83
+ #Load and run a file
84
+ def l(file_name)
85
+ @_break = false
86
+ lines = IO.readlines(file_name)
87
+
88
+ lines.each do |line|
89
+ exec_line(line)
90
+ return if @_break
91
+ end
92
+
93
+ "End of file '#{file_name}'."
94
+ end
95
+
96
+ #Execute a single line.
97
+ def exec_line(line)
98
+ result = eval line
99
+ pp result unless line.length == 0
100
+
101
+ rescue Interrupt => e
102
+ @_break = true
103
+ puts "\nExecution Interrupted!"
104
+ puts "\n#{e.class} detected: #{e}\n"
105
+ puts e.backtrace
106
+ puts "\n"
107
+
108
+ rescue Exception => e
109
+ @_break = true
110
+ puts "\n#{e.class} detected: #{e}\n"
111
+ puts e.backtrace
112
+ puts
113
+ end
114
+
115
+ #Run the interactive session.
116
+ def run_sire
117
+ until @_done
118
+ @_break = false
119
+ exec_line(@_edit.readline(prompt: 'SIRE>'))
120
+ end
121
+
122
+ puts "\n\n"
123
+
124
+ rescue MiniReadlineEOI, Interrupt => e
125
+ puts "\nInterrupted! Program Terminating."
126
+ end
127
+
128
+ end
129
+
130
+ if __FILE__ == $0
131
+ SIRE.new.run_sire
132
+ end
data/t.txt ADDED
@@ -0,0 +1,3 @@
1
+ XfOOrth.create_proxy(Numeric, XfOOrth.object_class)
2
+ Numeric.name
3
+ (4).name
@@ -0,0 +1,5 @@
1
+ // A general test file for fOOrth.
2
+ // Used in non-specific interactive tests.
3
+
4
+ )vm cr cr )vm! cr
5
+
@@ -0,0 +1,180 @@
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(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(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(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.recvr)
152
+
153
+ context = XfOOrth::Context.new(context, cls: 'cls_sample')
154
+ assert_equal('cls_sample', context.recvr)
155
+
156
+ context = XfOOrth::Context.new(context, obj: 'obj_sample')
157
+ assert_equal('obj_sample', context.recvr)
158
+
159
+ context = XfOOrth::Context.new(nil)
160
+
161
+ assert_raises(XfOOrth::XfOOrthError) do
162
+ context.recvr
163
+ end
164
+ end
165
+
166
+ def test_adding_and_removing_local_methods
167
+ context = XfOOrth::Context.new(nil, vm: 'vm_sample')
168
+ name = 'lm'
169
+ sym = XfOOrth::SymbolMap.add_entry(name)
170
+ spec = context.create_local_method(name, XfOOrth::LocalSpec, [])
171
+
172
+ assert_equal(spec, context[sym])
173
+
174
+ context.remove_local_method(name)
175
+
176
+ assert_equal(nil, context[sym])
177
+
178
+ end
179
+
180
+ end