goldstein 4.7.0 → 4.9.0

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/ChangeLog CHANGED
@@ -1,3 +1,13 @@
1
+ 2023.10.19, v4.9.0
2
+
3
+ feature:
4
+ - 2346464 goldstein: convert: add-array
5
+
6
+ 2023.10.19, v4.8.0
7
+
8
+ feature:
9
+ - 924f182 goldstein: add-array: add
10
+
1
11
  2023.10.04, v4.7.0
2
12
 
3
13
  feature:
package/README.md CHANGED
@@ -165,7 +165,7 @@ parse(`
165
165
 
166
166
  You can parse to **ESTree**:
167
167
 
168
- ```
168
+ ```js
169
169
  const options = {
170
170
  type: 'estree',
171
171
  };
@@ -184,8 +184,11 @@ parse(`
184
184
 
185
185
  You can make any modifications to **Goldstein AST** and then `print` back to **Goldstein**:
186
186
 
187
- ```
188
- import {parse, print} from 'goldstein';
187
+ ```js
188
+ import {
189
+ parse,
190
+ print,
191
+ } from 'goldstein';
189
192
 
190
193
  const ast = parse(`const t = try f('hello')`);
191
194
  const source = print(ast);
@@ -195,13 +198,13 @@ const source = print(ast);
195
198
 
196
199
  You can even convert **JavaScript** to **Goldstein** with:
197
200
 
198
- ```
201
+ ```js
199
202
  import {convert} from 'goldstein';
200
203
 
201
- const ast = convert(`const t = tryCatch(f, 'hello');`;
204
+ const ast = convert(`const t = tryCatch(f, 'hello')`);
202
205
 
203
206
  // returns
204
- `const t = try f('hello')`)
207
+ `const t = try f('hello')`;
205
208
  ```
206
209
 
207
210
  ## Keywords
@@ -227,6 +230,23 @@ function hello() {
227
230
  }
228
231
  ```
229
232
 
233
+ ### `append array`
234
+
235
+ Append new elements to an array just like in Swift:
236
+
237
+ ```js
238
+ let a = [1];
239
+
240
+ a += [2, 3];
241
+ ```
242
+
243
+ Is the same as:
244
+
245
+ ```js
246
+ const a = [1];
247
+ a.push(...[2, 3]);
248
+ ```
249
+
230
250
  ### `guard`
231
251
 
232
252
  Applies not to `IfCondition`:
package/build/parser.cjs CHANGED
@@ -5410,6 +5410,13 @@ function addKeyword(keyword, keywords3) {
5410
5410
  const str = keywords3.toString().replace(")$", `|${keyword})$`).slice(1, -1);
5411
5411
  return RegExp(str);
5412
5412
  }
5413
+ var DestructuringErrors3 = class {
5414
+ shorthandAssign = -1;
5415
+ trailingComma = -1;
5416
+ parenthesizedAssign = -1;
5417
+ parenthesizedBind = -1;
5418
+ doubleProto = -1;
5419
+ };
5413
5420
 
5414
5421
  // packages/keyword-fn/index.js
5415
5422
  function fn(Parser3) {
@@ -5902,6 +5909,97 @@ function fn3(Parser3) {
5902
5909
  };
5903
5910
  }
5904
5911
 
5912
+ // packages/keyword-add-array/index.js
5913
+ var import_putout7 = require("putout");
5914
+ var { assign: assign3 } = Object;
5915
+ var {
5916
+ identifier,
5917
+ isArrayExpression: isArrayExpression2,
5918
+ memberExpression,
5919
+ spreadElement
5920
+ } = import_putout7.types;
5921
+ function keywordAddArray(Parser3) {
5922
+ return class extends Parser3 {
5923
+ parseMaybeAssign(forInit, refDestructuringErrors, afterLeftParse) {
5924
+ if (this.isContextual("yield")) {
5925
+ if (this.inGenerator) {
5926
+ return this.parseYield(forInit);
5927
+ }
5928
+ this.exprAllowed = false;
5929
+ }
5930
+ let ownDestructuringErrors = false;
5931
+ let oldParenAssign = -1;
5932
+ let oldTrailingComma = -1;
5933
+ let oldDoubleProto = -1;
5934
+ if (refDestructuringErrors) {
5935
+ oldParenAssign = refDestructuringErrors.parenthesizedAssign;
5936
+ oldTrailingComma = refDestructuringErrors.trailingComma;
5937
+ oldDoubleProto = refDestructuringErrors.doubleProto;
5938
+ refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1;
5939
+ } else {
5940
+ refDestructuringErrors = new DestructuringErrors3();
5941
+ ownDestructuringErrors = true;
5942
+ }
5943
+ const startPos = this.start;
5944
+ const { startLoc } = this;
5945
+ if (this.type === types$1.parenL || this.type === types$1.name) {
5946
+ this.potentialArrowAt = this.start;
5947
+ this.potentialArrowInForAwait = forInit === "await";
5948
+ }
5949
+ let left = this.parseMaybeConditional(forInit, refDestructuringErrors);
5950
+ if (afterLeftParse) {
5951
+ left = afterLeftParse.call(this, left, startPos, startLoc);
5952
+ }
5953
+ if (this.type.isAssign) {
5954
+ const node = this.startNodeAt(startPos, startLoc);
5955
+ node.operator = this.value;
5956
+ if (this.type === types$1.eq) {
5957
+ left = this.toAssignable(left, false, refDestructuringErrors);
5958
+ }
5959
+ if (!ownDestructuringErrors) {
5960
+ refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = refDestructuringErrors.doubleProto = -1;
5961
+ }
5962
+ if (refDestructuringErrors.shorthandAssign >= left.start) {
5963
+ refDestructuringErrors.shorthandAssign = -1;
5964
+ }
5965
+ if (this.type === types$1.eq) {
5966
+ this.checkLValPattern(left);
5967
+ } else {
5968
+ this.checkLValSimple(left);
5969
+ }
5970
+ node.left = left;
5971
+ this.next();
5972
+ node.right = this.parseMaybeAssign(forInit);
5973
+ if (oldDoubleProto > -1) {
5974
+ refDestructuringErrors.doubleProto = oldDoubleProto;
5975
+ }
5976
+ if (node.operator === "+=" && isArrayExpression2(node.right))
5977
+ return createAppendNode(this, node);
5978
+ return this.finishNode(node, "AssignmentExpression");
5979
+ }
5980
+ if (ownDestructuringErrors) {
5981
+ this.checkExpressionErrors(refDestructuringErrors, true);
5982
+ }
5983
+ if (oldParenAssign > -1) {
5984
+ refDestructuringErrors.parenthesizedAssign = oldParenAssign;
5985
+ }
5986
+ if (oldTrailingComma > -1) {
5987
+ refDestructuringErrors.trailingComma = oldTrailingComma;
5988
+ }
5989
+ return left;
5990
+ }
5991
+ };
5992
+ }
5993
+ function createAppendNode(context, node) {
5994
+ const { left, right } = node;
5995
+ assign3(node, {
5996
+ a: "x",
5997
+ callee: memberExpression(left, identifier("push")),
5998
+ arguments: [spreadElement(right)]
5999
+ });
6000
+ return context.finishNode(node, "CallExpression");
6001
+ }
6002
+
5905
6003
  // packages/goldstein/parser.js
5906
6004
  var defaultKeywords = {
5907
6005
  keywordFn: fn,
@@ -5914,6 +6012,7 @@ var defaultKeywords = {
5914
6012
  keywordIf: fn2,
5915
6013
  keywordImport,
5916
6014
  keywordArrow: fn3,
6015
+ keywordAddArray,
5917
6016
  stringInterpolation
5918
6017
  };
5919
6018
  var keywords2 = defaultKeywords;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "goldstein",
3
- "version": "4.7.0",
3
+ "version": "4.9.0",
4
4
  "type": "module",
5
5
  "author": "coderaiser <mnemonic.enemy@gmail.com> (https://github.com/coderaiser)",
6
6
  "description": "JavaScript with no limits",
@@ -0,0 +1,4 @@
1
+ export const report = () => `Use 'add-array'`;
2
+ export const replace = () => ({
3
+ '__a.push(...__array)': '__a += __array',
4
+ });
@@ -3,6 +3,7 @@ import {transform} from 'putout';
3
3
  import {print} from '../printer/index.js';
4
4
  import * as removeImportTry from './remove-import-try/index.js';
5
5
  import * as applyTry from './apply-try/index.js';
6
+ import * as addArray from './add-array/index.js';
6
7
  import {
7
8
  fixEmpty,
8
9
  parse,
@@ -13,6 +14,7 @@ export const convert = (source) => {
13
14
 
14
15
  transform(ast, source, {
15
16
  plugins: [
17
+ ['add-array', addArray],
16
18
  ['apply-try', applyTry],
17
19
  ['remove-import-try', removeImportTry],
18
20
  ],
@@ -11,6 +11,7 @@ import keywordFreeze from '../keyword-freeze/index.js';
11
11
  import keywordIf from '../keyword-if/index.js';
12
12
  import keywordImport from '../keyword-import/index.js';
13
13
  import keywordArrow from '../keyword-arrow/index.js';
14
+ import keywordAddArray from '../keyword-add-array/index.js';
14
15
 
15
16
  const defaultKeywords = {
16
17
  keywordFn,
@@ -23,6 +24,7 @@ const defaultKeywords = {
23
24
  keywordIf,
24
25
  keywordImport,
25
26
  keywordArrow,
27
+ keywordAddArray,
26
28
  stringInterpolation,
27
29
  };
28
30
 
@@ -0,0 +1,121 @@
1
+ import {types} from 'putout';
2
+ import {tokTypes as tt} from 'acorn';
3
+ import {DestructuringErrors} from '../operator/index.js';
4
+
5
+ const {assign} = Object;
6
+
7
+ const {
8
+ identifier,
9
+ isArrayExpression,
10
+ memberExpression,
11
+ spreadElement,
12
+ } = types;
13
+
14
+ export default function keywordAddArray(Parser) {
15
+ return class extends Parser {
16
+ parseMaybeAssign(forInit, refDestructuringErrors, afterLeftParse) {
17
+ if (this.isContextual('yield')) {
18
+ if (this.inGenerator) {
19
+ return this.parseYield(forInit);
20
+ }
21
+
22
+ // The tokenizer will assume an expression is allowed after
23
+ // `yield`, but this isn't that kind of yield
24
+ this.exprAllowed = false;
25
+ }
26
+
27
+ let ownDestructuringErrors = false;
28
+ let oldParenAssign = -1;
29
+ let oldTrailingComma = -1;
30
+ let oldDoubleProto = -1;
31
+
32
+ if (refDestructuringErrors) {
33
+ oldParenAssign = refDestructuringErrors.parenthesizedAssign;
34
+ oldTrailingComma = refDestructuringErrors.trailingComma;
35
+ oldDoubleProto = refDestructuringErrors.doubleProto;
36
+ refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1;
37
+ } else {
38
+ refDestructuringErrors = new DestructuringErrors();
39
+ ownDestructuringErrors = true;
40
+ }
41
+
42
+ const startPos = this.start;
43
+ const {startLoc} = this;
44
+
45
+ if (this.type === tt.parenL || this.type === tt.name) {
46
+ this.potentialArrowAt = this.start;
47
+ this.potentialArrowInForAwait = forInit === 'await';
48
+ }
49
+
50
+ let left = this.parseMaybeConditional(forInit, refDestructuringErrors);
51
+
52
+ if (afterLeftParse) {
53
+ left = afterLeftParse.call(this, left, startPos, startLoc);
54
+ }
55
+
56
+ if (this.type.isAssign) {
57
+ const node = this.startNodeAt(startPos, startLoc);
58
+
59
+ node.operator = this.value;
60
+
61
+ if (this.type === tt.eq) {
62
+ left = this.toAssignable(left, false, refDestructuringErrors);
63
+ }
64
+
65
+ if (!ownDestructuringErrors) {
66
+ refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = refDestructuringErrors.doubleProto = -1;
67
+ }
68
+
69
+ if (refDestructuringErrors.shorthandAssign >= left.start) {
70
+ refDestructuringErrors.shorthandAssign = -1;
71
+ }
72
+
73
+ // reset because shorthand default was used correctly
74
+ if (this.type === tt.eq) {
75
+ this.checkLValPattern(left);
76
+ } else {
77
+ this.checkLValSimple(left);
78
+ }
79
+
80
+ node.left = left;
81
+ this.next();
82
+ node.right = this.parseMaybeAssign(forInit);
83
+
84
+ if (oldDoubleProto > -1) {
85
+ refDestructuringErrors.doubleProto = oldDoubleProto;
86
+ }
87
+
88
+ if (node.operator === '+=' && isArrayExpression(node.right))
89
+ return createAppendNode(this, node);
90
+
91
+ return this.finishNode(node, 'AssignmentExpression');
92
+ }
93
+
94
+ if (ownDestructuringErrors) {
95
+ this.checkExpressionErrors(refDestructuringErrors, true);
96
+ }
97
+
98
+ if (oldParenAssign > -1) {
99
+ refDestructuringErrors.parenthesizedAssign = oldParenAssign;
100
+ }
101
+
102
+ if (oldTrailingComma > -1) {
103
+ refDestructuringErrors.trailingComma = oldTrailingComma;
104
+ }
105
+
106
+ return left;
107
+ }
108
+ };
109
+ }
110
+
111
+ function createAppendNode(context, node) {
112
+ const {left, right} = node;
113
+
114
+ assign(node, {
115
+ a: 'x',
116
+ callee: memberExpression(left, identifier('push')),
117
+ arguments: [spreadElement(right)],
118
+ });
119
+
120
+ return context.finishNode(node, 'CallExpression');
121
+ }
@@ -9,3 +9,10 @@ export function addKeyword(keyword, keywords) {
9
9
  return RegExp(str);
10
10
  }
11
11
 
12
+ export class DestructuringErrors {
13
+ shorthandAssign = -1;
14
+ trailingComma = -1;
15
+ parenthesizedAssign = -1;
16
+ parenthesizedBind = -1;
17
+ doubleProto = -1;
18
+ }