Skip to content

Commit 68ef31d

Browse files
add a visual indicator to AC bodies (#684)
1 parent c6d1ea1 commit 68ef31d

6 files changed

Lines changed: 50 additions & 12 deletions

File tree

css/elements.css

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@
7575

7676
--attributes-tag-foreground-color: #884400;
7777

78+
--ac-body-border-color: #ddd;
79+
7880
--figure-background: #fff;
7981
}
8082

@@ -157,6 +159,8 @@
157159

158160
--attributes-tag-foreground-color: #e6a96d;
159161

162+
--ac-body-border-color: #555;
163+
160164
--figure-background: #fff;
161165
}
162166
}
@@ -496,6 +500,12 @@ emu-alg ol.nested-lots ol {
496500
list-style-type: lower-roman;
497501
}
498502

503+
emu-alg ol.ac-body {
504+
border-left: 3px solid var(--ac-body-border-color);
505+
border-radius: 0 0 0 20px;
506+
padding-bottom: 5px;
507+
}
508+
499509
emu-eqn {
500510
display: block;
501511
margin-left: 4em;

src/Algorithm.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { PartialBiblioEntry, StepBiblioEntry } from './Biblio';
44

55
import Builder from './Builder';
66
import { SPECIAL_KINDS_MAP, SPECIAL_KINDS } from './Clause';
7-
import { warnEmdFailure, wrapEmdFailure } from './utils';
7+
import { isAbstractClosureHeader, ownTextContent, warnEmdFailure, wrapEmdFailure } from './utils';
88
import { collectNonterminalsFromEmd } from './lint/utils';
99
import * as emd from 'ecmarkdown';
1010

@@ -119,6 +119,16 @@ export default class Algorithm extends Builder {
119119
}
120120
}
121121

122+
for (const step of node.querySelectorAll('li')) {
123+
if (isAbstractClosureHeader(ownTextContent(step))) {
124+
for (const ol of step.children) {
125+
if (ol.tagName === 'OL') {
126+
ol.classList.add('ac-body');
127+
}
128+
}
129+
}
130+
}
131+
122132
for (const step of node.querySelectorAll(kindSelector)) {
123133
// prettier-ignore
124134
const attributes = SPECIAL_KINDS

src/lint/rules/variable-use-def.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import type {
88
import type { Reporter } from '../algorithm-error-reporter-type';
99
import type { Seq } from '../../expr-parser';
1010
import { walk as walkExpr } from '../../expr-parser';
11-
import { offsetToLineAndColumn } from '../../utils';
11+
import { isAbstractClosureHeader, offsetToLineAndColumn } from '../../utils';
1212

1313
/*
1414
Ecmaspeak scope rules are a bit weird.
@@ -244,10 +244,7 @@ function walkAlgorithm(
244244
}
245245

246246
// handle abstract closures
247-
if (
248-
last?.name === 'text' &&
249-
/ performs the following steps (atomically )?when called:$/.test(last.contents)
250-
) {
247+
if (last?.name === 'text' && isAbstractClosureHeader(last.contents)) {
251248
if (first.name === 'text' && first.contents === 'Let ' && isVariable(expr.items[1])) {
252249
const closureName = expr.items[1];
253250
scope.declare(closureName.contents, closureName);

src/utils.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -284,10 +284,7 @@ export function doesEffectPropagateToParent(node: Element, effect: string) {
284284
// This is super hacky. It's checking the output of ecmarkdown.
285285
if (parent.tagName !== 'LI') continue;
286286

287-
if (
288-
effect === 'user-code' &&
289-
/be a new (\w+ )*Abstract Closure/.test(parent.textContent ?? '')
290-
) {
287+
if (effect === 'user-code' && isAbstractClosureHeader(ownTextContent(parent))) {
291288
return false;
292289
}
293290

@@ -343,3 +340,17 @@ export function withOrdinalSuffix(n: number): string {
343340
const suffixes = { one: 'st', two: 'nd', few: 'rd', other: 'th' };
344341
return `${n}${suffixes[rule as keyof typeof suffixes]}`;
345342
}
343+
344+
const acHeaderRe = / performs the following steps (atomically )?when called:$/;
345+
export function isAbstractClosureHeader(text: string): boolean {
346+
return acHeaderRe.test(text);
347+
}
348+
349+
export function ownTextContent(el: Element): string {
350+
let text = '';
351+
for (const child of el.childNodes) {
352+
if (child.nodeType === 1 && (child as Element).tagName === 'OL') continue;
353+
text += child.textContent;
354+
}
355+
return text;
356+
}

test/baselines/generated-reference/assets-inline.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1693,6 +1693,8 @@
16931693
16941694
--attributes-tag-foreground-color: #884400;
16951695
1696+
--ac-body-border-color: #ddd;
1697+
16961698
--figure-background: #fff;
16971699
}
16981700
@@ -1775,6 +1777,8 @@
17751777
17761778
--attributes-tag-foreground-color: #e6a96d;
17771779
1780+
--ac-body-border-color: #555;
1781+
17781782
--figure-background: #fff;
17791783
}
17801784
}
@@ -2114,6 +2118,12 @@
21142118
list-style-type: lower-roman;
21152119
}
21162120
2121+
emu-alg ol.ac-body {
2122+
border-left: 3px solid var(--ac-body-border-color);
2123+
border-radius: 0 0 0 20px;
2124+
padding-bottom: 5px;
2125+
}
2126+
21172127
emu-eqn {
21182128
display: block;
21192129
margin-left: 4em;

test/baselines/generated-reference/effect-user-code.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,13 +111,13 @@ <h1><span class="secnum">16</span> RenderedMeta ( )</h1>
111111
<emu-clause id="sec-make-abstract-closure" type="abstract operation" aoid="MakeAbstractClosure">
112112
<h1><span class="secnum">17</span> MakeAbstractClosure ( )</h1>
113113
<p>The abstract operation MakeAbstractClosure takes no arguments. The user-code effect doesn't propagate through <emu-xref href="#sec-abstract-closure"><a href="https://tc39.es/ecma262/#sec-abstract-closure">Abstract Closure</a></emu-xref> boundaries by recognizing the "be a new <emu-xref href="#sec-abstract-closure"><a href="https://tc39.es/ecma262/#sec-abstract-closure">Abstract Closure</a></emu-xref>" <emu-xref href="#substring"><a href="https://tc39.es/ecma262/#substring">substring</a></emu-xref>. It performs the following steps when called:</p>
114-
<emu-alg><ol><li>Let <var>closure</var> be a new <emu-xref href="#sec-abstract-closure"><a href="https://tc39.es/ecma262/#sec-abstract-closure">Abstract Closure</a></emu-xref> that captures nothing and performs the following steps when called:<ol><li><emu-xref aoid="UserCode" id="_ref_13"><a href="#sec-user-code" class="e-user-code">UserCode</a></emu-xref>().</li></ol></li><li>Return <var>closure</var>.</li></ol></emu-alg>
114+
<emu-alg><ol><li>Let <var>closure</var> be a new <emu-xref href="#sec-abstract-closure"><a href="https://tc39.es/ecma262/#sec-abstract-closure">Abstract Closure</a></emu-xref> that captures nothing and performs the following steps when called:<ol class="ac-body"><li><emu-xref aoid="UserCode" id="_ref_13"><a href="#sec-user-code" class="e-user-code">UserCode</a></emu-xref>().</li></ol></li><li>Return <var>closure</var>.</li></ol></emu-alg>
115115
</emu-clause>
116116

117117
<emu-clause id="sec-make-special-abstract-closure" type="abstract operation" aoid="MakeJobAbstractClosure">
118118
<h1><span class="secnum">18</span> MakeJobAbstractClosure ( )</h1>
119119
<p>The abstract operation MakeJobAbstractClosure takes no arguments. The user-code effect doesn't propagate through specialized <emu-xref href="#sec-abstract-closure"><a href="https://tc39.es/ecma262/#sec-abstract-closure">Abstract Closure</a></emu-xref> boundaries by recognizing the "be a new Something <emu-xref href="#sec-abstract-closure"><a href="https://tc39.es/ecma262/#sec-abstract-closure">Abstract Closure</a></emu-xref>" <emu-xref href="#substring"><a href="https://tc39.es/ecma262/#substring">substring</a></emu-xref>. It performs the following steps when called:</p>
120-
<emu-alg><ol><li>Let <var>closure</var> be a new <emu-xref href="#job"><a href="https://tc39.es/ecma262/#job">Job</a></emu-xref> <emu-xref href="#sec-abstract-closure"><a href="https://tc39.es/ecma262/#sec-abstract-closure">Abstract Closure</a></emu-xref> that captures nothing and performs the following steps when called:<ol><li><emu-xref aoid="UserCode" id="_ref_14"><a href="#sec-user-code" class="e-user-code">UserCode</a></emu-xref>().</li></ol></li><li>Return <var>closure</var>.</li></ol></emu-alg>
120+
<emu-alg><ol><li>Let <var>closure</var> be a new <emu-xref href="#job"><a href="https://tc39.es/ecma262/#job">Job</a></emu-xref> <emu-xref href="#sec-abstract-closure"><a href="https://tc39.es/ecma262/#sec-abstract-closure">Abstract Closure</a></emu-xref> that captures nothing and performs the following steps when called:<ol class="ac-body"><li><emu-xref aoid="UserCode" id="_ref_14"><a href="#sec-user-code" class="e-user-code">UserCode</a></emu-xref>().</li></ol></li><li>Return <var>closure</var>.</li></ol></emu-alg>
121121
</emu-clause>
122122

123123
<emu-clause id="sec-call-make-abstract-closure" type="abstract operation" aoid="CallMakeAbstractClosure">

0 commit comments

Comments
 (0)