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.
- checksums.yaml +7 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +75 -0
- data/CONTRIBUTING.md +123 -0
- data/LICENSE +21 -0
- data/README.md +257 -0
- data/Rakefile +11 -0
- data/bin/konpeito +6 -0
- data/konpeito.gemspec +43 -0
- data/lib/konpeito/ast/typed_ast.rb +620 -0
- data/lib/konpeito/ast/visitor.rb +78 -0
- data/lib/konpeito/cache/cache_manager.rb +230 -0
- data/lib/konpeito/cache/dependency_graph.rb +192 -0
- data/lib/konpeito/cache.rb +8 -0
- data/lib/konpeito/cli/base_command.rb +187 -0
- data/lib/konpeito/cli/build_command.rb +220 -0
- data/lib/konpeito/cli/check_command.rb +104 -0
- data/lib/konpeito/cli/config.rb +231 -0
- data/lib/konpeito/cli/deps_command.rb +128 -0
- data/lib/konpeito/cli/doctor_command.rb +340 -0
- data/lib/konpeito/cli/fmt_command.rb +199 -0
- data/lib/konpeito/cli/init_command.rb +312 -0
- data/lib/konpeito/cli/lsp_command.rb +40 -0
- data/lib/konpeito/cli/run_command.rb +150 -0
- data/lib/konpeito/cli/test_command.rb +248 -0
- data/lib/konpeito/cli/watch_command.rb +212 -0
- data/lib/konpeito/cli.rb +301 -0
- data/lib/konpeito/codegen/builtin_methods.rb +229 -0
- data/lib/konpeito/codegen/cruby_backend.rb +1090 -0
- data/lib/konpeito/codegen/debug_info.rb +352 -0
- data/lib/konpeito/codegen/inliner.rb +486 -0
- data/lib/konpeito/codegen/jvm_backend.rb +197 -0
- data/lib/konpeito/codegen/jvm_generator.rb +13412 -0
- data/lib/konpeito/codegen/llvm_generator.rb +13191 -0
- data/lib/konpeito/codegen/loop_optimizer.rb +363 -0
- data/lib/konpeito/codegen/monomorphizer.rb +359 -0
- data/lib/konpeito/codegen/profile_runtime.c +341 -0
- data/lib/konpeito/codegen/profiler.rb +99 -0
- data/lib/konpeito/compiler.rb +592 -0
- data/lib/konpeito/dependency_resolver.rb +296 -0
- data/lib/konpeito/diagnostics/collector.rb +127 -0
- data/lib/konpeito/diagnostics/diagnostic.rb +237 -0
- data/lib/konpeito/diagnostics/renderer.rb +144 -0
- data/lib/konpeito/formatter/formatter.rb +1214 -0
- data/lib/konpeito/hir/builder.rb +7167 -0
- data/lib/konpeito/hir/nodes.rb +2465 -0
- data/lib/konpeito/lsp/document_manager.rb +820 -0
- data/lib/konpeito/lsp/server.rb +183 -0
- data/lib/konpeito/lsp/transport.rb +38 -0
- data/lib/konpeito/parser/prism_adapter.rb +65 -0
- data/lib/konpeito/platform.rb +103 -0
- data/lib/konpeito/profile/report.rb +136 -0
- data/lib/konpeito/rbs_inline/preprocessor.rb +199 -0
- data/lib/konpeito/stdlib/compression/compression.rb +72 -0
- data/lib/konpeito/stdlib/compression/compression.rbs +60 -0
- data/lib/konpeito/stdlib/compression/compression_native.c +415 -0
- data/lib/konpeito/stdlib/compression/extconf.rb +19 -0
- data/lib/konpeito/stdlib/crypto/crypto.rb +85 -0
- data/lib/konpeito/stdlib/crypto/crypto.rbs +74 -0
- data/lib/konpeito/stdlib/crypto/crypto_native.c +312 -0
- data/lib/konpeito/stdlib/crypto/extconf.rb +40 -0
- data/lib/konpeito/stdlib/http/extconf.rb +19 -0
- data/lib/konpeito/stdlib/http/http.rb +125 -0
- data/lib/konpeito/stdlib/http/http.rbs +57 -0
- data/lib/konpeito/stdlib/http/http_native.c +440 -0
- data/lib/konpeito/stdlib/json/extconf.rb +17 -0
- data/lib/konpeito/stdlib/json/json.rb +44 -0
- data/lib/konpeito/stdlib/json/json.rbs +33 -0
- data/lib/konpeito/stdlib/json/json_native.c +286 -0
- data/lib/konpeito/stdlib/ui/extconf.rb +216 -0
- data/lib/konpeito/stdlib/ui/konpeito_ui_native.cpp +1625 -0
- data/lib/konpeito/stdlib/ui/konpeito_ui_native.h +162 -0
- data/lib/konpeito/stdlib/ui/ui.rb +318 -0
- data/lib/konpeito/stdlib/ui/ui.rbs +247 -0
- data/lib/konpeito/type_checker/annotation_parser.rb +67 -0
- data/lib/konpeito/type_checker/hm_inferrer.rb +2565 -0
- data/lib/konpeito/type_checker/inferrer.rb +565 -0
- data/lib/konpeito/type_checker/rbs_loader.rb +1621 -0
- data/lib/konpeito/type_checker/type_resolver.rb +276 -0
- data/lib/konpeito/type_checker/types.rb +1434 -0
- data/lib/konpeito/type_checker/unification.rb +323 -0
- data/lib/konpeito/ui/animation/animated_state.rb +80 -0
- data/lib/konpeito/ui/animation/easing.rb +59 -0
- data/lib/konpeito/ui/animation/value_tween.rb +66 -0
- data/lib/konpeito/ui/app.rb +379 -0
- data/lib/konpeito/ui/box.rb +38 -0
- data/lib/konpeito/ui/castella.rb +70 -0
- data/lib/konpeito/ui/castella_native.rb +76 -0
- data/lib/konpeito/ui/chart/area_chart.rb +305 -0
- data/lib/konpeito/ui/chart/bar_chart.rb +288 -0
- data/lib/konpeito/ui/chart/base_chart.rb +210 -0
- data/lib/konpeito/ui/chart/chart_helpers.rb +79 -0
- data/lib/konpeito/ui/chart/gauge_chart.rb +171 -0
- data/lib/konpeito/ui/chart/heatmap_chart.rb +222 -0
- data/lib/konpeito/ui/chart/line_chart.rb +289 -0
- data/lib/konpeito/ui/chart/pie_chart.rb +219 -0
- data/lib/konpeito/ui/chart/scales.rb +77 -0
- data/lib/konpeito/ui/chart/scatter_chart.rb +303 -0
- data/lib/konpeito/ui/chart/stacked_bar_chart.rb +276 -0
- data/lib/konpeito/ui/column.rb +271 -0
- data/lib/konpeito/ui/core.rb +2199 -0
- data/lib/konpeito/ui/dsl.rb +443 -0
- data/lib/konpeito/ui/frame.rb +171 -0
- data/lib/konpeito/ui/frame_native.rb +494 -0
- data/lib/konpeito/ui/markdown/ast.rb +124 -0
- data/lib/konpeito/ui/markdown/mermaid/layout.rb +387 -0
- data/lib/konpeito/ui/markdown/mermaid/models.rb +232 -0
- data/lib/konpeito/ui/markdown/mermaid/parser.rb +519 -0
- data/lib/konpeito/ui/markdown/mermaid/renderer.rb +336 -0
- data/lib/konpeito/ui/markdown/parser.rb +805 -0
- data/lib/konpeito/ui/markdown/renderer.rb +639 -0
- data/lib/konpeito/ui/markdown/theme.rb +165 -0
- data/lib/konpeito/ui/render_node.rb +260 -0
- data/lib/konpeito/ui/row.rb +207 -0
- data/lib/konpeito/ui/spacer.rb +18 -0
- data/lib/konpeito/ui/style.rb +799 -0
- data/lib/konpeito/ui/theme.rb +563 -0
- data/lib/konpeito/ui/themes/material.rb +35 -0
- data/lib/konpeito/ui/themes/tokyo_night.rb +6 -0
- data/lib/konpeito/ui/widgets/button.rb +103 -0
- data/lib/konpeito/ui/widgets/calendar.rb +1034 -0
- data/lib/konpeito/ui/widgets/checkbox.rb +119 -0
- data/lib/konpeito/ui/widgets/container.rb +91 -0
- data/lib/konpeito/ui/widgets/data_table.rb +667 -0
- data/lib/konpeito/ui/widgets/divider.rb +29 -0
- data/lib/konpeito/ui/widgets/image.rb +105 -0
- data/lib/konpeito/ui/widgets/input.rb +485 -0
- data/lib/konpeito/ui/widgets/markdown.rb +57 -0
- data/lib/konpeito/ui/widgets/modal.rb +163 -0
- data/lib/konpeito/ui/widgets/multiline_input.rb +968 -0
- data/lib/konpeito/ui/widgets/multiline_text.rb +180 -0
- data/lib/konpeito/ui/widgets/net_image.rb +100 -0
- data/lib/konpeito/ui/widgets/progress_bar.rb +70 -0
- data/lib/konpeito/ui/widgets/radio_buttons.rb +93 -0
- data/lib/konpeito/ui/widgets/slider.rb +133 -0
- data/lib/konpeito/ui/widgets/switch.rb +84 -0
- data/lib/konpeito/ui/widgets/tabs.rb +157 -0
- data/lib/konpeito/ui/widgets/text.rb +110 -0
- data/lib/konpeito/ui/widgets/tree.rb +426 -0
- data/lib/konpeito/version.rb +5 -0
- data/lib/konpeito.rb +109 -0
- data/test_native_array.rb +172 -0
- data/test_native_array_class.rb +197 -0
- data/test_native_class.rb +151 -0
- data/tools/konpeito-asm/build.sh +65 -0
- data/tools/konpeito-asm/lib/asm-9.7.1.jar +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KArray.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KCompression.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KConditionVariable.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KCrypto.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KFile.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KHTTP.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KHash.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KJSON$Parser.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KJSON.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KMath.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KRactor.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KRactorPort.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KSizedQueue.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KThread.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KTime.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/RubyDispatch.class +0 -0
- data/tools/konpeito-asm/src/ClassIntrospector.java +312 -0
- data/tools/konpeito-asm/src/KonpeitoAssembler.java +659 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KArray.java +390 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KCompression.java +168 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KConditionVariable.java +48 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KCrypto.java +151 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KFile.java +100 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KHTTP.java +113 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KHash.java +228 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KJSON.java +405 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KMath.java +54 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KRactor.java +244 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KRactorPort.java +53 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KSizedQueue.java +49 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KThread.java +49 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KTime.java +53 -0
- data/tools/konpeito-asm/src/konpeito/runtime/RubyDispatch.java +416 -0
- metadata +267 -0
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Konpeito JSON stdlib - yyjson wrapper
|
|
3
|
+
*
|
|
4
|
+
* Provides fast JSON parsing and generation using yyjson library.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
#include <ruby.h>
|
|
8
|
+
#include "../../../../vendor/yyjson/yyjson.h"
|
|
9
|
+
|
|
10
|
+
/* Forward declarations */
|
|
11
|
+
static VALUE yyjson_val_to_ruby(yyjson_val *val);
|
|
12
|
+
static yyjson_mut_val *ruby_to_yyjson_mut(yyjson_mut_doc *doc, VALUE obj);
|
|
13
|
+
|
|
14
|
+
/* Convert yyjson value to Ruby VALUE (recursive) */
|
|
15
|
+
static VALUE yyjson_val_to_ruby(yyjson_val *val) {
|
|
16
|
+
if (!val) return Qnil;
|
|
17
|
+
|
|
18
|
+
yyjson_type type = yyjson_get_type(val);
|
|
19
|
+
|
|
20
|
+
switch (type) {
|
|
21
|
+
case YYJSON_TYPE_NULL:
|
|
22
|
+
return Qnil;
|
|
23
|
+
|
|
24
|
+
case YYJSON_TYPE_BOOL:
|
|
25
|
+
return yyjson_get_bool(val) ? Qtrue : Qfalse;
|
|
26
|
+
|
|
27
|
+
case YYJSON_TYPE_NUM:
|
|
28
|
+
if (yyjson_is_sint(val)) {
|
|
29
|
+
return LONG2NUM(yyjson_get_sint(val));
|
|
30
|
+
} else if (yyjson_is_uint(val)) {
|
|
31
|
+
return ULONG2NUM(yyjson_get_uint(val));
|
|
32
|
+
} else {
|
|
33
|
+
return DBL2NUM(yyjson_get_real(val));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
case YYJSON_TYPE_STR: {
|
|
37
|
+
const char *str = yyjson_get_str(val);
|
|
38
|
+
size_t len = yyjson_get_len(val);
|
|
39
|
+
return rb_utf8_str_new(str, len);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
case YYJSON_TYPE_ARR: {
|
|
43
|
+
VALUE arr = rb_ary_new();
|
|
44
|
+
yyjson_arr_iter iter;
|
|
45
|
+
yyjson_arr_iter_init(val, &iter);
|
|
46
|
+
yyjson_val *elem;
|
|
47
|
+
while ((elem = yyjson_arr_iter_next(&iter))) {
|
|
48
|
+
rb_ary_push(arr, yyjson_val_to_ruby(elem));
|
|
49
|
+
}
|
|
50
|
+
return arr;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
case YYJSON_TYPE_OBJ: {
|
|
54
|
+
VALUE hash = rb_hash_new();
|
|
55
|
+
yyjson_obj_iter iter;
|
|
56
|
+
yyjson_obj_iter_init(val, &iter);
|
|
57
|
+
yyjson_val *key;
|
|
58
|
+
while ((key = yyjson_obj_iter_next(&iter))) {
|
|
59
|
+
yyjson_val *obj_val = yyjson_obj_iter_get_val(key);
|
|
60
|
+
const char *key_str = yyjson_get_str(key);
|
|
61
|
+
size_t key_len = yyjson_get_len(key);
|
|
62
|
+
rb_hash_aset(hash,
|
|
63
|
+
rb_utf8_str_new(key_str, key_len),
|
|
64
|
+
yyjson_val_to_ruby(obj_val));
|
|
65
|
+
}
|
|
66
|
+
return hash;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
default:
|
|
70
|
+
return Qnil;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* Convert Ruby VALUE to yyjson mutable value (recursive) */
|
|
75
|
+
static yyjson_mut_val *ruby_to_yyjson_mut(yyjson_mut_doc *doc, VALUE obj) {
|
|
76
|
+
if (NIL_P(obj)) {
|
|
77
|
+
return yyjson_mut_null(doc);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (obj == Qtrue) {
|
|
81
|
+
return yyjson_mut_bool(doc, true);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (obj == Qfalse) {
|
|
85
|
+
return yyjson_mut_bool(doc, false);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (RB_INTEGER_TYPE_P(obj)) {
|
|
89
|
+
if (FIXNUM_P(obj)) {
|
|
90
|
+
return yyjson_mut_sint(doc, FIX2LONG(obj));
|
|
91
|
+
} else {
|
|
92
|
+
/* Bignum - try to convert to long long */
|
|
93
|
+
return yyjson_mut_sint(doc, NUM2LL(obj));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (RB_FLOAT_TYPE_P(obj)) {
|
|
98
|
+
return yyjson_mut_real(doc, NUM2DBL(obj));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (RB_TYPE_P(obj, T_STRING)) {
|
|
102
|
+
const char *str = RSTRING_PTR(obj);
|
|
103
|
+
size_t len = RSTRING_LEN(obj);
|
|
104
|
+
return yyjson_mut_strncpy(doc, str, len);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (RB_TYPE_P(obj, T_SYMBOL)) {
|
|
108
|
+
VALUE str = rb_sym2str(obj);
|
|
109
|
+
const char *cstr = RSTRING_PTR(str);
|
|
110
|
+
size_t len = RSTRING_LEN(str);
|
|
111
|
+
return yyjson_mut_strncpy(doc, cstr, len);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (RB_TYPE_P(obj, T_ARRAY)) {
|
|
115
|
+
yyjson_mut_val *arr = yyjson_mut_arr(doc);
|
|
116
|
+
long len = RARRAY_LEN(obj);
|
|
117
|
+
for (long i = 0; i < len; i++) {
|
|
118
|
+
VALUE elem = rb_ary_entry(obj, i);
|
|
119
|
+
yyjson_mut_val *mut_elem = ruby_to_yyjson_mut(doc, elem);
|
|
120
|
+
yyjson_mut_arr_append(arr, mut_elem);
|
|
121
|
+
}
|
|
122
|
+
return arr;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (RB_TYPE_P(obj, T_HASH)) {
|
|
126
|
+
yyjson_mut_val *hash_obj = yyjson_mut_obj(doc);
|
|
127
|
+
VALUE keys = rb_funcall(obj, rb_intern("keys"), 0);
|
|
128
|
+
long len = RARRAY_LEN(keys);
|
|
129
|
+
for (long i = 0; i < len; i++) {
|
|
130
|
+
VALUE key = rb_ary_entry(keys, i);
|
|
131
|
+
VALUE val = rb_hash_aref(obj, key);
|
|
132
|
+
|
|
133
|
+
/* Convert key to string */
|
|
134
|
+
VALUE key_str;
|
|
135
|
+
if (RB_TYPE_P(key, T_STRING)) {
|
|
136
|
+
key_str = key;
|
|
137
|
+
} else if (RB_TYPE_P(key, T_SYMBOL)) {
|
|
138
|
+
key_str = rb_sym2str(key);
|
|
139
|
+
} else {
|
|
140
|
+
key_str = rb_funcall(key, rb_intern("to_s"), 0);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const char *key_cstr = RSTRING_PTR(key_str);
|
|
144
|
+
size_t key_len = RSTRING_LEN(key_str);
|
|
145
|
+
yyjson_mut_val *mut_key = yyjson_mut_strncpy(doc, key_cstr, key_len);
|
|
146
|
+
yyjson_mut_val *mut_val = ruby_to_yyjson_mut(doc, val);
|
|
147
|
+
yyjson_mut_obj_add(hash_obj, mut_key, mut_val);
|
|
148
|
+
}
|
|
149
|
+
return hash_obj;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/* For other objects, try to_json or to_s */
|
|
153
|
+
if (rb_respond_to(obj, rb_intern("to_json"))) {
|
|
154
|
+
VALUE json_str = rb_funcall(obj, rb_intern("to_json"), 0);
|
|
155
|
+
const char *str = RSTRING_PTR(json_str);
|
|
156
|
+
size_t len = RSTRING_LEN(json_str);
|
|
157
|
+
/* Parse and return as raw JSON */
|
|
158
|
+
yyjson_doc *inner_doc = yyjson_read(str, len, 0);
|
|
159
|
+
if (inner_doc) {
|
|
160
|
+
yyjson_val *root = yyjson_doc_get_root(inner_doc);
|
|
161
|
+
yyjson_mut_val *result = yyjson_val_mut_copy(doc, root);
|
|
162
|
+
yyjson_doc_free(inner_doc);
|
|
163
|
+
return result;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/* Fallback: convert to string */
|
|
168
|
+
VALUE str = rb_funcall(obj, rb_intern("to_s"), 0);
|
|
169
|
+
const char *cstr = RSTRING_PTR(str);
|
|
170
|
+
size_t len = RSTRING_LEN(str);
|
|
171
|
+
return yyjson_mut_strncpy(doc, cstr, len);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/*
|
|
175
|
+
* Parse JSON string to Ruby object
|
|
176
|
+
*
|
|
177
|
+
* @param json_string [String] JSON string to parse
|
|
178
|
+
* @return [Object] Ruby object (Hash, Array, String, Integer, Float, true, false, nil)
|
|
179
|
+
* @raise [ArgumentError] if JSON is invalid
|
|
180
|
+
*/
|
|
181
|
+
VALUE konpeito_json_parse(VALUE self, VALUE json_string) {
|
|
182
|
+
Check_Type(json_string, T_STRING);
|
|
183
|
+
|
|
184
|
+
const char *str = RSTRING_PTR(json_string);
|
|
185
|
+
size_t len = RSTRING_LEN(json_string);
|
|
186
|
+
|
|
187
|
+
yyjson_read_err err;
|
|
188
|
+
yyjson_doc *doc = yyjson_read_opts((char *)str, len, 0, NULL, &err);
|
|
189
|
+
|
|
190
|
+
if (!doc) {
|
|
191
|
+
rb_raise(rb_eArgError, "JSON parse error at position %zu: %s",
|
|
192
|
+
err.pos, err.msg);
|
|
193
|
+
return Qnil;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
yyjson_val *root = yyjson_doc_get_root(doc);
|
|
197
|
+
VALUE result = yyjson_val_to_ruby(root);
|
|
198
|
+
|
|
199
|
+
yyjson_doc_free(doc);
|
|
200
|
+
return result;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/*
|
|
204
|
+
* Generate JSON string from Ruby object
|
|
205
|
+
*
|
|
206
|
+
* @param obj [Object] Ruby object to convert
|
|
207
|
+
* @return [String] JSON string
|
|
208
|
+
*/
|
|
209
|
+
VALUE konpeito_json_generate(VALUE self, VALUE obj) {
|
|
210
|
+
yyjson_mut_doc *doc = yyjson_mut_doc_new(NULL);
|
|
211
|
+
if (!doc) {
|
|
212
|
+
rb_raise(rb_eNoMemError, "Failed to allocate JSON document");
|
|
213
|
+
return Qnil;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
yyjson_mut_val *root = ruby_to_yyjson_mut(doc, obj);
|
|
217
|
+
yyjson_mut_doc_set_root(doc, root);
|
|
218
|
+
|
|
219
|
+
size_t len;
|
|
220
|
+
char *json_str = yyjson_mut_write(doc, 0, &len);
|
|
221
|
+
|
|
222
|
+
yyjson_mut_doc_free(doc);
|
|
223
|
+
|
|
224
|
+
if (!json_str) {
|
|
225
|
+
rb_raise(rb_eRuntimeError, "Failed to generate JSON");
|
|
226
|
+
return Qnil;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
VALUE result = rb_utf8_str_new(json_str, len);
|
|
230
|
+
free(json_str);
|
|
231
|
+
|
|
232
|
+
return result;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/*
|
|
236
|
+
* Generate pretty-printed JSON string from Ruby object
|
|
237
|
+
*
|
|
238
|
+
* @param obj [Object] Ruby object to convert
|
|
239
|
+
* @param indent [Integer] indentation spaces (default: 2)
|
|
240
|
+
* @return [String] pretty-printed JSON string
|
|
241
|
+
*/
|
|
242
|
+
VALUE konpeito_json_generate_pretty(VALUE self, VALUE obj, VALUE indent) {
|
|
243
|
+
int indent_spaces = NUM2INT(indent);
|
|
244
|
+
(void)indent_spaces; /* yyjson uses fixed 4-space indent for pretty print */
|
|
245
|
+
|
|
246
|
+
yyjson_mut_doc *doc = yyjson_mut_doc_new(NULL);
|
|
247
|
+
if (!doc) {
|
|
248
|
+
rb_raise(rb_eNoMemError, "Failed to allocate JSON document");
|
|
249
|
+
return Qnil;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
yyjson_mut_val *root = ruby_to_yyjson_mut(doc, obj);
|
|
253
|
+
yyjson_mut_doc_set_root(doc, root);
|
|
254
|
+
|
|
255
|
+
size_t len;
|
|
256
|
+
char *json_str = yyjson_mut_write(doc, YYJSON_WRITE_PRETTY, &len);
|
|
257
|
+
|
|
258
|
+
yyjson_mut_doc_free(doc);
|
|
259
|
+
|
|
260
|
+
if (!json_str) {
|
|
261
|
+
rb_raise(rb_eRuntimeError, "Failed to generate JSON");
|
|
262
|
+
return Qnil;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
VALUE result = rb_utf8_str_new(json_str, len);
|
|
266
|
+
free(json_str);
|
|
267
|
+
|
|
268
|
+
return result;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/* Module initialization - called by Init_<extension_name> */
|
|
272
|
+
void Init_konpeito_json(void) {
|
|
273
|
+
VALUE mKonpeitoJSON = rb_define_module("KonpeitoJSON");
|
|
274
|
+
|
|
275
|
+
rb_define_module_function(mKonpeitoJSON, "parse", konpeito_json_parse, 1);
|
|
276
|
+
rb_define_module_function(mKonpeitoJSON, "generate", konpeito_json_generate, 1);
|
|
277
|
+
rb_define_module_function(mKonpeitoJSON, "generate_pretty", konpeito_json_generate_pretty, 2);
|
|
278
|
+
|
|
279
|
+
/* Parse flags as constants */
|
|
280
|
+
rb_define_const(mKonpeitoJSON, "ALLOW_COMMENTS",
|
|
281
|
+
UINT2NUM(YYJSON_READ_ALLOW_COMMENTS));
|
|
282
|
+
rb_define_const(mKonpeitoJSON, "ALLOW_TRAILING_COMMAS",
|
|
283
|
+
UINT2NUM(YYJSON_READ_ALLOW_TRAILING_COMMAS));
|
|
284
|
+
rb_define_const(mKonpeitoJSON, "ALLOW_INF_NAN",
|
|
285
|
+
UINT2NUM(YYJSON_READ_ALLOW_INF_AND_NAN));
|
|
286
|
+
}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Build script for konpeito_ui native extension (SDL3 + Skia)
|
|
5
|
+
#
|
|
6
|
+
# Prerequisites:
|
|
7
|
+
# macOS:
|
|
8
|
+
# brew install sdl3
|
|
9
|
+
# Download Skia prebuilt (Aseprite m124):
|
|
10
|
+
# https://github.com/aseprite/skia/releases
|
|
11
|
+
# Set SKIA_DIR=~/skia-prebuilt (or wherever you extracted it)
|
|
12
|
+
#
|
|
13
|
+
# Linux:
|
|
14
|
+
# sudo apt install libsdl3-dev libgl-dev libfontconfig-dev libfreetype-dev
|
|
15
|
+
# Download/build Skia, set SKIA_DIR
|
|
16
|
+
#
|
|
17
|
+
# Windows (MSYS2):
|
|
18
|
+
# pacman -S mingw-w64-ucrt-x86_64-SDL3
|
|
19
|
+
# Download/build Skia, set SKIA_DIR
|
|
20
|
+
#
|
|
21
|
+
# Build:
|
|
22
|
+
# cd lib/konpeito/stdlib/ui && ruby extconf.rb && make
|
|
23
|
+
|
|
24
|
+
require "mkmf"
|
|
25
|
+
|
|
26
|
+
# C++17 required for Skia
|
|
27
|
+
# Aseprite Skia build uses -frtti (extra_cflags_cc = ["-frtti"])
|
|
28
|
+
$CXXFLAGS = ($CXXFLAGS || "") + " -std=c++17"
|
|
29
|
+
$CFLAGS = ($CFLAGS || "") + " -std=c11"
|
|
30
|
+
|
|
31
|
+
# Source file
|
|
32
|
+
$srcs = ["konpeito_ui_native.cpp"]
|
|
33
|
+
|
|
34
|
+
skia_dir = ENV["SKIA_DIR"] || File.expand_path("~/skia-prebuilt")
|
|
35
|
+
|
|
36
|
+
case RUBY_PLATFORM
|
|
37
|
+
when /darwin/
|
|
38
|
+
# macOS: SDL3 via Homebrew, Skia from SKIA_DIR
|
|
39
|
+
sdl_prefix = `brew --prefix sdl3 2>/dev/null`.chomp
|
|
40
|
+
if sdl_prefix.empty?
|
|
41
|
+
sdl_prefix = `pkg-config --variable=prefix sdl3 2>/dev/null`.chomp
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
unless sdl_prefix.empty?
|
|
45
|
+
$CFLAGS << " -I#{sdl_prefix}/include"
|
|
46
|
+
$CXXFLAGS << " -I#{sdl_prefix}/include"
|
|
47
|
+
$LDFLAGS << " -L#{sdl_prefix}/lib -lSDL3"
|
|
48
|
+
else
|
|
49
|
+
abort "SDL3 not found. Install with: brew install sdl3"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Skia
|
|
53
|
+
if File.directory?(skia_dir)
|
|
54
|
+
# Include paths: top-level for "include/core/..." style includes
|
|
55
|
+
$INCFLAGS = "-I#{skia_dir} #{$INCFLAGS}"
|
|
56
|
+
$CXXFLAGS << " -I#{skia_dir}"
|
|
57
|
+
|
|
58
|
+
# Detect lib directory (Release-arm64, Release-x64, or Release)
|
|
59
|
+
skia_lib_dir = nil
|
|
60
|
+
["Release-arm64", "Release-x64", "Release"].each do |d|
|
|
61
|
+
candidate = File.join(skia_dir, "out", d)
|
|
62
|
+
if File.exist?(File.join(candidate, "libskia.a"))
|
|
63
|
+
skia_lib_dir = candidate
|
|
64
|
+
break
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
unless skia_lib_dir
|
|
69
|
+
abort "libskia.a not found in #{skia_dir}/out/. Check your Skia build."
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Link Skia and its bundled dependencies
|
|
73
|
+
$LDFLAGS << " -L#{skia_lib_dir}"
|
|
74
|
+
# Order matters for static linking: dependents first, then dependencies
|
|
75
|
+
$LDFLAGS << " -lskia"
|
|
76
|
+
# Skia sub-libraries that are built separately in Aseprite's build
|
|
77
|
+
%w[harfbuzz freetype2 png zlib expat skcms webp].each do |lib|
|
|
78
|
+
lib_path = File.join(skia_lib_dir, "lib#{lib}.a")
|
|
79
|
+
if File.exist?(lib_path)
|
|
80
|
+
$LDFLAGS << " -l#{lib}"
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
else
|
|
84
|
+
abort "Skia not found at #{skia_dir}. Set SKIA_DIR environment variable."
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# macOS frameworks for Metal + Cocoa + CoreText
|
|
88
|
+
$LDFLAGS << " -framework Metal -framework MetalKit -framework QuartzCore"
|
|
89
|
+
$LDFLAGS << " -framework Cocoa -framework IOKit -framework CoreFoundation"
|
|
90
|
+
$LDFLAGS << " -framework CoreGraphics -framework CoreText -framework CoreServices"
|
|
91
|
+
$LDFLAGS << " -framework Foundation -framework AppKit"
|
|
92
|
+
|
|
93
|
+
# Skia GPU backend defines (required for Metal/Ganesh headers)
|
|
94
|
+
$CXXFLAGS << " -DSK_GANESH -DSK_METAL"
|
|
95
|
+
|
|
96
|
+
# Objective-C++ support for Metal code
|
|
97
|
+
$CXXFLAGS << " -ObjC++"
|
|
98
|
+
|
|
99
|
+
# Suppress Skia deprecation warnings
|
|
100
|
+
$CXXFLAGS << " -Wno-deprecated-declarations"
|
|
101
|
+
|
|
102
|
+
when /linux/
|
|
103
|
+
# Linux: SDL3 via pkg-config, Skia from SKIA_DIR
|
|
104
|
+
sdl_cflags = `pkg-config --cflags sdl3 2>/dev/null`.chomp
|
|
105
|
+
sdl_libs = `pkg-config --libs sdl3 2>/dev/null`.chomp
|
|
106
|
+
|
|
107
|
+
if sdl_cflags.empty? && sdl_libs.empty?
|
|
108
|
+
abort "SDL3 not found. Install with: sudo apt install libsdl3-dev"
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
$CFLAGS << " " << sdl_cflags
|
|
112
|
+
$CXXFLAGS << " " << sdl_cflags
|
|
113
|
+
$LDFLAGS << " " << sdl_libs
|
|
114
|
+
|
|
115
|
+
# Skia
|
|
116
|
+
if File.directory?(skia_dir)
|
|
117
|
+
$INCFLAGS = "-I#{skia_dir} #{$INCFLAGS}"
|
|
118
|
+
$CXXFLAGS << " -I#{skia_dir}"
|
|
119
|
+
|
|
120
|
+
skia_lib_dir = nil
|
|
121
|
+
["Release-x64", "Release"].each do |d|
|
|
122
|
+
candidate = File.join(skia_dir, "out", d)
|
|
123
|
+
if File.exist?(File.join(candidate, "libskia.a"))
|
|
124
|
+
skia_lib_dir = candidate
|
|
125
|
+
break
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
unless skia_lib_dir
|
|
129
|
+
abort "libskia.a not found in #{skia_dir}/out/"
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
$LDFLAGS << " -L#{skia_lib_dir} -lskia"
|
|
133
|
+
%w[harfbuzz freetype2 png zlib expat skcms webp].each do |lib|
|
|
134
|
+
lib_path = File.join(skia_lib_dir, "lib#{lib}.a")
|
|
135
|
+
$LDFLAGS << " -l#{lib}" if File.exist?(lib_path)
|
|
136
|
+
end
|
|
137
|
+
else
|
|
138
|
+
abort "Skia not found at #{skia_dir}. Set SKIA_DIR environment variable."
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Linux: OpenGL GPU backend + fontconfig
|
|
142
|
+
$LDFLAGS << " -lGL -lfontconfig -lfreetype"
|
|
143
|
+
|
|
144
|
+
# Skia GPU backend defines (required for OpenGL/Ganesh headers)
|
|
145
|
+
$CXXFLAGS << " -DSK_GANESH -DSK_GL"
|
|
146
|
+
$CXXFLAGS << " -Wno-deprecated-declarations"
|
|
147
|
+
|
|
148
|
+
when /mingw|mswin/
|
|
149
|
+
# Windows: SDL3 via MSYS2 or SDL3_DIR, Skia from SKIA_DIR
|
|
150
|
+
#
|
|
151
|
+
# MSYS2 setup:
|
|
152
|
+
# pacman -S mingw-w64-ucrt-x86_64-SDL3
|
|
153
|
+
#
|
|
154
|
+
# Or set SDL3_DIR to the SDL3 development folder.
|
|
155
|
+
|
|
156
|
+
sdl3_dir = ENV["SDL3_DIR"]
|
|
157
|
+
if sdl3_dir && File.directory?(sdl3_dir)
|
|
158
|
+
$CFLAGS << " -I#{sdl3_dir}/include"
|
|
159
|
+
$CXXFLAGS << " -I#{sdl3_dir}/include"
|
|
160
|
+
$LDFLAGS << " -L#{sdl3_dir}/lib -lSDL3"
|
|
161
|
+
else
|
|
162
|
+
# Try pkg-config (MSYS2 provides it)
|
|
163
|
+
sdl_cflags = `pkg-config --cflags sdl3 2>NUL`.chomp rescue ""
|
|
164
|
+
sdl_libs = `pkg-config --libs sdl3 2>NUL`.chomp rescue ""
|
|
165
|
+
if !sdl_cflags.empty? || !sdl_libs.empty?
|
|
166
|
+
$CFLAGS << " " << sdl_cflags unless sdl_cflags.empty?
|
|
167
|
+
$CXXFLAGS << " " << sdl_cflags unless sdl_cflags.empty?
|
|
168
|
+
$LDFLAGS << " " << sdl_libs unless sdl_libs.empty?
|
|
169
|
+
else
|
|
170
|
+
abort "SDL3 not found. Install with: pacman -S mingw-w64-ucrt-x86_64-SDL3\n" \
|
|
171
|
+
"Or set SDL3_DIR environment variable."
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# Skia
|
|
176
|
+
if File.directory?(skia_dir)
|
|
177
|
+
$INCFLAGS = "-I#{skia_dir} #{$INCFLAGS}"
|
|
178
|
+
$CXXFLAGS << " -I#{skia_dir}"
|
|
179
|
+
|
|
180
|
+
skia_lib_dir = nil
|
|
181
|
+
["Release-x64", "Release"].each do |d|
|
|
182
|
+
candidate = File.join(skia_dir, "out", d)
|
|
183
|
+
skia_lib = File.join(candidate, "skia.lib")
|
|
184
|
+
skia_lib_a = File.join(candidate, "libskia.a")
|
|
185
|
+
if File.exist?(skia_lib) || File.exist?(skia_lib_a)
|
|
186
|
+
skia_lib_dir = candidate
|
|
187
|
+
break
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
unless skia_lib_dir
|
|
191
|
+
abort "skia.lib/libskia.a not found in #{skia_dir}/out/"
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
$LDFLAGS << " -L#{skia_lib_dir} -lskia"
|
|
195
|
+
%w[harfbuzz freetype2 png zlib expat skcms webp].each do |lib|
|
|
196
|
+
lib_path_a = File.join(skia_lib_dir, "lib#{lib}.a")
|
|
197
|
+
lib_path_lib = File.join(skia_lib_dir, "#{lib}.lib")
|
|
198
|
+
$LDFLAGS << " -l#{lib}" if File.exist?(lib_path_a) || File.exist?(lib_path_lib)
|
|
199
|
+
end
|
|
200
|
+
else
|
|
201
|
+
abort "Skia not found at #{skia_dir}. Set SKIA_DIR environment variable."
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# Windows: OpenGL + system libraries
|
|
205
|
+
$LDFLAGS << " -lopengl32 -lgdi32 -luser32"
|
|
206
|
+
|
|
207
|
+
# Skia GPU backend defines (required for OpenGL/Ganesh headers)
|
|
208
|
+
$CXXFLAGS << " -DSK_GANESH -DSK_GL"
|
|
209
|
+
$CXXFLAGS << " -Wno-deprecated-declarations"
|
|
210
|
+
|
|
211
|
+
else
|
|
212
|
+
abort "Unsupported platform: #{RUBY_PLATFORM}. macOS, Linux, and Windows (MSYS2) are supported."
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# Create Makefile
|
|
216
|
+
create_makefile("konpeito_ui")
|