HS: return via raise/guard, def param fix, script block extraction

- Compiler: return compiles to (raise (list "hs-return" value))
- Compiler: def wraps body in guard to catch hs-return exceptions
- Compiler: def params extract name from (ref name) nodes
- Test generator: extract <script type="text/hyperscript"> blocks
  and compile def functions as setup before tests
- Test generator: add eval-hs-with-me for {me: N} opts

The return mechanism enables repeat-forever with early exit via return.
Direct SX guard/raise works (returns correct value), but the compiled
HS repeat-forever thunk body needs further debugging for full coverage.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-16 17:26:43 +00:00
parent ca9196a693
commit 2285ea3e49
3 changed files with 125 additions and 209 deletions

View File

@@ -25,11 +25,25 @@ with open(INPUT) as f:
# ── HTML parsing ──────────────────────────────────────────────────
def extract_hs_scripts(html):
"""Extract <script type='text/hyperscript'>...</script> content blocks."""
scripts = []
for m in re.finditer(
r"<script\s+type=['\"]text/hyperscript['\"]>(.*?)</script>",
html, re.DOTALL
):
scripts.append(m.group(1).strip())
return scripts
def parse_html(html):
"""Parse HTML into list of element dicts with parent-child relationships.
Uses Python's html.parser for reliability with same-tag siblings."""
from html.parser import HTMLParser
# Remove script tags before parsing elements (they're handled separately)
html = re.sub(r"<script\s+type=['\"]text/hyperscript['\"]>.*?</script>", '', html, flags=re.DOTALL)
# Remove | separators
html = html.replace(' | ', '')
@@ -588,10 +602,20 @@ def generate_test_chai(test, elements, var_names, idx):
actions = parse_action(test['action'], ref)
checks = parse_checks(test['check'])
# Extract <script type="text/hyperscript"> blocks
hs_scripts = extract_hs_scripts(test.get('html', ''))
lines = []
lines.append(f' (deftest "{test["name"]}"')
lines.append(' (hs-cleanup!)')
# Compile HS script blocks as setup (def functions etc.)
for script in hs_scripts:
# Clean whitespace
clean = ' '.join(script.split())
escaped = clean.replace('\\', '\\\\').replace('"', '\\"')
lines.append(f' (eval-expr-cek (hs-to-sx (hs-compile "{escaped}")))')
bindings = [f'({var_names[i]} (dom-create-element "{el["tag"]}"))' for i, el in enumerate(elements)]
lines.append(f' (let ({" ".join(bindings)})')