@oddo/lang 0.0.10 → 0.0.12

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
@@ -179,6 +179,9 @@ var UnsignedRightShiftColonEqual = _chevrotain.createToken.call(void 0, { name:
179
179
  var AndColonEqual = _chevrotain.createToken.call(void 0, { name: "AndColonEqual", pattern: /&:=/ });
180
180
  var CaretColonEqual = _chevrotain.createToken.call(void 0, { name: "CaretColonEqual", pattern: /\^:=/ });
181
181
  var OrColonEqual = _chevrotain.createToken.call(void 0, { name: "OrColonEqual", pattern: /\|:=/ });
182
+ var AndAndColonEqual = _chevrotain.createToken.call(void 0, { name: "AndAndColonEqual", pattern: /&&:=/ });
183
+ var OrOrColonEqual = _chevrotain.createToken.call(void 0, { name: "OrOrColonEqual", pattern: /\|\|:=/ });
184
+ var QuestionQuestionColonEqual = _chevrotain.createToken.call(void 0, { name: "QuestionQuestionColonEqual", pattern: /\?\?:=/ });
182
185
  var Equal = _chevrotain.createToken.call(void 0, { name: "Equal", pattern: /=/ });
183
186
  var LeftParen = _chevrotain.createToken.call(void 0, { name: "LeftParen", pattern: /\(/ });
184
187
  var RightParen = _chevrotain.createToken.call(void 0, { name: "RightParen", pattern: /\)/ });
@@ -271,6 +274,12 @@ var allTokens = [
271
274
  // |:= must come before |
272
275
  CaretColonEqual,
273
276
  // ^:= must come before ^
277
+ AndAndColonEqual,
278
+ // &&:= must come before &&
279
+ OrOrColonEqual,
280
+ // ||:= must come before ||
281
+ QuestionQuestionColonEqual,
282
+ // ??:= must come before ??
274
283
  EqualEqual,
275
284
  BangEqual,
276
285
  LessThanEqual,
@@ -399,6 +408,9 @@ var OddoParser = class extends _chevrotain.CstParser {
399
408
  AndColonEqual,
400
409
  CaretColonEqual,
401
410
  OrColonEqual,
411
+ AndAndColonEqual,
412
+ OrOrColonEqual,
413
+ QuestionQuestionColonEqual,
402
414
  Equal,
403
415
  // Punctuation
404
416
  LeftParen,
@@ -811,7 +823,10 @@ var OddoParser = class extends _chevrotain.CstParser {
811
823
  { ALT: () => this.CONSUME(UnsignedRightShiftColonEqual) },
812
824
  { ALT: () => this.CONSUME(AndColonEqual) },
813
825
  { ALT: () => this.CONSUME(CaretColonEqual) },
814
- { ALT: () => this.CONSUME(OrColonEqual) }
826
+ { ALT: () => this.CONSUME(OrColonEqual) },
827
+ { ALT: () => this.CONSUME(AndAndColonEqual) },
828
+ { ALT: () => this.CONSUME(OrOrColonEqual) },
829
+ { ALT: () => this.CONSUME(QuestionQuestionColonEqual) }
815
830
  ]);
816
831
  this.SUBRULE1(this.assignment);
817
832
  });
@@ -1709,6 +1724,9 @@ var OddoParser = class extends _chevrotain.CstParser {
1709
1724
  { ALT: () => this.CONSUME(AndColonEqual) },
1710
1725
  { ALT: () => this.CONSUME(OrColonEqual) },
1711
1726
  { ALT: () => this.CONSUME(CaretColonEqual) },
1727
+ { ALT: () => this.CONSUME(AndAndColonEqual) },
1728
+ { ALT: () => this.CONSUME(OrOrColonEqual) },
1729
+ { ALT: () => this.CONSUME(QuestionQuestionColonEqual) },
1712
1730
  { ALT: () => this.CONSUME(EqualEqual) },
1713
1731
  { ALT: () => this.CONSUME(BangEqual) },
1714
1732
  { ALT: () => this.CONSUME(LessThanEqual) },
@@ -2372,10 +2390,10 @@ function convertObjectDestructuringList(cst) {
2372
2390
  return properties;
2373
2391
  }
2374
2392
  function convertAssignment(cst) {
2375
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B;
2393
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H;
2376
2394
  const destructuringPattern = getFirstChild(cst, "destructuringPattern");
2377
2395
  if (destructuringPattern) {
2378
- const opToken2 = ((_a = cst.children.Equal) == null ? void 0 : _a[0]) || ((_b = cst.children.ColonEqual) == null ? void 0 : _b[0]) || ((_c = cst.children.PlusColonEqual) == null ? void 0 : _c[0]) || ((_d = cst.children.MinusColonEqual) == null ? void 0 : _d[0]) || ((_e = cst.children.StarColonEqual) == null ? void 0 : _e[0]) || ((_f = cst.children.SlashColonEqual) == null ? void 0 : _f[0]) || ((_g = cst.children.PercentColonEqual) == null ? void 0 : _g[0]) || ((_h = cst.children.StarStarColonEqual) == null ? void 0 : _h[0]) || ((_i = cst.children.LeftShiftColonEqual) == null ? void 0 : _i[0]) || ((_j = cst.children.RightShiftColonEqual) == null ? void 0 : _j[0]) || ((_k = cst.children.UnsignedRightShiftColonEqual) == null ? void 0 : _k[0]) || ((_l = cst.children.AndColonEqual) == null ? void 0 : _l[0]) || ((_m = cst.children.CaretColonEqual) == null ? void 0 : _m[0]) || ((_n = cst.children.OrColonEqual) == null ? void 0 : _n[0]);
2396
+ const opToken2 = ((_a = cst.children.Equal) == null ? void 0 : _a[0]) || ((_b = cst.children.ColonEqual) == null ? void 0 : _b[0]) || ((_c = cst.children.PlusColonEqual) == null ? void 0 : _c[0]) || ((_d = cst.children.MinusColonEqual) == null ? void 0 : _d[0]) || ((_e = cst.children.StarColonEqual) == null ? void 0 : _e[0]) || ((_f = cst.children.SlashColonEqual) == null ? void 0 : _f[0]) || ((_g = cst.children.PercentColonEqual) == null ? void 0 : _g[0]) || ((_h = cst.children.StarStarColonEqual) == null ? void 0 : _h[0]) || ((_i = cst.children.LeftShiftColonEqual) == null ? void 0 : _i[0]) || ((_j = cst.children.RightShiftColonEqual) == null ? void 0 : _j[0]) || ((_k = cst.children.UnsignedRightShiftColonEqual) == null ? void 0 : _k[0]) || ((_l = cst.children.AndColonEqual) == null ? void 0 : _l[0]) || ((_m = cst.children.CaretColonEqual) == null ? void 0 : _m[0]) || ((_n = cst.children.OrColonEqual) == null ? void 0 : _n[0]) || ((_o = cst.children.AndAndColonEqual) == null ? void 0 : _o[0]) || ((_p = cst.children.OrOrColonEqual) == null ? void 0 : _p[0]) || ((_q = cst.children.QuestionQuestionColonEqual) == null ? void 0 : _q[0]);
2379
2397
  if (opToken2) {
2380
2398
  const left2 = convertDestructuringPattern(destructuringPattern);
2381
2399
  const right = convertExpression(getFirstChild(cst, "assignment"));
@@ -2397,7 +2415,7 @@ function convertAssignment(cst) {
2397
2415
  return convertDestructuringPattern(destructuringPattern);
2398
2416
  }
2399
2417
  const left = convertExpression(getFirstChild(cst, "conditional"));
2400
- const opToken = ((_o = cst.children.Equal) == null ? void 0 : _o[0]) || ((_p = cst.children.ColonEqual) == null ? void 0 : _p[0]) || ((_q = cst.children.PlusColonEqual) == null ? void 0 : _q[0]) || ((_r = cst.children.MinusColonEqual) == null ? void 0 : _r[0]) || ((_s = cst.children.StarColonEqual) == null ? void 0 : _s[0]) || ((_t = cst.children.SlashColonEqual) == null ? void 0 : _t[0]) || ((_u = cst.children.PercentColonEqual) == null ? void 0 : _u[0]) || ((_v = cst.children.StarStarColonEqual) == null ? void 0 : _v[0]) || ((_w = cst.children.LeftShiftColonEqual) == null ? void 0 : _w[0]) || ((_x = cst.children.RightShiftColonEqual) == null ? void 0 : _x[0]) || ((_y = cst.children.UnsignedRightShiftColonEqual) == null ? void 0 : _y[0]) || ((_z = cst.children.AndColonEqual) == null ? void 0 : _z[0]) || ((_A = cst.children.CaretColonEqual) == null ? void 0 : _A[0]) || ((_B = cst.children.OrColonEqual) == null ? void 0 : _B[0]);
2418
+ const opToken = ((_r = cst.children.Equal) == null ? void 0 : _r[0]) || ((_s = cst.children.ColonEqual) == null ? void 0 : _s[0]) || ((_t = cst.children.PlusColonEqual) == null ? void 0 : _t[0]) || ((_u = cst.children.MinusColonEqual) == null ? void 0 : _u[0]) || ((_v = cst.children.StarColonEqual) == null ? void 0 : _v[0]) || ((_w = cst.children.SlashColonEqual) == null ? void 0 : _w[0]) || ((_x = cst.children.PercentColonEqual) == null ? void 0 : _x[0]) || ((_y = cst.children.StarStarColonEqual) == null ? void 0 : _y[0]) || ((_z = cst.children.LeftShiftColonEqual) == null ? void 0 : _z[0]) || ((_A = cst.children.RightShiftColonEqual) == null ? void 0 : _A[0]) || ((_B = cst.children.UnsignedRightShiftColonEqual) == null ? void 0 : _B[0]) || ((_C = cst.children.AndColonEqual) == null ? void 0 : _C[0]) || ((_D = cst.children.CaretColonEqual) == null ? void 0 : _D[0]) || ((_E = cst.children.OrColonEqual) == null ? void 0 : _E[0]) || ((_F = cst.children.AndAndColonEqual) == null ? void 0 : _F[0]) || ((_G = cst.children.OrOrColonEqual) == null ? void 0 : _G[0]) || ((_H = cst.children.QuestionQuestionColonEqual) == null ? void 0 : _H[0]);
2401
2419
  if (opToken) {
2402
2420
  const right = convertExpression(getFirstChild(cst, "assignment"));
2403
2421
  if (left && left.type === "arraySlice") {
@@ -3706,10 +3724,29 @@ var MODIFIER_TRANSFORMATIONS = {
3706
3724
  state: {
3707
3725
  needsImport: true,
3708
3726
  // @state x = 3 -> const [x, setX] = _state(3);
3709
- transform: (valueExpr, leftExpr) => {
3727
+ // @state x = reactiveVar -> const [x, setX] = _state(_lift(_reactiveVar => _reactiveVar(), [reactiveVar]));
3728
+ // Receives Oddo AST, extracts deps, lifts if needed
3729
+ transform: (oddoExpr, leftExpr) => {
3730
+ const allIdentifiers = collectOddoIdentifiersOnly(oddoExpr);
3731
+ const reactiveDeps = allIdentifiers.filter((id) => isReactive(id));
3732
+ const convertedExpr = convertExpression2(oddoExpr);
3733
+ let stateArg;
3734
+ if (reactiveDeps.length > 0) {
3735
+ usedModifiers.add("lift");
3736
+ const prefixedParams = reactiveDeps.map((id) => t.identifier("_" + id));
3737
+ const deps = reactiveDeps.map((id) => t.identifier(id));
3738
+ const arrowFunc = t.arrowFunctionExpression(prefixedParams, convertedExpr);
3739
+ wrapDependenciesWithCalls(arrowFunc, reactiveDeps, "_");
3740
+ stateArg = t.callExpression(
3741
+ t.identifier(modifierAliases["lift"]),
3742
+ [arrowFunc, t.arrayExpression(deps)]
3743
+ );
3744
+ } else {
3745
+ stateArg = convertedExpr;
3746
+ }
3710
3747
  const stateCall = t.callExpression(
3711
3748
  t.identifier(modifierAliases["state"]),
3712
- [valueExpr]
3749
+ [stateArg]
3713
3750
  );
3714
3751
  if (leftExpr && t.isIdentifier(leftExpr)) {
3715
3752
  const getterName = leftExpr.name;
@@ -3725,6 +3762,19 @@ var MODIFIER_TRANSFORMATIONS = {
3725
3762
  stateCall
3726
3763
  )
3727
3764
  ]);
3765
+ } else if (leftExpr && t.isArrayPattern(leftExpr) && leftExpr.elements.length === 2) {
3766
+ const getterName = leftExpr.elements[0].name;
3767
+ const setterName = leftExpr.elements[1].name;
3768
+ stateSetterMap.set(getterName, setterName);
3769
+ return t.variableDeclaration("const", [
3770
+ t.variableDeclarator(
3771
+ t.arrayPattern([
3772
+ t.identifier(getterName),
3773
+ t.identifier(setterName)
3774
+ ]),
3775
+ stateCall
3776
+ )
3777
+ ]);
3728
3778
  }
3729
3779
  return t.expressionStatement(stateCall);
3730
3780
  }
@@ -3762,78 +3812,187 @@ var MODIFIER_TRANSFORMATIONS = {
3762
3812
  // @mutate x = (arg1, arg2) => { x1 := value1; x2 := value2 }
3763
3813
  // -> const x = mutate((finalizer, x1, x2, ...outerDeps, arg1, arg2) => { ... }, finalizerFn, stateContainers, outerDeps)
3764
3814
  transform: (oddoExpr, leftExpr) => {
3765
- var _a, _b, _c, _d;
3815
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
3766
3816
  if (oddoExpr.type !== "arrowFunction") {
3767
3817
  throw new Error("@mutate modifier must be a function");
3768
3818
  }
3769
3819
  const funcParams = (oddoExpr.parameters || []).map((p) => p.name);
3770
- const assignments = [];
3771
- const bodyStatements = ((_a = oddoExpr.body) == null ? void 0 : _a.body) || [];
3772
- for (const stmt of bodyStatements) {
3773
- if (stmt.type === "expressionStatement" && ((_b = stmt.expression) == null ? void 0 : _b.type) === "assignment" && ((_c = stmt.expression) == null ? void 0 : _c.operator) === ":=") {
3774
- const leftName = (_d = stmt.expression.left) == null ? void 0 : _d.name;
3775
- if (!leftName) {
3776
- throw new Error("@mutate: := assignment must have an identifier on the left side");
3820
+ const mutateScope = oddoExpr._scope;
3821
+ const stateAssignmentsMap = /* @__PURE__ */ new Map();
3822
+ const processedStatements = [];
3823
+ const oddoBodyStatements = ((_a = oddoExpr.body) == null ? void 0 : _a.body) || [];
3824
+ let hasMutation = false;
3825
+ for (const stmt of oddoBodyStatements) {
3826
+ if (stmt.type === "expressionStatement") {
3827
+ if (((_b = stmt.expression) == null ? void 0 : _b.type) === "assignment") {
3828
+ const leftName = (_c = stmt.expression.left) == null ? void 0 : _c.name;
3829
+ if (!leftName && ((_d = stmt.expression.left) == null ? void 0 : _d.type) === "memberAccess") {
3830
+ hasMutation = true;
3831
+ let rightOddo2 = stmt.expression.right;
3832
+ const op2 = stmt.expression.operator;
3833
+ if (op2 !== ":=") {
3834
+ const baseOp = op2.slice(0, -2);
3835
+ let exprType;
3836
+ if (baseOp === "??") {
3837
+ exprType = "nullishCoalescing";
3838
+ } else if (baseOp === "&&" || baseOp === "||") {
3839
+ exprType = "logical";
3840
+ } else {
3841
+ exprType = "binary";
3842
+ }
3843
+ rightOddo2 = {
3844
+ type: exprType,
3845
+ operator: baseOp,
3846
+ left: stmt.expression.left,
3847
+ right: stmt.expression.right
3848
+ };
3849
+ }
3850
+ processedStatements.push({
3851
+ kind: "member",
3852
+ leftOddo: stmt.expression.left,
3853
+ rightOddo: rightOddo2
3854
+ });
3855
+ continue;
3856
+ }
3857
+ if (!leftName) {
3858
+ throw new Error("@mutate: unsupported left-hand side in assignment");
3859
+ }
3860
+ let rightOddo = stmt.expression.right;
3861
+ const op = stmt.expression.operator;
3862
+ if (op !== ":=") {
3863
+ const baseOp = op.slice(0, -2);
3864
+ let exprType;
3865
+ if (baseOp === "??") {
3866
+ exprType = "nullishCoalescing";
3867
+ } else if (baseOp === "&&" || baseOp === "||") {
3868
+ exprType = "logical";
3869
+ } else {
3870
+ exprType = "binary";
3871
+ }
3872
+ rightOddo = {
3873
+ type: exprType,
3874
+ operator: baseOp,
3875
+ left: stmt.expression.left,
3876
+ right: stmt.expression.right
3877
+ };
3878
+ }
3879
+ if (stateSetterMap.has(leftName)) {
3880
+ hasMutation = true;
3881
+ stateAssignmentsMap.set(leftName, {
3882
+ kind: "state",
3883
+ setter: stateSetterMap.get(leftName)
3884
+ });
3885
+ processedStatements.push({
3886
+ kind: "state",
3887
+ name: leftName,
3888
+ rightOddo
3889
+ });
3890
+ } else if (mutableVariables.has(leftName)) {
3891
+ hasMutation = true;
3892
+ processedStatements.push({
3893
+ kind: "mutable",
3894
+ name: leftName,
3895
+ rightOddo
3896
+ });
3897
+ } else {
3898
+ processedStatements.push({
3899
+ kind: "regular",
3900
+ stmtOddo: stmt
3901
+ });
3902
+ }
3903
+ continue;
3777
3904
  }
3778
- if (stateSetterMap.has(leftName)) {
3779
- assignments.push({
3780
- name: leftName,
3781
- kind: "state",
3782
- setter: stateSetterMap.get(leftName),
3783
- rightOddo: stmt.expression.right
3784
- });
3785
- } else if (mutableVariables.has(leftName)) {
3786
- assignments.push({
3787
- name: leftName,
3788
- kind: "mutable",
3789
- rightOddo: stmt.expression.right
3790
- });
3791
- } else {
3792
- throw new Error(`@mutate: Cannot mutate '${leftName}': not a @state or @mutable variable in current scope`);
3905
+ if (((_e = stmt.expression) == null ? void 0 : _e.type) === "arraySliceAssignment") {
3906
+ const arrayName = (_g = (_f = stmt.expression.slice) == null ? void 0 : _f.object) == null ? void 0 : _g.name;
3907
+ if (!arrayName) {
3908
+ throw new Error("@mutate: array slice assignment must have an identifier as the array");
3909
+ }
3910
+ if (stateSetterMap.has(arrayName)) {
3911
+ hasMutation = true;
3912
+ if (!stateAssignmentsMap.has(arrayName)) {
3913
+ stateAssignmentsMap.set(arrayName, {
3914
+ kind: "state-slice",
3915
+ setter: stateSetterMap.get(arrayName)
3916
+ });
3917
+ }
3918
+ processedStatements.push({
3919
+ kind: "state-slice",
3920
+ name: arrayName,
3921
+ sliceOddo: stmt.expression.slice,
3922
+ rightOddo: stmt.expression.value
3923
+ });
3924
+ } else if (mutableVariables.has(arrayName)) {
3925
+ hasMutation = true;
3926
+ processedStatements.push({
3927
+ kind: "mutable-slice",
3928
+ name: arrayName,
3929
+ sliceOddo: stmt.expression.slice,
3930
+ rightOddo: stmt.expression.value
3931
+ });
3932
+ } else {
3933
+ throw new Error(`@mutate: Cannot mutate '${arrayName}': not a @state or @mutable variable in current scope`);
3934
+ }
3935
+ continue;
3793
3936
  }
3794
3937
  }
3938
+ processedStatements.push({
3939
+ kind: "regular",
3940
+ stmtOddo: stmt
3941
+ });
3795
3942
  }
3796
- if (assignments.length === 0) {
3797
- throw new Error("@mutate function must contain at least one := assignment");
3943
+ if (!hasMutation) {
3944
+ throw new Error("@mutate function must contain at least one mutation");
3798
3945
  }
3799
- const stateAssignments = assignments.filter((a) => a.kind === "state");
3800
- const mutableAssignments = assignments.filter((a) => a.kind === "mutable");
3801
- const stateContainerNames = stateAssignments.map((a) => a.name);
3802
- const allAssignmentNames = assignments.map((a) => a.name);
3803
- const outerDeps = /* @__PURE__ */ new Set();
3804
- for (const assignment of assignments) {
3805
- collectOddoIdentifiers(assignment.rightOddo).forEach((id) => {
3806
- if (!funcParams.includes(id) && !allAssignmentNames.includes(id)) {
3807
- outerDeps.add(id);
3946
+ const uniqueStateNames = Array.from(stateAssignmentsMap.keys());
3947
+ const savedScopeMutate = currentScope;
3948
+ currentScope = mutateScope;
3949
+ const outerReactiveDeps = /* @__PURE__ */ new Set();
3950
+ for (const processed of processedStatements) {
3951
+ const nodesToScan = [];
3952
+ if (processed.rightOddo) nodesToScan.push(processed.rightOddo);
3953
+ if ((_h = processed.sliceOddo) == null ? void 0 : _h.start) nodesToScan.push(processed.sliceOddo.start);
3954
+ if ((_i = processed.sliceOddo) == null ? void 0 : _i.end) nodesToScan.push(processed.sliceOddo.end);
3955
+ if (processed.stmtOddo) nodesToScan.push(processed.stmtOddo);
3956
+ for (const node of nodesToScan) {
3957
+ const ids = collectOddoIdentifiersOnly(node);
3958
+ for (const id of ids) {
3959
+ if (isReactive(id) && !uniqueStateNames.includes(id)) {
3960
+ outerReactiveDeps.add(id);
3961
+ }
3808
3962
  }
3809
- });
3963
+ }
3810
3964
  }
3811
- const outerDepsArray = Array.from(outerDeps);
3965
+ const outerDepsArray = Array.from(outerReactiveDeps);
3812
3966
  const mutateParams = [
3813
3967
  t.identifier("finalizer"),
3814
- ...stateContainerNames.map((n) => t.identifier(n)),
3968
+ ...uniqueStateNames.map((n) => t.identifier(n)),
3815
3969
  ...outerDepsArray.map((n) => t.identifier(n)),
3816
3970
  ...funcParams.map((n) => t.identifier(n))
3817
3971
  ];
3818
3972
  const mutateBodyStmts = [];
3819
- if (stateAssignments.length > 0) {
3973
+ const hasStateAssignments = Array.from(stateAssignmentsMap.values()).some((v) => v.kind === "state");
3974
+ if (hasStateAssignments) {
3820
3975
  usedModifiers.add("stateProxy");
3821
3976
  }
3822
3977
  const callableIds = /* @__PURE__ */ new Set([
3823
- ...stateContainerNames,
3824
- ...outerDepsArray.filter((id) => !mutableVariables.has(id))
3978
+ ...uniqueStateNames,
3979
+ ...outerDepsArray
3825
3980
  ]);
3826
- const savedScopeMutate = currentScope;
3827
- currentScope = Object.create(currentScope);
3981
+ currentScope = Object.create(mutateScope);
3828
3982
  currentScope[reactiveScope] = false;
3829
- for (const assignment of assignments) {
3830
- const rightBabel = convertExpression2(assignment.rightOddo);
3831
- const tempFile = t.file(t.program([t.expressionStatement(rightBabel)]));
3983
+ for (const id of callableIds) {
3984
+ currentScope[id] = { type: "param", reactive: false };
3985
+ }
3986
+ const wrapCallableIds = (babelExpr, skipNode = null) => {
3987
+ const tempFile = t.file(t.program([t.expressionStatement(babelExpr)]));
3832
3988
  const toReplace = [];
3833
3989
  const shorthandToExpand = [];
3834
3990
  traverse(tempFile, {
3835
3991
  noScope: true,
3836
3992
  Identifier(path) {
3993
+ if (skipNode && path.node === skipNode) {
3994
+ return;
3995
+ }
3837
3996
  const parent = path.parent;
3838
3997
  const isMemberProp = (t.isMemberExpression(parent) || t.isOptionalMemberExpression(parent)) && parent.property === path.node && !parent.computed;
3839
3998
  const isObjectKey = t.isObjectProperty(parent) && parent.key === path.node && !parent.shorthand;
@@ -3852,13 +4011,17 @@ var MODIFIER_TRANSFORMATIONS = {
3852
4011
  prop.value = t.callExpression(t.identifier(name), []);
3853
4012
  });
3854
4013
  toReplace.forEach((p) => p.replaceWith(t.callExpression(t.identifier(p.node.name), [])));
3855
- const wrappedRightExpr = tempFile.program.body[0].expression;
3856
- if (assignment.kind === "state") {
4014
+ return tempFile.program.body[0].expression;
4015
+ };
4016
+ for (const processed of processedStatements) {
4017
+ if (processed.kind === "state") {
4018
+ const rightBabel = convertExpression2(processed.rightOddo);
4019
+ const wrappedRightExpr = wrapCallableIds(rightBabel);
3857
4020
  mutateBodyStmts.push(
3858
4021
  t.expressionStatement(
3859
4022
  t.assignmentExpression(
3860
4023
  "=",
3861
- t.identifier(assignment.name),
4024
+ t.identifier(processed.name),
3862
4025
  t.callExpression(
3863
4026
  t.identifier(modifierAliases["stateProxy"]),
3864
4027
  [wrappedRightExpr]
@@ -3866,25 +4029,59 @@ var MODIFIER_TRANSFORMATIONS = {
3866
4029
  )
3867
4030
  )
3868
4031
  );
3869
- } else {
4032
+ } else if (processed.kind === "mutable") {
4033
+ const rightBabel = convertExpression2(processed.rightOddo);
4034
+ const wrappedRightExpr = wrapCallableIds(rightBabel);
3870
4035
  mutateBodyStmts.push(
3871
4036
  t.expressionStatement(
3872
4037
  t.assignmentExpression(
3873
4038
  "=",
3874
- t.identifier(assignment.name),
4039
+ t.identifier(processed.name),
3875
4040
  wrappedRightExpr
3876
4041
  )
3877
4042
  )
3878
4043
  );
4044
+ } else if (processed.kind === "state-slice" || processed.kind === "mutable-slice") {
4045
+ const sliceAssignmentOddo = {
4046
+ type: "arraySliceAssignment",
4047
+ slice: processed.sliceOddo,
4048
+ value: processed.rightOddo
4049
+ };
4050
+ const sliceExpr = convertExpression2(sliceAssignmentOddo);
4051
+ const firstArg = sliceExpr.arguments[0];
4052
+ const wrappedSliceExpr = wrapCallableIds(sliceExpr, firstArg);
4053
+ mutateBodyStmts.push(t.expressionStatement(wrappedSliceExpr));
4054
+ } else if (processed.kind === "member") {
4055
+ const leftBabel = convertExpression2(processed.leftOddo);
4056
+ const rightBabel = convertExpression2(processed.rightOddo);
4057
+ const wrappedRightExpr = wrapCallableIds(rightBabel);
4058
+ mutateBodyStmts.push(
4059
+ t.expressionStatement(
4060
+ t.assignmentExpression("=", leftBabel, wrappedRightExpr)
4061
+ )
4062
+ );
4063
+ } else if (processed.kind === "regular") {
4064
+ const convertedStmt = convertStatement2(processed.stmtOddo);
4065
+ if (t.isVariableDeclaration(convertedStmt)) {
4066
+ for (const decl of convertedStmt.declarations) {
4067
+ if (decl.init) {
4068
+ decl.init = wrapCallableIds(decl.init);
4069
+ }
4070
+ }
4071
+ } else if (t.isExpressionStatement(convertedStmt)) {
4072
+ convertedStmt.expression = wrapCallableIds(convertedStmt.expression);
4073
+ }
4074
+ mutateBodyStmts.push(convertedStmt);
3879
4075
  }
3880
4076
  }
3881
4077
  currentScope = savedScopeMutate;
3882
- if (stateContainerNames.length > 0) {
4078
+ const stateNamesForFinalizer = Array.from(stateAssignmentsMap.entries()).filter(([_, info]) => info.kind === "state").map(([name, _]) => name);
4079
+ if (stateNamesForFinalizer.length > 0) {
3883
4080
  mutateBodyStmts.push(
3884
4081
  t.expressionStatement(
3885
4082
  t.callExpression(
3886
4083
  t.identifier("finalizer"),
3887
- stateContainerNames.map((n) => t.callExpression(t.identifier(n), []))
4084
+ stateNamesForFinalizer.map((n) => t.callExpression(t.identifier(n), []))
3888
4085
  )
3889
4086
  )
3890
4087
  );
@@ -3893,14 +4090,15 @@ var MODIFIER_TRANSFORMATIONS = {
3893
4090
  mutateParams,
3894
4091
  t.blockStatement(mutateBodyStmts)
3895
4092
  );
3896
- const finalizerParams = stateContainerNames.map((n) => t.identifier(n));
3897
- const finalizerCalls = stateAssignments.map(
3898
- (a) => t.callExpression(t.identifier(a.setter), [t.identifier(a.name)])
3899
- );
4093
+ const finalizerParams = stateNamesForFinalizer.map((n) => t.identifier(n));
4094
+ const finalizerCalls = stateNamesForFinalizer.map((name) => {
4095
+ const info = stateAssignmentsMap.get(name);
4096
+ return t.callExpression(t.identifier(info.setter), [t.identifier(name)]);
4097
+ });
3900
4098
  const finalizerBody = finalizerCalls.length === 0 ? t.identifier("undefined") : finalizerCalls.length === 1 ? finalizerCalls[0] : t.sequenceExpression(finalizerCalls);
3901
4099
  const finalizerFunc = t.arrowFunctionExpression(finalizerParams, finalizerBody);
3902
4100
  const stateContainersArray = t.arrayExpression(
3903
- stateContainerNames.map((n) => t.identifier(n))
4101
+ uniqueStateNames.map((n) => t.identifier(n))
3904
4102
  );
3905
4103
  const outerDepsArrayExpr = t.arrayExpression(
3906
4104
  outerDepsArray.map((n) => t.identifier(n))
@@ -4082,7 +4280,7 @@ function generateUniqueId(baseName) {
4082
4280
  return candidate;
4083
4281
  }
4084
4282
  function collectOddoIdentifiers(node, names = /* @__PURE__ */ new Set()) {
4085
- var _a, _b, _c, _d;
4283
+ var _a, _b, _c, _d, _e, _f;
4086
4284
  if (!node || typeof node !== "object") return names;
4087
4285
  if (node.type === "program") {
4088
4286
  moduleScope = /* @__PURE__ */ Object.create(null);
@@ -4093,15 +4291,21 @@ function collectOddoIdentifiers(node, names = /* @__PURE__ */ new Set()) {
4093
4291
  names.add(node.name);
4094
4292
  }
4095
4293
  if (node.type === "expressionStatement") {
4096
- const varName = (_b = (_a = node.expression) == null ? void 0 : _a.left) == null ? void 0 : _b.name;
4097
- if (varName) {
4294
+ const left = (_a = node.expression) == null ? void 0 : _a.left;
4295
+ const varName = left == null ? void 0 : left.name;
4296
+ if (node.modifier === "state" && (left == null ? void 0 : left.type) === "arrayPattern" && ((_b = left.elements) == null ? void 0 : _b.length) === 2) {
4297
+ const getterName = (_c = left.elements[0]) == null ? void 0 : _c.name;
4298
+ const setterName = (_d = left.elements[1]) == null ? void 0 : _d.name;
4299
+ if (getterName) declareVariable(getterName, "state");
4300
+ if (setterName) declareVariable(setterName, "immutable");
4301
+ } else if (varName) {
4098
4302
  if (node.modifier === "state") {
4099
4303
  declareVariable(varName, "state");
4100
4304
  } else if (node.modifier === "computed") {
4101
4305
  declareVariable(varName, "computed");
4102
4306
  } else if (node.modifier === "mutable") {
4103
4307
  declareVariable(varName, "mutable");
4104
- } else if (!node.modifier && ((_c = node.expression) == null ? void 0 : _c.type) === "variableDeclaration") {
4308
+ } else if (!node.modifier && ((_e = node.expression) == null ? void 0 : _e.type) === "variableDeclaration") {
4105
4309
  declareVariable(varName, "immutable");
4106
4310
  }
4107
4311
  }
@@ -4133,7 +4337,7 @@ function collectOddoIdentifiers(node, names = /* @__PURE__ */ new Set()) {
4133
4337
  for (const name of boundNames) {
4134
4338
  declareVariable(name, "param");
4135
4339
  }
4136
- } else if (param.type === "restElement" && ((_d = param.argument) == null ? void 0 : _d.name)) {
4340
+ } else if (param.type === "restElement" && ((_f = param.argument) == null ? void 0 : _f.name)) {
4137
4341
  declareVariable(param.argument.name, "param");
4138
4342
  }
4139
4343
  }
@@ -4176,7 +4380,7 @@ function compileToJS(ast, config = {}) {
4176
4380
  moduleScope = null;
4177
4381
  currentScope = null;
4178
4382
  usedNames = collectOddoIdentifiers(ast);
4179
- const allImports = ["state", "computed", "mutate", "effect", "stateProxy", "lift", "liftFn", "e", "c", "x", "f"];
4383
+ const allImports = ["state", "computed", "mutate", "effect", "stateProxy", "arraySplice", "lift", "liftFn", "e", "c", "x", "f"];
4180
4384
  for (const name of allImports) {
4181
4385
  modifierAliases[name] = `__ODDO_IMPORT_${name}__`;
4182
4386
  }
@@ -4276,13 +4480,13 @@ function convertExpressionStatement2(stmt) {
4276
4480
  let leftExpr = null;
4277
4481
  if (stmt.expression.type === "variableDeclaration" || stmt.expression.type === "assignment") {
4278
4482
  leftExpr = convertExpression2(stmt.expression.left);
4279
- if (stmt.modifier === "mutate" || stmt.modifier === "effect" || stmt.modifier === "computed" || stmt.modifier === "mutable" || stmt.modifier === "component" || stmt.modifier === "hook") {
4483
+ if (stmt.modifier === "mutate" || stmt.modifier === "effect" || stmt.modifier === "computed" || stmt.modifier === "mutable" || stmt.modifier === "component" || stmt.modifier === "hook" || stmt.modifier === "state") {
4280
4484
  valueExpr = stmt.expression.right;
4281
4485
  } else {
4282
4486
  valueExpr = convertExpression2(stmt.expression.right);
4283
4487
  }
4284
4488
  } else {
4285
- if (stmt.modifier === "mutate" || stmt.modifier === "effect" || stmt.modifier === "computed" || stmt.modifier === "mutable" || stmt.modifier === "component" || stmt.modifier === "hook") {
4489
+ if (stmt.modifier === "mutate" || stmt.modifier === "effect" || stmt.modifier === "computed" || stmt.modifier === "mutable" || stmt.modifier === "component" || stmt.modifier === "hook" || stmt.modifier === "state") {
4286
4490
  valueExpr = stmt.expression;
4287
4491
  } else {
4288
4492
  valueExpr = convertExpression2(stmt.expression);
@@ -4303,13 +4507,13 @@ function convertExpressionStatement2(stmt) {
4303
4507
  let leftExpr = null;
4304
4508
  if (blockStmt.expression.type === "variableDeclaration" || blockStmt.expression.type === "assignment") {
4305
4509
  leftExpr = convertExpression2(blockStmt.expression.left);
4306
- if (stmt.modifier === "mutate" || stmt.modifier === "effect" || stmt.modifier === "computed" || stmt.modifier === "mutable" || stmt.modifier === "component" || stmt.modifier === "hook") {
4510
+ if (stmt.modifier === "mutate" || stmt.modifier === "effect" || stmt.modifier === "computed" || stmt.modifier === "mutable" || stmt.modifier === "component" || stmt.modifier === "hook" || stmt.modifier === "state") {
4307
4511
  valueExpr = blockStmt.expression.right;
4308
4512
  } else {
4309
4513
  valueExpr = convertExpression2(blockStmt.expression.right);
4310
4514
  }
4311
4515
  } else {
4312
- if (stmt.modifier === "mutate" || stmt.modifier === "effect" || stmt.modifier === "computed" || stmt.modifier === "mutable" || stmt.modifier === "component" || stmt.modifier === "hook") {
4516
+ if (stmt.modifier === "mutate" || stmt.modifier === "effect" || stmt.modifier === "computed" || stmt.modifier === "mutable" || stmt.modifier === "component" || stmt.modifier === "hook" || stmt.modifier === "state") {
4313
4517
  valueExpr = blockStmt.expression;
4314
4518
  } else {
4315
4519
  valueExpr = convertExpression2(blockStmt.expression);
@@ -4353,7 +4557,31 @@ function convertExpressionStatement2(stmt) {
4353
4557
  }
4354
4558
  let expression = null;
4355
4559
  if (stmt.expression) {
4356
- expression = convertExpression2(stmt.expression);
4560
+ const isPlainExpr = stmt.expression.type !== "variableDeclaration" && stmt.expression.type !== "assignment" && stmt.expression.type !== "arraySliceAssignment";
4561
+ if (isPlainExpr) {
4562
+ const allIdentifiers = collectOddoIdentifiersOnly(stmt.expression);
4563
+ const reactiveDeps = allIdentifiers.filter((id) => isReactive(id));
4564
+ if (reactiveDeps.length > 0) {
4565
+ const savedScope = currentScope;
4566
+ currentScope = Object.create(currentScope);
4567
+ currentScope[reactiveScope] = false;
4568
+ const convertedExpr = convertExpression2(stmt.expression);
4569
+ currentScope = savedScope;
4570
+ usedModifiers.add("lift");
4571
+ const prefixedParams = reactiveDeps.map((id) => t.identifier("_" + id));
4572
+ const deps = reactiveDeps.map((id) => t.identifier(id));
4573
+ const arrowFunc = t.arrowFunctionExpression(prefixedParams, convertedExpr);
4574
+ wrapDependenciesWithCalls(arrowFunc, reactiveDeps, "_");
4575
+ expression = t.callExpression(
4576
+ t.identifier(modifierAliases["lift"]),
4577
+ [arrowFunc, t.arrayExpression(deps)]
4578
+ );
4579
+ } else {
4580
+ expression = convertExpression2(stmt.expression);
4581
+ }
4582
+ } else {
4583
+ expression = convertExpression2(stmt.expression);
4584
+ }
4357
4585
  }
4358
4586
  if (stmt.block) {
4359
4587
  const block = convertBlockStatement(stmt.block);
@@ -4777,7 +5005,10 @@ function convertAssignmentExpression(expr) {
4777
5005
  ">>>:=": ">>>=",
4778
5006
  "&:=": "&=",
4779
5007
  "^:=": "^=",
4780
- "|:=": "|="
5008
+ "|:=": "|=",
5009
+ "&&:=": "&&=",
5010
+ "||:=": "||=",
5011
+ "??:=": "??="
4781
5012
  };
4782
5013
  const operator = operatorMap[expr.operator] || expr.operator;
4783
5014
  return t.assignmentExpression(operator, left, right);
@@ -4821,16 +5052,11 @@ function convertArraySliceAssignment(expr) {
4821
5052
  t.memberExpression(spliceArgs, t.identifier("concat"), false),
4822
5053
  [value]
4823
5054
  );
4824
- const spliceMethod = t.memberExpression(
4825
- t.memberExpression(
4826
- t.memberExpression(t.identifier("Array"), t.identifier("prototype"), false),
4827
- t.identifier("splice"),
4828
- false
4829
- ),
4830
- t.identifier("apply"),
4831
- false
5055
+ usedModifiers.add("arraySplice");
5056
+ return t.callExpression(
5057
+ t.identifier(modifierAliases["arraySplice"]),
5058
+ [object, concatCall]
4832
5059
  );
4833
- return t.callExpression(spliceMethod, [object, concatCall]);
4834
5060
  }
4835
5061
  function convertArrayPattern(expr) {
4836
5062
  const elements = expr.elements.map((el) => {
@@ -5091,6 +5317,9 @@ var tokenClassMap = {
5091
5317
  "AndColonEqual": "operator",
5092
5318
  "OrColonEqual": "operator",
5093
5319
  "CaretColonEqual": "operator",
5320
+ "AndAndColonEqual": "operator",
5321
+ "OrOrColonEqual": "operator",
5322
+ "QuestionQuestionColonEqual": "operator",
5094
5323
  // JSX
5095
5324
  "JSXCloseTagStart": "tag",
5096
5325
  "JSXSelfClosing": "tag",