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,24 @@
1
+ # coding: utf-8
2
+
3
+ #* compiler/process/generate.rb - Generate the Ruby object code.
4
+ module XfOOrth
5
+
6
+ #* compiler/process/generate.rb - Generate the Ruby object code.
7
+ class VirtualMachine
8
+
9
+ #Finally generate some code!
10
+ #<br>Parameters:
11
+ #* token - The token to receive the generated code.
12
+ #* word - The text of the word.
13
+ def generate_code(token, word)
14
+ if (spec = @context.map(word))
15
+ token.add(spec.builds, spec.tags)
16
+ elsif (value = word.to_foorth_n)
17
+ token.add("vm.push(#{value.foorth_embed}); ", [:numeric])
18
+ else
19
+ error "F10: ?#{word}?"
20
+ end
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+
3
+ #* compiler/process/get_token.rb - Get a complete language element.
4
+ module XfOOrth
5
+
6
+ #* compiler/process/get_token.rb - Get a complete language element.
7
+ class VirtualMachine
8
+
9
+ #Get the next token structure from the source code or nil if none
10
+ #can be found.
11
+ #<br>Returns
12
+ #* A Token structure or nil.
13
+ def get_token
14
+ return nil unless (word = parser.get_word)
15
+
16
+ token = Token.new
17
+ string_parms(token, word) || procedure_parms(token, word)
18
+ generate_code(token, word)
19
+ token
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,55 @@
1
+ # coding: utf-8
2
+
3
+ #* compiler/process/procedure.rb - Get an embedded procedure literal.
4
+ module XfOOrth
5
+
6
+ #* compiler/process/procedure.rb - Get an embedded procedure literal.
7
+ class VirtualMachine
8
+
9
+ private
10
+
11
+ #Process optional string parameters.
12
+ #<br>Parameters:
13
+ #* token - The token to receive the generated code.
14
+ #* word - The text of the word.
15
+ def procedure_parms(token, word)
16
+ if word.end_with?('{{')
17
+ token.add(get_procedure_literal, [:procedure])
18
+ end
19
+ end
20
+
21
+ #Extract a procedure literal from the source code.
22
+ def get_procedure_literal
23
+ save, @buffer = @buffer, ""
24
+ open_procedure_literal
25
+
26
+ begin
27
+ token = get_procedure_token
28
+ due_token(token)
29
+ end until token.has_tag?(:end)
30
+
31
+ close_procedure_literal
32
+ (result, @buffer = @buffer, save)[0]
33
+ end
34
+
35
+ #Handle the opening of a procedure literal.
36
+ def open_procedure_literal
37
+ suspend_execute_mode("vm.push(lambda {|vm, val=nil, idx=nil| ", :procedure)
38
+ context.create_local_method('v', MacroSpec, [:macro, "vm.push(val); "])
39
+ context.create_local_method('x', MacroSpec, [:macro, "vm.push(idx); "])
40
+ context.create_local_method('}}', MacroSpec, [:macro, :end, "}); "])
41
+ end
42
+
43
+ #Handle the closing of a procedure literal.
44
+ def close_procedure_literal
45
+ unnest_mode(nil, [:procedure])
46
+ end
47
+
48
+ #Get a token for the procedure literal.
49
+ def get_procedure_token
50
+ error "F12: Error, Invalid nesting." unless (token = get_token)
51
+ token
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,20 @@
1
+ # coding: utf-8
2
+
3
+ #* compiler/process/string.rb - Get an embedded string literal.
4
+ module XfOOrth
5
+
6
+ #* compiler/process/string.rb - Get an embedded string literal.
7
+ class VirtualMachine
8
+
9
+ #Process optional string parameters.
10
+ #<br>Parameters:
11
+ #* token - The token to receive the generated code.
12
+ #* word - The text of the word.
13
+ def string_parms(token, word)
14
+ if word.end_with?('"')
15
+ token.add("vm.push(#{parser.get_string.foorth_embed}); ")
16
+ end
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,51 @@
1
+ # coding: utf-8
2
+
3
+ require_relative 'source/read_point'
4
+
5
+ #* compiler/source.rb - The abstract source class shared by many code sources.
6
+ module XfOOrth
7
+
8
+ #The Source class used to contain code common to most sources.
9
+ class AbstractSource
10
+ include ReadPoint
11
+
12
+ #Initialize the abstract base class.
13
+ def initialize
14
+ reset_read_point
15
+ @eof = false
16
+ end
17
+
18
+ #Close the source.
19
+ def close
20
+ @eoln = true
21
+ @eof = true
22
+ end
23
+
24
+ #Get the next character of input data
25
+ #<br>Returns:
26
+ #* The next character or nil if none are available.
27
+ def get
28
+ return nil if @eof
29
+
30
+ read do
31
+ begin
32
+ @read_step.next.rstrip
33
+ rescue StopIteration
34
+ @eof = true
35
+ nil
36
+ end
37
+ end
38
+ end
39
+
40
+ #Has the source reached the end of the available data?
41
+ #<br>Returns:
42
+ #* True if the end is reached else false.
43
+ def eof?
44
+ @eof
45
+ end
46
+ end
47
+ end
48
+
49
+ require_relative 'source/string_source'
50
+ require_relative 'source/file_source'
51
+ require_relative 'source/console'
@@ -0,0 +1,70 @@
1
+ # coding: utf-8
2
+
3
+ #* compiler/console.rb - The fOOrth console support file.
4
+ module XfOOrth
5
+
6
+ #The console class enables the use of the command line console as a source
7
+ #for fOOrth commands and source code. The readline facility is used to enable
8
+ #editing and command history and retrieval.
9
+ class Console
10
+ include ReadPoint
11
+
12
+ #Initialize a new console command source.
13
+ def initialize
14
+ reset_read_point
15
+
16
+ auto_src = lambda { SymbolMap.forward_map.keys.sort }
17
+
18
+ @edit = MiniReadline::Readline.new(history: true,
19
+ auto_complete: true,
20
+ auto_source: MiniReadline::ArraySource,
21
+ array_src: auto_src,
22
+ eoi_detect: true)
23
+ end
24
+
25
+ alias close reset_read_point
26
+ alias flush reset_read_point
27
+
28
+ #Get the next character of command text from the user.
29
+ #<br>Returns
30
+ #* The next character of user input as a string.
31
+ def get
32
+ read do
33
+ @edit.readline(prompt: prompt).rstrip
34
+ end
35
+ end
36
+
37
+ #Has the scanning of the text reached the end of input?
38
+ #<br>Returns
39
+ #* Always returns false.
40
+ def eof?
41
+ false
42
+ end
43
+
44
+ #Build the command prompt for the user based on the state
45
+ #of the virtual machine.
46
+ #<br>Returns
47
+ #* A prompt string.
48
+ #<br> Endemic Code Smells
49
+ #* :reek:FeatureEnvy
50
+ def prompt
51
+ vm = Thread.current[:vm]
52
+ puts
53
+
54
+ if vm.show_stack
55
+ vm.data_stack.to_foorth_s(vm)
56
+ puts vm.pop
57
+ end
58
+
59
+ '>' * vm.context.depth + '"' * vm.quotes
60
+ end
61
+
62
+ #What is the source of this text?
63
+ def source_name
64
+ "The console."
65
+ end
66
+
67
+ alias :file_name :source_name
68
+
69
+ end
70
+ end
@@ -0,0 +1,37 @@
1
+ # coding: utf-8
2
+
3
+ #* compiler/file_source.rb - Uses a file as a source of fOOrth source code.
4
+ module XfOOrth
5
+
6
+ #The FileSource class used to extract fOOrth source code
7
+ #from a string.
8
+ class FileSource < AbstractSource
9
+
10
+ #Initialize from a file name.
11
+ #<br>Parameters:
12
+ #* name - The name of the file with the fOOrth source code.
13
+ def initialize(name)
14
+ @name = name
15
+ @file = File.new(name, "r")
16
+ @read_step = @file.each_line
17
+ super()
18
+ end
19
+
20
+ #Close the file
21
+ def close
22
+ @file.close
23
+ super()
24
+ end
25
+
26
+ #What is the source of this text?
27
+ def source_name
28
+ "A file: #{@name}"
29
+ end
30
+
31
+ #Get the name of the file
32
+ def file_name
33
+ File.absolute_path(@name)
34
+ end
35
+ end
36
+
37
+ end
@@ -0,0 +1,46 @@
1
+ # coding: utf-8
2
+
3
+ #* compiler/read_point.rb - A module used to read source code text from a buffer.
4
+ module XfOOrth
5
+
6
+ #This module is used to facilitate the reading
7
+ #of source code text from a buffer.
8
+ module ReadPoint
9
+ #Get the current line of text being read.
10
+ attr_reader :read_buffer
11
+
12
+ #Reset the read point to the initial conditions. Namely,
13
+ #no text in the buffer and not at end of line,
14
+ def reset_read_point
15
+ @read_point = nil
16
+ @eoln = false
17
+ end
18
+
19
+ #Read the next character of data from the source. If there
20
+ #is nothing to read, call the block to get some more data to
21
+ #work with.
22
+ #<br>Parameters
23
+ #* block - A block of code that retrieves the next line of
24
+ # source code to be processed.
25
+ def read(&block)
26
+ unless @read_point
27
+ return nil unless (@read_buffer = block.call)
28
+ @read_point = @read_buffer.each_char
29
+ end
30
+
31
+ begin
32
+ result, @eoln = @read_point.next, false
33
+ rescue StopIteration
34
+ result, @read_point, @eoln = ' ', nil, true
35
+ end
36
+
37
+ result
38
+ end
39
+
40
+ #Is the read point at the end of line?
41
+ def eoln?
42
+ @eoln
43
+ end
44
+ end
45
+
46
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+
3
+ #* compiler/string_source.rb - Uses a string as a source of fOOrth source code.
4
+ module XfOOrth
5
+
6
+ #The StringSource class used to extract fOOrth source code
7
+ #from a string.
8
+ class StringSource < AbstractSource
9
+
10
+ #Initialize from a string.
11
+ #<br>Parameters:
12
+ #* string - A string of fOOrth source code.
13
+ def initialize(string)
14
+ @string_list = string.split("\n")
15
+ @read_step = @string_list.each
16
+ super()
17
+ end
18
+
19
+ #What is the source of this text?
20
+ def source_name
21
+ "A string."
22
+ end
23
+
24
+ alias :file_name :source_name
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,37 @@
1
+ # coding: utf-8
2
+
3
+ #* compiler/token.rb - A little bit of object code compiled from the source.
4
+ module XfOOrth
5
+
6
+ #A class used to hold vital info extracted from the source code.
7
+ class Token
8
+
9
+ #The code fragment in this token.
10
+ attr_reader :code
11
+
12
+ #Set up an empty token
13
+ def initialize
14
+ @code = ''
15
+ @tags = []
16
+ end
17
+
18
+ #Append some text/tags to the code_fragment.
19
+ def add(text, tags=nil)
20
+ @code << text
21
+ @tags.concat(tags).uniq! if tags
22
+ self
23
+ end
24
+
25
+ #Does this token have the specified tag?
26
+ def has_tag?(value)
27
+ @tags.include?(value)
28
+ end
29
+
30
+ #As a string for debugging.
31
+ def to_s
32
+ "Tags=#{@tags.inspect} Code=#{@code.inspect}"
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1,178 @@
1
+ # coding: utf-8
2
+
3
+ #* compiler/word_specs.rb - The classes that support the specification of the
4
+ # compile and run-time behaviors of fOOrth definitions of all sorts.
5
+ module XfOOrth
6
+
7
+ #The abstract base class for all of the different sorts of word specs.
8
+ class AbstractWordSpec
9
+
10
+ #The compile-time text inserted into the buffer.
11
+ attr_reader :builds
12
+
13
+ #The run-time action; The block that gets linked to the method's symbol.
14
+ attr_reader :does
15
+
16
+ #The attributes tagged to this specification.
17
+ attr_reader :tags
18
+
19
+ #Set up the method spec.
20
+ #<br>Parameters:
21
+ #* name - The string that maps to the symbol.
22
+ #* symbol - The symbol that the name maps to.
23
+ #* tags - A an array of tags.
24
+ #<br>These may include:
25
+ #* :immediate - The word is executed, even in compile modes.
26
+ #* :macro - Identifies the spec as a macro spec to assist debugging.
27
+ #* :stub - The word is a place holder in the hierarchy.
28
+ #<br>Endemic Code Smells
29
+ #* :reek:ControlParameter -- false positive
30
+ def initialize(name, symbol, tags=[], &block)
31
+ @tags = tags
32
+ @does = block || get_stub_action(name, symbol)
33
+ build_builds_string(name, symbol)
34
+ end
35
+
36
+ #Get the default action if none is specified.
37
+ def get_stub_action(name, symbol)
38
+ lambda do |*_any|
39
+ error "F20: A #{self.foorth_name} does not understand #{name} (#{symbol.inspect})."
40
+ end
41
+ end
42
+
43
+ #Look up an tag of interest.
44
+ def has_tag?(tag)
45
+ @tags.include?(tag)
46
+ end
47
+
48
+ end
49
+
50
+ #A class used to specify the compile of VM words.
51
+ class VmSpec < AbstractWordSpec
52
+ #Generate the Ruby code for this method.
53
+ #<br>Parameters:
54
+ #* _name - The string that maps to the symbol. Unused
55
+ #* symbol - The symbol that the name maps to.
56
+ def build_builds_string(_name, symbol)
57
+ @builds = "vm.#{symbol}(vm); "
58
+ end
59
+ end
60
+
61
+ #A class used to specify the compile of public methods of a class or object.
62
+ class TosSpec < AbstractWordSpec
63
+ #Generate the Ruby code for this method.
64
+ #<br>Parameters:
65
+ #* _name - The string that maps to the symbol. Unused
66
+ #* symbol - The symbol that the name maps to.
67
+ def build_builds_string(_name, symbol)
68
+ @builds = "vm.pop.#{symbol}(vm); "
69
+ end
70
+ end
71
+
72
+ #A class used to specify the compile of private methods of a class or object.
73
+ class SelfSpec < AbstractWordSpec
74
+ #Generate the Ruby code for this method.
75
+ #<br>Parameters:
76
+ #* _name - The string that maps to the symbol. Unused
77
+ #* symbol - The symbol that the name maps to.
78
+ def build_builds_string(_name, symbol)
79
+ @builds = "self.#{symbol}(vm); "
80
+ end
81
+ end
82
+
83
+ #A class used to specify the compile of dyadic operators.
84
+ class NosSpec < AbstractWordSpec
85
+ #Generate the Ruby code for this dyadic operator.
86
+ #<br>Parameters:
87
+ #* _name - The string that maps to the symbol. Unused
88
+ #* symbol - The symbol that the name maps to.
89
+ def build_builds_string(_name, symbol)
90
+ @builds = "vm.swap_pop.#{symbol}(vm); "
91
+ end
92
+
93
+ #Get the default action if none is specified.
94
+ def get_stub_action(name, symbol)
95
+ lambda do |vm|
96
+ #NOS methods can leave an extra bit of mess on the stack which must
97
+ #be cleaned up at this time or it will cause further problems.
98
+ vm.data_stack.pop
99
+
100
+ error "F20: A #{self.foorth_name} does not understand #{name} (#{symbol.inspect})."
101
+ end
102
+ end
103
+
104
+ end
105
+
106
+ #A class used to specify the compile of fOOrth classes.
107
+ class ClassSpec < AbstractWordSpec
108
+ #Generate the Ruby code for this fOOrth class.
109
+ #<br>Parameters:
110
+ #* \new_class - The string that maps to the symbol.
111
+ #* _symbol - The symbol that the name maps to. Unused
112
+ def build_builds_string(new_class, _symbol)
113
+ @new_class = new_class
114
+ @builds = "vm.push(#{new_class.name}); "
115
+ end
116
+
117
+ #Give read access to the class for testing.
118
+ attr_reader :new_class
119
+ end
120
+
121
+ #A class used to specify the compile of fOOrth instances variables.
122
+ class InstanceVarSpec < AbstractWordSpec
123
+ #Generate the Ruby code for this fOOrth variable.
124
+ #<br>Parameters:
125
+ #* _name - The string that maps to the symbol. Unused
126
+ #* symbol - The symbol that the name maps to.
127
+ def build_builds_string(_name, symbol)
128
+ @builds = "vm.push(#{'@'+(symbol.to_s)}); "
129
+ end
130
+ end
131
+
132
+ #A class used to specify the compile of fOOrth thread variables.
133
+ class ThreadVarSpec < AbstractWordSpec
134
+ #Generate the Ruby code for this fOOrth variable.
135
+ #<br>Parameters:
136
+ #* _name - The string that maps to the symbol. Unused
137
+ #* symbol - The symbol that the name maps to.
138
+ def build_builds_string(_name, symbol)
139
+ @builds = "vm.push(vm.data[#{symbol.inspect}]); "
140
+ end
141
+ end
142
+
143
+ #A class used to specify the compile of fOOrth global variables.
144
+ class GlobalVarSpec < AbstractWordSpec
145
+ #Generate the Ruby code for this fOOrth variable.
146
+ #<br>Parameters:
147
+ #* _name - The string that maps to the symbol. Unused
148
+ #* symbol - The symbol that the name maps to.
149
+ def build_builds_string(_name, symbol)
150
+ @builds = "vm.push(#{'$' + symbol.to_s}); "
151
+ end
152
+ end
153
+
154
+ #A class used to specify the compile of fOOrth variable.
155
+ class LocalSpec < AbstractWordSpec
156
+ #Generate the Ruby code for this fOOrth variable.
157
+ #<br>Parameters:
158
+ #* _name - The string that maps to the symbol. Unused
159
+ #* symbol - The symbol that the name maps to.
160
+ def build_builds_string(_name, symbol)
161
+ @builds = "vm.context[#{symbol.inspect}].does.call(vm); "
162
+ end
163
+ end
164
+
165
+ #A class used to specify the compile of fOOrth macros.
166
+ class MacroSpec < AbstractWordSpec
167
+ #Generate the Ruby code for this macro.
168
+ #<br>Parameters:
169
+ #* _name - The string that maps to the symbol. Unused
170
+ #* _symbol - The symbol that the name maps to. Unused
171
+ #<br>Note:
172
+ #* The last entry in the tags array is expected to be a string
173
+ # with the text of the command macro.
174
+ def build_builds_string(_name, _symbol)
175
+ @builds = @tags.pop
176
+ end
177
+ end
178
+ end