goldstein 1.6.0 → 2.0.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,9 @@
1
+ 2022.06.22, v2.0.0
2
+
3
+ feature:
4
+ - goldstein: keyword: safe -> try
5
+
6
+
1
7
  2022.06.22, v1.6.0
2
8
 
3
9
  feature:
package/README.md CHANGED
@@ -77,7 +77,7 @@ Here is the list.
77
77
 
78
78
  You can use `fn` to declare a `function`:
79
79
 
80
- ```gs
80
+ ```rust
81
81
  fn hello() {
82
82
  return 'world';
83
83
  }
@@ -95,7 +95,7 @@ function hello() {
95
95
 
96
96
  Applies not to `IfCondition`:
97
97
 
98
- ```gs
98
+ ```swift
99
99
  fn hello() {
100
100
  guard text !== "world" else {
101
101
  return ""
@@ -117,12 +117,14 @@ function hello() {
117
117
  }
118
118
  ```
119
119
 
120
- ### `safe`
120
+ ### `try`
121
+
122
+ `try` can be used as an expression.
121
123
 
122
124
  Applies [`tryCatch`](https://github.com/coderaiser/try-catch):
123
125
 
124
126
  ```gs
125
- const [error, result] = safe hello(1, 2, 3);
127
+ const [error, result] = try hello(1, 2, 3);
126
128
  ```
127
129
 
128
130
  Is the same as:
@@ -135,7 +137,7 @@ const [error, result] = tryCatch(1, 2, 3);
135
137
  and
136
138
 
137
139
  ```gs
138
- const [error, result] = safe await hello(1, 2, 3);
140
+ const [error, result] = try await hello(1, 2, 3);
139
141
  ```
140
142
 
141
143
  Is the same as:
@@ -149,7 +151,7 @@ const [error, result] = await tryToCatch(1, 2, 3);
149
151
 
150
152
  You can omit parens. But you must use braces in this case.
151
153
 
152
- ```gs
154
+ ```rust
153
155
  if a > 3 {
154
156
  hello();
155
157
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "goldstein",
3
- "version": "1.6.0",
3
+ "version": "2.0.0",
4
4
  "type": "module",
5
5
  "commitType": "colon",
6
6
  "author": "coderaiser <mnemonic.enemy@gmail.com> (https://github.com/coderaiser)",
@@ -4,13 +4,13 @@ import putout, {
4
4
  import {extendParser} from '../parser/index.js';
5
5
  import keywordFn from '../keyword-fn/index.js';
6
6
  import keywordGuard from '../keyword-guard/index.js';
7
- import keywordSafe from '../keyword-safe/index.js';
7
+ import keywordTry from '../keyword-try/index.js';
8
8
 
9
9
  export const compile = (source) => {
10
10
  const {parse} = extendParser([
11
11
  keywordFn,
12
12
  keywordGuard,
13
- keywordSafe,
13
+ keywordTry,
14
14
  ]);
15
15
 
16
16
  const ast = parse(source);
@@ -1,7 +1,9 @@
1
1
  import {types} from 'putout';
2
2
  import {
3
- addKeyword,
4
- TokenType,
3
+ BIND_LEXICAL,
4
+ BIND_SIMPLE_CATCH,
5
+ SCOPE_SIMPLE_CATCH,
6
+ tokTypes as tt,
5
7
  } from '../operator/index.js';
6
8
 
7
9
  const {
@@ -9,39 +11,24 @@ const {
9
11
  isAwaitExpression,
10
12
  } = types;
11
13
 
12
- // why not 'try'?
13
- // because acorn internals should be copied, and added tests.
14
- // there is no such thing as this.previous(), only this.next() 🤷‍
15
-
16
14
  export default function newSpeak(Parser) {
17
15
  const {keywordTypes} = Parser.acorn;
18
- keywordTypes.safe = new TokenType('safe', {
19
- keyword: 'safe',
20
- });
21
16
 
22
17
  return class extends Parser {
23
- parse() {
24
- this.keywords = addKeyword('safe', this.keywords);
25
-
26
- return super.parse();
27
- }
28
- parseStatement(context, topLevel, exports) {
29
- if (this.type === keywordTypes.safe)
30
- return this.parseSafe();
31
-
32
- return super.parseStatement(context, topLevel, exports);
33
- }
34
18
  parseExprAtom(refDestructuringErrors, forInit) {
35
- if (this.type === keywordTypes.safe)
36
- return this.parseSafe();
19
+ if (this.type === keywordTypes.try)
20
+ return this.parseTryStatement();
37
21
 
38
22
  return super.parseExprAtom(refDestructuringErrors, forInit);
39
23
  }
40
24
 
41
- parseSafe() {
25
+ parseTryStatement() {
42
26
  this.next();
43
-
44
27
  const node = super.startNode();
28
+
29
+ if (this.type === tt.braceL)
30
+ return this.parseUglyTry(node);
31
+
45
32
  const expression = this.parseExpression();
46
33
 
47
34
  if (isCallExpression(expression))
@@ -74,10 +61,42 @@ export default function newSpeak(Parser) {
74
61
  };
75
62
 
76
63
  else
77
- this.raise(this.start, `After 'safe' only 'await' and 'function call' can come`);
64
+ this.raise(this.start, `After 'try' only '{', 'await' and 'function call' can come`);
78
65
 
79
66
  return super.finishNode(node, 'ExpressionStatement');
80
67
  }
68
+ parseUglyTry(node) {
69
+ node.block = this.parseBlock();
70
+ node.handler = null;
71
+
72
+ if (this.type === tt._catch) {
73
+ const clause = this.startNode();
74
+ this.next();
75
+
76
+ if (this.eat(tt.parenL)) {
77
+ clause.param = this.parseBindingAtom();
78
+ const simple = clause.param.type === 'Identifier';
79
+
80
+ this.enterScope(simple ? SCOPE_SIMPLE_CATCH : 0);
81
+ this.checkLValPattern(clause.param, simple ? BIND_SIMPLE_CATCH : BIND_LEXICAL);
82
+ this.expect(tt.parenR);
83
+ } else {
84
+ clause.param = null;
85
+ this.enterScope(0);
86
+ }
87
+
88
+ clause.body = this.parseBlock(false);
89
+ this.exitScope();
90
+ node.handler = this.finishNode(clause, 'CatchClause');
91
+ }
92
+
93
+ node.finalizer = this.eat(tt._finally) ? this.parseBlock() : null;
94
+
95
+ if (!node.handler && !node.finalizer)
96
+ this.raise(node.start, 'Missing catch or finally clause');
97
+
98
+ return this.finishNode(node, 'TryStatement');
99
+ }
81
100
  };
82
101
  }
83
102
 
@@ -1,4 +1,5 @@
1
1
  export * from 'acorn';
2
+ export * from './scopeflags.js';
2
3
 
3
4
  export function addKeyword(keyword, keywords) {
4
5
  const str = keywords
@@ -0,0 +1,21 @@
1
+ // Each scope gets a bitset that may contain these flags
2
+ export const
3
+ SCOPE_TOP = 1,
4
+ SCOPE_FUNCTION = 2,
5
+ SCOPE_ASYNC = 4,
6
+ SCOPE_GENERATOR = 8,
7
+ SCOPE_ARROW = 16,
8
+ SCOPE_SIMPLE_CATCH = 32,
9
+ SCOPE_SUPER = 64,
10
+ SCOPE_DIRECT_SUPER = 128,
11
+ SCOPE_CLASS_STATIC_BLOCK = 256,
12
+ SCOPE_VAR = SCOPE_TOP | SCOPE_FUNCTION | SCOPE_CLASS_STATIC_BLOCK;
13
+
14
+ // Used in checkLVal* and declareName to determine the type of a binding
15
+ export const
16
+ BIND_NONE = 0, // Not a binding
17
+ BIND_VAR = 1, // Var-style binding
18
+ BIND_LEXICAL = 2, // Let- or const-style binding
19
+ BIND_FUNCTION = 3, // Function declaration
20
+ BIND_SIMPLE_CATCH = 4, // Simple (identifier pattern) catch binding
21
+ BIND_OUTSIDE = 5; // Special case for function names as bound inside the function