Files
rose-ash/plans/designs/f2-tell.md
giles 985671cd76 hs: query targets, prolog hook, loop scripts, new plans, WASM regen
Hyperscript compiler/runtime:
- query target support in set/fire/put commands
- hs-set-prolog-hook! / hs-prolog-hook / hs-prolog in runtime
- runtime log-capture cleanup

Scripts: sx-loops-up/down, sx-hs-e-up/down, sx-primitives-down
Plans: datalog, elixir, elm, go, koka, minikanren, ocaml, hs-bucket-f,
       designs (breakpoint, null-safety, step-limit, tell, cookies, eval,
       plugin-system)
lib/prolog/hs-bridge.sx: initial hook-based bridge draft
lib/common-lisp/tests/runtime.sx: CL runtime tests

WASM: regenerate sx_browser.bc.js from updated hs sources

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 09:19:56 +00:00

4.1 KiB
Raw Blame History

F2 — tell Semantics Fix (+3)

Suite: hs-upstream-tell
Target: 3 failing tests out of 10. 7 already pass.

1. Failing tests

"attributes refer to the thing being told"

on click tell #d2 then put @foo into me

d2 has attribute foo="bar". After click, d1's text content should be "bar".
@foo is an attribute ref — it should resolve against the told element (d2), not the event target (d1).
Currently gets "" — attribute resolves against d1, which has no foo attribute.

"your symbol represents the thing being told"

on click tell #d2 then put your innerText into me

d2 has innerText "foo". After click, d1's text content should be "foo".
your is the possessive of you — inside a tell block, you/your should bind to the told element.
Currently gets "".

"does not overwrite the me symbol"

on click add .foo then tell #d2 then add .bar to me

After click: d1 should have both .foo and .bar; d2 should have neither.
me inside the tell block must still refer to d1 (the original event target).
Currently: assertion fails — .bar is going to d2 instead of d1.

2. What the 7 passing tests reveal about current behaviour

The passing tests include:

  • you symbol represents the thing being toldadd .bar to you adds to d2 ✓
  • establishes a proper beingTold symbol — bare add .bar (no target) adds to the told element ✓
  • restores a proper implicit me symbol — after tell block ends, bare commands target d1 again ✓
  • yourself attribute also worksremove yourself inside tell removes d2 ✓

So you, yourself, and bare implicit target all work. The three bugs are:

  1. Attribute refs (@foo) don't resolve against the told element
  2. your (possessive of you) doesn't resolve
  3. me is being rebound to the told element instead of kept as d1

3. Root cause analysis

Inside a tell X block, the runtime sets the implicit target to X. The three failures suggest:

Bug A — attribute refs: @foo resolves via a property-access path that reads from the current event target (me/self), not from the implicit tell target. The tell block sets implicit target but the attribute ref lookup skips it.

Bug B — your: your is parsed as a possessive modifier expecting you to be bound. If you is not bound in the tell scope (and only the implicit target is set), your X fails to resolve.

Bug C — me rebinding: The tell command saves/restores me but the save/restore is either not happening or is restoring the wrong value. me inside the block should remain d1 while the implicit default target is d2.

4. Fix

In lib/hyperscript/runtime.sx, find the tell command handler (search for hs-tell or the tell dispatch branch).

The correct semantics:

  • Save current me value
  • Set implicit target (used by bare commands like add .bar) to the told element
  • Bind you = told element (so you, your, yourself work)
  • Do not rebind me — keep it as the original event target
  • Restore implicit target and unbind you after the block

For attribute refs (@foo): resolve against the current implicit target (told element), not against me. Find where @attr expressions are evaluated and ensure they read from the implicit target when inside a tell block.

5. Implementation checklist

  1. sx_find_all in lib/hyperscript/runtime.sx for tell handler.
  2. sx_read_subtree on the tell handler — verify save/restore of me vs implicit target.
  3. Fix me rebinding: save old implicit target, set new one, do NOT touch me.
  4. Bind you/your/yourself to told element in the tell scope env.
  5. Find attribute ref (@) evaluation — ensure it reads from implicit target.
  6. Run hs_test_run suite="hs-upstream-tell" — expect 10/10.
  7. Run smoke 0195 — no regressions.
  8. Commit: HS: tell — fix me rebinding, your/attribute-ref resolution (+3)

6. Risk

Medium. The 7 passing tests constrain what can change — the fix must preserve you, yourself, bare implicit target, and restore-after-tell semantics. The three bugs are independent enough that they can be fixed one at a time and verified after each.