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
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
|
-
```
|
|
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
|
-
```
|
|
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
|
-
### `
|
|
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] =
|
|
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] =
|
|
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
|
-
```
|
|
154
|
+
```rust
|
|
153
155
|
if a > 3 {
|
|
154
156
|
hello();
|
|
155
157
|
}
|
package/package.json
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
4
|
-
|
|
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.
|
|
36
|
-
return this.
|
|
19
|
+
if (this.type === keywordTypes.try)
|
|
20
|
+
return this.parseTryStatement();
|
|
37
21
|
|
|
38
22
|
return super.parseExprAtom(refDestructuringErrors, forInit);
|
|
39
23
|
}
|
|
40
24
|
|
|
41
|
-
|
|
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 '
|
|
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
|
|
|
@@ -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
|