gofish-ir 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,288 @@
1
+ // <gofish-wiki> AUTO-GENERATED — see covers: in the essay; run `pnpm --filter docs sync-backlinks`
2
+ // @wiki Frontend IR — /internals/frontend/serialization
3
+ // </gofish-wiki>
4
+ /**
5
+ * Hand-written JSON Schema for the GoFish frontend IR (v0).
6
+ *
7
+ * Structural only — defines the document shape, the discriminator unions
8
+ * for operators / marks / channel values, and the validity envelope. Full
9
+ * field-level coverage matches `validate.ts`; this file is the wire
10
+ * artifact (consumed by external tooling, language servers, and the
11
+ * Python wrapper's parity-test harness).
12
+ */
13
+ export const FRONTEND_IR_JSON_SCHEMA = {
14
+ $schema: "https://json-schema.org/draft/2020-12/schema",
15
+ $id: "https://gofish.graphics/schema/frontend/v0.json",
16
+ title: "GoFish Frontend IR",
17
+ description: "Source-level chart specification produced by the v3 fluent API.",
18
+ type: "object",
19
+ required: ["irVersion", "ir", "root"],
20
+ additionalProperties: false,
21
+ properties: {
22
+ irVersion: { const: 0 },
23
+ ir: { const: "gofish-frontend" },
24
+ $schema: { type: "string" },
25
+ root: { $ref: "#/$defs/Root" },
26
+ },
27
+ $defs: {
28
+ Root: {
29
+ oneOf: [
30
+ { $ref: "#/$defs/ChartIR" },
31
+ { $ref: "#/$defs/LayerIR" },
32
+ { $ref: "#/$defs/RawMarkIR" },
33
+ ],
34
+ },
35
+ Origin: {
36
+ type: "object",
37
+ properties: {
38
+ name: { type: "string" },
39
+ stack: { type: "string" },
40
+ },
41
+ },
42
+ Meta: {
43
+ type: "object",
44
+ description: "Optional inline annotations populated by later passes. v0 emitters leave it absent.",
45
+ },
46
+ DataIR: {
47
+ oneOf: [
48
+ {
49
+ type: "object",
50
+ required: ["type", "rows"],
51
+ properties: {
52
+ type: { const: "inline" },
53
+ rows: { type: "array", items: { type: "object" } },
54
+ },
55
+ },
56
+ {
57
+ type: "object",
58
+ required: ["type", "layer"],
59
+ properties: {
60
+ type: { const: "select" },
61
+ layer: { type: "string" },
62
+ },
63
+ },
64
+ {
65
+ type: "object",
66
+ required: ["type"],
67
+ properties: {
68
+ type: { const: "external" },
69
+ id: { type: "string" },
70
+ },
71
+ },
72
+ ],
73
+ },
74
+ ChartIR: {
75
+ type: "object",
76
+ required: ["type", "mark"],
77
+ properties: {
78
+ type: { const: "chart" },
79
+ data: { oneOf: [{ $ref: "#/$defs/DataIR" }, { type: "null" }] },
80
+ operators: { type: "array", items: { $ref: "#/$defs/OperatorIR" } },
81
+ mark: { $ref: "#/$defs/MarkIR" },
82
+ options: { type: "object" },
83
+ zOrder: { type: "number" },
84
+ origin: { $ref: "#/$defs/Origin" },
85
+ meta: { $ref: "#/$defs/Meta" },
86
+ },
87
+ },
88
+ LayerIR: {
89
+ type: "object",
90
+ required: ["type", "charts"],
91
+ properties: {
92
+ type: { const: "layer" },
93
+ charts: { type: "array", items: { $ref: "#/$defs/ChartIR" } },
94
+ options: { type: "object" },
95
+ origin: { $ref: "#/$defs/Origin" },
96
+ meta: { $ref: "#/$defs/Meta" },
97
+ },
98
+ },
99
+ RawMarkIR: {
100
+ type: "object",
101
+ required: ["type", "mark"],
102
+ properties: {
103
+ type: { const: "raw-mark" },
104
+ mark: { $ref: "#/$defs/MarkIR" },
105
+ options: { type: "object" },
106
+ origin: { $ref: "#/$defs/Origin" },
107
+ meta: { $ref: "#/$defs/Meta" },
108
+ },
109
+ },
110
+ OperatorIR: {
111
+ type: "object",
112
+ required: ["type"],
113
+ properties: {
114
+ type: {
115
+ enum: [
116
+ "derive",
117
+ "spread",
118
+ "stack",
119
+ "group",
120
+ "scatter",
121
+ "table",
122
+ "log",
123
+ ],
124
+ },
125
+ },
126
+ },
127
+ MarkIR: {
128
+ oneOf: [
129
+ { $ref: "#/$defs/LeafMarkIR" },
130
+ { $ref: "#/$defs/CombinatorMarkIR" },
131
+ { $ref: "#/$defs/RefMarkIR" },
132
+ ],
133
+ },
134
+ LeafMarkIR: {
135
+ type: "object",
136
+ required: ["type"],
137
+ properties: {
138
+ type: {
139
+ enum: [
140
+ "rect",
141
+ "circle",
142
+ "line",
143
+ "area",
144
+ "blank",
145
+ "ellipse",
146
+ "petal",
147
+ "text",
148
+ "image",
149
+ "polygon",
150
+ "mark-fn",
151
+ ],
152
+ },
153
+ name: { type: "string" },
154
+ label: { $ref: "#/$defs/LabelIR" },
155
+ constraints: {
156
+ type: "array",
157
+ items: { $ref: "#/$defs/ConstraintIR" },
158
+ },
159
+ zOrder: { type: "number" },
160
+ },
161
+ },
162
+ CombinatorMarkIR: {
163
+ type: "object",
164
+ required: ["type", "__combinator", "children"],
165
+ properties: {
166
+ type: {
167
+ enum: [
168
+ "spread",
169
+ "stack",
170
+ "scatter",
171
+ "group",
172
+ "table",
173
+ "layer",
174
+ "arrow",
175
+ "connect",
176
+ "treemap",
177
+ "over",
178
+ "inside",
179
+ "xor",
180
+ "out",
181
+ "atop",
182
+ "mask",
183
+ ],
184
+ },
185
+ __combinator: { const: true },
186
+ options: { type: "object" },
187
+ children: { type: "array", items: { $ref: "#/$defs/MarkIR" } },
188
+ name: { type: "string" },
189
+ label: { $ref: "#/$defs/LabelIR" },
190
+ constraints: {
191
+ type: "array",
192
+ items: { $ref: "#/$defs/ConstraintIR" },
193
+ },
194
+ zOrder: { type: "number" },
195
+ },
196
+ },
197
+ RefMarkIR: {
198
+ type: "object",
199
+ required: ["type", "selection"],
200
+ properties: {
201
+ type: { const: "ref" },
202
+ selection: {
203
+ oneOf: [
204
+ { type: "string" },
205
+ {
206
+ type: "array",
207
+ items: { oneOf: [{ type: "string" }, { type: "number" }] },
208
+ },
209
+ ],
210
+ },
211
+ name: { type: "string" },
212
+ label: { $ref: "#/$defs/LabelIR" },
213
+ zOrder: { type: "number" },
214
+ },
215
+ },
216
+ LabelIR: {
217
+ // Three shapes: the canonical object form, a boolean shorthand
218
+ // (`label: true` — let the mark shape decide what to label), and
219
+ // a string shorthand (`label: "field"` — use this field accessor
220
+ // with default styling). All three match `LabelIR` in schema.ts.
221
+ oneOf: [
222
+ { type: "boolean" },
223
+ { type: "string" },
224
+ {
225
+ type: "object",
226
+ required: ["accessor"],
227
+ properties: {
228
+ accessor: { type: "string" },
229
+ position: { type: "string" },
230
+ fontSize: { type: "number" },
231
+ color: { type: "string" },
232
+ offset: { type: "number" },
233
+ minSpace: { type: "number" },
234
+ rotate: { type: "number" },
235
+ },
236
+ },
237
+ ],
238
+ },
239
+ ConstraintIR: {
240
+ type: "object",
241
+ required: ["type", "refs"],
242
+ properties: {
243
+ type: { enum: ["align", "distribute", "zAbove", "zBelow"] },
244
+ options: { type: "object" },
245
+ refs: { type: "array", items: { type: "string" } },
246
+ },
247
+ },
248
+ ChannelValue: {
249
+ description: "Right-hand side of a channel slot. Bare primitives for the shorthand path; tagged objects for the explicit field/datum/literal constructors and Python-bridge sentinels.",
250
+ oneOf: [
251
+ { type: "string" },
252
+ { type: "number" },
253
+ { type: "boolean" },
254
+ { type: "null" },
255
+ {
256
+ type: "object",
257
+ required: ["type", "name"],
258
+ properties: {
259
+ type: { const: "field" },
260
+ name: { type: "string" },
261
+ },
262
+ },
263
+ {
264
+ type: "object",
265
+ required: ["type", "value"],
266
+ properties: {
267
+ type: { const: "literal" },
268
+ value: {},
269
+ },
270
+ },
271
+ {
272
+ type: "object",
273
+ required: ["type", "datum"],
274
+ properties: {
275
+ type: { const: "datum" },
276
+ datum: {},
277
+ measure: { type: "string" },
278
+ },
279
+ },
280
+ {
281
+ type: "object",
282
+ required: ["__gofish_lambda"],
283
+ properties: { __gofish_lambda: { type: "string" } },
284
+ },
285
+ ],
286
+ },
287
+ },
288
+ };
@@ -0,0 +1,255 @@
1
+ /**
2
+ * GoFish Frontend IR — schema types.
3
+ *
4
+ * The frontend IR captures a GoFish chart specification at the source level,
5
+ * before macro expansion and elaboration. v0 mirrors the existing widget
6
+ * wire format exactly (lowercase type tags, __combinator flag, channel
7
+ * slots accept strings/numbers/sentinels). See the architecture essay for
8
+ * the multi-stage design and the planned v0.1+ improvements.
9
+ */
10
+ /** Top-level wrapper for a serialized GoFish chart. */
11
+ export interface FrontendIRDocument {
12
+ irVersion: 0;
13
+ ir: "gofish-frontend";
14
+ /** Optional URL of the JSON Schema this document claims to conform to. */
15
+ $schema?: string;
16
+ root: FrontendIR;
17
+ }
18
+ /** A frontend-IR root is a chart, a multi-chart layer, or a bare mark. */
19
+ export type FrontendIR = ChartIR | LayerIR | RawMarkIR;
20
+ /**
21
+ * Metadata that any node may carry. v0 emitters leave `meta` unset; later
22
+ * passes (underlying-space inference, scale resolution, etc.) populate the
23
+ * relevant fields. The slot is reserved so additive evolution doesn't
24
+ * require a schema bump.
25
+ */
26
+ export interface Meta {
27
+ /** Source-position attribution — populated by future build-time hooks. */
28
+ loc?: SourceLocation;
29
+ /** Underlying-space classification — populated post-elaboration. */
30
+ space?: UnderlyingSpaceAnnotation;
31
+ /** Open extension for unknown pass-specific annotations. */
32
+ [key: string]: unknown;
33
+ }
34
+ export interface SourceLocation {
35
+ file: string;
36
+ line: number;
37
+ column: number;
38
+ }
39
+ export interface UnderlyingSpaceAnnotation {
40
+ type: "SIZE" | "POSITION" | "ORDINAL" | "DIFFERENCE" | "UNDEFINED";
41
+ }
42
+ /** Mixin properties available on every IR node. */
43
+ export interface BaseIRNode {
44
+ /** User-supplied origin metadata. Currently carries the `.name(...)` value if set. */
45
+ origin?: Origin;
46
+ /** Reserved for inline annotations attached by future passes. */
47
+ meta?: Meta;
48
+ }
49
+ export interface Origin {
50
+ /** User-supplied name via `.name("bars")` on the v3 fluent builder. */
51
+ name?: string;
52
+ /** Optional captured call-site stack — unset in v0. */
53
+ stack?: string;
54
+ }
55
+ /** A standard chart: data → operators → mark. */
56
+ export interface ChartIR extends BaseIRNode {
57
+ type: "chart";
58
+ data?: DataIR | null;
59
+ operators?: OperatorIR[];
60
+ mark: MarkIR;
61
+ options?: Record<string, unknown>;
62
+ zOrder?: number;
63
+ }
64
+ /** Multiple charts composed on the same canvas. */
65
+ export interface LayerIR extends BaseIRNode {
66
+ type: "layer";
67
+ charts: ChartIR[];
68
+ options?: Record<string, unknown>;
69
+ }
70
+ /** A bare mark, used when no chart-level wrapping is needed. */
71
+ export interface RawMarkIR extends BaseIRNode {
72
+ type: "raw-mark";
73
+ mark: MarkIR;
74
+ options?: Record<string, unknown>;
75
+ }
76
+ /**
77
+ * The data field on a chart.
78
+ *
79
+ * - **Inline rows**: `{type: "inline", rows: [...]}` for charts whose data is
80
+ * embedded in the IR.
81
+ * - **Select reference**: `{type: "select", layer: "name"}` resolves a sibling
82
+ * chart's named-mark output at deserialize time.
83
+ * - **External**: `{type: "external", id?: "..."}` indicates data ships over a
84
+ * sidecar transport (anywidget's `arrow_data` trait) and the id keys into it.
85
+ */
86
+ export type DataIR = {
87
+ type: "inline";
88
+ rows: Array<Record<string, unknown>>;
89
+ } | {
90
+ type: "select";
91
+ layer: string;
92
+ } | {
93
+ type: "external";
94
+ id?: string;
95
+ };
96
+ export type OperatorIR = DeriveOperator | SpreadOperator | StackOperator | GroupOperator | ScatterOperator | TableOperator | LogOperator;
97
+ /**
98
+ * `derive(fn)` — opaque user transformation. Function bodies are not
99
+ * serializable; the IR carries a bridge handle (`lambdaId`) when the
100
+ * Python widget is the producer, and is otherwise empty.
101
+ */
102
+ export interface DeriveOperator extends BaseIRNode {
103
+ type: "derive";
104
+ lambdaId?: string;
105
+ }
106
+ export interface SpreadOperator extends BaseIRNode {
107
+ type: "spread";
108
+ by?: string;
109
+ dir?: "x" | "y";
110
+ spacing?: number;
111
+ alignment?: string;
112
+ sharedScale?: boolean;
113
+ mode?: "edge" | "center";
114
+ reverse?: boolean;
115
+ }
116
+ export interface StackOperator extends BaseIRNode {
117
+ type: "stack";
118
+ by?: string;
119
+ dir?: "x" | "y";
120
+ alignment?: string;
121
+ sharedScale?: boolean;
122
+ mode?: "edge" | "center";
123
+ reverse?: boolean;
124
+ }
125
+ export interface GroupOperator extends BaseIRNode {
126
+ type: "group";
127
+ by: string;
128
+ }
129
+ export interface ScatterOperator extends BaseIRNode {
130
+ type: "scatter";
131
+ by?: string;
132
+ x?: ChannelValue;
133
+ y?: ChannelValue;
134
+ xMin?: ChannelValue;
135
+ xMax?: ChannelValue;
136
+ yMin?: ChannelValue;
137
+ yMax?: ChannelValue;
138
+ alignment?: string;
139
+ }
140
+ export interface TableOperator extends BaseIRNode {
141
+ type: "table";
142
+ by: {
143
+ x: string;
144
+ y: string;
145
+ };
146
+ spacing?: number | [number, number];
147
+ numCols?: number;
148
+ }
149
+ export interface LogOperator extends BaseIRNode {
150
+ type: "log";
151
+ label?: string;
152
+ }
153
+ export type MarkIR = LeafMarkIR | CombinatorMarkIR | RefMarkIR;
154
+ export type LeafMarkType = "rect" | "circle" | "line" | "area" | "blank" | "ellipse" | "petal" | "text" | "image" | "polygon" | "mark-fn";
155
+ export type CombinatorMarkType = "spread" | "stack" | "scatter" | "group" | "table" | "layer" | "arrow" | "connect" | "treemap" | "over" | "inside" | "xor" | "out" | "atop" | "mask";
156
+ /**
157
+ * A leaf shape mark. Channel-valued props (`h`, `w`, `fill`, `x`, `y`, …)
158
+ * appear directly on the object alongside the well-known fields. TypeScript
159
+ * cannot precisely express the union of channel values per shape, so the
160
+ * index signature is permissive — mirrors the existing widget interface.
161
+ */
162
+ export interface LeafMarkIR extends BaseIRNode {
163
+ type: LeafMarkType;
164
+ name?: string;
165
+ label?: LabelIR;
166
+ constraints?: ConstraintIR[];
167
+ zOrder?: number;
168
+ [key: string]: unknown;
169
+ }
170
+ /**
171
+ * A combinator-form operator used as a mark (e.g. `spread([m1, m2])`).
172
+ * Distinguished from the operator-form by the `__combinator: true` flag
173
+ * and the presence of `children`.
174
+ */
175
+ export interface CombinatorMarkIR extends BaseIRNode {
176
+ type: CombinatorMarkType;
177
+ __combinator: true;
178
+ options?: Record<string, unknown>;
179
+ children: MarkIR[];
180
+ name?: string;
181
+ label?: LabelIR;
182
+ constraints?: ConstraintIR[];
183
+ zOrder?: number;
184
+ }
185
+ /** A by-name reference to another named mark (`ref("bars")`). */
186
+ export interface RefMarkIR extends BaseIRNode {
187
+ type: "ref";
188
+ selection: string | Array<string | number>;
189
+ name?: string;
190
+ label?: LabelIR;
191
+ zOrder?: number;
192
+ }
193
+ /**
194
+ * A channel value (the right-hand side of a mark or operator property like
195
+ * `h: …` or `fill: …`).
196
+ *
197
+ * Strings without explicit tagging disambiguate to field-accessor or
198
+ * literal at runtime by checking against `data[0]`. The explicit
199
+ * constructors `field(name)` / `datum(x)` / `literal(x)` emit their
200
+ * canonical tagged-object forms. `__gofish_lambda` is the one remaining
201
+ * Python-bridge sentinel — it encodes a remote callable that the widget
202
+ * resolves via the DeriveBridge.
203
+ *
204
+ * v0.1+ will move the v3 API to desugar string shorthand to explicit
205
+ * constructors eagerly, so the IR carries only canonical forms.
206
+ */
207
+ export type ChannelValue = string | number | boolean | null | DatumValue | BridgeLambdaSentinel;
208
+ export interface DatumValue {
209
+ type: "datum";
210
+ [key: string]: unknown;
211
+ }
212
+ /** Python-bridge sentinel for a remote callable. The JS side issues an RPC for each datum. */
213
+ export interface BridgeLambdaSentinel {
214
+ __gofish_lambda: string;
215
+ }
216
+ /**
217
+ * Label specification.
218
+ *
219
+ * The canonical object form `{accessor, position?, fontSize?, ...}` is
220
+ * what `mark.label("field", options)` produces. Shorthand forms (matching
221
+ * the JS mark-kwarg API):
222
+ *
223
+ * label: true — show a label with default styling
224
+ * label: "field" — label using this field accessor, defaults elsewhere
225
+ */
226
+ export type LabelIR = true | string | {
227
+ accessor: string;
228
+ position?: string;
229
+ fontSize?: number;
230
+ color?: string;
231
+ offset?: number;
232
+ minSpace?: number;
233
+ rotate?: number;
234
+ };
235
+ export interface ConstraintIR {
236
+ type: "align" | "distribute" | "zAbove" | "zBelow";
237
+ /** Positioning constraints carry `options`; z-order constraints don't. */
238
+ options?: Record<string, unknown>;
239
+ refs: string[];
240
+ }
241
+ /** Discriminate a root document. */
242
+ export declare function isChartIR(node: FrontendIR): node is ChartIR;
243
+ export declare function isLayerIR(node: FrontendIR): node is LayerIR;
244
+ export declare function isRawMarkIR(node: FrontendIR): node is RawMarkIR;
245
+ /** Discriminate a mark by family. */
246
+ export declare function isCombinatorMarkIR(mark: MarkIR): mark is CombinatorMarkIR;
247
+ export declare function isRefMarkIR(mark: MarkIR): mark is RefMarkIR;
248
+ export declare function isLeafMarkIR(mark: MarkIR): mark is LeafMarkIR;
249
+ /** The set of operator type discriminators recognized in v0. */
250
+ export declare const OPERATOR_TYPES: readonly ["derive", "spread", "stack", "group", "scatter", "table", "log"];
251
+ /** The set of leaf-mark type discriminators recognized in v0. */
252
+ export declare const LEAF_MARK_TYPES: readonly LeafMarkType[];
253
+ /** The set of combinator-mark type discriminators recognized in v0. */
254
+ export declare const COMBINATOR_MARK_TYPES: readonly CombinatorMarkType[];
255
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/frontend/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ // <gofish-wiki> AUTO-GENERATED — see covers: in the essay; run `pnpm --filter docs sync-backlinks`
2
+ // @wiki Frontend IR — /internals/frontend/serialization
3
+ // </gofish-wiki>
4
+ // ---------------------------------------------------------------------------
5
+ // Discriminator helpers (predicates)
6
+ // ---------------------------------------------------------------------------
7
+ /** Discriminate a root document. */
8
+ export function isChartIR(node) {
9
+ return node.type === "chart";
10
+ }
11
+ export function isLayerIR(node) {
12
+ return node.type === "layer";
13
+ }
14
+ export function isRawMarkIR(node) {
15
+ return node.type === "raw-mark";
16
+ }
17
+ /** Discriminate a mark by family. */
18
+ export function isCombinatorMarkIR(mark) {
19
+ return (mark.__combinator === true &&
20
+ Array.isArray(mark.children));
21
+ }
22
+ export function isRefMarkIR(mark) {
23
+ return mark.type === "ref";
24
+ }
25
+ export function isLeafMarkIR(mark) {
26
+ return !isCombinatorMarkIR(mark) && !isRefMarkIR(mark);
27
+ }
28
+ /** The set of operator type discriminators recognized in v0. */
29
+ export const OPERATOR_TYPES = [
30
+ "derive",
31
+ "spread",
32
+ "stack",
33
+ "group",
34
+ "scatter",
35
+ "table",
36
+ "log",
37
+ ];
38
+ /** The set of leaf-mark type discriminators recognized in v0. */
39
+ export const LEAF_MARK_TYPES = [
40
+ "rect",
41
+ "circle",
42
+ "line",
43
+ "area",
44
+ "blank",
45
+ "ellipse",
46
+ "petal",
47
+ "text",
48
+ "image",
49
+ "polygon",
50
+ "mark-fn",
51
+ ];
52
+ /** The set of combinator-mark type discriminators recognized in v0. */
53
+ export const COMBINATOR_MARK_TYPES = [
54
+ "spread",
55
+ "stack",
56
+ "scatter",
57
+ "group",
58
+ "table",
59
+ "layer",
60
+ "arrow",
61
+ "connect",
62
+ "treemap",
63
+ "over",
64
+ "inside",
65
+ "xor",
66
+ "out",
67
+ "atop",
68
+ "mask",
69
+ ];