functionalscript 0.2.4 → 0.2.5
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 +6 -0
- package/README.md +1 -1
- package/crypto/README.md +3 -0
- package/{prime_field → crypto/prime_field}/module.f.mjs +2 -2
- package/{secp → crypto/secp}/module.f.mjs +2 -2
- package/{sha2 → crypto/sha2}/module.f.mjs +4 -4
- package/{sha2 → crypto/sha2}/test.f.mjs +2 -2
- package/djs/module.f.mjs +4 -1
- package/djs/parser/module.f.mjs +122 -45
- package/djs/parser/test.f.mjs +30 -4
- package/djs/tokenizer/module.f.mjs +6 -2
- package/djs/tokenizer/test.f.mjs +34 -0
- package/html/module.f.mjs +18 -33
- package/html/test.f.mjs +6 -6
- package/issues/05-publish.md +17 -22
- package/issues/README.md +10 -2
- package/js/tokenizer/module.f.mjs +75 -26
- package/js/tokenizer/test.f.mjs +42 -0
- package/json/parser/test.f.mjs +6 -0
- package/jsr.json +4 -4
- package/nanvm-lib/src/extension.rs +1 -1
- package/nanvm-lib/src/nanenum.rs +22 -20
- package/out/{prime_field → crypto/prime_field}/module.f.d.mts +1 -1
- package/out/{prime_field → crypto/prime_field}/module.f.mjs +2 -2
- package/out/{secp → crypto/secp}/module.f.d.mts +1 -1
- package/out/{secp → crypto/secp}/module.f.mjs +2 -2
- package/out/{sha2 → crypto/sha2}/module.f.d.mts +3 -3
- package/out/{sha2 → crypto/sha2}/module.f.mjs +4 -4
- package/out/{sha2 → crypto/sha2}/test.f.mjs +2 -2
- package/out/djs/module.f.d.mts +1 -1
- package/out/djs/module.f.mjs +5 -1
- package/out/djs/parser/module.f.d.mts +1 -1
- package/out/djs/parser/module.f.mjs +105 -89
- package/out/djs/parser/test.f.d.mts +1 -0
- package/out/djs/parser/test.f.mjs +38 -4
- package/out/djs/tokenizer/module.f.d.mts +2 -2
- package/out/djs/tokenizer/module.f.mjs +6 -2
- package/out/djs/tokenizer/test.f.d.mts +1 -0
- package/out/djs/tokenizer/test.f.mjs +50 -0
- package/out/html/module.f.d.mts +8 -6
- package/out/html/module.f.mjs +17 -31
- package/out/html/test.f.mjs +5 -5
- package/out/js/tokenizer/module.f.d.mts +15 -3
- package/out/js/tokenizer/module.f.mjs +65 -22
- package/out/js/tokenizer/test.f.d.mts +1 -0
- package/out/js/tokenizer/test.f.mjs +62 -0
- package/out/json/parser/test.f.mjs +8 -0
- package/package.json +1 -1
- /package/{prime_field → crypto/prime_field}/test.f.mjs +0 -0
- /package/{secp → crypto/secp}/test.f.mjs +0 -0
- /package/out/{prime_field → crypto/prime_field}/test.f.d.mts +0 -0
- /package/out/{prime_field → crypto/prime_field}/test.f.mjs +0 -0
- /package/out/{secp → crypto/secp}/test.f.d.mts +0 -0
- /package/out/{secp → crypto/secp}/test.f.mjs +0 -0
- /package/out/{sha2 → crypto/sha2}/test.f.d.mts +0 -0
package/html/test.f.mjs
CHANGED
|
@@ -2,8 +2,8 @@ import * as _ from './module.f.mjs'
|
|
|
2
2
|
|
|
3
3
|
export default {
|
|
4
4
|
empty: () => {
|
|
5
|
-
const r = _.htmlToString(['html'
|
|
6
|
-
if (r !== '<!DOCTYPE html><html></html>') { throw r }
|
|
5
|
+
const r = _.htmlToString(['html'])
|
|
6
|
+
if (r !== '<!DOCTYPE html><html></html>') { throw `empty: ${r}` }
|
|
7
7
|
},
|
|
8
8
|
empty2: () => {
|
|
9
9
|
const r = _.htmlToString(['html'])
|
|
@@ -15,20 +15,20 @@ export default {
|
|
|
15
15
|
},
|
|
16
16
|
some: () => {
|
|
17
17
|
/** @type {_.Element} */
|
|
18
|
-
const x = ['div', {},
|
|
18
|
+
const x = ['div', {}, '<div>&</div>', ['a', { href: 'hello"' }]]
|
|
19
19
|
const s = _.htmlToString(x)
|
|
20
20
|
if (s !== '<!DOCTYPE html><div><div>&amp;</div><a href="hello""></a></div>') { throw s }
|
|
21
21
|
},
|
|
22
22
|
some2: () => {
|
|
23
23
|
/** @type {_.Element} */
|
|
24
|
-
const x = ['div',
|
|
24
|
+
const x = ['div', '<div>&</div>', ['a', { href: 'hello"' }]]
|
|
25
25
|
const s = _.htmlToString(x)
|
|
26
26
|
if (s !== '<!DOCTYPE html><div><div>&amp;</div><a href="hello""></a></div>') { throw s }
|
|
27
27
|
},
|
|
28
28
|
someVoid: () => {
|
|
29
29
|
/** @type {_.Element} */
|
|
30
|
-
const x = ['div', [
|
|
30
|
+
const x = ['div', ['br', {id: '5'}], '<div>&</div>', ['a', { href: 'hello"' }]]
|
|
31
31
|
const s = _.htmlToString(x)
|
|
32
32
|
if (s !== '<!DOCTYPE html><div><br id="5"><div>&amp;</div><a href="hello""></a></div>') { throw s }
|
|
33
33
|
}
|
|
34
|
-
}
|
|
34
|
+
}
|
package/issues/05-publish.md
CHANGED
|
@@ -9,37 +9,32 @@ We are targeting the following systems:
|
|
|
9
9
|
- Rust:
|
|
10
10
|
- [ ] https://crates.io/
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
The main principle is that we should be able to install FunctionalScript from Git/GitHub. Currently,
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
- `NPM` works with Git links and `.mjs` files.
|
|
15
|
+
- `JSR`. Unfortunately, JSR doesn't support JSDoc type information, see [jsr-io/jsr/issues/494](https://github.com/jsr-io/jsr/issues/494).
|
|
16
|
+
- Browsers. `import * from 'https://...'`.
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
- [jsr.json](./jsr.json), `version` property
|
|
18
|
-
- [index.f.mjs](./index.f.mjs)
|
|
19
|
-
|
|
20
|
-
`version` property should be `version` calculated on a `main` branch.
|
|
18
|
+
We have two options:
|
|
21
19
|
|
|
22
|
-
|
|
20
|
+
- Continue to use JavaScript source files and generate JSR package before publishing,
|
|
21
|
+
- Switch to TypeScript source files and write [prepack](https://docs.npmjs.com/cli/v7/using-npm/scripts) script. TS files could be a problem for our parser because it doesn't strip type annotations yet.
|
|
23
22
|
|
|
24
|
-
|
|
23
|
+
This problem will go away as soon as ECMAScript supports for [Type Annotations](https://github.com/tc39/proposal-type-annotations).
|
|
25
24
|
|
|
26
|
-
|
|
25
|
+
## Updating Packages
|
|
27
26
|
|
|
28
|
-
|
|
29
|
-
2. `version` is updated in [jsr.json](./jsr.json) and [package.json](./package.json).
|
|
27
|
+
Currently, we regenerate `exports` in [./jsr.json](./index.f.mjs) using `npm run index` during CD (publishing) and `version` using `npm run version`. We should combine it into `update` script.
|
|
30
28
|
|
|
31
|
-
|
|
29
|
+
We don't check in CI if it was regenerated. The idea is that CI should check if all generated files in Git are updated:
|
|
32
30
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
Check if the version is new, then publish.
|
|
36
|
-
|
|
37
|
-
### 2. CI
|
|
31
|
+
- [package.json](./package.json) `version` property
|
|
32
|
+
- [jsr.json](./jsr.json), `version` and `exports` property.
|
|
38
33
|
|
|
39
|
-
|
|
34
|
+
`version` property should be the same in `package.json` and `jsr.json`.
|
|
40
35
|
|
|
41
|
-
|
|
36
|
+
We abandoned the idea to publish on every commit on `main`. Instead, we publish only when there is an new version in the `main`. This strategy can also work for Rust packages.
|
|
42
37
|
|
|
43
|
-
|
|
38
|
+
## CI Publishing (merge to `main`)
|
|
44
39
|
|
|
45
|
-
|
|
40
|
+
Check if the version is new, then publish.
|
package/issues/README.md
CHANGED
|
@@ -27,5 +27,13 @@
|
|
|
27
27
|
18. [ ] Formatter for `.f.js` and `.f.ts` files.
|
|
28
28
|
19. [ ] Convert FunctionalScript code using non-default `export`.
|
|
29
29
|
20. [ ] Test framework should be able to run a subset of tests.
|
|
30
|
-
21. [ ] Test Framework silent mode. Show progress and
|
|
31
|
-
22. [
|
|
30
|
+
21. [ ] Test Framework silent mode. Show progress and failed tests only.
|
|
31
|
+
22. [x] bit sequences based on bigint
|
|
32
|
+
23. [ ] a console program similar to one that we have in the NaNVM repo.
|
|
33
|
+
24. [ ] create `./module.mjs` that supports the same behavior like current NaNVM Rust implementation:
|
|
34
|
+
- [ ] run `node ./module.mjs input.f.mjs output.f.mjs`
|
|
35
|
+
- [ ] run `deno ./module.mjs input.f.mjs output.f.mjs`
|
|
36
|
+
|
|
37
|
+
## Language Specification
|
|
38
|
+
|
|
39
|
+
See [lang/README.md](./lang/README.md).
|
|
@@ -104,6 +104,8 @@ const {
|
|
|
104
104
|
|
|
105
105
|
/** @typedef {{readonly kind: 'null'}} NullToken */
|
|
106
106
|
|
|
107
|
+
/** @typedef {{readonly kind: 'undefined'}} UndefinedToken */
|
|
108
|
+
|
|
107
109
|
/**
|
|
108
110
|
* @typedef {|
|
|
109
111
|
* {readonly kind: 'arguments' | 'await' | 'break' | 'case' | 'catch' | 'class' | 'const' | 'continue' } |
|
|
@@ -138,6 +140,13 @@ const {
|
|
|
138
140
|
* } OperatorToken
|
|
139
141
|
*/
|
|
140
142
|
|
|
143
|
+
/**
|
|
144
|
+
* @typedef {{
|
|
145
|
+
* readonly kind: '//' | '/*'
|
|
146
|
+
* readonly value: string
|
|
147
|
+
* }} CommentToken
|
|
148
|
+
* */
|
|
149
|
+
|
|
141
150
|
/**
|
|
142
151
|
* @typedef {|
|
|
143
152
|
* KeywordToken |
|
|
@@ -151,7 +160,9 @@ const {
|
|
|
151
160
|
* ErrorToken |
|
|
152
161
|
* IdToken |
|
|
153
162
|
* BigIntToken |
|
|
154
|
-
*
|
|
163
|
+
* UndefinedToken |
|
|
164
|
+
* OperatorToken |
|
|
165
|
+
* CommentToken
|
|
155
166
|
* } JsToken
|
|
156
167
|
*/
|
|
157
168
|
|
|
@@ -240,21 +251,23 @@ const rangeId = [digitRange, ...rangeIdStart]
|
|
|
240
251
|
* ParseNumberState |
|
|
241
252
|
* InvalidNumberState |
|
|
242
253
|
* ParseOperatorState |
|
|
243
|
-
* ParseMinusState |
|
|
244
254
|
* ParseWhitespaceState |
|
|
245
255
|
* ParseNewLineState |
|
|
256
|
+
* ParseCommentState |
|
|
246
257
|
* EofState
|
|
247
258
|
* } TokenizerState
|
|
248
259
|
*/
|
|
249
260
|
|
|
250
261
|
/**
|
|
251
262
|
* @typedef {|
|
|
252
|
-
|
|
263
|
+
* '" are missing' |
|
|
253
264
|
* 'unescaped character' |
|
|
254
265
|
* 'invalid hex value' |
|
|
255
266
|
* 'unexpected character' |
|
|
256
267
|
* 'invalid number' |
|
|
257
268
|
* 'invalid token' |
|
|
269
|
+
* '*\/ expected' |
|
|
270
|
+
* 'unterminated string literal' |
|
|
258
271
|
* 'eof'
|
|
259
272
|
* } ErrorMessage
|
|
260
273
|
*/
|
|
@@ -275,6 +288,14 @@ const rangeId = [digitRange, ...rangeIdStart]
|
|
|
275
288
|
|
|
276
289
|
/** @typedef {{ readonly kind: '-'}} ParseMinusState */
|
|
277
290
|
|
|
291
|
+
/**
|
|
292
|
+
* @typedef {{
|
|
293
|
+
* readonly kind: '//' | '/*' | '/**'
|
|
294
|
+
* readonly value: string
|
|
295
|
+
* readonly newLine: boolean
|
|
296
|
+
* }} ParseCommentState
|
|
297
|
+
*/
|
|
298
|
+
|
|
278
299
|
/**
|
|
279
300
|
* @typedef {{
|
|
280
301
|
* readonly kind: 'unicodeChar'
|
|
@@ -286,7 +307,7 @@ const rangeId = [digitRange, ...rangeIdStart]
|
|
|
286
307
|
|
|
287
308
|
/**
|
|
288
309
|
* @typedef {{
|
|
289
|
-
* readonly kind: 'number'
|
|
310
|
+
* readonly kind: 'number'
|
|
290
311
|
* readonly numberKind: '0' | 'int' | '.' | 'fractional' | 'e' | 'e+' | 'e-' | 'expDigits' | 'bigint'
|
|
291
312
|
* readonly value: string
|
|
292
313
|
* readonly b: ParseNumberBuffer
|
|
@@ -448,6 +469,7 @@ const keywordEntries = [
|
|
|
448
469
|
['true', { kind: 'true'}],
|
|
449
470
|
['try', { kind: 'try'}],
|
|
450
471
|
['typeof', { kind: 'typeof'}],
|
|
472
|
+
['undefined', { kind: 'undefined'}],
|
|
451
473
|
['var', { kind: 'var'}],
|
|
452
474
|
['void', { kind: 'void'}],
|
|
453
475
|
['while', { kind: 'while'}],
|
|
@@ -534,8 +556,8 @@ const hasOperatorToken = op => at(op)(operatorMap) !== null
|
|
|
534
556
|
const initialStateOp = create(state => () => [[{ kind: 'error', message: 'unexpected character' }], state])([
|
|
535
557
|
rangeFunc(rangeOneNine)(() => input => [empty, { kind: 'number', value: fromCharCode(input), b: startNumber(input), numberKind: 'int' }]),
|
|
536
558
|
rangeSetFunc(rangeIdStart)(() => input => [empty, { kind: 'id', value: fromCharCode(input) }]),
|
|
537
|
-
rangeSetFunc(rangeSetWhiteSpace)(
|
|
538
|
-
rangeSetFunc(rangeSetNewLine)(
|
|
559
|
+
rangeSetFunc(rangeSetWhiteSpace)(() => () => [empty, { kind: 'ws' }]),
|
|
560
|
+
rangeSetFunc(rangeSetNewLine)(() => () => [empty, { kind: 'nl' }]),
|
|
539
561
|
rangeFunc(one(quotationMark))(() => () => [empty, { kind: 'string', value: '' }]),
|
|
540
562
|
rangeFunc(one(digit0))(() => input => [empty, { kind: 'number', value: fromCharCode(input), b: startNumber(input), numberKind: '0' }]),
|
|
541
563
|
rangeSetFunc(rangeOpStart)(() => input => [empty, { kind: 'op', value: fromCharCode(input) }])
|
|
@@ -666,17 +688,11 @@ const invalidNumberStateOp = create(() => () => [empty, { kind: 'invalidNumber'
|
|
|
666
688
|
})
|
|
667
689
|
])
|
|
668
690
|
|
|
669
|
-
/** @type {(state: ParseMinusState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
|
|
670
|
-
const parseMinusStateOp = create(() => input => tokenizeOp({ kind: 'op', value: '-' })(input))([
|
|
671
|
-
rangeFunc(one(fullStop))(() => input => tokenizeOp({ kind: 'invalidNumber' })(input)),
|
|
672
|
-
rangeFunc(one(digit0))(() => () => [empty, { kind: 'number', value: '-0', b: startNegativeNumber, numberKind: '0' }]),
|
|
673
|
-
rangeFunc(rangeOneNine)(() => input => [empty, { kind: 'number', value: appendChar('-')(input), b: addIntDigit(input)(startNegativeNumber), numberKind: 'int' }]),
|
|
674
|
-
])
|
|
675
|
-
|
|
676
691
|
/** @type {(state: ParseStringState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
|
|
677
|
-
const parseStringStateOp = create(state => input => [empty, { kind: 'string', value: appendChar(state.value)(input) }])([
|
|
692
|
+
const parseStringStateOp = create(state => input => [empty, { kind: 'string', value: appendChar(state.value)(input) }])([
|
|
678
693
|
rangeFunc(one(quotationMark))(state => () => [[{ kind: 'string', value: state.value }], { kind: 'initial' }]),
|
|
679
|
-
rangeFunc(one(reverseSolidus))(state => () => [empty, { kind: 'escapeChar', value: state.value }])
|
|
694
|
+
rangeFunc(one(reverseSolidus))(state => () => [empty, { kind: 'escapeChar', value: state.value }]),
|
|
695
|
+
rangeSetFunc(rangeSetNewLine)(() => () => [[{ kind: 'error', message: 'unterminated string literal'}], { kind: 'nl'}])
|
|
680
696
|
])
|
|
681
697
|
|
|
682
698
|
/** @type {(state: ParseEscapeCharState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
|
|
@@ -736,14 +752,43 @@ const parseIdStateOp = create(parseIdDefault)([
|
|
|
736
752
|
/** @type {(state: ParseOperatorState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
|
|
737
753
|
const parseOperatorStateOp = state => input => {
|
|
738
754
|
const nextStateValue = appendChar(state.value)(input)
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
755
|
+
switch (nextStateValue)
|
|
756
|
+
{
|
|
757
|
+
case '//': return [empty, { kind: '//', value: '', newLine: false }]
|
|
758
|
+
case '/*': return [empty, { kind: '/*', value: '', newLine: false }]
|
|
759
|
+
default: {
|
|
760
|
+
if (hasOperatorToken(nextStateValue))
|
|
761
|
+
return [empty, { kind: 'op', value: nextStateValue }]
|
|
762
|
+
const next = tokenizeOp({ kind: 'initial' })(input)
|
|
763
|
+
return [{ first: getOperatorToken(state.value), tail: next[0] }, next[1]]
|
|
764
|
+
}
|
|
765
|
+
}
|
|
743
766
|
}
|
|
744
767
|
|
|
768
|
+
/** @type {(state: ParseCommentState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
|
|
769
|
+
const parseSinglelineCommentStateOp = create(state => input => [empty, { ...state, value: appendChar(state.value)(input) }])([
|
|
770
|
+
rangeSetFunc(rangeSetNewLine)(state => () => [[{ kind: '//', value: state.value }], { kind: 'nl' }])
|
|
771
|
+
])
|
|
772
|
+
|
|
773
|
+
/** @type {(state: ParseCommentState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
|
|
774
|
+
const parseMultilineCommentStateOp = create(state => input => [empty, { ...state, value: appendChar(state.value)(input) }])([
|
|
775
|
+
rangeFunc(one(asterisk))(state => () => [empty, { ...state, kind: '/**' }]),
|
|
776
|
+
rangeSetFunc(rangeSetNewLine)(state => input => [empty, { ...state, value: appendChar(state.value)(input), newLine: true }]),
|
|
777
|
+
])
|
|
778
|
+
|
|
779
|
+
/** @type {(state: ParseCommentState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
|
|
780
|
+
const parseMultilineCommentAsteriskStateOp = create(state => input => [empty, { ...state, kind: '/*', value: appendChar(appendChar(state.value)(asterisk))(input)}])([
|
|
781
|
+
rangeFunc(one(asterisk))(state => () => [empty, { ...state, value: appendChar(state.value)(asterisk) }]),
|
|
782
|
+
rangeSetFunc(rangeSetNewLine)(state => input => [empty, { kind: '/*', value: appendChar(appendChar(state.value)(asterisk))(input), newLine: true }]),
|
|
783
|
+
rangeFunc(one(solidus))(state => () => {
|
|
784
|
+
/** @type {list.List<JsToken>} */
|
|
785
|
+
const tokens = state.newLine ? [{ kind: '/*', value: state.value }, { kind: 'nl' }] : [{ kind: '/*', value: state.value }]
|
|
786
|
+
return [tokens, { kind: 'initial' }]
|
|
787
|
+
})
|
|
788
|
+
])
|
|
789
|
+
|
|
745
790
|
/** @type {(state: ParseWhitespaceState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
|
|
746
|
-
const parseWhitespaceDefault =
|
|
791
|
+
const parseWhitespaceDefault = () => input => {
|
|
747
792
|
const next = tokenizeOp({ kind: 'initial' })(input)
|
|
748
793
|
return [{ first: { kind: 'ws' }, tail: next[0] }, next[1]]
|
|
749
794
|
}
|
|
@@ -751,7 +796,7 @@ const parseWhitespaceDefault = state => input => {
|
|
|
751
796
|
/** @type {(state: ParseWhitespaceState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
|
|
752
797
|
const parseWhitespaceStateOp = create(parseWhitespaceDefault)([
|
|
753
798
|
rangeSetFunc(rangeSetWhiteSpace)(state => () => [empty, state]),
|
|
754
|
-
rangeSetFunc(rangeSetNewLine)(
|
|
799
|
+
rangeSetFunc(rangeSetNewLine)(() => () => [empty, { kind: 'nl' }])
|
|
755
800
|
])
|
|
756
801
|
|
|
757
802
|
/** @type {(state: ParseNewLineState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
|
|
@@ -780,7 +825,9 @@ const tokenizeCharCodeOp = state => {
|
|
|
780
825
|
case 'invalidNumber': return invalidNumberStateOp(state)
|
|
781
826
|
case 'number': return parseNumberStateOp(state)
|
|
782
827
|
case 'op': return parseOperatorStateOp(state)
|
|
783
|
-
case '
|
|
828
|
+
case '//': return parseSinglelineCommentStateOp(state)
|
|
829
|
+
case '/*': return parseMultilineCommentStateOp(state)
|
|
830
|
+
case '/**': return parseMultilineCommentAsteriskStateOp(state)
|
|
784
831
|
case 'ws': return parseWhitespaceStateOp(state)
|
|
785
832
|
case 'nl': return parseNewLineStateOp(state)
|
|
786
833
|
case 'eof': return eofStateOp(state)
|
|
@@ -801,11 +848,13 @@ const tokenizeEofOp = state => {
|
|
|
801
848
|
case '.':
|
|
802
849
|
case 'e':
|
|
803
850
|
case 'e+':
|
|
804
|
-
case 'e-': return [[{ kind: 'error', message: 'invalid number' }], { kind: '
|
|
851
|
+
case 'e-': return [[{ kind: 'error', message: 'invalid number' }], { kind: 'eof', }]
|
|
805
852
|
default: return [[bufferToNumberToken(state)], { kind: 'eof' }]
|
|
806
853
|
}
|
|
807
|
-
case 'op': return [[getOperatorToken(state.value)], { kind: 'eof' }]
|
|
808
|
-
case '
|
|
854
|
+
case 'op': return [[getOperatorToken(state.value)], { kind: 'eof' }]
|
|
855
|
+
case '//': return [[{kind: '//', value: state.value}], { kind: 'eof' }]
|
|
856
|
+
case '/*':
|
|
857
|
+
case '/**': return [[{ kind: 'error', message: '*/ expected' }], { kind: 'eof', }]
|
|
809
858
|
case 'ws': return [[{kind: 'ws'}], { kind: 'eof' }]
|
|
810
859
|
case 'nl': return [[{kind: 'nl'}], { kind: 'eof' }]
|
|
811
860
|
case 'eof': return [[{ kind: 'error', message: 'eof' }], state]
|
|
@@ -820,4 +869,4 @@ const scanTokenize = stateScan(tokenizeOp)
|
|
|
820
869
|
const initial = scanTokenize({ kind: 'initial' })
|
|
821
870
|
|
|
822
871
|
/** @type {(input: list.List<number>) => list.List<JsToken>} */
|
|
823
|
-
export const tokenize = input => flat(initial(flat([/** @type {list.List<CharCodeOrEof>} */(input), [null]])))
|
|
872
|
+
export const tokenize = input => flat(initial(flat([/** @type {list.List<CharCodeOrEof>} */(input), [null]])))
|
package/js/tokenizer/test.f.mjs
CHANGED
|
@@ -89,6 +89,14 @@ export default {
|
|
|
89
89
|
const result = stringify(tokenizeString('"\\'))
|
|
90
90
|
if (result !== '[{"kind":"error","message":"\\" are missing"}]') { throw result }
|
|
91
91
|
},
|
|
92
|
+
() => {
|
|
93
|
+
const result = stringify(tokenizeString('"\r"'))
|
|
94
|
+
if (result !== '[{"kind":"error","message":"unterminated string literal"},{"kind":"nl"},{"kind":"error","message":"\\" are missing"}]') { throw result }
|
|
95
|
+
},
|
|
96
|
+
() => {
|
|
97
|
+
const result = stringify(tokenizeString('"\n null'))
|
|
98
|
+
if (result !== '[{"kind":"error","message":"unterminated string literal"},{"kind":"nl"},{"kind":"null"}]') { throw result }
|
|
99
|
+
},
|
|
92
100
|
() => {
|
|
93
101
|
const result = stringify(tokenizeString('"\\b\\f\\n\\r\\t"'))
|
|
94
102
|
if (result !== '[{"kind":"string","value":"\\b\\f\\n\\r\\t"}]') { throw result }
|
|
@@ -386,6 +394,10 @@ export default {
|
|
|
386
394
|
const result = stringify(tokenizeString('null'))
|
|
387
395
|
if (result !== '[{"kind":"null"}]') { throw result }
|
|
388
396
|
},
|
|
397
|
+
() => {
|
|
398
|
+
const result = stringify(tokenizeString('undefined'))
|
|
399
|
+
if (result !== '[{"kind":"undefined"}]') { throw result }
|
|
400
|
+
},
|
|
389
401
|
() => {
|
|
390
402
|
const result = stringify(tokenizeString('[null]'))
|
|
391
403
|
if (result !== '[{"kind":"["},{"kind":"null"},{"kind":"]"}]') { throw result }
|
|
@@ -570,5 +582,35 @@ export default {
|
|
|
570
582
|
const result = stringify(tokenizeString('yield'))
|
|
571
583
|
if (result !== '[{"kind":"yield"}]') { throw result }
|
|
572
584
|
},
|
|
585
|
+
],
|
|
586
|
+
comments: [
|
|
587
|
+
() => {
|
|
588
|
+
const result = stringify(tokenizeString('//singleline comment'))
|
|
589
|
+
if (result !== '[{"kind":"//","value":"singleline comment"}]') { throw result }
|
|
590
|
+
},
|
|
591
|
+
() => {
|
|
592
|
+
const result = stringify(tokenizeString('true//singleline comment\nfalse'))
|
|
593
|
+
if (result !== '[{"kind":"true"},{"kind":"//","value":"singleline comment"},{"kind":"nl"},{"kind":"false"}]') { throw result }
|
|
594
|
+
},
|
|
595
|
+
() => {
|
|
596
|
+
const result = stringify(tokenizeString('/* multiline comment */'))
|
|
597
|
+
if (result !== '[{"kind":"/*","value":" multiline comment "}]') { throw result }
|
|
598
|
+
},
|
|
599
|
+
() => {
|
|
600
|
+
const result = stringify(tokenizeString('/* multiline comment *'))
|
|
601
|
+
if (result !== '[{"kind":"error","message":"*/ expected"}]') { throw result }
|
|
602
|
+
},
|
|
603
|
+
() => {
|
|
604
|
+
const result = stringify(tokenizeString('/* multiline comment '))
|
|
605
|
+
if (result !== '[{"kind":"error","message":"*/ expected"}]') { throw result }
|
|
606
|
+
},
|
|
607
|
+
() => {
|
|
608
|
+
const result = stringify(tokenizeString('/* multiline comment \n * **/'))
|
|
609
|
+
if (result !== '[{"kind":"/*","value":" multiline comment \\n * *"},{"kind":"nl"}]') { throw result }
|
|
610
|
+
},
|
|
611
|
+
() => {
|
|
612
|
+
const result = stringify(tokenizeString('/* multiline comment *\n * **/'))
|
|
613
|
+
if (result !== '[{"kind":"/*","value":" multiline comment *\\n * *"},{"kind":"nl"}]') { throw result }
|
|
614
|
+
},
|
|
573
615
|
]
|
|
574
616
|
}
|
package/json/parser/test.f.mjs
CHANGED
|
@@ -244,5 +244,11 @@ export default {
|
|
|
244
244
|
const result = stringify(obj)
|
|
245
245
|
if (result !== '["error","unexpected token"]') { throw result }
|
|
246
246
|
},
|
|
247
|
+
() => {
|
|
248
|
+
const tokenList = tokenizeString('undefined')
|
|
249
|
+
const obj = parser.parse(tokenList)
|
|
250
|
+
const result = stringify(obj)
|
|
251
|
+
if (result !== '["error","unexpected token"]') { throw result }
|
|
252
|
+
},
|
|
247
253
|
]
|
|
248
254
|
}
|
package/jsr.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@functionalscript/functionalscript",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"license": "AGPL-3.0-only",
|
|
5
5
|
"exports": {
|
|
6
6
|
"./com/cpp": "./out/com/cpp/module.f.mjs",
|
|
@@ -14,6 +14,9 @@
|
|
|
14
14
|
"./commonjs/package/dependencies": "./out/commonjs/package/dependencies/module.f.mjs",
|
|
15
15
|
"./commonjs/package": "./out/commonjs/package/module.f.mjs",
|
|
16
16
|
"./commonjs/path": "./out/commonjs/path/module.f.mjs",
|
|
17
|
+
"./crypto/prime_field": "./out/crypto/prime_field/module.f.mjs",
|
|
18
|
+
"./crypto/secp": "./out/crypto/secp/module.f.mjs",
|
|
19
|
+
"./crypto/sha2": "./out/crypto/sha2/module.f.mjs",
|
|
17
20
|
"./dev": "./out/dev/module.f.mjs",
|
|
18
21
|
"./dev/test": "./out/dev/test/module.f.mjs",
|
|
19
22
|
"./djs": "./out/djs/module.f.mjs",
|
|
@@ -28,9 +31,6 @@
|
|
|
28
31
|
"./json/serializer": "./out/json/serializer/module.f.mjs",
|
|
29
32
|
"./json/tokenizer": "./out/json/tokenizer/module.f.mjs",
|
|
30
33
|
"./nodejs/version": "./out/nodejs/version/module.f.mjs",
|
|
31
|
-
"./prime_field": "./out/prime_field/module.f.mjs",
|
|
32
|
-
"./secp": "./out/secp/module.f.mjs",
|
|
33
|
-
"./sha2": "./out/sha2/module.f.mjs",
|
|
34
34
|
"./text/ascii": "./out/text/ascii/module.f.mjs",
|
|
35
35
|
"./text": "./out/text/module.f.mjs",
|
|
36
36
|
"./text/sgr": "./out/text/sgr/module.f.mjs",
|
package/nanvm-lib/src/nanenum.rs
CHANGED
|
@@ -99,7 +99,7 @@ impl<T: Raw64> Drop for NaNEnumPack<T> {
|
|
|
99
99
|
|
|
100
100
|
#[cfg(test)]
|
|
101
101
|
mod test {
|
|
102
|
-
use core::{mem::
|
|
102
|
+
use core::{mem::forget, ptr::null, sync::atomic::{AtomicUsize, Ordering}};
|
|
103
103
|
use std::rc::Rc;
|
|
104
104
|
|
|
105
105
|
use crate::nanenum::{Raw64, NEGATIVE, NOT_FINITE};
|
|
@@ -108,6 +108,7 @@ mod test {
|
|
|
108
108
|
|
|
109
109
|
// See https://doc.rust-lang.org/std/mem/fn.needs_drop.html
|
|
110
110
|
|
|
111
|
+
/*
|
|
111
112
|
trait Dropable {
|
|
112
113
|
const _A: () = assert!(needs_drop::<Self>());
|
|
113
114
|
}
|
|
@@ -115,6 +116,7 @@ mod test {
|
|
|
115
116
|
trait NonDropable {
|
|
116
117
|
const _A: () = assert!(!needs_drop::<Self>());
|
|
117
118
|
}
|
|
119
|
+
*/
|
|
118
120
|
|
|
119
121
|
#[test]
|
|
120
122
|
fn test_f64() {
|
|
@@ -125,13 +127,13 @@ mod test {
|
|
|
125
127
|
|
|
126
128
|
#[test]
|
|
127
129
|
fn test_pack() {
|
|
128
|
-
static
|
|
130
|
+
static I: AtomicUsize = AtomicUsize::new(0);
|
|
129
131
|
|
|
130
132
|
struct P();
|
|
131
133
|
|
|
132
134
|
impl Default for P {
|
|
133
135
|
fn default() -> Self {
|
|
134
|
-
|
|
136
|
+
I.fetch_add(1, Ordering::Relaxed);
|
|
135
137
|
Self()
|
|
136
138
|
}
|
|
137
139
|
}
|
|
@@ -144,7 +146,7 @@ mod test {
|
|
|
144
146
|
|
|
145
147
|
impl Drop for P {
|
|
146
148
|
fn drop(&mut self) {
|
|
147
|
-
|
|
149
|
+
I.fetch_sub(1, Ordering::Relaxed);
|
|
148
150
|
}
|
|
149
151
|
}
|
|
150
152
|
|
|
@@ -162,20 +164,20 @@ mod test {
|
|
|
162
164
|
//
|
|
163
165
|
|
|
164
166
|
{
|
|
165
|
-
|
|
167
|
+
assert_eq!(I.load(Ordering::Relaxed), 0);
|
|
166
168
|
{
|
|
167
169
|
let x = P::default();
|
|
168
|
-
|
|
170
|
+
assert_eq!(I.load(Ordering::Relaxed), 1);
|
|
169
171
|
let m = NaNEnum::Else(x);
|
|
170
|
-
|
|
172
|
+
assert_eq!(I.load(Ordering::Relaxed), 1);
|
|
171
173
|
let p = NaNEnumPack::pack(m);
|
|
172
|
-
|
|
174
|
+
assert_eq!(I.load(Ordering::Relaxed), 1);
|
|
173
175
|
let p1 = p.clone();
|
|
174
|
-
|
|
176
|
+
assert_eq!(I.load(Ordering::Relaxed), 2);
|
|
175
177
|
let m1 = p1.unpack();
|
|
176
|
-
|
|
178
|
+
assert_eq!(I.load(Ordering::Relaxed), 2);
|
|
177
179
|
if let NaNEnum::Else(x1) = m1 {
|
|
178
|
-
|
|
180
|
+
assert_eq!(I.load(Ordering::Relaxed), 2);
|
|
179
181
|
// assert_ne!(&x as *const _, null())
|
|
180
182
|
// assert_ne!(&m as *const _, null())
|
|
181
183
|
assert_ne!(&p as *const _, null());
|
|
@@ -186,26 +188,26 @@ mod test {
|
|
|
186
188
|
panic!()
|
|
187
189
|
}
|
|
188
190
|
}
|
|
189
|
-
|
|
191
|
+
assert_eq!(I.load(Ordering::Relaxed), 0);
|
|
190
192
|
}
|
|
191
193
|
|
|
192
194
|
//
|
|
193
195
|
|
|
194
196
|
{
|
|
195
|
-
|
|
197
|
+
assert_eq!(I.load(Ordering::Relaxed), 0);
|
|
196
198
|
{
|
|
197
199
|
let x = P::default();
|
|
198
|
-
|
|
200
|
+
assert_eq!(I.load(Ordering::Relaxed), 1);
|
|
199
201
|
let m = NaNEnum::Else(x.clone());
|
|
200
|
-
|
|
202
|
+
assert_eq!(I.load(Ordering::Relaxed), 2);
|
|
201
203
|
let p = NaNEnumPack::pack(m.clone());
|
|
202
|
-
|
|
204
|
+
assert_eq!(I.load(Ordering::Relaxed), 3);
|
|
203
205
|
let p1 = p.clone();
|
|
204
|
-
|
|
206
|
+
assert_eq!(I.load(Ordering::Relaxed), 4);
|
|
205
207
|
let m1 = p1.clone().unpack();
|
|
206
|
-
|
|
208
|
+
assert_eq!(I.load(Ordering::Relaxed), 5);
|
|
207
209
|
if let NaNEnum::Else(x1) = m1.clone() {
|
|
208
|
-
|
|
210
|
+
assert_eq!(I.load(Ordering::Relaxed), 6);
|
|
209
211
|
assert_ne!(&x as *const _, null());
|
|
210
212
|
assert_ne!(&m as *const _, null());
|
|
211
213
|
assert_ne!(&p as *const _, null());
|
|
@@ -216,7 +218,7 @@ mod test {
|
|
|
216
218
|
panic!()
|
|
217
219
|
}
|
|
218
220
|
}
|
|
219
|
-
|
|
221
|
+
assert_eq!(I.load(Ordering::Relaxed), 0);
|
|
220
222
|
}
|
|
221
223
|
}
|
|
222
224
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @ts-self-types="./module.f.d.mts"
|
|
2
|
-
import * as Operator from '
|
|
3
|
-
import * as bi from '
|
|
2
|
+
import * as Operator from '../../types/function/operator/module.f.mjs';
|
|
3
|
+
import * as bi from '../../types/bigint/module.f.mjs';
|
|
4
4
|
const { scalar_mul } = bi;
|
|
5
5
|
/** @typedef {Operator.Reduce<bigint>} Reduce */
|
|
6
6
|
/** @typedef {Operator.Unary<bigint, bigint>} Unary*/
|
|
@@ -107,4 +107,4 @@ export type Curve = {
|
|
|
107
107
|
readonly mul: (a: Point) => (n: bigint) => Point;
|
|
108
108
|
};
|
|
109
109
|
import * as pf from '../prime_field/module.f.mjs';
|
|
110
|
-
import * as Operator from '
|
|
110
|
+
import * as Operator from '../../types/function/operator/module.f.mjs';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @ts-self-types="./module.f.d.mts"
|
|
2
|
-
import * as Operator from '
|
|
2
|
+
import * as Operator from '../../types/function/operator/module.f.mjs';
|
|
3
3
|
import * as pf from '../prime_field/module.f.mjs';
|
|
4
|
-
import * as bi from '
|
|
4
|
+
import * as bi from '../../types/bigint/module.f.mjs';
|
|
5
5
|
const { scalar_mul } = bi;
|
|
6
6
|
const { prime_field, sqrt } = pf;
|
|
7
7
|
/**
|
|
@@ -10,6 +10,6 @@ export type HashInput = {
|
|
|
10
10
|
readonly f: (i: number) => number;
|
|
11
11
|
readonly length: number;
|
|
12
12
|
};
|
|
13
|
-
export type Hash8 =
|
|
14
|
-
export type Array16 =
|
|
15
|
-
import * as
|
|
13
|
+
export type Hash8 = array.Array8<number>;
|
|
14
|
+
export type Array16 = array.Array16<number>;
|
|
15
|
+
import * as array from '../../types/array/module.f.mjs';
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// @ts-self-types="./module.f.d.mts"
|
|
2
|
-
import * as
|
|
2
|
+
import * as array from '../../types/array/module.f.mjs';
|
|
3
3
|
/**
|
|
4
4
|
* @typedef {{
|
|
5
5
|
* readonly f: (i: number) => number
|
|
6
6
|
* readonly length: number
|
|
7
7
|
* }} HashInput
|
|
8
8
|
*/
|
|
9
|
-
/** @typedef {
|
|
10
|
-
/** @typedef {
|
|
9
|
+
/** @typedef {array.Array8<number>} Hash8 */
|
|
10
|
+
/** @typedef {array.Array16<number>} Array16 */
|
|
11
11
|
/** @type {(input: number) => (pos: number) => number} */
|
|
12
12
|
const appendOneWithZeros = input => pos => (input >> pos << pos) | (1 << pos);
|
|
13
13
|
/** @type {(input: number) => (pos: number) => number} */
|
|
@@ -63,7 +63,7 @@ const smallSigma = a => b => c => {
|
|
|
63
63
|
};
|
|
64
64
|
const smallSigma0 = smallSigma(7)(18)(3);
|
|
65
65
|
const smallSigma1 = smallSigma(17)(19)(10);
|
|
66
|
-
/** @type {(a:
|
|
66
|
+
/** @type {(a: array.Array4<number>) => number} */
|
|
67
67
|
const wi = ([a0, a1, a2, a3]) => (smallSigma1(a0) + a1 + smallSigma0(a2) + a3) | 0;
|
|
68
68
|
/** @type {(w: Array16) => Array16} */
|
|
69
69
|
const nextW = ([w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, wA, wB, wC, wD, wE, wF]) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as _ from './module.f.mjs';
|
|
2
|
-
import * as json from '
|
|
3
|
-
import * as o from '
|
|
2
|
+
import * as json from '../../json/module.f.mjs';
|
|
3
|
+
import * as o from '../../types/object/module.f.mjs';
|
|
4
4
|
const { sort } = o;
|
|
5
5
|
/** @type {(a: number) => number} */
|
|
6
6
|
const toU32 = x => (x + 0x1_0000_0000) % 0x1_0000_0000;
|