konpeito 0.7.1 → 0.9.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/CHANGELOG.md +72 -2
- data/lib/konpeito/codegen/llvm_generator.rb +121 -11
- data/lib/konpeito/codegen/mruby_backend.rb +44 -10
- data/lib/konpeito/codegen/mruby_helpers.c +107 -0
- data/lib/konpeito/stdlib/clay/clay.rb +26 -0
- data/lib/konpeito/stdlib/clay/clay.rbs +86 -0
- data/lib/konpeito/stdlib/clay/clay_native.c +371 -2
- data/lib/konpeito/stdlib/clay_tui/clay_tui.rb +41 -0
- data/lib/konpeito/stdlib/clay_tui/clay_tui.rbs +117 -0
- data/lib/konpeito/stdlib/clay_tui/clay_tui_native.c +263 -0
- data/lib/konpeito/stdlib/game_framework/game_framework.rb +1552 -0
- data/lib/konpeito/stdlib/kui/kui.rb +158 -96
- data/lib/konpeito/stdlib/kui/kui.rbs +180 -0
- data/lib/konpeito/stdlib/kui/kui_charts.rb +409 -0
- data/lib/konpeito/stdlib/kui/kui_charts.rbs +8 -0
- data/lib/konpeito/stdlib/kui/kui_containers.rb +202 -0
- data/lib/konpeito/stdlib/kui/kui_data.rb +284 -0
- data/lib/konpeito/stdlib/kui/kui_events.rb +27 -0
- data/lib/konpeito/stdlib/kui/kui_forms.rb +563 -0
- data/lib/konpeito/stdlib/kui/kui_gui.rb +360 -20
- data/lib/konpeito/stdlib/kui/kui_interactive.rb +428 -0
- data/lib/konpeito/stdlib/kui/kui_layouts.rb +150 -0
- data/lib/konpeito/stdlib/kui/kui_markdown.rb +1765 -0
- data/lib/konpeito/stdlib/kui/kui_markdown.rbs +6 -0
- data/lib/konpeito/stdlib/kui/kui_nav.rb +158 -0
- data/lib/konpeito/stdlib/kui/kui_overlay.rb +355 -0
- data/lib/konpeito/stdlib/kui/kui_state.rb +20 -0
- data/lib/konpeito/stdlib/kui/kui_state.rbs +5 -0
- data/lib/konpeito/stdlib/kui/kui_theme.rb +376 -6
- data/lib/konpeito/stdlib/kui/kui_theme.rbs +6 -1
- data/lib/konpeito/stdlib/kui/kui_tui.rb +281 -14
- data/lib/konpeito/stdlib/raylib/raylib.rb +27 -0
- data/lib/konpeito/stdlib/raylib/raylib.rbs +81 -0
- data/lib/konpeito/stdlib/raylib/raylib_native.c +29 -0
- data/lib/konpeito/version.rb +1 -1
- data/vendor/clay/clay_renderer_raylib.c +1 -1
- metadata +15 -2
- data/lib/konpeito/stdlib/rpg_framework/rpg_framework.rb +0 -668
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d513cebc5d3b0574c814b92901fbe2f4154e4ffc905da31c095abf9375bcaf34
|
|
4
|
+
data.tar.gz: 8becb035b3dc4e7aa9f2cb482fa658fcf4551ceeb734fba5c7727eb87e06babd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e37567409349ff5fe6c87802b89ffe2ecef3cd7b4b74fc332df6534e5c5e144b0d527d9f2d67d39c532dd117ebe35aa654e2779a4c10f6191f96b0a8fa9bb168
|
|
7
|
+
data.tar.gz: aef79cd03516814b259747bf9eaa0b449d692ca6568b6ecf9c4939e05ce279d7343d65caf8ceccc74e63094839e318bf5a855ea8b2d75e54f83d6e1e7f5ef6e8
|
data/CHANGELOG.md
CHANGED
|
@@ -5,7 +5,70 @@ 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
|
-
## [
|
|
8
|
+
## [0.9.0] - 2026-03-16
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **KUI widget expansion** (25→66 widgets): badge, avatar, progress_steps, number_stepper,
|
|
12
|
+
segmented_control, accordion, dropdown, tooltip, toast, alert/confirm dialog, slider,
|
|
13
|
+
switch, rating, textarea, color_picker, date_picker, grid, zstack, scaffold, wrap_panel,
|
|
14
|
+
nav_bar, bottom_nav, drawer, bottom_sheet, list_section, sortable_header, timeline,
|
|
15
|
+
skeleton, carousel_dots, and nested yield fix in mruby backend
|
|
16
|
+
- **KUI Markdown renderer** with live window resize support
|
|
17
|
+
- **KUI chart rendering**: bar, line, and pie charts
|
|
18
|
+
- **KUI Castella-style theming**: style composition and theme presets
|
|
19
|
+
(dark, light, solarized, etc.)
|
|
20
|
+
- **Basic IME support**: UTF-8 text buffers and CJK font loading
|
|
21
|
+
- **TUI Markdown demo** and TUI build resize stubs
|
|
22
|
+
- **Pomodoro Timer** KUI utility app
|
|
23
|
+
- **KUI framework extensions** and two new example apps (café menu, dashboard)
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
- **case/when with integer constants** crashed with SIGSEGV
|
|
27
|
+
- **Large draw functions** caused SIGSEGV in Pomodoro Timer (resolved by function splitting)
|
|
28
|
+
- **Unboxed captures in escape-cells** caused GC SIGSEGV (now boxed before capture)
|
|
29
|
+
- **Nested yield+block** caused SIGSEGV (re-enabled yield target stack)
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
- KUI tutorial updated with new widget features
|
|
33
|
+
- KUI documentation clarified as immediate-mode UI framework
|
|
34
|
+
|
|
35
|
+
## [0.8.0] - 2026-03-14
|
|
36
|
+
|
|
37
|
+
### Added
|
|
38
|
+
- **KUI widget expansion**: text_input, checkbox, radio, toggle, spinner, status_bar,
|
|
39
|
+
selectable_list, list_item, table (header/row/cell), modal, tab_bar, tab_button,
|
|
40
|
+
tab_content — all with keyboard focus support and click-to-focus
|
|
41
|
+
- **KUI focus system**: Tab/arrow key navigation across all interactive widgets with
|
|
42
|
+
focus highlight and Enter key activation
|
|
43
|
+
- **KUI extended key input**: `kui_char_pressed()`, `kui_mod_pressed()`,
|
|
44
|
+
Delete/Home/End/PgUp/PgDn/F1-F12 key constants
|
|
45
|
+
- **KUI text buffer API**: `kui_textbuf_copy`, `kui_textbuf_render` for dynamic content
|
|
46
|
+
- **KUI GUI backend**: Full GUI implementations for all new widgets (Clay+Raylib)
|
|
47
|
+
- **Game framework expansion**: tween/easing (linear, quad, cubic, bounce, elastic),
|
|
48
|
+
screen shake, scene transitions (fade), FSM, timer system, parallax scrolling,
|
|
49
|
+
simple physics (AABB, gravity, friction), particle system, object pool, grid/tile
|
|
50
|
+
utilities, debug overlay (FPS, collision rects), gamepad abstraction, save/load
|
|
51
|
+
- **Game showcase demo**: "Coin Dash" score-attack platformer demonstrating
|
|
52
|
+
game framework API (physics, particles, tween, FSM, parallax, Camera2D)
|
|
53
|
+
- **Physics demo**: Platformer demo showcasing NativeArray-based physics
|
|
54
|
+
- **KUI form demo**: Text input, checkbox, radio, toggle showcase
|
|
55
|
+
- **KUI tabs demo**: Tab bar, table, modal dialog, selectable list, status bar showcase
|
|
56
|
+
- **KUI showcase demo**: Rich GUI app demonstrating all v0.8.0 widgets in a 4-tab layout
|
|
57
|
+
|
|
58
|
+
### Fixed
|
|
59
|
+
- **NativeArray SEGV as function argument**: `convert_value()` lacked
|
|
60
|
+
`[:native_array, :value]` case, causing raw LLVM pointers where Ruby VALUEs
|
|
61
|
+
were expected
|
|
62
|
+
- **NativeArray SEGV in compound expressions**: `get_effective_unboxed_type()`
|
|
63
|
+
only checked `@variable_types` for LoadLocal nodes, causing incorrect float path
|
|
64
|
+
for integer arithmetic in if conditions
|
|
65
|
+
- **KUI text input isolation**: Only focused text_input processes keyboard input
|
|
66
|
+
- **KUI toggle flip-back**: Filter out termbox2 mouse release events (key 65509)
|
|
67
|
+
- **KUI modal layout**: Reduced TUI padding from 16 to 1 char cells
|
|
68
|
+
- **mruby keyword argument handling**: Optional keyword hash with `MRB_ARGS_ARG`
|
|
69
|
+
- **KUI scroll containers not scrolling**: `Clay_GetScrollOffset()` was not called
|
|
70
|
+
in `konpeito_clay_scroll` / `konpeito_clay_tui_scroll`, so `childOffset` remained
|
|
71
|
+
zero and scroll position was never visually applied
|
|
9
72
|
|
|
10
73
|
## [0.7.1] - 2026-03-14
|
|
11
74
|
|
|
@@ -18,7 +81,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
18
81
|
- **KUI declarative UI framework**: Pure Ruby DSL for building GUI/TUI apps with a single codebase. Wraps Clay+Raylib (GUI) or ClayTUI (TUI). Widgets: `vpanel`, `hpanel`, `fixed_panel`, `label`, `label_num`, `button`, `menu_item`, `spacer`, `divider`, `progress_bar`. Theme system and unified key event abstraction.
|
|
19
82
|
- **ClayTUI stdlib**: Terminal UI backend using Clay layout engine + termbox2 rendering. Auto-detected via `ClayTUI` module reference.
|
|
20
83
|
- **KonpeitoShell stdlib**: Shell execution (`exec`, `system`), environment variables (`getenv`, `setenv`), and file I/O (`read_file`, `write_file`, `append_file`, `file_exists`) for mruby backend.
|
|
21
|
-
- **
|
|
84
|
+
- **Game framework stdlib**: Reusable 2D game components (tilemap, sprites, camera, battle system) for raylib-based games.
|
|
22
85
|
- **Stdlib auto-detection expansion**: `KonpeitoJSON`, `KonpeitoHTTP`, `KonpeitoCrypto`, `KonpeitoCompression` added to `STDLIB_MODULE_MAP` for automatic RBS injection when referenced in source code.
|
|
23
86
|
- **KUI auto-path resolution**: `require "kui_gui"` / `require "kui_tui"` works without `-I` flags — KUI stdlib directory is automatically included in compiler search paths.
|
|
24
87
|
- **KUI example apps**: Counter (GUI + TUI), minimal hello, multi-page dashboard with sidebar navigation.
|
|
@@ -341,6 +404,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
341
404
|
- `%a{extern}` - external C struct wrappers
|
|
342
405
|
- `%a{simd}` - SIMD vectorization
|
|
343
406
|
|
|
407
|
+
[0.9.0]: https://github.com/i2y/konpeito/compare/v0.8.0...v0.9.0
|
|
408
|
+
[0.8.0]: https://github.com/i2y/konpeito/compare/v0.7.1...v0.8.0
|
|
409
|
+
[0.7.1]: https://github.com/i2y/konpeito/compare/v0.7.0...v0.7.1
|
|
410
|
+
[0.7.0]: https://github.com/i2y/konpeito/compare/v0.6.0...v0.7.0
|
|
411
|
+
[0.6.0]: https://github.com/i2y/konpeito/compare/v0.5.0...v0.6.0
|
|
412
|
+
[0.5.0]: https://github.com/i2y/konpeito/compare/v0.4.2...v0.5.0
|
|
413
|
+
[0.4.2]: https://github.com/i2y/konpeito/compare/v0.4.1...v0.4.2
|
|
344
414
|
[0.4.1]: https://github.com/i2y/konpeito/compare/v0.4.0...v0.4.1
|
|
345
415
|
[0.4.0]: https://github.com/i2y/konpeito/compare/v0.3.1...v0.4.0
|
|
346
416
|
[0.3.1]: https://github.com/i2y/konpeito/compare/v0.3.0...v0.3.1
|
|
@@ -823,6 +823,13 @@ module Konpeito
|
|
|
823
823
|
# We'll use rb_yield_values2 instead: VALUE rb_yield_values2(int argc, const VALUE *argv)
|
|
824
824
|
@rb_yield_values2 = @mod.functions.add("rb_yield_values2", [LLVM::Int32, LLVM::Pointer(value_type)], value_type)
|
|
825
825
|
|
|
826
|
+
# Nested yield: yield to the enclosing method's block from inside a block callback
|
|
827
|
+
@konpeito_yield_to_method_block = @mod.functions.add("konpeito_yield_to_method_block", [value_type], value_type)
|
|
828
|
+
@konpeito_yield_to_method_block_values = @mod.functions.add("konpeito_yield_to_method_block_values",
|
|
829
|
+
[LLVM::Int32, LLVM::Pointer(value_type)], value_type)
|
|
830
|
+
@konpeito_push_yield_target = @mod.functions.add("konpeito_push_yield_target", [], LLVM::Type.void)
|
|
831
|
+
@konpeito_pop_yield_target = @mod.functions.add("konpeito_pop_yield_target", [], LLVM::Type.void)
|
|
832
|
+
|
|
826
833
|
# int rb_block_given_p(void) - check if block is given
|
|
827
834
|
@rb_block_given_p = @mod.functions.add("rb_block_given_p", [], LLVM::Int32)
|
|
828
835
|
|
|
@@ -1597,6 +1604,24 @@ module Konpeito
|
|
|
1597
1604
|
boxed_value = func.params[i + 1] # +1 to skip self
|
|
1598
1605
|
type_tag = @variable_types[param.name]
|
|
1599
1606
|
|
|
1607
|
+
if type_tag == :native_array
|
|
1608
|
+
# NativeArray parameter: the VALUE is actually a pointer address (via ptr2int).
|
|
1609
|
+
# Reconstruct the pointer and store directly in @variables (not alloca).
|
|
1610
|
+
# generate_load_local reads NativeArray values from @variables, not allocas.
|
|
1611
|
+
array_ptr = @builder.int2ptr(boxed_value, ptr_type, "#{param.name}_ptr")
|
|
1612
|
+
@variables[param.name] = array_ptr
|
|
1613
|
+
# Propagate element type and length from the parameter's HM type if available
|
|
1614
|
+
if param.type.is_a?(TypeChecker::Types::NativeArrayType)
|
|
1615
|
+
elem_type = param.type.element_type
|
|
1616
|
+
@variables["#{param.name}_len"] = LLVM::Int64.from_i(param.type.size || 0)
|
|
1617
|
+
if elem_type && elem_type != :Int64 && elem_type != :Float64
|
|
1618
|
+
@native_array_class_types ||= {}
|
|
1619
|
+
@native_array_class_types[param.name] = elem_type
|
|
1620
|
+
end
|
|
1621
|
+
end
|
|
1622
|
+
next
|
|
1623
|
+
end
|
|
1624
|
+
|
|
1600
1625
|
# Unbox parameter if it's a numeric type
|
|
1601
1626
|
value_to_store = case type_tag
|
|
1602
1627
|
when :i64
|
|
@@ -1749,6 +1774,15 @@ module Konpeito
|
|
|
1749
1774
|
@builder.store(arena_idx, @mruby_gc_arena_alloca)
|
|
1750
1775
|
end
|
|
1751
1776
|
|
|
1777
|
+
# For mruby: if this function has yield inside block callbacks (nested yield),
|
|
1778
|
+
# push the current method's block as the yield target so that nested callbacks
|
|
1779
|
+
# can yield to the correct block instead of the innermost callback.
|
|
1780
|
+
@needs_yield_target_pop = false
|
|
1781
|
+
if @runtime == :mruby && function_has_nested_yield?(hir_func)
|
|
1782
|
+
@builder.call(@konpeito_push_yield_target)
|
|
1783
|
+
@needs_yield_target_pop = true
|
|
1784
|
+
end
|
|
1785
|
+
|
|
1752
1786
|
# Insert profiling entry probe after parameter setup
|
|
1753
1787
|
insert_profile_entry_probe(hir_func)
|
|
1754
1788
|
|
|
@@ -1778,6 +1812,10 @@ module Konpeito
|
|
|
1778
1812
|
# For the mruby backend, restores the arena to the saved index and
|
|
1779
1813
|
# protects the return value from GC before returning.
|
|
1780
1814
|
def emit_ret(value)
|
|
1815
|
+
# Pop yield target before return if this function pushed one
|
|
1816
|
+
if @needs_yield_target_pop
|
|
1817
|
+
@builder.call(@konpeito_pop_yield_target)
|
|
1818
|
+
end
|
|
1781
1819
|
if @mruby_gc_arena_alloca
|
|
1782
1820
|
idx = @builder.load2(LLVM::Int32, @mruby_gc_arena_alloca, "_arena_r")
|
|
1783
1821
|
@builder.call(@konpeito_gc_arena_restore, idx)
|
|
@@ -1789,6 +1827,32 @@ module Konpeito
|
|
|
1789
1827
|
@builder.ret(value)
|
|
1790
1828
|
end
|
|
1791
1829
|
|
|
1830
|
+
# Check if a function has yield inside any block callback body (nested yield).
|
|
1831
|
+
# Direct yield in the function body does NOT count (that uses rb_yield normally).
|
|
1832
|
+
def function_has_nested_yield?(hir_func)
|
|
1833
|
+
hir_func.body.each do |bb|
|
|
1834
|
+
bb.instructions.each do |inst|
|
|
1835
|
+
if inst.is_a?(HIR::Call) && inst.block
|
|
1836
|
+
return true if block_body_contains_yield?(inst.block)
|
|
1837
|
+
end
|
|
1838
|
+
end
|
|
1839
|
+
end
|
|
1840
|
+
false
|
|
1841
|
+
end
|
|
1842
|
+
|
|
1843
|
+
# Recursively check if a block body contains a Yield instruction.
|
|
1844
|
+
def block_body_contains_yield?(block_def)
|
|
1845
|
+
block_def.body.each do |bb|
|
|
1846
|
+
bb.instructions.each do |inst|
|
|
1847
|
+
return true if inst.is_a?(HIR::Yield)
|
|
1848
|
+
if inst.is_a?(HIR::Call) && inst.block
|
|
1849
|
+
return true if block_body_contains_yield?(inst.block)
|
|
1850
|
+
end
|
|
1851
|
+
end
|
|
1852
|
+
end
|
|
1853
|
+
false
|
|
1854
|
+
end
|
|
1855
|
+
|
|
1792
1856
|
# Topologically sort blocks based on phi dependencies
|
|
1793
1857
|
# Ensures blocks are generated after the blocks their phi nodes reference
|
|
1794
1858
|
def sort_blocks_by_phi_dependencies(blocks)
|
|
@@ -2004,6 +2068,10 @@ module Konpeito
|
|
|
2004
2068
|
[LLVM::Int64, :i64]
|
|
2005
2069
|
elsif float_type?(ruby_type)
|
|
2006
2070
|
[LLVM::Double, :double]
|
|
2071
|
+
elsif ruby_type.is_a?(TypeChecker::Types::NativeArrayType)
|
|
2072
|
+
# NativeArray parameters: alloca holds VALUE (i64) but type is :native_array
|
|
2073
|
+
# The actual pointer is reconstructed from the VALUE in parameter setup
|
|
2074
|
+
[value_type, :native_array]
|
|
2007
2075
|
else
|
|
2008
2076
|
[value_type, :value]
|
|
2009
2077
|
end
|
|
@@ -3029,6 +3097,9 @@ module Konpeito
|
|
|
3029
3097
|
when [:native_class, :value]
|
|
3030
3098
|
# NativeClass struct pointer to VALUE (i64)
|
|
3031
3099
|
@builder.ptr2int(value, LLVM::Int64)
|
|
3100
|
+
when [:native_array, :value]
|
|
3101
|
+
# NativeArray pointer to VALUE (i64) — encode pointer address as integer
|
|
3102
|
+
@builder.ptr2int(value, LLVM::Int64)
|
|
3032
3103
|
when [:i64, :double]
|
|
3033
3104
|
@builder.si2fp(value, LLVM::Double)
|
|
3034
3105
|
when [:double, :i64]
|
|
@@ -4789,11 +4860,19 @@ module Konpeito
|
|
|
4789
4860
|
if use_escape_cells
|
|
4790
4861
|
esc_ary = @builder.call(@rb_ary_new_capa, LLVM::Int64.from_i(all_captures.size), "blk_esc_ary")
|
|
4791
4862
|
all_captures.each do |cap|
|
|
4863
|
+
cap_type = capture_types[cap.name] || :value
|
|
4792
4864
|
val = if @variable_allocas[cap.name]
|
|
4793
4865
|
@builder.load2(value_type, @variable_allocas[cap.name], "blk_esc_#{cap.name}")
|
|
4794
4866
|
else
|
|
4795
4867
|
qnil
|
|
4796
4868
|
end
|
|
4869
|
+
# Box unboxed values before pushing to the escape-cells Ruby Array.
|
|
4870
|
+
# The GC scans array elements as mrb_values; a raw unboxed integer
|
|
4871
|
+
# (e.g., from NativeArray) without fixnum tag bits would be
|
|
4872
|
+
# misinterpreted as a heap pointer → SIGSEGV in gc_mark_children.
|
|
4873
|
+
if cap_type != :value
|
|
4874
|
+
val = convert_value(val, cap_type, :value)
|
|
4875
|
+
end
|
|
4797
4876
|
@builder.call(@rb_ary_push, esc_ary, val)
|
|
4798
4877
|
end
|
|
4799
4878
|
|
|
@@ -4891,8 +4970,9 @@ module Konpeito
|
|
|
4891
4970
|
# Set @in_block_callback so nested proc creation uses GC-safe escape-cells mode.
|
|
4892
4971
|
# Reset mruby constant cache — LLVM values are scoped per function, so
|
|
4893
4972
|
# cached %qnil/%qtrue from the parent function are invalid here.
|
|
4894
|
-
# Clear GC arena alloca — callbacks don't own their own arena scope.
|
|
4895
4973
|
@in_block_callback = true
|
|
4974
|
+
|
|
4975
|
+
# Clear GC arena alloca — callbacks run under the caller's arena scope.
|
|
4896
4976
|
@mruby_gc_arena_alloca = nil
|
|
4897
4977
|
@variables = {}
|
|
4898
4978
|
@variable_types = {}
|
|
@@ -4911,13 +4991,21 @@ module Konpeito
|
|
|
4911
4991
|
captures.each_with_index do |capture, i|
|
|
4912
4992
|
val = @builder.call(@rb_ary_entry, ary_val,
|
|
4913
4993
|
LLVM::Int64.from_i(i), "esc_#{capture.name}")
|
|
4994
|
+
# Values were boxed when pushed to the escape-cells array
|
|
4995
|
+
# (to prevent GC from misinterpreting raw unboxed integers as
|
|
4996
|
+
# heap pointers). Unbox them back to their original type.
|
|
4997
|
+
cap_type = capture_types[capture.name] || :value
|
|
4998
|
+
if cap_type != :value
|
|
4999
|
+
val = convert_value(val, :value, cap_type)
|
|
5000
|
+
end
|
|
4914
5001
|
# Store in an alloca so LoadLocal/StoreLocal can use it normally.
|
|
4915
5002
|
# Writes to this alloca stay local (no back-write to the GC array),
|
|
4916
5003
|
# which is correct for snapshots from a returned outer scope.
|
|
4917
|
-
|
|
5004
|
+
llvm_type = type_tag_to_llvm_type(cap_type)
|
|
5005
|
+
cap_alloca = @builder.alloca(llvm_type, "esc_alloca_#{capture.name}")
|
|
4918
5006
|
@builder.store(val, cap_alloca)
|
|
4919
5007
|
@variable_allocas[capture.name] = cap_alloca
|
|
4920
|
-
@variable_types[capture.name] =
|
|
5008
|
+
@variable_types[capture.name] = cap_type
|
|
4921
5009
|
end
|
|
4922
5010
|
else
|
|
4923
5011
|
# data2 is a pointer to array of VALUE* (pointers to captured variables).
|
|
@@ -5124,10 +5212,7 @@ module Konpeito
|
|
|
5124
5212
|
# Return the last value in the block, or Qnil
|
|
5125
5213
|
# For while_exit blocks, the last instruction loads the break value
|
|
5126
5214
|
if last_instr
|
|
5127
|
-
|
|
5128
|
-
# Box unboxed values before returning
|
|
5129
|
-
result_type = :value # Default
|
|
5130
|
-
@builder.ret(result_val)
|
|
5215
|
+
@builder.ret(last_instr)
|
|
5131
5216
|
else
|
|
5132
5217
|
@builder.ret(qnil)
|
|
5133
5218
|
end
|
|
@@ -7372,6 +7457,15 @@ module Konpeito
|
|
|
7372
7457
|
return type_tag if type_tag == :i64 || type_tag == :double
|
|
7373
7458
|
end
|
|
7374
7459
|
|
|
7460
|
+
# Check @variable_types for any instruction with result_var.
|
|
7461
|
+
# This is critical for sub-expressions (e.g. NativeArrayGet, Call) whose
|
|
7462
|
+
# HIR type may be an unresolved TypeVar but whose actual generated type
|
|
7463
|
+
# is correctly tracked in @variable_types.
|
|
7464
|
+
if hir_value.is_a?(HIR::Instruction) && hir_value.result_var
|
|
7465
|
+
type_tag = @variable_types[hir_value.result_var]
|
|
7466
|
+
return type_tag if type_tag == :i64 || type_tag == :double
|
|
7467
|
+
end
|
|
7468
|
+
|
|
7375
7469
|
# Check HIR type
|
|
7376
7470
|
hir_type = get_type(hir_value)
|
|
7377
7471
|
if integer_type?(hir_type)
|
|
@@ -7948,15 +8042,20 @@ module Konpeito
|
|
|
7948
8042
|
end
|
|
7949
8043
|
|
|
7950
8044
|
def generate_yield(inst)
|
|
8045
|
+
# When yield is inside a block callback, use the yield target stack
|
|
8046
|
+
# to reach the enclosing method's block instead of the innermost callback.
|
|
8047
|
+
yield_fn = @in_block_callback ? @konpeito_yield_to_method_block : @rb_yield
|
|
8048
|
+
yield_values_fn = @in_block_callback ? @konpeito_yield_to_method_block_values : @rb_yield_values2
|
|
8049
|
+
|
|
7951
8050
|
result = if inst.args.empty?
|
|
7952
8051
|
# yield with no arguments - pass Qnil
|
|
7953
|
-
@builder.call(
|
|
8052
|
+
@builder.call(yield_fn, qnil)
|
|
7954
8053
|
elsif inst.args.size == 1
|
|
7955
8054
|
# yield with single argument — must be boxed VALUE for rb_yield
|
|
7956
8055
|
arg_value = get_value_as_ruby(inst.args.first)
|
|
7957
|
-
@builder.call(
|
|
8056
|
+
@builder.call(yield_fn, arg_value)
|
|
7958
8057
|
else
|
|
7959
|
-
# yield with multiple arguments
|
|
8058
|
+
# yield with multiple arguments
|
|
7960
8059
|
argc = LLVM::Int32.from_i(inst.args.size)
|
|
7961
8060
|
|
|
7962
8061
|
# Allocate array on stack
|
|
@@ -7970,7 +8069,7 @@ module Konpeito
|
|
|
7970
8069
|
|
|
7971
8070
|
# Cast to VALUE*
|
|
7972
8071
|
argv_ptr = @builder.bit_cast(argv, LLVM::Pointer(value_type))
|
|
7973
|
-
@builder.call(
|
|
8072
|
+
@builder.call(yield_values_fn, argc, argv_ptr)
|
|
7974
8073
|
end
|
|
7975
8074
|
|
|
7976
8075
|
@variables[inst.result_var] = result if inst.result_var
|
|
@@ -8855,6 +8954,10 @@ module Konpeito
|
|
|
8855
8954
|
# String === arg: Use rb_str_equal
|
|
8856
8955
|
return inline_string_case_eq(receiver, arg)
|
|
8857
8956
|
elsif receiver_hir.is_a?(HIR::ConstantLookup)
|
|
8957
|
+
if is_integer_type?(receiver_hir.type)
|
|
8958
|
+
# Integer constant (e.g. OP_ADD = 1) === arg: VALUE equality check
|
|
8959
|
+
return inline_value_case_eq(receiver, arg)
|
|
8960
|
+
end
|
|
8858
8961
|
# Class/Module === arg: Use rb_obj_is_kind_of
|
|
8859
8962
|
return inline_class_case_eq(receiver, arg)
|
|
8860
8963
|
end
|
|
@@ -8892,6 +8995,13 @@ module Konpeito
|
|
|
8892
8995
|
@builder.select(result_bool, qtrue, qfalse)
|
|
8893
8996
|
end
|
|
8894
8997
|
|
|
8998
|
+
# Inline VALUE equality check for integer constants (e.g. OP_ADD = 1)
|
|
8999
|
+
# Since CRuby/mruby Fixnums are immediate values, VALUE equality == numeric equality
|
|
9000
|
+
def inline_value_case_eq(receiver, arg)
|
|
9001
|
+
eq_bool = @builder.icmp(:eq, receiver, arg)
|
|
9002
|
+
@builder.select(eq_bool, qtrue, qfalse)
|
|
9003
|
+
end
|
|
9004
|
+
|
|
8895
9005
|
# Inline String === arg comparison
|
|
8896
9006
|
def inline_string_case_eq(receiver, arg)
|
|
8897
9007
|
# Use rb_str_equal which returns Qtrue/Qfalse
|
|
@@ -78,13 +78,17 @@ module Konpeito
|
|
|
78
78
|
# Generate license file alongside the executable
|
|
79
79
|
generate_license_file
|
|
80
80
|
ensure
|
|
81
|
-
# Clean up intermediate files
|
|
81
|
+
# Clean up intermediate files (keep .ll for debugging if ENV['KONPEITO_KEEP_IR'] is set)
|
|
82
|
+
keep_ir = ENV['KONPEITO_KEEP_IR']
|
|
82
83
|
all_temps = [ir_file, obj_file, init_c_file, init_obj_file, helpers_obj_file] + extra_obj_files
|
|
83
84
|
all_temps.each do |f|
|
|
85
|
+
next if keep_ir && f&.end_with?('.ll')
|
|
84
86
|
FileUtils.rm_f(f) if f && File.exist?(f)
|
|
85
87
|
end
|
|
86
88
|
# Also clean optimized IR if it was generated
|
|
87
|
-
|
|
89
|
+
unless keep_ir
|
|
90
|
+
FileUtils.rm_f("#{ir_file}.opt.ll") if File.exist?("#{ir_file}.opt.ll")
|
|
91
|
+
end
|
|
88
92
|
end
|
|
89
93
|
end
|
|
90
94
|
|
|
@@ -125,6 +129,8 @@ module Konpeito
|
|
|
125
129
|
lines << "/* Block stack for rb_yield/rb_block_given_p support */"
|
|
126
130
|
lines << "extern void konpeito_push_block(mrb_value block);"
|
|
127
131
|
lines << "extern void konpeito_pop_block(void);"
|
|
132
|
+
lines << "extern void konpeito_push_yield_target(void);"
|
|
133
|
+
lines << "extern void konpeito_pop_yield_target(void);"
|
|
128
134
|
lines << ""
|
|
129
135
|
|
|
130
136
|
# Collect NativeClasses from RBS loader
|
|
@@ -302,7 +308,7 @@ module Konpeito
|
|
|
302
308
|
|
|
303
309
|
arity = llvm_generator.variadic_functions[mangled_name] ? -1 : func.params.size - 1
|
|
304
310
|
wrapper = "mrb_wrap_#{mangled_name}"
|
|
305
|
-
mrb_args =
|
|
311
|
+
mrb_args = effective_mrb_args(mangled_name, arity)
|
|
306
312
|
lines << " mrb_define_method(mrb, #{module_var}, \"#{method_name}\", #{wrapper}, #{mrb_args});"
|
|
307
313
|
end
|
|
308
314
|
|
|
@@ -316,7 +322,7 @@ module Konpeito
|
|
|
316
322
|
|
|
317
323
|
arity = llvm_generator.variadic_functions[mangled_name] ? -1 : func.params.size - 1
|
|
318
324
|
wrapper = "mrb_wrap_#{mangled_name}"
|
|
319
|
-
mrb_args =
|
|
325
|
+
mrb_args = effective_mrb_args(mangled_name, arity)
|
|
320
326
|
lines << " mrb_define_class_method(mrb, #{module_var}, \"#{method_name}\", #{wrapper}, #{mrb_args});"
|
|
321
327
|
end
|
|
322
328
|
|
|
@@ -372,7 +378,7 @@ module Konpeito
|
|
|
372
378
|
|
|
373
379
|
arity = llvm_generator.variadic_functions[mangled_name] ? -1 : func.params.size - 1
|
|
374
380
|
wrapper = "mrb_wrap_#{mangled_name}"
|
|
375
|
-
mrb_args =
|
|
381
|
+
mrb_args = effective_mrb_args(mangled_name, arity)
|
|
376
382
|
lines << " mrb_define_method(mrb, #{class_var}, \"#{method_name}\", #{wrapper}, #{mrb_args});"
|
|
377
383
|
end
|
|
378
384
|
|
|
@@ -386,7 +392,7 @@ module Konpeito
|
|
|
386
392
|
|
|
387
393
|
arity = llvm_generator.variadic_functions[mangled_name] ? -1 : func.params.size - 1
|
|
388
394
|
wrapper = "mrb_wrap_#{mangled_name}"
|
|
389
|
-
mrb_args =
|
|
395
|
+
mrb_args = effective_mrb_args(mangled_name, arity)
|
|
390
396
|
lines << " mrb_define_class_method(mrb, #{class_var}, \"#{method_name}\", #{wrapper}, #{mrb_args});"
|
|
391
397
|
end
|
|
392
398
|
|
|
@@ -408,7 +414,7 @@ module Konpeito
|
|
|
408
414
|
|
|
409
415
|
arity = llvm_generator.variadic_functions[mangled_name] ? -1 : func.params.size - 1
|
|
410
416
|
wrapper = "mrb_wrap_#{mangled_name}"
|
|
411
|
-
mrb_args =
|
|
417
|
+
mrb_args = effective_mrb_args(mangled_name, arity)
|
|
412
418
|
lines << " mrb_define_method(mrb, mrb->object_class, \"#{func_def.name}\", #{wrapper}, #{mrb_args});"
|
|
413
419
|
end
|
|
414
420
|
|
|
@@ -456,13 +462,14 @@ module Konpeito
|
|
|
456
462
|
else
|
|
457
463
|
arity = llvm_func.params.size - 1 # Subtract self
|
|
458
464
|
|
|
459
|
-
# Check if this function has
|
|
460
|
-
#
|
|
461
|
-
# when no keywords are specified
|
|
465
|
+
# Check if this function has keyword args.
|
|
466
|
+
# The kwargs hash arg should be optional — caller may pass only
|
|
467
|
+
# positional args when no keywords are specified.
|
|
462
468
|
func_base_name = mangled_name.sub(/\Arn_/, "")
|
|
463
469
|
kw_info = llvm_generator.keyword_param_functions[func_base_name] ||
|
|
464
470
|
llvm_generator.keyword_param_functions[func_base_name.to_sym]
|
|
465
471
|
kwargs_only = kw_info && kw_info[:regular_count] == 0 && arity == 1
|
|
472
|
+
has_mixed_kwargs = kw_info && kw_info[:regular_count] > 0 && arity > 1
|
|
466
473
|
|
|
467
474
|
lines << "static mrb_value #{wrapper_name}(mrb_state *mrb, mrb_value self) {"
|
|
468
475
|
if kwargs_only
|
|
@@ -470,6 +477,15 @@ module Konpeito
|
|
|
470
477
|
lines << " mrb_value a0 = mrb_nil_value(), _block = mrb_nil_value();"
|
|
471
478
|
lines << " mrb_get_args(mrb, \"|o&\", &a0, &_block);"
|
|
472
479
|
lines << " if (mrb_nil_p(a0)) a0 = mrb_hash_new(mrb);"
|
|
480
|
+
elsif has_mixed_kwargs
|
|
481
|
+
# Positional args + optional kwargs hash — last arg defaults to empty hash
|
|
482
|
+
kw_hash_idx = arity - 1
|
|
483
|
+
req_count = kw_info[:regular_count]
|
|
484
|
+
lines << " mrb_value #{(0...arity).map { |i| "a#{i} = mrb_nil_value()" }.join(', ')}, _block = mrb_nil_value();"
|
|
485
|
+
format_str = "o" * req_count + "|o&"
|
|
486
|
+
args_list = (0...arity).map { |i| "&a#{i}" }.join(", ") + ", &_block"
|
|
487
|
+
lines << " mrb_get_args(mrb, \"#{format_str}\", #{args_list});"
|
|
488
|
+
lines << " if (mrb_nil_p(a#{kw_hash_idx})) a#{kw_hash_idx} = mrb_hash_new(mrb);"
|
|
473
489
|
elsif arity > 0
|
|
474
490
|
lines << " mrb_value #{(0...arity).map { |i| "a#{i}" }.join(', ')}, _block;"
|
|
475
491
|
format_str = "o" * arity + "&"
|
|
@@ -804,6 +820,24 @@ module Konpeito
|
|
|
804
820
|
end
|
|
805
821
|
end
|
|
806
822
|
|
|
823
|
+
# Compute mrb_args for a function, accounting for optional keyword hash.
|
|
824
|
+
# Functions with keyword params can be called with or without the keyword
|
|
825
|
+
# hash argument, so the kwargs arg must be registered as optional.
|
|
826
|
+
def effective_mrb_args(mangled_name, arity)
|
|
827
|
+
return arity_to_mrb_args(arity) if arity <= 0
|
|
828
|
+
|
|
829
|
+
func_base_name = mangled_name.sub(/\Arn_/, "")
|
|
830
|
+
kw_info = llvm_generator.keyword_param_functions[func_base_name] ||
|
|
831
|
+
llvm_generator.keyword_param_functions[func_base_name.to_sym]
|
|
832
|
+
if kw_info
|
|
833
|
+
# Keyword hash is optional — use MRB_ARGS_ARG(required, optional)
|
|
834
|
+
req = kw_info[:regular_count]
|
|
835
|
+
"MRB_ARGS_ARG(#{req}, #{arity - req})"
|
|
836
|
+
else
|
|
837
|
+
arity_to_mrb_args(arity)
|
|
838
|
+
end
|
|
839
|
+
end
|
|
840
|
+
|
|
807
841
|
def resolve_superclass_mrb_expr(superclass, non_native_classes)
|
|
808
842
|
return "mrb->object_class" unless superclass
|
|
809
843
|
|
|
@@ -96,6 +96,90 @@ void konpeito_pop_block(void) {
|
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
/* Forward declarations for yield target stack and nested yield support */
|
|
100
|
+
static mrb_value konpeito_get_block(void);
|
|
101
|
+
static konpeito_native_cb_entry *konpeito_get_native_cb(void);
|
|
102
|
+
mrb_value rb_yield(mrb_value val);
|
|
103
|
+
mrb_value rb_yield_values2(int argc, const mrb_value *argv);
|
|
104
|
+
|
|
105
|
+
/* ================================================================
|
|
106
|
+
* Yield target stack for nested yield
|
|
107
|
+
*
|
|
108
|
+
* When a method receives a block and its body (via nested block
|
|
109
|
+
* callbacks) calls yield, the global block stack top points to the
|
|
110
|
+
* innermost callback, not the method's block.
|
|
111
|
+
*
|
|
112
|
+
* The yield target stack captures the block at method entry so that
|
|
113
|
+
* yield inside any nested callback can find the correct target.
|
|
114
|
+
* ================================================================ */
|
|
115
|
+
|
|
116
|
+
static mrb_value konpeito_yield_target_block[KONPEITO_MAX_BLOCK_STACK];
|
|
117
|
+
static konpeito_native_cb_entry konpeito_yield_target_native[KONPEITO_MAX_BLOCK_STACK];
|
|
118
|
+
static int konpeito_yield_target_depth = 0;
|
|
119
|
+
|
|
120
|
+
void konpeito_push_yield_target(void) {
|
|
121
|
+
if (konpeito_yield_target_depth < KONPEITO_MAX_BLOCK_STACK) {
|
|
122
|
+
/* Capture the current top of block_stack as the yield target */
|
|
123
|
+
konpeito_yield_target_block[konpeito_yield_target_depth] = konpeito_get_block();
|
|
124
|
+
konpeito_native_cb_entry *native = konpeito_get_native_cb();
|
|
125
|
+
if (native) {
|
|
126
|
+
konpeito_yield_target_native[konpeito_yield_target_depth] = *native;
|
|
127
|
+
} else {
|
|
128
|
+
konpeito_yield_target_native[konpeito_yield_target_depth].func = NULL;
|
|
129
|
+
}
|
|
130
|
+
konpeito_yield_target_depth++;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
void konpeito_pop_yield_target(void) {
|
|
135
|
+
if (konpeito_yield_target_depth > 0) {
|
|
136
|
+
konpeito_yield_target_depth--;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/* Yield to the enclosing method's block (not the immediate callback).
|
|
141
|
+
* Used by yield inside block callbacks to propagate correctly. */
|
|
142
|
+
mrb_value konpeito_yield_to_method_block(mrb_value val) {
|
|
143
|
+
mrb_state *mrb = konpeito_mrb_state;
|
|
144
|
+
|
|
145
|
+
if (konpeito_yield_target_depth > 0) {
|
|
146
|
+
konpeito_native_cb_entry *target =
|
|
147
|
+
&konpeito_yield_target_native[konpeito_yield_target_depth - 1];
|
|
148
|
+
if (target->func) {
|
|
149
|
+
mrb_value argv[1];
|
|
150
|
+
argv[0] = val;
|
|
151
|
+
return target->func(val, target->data2, 1, argv);
|
|
152
|
+
}
|
|
153
|
+
mrb_value block = konpeito_yield_target_block[konpeito_yield_target_depth - 1];
|
|
154
|
+
if (!mrb_nil_p(block)) {
|
|
155
|
+
return mrb_funcall(mrb, block, "call", 1, val);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/* Fallback to normal yield */
|
|
160
|
+
return rb_yield(val);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
mrb_value konpeito_yield_to_method_block_values(int argc, const mrb_value *argv) {
|
|
164
|
+
mrb_state *mrb = konpeito_mrb_state;
|
|
165
|
+
|
|
166
|
+
if (konpeito_yield_target_depth > 0) {
|
|
167
|
+
konpeito_native_cb_entry *target =
|
|
168
|
+
&konpeito_yield_target_native[konpeito_yield_target_depth - 1];
|
|
169
|
+
if (target->func) {
|
|
170
|
+
mrb_value yielded = (argc > 0) ? argv[0] : mrb_nil_value();
|
|
171
|
+
return target->func(yielded, target->data2, argc, argv);
|
|
172
|
+
}
|
|
173
|
+
mrb_value block = konpeito_yield_target_block[konpeito_yield_target_depth - 1];
|
|
174
|
+
if (!mrb_nil_p(block)) {
|
|
175
|
+
mrb_sym call_sym = mrb_intern_cstr(mrb, "call");
|
|
176
|
+
return mrb_funcall_argv(mrb, block, call_sym, argc, argv);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return rb_yield_values2(argc, argv);
|
|
181
|
+
}
|
|
182
|
+
|
|
99
183
|
static mrb_value konpeito_get_block(void) {
|
|
100
184
|
if (konpeito_block_stack_depth > 0) {
|
|
101
185
|
return konpeito_block_stack[konpeito_block_stack_depth - 1];
|
|
@@ -1052,3 +1136,26 @@ void konpeito_mrb_data_init(mrb_value obj, void *ptr, const mrb_data_type *type)
|
|
|
1052
1136
|
|
|
1053
1137
|
/* mrb_top_self wrapper */
|
|
1054
1138
|
mrb_value konpeito_mrb_top_self(mrb_state *mrb) { return mrb_top_self(mrb); }
|
|
1139
|
+
|
|
1140
|
+
/* ================================================================
|
|
1141
|
+
* Live resize bridge — calls Ruby _kui_resize_frame() from C
|
|
1142
|
+
* ================================================================ */
|
|
1143
|
+
|
|
1144
|
+
/* Forward declaration from clay_native.c */
|
|
1145
|
+
typedef void (*clay_frame_fn)(void);
|
|
1146
|
+
extern void konpeito_clay_set_resize_frame_fn(clay_frame_fn fn);
|
|
1147
|
+
|
|
1148
|
+
static void konpeito_resize_frame_bridge(void) {
|
|
1149
|
+
mrb_state *mrb = konpeito_mrb_state;
|
|
1150
|
+
if (!mrb) return;
|
|
1151
|
+
int ai = mrb_gc_arena_save(mrb);
|
|
1152
|
+
mrb_funcall(mrb, mrb_top_self(mrb), "_kui_resize_frame", 0);
|
|
1153
|
+
if (mrb->exc) {
|
|
1154
|
+
mrb->exc = NULL; /* swallow errors during resize */
|
|
1155
|
+
}
|
|
1156
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
void konpeito_register_resize_callback(void) {
|
|
1160
|
+
konpeito_clay_set_resize_frame_fn(konpeito_resize_frame_bridge);
|
|
1161
|
+
}
|
|
@@ -26,6 +26,7 @@ module Clay
|
|
|
26
26
|
def self.layout(dir, pl, pr, pt, pb, gap, swt, swv, sht, shv, ax, ay) end
|
|
27
27
|
def self.bg(r, g, b, a, corner_radius) end
|
|
28
28
|
def self.border(r, g, b, a, top, right, bottom, left, corner_radius) end
|
|
29
|
+
def self.set_custom(chart_id) end
|
|
29
30
|
def self.scroll(horizontal, vertical) end
|
|
30
31
|
def self.floating(ox, oy, z, att_elem, att_parent) end
|
|
31
32
|
|
|
@@ -33,6 +34,7 @@ module Clay
|
|
|
33
34
|
def self.text(text, font_id, font_size, r, g, b, a, wrap) end
|
|
34
35
|
def self.set_measure_text_raylib() end
|
|
35
36
|
def self.load_font(path, size) end
|
|
37
|
+
def self.load_font_cjk(path, size) end
|
|
36
38
|
|
|
37
39
|
# Render Command Access
|
|
38
40
|
def self.cmd_type(index) end
|
|
@@ -48,10 +50,18 @@ module Clay
|
|
|
48
50
|
def self.cmd_font_id(index) end
|
|
49
51
|
def self.cmd_font_size(index) end
|
|
50
52
|
def self.cmd_corner_radius(index) end
|
|
53
|
+
def self.cmd_ix(index) end
|
|
54
|
+
def self.cmd_iy(index) end
|
|
55
|
+
def self.cmd_iw(index) end
|
|
56
|
+
def self.cmd_ih(index) end
|
|
57
|
+
def self.cmd_custom_data(index) end
|
|
51
58
|
def self.cmd_border_width_top(index) end
|
|
52
59
|
|
|
53
60
|
# Bulk Rendering
|
|
54
61
|
def self.render_raylib() end
|
|
62
|
+
def self.set_bg_color(r, g, b) end
|
|
63
|
+
def self.is_resizing() end
|
|
64
|
+
def self.register_resize_callback() end
|
|
55
65
|
|
|
56
66
|
# Scroll
|
|
57
67
|
def self.update_scroll(dx, dy, dt) end
|
|
@@ -63,4 +73,20 @@ module Clay
|
|
|
63
73
|
def self.sizing_percent() end
|
|
64
74
|
def self.left_to_right() end
|
|
65
75
|
def self.top_to_bottom() end
|
|
76
|
+
|
|
77
|
+
# Text Buffer System
|
|
78
|
+
def self.textbuf_clear(id) end
|
|
79
|
+
def self.textbuf_copy(dst, src) end
|
|
80
|
+
def self.textbuf_putchar(id, ch) end
|
|
81
|
+
def self.textbuf_backspace(id) end
|
|
82
|
+
def self.textbuf_delete(id) end
|
|
83
|
+
def self.textbuf_cursor_left(id) end
|
|
84
|
+
def self.textbuf_cursor_right(id) end
|
|
85
|
+
def self.textbuf_cursor_home(id) end
|
|
86
|
+
def self.textbuf_cursor_end(id) end
|
|
87
|
+
def self.textbuf_len(id) end
|
|
88
|
+
def self.textbuf_cursor(id) end
|
|
89
|
+
def self.textbuf_render(id, fid, fsz, r, g, b) end
|
|
90
|
+
def self.textbuf_render_range(id, start_pos, end_pos, fid, fsz, r, g, b) end
|
|
91
|
+
def self.text_char(ch, fid, fsz, r, g, b) end
|
|
66
92
|
end
|