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.
@@ -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: string | null;
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, string>;
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;
@@ -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) => import(__rewriteRelativeImportExtension(`${prefix}${concat(process.cwd())(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 => {
@@ -1 +1 @@
1
- type TerminalRange = readonly [number, number];
1
+ export {};
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  // JSON: https://www.json.org/json-en.html
3
2
  {
4
3
  // null, [0x09, 0x0A], 0x0D, 0x20
@@ -239,3 +238,4 @@
239
238
  };
240
239
  const _map = map;
241
240
  }
241
+ export {};
@@ -0,0 +1,12 @@
1
+ import shared from "./shared.f.js"
2
+
3
+ // comment
4
+ const s = "Hello, world!"
5
+
6
+ export default {
7
+ "a": shared,
8
+ "b": shared,
9
+ "s": s,
10
+ d: -24n,
11
+ x: undefined,
12
+ }
@@ -0,0 +1,3 @@
1
+ export default {
2
+ "name": "shared object"
3
+ }
@@ -0,0 +1,4 @@
1
+ import math from "./math.f.js"
2
+
3
+ const add2 = math.add(2)
4
+ console.log("5 ===", add2(3))
@@ -0,0 +1,4 @@
1
+ export default {
2
+ add: a => b => a + b,
3
+ mul: a => b => a * b,
4
+ }
@@ -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 JsToken = KeywordToken | TrueToken | FalseToken | NullToken | WhitespaceToken | NewLineToken | StringToken | NumberToken | ErrorToken | IdToken | BigIntToken | UndefinedToken | OperatorToken | CommentToken;
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<JsToken>;
97
+ export declare const tokenize: (input: list.List<number>) => (path: string) => list.List<JsTokenWithMetadata>;
86
98
  export {};
@@ -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 = state => input => {
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 [empty, { kind: 'eof' }];
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 scanTokenize = stateScan(tokenizeOp);
506
- const initial = scanTokenize({ kind: 'initial' });
507
- export const tokenize = (input) => flat(initial(flat([input, [null]])));
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
+ };
@@ -5,5 +5,6 @@ declare const _default: {
5
5
  id: (() => void)[];
6
6
  keywords: (() => void)[];
7
7
  comments: (() => void)[];
8
+ metadata: (() => void)[];
8
9
  };
9
10
  export default _default;