t-ruby 0.0.38 → 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.
data/lib/t_ruby/parser.rb CHANGED
@@ -7,13 +7,22 @@ module TRuby
7
7
  # Type names that are recognized as valid
8
8
  VALID_TYPES = %w[String Integer Boolean Array Hash Symbol void nil].freeze
9
9
 
10
- attr_reader :source, :ir_program, :use_combinator
10
+ # Pattern for method/variable names that supports Unicode characters
11
+ # \p{L} matches any Unicode letter, \p{N} matches any Unicode number
12
+ IDENTIFIER_CHAR = '[\p{L}\p{N}_]'
13
+ # Method names can end with ? or !
14
+ METHOD_NAME_PATTERN = "#{IDENTIFIER_CHAR}+[?!]?".freeze
15
+ # Visibility modifiers for method definitions
16
+ VISIBILITY_PATTERN = '(?:(?:private|protected|public)\s+)?'
11
17
 
12
- def initialize(source, use_combinator: true)
18
+ attr_reader :source, :ir_program
19
+
20
+ def initialize(source, parse_body: true)
13
21
  @source = source
14
22
  @lines = source.split("\n")
15
- @use_combinator = use_combinator
16
- @type_parser = ParserCombinator::TypeParser.new if use_combinator
23
+ @parse_body = parse_body
24
+ @type_parser = ParserCombinator::TypeParser.new
25
+ @body_parser = BodyParser.new if parse_body
17
26
  @ir_program = nil
18
27
  end
19
28
 
@@ -21,9 +30,19 @@ module TRuby
21
30
  functions = []
22
31
  type_aliases = []
23
32
  interfaces = []
33
+ classes = []
24
34
  i = 0
25
35
 
36
+ # Pre-detect heredoc regions to skip
37
+ heredoc_ranges = HeredocDetector.detect(@lines)
38
+
26
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
+
27
46
  line = @lines[i]
28
47
 
29
48
  # Match type alias definitions
@@ -42,10 +61,24 @@ module TRuby
42
61
  end
43
62
  end
44
63
 
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
64
+ # Match class definitions
65
+ if line.match?(/^\s*class\s+\w+/)
66
+ class_info, next_i = parse_class(i)
67
+ if class_info
68
+ classes << class_info
69
+ i = next_i
70
+ next
71
+ end
72
+ end
73
+
74
+ # Match function definitions (top-level only, not inside class)
75
+ if line.match?(/^\s*#{VISIBILITY_PATTERN}def\s+#{IDENTIFIER_CHAR}+/)
76
+ func_info, next_i = parse_function_with_body(i)
77
+ if func_info
78
+ functions << func_info
79
+ i = next_i
80
+ next
81
+ end
49
82
  end
50
83
 
51
84
  i += 1
@@ -56,13 +89,12 @@ module TRuby
56
89
  functions: functions,
57
90
  type_aliases: type_aliases,
58
91
  interfaces: interfaces,
92
+ classes: classes,
59
93
  }
60
94
 
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
95
+ # Build IR
96
+ builder = IR::Builder.new
97
+ @ir_program = builder.build(result, source: @source)
66
98
 
67
99
  result
68
100
  end
@@ -73,16 +105,49 @@ module TRuby
73
105
  @ir_program
74
106
  end
75
107
 
76
- # Parse a type expression using combinator (new API)
108
+ # Parse a type expression using combinator
77
109
  def parse_type(type_string)
78
- return nil unless @use_combinator
79
-
80
110
  result = @type_parser.parse(type_string)
81
111
  result[:success] ? result[:type] : nil
82
112
  end
83
113
 
84
114
  private
85
115
 
116
+ # 최상위 함수를 본문까지 포함하여 파싱
117
+ def parse_function_with_body(start_index)
118
+ line = @lines[start_index]
119
+ func_info = parse_function_definition(line)
120
+ return [nil, start_index] unless func_info
121
+
122
+ def_indent = line.match(/^(\s*)/)[1].length
123
+ i = start_index + 1
124
+ body_start = i
125
+ body_end = i
126
+
127
+ # end 키워드 찾기
128
+ while i < @lines.length
129
+ current_line = @lines[i]
130
+
131
+ if current_line.match?(/^\s*end\s*$/)
132
+ end_indent = current_line.match(/^(\s*)/)[1].length
133
+ if end_indent <= def_indent
134
+ body_end = i
135
+ break
136
+ end
137
+ end
138
+
139
+ i += 1
140
+ end
141
+
142
+ # 본문 파싱 (parse_body 옵션이 활성화된 경우)
143
+ if @parse_body && @body_parser && body_start < body_end
144
+ func_info[:body_ir] = @body_parser.parse(@lines, body_start, body_end)
145
+ func_info[:body_range] = { start: body_start, end: body_end }
146
+ end
147
+
148
+ [func_info, i]
149
+ end
150
+
86
151
  def parse_type_alias(line)
87
152
  match = line.match(/^\s*type\s+(\w+)\s*=\s*(.+?)\s*$/)
88
153
  return nil unless match
@@ -90,16 +155,14 @@ module TRuby
90
155
  alias_name = match[1]
91
156
  definition = match[2].strip
92
157
 
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
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
+ }
103
166
  end
104
167
 
105
168
  {
@@ -109,12 +172,19 @@ module TRuby
109
172
  end
110
173
 
111
174
  def parse_function_definition(line)
112
- match = line.match(/^\s*def\s+(\w+)\s*\((.*?)\)\s*(?::\s*(.+?))?\s*$/)
175
+ # Match methods with or without parentheses
176
+ # def foo(params): Type - with params and return type
177
+ # def foo(): Type - no params but with return type
178
+ # def foo(params) - with params, no return type
179
+ # def foo - no params, no return type
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*$/)
113
182
  return nil unless match
114
183
 
115
- function_name = match[1]
116
- params_str = match[2]
117
- return_type_str = match[3]&.strip
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
118
188
 
119
189
  # Validate return type if present
120
190
  if return_type_str
@@ -127,10 +197,11 @@ module TRuby
127
197
  name: function_name,
128
198
  params: params,
129
199
  return_type: return_type_str,
200
+ visibility: visibility,
130
201
  }
131
202
 
132
- # Parse return type with combinator if available
133
- if @use_combinator && return_type_str
203
+ # Parse return type with combinator
204
+ if return_type_str
134
205
  type_result = @type_parser.parse(return_type_str)
135
206
  result[:ir_return_type] = type_result[:type] if type_result[:success]
136
207
  end
@@ -222,8 +293,8 @@ module TRuby
222
293
  type: type_str,
223
294
  }
224
295
 
225
- # Parse type with combinator if available
226
- if @use_combinator && type_str
296
+ # Parse type with combinator
297
+ if type_str
227
298
  type_result = @type_parser.parse(type_str)
228
299
  result[:ir_type] = type_result[:type] if type_result[:success]
229
300
  end
@@ -231,6 +302,127 @@ module TRuby
231
302
  result
232
303
  end
233
304
 
305
+ def parse_class(start_index)
306
+ line = @lines[start_index]
307
+ match = line.match(/^\s*class\s+(\w+)(?:\s*<\s*(\w+))?/)
308
+ return [nil, start_index] unless match
309
+
310
+ class_name = match[1]
311
+ superclass = match[2]
312
+ methods = []
313
+ instance_vars = []
314
+ i = start_index + 1
315
+ class_indent = line.match(/^(\s*)/)[1].length
316
+ class_end = i
317
+
318
+ # 먼저 클래스의 끝을 찾음
319
+ temp_i = i
320
+ while temp_i < @lines.length
321
+ current_line = @lines[temp_i]
322
+ if current_line.match?(/^\s*end\s*$/)
323
+ end_indent = current_line.match(/^(\s*)/)[1].length
324
+ if end_indent <= class_indent
325
+ class_end = temp_i
326
+ break
327
+ end
328
+ end
329
+ temp_i += 1
330
+ end
331
+
332
+ while i < class_end
333
+ current_line = @lines[i]
334
+
335
+ # Match method definitions inside class
336
+ if current_line.match?(/^\s*#{VISIBILITY_PATTERN}def\s+#{IDENTIFIER_CHAR}+/)
337
+ method_info, next_i = parse_method_in_class(i, class_end)
338
+ if method_info
339
+ methods << method_info
340
+ i = next_i
341
+ next
342
+ end
343
+ end
344
+
345
+ i += 1
346
+ end
347
+
348
+ # 메서드 본문에서 인스턴스 변수 추출
349
+ methods.each do |method_info|
350
+ extract_instance_vars_from_body(method_info[:body_ir], instance_vars)
351
+ end
352
+
353
+ # Try to infer instance variable types from initialize parameters
354
+ init_method = methods.find { |m| m[:name] == "initialize" }
355
+ if init_method
356
+ instance_vars.each do |ivar|
357
+ # Find matching parameter (e.g., @name = name)
358
+ matching_param = init_method[:params]&.find { |p| p[:name] == ivar[:name] }
359
+ ivar[:type] = matching_param[:type] if matching_param && matching_param[:type]
360
+ ivar[:ir_type] = matching_param[:ir_type] if matching_param && matching_param[:ir_type]
361
+ end
362
+ end
363
+
364
+ [{
365
+ name: class_name,
366
+ superclass: superclass,
367
+ methods: methods,
368
+ instance_vars: instance_vars,
369
+ }, class_end,]
370
+ end
371
+
372
+ # 클래스 내부의 메서드를 본문까지 포함하여 파싱
373
+ def parse_method_in_class(start_index, class_end)
374
+ line = @lines[start_index]
375
+ method_info = parse_function_definition(line)
376
+ return [nil, start_index] unless method_info
377
+
378
+ def_indent = line.match(/^(\s*)/)[1].length
379
+ i = start_index + 1
380
+ body_start = i
381
+ body_end = i
382
+
383
+ # 메서드의 end 키워드 찾기
384
+ while i < class_end
385
+ current_line = @lines[i]
386
+
387
+ if current_line.match?(/^\s*end\s*$/)
388
+ end_indent = current_line.match(/^(\s*)/)[1].length
389
+ if end_indent <= def_indent
390
+ body_end = i
391
+ break
392
+ end
393
+ end
394
+
395
+ i += 1
396
+ end
397
+
398
+ # 본문 파싱 (parse_body 옵션이 활성화된 경우)
399
+ if @parse_body && @body_parser && body_start < body_end
400
+ method_info[:body_ir] = @body_parser.parse(@lines, body_start, body_end)
401
+ method_info[:body_range] = { start: body_start, end: body_end }
402
+ end
403
+
404
+ [method_info, i]
405
+ end
406
+
407
+ # 본문 IR에서 인스턴스 변수 추출
408
+ def extract_instance_vars_from_body(body_ir, instance_vars)
409
+ return unless body_ir.is_a?(IR::Block)
410
+
411
+ body_ir.statements.each do |stmt|
412
+ case stmt
413
+ when IR::Assignment
414
+ if stmt.target.start_with?("@") && !stmt.target.start_with?("@@")
415
+ ivar_name = stmt.target[1..] # @ 제거
416
+ unless instance_vars.any? { |iv| iv[:name] == ivar_name }
417
+ instance_vars << { name: ivar_name }
418
+ end
419
+ end
420
+ when IR::Block
421
+ extract_instance_vars_from_body(stmt, instance_vars)
422
+ end
423
+ end
424
+ end
425
+
234
426
  def parse_interface(start_index)
235
427
  line = @lines[start_index]
236
428
  match = line.match(/^\s*interface\s+([\w:]+)/)
@@ -253,10 +445,8 @@ module TRuby
253
445
  }
254
446
 
255
447
  # Parse member type with combinator
256
- if @use_combinator
257
- type_result = @type_parser.parse(member[:type])
258
- member[:ir_type] = type_result[:type] if type_result[:success]
259
- end
448
+ type_result = @type_parser.parse(member[:type])
449
+ member[:ir_type] = type_result[:type] if type_result[:success]
260
450
 
261
451
  members << member
262
452
  end
@@ -268,11 +458,4 @@ module TRuby
268
458
  [{ name: interface_name, members: members }, i]
269
459
  end
270
460
  end
271
-
272
- # Legacy Parser for backward compatibility (regex-only)
273
- class LegacyParser < Parser
274
- def initialize(source)
275
- super(source, use_combinator: false)
276
- end
277
- end
278
461
  end
@@ -1,38 +1,41 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TRuby
4
- # Represents a type checking error
5
- class TypeCheckError
6
- attr_reader :message, :location, :expected, :actual, :suggestion, :severity
4
+ # Represents a type checking error (can be raised as an exception)
5
+ class TypeCheckError < StandardError
6
+ attr_reader :error_message, :location, :expected, :actual, :suggestion, :severity
7
7
 
8
8
  def initialize(message:, location: nil, expected: nil, actual: nil, suggestion: nil, severity: :error)
9
- @message = message
9
+ @error_message = message
10
10
  @location = location
11
11
  @expected = expected
12
12
  @actual = actual
13
13
  @suggestion = suggestion
14
14
  @severity = severity
15
- end
16
-
17
- def to_s
18
- parts = [@message]
19
- parts << " Expected: #{@expected}" if @expected
20
- parts << " Actual: #{@actual}" if @actual
21
- parts << " Suggestion: #{@suggestion}" if @suggestion
22
- parts << " at #{@location}" if @location
23
- parts.join("\n")
15
+ super(build_full_message)
24
16
  end
25
17
 
26
18
  def to_diagnostic
27
19
  {
28
20
  severity: @severity,
29
- message: @message,
21
+ message: @error_message,
30
22
  location: @location,
31
23
  expected: @expected,
32
24
  actual: @actual,
33
25
  suggestion: @suggestion,
34
26
  }
35
27
  end
28
+
29
+ private
30
+
31
+ def build_full_message
32
+ parts = [@error_message]
33
+ parts << " Expected: #{@expected}" if @expected
34
+ parts << " Actual: #{@actual}" if @actual
35
+ parts << " Suggestion: #{@suggestion}" if @suggestion
36
+ parts << " at #{@location}" if @location
37
+ parts.join("\n")
38
+ end
36
39
  end
37
40
 
38
41
  # Type hierarchy for subtype checking
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TRuby
4
+ # TypeEnv - 타입 환경 (스코프 체인)
5
+ # TypeScript의 Checker에서 심볼 타입을 추적하는 방식을 참고
6
+ class TypeEnv
7
+ attr_reader :parent, :bindings, :instance_vars
8
+
9
+ def initialize(parent = nil)
10
+ @parent = parent
11
+ @bindings = {} # 지역 변수 { name => type }
12
+ @instance_vars = {} # 인스턴스 변수 { name => type }
13
+ @class_vars = {} # 클래스 변수 { name => type }
14
+ end
15
+
16
+ # 지역 변수 타입 정의
17
+ # @param name [String] 변수 이름
18
+ # @param type [IR::TypeNode, String] 타입
19
+ def define(name, type)
20
+ @bindings[name] = type
21
+ end
22
+
23
+ # 변수 타입 조회 (스코프 체인 탐색)
24
+ # @param name [String] 변수 이름
25
+ # @return [IR::TypeNode, String, nil] 타입 또는 nil
26
+ def lookup(name)
27
+ # 인스턴스 변수
28
+ if name.start_with?("@") && !name.start_with?("@@")
29
+ return lookup_instance_var(name)
30
+ end
31
+
32
+ # 클래스 변수
33
+ if name.start_with?("@@")
34
+ return lookup_class_var(name)
35
+ end
36
+
37
+ # 지역 변수 또는 메서드 파라미터
38
+ return @bindings[name] if @bindings.key?(name)
39
+
40
+ # 부모 스코프에서 검색
41
+ @parent&.lookup(name)
42
+ end
43
+
44
+ # 인스턴스 변수 타입 정의
45
+ # @param name [String] 변수 이름 (@포함)
46
+ # @param type [IR::TypeNode, String] 타입
47
+ def define_instance_var(name, type)
48
+ # @ 접두사 정규화
49
+ normalized = name.start_with?("@") ? name : "@#{name}"
50
+ @instance_vars[normalized] = type
51
+ end
52
+
53
+ # 인스턴스 변수 타입 조회
54
+ # @param name [String] 변수 이름 (@포함)
55
+ # @return [IR::TypeNode, String, nil] 타입 또는 nil
56
+ def lookup_instance_var(name)
57
+ normalized = name.start_with?("@") ? name : "@#{name}"
58
+ return @instance_vars[normalized] if @instance_vars.key?(normalized)
59
+
60
+ @parent&.lookup_instance_var(normalized)
61
+ end
62
+
63
+ # 클래스 변수 타입 정의
64
+ # @param name [String] 변수 이름 (@@포함)
65
+ # @param type [IR::TypeNode, String] 타입
66
+ def define_class_var(name, type)
67
+ normalized = name.start_with?("@@") ? name : "@@#{name}"
68
+ @class_vars[normalized] = type
69
+ end
70
+
71
+ # 클래스 변수 타입 조회
72
+ # @param name [String] 변수 이름 (@@포함)
73
+ # @return [IR::TypeNode, String, nil] 타입 또는 nil
74
+ def lookup_class_var(name)
75
+ normalized = name.start_with?("@@") ? name : "@@#{name}"
76
+ return @class_vars[normalized] if @class_vars.key?(normalized)
77
+
78
+ @parent&.lookup_class_var(normalized)
79
+ end
80
+
81
+ # 자식 스코프 생성 (블록, 람다 등)
82
+ # @return [TypeEnv] 새 자식 스코프
83
+ def child_scope
84
+ TypeEnv.new(self)
85
+ end
86
+
87
+ # 현재 스코프에서 정의된 모든 변수 이름
88
+ # @return [Array<String>] 변수 이름 배열
89
+ def local_names
90
+ @bindings.keys
91
+ end
92
+
93
+ # 현재 스코프에서 정의된 모든 인스턴스 변수 이름
94
+ # @return [Array<String>] 인스턴스 변수 이름 배열
95
+ def instance_var_names
96
+ @instance_vars.keys
97
+ end
98
+
99
+ # 변수가 현재 스코프에 정의되어 있는지 확인
100
+ # @param name [String] 변수 이름
101
+ # @return [Boolean]
102
+ def defined_locally?(name)
103
+ @bindings.key?(name)
104
+ end
105
+
106
+ # 스코프 깊이 (디버깅용)
107
+ # @return [Integer] 스코프 깊이
108
+ def depth
109
+ @parent ? @parent.depth + 1 : 0
110
+ end
111
+
112
+ # 스코프 체인에서 모든 변수 수집
113
+ # @return [Hash] 모든 변수의 { name => type }
114
+ def all_bindings
115
+ parent_bindings = @parent ? @parent.all_bindings : {}
116
+ parent_bindings.merge(@bindings)
117
+ end
118
+
119
+ # 디버그 출력
120
+ def to_s
121
+ parts = ["TypeEnv(depth=#{depth})"]
122
+ parts << " locals: #{@bindings.keys.join(", ")}" if @bindings.any?
123
+ parts << " ivars: #{@instance_vars.keys.join(", ")}" if @instance_vars.any?
124
+ parts.join("\n")
125
+ end
126
+ end
127
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TRuby
4
- VERSION = "0.0.38"
4
+ VERSION = "0.0.40"
5
5
  end
@@ -80,14 +80,18 @@ module TRuby
80
80
 
81
81
  private
82
82
 
83
+ def watch_directory(path)
84
+ File.directory?(path) ? path : File.dirname(path)
85
+ end
86
+
83
87
  def watch_directories
84
- @paths.map do |path|
85
- if File.directory?(path)
86
- path
87
- else
88
- File.dirname(path)
89
- end
90
- end.uniq
88
+ if @paths == [File.expand_path(".")]
89
+ # Default case: only watch source_include directories from config
90
+ @config.source_include.map { |dir| File.expand_path(dir) }.select { |dir| Dir.exist?(dir) }
91
+ else
92
+ # Specific paths provided: watch those paths
93
+ @paths.map { |path| watch_directory(path) }.uniq
94
+ end
91
95
  end
92
96
 
93
97
  def handle_changes(modified, added, removed)
@@ -243,20 +247,21 @@ module TRuby
243
247
  def find_source_files_by_extension(ext)
244
248
  files = []
245
249
 
246
- # If watching specific paths, use those paths
247
- # Otherwise, use Config's find_source_files which respects include/exclude patterns
248
- if @paths == [File.expand_path(".")]
249
- # Default case: use config's src_dir with include/exclude patterns
250
- files = @config.find_source_files.select { |f| f.end_with?(ext) }
251
- else
252
- # Specific paths provided: search in those paths but still apply exclude patterns
253
- @paths.each do |path|
254
- if File.directory?(path)
255
- Dir.glob(File.join(path, "**", "*#{ext}")).each do |file|
256
- files << file unless @config.excluded?(file)
257
- end
258
- elsif File.file?(path) && path.end_with?(ext) && !@config.excluded?(path)
259
- files << path
250
+ # Always search in source_include directories only
251
+ source_paths = if @paths == [File.expand_path(".")]
252
+ @config.source_include.map { |dir| File.expand_path(dir) }
253
+ else
254
+ @paths.map { |path| File.expand_path(path) }
255
+ end
256
+
257
+ source_paths.each do |path|
258
+ if File.file?(path)
259
+ # Handle single file path
260
+ files << path if path.end_with?(ext) && !@config.excluded?(path)
261
+ elsif Dir.exist?(path)
262
+ # Handle directory path
263
+ Dir.glob(File.join(path, "**", "*#{ext}")).each do |file|
264
+ files << file unless @config.excluded?(file)
260
265
  end
261
266
  end
262
267
  end
data/lib/t_ruby.rb CHANGED
@@ -11,13 +11,14 @@ 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"
15
+ require_relative "t_ruby/body_parser"
14
16
  require_relative "t_ruby/parser"
15
17
  require_relative "t_ruby/union_type_parser"
16
18
  require_relative "t_ruby/generic_type_parser"
17
19
  require_relative "t_ruby/intersection_type_parser"
18
20
  require_relative "t_ruby/type_erasure"
19
21
  require_relative "t_ruby/error_handler"
20
- require_relative "t_ruby/rbs_generator"
21
22
  require_relative "t_ruby/declaration_generator"
22
23
  require_relative "t_ruby/compiler"
23
24
  require_relative "t_ruby/lsp_server"
@@ -29,6 +30,8 @@ require_relative "t_ruby/constraint_checker"
29
30
  require_relative "t_ruby/type_inferencer"
30
31
  require_relative "t_ruby/runtime_validator"
31
32
  require_relative "t_ruby/type_checker"
33
+ require_relative "t_ruby/type_env"
34
+ require_relative "t_ruby/ast_type_inferrer"
32
35
  require_relative "t_ruby/cache"
33
36
  require_relative "t_ruby/package_manager"
34
37
 
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.38
4
+ version: 0.0.40
5
5
  platform: ruby
6
6
  authors:
7
7
  - Y. Fred Kim
@@ -36,7 +36,9 @@ files:
36
36
  - README.md
37
37
  - bin/trc
38
38
  - lib/t_ruby.rb
39
+ - lib/t_ruby/ast_type_inferrer.rb
39
40
  - lib/t_ruby/benchmark.rb
41
+ - lib/t_ruby/body_parser.rb
40
42
  - lib/t_ruby/bundler_integration.rb
41
43
  - lib/t_ruby/cache.rb
42
44
  - lib/t_ruby/cli.rb
@@ -50,17 +52,18 @@ files:
50
52
  - lib/t_ruby/docs_example_verifier.rb
51
53
  - lib/t_ruby/error_handler.rb
52
54
  - lib/t_ruby/generic_type_parser.rb
55
+ - lib/t_ruby/heredoc_detector.rb
53
56
  - lib/t_ruby/intersection_type_parser.rb
54
57
  - lib/t_ruby/ir.rb
55
58
  - lib/t_ruby/lsp_server.rb
56
59
  - lib/t_ruby/package_manager.rb
57
60
  - lib/t_ruby/parser.rb
58
61
  - lib/t_ruby/parser_combinator.rb
59
- - lib/t_ruby/rbs_generator.rb
60
62
  - lib/t_ruby/runtime_validator.rb
61
63
  - lib/t_ruby/smt_solver.rb
62
64
  - lib/t_ruby/type_alias_registry.rb
63
65
  - lib/t_ruby/type_checker.rb
66
+ - lib/t_ruby/type_env.rb
64
67
  - lib/t_ruby/type_erasure.rb
65
68
  - lib/t_ruby/type_inferencer.rb
66
69
  - lib/t_ruby/union_type_parser.rb
@@ -69,7 +72,7 @@ files:
69
72
  - lib/t_ruby/watcher.rb
70
73
  homepage: https://type-ruby.github.io
71
74
  licenses:
72
- - MIT
75
+ - BSD-2-Clause
73
76
  metadata:
74
77
  rubygems_mfa_required: 'true'
75
78
  rdoc_options: []