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.
- 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
|