fOOrth 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/.rdoc_options +17 -0
- data/Gemfile +4 -0
- data/README.md +67 -0
- data/bin/fOOrth +8 -0
- data/demo.rb +24 -0
- data/fOOrth.gemspec +40 -0
- data/fOOrth.reek +109 -0
- data/integration/README.md +12 -0
- data/integration/_FILE_test.foorth +5 -0
- data/integration/array_lib_tests.rb +360 -0
- data/integration/class_lib_tests.rb +116 -0
- data/integration/clone_lib_tests.rb +108 -0
- data/integration/comparison_tests.rb +132 -0
- data/integration/compile_lib_tests.rb +190 -0
- data/integration/ctrl_struct_lib_tests.rb +80 -0
- data/integration/data_ref_lib_tests.rb +43 -0
- data/integration/exception_lib_tests.rb +86 -0
- data/integration/fiber_bundle_tests.rb +380 -0
- data/integration/hash_lib_tests.rb +120 -0
- data/integration/in_stream_test_1.txt +4 -0
- data/integration/load_test_one.foorth +6 -0
- data/integration/load_test_two.foorth +4 -0
- data/integration/numeric_lib_tests.rb +321 -0
- data/integration/object_lib_tests.rb +38 -0
- data/integration/procedure_lib_tests.rb +40 -0
- data/integration/queue_lib_tests.rb +66 -0
- data/integration/stack_lib_tests.rb +70 -0
- data/integration/standard_lib_tests.rb +208 -0
- data/integration/stdio_lib_tests.rb +52 -0
- data/integration/stream_lib_tests.rb +196 -0
- data/integration/string_lib_tests.rb +217 -0
- data/integration/support/foorth_testing.rb +135 -0
- data/integration/thread_lib_tests.rb +83 -0
- data/integration/time_lib_tests.rb +791 -0
- data/integration/vm_lib_tests.rb +38 -0
- data/lib/fOOrth.rb +57 -0
- data/lib/fOOrth/compiler.rb +78 -0
- data/lib/fOOrth/compiler/context.rb +49 -0
- data/lib/fOOrth/compiler/context/locals.rb +34 -0
- data/lib/fOOrth/compiler/context/map_name.rb +92 -0
- data/lib/fOOrth/compiler/context/tags.rb +48 -0
- data/lib/fOOrth/compiler/modes.rb +32 -0
- data/lib/fOOrth/compiler/modes/compiled.rb +41 -0
- data/lib/fOOrth/compiler/modes/deferred.rb +57 -0
- data/lib/fOOrth/compiler/modes/delayed.rb +40 -0
- data/lib/fOOrth/compiler/modes/nested.rb +34 -0
- data/lib/fOOrth/compiler/modes/suspend.rb +32 -0
- data/lib/fOOrth/compiler/parser.rb +26 -0
- data/lib/fOOrth/compiler/parser/get_string.rb +71 -0
- data/lib/fOOrth/compiler/parser/normal.rb +53 -0
- data/lib/fOOrth/compiler/parser/skip.rb +50 -0
- data/lib/fOOrth/compiler/parser/special.rb +42 -0
- data/lib/fOOrth/compiler/process.rb +47 -0
- data/lib/fOOrth/compiler/process/generate.rb +24 -0
- data/lib/fOOrth/compiler/process/get_token.rb +23 -0
- data/lib/fOOrth/compiler/process/procedure.rb +55 -0
- data/lib/fOOrth/compiler/process/string.rb +20 -0
- data/lib/fOOrth/compiler/source.rb +51 -0
- data/lib/fOOrth/compiler/source/console.rb +70 -0
- data/lib/fOOrth/compiler/source/file_source.rb +37 -0
- data/lib/fOOrth/compiler/source/read_point.rb +46 -0
- data/lib/fOOrth/compiler/source/string_source.rb +28 -0
- data/lib/fOOrth/compiler/token.rb +37 -0
- data/lib/fOOrth/compiler/word_specs.rb +178 -0
- data/lib/fOOrth/core.rb +27 -0
- data/lib/fOOrth/core/class.rb +116 -0
- data/lib/fOOrth/core/object.rb +78 -0
- data/lib/fOOrth/core/virtual_machine.rb +28 -0
- data/lib/fOOrth/debug.rb +13 -0
- data/lib/fOOrth/debug/context_dump.rb +31 -0
- data/lib/fOOrth/debug/dbg_puts.rb +17 -0
- data/lib/fOOrth/debug/display_abort.rb +37 -0
- data/lib/fOOrth/debug/vm_dump.rb +27 -0
- data/lib/fOOrth/initialize.rb +83 -0
- data/lib/fOOrth/interpreter.rb +24 -0
- data/lib/fOOrth/interpreter/add_to_hash.rb +17 -0
- data/lib/fOOrth/interpreter/data_stack.rb +125 -0
- data/lib/fOOrth/interpreter/do_loop.rb +55 -0
- data/lib/fOOrth/interpreter/squash.rb +25 -0
- data/lib/fOOrth/library.rb +38 -0
- data/lib/fOOrth/library/array_library.rb +577 -0
- data/lib/fOOrth/library/bundle_library.rb +112 -0
- data/lib/fOOrth/library/class_library.rb +90 -0
- data/lib/fOOrth/library/clone_library.rb +72 -0
- data/lib/fOOrth/library/command_library.rb +205 -0
- data/lib/fOOrth/library/compile_library.rb +181 -0
- data/lib/fOOrth/library/complex_library.rb +81 -0
- data/lib/fOOrth/library/ctrl_struct_library.rb +116 -0
- data/lib/fOOrth/library/data_ref_library.rb +100 -0
- data/lib/fOOrth/library/duration/arithmetic.rb +114 -0
- data/lib/fOOrth/library/duration/formatter.rb +152 -0
- data/lib/fOOrth/library/duration/intervals.rb +233 -0
- data/lib/fOOrth/library/duration/make.rb +75 -0
- data/lib/fOOrth/library/duration_library.rb +52 -0
- data/lib/fOOrth/library/fiber_library.rb +120 -0
- data/lib/fOOrth/library/hash_library.rb +203 -0
- data/lib/fOOrth/library/in_stream_library.rb +81 -0
- data/lib/fOOrth/library/integer_library.rb +104 -0
- data/lib/fOOrth/library/mutex_library.rb +31 -0
- data/lib/fOOrth/library/numeric_library.rb +380 -0
- data/lib/fOOrth/library/object_library.rb +80 -0
- data/lib/fOOrth/library/other_value_types_library.rb +96 -0
- data/lib/fOOrth/library/out_stream_library.rb +146 -0
- data/lib/fOOrth/library/procedure_library.rb +65 -0
- data/lib/fOOrth/library/queue_library.rb +47 -0
- data/lib/fOOrth/library/rational_library.rb +90 -0
- data/lib/fOOrth/library/stack_library.rb +56 -0
- data/lib/fOOrth/library/stdio_library.rb +56 -0
- data/lib/fOOrth/library/string_library.rb +285 -0
- data/lib/fOOrth/library/stubs.rb +76 -0
- data/lib/fOOrth/library/sync_bundle_library.rb +50 -0
- data/lib/fOOrth/library/thread_library.rb +73 -0
- data/lib/fOOrth/library/time_library.rb +302 -0
- data/lib/fOOrth/library/vm_library.rb +105 -0
- data/lib/fOOrth/main.rb +125 -0
- data/lib/fOOrth/monkey_patch.rb +14 -0
- data/lib/fOOrth/monkey_patch/complex.rb +30 -0
- data/lib/fOOrth/monkey_patch/exceptions.rb +154 -0
- data/lib/fOOrth/monkey_patch/false.rb +11 -0
- data/lib/fOOrth/monkey_patch/float.rb +22 -0
- data/lib/fOOrth/monkey_patch/integer.rb +22 -0
- data/lib/fOOrth/monkey_patch/nil.rb +11 -0
- data/lib/fOOrth/monkey_patch/numeric.rb +33 -0
- data/lib/fOOrth/monkey_patch/object.rb +43 -0
- data/lib/fOOrth/monkey_patch/rational.rb +31 -0
- data/lib/fOOrth/monkey_patch/string.rb +51 -0
- data/lib/fOOrth/symbol_map.rb +82 -0
- data/lib/fOOrth/version.rb +7 -0
- data/license.txt +21 -0
- data/rakefile.rb +65 -0
- data/reek.txt +1 -0
- data/sire.rb +132 -0
- data/t.txt +3 -0
- data/test.foorth +5 -0
- data/tests/compiler/context_tests.rb +180 -0
- data/tests/compiler/file_source_test_one.txt +1 -0
- data/tests/compiler/file_source_test_three.txt +3 -0
- data/tests/compiler/file_source_test_two.txt +3 -0
- data/tests/compiler/file_source_tests.rb +130 -0
- data/tests/compiler/mode_tests.rb +45 -0
- data/tests/compiler/parser_tests.rb +116 -0
- data/tests/compiler/spec_tests.rb +113 -0
- data/tests/compiler/string_source_tests.rb +128 -0
- data/tests/core_tests.rb +138 -0
- data/tests/interpreter/data_stack_tests.rb +119 -0
- data/tests/monkey_patch/coerce_test.rb +131 -0
- data/tests/monkey_patch/complex_test.rb +25 -0
- data/tests/monkey_patch/numeric_test.rb +62 -0
- data/tests/monkey_patch/object_test.rb +49 -0
- data/tests/monkey_patch/rational_test.rb +57 -0
- data/tests/monkey_patch/string_test.rb +53 -0
- data/tests/symbol_map_tests.rb +53 -0
- 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
|