functionalscript 0.6.9 → 0.6.10
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/README.md +2 -2
- package/bnf/data/module.f.d.ts +2 -0
- package/bnf/data/test.f.d.ts +1 -0
- package/bnf/data/test.f.js +11 -0
- package/bnf/module.f.d.ts +8 -0
- package/bnf/module.f.js +1 -1
- package/bnf/testlib.f.js +1 -0
- package/dev/module.f.d.ts +1 -1
- package/dev/module.f.js +7 -4
- package/djs/module.f.js +2 -1
- package/djs/parser/module.f.d.ts +7 -2
- package/djs/parser/module.f.js +80 -52
- package/djs/parser/test.f.d.ts +1 -0
- package/djs/parser/test.f.js +104 -76
- package/djs/tokenizer/module.f.d.ts +6 -2
- package/djs/tokenizer/module.f.js +12 -7
- package/djs/tokenizer/test.f.d.ts +1 -0
- package/djs/tokenizer/test.f.js +103 -87
- package/djs/transpiler/module.f.d.ts +3 -2
- package/djs/transpiler/module.f.js +3 -3
- package/djs/transpiler/test.f.js +2 -2
- package/io/module.js +5 -1
- package/issues/31-json.f.d.ts +1 -1
- package/issues/31-json.f.js +1 -1
- package/issues/demo/data/data.f.js +12 -0
- package/issues/demo/data/shared.f.js +3 -0
- package/issues/demo/fs/app.js +4 -0
- package/issues/demo/fs/math.f.js +4 -0
- package/issues/demo/test/test.f.js +13 -0
- package/js/tokenizer/module.f.d.ts +14 -2
- package/js/tokenizer/module.f.js +30 -17
- package/js/tokenizer/test.f.d.ts +1 -0
- package/js/tokenizer/test.f.js +159 -149
- package/json/parser/module.f.js +18 -9
- package/json/parser/test.f.js +16 -16
- package/json/tokenizer/module.f.d.ts +1 -1
- package/json/tokenizer/module.f.js +7 -6
- package/json/tokenizer/test.f.js +68 -68
- package/package.json +9 -11
|
@@ -3,13 +3,14 @@ import { type Result } from '../../types/result/module.f.ts';
|
|
|
3
3
|
import { type List } from '../../types/list/module.f.ts';
|
|
4
4
|
import { type OrderedMap } from '../../types/ordered_map/module.f.ts';
|
|
5
5
|
import type { Fs } from '../../io/module.f.ts';
|
|
6
|
+
import { type ParseError } from '../parser/module.f.ts';
|
|
6
7
|
export type ParseContext = {
|
|
7
8
|
readonly fs: Fs;
|
|
8
9
|
readonly complete: OrderedMap<djsResult>;
|
|
9
10
|
readonly stack: List<string>;
|
|
10
|
-
readonly error:
|
|
11
|
+
readonly error: ParseError | null;
|
|
11
12
|
};
|
|
12
13
|
export type djsResult = {
|
|
13
14
|
djs: djs.Unknown;
|
|
14
15
|
};
|
|
15
|
-
export declare const transpile: (fs: Fs) => (path: string) => Result<djs.Unknown,
|
|
16
|
+
export declare const transpile: (fs: Fs) => (path: string) => Result<djs.Unknown, ParseError>;
|
|
@@ -30,9 +30,9 @@ const transpileWithImports = path => parseModuleResult => context => {
|
|
|
30
30
|
const parseModule = path => context => {
|
|
31
31
|
const content = context.fs.readFileSync(path, 'utf8');
|
|
32
32
|
if (content === null) {
|
|
33
|
-
return error('file not found');
|
|
33
|
+
return error({ message: 'file not found', metadata: null });
|
|
34
34
|
}
|
|
35
|
-
const tokens = tokenize(stringToList(content));
|
|
35
|
+
const tokens = tokenize(stringToList(content))(path);
|
|
36
36
|
return parseFromTokens(tokens);
|
|
37
37
|
};
|
|
38
38
|
const foldNextModuleOp = path => context => {
|
|
@@ -40,7 +40,7 @@ const foldNextModuleOp = path => context => {
|
|
|
40
40
|
return context;
|
|
41
41
|
}
|
|
42
42
|
if (includes(path)(context.stack)) {
|
|
43
|
-
return { ...context, error: 'circular dependency' };
|
|
43
|
+
return { ...context, error: { message: 'circular dependency', metadata: null } };
|
|
44
44
|
}
|
|
45
45
|
if (at(path)(context.complete) !== null) {
|
|
46
46
|
return context;
|
package/djs/transpiler/test.f.js
CHANGED
|
@@ -54,7 +54,7 @@ export default {
|
|
|
54
54
|
if (result[0] !== 'error') {
|
|
55
55
|
throw result;
|
|
56
56
|
}
|
|
57
|
-
if (result[1] !== 'file not found') {
|
|
57
|
+
if (result[1].message !== 'file not found') {
|
|
58
58
|
throw result;
|
|
59
59
|
}
|
|
60
60
|
},
|
|
@@ -67,7 +67,7 @@ export default {
|
|
|
67
67
|
if (result[0] !== 'error') {
|
|
68
68
|
throw result;
|
|
69
69
|
}
|
|
70
|
-
if (result[1] !== 'circular dependency') {
|
|
70
|
+
if (result[1].message !== 'circular dependency') {
|
|
71
71
|
throw result;
|
|
72
72
|
}
|
|
73
73
|
},
|
package/io/module.js
CHANGED
|
@@ -15,7 +15,11 @@ export const io = {
|
|
|
15
15
|
console,
|
|
16
16
|
fs,
|
|
17
17
|
process,
|
|
18
|
-
asyncImport: (v) =>
|
|
18
|
+
asyncImport: (v) => {
|
|
19
|
+
const s0 = v.includes(':') || v.startsWith('/') ? v : concat(process.cwd())(v);
|
|
20
|
+
const s1 = s0.startsWith(prefix) ? s0 : `${prefix}${s0}`;
|
|
21
|
+
return import(__rewriteRelativeImportExtension(s1));
|
|
22
|
+
},
|
|
19
23
|
performance,
|
|
20
24
|
fetch,
|
|
21
25
|
tryCatch: f => {
|
package/issues/31-json.f.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
export {};
|
package/issues/31-json.f.js
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const arrayOfTests = [
|
|
2
|
+
() => {
|
|
3
|
+
if (2 + 2 !== 4) throw "It's the end of the world as we know it!"
|
|
4
|
+
},
|
|
5
|
+
() => {
|
|
6
|
+
if (2n + 2n !== 4n) throw "It's the end of the world as we know it!"
|
|
7
|
+
}
|
|
8
|
+
]
|
|
9
|
+
|
|
10
|
+
export default {
|
|
11
|
+
arrayOfTests,
|
|
12
|
+
generatingTests: () => arrayOfTests,
|
|
13
|
+
}
|
|
@@ -79,8 +79,20 @@ export type CommentToken = {
|
|
|
79
79
|
readonly kind: '//' | '/*';
|
|
80
80
|
readonly value: string;
|
|
81
81
|
};
|
|
82
|
-
export type
|
|
82
|
+
export type EofToken = {
|
|
83
|
+
readonly kind: 'eof';
|
|
84
|
+
};
|
|
85
|
+
export type JsToken = KeywordToken | TrueToken | FalseToken | NullToken | WhitespaceToken | NewLineToken | StringToken | NumberToken | ErrorToken | IdToken | BigIntToken | UndefinedToken | OperatorToken | CommentToken | EofToken;
|
|
86
|
+
export type TokenMetadata = {
|
|
87
|
+
readonly path: string;
|
|
88
|
+
readonly line: number;
|
|
89
|
+
readonly column: number;
|
|
90
|
+
};
|
|
91
|
+
export type JsTokenWithMetadata = {
|
|
92
|
+
readonly token: JsToken;
|
|
93
|
+
readonly metadata: TokenMetadata;
|
|
94
|
+
};
|
|
83
95
|
type ErrorMessage = '" are missing' | 'unescaped character' | 'invalid hex value' | 'unexpected character' | 'invalid number' | 'invalid token' | '*\/ expected' | 'unterminated string literal' | 'eof';
|
|
84
96
|
export declare const isKeywordToken: (token: JsToken) => boolean;
|
|
85
|
-
export declare const tokenize: (input: list.List<number>) => list.List<
|
|
97
|
+
export declare const tokenize: (input: list.List<number>) => (path: string) => list.List<JsTokenWithMetadata>;
|
|
86
98
|
export {};
|
package/js/tokenizer/module.f.js
CHANGED
|
@@ -6,7 +6,7 @@ import * as map from "../../types/ordered_map/module.f.js";
|
|
|
6
6
|
const { at } = map;
|
|
7
7
|
import * as _range from "../../types/range/module.f.js";
|
|
8
8
|
const { one } = _range;
|
|
9
|
-
const { empty, stateScan, flat, toArray, reduce: listReduce, scan } = list;
|
|
9
|
+
const { empty, stateScan, flat, toArray, reduce: listReduce, scan, map: listMap } = list;
|
|
10
10
|
const { fromCharCode } = String;
|
|
11
11
|
import * as ascii from "../../text/ascii/module.f.js";
|
|
12
12
|
const { range } = ascii;
|
|
@@ -449,7 +449,7 @@ const parseWhitespaceStateOp = create(parseWhitespaceDefault)([
|
|
|
449
449
|
rangeSetFunc(rangeSetWhiteSpace)(state => () => [empty, state]),
|
|
450
450
|
rangeSetFunc(rangeSetNewLine)(() => () => [empty, { kind: 'nl' }])
|
|
451
451
|
]);
|
|
452
|
-
const parseNewLineDefault =
|
|
452
|
+
const parseNewLineDefault = _ => input => {
|
|
453
453
|
const next = tokenizeOp({ kind: 'initial' })(input);
|
|
454
454
|
return [{ first: { kind: 'nl' }, tail: next[0] }, next[1]];
|
|
455
455
|
};
|
|
@@ -478,30 +478,43 @@ const tokenizeCharCodeOp = state => {
|
|
|
478
478
|
};
|
|
479
479
|
const tokenizeEofOp = state => {
|
|
480
480
|
switch (state.kind) {
|
|
481
|
-
case 'initial': return [
|
|
482
|
-
case 'id': return [[idToToken(state.value)], { kind: 'eof' }];
|
|
481
|
+
case 'initial': return [[{ kind: 'eof' }], { kind: 'eof' }];
|
|
482
|
+
case 'id': return [[idToToken(state.value), { kind: 'eof' }], { kind: 'eof' }];
|
|
483
483
|
case 'string':
|
|
484
484
|
case 'escapeChar':
|
|
485
|
-
case 'unicodeChar': return [[{ kind: 'error', message: '" are missing' }], { kind: 'eof' }];
|
|
486
|
-
case 'invalidNumber': return [[{ kind: 'error', message: 'invalid number' }], { kind: 'eof' }];
|
|
485
|
+
case 'unicodeChar': return [[{ kind: 'error', message: '" are missing' }, { kind: 'eof' }], { kind: 'eof' }];
|
|
486
|
+
case 'invalidNumber': return [[{ kind: 'error', message: 'invalid number' }, { kind: 'eof' }], { kind: 'eof' }];
|
|
487
487
|
case 'number':
|
|
488
488
|
switch (state.numberKind) {
|
|
489
489
|
case '.':
|
|
490
490
|
case 'e':
|
|
491
491
|
case 'e+':
|
|
492
|
-
case 'e-': return [[{ kind: 'error', message: 'invalid number' }], { kind: 'eof', }];
|
|
492
|
+
case 'e-': return [[{ kind: 'error', message: 'invalid number' }, { kind: 'eof' }], { kind: 'eof', }];
|
|
493
493
|
}
|
|
494
|
-
return [[bufferToNumberToken(state)], { kind: 'eof' }];
|
|
495
|
-
case 'op': return [[getOperatorToken(state.value)], { kind: 'eof' }];
|
|
496
|
-
case '//': return [[{ kind: '//', value: state.value }], { kind: 'eof' }];
|
|
494
|
+
return [[bufferToNumberToken(state), { kind: 'eof' }], { kind: 'eof' }];
|
|
495
|
+
case 'op': return [[getOperatorToken(state.value), { kind: 'eof' }], { kind: 'eof' }];
|
|
496
|
+
case '//': return [[{ kind: '//', value: state.value }, { kind: 'eof' }], { kind: 'eof' }];
|
|
497
497
|
case '/*':
|
|
498
|
-
case '/**': return [[{ kind: 'error', message: '*/ expected' }], { kind: 'eof', }];
|
|
499
|
-
case 'ws': return [[{ kind: 'ws' }], { kind: 'eof' }];
|
|
500
|
-
case 'nl': return [[{ kind: 'nl' }], { kind: 'eof' }];
|
|
501
|
-
case 'eof': return [[{ kind: 'error', message: 'eof' }], state];
|
|
498
|
+
case '/**': return [[{ kind: 'error', message: '*/ expected' }, { kind: 'eof' }], { kind: 'eof', }];
|
|
499
|
+
case 'ws': return [[{ kind: 'ws' }, { kind: 'eof' }], { kind: 'eof' }];
|
|
500
|
+
case 'nl': return [[{ kind: 'nl' }, { kind: 'eof' }], { kind: 'eof' }];
|
|
501
|
+
case 'eof': return [[{ kind: 'error', message: 'eof' }, { kind: 'eof' }], state];
|
|
502
502
|
}
|
|
503
503
|
};
|
|
504
504
|
const tokenizeOp = state => input => input === null ? tokenizeEofOp(state) : tokenizeCharCodeOp(state)(input);
|
|
505
|
-
const
|
|
506
|
-
const
|
|
507
|
-
|
|
505
|
+
const mapTokenWithMetadata = metadata => token => { return { token, metadata }; };
|
|
506
|
+
const tokenizeWithPositionOp = ({ state, metadata }) => input => {
|
|
507
|
+
if (input == null) {
|
|
508
|
+
const newState = tokenizeEofOp(state);
|
|
509
|
+
return [listMap(mapTokenWithMetadata(metadata))(newState[0]), { state: newState[1], metadata }];
|
|
510
|
+
}
|
|
511
|
+
const newState = tokenizeCharCodeOp(state)(input);
|
|
512
|
+
const isNewLine = input == lf;
|
|
513
|
+
const newMetadata = { path: metadata.path, line: isNewLine ? metadata.line + 1 : metadata.line, column: isNewLine ? 1 : metadata.column + 1 };
|
|
514
|
+
return [listMap(mapTokenWithMetadata(metadata))(newState[0]), { state: newState[1], metadata: newMetadata }];
|
|
515
|
+
};
|
|
516
|
+
const scanTokenize = stateScan(tokenizeWithPositionOp);
|
|
517
|
+
export const tokenize = input => path => {
|
|
518
|
+
const scan = scanTokenize({ state: { kind: 'initial' }, metadata: { path, line: 1, column: 1 } });
|
|
519
|
+
return flat(scan(flat([input, [null]])));
|
|
520
|
+
};
|