1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
//! The implicit parameter must bind every `~` in an expression, not the first.
//!
//! `ish -a` exists to save tokens. It could not be used on the expressions that
//! spend them, because the desugaring built its lambda at the first `~` it
//! reached and then ran to the end of the body:
//!
//! ```text
//! w(~.is_pr) where(fn(__) => __.is_pr) ok
//! w(!~.is_pr && ~.state=="open") where(!fn(__) => __.is_pr && …) broken
//! error: where: expected a lambda, got Bool
//! w(contains(lower(~.title), "x")) where(contains(lower(fn(__) => …))) broken
//! error: lower: expected a string, got Lambda
//! ```
//!
//! One reference worked and two did not, which ruled out six of the ten queries
//! in `benches/agentic/` -- the six with compound predicates. The token-
//! minimised syntax was unusable on the shape that spends the tokens, and
//! nothing caught it because nothing had ever benchmarked `-a`.
//!
//! The lambda is now lifted to the argument of the lambda-taking builtin, with
//! every `~.` in it bound to the same parameter.
use iron_shell::transpile::agentic::transpile_agentic_to_ae;
/// Transpile the stage in pipeline position and return just the stage.
///
/// A bare `w(...)` at statement start is not pipeline position and does not
/// desugar; every realistic use of an implicit parameter is a pipeline stage.
fn stage(src: &str) -> String {
let full = t(&format!("xs|{src}"));
match full.split_once('|') {
Some((_, rhs)) => rhs.trim().to_string(),
None => full,
}
}
fn t(src: &str) -> String {
transpile_agentic_to_ae(src)
.unwrap_or_else(|e| panic!("transpile {src}: {e}"))
.trim()
.to_string()
}
#[test]
fn one_reference_desugars_exactly_as_before() {
// The case that already worked must be untouched, or the fix is a rewrite
// rather than a widening.
// `w(~.is_pr)` keeps the caller's own parentheses around the body
// (`fn(__) => (__.is_pr)`), which is semantically identical and costs the
// agent nothing: the transpiled source is internal, and what is token-
// counted is the agentic text the agent wrote. Assert the binding, not the
// spelling.
let one = stage("w(~.is_pr)");
assert!(
one.contains("where(fn(__) =>") && one.contains("__.is_pr"),
"got: {one}"
);
assert_eq!(one.matches("fn(__)").count(), 1, "got: {one}");
let cmp = stage(r#"w(~.state=="closed")"#);
assert!(
cmp.contains("where(fn(__) =>")
&& cmp.contains(r#"__.state"#)
&& cmp.contains(r#""closed""#),
"got: {cmp}"
);
assert_eq!(cmp.matches("fn(__)").count(), 1, "got: {cmp}");
}
#[test]
fn two_references_share_one_parameter() {
// The defect: this produced `where(!fn(__) => …)`.
let out = stage(r#"w(!~.is_pr&&~.state=="open")"#);
assert!(
out.starts_with("where(fn(__) =>") || out.contains("where(fn(__) =>"),
"the lambda must wrap the whole predicate, got: {out}"
);
assert_eq!(
out.matches("fn(__)").count(),
1,
"two references must share one lambda, not make two: {out}"
);
assert!(
!out.contains("!fn(__)"),
"the negation is still outside the lambda: {out}"
);
}
#[test]
fn a_reference_nested_in_a_call_is_bound_too() {
// The second shape of the defect: `lower(fn(__) => …)`.
let out = stage(r#"w(contains(lower(~.title+" "+~.body),"security"))"#);
assert_eq!(out.matches("fn(__)").count(), 1, "got: {out}");
assert!(
!out.contains("lower(fn(__)"),
"a nested reference still builds its own lambda: {out}"
);
assert!(
out.contains("__.title") && out.contains("__.body"),
"got: {out}"
);
}
#[test]
fn an_explicit_parameter_is_left_alone() {
// `~x:body` names its parameter and must not be hoisted.
let out = stage("w~x:x.is_pr");
assert!(
out.contains("fn(x)") && !out.contains("fn(__)"),
"the explicit-parameter form was rewritten: {out}"
);
}
#[test]
fn a_tilde_inside_a_string_is_not_a_parameter() {
// The substitution runs over source text, so it has to respect literals.
let out = stage(r#"w(~.name=="~.odd")"#);
assert!(
out.contains(r#""~.odd""#),
"the literal was rewritten: {out}"
);
assert_eq!(
out.matches("__").count(),
2,
"expected one fn(__) and one __.name: {out}"
);
}
#[test]
fn an_expression_with_no_implicit_parameter_is_unchanged() {
// The hoist must return None and leave the old path alone.
let out = stage(r#"w(fn(r) => r.is_pr)"#);
assert!(
out.contains("fn(r) => r.is_pr"),
"an explicit lambda was disturbed: {out}"
);
assert!(!out.contains("fn(__)"), "a parameter was invented: {out}");
}
#[test]
fn the_bare_dot_form_still_works() {
// `w.size>1k` is sugar for `w~.size>1k` and is the measured token lever.
let out = stage("w.is_pr");
assert!(out.contains("where(fn(__) => __.is_pr)"), "got: {out}");
}
// ── non-vacuity ─────────────────────────────────────────────────────────
#[test]
fn non_vacuity_the_transpiler_is_producing_ironshell() {
// If `transpile_agentic_to_ae` echoed its input, several assertions above
// would hold for the wrong reason.
let out = stage("w(~.is_pr)");
assert!(out.contains("where"), "the builtin was not expanded: {out}");
assert_ne!(out.trim(), "w(~.is_pr)", "the input came back unchanged");
// And the broken emission must now be impossible.
let compound = stage(r#"w(!~.is_pr&&~.state=="open")"#);
assert!(
!compound.contains("!fn(__)"),
"the first-reference-only desugaring is back: {compound}"
);
}