forthic 0.1.0 → 0.2.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 +4 -4
- data/CHANGELOG.md +6 -0
- data/CLAUDE.md +74 -0
- data/Guardfile +3 -3
- data/Rakefile +1 -1
- data/lib/forthic/forthic_error.rb +1 -2
- data/lib/forthic/forthic_module.rb +10 -9
- data/lib/forthic/global_module.rb +321 -334
- data/lib/forthic/interpreter.rb +204 -104
- data/lib/forthic/token.rb +1 -2
- data/lib/forthic/tokenizer.rb +3 -3
- data/lib/forthic/variable.rb +1 -1
- data/lib/forthic/version.rb +1 -1
- data/lib/forthic/words/definition_word.rb +15 -17
- data/lib/forthic/words/end_array_word.rb +3 -3
- data/lib/forthic/words/end_module_word.rb +2 -2
- data/lib/forthic/words/imported_word.rb +3 -3
- data/lib/forthic/words/map_word.rb +5 -5
- data/lib/forthic/words/module_memo_bang_at_word.rb +3 -3
- data/lib/forthic/words/module_memo_bang_word.rb +3 -3
- data/lib/forthic/words/module_memo_word.rb +2 -2
- data/lib/forthic/words/module_word.rb +3 -3
- data/lib/forthic/words/push_value_word.rb +3 -3
- data/lib/forthic/words/start_module_word.rb +6 -6
- data/lib/forthic/words/word.rb +1 -1
- data/lib/forthic.rb +19 -19
- metadata +7 -3
data/lib/forthic/interpreter.rb
CHANGED
@@ -1,49 +1,137 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
5
|
-
require_relative
|
6
|
-
require_relative
|
7
|
-
require_relative
|
8
|
-
require_relative
|
9
|
-
require_relative
|
10
|
-
require_relative
|
11
|
-
require_relative
|
12
|
-
require_relative
|
13
|
-
require_relative
|
14
|
-
require_relative
|
3
|
+
require_relative "forthic_error"
|
4
|
+
require_relative "tokenizer"
|
5
|
+
require_relative "token"
|
6
|
+
require_relative "code_location"
|
7
|
+
require_relative "positioned_string"
|
8
|
+
require_relative "words/word"
|
9
|
+
require_relative "words/push_value_word"
|
10
|
+
require_relative "words/start_module_word"
|
11
|
+
require_relative "words/end_module_word"
|
12
|
+
require_relative "words/end_array_word"
|
13
|
+
require_relative "words/definition_word"
|
14
|
+
require_relative "global_module"
|
15
15
|
|
16
16
|
module Forthic
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
# Error codes used throughout the interpreter
|
18
|
+
module ErrorCodes
|
19
|
+
SCREEN_NOT_FOUND = "screen-not-found"
|
20
|
+
EXECUTION_ERROR = "execution-error"
|
21
|
+
MODULE_NOT_FOUND = "module-not-found"
|
22
|
+
STACK_UNDERFLOW = "stack-underflow"
|
23
|
+
MODULE_EXECUTION_ERROR = "module-execution-error"
|
24
|
+
UNKNOWN_TOKEN = "unknown-token"
|
25
|
+
NESTED_DEFINITION = "nested-definition"
|
26
|
+
NESTED_MEMO_DEFINITION = "nested-memo-definition"
|
27
|
+
DEFINITION_WITHOUT_START = "definition-without-start"
|
28
|
+
MISSING_DEFINITION = "missing-definition"
|
29
|
+
WORD_NOT_FOUND = "word-not-found"
|
30
|
+
end
|
22
31
|
|
23
|
-
|
32
|
+
# Manages execution state for the interpreter
|
33
|
+
class ExecutionState
|
34
|
+
attr_accessor :stack, :module_stack, :is_compiling, :should_stop,
|
35
|
+
:is_memo_definition, :cur_definition, :string_location
|
36
|
+
|
37
|
+
def initialize(app_module)
|
24
38
|
@stack = []
|
25
|
-
@
|
39
|
+
@module_stack = [app_module]
|
26
40
|
@is_compiling = false
|
27
41
|
@should_stop = false
|
28
42
|
@is_memo_definition = false
|
29
43
|
@cur_definition = nil
|
30
|
-
@screens = {}
|
31
|
-
@default_module_flags = {}
|
32
|
-
@module_flags = {}
|
33
44
|
@string_location = nil
|
45
|
+
end
|
34
46
|
|
35
|
-
|
36
|
-
@
|
37
|
-
@module_stack = [
|
47
|
+
def reset(app_module)
|
48
|
+
@stack = []
|
49
|
+
@module_stack = [app_module]
|
50
|
+
@is_compiling = false
|
51
|
+
@is_memo_definition = false
|
52
|
+
@cur_definition = nil
|
53
|
+
@string_location = nil
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Manages profiling state and operations
|
58
|
+
class ProfilingState
|
59
|
+
attr_reader :word_counts, :is_profiling, :start_profile_time, :timestamps
|
38
60
|
|
61
|
+
def initialize
|
39
62
|
@word_counts = {}
|
40
63
|
@is_profiling = false
|
41
64
|
@start_profile_time = nil
|
42
65
|
@timestamps = []
|
43
66
|
end
|
44
67
|
|
68
|
+
def start_profiling
|
69
|
+
@is_profiling = true
|
70
|
+
@timestamps = []
|
71
|
+
@start_profile_time = Time.now
|
72
|
+
add_timestamp("START")
|
73
|
+
@word_counts = {}
|
74
|
+
end
|
75
|
+
|
76
|
+
def stop_profiling
|
77
|
+
add_timestamp("END")
|
78
|
+
@is_profiling = false
|
79
|
+
end
|
80
|
+
|
81
|
+
def count_word(word)
|
82
|
+
return unless @is_profiling
|
83
|
+
@word_counts[word.name] ||= 0
|
84
|
+
@word_counts[word.name] += 1
|
85
|
+
end
|
86
|
+
|
87
|
+
def add_timestamp(label)
|
88
|
+
return unless @is_profiling
|
89
|
+
timestamp = {label: label, time_ms: (Time.now - @start_profile_time) * 1000}
|
90
|
+
@timestamps.push(timestamp)
|
91
|
+
end
|
92
|
+
|
93
|
+
def word_histogram
|
94
|
+
@word_counts.map { |name, count| {word: name, count: count} }.sort_by { |item| -item[:count] }
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
class Interpreter
|
99
|
+
# Core interpreter components
|
100
|
+
attr_reader :global_module, :app_module, :registered_modules
|
101
|
+
# Screen and module management
|
102
|
+
attr_accessor :screens, :default_module_flags, :module_flags
|
103
|
+
# State objects
|
104
|
+
attr_reader :execution_state, :profiling_state
|
105
|
+
|
106
|
+
# Token handler lookup table
|
107
|
+
TOKEN_HANDLERS = {
|
108
|
+
TokenType::STRING => :handle_string_token,
|
109
|
+
TokenType::COMMENT => :handle_comment_token,
|
110
|
+
TokenType::START_ARRAY => :handle_start_array_token,
|
111
|
+
TokenType::END_ARRAY => :handle_end_array_token,
|
112
|
+
TokenType::START_MODULE => :handle_start_module_token,
|
113
|
+
TokenType::END_MODULE => :handle_end_module_token,
|
114
|
+
TokenType::START_DEF => :handle_start_definition_token,
|
115
|
+
TokenType::START_MEMO => :handle_start_memo_token,
|
116
|
+
TokenType::END_DEF => :handle_end_definition_token,
|
117
|
+
TokenType::WORD => :handle_word_token
|
118
|
+
}.freeze
|
119
|
+
|
120
|
+
def initialize
|
121
|
+
@registered_modules = {}
|
122
|
+
@screens = {}
|
123
|
+
@default_module_flags = {}
|
124
|
+
@module_flags = {}
|
125
|
+
|
126
|
+
@global_module = GlobalModule.new(self)
|
127
|
+
@app_module = ForthicModule.new("", self)
|
128
|
+
|
129
|
+
@execution_state = ExecutionState.new(@app_module)
|
130
|
+
@profiling_state = ProfilingState.new
|
131
|
+
end
|
132
|
+
|
45
133
|
def halt
|
46
|
-
@should_stop = true
|
134
|
+
@execution_state.should_stop = true
|
47
135
|
end
|
48
136
|
|
49
137
|
# @return [ForthicModule]
|
@@ -53,7 +141,28 @@ module Forthic
|
|
53
141
|
|
54
142
|
# @return [CodeLocation, nil]
|
55
143
|
def get_string_location
|
56
|
-
@string_location
|
144
|
+
@execution_state.string_location
|
145
|
+
end
|
146
|
+
|
147
|
+
# Delegation methods for execution state
|
148
|
+
def stack
|
149
|
+
@execution_state.stack
|
150
|
+
end
|
151
|
+
|
152
|
+
def stack=(new_stack)
|
153
|
+
@execution_state.stack = new_stack
|
154
|
+
end
|
155
|
+
|
156
|
+
def module_stack
|
157
|
+
@execution_state.module_stack
|
158
|
+
end
|
159
|
+
|
160
|
+
def is_compiling
|
161
|
+
@execution_state.is_compiling
|
162
|
+
end
|
163
|
+
|
164
|
+
def cur_definition
|
165
|
+
@execution_state.cur_definition
|
57
166
|
end
|
58
167
|
|
59
168
|
# @param [String] module_id
|
@@ -80,20 +189,15 @@ module Forthic
|
|
80
189
|
end
|
81
190
|
|
82
191
|
def reset
|
83
|
-
@stack = []
|
84
192
|
@app_module.variables = {}
|
85
|
-
@
|
86
|
-
@is_compiling = false
|
87
|
-
@is_memo_definition = false
|
88
|
-
@cur_definition = nil
|
89
|
-
@string_location = nil
|
193
|
+
@execution_state.reset(@app_module)
|
90
194
|
end
|
91
195
|
|
92
196
|
# @param [String] screen_name
|
93
197
|
# @return [String]
|
94
198
|
def get_screen_forthic(screen_name)
|
95
199
|
screen = @screens[screen_name]
|
96
|
-
raise ForthicError.new(
|
200
|
+
raise ForthicError.new(ErrorCodes::SCREEN_NOT_FOUND, "Unable to find screen \"#{screen_name}\"", "Screen not found. Check the screen name for typos or ensure it has been properly registered.") unless screen
|
97
201
|
screen
|
98
202
|
end
|
99
203
|
|
@@ -112,63 +216,78 @@ module Forthic
|
|
112
216
|
loop do
|
113
217
|
token = tokenizer.next_token
|
114
218
|
handle_token(token)
|
115
|
-
break if token.type == TokenType::EOS || @should_stop
|
116
|
-
next if [TokenType::START_DEF, TokenType::END_DEF, TokenType::COMMENT].include?(token.type) || @is_compiling
|
219
|
+
break if token.type == TokenType::EOS || @execution_state.should_stop
|
220
|
+
next if [TokenType::START_DEF, TokenType::END_DEF, TokenType::COMMENT].include?(token.type) || @execution_state.is_compiling
|
117
221
|
end
|
118
222
|
true
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
223
|
+
rescue => e
|
224
|
+
error = ForthicError.new(ErrorCodes::EXECUTION_ERROR, "Error executing token '#{token&.string}'", "An unexpected error occurred during execution. Check the token syntax and try again.", token&.location)
|
225
|
+
error.set_caught_error(e)
|
226
|
+
raise error
|
123
227
|
end
|
124
228
|
|
125
229
|
# @return [ForthicModule]
|
126
230
|
def cur_module
|
127
|
-
@module_stack.last
|
231
|
+
@execution_state.module_stack.last
|
128
232
|
end
|
129
233
|
|
130
234
|
# @param [String] name
|
131
235
|
# @return [ForthicModule]
|
132
236
|
def find_module(name)
|
237
|
+
raise ArgumentError, "Module name cannot be nil" if name.nil?
|
238
|
+
raise ArgumentError, "Module name cannot be empty" if name.empty?
|
239
|
+
|
133
240
|
result = @registered_modules[name]
|
134
|
-
raise ForthicError.new(
|
241
|
+
raise ForthicError.new(ErrorCodes::MODULE_NOT_FOUND, "Module '#{name}' not found", "Check the module name for typos and ensure it has been properly registered.") unless result
|
135
242
|
result
|
136
243
|
end
|
137
244
|
|
138
245
|
# @param [Object] val
|
139
246
|
def stack_push(val)
|
140
|
-
@stack.push(val)
|
247
|
+
@execution_state.stack.push(val)
|
141
248
|
end
|
142
249
|
|
143
250
|
# @return [Object]
|
144
251
|
def stack_pop
|
145
|
-
raise ForthicError.new(
|
146
|
-
result = @stack.pop
|
147
|
-
@string_location = result.is_a?(PositionedString) ? result.location : nil
|
252
|
+
raise ForthicError.new(ErrorCodes::STACK_UNDERFLOW, "Stack underflow", "Attempted to pop from an empty stack. This indicates a logical error in the Forthic code.") if @execution_state.stack.empty?
|
253
|
+
result = @execution_state.stack.pop
|
254
|
+
@execution_state.string_location = result.is_a?(PositionedString) ? result.location : nil
|
148
255
|
result.is_a?(PositionedString) ? result.value_of : result
|
149
256
|
end
|
150
257
|
|
151
258
|
# @param [ForthicModule] mod
|
152
259
|
def module_stack_push(mod)
|
153
|
-
|
260
|
+
raise ArgumentError, "Module cannot be nil" if mod.nil?
|
261
|
+
@execution_state.module_stack.push(mod)
|
154
262
|
end
|
155
263
|
|
156
264
|
def module_stack_pop
|
157
|
-
@module_stack.pop
|
265
|
+
@execution_state.module_stack.pop
|
158
266
|
end
|
159
267
|
|
160
268
|
# @param [ForthicModule] mod
|
161
269
|
def register_module(mod)
|
270
|
+
raise ArgumentError, "Module cannot be nil" if mod.nil?
|
271
|
+
raise ArgumentError, "Module must respond to :name" unless mod.respond_to?(:name)
|
162
272
|
@registered_modules[mod.name] = mod
|
163
273
|
end
|
164
274
|
|
275
|
+
# @param [ForthicModule] mod
|
276
|
+
# @param [String] prefix
|
277
|
+
def import_module(mod, prefix = "")
|
278
|
+
raise ArgumentError, "Module cannot be nil" if mod.nil?
|
279
|
+
register_module(mod)
|
280
|
+
@app_module.import_module(prefix, mod, self)
|
281
|
+
end
|
282
|
+
|
165
283
|
# @param [ForthicModule] mod
|
166
284
|
def run_module_code(mod)
|
285
|
+
raise ArgumentError, "Module cannot be nil" if mod.nil?
|
167
286
|
module_stack_push(mod)
|
168
287
|
run(mod.forthic_code)
|
169
288
|
module_stack_pop
|
170
289
|
rescue => e
|
171
|
-
error = ForthicError.new(
|
290
|
+
error = ForthicError.new(ErrorCodes::MODULE_EXECUTION_ERROR, "Error executing module '#{mod.name}'", "An error occurred while running the module code. Check the module implementation for syntax errors.")
|
172
291
|
error.set_caught_error(e)
|
173
292
|
raise error
|
174
293
|
end
|
@@ -177,7 +296,7 @@ module Forthic
|
|
177
296
|
# @return [Word, nil]
|
178
297
|
def find_word(name)
|
179
298
|
result = nil
|
180
|
-
@module_stack.reverse_each do |m|
|
299
|
+
@execution_state.module_stack.reverse_each do |m|
|
181
300
|
result = m.find_word(name)
|
182
301
|
break if result
|
183
302
|
end
|
@@ -185,59 +304,40 @@ module Forthic
|
|
185
304
|
result
|
186
305
|
end
|
187
306
|
|
307
|
+
# Delegation methods for profiling
|
188
308
|
def start_profiling
|
189
|
-
@
|
190
|
-
@timestamps = []
|
191
|
-
@start_profile_time = Time.now
|
192
|
-
add_timestamp("START")
|
193
|
-
@word_counts = {}
|
309
|
+
@profiling_state.start_profiling
|
194
310
|
end
|
195
311
|
|
196
|
-
|
197
|
-
|
198
|
-
return unless @is_profiling
|
199
|
-
@word_counts[word.name] ||= 0
|
200
|
-
@word_counts[word.name] += 1
|
312
|
+
def stop_profiling
|
313
|
+
@profiling_state.stop_profiling
|
201
314
|
end
|
202
315
|
|
203
|
-
def
|
204
|
-
|
205
|
-
@is_profiling = false
|
316
|
+
def count_word(word)
|
317
|
+
@profiling_state.count_word(word)
|
206
318
|
end
|
207
319
|
|
208
|
-
# @param [String] label
|
209
320
|
def add_timestamp(label)
|
210
|
-
|
211
|
-
timestamp = { label: label, time_ms: (Time.now - @start_profile_time) * 1000 }
|
212
|
-
@timestamps.push(timestamp)
|
321
|
+
@profiling_state.add_timestamp(label)
|
213
322
|
end
|
214
323
|
|
215
|
-
# @return [Array<Hash>]
|
216
324
|
def word_histogram
|
217
|
-
@
|
325
|
+
@profiling_state.word_histogram
|
218
326
|
end
|
219
327
|
|
220
|
-
# @return [Array<Hash>]
|
221
328
|
def profile_timestamps
|
222
|
-
@timestamps
|
329
|
+
@profiling_state.timestamps
|
223
330
|
end
|
224
331
|
|
225
332
|
# @param [Token] token
|
226
333
|
def handle_token(token)
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
when TokenType::START_MODULE then handle_start_module_token(token)
|
233
|
-
when TokenType::END_MODULE then handle_end_module_token(token)
|
234
|
-
when TokenType::START_DEF then handle_start_definition_token(token)
|
235
|
-
when TokenType::START_MEMO then handle_start_memo_token(token)
|
236
|
-
when TokenType::END_DEF then handle_end_definition_token(token)
|
237
|
-
when TokenType::WORD then handle_word_token(token)
|
238
|
-
when TokenType::EOS then return
|
334
|
+
return if token.type == TokenType::EOS
|
335
|
+
|
336
|
+
handler = TOKEN_HANDLERS[token.type]
|
337
|
+
if handler
|
338
|
+
send(handler, token)
|
239
339
|
else
|
240
|
-
raise ForthicError.new(
|
340
|
+
raise ForthicError.new(ErrorCodes::UNKNOWN_TOKEN, "Unknown token type '#{token.string}'", "This token type is not recognized. Check for typos or unsupported syntax.", token.location)
|
241
341
|
end
|
242
342
|
end
|
243
343
|
|
@@ -250,7 +350,7 @@ module Forthic
|
|
250
350
|
# @param [Token] token
|
251
351
|
def handle_start_module_token(token)
|
252
352
|
word = StartModuleWord.new(token.string)
|
253
|
-
@cur_definition.add_word(word) if @is_compiling
|
353
|
+
@execution_state.cur_definition.add_word(word) if @execution_state.is_compiling
|
254
354
|
count_word(word)
|
255
355
|
word.execute(self)
|
256
356
|
end
|
@@ -258,7 +358,7 @@ module Forthic
|
|
258
358
|
# @param [Token] _token
|
259
359
|
def handle_end_module_token(_token)
|
260
360
|
word = EndModuleWord.new
|
261
|
-
@cur_definition.add_word(word) if @is_compiling
|
361
|
+
@execution_state.cur_definition.add_word(word) if @execution_state.is_compiling
|
262
362
|
count_word(word)
|
263
363
|
word.execute(self)
|
264
364
|
end
|
@@ -280,49 +380,49 @@ module Forthic
|
|
280
380
|
|
281
381
|
# @param [Token] token
|
282
382
|
def handle_start_definition_token(token)
|
283
|
-
raise ForthicError.new("
|
284
|
-
@cur_definition = DefinitionWord.new(token.string)
|
285
|
-
@is_compiling = true
|
286
|
-
@is_memo_definition = false
|
383
|
+
raise ForthicError.new(ErrorCodes::NESTED_DEFINITION, "Nested definition not allowed", "A definition was started while another definition is active. Ensure all definitions end with semicolons.", token.location) if @execution_state.is_compiling
|
384
|
+
@execution_state.cur_definition = DefinitionWord.new(token.string)
|
385
|
+
@execution_state.is_compiling = true
|
386
|
+
@execution_state.is_memo_definition = false
|
287
387
|
end
|
288
388
|
|
289
389
|
# @param [Token] token
|
290
390
|
def handle_start_memo_token(token)
|
291
|
-
raise ForthicError.new("
|
292
|
-
@cur_definition = DefinitionWord.new(token.string)
|
293
|
-
@is_compiling = true
|
294
|
-
@is_memo_definition = true
|
391
|
+
raise ForthicError.new(ErrorCodes::NESTED_MEMO_DEFINITION, "Nested memo definition not allowed", "A memo definition was started while another definition is active. Ensure all definitions end with semicolons.", token.location) if @execution_state.is_compiling
|
392
|
+
@execution_state.cur_definition = DefinitionWord.new(token.string)
|
393
|
+
@execution_state.is_compiling = true
|
394
|
+
@execution_state.is_memo_definition = true
|
295
395
|
end
|
296
396
|
|
297
397
|
# @param [Token] token
|
298
398
|
def handle_end_definition_token(token)
|
299
|
-
raise ForthicError.new(
|
300
|
-
raise ForthicError.new(
|
301
|
-
if @is_memo_definition
|
302
|
-
cur_module.add_memo_words(@cur_definition)
|
399
|
+
raise ForthicError.new(ErrorCodes::DEFINITION_WITHOUT_START, "Definition ended without start", "A definition was ended when none was active. Check for extra semicolons.", token.location) unless @execution_state.is_compiling
|
400
|
+
raise ForthicError.new(ErrorCodes::MISSING_DEFINITION, "No current definition to end", "Internal error: definition state is inconsistent.", token.location) unless @execution_state.cur_definition
|
401
|
+
if @execution_state.is_memo_definition
|
402
|
+
cur_module.add_memo_words(@execution_state.cur_definition)
|
303
403
|
else
|
304
|
-
cur_module.add_word(@cur_definition)
|
404
|
+
cur_module.add_word(@execution_state.cur_definition)
|
305
405
|
end
|
306
|
-
@is_compiling = false
|
406
|
+
@execution_state.is_compiling = false
|
307
407
|
end
|
308
408
|
|
309
409
|
# @param [Token] token
|
310
410
|
def handle_word_token(token)
|
311
411
|
word = find_word(token.string)
|
312
|
-
raise ForthicError.new(
|
412
|
+
raise ForthicError.new(ErrorCodes::WORD_NOT_FOUND, "Word '#{token.string}' not found", "Check for typos in the word name or ensure the word has been defined.", token.location) unless word
|
313
413
|
handle_word(word, token.location)
|
314
414
|
end
|
315
415
|
|
316
416
|
# @param [Word] word
|
317
417
|
# @param [CodeLocation, nil] location
|
318
418
|
def handle_word(word, location = nil)
|
319
|
-
if @is_compiling
|
419
|
+
if @execution_state.is_compiling
|
320
420
|
word.set_location(location)
|
321
|
-
@cur_definition.add_word(word)
|
421
|
+
@execution_state.cur_definition.add_word(word)
|
322
422
|
else
|
323
423
|
count_word(word)
|
324
424
|
word.execute(self)
|
325
425
|
end
|
326
426
|
end
|
327
427
|
end
|
328
|
-
end
|
428
|
+
end
|
data/lib/forthic/token.rb
CHANGED
data/lib/forthic/tokenizer.rb
CHANGED
@@ -3,8 +3,8 @@
|
|
3
3
|
module Forthic
|
4
4
|
class Tokenizer
|
5
5
|
attr_accessor :reference_location, :line, :column, :input_string, :input_pos,
|
6
|
-
|
7
|
-
|
6
|
+
:whitespace, :quote_chars, :token_start_pos, :token_end_pos,
|
7
|
+
:token_line, :token_column, :token_string
|
8
8
|
|
9
9
|
# @param [String] string
|
10
10
|
# @param [CodeLocation, nil] reference_location
|
@@ -302,4 +302,4 @@ module Forthic
|
|
302
302
|
Token.new(TokenType::WORD, @token_string, get_token_location)
|
303
303
|
end
|
304
304
|
end
|
305
|
-
end
|
305
|
+
end
|
data/lib/forthic/variable.rb
CHANGED
data/lib/forthic/version.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
3
|
+
require_relative "word"
|
4
|
+
require_relative "../forthic_error"
|
5
5
|
|
6
6
|
module Forthic
|
7
7
|
class DefinitionWord < Word
|
@@ -9,7 +9,7 @@ module Forthic
|
|
9
9
|
|
10
10
|
# @param [String] name
|
11
11
|
def initialize(name)
|
12
|
-
super
|
12
|
+
super
|
13
13
|
@words = []
|
14
14
|
@cur_index = 0
|
15
15
|
end
|
@@ -22,19 +22,17 @@ module Forthic
|
|
22
22
|
# @param [Interpreter] interp
|
23
23
|
def execute(interp)
|
24
24
|
@words.each do |word|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
raise error
|
36
|
-
end
|
25
|
+
word.execute(interp)
|
26
|
+
rescue => e
|
27
|
+
error = ForthicError.new(
|
28
|
+
"definition_word-29",
|
29
|
+
"Error executing word #{word.name}",
|
30
|
+
"Error in #{name} definition",
|
31
|
+
interp.get_string_location
|
32
|
+
)
|
33
|
+
error.set_caught_error(e)
|
34
|
+
raise error
|
37
35
|
end
|
38
36
|
end
|
39
37
|
end
|
40
|
-
end
|
38
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# # frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
3
|
+
require_relative "word"
|
4
|
+
require_relative "../token"
|
5
5
|
|
6
6
|
module Forthic
|
7
7
|
class EndArrayWord < Word
|
@@ -25,4 +25,4 @@ module Forthic
|
|
25
25
|
interp.stack_push(items)
|
26
26
|
end
|
27
27
|
end
|
28
|
-
end
|
28
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# # frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
3
|
+
require_relative "word"
|
4
|
+
require_relative "module_word"
|
5
5
|
|
6
6
|
module Forthic
|
7
7
|
class ImportedWord < Word
|
@@ -24,4 +24,4 @@ module Forthic
|
|
24
24
|
interp.module_stack_pop
|
25
25
|
end
|
26
26
|
end
|
27
|
-
end
|
27
|
+
end
|
@@ -157,13 +157,13 @@ module Forthic
|
|
157
157
|
|
158
158
|
errors = []
|
159
159
|
result = if items.is_a?(Array)
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
160
|
+
descend_list.call(items, @depth, [], errors)
|
161
|
+
else
|
162
|
+
descend_record.call(items, @depth, {}, errors)
|
163
|
+
end
|
164
164
|
@result = result
|
165
165
|
@errors = errors
|
166
166
|
[result, errors]
|
167
167
|
end
|
168
168
|
end
|
169
|
-
end
|
169
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# # frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
3
|
+
require_relative "word"
|
4
|
+
require_relative "module_memo_word"
|
5
5
|
|
6
6
|
module Forthic
|
7
7
|
class ModuleMemoBangAtWord < Word
|
@@ -19,4 +19,4 @@ module Forthic
|
|
19
19
|
interp.stack_push(@memo_word.value)
|
20
20
|
end
|
21
21
|
end
|
22
|
-
end
|
22
|
+
end
|