forthic 0.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4e71f6368dc2bcc817f0095a389740a6676005ab8ddb862cdef02f0e0910d09d
4
- data.tar.gz: b408177ce893d5353aa00ce2a73698005c07e22e3d68a8ec6cade6032887a591
3
+ metadata.gz: 4ebffd3b7bf74a96a5bdbb6d178996eeea1c2d35edc22743e4dba9154e1e40f9
4
+ data.tar.gz: a34907460efd7db068214dff1410b512a9a9ad10e3eee149e120eb5b414ebc2f
5
5
  SHA512:
6
- metadata.gz: 2ffd692800bdf839d25a106c79bea485addaeabb7d2eafd5366a9d034927a642fed7b4ecb498e5f081016f5079077d3a4db4ba96eae113a8ce547024b4164736
7
- data.tar.gz: b4ab0aec5f7b788873bbbc71761f5382f565864057101125919338c24453bdccdedbcf26f281dc5c46dee4a16fc7824a08516a52c9c318af91ab0f932a329f42
6
+ metadata.gz: 7013c8908441bc6aaee014af8e6ac124bf0e60245474adacdcf4a8633c686ef781dc022e0f163a93222dfd3435e5e21c875ac273f13ae029909f51d354fbfdeb
7
+ data.tar.gz: 759a725d11e735ab283d99e076cf314f72ff98c086cf2dcd0ff93077f2031fa0bb27d814008f63ced3c179b6803f566a10d6b79a5e0082d9c91c30f9159b3d03
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.2.0] - 2025-01-13
4
+
5
+ - Add `import_module` method to Interpreter class
6
+ - Add test coverage for module importing functionality
7
+ - Implement module importing with prefix support matching forthic-ts behavior
8
+
3
9
  ## [0.1.0] - 2024-12-27
4
10
 
5
11
  - Initial release
data/CLAUDE.md ADDED
@@ -0,0 +1,74 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Development Commands
6
+
7
+ ### Testing
8
+ - `rake test` - Run all tests using Minitest
9
+ - `rake test TEST=test/test_specific_file.rb` - Run a specific test file
10
+ - `bundle exec guard` - Start Guard for continuous testing (watches file changes)
11
+ - `rake guard` - Alternative command to start Guard
12
+
13
+ ### Code Quality
14
+ - `rake standard` - Run StandardRB linter for code formatting and style
15
+ - `rake standard:fix` - Auto-fix StandardRB issues where possible
16
+ - `rake` - Run default task (both tests and linting)
17
+
18
+ ### Development
19
+ - `bundle install` - Install gem dependencies
20
+ - `bundle exec rake build` - Build the gem
21
+ - `bundle exec rake install` - Install the gem locally
22
+ - `bundle exec rake release` - Release the gem (requires proper credentials)
23
+
24
+ ## Architecture Overview
25
+
26
+ This is a Ruby implementation of the Forthic programming language - a stack-based language inspired by Forth. The codebase follows a clean modular architecture:
27
+
28
+ ### Core Components
29
+
30
+ **Interpreter (`lib/forthic/interpreter.rb`)**: The main execution engine that:
31
+ - Manages the execution stack and module stack
32
+ - Handles tokenization and parsing of Forthic code
33
+ - Provides word lookup and execution
34
+ - Supports profiling and debugging capabilities
35
+ - Manages compilation of word definitions
36
+
37
+ **Tokenizer (`lib/forthic/tokenizer.rb`)**: Lexical analyzer that breaks Forthic code into tokens (strings, words, arrays, modules, definitions, comments).
38
+
39
+ **Word System (`lib/forthic/words/`)**: Polymorphic word execution system where each word type implements an `execute` method:
40
+ - `Word` - Base class for all executable words
41
+ - `PushValueWord` - Pushes values onto the stack
42
+ - `DefinitionWord` - User-defined words compiled from Forthic code
43
+ - `EndArrayWord` - Handles array construction
44
+ - `ModuleWord` variants - Handle module operations and memoization
45
+ - `StartModuleWord`/`EndModuleWord` - Module boundary management
46
+
47
+ **Module System**:
48
+ - `GlobalModule` - Built-in words and core functionality
49
+ - `ForthicModule` - User-defined modules with isolated namespaces
50
+ - Module stack for hierarchical word resolution
51
+
52
+ ### Key Design Patterns
53
+
54
+ - **Stack-based execution**: All operations work with a central execution stack
55
+ - **Autoloading**: Classes are autoloaded for better startup performance
56
+ - **Error handling**: Custom `ForthicError` with location tracking for debugging
57
+ - **Compilation**: Words can be compiled into definition words for reuse
58
+ - **Memoization**: Special memo words for caching expensive computations
59
+
60
+ ### Testing Strategy
61
+
62
+ Uses Minitest for testing with:
63
+ - `test_helper.rb` sets up Minitest with SpecReporter for better output
64
+ - Guard for continuous testing during development
65
+ - Tests cover tokenizer, interpreter, and module functionality
66
+ - StandardRB enforces consistent code style
67
+
68
+ ### File Organization
69
+
70
+ - `lib/forthic.rb` - Main entry point with autoload declarations
71
+ - `lib/forthic/` - Core implementation files
72
+ - `lib/forthic/words/` - Word implementation classes
73
+ - `test/` - Test files following Minitest conventions
74
+ - `sig/` - RBS type signatures for static analysis
data/Guardfile CHANGED
@@ -17,9 +17,9 @@
17
17
 
18
18
  guard :minitest do
19
19
  # with Minitest::Unit
20
- watch(%r{^test/(.*)\/?test_(.*)\.rb$})
21
- watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { |m| "test/#{m[1]}test_#{m[2]}.rb" }
22
- watch(%r{^test/test_helper\.rb$}) { 'test' }
20
+ watch(%r{^test/(.*)/?test_(.*)\.rb$})
21
+ watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { |m| "test/#{m[1]}test_#{m[2]}.rb" }
22
+ watch(%r{^test/test_helper\.rb$}) { "test" }
23
23
 
24
24
  # with Minitest::Spec
25
25
  # watch(%r{^spec/(.*)_spec\.rb$})
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.
data/Rakefile CHANGED
@@ -11,4 +11,4 @@ task default: %i[test standard]
11
11
 
12
12
  task :guard do
13
13
  sh "bundle exec guard"
14
- end
14
+ end
@@ -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
@@ -14,7 +14,6 @@ module Forthic
14
14
  @description = description
15
15
  @location = location
16
16
  @caught_error = nil
17
- puts "ForthicError: #{error_key}, #{title}, #{description}, #{location}"
18
17
  end
19
18
 
20
19
  # @param [ForthicError] error
@@ -47,5 +46,20 @@ module Forthic
47
46
 
48
47
  result.reverse
49
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
50
64
  end
51
- end
65
+ end
@@ -1,12 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'words/word'
4
- require_relative 'words/module_word'
5
- require_relative 'words/module_memo_word'
6
- require_relative 'words/module_memo_bang_word'
7
- require_relative 'words/module_memo_bang_at_word'
8
- require_relative 'words/imported_word'
9
- require_relative 'variable'
3
+ require "set"
4
+ require_relative "words/word"
5
+ require_relative "words/module_word"
6
+ require_relative "words/module_memo_word"
7
+ require_relative "words/module_memo_bang_word"
8
+ require_relative "words/module_memo_bang_at_word"
9
+ require_relative "words/imported_word"
10
+ require_relative "variable"
10
11
 
11
12
  module Forthic
12
13
  class ForthicModule
@@ -42,7 +43,7 @@ module Forthic
42
43
  # @param [String] prefix
43
44
  # @param [ForthicModule] mod
44
45
  def require_module(prefix, mod)
45
- @required_modules << { prefix: prefix, module: mod }
46
+ @required_modules << {prefix: prefix, module: mod}
46
47
  end
47
48
 
48
49
  # @param [String] name
@@ -142,4 +143,4 @@ module Forthic
142
143
  var_result ? PushValueWord.new(varname, var_result) : nil
143
144
  end
144
145
  end
145
- end
146
+ end