@oddo/lang 0.0.1 → 0.0.3

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.js CHANGED
@@ -1849,6 +1849,7 @@ var OddoParser = class extends _chevrotain.CstParser {
1849
1849
  var parser = new OddoParser();
1850
1850
 
1851
1851
  // src/ast-converter.mjs
1852
+ var sourceText = "";
1852
1853
  function getFirstChild(node, ruleName) {
1853
1854
  var _a;
1854
1855
  const children = (_a = node.children) == null ? void 0 : _a[ruleName];
@@ -2022,8 +2023,11 @@ function convertImportSpecifier(cst) {
2022
2023
  local
2023
2024
  };
2024
2025
  }
2025
- function convertExpression(cst) {
2026
+ function convertExpression(cst, source) {
2026
2027
  if (!cst) return null;
2028
+ if (source !== void 0) {
2029
+ sourceText = source;
2030
+ }
2027
2031
  const nodeName = cst.name;
2028
2032
  if (nodeName === "assignment") return convertAssignment(cst);
2029
2033
  if (nodeName === "conditional") return convertConditional(cst);
@@ -2629,8 +2633,10 @@ function convertPostfix(cst) {
2629
2633
  return operand;
2630
2634
  }
2631
2635
  function convertFunctionCall(cst) {
2636
+ var _a;
2632
2637
  let callee = convertExpression(getFirstChild(cst, "memberAccess"));
2633
2638
  const leftParens = cst.children.LeftParen || [];
2639
+ const rightParens = cst.children.RightParen || [];
2634
2640
  const questionDots = cst.children.QuestionDot || [];
2635
2641
  const templateLiterals = cst.children.TemplateLiteral || [];
2636
2642
  if (templateLiterals.length > 0 && leftParens.length === 0) {
@@ -2648,11 +2654,16 @@ function convertFunctionCall(cst) {
2648
2654
  const argLists = getAllChildren(cst, "argumentList");
2649
2655
  const allExprs = getAllChildren(cst, "expression");
2650
2656
  const ops = [
2651
- ...leftParens.map((t2, i) => ({ k: "c", off: t2.startOffset, i, token: t2 })),
2657
+ ...leftParens.map((t2, i) => ({
2658
+ k: "c",
2659
+ off: t2.startOffset,
2660
+ token: t2,
2661
+ rightParen: rightParens[i]
2662
+ })),
2652
2663
  ...dots.map((t2, i) => ({ k: "d", off: t2.startOffset, i })),
2653
2664
  ...brackets.map((t2, i) => {
2654
- var _a;
2655
- return { k: "b", off: t2.startOffset, i, end: (_a = rightBrackets[i]) == null ? void 0 : _a.endOffset };
2665
+ var _a2;
2666
+ return { k: "b", off: t2.startOffset, i, end: (_a2 = rightBrackets[i]) == null ? void 0 : _a2.endOffset };
2656
2667
  }),
2657
2668
  ...questionDots.filter((q) => !leftParens.some((p) => Math.abs(p.startOffset - q.endOffset) <= 1)).map((t2, i) => ({ k: "q", off: t2.startOffset, i }))
2658
2669
  ].sort((a, b) => a.off - b.off);
@@ -2660,7 +2671,12 @@ function convertFunctionCall(cst) {
2660
2671
  for (const op of ops) {
2661
2672
  if (op.k === "c") {
2662
2673
  const isOptional = questionDots.some((q) => q.endOffset < op.token.startOffset && op.token.startOffset - q.endOffset <= 1);
2663
- const argsCST = argLists[op.i];
2674
+ const leftOff = op.token.startOffset;
2675
+ const rightOff = (_a = op.rightParen) == null ? void 0 : _a.endOffset;
2676
+ const argsCST = argLists.find((al) => {
2677
+ const alStart = getFirstTokenOffset(al);
2678
+ return alStart !== void 0 && alStart > leftOff && (rightOff === void 0 || alStart < rightOff);
2679
+ });
2664
2680
  const args = [];
2665
2681
  if (argsCST) {
2666
2682
  const exprs = getAllChildren(argsCST, "expression");
@@ -2680,9 +2696,9 @@ function convertFunctionCall(cst) {
2680
2696
  if (nextBracket) {
2681
2697
  const bIdx = brackets.indexOf(nextBracket);
2682
2698
  const expr = allExprs.find((e) => {
2683
- var _a;
2699
+ var _a2;
2684
2700
  const o = getFirstTokenOffset(e);
2685
- return o > nextBracket.startOffset && o < ((_a = rightBrackets[bIdx]) == null ? void 0 : _a.endOffset);
2701
+ return o > nextBracket.startOffset && o < ((_a2 = rightBrackets[bIdx]) == null ? void 0 : _a2.endOffset);
2686
2702
  });
2687
2703
  if (expr) callee = { type: "memberAccess", object: callee, property: convertExpression(expr), computed: true, optional: true };
2688
2704
  ops.splice(ops.findIndex((o) => o.k === "b" && o.i === bIdx), 1);
@@ -2705,6 +2721,7 @@ function convertMemberAccess(cst) {
2705
2721
  const dots = cst.children.Dot || [];
2706
2722
  const questionDots = cst.children.QuestionDot || [];
2707
2723
  const brackets = cst.children.LeftBracket || [];
2724
+ const rightBrackets = cst.children.RightBracket || [];
2708
2725
  const dotDotDots = cst.children.DotDotDot || [];
2709
2726
  if (dots.length === 0 && questionDots.length === 0 && brackets.length === 0) {
2710
2727
  return object;
@@ -2714,85 +2731,96 @@ function convertMemberAccess(cst) {
2714
2731
  allOps.push({ type: "dot", token: dot, optional: false });
2715
2732
  }
2716
2733
  for (const qDot of questionDots) {
2717
- allOps.push({ type: "dot", token: qDot, optional: true });
2718
- }
2719
- allOps.sort((a, b) => a.token.startOffset - b.token.startOffset);
2720
- const identifiers = cst.children.Identifier || [];
2721
- let identifierIndex = 0;
2722
- for (let i = 0; i < allOps.length; i++) {
2723
- const op = allOps[i];
2724
- const identifier2 = identifiers[identifierIndex];
2725
- if (identifier2) {
2726
- identifierIndex++;
2727
- object = {
2728
- type: "memberAccess",
2729
- object,
2730
- property: identifier2.image,
2731
- computed: false,
2732
- optional: op.optional
2733
- };
2734
+ const isFollowedByBracket = brackets.some((b) => b.startOffset > qDot.endOffset && b.startOffset - qDot.endOffset <= 1);
2735
+ if (!isFollowedByBracket) {
2736
+ allOps.push({ type: "dot", token: qDot, optional: true });
2734
2737
  }
2735
2738
  }
2736
- const expressions = getAllChildren(cst, "expression");
2737
- let expressionIndex = 0;
2738
2739
  for (let i = 0; i < brackets.length; i++) {
2739
2740
  const bracket = brackets[i];
2740
- const bracketStart = bracket.startOffset;
2741
- const isOptional = questionDots.some((qDot) => {
2742
- return qDot.endOffset < bracketStart && bracketStart - qDot.endOffset <= 1;
2743
- });
2744
- const rightBrackets = cst.children.RightBracket || [];
2745
2741
  const rightBracket = rightBrackets[i];
2746
2742
  if (!rightBracket) continue;
2743
+ const isOptional = questionDots.some(
2744
+ (qDot) => qDot.endOffset < bracket.startOffset && bracket.startOffset - qDot.endOffset <= 1
2745
+ );
2747
2746
  const dotDotDotsInRange = dotDotDots.filter(
2748
- (ddd) => ddd.startOffset > bracketStart && ddd.startOffset < rightBracket.startOffset
2747
+ (ddd) => ddd.startOffset > bracket.startOffset && ddd.startOffset < rightBracket.startOffset
2749
2748
  );
2750
- if (dotDotDotsInRange.length > 0) {
2751
- if (expressions.length === expressionIndex) {
2752
- object = {
2753
- type: "arraySlice",
2754
- object,
2755
- start: null,
2756
- end: null
2757
- };
2758
- continue;
2759
- }
2760
- if (expressions.length >= expressionIndex + 2) {
2761
- const startExpr = expressions[expressionIndex];
2762
- const endExpr = expressions[expressionIndex + 1];
2763
- expressionIndex += 2;
2749
+ allOps.push({
2750
+ type: "bracket",
2751
+ token: bracket,
2752
+ rightBracket,
2753
+ optional: isOptional,
2754
+ isSlice: dotDotDotsInRange.length > 0
2755
+ });
2756
+ }
2757
+ allOps.sort((a, b) => a.token.startOffset - b.token.startOffset);
2758
+ const identifiers = cst.children.Identifier || [];
2759
+ const expressions = getAllChildren(cst, "expression");
2760
+ let identifierIndex = 0;
2761
+ let expressionIndex = 0;
2762
+ for (const op of allOps) {
2763
+ if (op.type === "dot") {
2764
+ const identifier2 = identifiers[identifierIndex];
2765
+ if (identifier2) {
2766
+ identifierIndex++;
2764
2767
  object = {
2765
- type: "arraySlice",
2768
+ type: "memberAccess",
2766
2769
  object,
2767
- start: convertExpression(startExpr),
2768
- end: convertExpression(endExpr)
2770
+ property: identifier2.image,
2771
+ computed: false,
2772
+ optional: op.optional
2769
2773
  };
2770
- continue;
2771
2774
  }
2772
- if (expressions.length === expressionIndex + 1) {
2773
- const startExpr = expressions[expressionIndex];
2774
- expressionIndex++;
2775
- object = {
2776
- type: "arraySlice",
2777
- object,
2778
- start: convertExpression(startExpr),
2779
- end: null
2780
- };
2781
- continue;
2775
+ } else if (op.type === "bracket") {
2776
+ if (op.isSlice) {
2777
+ const exprsInBracket = expressions.filter((e, idx) => {
2778
+ if (idx < expressionIndex) return false;
2779
+ const exprStart = getFirstTokenOffset(e);
2780
+ return exprStart > op.token.startOffset && exprStart < op.rightBracket.startOffset;
2781
+ });
2782
+ if (exprsInBracket.length === 0) {
2783
+ object = {
2784
+ type: "arraySlice",
2785
+ object,
2786
+ start: null,
2787
+ end: null
2788
+ };
2789
+ } else if (exprsInBracket.length >= 2) {
2790
+ const startExpr = expressions[expressionIndex];
2791
+ const endExpr = expressions[expressionIndex + 1];
2792
+ expressionIndex += 2;
2793
+ object = {
2794
+ type: "arraySlice",
2795
+ object,
2796
+ start: convertExpression(startExpr),
2797
+ end: convertExpression(endExpr)
2798
+ };
2799
+ } else {
2800
+ const startExpr = expressions[expressionIndex];
2801
+ expressionIndex++;
2802
+ object = {
2803
+ type: "arraySlice",
2804
+ object,
2805
+ start: convertExpression(startExpr),
2806
+ end: null
2807
+ };
2808
+ }
2809
+ } else {
2810
+ if (expressions.length > expressionIndex) {
2811
+ const exprCst = expressions[expressionIndex];
2812
+ expressionIndex++;
2813
+ const property = convertExpression(exprCst);
2814
+ object = {
2815
+ type: "memberAccess",
2816
+ object,
2817
+ property,
2818
+ computed: true,
2819
+ optional: op.optional
2820
+ };
2821
+ }
2782
2822
  }
2783
2823
  }
2784
- if (expressions.length > expressionIndex) {
2785
- const exprCst = expressions[expressionIndex];
2786
- expressionIndex++;
2787
- const property = convertExpression(exprCst);
2788
- object = {
2789
- type: "memberAccess",
2790
- object,
2791
- property,
2792
- computed: true,
2793
- optional: isOptional
2794
- };
2795
- }
2796
2824
  }
2797
2825
  return object;
2798
2826
  }
@@ -3282,7 +3310,7 @@ function convertJSXElement(cst) {
3282
3310
  const isSelfClosing = cst.children.JSXSelfClosing && cst.children.JSXSelfClosing.length > 0;
3283
3311
  let children = [];
3284
3312
  if (!isSelfClosing) {
3285
- children = getAllChildren(cst, "jsxChild").map(convertJSXChild).filter((child) => child !== null);
3313
+ children = convertJSXChildren(getAllChildren(cst, "jsxChild"));
3286
3314
  }
3287
3315
  return {
3288
3316
  type: "jsxElement",
@@ -3295,7 +3323,7 @@ function convertJSXElement(cst) {
3295
3323
  }
3296
3324
  function convertJSXFragment(cst) {
3297
3325
  const childrenCST = getAllChildren(cst, "jsxChild");
3298
- const children = childrenCST.map(convertJSXChild).filter((child) => child !== null);
3326
+ const children = convertJSXChildren(childrenCST);
3299
3327
  return {
3300
3328
  type: "jsxFragment",
3301
3329
  children
@@ -3420,6 +3448,61 @@ function decodeHTMLEntities(text) {
3420
3448
  }
3421
3449
  });
3422
3450
  }
3451
+ function convertJSXChildren(childrenCST) {
3452
+ if (!childrenCST || childrenCST.length === 0) return [];
3453
+ const childrenWithOffsets = childrenCST.map((child) => {
3454
+ const firstOffset = getFirstTokenOffset(child);
3455
+ const lastOffset = getLastTokenOffset(child);
3456
+ return { cst: child, firstOffset, lastOffset };
3457
+ }).filter((c) => c.firstOffset !== void 0);
3458
+ childrenWithOffsets.sort((a, b) => a.firstOffset - b.firstOffset);
3459
+ const result = [];
3460
+ for (let i = 0; i < childrenWithOffsets.length; i++) {
3461
+ const current = childrenWithOffsets[i];
3462
+ if (i > 0 && sourceText) {
3463
+ const prev = childrenWithOffsets[i - 1];
3464
+ const gapStart = prev.lastOffset + 1;
3465
+ const gapEnd = current.firstOffset;
3466
+ if (gapEnd > gapStart) {
3467
+ const gap = sourceText.slice(gapStart, gapEnd);
3468
+ if (gap && /\s/.test(gap)) {
3469
+ result.push({ type: "jsxText", value: " " });
3470
+ }
3471
+ }
3472
+ }
3473
+ const converted = convertJSXChild(current.cst);
3474
+ if (converted !== null) {
3475
+ result.push(converted);
3476
+ }
3477
+ }
3478
+ return result;
3479
+ }
3480
+ function getLastTokenOffset(node) {
3481
+ if (!node) return void 0;
3482
+ if (node.endOffset !== void 0) {
3483
+ return node.endOffset;
3484
+ }
3485
+ if (node.image !== void 0 && node.startOffset !== void 0) {
3486
+ return node.startOffset + node.image.length - 1;
3487
+ }
3488
+ let lastOffset;
3489
+ if (node.children) {
3490
+ for (const key in node.children) {
3491
+ const children = node.children[key];
3492
+ if (Array.isArray(children)) {
3493
+ for (const child of children) {
3494
+ const childOffset = getLastTokenOffset(child);
3495
+ if (childOffset !== void 0) {
3496
+ if (lastOffset === void 0 || childOffset > lastOffset) {
3497
+ lastOffset = childOffset;
3498
+ }
3499
+ }
3500
+ }
3501
+ }
3502
+ }
3503
+ }
3504
+ return lastOffset;
3505
+ }
3423
3506
  function convertJSXChild(cst) {
3424
3507
  if (cst.children.jsxElement) {
3425
3508
  return convertJSXElement(getFirstChild(cst, "jsxElement"));
@@ -3473,8 +3556,9 @@ function convertJSXChild(cst) {
3473
3556
  }
3474
3557
  return null;
3475
3558
  }
3476
- function convertCSTToAST(cst) {
3559
+ function convertCSTToAST(cst, source = "") {
3477
3560
  if (!cst) return null;
3561
+ sourceText = source;
3478
3562
  if (cst.name === "program") {
3479
3563
  const statements = getAllChildren(cst, "statement").map(convertStatement);
3480
3564
  return {
@@ -3491,6 +3575,9 @@ var _traverse2 = require('@babel/traverse'); var _traverse3 = _interopRequireDef
3491
3575
  var _types = require('@babel/types'); var t = _interopRequireWildcard(_types);
3492
3576
  var generate = _generator2.default.default || _generator2.default;
3493
3577
  var traverse = _traverse3.default.default || _traverse3.default;
3578
+ function isValidJSIdentifier(name) {
3579
+ return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
3580
+ }
3494
3581
  function extractIdentifiers(babelNode) {
3495
3582
  const identifiers = /* @__PURE__ */ new Set();
3496
3583
  const locals = /* @__PURE__ */ new Set();
@@ -3891,6 +3978,11 @@ var MODIFIER_TRANSFORMATIONS = {
3891
3978
  const identifiers = bodyIdentifiers.filter((id) => !ownParams.has(id) && isReactive(id));
3892
3979
  const params = identifiers.map((id) => t.identifier(id));
3893
3980
  const deps = identifiers.map((id) => t.identifier(id));
3981
+ const savedScope = currentScope;
3982
+ currentScope = Object.create(currentScope);
3983
+ for (const id of identifiers) {
3984
+ currentScope[id] = { type: "param", reactive: false };
3985
+ }
3894
3986
  let convertedBody;
3895
3987
  if (oddoExpr.body && oddoExpr.body.type === "blockStatement") {
3896
3988
  const statements = oddoExpr.body.body.map((stmt) => convertStatement2(stmt));
@@ -3901,6 +3993,7 @@ var MODIFIER_TRANSFORMATIONS = {
3901
3993
  } else {
3902
3994
  convertedBody = t.blockStatement([]);
3903
3995
  }
3996
+ currentScope = savedScope;
3904
3997
  const arrowFunc = t.arrowFunctionExpression(params, convertedBody);
3905
3998
  wrapDependenciesWithCalls(arrowFunc, identifiers);
3906
3999
  const effectCall = t.callExpression(
@@ -3949,6 +4042,37 @@ function isNonReactive(name) {
3949
4042
  var _a;
3950
4043
  return ((_a = currentScope[name]) == null ? void 0 : _a.reactive) === false;
3951
4044
  }
4045
+ function extractBoundNames(pattern, names = []) {
4046
+ var _a, _b;
4047
+ if (!pattern) return names;
4048
+ if (pattern.type === "identifier") {
4049
+ names.push(pattern.name);
4050
+ } else if (pattern.type === "objectPattern") {
4051
+ for (const prop of pattern.properties || []) {
4052
+ if (prop.type === "property") {
4053
+ extractBoundNames(prop.value, names);
4054
+ } else if (prop.type === "restProperty") {
4055
+ if (((_a = prop.argument) == null ? void 0 : _a.type) === "identifier") {
4056
+ names.push(prop.argument.name);
4057
+ }
4058
+ }
4059
+ }
4060
+ } else if (pattern.type === "arrayPattern") {
4061
+ for (const element of pattern.elements || []) {
4062
+ if (!element) continue;
4063
+ if (element.type === "identifier") {
4064
+ names.push(element.name);
4065
+ } else if (element.type === "restElement") {
4066
+ if (((_b = element.argument) == null ? void 0 : _b.type) === "identifier") {
4067
+ names.push(element.argument.name);
4068
+ }
4069
+ } else {
4070
+ extractBoundNames(element, names);
4071
+ }
4072
+ }
4073
+ }
4074
+ return names;
4075
+ }
3952
4076
  function generateUniqueId(baseName) {
3953
4077
  let candidate = baseName;
3954
4078
  let i = 2;
@@ -3959,7 +4083,7 @@ function generateUniqueId(baseName) {
3959
4083
  return candidate;
3960
4084
  }
3961
4085
  function collectOddoIdentifiers(node, names = /* @__PURE__ */ new Set()) {
3962
- var _a, _b, _c;
4086
+ var _a, _b, _c, _d;
3963
4087
  if (!node || typeof node !== "object") return names;
3964
4088
  if (node.type === "program") {
3965
4089
  moduleScope = /* @__PURE__ */ Object.create(null);
@@ -3990,6 +4114,13 @@ function collectOddoIdentifiers(node, names = /* @__PURE__ */ new Set()) {
3990
4114
  for (const param of node.parameters) {
3991
4115
  if (param.name) {
3992
4116
  declareVariable(param.name, "param");
4117
+ } else if (param.type === "destructuringPattern") {
4118
+ const boundNames = extractBoundNames(param.pattern);
4119
+ for (const name of boundNames) {
4120
+ declareVariable(name, "param");
4121
+ }
4122
+ } else if (param.type === "restElement" && ((_d = param.argument) == null ? void 0 : _d.name)) {
4123
+ declareVariable(param.argument.name, "param");
3993
4124
  }
3994
4125
  }
3995
4126
  }
@@ -4149,9 +4280,17 @@ function convertExpressionStatement2(stmt) {
4149
4280
  let leftExpr = null;
4150
4281
  if (blockStmt.expression.type === "variableDeclaration" || blockStmt.expression.type === "assignment") {
4151
4282
  leftExpr = convertExpression2(blockStmt.expression.left);
4152
- valueExpr = convertExpression2(blockStmt.expression.right);
4283
+ if (stmt.modifier === "mutate" || stmt.modifier === "effect") {
4284
+ valueExpr = blockStmt.expression.right;
4285
+ } else {
4286
+ valueExpr = convertExpression2(blockStmt.expression.right);
4287
+ }
4153
4288
  } else {
4154
- valueExpr = convertExpression2(blockStmt.expression);
4289
+ if (stmt.modifier === "mutate" || stmt.modifier === "effect") {
4290
+ valueExpr = blockStmt.expression;
4291
+ } else {
4292
+ valueExpr = convertExpression2(blockStmt.expression);
4293
+ }
4155
4294
  }
4156
4295
  const { transform } = modifierTransform;
4157
4296
  usedModifiers.add(stmt.modifier);
@@ -4616,7 +4755,7 @@ function convertObjectPattern(expr) {
4616
4755
  function convertJSXChild2(child) {
4617
4756
  if (child.type === "jsxText") {
4618
4757
  const text = child.value;
4619
- if (!text.trim()) return null;
4758
+ if (!text) return null;
4620
4759
  return t.stringLiteral(text);
4621
4760
  } else if (child.type === "jsxExpression") {
4622
4761
  const innerExpr = convertExpression2(child.expression);
@@ -4641,7 +4780,7 @@ function convertJSXElement2(expr) {
4641
4780
  if (attr.type === "jsxSpread") {
4642
4781
  properties.push(t.spreadElement(convertExpression2(attr.expression)));
4643
4782
  } else {
4644
- const key = t.identifier(attr.name);
4783
+ const key = isValidJSIdentifier(attr.name) ? t.identifier(attr.name) : t.stringLiteral(attr.name);
4645
4784
  let value;
4646
4785
  if (attr.value === null) {
4647
4786
  value = t.booleanLiteral(true);
@@ -4662,7 +4801,7 @@ function convertJSXElement2(expr) {
4662
4801
  } else {
4663
4802
  const properties = [];
4664
4803
  for (const attr of expr.attributes) {
4665
- const key = t.identifier(attr.name);
4804
+ const key = isValidJSIdentifier(attr.name) ? t.identifier(attr.name) : t.stringLiteral(attr.name);
4666
4805
  let value;
4667
4806
  if (attr.value === null) {
4668
4807
  value = t.booleanLiteral(true);
@@ -4917,7 +5056,7 @@ function parseOddo(input) {
4917
5056
  });
4918
5057
  throw new Error(`Parser errors: ${JSON.stringify(errors)}`);
4919
5058
  }
4920
- const ast = convertCSTToAST(cst);
5059
+ const ast = convertCSTToAST(cst, input);
4921
5060
  return ast;
4922
5061
  }
4923
5062
  function parseOddoExpression(input) {
@@ -4944,7 +5083,7 @@ function parseOddoExpression(input) {
4944
5083
  });
4945
5084
  throw new Error(`Parser errors: ${JSON.stringify(errors)}`);
4946
5085
  }
4947
- const ast = convertExpression(cst);
5086
+ const ast = convertExpression(cst, input);
4948
5087
  return ast;
4949
5088
  }
4950
5089
  function compileOddoToJS(input, config = {}) {