wesl 0.7.26 → 0.7.28
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/README.md +1 -1
- package/dist/index.d.ts +283 -147
- package/dist/index.js +1765 -1143
- package/package.json +2 -2
- package/src/AbstractElems.ts +264 -82
- package/src/ClickableError.ts +8 -1
- package/src/Linker.ts +63 -67
- package/src/LinkerUtil.ts +141 -7
- package/src/LowerAndEmit.ts +660 -304
- package/src/Mangler.ts +1 -1
- package/src/ModuleResolver.ts +15 -4
- package/src/ParseWESL.ts +21 -33
- package/src/SrcMap.ts +7 -19
- package/src/StandardTypes.ts +1 -1
- package/src/WeslDevice.ts +1 -0
- package/src/debug/ASTtoString.ts +92 -76
- package/src/index.ts +1 -1
- package/src/parse/AttachComments.ts +289 -0
- package/src/parse/ExpressionUtil.ts +3 -3
- package/src/parse/Keywords.ts +1 -1
- package/src/parse/ParseAttribute.ts +49 -71
- package/src/parse/ParseCall.ts +3 -4
- package/src/parse/ParseControlFlow.ts +100 -56
- package/src/parse/ParseDirective.ts +9 -8
- package/src/parse/ParseDoBlock.ts +63 -0
- package/src/parse/ParseExpression.ts +11 -10
- package/src/parse/ParseFn.ts +11 -33
- package/src/parse/ParseGlobalVar.ts +36 -27
- package/src/parse/ParseIdent.ts +4 -5
- package/src/parse/ParseLocalVar.ts +16 -12
- package/src/parse/ParseLoop.ts +76 -39
- package/src/parse/ParseModule.ts +65 -19
- package/src/parse/ParseSimpleStatement.ts +112 -66
- package/src/parse/ParseStatement.ts +40 -67
- package/src/parse/ParseStruct.ts +8 -22
- package/src/parse/ParseType.ts +10 -13
- package/src/parse/ParseUtil.ts +26 -12
- package/src/parse/ParseValueDeclaration.ts +18 -31
- package/src/parse/ParseWesl.ts +11 -14
- package/src/parse/ParsingContext.ts +11 -9
- package/src/parse/WeslStream.ts +138 -121
- package/src/parse/stream/RegexMatchers.ts +45 -0
- package/src/parse/stream/WeslLexer.ts +249 -0
- package/src/test/BevyLink.test.ts +18 -11
- package/src/test/ConditionalElif.test.ts +4 -2
- package/src/test/DeclCommentEmit.test.ts +122 -0
- package/src/test/DoBlock.test.ts +164 -0
- package/src/test/FilterValidElements.test.ts +4 -6
- package/src/test/Linker.test.ts +23 -7
- package/src/test/Mangling.test.ts +8 -4
- package/src/test/ParseComments.test.ts +234 -6
- package/src/test/ParseConditionsV2.test.ts +47 -175
- package/src/test/ParseElifV2.test.ts +12 -33
- package/src/test/ParseErrorV2.test.ts +0 -0
- package/src/test/ParseWeslV2.test.ts +247 -626
- package/src/test/StatementEmit.test.ts +143 -0
- package/src/test/StripWesl.ts +24 -3
- package/src/test/TestLink.ts +19 -3
- package/src/test/TestUtil.ts +18 -8
- package/src/test/Tokenizer.test.ts +96 -0
- package/src/test/__snapshots__/ParseWeslV2.test.ts.snap +10 -42
- package/src/RawEmit.ts +0 -103
- package/src/Reflection.ts +0 -336
- package/src/TransformBindingStructs.ts +0 -320
- package/src/parse/ContentsHelpers.ts +0 -70
- package/src/parse/stream/CachingStream.ts +0 -48
- package/src/parse/stream/MatchersStream.ts +0 -85
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
ContainerElem,
|
|
3
|
-
ElemKindMap,
|
|
4
|
-
GrammarElem,
|
|
5
|
-
TextElem,
|
|
6
|
-
} from "../AbstractElems.ts";
|
|
7
|
-
import type { SrcModule } from "../Scope.ts";
|
|
8
|
-
import type { ParsingContext } from "./ParsingContext.ts";
|
|
9
|
-
|
|
10
|
-
/** Push partial element onto stack for content collection. */
|
|
11
|
-
export function beginElem(
|
|
12
|
-
ctx: ParsingContext,
|
|
13
|
-
kind: ContainerElem["kind"],
|
|
14
|
-
contents: readonly GrammarElem[] = [],
|
|
15
|
-
): void {
|
|
16
|
-
ctx.state.context.openElems.push({ kind, contents: [...contents] });
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/** Pop element from stack, fill gaps with TextElems, return contents. */
|
|
20
|
-
export function finishContents(
|
|
21
|
-
ctx: ParsingContext,
|
|
22
|
-
start: number,
|
|
23
|
-
end: number,
|
|
24
|
-
): GrammarElem[] {
|
|
25
|
-
const open = ctx.state.context.openElems.pop();
|
|
26
|
-
if (!open) throw new Error("No open element to close");
|
|
27
|
-
return coverWithText(ctx, open.contents as GrammarElem[], start, end);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/** Finish element: get end position, close contents, return complete element. */
|
|
31
|
-
export function finishElem<K extends keyof ElemKindMap>(
|
|
32
|
-
kind: K,
|
|
33
|
-
start: number,
|
|
34
|
-
ctx: ParsingContext,
|
|
35
|
-
params: Omit<ElemKindMap[K], "kind" | "start" | "end" | "contents">,
|
|
36
|
-
): ElemKindMap[K] {
|
|
37
|
-
const end = ctx.stream.checkpoint();
|
|
38
|
-
const contents = finishContents(ctx, start, end);
|
|
39
|
-
return { kind, start, end, contents, ...params } as ElemKindMap[K];
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/** Create a TextElem */
|
|
43
|
-
export function makeText(
|
|
44
|
-
srcModule: SrcModule,
|
|
45
|
-
start: number,
|
|
46
|
-
end: number,
|
|
47
|
-
): TextElem {
|
|
48
|
-
return { kind: "text", start, end, srcModule };
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/** Fill gaps between child elements with TextElems. */
|
|
52
|
-
function coverWithText(
|
|
53
|
-
ctx: ParsingContext,
|
|
54
|
-
contents: GrammarElem[],
|
|
55
|
-
start: number,
|
|
56
|
-
end: number,
|
|
57
|
-
): GrammarElem[] {
|
|
58
|
-
const { srcModule } = ctx.state.stable;
|
|
59
|
-
const sorted = contents.slice().sort((a, b) => a.start - b.start);
|
|
60
|
-
const elems: GrammarElem[] = [];
|
|
61
|
-
let pos = start;
|
|
62
|
-
|
|
63
|
-
for (const elem of sorted) {
|
|
64
|
-
if (pos < elem.start) elems.push(makeText(srcModule, pos, elem.start));
|
|
65
|
-
elems.push(elem);
|
|
66
|
-
pos = elem.end;
|
|
67
|
-
}
|
|
68
|
-
if (pos < end) elems.push(makeText(srcModule, pos, end));
|
|
69
|
-
return elems;
|
|
70
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import type { Stream, Token } from "../../Stream.ts";
|
|
2
|
-
|
|
3
|
-
export class CachingStream<T extends Token> implements Stream<T> {
|
|
4
|
-
private cache = new Cache<number, { token: T | null; checkpoint: number }>(5);
|
|
5
|
-
private inner: Stream<T>;
|
|
6
|
-
constructor(inner: Stream<T>) {
|
|
7
|
-
this.inner = inner;
|
|
8
|
-
}
|
|
9
|
-
checkpoint(): number {
|
|
10
|
-
return this.inner.checkpoint();
|
|
11
|
-
}
|
|
12
|
-
reset(position: number): void {
|
|
13
|
-
this.inner.reset(position);
|
|
14
|
-
}
|
|
15
|
-
nextToken(): T | null {
|
|
16
|
-
const startPos = this.checkpoint();
|
|
17
|
-
const cachedValue = this.cache.get(startPos);
|
|
18
|
-
if (cachedValue !== undefined) {
|
|
19
|
-
this.reset(cachedValue.checkpoint);
|
|
20
|
-
return cachedValue.token;
|
|
21
|
-
} else {
|
|
22
|
-
const token = this.inner.nextToken();
|
|
23
|
-
const checkpoint = this.checkpoint();
|
|
24
|
-
this.cache.set(startPos, { token, checkpoint });
|
|
25
|
-
return token;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
get src(): string {
|
|
29
|
-
return this.inner.src;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/** size limited key value cache */
|
|
34
|
-
class Cache<K, V> extends Map<K, V> {
|
|
35
|
-
private readonly max: number;
|
|
36
|
-
constructor(max: number) {
|
|
37
|
-
super();
|
|
38
|
-
this.max = max;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
set(k: K, v: V): this {
|
|
42
|
-
if (this.size > this.max) {
|
|
43
|
-
const first = this.keys().next().value;
|
|
44
|
-
if (first) this.delete(first);
|
|
45
|
-
}
|
|
46
|
-
return super.set(k, v);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import type { Span } from "../../Span.ts";
|
|
2
|
-
import type { Stream, TypedToken } from "../../Stream.ts";
|
|
3
|
-
import { toRegexSource } from "./RegexHelpers.ts";
|
|
4
|
-
|
|
5
|
-
/** Runs a `RegexMatchers` on an input string */
|
|
6
|
-
export class MatchersStream<Kind extends string>
|
|
7
|
-
implements Stream<TypedToken<Kind>>
|
|
8
|
-
{
|
|
9
|
-
private position = 0;
|
|
10
|
-
public text: string;
|
|
11
|
-
private matchers: RegexMatchers<Kind>;
|
|
12
|
-
|
|
13
|
-
constructor(text: string, matchers: RegexMatchers<Kind>) {
|
|
14
|
-
this.text = text;
|
|
15
|
-
this.matchers = matchers;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
checkpoint(): number {
|
|
19
|
-
return this.position;
|
|
20
|
-
}
|
|
21
|
-
reset(position: number): void {
|
|
22
|
-
this.position = position;
|
|
23
|
-
}
|
|
24
|
-
nextToken(): TypedToken<Kind> | null {
|
|
25
|
-
const result = this.matchers.execAt(this.text, this.position);
|
|
26
|
-
if (result === null) return null;
|
|
27
|
-
this.position = result.span[1];
|
|
28
|
-
return result;
|
|
29
|
-
}
|
|
30
|
-
get src(): string {
|
|
31
|
-
return this.text;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* The matchers passed to this object must follow certain rules:
|
|
37
|
-
* - They must use non-capturing groups: `(?:...)`
|
|
38
|
-
* - They must NOT use `^` or `$`
|
|
39
|
-
*/
|
|
40
|
-
export class RegexMatchers<Kind extends string> {
|
|
41
|
-
private groups: Kind[];
|
|
42
|
-
private exp: RegExp;
|
|
43
|
-
constructor(matchers: Record<Kind, string | RegExp>) {
|
|
44
|
-
this.groups = Object.keys(matchers) as Kind[];
|
|
45
|
-
const expParts = Object.entries(matchers as Record<string, string | RegExp>)
|
|
46
|
-
.map(toRegexSource)
|
|
47
|
-
.join("|");
|
|
48
|
-
// d = return substrings of each match
|
|
49
|
-
// y = sticky, only match at the start of the string
|
|
50
|
-
// u = unicode aware
|
|
51
|
-
this.exp = new RegExp(expParts, "dyu");
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
execAt(text: string, position: number): TypedToken<Kind> | null {
|
|
55
|
-
this.exp.lastIndex = position;
|
|
56
|
-
const matches = this.exp.exec(text);
|
|
57
|
-
const matchedIndex = findGroupDex(matches?.indices);
|
|
58
|
-
|
|
59
|
-
if (matchedIndex) {
|
|
60
|
-
const { span, groupDex } = matchedIndex;
|
|
61
|
-
const kind = this.groups[groupDex];
|
|
62
|
-
return { kind, span, text: text.slice(span[0], span[1]) };
|
|
63
|
-
} else {
|
|
64
|
-
return null;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
interface MatchedIndex {
|
|
70
|
-
span: Span;
|
|
71
|
-
groupDex: number;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function findGroupDex(
|
|
75
|
-
indices: RegExpIndicesArray | undefined,
|
|
76
|
-
): MatchedIndex | undefined {
|
|
77
|
-
if (indices !== undefined) {
|
|
78
|
-
for (let i = 1; i < indices.length; i++) {
|
|
79
|
-
const span = indices[i];
|
|
80
|
-
if (span !== undefined) {
|
|
81
|
-
return { span, groupDex: i - 1 };
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|