konpeito 0.2.4 → 0.3.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +645 -0
- data/CHANGELOG.md +37 -0
- data/Justfile +107 -0
- data/README.md +143 -43
- data/konpeito.gemspec +3 -2
- data/lib/konpeito/cli/build_command.rb +21 -3
- data/lib/konpeito/cli/completion_command.rb +298 -0
- data/lib/konpeito/cli/deps_command.rb +129 -21
- data/lib/konpeito/cli/fmt_command.rb +24 -132
- data/lib/konpeito/cli/run_command.rb +29 -3
- data/lib/konpeito/cli.rb +45 -14
- data/lib/konpeito/codegen/builtin_methods.rb +16 -0
- data/lib/konpeito/codegen/cruby_backend.rb +76 -6
- data/lib/konpeito/codegen/jvm_generator.rb +100 -9
- data/lib/konpeito/codegen/llvm_generator.rb +907 -195
- data/lib/konpeito/dependency_resolver.rb +32 -9
- data/lib/konpeito/hir/builder.rb +369 -57
- data/lib/konpeito/hir/nodes.rb +25 -5
- data/lib/konpeito/type_checker/rbs_loader.rb +3 -2
- data/lib/konpeito/ui/app.rb +1 -1
- data/lib/konpeito/version.rb +1 -1
- data/lib/konpeito.rb +0 -7
- data/tools/konpeito-asm/src/konpeito/runtime/RubyDispatch.java +32 -0
- metadata +6 -23
- data/lib/konpeito/cli/lsp_command.rb +0 -40
- data/lib/konpeito/formatter/formatter.rb +0 -1214
- data/lib/konpeito/lsp/document_manager.rb +0 -820
- data/lib/konpeito/lsp/server.rb +0 -183
- data/lib/konpeito/lsp/transport.rb +0 -38
- data/test_native_array.rb +0 -172
- data/test_native_array_class.rb +0 -197
- data/test_native_class.rb +0 -151
data/lib/konpeito/lsp/server.rb
DELETED
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "transport"
|
|
4
|
-
require_relative "document_manager"
|
|
5
|
-
|
|
6
|
-
module Konpeito
|
|
7
|
-
module LSP
|
|
8
|
-
# Main LSP server that handles client requests
|
|
9
|
-
class Server
|
|
10
|
-
attr_reader :transport, :document_manager
|
|
11
|
-
|
|
12
|
-
def initialize(input: $stdin, output: $stdout)
|
|
13
|
-
@transport = Transport.new(input: input, output: output)
|
|
14
|
-
@document_manager = DocumentManager.new(@transport)
|
|
15
|
-
@running = false
|
|
16
|
-
@initialized = false
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
# Start the LSP server main loop
|
|
20
|
-
def start
|
|
21
|
-
@running = true
|
|
22
|
-
while @running
|
|
23
|
-
request = @transport.read
|
|
24
|
-
break unless request
|
|
25
|
-
|
|
26
|
-
response = handle_request(request)
|
|
27
|
-
@transport.write(response) if response
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
# Stop the server
|
|
32
|
-
def stop
|
|
33
|
-
@running = false
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# Handle a single request (exposed for testing)
|
|
37
|
-
# @param request [Hash] The LSP request
|
|
38
|
-
# @return [Hash, nil] The response or nil for notifications
|
|
39
|
-
def handle_request(request)
|
|
40
|
-
method = request[:method]
|
|
41
|
-
id = request[:id]
|
|
42
|
-
params = request[:params] || {}
|
|
43
|
-
|
|
44
|
-
result = case method
|
|
45
|
-
when "initialize"
|
|
46
|
-
handle_initialize(params)
|
|
47
|
-
when "initialized"
|
|
48
|
-
# Notification, no response needed
|
|
49
|
-
nil
|
|
50
|
-
when "shutdown"
|
|
51
|
-
handle_shutdown
|
|
52
|
-
when "exit"
|
|
53
|
-
@running = false
|
|
54
|
-
nil
|
|
55
|
-
when "textDocument/didOpen"
|
|
56
|
-
handle_did_open(params)
|
|
57
|
-
when "textDocument/didChange"
|
|
58
|
-
handle_did_change(params)
|
|
59
|
-
when "textDocument/didClose"
|
|
60
|
-
handle_did_close(params)
|
|
61
|
-
when "textDocument/hover"
|
|
62
|
-
handle_hover(params)
|
|
63
|
-
when "textDocument/completion"
|
|
64
|
-
handle_completion(params)
|
|
65
|
-
when "textDocument/definition"
|
|
66
|
-
handle_definition(params)
|
|
67
|
-
when "textDocument/references"
|
|
68
|
-
handle_references(params)
|
|
69
|
-
when "textDocument/rename"
|
|
70
|
-
handle_rename(params)
|
|
71
|
-
when "textDocument/prepareRename"
|
|
72
|
-
handle_prepare_rename(params)
|
|
73
|
-
else
|
|
74
|
-
# Unknown method
|
|
75
|
-
if id
|
|
76
|
-
{ error: { code: -32601, message: "Method not found: #{method}" } }
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
# Build response for requests (not notifications)
|
|
81
|
-
if id && result != :notification
|
|
82
|
-
{ jsonrpc: "2.0", id: id, result: result }
|
|
83
|
-
else
|
|
84
|
-
nil
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
private
|
|
89
|
-
|
|
90
|
-
def handle_initialize(params)
|
|
91
|
-
@initialized = true
|
|
92
|
-
|
|
93
|
-
{
|
|
94
|
-
capabilities: {
|
|
95
|
-
textDocumentSync: {
|
|
96
|
-
openClose: true,
|
|
97
|
-
change: 1 # Full content sync
|
|
98
|
-
},
|
|
99
|
-
hoverProvider: true,
|
|
100
|
-
completionProvider: {
|
|
101
|
-
triggerCharacters: ["."],
|
|
102
|
-
resolveProvider: false
|
|
103
|
-
},
|
|
104
|
-
definitionProvider: true,
|
|
105
|
-
referencesProvider: true,
|
|
106
|
-
renameProvider: {
|
|
107
|
-
prepareProvider: true
|
|
108
|
-
}
|
|
109
|
-
},
|
|
110
|
-
serverInfo: {
|
|
111
|
-
name: "konpeito-lsp",
|
|
112
|
-
version: Konpeito::VERSION
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
def handle_shutdown
|
|
118
|
-
@initialized = false
|
|
119
|
-
nil
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
def handle_did_open(params)
|
|
123
|
-
uri = params.dig(:textDocument, :uri)
|
|
124
|
-
text = params.dig(:textDocument, :text)
|
|
125
|
-
@document_manager.open(uri, text)
|
|
126
|
-
:notification
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
def handle_did_change(params)
|
|
130
|
-
uri = params.dig(:textDocument, :uri)
|
|
131
|
-
# We use full sync, so first contentChanges has full text
|
|
132
|
-
changes = params[:contentChanges]
|
|
133
|
-
text = changes&.first&.dig(:text)
|
|
134
|
-
@document_manager.change(uri, text) if text
|
|
135
|
-
:notification
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
def handle_did_close(params)
|
|
139
|
-
uri = params.dig(:textDocument, :uri)
|
|
140
|
-
@document_manager.close(uri)
|
|
141
|
-
:notification
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
def handle_hover(params)
|
|
145
|
-
uri = params.dig(:textDocument, :uri)
|
|
146
|
-
position = params[:position]
|
|
147
|
-
@document_manager.hover(uri, position)
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
def handle_completion(params)
|
|
151
|
-
uri = params.dig(:textDocument, :uri)
|
|
152
|
-
position = params[:position]
|
|
153
|
-
@document_manager.completion(uri, position)
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
def handle_definition(params)
|
|
157
|
-
uri = params.dig(:textDocument, :uri)
|
|
158
|
-
position = params[:position]
|
|
159
|
-
@document_manager.definition(uri, position)
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
def handle_references(params)
|
|
163
|
-
uri = params.dig(:textDocument, :uri)
|
|
164
|
-
position = params[:position]
|
|
165
|
-
include_declaration = params.dig(:context, :includeDeclaration) != false
|
|
166
|
-
@document_manager.references(uri, position, include_declaration: include_declaration)
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
def handle_rename(params)
|
|
170
|
-
uri = params.dig(:textDocument, :uri)
|
|
171
|
-
position = params[:position]
|
|
172
|
-
new_name = params[:newName]
|
|
173
|
-
@document_manager.rename(uri, position, new_name)
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
def handle_prepare_rename(params)
|
|
177
|
-
uri = params.dig(:textDocument, :uri)
|
|
178
|
-
position = params[:position]
|
|
179
|
-
@document_manager.prepare_rename(uri, position)
|
|
180
|
-
end
|
|
181
|
-
end
|
|
182
|
-
end
|
|
183
|
-
end
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "language_server-protocol"
|
|
4
|
-
|
|
5
|
-
module Konpeito
|
|
6
|
-
module LSP
|
|
7
|
-
# Handles LSP JSON-RPC communication over stdio
|
|
8
|
-
class Transport
|
|
9
|
-
def initialize(input: $stdin, output: $stdout)
|
|
10
|
-
@reader = LanguageServer::Protocol::Transport::Io::Reader.new(input)
|
|
11
|
-
@writer = LanguageServer::Protocol::Transport::Io::Writer.new(output)
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
# Read next request/notification from client
|
|
15
|
-
# @return [Hash, nil] The request object or nil if EOF
|
|
16
|
-
def read
|
|
17
|
-
@reader.read
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
# Write response to client
|
|
21
|
-
# @param response [Hash] The response object
|
|
22
|
-
def write(response)
|
|
23
|
-
@writer.write(response)
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
# Send notification to client (no response expected)
|
|
27
|
-
# @param method [String] The notification method
|
|
28
|
-
# @param params [Hash] The notification parameters
|
|
29
|
-
def notify(method, params)
|
|
30
|
-
@writer.write({
|
|
31
|
-
jsonrpc: "2.0",
|
|
32
|
-
method: method,
|
|
33
|
-
params: params
|
|
34
|
-
})
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
data/test_native_array.rb
DELETED
|
@@ -1,172 +0,0 @@
|
|
|
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"
|
data/test_native_array_class.rb
DELETED
|
@@ -1,197 +0,0 @@
|
|
|
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"
|