e7e67e1a40
Closes fieldtest-form-a friction finding #4. `str_concat : (borrow Str, borrow Str) -> Str` ships in the four-site-lockstep pattern established by `str_clone` / `int_to_str` / `bool_to_str` (iter 24.1). The LLM-natural Show-MyType body `(app str_concat "label=" (app int_to_str x))` now parses, checks, builds, and runs end-to-end. Sites touched (lockstep): - runtime/str.c — `ailang_str_concat(a, b)` slab-allocates and memcpys both source payloads into a new heap-Str. - ailang-check/src/builtins.rs — `env.globals.insert("str_concat", Fn { 2x Str borrow, ret Str own, effects [] })` + `list()` row + `install_str_concat_signature` unit test. - ailang-codegen/src/lib.rs — `declare ptr @ailang_str_concat(ptr, ptr)` extern + `lower_app` arm after str_clone + `is_builtin_callable` extension + IR-pin unit test `str_concat_emits_call_to_ailang_str_concat`. - examples/show_user_adt_with_label.ail (new) + crates/ail/tests/ str_concat_e2e.rs (new) — corpus fixture exercising the LLM-natural Show body shape + E2E pin asserting check + build + run produce `Item 42\n`. Lockstep collision repaired: examples/bug_unbound_in_instance_method.ail used `str_concat` as its UNBOUND name (because that was the literal fieldtester repro). Renamed to `format_label` (LLM-author-realistic helper name that will never become a builtin) and updated the pin test `crates/ail/tests/unbound_in_instance_method_pin.rs` accordingly, preserving the regression guard's intent (instance-method-body walked through unbound-var check). DESIGN.md amended: new §"Heap-Str primitives" subsection between the milestone-24 Show-backer enumeration and the existing `Primitive output goes through ...` paragraph, cataloguing all five heap-Str primitives (`int_to_str`, `bool_to_str`, `float_to_str`, `str_clone`, `str_concat`) with signatures, iter origins, and the user-visible-vs-prelude-internal distinction. Show-backer block unchanged. IR snapshots regenerated (hello, list, max3, sum, ws_main) to absorb the new `declare ptr @ailang_str_concat(ptr, ptr)` line in the unconditional extern header — same upkeep pattern as hs.4 which regenerated the same 5 snapshots for the same reason (unconditional declares dead-stripped by clang -O2 when unused). Tests: 559 + 3 = 562 green (E2E pin + builtin-signature test + IR-pin test). Zero re-loops across all 7 tasks.
52 lines
1.4 KiB
LLVM
52 lines
1.4 KiB
LLVM
; AILang generated workspace; entry: ws_main
|
|
source_filename = "ws_main.ail"
|
|
target triple = "<NORMALIZED>"
|
|
|
|
@.str_ws_main_fmt_int_0 = private unnamed_addr constant [6 x i8] c"%lld\0A\00", align 1
|
|
|
|
declare i32 @printf(ptr, ...)
|
|
declare i32 @puts(ptr)
|
|
declare ptr @GC_malloc(i64)
|
|
declare i32 @strcmp(ptr, ptr)
|
|
declare zeroext i1 @ail_str_eq(ptr, ptr)
|
|
declare i32 @ail_str_compare(ptr, ptr)
|
|
declare ptr @ailang_int_to_str(i64)
|
|
declare ptr @ailang_float_to_str(double)
|
|
declare ptr @ailang_bool_to_str(i1)
|
|
declare ptr @ailang_str_clone(ptr)
|
|
declare ptr @ailang_str_concat(ptr, ptr)
|
|
declare i64 @llvm.fptosi.sat.i64.f64(double)
|
|
|
|
@ail_ws_lib_add_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_ws_lib_add_adapter, ptr null }
|
|
@ail_ws_main_main_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_ws_main_main_adapter, ptr null }
|
|
define i64 @ail_ws_lib_add(i64 %arg_a, i64 %arg_b) {
|
|
entry:
|
|
%v1 = add i64 %arg_a, %arg_b
|
|
ret i64 %v1
|
|
}
|
|
|
|
define i64 @ail_ws_lib_add_adapter(ptr %_env, i64 %a0, i64 %a1) {
|
|
entry:
|
|
%r = call i64 @ail_ws_lib_add(i64 %a0, i64 %a1)
|
|
ret i64 %r
|
|
}
|
|
|
|
define i8 @ail_ws_main_main() {
|
|
entry:
|
|
%v1 = call i64 @ail_ws_lib_add(i64 2, i64 3)
|
|
call i32 (ptr, ...) @printf(ptr @.str_ws_main_fmt_int_0, i64 %v1)
|
|
ret i8 0
|
|
}
|
|
|
|
define i8 @ail_ws_main_main_adapter(ptr %_env) {
|
|
entry:
|
|
%r = call i8 @ail_ws_main_main()
|
|
ret i8 %r
|
|
}
|
|
|
|
|
|
define i32 @main() {
|
|
call i8 @ail_ws_main_main()
|
|
ret i32 0
|
|
}
|