diff --git a/css/elements.css b/css/elements.css index 6384489b..6becbebc 100644 --- a/css/elements.css +++ b/css/elements.css @@ -5,7 +5,7 @@ --link-foreground-color: #206ca7; --link-hover-foreground-color: #239dee; - --user-code-foreground-color: brown; + --annotation-foreground-color: brown; --var-foreground-color: #218379; @@ -89,7 +89,7 @@ --link-foreground-color: #439de2; --link-hover-foreground-color: #80cafb; - --user-code-foreground-color: brown; + --annotation-foreground-color: brown; --var-foreground-color: #4fb6ab; @@ -337,9 +337,9 @@ span.e-user-code { a.e-user-code::before, span.e-user-code::before { display: none; - color: var(--user-code-foreground-color); + color: var(--annotation-foreground-color); background-color: var(--background-color); - border: 2pt solid var(--user-code-foreground-color); + border: 2pt solid var(--annotation-foreground-color); padding: 0.3ex; margin: 0 0.25em 0 0; line-height: normal; @@ -354,12 +354,12 @@ span.e-user-code::before { a.e-user-code:hover::before, span.e-user-code:hover::before { - background-color: var(--user-code-foreground-color); + background-color: var(--annotation-foreground-color); color: var(--background-color); } -html.show-ao-annotations a.e-user-code::before, -html.show-ao-annotations span.e-user-code::before { +html.show-uc-annotations a.e-user-code::before, +html.show-uc-annotations span.e-user-code::before { display: inline-block; } @@ -462,6 +462,24 @@ emu-val { font-weight: bold; } +emu-alg li.exit:not(emu-alg ol.ac-body > li:last-child):not(emu-alg > ol > li:last-child)::before { + display: none; + border: 2pt solid var(--annotation-foreground-color); + font-size: small; + color: var(--annotation-foreground-color); + padding: 0 0.25em; + background-color: var(--background-color); + content: '⏎'; + margin-right: 0.25em; + line-height: 15px; + vertical-align: middle; +} + +html.show-early-exits emu-alg li.exit:not(emu-alg ol.ac-body > li:last-child):not(emu-alg > ol > li:last-child)::before { + display: inline-block; +} + + /* depth 1 */ emu-alg ol, /* depth 4 */ diff --git a/js/menu.js b/js/menu.js index 59349fad..4b1a8515 100644 --- a/js/menu.js +++ b/js/menu.js @@ -1111,7 +1111,9 @@ function doShortcut(e) { location = 'multipage/' + hash; } } else if (e.key === 'u') { - document.documentElement.classList.toggle('show-ao-annotations'); + document.documentElement.classList.toggle('show-uc-annotations'); + } else if (e.key === 'e') { + document.documentElement.classList.toggle('show-early-exits'); } else if (e.key === '?') { document.getElementById('shortcuts-help').classList.toggle('active'); } diff --git a/src/Algorithm.ts b/src/Algorithm.ts index 9a5df160..bbbadcd6 100644 --- a/src/Algorithm.ts +++ b/src/Algorithm.ts @@ -78,6 +78,21 @@ export default class Algorithm extends Builder { html = html.replace(/[ \t]+([»}])/g, ' $1'); node.innerHTML = html; + // mark steps containing early exits (return/throw/?) with the early-exit class + const earlyExitIndicator = /\b(?:return|throw)\b|[\s(]\?\s/i; + // these are macros in ECMA-262 that expand to steps that include a return/throw/? + const earlyExitMacro = /\bIfAbrupt(?:CloseIterator|CloseAsyncIterator|RejectPromise)\(/; + const note = /^(?:NOTE|Assert): /; + for (const ol of node.querySelectorAll('ol')) { + const items = ol.children; + for (let i = 0; i < items.length; i++) { + const text = ownTextContent(items[i]); + if ((earlyExitIndicator.test(text) || earlyExitMacro.test(text)) && !note.test(text)) { + items[i].classList.add('exit'); + } + } + } + const labeledStepEntries: StepBiblioEntry[] = []; const replaces = node.getAttribute('replaces-step'); if (replaces) { diff --git a/src/Spec.ts b/src/Spec.ts index 122d3894..cf675b84 100644 --- a/src/Spec.ts +++ b/src/Spec.ts @@ -1328,6 +1328,7 @@ ${await utils.readFile(path.join(__dirname, '../js/multipage.js'))}
?uem/p?ue/pThe
The
The abstract operation UseIt takes argument module (a