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
data/lib/fOOrth/main.rb
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'getoptlong'
|
|
4
|
+
|
|
5
|
+
#* main.rb - The entry point for a stand-alone foorth session.
|
|
6
|
+
module XfOOrth
|
|
7
|
+
|
|
8
|
+
#The user facing format used for date/time display.
|
|
9
|
+
TimeFormat = '%Y-%m-%d at %I:%M%P'
|
|
10
|
+
|
|
11
|
+
#The starting point for an interactive fOOrth programming session.
|
|
12
|
+
#This method only returns when the session is closed.
|
|
13
|
+
#<br>Returns:
|
|
14
|
+
#* The virtual machine used to run the session.
|
|
15
|
+
#<br>To launch a fOOrth interactive session, simply use:
|
|
16
|
+
# XfOOrth::main
|
|
17
|
+
#<br>Endemic Code Smells
|
|
18
|
+
#* :reek:TooManyStatements
|
|
19
|
+
def self.main
|
|
20
|
+
vm = VirtualMachine.vm('Console')
|
|
21
|
+
running = false
|
|
22
|
+
|
|
23
|
+
loop do
|
|
24
|
+
begin
|
|
25
|
+
running ||= start_up(vm)
|
|
26
|
+
vm.process_console
|
|
27
|
+
|
|
28
|
+
rescue Interrupt, ForceExit, SilentExit, MiniReadlineEOI => err
|
|
29
|
+
puts "\n#{err.foorth_message}"
|
|
30
|
+
break
|
|
31
|
+
|
|
32
|
+
rescue StandardError => err
|
|
33
|
+
vm.display_abort(err)
|
|
34
|
+
|
|
35
|
+
rescue Exception => err
|
|
36
|
+
puts "\n#{err.class.to_s.gsub(/.*::/, '')} detected: #{err}"
|
|
37
|
+
puts err.backtrace
|
|
38
|
+
break
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
break unless running
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
vm
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
#Perform one time start-up actions.
|
|
48
|
+
def self.start_up(vm)
|
|
49
|
+
announcements
|
|
50
|
+
vm.debug = false
|
|
51
|
+
vm.show_stack = false
|
|
52
|
+
vm.process_string(process_command_line_options)
|
|
53
|
+
true
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
#Display the start-up messages for the interactive session.
|
|
57
|
+
def self.announcements
|
|
58
|
+
puts "Welcome to fOOrth: fO(bject)O(riented)rth."
|
|
59
|
+
puts "\nfOOrth Reference Implementation Version: #{XfOOrth.version}"
|
|
60
|
+
puts "\nSession began on: #{Time.now.strftime(TimeFormat)}"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
#Process the command line arguments. A string is returned containing
|
|
64
|
+
#fOOrth commands to be executed after the dictionary is loaded.
|
|
65
|
+
#<br>Returns
|
|
66
|
+
#* A string of fOOrth commands to be executed after the dictionary is loaded.
|
|
67
|
+
#<br>Endemic Code Smells
|
|
68
|
+
#* :reek:TooManyStatements
|
|
69
|
+
def self.process_command_line_options
|
|
70
|
+
begin
|
|
71
|
+
|
|
72
|
+
defer, found = "", false
|
|
73
|
+
|
|
74
|
+
opts = GetoptLong.new(
|
|
75
|
+
[ "--help", "-h", "-?", GetoptLong::NO_ARGUMENT ],
|
|
76
|
+
[ "--load", "-l", GetoptLong::REQUIRED_ARGUMENT ],
|
|
77
|
+
[ "--debug", "-d", GetoptLong::NO_ARGUMENT ],
|
|
78
|
+
[ "--show", "-s", GetoptLong::NO_ARGUMENT ],
|
|
79
|
+
[ "--quit", "-q", GetoptLong::NO_ARGUMENT ],
|
|
80
|
+
[ "--words", "-w", GetoptLong::NO_ARGUMENT ])
|
|
81
|
+
|
|
82
|
+
# Translate the parsed options into fOOrth.
|
|
83
|
+
opts.each do |opt, arg|
|
|
84
|
+
|
|
85
|
+
unless found
|
|
86
|
+
puts
|
|
87
|
+
found = true
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
case opt
|
|
91
|
+
when "--debug"
|
|
92
|
+
defer << ")debug "
|
|
93
|
+
when "--show"
|
|
94
|
+
defer << ")show "
|
|
95
|
+
when "--load"
|
|
96
|
+
defer << "\"#{arg}\" .load "
|
|
97
|
+
when "--quit"
|
|
98
|
+
defer << ")quit "
|
|
99
|
+
when "--words"
|
|
100
|
+
defer << ")words "
|
|
101
|
+
else
|
|
102
|
+
fail SilentExit
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
puts if found
|
|
107
|
+
|
|
108
|
+
rescue Exception
|
|
109
|
+
puts
|
|
110
|
+
puts "fOOrth available options:"
|
|
111
|
+
puts
|
|
112
|
+
puts "--help -h -? Display this message and exit."
|
|
113
|
+
puts "--load -l <filename> Load the specified fOOrth source file."
|
|
114
|
+
puts "--debug -d Default to debug ON."
|
|
115
|
+
puts "--quit -q Quit after processing the command line."
|
|
116
|
+
puts "--show -s Default to show results ON."
|
|
117
|
+
puts "--words -w List the current vocabulary."
|
|
118
|
+
puts
|
|
119
|
+
raise SilentExit
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
defer
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
#A collection of standard library monkey patches required by foorth.
|
|
4
|
+
|
|
5
|
+
require_relative 'monkey_patch/exceptions'
|
|
6
|
+
require_relative 'monkey_patch/object'
|
|
7
|
+
require_relative 'monkey_patch/false'
|
|
8
|
+
require_relative 'monkey_patch/nil'
|
|
9
|
+
require_relative 'monkey_patch/numeric'
|
|
10
|
+
require_relative 'monkey_patch/integer'
|
|
11
|
+
require_relative 'monkey_patch/float'
|
|
12
|
+
require_relative 'monkey_patch/rational'
|
|
13
|
+
require_relative 'monkey_patch/complex'
|
|
14
|
+
require_relative 'monkey_patch/string'
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
#Extensions to the \Complex class required by the fOOrth language system.
|
|
4
|
+
class Complex
|
|
5
|
+
#Convert this complex number to a form suitable for embedding in a source string.
|
|
6
|
+
#<br>Returns
|
|
7
|
+
#* An embeddable form of this complex number as a string.
|
|
8
|
+
def foorth_embed
|
|
9
|
+
"Complex(#{self.real.foorth_embed},#{self.imaginary.foorth_embed})"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
#Argument coercion methods.
|
|
13
|
+
|
|
14
|
+
#Coerce the argument to match my type.
|
|
15
|
+
def foorth_coerce(arg)
|
|
16
|
+
Complex(arg)
|
|
17
|
+
rescue
|
|
18
|
+
error "F40: Cannot coerce a #{arg.foorth_name} to a Complex"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
#Cannot convert this number to a single character string.
|
|
22
|
+
def to_foorth_c
|
|
23
|
+
error "F40: Cannot convert a Complex instance to a character"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
#Cannot convert this number to a Rational.
|
|
27
|
+
def to_foorth_r
|
|
28
|
+
nil
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
# Extensions to Exception to support fOOrth.
|
|
4
|
+
class Exception
|
|
5
|
+
|
|
6
|
+
#A hash of exception classes and their fOOrth codes.
|
|
7
|
+
FOORTH_EXCEPTION_CODE = {
|
|
8
|
+
SignalException => "E30:",
|
|
9
|
+
Interrupt => "E30,01:",
|
|
10
|
+
MiniReadlineEOI => "E30,02:",
|
|
11
|
+
StandardError => "E:",
|
|
12
|
+
ArgumentError => "E01:",
|
|
13
|
+
Gem::Requirement::BadRequirementError => "E01,01:",
|
|
14
|
+
EncodingError => "E02:",
|
|
15
|
+
Encoding::CompatibilityError => "E02,01:",
|
|
16
|
+
Encoding::ConverterNotFoundError => "E02,02:",
|
|
17
|
+
Encoding::InvalidByteSequenceError => "E02,03:",
|
|
18
|
+
Encoding::UndefinedConversionError => "E02,04:",
|
|
19
|
+
FiberError => "E03:",
|
|
20
|
+
IOError => "E04:",
|
|
21
|
+
EOFError => "E04,01:",
|
|
22
|
+
IndexError => "E05:",
|
|
23
|
+
KeyError => "E05,01:",
|
|
24
|
+
StopIteration => "E05,02:",
|
|
25
|
+
LocalJumpError => "E06:",
|
|
26
|
+
Math::DomainError => "E07:",
|
|
27
|
+
NameError => "E08:",
|
|
28
|
+
NoMethodError => "E08,01:",
|
|
29
|
+
RangeError => "E09:",
|
|
30
|
+
FloatDomainError => "E09,01:",
|
|
31
|
+
RegexpError => "E10:",
|
|
32
|
+
RuntimeError => "E11:",
|
|
33
|
+
Gem::Exception => "E11,01:",
|
|
34
|
+
Gem::CommandLineError => "E11,01,01:",
|
|
35
|
+
Gem::DependencyError => "E11,01,02:",
|
|
36
|
+
Gem::DependencyRemovalException => "E11,01,03:",
|
|
37
|
+
Gem::DependencyResolutionError => "E11,01,04:",
|
|
38
|
+
Gem::DocumentError => "E11,01,05:",
|
|
39
|
+
Gem::EndOfYAMLException => "E11,01,06:",
|
|
40
|
+
Gem::FilePermissionError => "E11,01,07:",
|
|
41
|
+
Gem::FormatException => "E11,01,08:",
|
|
42
|
+
Gem::GemNotFoundException => "E11,01,09:",
|
|
43
|
+
Gem::SpecificGemNotFoundException => "E11,01,09,01:",
|
|
44
|
+
Gem::GemNotInHomeException => "E11,01,10:",
|
|
45
|
+
Gem::ImpossibleDependenciesError => "E11,01,11:",
|
|
46
|
+
Gem::InstallError => "E11,01,12:",
|
|
47
|
+
Gem::InvalidSpecificationException => "E11,01,13:",
|
|
48
|
+
Gem::OperationNotSupportedError => "E11,01,14:",
|
|
49
|
+
Gem::RemoteError => "E11,01,15:",
|
|
50
|
+
Gem::RemoteInstallationCancelled => "E11,01,16:",
|
|
51
|
+
Gem::RemoteInstallationSkipped => "E11,01,17:",
|
|
52
|
+
Gem::RemoteSourceException => "E11,01,18:",
|
|
53
|
+
#Gem::RubyVersionMismatch => "E11,01,19:",
|
|
54
|
+
Gem::UnsatisfiableDependencyError => "E11,01,20:",
|
|
55
|
+
Gem::VerificationError => "E11,01,21:",
|
|
56
|
+
#SystemCallError => "E12,<error_name>:",
|
|
57
|
+
ThreadError => "E13:",
|
|
58
|
+
TypeError => "E14:",
|
|
59
|
+
ZeroDivisionError => "E15:"}
|
|
60
|
+
|
|
61
|
+
if Object.const_defined?('RubyVersionMismatch')
|
|
62
|
+
FOORTH_EXCEPTION_CODE[Gem::RubyVersionMismatch] = "E11,01,19:"
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
#Retrieve the fOOrth exception code of this exception.
|
|
66
|
+
def foorth_code
|
|
67
|
+
if /^[A-Z]\d\d(,\d\d)*:/ =~ self.message
|
|
68
|
+
result = $MATCH
|
|
69
|
+
else
|
|
70
|
+
klass = self.class
|
|
71
|
+
|
|
72
|
+
while (klass)
|
|
73
|
+
break if (result = FOORTH_EXCEPTION_CODE[klass])
|
|
74
|
+
klass = klass.superclass
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
result ||= "E??:"
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
#Is this exception covered by target?
|
|
82
|
+
def foorth_match(target)
|
|
83
|
+
self.foorth_code[0, target.length] == target
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
#Get the error message for this exception.
|
|
87
|
+
def foorth_message
|
|
88
|
+
"#{self.foorth_code} #{self.message}"
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Extensions to SystemCallError to support fOOrth.
|
|
93
|
+
class SystemCallError
|
|
94
|
+
|
|
95
|
+
#Get the fOOrth error code for a system call error.
|
|
96
|
+
def foorth_code
|
|
97
|
+
result = "E12"
|
|
98
|
+
|
|
99
|
+
if /::/ =~ self.class.to_s
|
|
100
|
+
result += ",#{$POSTMATCH}"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
result + ':'
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Extensions to Interrupt to support fOOrth.
|
|
109
|
+
class Interrupt
|
|
110
|
+
|
|
111
|
+
#The message text for the interrupt. Needed as Ruby provides none.
|
|
112
|
+
def message
|
|
113
|
+
"Interrupt detected. Exiting fOOrth."
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
#Shut up already!
|
|
119
|
+
module Exception::Gem #:nodoc: don't document this!
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
#* exceptions.rb - Exception classes for the fOOrth language interpreter.
|
|
123
|
+
module XfOOrth
|
|
124
|
+
#The generalize exception used by all fOOrth specific exceptions.
|
|
125
|
+
class XfOOrthError < StandardError
|
|
126
|
+
|
|
127
|
+
#Get the error message for this exception.
|
|
128
|
+
def foorth_message
|
|
129
|
+
self.message
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
#The exception raised to force the fOOrth language system to exit.
|
|
135
|
+
class ForceExit < StandardError
|
|
136
|
+
|
|
137
|
+
#Get the error message for this exception.
|
|
138
|
+
def foorth_message
|
|
139
|
+
"F00: Quit command received. Exiting fOOrth."
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
#The exception raised to silently force the fOOrth language system to exit.
|
|
145
|
+
class SilentExit < StandardError
|
|
146
|
+
|
|
147
|
+
#Get the error message for this exception. Nothing... It's silent!
|
|
148
|
+
def foorth_message
|
|
149
|
+
""
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
#Extensions to the \Float class required by the fOOrth language system.
|
|
4
|
+
class Float
|
|
5
|
+
|
|
6
|
+
#Argument coercion methods.
|
|
7
|
+
|
|
8
|
+
#Coerce the argument to match my type.
|
|
9
|
+
def self.foorth_coerce(arg)
|
|
10
|
+
Float(arg)
|
|
11
|
+
rescue
|
|
12
|
+
error "F40: Cannot coerce a #{arg.foorth_name} to a Float instance"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
#Coerce the argument to match my type.
|
|
16
|
+
def foorth_coerce(arg)
|
|
17
|
+
Float(arg)
|
|
18
|
+
rescue
|
|
19
|
+
error "F40: Cannot coerce a #{arg.foorth_name} to a Float instance"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
#Extensions to the \Integer class required by the fOOrth language system.
|
|
4
|
+
class Integer
|
|
5
|
+
|
|
6
|
+
#Argument coercion methods.
|
|
7
|
+
|
|
8
|
+
#Coerce the argument to match my type.
|
|
9
|
+
def self.foorth_coerce(arg)
|
|
10
|
+
Integer(arg)
|
|
11
|
+
rescue
|
|
12
|
+
error "F40: Cannot coerce a #{arg.foorth_name} to an Integer instance"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
#Coerce the argument to match my type.
|
|
16
|
+
def foorth_coerce(arg)
|
|
17
|
+
Integer(arg)
|
|
18
|
+
rescue
|
|
19
|
+
error "F40: Cannot coerce a #{arg.foorth_name} to an Integer instance"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
#Extensions to the \Numeric class required by the fOOrth language system.
|
|
4
|
+
class Numeric
|
|
5
|
+
#Convert this number to a form suitable for embedding in a source string.
|
|
6
|
+
#<br>Returns
|
|
7
|
+
#* An embeddable form of this number as a string.
|
|
8
|
+
def foorth_embed
|
|
9
|
+
self.to_s
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
#Convert this number to a single character string.
|
|
13
|
+
def to_foorth_c
|
|
14
|
+
as_int = Integer.foorth_coerce(self)
|
|
15
|
+
|
|
16
|
+
if as_int < 0 || as_int > 1114111
|
|
17
|
+
error "F40: Can't convert #{self} to a character."
|
|
18
|
+
else
|
|
19
|
+
[as_int].pack('U')
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
#Convert this numeric to a numeric. Return self.
|
|
24
|
+
def to_foorth_n
|
|
25
|
+
self
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
#Convert this numeric to a rational.
|
|
29
|
+
def to_foorth_r
|
|
30
|
+
self.rationalize
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
#Extensions to the \Object class required by the fOOrth language system.
|
|
4
|
+
class Object
|
|
5
|
+
|
|
6
|
+
#Raise a fOOrth language internal exception as this operation is not allowed.
|
|
7
|
+
def foorth_embed
|
|
8
|
+
error "F40: Can't embed class #{self.class.to_s}"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
#Convert this object to a fOOrth boolean.
|
|
12
|
+
def to_foorth_b
|
|
13
|
+
true
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
#Convert this object to a single character string.
|
|
17
|
+
def to_foorth_c
|
|
18
|
+
"\x00"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
#Convert this object to a numeric. Returns nil for fail.
|
|
22
|
+
def to_foorth_n
|
|
23
|
+
nil
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
#Convert this object to a rational. Returns nil for fail.
|
|
27
|
+
def to_foorth_r
|
|
28
|
+
nil
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
#Fail with XfOOrthError argument error.
|
|
32
|
+
def error(msg)
|
|
33
|
+
fail XfOOrth::XfOOrthError, msg, caller
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
#Argument coercion methods. These are stubs.
|
|
37
|
+
|
|
38
|
+
#Coerce the argument to match my type. Stub
|
|
39
|
+
def foorth_coerce(_arg)
|
|
40
|
+
error "F40: Cannot coerce to a #{self.foorth_name}"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|