Skip to content

Commit 04afccf

Browse files
thefallentreeclaude
andcommitted
Bytecode view: delimit embedded closure bodies
A (: expr :) functional's and an anonymous function's code is EMBEDDED inline in the enclosing function's bytecode right after the F_FUNCTION_CONSTRUCTOR header (make_functional_funp records offset = here into the same program; the interpreter skips the body). The view now shows that: the constructor row gets a 'closure body follows' tag and the body rows a purple gutter bar, computed from the header's 'Code size: N' (functionals) or decimal 'ends at N' (anonymous). FP_LOCAL/FP_EFUN/FP_SIMUL closures have no embedded code and correctly get no marker. Root-caused a repeat of the template-escape trap: \d in webview code must be written doubled or the page receives a plain 'd'. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AXqX4Kf55ArA39suS9cdCv
1 parent bbdfea6 commit 04afccf

1 file changed

Lines changed: 32 additions & 2 deletions

File tree

extension/explorer.js

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,9 @@ function webviewHtml(webview) {
261261
#bc-bar { display: flex; gap: 14px; align-items: center; margin: 4px 0 8px; }
262262
#bc-bar label { cursor: pointer; }
263263
tr.ins.haslink { cursor: pointer; }
264+
tr.ins.fnl td:first-child { border-left: 3px solid var(--vscode-charts-purple, #c586c0); padding-left: 6px; }
265+
tr.ins.fnl .addr { opacity: .9; }
266+
.fnl-tag { color: var(--vscode-charts-purple, #c586c0); font-size: 11px; margin-left: 6px; }
264267
#bc-tip { position: fixed; z-index: 10; display: none; max-width: 640px; overflow: hidden;
265268
background: var(--vscode-editorWidget-background, #252526);
266269
border: 1px solid var(--vscode-focusBorder, #07f); border-radius: 4px;
@@ -621,6 +624,30 @@ function webviewHtml(webview) {
621624
function renderProgramFns(p, outlineByName, isTop) {
622625
let html = '';
623626
for (const fn of p.functions) {
627+
// A (: ... :) functional's body is EMBEDDED inline right after its
628+
// F_FUNCTION_CONSTRUCTOR header (the runtime records offset = here
629+
// and skips it). Delimit those rows so the embedding is visible.
630+
const fnlRanges = [];
631+
for (const ins of fn.instructions) {
632+
const fm = /<functional, (\\d+) args?>: Code size: (\\d+)/.exec(ins.comment);
633+
if (fm) {
634+
const headerLen = ins.hex ? ins.hex.trim().split(/\\s+/).length : 5;
635+
const start = parseInt(ins.addr, 16) + headerLen;
636+
fnlRanges.push([start, start + (+fm[2])]);
637+
ins.isFnlHead = true;
638+
}
639+
// Anonymous closures print their end address in DECIMAL (%04tu).
640+
const am = /<anonymous function, \\d+ args?, \\d+ locals, ends at (\\d+)>/.exec(ins.comment);
641+
if (am) {
642+
const headerLen = ins.hex ? ins.hex.trim().split(/\\s+/).length : 6;
643+
fnlRanges.push([parseInt(ins.addr, 16) + headerLen, parseInt(am[1], 10)]);
644+
ins.isFnlHead = true;
645+
}
646+
}
647+
const inFnl = (addrHex) => {
648+
const a = parseInt(addrHex, 16);
649+
return fnlRanges.some((r) => a >= r[0] && a < r[1]);
650+
};
624651
const o = isTop ? outlineByName.get(fn.name) : null;
625652
html += '<details open><summary>' + esc(fn.signature) +
626653
(o ? ' <a class="link jump" data-l="' + o.line + '" data-c="' + o.col + '">go to source ↗</a>' : '') +
@@ -634,9 +661,12 @@ function webviewHtml(webview) {
634661
}
635662
const inFile = ins.srcFile && model.lpcc.relPath &&
636663
(ins.srcFile === model.lpcc.relPath || '/' + ins.srcFile === model.lpcc.relPath);
637-
html += '<tr id="a' + ins.addr + '" class="ins' + (inFile ? ' haslink' : '') +
664+
const fnlCls = inFnl(ins.addr) ? ' fnl' : '';
665+
html += '<tr id="a' + ins.addr + '" class="ins' + fnlCls + (inFile ? ' haslink' : '') +
638666
(inFile ? '" data-srcl="' + ins.srcLine : '') + '"><td class="addr">' + ins.addr + '</td><td class="hex">' +
639-
esc(ins.hex.length > 26 ? ins.hex.slice(0, 24) + '…' : ins.hex) + '</td><td>' + esc(ins.mnemonic) +
667+
esc(ins.hex.length > 26 ? ins.hex.slice(0, 24) + '…' : ins.hex) + '</td><td>' +
668+
(fnlCls ? '<span class="fnl-tag">│ </span>' : '') + esc(ins.mnemonic) +
669+
(ins.isFnlHead ? ' <span class="fnl-tag">closure body follows ↓</span>' : '') +
640670
'</td><td>' + comment + '</td><td>' +
641671
(ins.srcLine ? '<a class="link src" data-f="' + esc(ins.srcFile) + '" data-l="' + ins.srcLine +
642672
'">' + esc(ins.srcFile.split('/').pop()) + ':' + ins.srcLine + '</a>' : '') +

0 commit comments

Comments
 (0)