forthic 0.1.0 → 0.3.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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +314 -14
  3. data/Rakefile +37 -8
  4. data/lib/forthic/decorators/docs.rb +69 -0
  5. data/lib/forthic/decorators/word.rb +331 -0
  6. data/lib/forthic/errors.rb +270 -0
  7. data/lib/forthic/grpc/client.rb +223 -0
  8. data/lib/forthic/grpc/errors.rb +149 -0
  9. data/lib/forthic/grpc/forthic_runtime_pb.rb +32 -0
  10. data/lib/forthic/grpc/forthic_runtime_services_pb.rb +31 -0
  11. data/lib/forthic/grpc/remote_module.rb +120 -0
  12. data/lib/forthic/grpc/remote_runtime_module.rb +148 -0
  13. data/lib/forthic/grpc/remote_word.rb +91 -0
  14. data/lib/forthic/grpc/runtime_manager.rb +60 -0
  15. data/lib/forthic/grpc/serializer.rb +184 -0
  16. data/lib/forthic/grpc/server.rb +361 -0
  17. data/lib/forthic/interpreter.rb +682 -133
  18. data/lib/forthic/literals.rb +170 -0
  19. data/lib/forthic/module.rb +383 -0
  20. data/lib/forthic/modules/standard/array_module.rb +940 -0
  21. data/lib/forthic/modules/standard/boolean_module.rb +176 -0
  22. data/lib/forthic/modules/standard/core_module.rb +362 -0
  23. data/lib/forthic/modules/standard/datetime_module.rb +349 -0
  24. data/lib/forthic/modules/standard/json_module.rb +55 -0
  25. data/lib/forthic/modules/standard/math_module.rb +365 -0
  26. data/lib/forthic/modules/standard/record_module.rb +203 -0
  27. data/lib/forthic/modules/standard/string_module.rb +170 -0
  28. data/lib/forthic/tokenizer.rb +225 -78
  29. data/lib/forthic/utils.rb +35 -0
  30. data/lib/forthic/websocket/handler.rb +548 -0
  31. data/lib/forthic/websocket/serializer.rb +160 -0
  32. data/lib/forthic/word_options.rb +141 -0
  33. data/lib/forthic.rb +30 -20
  34. data/protos/README.md +43 -0
  35. data/protos/v1/forthic_runtime.proto +200 -0
  36. metadata +76 -39
  37. data/.standard.yml +0 -3
  38. data/CHANGELOG.md +0 -5
  39. data/Guardfile +0 -42
  40. data/lib/forthic/code_location.rb +0 -20
  41. data/lib/forthic/forthic_error.rb +0 -51
  42. data/lib/forthic/forthic_module.rb +0 -145
  43. data/lib/forthic/global_module.rb +0 -2341
  44. data/lib/forthic/positioned_string.rb +0 -19
  45. data/lib/forthic/token.rb +0 -38
  46. data/lib/forthic/variable.rb +0 -34
  47. data/lib/forthic/version.rb +0 -5
  48. data/lib/forthic/words/definition_word.rb +0 -40
  49. data/lib/forthic/words/end_array_word.rb +0 -28
  50. data/lib/forthic/words/end_module_word.rb +0 -16
  51. data/lib/forthic/words/imported_word.rb +0 -27
  52. data/lib/forthic/words/map_word.rb +0 -169
  53. data/lib/forthic/words/module_memo_bang_at_word.rb +0 -22
  54. data/lib/forthic/words/module_memo_bang_word.rb +0 -21
  55. data/lib/forthic/words/module_memo_word.rb +0 -35
  56. data/lib/forthic/words/module_word.rb +0 -21
  57. data/lib/forthic/words/push_value_word.rb +0 -21
  58. data/lib/forthic/words/start_module_word.rb +0 -31
  59. data/lib/forthic/words/word.rb +0 -30
  60. data/sig/forthic.rbs +0 -4
metadata CHANGED
@@ -1,57 +1,93 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: forthic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rino Jose
8
- bindir: exe
8
+ autorequire:
9
+ bindir: bin
9
10
  cert_chain: []
10
- date: 2025-01-02 00:00:00.000000000 Z
11
- dependencies: []
12
- description: This package provides a Forthic interpreter that allows you to execute
13
- Forthic code within your Ruby projects. Forthic is a stack-based programming language
14
- inspired by Forth.
11
+ date: 2025-11-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.12'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.12'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '13.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '13.0'
41
+ description: Forthic is a stack-based, concatenative programming language designed
42
+ for data manipulation and processing. This is the Ruby implementation with WebSocket
43
+ support for remote word execution.
15
44
  email:
16
- - rjose@forthix.com
45
+ - rjose@gmail.com
17
46
  executables: []
18
47
  extensions: []
19
48
  extra_rdoc_files: []
20
49
  files:
21
- - ".standard.yml"
22
- - CHANGELOG.md
23
- - Guardfile
24
50
  - README.md
25
51
  - Rakefile
26
52
  - lib/forthic.rb
27
- - lib/forthic/code_location.rb
28
- - lib/forthic/forthic_error.rb
29
- - lib/forthic/forthic_module.rb
30
- - lib/forthic/global_module.rb
53
+ - lib/forthic/decorators/docs.rb
54
+ - lib/forthic/decorators/word.rb
55
+ - lib/forthic/errors.rb
56
+ - lib/forthic/grpc/client.rb
57
+ - lib/forthic/grpc/errors.rb
58
+ - lib/forthic/grpc/forthic_runtime_pb.rb
59
+ - lib/forthic/grpc/forthic_runtime_services_pb.rb
60
+ - lib/forthic/grpc/remote_module.rb
61
+ - lib/forthic/grpc/remote_runtime_module.rb
62
+ - lib/forthic/grpc/remote_word.rb
63
+ - lib/forthic/grpc/runtime_manager.rb
64
+ - lib/forthic/grpc/serializer.rb
65
+ - lib/forthic/grpc/server.rb
31
66
  - lib/forthic/interpreter.rb
32
- - lib/forthic/positioned_string.rb
33
- - lib/forthic/token.rb
67
+ - lib/forthic/literals.rb
68
+ - lib/forthic/module.rb
69
+ - lib/forthic/modules/standard/array_module.rb
70
+ - lib/forthic/modules/standard/boolean_module.rb
71
+ - lib/forthic/modules/standard/core_module.rb
72
+ - lib/forthic/modules/standard/datetime_module.rb
73
+ - lib/forthic/modules/standard/json_module.rb
74
+ - lib/forthic/modules/standard/math_module.rb
75
+ - lib/forthic/modules/standard/record_module.rb
76
+ - lib/forthic/modules/standard/string_module.rb
34
77
  - lib/forthic/tokenizer.rb
35
- - lib/forthic/variable.rb
36
- - lib/forthic/version.rb
37
- - lib/forthic/words/definition_word.rb
38
- - lib/forthic/words/end_array_word.rb
39
- - lib/forthic/words/end_module_word.rb
40
- - lib/forthic/words/imported_word.rb
41
- - lib/forthic/words/map_word.rb
42
- - lib/forthic/words/module_memo_bang_at_word.rb
43
- - lib/forthic/words/module_memo_bang_word.rb
44
- - lib/forthic/words/module_memo_word.rb
45
- - lib/forthic/words/module_word.rb
46
- - lib/forthic/words/push_value_word.rb
47
- - lib/forthic/words/start_module_word.rb
48
- - lib/forthic/words/word.rb
49
- - sig/forthic.rbs
50
- homepage: https://github.com/linkedin/forthic
51
- licenses: []
78
+ - lib/forthic/utils.rb
79
+ - lib/forthic/websocket/handler.rb
80
+ - lib/forthic/websocket/serializer.rb
81
+ - lib/forthic/word_options.rb
82
+ - protos/README.md
83
+ - protos/v1/forthic_runtime.proto
84
+ homepage: https://github.com/forthix/forthic
85
+ licenses:
86
+ - MIT
52
87
  metadata:
53
- homepage_uri: https://github.com/linkedin/forthic
54
- source_code_uri: https://github.com/linkedin/forthic
88
+ homepage_uri: https://github.com/forthix/forthic
89
+ source_code_uri: https://github.com/forthix/forthic
90
+ post_install_message:
55
91
  rdoc_options: []
56
92
  require_paths:
57
93
  - lib
@@ -59,14 +95,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
59
95
  requirements:
60
96
  - - ">="
61
97
  - !ruby/object:Gem::Version
62
- version: 3.1.0
98
+ version: 3.0.0
63
99
  required_rubygems_version: !ruby/object:Gem::Requirement
64
100
  requirements:
65
101
  - - ">="
66
102
  - !ruby/object:Gem::Version
67
103
  version: '0'
68
104
  requirements: []
69
- rubygems_version: 3.6.2
105
+ rubygems_version: 3.3.26
106
+ signing_key:
70
107
  specification_version: 4
71
- summary: A Forthic interpreter that runs within Ruby.
108
+ summary: Ruby implementation of the Forthic programming language
72
109
  test_files: []
data/.standard.yml DELETED
@@ -1,3 +0,0 @@
1
- # For available configuration options, see:
2
- # https://github.com/standardrb/standard
3
- ruby_version: 3.1
data/CHANGELOG.md DELETED
@@ -1,5 +0,0 @@
1
- ## [Unreleased]
2
-
3
- ## [0.1.0] - 2024-12-27
4
-
5
- - Initial release
data/Guardfile DELETED
@@ -1,42 +0,0 @@
1
- # A sample Guardfile
2
- # More info at https://github.com/guard/guard#readme
3
-
4
- ## Uncomment and set this to only include directories you want to watch
5
- # directories %w(app lib config test spec features) \
6
- # .select{|d| Dir.exist?(d) ? d : UI.warning("Directory #{d} does not exist")}
7
-
8
- ## Note: if you are using the `directories` clause above and you are not
9
- ## watching the project directory ('.'), then you will want to move
10
- ## the Guardfile to a watched dir and symlink it back, e.g.
11
- #
12
- # $ mkdir config
13
- # $ mv Guardfile config/
14
- # $ ln -s config/Guardfile .
15
- #
16
- # and, you'll have to watch "config/Guardfile" instead of "Guardfile"
17
-
18
- guard :minitest do
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' }
23
-
24
- # with Minitest::Spec
25
- # watch(%r{^spec/(.*)_spec\.rb$})
26
- # watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
27
- # watch(%r{^spec/spec_helper\.rb$}) { 'spec' }
28
-
29
- # Rails 4
30
- # watch(%r{^app/(.+)\.rb$}) { |m| "test/#{m[1]}_test.rb" }
31
- # watch(%r{^app/controllers/application_controller\.rb$}) { 'test/controllers' }
32
- # watch(%r{^app/controllers/(.+)_controller\.rb$}) { |m| "test/integration/#{m[1]}_test.rb" }
33
- # watch(%r{^app/views/(.+)_mailer/.+}) { |m| "test/mailers/#{m[1]}_mailer_test.rb" }
34
- # watch(%r{^lib/(.+)\.rb$}) { |m| "test/lib/#{m[1]}_test.rb" }
35
- # watch(%r{^test/.+_test\.rb$})
36
- # watch(%r{^test/test_helper\.rb$}) { 'test' }
37
-
38
- # Rails < 4
39
- # watch(%r{^app/controllers/(.*)\.rb$}) { |m| "test/functional/#{m[1]}_test.rb" }
40
- # watch(%r{^app/helpers/(.*)\.rb$}) { |m| "test/helpers/#{m[1]}_test.rb" }
41
- # watch(%r{^app/models/(.*)\.rb$}) { |m| "test/unit/#{m[1]}_test.rb" }
42
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Forthic
4
- class CodeLocation
5
- attr_accessor :screen_name, :line, :column, :start_pos, :end_pos
6
-
7
- # @param [String] screen_name
8
- # @param [Integer] line
9
- # @param [Integer] column
10
- # @param [Integer] start_pos
11
- # @param [Integer] end_pos
12
- def initialize(screen_name: "<ad-hoc>", line: 1, column: 1, start_pos: 0, end_pos: 0)
13
- @screen_name = screen_name
14
- @line = line
15
- @column = column
16
- @start_pos = start_pos
17
- @end_pos = end_pos
18
- end
19
- end
20
- end
@@ -1,51 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Forthic
4
- class ForthicError < StandardError
5
- attr_accessor :error_key, :title, :description, :location, :caught_error
6
-
7
- # @param [String] error_key
8
- # @param [String] title
9
- # @param [String] description
10
- # @param [CodeLocation, nil] location
11
- def initialize(error_key, title, description, location = nil)
12
- @error_key = error_key
13
- @title = title
14
- @description = description
15
- @location = location
16
- @caught_error = nil
17
- puts "ForthicError: #{error_key}, #{title}, #{description}, #{location}"
18
- end
19
-
20
- # @param [ForthicError] error
21
- def set_caught_error(error)
22
- @caught_error = error
23
- end
24
-
25
- # @return [String]
26
- def get_title
27
- @title
28
- end
29
-
30
- # @return [String]
31
- def get_description
32
- @description
33
- end
34
-
35
- # @return [Array<ForthicError>]
36
- def get_error_stack
37
- max_depth = 100
38
- cur_error = self
39
- result = [cur_error]
40
-
41
- max_depth.times do
42
- break unless cur_error.caught_error
43
-
44
- result << cur_error.caught_error
45
- cur_error = cur_error.caught_error
46
- end
47
-
48
- result.reverse
49
- end
50
- end
51
- end
@@ -1,145 +0,0 @@
1
- # frozen_string_literal: true
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'
10
-
11
- module Forthic
12
- class ForthicModule
13
- attr_accessor :words, :exportable, :variables, :modules, :module_prefixes, :required_modules, :name, :forthic_code, :module_id
14
-
15
- # @param [String] name
16
- # @param [Interpreter, nil] interp
17
- # @param [String] forthic_code
18
- def initialize(name, interp = nil, forthic_code = "")
19
- @words = []
20
- @exportable = []
21
- @variables = {}
22
- @modules = {}
23
- @module_prefixes = {}
24
- @required_modules = []
25
- @name = name
26
- @forthic_code = forthic_code
27
- @module_id = "#{name}-#{rand(1_000_000)}"
28
- end
29
-
30
- # @return [ForthicModule]
31
- def dup
32
- result = ForthicModule.new(@name, @interp, @forthic_code)
33
- result.words = @words.dup
34
- result.exportable = @exportable.dup
35
- @variables.each { |key, var| result.variables[key] = var.dup }
36
- @modules.each { |key, mod| result.modules[key] = mod }
37
- result.required_modules = @required_modules.dup
38
- result.forthic_code = @forthic_code
39
- result
40
- end
41
-
42
- # @param [String] prefix
43
- # @param [ForthicModule] mod
44
- def require_module(prefix, mod)
45
- @required_modules << { prefix: prefix, module: mod }
46
- end
47
-
48
- # @param [String] name
49
- # @return [ForthicModule, nil]
50
- def find_module(name)
51
- @modules[name]
52
- end
53
-
54
- # @param [String] word_name
55
- # @param [Proc] word_func
56
- def add_module_word(word_name, word_func)
57
- add_exportable_word(ModuleWord.new(word_name, word_func))
58
- end
59
-
60
- # @param [Word] word
61
- def add_word(word)
62
- @words << word
63
- end
64
-
65
- # @param [Word] word
66
- # @return [ModuleMemoWord]
67
- def add_memo_words(word)
68
- memo_word = ModuleMemoWord.new(word)
69
- @words << memo_word
70
- @words << ModuleMemoBangWord.new(memo_word)
71
- @words << ModuleMemoBangAtWord.new(memo_word)
72
- memo_word
73
- end
74
-
75
- # @param [Array<String>] names
76
- def add_exportable(names)
77
- @exportable.concat(names)
78
- end
79
-
80
- # @return [Array<Word>]
81
- def exportable_words
82
- @words.select { |word| @exportable.include?(word.name) }
83
- end
84
-
85
- # @param [Word] word
86
- def add_exportable_word(word)
87
- @words << word
88
- @exportable << word.name
89
- end
90
-
91
- # @param [String] name
92
- # @param [Object, nil] value
93
- def add_variable(name, value = nil)
94
- @variables[name] ||= Variable.new(name, value)
95
- end
96
-
97
- # @param [Interpreter] interp
98
- def initialize_modules(interp)
99
- @required_modules.each do |rec|
100
- import_module(rec[:prefix], rec[:module], interp)
101
- end
102
- end
103
-
104
- # @param [String] module_name
105
- # @param [String] prefix
106
- # @param [ForthicModule] mod
107
- def register_module(module_name, prefix, mod)
108
- @modules[module_name] = mod
109
- @module_prefixes[module_name] ||= Set.new
110
- @module_prefixes[module_name] << prefix
111
- end
112
-
113
- # @param [String] prefix
114
- # @param [ForthicModule] mod
115
- # @param [Interpreter] interp
116
- def import_module(prefix, mod, interp)
117
- new_module = mod.dup
118
- new_module.initialize_modules(interp)
119
-
120
- new_module.exportable_words.each do |word|
121
- add_word(ImportedWord.new(word, prefix, new_module))
122
- end
123
- register_module(mod.name, prefix, new_module)
124
- end
125
-
126
- # @param [String] name
127
- # @return [Word, nil]
128
- def find_word(name)
129
- find_dictionary_word(name) || find_variable(name)
130
- end
131
-
132
- # @param [String] word_name
133
- # @return [Word, nil]
134
- def find_dictionary_word(word_name)
135
- @words.reverse.find { |w| w.name == word_name }
136
- end
137
-
138
- # @param [String] varname
139
- # @return [PushValueWord, nil]
140
- def find_variable(varname)
141
- var_result = @variables[varname]
142
- var_result ? PushValueWord.new(varname, var_result) : nil
143
- end
144
- end
145
- end