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,181 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
#* library/compile_library.rb - The compile support fOOrth library.
|
|
4
|
+
module XfOOrth
|
|
5
|
+
|
|
6
|
+
# COLON =======================================
|
|
7
|
+
|
|
8
|
+
#The classic colon definition that creates a word in the Virtual Machine class.
|
|
9
|
+
# [] : <name> <stuff omitted> ; []; creates <name> on the VirtualMachine
|
|
10
|
+
VirtualMachine.create_shared_method(':', VmSpec, [:immediate], &lambda {|vm|
|
|
11
|
+
if execute_mode?
|
|
12
|
+
target = VirtualMachine
|
|
13
|
+
name = vm.parser.get_word()
|
|
14
|
+
type = VmSpec
|
|
15
|
+
XfOOrth.validate_type(vm, type, name)
|
|
16
|
+
|
|
17
|
+
begin_compile_mode(':', vm: vm, &lambda {|vm, src, tags|
|
|
18
|
+
vm.dbg_puts "#{name} => #{src}"
|
|
19
|
+
target.create_shared_method(name, type, tags, &eval(src))
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
XfOOrth.add_common_compiler_locals(vm, ':')
|
|
23
|
+
else
|
|
24
|
+
delayed_compile_mode(':')
|
|
25
|
+
end
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
# BANG COLON ==================================
|
|
29
|
+
|
|
30
|
+
#A special colon definition that creates an immediate word in the
|
|
31
|
+
#Virtual Machine class.
|
|
32
|
+
# [] !: <name> <stuff omitted> ; []; creates <name> on the VirtualMachine
|
|
33
|
+
VirtualMachine.create_shared_method('!:', VmSpec, [:immediate], &lambda {|vm|
|
|
34
|
+
if execute_mode?
|
|
35
|
+
target = VirtualMachine
|
|
36
|
+
name = vm.parser.get_word()
|
|
37
|
+
type = VmSpec
|
|
38
|
+
XfOOrth.validate_type(vm, type, name)
|
|
39
|
+
|
|
40
|
+
begin_compile_mode('!:', vm: vm, tags: [:immediate], &lambda {|vm, src, tags|
|
|
41
|
+
vm.dbg_puts "(!) #{name} => #{src}"
|
|
42
|
+
target.create_shared_method(name, type, tags, &eval(src))
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
XfOOrth.add_common_compiler_locals(vm, '!:')
|
|
46
|
+
else
|
|
47
|
+
delayed_compile_mode('!:')
|
|
48
|
+
end
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
# DOT COLON ===================================
|
|
53
|
+
|
|
54
|
+
# [a_class] .: <name> <stuff omitted> ; []; creates <name> on a_class
|
|
55
|
+
VirtualMachine.create_shared_method('.:', VmSpec, [:immediate], &lambda {|vm|
|
|
56
|
+
if execute_mode?
|
|
57
|
+
target = vm.pop
|
|
58
|
+
error "F13: The target of .: must be a class" unless target.is_a?(Class)
|
|
59
|
+
|
|
60
|
+
name = vm.parser.get_word()
|
|
61
|
+
type = XfOOrth.name_to_type(name)
|
|
62
|
+
XfOOrth.validate_type(vm, type, name)
|
|
63
|
+
XfOOrth.validate_string_method(type, target, name)
|
|
64
|
+
|
|
65
|
+
begin_compile_mode('.:', cls: target, &lambda {|vm, src, tags|
|
|
66
|
+
vm.dbg_puts "#{target.foorth_name} #{name} => #{src}"
|
|
67
|
+
target.create_shared_method(name, type, tags, &eval(src))
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
XfOOrth.add_common_compiler_locals(vm, '.:')
|
|
71
|
+
else
|
|
72
|
+
delayed_compile_mode('.:')
|
|
73
|
+
end
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
# DOT COLON COLON =============================
|
|
78
|
+
|
|
79
|
+
# [an_object] .:: <name> <stuff omitted> ; []; creates <name> on an_object
|
|
80
|
+
VirtualMachine.create_shared_method('.::', VmSpec, [:immediate], &lambda {|vm|
|
|
81
|
+
if execute_mode?
|
|
82
|
+
target = vm.pop
|
|
83
|
+
name = vm.parser.get_word()
|
|
84
|
+
type = XfOOrth.name_to_type(name)
|
|
85
|
+
XfOOrth.validate_type(vm, type, name)
|
|
86
|
+
XfOOrth.validate_string_method(type, target.class, name)
|
|
87
|
+
|
|
88
|
+
begin_compile_mode('.::', obj: target, &lambda {|vm, src, tags|
|
|
89
|
+
vm.dbg_puts "#{target.foorth_name} #{name} => #{src}"
|
|
90
|
+
target.create_exclusive_method(name, type, tags, &eval(src))
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
XfOOrth.add_common_compiler_locals(vm, '.::')
|
|
94
|
+
else
|
|
95
|
+
delayed_compile_mode('.::')
|
|
96
|
+
end
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
# COMMON LOCAL DEFNS ==========================
|
|
101
|
+
|
|
102
|
+
#Set up the common local defns.
|
|
103
|
+
#<br>Parameters:
|
|
104
|
+
#* vm - The current virtual machine instance.
|
|
105
|
+
#* ctrl - A list of valid start controls.
|
|
106
|
+
#<br>Endemic Code Smells
|
|
107
|
+
#* :reek:TooManyStatements
|
|
108
|
+
def self.add_common_compiler_locals(vm, ctrl)
|
|
109
|
+
context = vm.context
|
|
110
|
+
|
|
111
|
+
#Support for local variables.
|
|
112
|
+
context.create_local_method('var:', LocalSpec, [:immediate], &Local_Var_Action)
|
|
113
|
+
context.create_local_method('val:', LocalSpec, [:immediate], &Local_Val_Action)
|
|
114
|
+
|
|
115
|
+
#Support for instance variables.
|
|
116
|
+
context.create_local_method('var@:', LocalSpec, [:immediate], &Inst_Var_Action)
|
|
117
|
+
context.create_local_method('val@:', LocalSpec, [:immediate], &Inst_Val_Action)
|
|
118
|
+
|
|
119
|
+
#Support for super methods.
|
|
120
|
+
context.create_local_method('super', LocalSpec, [:immediate],
|
|
121
|
+
&lambda {|vm| vm << 'super(vm); ' })
|
|
122
|
+
|
|
123
|
+
#The standard end-compile adapter word: ';' semi-colon.
|
|
124
|
+
context.create_local_method(';', LocalSpec, [:immediate],
|
|
125
|
+
&lambda {|vm| vm.end_compile_mode([ctrl]) })
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
#Determine the type of method being created. This only applies to non-vm
|
|
129
|
+
#methods as vm methods are all of type VmSpec.
|
|
130
|
+
#<br>Parameters
|
|
131
|
+
#*name - The name of the method to be created.
|
|
132
|
+
#<Returns>
|
|
133
|
+
#* The class of the spec to be used for this method.
|
|
134
|
+
def self.name_to_type(name)
|
|
135
|
+
case name[0]
|
|
136
|
+
when '.'
|
|
137
|
+
TosSpec
|
|
138
|
+
|
|
139
|
+
when '~'
|
|
140
|
+
SelfSpec
|
|
141
|
+
|
|
142
|
+
when /[0-9A-Z$@#]/
|
|
143
|
+
error "F10: Invalid name for a method: #{name}"
|
|
144
|
+
|
|
145
|
+
else
|
|
146
|
+
NosSpec
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
#Compare the new method's spec against the specs of other methods of the
|
|
151
|
+
#same name. If no specs exist, create one on Object if the new spec is not
|
|
152
|
+
#a virtual machine spec.
|
|
153
|
+
#<br>Parameters
|
|
154
|
+
#*vm - The current virtual machine.
|
|
155
|
+
#*type - The class of the method to be created.
|
|
156
|
+
#*name - The name of the method to be created.
|
|
157
|
+
def self.validate_type(vm, type, name)
|
|
158
|
+
if (spec = vm.context.map(name))
|
|
159
|
+
if spec.class != type
|
|
160
|
+
error "F90: Spec type mismatch #{spec.foorth_name} vs #{type.foorth_name}"
|
|
161
|
+
end
|
|
162
|
+
else
|
|
163
|
+
Object.create_shared_method(name, type, [:stub]) unless type == VmSpec
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
#Check for the case where a string method is created on another class.
|
|
169
|
+
#<br>Parameters
|
|
170
|
+
#*type - The class of the method to be created.
|
|
171
|
+
#*target - The object that is to receive this method.
|
|
172
|
+
#*name - The name of the method to be created.
|
|
173
|
+
#<br>Endemic Code Smells
|
|
174
|
+
#* :reek:ControlParameter -- false positive
|
|
175
|
+
def self.validate_string_method(type, target, name)
|
|
176
|
+
if type == TosSpec && name[-1] == '"' && target != String
|
|
177
|
+
error "F13: Creating a string method #{name} on a #{target.foorth_name}"
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
#* library/complex_library.rb - Numeric support for the fOOrth library.
|
|
4
|
+
module XfOOrth
|
|
5
|
+
|
|
6
|
+
#Connect the Complex class to the fOOrth class system.
|
|
7
|
+
Complex.create_foorth_proxy
|
|
8
|
+
|
|
9
|
+
#Some complex stubs.
|
|
10
|
+
Complex.create_shared_method('mod', NosSpec, [:stub])
|
|
11
|
+
Complex.create_shared_method('.ceil', TosSpec, [:stub])
|
|
12
|
+
Complex.create_shared_method('.floor', TosSpec, [:stub])
|
|
13
|
+
Complex.create_shared_method('.round', TosSpec, [:stub])
|
|
14
|
+
Complex.create_shared_method('<', NosSpec, [:stub])
|
|
15
|
+
Complex.create_shared_method('>', NosSpec, [:stub])
|
|
16
|
+
Complex.create_shared_method('<=', NosSpec, [:stub])
|
|
17
|
+
Complex.create_shared_method('>=', NosSpec, [:stub])
|
|
18
|
+
Complex.create_shared_method('<=>', NosSpec, [:stub])
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
#Some conversion words.
|
|
22
|
+
# [a b] complex [a+bi]
|
|
23
|
+
VirtualMachine.create_shared_method('complex', VmSpec, [], &lambda {|vm|
|
|
24
|
+
real,imag = popm(2)
|
|
25
|
+
|
|
26
|
+
begin
|
|
27
|
+
push(Complex(real,imag));
|
|
28
|
+
rescue
|
|
29
|
+
error "F40: Cannot coerce a #{real.foorth_name}, #{imag.foorth_name} to a Complex"
|
|
30
|
+
end
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
# [a+bi] .split [a b]
|
|
34
|
+
Complex.create_shared_method('.split', TosSpec, [],
|
|
35
|
+
&lambda {|vm| vm.push(self.real); vm.push(self.imaginary); })
|
|
36
|
+
|
|
37
|
+
# [a] .to_x [compleX or nil]
|
|
38
|
+
Object.create_shared_method('.to_x', TosSpec, [], &lambda {|vm|
|
|
39
|
+
begin
|
|
40
|
+
vm.push(Complex(self))
|
|
41
|
+
rescue
|
|
42
|
+
vm.push(nil)
|
|
43
|
+
end
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
# [a] .to_x! [compleX]
|
|
47
|
+
Object.create_shared_method('.to_x!', TosSpec, [], &lambda {|vm|
|
|
48
|
+
begin
|
|
49
|
+
vm.push(Complex(self))
|
|
50
|
+
rescue
|
|
51
|
+
error "F40: Cannot coerce a #{self.foorth_name} to a Complex"
|
|
52
|
+
end
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
# [a+bi] .imaginary [b]
|
|
56
|
+
Numeric.create_shared_method('.imaginary', TosSpec, [],
|
|
57
|
+
&lambda {|vm| vm.push(self.imaginary); })
|
|
58
|
+
|
|
59
|
+
# [a+bi] .real [a]
|
|
60
|
+
Numeric.create_shared_method('.real', TosSpec, [],
|
|
61
|
+
&lambda {|vm| vm.push(self.real); })
|
|
62
|
+
|
|
63
|
+
# [a+bi] .angle [atan2(b,a) or 0]
|
|
64
|
+
Numeric.create_shared_method('.angle', TosSpec, [],
|
|
65
|
+
&lambda {|vm| vm.push(self.angle); })
|
|
66
|
+
|
|
67
|
+
# [a+bi] .magnitude [sqrt(a**2 + b**2)]
|
|
68
|
+
Numeric.create_shared_method('.magnitude', TosSpec, [],
|
|
69
|
+
&lambda {|vm| vm.push(self.magnitude); })
|
|
70
|
+
|
|
71
|
+
# [a+bi] .conjugate [a-bi]
|
|
72
|
+
# Complex convicts that behave well are allowed .conjugate visits.
|
|
73
|
+
Numeric.create_shared_method('.conjugate', TosSpec, [],
|
|
74
|
+
&lambda {|vm| vm.push(self.conjugate); })
|
|
75
|
+
|
|
76
|
+
# [a+bi] .polar [magnitude angle]
|
|
77
|
+
# Convert a complex number to polar format
|
|
78
|
+
Numeric.create_shared_method('.polar', TosSpec, [],
|
|
79
|
+
&lambda {|vm| vm.pushm(self.polar); })
|
|
80
|
+
|
|
81
|
+
end
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
#* library/ctrl_struct_library.rb - The control structures fOOrth library.
|
|
4
|
+
module XfOOrth
|
|
5
|
+
|
|
6
|
+
# [boolean] if (boolean true code) else (boolean false code) then
|
|
7
|
+
VirtualMachine.create_shared_method('if', VmSpec, [:immediate], &lambda {|vm|
|
|
8
|
+
suspend_execute_mode('if vm.pop? then ', :if)
|
|
9
|
+
|
|
10
|
+
context.create_local_method('else', LocalSpec, [:immediate], &lambda {|vm|
|
|
11
|
+
check_deferred_mode('else ', [:if])
|
|
12
|
+
vm.context.remove_local_method('else')
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
context.create_local_method('then', LocalSpec, [:immediate],
|
|
16
|
+
&lambda {|vm| resume_execute_mode('end; ', [:if]) })
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
# [unspecified] switch ... end [unspecified]
|
|
20
|
+
VirtualMachine.create_shared_method('switch', VmSpec, [:immediate], &lambda {|vm|
|
|
21
|
+
suspend_execute_mode('loop do; ', :switch)
|
|
22
|
+
|
|
23
|
+
context.create_local_method('break', LocalSpec, [:immediate],
|
|
24
|
+
&lambda {|vm| vm << 'break; ' })
|
|
25
|
+
|
|
26
|
+
context.create_local_method('?break', LocalSpec, [:immediate],
|
|
27
|
+
&lambda {|vm| vm << 'break if vm.pop?; ' })
|
|
28
|
+
|
|
29
|
+
context.create_local_method('end', LocalSpec, [:immediate],
|
|
30
|
+
&lambda {|vm| resume_execute_mode('break; end; ', [:switch]) })
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
# Looping constructs for fOOrth.
|
|
34
|
+
VirtualMachine.create_shared_method('begin', VmSpec, [:immediate], &lambda {|vm|
|
|
35
|
+
suspend_execute_mode('begin ', :begin)
|
|
36
|
+
|
|
37
|
+
context.create_local_method('while', LocalSpec, [:immediate],
|
|
38
|
+
&lambda {|vm| check_deferred_mode('break unless vm.pop?; ', [:begin]) })
|
|
39
|
+
|
|
40
|
+
context.create_local_method('until', LocalSpec, [:immediate],
|
|
41
|
+
&lambda {|vm| resume_execute_mode('end until vm.pop?; ', [:begin]) })
|
|
42
|
+
|
|
43
|
+
context.create_local_method('again', LocalSpec, [:immediate],
|
|
44
|
+
&lambda {|vm| resume_execute_mode('end until false; ', [:begin]) })
|
|
45
|
+
|
|
46
|
+
context.create_local_method('repeat', LocalSpec, [:immediate],
|
|
47
|
+
&lambda {|vm| resume_execute_mode('end until false; ', [:begin]) })
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
# Support for the sanitized do loop constructs!
|
|
51
|
+
VirtualMachine.create_shared_method('do', VmSpec, [:immediate], &lambda {|vm|
|
|
52
|
+
jvar = context[:jloop].to_s
|
|
53
|
+
suspend_execute_mode("vm.vm_do(#{jvar}) {|iloop, jloop| ", :do)
|
|
54
|
+
context[:jloop] = 'iloop'
|
|
55
|
+
|
|
56
|
+
context.create_local_method('i', MacroSpec,
|
|
57
|
+
[:macro, 'vm.push(iloop[0]); '])
|
|
58
|
+
|
|
59
|
+
context.create_local_method('j', MacroSpec,
|
|
60
|
+
[:macro, 'vm.push(jloop[0]); '])
|
|
61
|
+
|
|
62
|
+
context.create_local_method('-i', MacroSpec,
|
|
63
|
+
[:macro, 'vm.push(iloop[2] - iloop[0]); '])
|
|
64
|
+
|
|
65
|
+
context.create_local_method('-j', MacroSpec,
|
|
66
|
+
[:macro, 'vm.push(jloop[2] - jloop[0]); '])
|
|
67
|
+
|
|
68
|
+
context.create_local_method('loop', LocalSpec, [:immediate],
|
|
69
|
+
&lambda {|vm| resume_execute_mode('iloop[0] += 1}; ', [:do]) })
|
|
70
|
+
|
|
71
|
+
context.create_local_method('+loop', LocalSpec, [:immediate],
|
|
72
|
+
&lambda {|vm| resume_execute_mode('iloop[0] += vm.vm_do_increment}; ', [:do]) })
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
#Support for the try ... catch ... finally ... end construct.
|
|
76
|
+
VirtualMachine.create_shared_method('try', VmSpec, [:immediate], &lambda {|vm|
|
|
77
|
+
suspend_execute_mode('begin; ', :try_block)
|
|
78
|
+
|
|
79
|
+
SymbolMap.add_entry('error') #Make sure an entry for 'error' exists.
|
|
80
|
+
SymbolMap.add_entry('?"') #Make sure an entry for '?"' exists.
|
|
81
|
+
|
|
82
|
+
context.create_local_method('catch', LocalSpec, [:immediate], &lambda {|vm|
|
|
83
|
+
check_deferred_mode('rescue StandardError, SignalException => error; ', [:try_block])
|
|
84
|
+
|
|
85
|
+
vm.context.create_local_method('?"', LocalSpec, [:immediate], &lambda {|vm|
|
|
86
|
+
str = vm.pop
|
|
87
|
+
vm << "vm.push(error.foorth_match(#{str.foorth_embed})); "
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
vm.context.create_local_method('error', LocalSpec, [:immediate], &lambda {|vm|
|
|
91
|
+
vm << 'vm.push(error.foorth_message); '
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
vm.context.create_local_method('bounce', LocalSpec, [:immediate], &lambda {|vm|
|
|
95
|
+
vm << 'raise; '
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
vm.context.remove_local_method('catch')
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
context.create_local_method('finally', LocalSpec, [:immediate], &lambda {|vm|
|
|
102
|
+
check_deferred_mode('ensure; ', [:try_block])
|
|
103
|
+
|
|
104
|
+
vm.context.remove_local_method('catch')
|
|
105
|
+
vm.context.remove_local_method('finally')
|
|
106
|
+
vm.context.remove_local_method('?"')
|
|
107
|
+
vm.context.remove_local_method('error')
|
|
108
|
+
vm.context.remove_local_method('bounce')
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
vm.context.create_local_method('end', LocalSpec, [:immediate], &lambda {|vm|
|
|
112
|
+
vm.resume_execute_mode('end; ', [:try_block])
|
|
113
|
+
})
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
#* library/data_ref_library.rb - The data references (variables) fOOrth library.
|
|
4
|
+
module XfOOrth
|
|
5
|
+
|
|
6
|
+
#The lambda used to define local variables. fOOrth language definition is:
|
|
7
|
+
# [n] var: lv [], lv = [n]
|
|
8
|
+
Local_Var_Action = lambda {|vm|
|
|
9
|
+
name = vm.parser.get_word()
|
|
10
|
+
error "F10: Invalid var name #{name}" unless /^[a-z][a-z0-9_]*$/ =~ name
|
|
11
|
+
symbol = XfOOrth::SymbolMap.add_entry(name)
|
|
12
|
+
vm << "#{symbol} = [vm.pop]; "
|
|
13
|
+
|
|
14
|
+
#Add a local defn for the local variable.
|
|
15
|
+
vm.context.create_local_method(name, LocalSpec, [:immediate],
|
|
16
|
+
&lambda {|vm| vm << "vm.push(#{symbol}); "} )
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
#The lambda used to define local values. fOOrth language definition is:
|
|
20
|
+
# [n] val: lv [], lv = n
|
|
21
|
+
Local_Val_Action = lambda {|vm|
|
|
22
|
+
name = vm.parser.get_word()
|
|
23
|
+
error "F10: Invalid val name #{name}" unless /^[a-z][a-z0-9_]*$/ =~ name
|
|
24
|
+
symbol = XfOOrth::SymbolMap.add_entry(name)
|
|
25
|
+
vm << "#{symbol} = vm.pop; "
|
|
26
|
+
|
|
27
|
+
#Add a local defn for the local variable.
|
|
28
|
+
vm.context.create_local_method(name, LocalSpec, [:immediate],
|
|
29
|
+
&lambda {|vm| vm << "vm.push(#{symbol}); "} )
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
#The lambda used to define instance variables. fOOrth language definition is:
|
|
33
|
+
# [n] var@: @iv [], @iv = [n]
|
|
34
|
+
Inst_Var_Action = lambda { |vm|
|
|
35
|
+
name = vm.parser.get_word()
|
|
36
|
+
error "F10: Invalid var name #{name}" unless /^@[a-z][a-z0-9_]*$/ =~ name
|
|
37
|
+
symbol = XfOOrth::SymbolMap.add_entry(name)
|
|
38
|
+
vm << "#{'@'+(symbol.to_s)} = [vm.pop]; "
|
|
39
|
+
|
|
40
|
+
#Add a defn for the instance variable.
|
|
41
|
+
vm.context.recvr.create_shared_method(name, InstanceVarSpec, [])
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
#The lambda used to define instance values. fOOrth language definition is:
|
|
45
|
+
# [n] val@: @iv [], @iv = n
|
|
46
|
+
Inst_Val_Action = lambda { |vm|
|
|
47
|
+
name = vm.parser.get_word()
|
|
48
|
+
error "F10: Invalid val name #{name}" unless /^@[a-z][a-z0-9_]*$/ =~ name
|
|
49
|
+
symbol = XfOOrth::SymbolMap.add_entry(name)
|
|
50
|
+
vm << "#{'@'+(symbol.to_s)} = vm.pop; "
|
|
51
|
+
|
|
52
|
+
#Add a defn for the instance variable.
|
|
53
|
+
vm.context.recvr.create_shared_method(name, InstanceVarSpec, [])
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
# Thread Variables
|
|
57
|
+
# [n] var#: #tv [], Thread.current[#tv] = [n]
|
|
58
|
+
VirtualMachine.create_shared_method('var#:', VmSpec, [], &lambda {|vm|
|
|
59
|
+
name = vm.parser.get_word()
|
|
60
|
+
error "F10: Invalid var name #{name}" unless /^#[a-z][a-z0-9_]*$/ =~ name
|
|
61
|
+
symbol = XfOOrth::SymbolMap.add_entry(name)
|
|
62
|
+
@data[symbol] = [vm.pop]
|
|
63
|
+
|
|
64
|
+
vm.create_exclusive_method(name, ThreadVarSpec, [])
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
# Thread values.
|
|
68
|
+
# [n] val#: #tv [], Thread.current[#tv] = n
|
|
69
|
+
VirtualMachine.create_shared_method('val#:', VmSpec, [], &lambda {|vm|
|
|
70
|
+
name = vm.parser.get_word()
|
|
71
|
+
error "F10: Invalid val name #{name}" unless /^#[a-z][a-z0-9_]*$/ =~ name
|
|
72
|
+
symbol = XfOOrth::SymbolMap.add_entry(name)
|
|
73
|
+
@data[symbol] = vm.pop
|
|
74
|
+
|
|
75
|
+
vm.create_exclusive_method(name, ThreadVarSpec, [])
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
# Global Variables
|
|
79
|
+
# [n] var$: $gv [], $gv = [n]
|
|
80
|
+
VirtualMachine.create_shared_method('var$:', VmSpec, [], &lambda {|vm|
|
|
81
|
+
name = vm.parser.get_word()
|
|
82
|
+
error "F10: Invalid var name #{name}" unless /^\$[a-z][a-z0-9_]*$/ =~ name
|
|
83
|
+
symbol = XfOOrth::SymbolMap.add_entry(name)
|
|
84
|
+
eval "#{'$' + symbol.to_s} = [vm.pop]"
|
|
85
|
+
|
|
86
|
+
$FOORTH_GLOBALS[symbol] = GlobalVarSpec.new(name, symbol, [])
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
# Global Values
|
|
90
|
+
# [n] val$: $gv [], $gv = n
|
|
91
|
+
VirtualMachine.create_shared_method('val$:', VmSpec, [], &lambda {|vm|
|
|
92
|
+
name = vm.parser.get_word()
|
|
93
|
+
error "F10: Invalid val name #{name}" unless /^\$[a-z][a-z0-9_]*$/ =~ name
|
|
94
|
+
symbol = XfOOrth::SymbolMap.add_entry(name)
|
|
95
|
+
eval "#{'$' + symbol.to_s} = vm.pop"
|
|
96
|
+
|
|
97
|
+
$FOORTH_GLOBALS[symbol] = GlobalVarSpec.new(name, symbol, [])
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
end
|