Skip to content

Commit a9dbbbb

Browse files
authored
Merge pull request #144 from ethdebug/fancy-contexts
Define a few new context properties
2 parents 193c181 + 38b266d commit a9dbbbb

File tree

15 files changed

+321
-64
lines changed

15 files changed

+321
-64
lines changed

packages/format/src/types/program/context.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,16 @@ testSchemaGuards("ethdebug/format/program/context", [
1818
schema: "schema:ethdebug/format/program/context/remark",
1919
guard: Context.isRemark
2020
},
21+
{
22+
schema: "schema:ethdebug/format/program/context/pick",
23+
guard: Context.isPick
24+
},
25+
{
26+
schema: "schema:ethdebug/format/program/context/gather",
27+
guard: Context.isGather
28+
},
29+
{
30+
schema: "schema:ethdebug/format/program/context/frame",
31+
guard: Context.isFrame
32+
},
2133
] as const);

packages/format/src/types/program/context.ts

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,18 @@ import { Pointer, isPointer } from "../pointer";
55
export type Context =
66
| Context.Code
77
| Context.Variables
8-
| Context.Remark;
8+
| Context.Remark
9+
| Context.Pick
10+
| Context.Gather
11+
| Context.Frame;
912

1013
export const isContext = (value: unknown): value is Context => [
1114
Context.isCode,
1215
Context.isVariables,
1316
Context.isRemark,
17+
Context.isPick,
18+
Context.isFrame,
19+
Context.isGather,
1420
].some(guard => guard(value));
1521

1622
export namespace Context {
@@ -76,4 +82,30 @@ export namespace Context {
7682
export const isRemark = (value: unknown): value is Remark =>
7783
typeof value === "object" && !!value &&
7884
"remark" in value && typeof value.remark === "string";
85+
86+
export interface Pick {
87+
pick: Context[];
88+
}
89+
90+
export const isPick = (value: unknown): value is Pick =>
91+
typeof value === "object" && !!value &&
92+
"pick" in value && Array.isArray(value.pick) &&
93+
value.pick.every(isContext);
94+
95+
export interface Gather {
96+
gather: Context[];
97+
}
98+
99+
export const isGather = (value: unknown): value is Gather =>
100+
typeof value === "object" && !!value &&
101+
"gather" in value && Array.isArray(value.gather) &&
102+
value.gather.every(isContext);
103+
104+
export interface Frame {
105+
frame: string;
106+
}
107+
108+
export const isFrame = (value: unknown): value is Frame =>
109+
typeof value === "object" && !!value &&
110+
"frame" in value && typeof value.frame === "string";
79111
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
sidebar_position: 7
3+
---
4+
5+
import SchemaViewer from "@site/src/components/SchemaViewer";
6+
7+
# Frame contexts
8+
9+
<SchemaViewer
10+
schema={{ id: "schema:ethdebug/format/program/context/frame" }}
11+
/>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
sidebar_position: 7
3+
---
4+
5+
import SchemaViewer from "@site/src/components/SchemaViewer";
6+
7+
# Gather multiple contexts
8+
9+
<SchemaViewer
10+
schema={{ id: "schema:ethdebug/format/program/context/gather" }}
11+
/>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
sidebar_position: 7
3+
---
4+
5+
import SchemaViewer from "@site/src/components/SchemaViewer";
6+
7+
# Pick one of several contexts
8+
9+
<SchemaViewer
10+
schema={{ id: "schema:ethdebug/format/program/context/pick" }}
11+
/>

packages/web/spec/program/example.mdx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ code {
2828
2929
let localValue = storedValue + 1;
3030
storedValue = localValue;
31+
return;
3132
}
3233
`}]}
3334
instructions={[
@@ -285,8 +286,10 @@ code {
285286
mnemonic: "JUMPDEST"
286287
},
287288
context: ({ findSourceRange }) => ({
288-
code: findSourceRange("return;"),
289-
remark: "skip to here if not enough paid"
289+
pick: [
290+
{ code: findSourceRange("return;") },
291+
{ code: findSourceRange("return;", { after: "return;" }) },
292+
]
290293
})
291294
}
292295
]}

packages/web/src/schemas.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ const programSchemaIndex: SchemaIndex = {
215215
},
216216

217217
...(
218-
["code", "variables", "remark"].map(name => ({
218+
["code", "variables", "remark", "pick", "gather", "frame"].map(name => ({
219219
[`schema:ethdebug/format/program/context/${name}`]: {
220220
href: `/spec/program/context/${name}`
221221
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import Admonition from "@theme/Admonition";
2+
import Link from "@docusaurus/Link";
3+
import { Program } from "@ethdebug/format";
4+
import { useProgramExampleContext } from "./ProgramExampleContext";
5+
import { HighlightedInstruction } from "./HighlightedInstruction";
6+
import { Variables } from "./Variables";
7+
8+
// imported for style legend
9+
import "./SourceContents.css";
10+
11+
export interface Props {
12+
}
13+
14+
export function Details(props: Props): JSX.Element {
15+
const { highlightedInstruction, highlightMode } = useProgramExampleContext();
16+
17+
if (highlightMode === "simple" || !highlightedInstruction) {
18+
return <>
19+
<h3>Details</h3>
20+
<BasicAdmonition />
21+
</>;
22+
}
23+
24+
25+
return <>
26+
<h3>Details</h3>
27+
<InstructionAdmonition instruction={highlightedInstruction} />
28+
<details>
29+
<summary>See full <strong>ethdebug/format/program/instruction</strong> object</summary>
30+
<HighlightedInstruction />
31+
</details>
32+
</>;
33+
}
34+
35+
interface InstructionAdmonitionProps {
36+
instruction: Program.Instruction;
37+
}
38+
function InstructionAdmonition({
39+
instruction
40+
}: InstructionAdmonitionProps): JSX.Element {
41+
return <Admonition type="info">
42+
<p>
43+
The selected instruction provides the following <Link to="/spec/program/context">
44+
<strong>ethdebug/format</strong> Program contexts
45+
</Link>:
46+
</p>
47+
<ul>
48+
<li>
49+
<strong>Code context</strong> is highlighted <span className="highlighted-code">in this
50+
style</span> above.
51+
</li>
52+
<li>
53+
<strong>Variables context</strong> is indicated by variable declarations
54+
highlighted <span className="highlighted-variable-declaration">in this
55+
style</span> above.
56+
</li>
57+
</ul>
58+
</Admonition>;
59+
}
60+
61+
function BasicAdmonition(props: {}): JSX.Element {
62+
return <Admonition type="tip">
63+
Select an instruction offset to see associated <strong>
64+
ethdebug/format
65+
</strong> debugging information.
66+
</Admonition>;
67+
}

packages/web/src/theme/ProgramExample/SourceContents.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
background-color: var(--ifm-color-primary-lightest);
55
}
66

7+
.highlighted-ambiguous-code {
8+
font-weight: bold;
9+
background-color: var(--ifm-color-warning-lightest);
10+
}
11+
712
.highlighted-variable-declaration {
813
text-decoration: underline;
914
text-decoration-style: wavy;

packages/web/src/theme/ProgramExample/SourceContents.tsx

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ export function SourceContents(
3131

3232
const simpleDecorations = Program.Context.isCode(context)
3333
? decorateCodeContext(context, source)
34-
: [];
34+
: Program.Context.isPick(context)
35+
? decoratePickContext(context, source)
36+
: [];
3537

3638
const detailedDecorations = [
3739
...simpleDecorations,
@@ -56,7 +58,8 @@ export function SourceContents(
5658

5759
function decorateCodeContext(
5860
{ code }: Program.Context.Code,
59-
source: Materials.Source
61+
source: Materials.Source,
62+
className: string = "highlighted-code"
6063
): Shiki.DecorationItem[] {
6164
const { offset, length } = normalizeRange(code.range, source);
6265

@@ -65,12 +68,29 @@ function decorateCodeContext(
6568
start: offset,
6669
end: offset + length,
6770
properties: {
68-
class: "highlighted-code"
71+
class: className
6972
}
7073
}
7174
];
7275
}
7376

77+
function decoratePickContext(
78+
{ pick }: Program.Context.Pick,
79+
source: Materials.Source
80+
): Shiki.DecorationItem[] {
81+
// HACK this only supports picking from a choice of several different code
82+
// contexts
83+
if (!pick.every(Program.Context.isCode)) {
84+
console.warn("decoratePickContext encountered non-code contexts in pick array. These will be ignored.");
85+
return [];
86+
}
87+
88+
return pick.flatMap(
89+
(choice) => decorateCodeContext(choice, source, "highlighted-ambiguous-code")
90+
);
91+
}
92+
93+
7494
function decorateVariablesContext(
7595
{ variables }: Program.Context.Variables,
7696
source: Materials.Source

0 commit comments

Comments
 (0)