konpeito 0.1.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 (180) hide show
  1. checksums.yaml +7 -0
  2. data/.ruby-version +1 -0
  3. data/CHANGELOG.md +75 -0
  4. data/CONTRIBUTING.md +123 -0
  5. data/LICENSE +21 -0
  6. data/README.md +257 -0
  7. data/Rakefile +11 -0
  8. data/bin/konpeito +6 -0
  9. data/konpeito.gemspec +43 -0
  10. data/lib/konpeito/ast/typed_ast.rb +620 -0
  11. data/lib/konpeito/ast/visitor.rb +78 -0
  12. data/lib/konpeito/cache/cache_manager.rb +230 -0
  13. data/lib/konpeito/cache/dependency_graph.rb +192 -0
  14. data/lib/konpeito/cache.rb +8 -0
  15. data/lib/konpeito/cli/base_command.rb +187 -0
  16. data/lib/konpeito/cli/build_command.rb +220 -0
  17. data/lib/konpeito/cli/check_command.rb +104 -0
  18. data/lib/konpeito/cli/config.rb +231 -0
  19. data/lib/konpeito/cli/deps_command.rb +128 -0
  20. data/lib/konpeito/cli/doctor_command.rb +340 -0
  21. data/lib/konpeito/cli/fmt_command.rb +199 -0
  22. data/lib/konpeito/cli/init_command.rb +312 -0
  23. data/lib/konpeito/cli/lsp_command.rb +40 -0
  24. data/lib/konpeito/cli/run_command.rb +150 -0
  25. data/lib/konpeito/cli/test_command.rb +248 -0
  26. data/lib/konpeito/cli/watch_command.rb +212 -0
  27. data/lib/konpeito/cli.rb +301 -0
  28. data/lib/konpeito/codegen/builtin_methods.rb +229 -0
  29. data/lib/konpeito/codegen/cruby_backend.rb +1090 -0
  30. data/lib/konpeito/codegen/debug_info.rb +352 -0
  31. data/lib/konpeito/codegen/inliner.rb +486 -0
  32. data/lib/konpeito/codegen/jvm_backend.rb +197 -0
  33. data/lib/konpeito/codegen/jvm_generator.rb +13412 -0
  34. data/lib/konpeito/codegen/llvm_generator.rb +13191 -0
  35. data/lib/konpeito/codegen/loop_optimizer.rb +363 -0
  36. data/lib/konpeito/codegen/monomorphizer.rb +359 -0
  37. data/lib/konpeito/codegen/profile_runtime.c +341 -0
  38. data/lib/konpeito/codegen/profiler.rb +99 -0
  39. data/lib/konpeito/compiler.rb +592 -0
  40. data/lib/konpeito/dependency_resolver.rb +296 -0
  41. data/lib/konpeito/diagnostics/collector.rb +127 -0
  42. data/lib/konpeito/diagnostics/diagnostic.rb +237 -0
  43. data/lib/konpeito/diagnostics/renderer.rb +144 -0
  44. data/lib/konpeito/formatter/formatter.rb +1214 -0
  45. data/lib/konpeito/hir/builder.rb +7167 -0
  46. data/lib/konpeito/hir/nodes.rb +2465 -0
  47. data/lib/konpeito/lsp/document_manager.rb +820 -0
  48. data/lib/konpeito/lsp/server.rb +183 -0
  49. data/lib/konpeito/lsp/transport.rb +38 -0
  50. data/lib/konpeito/parser/prism_adapter.rb +65 -0
  51. data/lib/konpeito/platform.rb +103 -0
  52. data/lib/konpeito/profile/report.rb +136 -0
  53. data/lib/konpeito/rbs_inline/preprocessor.rb +199 -0
  54. data/lib/konpeito/stdlib/compression/compression.rb +72 -0
  55. data/lib/konpeito/stdlib/compression/compression.rbs +60 -0
  56. data/lib/konpeito/stdlib/compression/compression_native.c +415 -0
  57. data/lib/konpeito/stdlib/compression/extconf.rb +19 -0
  58. data/lib/konpeito/stdlib/crypto/crypto.rb +85 -0
  59. data/lib/konpeito/stdlib/crypto/crypto.rbs +74 -0
  60. data/lib/konpeito/stdlib/crypto/crypto_native.c +312 -0
  61. data/lib/konpeito/stdlib/crypto/extconf.rb +40 -0
  62. data/lib/konpeito/stdlib/http/extconf.rb +19 -0
  63. data/lib/konpeito/stdlib/http/http.rb +125 -0
  64. data/lib/konpeito/stdlib/http/http.rbs +57 -0
  65. data/lib/konpeito/stdlib/http/http_native.c +440 -0
  66. data/lib/konpeito/stdlib/json/extconf.rb +17 -0
  67. data/lib/konpeito/stdlib/json/json.rb +44 -0
  68. data/lib/konpeito/stdlib/json/json.rbs +33 -0
  69. data/lib/konpeito/stdlib/json/json_native.c +286 -0
  70. data/lib/konpeito/stdlib/ui/extconf.rb +216 -0
  71. data/lib/konpeito/stdlib/ui/konpeito_ui_native.cpp +1625 -0
  72. data/lib/konpeito/stdlib/ui/konpeito_ui_native.h +162 -0
  73. data/lib/konpeito/stdlib/ui/ui.rb +318 -0
  74. data/lib/konpeito/stdlib/ui/ui.rbs +247 -0
  75. data/lib/konpeito/type_checker/annotation_parser.rb +67 -0
  76. data/lib/konpeito/type_checker/hm_inferrer.rb +2565 -0
  77. data/lib/konpeito/type_checker/inferrer.rb +565 -0
  78. data/lib/konpeito/type_checker/rbs_loader.rb +1621 -0
  79. data/lib/konpeito/type_checker/type_resolver.rb +276 -0
  80. data/lib/konpeito/type_checker/types.rb +1434 -0
  81. data/lib/konpeito/type_checker/unification.rb +323 -0
  82. data/lib/konpeito/ui/animation/animated_state.rb +80 -0
  83. data/lib/konpeito/ui/animation/easing.rb +59 -0
  84. data/lib/konpeito/ui/animation/value_tween.rb +66 -0
  85. data/lib/konpeito/ui/app.rb +379 -0
  86. data/lib/konpeito/ui/box.rb +38 -0
  87. data/lib/konpeito/ui/castella.rb +70 -0
  88. data/lib/konpeito/ui/castella_native.rb +76 -0
  89. data/lib/konpeito/ui/chart/area_chart.rb +305 -0
  90. data/lib/konpeito/ui/chart/bar_chart.rb +288 -0
  91. data/lib/konpeito/ui/chart/base_chart.rb +210 -0
  92. data/lib/konpeito/ui/chart/chart_helpers.rb +79 -0
  93. data/lib/konpeito/ui/chart/gauge_chart.rb +171 -0
  94. data/lib/konpeito/ui/chart/heatmap_chart.rb +222 -0
  95. data/lib/konpeito/ui/chart/line_chart.rb +289 -0
  96. data/lib/konpeito/ui/chart/pie_chart.rb +219 -0
  97. data/lib/konpeito/ui/chart/scales.rb +77 -0
  98. data/lib/konpeito/ui/chart/scatter_chart.rb +303 -0
  99. data/lib/konpeito/ui/chart/stacked_bar_chart.rb +276 -0
  100. data/lib/konpeito/ui/column.rb +271 -0
  101. data/lib/konpeito/ui/core.rb +2199 -0
  102. data/lib/konpeito/ui/dsl.rb +443 -0
  103. data/lib/konpeito/ui/frame.rb +171 -0
  104. data/lib/konpeito/ui/frame_native.rb +494 -0
  105. data/lib/konpeito/ui/markdown/ast.rb +124 -0
  106. data/lib/konpeito/ui/markdown/mermaid/layout.rb +387 -0
  107. data/lib/konpeito/ui/markdown/mermaid/models.rb +232 -0
  108. data/lib/konpeito/ui/markdown/mermaid/parser.rb +519 -0
  109. data/lib/konpeito/ui/markdown/mermaid/renderer.rb +336 -0
  110. data/lib/konpeito/ui/markdown/parser.rb +805 -0
  111. data/lib/konpeito/ui/markdown/renderer.rb +639 -0
  112. data/lib/konpeito/ui/markdown/theme.rb +165 -0
  113. data/lib/konpeito/ui/render_node.rb +260 -0
  114. data/lib/konpeito/ui/row.rb +207 -0
  115. data/lib/konpeito/ui/spacer.rb +18 -0
  116. data/lib/konpeito/ui/style.rb +799 -0
  117. data/lib/konpeito/ui/theme.rb +563 -0
  118. data/lib/konpeito/ui/themes/material.rb +35 -0
  119. data/lib/konpeito/ui/themes/tokyo_night.rb +6 -0
  120. data/lib/konpeito/ui/widgets/button.rb +103 -0
  121. data/lib/konpeito/ui/widgets/calendar.rb +1034 -0
  122. data/lib/konpeito/ui/widgets/checkbox.rb +119 -0
  123. data/lib/konpeito/ui/widgets/container.rb +91 -0
  124. data/lib/konpeito/ui/widgets/data_table.rb +667 -0
  125. data/lib/konpeito/ui/widgets/divider.rb +29 -0
  126. data/lib/konpeito/ui/widgets/image.rb +105 -0
  127. data/lib/konpeito/ui/widgets/input.rb +485 -0
  128. data/lib/konpeito/ui/widgets/markdown.rb +57 -0
  129. data/lib/konpeito/ui/widgets/modal.rb +163 -0
  130. data/lib/konpeito/ui/widgets/multiline_input.rb +968 -0
  131. data/lib/konpeito/ui/widgets/multiline_text.rb +180 -0
  132. data/lib/konpeito/ui/widgets/net_image.rb +100 -0
  133. data/lib/konpeito/ui/widgets/progress_bar.rb +70 -0
  134. data/lib/konpeito/ui/widgets/radio_buttons.rb +93 -0
  135. data/lib/konpeito/ui/widgets/slider.rb +133 -0
  136. data/lib/konpeito/ui/widgets/switch.rb +84 -0
  137. data/lib/konpeito/ui/widgets/tabs.rb +157 -0
  138. data/lib/konpeito/ui/widgets/text.rb +110 -0
  139. data/lib/konpeito/ui/widgets/tree.rb +426 -0
  140. data/lib/konpeito/version.rb +5 -0
  141. data/lib/konpeito.rb +109 -0
  142. data/test_native_array.rb +172 -0
  143. data/test_native_array_class.rb +197 -0
  144. data/test_native_class.rb +151 -0
  145. data/tools/konpeito-asm/build.sh +65 -0
  146. data/tools/konpeito-asm/lib/asm-9.7.1.jar +0 -0
  147. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KArray.class +0 -0
  148. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KCompression.class +0 -0
  149. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KConditionVariable.class +0 -0
  150. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KCrypto.class +0 -0
  151. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KFile.class +0 -0
  152. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KHTTP.class +0 -0
  153. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KHash.class +0 -0
  154. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KJSON$Parser.class +0 -0
  155. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KJSON.class +0 -0
  156. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KMath.class +0 -0
  157. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KRactor.class +0 -0
  158. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KRactorPort.class +0 -0
  159. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KSizedQueue.class +0 -0
  160. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KThread.class +0 -0
  161. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KTime.class +0 -0
  162. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/RubyDispatch.class +0 -0
  163. data/tools/konpeito-asm/src/ClassIntrospector.java +312 -0
  164. data/tools/konpeito-asm/src/KonpeitoAssembler.java +659 -0
  165. data/tools/konpeito-asm/src/konpeito/runtime/KArray.java +390 -0
  166. data/tools/konpeito-asm/src/konpeito/runtime/KCompression.java +168 -0
  167. data/tools/konpeito-asm/src/konpeito/runtime/KConditionVariable.java +48 -0
  168. data/tools/konpeito-asm/src/konpeito/runtime/KCrypto.java +151 -0
  169. data/tools/konpeito-asm/src/konpeito/runtime/KFile.java +100 -0
  170. data/tools/konpeito-asm/src/konpeito/runtime/KHTTP.java +113 -0
  171. data/tools/konpeito-asm/src/konpeito/runtime/KHash.java +228 -0
  172. data/tools/konpeito-asm/src/konpeito/runtime/KJSON.java +405 -0
  173. data/tools/konpeito-asm/src/konpeito/runtime/KMath.java +54 -0
  174. data/tools/konpeito-asm/src/konpeito/runtime/KRactor.java +244 -0
  175. data/tools/konpeito-asm/src/konpeito/runtime/KRactorPort.java +53 -0
  176. data/tools/konpeito-asm/src/konpeito/runtime/KSizedQueue.java +49 -0
  177. data/tools/konpeito-asm/src/konpeito/runtime/KThread.java +49 -0
  178. data/tools/konpeito-asm/src/konpeito/runtime/KTime.java +53 -0
  179. data/tools/konpeito-asm/src/konpeito/runtime/RubyDispatch.java +416 -0
  180. metadata +267 -0
@@ -0,0 +1,276 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "set"
4
+ require_relative "types"
5
+ require_relative "unification"
6
+
7
+ module Konpeito
8
+ module TypeChecker
9
+ # Pre-codegen validation pass: checks for remaining unresolved TypeVars in HIR.
10
+ #
11
+ # This pass runs between type inference (HM) and code generation. It attempts
12
+ # to resolve TypeVars that HM couldn't determine using:
13
+ # 1. Class hierarchy information (parent method signatures)
14
+ # 2. Call-site argument types (supplements HM unification)
15
+ #
16
+ # Structural typing heuristics (e.g., "find class by method set") are intentionally
17
+ # NOT used — per Kotlin-style design, all types must be resolved by type inference.
18
+ # If resolution fails, it collects actionable error messages directing the user
19
+ # to add RBS type annotations for the specific parameters/variables involved.
20
+ class TypeResolver
21
+ attr_reader :errors
22
+
23
+ def initialize(hir_program, hm_inferrer: nil, rbs_loader: nil, jvm_interop_classes: nil, monomorphizer: nil)
24
+ @hir = hir_program
25
+ @hm_inferrer = hm_inferrer
26
+ @rbs_loader = rbs_loader
27
+ @jvm_interop_classes = jvm_interop_classes || {}
28
+ @monomorphizer = monomorphizer
29
+ @errors = []
30
+
31
+ # Collect class info from HIR
32
+ @class_methods = {} # "ClassName" => Set of method names
33
+ @class_parents = {} # "ClassName" => "ParentName"
34
+ collect_class_info
35
+ end
36
+
37
+ # Run the type resolution pass.
38
+ # Returns true if all types were resolved, false if errors remain.
39
+ def resolve!
40
+ @errors.clear
41
+
42
+ # Propagate types from parent method signatures to overriding methods
43
+ resolve_parent_method_params
44
+
45
+ # Resolve TypeVar parameters using call-site argument types
46
+ resolve_call_site_params
47
+
48
+ # Structural typing heuristic was removed per Kotlin-style design.
49
+ # All types must be resolved by HM inference + RBS, not by guessing from method names.
50
+
51
+ # Scan remaining unresolved TypeVars and collect error messages
52
+ collect_unresolved_errors
53
+
54
+ @errors.empty?
55
+ end
56
+
57
+ private
58
+
59
+ def collect_class_info
60
+ @hir.classes.each do |class_def|
61
+ name = class_def.name.to_s
62
+ @class_parents[name] = class_def.superclass.to_s if class_def.respond_to?(:superclass) && class_def.superclass
63
+ @class_methods[name] = Set.new
64
+ end
65
+
66
+ @hir.functions.each do |func|
67
+ if func.owner_class
68
+ @class_methods[func.owner_class.to_s] ||= Set.new
69
+ method_name = func.name.to_s.sub(/^#{Regexp.escape(func.owner_class.to_s)}#/, "")
70
+ @class_methods[func.owner_class.to_s].add(method_name)
71
+ end
72
+ end
73
+ end
74
+
75
+ # Propagate parameter types from parent class methods to child overrides
76
+ def resolve_parent_method_params
77
+ @hir.functions.each do |func|
78
+ next unless func.owner_class
79
+ next if func.params.empty?
80
+
81
+ unresolved_params = func.params.select { |p| unresolved?(p.type) }
82
+ next if unresolved_params.empty?
83
+
84
+ parent_name = @class_parents[func.owner_class.to_s]
85
+ while parent_name
86
+ method_name = func.name.to_s.sub(/^#{Regexp.escape(func.owner_class.to_s)}#/, "")
87
+ parent_func = @hir.functions.find { |f|
88
+ f.owner_class.to_s == parent_name &&
89
+ f.name.to_s == "#{parent_name}##{method_name}"
90
+ }
91
+
92
+ if parent_func && parent_func.params.size == func.params.size
93
+ func.params.each_with_index do |param, i|
94
+ parent_param = parent_func.params[i]
95
+ if unresolved?(param.type) && !unresolved?(parent_param.type)
96
+ begin
97
+ unifier = Unifier.new
98
+ unifier.unify(param.type, parent_param.type)
99
+ rescue UnificationError
100
+ # Incompatible types — skip
101
+ end
102
+ end
103
+ end
104
+ break
105
+ end
106
+
107
+ parent_name = @class_parents[parent_name]
108
+ end
109
+ end
110
+ end
111
+
112
+ # Try to resolve parameter TypeVars from call-site argument types
113
+ def resolve_call_site_params
114
+ @hir.functions.each do |func|
115
+ func.body.each do |bb|
116
+ bb.instructions.each do |inst|
117
+ next unless inst.is_a?(HIR::Call)
118
+ next unless inst.args
119
+
120
+ target_name = inst.method_name.to_s
121
+ # Try to find the function being called (for self/top-level calls)
122
+ target_func = nil
123
+ if inst.receiver.nil? || inst.receiver.is_a?(HIR::SelfRef)
124
+ target_func = @hir.functions.find { |f| f.name.to_s == target_name }
125
+ end
126
+ next unless target_func
127
+
128
+ inst.args.each_with_index do |arg, i|
129
+ next if i >= target_func.params.size
130
+ param = target_func.params[i]
131
+ next unless unresolved?(param.type)
132
+
133
+ arg_type = infer_instruction_type(arg)
134
+ next unless arg_type && !unresolved?(arg_type)
135
+
136
+ begin
137
+ unifier = Unifier.new
138
+ unifier.unify(param.type, arg_type)
139
+ rescue UnificationError
140
+ # Incompatible — skip
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
147
+
148
+ # Scan all HIR instructions and collect errors for remaining unresolved types
149
+ def collect_unresolved_errors
150
+ seen_typevars = Set.new # Track TypeVar IDs to avoid duplicate errors
151
+
152
+ @hir.functions.each do |func|
153
+ # Skip polymorphic functions (type erasure is expected, not an error).
154
+ # These have monomorphized specializations with concrete types.
155
+ next if function_is_polymorphic?(func.name.to_s)
156
+
157
+ collect_unresolved_from_blocks(func.body, func, seen_typevars)
158
+ end
159
+ end
160
+
161
+ # Check if a function is polymorphic or a monomorphized specialization.
162
+ # - Original polymorphic functions have TypeVar params (type erasure, expected).
163
+ # - Monomorphized copies (e.g., add_Integer_Integer) share TypeVar references
164
+ # from the original but receive concrete types via params — not an error.
165
+ def function_is_polymorphic?(func_name)
166
+ return false unless @monomorphizer
167
+ # Original polymorphic function (has specializations)
168
+ return true if @monomorphizer.specializations.any? { |key, _| key[0] == func_name }
169
+ # Monomorphized copy (is a specialization of another function)
170
+ return true if @monomorphizer.specializations.any? { |_, name| name == func_name }
171
+ false
172
+ end
173
+
174
+ def collect_unresolved_from_blocks(blocks, func, seen_typevars)
175
+ blocks.each do |bb|
176
+ bb.instructions.each do |inst|
177
+ # Recurse into block bodies
178
+ if inst.respond_to?(:block) && inst.block && inst.block.respond_to?(:body)
179
+ collect_unresolved_from_blocks(inst.block.body, func, seen_typevars)
180
+ end
181
+
182
+ next unless inst.is_a?(HIR::Call)
183
+ next unless inst.receiver
184
+ next unless unresolved?(inst.receiver.type)
185
+ # .call on block/proc variables is handled at codegen as invokevirtual.
186
+ # The receiver TypeVar represents a captured block — not an inference failure.
187
+ next if inst.method_name.to_s == "call"
188
+
189
+ recv_type = inst.receiver.type.prune
190
+ next unless recv_type.is_a?(TypeVar)
191
+ next if seen_typevars.include?(recv_type.id)
192
+
193
+ seen_typevars.add(recv_type.id)
194
+
195
+ location = format_location(func)
196
+ method_name = inst.method_name.to_s
197
+
198
+ @errors << format_error(
199
+ location: location,
200
+ method_name: method_name,
201
+ receiver_type: recv_type.to_s,
202
+ hint: suggest_fix(func, inst)
203
+ )
204
+ end
205
+ end
206
+ end
207
+
208
+ def format_error(location:, method_name:, receiver_type:, hint:)
209
+ msg = "#{location}: cannot resolve receiver type for .#{method_name} (type: #{receiver_type})"
210
+ msg += "\n #{hint}" if hint
211
+ msg
212
+ end
213
+
214
+ def suggest_fix(func, inst)
215
+ if func.owner_class
216
+ method_name = func.name.to_s.sub(/^#{Regexp.escape(func.owner_class.to_s)}#/, "")
217
+ param_name = extract_param_name(inst.receiver)
218
+
219
+ if param_name
220
+ "Add RBS type annotation for parameter '#{param_name}' in #{func.owner_class}##{method_name}"
221
+ else
222
+ "Add RBS type annotations for #{func.owner_class}##{method_name}"
223
+ end
224
+ else
225
+ "Add RBS type annotations to resolve the receiver type"
226
+ end
227
+ end
228
+
229
+ def extract_param_name(inst)
230
+ if inst.respond_to?(:name)
231
+ inst.name.to_s
232
+ elsif inst.respond_to?(:var_name)
233
+ inst.var_name.to_s
234
+ else
235
+ nil
236
+ end
237
+ end
238
+
239
+ def format_location(func)
240
+ if func.owner_class
241
+ method_name = func.name.to_s.sub(/^#{Regexp.escape(func.owner_class.to_s)}#/, "")
242
+ "#{func.owner_class}##{method_name}"
243
+ else
244
+ func.name.to_s
245
+ end
246
+ end
247
+
248
+ def unresolved?(type)
249
+ return false unless type
250
+ if type.is_a?(TypeVar)
251
+ pruned = type.prune
252
+ pruned.is_a?(TypeVar) && !pruned.instance
253
+ else
254
+ false
255
+ end
256
+ end
257
+
258
+ def prune(type)
259
+ if type.is_a?(TypeVar)
260
+ type.prune
261
+ else
262
+ type
263
+ end
264
+ end
265
+
266
+ def infer_instruction_type(inst)
267
+ return nil unless inst
268
+ return nil unless inst.respond_to?(:type)
269
+ type = inst.type
270
+ return nil unless type
271
+ # Prune TypeVars to get concrete type
272
+ type.is_a?(TypeVar) ? type.prune : type
273
+ end
274
+ end
275
+ end
276
+ end