@galacean/engine-shader-compiler 2.0.0-alpha.32 → 2.0.0-alpha.33

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@galacean/engine-shader-compiler",
3
- "version": "2.0.0-alpha.32",
3
+ "version": "2.0.0-alpha.33",
4
4
  "publishConfig": {
5
5
  "access": "public",
6
6
  "registry": "https://registry.npmjs.org"
@@ -21,10 +21,15 @@
21
21
  "types": "./types/index.d.ts"
22
22
  },
23
23
  "./bundler/rollup": {
24
- "import": "./dist/bundler/rollup.js",
25
- "require": "./dist/bundler/rollup.cjs.js",
24
+ "import": "./bundler/rollup.js",
25
+ "require": "./bundler/rollup.cjs.js",
26
26
  "types": "./types/bundler/rollup.d.ts"
27
27
  },
28
+ "./bundler/precompile": {
29
+ "import": "./bundler/precompile.js",
30
+ "require": "./bundler/precompile.cjs.js",
31
+ "types": "./types/bundler/precompile.d.ts"
32
+ },
28
33
  "./verbose": {
29
34
  "import": "./dist/module.verbose.js",
30
35
  "require": "./dist/main.verbose.js",
@@ -34,7 +39,7 @@
34
39
  "./package.json": "./package.json"
35
40
  },
36
41
  "bin": {
37
- "shader-compiler-precompile": "./dist/bundler/cli.js"
42
+ "shader-compiler-precompile": "./bundler/cli.js"
38
43
  },
39
44
  "umd": {
40
45
  "name": "Galacean.ShaderCompiler",
@@ -45,19 +50,20 @@
45
50
  },
46
51
  "files": [
47
52
  "dist/**/*",
53
+ "bundler/**/*",
48
54
  "types/**/*",
49
55
  "verbose/package.json"
50
56
  ],
51
57
  "dependencies": {
52
58
  "@rollup/pluginutils": "^5.0.0",
53
- "@galacean/engine-math": "2.0.0-alpha.32",
54
- "@galacean/engine-core": "2.0.0-alpha.32"
59
+ "@galacean/engine-math": "2.0.0-alpha.33",
60
+ "@galacean/engine-core": "2.0.0-alpha.33"
55
61
  },
56
62
  "devDependencies": {
57
- "@galacean/engine-design": "2.0.0-alpha.32"
63
+ "@galacean/engine-design": "2.0.0-alpha.33"
58
64
  },
59
65
  "scripts": {
60
- "build": "rollup -c rollup.config.js && chmod +x dist/bundler/cli.js",
66
+ "build": "rollup -c rollup.config.js && chmod +x bundler/cli.js",
61
67
  "b:types": "tsc"
62
68
  }
63
69
  }
@@ -1,5 +1,5 @@
1
1
  import { GalaceanDataType } from "./common";
2
- import { TreeNode } from "./parser/AST";
2
+ import { ASTNode, TreeNode } from "./parser/AST";
3
3
  import { GrammarSymbol, NoneTerminal } from "./parser/GrammarSymbol";
4
4
  export declare class ParserUtils {
5
5
  static unwrapNodeByType<T = TreeNode>(node: TreeNode, type: NoneTerminal): T | undefined;
@@ -10,11 +10,24 @@ export declare class ParserUtils {
10
10
  */
11
11
  static parseMacroParamList(lexeme: string): string[];
12
12
  /**
13
- * Return the lexeme of `expr` when it is (transitively) a single bare identifier
14
- * wrapped in primary/postfix expression nodes, e.g. `o` → "o". Returns null for
15
- * compound expressions (`o.x`, `foo(..)`, `arr[0]`, …). Useful for callers that
16
- * want to apply a substitution rule only at the root of an expression, never on
17
- * swizzles or nested member access.
13
+ * Walk single-child precedence-chain wrappers down to a `VariableIdentifier`,
14
+ * returning the leaf node (or `undefined` for any compound expression).
15
+ *
16
+ * `allowParens` chooses between two callers' needs:
17
+ * - `true` — descend through `( expression )` form, so `(v)` resolves to
18
+ * `v`. Use when the caller substitutes at the expression root
19
+ * (aliasing, renaming); user-written parens carry no extra meaning.
20
+ * - `false` — any 3-child `PrimaryExpression` aborts; `(v)` stays
21
+ * compound. Use when the caller treats the unwrapped node as a single
22
+ * token (IO-struct arg drop, alias detection); user-written parens
23
+ * must not collapse.
24
+ */
25
+ static unwrapBareIdentifier(node: TreeNode, options: {
26
+ allowParens: boolean;
27
+ }): ASTNode.VariableIdentifier | undefined;
28
+ /**
29
+ * Lexeme variant of `unwrapBareIdentifier({ allowParens: true })` for callers
30
+ * that already work with strings. Returns `null` for compound expressions.
18
31
  */
19
32
  static extractDirectIdentLexeme(expr: TreeNode): string | null;
20
33
  /**
@@ -4,23 +4,20 @@ export type IncludeMap = {
4
4
  readonly [includeName: string]: string | undefined;
5
5
  };
6
6
  export type ChunkOutputCache = Map<string, string>;
7
- /**
8
- * Record for a single `#define` directive. `valueAst` is set for expression
9
- * macros (joined into the AST pipeline); opaque macros leave it undefined and
10
- * are emitted verbatim to the GLSL driver.
11
- */
12
7
  export interface MacroDefineInfo {
13
8
  isFunction: boolean;
14
- name: string;
15
9
  params: string[];
16
- valueAst?: ASTNode.AssignmentExpression;
17
- /** Leading identifier of the value (`#define F foo` → `foo`, `#define F foo(a)`
18
- * → `foo`), or empty for literals / operator expressions. Drives symbol-table
19
- * lookup at macro call sites. */
20
- referenceName: string;
21
- /** Branch signature at the point of registration. The same `#define` repeated
22
- * in different `#ifdef` branches produces multiple entries with different
23
- * signatures; call sites filter to those visible from their own position. */
10
+ /** Value AST. Set when the replacement list parses as `expression` (which
11
+ * includes comma-separated lists per C99 §6.10.3); absent for the GLSL ES
12
+ * 3.00 §3.4 opaque cases the grammar can't reduce (empty, type-alias keyword,
13
+ * trailing punctuation, unbalanced bracket, trailing operator). Identifier
14
+ * references inside are collected by `MacroCallSymbol._collectIdentifierRefs`
15
+ * walking this subtree. */
16
+ valueAst?: ASTNode.Expression;
17
+ /** Whitespace-normalized directive text. Dedup key against re-includes in
18
+ * the same branch; differing values produce different keys. */
19
+ dedupKey: string;
20
+ /** `#ifdef` branch at registration time; call sites filter to visible entries. */
24
21
  branch: BranchSignature;
25
22
  }
26
23
  export interface MacroDefineList {
@@ -6,5 +6,5 @@ export declare class ShaderCompilerUtils {
6
6
  private static _shaderCompilerObjectPoolSet;
7
7
  static createObjectPool<T extends IPoolElement>(type: new () => T): ClearableObjectPool<T>;
8
8
  static clearAllShaderCompilerObjectPool(): void;
9
- static createGSError(message: string, errorName: GSErrorName, source: string, location: ShaderRange | ShaderPosition, file?: string): Error | undefined;
9
+ static createGSError(message: string, errorName: GSErrorName, source: string, location: ShaderRange | ShaderPosition, file?: string): Error;
10
10
  }
@@ -21,6 +21,7 @@ export declare class LALR1 {
21
21
  private _inferNextState;
22
22
  /** Resolve shift-reduce/reduce-reduce conflict detect */
23
23
  private _addAction;
24
+ private static _isKnownShiftPreferred;
24
25
  private computeFirstSet;
25
26
  private _computeFirstSetForNT;
26
27
  }
@@ -7,9 +7,6 @@ import { MacroDefineList } from "../Preprocessor";
7
7
  export declare class Lexer extends BaseLexer {
8
8
  macroDefineList: MacroDefineList;
9
9
  private static _lexemeTable;
10
- private static readonly _defineDirectiveReg;
11
- private static readonly _referenceReg;
12
- private static readonly _lineContinuationReg;
13
10
  private static _ifCounter;
14
11
  /** Two branch signatures are equal iff they have the same constraints in the
15
12
  * same order with the same polarity. Used by `#define` dedup and AST upgrade
@@ -33,7 +30,9 @@ export declare class Lexer extends BaseLexer {
33
30
  private _inMacroDefineValue;
34
31
  private _macroDefineExpectsNameToken;
35
32
  private _macroDefineExpectsParamsToken;
36
- private _macroDefineDirectiveStart;
33
+ private _currentMacroName;
34
+ private _currentMacroParamsLexeme;
35
+ private _currentMacroValueStart;
37
36
  private _branchStack;
38
37
  private _pendingBranchPushDefined;
39
38
  tokenize(): Generator<BaseToken<number>, BaseToken<number>, unknown>;
@@ -46,22 +45,52 @@ export declare class Lexer extends BaseLexer {
46
45
  /** True if the current char is an unescaped line break (ignoring `\` continuation). */
47
46
  private _isAtLineBreak;
48
47
  /**
49
- * Peek forward from `#define` and decide whether this directive should use the
50
- * expression-AST path or the legacy opaque path.
48
+ * Walk a `#define` directive head once and produce everything both routing
49
+ * and registration need: name range, optional params range, value range,
50
+ * and whether the value parses as an `expression`.
51
51
  *
52
- * The AST path's only purpose is to enable the shader compiler's structural rewrites
53
- * (varying flatten, struct-property reference tracking) on macro values that
54
- * mention struct members. Every other shape — bare identifiers, numeric
55
- * literals, type-alias keywords (`#define FxaaFloat2 vec2`), constructor
56
- * calls, qualifier fragments, `#define COMMA ,` etc. — is correctly handled
57
- * by the GLSL driver via textual substitution and needs no AST.
52
+ * The replacement list is split three ways:
58
53
  *
59
- * So the routing rule is positive and information-driven: **AST iff the
60
- * replacement list contains a `.` member-access operator**. This is robust
61
- * against new GLSL keywords / extensions and incidentally moves all simple
62
- * constants and type aliases off the 18-layer expression precedence chain.
54
+ * - **AST path** (`isExpression = true`): value parses as `expression`.
55
+ * Covers identifiers, literals, parenthesized sub-expressions, operator
56
+ * expressions, function calls, top-level comma lists (per C99 §6.10.3).
57
+ *
58
+ * - **Legacy opaque path** (`isExpression = false`, no throw): the three
59
+ * GLSL-ES-§3.4-legal-but-not-an-expression shapes with real-world use —
60
+ * 1. empty value e.g. `#define COMMON_INCLUDED`
61
+ * 2. single type/qualifier keyword e.g. `#define FxaaFloat float`
62
+ * 3. type-qualifier list e.g. `#define TEX_PARAM(s) mediump sampler2D s`
63
+ *
64
+ * Note on X-macro support: the classical C X-macro pattern (a list
65
+ * macro re-expanded with redefined `X(...)`) works fine — it uses
66
+ * function-like macros + `\` line-continuation + `#undef`, all of
67
+ * which Galacean supports. It does NOT require unbalanced parens.
68
+ *
69
+ * - **Authoring error** (throws): every other shape that's not a valid
70
+ * `expression`. Legal token sequences in theory but not used in real
71
+ * GLSL — almost always author mistakes. We surface one uniform
72
+ * diagnostic with the macro name and value text and let the user fix
73
+ * their code instead of routing politely.
74
+ *
75
+ * Unsupported shapes that throw (non-exhaustive — the predicate is
76
+ * "the value doesn't reduce as `expression` and isn't one of the three
77
+ * legacy shapes above"):
78
+ * - leading bare punctuation `,` `;` `:` `?` `)` `]`
79
+ * - trailing `,` or `;` e.g. `#define X a, b,`
80
+ * - trailing binary / unary op `+` `-` `*` `/` `%` `&` `|` `^`
81
+ * `<` `>` `=` `!` `~`
82
+ * - trailing ternary fragment `?` or `:`
83
+ * - unbalanced `[` / `]` e.g. `#define X a[b`
84
+ * - unbalanced `(` / `)` e.g. `#define PAREN (`
85
+ *
86
+ * Returns `null` if the directive is malformed before the name. `cursor` is
87
+ * the position past the last non-newline char (caller advances from there).
63
88
  */
64
- private _defineHasValue;
89
+ private _peekMacroDefine;
90
+ /** GLSL type / qualifier keywords that aren't expression starters when standing alone.
91
+ * `true` / `false` are excluded — they're `primary_expression` literals.
92
+ * `#`-prefixed entries are excluded — they're preprocessor directive names. */
93
+ private static _isNonExpressionLeadingKeyword;
65
94
  /**
66
95
  * If `i` points at a `\` immediately followed by a newline (`\n`, `\r`, or
67
96
  * `\r\n`), return the index just past the pair (a single atom in the C/GLSL
@@ -69,8 +98,7 @@ export declare class Lexer extends BaseLexer {
69
98
  * source of truth for line-continuation detection — callers along the
70
99
  * directive-scanning path (`_skipNonSemantic`, `_scanUtilBreakLine`,
71
100
  * `_scanMacroDefineParams`) all delegate here so the rule stays in one
72
- * place. The string-level `_lineContinuationReg` covers the regex path
73
- * used by `_registerMacroDefine` for one-shot folding.
101
+ * place.
74
102
  */
75
103
  private static _skipLineContinuation;
76
104
  /**
@@ -101,6 +129,10 @@ export declare class Lexer extends BaseLexer {
101
129
  /** Emit `MACRO_DEFINE_END` at the end of a `#define` value, consuming the newline. */
102
130
  private _emitMacroDefineEnd;
103
131
  private _registerMacroDefine;
132
+ /** Render a `[start, end)` value range as space-separated significant chars,
133
+ * using the same comment / line-continuation rules `_skipNonSemantic`
134
+ * applies on the token-stream path. Used as the dedup key body. */
135
+ private static _normalizeValueText;
104
136
  private _scanMacroConditionExpression;
105
137
  private _scanWord;
106
138
  /** True iff at least one `#define <word>` is reachable from the current branch. */
@@ -383,6 +383,21 @@ export declare namespace ASTNode {
383
383
  private _symbols;
384
384
  init(): void;
385
385
  semanticAnalyze(sa: SemanticAnalyzer): void;
386
+ /** Run the cross-arm shadowing probe for a MACRO_CALL site. No-op when the
387
+ * probe isn't meaningful: no macro name, name already resolved as a real
388
+ * reference, or name is a builtin (builtins can't be shadowed by a
389
+ * sibling-arm decl). */
390
+ private static _probeCrossArmShadowing;
391
+ /** Look up `name` in the symbol stack and, if a global var/fn declaration
392
+ * exists, push it into `referenceGlobalSymbolNames`. Returns `true` iff
393
+ * the lookup hit (caller can then derive type info). When `missWarnLoc`
394
+ * is non-null, a miss reports a "declared before used" warning; pass
395
+ * `null` for silent probes (e.g. FXAA-style cross-arm shadowing).
396
+ *
397
+ * Mutation contract: `symbols` is used as scratch storage — `lookupAll`
398
+ * clears and refills it. On hit, the caller may read `symbols[0]` for
399
+ * type info before the next call overwrites the contents. */
400
+ private static _lookupAndMarkGlobalReference;
386
401
  codeGen(visitor: CodeGenVisitor): string;
387
402
  getLexeme(visitor: CodeGenVisitor): string;
388
403
  }
@@ -442,18 +457,23 @@ export declare namespace ASTNode {
442
457
  * a root of `referenceSymbolNames`. Mixed forms across branches → false,
443
458
  * fall back to legacy inference. */
444
459
  hasAstValue: boolean;
445
- /** True when the macro is defined as function-like (`#define NAME(params) …`).
446
- * Used by `MacroCallFunction` codegen to pick between the two call shapes
447
- * — object-like-macro-as-function-name vs true function-like macro. */
460
+ /** `#define NAME(params) …` form — drives function-like vs object-like codegen. */
448
461
  isFunctionLikeMacro: boolean;
462
+ /** Every visible replacement is a non-builtin identifier — assume user fn alias. */
463
+ aliasesNonBuiltinIdent: boolean;
449
464
  init(): void;
450
465
  semanticAnalyze(sa: SemanticAnalyzer): void;
466
+ /** Push every leaf `VariableIdentifier`'s lexeme into `out`, skipping
467
+ * function-like parameter names (local to the macro, not call-site refs)
468
+ * and duplicates. */
469
+ private static _collectIdentifierRefs;
451
470
  }
452
471
  export class MacroCallFunction extends TreeNode {
453
472
  referenceSymbolNames: string[];
454
473
  macroName: string;
455
474
  hasAstValue: boolean;
456
475
  isFunctionLikeMacro: boolean;
476
+ aliasesNonBuiltinIdent: boolean;
457
477
  init(): void;
458
478
  semanticAnalyze(sa: SemanticAnalyzer): void;
459
479
  codeGen(visitor: CodeGenVisitor): string;
@@ -473,7 +493,7 @@ export declare namespace ASTNode {
473
493
  export class MacroDefine extends TreeNode {
474
494
  macroName: string;
475
495
  isFunction: boolean;
476
- valueExpression?: AssignmentExpression;
496
+ valueExpression?: Expression;
477
497
  init(): void;
478
498
  semanticAnalyze(sa: SemanticAnalyzer): void;
479
499
  codeGen(visitor: CodeGenVisitor): string;