konpeito 0.1.3 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b559f8a6de1d213b466939fb5fbde0a797a6808a7ce664f28d55ed0496696dde
4
- data.tar.gz: 6809762994527a50fcf96c1644f24cde5f2324b668e1dc646bf32077ea679af0
3
+ metadata.gz: 85de87c8abf1bbf3ecaf6303ba4fd875f16016099a38734c55c108f123fa4086
4
+ data.tar.gz: 843f4b6d722d68526d031734c035c9126c520d9869a2488259dbf39ce1eade84
5
5
  SHA512:
6
- metadata.gz: c8c43cca2f5e3812ee706a9b2b2c833ad9036d98e997b4481ce701d0edfa98b03a967f935c2b6aec7b8b2dfb19d27225b0e7a6f5e091ecc993a0786cec3cc2d7
7
- data.tar.gz: 27acd8361e403febf7fd4e45b5ab832f1c767deedf329b8e164c8b62f7f1aa127c0ea75eeccaee7d5ef6767ea7f45c787baa526461bfa6dbf6ba034f90815bff
6
+ metadata.gz: eaf22b341a9135b2d81fcda350790330a78f2da9255771833676047086fbcd861919295f8cf7f4967f380cc62c8ea882499cd6b89a863b86bbd1c53e6e6f2b9e
7
+ data.tar.gz: ab456db3432eca45ff8b658b80c07d38cdbec33c1e4cd6e379d59dbb0cf8f3384b6f715b3bac61f7d120dfb25e479fe86b65dc4c44ad5c7e86ab18703ff6e6a9
data/CHANGELOG.md CHANGED
@@ -5,6 +5,19 @@ All notable changes to Konpeito will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.2.0] - 2026-02-19
9
+
10
+ ### Added
11
+ - Inliner: keyword argument mapping for correct inlining of functions with keyword params
12
+ - Inliner: ProcNew/BlockDef deep cloning with proper captured variable renaming
13
+ - Vendor setup script (`scripts/setup_vendor.sh`) to download yyjson source files
14
+
15
+ ### Fixed
16
+ - HIR builder: save/restore `@current_block` in NativeHashEach to emit into correct basic block
17
+ - Inliner: ProcCall handler for proc_value and args renaming during inlining
18
+ - JSON stdlib: add tracked `yyjson_wrapper.c` providing non-inline wrappers for LLVM-generated code (fixes SEGV in `parse_as`/`parse_array_as` tests)
19
+ - CRuby backend: reference yyjson wrapper from tracked source location instead of vendor directory
20
+
8
21
  ## [0.1.3] - 2026-02-18
9
22
 
10
23
  ### Fixed
@@ -108,6 +121,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
108
121
  - `%a{extern}` - external C struct wrappers
109
122
  - `%a{simd}` - SIMD vectorization
110
123
 
124
+ [0.2.0]: https://github.com/i2y/konpeito/compare/v0.1.3...v0.2.0
111
125
  [0.1.3]: https://github.com/i2y/konpeito/compare/v0.1.2...v0.1.3
112
126
  [0.1.2]: https://github.com/i2y/konpeito/compare/v0.1.1...v0.1.2
113
127
  [0.1.1]: https://github.com/i2y/konpeito/compare/v0.1.0...v0.1.1
@@ -893,7 +893,10 @@ module Konpeito
893
893
  yyjson_dir = File.expand_path("../../../vendor/yyjson", __dir__)
894
894
  yyjson_c = File.join(yyjson_dir, "yyjson.c")
895
895
  yyjson_obj = File.join(yyjson_dir, "yyjson.o")
896
- wrapper_c = File.join(yyjson_dir, "yyjson_wrapper.c")
896
+
897
+ # Wrapper source is tracked in repo alongside JSON stdlib
898
+ json_stdlib_dir = File.expand_path("../stdlib/json", __dir__)
899
+ wrapper_c = File.join(json_stdlib_dir, "yyjson_wrapper.c")
897
900
  wrapper_obj = File.join(yyjson_dir, "yyjson_wrapper.o")
898
901
 
899
902
  return [] unless File.exist?(yyjson_c) && File.exist?(wrapper_c)
@@ -906,7 +909,7 @@ module Konpeito
906
909
  system(*cmd) or return []
907
910
  end
908
911
 
909
- # Compile wrapper
912
+ # Compile wrapper (needs yyjson.h from vendor dir)
910
913
  unless File.exist?(wrapper_obj) && File.mtime(wrapper_obj) > File.mtime(wrapper_c)
911
914
  cmd = [cc, "-c", "-O3", "-fPIC", "-I#{yyjson_dir}", "-o", wrapper_obj, wrapper_c]
912
915
  system(*cmd) or return []
@@ -178,6 +178,17 @@ module Konpeito
178
178
  param_map[param.name] = call_inst.args[i]
179
179
  end
180
180
  end
181
+ # Also map keyword arguments by name
182
+ if call_inst.respond_to?(:keyword_args) && call_inst.has_keyword_args?
183
+ call_inst.keyword_args.each do |kw_name, kw_value|
184
+ # Find the callee param with matching name
185
+ callee.params.each do |param|
186
+ if param.name.to_s == kw_name.to_s
187
+ param_map[param.name] = kw_value
188
+ end
189
+ end
190
+ end
191
+ end
181
192
 
182
193
  # Clone and transform instructions from callee
183
194
  result_instructions = []
@@ -438,6 +449,17 @@ module Konpeito
438
449
  new_args = inst.args.map { |a| transform_value(a, prefix, param_map) }
439
450
  HIR::SuperCall.new(args: new_args, type: inst.type, result_var: new_result)
440
451
 
452
+ when HIR::ProcNew
453
+ new_result = inst.result_var ? prefix + inst.result_var : nil
454
+ new_block_def = clone_block_def(inst.block_def, prefix, param_map)
455
+ HIR::ProcNew.new(block_def: new_block_def, result_var: new_result)
456
+
457
+ when HIR::ProcCall
458
+ new_result = inst.result_var ? prefix + inst.result_var : nil
459
+ new_proc = transform_value(inst.proc_value, prefix, param_map)
460
+ new_args = inst.args.map { |a| transform_value(a, prefix, param_map) }
461
+ HIR::ProcCall.new(proc_value: new_proc, args: new_args, type: inst.type, result_var: new_result)
462
+
441
463
  else
442
464
  # For other instructions, just return as-is with renamed result
443
465
  inst
@@ -481,6 +503,90 @@ module Konpeito
481
503
  value
482
504
  end
483
505
  end
506
+
507
+ # Deep-clone a BlockDef, renaming captured (non-block-local) variables.
508
+ # Block parameters are NOT renamed (they are local to the closure).
509
+ def clone_block_def(block_def, prefix, param_map)
510
+ return block_def unless block_def
511
+
512
+ block_param_names = Set.new(block_def.params.map { |p| p.name.to_s })
513
+
514
+ new_body = block_def.body.map do |bb|
515
+ if bb.respond_to?(:instructions)
516
+ new_bb = HIR::BasicBlock.new(label: bb.label)
517
+ bb.instructions.each do |bi|
518
+ new_inst = clone_block_instruction(bi, prefix, param_map, block_param_names)
519
+ new_bb.add_instruction(new_inst) if new_inst
520
+ end
521
+ new_bb.set_terminator(bb.terminator) if bb.terminator
522
+ new_bb
523
+ else
524
+ clone_block_instruction(bb, prefix, param_map, block_param_names)
525
+ end
526
+ end
527
+
528
+ HIR::BlockDef.new(
529
+ params: block_def.params,
530
+ body: new_body,
531
+ captures: block_def.captures,
532
+ is_lambda: block_def.is_lambda
533
+ )
534
+ end
535
+
536
+ # Clone a single instruction inside a block body, renaming captured vars.
537
+ def clone_block_instruction(inst, prefix, param_map, block_param_names)
538
+ case inst
539
+ when HIR::LoadLocal
540
+ var_name = inst.var.name.to_s
541
+ if block_param_names.include?(var_name)
542
+ # Block-local parameter: don't rename
543
+ inst
544
+ else
545
+ # Captured variable: rename with prefix
546
+ new_var = HIR::LocalVar.new(
547
+ name: prefix + var_name,
548
+ type: inst.var.type
549
+ )
550
+ HIR::LoadLocal.new(var: new_var, type: inst.type, result_var: inst.result_var)
551
+ end
552
+ when HIR::StoreLocal
553
+ var_name = inst.var.name.to_s
554
+ new_value = clone_block_value(inst.value, prefix, param_map, block_param_names)
555
+ if block_param_names.include?(var_name)
556
+ HIR::StoreLocal.new(var: inst.var, value: new_value, type: inst.type)
557
+ else
558
+ new_var = HIR::LocalVar.new(name: prefix + var_name, type: inst.var.type)
559
+ HIR::StoreLocal.new(var: new_var, value: new_value, type: inst.type)
560
+ end
561
+ when HIR::Call
562
+ new_receiver = clone_block_value(inst.receiver, prefix, param_map, block_param_names)
563
+ new_args = inst.args.map { |a| clone_block_value(a, prefix, param_map, block_param_names) }
564
+ HIR::Call.new(
565
+ receiver: new_receiver, method_name: inst.method_name,
566
+ args: new_args, block: inst.block,
567
+ type: inst.type, result_var: inst.result_var
568
+ )
569
+ else
570
+ # Other instructions: return as-is (literals, etc.)
571
+ inst
572
+ end
573
+ end
574
+
575
+ # Clone a value reference inside a block, renaming captured variables.
576
+ def clone_block_value(value, prefix, param_map, block_param_names)
577
+ case value
578
+ when HIR::LoadLocal
579
+ var_name = value.var.name.to_s
580
+ if block_param_names.include?(var_name)
581
+ value
582
+ else
583
+ new_var = HIR::LocalVar.new(name: prefix + var_name, type: value.var.type)
584
+ HIR::LoadLocal.new(var: new_var, type: value.type, result_var: nil)
585
+ end
586
+ else
587
+ value
588
+ end
589
+ end
484
590
  end
485
591
  end
486
592
  end
@@ -4038,13 +4038,15 @@ module Konpeito
4038
4038
  key_var = param_names[0] || "k"
4039
4039
  value_var = param_names[1] || "v"
4040
4040
 
4041
- # Build block body
4041
+ # Build block body — save/restore @current_block so NativeHashEach
4042
+ # is emitted into the original block, not the loop body block
4043
+ saved_block = @current_block
4042
4044
  body_child = block_child.children.find { |c| c.node_type == :statements }
4043
4045
  block_body = []
4044
4046
 
4045
4047
  if body_child
4046
4048
  # Create a new basic block for the iteration body
4047
- loop_bb = BasicBlock.new(label: new_label("hash_each_body"))
4049
+ loop_bb = BasicBlock.new(label: "hash_each_body_#{@block_counter}")
4048
4050
  @current_block = loop_bb
4049
4051
  block_body << loop_bb
4050
4052
 
@@ -4052,6 +4054,7 @@ module Konpeito
4052
4054
  visit(stmt)
4053
4055
  end
4054
4056
  end
4057
+ @current_block = saved_block
4055
4058
 
4056
4059
  result_var = new_temp_var
4057
4060
  inst = NativeHashEach.new(
@@ -0,0 +1,60 @@
1
+ /*
2
+ * yyjson_wrapper.c - Non-inline wrappers for yyjson functions
3
+ *
4
+ * yyjson uses static inline functions in its header. When linking with
5
+ * LLVM-generated code, we need non-inline versions that can be called
6
+ * via external symbol references. This file provides those wrappers.
7
+ */
8
+
9
+ #include "yyjson.h"
10
+ #include <stddef.h>
11
+ #include <stdint.h>
12
+ #include <stdbool.h>
13
+
14
+ yyjson_doc *konpeito_yyjson_read(const char *dat, size_t len, yyjson_read_flag flg) {
15
+ return yyjson_read(dat, len, flg);
16
+ }
17
+
18
+ yyjson_val *konpeito_yyjson_doc_get_root(yyjson_doc *doc) {
19
+ return yyjson_doc_get_root(doc);
20
+ }
21
+
22
+ void konpeito_yyjson_doc_free(yyjson_doc *doc) {
23
+ yyjson_doc_free(doc);
24
+ }
25
+
26
+ yyjson_val *konpeito_yyjson_obj_get(yyjson_val *obj, const char *key) {
27
+ return yyjson_obj_get(obj, key);
28
+ }
29
+
30
+ int64_t konpeito_yyjson_get_sint(yyjson_val *val) {
31
+ return yyjson_get_sint(val);
32
+ }
33
+
34
+ uint64_t konpeito_yyjson_get_uint(yyjson_val *val) {
35
+ return yyjson_get_uint(val);
36
+ }
37
+
38
+ double konpeito_yyjson_get_real(yyjson_val *val) {
39
+ return yyjson_get_real(val);
40
+ }
41
+
42
+ bool konpeito_yyjson_get_bool(yyjson_val *val) {
43
+ return yyjson_get_bool(val);
44
+ }
45
+
46
+ const char *konpeito_yyjson_get_str(yyjson_val *val) {
47
+ return yyjson_get_str(val);
48
+ }
49
+
50
+ size_t konpeito_yyjson_get_len(yyjson_val *val) {
51
+ return yyjson_get_len(val);
52
+ }
53
+
54
+ size_t konpeito_yyjson_arr_size(yyjson_val *arr) {
55
+ return yyjson_arr_size(arr);
56
+ }
57
+
58
+ yyjson_val *konpeito_yyjson_arr_get(yyjson_val *arr, size_t idx) {
59
+ return yyjson_arr_get(arr, idx);
60
+ }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Konpeito
4
- VERSION = "0.1.3"
4
+ VERSION = "0.2.0"
5
5
  end
@@ -0,0 +1,33 @@
1
+ #!/bin/bash
2
+ # Setup vendored dependencies for Konpeito
3
+ #
4
+ # Downloads yyjson (fast JSON library) source files.
5
+ # Run this after cloning the repository:
6
+ # bash scripts/setup_vendor.sh
7
+
8
+ set -e
9
+
10
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
11
+ PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
12
+ YYJSON_DIR="$PROJECT_ROOT/vendor/yyjson"
13
+
14
+ YYJSON_VERSION="0.10.0"
15
+ YYJSON_BASE_URL="https://raw.githubusercontent.com/ibireme/yyjson/${YYJSON_VERSION}/src"
16
+
17
+ echo "Setting up vendored dependencies..."
18
+
19
+ # --- yyjson ---
20
+ mkdir -p "$YYJSON_DIR"
21
+
22
+ if [ -f "$YYJSON_DIR/yyjson.h" ] && [ -f "$YYJSON_DIR/yyjson.c" ]; then
23
+ echo " yyjson: already present (skipping download)"
24
+ else
25
+ echo " yyjson: downloading v${YYJSON_VERSION}..."
26
+ curl -sL "${YYJSON_BASE_URL}/yyjson.h" -o "$YYJSON_DIR/yyjson.h"
27
+ curl -sL "${YYJSON_BASE_URL}/yyjson.c" -o "$YYJSON_DIR/yyjson.c"
28
+ echo " yyjson: downloaded yyjson.h and yyjson.c"
29
+ fi
30
+
31
+ echo ""
32
+ echo "Done. Vendor dependencies are ready."
33
+ echo " yyjson: $YYJSON_DIR"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: konpeito
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yasushi Itoh
@@ -131,6 +131,7 @@ files:
131
131
  - lib/konpeito/stdlib/json/json.rb
132
132
  - lib/konpeito/stdlib/json/json.rbs
133
133
  - lib/konpeito/stdlib/json/json_native.c
134
+ - lib/konpeito/stdlib/json/yyjson_wrapper.c
134
135
  - lib/konpeito/stdlib/ui/extconf.rb
135
136
  - lib/konpeito/stdlib/ui/konpeito_ui_native.cpp
136
137
  - lib/konpeito/stdlib/ui/konpeito_ui_native.h
@@ -202,6 +203,7 @@ files:
202
203
  - lib/konpeito/ui/widgets/text.rb
203
204
  - lib/konpeito/ui/widgets/tree.rb
204
205
  - lib/konpeito/version.rb
206
+ - scripts/setup_vendor.sh
205
207
  - test_native_array.rb
206
208
  - test_native_array_class.rb
207
209
  - test_native_class.rb