goldstein 2.1.0 → 2.4.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,22 @@
1
+ 2022.06.30, v2.4.0
2
+
3
+ feature:
4
+ - goldstein: freeze: simplify: MemberExpression -> Identifier
5
+ - goldstein: add freeze keyword (#6)
6
+
7
+
8
+ 2022.06.27, v2.3.0
9
+
10
+ feature:
11
+ - goldstein: add curry
12
+
13
+
14
+ 2022.06.27, v2.2.0
15
+
16
+ feature:
17
+ - goldstein: add support of throw expressions
18
+
19
+
1
20
  2022.06.25, v2.1.0
2
21
 
3
22
  feature:
package/README.md CHANGED
@@ -166,6 +166,24 @@ try hello();
166
166
 
167
167
  > ☝️ *Warning: this feature can be helpful but also dangerous especially if you're debugging your application. In fact, this is made to be used as an optional function call (ex. should load content, but not necessary and knowing this feature is optional), if you call a function in this way while debugging, no error will be printed and the application will continue run as nothing happened.*
168
168
 
169
+ ### `freeze`
170
+
171
+ You can use `freeze` instead of `Object.freeze()` like that:
172
+
173
+ ```gs
174
+ freeze {
175
+ 'example': true
176
+ }
177
+ ```
178
+
179
+ Is the same as:
180
+
181
+ ```js
182
+ Object.freeze({
183
+ example: true,
184
+ });
185
+ ```
186
+
169
187
  ### `if`
170
188
 
171
189
  You can omit parens. But you must use braces in this case.
@@ -176,6 +194,27 @@ if a > 3 {
176
194
  }
177
195
  ```
178
196
 
197
+ ### `throw expression`
198
+
199
+ You can use [throw as expression](https://github.com/tc39/proposal-throw-expressions), just like that:
200
+
201
+ ```js
202
+ const a = () => throw 'hello';
203
+ ```
204
+
205
+ ### `Curry`
206
+
207
+ Similar to [partial application](https://github.com/tc39/proposal-partial-application):
208
+
209
+ ```gs
210
+ const sum = (a, b) => a + b;
211
+ const inc = sum~(1);
212
+
213
+ inc(5);
214
+ // returns
215
+ 6
216
+ ```
217
+
179
218
  ## How to contribute?
180
219
 
181
220
  Clone the registry, create a new keyword with a prefix `keyword-`, then create directory `fixture` and put there two files with extensions `.js` and `.gs`. Half way done 🥳!
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "goldstein",
3
- "version": "2.1.0",
3
+ "version": "2.4.0",
4
4
  "type": "module",
5
5
  "commitType": "colon",
6
6
  "author": "coderaiser <mnemonic.enemy@gmail.com> (https://github.com/coderaiser)",
@@ -6,7 +6,10 @@ import keywordFn from '../keyword-fn/index.js';
6
6
  import keywordGuard from '../keyword-guard/index.js';
7
7
  import keywordTry from '../keyword-try/index.js';
8
8
  import keywordShould from '../keyword-should/index.js';
9
+ import keywordThrow from '../keyword-throw/index.js';
9
10
  import stringInterpolation from '../string-interpolation/index.js';
11
+ import keywordCurry from '../keyword-curry/index.js';
12
+ import keywordFreeze from '../keyword-freeze/index.js';
10
13
 
11
14
  export const compile = (source) => {
12
15
  const {parse} = extendParser([
@@ -14,6 +17,9 @@ export const compile = (source) => {
14
17
  keywordGuard,
15
18
  keywordTry,
16
19
  keywordShould,
20
+ keywordThrow,
21
+ keywordCurry,
22
+ keywordFreeze,
17
23
  stringInterpolation,
18
24
  ]);
19
25
 
@@ -23,6 +29,7 @@ export const compile = (source) => {
23
29
  const {code} = putout(jsCode, {
24
30
  plugins: [
25
31
  'try-catch',
32
+ 'declare-undefined-variables',
26
33
  ],
27
34
  });
28
35
 
@@ -0,0 +1,32 @@
1
+ import {types} from 'putout';
2
+ import {tokTypes as tt} from '../operator/index.js';
3
+
4
+ const {Identifier} = types;
5
+
6
+ export default function keywordCurry(Parser) {
7
+ return class extends Parser {
8
+ parseSubscript(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained, forInit) {
9
+ const isTRA = this.eat(tt.prefix);
10
+
11
+ if (isTRA)
12
+ return this.parseCurry(base, startPos, startLoc);
13
+
14
+ return super.parseSubscript(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained, forInit);
15
+ }
16
+ parseCurry(base, startPos, startLoc) {
17
+ const node = this.startNodeAt(startPos, startLoc);
18
+ const isParenL = this.eat(tt.parenL);
19
+
20
+ if (!isParenL)
21
+ this.raise(this.start, `After '~' should always go '(' when you use curry`);
22
+
23
+ node.callee = Identifier('currify');
24
+ node.arguments = [base, this.parseExpression()];
25
+
26
+ this.expect(tt.parenR);
27
+
28
+ return this.finishNode(node, 'CallExpression');
29
+ }
30
+ };
31
+ }
32
+
@@ -0,0 +1,59 @@
1
+ import {types} from 'putout';
2
+ import {
3
+ addKeyword,
4
+ TokenType,
5
+ } from '../operator/index.js';
6
+
7
+ const {
8
+ isObjectExpression,
9
+ isArrayExpression,
10
+ } = types;
11
+
12
+ export default function keywordFreeze(Parser) {
13
+ const {keywordTypes} = Parser.acorn;
14
+ keywordTypes.freeze = new TokenType('freeze', {
15
+ keyword: 'freeze',
16
+ });
17
+
18
+ return class extends Parser {
19
+ parse() {
20
+ this.keywords = addKeyword('freeze', this.keywords);
21
+ return super.parse();
22
+ }
23
+ parseStatement(context, topLevel, exports) {
24
+ if (this.type === keywordTypes.freeze) {
25
+ return this.parseFreeze();
26
+ }
27
+
28
+ return super.parseStatement(context, topLevel, exports);
29
+ }
30
+
31
+ parseFreeze() {
32
+ this.next();
33
+
34
+ const node = super.startNode();
35
+ const expression = this.parseExpression();
36
+
37
+ if (isObjectExpression(expression) || isArrayExpression(expression))
38
+ node.expression = {
39
+ type: 'ExpressionStatement',
40
+ expression: {
41
+ type: 'CallExpression',
42
+ callee: {
43
+ type: 'Identifier',
44
+ name: 'freeze',
45
+ },
46
+ arguments: [
47
+ expression,
48
+ ],
49
+ },
50
+ };
51
+
52
+ else
53
+ this.raise(this.start, `After 'freeze' only objects and arrays can come`);
54
+
55
+ return super.finishNode(node, 'ExpressionStatement');
56
+ }
57
+ };
58
+ }
59
+
@@ -0,0 +1,30 @@
1
+ const {assign} = Object;
2
+
3
+ export default function keywordThrow(Parser) {
4
+ const {keywordTypes} = Parser.acorn;
5
+
6
+ return class extends Parser {
7
+ parseExprAtom(refDestructuringErrors, forInit) {
8
+ if (this.type === keywordTypes.throw) {
9
+ return this.parseThrowExpression();
10
+ }
11
+
12
+ return super.parseExprAtom(refDestructuringErrors, forInit);
13
+ }
14
+
15
+ parseThrowExpression() {
16
+ this.next();
17
+
18
+ const node = super.startNode();
19
+ const expression = this.parseExpression();
20
+
21
+ assign(node, {
22
+ operator: 'throw',
23
+ argument: expression,
24
+ });
25
+
26
+ return super.finishNode(node, 'UnaryExpression');
27
+ }
28
+ };
29
+ }
30
+
@@ -1,9 +1,13 @@
1
1
  import {template} from 'putout';
2
+ const isString = (a) => typeof a === 'string';
2
3
  const {assign} = Object;
3
4
 
4
5
  export default function stringInterpolation(Parser) {
5
6
  return class extends Parser {
6
7
  parseLiteral(value) {
8
+ if (!isString(value))
9
+ return super.parseLiteral(value);
10
+
7
11
  const chars = value.split('');
8
12
 
9
13
  let literalOpened = false;