t-ruby 0.0.1
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 +7 -0
- data/LICENSE +21 -0
- data/README.md +221 -0
- data/bin/trc +6 -0
- data/lib/t_ruby/benchmark.rb +592 -0
- data/lib/t_ruby/bundler_integration.rb +569 -0
- data/lib/t_ruby/cache.rb +774 -0
- data/lib/t_ruby/cli.rb +106 -0
- data/lib/t_ruby/compiler.rb +299 -0
- data/lib/t_ruby/config.rb +53 -0
- data/lib/t_ruby/constraint_checker.rb +441 -0
- data/lib/t_ruby/declaration_generator.rb +298 -0
- data/lib/t_ruby/doc_generator.rb +474 -0
- data/lib/t_ruby/error_handler.rb +132 -0
- data/lib/t_ruby/generic_type_parser.rb +68 -0
- data/lib/t_ruby/intersection_type_parser.rb +30 -0
- data/lib/t_ruby/ir.rb +1301 -0
- data/lib/t_ruby/lsp_server.rb +994 -0
- data/lib/t_ruby/package_manager.rb +735 -0
- data/lib/t_ruby/parser.rb +245 -0
- data/lib/t_ruby/parser_combinator.rb +942 -0
- data/lib/t_ruby/rbs_generator.rb +71 -0
- data/lib/t_ruby/runtime_validator.rb +367 -0
- data/lib/t_ruby/smt_solver.rb +1076 -0
- data/lib/t_ruby/type_alias_registry.rb +102 -0
- data/lib/t_ruby/type_checker.rb +770 -0
- data/lib/t_ruby/type_erasure.rb +26 -0
- data/lib/t_ruby/type_inferencer.rb +580 -0
- data/lib/t_ruby/union_type_parser.rb +38 -0
- data/lib/t_ruby/version.rb +5 -0
- data/lib/t_ruby/watcher.rb +320 -0
- data/lib/t_ruby.rb +42 -0
- metadata +87 -0
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module TRuby
|
|
4
|
+
# Enhanced Parser using Parser Combinator for complex type expressions
|
|
5
|
+
# Maintains backward compatibility with original Parser interface
|
|
6
|
+
class Parser
|
|
7
|
+
# Type names that are recognized as valid
|
|
8
|
+
VALID_TYPES = %w[String Integer Boolean Array Hash Symbol void nil].freeze
|
|
9
|
+
|
|
10
|
+
attr_reader :source, :ir_program, :use_combinator
|
|
11
|
+
|
|
12
|
+
def initialize(source, use_combinator: true)
|
|
13
|
+
@source = source
|
|
14
|
+
@lines = source.split("\n")
|
|
15
|
+
@use_combinator = use_combinator
|
|
16
|
+
@type_parser = ParserCombinator::TypeParser.new if use_combinator
|
|
17
|
+
@ir_program = nil
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def parse
|
|
21
|
+
functions = []
|
|
22
|
+
type_aliases = []
|
|
23
|
+
interfaces = []
|
|
24
|
+
i = 0
|
|
25
|
+
|
|
26
|
+
while i < @lines.length
|
|
27
|
+
line = @lines[i]
|
|
28
|
+
|
|
29
|
+
# Match type alias definitions
|
|
30
|
+
if line.match?(/^\s*type\s+\w+/)
|
|
31
|
+
alias_info = parse_type_alias(line)
|
|
32
|
+
type_aliases << alias_info if alias_info
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Match interface definitions
|
|
36
|
+
if line.match?(/^\s*interface\s+\w+/)
|
|
37
|
+
interface_info, next_i = parse_interface(i)
|
|
38
|
+
if interface_info
|
|
39
|
+
interfaces << interface_info
|
|
40
|
+
i = next_i
|
|
41
|
+
next
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Match function definitions
|
|
46
|
+
if line.match?(/^\s*def\s+\w+/)
|
|
47
|
+
func_info = parse_function_definition(line)
|
|
48
|
+
functions << func_info if func_info
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
i += 1
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
result = {
|
|
55
|
+
type: :success,
|
|
56
|
+
functions: functions,
|
|
57
|
+
type_aliases: type_aliases,
|
|
58
|
+
interfaces: interfaces
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
# Build IR if combinator is enabled
|
|
62
|
+
if @use_combinator
|
|
63
|
+
builder = IR::Builder.new
|
|
64
|
+
@ir_program = builder.build(result, source: @source)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
result
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Parse to IR directly (new API)
|
|
71
|
+
def parse_to_ir
|
|
72
|
+
parse unless @ir_program
|
|
73
|
+
@ir_program
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Parse a type expression using combinator (new API)
|
|
77
|
+
def parse_type(type_string)
|
|
78
|
+
return nil unless @use_combinator
|
|
79
|
+
|
|
80
|
+
result = @type_parser.parse(type_string)
|
|
81
|
+
result[:success] ? result[:type] : nil
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
private
|
|
85
|
+
|
|
86
|
+
def parse_type_alias(line)
|
|
87
|
+
match = line.match(/^\s*type\s+(\w+)\s*=\s*(.+?)\s*$/)
|
|
88
|
+
return nil unless match
|
|
89
|
+
|
|
90
|
+
alias_name = match[1]
|
|
91
|
+
definition = match[2].strip
|
|
92
|
+
|
|
93
|
+
# Use combinator for complex type parsing if available
|
|
94
|
+
if @use_combinator
|
|
95
|
+
type_result = @type_parser.parse(definition)
|
|
96
|
+
if type_result[:success]
|
|
97
|
+
return {
|
|
98
|
+
name: alias_name,
|
|
99
|
+
definition: definition,
|
|
100
|
+
ir_type: type_result[:type]
|
|
101
|
+
}
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
{
|
|
106
|
+
name: alias_name,
|
|
107
|
+
definition: definition
|
|
108
|
+
}
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def parse_function_definition(line)
|
|
112
|
+
match = line.match(/^\s*def\s+(\w+)\s*\((.*?)\)\s*(?::\s*(.+?))?\s*$/)
|
|
113
|
+
return nil unless match
|
|
114
|
+
|
|
115
|
+
function_name = match[1]
|
|
116
|
+
params_str = match[2]
|
|
117
|
+
return_type_str = match[3]&.strip
|
|
118
|
+
|
|
119
|
+
params = parse_parameters(params_str)
|
|
120
|
+
|
|
121
|
+
result = {
|
|
122
|
+
name: function_name,
|
|
123
|
+
params: params,
|
|
124
|
+
return_type: return_type_str
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
# Parse return type with combinator if available
|
|
128
|
+
if @use_combinator && return_type_str
|
|
129
|
+
type_result = @type_parser.parse(return_type_str)
|
|
130
|
+
result[:ir_return_type] = type_result[:type] if type_result[:success]
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
result
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def parse_parameters(params_str)
|
|
137
|
+
return [] if params_str.empty?
|
|
138
|
+
|
|
139
|
+
parameters = []
|
|
140
|
+
param_list = split_params(params_str)
|
|
141
|
+
|
|
142
|
+
param_list.each do |param|
|
|
143
|
+
param_info = parse_single_parameter(param)
|
|
144
|
+
parameters << param_info if param_info
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
parameters
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def split_params(params_str)
|
|
151
|
+
# Handle nested generics like Array<Map<String, Int>>
|
|
152
|
+
result = []
|
|
153
|
+
current = ""
|
|
154
|
+
depth = 0
|
|
155
|
+
|
|
156
|
+
params_str.each_char do |char|
|
|
157
|
+
case char
|
|
158
|
+
when "<", "[", "("
|
|
159
|
+
depth += 1
|
|
160
|
+
current += char
|
|
161
|
+
when ">", "]", ")"
|
|
162
|
+
depth -= 1
|
|
163
|
+
current += char
|
|
164
|
+
when ","
|
|
165
|
+
if depth == 0
|
|
166
|
+
result << current.strip
|
|
167
|
+
current = ""
|
|
168
|
+
else
|
|
169
|
+
current += char
|
|
170
|
+
end
|
|
171
|
+
else
|
|
172
|
+
current += char
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
result << current.strip unless current.empty?
|
|
177
|
+
result
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def parse_single_parameter(param)
|
|
181
|
+
match = param.match(/^(\w+)(?::\s*(.+?))?$/)
|
|
182
|
+
return nil unless match
|
|
183
|
+
|
|
184
|
+
param_name = match[1]
|
|
185
|
+
type_str = match[2]&.strip
|
|
186
|
+
|
|
187
|
+
result = {
|
|
188
|
+
name: param_name,
|
|
189
|
+
type: type_str
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
# Parse type with combinator if available
|
|
193
|
+
if @use_combinator && type_str
|
|
194
|
+
type_result = @type_parser.parse(type_str)
|
|
195
|
+
result[:ir_type] = type_result[:type] if type_result[:success]
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
result
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def parse_interface(start_index)
|
|
202
|
+
line = @lines[start_index]
|
|
203
|
+
match = line.match(/^\s*interface\s+(\w+)/)
|
|
204
|
+
return [nil, start_index] unless match
|
|
205
|
+
|
|
206
|
+
interface_name = match[1]
|
|
207
|
+
members = []
|
|
208
|
+
i = start_index + 1
|
|
209
|
+
|
|
210
|
+
while i < @lines.length
|
|
211
|
+
current_line = @lines[i]
|
|
212
|
+
break if current_line.match?(/^\s*end\s*$/)
|
|
213
|
+
|
|
214
|
+
if current_line.match?(/^\s*\w+\s*:\s*/)
|
|
215
|
+
member_match = current_line.match(/^\s*(\w+)\s*:\s*(.+?)\s*$/)
|
|
216
|
+
if member_match
|
|
217
|
+
member = {
|
|
218
|
+
name: member_match[1],
|
|
219
|
+
type: member_match[2].strip
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
# Parse member type with combinator
|
|
223
|
+
if @use_combinator
|
|
224
|
+
type_result = @type_parser.parse(member[:type])
|
|
225
|
+
member[:ir_type] = type_result[:type] if type_result[:success]
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
members << member
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
i += 1
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
[{ name: interface_name, members: members }, i]
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
# Legacy Parser for backward compatibility (regex-only)
|
|
240
|
+
class LegacyParser < Parser
|
|
241
|
+
def initialize(source)
|
|
242
|
+
super(source, use_combinator: false)
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
end
|