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,27 @@
1
+ # coding: utf-8
2
+
3
+ require_relative 'compiler/word_specs'
4
+ require_relative 'core/object'
5
+ require_relative 'core/class'
6
+ require_relative 'core/virtual_machine'
7
+
8
+ #* core.rb - The fOOrth language OO core.
9
+ module XfOOrth
10
+
11
+ $FOORTH_GLOBALS = Hash.new
12
+ Object.create_foorth_proxy
13
+ Class.create_foorth_proxy
14
+ VirtualMachine.create_foorth_proxy('VirtualMachine')
15
+
16
+ #Predefine the default implementation of the .init method. This method must
17
+ #exist at this point in order to proceed further.
18
+ name = '.init'
19
+ sym = SymbolMap.add_entry(name, :foorth_init)
20
+ Object.create_shared_method(name, TosSpec, [], &lambda {|vm| })
21
+
22
+ #Create a virtual machine instance for the main thread. The constructor
23
+ #connects the new instance to a thread variable so we don't need to do
24
+ #anything with it here.
25
+ VirtualMachine.new('Main')
26
+
27
+ end
@@ -0,0 +1,116 @@
1
+ # coding: utf-8
2
+
3
+ #* The additions to the Ruby Class class required to support fOOrth.
4
+ class Class
5
+
6
+ #Get the foorth name of this class.
7
+ #<br>Decree!
8
+ #* These are to be the only references to @_private_foorth_name!
9
+ def foorth_name
10
+ @_private_foorth_name ||= name
11
+ end
12
+
13
+ #Set the foorth name of this class.
14
+ #<br>Decree!
15
+ #* These are to be the only references to @_private_foorth_name!
16
+ def foorth_name=(new_name)
17
+ @_private_foorth_name = new_name
18
+ end
19
+
20
+ #Access/create the class's shared fOOrth dictionary.
21
+ #<br>Decree!
22
+ #* This is to be the only reference to @_private_foorth_shared!
23
+ def foorth_shared
24
+ @_private_foorth_shared ||= Hash.new
25
+ end
26
+
27
+ #Create a shared method on this fOOrth class.
28
+ #<br>Parameters:
29
+ #* name - The name of the method to create.
30
+ #* spec_class - The specification class to use.
31
+ #* options - An array of options.
32
+ #* block - A block to associate with the name.
33
+ #<br>Returns
34
+ #* The spec created for the shared method.
35
+ def create_shared_method(name, spec_class, options, &block)
36
+ sym = XfOOrth::SymbolMap.add_entry(name)
37
+ spec = spec_class.new(name, sym, options, &block)
38
+
39
+ unless self == Object && options.include?(:stub)
40
+ define_method(sym, &spec.does)
41
+ end
42
+
43
+ foorth_shared[sym] = spec
44
+ end
45
+
46
+ #Map the symbol to a specification or nil if there is no mapping.
47
+ def map_foorth_shared(symbol)
48
+ foorth_shared[symbol] || ((sc = superclass) && sc.map_foorth_shared(symbol))
49
+ end
50
+
51
+ #Create an instance of this fOOrth class.
52
+ #<br>Parameters:
53
+ #* vm - The current fOOrth virtual machine.
54
+ def create_foorth_instance(vm)
55
+ (obj = self.new).foorth_init(vm)
56
+ obj
57
+ end
58
+
59
+ #Create a new fOOrth subclass of this class.
60
+ #<br>Parameters:
61
+ #* foorth_name - The foorth_name of the new sub-class.
62
+ #<br>Returns:
63
+ #* The spec of the subclass.
64
+ #<br>Note:
65
+ #* If a sub-class with the given name already exists, an exception is raised.
66
+ def create_foorth_subclass(foorth_name)
67
+ if $FOORTH_GLOBALS[XfOOrth::SymbolMap.map(foorth_name)]
68
+ error "F10: The class #{foorth_name} already exists."
69
+ end
70
+
71
+ validate_class_name(foorth_name)
72
+
73
+ new_class = Class.new(self) {self.foorth_name = foorth_name}
74
+
75
+ XfOOrth.const_set('XfOOrth_' + foorth_name, new_class)
76
+ install_foorth_class(foorth_name, new_class)
77
+ end
78
+
79
+ #Add this class as a proxy class in the foorth class system.
80
+ #<br>Parameters:
81
+ #* proxy_name - the optional name of the proxy. Defaults to the Ruby name.
82
+ #<br>Returns:
83
+ #* The spec of the proxy class.
84
+ def create_foorth_proxy(proxy_name = nil)
85
+ if proxy_name
86
+ self.foorth_name = proxy_name
87
+ end
88
+
89
+ validate_class_name(foorth_name)
90
+
91
+ error "F10: The class #{foorth_name} already exists." if $FOORTH_GLOBALS[foorth_name]
92
+
93
+ install_foorth_class(foorth_name, self)
94
+ end
95
+
96
+ private
97
+
98
+ #Connect the class named foorth_name to the foorth system.
99
+ #<br>Returns:
100
+ #* The newly created spec object.
101
+ #<br> Endemic Code Smells
102
+ #* :reek:UtilityFunction
103
+ def install_foorth_class(new_name, new_class)
104
+ fail "Bad name" unless new_name
105
+ symbol = XfOOrth::SymbolMap.add_entry(new_name)
106
+ $FOORTH_GLOBALS[symbol] = XfOOrth::ClassSpec.new(new_class, nil, [:class])
107
+ end
108
+
109
+ #Is this a valid class name?
110
+ def validate_class_name(name)
111
+ unless /^[A-Z][A-Za-z0-9]+$/ =~ name
112
+ error "F10: Invalid class name #{name}"
113
+ end
114
+ end
115
+
116
+ end
@@ -0,0 +1,78 @@
1
+ # coding: utf-8
2
+
3
+ #* The additions to the Ruby Object class required to support fOOrth.
4
+ class Object
5
+
6
+ #Get the foorth name of this object.
7
+ def foorth_name
8
+ "#{self.class.foorth_name} instance"
9
+ end
10
+
11
+ #Access/create the object's exclusive fOOrth dictionary.
12
+ #<br>Decree!
13
+ #* These are to be the only reference to @_private_foorth_exclusive!
14
+ def foorth_exclusive
15
+ @_private_foorth_exclusive ||= Hash.new
16
+ end
17
+
18
+ #Does this object have exclusive methods defined on it?
19
+ #<br>Decree!
20
+ #* These are to be the only reference to @_private_foorth_exclusive!
21
+ def foorth_has_exclusive?
22
+ instance_variable_defined?(:@_private_foorth_exclusive)
23
+ end
24
+
25
+ #Create an exclusive method on this fOOrth object.
26
+ #<br>Parameters:
27
+ #* name - The name of the method to create.
28
+ #* spec_class - The specification class to use.
29
+ #* options - An array of options.
30
+ #* block - A block to associate with the name.
31
+ #<br>Returns
32
+ #* The spec created for the shared method.
33
+ def create_exclusive_method(name, spec_class, options, &block)
34
+ sym = XfOOrth::SymbolMap.add_entry(name)
35
+ spec = spec_class.new(name, sym, options, &block)
36
+ cache_exclusive_method(sym, &spec.does)
37
+ foorth_exclusive[sym] = spec
38
+ end
39
+
40
+ #Load the new exclusive method into the object.
41
+ def cache_exclusive_method(symbol, &block)
42
+ define_singleton_method(symbol, &block)
43
+ rescue TypeError
44
+ error "F13: Exclusive methods not allowed for type: #{self.class.foorth_name}"
45
+ end
46
+
47
+ #Map the symbol to a specification or nil if there is no mapping.
48
+ def map_foorth_exclusive(symbol)
49
+ (foorth_has_exclusive? && foorth_exclusive[symbol]) ||
50
+ self.class.map_foorth_shared(symbol)
51
+ end
52
+
53
+ #The default foorth_init method does nothing.
54
+ def foorth_init(_vm)
55
+ end
56
+
57
+ #The \method_missing hook is used to provide meaningful error messages
58
+ #when problems are encountered.
59
+ #<br>Parameters:
60
+ #* symbol - The symbol of the missing method.
61
+ #* args - Any arguments that were passed to that method.
62
+ #* block - Any block that might have passed to the method.
63
+ #<br>Note:
64
+ #* Since stubs for Object class do not create methods, an attempt is made
65
+ # to execute the stub if the symbol maps and is in the Object class.
66
+ def method_missing(symbol, *args, &block)
67
+ if (name = XfOOrth::SymbolMap.unmap(symbol))
68
+ if (stub_spec = Object.foorth_shared[symbol])
69
+ self.instance_exec(*args, &stub_spec.does)
70
+ else
71
+ error "F20: A #{self.foorth_name} does not understand #{name} (#{symbol})."
72
+ end
73
+ else
74
+ super
75
+ end
76
+ end
77
+
78
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+
3
+ #* core/virtual_machine.rb - The core connection to the virtual machine.
4
+ module XfOOrth
5
+
6
+ #* core/virtual_machine.rb - The core connection to the virtual machine.
7
+ class VirtualMachine
8
+
9
+ #The name of the virtual machine instance
10
+ def foorth_name
11
+ "#{self.class.foorth_name} instance <#{@name}>"
12
+ end
13
+
14
+ #The currently active fiber, if any.
15
+ attr_accessor :fiber
16
+
17
+ class << self
18
+
19
+ #Create a new fOOrth subclass of this class. This is not allowed for the
20
+ #VirtualMachine class so this stub merely raises an exception.
21
+ def create_foorth_subclass(_name)
22
+ error "F13: Forbidden operation: (VirtualMachine.create_foorth_subclass)."
23
+ end
24
+
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,13 @@
1
+ # coding: utf-8
2
+
3
+ require_relative 'debug/display_abort'
4
+ require_relative 'debug/dbg_puts'
5
+ require_relative 'debug/context_dump'
6
+ require_relative 'debug/vm_dump'
7
+
8
+ #Set up the default debug conduit.
9
+ $foorth_dbg = $stdout
10
+
11
+ #* debug.rb - Internal debug support.
12
+ module XfOOrth
13
+ end
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+
3
+ #* debug/context_dump.rb - Debug support for the compiler context.
4
+ module XfOOrth
5
+
6
+ #* debug/context_dump.rb - Debug support for the compiler context.
7
+ class Context
8
+
9
+ #Dump the context chain to the console for debug.
10
+ #<br>Parameters
11
+ #* vm - The current virtual machine for this thread.
12
+ def debug_dump(vm)
13
+ puts "\nContext level #{self.depth}"
14
+
15
+ @data.each do |key, value|
16
+ if key == :vm
17
+ puts "virtual machine => #{value.foorth_name}"
18
+ else
19
+ if (name = SymbolMap.unmap(key))
20
+ key = name.inspect
21
+ end
22
+
23
+ puts "#{key} => #{value}"
24
+ end
25
+ end
26
+
27
+ (prev = self.previous) && prev.debug_dump(vm)
28
+ end
29
+ end
30
+
31
+ end
@@ -0,0 +1,17 @@
1
+ # coding: utf-8
2
+
3
+ #* debug/dbg_puts.rb - Display diagnostic/debug information if enabled.
4
+ module XfOOrth
5
+
6
+ #* debug/dbg_puts.rb - Display diagnostic/debug information if enabled.
7
+ class VirtualMachine
8
+
9
+ #Send out debug info to the fOOrth debug port if debug is enabled.
10
+ def dbg_puts(*args)
11
+ $foorth_dbg.puts(*args) if debug
12
+ end
13
+
14
+ end
15
+
16
+ end
17
+
@@ -0,0 +1,37 @@
1
+ # coding: utf-8
2
+
3
+ #* debug/display_abort.rb - Display diagnostic information on an error.
4
+ module XfOOrth
5
+
6
+ #* debug/display_abort.rb - Display diagnostic information on an error.
7
+ class VirtualMachine
8
+
9
+ #Display the diagnostic data required for a language abort error.
10
+ #<br>Parameters:
11
+ #* exception - The exception object that required the system abort or a
12
+ # string describing the error that was encountered.
13
+ def display_abort(exception)
14
+ puts "\n#{exception.foorth_message}"
15
+
16
+ if debug
17
+ puts "Data Stack Contents: #{data_stack.inspect}"
18
+
19
+ if @context
20
+ @context.debug_dump(self)
21
+ else
22
+ puts "Error: No context is available!"
23
+ end
24
+
25
+ puts "\nInternal Backtrace Dump:"
26
+ puts
27
+ puts exception.backtrace
28
+ puts
29
+ end
30
+
31
+ reset
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+
3
+ #* debug/vm_dump.rb - Debug support for the virtual machine.
4
+ module XfOOrth
5
+
6
+ #* debug/vm_dump.rb - Debug support for the virtual machine.
7
+ class VirtualMachine
8
+
9
+ #Dump the virtual machine to the console for debug.
10
+ def debug_dump
11
+ source = @parser && @parser.source
12
+
13
+ puts "\n#{self.foorth_name}" \
14
+ "\n Ruby = #{self.to_s}" \
15
+ "\n Stack = #{@data_stack.inspect}" \
16
+ "\n Nesting = #{@context.depth}" \
17
+ "\n Quotes = #{@quotes}" \
18
+ "\n Debug = #{@debug}" \
19
+ "\n Show = #{@show_stack}" \
20
+ "\n Force = #{@force}" \
21
+ "\n Start = #{@start_time}" \
22
+ "\n Source = #{source && source.source_name}" \
23
+ "\n Buffer = #{source && source.read_buffer.inspect}"
24
+ end
25
+ end
26
+
27
+ end
@@ -0,0 +1,83 @@
1
+ # coding: utf-8
2
+
3
+ #* initialize.rb - The initialize method for the virtual machine
4
+ module XfOOrth
5
+
6
+ #* initialize.rb - The initialize method for the virtual machine
7
+ class VirtualMachine
8
+
9
+ #Get or create a virtual machine for this thread.
10
+ #<br>Paramters:
11
+ #* name - The name of the virtual machine, if one is created. If a virtual
12
+ # machine already exists for this thread, this parameter is ignored.
13
+ #<br>Note: Non-intuitive code.
14
+ #* VitualMachine.new connects to the thread, setting up
15
+ # \Thread.current[:vm] as a side-effect. Thus it is not done here.
16
+ def self.vm(name='-')
17
+ Thread.current[:vm] || VirtualMachine.new(name)
18
+ end
19
+
20
+ #Set true for verbose compiler play-by-plays and detailed error reports.
21
+ attr_accessor :debug
22
+
23
+ #Set true to print out the data stack after every interactive line is processed.
24
+ attr_accessor :show_stack
25
+
26
+ #The descriptive name of this virtual machine.
27
+ attr_reader :name
28
+
29
+ #The thread data associated with this virtual machine.
30
+ attr_reader :data
31
+
32
+ #Create an new instance of a fOOrth virtual machine
33
+ #<br>Parameters:
34
+ #* name - An optional string that describes this virtual machine instance.
35
+ #<br>Note
36
+ #* A XfOOrthError will be raised if an attempt is made to create more than
37
+ # one virtual machine on a thread.
38
+ def initialize(name='-')
39
+ @name, @debug, @show_stack, @data = name, false, false, {}
40
+
41
+ #Bring the major sub-systems to a known state.
42
+ self.reset.connect_vm_to_thread
43
+ end
44
+
45
+ #Create a copy of a donor vm instance.
46
+ #<br>Parameters:
47
+ #* name - An optional string that describes this virtual machine instance.
48
+ def foorth_copy(name)
49
+ copy = self.clone
50
+ copy.reinitialize(name)
51
+ copy
52
+ end
53
+
54
+ #Get the vm ready for operation
55
+ #<br>Parameters:
56
+ #* name - A string that describes this virtual machine instance.
57
+ def reinitialize(name)
58
+ @data_stack = @data_stack.clone
59
+ @name = name
60
+ @data = @data.full_clone
61
+ end
62
+
63
+ #Reset the interpreter and the compiler.
64
+ def reset
65
+ interpreter_reset
66
+ compiler_reset
67
+ end
68
+
69
+ #Connect the vm to a thread variable.
70
+ def connect_vm_to_thread
71
+ #Check for duplicates.
72
+ current = Thread.current
73
+ error "F91: Only one virtual machine allowed per thread" if current[:vm]
74
+
75
+ #This virtual machine is associated with this thread.
76
+ current[:vm] = self
77
+ @start_time = Time.now
78
+
79
+ self
80
+ end
81
+ end
82
+
83
+ end