fOOrth 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.rdoc_options +17 -0
  4. data/Gemfile +4 -0
  5. data/README.md +67 -0
  6. data/bin/fOOrth +8 -0
  7. data/demo.rb +24 -0
  8. data/fOOrth.gemspec +40 -0
  9. data/fOOrth.reek +109 -0
  10. data/integration/README.md +12 -0
  11. data/integration/_FILE_test.foorth +5 -0
  12. data/integration/array_lib_tests.rb +360 -0
  13. data/integration/class_lib_tests.rb +116 -0
  14. data/integration/clone_lib_tests.rb +108 -0
  15. data/integration/comparison_tests.rb +132 -0
  16. data/integration/compile_lib_tests.rb +190 -0
  17. data/integration/ctrl_struct_lib_tests.rb +80 -0
  18. data/integration/data_ref_lib_tests.rb +43 -0
  19. data/integration/exception_lib_tests.rb +86 -0
  20. data/integration/fiber_bundle_tests.rb +380 -0
  21. data/integration/hash_lib_tests.rb +120 -0
  22. data/integration/in_stream_test_1.txt +4 -0
  23. data/integration/load_test_one.foorth +6 -0
  24. data/integration/load_test_two.foorth +4 -0
  25. data/integration/numeric_lib_tests.rb +321 -0
  26. data/integration/object_lib_tests.rb +38 -0
  27. data/integration/procedure_lib_tests.rb +40 -0
  28. data/integration/queue_lib_tests.rb +66 -0
  29. data/integration/stack_lib_tests.rb +70 -0
  30. data/integration/standard_lib_tests.rb +208 -0
  31. data/integration/stdio_lib_tests.rb +52 -0
  32. data/integration/stream_lib_tests.rb +196 -0
  33. data/integration/string_lib_tests.rb +217 -0
  34. data/integration/support/foorth_testing.rb +135 -0
  35. data/integration/thread_lib_tests.rb +83 -0
  36. data/integration/time_lib_tests.rb +791 -0
  37. data/integration/vm_lib_tests.rb +38 -0
  38. data/lib/fOOrth.rb +57 -0
  39. data/lib/fOOrth/compiler.rb +78 -0
  40. data/lib/fOOrth/compiler/context.rb +49 -0
  41. data/lib/fOOrth/compiler/context/locals.rb +34 -0
  42. data/lib/fOOrth/compiler/context/map_name.rb +92 -0
  43. data/lib/fOOrth/compiler/context/tags.rb +48 -0
  44. data/lib/fOOrth/compiler/modes.rb +32 -0
  45. data/lib/fOOrth/compiler/modes/compiled.rb +41 -0
  46. data/lib/fOOrth/compiler/modes/deferred.rb +57 -0
  47. data/lib/fOOrth/compiler/modes/delayed.rb +40 -0
  48. data/lib/fOOrth/compiler/modes/nested.rb +34 -0
  49. data/lib/fOOrth/compiler/modes/suspend.rb +32 -0
  50. data/lib/fOOrth/compiler/parser.rb +26 -0
  51. data/lib/fOOrth/compiler/parser/get_string.rb +71 -0
  52. data/lib/fOOrth/compiler/parser/normal.rb +53 -0
  53. data/lib/fOOrth/compiler/parser/skip.rb +50 -0
  54. data/lib/fOOrth/compiler/parser/special.rb +42 -0
  55. data/lib/fOOrth/compiler/process.rb +47 -0
  56. data/lib/fOOrth/compiler/process/generate.rb +24 -0
  57. data/lib/fOOrth/compiler/process/get_token.rb +23 -0
  58. data/lib/fOOrth/compiler/process/procedure.rb +55 -0
  59. data/lib/fOOrth/compiler/process/string.rb +20 -0
  60. data/lib/fOOrth/compiler/source.rb +51 -0
  61. data/lib/fOOrth/compiler/source/console.rb +70 -0
  62. data/lib/fOOrth/compiler/source/file_source.rb +37 -0
  63. data/lib/fOOrth/compiler/source/read_point.rb +46 -0
  64. data/lib/fOOrth/compiler/source/string_source.rb +28 -0
  65. data/lib/fOOrth/compiler/token.rb +37 -0
  66. data/lib/fOOrth/compiler/word_specs.rb +178 -0
  67. data/lib/fOOrth/core.rb +27 -0
  68. data/lib/fOOrth/core/class.rb +116 -0
  69. data/lib/fOOrth/core/object.rb +78 -0
  70. data/lib/fOOrth/core/virtual_machine.rb +28 -0
  71. data/lib/fOOrth/debug.rb +13 -0
  72. data/lib/fOOrth/debug/context_dump.rb +31 -0
  73. data/lib/fOOrth/debug/dbg_puts.rb +17 -0
  74. data/lib/fOOrth/debug/display_abort.rb +37 -0
  75. data/lib/fOOrth/debug/vm_dump.rb +27 -0
  76. data/lib/fOOrth/initialize.rb +83 -0
  77. data/lib/fOOrth/interpreter.rb +24 -0
  78. data/lib/fOOrth/interpreter/add_to_hash.rb +17 -0
  79. data/lib/fOOrth/interpreter/data_stack.rb +125 -0
  80. data/lib/fOOrth/interpreter/do_loop.rb +55 -0
  81. data/lib/fOOrth/interpreter/squash.rb +25 -0
  82. data/lib/fOOrth/library.rb +38 -0
  83. data/lib/fOOrth/library/array_library.rb +577 -0
  84. data/lib/fOOrth/library/bundle_library.rb +112 -0
  85. data/lib/fOOrth/library/class_library.rb +90 -0
  86. data/lib/fOOrth/library/clone_library.rb +72 -0
  87. data/lib/fOOrth/library/command_library.rb +205 -0
  88. data/lib/fOOrth/library/compile_library.rb +181 -0
  89. data/lib/fOOrth/library/complex_library.rb +81 -0
  90. data/lib/fOOrth/library/ctrl_struct_library.rb +116 -0
  91. data/lib/fOOrth/library/data_ref_library.rb +100 -0
  92. data/lib/fOOrth/library/duration/arithmetic.rb +114 -0
  93. data/lib/fOOrth/library/duration/formatter.rb +152 -0
  94. data/lib/fOOrth/library/duration/intervals.rb +233 -0
  95. data/lib/fOOrth/library/duration/make.rb +75 -0
  96. data/lib/fOOrth/library/duration_library.rb +52 -0
  97. data/lib/fOOrth/library/fiber_library.rb +120 -0
  98. data/lib/fOOrth/library/hash_library.rb +203 -0
  99. data/lib/fOOrth/library/in_stream_library.rb +81 -0
  100. data/lib/fOOrth/library/integer_library.rb +104 -0
  101. data/lib/fOOrth/library/mutex_library.rb +31 -0
  102. data/lib/fOOrth/library/numeric_library.rb +380 -0
  103. data/lib/fOOrth/library/object_library.rb +80 -0
  104. data/lib/fOOrth/library/other_value_types_library.rb +96 -0
  105. data/lib/fOOrth/library/out_stream_library.rb +146 -0
  106. data/lib/fOOrth/library/procedure_library.rb +65 -0
  107. data/lib/fOOrth/library/queue_library.rb +47 -0
  108. data/lib/fOOrth/library/rational_library.rb +90 -0
  109. data/lib/fOOrth/library/stack_library.rb +56 -0
  110. data/lib/fOOrth/library/stdio_library.rb +56 -0
  111. data/lib/fOOrth/library/string_library.rb +285 -0
  112. data/lib/fOOrth/library/stubs.rb +76 -0
  113. data/lib/fOOrth/library/sync_bundle_library.rb +50 -0
  114. data/lib/fOOrth/library/thread_library.rb +73 -0
  115. data/lib/fOOrth/library/time_library.rb +302 -0
  116. data/lib/fOOrth/library/vm_library.rb +105 -0
  117. data/lib/fOOrth/main.rb +125 -0
  118. data/lib/fOOrth/monkey_patch.rb +14 -0
  119. data/lib/fOOrth/monkey_patch/complex.rb +30 -0
  120. data/lib/fOOrth/monkey_patch/exceptions.rb +154 -0
  121. data/lib/fOOrth/monkey_patch/false.rb +11 -0
  122. data/lib/fOOrth/monkey_patch/float.rb +22 -0
  123. data/lib/fOOrth/monkey_patch/integer.rb +22 -0
  124. data/lib/fOOrth/monkey_patch/nil.rb +11 -0
  125. data/lib/fOOrth/monkey_patch/numeric.rb +33 -0
  126. data/lib/fOOrth/monkey_patch/object.rb +43 -0
  127. data/lib/fOOrth/monkey_patch/rational.rb +31 -0
  128. data/lib/fOOrth/monkey_patch/string.rb +51 -0
  129. data/lib/fOOrth/symbol_map.rb +82 -0
  130. data/lib/fOOrth/version.rb +7 -0
  131. data/license.txt +21 -0
  132. data/rakefile.rb +65 -0
  133. data/reek.txt +1 -0
  134. data/sire.rb +132 -0
  135. data/t.txt +3 -0
  136. data/test.foorth +5 -0
  137. data/tests/compiler/context_tests.rb +180 -0
  138. data/tests/compiler/file_source_test_one.txt +1 -0
  139. data/tests/compiler/file_source_test_three.txt +3 -0
  140. data/tests/compiler/file_source_test_two.txt +3 -0
  141. data/tests/compiler/file_source_tests.rb +130 -0
  142. data/tests/compiler/mode_tests.rb +45 -0
  143. data/tests/compiler/parser_tests.rb +116 -0
  144. data/tests/compiler/spec_tests.rb +113 -0
  145. data/tests/compiler/string_source_tests.rb +128 -0
  146. data/tests/core_tests.rb +138 -0
  147. data/tests/interpreter/data_stack_tests.rb +119 -0
  148. data/tests/monkey_patch/coerce_test.rb +131 -0
  149. data/tests/monkey_patch/complex_test.rb +25 -0
  150. data/tests/monkey_patch/numeric_test.rb +62 -0
  151. data/tests/monkey_patch/object_test.rb +49 -0
  152. data/tests/monkey_patch/rational_test.rb +57 -0
  153. data/tests/monkey_patch/string_test.rb +53 -0
  154. data/tests/symbol_map_tests.rb +53 -0
  155. metadata +366 -0
@@ -0,0 +1,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