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
data/lib/konpeito.rb ADDED
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "konpeito/version"
4
+
5
+ module Konpeito
6
+ class Error < StandardError; end
7
+ class ParseError < Error; end
8
+ class TypeError < Error; end
9
+ class CodegenError < Error; end
10
+
11
+ class DependencyError < Error
12
+ attr_reader :from_file, :line, :cycle, :missing_file
13
+
14
+ def initialize(message, from_file: nil, line: nil, cycle: nil, missing_file: nil)
15
+ @from_file = from_file
16
+ @line = line
17
+ @cycle = cycle # Array of file names in the cycle
18
+ @missing_file = missing_file
19
+ super(message)
20
+ end
21
+ end
22
+
23
+ module Diagnostics
24
+ autoload :SourceSpan, "konpeito/diagnostics/diagnostic"
25
+ autoload :Label, "konpeito/diagnostics/diagnostic"
26
+ autoload :Diagnostic, "konpeito/diagnostics/diagnostic"
27
+ autoload :DiagnosticRenderer, "konpeito/diagnostics/renderer"
28
+ autoload :Collector, "konpeito/diagnostics/collector"
29
+ end
30
+
31
+ autoload :Platform, "konpeito/platform"
32
+ autoload :CLI, "konpeito/cli"
33
+ autoload :LegacyCLI, "konpeito/cli"
34
+ autoload :Compiler, "konpeito/compiler"
35
+ autoload :DependencyResolver, "konpeito/dependency_resolver"
36
+
37
+ # Commands module for CLI subcommands
38
+ module Commands
39
+ autoload :Config, "konpeito/cli/config"
40
+ autoload :BaseCommand, "konpeito/cli/base_command"
41
+ autoload :BuildCommand, "konpeito/cli/build_command"
42
+ autoload :CheckCommand, "konpeito/cli/check_command"
43
+ autoload :LspCommand, "konpeito/cli/lsp_command"
44
+ autoload :InitCommand, "konpeito/cli/init_command"
45
+ autoload :FmtCommand, "konpeito/cli/fmt_command"
46
+ autoload :TestCommand, "konpeito/cli/test_command"
47
+ autoload :WatchCommand, "konpeito/cli/watch_command"
48
+ end
49
+
50
+ module Parser
51
+ autoload :PrismAdapter, "konpeito/parser/prism_adapter"
52
+ end
53
+
54
+ module TypeChecker
55
+ # Types must be loaded first as other modules depend on it
56
+ require_relative "konpeito/type_checker/types"
57
+
58
+ autoload :Checker, "konpeito/type_checker/checker"
59
+ autoload :Inferrer, "konpeito/type_checker/inferrer"
60
+ autoload :HMInferrer, "konpeito/type_checker/hm_inferrer"
61
+ autoload :RBSLoader, "konpeito/type_checker/rbs_loader"
62
+ autoload :TypeVar, "konpeito/type_checker/unification"
63
+ autoload :FunctionType, "konpeito/type_checker/unification"
64
+ autoload :Unifier, "konpeito/type_checker/unification"
65
+ autoload :TypeScheme, "konpeito/type_checker/unification"
66
+ autoload :UnificationError, "konpeito/type_checker/unification"
67
+ end
68
+
69
+ module AST
70
+ autoload :TypedNode, "konpeito/ast/typed_ast"
71
+ autoload :TypedASTBuilder, "konpeito/ast/typed_ast"
72
+ autoload :Visitor, "konpeito/ast/visitor"
73
+ end
74
+
75
+ module HIR
76
+ autoload :Builder, "konpeito/hir/builder"
77
+ # Load nodes directly since they define classes in HIR namespace
78
+ require_relative "konpeito/hir/nodes"
79
+ end
80
+
81
+ module Codegen
82
+ autoload :LLVMGenerator, "konpeito/codegen/llvm_generator"
83
+ autoload :CRubyBackend, "konpeito/codegen/cruby_backend"
84
+ autoload :Monomorphizer, "konpeito/codegen/monomorphizer"
85
+ autoload :Inliner, "konpeito/codegen/inliner"
86
+ autoload :LoopOptimizer, "konpeito/codegen/loop_optimizer"
87
+ end
88
+
89
+ module LSP
90
+ autoload :Server, "konpeito/lsp/server"
91
+ autoload :Transport, "konpeito/lsp/transport"
92
+ autoload :DocumentManager, "konpeito/lsp/document_manager"
93
+ end
94
+
95
+ module RBSInline
96
+ autoload :Preprocessor, "konpeito/rbs_inline/preprocessor"
97
+ end
98
+
99
+ # Convenience method
100
+ def self.compile(source_file, output_file: nil, format: :cruby_ext, verbose: false, optimize: true)
101
+ Compiler.new(
102
+ source_file: source_file,
103
+ output_file: output_file,
104
+ format: format,
105
+ verbose: verbose,
106
+ optimize: optimize
107
+ ).compile
108
+ end
109
+ end
@@ -0,0 +1,172 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Simple test for NativeArray
4
+
5
+ $LOAD_PATH.unshift File.expand_path("lib", __dir__)
6
+ require "konpeito"
7
+
8
+ source = <<~RUBY
9
+ def test_alloc(n)
10
+ arr = NativeArray.new(n)
11
+ arr.length
12
+ end
13
+
14
+ def test_set(n)
15
+ arr = NativeArray.new(n)
16
+ arr[0] = 3.14
17
+ arr[0]
18
+ end
19
+
20
+ def test_fill(n)
21
+ arr = NativeArray.new(n)
22
+
23
+ # Just fill array
24
+ i = 0
25
+ while i < n
26
+ arr[i] = i * 1.5
27
+ i = i + 1
28
+ end
29
+
30
+ arr[0]
31
+ end
32
+
33
+ def test_read_sum(n)
34
+ arr = NativeArray.new(n)
35
+
36
+ # Fill with simple values
37
+ i = 0
38
+ while i < n
39
+ arr[i] = 1.0
40
+ i = i + 1
41
+ end
42
+
43
+ # Try to read all values
44
+ total = arr[0]
45
+ total = total + arr[1]
46
+ total = total + arr[2]
47
+
48
+ total
49
+ end
50
+ RUBY
51
+
52
+ rbs = <<~RBS
53
+ class NativeArray[T]
54
+ def self.new: (Integer size) -> NativeArray[Float]
55
+ def []: (Integer index) -> Float
56
+ def []=: (Integer index, Float value) -> Float
57
+ def length: () -> Integer
58
+ end
59
+
60
+ class Object
61
+ def test_alloc: (Integer n) -> Integer
62
+ def test_set: (Integer n) -> Float
63
+ def test_fill: (Integer n) -> Float
64
+ def test_read_sum: (Integer n) -> Float
65
+ end
66
+ RBS
67
+
68
+ require "tempfile"
69
+ require "fileutils"
70
+
71
+ tmp_dir = "tmp"
72
+ FileUtils.mkdir_p(tmp_dir)
73
+
74
+ source_path = File.join(tmp_dir, "test_native.rb")
75
+ rbs_path = File.join(tmp_dir, "test_native.rbs")
76
+ output_path = File.join(tmp_dir, "test_native.bundle")
77
+
78
+ File.write(source_path, source)
79
+ File.write(rbs_path, rbs)
80
+
81
+ compiler = Konpeito::Compiler.new(
82
+ source_file: source_path,
83
+ output_file: output_path,
84
+ format: :cruby_ext,
85
+ rbs_paths: [rbs_path],
86
+ optimize: false, # Disable optimization for debugging
87
+ verbose: true
88
+ )
89
+
90
+ # Patch to capture LLVM IR
91
+ module Konpeito
92
+ module Codegen
93
+ class LLVMGenerator
94
+ def to_ir
95
+ @mod.to_s
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ puts "Compiling..."
102
+
103
+ # Manual compilation steps to capture IR
104
+ ast = compiler.send(:parse)
105
+ typed_ast = compiler.send(:type_check_ast, ast)
106
+ hir = compiler.send(:generate_hir, typed_ast)
107
+
108
+ puts "\n=== HIR Functions ==="
109
+ hir.functions.each do |func|
110
+ puts "Function: #{func.name}"
111
+ func.body.each do |block|
112
+ puts " Block: #{block.label}"
113
+ block.instructions.each do |inst|
114
+ puts " #{inst.class.name.split('::').last}: #{inst.result_var}"
115
+ end
116
+ puts " Terminator: #{block.terminator.class.name.split('::').last}" if block.terminator
117
+ end
118
+ end
119
+
120
+ llvm_gen = Konpeito::Codegen::LLVMGenerator.new(
121
+ module_name: "test_native",
122
+ monomorphizer: nil
123
+ )
124
+ llvm_gen.generate(hir)
125
+
126
+ puts "\n=== LLVM IR ==="
127
+ puts llvm_gen.to_ir
128
+
129
+ puts "\n=== Compiling to native ==="
130
+ backend = Konpeito::Codegen::CRubyBackend.new(
131
+ llvm_gen,
132
+ output_file: output_path,
133
+ module_name: "test_native"
134
+ )
135
+ backend.generate
136
+ puts "Generated: #{output_path}"
137
+
138
+ puts "\n=== Testing ==="
139
+ require File.expand_path(output_path)
140
+
141
+ puts "\nTest 1: test_alloc"
142
+ result = Object.new.send(:test_alloc, 10)
143
+ puts "test_alloc(10) = #{result}"
144
+ puts "Expected: 10"
145
+ puts result == 10 ? "PASS" : "FAIL"
146
+
147
+ puts "\nTest 2: test_set"
148
+ result = Object.new.send(:test_set, 5)
149
+ expected = 3.14
150
+ puts "test_set(5) = #{result}"
151
+ puts "Expected: #{expected}"
152
+ puts (result - expected).abs < 0.001 ? "PASS" : "FAIL"
153
+
154
+ puts "\nTest 3: test_fill"
155
+ result = Object.new.send(:test_fill, 5)
156
+ # arr[0] = 0 * 1.5 = 0.0
157
+ expected = 0.0
158
+ puts "test_fill(5) = #{result}"
159
+ puts "Expected: #{expected}"
160
+ puts (result - expected).abs < 0.001 ? "PASS" : "FAIL"
161
+
162
+ puts "\nTest 4: test_read_sum"
163
+ result = Object.new.send(:test_read_sum, 5)
164
+ # 1.0 + 1.0 + 1.0 = 3.0
165
+ expected = 3.0
166
+ puts "test_read_sum(5) = #{result}"
167
+ puts "Expected: #{expected}"
168
+ puts (result - expected).abs < 0.001 ? "PASS" : "FAIL"
169
+ result = Object.new.send(:test_alloc, 10)
170
+ puts "test_alloc(10) = #{result}"
171
+ puts "Expected: 10"
172
+ puts result == 10 ? "PASS" : "FAIL"
@@ -0,0 +1,197 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Test for NativeArray[NativeClass] - array of structs
4
+
5
+ $LOAD_PATH.unshift File.expand_path("lib", __dir__)
6
+ require "konpeito"
7
+
8
+ source = <<~RUBY
9
+ def test_create_and_access(n)
10
+ particles = NativeArray.new(n)
11
+
12
+ # Set first particle
13
+ particles[0].x = 1.0
14
+ particles[0].y = 2.0
15
+
16
+ # Set second particle
17
+ particles[1].x = 3.0
18
+ particles[1].y = 4.0
19
+
20
+ # Return sum of all coordinates
21
+ particles[0].x + particles[0].y + particles[1].x + particles[1].y
22
+ end
23
+
24
+ def test_loop_access(n)
25
+ particles = NativeArray.new(n)
26
+
27
+ # Initialize particles
28
+ i = 0
29
+ while i < n
30
+ particles[i].x = i * 1.0
31
+ particles[i].y = i * 2.0
32
+ i = i + 1
33
+ end
34
+
35
+ # Sum all x coordinates
36
+ total = 0.0
37
+ i = 0
38
+ while i < n
39
+ total = total + particles[i].x
40
+ i = i + 1
41
+ end
42
+
43
+ total
44
+ end
45
+
46
+ def test_distance_sum(n)
47
+ particles = NativeArray.new(n)
48
+
49
+ # Place particles in a line
50
+ i = 0
51
+ while i < n
52
+ particles[i].x = i * 10.0
53
+ particles[i].y = 0.0
54
+ i = i + 1
55
+ end
56
+
57
+ # Sum distances between consecutive particles
58
+ total = 0.0
59
+ i = 0
60
+ while i < n - 1
61
+ dx = particles[i + 1].x - particles[i].x
62
+ dy = particles[i + 1].y - particles[i].y
63
+ total = total + dx * dx + dy * dy
64
+ i = i + 1
65
+ end
66
+
67
+ total
68
+ end
69
+ RUBY
70
+
71
+ rbs = <<~RBS
72
+ # @native
73
+ class Particle
74
+ @x: Float
75
+ @y: Float
76
+
77
+ def self.new: () -> Particle
78
+ def x: () -> Float
79
+ def x=: (Float value) -> Float
80
+ def y: () -> Float
81
+ def y=: (Float value) -> Float
82
+ end
83
+
84
+ class Object
85
+ def test_create_and_access: (Integer n) -> Float
86
+ def test_loop_access: (Integer n) -> Float
87
+ def test_distance_sum: (Integer n) -> Float
88
+ end
89
+ RBS
90
+
91
+ require "tempfile"
92
+ require "fileutils"
93
+
94
+ tmp_dir = "tmp"
95
+ FileUtils.mkdir_p(tmp_dir)
96
+
97
+ source_path = File.join(tmp_dir, "test_native_array_class.rb")
98
+ rbs_path = File.join(tmp_dir, "test_native_array_class.rbs")
99
+ output_path = File.join(tmp_dir, "test_native_array_class.bundle")
100
+
101
+ File.write(source_path, source)
102
+ File.write(rbs_path, rbs)
103
+
104
+ compiler = Konpeito::Compiler.new(
105
+ source_file: source_path,
106
+ output_file: output_path,
107
+ format: :cruby_ext,
108
+ rbs_paths: [rbs_path],
109
+ optimize: false,
110
+ verbose: true
111
+ )
112
+
113
+ # Patch to capture LLVM IR
114
+ module Konpeito
115
+ module Codegen
116
+ class LLVMGenerator
117
+ def to_ir
118
+ @mod.to_s
119
+ end
120
+ end
121
+ end
122
+ end
123
+
124
+ puts "Compiling..."
125
+
126
+ # Manual compilation steps to capture IR
127
+ ast = compiler.send(:parse)
128
+ typed_ast = compiler.send(:type_check_ast, ast)
129
+ hir = compiler.send(:generate_hir, typed_ast)
130
+
131
+ puts "\n=== HIR Functions ==="
132
+ hir.functions.each do |func|
133
+ puts "Function: #{func.name}"
134
+ func.body.each do |block|
135
+ puts " Block: #{block.label}"
136
+ block.instructions.each do |inst|
137
+ case inst
138
+ when Konpeito::HIR::NativeArrayAlloc
139
+ puts " NativeArrayAlloc: #{inst.result_var} (element: #{inst.element_type})"
140
+ when Konpeito::HIR::NativeArrayGet
141
+ puts " NativeArrayGet: #{inst.result_var} (element: #{inst.element_type})"
142
+ when Konpeito::HIR::NativeFieldGet
143
+ puts " NativeFieldGet: #{inst.result_var} (field: #{inst.field_name})"
144
+ when Konpeito::HIR::NativeFieldSet
145
+ puts " NativeFieldSet: (field: #{inst.field_name})"
146
+ else
147
+ puts " #{inst.class.name.split('::').last}: #{inst.result_var}"
148
+ end
149
+ end
150
+ puts " Terminator: #{block.terminator.class.name.split('::').last}" if block.terminator
151
+ end
152
+ end
153
+
154
+ llvm_gen = Konpeito::Codegen::LLVMGenerator.new(
155
+ module_name: "test_native_array_class",
156
+ monomorphizer: nil
157
+ )
158
+ llvm_gen.generate(hir)
159
+
160
+ puts "\n=== LLVM IR ==="
161
+ puts llvm_gen.to_ir
162
+
163
+ puts "\n=== Compiling to native ==="
164
+ backend = Konpeito::Codegen::CRubyBackend.new(
165
+ llvm_gen,
166
+ output_file: output_path,
167
+ module_name: "test_native_array_class"
168
+ )
169
+ backend.generate
170
+ puts "Generated: #{output_path}"
171
+
172
+ puts "\n=== Testing ==="
173
+ require File.expand_path(output_path)
174
+
175
+ puts "\nTest 1: test_create_and_access"
176
+ result = Object.new.send(:test_create_and_access, 5)
177
+ expected = 1.0 + 2.0 + 3.0 + 4.0 # 10.0
178
+ puts "test_create_and_access(5) = #{result}"
179
+ puts "Expected: #{expected}"
180
+ puts (result - expected).abs < 0.001 ? "PASS" : "FAIL"
181
+
182
+ puts "\nTest 2: test_loop_access"
183
+ result = Object.new.send(:test_loop_access, 5)
184
+ # Sum of 0*1.0 + 1*1.0 + 2*1.0 + 3*1.0 + 4*1.0 = 0+1+2+3+4 = 10.0
185
+ expected = 10.0
186
+ puts "test_loop_access(5) = #{result}"
187
+ puts "Expected: #{expected}"
188
+ puts (result - expected).abs < 0.001 ? "PASS" : "FAIL"
189
+
190
+ puts "\nTest 3: test_distance_sum"
191
+ result = Object.new.send(:test_distance_sum, 5)
192
+ # Distance squared between consecutive particles at x=0,10,20,30,40
193
+ # Each distance squared = 10*10 = 100, 4 pairs = 400
194
+ expected = 400.0
195
+ puts "test_distance_sum(5) = #{result}"
196
+ puts "Expected: #{expected}"
197
+ puts (result - expected).abs < 0.001 ? "PASS" : "FAIL"
@@ -0,0 +1,151 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Simple test for NativeClass (Point with x, y fields)
4
+
5
+ $LOAD_PATH.unshift File.expand_path("lib", __dir__)
6
+ require "konpeito"
7
+
8
+ source = <<~RUBY
9
+ def test_create
10
+ p = Point.new
11
+ p.x = 3.0
12
+ p.y = 4.0
13
+ p.x
14
+ end
15
+
16
+ def test_distance(x1, y1, x2, y2)
17
+ p1 = Point.new
18
+ p1.x = x1
19
+ p1.y = y1
20
+
21
+ p2 = Point.new
22
+ p2.x = x2
23
+ p2.y = y2
24
+
25
+ dx = p2.x - p1.x
26
+ dy = p2.y - p1.y
27
+ dx * dx + dy * dy
28
+ end
29
+
30
+ def test_sum_coords
31
+ p = Point.new
32
+ p.x = 10.0
33
+ p.y = 20.0
34
+ p.x + p.y
35
+ end
36
+ RUBY
37
+
38
+ rbs = <<~RBS
39
+ # @native
40
+ class Point
41
+ @x: Float
42
+ @y: Float
43
+
44
+ def self.new: () -> Point
45
+ def x: () -> Float
46
+ def x=: (Float value) -> Float
47
+ def y: () -> Float
48
+ def y=: (Float value) -> Float
49
+ end
50
+
51
+ class Object
52
+ def test_create: () -> Float
53
+ def test_distance: (Float x1, Float y1, Float x2, Float y2) -> Float
54
+ def test_sum_coords: () -> Float
55
+ end
56
+ RBS
57
+
58
+ require "tempfile"
59
+ require "fileutils"
60
+
61
+ tmp_dir = "tmp"
62
+ FileUtils.mkdir_p(tmp_dir)
63
+
64
+ source_path = File.join(tmp_dir, "test_native_class.rb")
65
+ rbs_path = File.join(tmp_dir, "test_native_class.rbs")
66
+ output_path = File.join(tmp_dir, "test_native_class.bundle")
67
+
68
+ File.write(source_path, source)
69
+ File.write(rbs_path, rbs)
70
+
71
+ compiler = Konpeito::Compiler.new(
72
+ source_file: source_path,
73
+ output_file: output_path,
74
+ format: :cruby_ext,
75
+ rbs_paths: [rbs_path],
76
+ optimize: false,
77
+ verbose: true
78
+ )
79
+
80
+ # Patch to capture LLVM IR
81
+ module Konpeito
82
+ module Codegen
83
+ class LLVMGenerator
84
+ def to_ir
85
+ @mod.to_s
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+ puts "Compiling..."
92
+
93
+ # Manual compilation steps to capture IR
94
+ ast = compiler.send(:parse)
95
+ typed_ast = compiler.send(:type_check_ast, ast)
96
+ hir = compiler.send(:generate_hir, typed_ast)
97
+
98
+ puts "\n=== HIR Functions ==="
99
+ hir.functions.each do |func|
100
+ puts "Function: #{func.name}"
101
+ func.body.each do |block|
102
+ puts " Block: #{block.label}"
103
+ block.instructions.each do |inst|
104
+ puts " #{inst.class.name.split('::').last}: #{inst.result_var}"
105
+ end
106
+ puts " Terminator: #{block.terminator.class.name.split('::').last}" if block.terminator
107
+ end
108
+ end
109
+
110
+ llvm_gen = Konpeito::Codegen::LLVMGenerator.new(
111
+ module_name: "test_native_class",
112
+ monomorphizer: nil
113
+ )
114
+ llvm_gen.generate(hir)
115
+
116
+ puts "\n=== LLVM IR ==="
117
+ puts llvm_gen.to_ir
118
+
119
+ puts "\n=== Compiling to native ==="
120
+ backend = Konpeito::Codegen::CRubyBackend.new(
121
+ llvm_gen,
122
+ output_file: output_path,
123
+ module_name: "test_native_class"
124
+ )
125
+ backend.generate
126
+ puts "Generated: #{output_path}"
127
+
128
+ puts "\n=== Testing ==="
129
+ require File.expand_path(output_path)
130
+
131
+ puts "\nTest 1: test_create"
132
+ result = Object.new.send(:test_create)
133
+ expected = 3.0
134
+ puts "test_create() = #{result}"
135
+ puts "Expected: #{expected}"
136
+ puts (result - expected).abs < 0.001 ? "PASS" : "FAIL"
137
+
138
+ puts "\nTest 2: test_distance"
139
+ # Distance squared from (0,0) to (3,4) = 9 + 16 = 25
140
+ result = Object.new.send(:test_distance, 0.0, 0.0, 3.0, 4.0)
141
+ expected = 25.0
142
+ puts "test_distance(0, 0, 3, 4) = #{result}"
143
+ puts "Expected: #{expected}"
144
+ puts (result - expected).abs < 0.001 ? "PASS" : "FAIL"
145
+
146
+ puts "\nTest 3: test_sum_coords"
147
+ result = Object.new.send(:test_sum_coords)
148
+ expected = 30.0
149
+ puts "test_sum_coords() = #{result}"
150
+ puts "Expected: #{expected}"
151
+ puts (result - expected).abs < 0.001 ? "PASS" : "FAIL"
@@ -0,0 +1,65 @@
1
+ #!/bin/bash
2
+ # Build the Konpeito ASM tool
3
+ set -e
4
+
5
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
6
+ JAVA="${JAVA_HOME:-/opt/homebrew/opt/openjdk@21}/bin/javac"
7
+ JAR_CMD="${JAVA_HOME:-/opt/homebrew/opt/openjdk@21}/bin/jar"
8
+ ASM_JAR="$SCRIPT_DIR/lib/asm-9.7.1.jar"
9
+ BUILD_DIR="$SCRIPT_DIR/build"
10
+ OUT_JAR="$SCRIPT_DIR/konpeito-asm.jar"
11
+
12
+ # Use javac/jar from PATH if JAVA_HOME not set and homebrew path doesn't exist
13
+ if [ ! -f "$JAVA" ]; then
14
+ JAVA="javac"
15
+ JAR_CMD="jar"
16
+ fi
17
+
18
+ echo "Building konpeito-asm tool..."
19
+
20
+ # Clean and create build directory
21
+ rm -rf "$BUILD_DIR"
22
+ mkdir -p "$BUILD_DIR/com/konpeito/asm"
23
+ mkdir -p "$BUILD_DIR/konpeito/runtime"
24
+
25
+ # Compile ASM tool and runtime classes
26
+ "$JAVA" -cp "$ASM_JAR" \
27
+ -Xlint:none \
28
+ -nowarn \
29
+ -d "$BUILD_DIR" \
30
+ "$SCRIPT_DIR/src/KonpeitoAssembler.java" \
31
+ "$SCRIPT_DIR/src/ClassIntrospector.java" \
32
+ "$SCRIPT_DIR/src/konpeito/runtime/KArray.java" \
33
+ "$SCRIPT_DIR/src/konpeito/runtime/KHash.java" \
34
+ "$SCRIPT_DIR/src/konpeito/runtime/KThread.java" \
35
+ "$SCRIPT_DIR/src/konpeito/runtime/KConditionVariable.java" \
36
+ "$SCRIPT_DIR/src/konpeito/runtime/KSizedQueue.java" \
37
+ "$SCRIPT_DIR/src/konpeito/runtime/KJSON.java" \
38
+ "$SCRIPT_DIR/src/konpeito/runtime/KCrypto.java" \
39
+ "$SCRIPT_DIR/src/konpeito/runtime/KCompression.java" \
40
+ "$SCRIPT_DIR/src/konpeito/runtime/KHTTP.java" \
41
+ "$SCRIPT_DIR/src/konpeito/runtime/KTime.java" \
42
+ "$SCRIPT_DIR/src/konpeito/runtime/KFile.java" \
43
+ "$SCRIPT_DIR/src/konpeito/runtime/KMath.java" \
44
+ "$SCRIPT_DIR/src/konpeito/runtime/KRactor.java" \
45
+ "$SCRIPT_DIR/src/konpeito/runtime/KRactorPort.java" \
46
+ "$SCRIPT_DIR/src/konpeito/runtime/RubyDispatch.java"
47
+
48
+ # Copy runtime classes to a separate directory for JAR bundling
49
+ RUNTIME_DIR="$SCRIPT_DIR/runtime-classes"
50
+ rm -rf "$RUNTIME_DIR"
51
+ mkdir -p "$RUNTIME_DIR/konpeito/runtime"
52
+ cp "$BUILD_DIR/konpeito/runtime/"*.class "$RUNTIME_DIR/konpeito/runtime/"
53
+
54
+ # Create manifest
55
+ echo "Main-Class: com.konpeito.asm.KonpeitoAssembler" > "$BUILD_DIR/MANIFEST.MF"
56
+
57
+ # Extract ASM classes into build dir (to create a fat jar)
58
+ cd "$BUILD_DIR"
59
+ "$JAR_CMD" xf "$ASM_JAR"
60
+ rm -rf META-INF/MANIFEST.MF 2>/dev/null || true
61
+
62
+ # Create fat jar
63
+ "$JAR_CMD" cfm "$OUT_JAR" "$BUILD_DIR/MANIFEST.MF" -C "$BUILD_DIR" .
64
+
65
+ echo "Built: $OUT_JAR"