HS: possessive expression via its (+1 test)
Two generator changes: (a) `parse_run_locals` for Pattern 2
(`var R = await run(...)`) now recognises `result: <literal>` in the
opts dict and binds it to `it` so `run("its foo", {result: {foo: "foo"}})`
produces `(eval-hs-locals "its foo" (list (list (quote it) {:foo "foo"})))`.
Also adds the same extraction to Pattern 1 (`expect(run(...)).toBe(...)`).
(b) `_hs-wrap-body` emitted by the generator no longer shadows `it` to
nil — it only binds `event` — so eval-hs-locals's outer `it` binding is
visible inside the wrapped body. `eval-hs` still binds `it` nil at its
own `fn` wrapper so nothing regresses.
Suite hs-upstream-expressions/possessiveExpression: 22/23 → 23/23.
Smoke 0-195: 162/195 unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -27,8 +27,10 @@
|
|||||||
;; bare expressions (e.g. `foo.foo`) get the expression value back.
|
;; bare expressions (e.g. `foo.foo`) get the expression value back.
|
||||||
(define _hs-wrap-body
|
(define _hs-wrap-body
|
||||||
(fn (sx)
|
(fn (sx)
|
||||||
|
;; Wrap body to capture return via `it`. `event` default is always nil.
|
||||||
|
;; `it` is NOT shadowed here — callers (eval-hs-locals) may pre-bind it.
|
||||||
(list (quote let)
|
(list (quote let)
|
||||||
(list (list (quote it) nil) (list (quote event) nil))
|
(list (list (quote event) nil))
|
||||||
(list (quote let)
|
(list (quote let)
|
||||||
(list (list (quote _ret) sx))
|
(list (list (quote _ret) sx))
|
||||||
(list (quote if) (list (quote nil?) (quote _ret)) (quote it) (quote _ret))))))
|
(list (quote if) (list (quote nil?) (quote _ret)) (quote it) (quote _ret))))))
|
||||||
@@ -5679,7 +5681,7 @@
|
|||||||
(dom-append (dom-body) _el-pDiv)
|
(dom-append (dom-body) _el-pDiv)
|
||||||
))
|
))
|
||||||
(deftest "can access its properties"
|
(deftest "can access its properties"
|
||||||
(assert= (eval-hs "its foo") "foo")
|
(assert= (eval-hs-locals "its foo" (list (list (quote it) {:foo "foo"}))) "foo")
|
||||||
)
|
)
|
||||||
(deftest "can access multiple basic attributes"
|
(deftest "can access multiple basic attributes"
|
||||||
(hs-cleanup!)
|
(hs-cleanup!)
|
||||||
|
|||||||
@@ -1760,6 +1760,14 @@ def generate_eval_only_test(test, idx):
|
|||||||
extra.append((m2.group(1), js_val_to_sx(m2.group(2).strip())))
|
extra.append((m2.group(1), js_val_to_sx(m2.group(2).strip())))
|
||||||
if me_val_match:
|
if me_val_match:
|
||||||
extra.append(('me', js_val_to_sx(me_val_match.group(1))))
|
extra.append(('me', js_val_to_sx(me_val_match.group(1))))
|
||||||
|
# `result: X` (or `it: X`) binds `it` — upstream `run("expr", { result: ... })`
|
||||||
|
# uses the value as the implicit `it` for possessive expressions like `its foo`.
|
||||||
|
result_match = re.search(
|
||||||
|
r'\b(?:result|it):\s*(\[[^\]]*\]|\{[^}]*(?:\{[^}]*\}[^}]*)?\}|"[^"]*"|\'[^\']*\'|[\w.]+)',
|
||||||
|
opts_str,
|
||||||
|
)
|
||||||
|
if result_match:
|
||||||
|
extra.append(('it', js_val_to_sx(result_match.group(1))))
|
||||||
if me_num_match and not (window_setups or extra):
|
if me_num_match and not (window_setups or extra):
|
||||||
assertions.append(f' (assert= (eval-hs-with-me "{hs_expr}" {me_num_match.group(1)}) {expected_sx})')
|
assertions.append(f' (assert= (eval-hs-with-me "{hs_expr}" {me_num_match.group(1)}) {expected_sx})')
|
||||||
else:
|
else:
|
||||||
@@ -1917,6 +1925,13 @@ def generate_eval_only_test(test, idx):
|
|||||||
args_str)
|
args_str)
|
||||||
if me_m:
|
if me_m:
|
||||||
pairs.append(('me', js_val_to_sx(me_m.group(1))))
|
pairs.append(('me', js_val_to_sx(me_m.group(1))))
|
||||||
|
# `result: <literal>` binds `it` — upstream `run("its X", {result: obj})`
|
||||||
|
# passes `obj` as the implicit `it` for possessive expressions.
|
||||||
|
result_m = re.search(
|
||||||
|
r'\bresult:\s*(\{[^}]*(?:\{[^}]*\}[^}]*)?\}|\[[^\]]*\]|"[^"]*"|\'[^\']*\'|\d+(?:\.\d+)?)',
|
||||||
|
args_str)
|
||||||
|
if result_m:
|
||||||
|
pairs.append(('it', js_val_to_sx(result_m.group(1))))
|
||||||
lm = re.search(r'locals:\s*\{', args_str)
|
lm = re.search(r'locals:\s*\{', args_str)
|
||||||
if not lm:
|
if not lm:
|
||||||
return pairs
|
return pairs
|
||||||
@@ -2453,8 +2468,10 @@ output.append(';; mutate `it` (e.g. `pick first 3 of arr; set $test to it`) get
|
|||||||
output.append(';; bare expressions (e.g. `foo.foo`) get the expression value back.')
|
output.append(';; bare expressions (e.g. `foo.foo`) get the expression value back.')
|
||||||
output.append('(define _hs-wrap-body')
|
output.append('(define _hs-wrap-body')
|
||||||
output.append(' (fn (sx)')
|
output.append(' (fn (sx)')
|
||||||
|
output.append(' ;; Wrap body to capture return via `it`. `event` default is always nil.')
|
||||||
|
output.append(' ;; `it` is NOT shadowed here — callers (eval-hs-locals) may pre-bind it.')
|
||||||
output.append(' (list (quote let)')
|
output.append(' (list (quote let)')
|
||||||
output.append(' (list (list (quote it) nil) (list (quote event) nil))')
|
output.append(' (list (list (quote event) nil))')
|
||||||
output.append(' (list (quote let)')
|
output.append(' (list (quote let)')
|
||||||
output.append(' (list (list (quote _ret) sx))')
|
output.append(' (list (list (quote _ret) sx))')
|
||||||
output.append(' (list (quote if) (list (quote nil?) (quote _ret)) (quote it) (quote _ret))))))')
|
output.append(' (list (quote if) (list (quote nil?) (quote _ret)) (quote it) (quote _ret))))))')
|
||||||
|
|||||||
Reference in New Issue
Block a user