t-ruby 0.0.39 → 0.0.40
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/compiler.rb +29 -61
- data/lib/t_ruby/heredoc_detector.rb +74 -0
- data/lib/t_ruby/ir.rb +15 -2
- data/lib/t_ruby/lsp_server.rb +1 -1
- data/lib/t_ruby/parser.rb +41 -43
- data/lib/t_ruby/version.rb +1 -1
- data/lib/t_ruby.rb +1 -1
- metadata +2 -2
- data/lib/t_ruby/rbs_generator.rb +0 -69
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 54f0b9008d5a42a8cbf851eac8a0eb540670c3c87018dd87182baf6ab30c7d55
|
|
4
|
+
data.tar.gz: 42929dd91ae55ea84e75fd6978298deea2fec1d3517a801bde06af6f70865557
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 20916cbdb9a4d62bd9208c8496df8e8f425885c600d5caa9ef0d5a545c4d52a62fa66d05157bfc89a0c57328658f6ecb08889336352e76b4cfb757518365f50b
|
|
7
|
+
data.tar.gz: b6125521d066808e825747418d794ca6adb94503e7d89b61fe5a9bb009e2c2fcc49952b0ea3fd12f5c0bb51de9d20de0ff3a7b4f0ab37358d0616010e1f9ca55
|
data/lib/t_ruby/compiler.rb
CHANGED
|
@@ -7,16 +7,17 @@ module TRuby
|
|
|
7
7
|
# \p{L} matches any Unicode letter, \p{N} matches any Unicode number
|
|
8
8
|
IDENTIFIER_CHAR = '[\p{L}\p{N}_]'
|
|
9
9
|
METHOD_NAME_PATTERN = "#{IDENTIFIER_CHAR}+[?!]?".freeze
|
|
10
|
+
# Visibility modifiers for method definitions
|
|
11
|
+
VISIBILITY_PATTERN = '(?:(?:private|protected|public)\s+)?'
|
|
10
12
|
|
|
11
13
|
class Compiler
|
|
12
|
-
attr_reader :declaration_loader, :
|
|
14
|
+
attr_reader :declaration_loader, :optimizer
|
|
13
15
|
|
|
14
|
-
def initialize(config = nil,
|
|
16
|
+
def initialize(config = nil, optimize: true)
|
|
15
17
|
@config = config || Config.new
|
|
16
|
-
@use_ir = use_ir
|
|
17
18
|
@optimize = optimize
|
|
18
19
|
@declaration_loader = DeclarationLoader.new
|
|
19
|
-
@optimizer = IR::Optimizer.new if
|
|
20
|
+
@optimizer = IR::Optimizer.new if optimize
|
|
20
21
|
@type_inferrer = ASTTypeInferrer.new if type_check?
|
|
21
22
|
setup_declaration_paths if @config
|
|
22
23
|
end
|
|
@@ -42,16 +43,16 @@ module TRuby
|
|
|
42
43
|
source = File.read(input_path)
|
|
43
44
|
|
|
44
45
|
# Parse with IR support
|
|
45
|
-
parser = Parser.new(source
|
|
46
|
-
|
|
46
|
+
parser = Parser.new(source)
|
|
47
|
+
parser.parse
|
|
47
48
|
|
|
48
49
|
# Run type checking if enabled
|
|
49
|
-
if type_check? &&
|
|
50
|
+
if type_check? && parser.ir_program
|
|
50
51
|
check_types(parser.ir_program, input_path)
|
|
51
52
|
end
|
|
52
53
|
|
|
53
54
|
# Transform source to Ruby code
|
|
54
|
-
output =
|
|
55
|
+
output = transform_with_ir(source, parser)
|
|
55
56
|
|
|
56
57
|
# Compute output path (respects preserve_structure setting)
|
|
57
58
|
output_path = compute_output_path(input_path, @config.ruby_dir, ".rb")
|
|
@@ -63,11 +64,7 @@ module TRuby
|
|
|
63
64
|
if @config.compiler["generate_rbs"]
|
|
64
65
|
rbs_path = compute_output_path(input_path, @config.rbs_dir, ".rbs")
|
|
65
66
|
FileUtils.mkdir_p(File.dirname(rbs_path))
|
|
66
|
-
|
|
67
|
-
generate_rbs_from_ir_to_path(rbs_path, parser.ir_program)
|
|
68
|
-
else
|
|
69
|
-
generate_rbs_file_to_path(rbs_path, parse_result)
|
|
70
|
-
end
|
|
67
|
+
generate_rbs_from_ir_to_path(rbs_path, parser.ir_program)
|
|
71
68
|
end
|
|
72
69
|
|
|
73
70
|
# Generate .d.trb file if enabled in config (legacy support)
|
|
@@ -87,25 +84,17 @@ module TRuby
|
|
|
87
84
|
def compile_string(source, options = {})
|
|
88
85
|
generate_rbs = options.fetch(:rbs, true)
|
|
89
86
|
|
|
90
|
-
parser = Parser.new(source
|
|
91
|
-
|
|
87
|
+
parser = Parser.new(source)
|
|
88
|
+
parser.parse
|
|
92
89
|
|
|
93
90
|
# Transform source to Ruby code
|
|
94
|
-
ruby_output =
|
|
91
|
+
ruby_output = transform_with_ir(source, parser)
|
|
95
92
|
|
|
96
93
|
# Generate RBS if requested
|
|
97
94
|
rbs_output = ""
|
|
98
|
-
if generate_rbs
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
rbs_output = generator.generate(parser.ir_program)
|
|
102
|
-
else
|
|
103
|
-
generator = RBSGenerator.new
|
|
104
|
-
rbs_output = generator.generate(
|
|
105
|
-
parse_result[:functions] || [],
|
|
106
|
-
parse_result[:type_aliases] || []
|
|
107
|
-
)
|
|
108
|
-
end
|
|
95
|
+
if generate_rbs && parser.ir_program
|
|
96
|
+
generator = IR::RBSGenerator.new
|
|
97
|
+
rbs_output = generator.generate(parser.ir_program)
|
|
109
98
|
end
|
|
110
99
|
|
|
111
100
|
{
|
|
@@ -134,7 +123,7 @@ module TRuby
|
|
|
134
123
|
end
|
|
135
124
|
|
|
136
125
|
source = File.read(input_path)
|
|
137
|
-
parser = Parser.new(source
|
|
126
|
+
parser = Parser.new(source)
|
|
138
127
|
parser.parse
|
|
139
128
|
parser.ir_program
|
|
140
129
|
end
|
|
@@ -380,10 +369,10 @@ module TRuby
|
|
|
380
369
|
@declaration_loader.add_search_path("./lib/types")
|
|
381
370
|
end
|
|
382
371
|
|
|
383
|
-
# Transform using IR system
|
|
372
|
+
# Transform using IR system
|
|
384
373
|
def transform_with_ir(source, parser)
|
|
385
374
|
ir_program = parser.ir_program
|
|
386
|
-
return
|
|
375
|
+
return source unless ir_program
|
|
387
376
|
|
|
388
377
|
# Run optimization passes if enabled
|
|
389
378
|
if @optimize && @optimizer
|
|
@@ -396,33 +385,15 @@ module TRuby
|
|
|
396
385
|
generator.generate_with_source(ir_program, source)
|
|
397
386
|
end
|
|
398
387
|
|
|
399
|
-
# Legacy transformation using TypeErasure (backward compatible)
|
|
400
|
-
def transform_legacy(source, parse_result)
|
|
401
|
-
if parse_result[:type] == :success
|
|
402
|
-
eraser = TypeErasure.new(source)
|
|
403
|
-
eraser.erase
|
|
404
|
-
else
|
|
405
|
-
source
|
|
406
|
-
end
|
|
407
|
-
end
|
|
408
|
-
|
|
409
388
|
# Generate RBS from IR to a specific path
|
|
410
389
|
def generate_rbs_from_ir_to_path(rbs_path, ir_program)
|
|
390
|
+
return unless ir_program
|
|
391
|
+
|
|
411
392
|
generator = IR::RBSGenerator.new
|
|
412
393
|
rbs_content = generator.generate(ir_program)
|
|
413
394
|
File.write(rbs_path, rbs_content) unless rbs_content.strip.empty?
|
|
414
395
|
end
|
|
415
396
|
|
|
416
|
-
# Legacy RBS generation to a specific path
|
|
417
|
-
def generate_rbs_file_to_path(rbs_path, parse_result)
|
|
418
|
-
generator = RBSGenerator.new
|
|
419
|
-
rbs_content = generator.generate(
|
|
420
|
-
parse_result[:functions] || [],
|
|
421
|
-
parse_result[:type_aliases] || []
|
|
422
|
-
)
|
|
423
|
-
File.write(rbs_path, rbs_content) unless rbs_content.empty?
|
|
424
|
-
end
|
|
425
|
-
|
|
426
397
|
def generate_dtrb_file(input_path, out_dir)
|
|
427
398
|
dtrb_path = compute_output_path(input_path, out_dir, DeclarationGenerator::DECLARATION_EXTENSION)
|
|
428
399
|
FileUtils.mkdir_p(File.dirname(dtrb_path))
|
|
@@ -511,7 +482,8 @@ module TRuby
|
|
|
511
482
|
result = source.dup
|
|
512
483
|
|
|
513
484
|
# Match function definitions and remove type annotations from parameters
|
|
514
|
-
|
|
485
|
+
# Also supports visibility modifiers: private def, protected def, public def
|
|
486
|
+
result.gsub!(/^(\s*#{TRuby::VISIBILITY_PATTERN}def\s+#{TRuby::METHOD_NAME_PATTERN}\s*\()([^)]+)(\)\s*)(?::\s*[^\n]+)?(\s*$)/) do |_match|
|
|
515
487
|
indent = ::Regexp.last_match(1)
|
|
516
488
|
params = ::Regexp.last_match(2)
|
|
517
489
|
close_paren = ::Regexp.last_match(3)
|
|
@@ -558,10 +530,13 @@ module TRuby
|
|
|
558
530
|
params.join(", ")
|
|
559
531
|
end
|
|
560
532
|
|
|
561
|
-
# Clean a single parameter (remove type annotation)
|
|
533
|
+
# Clean a single parameter (remove type annotation, preserve default value)
|
|
562
534
|
def clean_param(param)
|
|
563
|
-
# Match: name: Type
|
|
564
|
-
if (match = param.match(/^(#{TRuby::IDENTIFIER_CHAR}+)\s
|
|
535
|
+
# Match: name: Type = value (with default value)
|
|
536
|
+
if (match = param.match(/^(#{TRuby::IDENTIFIER_CHAR}+)\s*:\s*.+?\s*(=\s*.+)$/))
|
|
537
|
+
"#{match[1]} #{match[2]}"
|
|
538
|
+
# Match: name: Type (without default value)
|
|
539
|
+
elsif (match = param.match(/^(#{TRuby::IDENTIFIER_CHAR}+)\s*:/))
|
|
565
540
|
match[1]
|
|
566
541
|
else
|
|
567
542
|
param
|
|
@@ -580,11 +555,4 @@ module TRuby
|
|
|
580
555
|
result
|
|
581
556
|
end
|
|
582
557
|
end
|
|
583
|
-
|
|
584
|
-
# Legacy Compiler for backward compatibility (no IR)
|
|
585
|
-
class LegacyCompiler < Compiler
|
|
586
|
-
def initialize(config)
|
|
587
|
-
super(config, use_ir: false, optimize: false)
|
|
588
|
-
end
|
|
589
|
-
end
|
|
590
558
|
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module TRuby
|
|
4
|
+
# Detects regions that should be skipped during parsing:
|
|
5
|
+
# - Heredoc content
|
|
6
|
+
# - Block comments (=begin/=end)
|
|
7
|
+
class HeredocDetector
|
|
8
|
+
# Heredoc start patterns:
|
|
9
|
+
# <<IDENTIFIER, <<-IDENTIFIER, <<~IDENTIFIER
|
|
10
|
+
# <<'IDENTIFIER', <<"IDENTIFIER"
|
|
11
|
+
HEREDOC_START_PATTERN = /<<([~-])?(['"]?)(\w+)\2/
|
|
12
|
+
|
|
13
|
+
# Detect all skippable ranges in lines (heredocs and block comments)
|
|
14
|
+
# @param lines [Array<String>] source lines
|
|
15
|
+
# @return [Array<Range>] content ranges to skip (0-indexed)
|
|
16
|
+
def self.detect(lines)
|
|
17
|
+
ranges = []
|
|
18
|
+
i = 0
|
|
19
|
+
|
|
20
|
+
while i < lines.length
|
|
21
|
+
line = lines[i]
|
|
22
|
+
|
|
23
|
+
# Check for =begin block comment
|
|
24
|
+
if line.strip == "=begin"
|
|
25
|
+
start_line = i
|
|
26
|
+
i += 1
|
|
27
|
+
|
|
28
|
+
# Find =end
|
|
29
|
+
while i < lines.length
|
|
30
|
+
break if lines[i].strip == "=end"
|
|
31
|
+
|
|
32
|
+
i += 1
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Range covers from =begin to =end (inclusive)
|
|
36
|
+
ranges << (start_line..i) if i < lines.length
|
|
37
|
+
# Check for heredoc
|
|
38
|
+
elsif (match = line.match(HEREDOC_START_PATTERN))
|
|
39
|
+
delimiter = match[3]
|
|
40
|
+
squiggly = match[1] == "~"
|
|
41
|
+
start_line = i
|
|
42
|
+
i += 1
|
|
43
|
+
|
|
44
|
+
# Find closing delimiter
|
|
45
|
+
while i < lines.length
|
|
46
|
+
# For squiggly heredoc or dash heredoc, delimiter can be indented
|
|
47
|
+
# For regular heredoc, delimiter must be at line start
|
|
48
|
+
if squiggly || match[1] == "-"
|
|
49
|
+
break if lines[i].strip == delimiter
|
|
50
|
+
elsif lines[i].chomp == delimiter
|
|
51
|
+
break
|
|
52
|
+
end
|
|
53
|
+
i += 1
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Range covers content lines (after start, up to and including end delimiter)
|
|
57
|
+
ranges << ((start_line + 1)..i) if i < lines.length
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
i += 1
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
ranges
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Check if a line index is inside any skippable region
|
|
67
|
+
# @param line_index [Integer] line index to check
|
|
68
|
+
# @param heredoc_ranges [Array<Range>] ranges from detect()
|
|
69
|
+
# @return [Boolean]
|
|
70
|
+
def self.inside_heredoc?(line_index, heredoc_ranges)
|
|
71
|
+
heredoc_ranges.any? { |range| range.include?(line_index) }
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
data/lib/t_ruby/ir.rb
CHANGED
|
@@ -778,7 +778,8 @@ module TRuby
|
|
|
778
778
|
name: info[:name],
|
|
779
779
|
params: params,
|
|
780
780
|
return_type: info[:return_type] ? parse_type(info[:return_type]) : nil,
|
|
781
|
-
body: body
|
|
781
|
+
body: body,
|
|
782
|
+
visibility: info[:visibility] || :public
|
|
782
783
|
)
|
|
783
784
|
end
|
|
784
785
|
|
|
@@ -1051,7 +1052,8 @@ module TRuby
|
|
|
1051
1052
|
end
|
|
1052
1053
|
|
|
1053
1054
|
return_type ||= "untyped"
|
|
1054
|
-
|
|
1055
|
+
visibility_prefix = format_visibility(node.visibility)
|
|
1056
|
+
emit("#{visibility_prefix}def #{node.name}: (#{params}) -> #{return_type}")
|
|
1055
1057
|
end
|
|
1056
1058
|
|
|
1057
1059
|
def visit_class_decl(node)
|
|
@@ -1092,6 +1094,17 @@ module TRuby
|
|
|
1092
1094
|
def emit(text)
|
|
1093
1095
|
@output << ((" " * @indent) + text)
|
|
1094
1096
|
end
|
|
1097
|
+
|
|
1098
|
+
def format_visibility(visibility)
|
|
1099
|
+
# RBS only supports private visibility, not protected
|
|
1100
|
+
# See: https://github.com/ruby/rbs/issues/579
|
|
1101
|
+
case visibility
|
|
1102
|
+
when :private
|
|
1103
|
+
"private "
|
|
1104
|
+
else
|
|
1105
|
+
""
|
|
1106
|
+
end
|
|
1107
|
+
end
|
|
1095
1108
|
end
|
|
1096
1109
|
|
|
1097
1110
|
#==========================================================================
|
data/lib/t_ruby/lsp_server.rb
CHANGED
data/lib/t_ruby/parser.rb
CHANGED
|
@@ -12,15 +12,16 @@ module TRuby
|
|
|
12
12
|
IDENTIFIER_CHAR = '[\p{L}\p{N}_]'
|
|
13
13
|
# Method names can end with ? or !
|
|
14
14
|
METHOD_NAME_PATTERN = "#{IDENTIFIER_CHAR}+[?!]?".freeze
|
|
15
|
+
# Visibility modifiers for method definitions
|
|
16
|
+
VISIBILITY_PATTERN = '(?:(?:private|protected|public)\s+)?'
|
|
15
17
|
|
|
16
|
-
attr_reader :source, :ir_program
|
|
18
|
+
attr_reader :source, :ir_program
|
|
17
19
|
|
|
18
|
-
def initialize(source,
|
|
20
|
+
def initialize(source, parse_body: true)
|
|
19
21
|
@source = source
|
|
20
22
|
@lines = source.split("\n")
|
|
21
|
-
@use_combinator = use_combinator
|
|
22
23
|
@parse_body = parse_body
|
|
23
|
-
@type_parser = ParserCombinator::TypeParser.new
|
|
24
|
+
@type_parser = ParserCombinator::TypeParser.new
|
|
24
25
|
@body_parser = BodyParser.new if parse_body
|
|
25
26
|
@ir_program = nil
|
|
26
27
|
end
|
|
@@ -32,7 +33,16 @@ module TRuby
|
|
|
32
33
|
classes = []
|
|
33
34
|
i = 0
|
|
34
35
|
|
|
36
|
+
# Pre-detect heredoc regions to skip
|
|
37
|
+
heredoc_ranges = HeredocDetector.detect(@lines)
|
|
38
|
+
|
|
35
39
|
while i < @lines.length
|
|
40
|
+
# Skip lines inside heredoc content
|
|
41
|
+
if HeredocDetector.inside_heredoc?(i, heredoc_ranges)
|
|
42
|
+
i += 1
|
|
43
|
+
next
|
|
44
|
+
end
|
|
45
|
+
|
|
36
46
|
line = @lines[i]
|
|
37
47
|
|
|
38
48
|
# Match type alias definitions
|
|
@@ -62,7 +72,7 @@ module TRuby
|
|
|
62
72
|
end
|
|
63
73
|
|
|
64
74
|
# Match function definitions (top-level only, not inside class)
|
|
65
|
-
if line.match?(/^\s
|
|
75
|
+
if line.match?(/^\s*#{VISIBILITY_PATTERN}def\s+#{IDENTIFIER_CHAR}+/)
|
|
66
76
|
func_info, next_i = parse_function_with_body(i)
|
|
67
77
|
if func_info
|
|
68
78
|
functions << func_info
|
|
@@ -82,11 +92,9 @@ module TRuby
|
|
|
82
92
|
classes: classes,
|
|
83
93
|
}
|
|
84
94
|
|
|
85
|
-
# Build IR
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
@ir_program = builder.build(result, source: @source)
|
|
89
|
-
end
|
|
95
|
+
# Build IR
|
|
96
|
+
builder = IR::Builder.new
|
|
97
|
+
@ir_program = builder.build(result, source: @source)
|
|
90
98
|
|
|
91
99
|
result
|
|
92
100
|
end
|
|
@@ -97,10 +105,8 @@ module TRuby
|
|
|
97
105
|
@ir_program
|
|
98
106
|
end
|
|
99
107
|
|
|
100
|
-
# Parse a type expression using combinator
|
|
108
|
+
# Parse a type expression using combinator
|
|
101
109
|
def parse_type(type_string)
|
|
102
|
-
return nil unless @use_combinator
|
|
103
|
-
|
|
104
110
|
result = @type_parser.parse(type_string)
|
|
105
111
|
result[:success] ? result[:type] : nil
|
|
106
112
|
end
|
|
@@ -149,16 +155,14 @@ module TRuby
|
|
|
149
155
|
alias_name = match[1]
|
|
150
156
|
definition = match[2].strip
|
|
151
157
|
|
|
152
|
-
# Use combinator for complex type parsing
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
end
|
|
158
|
+
# Use combinator for complex type parsing
|
|
159
|
+
type_result = @type_parser.parse(definition)
|
|
160
|
+
if type_result[:success]
|
|
161
|
+
return {
|
|
162
|
+
name: alias_name,
|
|
163
|
+
definition: definition,
|
|
164
|
+
ir_type: type_result[:type],
|
|
165
|
+
}
|
|
162
166
|
end
|
|
163
167
|
|
|
164
168
|
{
|
|
@@ -173,12 +177,14 @@ module TRuby
|
|
|
173
177
|
# def foo(): Type - no params but with return type
|
|
174
178
|
# def foo(params) - with params, no return type
|
|
175
179
|
# def foo - no params, no return type
|
|
176
|
-
|
|
180
|
+
# Also supports visibility modifiers: private def, protected def, public def
|
|
181
|
+
match = line.match(/^\s*(?:(private|protected|public)\s+)?def\s+(#{METHOD_NAME_PATTERN})\s*(?:\((.*?)\))?\s*(?::\s*(.+?))?\s*$/)
|
|
177
182
|
return nil unless match
|
|
178
183
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
184
|
+
visibility = match[1] ? match[1].to_sym : :public
|
|
185
|
+
function_name = match[2]
|
|
186
|
+
params_str = match[3] || ""
|
|
187
|
+
return_type_str = match[4]&.strip
|
|
182
188
|
|
|
183
189
|
# Validate return type if present
|
|
184
190
|
if return_type_str
|
|
@@ -191,10 +197,11 @@ module TRuby
|
|
|
191
197
|
name: function_name,
|
|
192
198
|
params: params,
|
|
193
199
|
return_type: return_type_str,
|
|
200
|
+
visibility: visibility,
|
|
194
201
|
}
|
|
195
202
|
|
|
196
|
-
# Parse return type with combinator
|
|
197
|
-
if
|
|
203
|
+
# Parse return type with combinator
|
|
204
|
+
if return_type_str
|
|
198
205
|
type_result = @type_parser.parse(return_type_str)
|
|
199
206
|
result[:ir_return_type] = type_result[:type] if type_result[:success]
|
|
200
207
|
end
|
|
@@ -286,8 +293,8 @@ module TRuby
|
|
|
286
293
|
type: type_str,
|
|
287
294
|
}
|
|
288
295
|
|
|
289
|
-
# Parse type with combinator
|
|
290
|
-
if
|
|
296
|
+
# Parse type with combinator
|
|
297
|
+
if type_str
|
|
291
298
|
type_result = @type_parser.parse(type_str)
|
|
292
299
|
result[:ir_type] = type_result[:type] if type_result[:success]
|
|
293
300
|
end
|
|
@@ -326,7 +333,7 @@ module TRuby
|
|
|
326
333
|
current_line = @lines[i]
|
|
327
334
|
|
|
328
335
|
# Match method definitions inside class
|
|
329
|
-
if current_line.match?(/^\s
|
|
336
|
+
if current_line.match?(/^\s*#{VISIBILITY_PATTERN}def\s+#{IDENTIFIER_CHAR}+/)
|
|
330
337
|
method_info, next_i = parse_method_in_class(i, class_end)
|
|
331
338
|
if method_info
|
|
332
339
|
methods << method_info
|
|
@@ -438,10 +445,8 @@ module TRuby
|
|
|
438
445
|
}
|
|
439
446
|
|
|
440
447
|
# Parse member type with combinator
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
member[:ir_type] = type_result[:type] if type_result[:success]
|
|
444
|
-
end
|
|
448
|
+
type_result = @type_parser.parse(member[:type])
|
|
449
|
+
member[:ir_type] = type_result[:type] if type_result[:success]
|
|
445
450
|
|
|
446
451
|
members << member
|
|
447
452
|
end
|
|
@@ -453,11 +458,4 @@ module TRuby
|
|
|
453
458
|
[{ name: interface_name, members: members }, i]
|
|
454
459
|
end
|
|
455
460
|
end
|
|
456
|
-
|
|
457
|
-
# Legacy Parser for backward compatibility (regex-only)
|
|
458
|
-
class LegacyParser < Parser
|
|
459
|
-
def initialize(source)
|
|
460
|
-
super(source, use_combinator: false)
|
|
461
|
-
end
|
|
462
|
-
end
|
|
463
461
|
end
|
data/lib/t_ruby/version.rb
CHANGED
data/lib/t_ruby.rb
CHANGED
|
@@ -11,6 +11,7 @@ require_relative "t_ruby/smt_solver"
|
|
|
11
11
|
|
|
12
12
|
# Basic components
|
|
13
13
|
require_relative "t_ruby/type_alias_registry"
|
|
14
|
+
require_relative "t_ruby/heredoc_detector"
|
|
14
15
|
require_relative "t_ruby/body_parser"
|
|
15
16
|
require_relative "t_ruby/parser"
|
|
16
17
|
require_relative "t_ruby/union_type_parser"
|
|
@@ -18,7 +19,6 @@ require_relative "t_ruby/generic_type_parser"
|
|
|
18
19
|
require_relative "t_ruby/intersection_type_parser"
|
|
19
20
|
require_relative "t_ruby/type_erasure"
|
|
20
21
|
require_relative "t_ruby/error_handler"
|
|
21
|
-
require_relative "t_ruby/rbs_generator"
|
|
22
22
|
require_relative "t_ruby/declaration_generator"
|
|
23
23
|
require_relative "t_ruby/compiler"
|
|
24
24
|
require_relative "t_ruby/lsp_server"
|
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.40
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Y. Fred Kim
|
|
@@ -52,13 +52,13 @@ files:
|
|
|
52
52
|
- lib/t_ruby/docs_example_verifier.rb
|
|
53
53
|
- lib/t_ruby/error_handler.rb
|
|
54
54
|
- lib/t_ruby/generic_type_parser.rb
|
|
55
|
+
- lib/t_ruby/heredoc_detector.rb
|
|
55
56
|
- lib/t_ruby/intersection_type_parser.rb
|
|
56
57
|
- lib/t_ruby/ir.rb
|
|
57
58
|
- lib/t_ruby/lsp_server.rb
|
|
58
59
|
- lib/t_ruby/package_manager.rb
|
|
59
60
|
- lib/t_ruby/parser.rb
|
|
60
61
|
- lib/t_ruby/parser_combinator.rb
|
|
61
|
-
- lib/t_ruby/rbs_generator.rb
|
|
62
62
|
- lib/t_ruby/runtime_validator.rb
|
|
63
63
|
- lib/t_ruby/smt_solver.rb
|
|
64
64
|
- lib/t_ruby/type_alias_registry.rb
|
data/lib/t_ruby/rbs_generator.rb
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module TRuby
|
|
4
|
-
class RBSGenerator
|
|
5
|
-
def initialize
|
|
6
|
-
# RBS generation configuration
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
def generate(functions, type_aliases)
|
|
10
|
-
# Add type aliases
|
|
11
|
-
lines = type_aliases.map do |type_alias|
|
|
12
|
-
generate_type_alias(type_alias)
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
lines << "" if type_aliases.any? && functions.any?
|
|
16
|
-
|
|
17
|
-
# Add function signatures
|
|
18
|
-
functions.each do |func|
|
|
19
|
-
lines << generate_function_signature(func)
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
lines.compact.join("\n")
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def generate_type_aliases(aliases)
|
|
26
|
-
aliases.map { |alias_def| generate_type_alias(alias_def) }.join("\n")
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def generate_type_alias(type_alias)
|
|
30
|
-
name = type_alias[:name]
|
|
31
|
-
definition = type_alias[:definition]
|
|
32
|
-
|
|
33
|
-
"type #{name} = #{definition}"
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def generate_function_signature(func)
|
|
37
|
-
name = func[:name]
|
|
38
|
-
params = func[:params] || []
|
|
39
|
-
return_type = func[:return_type]
|
|
40
|
-
|
|
41
|
-
param_str = format_parameters(params)
|
|
42
|
-
return_str = format_return_type(return_type)
|
|
43
|
-
|
|
44
|
-
"def #{name}: (#{param_str}) -> #{return_str}"
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
private
|
|
48
|
-
|
|
49
|
-
def format_parameters(params)
|
|
50
|
-
return if params.empty?
|
|
51
|
-
|
|
52
|
-
param_strs = params.map do |param|
|
|
53
|
-
param_name = param[:name]
|
|
54
|
-
param_type = param[:type] || "Object"
|
|
55
|
-
|
|
56
|
-
"#{param_name}: #{param_type}"
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
param_strs.join(", ")
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def format_return_type(return_type)
|
|
63
|
-
return "void" if return_type == "void"
|
|
64
|
-
return "nil" if return_type.nil?
|
|
65
|
-
|
|
66
|
-
return_type
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
end
|