functionalscript 0.1.607 → 0.1.609
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.md +10 -0
- package/Cargo.lock +4 -0
- package/Cargo.toml +4 -2
- package/README.md +1 -1
- package/com/rust/nanocom/src/cobject.rs +1 -1
- package/com/test/rust/src/lib.rs +4 -4
- package/dev/module.mjs +10 -33
- package/dev/test/module.f.mjs +1 -1
- package/djs/parser/module.f.d.mts +51 -31
- package/djs/parser/module.f.mjs +275 -122
- package/djs/parser/test.f.d.mts +4 -0
- package/djs/parser/test.f.mjs +179 -63
- package/djs/tokenizer/module.f.d.mts +1 -1
- package/djs/tokenizer/module.f.mjs +3 -1
- package/djs/tokenizer/test.f.mjs +1 -1
- package/doc/LANGUAGE.md +17 -16
- package/doc/README.md +14 -50
- package/fsc/README.md +0 -3
- package/fsm/README.md +1 -1
- package/html/README.md +24 -0
- package/issues/01-test-debug.md +3 -0
- package/issues/{publish.md → 05-publish.md} +8 -8
- package/issues/17-djs-extension.md +6 -0
- package/issues/README.md +20 -13
- package/issues/lang/1000-json.md +38 -0
- package/issues/lang/2110-default-export.md +2 -2
- package/issues/lang/2310-undefined.md +1 -1
- package/issues/lang/2330-property-accessor.md +225 -0
- package/issues/lang/2360-built-in.md +54 -47
- package/issues/lang/3240-export.md +44 -0
- package/issues/lang/README.md +64 -22
- package/issues/test.f.d.mts +16 -0
- package/issues/test.f.mjs +57 -0
- package/js/tokenizer/module.f.d.mts +8 -2
- package/js/tokenizer/module.f.mjs +29 -3
- package/js/tokenizer/test.f.mjs +9 -6
- package/json/tokenizer/module.f.mjs +2 -1
- package/jsr.json +1 -1
- package/nanvm-lib/Cargo.toml +6 -0
- package/nanvm-lib/src/extension.rs +119 -0
- package/nanvm-lib/src/interface.rs +136 -0
- package/nanvm-lib/src/lib.rs +7 -0
- package/nanvm-lib/src/naive.rs +229 -0
- package/nanvm-lib/src/nanenum.rs +230 -0
- package/nanvm-lib/src/nullish.rs +7 -0
- package/nanvm-lib/src/sign.rs +5 -0
- package/nanvm-lib/src/simple.rs +32 -0
- package/nanvm-lib/tests/test.f.d.mts +36 -0
- package/nanvm-lib/tests/test.f.mjs +79 -0
- package/nanvm-lib/tests/test.rs +108 -0
- package/package.json +1 -2
- package/text/README.md +2 -2
- package/index.f.d.mts +0 -83
- package/index.f.mjs +0 -83
- package/issues/lang/2351-property-accessor.md +0 -44
- package/issues/lang/2352-property-call.md +0 -43
- package/issues/lang/2353-property-at.md +0 -19
- package/issues/test-debug.md +0 -12
- /package/issues/{esm.md → 02-esm.md} +0 -0
- /package/issues/{djs.md → 03-djs.md} +0 -0
- /package/issues/{fs-load.md → 11-fs-load.md} +0 -0
- /package/issues/lang/{2330-grouping.md → 2350-grouping.md} +0 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Non-default Export
|
|
2
|
+
|
|
3
|
+
In FunctionalScript we use `export default`:
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
export default 17
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
The main reason is that it's compatible with other module types, such as JSON and CommonJS.
|
|
10
|
+
|
|
11
|
+
ECMAScript supports `export` of other non-default objects. We wouldn't have much reasons to support but systems as JSR doesn't really like `default` exports.
|
|
12
|
+
|
|
13
|
+
To implement `export` we should change our definition of a module from `unknown` to
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
type Module = {
|
|
17
|
+
readonly [k in string]?: unknonwn
|
|
18
|
+
readonly default?: unknown
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Or, more strict version, which allows either `export` or `export default` but not both:
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
type Module = ExportMap | ExportDefault
|
|
26
|
+
type ExportMap = Omit<{
|
|
27
|
+
readonly[k in string]: unknown
|
|
28
|
+
}, 'default'>
|
|
29
|
+
type DefaultExport = {
|
|
30
|
+
readonly default: unknown
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
We don't need to change `import` for now if we implement `import * as X from ...`. For example
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
// types/list/module.d.mjs
|
|
38
|
+
export const map = ...
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
```js
|
|
42
|
+
import * as List from 'types/list/module.f.mjs'
|
|
43
|
+
const { map } = List
|
|
44
|
+
```
|
package/issues/lang/README.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# FunctionalScript Language
|
|
2
2
|
|
|
3
|
+
Two main FunctionsScript princples:
|
|
4
|
+
1. if FS code pass validation/compilation, then it doesn't have side-effects,
|
|
5
|
+
2. the code that passed validation/compilation should behave on FunctionalScript VM the same way as on any other modern JavaScript engine.
|
|
6
|
+
|
|
3
7
|
When we implement features of FunctionalScript, the first priority is a simplification of the VM.
|
|
4
8
|
|
|
5
9
|
File Types:
|
|
@@ -16,44 +20,67 @@ File Types:
|
|
|
16
20
|
|
|
17
21
|
- [ ] [JSON](./1000-json.md).
|
|
18
22
|
|
|
23
|
+
**VM**:
|
|
24
|
+
|
|
25
|
+
We are introducing new commands in the order that every new command depends only on previous commands.
|
|
26
|
+
|
|
27
|
+
|format|any |Tag| |
|
|
28
|
+
|------|--------------|---|----------|
|
|
29
|
+
|JSON |null | 00| |
|
|
30
|
+
| |number | 01|u64 |
|
|
31
|
+
| |false | 02| |
|
|
32
|
+
| |true | 03| |
|
|
33
|
+
| |string | 04|String |
|
|
34
|
+
| |array | 05|Array<Any>|
|
|
35
|
+
| |object | 06|Object |
|
|
36
|
+
|
|
19
37
|
## 2. DJS
|
|
20
38
|
|
|
21
39
|
The DJS form a graph of values. It can be serialized without additional run-time information.
|
|
22
40
|
|
|
23
41
|
File extensions: `.d.js` and `.d.mjs`.
|
|
24
42
|
|
|
43
|
+
|format|any |Tag| |Notes |
|
|
44
|
+
|------|------------------------|---|----------|------------------------------------------------|
|
|
45
|
+
|DJS |const_ref | 07|u32 |[const](./2120-const.md) |
|
|
46
|
+
| |bigint_plus | 08|Array<u64>|[bigint](./2320-bigint.md) |
|
|
47
|
+
| |bigint_minus | 09|Array<u64>|[bigint](./2320-bigint.md) |
|
|
48
|
+
| |undefined | 0A| |[undefined](./2310-undefined.md) |
|
|
49
|
+
| |own_property | 0B| |[property-accessor](./2330-property-accessor.md)|
|
|
50
|
+
| |instance_property | 0C| |[property-accessor](./2330-property-accessor.md)|
|
|
51
|
+
| |instance_method_call | 0D| |[property-accessor](./2330-property-accessor.md)|
|
|
52
|
+
| |at | 0E| |[property-accessor](./2330-property-accessor.md)|
|
|
53
|
+
| |operators | | |[operators](./2340-operators.md) |
|
|
54
|
+
|
|
25
55
|
### 2.1. Required
|
|
26
56
|
|
|
27
|
-
1. [ ] [default-export](./2110-default-export.md)
|
|
28
|
-
2. [ ] [const](./2120-const.md)
|
|
29
|
-
3. [ ] [default-import](./2130-default-import.md)
|
|
57
|
+
1. [ ] [default-export](./2110-default-export.md),
|
|
58
|
+
2. [ ] [const](./2120-const.md),
|
|
59
|
+
3. [ ] [default-import](./2130-default-import.md).
|
|
30
60
|
|
|
31
61
|
### 2.2. Priority 1
|
|
32
62
|
|
|
33
63
|
We need it to use JSDoc and TypeScript.
|
|
34
64
|
|
|
35
|
-
1. [ ] [block-comment](./2210-block-comment.md)
|
|
36
|
-
2. [ ] [namespace-import](./2220-namespace-import.md)
|
|
65
|
+
1. [ ] [block-comment](./2210-block-comment.md),
|
|
66
|
+
2. [ ] [namespace-import](./2220-namespace-import.md).
|
|
37
67
|
|
|
38
68
|
### 2.3. Priority 2
|
|
39
69
|
|
|
40
|
-
1. [ ] [undefined](./
|
|
41
|
-
2. [ ] [bigint](./
|
|
42
|
-
3. [ ] [
|
|
43
|
-
4. [ ] [operators](./
|
|
44
|
-
5. [ ]
|
|
45
|
-
|
|
46
|
-
2. [ ] [property-call](./2352-property-call.md)
|
|
47
|
-
3. [ ] [at](./2353-at.md)
|
|
48
|
-
6. [ ] [global](./2360-built-in.md)
|
|
70
|
+
1. [ ] [undefined](./2310-undefined.md),
|
|
71
|
+
2. [ ] [bigint](./2320-bigint.md),
|
|
72
|
+
3. [ ] [property-accessor](./2330-property-accessor.md),
|
|
73
|
+
4. [ ] [operators](./2340-operators.md),
|
|
74
|
+
5. [ ] [grouping](./2350-grouping.md),
|
|
75
|
+
6. [ ] [built-in](./2360-built-in.md).
|
|
49
76
|
|
|
50
77
|
### 2.4. Syntactic Sugar
|
|
51
78
|
|
|
52
|
-
1. [ ] [identifier-property](./2410-identifier-property.md)
|
|
53
|
-
2. [ ] [line-comment](./2420-line-comment.md)
|
|
54
|
-
3. [ ] [trailing-comma](./2430-trailing-comma.md)
|
|
55
|
-
4. [ ] [shorthand](./2440-shorthand.md)
|
|
56
|
-
5. [ ] [destructuring](./2450-destructuring.md)
|
|
79
|
+
1. [ ] [identifier-property](./2410-identifier-property.md),
|
|
80
|
+
2. [ ] [line-comment](./2420-line-comment.md),
|
|
81
|
+
3. [ ] [trailing-comma](./2430-trailing-comma.md),
|
|
82
|
+
4. [ ] [shorthand](./2440-shorthand.md),
|
|
83
|
+
5. [ ] [destructuring](./2450-destructuring.md).
|
|
57
84
|
|
|
58
85
|
## 3. FJS
|
|
59
86
|
|
|
@@ -61,6 +88,10 @@ The FJS can have functions. The format requires additional run-time information
|
|
|
61
88
|
|
|
62
89
|
File extensions: `.f.js` and `.f.mjs`.
|
|
63
90
|
|
|
91
|
+
|format|any |Tag| |Notes |
|
|
92
|
+
|------|--------|---|----|--------------------------------|
|
|
93
|
+
|FJS |function| |Func|[function](./3110-function.md) |
|
|
94
|
+
|
|
64
95
|
### 3.1. Required
|
|
65
96
|
|
|
66
97
|
1. [ ] [function](./3110-function.md)
|
|
@@ -69,12 +100,23 @@ File extensions: `.f.js` and `.f.mjs`.
|
|
|
69
100
|
|
|
70
101
|
### 3.2. Priority 1
|
|
71
102
|
|
|
72
|
-
1. [ ] `if
|
|
103
|
+
1. [ ] `if`. See https://developer.mozilla.org/en-US/docs/Glossary/Falsy
|
|
73
104
|
2. [ ] [let](./3220-let.md)
|
|
74
105
|
3. [ ] `while`
|
|
106
|
+
4. [ ] [export](./3240-export.md)
|
|
75
107
|
|
|
76
108
|
### 3.3. Syntactic Sugar
|
|
77
109
|
|
|
78
|
-
1. [ ] [expression](./
|
|
79
|
-
2. [ ] [one-parameter](./
|
|
110
|
+
1. [ ] [expression](./3210-expression.md)
|
|
111
|
+
2. [ ] [one-parameter](./3220-one-parameter.md)
|
|
80
112
|
3. [ ] [assignments](./3330-assignments.md)
|
|
113
|
+
|
|
114
|
+
## 4. ECMAScript Proposals
|
|
115
|
+
|
|
116
|
+
1. [ ] [Type Annotations](https://github.com/tc39/proposal-type-annotations), Stage 1:
|
|
117
|
+
- [Node.js](https://nodejs.org/en/learn/typescript/run-natively),
|
|
118
|
+
- `Deno` supports TypeScript,
|
|
119
|
+
- `Bun` supports TypeScript,
|
|
120
|
+
- most browsers don't support the feature.
|
|
121
|
+
2. [ ] [Pipe Operator `|>`](https://github.com/tc39/proposal-pipeline-operator), Stage 2.
|
|
122
|
+
3. [ ] [Records and Tuples](https://github.com/tc39/proposal-record-tuple), Stage 2.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
declare namespace _default {
|
|
2
|
+
namespace ownProperty {
|
|
3
|
+
function nullish(): void;
|
|
4
|
+
function bool(): void;
|
|
5
|
+
function array(): void;
|
|
6
|
+
namespace object {
|
|
7
|
+
export function _null(): void;
|
|
8
|
+
export { _null as null };
|
|
9
|
+
export function undefined(): void;
|
|
10
|
+
}
|
|
11
|
+
namespace string {
|
|
12
|
+
function number(): void;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export default _default;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/** @type {(a: unknown) => (i: any) =>unknown} */
|
|
2
|
+
const at = a => i => Object.getOwnPropertyDescriptor(a, i)?.value
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
ownProperty: {
|
|
6
|
+
nullish: () => {
|
|
7
|
+
/* // panic
|
|
8
|
+
const v = Object.getOwnPropertyDescriptor(null, 0)
|
|
9
|
+
if (v !== undefined) {
|
|
10
|
+
throw v
|
|
11
|
+
}
|
|
12
|
+
*/
|
|
13
|
+
/* // panic
|
|
14
|
+
const v = Object.getOwnPropertyDescriptor(undefined, 0)
|
|
15
|
+
if (v !== undefined) {
|
|
16
|
+
throw v
|
|
17
|
+
}
|
|
18
|
+
*/
|
|
19
|
+
},
|
|
20
|
+
bool: () => {
|
|
21
|
+
const v = at(true)('x')
|
|
22
|
+
if (v !== undefined) {
|
|
23
|
+
throw v
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
array: () => {
|
|
27
|
+
const a = ['42']
|
|
28
|
+
{
|
|
29
|
+
const v = at(a)('0')
|
|
30
|
+
if (v !== '42') { throw v }
|
|
31
|
+
}
|
|
32
|
+
{
|
|
33
|
+
const v = at(a)(0)
|
|
34
|
+
if (v !== '42') { throw v }
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
object: {
|
|
38
|
+
null: () => {
|
|
39
|
+
const o = { null: 'hello' }
|
|
40
|
+
const v = at(o)(null)
|
|
41
|
+
if (v !== 'hello') { throw v }
|
|
42
|
+
},
|
|
43
|
+
undefined: () => {
|
|
44
|
+
const o = { undefined: 'hello' }
|
|
45
|
+
const v = at(o)(undefined)
|
|
46
|
+
if (v !== 'hello') { throw v }
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
string: {
|
|
50
|
+
number: () => {
|
|
51
|
+
const o = 'hello'
|
|
52
|
+
const v = at(o)(1)
|
|
53
|
+
if (v !== 'e') { throw v }
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -23,6 +23,9 @@ export type ErrorToken = {
|
|
|
23
23
|
export type WhitespaceToken = {
|
|
24
24
|
readonly kind: "ws";
|
|
25
25
|
};
|
|
26
|
+
export type NewLineToken = {
|
|
27
|
+
readonly kind: "nl";
|
|
28
|
+
};
|
|
26
29
|
export type TrueToken = {
|
|
27
30
|
readonly kind: "true";
|
|
28
31
|
};
|
|
@@ -72,8 +75,8 @@ export type OperatorToken = {
|
|
|
72
75
|
} | {
|
|
73
76
|
readonly kind: "?" | "?." | "=>";
|
|
74
77
|
};
|
|
75
|
-
export type JsToken = KeywordToken | TrueToken | FalseToken | NullToken | WhitespaceToken | StringToken | NumberToken | ErrorToken | IdToken | BigIntToken | OperatorToken;
|
|
76
|
-
export type TokenizerState = InitialState | ParseIdState | ParseStringState | ParseEscapeCharState | ParseUnicodeCharState | ParseNumberState | InvalidNumberState | ParseOperatorState | ParseMinusState | ParseWhitespaceState | EofState;
|
|
78
|
+
export type JsToken = KeywordToken | TrueToken | FalseToken | NullToken | WhitespaceToken | NewLineToken | StringToken | NumberToken | ErrorToken | IdToken | BigIntToken | OperatorToken;
|
|
79
|
+
export type TokenizerState = InitialState | ParseIdState | ParseStringState | ParseEscapeCharState | ParseUnicodeCharState | ParseNumberState | InvalidNumberState | ParseOperatorState | ParseMinusState | ParseWhitespaceState | ParseNewLineState | EofState;
|
|
77
80
|
export type ErrorMessage = "\" are missing" | "unescaped character" | "invalid hex value" | "unexpected character" | "invalid number" | "invalid token" | "eof";
|
|
78
81
|
export type InitialState = {
|
|
79
82
|
readonly kind: "initial";
|
|
@@ -85,6 +88,9 @@ export type ParseIdState = {
|
|
|
85
88
|
export type ParseWhitespaceState = {
|
|
86
89
|
readonly kind: "ws";
|
|
87
90
|
};
|
|
91
|
+
export type ParseNewLineState = {
|
|
92
|
+
readonly kind: "nl";
|
|
93
|
+
};
|
|
88
94
|
export type ParseStringState = {
|
|
89
95
|
readonly kind: "string";
|
|
90
96
|
readonly value: string;
|
|
@@ -96,6 +96,8 @@ const {
|
|
|
96
96
|
|
|
97
97
|
/** @typedef {{readonly kind: 'ws'}} WhitespaceToken */
|
|
98
98
|
|
|
99
|
+
/** @typedef {{readonly kind: 'nl'}} NewLineToken */
|
|
100
|
+
|
|
99
101
|
/** @typedef {{readonly kind: 'true'}} TrueToken */
|
|
100
102
|
|
|
101
103
|
/** @typedef {{readonly kind: 'false'}} FalseToken */
|
|
@@ -143,6 +145,7 @@ const {
|
|
|
143
145
|
* FalseToken |
|
|
144
146
|
* NullToken |
|
|
145
147
|
* WhitespaceToken |
|
|
148
|
+
* NewLineToken |
|
|
146
149
|
* StringToken |
|
|
147
150
|
* NumberToken |
|
|
148
151
|
* ErrorToken |
|
|
@@ -154,15 +157,19 @@ const {
|
|
|
154
157
|
|
|
155
158
|
const rangeOneNine = range('19')
|
|
156
159
|
|
|
160
|
+
const rangeSetNewLine = [
|
|
161
|
+
one(lf),
|
|
162
|
+
one(cr)
|
|
163
|
+
]
|
|
164
|
+
|
|
157
165
|
const rangeSetWhiteSpace = [
|
|
158
166
|
one(ht),
|
|
159
|
-
one(lf),
|
|
160
|
-
one(cr),
|
|
161
167
|
one(space)
|
|
162
168
|
]
|
|
163
169
|
|
|
164
170
|
const rangeSetTerminalForNumber = [
|
|
165
171
|
...rangeSetWhiteSpace,
|
|
172
|
+
...rangeSetNewLine,
|
|
166
173
|
one(exclamationMark),
|
|
167
174
|
one(percentSign),
|
|
168
175
|
one(ampersand),
|
|
@@ -235,6 +242,7 @@ const rangeId = [digitRange, ...rangeIdStart]
|
|
|
235
242
|
* ParseOperatorState |
|
|
236
243
|
* ParseMinusState |
|
|
237
244
|
* ParseWhitespaceState |
|
|
245
|
+
* ParseNewLineState |
|
|
238
246
|
* EofState
|
|
239
247
|
* } TokenizerState
|
|
240
248
|
*/
|
|
@@ -257,6 +265,8 @@ const rangeId = [digitRange, ...rangeIdStart]
|
|
|
257
265
|
|
|
258
266
|
/** @typedef {{ readonly kind: 'ws'}} ParseWhitespaceState */
|
|
259
267
|
|
|
268
|
+
/** @typedef {{ readonly kind: 'nl'}} ParseNewLineState */
|
|
269
|
+
|
|
260
270
|
/** @typedef {{ readonly kind: 'string', readonly value: string}} ParseStringState */
|
|
261
271
|
|
|
262
272
|
/** @typedef {{ readonly kind: 'escapeChar', readonly value: string}} ParseEscapeCharState */
|
|
@@ -525,6 +535,7 @@ const initialStateOp = create(state => () => [[{ kind: 'error', message: 'unexpe
|
|
|
525
535
|
rangeFunc(rangeOneNine)(() => input => [empty, { kind: 'number', value: fromCharCode(input), b: startNumber(input), numberKind: 'int' }]),
|
|
526
536
|
rangeSetFunc(rangeIdStart)(() => input => [empty, { kind: 'id', value: fromCharCode(input) }]),
|
|
527
537
|
rangeSetFunc(rangeSetWhiteSpace)(state => () => [empty, { kind: 'ws' }]),
|
|
538
|
+
rangeSetFunc(rangeSetNewLine)(state => () => [empty, { kind: 'nl' }]),
|
|
528
539
|
rangeFunc(one(quotationMark))(() => () => [empty, { kind: 'string', value: '' }]),
|
|
529
540
|
rangeFunc(one(digit0))(() => input => [empty, { kind: 'number', value: fromCharCode(input), b: startNumber(input), numberKind: '0' }]),
|
|
530
541
|
rangeSetFunc(rangeOpStart)(() => input => [empty, { kind: 'op', value: fromCharCode(input) }])
|
|
@@ -739,7 +750,20 @@ const parseWhitespaceDefault = state => input => {
|
|
|
739
750
|
|
|
740
751
|
/** @type {(state: ParseWhitespaceState) => (input: number) => readonly[List.List<JsToken>, TokenizerState]} */
|
|
741
752
|
const parseWhitespaceStateOp = create(parseWhitespaceDefault)([
|
|
742
|
-
rangeSetFunc(rangeSetWhiteSpace)(state => () => [empty, state])
|
|
753
|
+
rangeSetFunc(rangeSetWhiteSpace)(state => () => [empty, state]),
|
|
754
|
+
rangeSetFunc(rangeSetNewLine)(state => () => [empty, { kind: 'nl' }])
|
|
755
|
+
])
|
|
756
|
+
|
|
757
|
+
/** @type {(state: ParseNewLineState) => (input: number) => readonly[List.List<JsToken>, TokenizerState]} */
|
|
758
|
+
const parseNewLineDefault = state => input => {
|
|
759
|
+
const next = tokenizeOp({ kind: 'initial' })(input)
|
|
760
|
+
return [{ first: { kind: 'nl' }, tail: next[0] }, next[1]]
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
/** @type {(state: ParseNewLineState) => (input: number) => readonly[List.List<JsToken>, TokenizerState]} */
|
|
764
|
+
const parseNewLineStateOp = create(parseNewLineDefault)([
|
|
765
|
+
rangeSetFunc(rangeSetWhiteSpace)(state => () => [empty, state]),
|
|
766
|
+
rangeSetFunc(rangeSetNewLine)(state => () => [empty, state])
|
|
743
767
|
])
|
|
744
768
|
|
|
745
769
|
/** @type {(state: EofState) => (input: number) => readonly[List.List<JsToken>, TokenizerState]} */
|
|
@@ -758,6 +782,7 @@ const tokenizeCharCodeOp = state => {
|
|
|
758
782
|
case 'op': return parseOperatorStateOp(state)
|
|
759
783
|
case '-': return parseMinusStateOp(state)
|
|
760
784
|
case 'ws': return parseWhitespaceStateOp(state)
|
|
785
|
+
case 'nl': return parseNewLineStateOp(state)
|
|
761
786
|
case 'eof': return eofStateOp(state)
|
|
762
787
|
}
|
|
763
788
|
}
|
|
@@ -782,6 +807,7 @@ const tokenizeEofOp = state => {
|
|
|
782
807
|
case 'op': return [[getOperatorToken(state.value)], { kind: 'eof' }]
|
|
783
808
|
case '-': return [[{kind: '-'}], { kind: 'eof' }]
|
|
784
809
|
case 'ws': return [[{kind: 'ws'}], { kind: 'eof' }]
|
|
810
|
+
case 'nl': return [[{kind: 'nl'}], { kind: 'eof' }]
|
|
785
811
|
case 'eof': return [[{ kind: 'error', message: 'eof' }], state]
|
|
786
812
|
}
|
|
787
813
|
}
|
package/js/tokenizer/test.f.mjs
CHANGED
|
@@ -47,9 +47,8 @@ export default {
|
|
|
47
47
|
},
|
|
48
48
|
() => {
|
|
49
49
|
const result = stringify(tokenizeString('{ \t\n\r}'))
|
|
50
|
-
if (result !== '[{"kind":"{"},{"kind":"
|
|
50
|
+
if (result !== '[{"kind":"{"},{"kind":"nl"},{"kind":"}"}]') { throw result }
|
|
51
51
|
},
|
|
52
|
-
|
|
53
52
|
() => {
|
|
54
53
|
const result = stringify(tokenizeString('""'))
|
|
55
54
|
if (result !== '[{"kind":"string","value":""}]') { throw result }
|
|
@@ -344,16 +343,20 @@ export default {
|
|
|
344
343
|
if (result !== '[{"kind":"ws"}]') { throw result }
|
|
345
344
|
},
|
|
346
345
|
() => {
|
|
347
|
-
const result = stringify(tokenizeString('\
|
|
346
|
+
const result = stringify(tokenizeString(' \t'))
|
|
348
347
|
if (result !== '[{"kind":"ws"}]') { throw result }
|
|
349
348
|
},
|
|
349
|
+
() => {
|
|
350
|
+
const result = stringify(tokenizeString('\n'))
|
|
351
|
+
if (result !== '[{"kind":"nl"}]') { throw result }
|
|
352
|
+
},
|
|
350
353
|
() => {
|
|
351
354
|
const result = stringify(tokenizeString('\r'))
|
|
352
|
-
if (result !== '[{"kind":"
|
|
355
|
+
if (result !== '[{"kind":"nl"}]') { throw result }
|
|
353
356
|
},
|
|
354
357
|
() => {
|
|
355
|
-
const result = stringify(tokenizeString(' \t\n\r'))
|
|
356
|
-
if (result !== '[{"kind":"
|
|
358
|
+
const result = stringify(tokenizeString(' \t\n\r '))
|
|
359
|
+
if (result !== '[{"kind":"nl"}]') { throw result }
|
|
357
360
|
},
|
|
358
361
|
],
|
|
359
362
|
id: [
|
package/jsr.json
CHANGED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
use crate::{interface::{Any, Container, Extension, Unpacked}, nullish::Nullish::*, simple::Simple};
|
|
2
|
+
|
|
3
|
+
pub trait AnyExtension: Any {
|
|
4
|
+
fn string(c: &str) -> Self::String16 {
|
|
5
|
+
c.encode_utf16().into_iter().to_complex()
|
|
6
|
+
}
|
|
7
|
+
fn to_string(self) -> Self::String16 {
|
|
8
|
+
match self.unpack() {
|
|
9
|
+
Unpacked::Nullish(v) => Self::string(match v {
|
|
10
|
+
Null => "null",
|
|
11
|
+
Undefined => "undefined",
|
|
12
|
+
}),
|
|
13
|
+
Unpacked::Bool(v) => Self::string(match v {
|
|
14
|
+
true => "true",
|
|
15
|
+
false => "false",
|
|
16
|
+
}),
|
|
17
|
+
Unpacked::Number(_) => todo!(),
|
|
18
|
+
Unpacked::String16(v) => v,
|
|
19
|
+
Unpacked::BigInt(_) => todo!(),
|
|
20
|
+
Unpacked::Array(_) => [].to_complex(),
|
|
21
|
+
Unpacked::Object(_) => Self::string("[object Object"),
|
|
22
|
+
Unpacked::Function(_) => todo!(),
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
fn own_property(self, i: Self) -> Self {
|
|
26
|
+
match self.unpack() {
|
|
27
|
+
Unpacked::Nullish(_) => panic!("own_property(\"nullish\")"),
|
|
28
|
+
Unpacked::Bool(_) => Simple::Nullish(Undefined).to_unknown(),
|
|
29
|
+
Unpacked::Number(_) => todo!(),
|
|
30
|
+
Unpacked::String16(_) => todo!(),
|
|
31
|
+
Unpacked::BigInt(_) => todo!(),
|
|
32
|
+
Unpacked::Array(_) => match i.unpack() {
|
|
33
|
+
Unpacked::Nullish(_) => todo!(),
|
|
34
|
+
Unpacked::Bool(_) => todo!(),
|
|
35
|
+
Unpacked::Number(_) => todo!(),
|
|
36
|
+
Unpacked::String16(_) => todo!(),
|
|
37
|
+
Unpacked::BigInt(_) => todo!(),
|
|
38
|
+
Unpacked::Array(_) => todo!(),
|
|
39
|
+
Unpacked::Object(_) => todo!(),
|
|
40
|
+
Unpacked::Function(_) => todo!(),
|
|
41
|
+
},
|
|
42
|
+
Unpacked::Object(_) => todo!(),
|
|
43
|
+
Unpacked::Function(_) => todo!(),
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
impl<T: Any> AnyExtension for T {}
|
|
49
|
+
|
|
50
|
+
#[cfg(test)]
|
|
51
|
+
mod test {
|
|
52
|
+
mod to_string {
|
|
53
|
+
use crate::{
|
|
54
|
+
extension::AnyExtension, interface::{Complex, Extension}, naive::{Any, Array, Object}, nullish::Nullish::*, simple::Simple
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
#[test]
|
|
58
|
+
fn test_string() {
|
|
59
|
+
let s = Any::string("Hello world!");
|
|
60
|
+
let xs: Any = s.clone().to_unknown();
|
|
61
|
+
let sxs = xs.to_string();
|
|
62
|
+
assert_eq!(s, sxs);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
#[test]
|
|
66
|
+
fn test_nullish() {
|
|
67
|
+
{
|
|
68
|
+
let x: Any = Simple::Nullish(Null).to_unknown();
|
|
69
|
+
assert_eq!(Any::string("null"), x.to_string());
|
|
70
|
+
}
|
|
71
|
+
{
|
|
72
|
+
let x: Any = Simple::Nullish(Undefined).to_unknown();
|
|
73
|
+
assert_eq!(Any::string("undefined"), x.to_string());
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
#[test]
|
|
78
|
+
fn test_boolean() {
|
|
79
|
+
{
|
|
80
|
+
let x: Any = Simple::Boolean(true).to_unknown();
|
|
81
|
+
assert_eq!(Any::string("true"), x.to_string());
|
|
82
|
+
}
|
|
83
|
+
{
|
|
84
|
+
let x: Any = Simple::Boolean(false).to_unknown();
|
|
85
|
+
assert_eq!(Any::string("false"), x.to_string());
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
#[test]
|
|
90
|
+
fn test_object() {
|
|
91
|
+
let x: Any = [].to_object_unknown();
|
|
92
|
+
assert_eq!(Any::string("[object Object"), x.to_string());
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
#[test]
|
|
96
|
+
fn test_array() {
|
|
97
|
+
let x: Any = [].to_array_unknown();
|
|
98
|
+
assert_eq!(Any::string(""), x.to_string());
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
mod own_property {
|
|
103
|
+
use crate::{extension::AnyExtension, interface::Complex, naive::Any, nullish::Nullish::*, simple::Simple};
|
|
104
|
+
|
|
105
|
+
#[test]
|
|
106
|
+
#[should_panic]
|
|
107
|
+
fn test_own_property_null() {
|
|
108
|
+
let x: Any = Simple::Nullish(Null).to_unknown();
|
|
109
|
+
x.own_property(Any::string("hello").to_unknown());
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
#[test]
|
|
113
|
+
fn test_own_property_bool() {
|
|
114
|
+
let x: Any = Simple::Boolean(true).to_unknown();
|
|
115
|
+
let undefined: Any = Simple::Nullish(Undefined).to_unknown();
|
|
116
|
+
assert_eq!(undefined, x.own_property(Any::string("hello").to_unknown()));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|