wesl 0.6.49 → 0.7.1
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.
- package/dist/index.d.ts +269 -215
- package/dist/index.js +2911 -1539
- package/package.json +6 -8
- package/src/AbstractElems.ts +81 -81
- package/src/Assertions.ts +5 -5
- package/src/BindIdents.ts +192 -306
- package/src/ClickableError.ts +3 -2
- package/src/Conditions.ts +2 -2
- package/src/LinkedWesl.ts +1 -1
- package/src/Linker.ts +4 -3
- package/src/LinkerUtil.ts +1 -1
- package/src/Logging.ts +165 -0
- package/src/LowerAndEmit.ts +278 -110
- package/src/ModuleResolver.ts +15 -25
- package/src/ParseError.ts +9 -0
- package/src/ParseWESL.ts +30 -94
- package/src/RawEmit.ts +1 -4
- package/src/Reflection.ts +1 -1
- package/src/Scope.ts +3 -0
- package/src/Span.ts +2 -0
- package/src/SrcMap.ts +208 -0
- package/src/Stream.ts +30 -0
- package/src/TransformBindingStructs.ts +2 -2
- package/src/Util.ts +1 -1
- package/src/debug/ASTtoString.ts +84 -135
- package/src/discovery/FindUnboundIdents.ts +14 -5
- package/src/index.ts +4 -0
- package/src/parse/ContentsHelpers.ts +70 -0
- package/src/parse/ExpressionUtil.ts +121 -0
- package/src/parse/Keywords.ts +12 -12
- package/src/parse/OperatorBinding.ts +146 -0
- package/src/parse/ParseAttribute.ts +272 -0
- package/src/parse/ParseCall.ts +77 -0
- package/src/parse/ParseControlFlow.ts +129 -0
- package/src/parse/ParseDirective.ts +105 -0
- package/src/parse/ParseExpression.ts +288 -0
- package/src/parse/ParseFn.ts +151 -0
- package/src/parse/ParseGlobalVar.ts +131 -0
- package/src/parse/ParseIdent.ts +77 -0
- package/src/parse/ParseImport.ts +160 -0
- package/src/parse/ParseLocalVar.ts +69 -0
- package/src/parse/ParseLoop.ts +112 -0
- package/src/parse/ParseModule.ts +116 -0
- package/src/parse/ParseSimpleStatement.ts +162 -0
- package/src/parse/ParseStatement.ts +215 -0
- package/src/parse/ParseStruct.ts +89 -0
- package/src/parse/ParseType.ts +71 -0
- package/src/parse/ParseUtil.ts +174 -0
- package/src/parse/ParseValueDeclaration.ts +130 -0
- package/src/parse/ParseWesl.ts +51 -0
- package/src/parse/ParsingContext.ts +93 -0
- package/src/parse/WeslStream.ts +63 -20
- package/src/parse/stream/CachingStream.ts +48 -0
- package/src/parse/stream/MatchersStream.ts +85 -0
- package/src/parse/stream/RegexHelpers.ts +38 -0
- package/src/test/BevyLink.test.ts +100 -0
- package/src/test/BindStdTypes.test.ts +110 -0
- package/src/test/{BindWESL.test.ts → BindWESLV2.test.ts} +21 -22
- package/src/test/BulkTests.test.ts +11 -12
- package/src/test/ConditionLinking.test.ts +107 -0
- package/src/test/ConditionalElif.test.ts +1 -13
- package/src/test/ConditionalTranslationCases.test.ts +5 -0
- package/src/test/ErrorLogging.test.ts +2 -2
- package/src/test/ImportCasesV2.test.ts +63 -0
- package/src/test/LinkFails.test.ts +69 -0
- package/src/test/LinkPackage.test.ts +1 -1
- package/src/test/Linker.test.ts +75 -2
- package/src/test/LogCatcher.ts +53 -0
- package/src/test/Mangling.test.ts +1 -1
- package/src/test/ParseComments.test.ts +1 -2
- package/src/test/{ParseConditions.test.ts → ParseConditionsV2.test.ts} +57 -49
- package/src/test/ParseErrorV2.test.ts +73 -0
- package/src/test/{ParseWESL.test.ts → ParseWeslV2.test.ts} +288 -370
- package/src/test/{ScopeWESL.test.ts → ScopeWESLV2.test.ts} +205 -176
- package/src/test/TestLink.ts +51 -51
- package/src/test/TestSetup.ts +9 -3
- package/src/test/TestUtil.ts +47 -77
- package/src/test/TrimmedMatch.ts +40 -0
- package/src/test/VirtualModules.test.ts +33 -2
- package/src/test/WeslDevice.test.ts +9 -2
- package/src/test/__snapshots__/ParseWeslV2.test.ts.snap +67 -0
- package/src/test-util.ts +7 -0
- package/src/WESLCollect.ts +0 -656
- package/src/parse/AttributeGrammar.ts +0 -232
- package/src/parse/ImportGrammar.ts +0 -195
- package/src/parse/WeslBaseGrammar.ts +0 -11
- package/src/parse/WeslExpression.ts +0 -231
- package/src/parse/WeslGrammar.ts +0 -739
- package/src/test/Expression.test.ts +0 -22
- package/src/test/ImportSyntaxCases.test.ts +0 -24
- package/src/test/ParseError.test.ts +0 -45
- package/src/test/Reflection.test.ts +0 -176
- package/src/test/TransformBindingStructs.test.ts +0 -238
- /package/src/test/{ParseElif.test.ts → ParseElifV2.test.ts} +0 -0
package/src/ParseWESL.ts
CHANGED
|
@@ -1,80 +1,67 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type AppState,
|
|
3
|
-
ParseError,
|
|
4
|
-
type ParserInit,
|
|
5
|
-
type Span,
|
|
6
|
-
} from "mini-parse";
|
|
7
1
|
import type {
|
|
8
2
|
ConstAssertElem,
|
|
3
|
+
ContainerElem,
|
|
9
4
|
ImportElem,
|
|
10
5
|
ImportStatement,
|
|
11
6
|
ModuleElem,
|
|
12
7
|
} from "./AbstractElems.ts";
|
|
13
|
-
import { throwClickableError } from "./ClickableError.ts";
|
|
14
8
|
import { filterValidElements } from "./Conditions.ts";
|
|
15
9
|
import { type FlatImport, flattenTreeImport } from "./FlattenTreeImport.ts";
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
emptyScope,
|
|
21
|
-
type Scope,
|
|
22
|
-
type SrcModule,
|
|
23
|
-
} from "./Scope.ts";
|
|
10
|
+
import type { ParseError } from "./ParseError.ts";
|
|
11
|
+
import { parseWesl } from "./parse/ParseWesl.ts";
|
|
12
|
+
import type { Conditions, Scope, SrcModule } from "./Scope.ts";
|
|
13
|
+
import type { Span } from "./Span.ts";
|
|
24
14
|
import { errorHighlight, offsetToLineNumber } from "./Util.ts";
|
|
25
|
-
import type { OpenElem } from "./WESLCollect.ts";
|
|
26
15
|
|
|
27
|
-
/**
|
|
16
|
+
/** Partial element being constructed during parsing. */
|
|
17
|
+
export type OpenElem<T extends ContainerElem = ContainerElem> = Pick<
|
|
18
|
+
T,
|
|
19
|
+
"kind" | "contents"
|
|
20
|
+
>;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Result of parsing one WESL module (e.g., one .wesl file).
|
|
28
24
|
*
|
|
29
|
-
* The
|
|
30
|
-
* for convenient access by the binding stage.
|
|
25
|
+
* The AST is constructed into three sections for the binding stage:
|
|
31
26
|
* - import statements
|
|
32
27
|
* - language elements (fn, struct, etc)
|
|
33
28
|
* - scopes
|
|
34
|
-
*
|
|
35
29
|
*/
|
|
36
30
|
export interface WeslAST {
|
|
37
|
-
/**
|
|
31
|
+
/** Source text for this module. */
|
|
38
32
|
srcModule: SrcModule;
|
|
39
|
-
|
|
40
|
-
/** root module element */
|
|
33
|
+
/** Root module element. */
|
|
41
34
|
moduleElem: ModuleElem;
|
|
42
|
-
|
|
43
|
-
/** root scope for this module */
|
|
35
|
+
/** Root scope for this module. */
|
|
44
36
|
rootScope: Scope;
|
|
45
|
-
|
|
46
|
-
/** imports found in this module */
|
|
37
|
+
/** Imports found in this module. */
|
|
47
38
|
imports: ImportStatement[];
|
|
48
|
-
|
|
49
|
-
/** module level const_assert statements */
|
|
39
|
+
/** Module level const_assert statements. */
|
|
50
40
|
moduleAsserts?: ConstAssertElem[];
|
|
51
41
|
}
|
|
52
42
|
|
|
53
|
-
/**
|
|
43
|
+
/** Extended AST with cached flattened imports. */
|
|
54
44
|
export interface BindingAST extends WeslAST {
|
|
55
|
-
|
|
45
|
+
/** Flattened import statements (cached on demand). */
|
|
56
46
|
_flatImports?: FlatImport[];
|
|
57
47
|
}
|
|
58
48
|
|
|
59
|
-
/**
|
|
60
|
-
export interface WeslParseState
|
|
61
|
-
extends AppState<WeslParseContext, StableState> {
|
|
49
|
+
/** Stable and unstable state used during parsing. */
|
|
50
|
+
export interface WeslParseState {
|
|
62
51
|
context: WeslParseContext;
|
|
63
52
|
stable: StableState;
|
|
64
53
|
}
|
|
65
54
|
|
|
66
|
-
/**
|
|
55
|
+
/** Stable values used or accumulated during parsing. */
|
|
67
56
|
export type StableState = WeslAST;
|
|
68
57
|
|
|
69
|
-
/**
|
|
58
|
+
/** Unstable values used during parse collection. */
|
|
70
59
|
export interface WeslParseContext {
|
|
71
60
|
scope: Scope; // current scope (points somewhere in rootScope)
|
|
72
61
|
openElems: OpenElem[]; // elems that are collecting their contents
|
|
73
62
|
}
|
|
74
63
|
|
|
75
|
-
/**
|
|
76
|
-
* An error when parsing WESL fails. Designed to be human-readable.
|
|
77
|
-
*/
|
|
64
|
+
/** Human-readable error when parsing WESL fails. */
|
|
78
65
|
export class WeslParseError extends Error {
|
|
79
66
|
span: Span;
|
|
80
67
|
src: SrcModule;
|
|
@@ -84,69 +71,18 @@ export class WeslParseError extends Error {
|
|
|
84
71
|
let message = `${opts.src.debugFilePath}:${lineNum}:${linePos}`;
|
|
85
72
|
message += ` error: ${opts.cause.message}\n`;
|
|
86
73
|
message += errorHighlight(source, opts.cause.span).join("\n");
|
|
87
|
-
super(message, {
|
|
88
|
-
cause: opts.cause,
|
|
89
|
-
});
|
|
74
|
+
super(message, { cause: opts.cause });
|
|
90
75
|
this.span = opts.cause.span;
|
|
91
76
|
this.src = opts.src;
|
|
92
77
|
}
|
|
93
78
|
}
|
|
94
79
|
|
|
95
|
-
/** Parse a WESL file.
|
|
80
|
+
/** Parse a WESL file. */
|
|
96
81
|
export function parseSrcModule(srcModule: SrcModule): WeslAST {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
const appState = blankWeslParseState(srcModule);
|
|
100
|
-
|
|
101
|
-
const init: ParserInit = { stream, appState };
|
|
102
|
-
try {
|
|
103
|
-
const parseResult = weslRoot.parse(init);
|
|
104
|
-
if (parseResult === null) {
|
|
105
|
-
throw new Error("parseWESL failed");
|
|
106
|
-
}
|
|
107
|
-
} catch (e) {
|
|
108
|
-
if (e instanceof ParseError) {
|
|
109
|
-
const [lineNumber, lineColumn] = offsetToLineNumber(
|
|
110
|
-
e.span[0],
|
|
111
|
-
srcModule.src,
|
|
112
|
-
);
|
|
113
|
-
const error = new WeslParseError({ cause: e, src: srcModule });
|
|
114
|
-
throwClickableError({
|
|
115
|
-
url: srcModule.debugFilePath,
|
|
116
|
-
text: srcModule.src,
|
|
117
|
-
error,
|
|
118
|
-
lineNumber,
|
|
119
|
-
lineColumn,
|
|
120
|
-
length: e.span[1] - e.span[0],
|
|
121
|
-
});
|
|
122
|
-
} else {
|
|
123
|
-
throw e;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return appState.stable as WeslAST;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export function blankWeslParseState(srcModule: SrcModule): WeslParseState {
|
|
131
|
-
const rootScope = emptyScope(null);
|
|
132
|
-
const moduleElem = null as any; // we'll fill this in later
|
|
133
|
-
return {
|
|
134
|
-
context: { scope: rootScope, openElems: [] },
|
|
135
|
-
stable: { srcModule, imports: [], rootScope, moduleElem },
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
export function syntheticWeslParseState(): WeslParseState {
|
|
140
|
-
const srcModule: SrcModule = {
|
|
141
|
-
modulePath: "package::test",
|
|
142
|
-
debugFilePath: "./test.wesl",
|
|
143
|
-
src: "",
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
return blankWeslParseState(srcModule);
|
|
82
|
+
return parseWesl(srcModule);
|
|
147
83
|
}
|
|
148
84
|
|
|
149
|
-
/** @return
|
|
85
|
+
/** @return flattened form of import tree for binding idents. */
|
|
150
86
|
export function flatImports(
|
|
151
87
|
ast: BindingAST,
|
|
152
88
|
conditions?: Conditions,
|
package/src/RawEmit.ts
CHANGED
|
@@ -56,11 +56,8 @@ export function typeListToString(params: TypeTemplateParameter[]): string {
|
|
|
56
56
|
|
|
57
57
|
export function typeParamToString(param?: TypeTemplateParameter): string {
|
|
58
58
|
if (param === undefined) return "?";
|
|
59
|
-
if (typeof param === "string") return param;
|
|
60
|
-
|
|
61
|
-
if (param.kind === "expression") return contentsToString(param);
|
|
62
59
|
if (param.kind === "type") return typeRefToString(param);
|
|
63
|
-
|
|
60
|
+
return expressionToString(param);
|
|
64
61
|
}
|
|
65
62
|
|
|
66
63
|
export function typeRefToString(t?: TypeRefElem): string {
|
package/src/Reflection.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { matchOneOf } from "mini-parse";
|
|
2
1
|
import type {
|
|
3
2
|
BindingStructElem,
|
|
4
3
|
NameElem,
|
|
@@ -11,6 +10,7 @@ import type {
|
|
|
11
10
|
import { assertThat } from "./Assertions.ts";
|
|
12
11
|
import type { TransformedAST, WeslJsPlugin } from "./Linker.ts";
|
|
13
12
|
import { identElemLog } from "./LinkerUtil.ts";
|
|
13
|
+
import { matchOneOf } from "./parse/stream/RegexHelpers.ts";
|
|
14
14
|
import type { RefIdent } from "./Scope.ts";
|
|
15
15
|
import {
|
|
16
16
|
multisampledTextureTypes,
|
package/src/Scope.ts
CHANGED
|
@@ -38,6 +38,9 @@ export interface RefIdent extends IdentBase {
|
|
|
38
38
|
refersTo?: Ident; // import or decl ident in scope to which this ident refers. undefined before binding
|
|
39
39
|
std?: true; // true if this is a standard wgsl identifier (like sin, or u32)
|
|
40
40
|
|
|
41
|
+
/** True for identifiers in @if/@elif conditions. Binding skips these (for now). */
|
|
42
|
+
conditionRef?: true;
|
|
43
|
+
|
|
41
44
|
// LATER consider tracking the current ast in BindIdents so that this field is unnecessary
|
|
42
45
|
ast: WeslAST; // AST from module that contains this ident (to find imports during decl binding)
|
|
43
46
|
|
package/src/Span.ts
ADDED
package/src/SrcMap.ts
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/** A source map file, and a path for debug purposes. */
|
|
2
|
+
export interface SrcWithPath {
|
|
3
|
+
/** User friendly path */
|
|
4
|
+
path?: string;
|
|
5
|
+
text: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface SrcMapEntry {
|
|
9
|
+
src: SrcWithPath;
|
|
10
|
+
srcStart: number;
|
|
11
|
+
srcEnd: number;
|
|
12
|
+
destStart: number;
|
|
13
|
+
destEnd: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface SrcPosition {
|
|
17
|
+
src: SrcWithPath;
|
|
18
|
+
position: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** map text ranges in multiple src texts to a single dest text */
|
|
22
|
+
export class SrcMap {
|
|
23
|
+
entries: SrcMapEntry[];
|
|
24
|
+
dest: SrcWithPath;
|
|
25
|
+
|
|
26
|
+
constructor(dest: SrcWithPath, entries: SrcMapEntry[] = []) {
|
|
27
|
+
this.dest = dest;
|
|
28
|
+
this.entries = entries;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** add a new mapping from src to dest ranges (must be non-overlapping in destination) */
|
|
32
|
+
addEntries(newEntries: SrcMapEntry[]): void {
|
|
33
|
+
this.entries.push(...newEntries);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** given positions in the dest string, return corresponding positions in the src strings */
|
|
37
|
+
mapPositions(...positions: number[]): SrcPosition[] {
|
|
38
|
+
return positions.map(p => this.destToSrc(p));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** internally compress adjacent entries where possible */
|
|
42
|
+
compact(): void {
|
|
43
|
+
if (!this.entries.length) return;
|
|
44
|
+
let prev = this.entries[0];
|
|
45
|
+
const newEntries: SrcMapEntry[] = [prev];
|
|
46
|
+
|
|
47
|
+
for (let i = 1; i < this.entries.length; i++) {
|
|
48
|
+
const e = this.entries[i];
|
|
49
|
+
if (
|
|
50
|
+
e.src.path === prev.src.path &&
|
|
51
|
+
e.src.text === prev.src.text &&
|
|
52
|
+
prev.destEnd === e.destStart &&
|
|
53
|
+
prev.srcEnd === e.srcStart
|
|
54
|
+
) {
|
|
55
|
+
// combine adjacent range entries into one
|
|
56
|
+
prev.destEnd = e.destEnd;
|
|
57
|
+
prev.srcEnd = e.srcEnd;
|
|
58
|
+
} else {
|
|
59
|
+
newEntries.push(e);
|
|
60
|
+
prev = e;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
this.entries = newEntries;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** sort in destination order */
|
|
67
|
+
sort(): void {
|
|
68
|
+
this.entries.sort((a, b) => a.destStart - b.destStart);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* This SrcMap's destination is a src for the other srcmap,
|
|
73
|
+
* so combine the two and return the result.
|
|
74
|
+
*/
|
|
75
|
+
merge(other: SrcMap): SrcMap {
|
|
76
|
+
if (other === this) return this;
|
|
77
|
+
|
|
78
|
+
const mappedEntries = other.entries.filter(
|
|
79
|
+
e => e.src.path === this.dest.path && e.src.text === this.dest.text,
|
|
80
|
+
);
|
|
81
|
+
if (mappedEntries.length === 0) {
|
|
82
|
+
console.log("other source map does not link to this one");
|
|
83
|
+
return other;
|
|
84
|
+
}
|
|
85
|
+
sortSrc(mappedEntries);
|
|
86
|
+
const newEntries = mappedEntries.map(e => {
|
|
87
|
+
const { src, position: srcStart } = this.destToSrc(e.srcStart);
|
|
88
|
+
const { src: endSrc, position: srcEnd } = this.destToSrc(e.srcEnd);
|
|
89
|
+
if (endSrc !== src) throw new Error("NYI, need to split");
|
|
90
|
+
const newEntry: SrcMapEntry = {
|
|
91
|
+
src,
|
|
92
|
+
srcStart,
|
|
93
|
+
srcEnd,
|
|
94
|
+
destStart: e.destStart,
|
|
95
|
+
destEnd: e.destEnd,
|
|
96
|
+
};
|
|
97
|
+
return newEntry;
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
const otherSources = other.entries.filter(
|
|
101
|
+
e => e.src.path !== this.dest.path || e.src.text !== this.dest.text,
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
const newMap = new SrcMap(other.dest, [...otherSources, ...newEntries]);
|
|
105
|
+
newMap.sort();
|
|
106
|
+
return newMap;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** @return the source position corresponding to a provided destination position */
|
|
110
|
+
destToSrc(destPos: number): SrcPosition {
|
|
111
|
+
const entry = this.entries.find(
|
|
112
|
+
e => e.destStart <= destPos && e.destEnd >= destPos,
|
|
113
|
+
);
|
|
114
|
+
if (!entry) {
|
|
115
|
+
return { src: this.dest, position: destPos };
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
src: entry.src,
|
|
119
|
+
position: entry.srcStart + destPos - entry.destStart,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** sort entries in place by src start position */
|
|
125
|
+
function sortSrc(entries: SrcMapEntry[]): void {
|
|
126
|
+
entries.sort((a, b) => a.srcStart - b.srcStart);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Incrementally append to a string, tracking source references */
|
|
130
|
+
export class SrcMapBuilder {
|
|
131
|
+
#fragments: string[] = [];
|
|
132
|
+
#destLength = 0;
|
|
133
|
+
#entries: SrcMapEntry[] = [];
|
|
134
|
+
source: SrcWithPath;
|
|
135
|
+
|
|
136
|
+
constructor(source: SrcWithPath) {
|
|
137
|
+
this.source = source;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** append a string fragment to the destination string */
|
|
141
|
+
add(fragment: string, srcStart: number, srcEnd: number): void {
|
|
142
|
+
const destStart = this.#destLength;
|
|
143
|
+
this.#destLength += fragment.length;
|
|
144
|
+
const destEnd = this.#destLength;
|
|
145
|
+
|
|
146
|
+
this.#fragments.push(fragment);
|
|
147
|
+
this.#entries.push({
|
|
148
|
+
src: this.source,
|
|
149
|
+
srcStart,
|
|
150
|
+
srcEnd,
|
|
151
|
+
destStart,
|
|
152
|
+
destEnd,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Append a fragment to the destination string,
|
|
158
|
+
* mapping source to the previous,
|
|
159
|
+
* and guessing that the source fragment is just as long as the dest fragment.
|
|
160
|
+
*/
|
|
161
|
+
appendNext(fragment: string): void {
|
|
162
|
+
const lastEnd = this.#entries.at(-1)?.destEnd ?? 0;
|
|
163
|
+
this.add(fragment, lastEnd, lastEnd + fragment.length);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
addSynthetic(
|
|
167
|
+
fragment: string,
|
|
168
|
+
syntheticSource: string,
|
|
169
|
+
srcStart: number,
|
|
170
|
+
srcEnd: number,
|
|
171
|
+
): void {
|
|
172
|
+
const destStart = this.#destLength;
|
|
173
|
+
this.#destLength += fragment.length;
|
|
174
|
+
const destEnd = this.#destLength;
|
|
175
|
+
|
|
176
|
+
this.#fragments.push(fragment);
|
|
177
|
+
this.#entries.push({
|
|
178
|
+
src: { text: syntheticSource },
|
|
179
|
+
srcStart,
|
|
180
|
+
srcEnd,
|
|
181
|
+
destStart,
|
|
182
|
+
destEnd,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** append a synthetic newline, mapped to previous source location */
|
|
187
|
+
addNl(): void {
|
|
188
|
+
const lastEntry = this.#entries.at(-1) ?? { srcStart: 0, srcEnd: 0 };
|
|
189
|
+
const { srcStart, srcEnd } = lastEntry;
|
|
190
|
+
this.add("\n", srcStart, srcEnd);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/** copy a string fragment from the src to the destination string */
|
|
194
|
+
addCopy(srcStart: number, srcEnd: number): void {
|
|
195
|
+
const fragment = this.source.text.slice(srcStart, srcEnd);
|
|
196
|
+
this.add(fragment, srcStart, srcEnd);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/** return a SrcMap */
|
|
200
|
+
static build(builders: SrcMapBuilder[]): SrcMap {
|
|
201
|
+
const map = new SrcMap(
|
|
202
|
+
{ text: builders.map(b => b.#fragments.join("")).join("") },
|
|
203
|
+
builders.flatMap(b => b.#entries),
|
|
204
|
+
);
|
|
205
|
+
map.compact();
|
|
206
|
+
return map;
|
|
207
|
+
}
|
|
208
|
+
}
|
package/src/Stream.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Span } from "./Span.ts";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Interface for a tokenizer. Returns a "next token", and can be reset to
|
|
5
|
+
* previously saved positions (checkpoints).
|
|
6
|
+
*/
|
|
7
|
+
export interface Stream<T extends Token> {
|
|
8
|
+
/** Returns the current position */
|
|
9
|
+
checkpoint(): number;
|
|
10
|
+
/** Restores a position */
|
|
11
|
+
reset(position: number): void;
|
|
12
|
+
/**
|
|
13
|
+
* Returns the next token, or `null` if the end of the stream has been reached.
|
|
14
|
+
* Always leaves `checkpoint` right after the token.
|
|
15
|
+
*/
|
|
16
|
+
nextToken(): T | null;
|
|
17
|
+
/** src text */
|
|
18
|
+
src: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** A text token */
|
|
22
|
+
export interface Token {
|
|
23
|
+
kind: string;
|
|
24
|
+
text: string;
|
|
25
|
+
span: Span;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface TypedToken<Kind extends string> extends Token {
|
|
29
|
+
kind: Kind;
|
|
30
|
+
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { tracing } from "mini-parse";
|
|
2
1
|
import type {
|
|
3
2
|
AbstractElem,
|
|
4
3
|
AttributeElem,
|
|
@@ -13,6 +12,7 @@ import type {
|
|
|
13
12
|
} from "./AbstractElems.ts";
|
|
14
13
|
import type { TransformedAST, WeslJsPlugin } from "./Linker.ts";
|
|
15
14
|
import { visitAst } from "./LinkerUtil.ts";
|
|
15
|
+
import { debug } from "./Logging.ts";
|
|
16
16
|
import { findDecl } from "./LowerAndEmit.ts";
|
|
17
17
|
import { minimallyMangledName } from "./Mangler.ts";
|
|
18
18
|
import {
|
|
@@ -307,7 +307,7 @@ export function transformBindingReference(
|
|
|
307
307
|
const refName = memberRef.member.name;
|
|
308
308
|
const structMember = struct.members.find(m => m.name.name === refName)!;
|
|
309
309
|
if (!structMember || !structMember.mangledVarName) {
|
|
310
|
-
if (
|
|
310
|
+
if (debug) console.log(`missing mangledVarName for ${refName}`);
|
|
311
311
|
return { kind: "synthetic", text: refName };
|
|
312
312
|
}
|
|
313
313
|
const { extraComponents } = memberRef;
|
package/src/Util.ts
CHANGED