t-ruby 0.0.41 → 0.0.42
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/lib/t_ruby/cli.rb +1 -1
- data/lib/t_ruby/code_emitter.rb +254 -0
- data/lib/t_ruby/compiler.rb +18 -3
- data/lib/t_ruby/config.rb +18 -3
- data/lib/t_ruby/ruby_version.rb +112 -0
- data/lib/t_ruby/version.rb +1 -1
- data/lib/t_ruby/watcher.rb +16 -1
- data/lib/t_ruby.rb +2 -0
- metadata +8 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 75019794a577853cf5a7e704febef3868a1ddd06776e43f50dc684d7dde87e3c
|
|
4
|
+
data.tar.gz: 89a255f7e7b68e2becd6314be09470424d5f418324c40bcc77a7311e6006d9f0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4000a38df6e83591a15f453af3b4d5f759b1af8e869478737c1d7711e34c7e1d65c89df34e56a6575d41e2f120e951970fde1ac444bf24d73c1167a24de875c4
|
|
7
|
+
data.tar.gz: 9273b4bf7d8a9af3ccbe0fa0d93914b13c9ce09f464902a4974749780871516c8fbaeb33a60d1dca754914dde09e498148ec080ff31fef3b11a0a88d96642eee
|
data/lib/t_ruby/cli.rb
CHANGED
|
@@ -135,7 +135,7 @@ module TRuby
|
|
|
135
135
|
compiler:
|
|
136
136
|
strictness: standard # strict | standard | permissive
|
|
137
137
|
generate_rbs: true
|
|
138
|
-
target_ruby: "
|
|
138
|
+
target_ruby: "#{RubyVersion.current.major}.#{RubyVersion.current.minor}"
|
|
139
139
|
# experimental: []
|
|
140
140
|
# checks:
|
|
141
141
|
# no_implicit_any: false
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module TRuby
|
|
4
|
+
# Version-specific code transformation strategies
|
|
5
|
+
#
|
|
6
|
+
# @example
|
|
7
|
+
# emitter = CodeEmitter.for_version("4.0")
|
|
8
|
+
# result = emitter.transform(source)
|
|
9
|
+
#
|
|
10
|
+
module CodeEmitter
|
|
11
|
+
# Factory method to get appropriate emitter for target Ruby version
|
|
12
|
+
#
|
|
13
|
+
# @param target_ruby [String] target Ruby version (e.g., "3.0", "4.0")
|
|
14
|
+
# @return [Base] appropriate emitter instance
|
|
15
|
+
def self.for_version(target_ruby)
|
|
16
|
+
version = RubyVersion.parse(target_ruby)
|
|
17
|
+
|
|
18
|
+
if version.numbered_parameters_raise_error?
|
|
19
|
+
Ruby40.new(version)
|
|
20
|
+
elsif version.supports_it_parameter?
|
|
21
|
+
Ruby34.new(version)
|
|
22
|
+
elsif version.supports_anonymous_block_forwarding?
|
|
23
|
+
Ruby31.new(version)
|
|
24
|
+
else
|
|
25
|
+
Ruby30.new(version)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Base class for version-specific code emitters
|
|
30
|
+
class Base
|
|
31
|
+
attr_reader :version
|
|
32
|
+
|
|
33
|
+
def initialize(version)
|
|
34
|
+
@version = version
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Apply all transformations for this version
|
|
38
|
+
#
|
|
39
|
+
# @param source [String] source code to transform
|
|
40
|
+
# @return [String] transformed source code
|
|
41
|
+
def transform(source)
|
|
42
|
+
result = source.dup
|
|
43
|
+
result = transform_numbered_params(result)
|
|
44
|
+
transform_block_forwarding(result)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Transform numbered block parameters (_1, _2, etc.)
|
|
48
|
+
# Default: no transformation
|
|
49
|
+
#
|
|
50
|
+
# @param source [String] source code
|
|
51
|
+
# @return [String] transformed source code
|
|
52
|
+
def transform_numbered_params(source)
|
|
53
|
+
source
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Transform block forwarding syntax
|
|
57
|
+
# Default: no transformation
|
|
58
|
+
#
|
|
59
|
+
# @param source [String] source code
|
|
60
|
+
# @return [String] transformed source code
|
|
61
|
+
def transform_block_forwarding(source)
|
|
62
|
+
source
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Check if this version supports the `it` implicit block parameter
|
|
66
|
+
#
|
|
67
|
+
# @return [Boolean]
|
|
68
|
+
def supports_it?
|
|
69
|
+
false
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Check if numbered parameters raise NameError in this version
|
|
73
|
+
#
|
|
74
|
+
# @return [Boolean]
|
|
75
|
+
def numbered_params_error?
|
|
76
|
+
false
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Ruby 3.0 emitter - baseline, no transformations
|
|
81
|
+
class Ruby30 < Base
|
|
82
|
+
# Ruby 3.0 uses standard syntax, no transformations needed
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Ruby 3.1+ emitter - supports anonymous block forwarding
|
|
86
|
+
class Ruby31 < Base
|
|
87
|
+
# Transform `def foo(&block) ... bar(&block)` to `def foo(&) ... bar(&)`
|
|
88
|
+
#
|
|
89
|
+
# Only transforms when the block parameter is ONLY used for forwarding,
|
|
90
|
+
# not when it's called directly (e.g., block.call)
|
|
91
|
+
def transform_block_forwarding(source)
|
|
92
|
+
result = source.dup
|
|
93
|
+
|
|
94
|
+
# Find method definitions with block parameters
|
|
95
|
+
# Pattern: def method_name(&block_name)
|
|
96
|
+
result.gsub!(/def\s+(\w+[?!=]?)\s*\(([^)]*?)&(\w+)\s*\)/) do |_match|
|
|
97
|
+
method_name = ::Regexp.last_match(1)
|
|
98
|
+
other_params = ::Regexp.last_match(2)
|
|
99
|
+
block_name = ::Regexp.last_match(3)
|
|
100
|
+
|
|
101
|
+
# Find the method body to check block usage
|
|
102
|
+
method_start = ::Regexp.last_match.begin(0)
|
|
103
|
+
remaining = result[method_start..]
|
|
104
|
+
|
|
105
|
+
# Check if block is only used for forwarding (not called directly)
|
|
106
|
+
if block_only_forwarded?(remaining, block_name)
|
|
107
|
+
"def #{method_name}(#{other_params}&)"
|
|
108
|
+
else
|
|
109
|
+
"def #{method_name}(#{other_params}&#{block_name})"
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Replace block forwarding calls with anonymous forwarding
|
|
114
|
+
# This is a simplified approach - in practice we'd need proper scope tracking
|
|
115
|
+
result.gsub!(/(\w+)\s*\(\s*&(\w+)\s*\)/) do |match|
|
|
116
|
+
call_name = ::Regexp.last_match(1)
|
|
117
|
+
::Regexp.last_match(2)
|
|
118
|
+
|
|
119
|
+
# Check if this block name was converted to anonymous
|
|
120
|
+
if result.include?("def ") && result.include?("(&)")
|
|
121
|
+
"#{call_name}(&)"
|
|
122
|
+
else
|
|
123
|
+
match
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
result
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
private
|
|
131
|
+
|
|
132
|
+
# Check if a block parameter is only used for forwarding
|
|
133
|
+
def block_only_forwarded?(method_body, block_name)
|
|
134
|
+
# Simple heuristic: if block_name appears with .call or without &, it's not just forwarding
|
|
135
|
+
# Look for patterns like: block_name.call, block_name.(), yield
|
|
136
|
+
|
|
137
|
+
# Extract method body (until next def or end of class)
|
|
138
|
+
lines = method_body.lines
|
|
139
|
+
depth = 0
|
|
140
|
+
body_lines = []
|
|
141
|
+
|
|
142
|
+
lines.each do |line|
|
|
143
|
+
depth += 1 if line.match?(/\b(def|class|module|do|begin|case|if|unless|while|until)\b/)
|
|
144
|
+
depth -= 1 if line.match?(/\bend\b/)
|
|
145
|
+
body_lines << line
|
|
146
|
+
break if depth <= 0 && body_lines.length > 1
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
body = body_lines.join
|
|
150
|
+
|
|
151
|
+
# Check for direct block usage
|
|
152
|
+
return false if body.match?(/\b#{block_name}\s*\./) # block.call, block.(), etc.
|
|
153
|
+
return false if body.match?(/\b#{block_name}\s*\[/) # block[args]
|
|
154
|
+
return false if body.match?(/\byield\b/) # yield instead of forwarding
|
|
155
|
+
|
|
156
|
+
# Only &block_name patterns - this is forwarding
|
|
157
|
+
true
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Ruby 3.4+ emitter - supports `it` implicit block parameter
|
|
162
|
+
class Ruby34 < Ruby31
|
|
163
|
+
def supports_it?
|
|
164
|
+
true
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Ruby 3.4 still supports _1 syntax, so no transformation needed by default
|
|
168
|
+
# Users can opt-in to using `it` style if they want
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Ruby 4.0+ emitter - _1 raises NameError, must use `it`
|
|
172
|
+
class Ruby40 < Ruby34
|
|
173
|
+
def numbered_params_error?
|
|
174
|
+
true
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Transform numbered parameters to appropriate syntax
|
|
178
|
+
#
|
|
179
|
+
# - Single _1 → it
|
|
180
|
+
# - Multiple (_1, _2) → explicit |k, v| params
|
|
181
|
+
def transform_numbered_params(source)
|
|
182
|
+
result = source.dup
|
|
183
|
+
|
|
184
|
+
# Simple approach: replace all _1 with it when it's the only numbered param in scope
|
|
185
|
+
# For complex cases with _2+, we'd need proper parsing
|
|
186
|
+
# For now, do a global replacement if _2 etc are not present
|
|
187
|
+
if result.match?(/\b_[2-9]\b/)
|
|
188
|
+
# Has multiple numbered params - need to convert to explicit params
|
|
189
|
+
# This is a complex case that requires proper block parsing
|
|
190
|
+
transform_multi_numbered_params(result)
|
|
191
|
+
else
|
|
192
|
+
# Only _1 is used - simple replacement
|
|
193
|
+
result.gsub(/\b_1\b/, "it")
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
private
|
|
198
|
+
|
|
199
|
+
def transform_multi_numbered_params(source)
|
|
200
|
+
result = source.dup
|
|
201
|
+
|
|
202
|
+
# Find blocks and transform them
|
|
203
|
+
# Use a recursive approach with placeholder replacement
|
|
204
|
+
|
|
205
|
+
# Replace innermost blocks first
|
|
206
|
+
loop do
|
|
207
|
+
changed = false
|
|
208
|
+
result = result.gsub(/\{([^{}]*)\}/) do |block|
|
|
209
|
+
content = ::Regexp.last_match(1)
|
|
210
|
+
max_param = find_max_numbered_param(content)
|
|
211
|
+
|
|
212
|
+
if max_param > 1
|
|
213
|
+
# Multiple params - convert to explicit
|
|
214
|
+
param_names = generate_param_names(max_param)
|
|
215
|
+
new_content = content.dup
|
|
216
|
+
(1..max_param).each do |i|
|
|
217
|
+
new_content.gsub!(/\b_#{i}\b/, param_names[i - 1])
|
|
218
|
+
end
|
|
219
|
+
changed = true
|
|
220
|
+
"{ |#{param_names.join(", ")}| #{new_content.strip} }"
|
|
221
|
+
elsif max_param == 1
|
|
222
|
+
# Single _1 - convert to it
|
|
223
|
+
changed = true
|
|
224
|
+
"{ #{content.gsub(/\b_1\b/, "it").strip} }"
|
|
225
|
+
else
|
|
226
|
+
block
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
break unless changed
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
result
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def find_max_numbered_param(content)
|
|
236
|
+
max = 0
|
|
237
|
+
content.scan(/\b_(\d+)\b/) do |match|
|
|
238
|
+
num = match[0].to_i
|
|
239
|
+
max = num if num > max
|
|
240
|
+
end
|
|
241
|
+
max
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def generate_param_names(count)
|
|
245
|
+
# Generate simple parameter names: a, b, c, ... or k, v for 2
|
|
246
|
+
if count == 2
|
|
247
|
+
%w[k v]
|
|
248
|
+
else
|
|
249
|
+
("a".."z").take(count)
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
end
|
data/lib/t_ruby/compiler.rb
CHANGED
|
@@ -380,8 +380,8 @@ module TRuby
|
|
|
380
380
|
ir_program = result[:program]
|
|
381
381
|
end
|
|
382
382
|
|
|
383
|
-
# Generate Ruby code using IR-aware generator
|
|
384
|
-
generator = IRCodeGenerator.new
|
|
383
|
+
# Generate Ruby code using IR-aware generator with target Ruby version
|
|
384
|
+
generator = IRCodeGenerator.new(target_ruby: @config.target_ruby)
|
|
385
385
|
generator.generate_with_source(ir_program, source)
|
|
386
386
|
end
|
|
387
387
|
|
|
@@ -434,8 +434,12 @@ module TRuby
|
|
|
434
434
|
|
|
435
435
|
# IR-aware code generator for source-preserving transformation
|
|
436
436
|
class IRCodeGenerator
|
|
437
|
-
|
|
437
|
+
attr_reader :emitter
|
|
438
|
+
|
|
439
|
+
# @param target_ruby [String] target Ruby version (e.g., "3.0", "4.0")
|
|
440
|
+
def initialize(target_ruby: "3.0")
|
|
438
441
|
@output = []
|
|
442
|
+
@emitter = CodeEmitter.for_version(target_ruby)
|
|
439
443
|
end
|
|
440
444
|
|
|
441
445
|
# Generate Ruby code from IR program
|
|
@@ -471,6 +475,9 @@ module TRuby
|
|
|
471
475
|
# Remove return type annotations
|
|
472
476
|
result = erase_return_types(result)
|
|
473
477
|
|
|
478
|
+
# Apply version-specific transformations
|
|
479
|
+
result = @emitter.transform(result)
|
|
480
|
+
|
|
474
481
|
# Clean up extra blank lines
|
|
475
482
|
result.gsub(/\n{3,}/, "\n\n")
|
|
476
483
|
end
|
|
@@ -545,6 +552,14 @@ module TRuby
|
|
|
545
552
|
param = param.strip
|
|
546
553
|
return nil if param.empty?
|
|
547
554
|
|
|
555
|
+
# 0. 블록 파라미터: &name: Type -> &name
|
|
556
|
+
if param.start_with?("&")
|
|
557
|
+
match = param.match(/^&(\w+)(?::\s*.+)?$/)
|
|
558
|
+
return "&#{match[1]}" if match
|
|
559
|
+
|
|
560
|
+
return param
|
|
561
|
+
end
|
|
562
|
+
|
|
548
563
|
# 1. 더블 스플랫: **name: Type -> **name
|
|
549
564
|
if param.start_with?("**")
|
|
550
565
|
match = param.match(/^\*\*(\w+)(?::\s*.+)?$/)
|
data/lib/t_ruby/config.rb
CHANGED
|
@@ -25,7 +25,7 @@ module TRuby
|
|
|
25
25
|
"strictness" => "standard",
|
|
26
26
|
"generate_rbs" => true,
|
|
27
27
|
"type_check" => true,
|
|
28
|
-
"target_ruby" =>
|
|
28
|
+
"target_ruby" => nil, # Auto-detect from current Ruby version
|
|
29
29
|
"experimental" => [],
|
|
30
30
|
"checks" => {
|
|
31
31
|
"no_implicit_any" => false,
|
|
@@ -97,9 +97,24 @@ module TRuby
|
|
|
97
97
|
end
|
|
98
98
|
|
|
99
99
|
# Get target Ruby version
|
|
100
|
-
#
|
|
100
|
+
# If not specified in config, auto-detects from current Ruby environment
|
|
101
|
+
# @return [String] target Ruby version (e.g., "3.0", "3.2", "4.0")
|
|
102
|
+
# @raise [UnsupportedRubyVersionError] if detected version is not supported
|
|
101
103
|
def target_ruby
|
|
102
|
-
|
|
104
|
+
configured = @compiler["target_ruby"]
|
|
105
|
+
if configured
|
|
106
|
+
RubyVersion.parse(configured).validate!
|
|
107
|
+
configured.to_s
|
|
108
|
+
else
|
|
109
|
+
version = RubyVersion.current.validate!
|
|
110
|
+
"#{version.major}.#{version.minor}"
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Get target Ruby version as RubyVersion object
|
|
115
|
+
# @return [RubyVersion] target Ruby version object
|
|
116
|
+
def target_ruby_version
|
|
117
|
+
RubyVersion.parse(target_ruby)
|
|
103
118
|
end
|
|
104
119
|
|
|
105
120
|
# Get list of enabled experimental features
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module TRuby
|
|
4
|
+
# Error raised when an unsupported Ruby version is detected
|
|
5
|
+
class UnsupportedRubyVersionError < StandardError; end
|
|
6
|
+
|
|
7
|
+
# Value object representing a Ruby version with comparison and feature detection
|
|
8
|
+
#
|
|
9
|
+
# @example
|
|
10
|
+
# version = RubyVersion.parse("3.4")
|
|
11
|
+
# version.supports_it_parameter? # => true
|
|
12
|
+
# version >= RubyVersion.parse("3.0") # => true
|
|
13
|
+
#
|
|
14
|
+
class RubyVersion
|
|
15
|
+
include Comparable
|
|
16
|
+
|
|
17
|
+
# Supported version range
|
|
18
|
+
MIN_VERSION = [3, 0].freeze
|
|
19
|
+
MAX_MAJOR = 4
|
|
20
|
+
|
|
21
|
+
# Version string pattern: major.minor or major.minor.patch
|
|
22
|
+
VERSION_REGEX = /\A(\d+)\.(\d+)(?:\.(\d+))?\z/
|
|
23
|
+
|
|
24
|
+
attr_reader :major, :minor, :patch
|
|
25
|
+
|
|
26
|
+
# @param major [Integer] major version number
|
|
27
|
+
# @param minor [Integer] minor version number
|
|
28
|
+
# @param patch [Integer] patch version number (default: 0)
|
|
29
|
+
def initialize(major, minor, patch = 0)
|
|
30
|
+
@major = major
|
|
31
|
+
@minor = minor
|
|
32
|
+
@patch = patch
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Parse a version string into a RubyVersion object
|
|
36
|
+
#
|
|
37
|
+
# @param version_string [String, Numeric] version string (e.g., "3.4", "3.4.1")
|
|
38
|
+
# @return [RubyVersion] parsed version object
|
|
39
|
+
# @raise [ArgumentError] if version format is invalid
|
|
40
|
+
def self.parse(version_string)
|
|
41
|
+
str = version_string.to_s
|
|
42
|
+
match = VERSION_REGEX.match(str)
|
|
43
|
+
|
|
44
|
+
raise ArgumentError, "Invalid version: #{version_string}" unless match
|
|
45
|
+
|
|
46
|
+
new(match[1].to_i, match[2].to_i, (match[3] || 0).to_i)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Get the current Ruby version from the environment
|
|
50
|
+
#
|
|
51
|
+
# @return [RubyVersion] current Ruby version
|
|
52
|
+
def self.current
|
|
53
|
+
parse(RUBY_VERSION)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Compare two versions
|
|
57
|
+
#
|
|
58
|
+
# @param other [RubyVersion] version to compare with
|
|
59
|
+
# @return [Integer] -1, 0, or 1
|
|
60
|
+
def <=>(other)
|
|
61
|
+
[major, minor, patch] <=> [other.major, other.minor, other.patch]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Convert to string representation
|
|
65
|
+
#
|
|
66
|
+
# @return [String] version string (e.g., "3.4" or "3.4.1")
|
|
67
|
+
def to_s
|
|
68
|
+
patch.zero? ? "#{major}.#{minor}" : "#{major}.#{minor}.#{patch}"
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Check if this version is within the supported range (3.0 ~ 4.x)
|
|
72
|
+
#
|
|
73
|
+
# @return [Boolean] true if version is supported
|
|
74
|
+
def supported?
|
|
75
|
+
self >= self.class.parse("#{MIN_VERSION[0]}.#{MIN_VERSION[1]}") && major <= MAX_MAJOR
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Validate that this version is supported, raising an error if not
|
|
79
|
+
#
|
|
80
|
+
# @return [RubyVersion] self if valid
|
|
81
|
+
# @raise [UnsupportedRubyVersionError] if version is not supported
|
|
82
|
+
def validate!
|
|
83
|
+
unless supported?
|
|
84
|
+
raise UnsupportedRubyVersionError,
|
|
85
|
+
"Ruby #{self}는 지원되지 않습니다. 지원 범위: #{MIN_VERSION.join(".")} ~ #{MAX_MAJOR}.x"
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
self
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Check if this version supports the `it` implicit block parameter (Ruby 3.4+)
|
|
92
|
+
#
|
|
93
|
+
# @return [Boolean] true if `it` parameter is supported
|
|
94
|
+
def supports_it_parameter?
|
|
95
|
+
self >= self.class.parse("3.4")
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Check if this version supports anonymous block forwarding `def foo(&) ... end` (Ruby 3.1+)
|
|
99
|
+
#
|
|
100
|
+
# @return [Boolean] true if anonymous block forwarding is supported
|
|
101
|
+
def supports_anonymous_block_forwarding?
|
|
102
|
+
self >= self.class.parse("3.1")
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Check if numbered parameters (_1, _2, etc.) raise NameError (Ruby 4.0+)
|
|
106
|
+
#
|
|
107
|
+
# @return [Boolean] true if numbered parameters cause errors
|
|
108
|
+
def numbered_parameters_raise_error?
|
|
109
|
+
self >= self.class.parse("4.0")
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
data/lib/t_ruby/version.rb
CHANGED
data/lib/t_ruby/watcher.rb
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# listen gem is optional - only required for watch mode
|
|
4
|
+
# This allows T-Ruby core functionality to work on Ruby 4.0+ where listen/ffi may not be available
|
|
5
|
+
begin
|
|
6
|
+
require "listen"
|
|
7
|
+
LISTEN_AVAILABLE = true
|
|
8
|
+
rescue LoadError
|
|
9
|
+
LISTEN_AVAILABLE = false
|
|
10
|
+
end
|
|
4
11
|
|
|
5
12
|
module TRuby
|
|
6
13
|
class Watcher
|
|
@@ -52,6 +59,14 @@ module TRuby
|
|
|
52
59
|
end
|
|
53
60
|
|
|
54
61
|
def watch
|
|
62
|
+
unless LISTEN_AVAILABLE
|
|
63
|
+
puts colorize(:red, "Error: Watch mode requires the 'listen' gem.")
|
|
64
|
+
puts colorize(:yellow, "The 'listen' gem is not available (possibly due to Ruby 4.0+ ffi compatibility).")
|
|
65
|
+
puts colorize(:dim, "Install with: gem install listen")
|
|
66
|
+
puts colorize(:dim, "Or run without watch mode: trc")
|
|
67
|
+
exit 1
|
|
68
|
+
end
|
|
69
|
+
|
|
55
70
|
print_start_message
|
|
56
71
|
|
|
57
72
|
# Initial compilation
|
data/lib/t_ruby.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: t-ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.42
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Y. Fred Kim
|
|
@@ -10,19 +10,19 @@ cert_chain: []
|
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
|
-
name:
|
|
13
|
+
name: benchmark
|
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
|
15
15
|
requirements:
|
|
16
|
-
- - "
|
|
16
|
+
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: '
|
|
18
|
+
version: '0'
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
|
-
- - "
|
|
23
|
+
- - ">="
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: '
|
|
25
|
+
version: '0'
|
|
26
26
|
description: t-ruby compiles .trb files with type annotations to executable Ruby (.rb)
|
|
27
27
|
and optional type signature files (.rbs)
|
|
28
28
|
email:
|
|
@@ -42,6 +42,7 @@ files:
|
|
|
42
42
|
- lib/t_ruby/bundler_integration.rb
|
|
43
43
|
- lib/t_ruby/cache.rb
|
|
44
44
|
- lib/t_ruby/cli.rb
|
|
45
|
+
- lib/t_ruby/code_emitter.rb
|
|
45
46
|
- lib/t_ruby/compiler.rb
|
|
46
47
|
- lib/t_ruby/config.rb
|
|
47
48
|
- lib/t_ruby/constraint_checker.rb
|
|
@@ -59,6 +60,7 @@ files:
|
|
|
59
60
|
- lib/t_ruby/package_manager.rb
|
|
60
61
|
- lib/t_ruby/parser.rb
|
|
61
62
|
- lib/t_ruby/parser_combinator.rb
|
|
63
|
+
- lib/t_ruby/ruby_version.rb
|
|
62
64
|
- lib/t_ruby/runtime_validator.rb
|
|
63
65
|
- lib/t_ruby/smt_solver.rb
|
|
64
66
|
- lib/t_ruby/string_utils.rb
|