@xaendar/compiler 0.7.27 → 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.
@@ -2878,7 +2878,7 @@ var Parser = class {
2878
2878
  * `TypeChecker` for why) — attribute expressions and event calls are
2879
2879
  * emitted as bare statements, validated in place.
2880
2880
  */
2881
- function typeCheckElement(node, processNode) {
2881
+ function typeCheckElement(node, processNode, context) {
2882
2882
  const lines = [];
2883
2883
  node.attributes.forEach(({ value }) => {
2884
2884
  if (typeof value !== "string") lines.push(`${resolveExpression(value.expression, { resolver: "root" })};`);
@@ -2888,7 +2888,7 @@ function typeCheckElement(node, processNode) {
2888
2888
  lines.push(`root.${handler}(${args});`);
2889
2889
  });
2890
2890
  node.children.forEach((child, i) => {
2891
- lines.push(...processNode(child));
2891
+ lines.push(...processNode(child, context));
2892
2892
  });
2893
2893
  return lines;
2894
2894
  }
@@ -2904,12 +2904,21 @@ function typeCheckElement(node, processNode) {
2904
2904
  * exactly like it would for a loop written by hand — with no synthetic
2905
2905
  * function boundary needed.
2906
2906
  */
2907
- function typeCheckFor(node, processNode) {
2907
+ function typeCheckFor(node, processNode, context) {
2908
+ const forContext = new CompilerContext([], context);
2908
2909
  const indexName = resolveImplicit(node, "$index");
2909
2910
  const firstName = resolveImplicit(node, "$first");
2910
2911
  const lastName = resolveImplicit(node, "$last");
2911
2912
  const evenName = resolveImplicit(node, "$even");
2912
2913
  const oddName = resolveImplicit(node, "$odd");
2914
+ [
2915
+ indexName,
2916
+ firstName,
2917
+ lastName,
2918
+ evenName,
2919
+ oddName,
2920
+ node.itemAlias
2921
+ ].forEach((identifier) => forContext.addUnresolvableIdentifier(identifier));
2913
2922
  const lines = [];
2914
2923
  lines.push(`for (const ${node.itemAlias} of root.${node.iterableSource}) {`);
2915
2924
  lines.push(...indent([
@@ -2919,7 +2928,7 @@ function typeCheckFor(node, processNode) {
2919
2928
  `let ${evenName}!: boolean;`,
2920
2929
  `let ${oddName}!: boolean;`,
2921
2930
  `${resolveExpression(node.trackExpression, { skipResolution: true })};`,
2922
- ...node.children.flatMap((child, i) => processNode(child))
2931
+ ...node.children.flatMap((child) => processNode(child, context))
2923
2932
  ]));
2924
2933
  lines.push("}");
2925
2934
  return lines;
@@ -2952,23 +2961,23 @@ function resolveImplicit(node, implicit) {
2952
2961
  * `else if`, TS already knows the first condition was false) — something
2953
2962
  * flat sibling functions could never express.
2954
2963
  */
2955
- function typeCheckIf(node, processNode) {
2964
+ function typeCheckIf(node, processNode, context) {
2956
2965
  const lines = [];
2957
2966
  const condition = resolveExpression(node.conditionNode, { resolver: "root" });
2958
2967
  lines.push(`if (${condition}) {`);
2959
- lines.push(...indent(node.children.flatMap((child) => processNode(child))));
2968
+ lines.push(...indent(node.children.flatMap((child) => processNode(child, context))));
2960
2969
  lines.push("}");
2961
2970
  let alt = node.alternate;
2962
2971
  while (alt?.type === ASTNodeType.ElseIf) {
2963
2972
  const elseIfCondition = resolveExpression(alt.conditionNode, { resolver: "root" });
2964
2973
  lines.push(`else if (${elseIfCondition}) {`);
2965
- lines.push(...indent(alt.children.flatMap((child) => processNode(child))));
2974
+ lines.push(...indent(alt.children.flatMap((child) => processNode(child, context))));
2966
2975
  lines.push("}");
2967
2976
  alt = alt.alternate;
2968
2977
  }
2969
2978
  if (alt) {
2970
2979
  lines.push("else {");
2971
- lines.push(...indent(alt.children.flatMap((child) => processNode(child))));
2980
+ lines.push(...indent(alt.children.flatMap((child) => processNode(child, context))));
2972
2981
  lines.push("}");
2973
2982
  }
2974
2983
  return lines;
@@ -2990,14 +2999,11 @@ function typeCheckIf(node, processNode) {
2990
2999
  * emitted as stacked `case` labels sharing that same body, matching real
2991
3000
  * JS/TS fallthrough syntax directly.
2992
3001
  */
2993
- function typeCheckSwitch(node, processNode) {
3002
+ function typeCheckSwitch(node, processNode, context) {
2994
3003
  const lines = [`switch (${resolveExpression(node.expression, { resolver: "root" })}) {`];
2995
- node.children.forEach((caseNode, i) => {
2996
- if (caseNode.condition?.length) caseNode.condition.forEach((conditionValue) => {
2997
- lines.push(` case ${conditionValue}:`);
2998
- });
2999
- else lines.push(" default:");
3000
- lines.push(...indent(indent([...caseNode.children.flatMap((child) => processNode(child)), "break;"])));
3004
+ node.children.forEach((caseNode) => {
3005
+ caseNode.condition?.length ? caseNode.condition.forEach((conditionValue) => lines.push(` case ${conditionValue}:`)) : lines.push(" default:");
3006
+ lines.push(...indent(indent([...caseNode.children.flatMap((child) => processNode(child, context)), "break;"])));
3001
3007
  });
3002
3008
  lines.push("}");
3003
3009
  return lines;
@@ -3011,7 +3017,7 @@ function typeCheckSwitch(node, processNode) {
3011
3017
  * interpolation's expression is emitted as a bare statement — enough for
3012
3018
  * TS to validate it, with no name needing to be bound to the result.
3013
3019
  */
3014
- function typeCheckTextAndInterpolation(node, _processNode) {
3020
+ function typeCheckTextAndInterpolation(node, _processNode, _context) {
3015
3021
  return node.type === ASTNodeType.Interpolation ? [`${resolveExpression(node.expression, { resolver: "root" })};`] : [];
3016
3022
  }
3017
3023
  //#endregion
@@ -3062,7 +3068,7 @@ var TypeChecker = class {
3062
3068
  * relevant if the consuming project has `noUnusedLocals` enabled.
3063
3069
  */
3064
3070
  generate() {
3065
- const body = this._ast.flatMap((node, i) => this._processNode(node));
3071
+ const body = this._ast.flatMap((node) => this._processNode(node));
3066
3072
  return [
3067
3073
  "function typeCheck() {",
3068
3074
  ...indent(body.some((line) => line.includes("$event")) ? ["let $event!: Event;", ...body] : body),
@@ -3074,10 +3080,10 @@ var TypeChecker = class {
3074
3080
  * back down as `processNode` so state functions can recurse into their
3075
3081
  * own children inline.
3076
3082
  */
3077
- _processNode = (node) => {
3083
+ _processNode = (node, context) => {
3078
3084
  const state = this._states[node.type];
3079
3085
  if (!state) throw new Error(`[Type Checker] No transition function for token type ${ASTNodeType[node.type]}`);
3080
- return state(node, this._processNode);
3086
+ return state(node, this._processNode, context);
3081
3087
  };
3082
3088
  };
3083
3089
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xaendar/compiler",
3
- "version": "0.7.27",
3
+ "version": "0.7.28",
4
4
  "description": "A library for transpiling Xaendar Templates into JavaScript code",
5
5
  "sideEffects": false,
6
6
  "type": "module",
@@ -16,8 +16,8 @@
16
16
  }
17
17
  },
18
18
  "dependencies": {
19
- "@xaendar/common": "0.7.27",
20
- "@xaendar/types": "0.7.27",
19
+ "@xaendar/common": "0.7.28",
20
+ "@xaendar/types": "0.7.28",
21
21
  "typescript": "^6.0.3"
22
22
  }
23
23
  }