forthic 0.2.0 → 0.2.4
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/README.md +10 -0
- data/lib/forthic/code_location.rb +15 -0
- data/lib/forthic/errors/unknown_word_error.rb +39 -0
- data/lib/forthic/forthic_error.rb +15 -0
- data/lib/forthic/interpreter.rb +91 -1
- data/lib/forthic/version.rb +1 -1
- data/lib/forthic.rb +4 -0
- metadata +16 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4ebffd3b7bf74a96a5bdbb6d178996eeea1c2d35edc22743e4dba9154e1e40f9
|
|
4
|
+
data.tar.gz: a34907460efd7db068214dff1410b512a9a9ad10e3eee149e120eb5b414ebc2f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7013c8908441bc6aaee014af8e6ac124bf0e60245474adacdcf4a8633c686ef781dc022e0f163a93222dfd3435e5e21c875ac273f13ae029909f51d354fbfdeb
|
|
7
|
+
data.tar.gz: 759a725d11e735ab283d99e076cf314f72ff98c086cf2dcd0ff93077f2031fa0bb27d814008f63ced3c179b6803f566a10d6b79a5e0082d9c91c30f9159b3d03
|
data/README.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
> **⚠️ DEPRECATED PACKAGE**
|
|
2
|
+
>
|
|
3
|
+
> This package is from an archived repository and will not receive updates.
|
|
4
|
+
>
|
|
5
|
+
> **New repository:** https://github.com/forthix/forthic-rb
|
|
6
|
+
>
|
|
7
|
+
> Watch the new repository for announcements about updated packages.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
1
11
|
# Forthic
|
|
2
12
|
|
|
3
13
|
A Forthic interpreter that runs within Ruby.
|
|
@@ -16,5 +16,20 @@ module Forthic
|
|
|
16
16
|
@start_pos = start_pos
|
|
17
17
|
@end_pos = end_pos
|
|
18
18
|
end
|
|
19
|
+
|
|
20
|
+
# @return [String]
|
|
21
|
+
def to_s
|
|
22
|
+
"#{@screen_name}:#{@line}:#{@column}"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# @return [Integer]
|
|
26
|
+
def line_number
|
|
27
|
+
@line
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# @return [Integer]
|
|
31
|
+
def column_number
|
|
32
|
+
@column
|
|
33
|
+
end
|
|
19
34
|
end
|
|
20
35
|
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../forthic_error"
|
|
4
|
+
|
|
5
|
+
module Forthic
|
|
6
|
+
module Errors
|
|
7
|
+
class UnknownWordError < ForthicError
|
|
8
|
+
attr_reader :word_name
|
|
9
|
+
|
|
10
|
+
# @param [String] word_name The name of the unknown word
|
|
11
|
+
# @param [CodeLocation, nil] location Where the error occurred
|
|
12
|
+
# @param [Array<String>] suggested_words Optional list of similar words for suggestions
|
|
13
|
+
def initialize(word_name, location = nil, suggested_words = [])
|
|
14
|
+
@word_name = word_name
|
|
15
|
+
@suggested_words = suggested_words
|
|
16
|
+
|
|
17
|
+
description = build_description(suggested_words)
|
|
18
|
+
super(ErrorCodes::WORD_NOT_FOUND, "Word '#{word_name}' not found", description, location)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# @return [Array<String>] List of suggested similar words
|
|
22
|
+
def suggested_words
|
|
23
|
+
@suggested_words.dup
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
# @param [Array<String>] suggested_words
|
|
29
|
+
# @return [String]
|
|
30
|
+
def build_description(suggested_words)
|
|
31
|
+
base_description = "Check for typos in the word name or ensure the word has been defined."
|
|
32
|
+
return base_description if suggested_words.empty?
|
|
33
|
+
|
|
34
|
+
suggestions = suggested_words.take(3).join(", ")
|
|
35
|
+
"#{base_description} Did you mean: #{suggestions}?"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -46,5 +46,20 @@ module Forthic
|
|
|
46
46
|
|
|
47
47
|
result.reverse
|
|
48
48
|
end
|
|
49
|
+
|
|
50
|
+
# @return [String]
|
|
51
|
+
def message
|
|
52
|
+
to_s
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# @return [String]
|
|
56
|
+
def to_s
|
|
57
|
+
parts = [@title]
|
|
58
|
+
parts << "at #{@location}" if @location
|
|
59
|
+
if @description && !@description.empty?
|
|
60
|
+
parts[-1] = "#{parts[-1]}: #{@description}"
|
|
61
|
+
end
|
|
62
|
+
parts.join(" ")
|
|
63
|
+
end
|
|
49
64
|
end
|
|
50
65
|
end
|
data/lib/forthic/interpreter.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "forthic_error"
|
|
4
|
+
require_relative "errors/unknown_word_error"
|
|
4
5
|
require_relative "tokenizer"
|
|
5
6
|
require_relative "token"
|
|
6
7
|
require_relative "code_location"
|
|
@@ -220,7 +221,11 @@ module Forthic
|
|
|
220
221
|
next if [TokenType::START_DEF, TokenType::END_DEF, TokenType::COMMENT].include?(token.type) || @execution_state.is_compiling
|
|
221
222
|
end
|
|
222
223
|
true
|
|
224
|
+
rescue ForthicError => e
|
|
225
|
+
# Re-raise ForthicError and its subclasses without wrapping
|
|
226
|
+
raise e
|
|
223
227
|
rescue => e
|
|
228
|
+
# Wrap non-ForthicError exceptions
|
|
224
229
|
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
230
|
error.set_caught_error(e)
|
|
226
231
|
raise error
|
|
@@ -409,7 +414,11 @@ module Forthic
|
|
|
409
414
|
# @param [Token] token
|
|
410
415
|
def handle_word_token(token)
|
|
411
416
|
word = find_word(token.string)
|
|
412
|
-
|
|
417
|
+
unless word
|
|
418
|
+
# Generate suggested words for better error messages
|
|
419
|
+
suggested_words = find_similar_words(token.string)
|
|
420
|
+
raise Errors::UnknownWordError.new(token.string, token.location, suggested_words)
|
|
421
|
+
end
|
|
413
422
|
handle_word(word, token.location)
|
|
414
423
|
end
|
|
415
424
|
|
|
@@ -424,5 +433,86 @@ module Forthic
|
|
|
424
433
|
word.execute(self)
|
|
425
434
|
end
|
|
426
435
|
end
|
|
436
|
+
|
|
437
|
+
private
|
|
438
|
+
|
|
439
|
+
# Find words similar to the given word name for error suggestions
|
|
440
|
+
# @param [String] word_name The unknown word to find suggestions for
|
|
441
|
+
# @return [Array<String>] Array of similar word names
|
|
442
|
+
def find_similar_words(word_name)
|
|
443
|
+
return [] if word_name.nil? || word_name.empty?
|
|
444
|
+
|
|
445
|
+
all_words = collect_available_words
|
|
446
|
+
|
|
447
|
+
# Find words with similar names using simple string distance
|
|
448
|
+
suggestions = all_words.select do |available_word|
|
|
449
|
+
levenshtein_distance(word_name.downcase, available_word.downcase) <= 2
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
# If no close matches, try prefix matching
|
|
453
|
+
if suggestions.empty?
|
|
454
|
+
suggestions = all_words.select do |available_word|
|
|
455
|
+
available_word.downcase.start_with?(word_name[0, 2].downcase) ||
|
|
456
|
+
word_name.downcase.start_with?(available_word[0, 2].downcase)
|
|
457
|
+
end
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
suggestions.take(3)
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
# Collect all available word names from all modules in scope
|
|
464
|
+
# @return [Array<String>] Array of all available word names
|
|
465
|
+
def collect_available_words
|
|
466
|
+
words = []
|
|
467
|
+
|
|
468
|
+
# Collect from global module (hardcoded common words since GlobalModule uses methods)
|
|
469
|
+
global_words = %w[
|
|
470
|
+
POP DUP SWAP >STR CONCAT SPLIT JOIN /N /R /T LOWERCASE UPPERCASE
|
|
471
|
+
APPEND REVERSE UNIQUE MAP FOREACH KEYS VALUES LENGTH RANGE SLICE
|
|
472
|
+
SELECT TAKE DROP NTH LAST FLATTEN REDUCE + - * / MOD
|
|
473
|
+
== != > >= < <= OR AND NOT IN BOOL INT FLOAT
|
|
474
|
+
VARIABLES ! @ !@ INTERPRET EXPORT USE-MODULES REC
|
|
475
|
+
]
|
|
476
|
+
words.concat(global_words)
|
|
477
|
+
|
|
478
|
+
# Collect from module stack
|
|
479
|
+
@execution_state.module_stack.each do |mod|
|
|
480
|
+
if mod.respond_to?(:words) && mod.words
|
|
481
|
+
words.concat(mod.words.map(&:name))
|
|
482
|
+
end
|
|
483
|
+
end
|
|
484
|
+
|
|
485
|
+
words.uniq.compact
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
# Calculate Levenshtein distance between two strings
|
|
489
|
+
# @param [String] str1
|
|
490
|
+
# @param [String] str2
|
|
491
|
+
# @return [Integer] The edit distance between the strings
|
|
492
|
+
def levenshtein_distance(str1, str2)
|
|
493
|
+
return str2.length if str1.empty?
|
|
494
|
+
return str1.length if str2.empty?
|
|
495
|
+
|
|
496
|
+
# Create matrix
|
|
497
|
+
matrix = Array.new(str1.length + 1) { Array.new(str2.length + 1, 0) }
|
|
498
|
+
|
|
499
|
+
# Initialize first row and column
|
|
500
|
+
(0..str1.length).each { |i| matrix[i][0] = i }
|
|
501
|
+
(0..str2.length).each { |j| matrix[0][j] = j }
|
|
502
|
+
|
|
503
|
+
# Fill matrix
|
|
504
|
+
(1..str1.length).each do |i|
|
|
505
|
+
(1..str2.length).each do |j|
|
|
506
|
+
cost = (str1[i - 1] == str2[j - 1]) ? 0 : 1
|
|
507
|
+
matrix[i][j] = [
|
|
508
|
+
matrix[i - 1][j] + 1, # deletion
|
|
509
|
+
matrix[i][j - 1] + 1, # insertion
|
|
510
|
+
matrix[i - 1][j - 1] + cost # substitution
|
|
511
|
+
].min
|
|
512
|
+
end
|
|
513
|
+
end
|
|
514
|
+
|
|
515
|
+
matrix[str1.length][str2.length]
|
|
516
|
+
end
|
|
427
517
|
end
|
|
428
518
|
end
|
data/lib/forthic/version.rb
CHANGED
data/lib/forthic.rb
CHANGED
|
@@ -8,6 +8,10 @@ module Forthic
|
|
|
8
8
|
autoload :Token, "forthic/token"
|
|
9
9
|
autoload :PositionedString, "forthic/positioned_string"
|
|
10
10
|
autoload :ForthicError, "forthic/forthic_error"
|
|
11
|
+
|
|
12
|
+
module Errors
|
|
13
|
+
autoload :UnknownWordError, "forthic/errors/unknown_word_error"
|
|
14
|
+
end
|
|
11
15
|
autoload :Word, "forthic/words/word"
|
|
12
16
|
autoload :PushValueWord, "forthic/words/push_value_word"
|
|
13
17
|
autoload :DefinitionWord, "forthic/words/definition_word"
|
metadata
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: forthic
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Rino Jose
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-01-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
|
-
description: This package provides a Forthic interpreter that allows you
|
|
14
|
-
Forthic code within your Ruby projects. Forthic is a stack-based programming
|
|
15
|
-
inspired by Forth.
|
|
13
|
+
description: "[ARCHIVED] This package provides a Forthic interpreter that allows you
|
|
14
|
+
to execute Forthic code within your Ruby projects. Forthic is a stack-based programming
|
|
15
|
+
language inspired by Forth. This gem is from an archived repository. Please see
|
|
16
|
+
https://github.com/forthix/forthic-rb for the new official repository."
|
|
16
17
|
email:
|
|
17
18
|
- rjose@forthix.com
|
|
18
19
|
executables: []
|
|
@@ -27,6 +28,7 @@ files:
|
|
|
27
28
|
- Rakefile
|
|
28
29
|
- lib/forthic.rb
|
|
29
30
|
- lib/forthic/code_location.rb
|
|
31
|
+
- lib/forthic/errors/unknown_word_error.rb
|
|
30
32
|
- lib/forthic/forthic_error.rb
|
|
31
33
|
- lib/forthic/forthic_module.rb
|
|
32
34
|
- lib/forthic/global_module.rb
|
|
@@ -49,12 +51,16 @@ files:
|
|
|
49
51
|
- lib/forthic/words/start_module_word.rb
|
|
50
52
|
- lib/forthic/words/word.rb
|
|
51
53
|
- sig/forthic.rbs
|
|
52
|
-
homepage: https://github.com/
|
|
54
|
+
homepage: https://github.com/forthix/forthic-rb
|
|
53
55
|
licenses: []
|
|
54
56
|
metadata:
|
|
55
|
-
homepage_uri: https://github.com/
|
|
56
|
-
source_code_uri: https://github.com/
|
|
57
|
-
post_install_message:
|
|
57
|
+
homepage_uri: https://github.com/forthix/forthic-rb
|
|
58
|
+
source_code_uri: https://github.com/forthix/forthic-rb
|
|
59
|
+
post_install_message: |
|
|
60
|
+
⚠️ NOTICE: This gem is from an archived repository.
|
|
61
|
+
|
|
62
|
+
The Forthic project has moved to: https://github.com/forthix/forthic-rb
|
|
63
|
+
Please visit the new repository for updates and support.
|
|
58
64
|
rdoc_options: []
|
|
59
65
|
require_paths:
|
|
60
66
|
- lib
|
|
@@ -72,5 +78,5 @@ requirements: []
|
|
|
72
78
|
rubygems_version: 3.3.26
|
|
73
79
|
signing_key:
|
|
74
80
|
specification_version: 4
|
|
75
|
-
summary: A Forthic interpreter that runs within Ruby.
|
|
81
|
+
summary: "[ARCHIVED] A Forthic interpreter that runs within Ruby - See https://github.com/forthix/forthic-rb"
|
|
76
82
|
test_files: []
|