functionalscript 0.4.3 → 0.5.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.
Files changed (62) hide show
  1. package/README.md +1 -1
  2. package/bnf/data/module.f.d.ts +12 -0
  3. package/bnf/data/module.f.js +85 -0
  4. package/bnf/data/test.f.d.ts +4 -0
  5. package/bnf/data/test.f.js +8 -0
  6. package/bnf/module.f.d.ts +55 -0
  7. package/bnf/module.f.js +98 -0
  8. package/bnf/test.f.d.ts +4 -0
  9. package/bnf/test.f.js +7 -0
  10. package/bnf/testlib.f.d.ts +3 -0
  11. package/bnf/{tag/test.f.js → testlib.f.js} +48 -44
  12. package/crypto/secp/module.f.d.ts +8 -0
  13. package/crypto/secp/module.f.js +30 -0
  14. package/crypto/secp/test.f.d.ts +3 -0
  15. package/crypto/secp/test.f.js +67 -3
  16. package/djs/ast/module.f.d.ts +10 -0
  17. package/djs/ast/module.f.js +52 -0
  18. package/djs/ast/test.f.d.ts +8 -0
  19. package/djs/ast/test.f.js +41 -0
  20. package/djs/module.f.d.ts +7 -15
  21. package/djs/module.f.js +23 -60
  22. package/djs/parser/module.f.d.ts +9 -9
  23. package/djs/parser/module.f.js +7 -8
  24. package/djs/parser/test.f.js +97 -97
  25. package/djs/serializer/module.f.d.ts +8 -4
  26. package/djs/serializer/module.f.js +9 -27
  27. package/djs/{test.f.d.ts → serializer/test.f.d.ts} +3 -3
  28. package/djs/{test.f.js → serializer/test.f.js} +13 -13
  29. package/djs/tokenizer/test.f.js +2 -2
  30. package/djs/transpiler/module.f.d.ts +15 -0
  31. package/djs/transpiler/module.f.js +58 -0
  32. package/djs/transpiler/test.f.d.ts +8 -0
  33. package/djs/transpiler/test.f.js +74 -0
  34. package/fsc.js +4 -0
  35. package/io/module.f.d.ts +17 -0
  36. package/io/node-io.js +7 -0
  37. package/io/virtual-io.f.d.ts +3 -0
  38. package/io/virtual-io.f.js +14 -0
  39. package/js/tokenizer/test.f.js +2 -2
  40. package/json/module.f.d.ts +2 -1
  41. package/json/tokenizer/test.f.js +2 -2
  42. package/nanvm-lib/tests/test.f.js +4 -4
  43. package/package.json +16 -9
  44. package/path/module.f.d.ts +2 -0
  45. package/path/module.f.js +31 -0
  46. package/path/test.f.d.ts +5 -0
  47. package/path/test.f.js +49 -0
  48. package/text/sgr/module.f.d.ts +19 -1
  49. package/text/sgr/module.f.js +26 -1
  50. package/text/sgr/test.f.d.ts +2 -0
  51. package/text/sgr/test.f.js +8 -0
  52. package/text/utf16/module.f.d.ts +116 -0
  53. package/text/utf16/module.f.js +285 -0
  54. package/text/utf16/test.f.d.ts +4 -0
  55. package/text/utf16/test.f.js +28 -0
  56. package/types/monoid/module.f.d.ts +3 -1
  57. package/types/monoid/module.f.js +2 -0
  58. package/types/object/module.f.d.ts +18 -0
  59. package/types/object/module.f.js +1 -1
  60. package/bnf/tag/module.f.d.ts +0 -30
  61. package/bnf/tag/module.f.js +0 -37
  62. /package/{bnf/tag/test.f.d.ts → io/module.f.js} +0 -0
@@ -1,9 +1,13 @@
1
1
  import * as list from '../../types/list/module.f.ts';
2
2
  import type * as O from '../../types/object/module.f.ts';
3
- import type * as DjsParser from '../parser/module.f.ts';
4
- export declare const undefinedSerialize: string[];
5
- type Entry = O.Entry<DjsParser.DjsConst>;
3
+ import type { Unknown } from '../module.f.ts';
4
+ type Entry = O.Entry<Unknown>;
6
5
  type Entries = list.List<Entry>;
7
6
  type MapEntries = (entries: Entries) => Entries;
8
- export declare const djsModuleStringify: (mapEntries: MapEntries) => (djsModule: DjsParser.DjsModule) => string;
7
+ export declare const serialize: (mapEntries: MapEntries) => (value: Unknown) => list.List<string>;
8
+ /**
9
+ * The standard `JSON.stringify` rules determined by
10
+ * https://262.ecma-international.org/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys
11
+ */
12
+ export declare const stringify: (mapEntries: MapEntries) => (value: Unknown) => string;
9
13
  export {};
@@ -1,5 +1,5 @@
1
1
  import * as list from "../../types/list/module.f.js";
2
- const { flat, map, entries: listEntries, concat: listConcat, flatMap } = list;
2
+ const { flat, map } = list;
3
3
  import * as string from "../../types/string/module.f.js";
4
4
  const { concat } = string;
5
5
  import * as f from "../../types/function/module.f.js";
@@ -10,8 +10,8 @@ const { serialize: bigintSerialize } = bi;
10
10
  import * as j from "../../json/serializer/module.f.js";
11
11
  const { objectWrap, arrayWrap, stringSerialize, numberSerialize, nullSerialize, boolSerialize } = j;
12
12
  const colon = [':'];
13
- export const undefinedSerialize = ['undefined'];
14
- const djsConstSerialize = sort => {
13
+ const undefinedSerialize = ['undefined'];
14
+ export const serialize = sort => {
15
15
  const propertySerialize = ([k, v]) => flat([
16
16
  stringSerialize(k),
17
17
  colon,
@@ -45,17 +45,7 @@ const djsConstSerialize = sort => {
45
45
  return undefinedSerialize;
46
46
  }
47
47
  if (value instanceof Array) {
48
- switch (value[0]) {
49
- case 'aref': {
50
- return [`a${value[1]}`];
51
- }
52
- case 'cref': {
53
- return [`c${value[1]}`];
54
- }
55
- case 'array': {
56
- return arraySerialize(value[1]);
57
- }
58
- }
48
+ return arraySerialize(value);
59
49
  }
60
50
  return objectSerialize(value);
61
51
  }
@@ -64,16 +54,8 @@ const djsConstSerialize = sort => {
64
54
  const arraySerialize = compose(map(f))(arrayWrap);
65
55
  return f;
66
56
  };
67
- export const djsModuleStringify = sort => djsModule => {
68
- const importEntries = listEntries(djsModule[0]);
69
- const importSerialize = entry => flat([['import a'], numberSerialize(entry[0]), [' from "', entry[1], '"\n']]);
70
- const len = djsModule[1].length;
71
- const constEntries = listEntries(djsModule[1]);
72
- const moduleEntrySerialize = entry => {
73
- if (entry[0] === len - 1) {
74
- return listConcat(['export default '])(djsConstSerialize(sort)(entry[1]));
75
- }
76
- return flat([['const c'], numberSerialize(entry[0]), [' = '], djsConstSerialize(sort)(entry[1]), ['\n']]);
77
- };
78
- return concat(listConcat(flatMap(importSerialize)(importEntries))(flatMap(moduleEntrySerialize)(constEntries)));
79
- };
57
+ /**
58
+ * The standard `JSON.stringify` rules determined by
59
+ * https://262.ecma-international.org/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys
60
+ */
61
+ export const stringify = sort => compose(serialize(sort))(concat);
@@ -2,11 +2,11 @@ declare const _default: {
2
2
  stringify: ({
3
3
  sort: () => void;
4
4
  identity: () => void;
5
- stringify?: undefined;
5
+ stringify?: never;
6
6
  } | {
7
7
  stringify: () => void;
8
- sort?: undefined;
9
- identity?: undefined;
8
+ sort?: never;
9
+ identity?: never;
10
10
  })[];
11
11
  };
12
12
  export default _default;
@@ -1,21 +1,21 @@
1
- import * as json from "../json/module.f.js";
2
- import * as list from "../types/object/module.f.js";
1
+ import * as json from "../../json/module.f.js";
2
+ import * as list from "../../types/object/module.f.js";
3
3
  const { sort } = list;
4
- import * as f from "../types/function/module.f.js";
4
+ import * as f from "../../types/function/module.f.js";
5
5
  const { identity } = f;
6
- import * as djs from "./module.f.js";
6
+ import * as serializer from "./module.f.js";
7
7
  export default {
8
8
  stringify: [
9
9
  {
10
10
  sort: () => {
11
11
  const r = json.setProperty("Hello")(['a'])({});
12
- const x = djs.stringify(sort)(r);
12
+ const x = serializer.stringify(sort)(r);
13
13
  if (x !== '{"a":"Hello"}') {
14
14
  throw x;
15
15
  }
16
16
  },
17
17
  identity: () => {
18
- const x = djs.stringify(identity)(json.setProperty("Hello")(['a'])({}));
18
+ const x = serializer.stringify(identity)(json.setProperty("Hello")(['a'])({}));
19
19
  if (x !== '{"a":"Hello"}') {
20
20
  throw x;
21
21
  }
@@ -23,13 +23,13 @@ export default {
23
23
  },
24
24
  {
25
25
  sort: () => {
26
- const x = djs.stringify(sort)(json.setProperty("Hello")(['a'])({ c: [], b: 12 }));
26
+ const x = serializer.stringify(sort)(json.setProperty("Hello")(['a'])({ c: [], b: 12 }));
27
27
  if (x !== '{"a":"Hello","b":12,"c":[]}') {
28
28
  throw x;
29
29
  }
30
30
  },
31
31
  identity: () => {
32
- const x = djs.stringify(identity)(json.setProperty("Hello")(['a'])({ c: [], b: 12 }));
32
+ const x = serializer.stringify(identity)(json.setProperty("Hello")(['a'])({ c: [], b: 12 }));
33
33
  if (x !== '{"c":[],"b":12,"a":"Hello"}') {
34
34
  throw x;
35
35
  }
@@ -39,7 +39,7 @@ export default {
39
39
  sort: () => {
40
40
  const _0 = { a: { y: [24] }, c: [], b: 12 };
41
41
  const _1 = json.setProperty("Hello")(['a', 'x'])(_0);
42
- const _2 = djs.stringify(sort)(_1);
42
+ const _2 = serializer.stringify(sort)(_1);
43
43
  if (_2 !== '{"a":{"x":"Hello","y":[24]},"b":12,"c":[]}') {
44
44
  throw _2;
45
45
  }
@@ -47,7 +47,7 @@ export default {
47
47
  identity: () => {
48
48
  const _0 = { a: { y: [24] }, c: [], b: 12 };
49
49
  const _1 = json.setProperty("Hello")(['a', 'x'])(_0);
50
- const _2 = djs.stringify(identity)(_1);
50
+ const _2 = serializer.stringify(identity)(_1);
51
51
  if (_2 !== '{"a":{"y":[24],"x":"Hello"},"c":[],"b":12}') {
52
52
  throw _2;
53
53
  }
@@ -56,7 +56,7 @@ export default {
56
56
  {
57
57
  stringify: () => {
58
58
  const bi = 1234567890n;
59
- const result = djs.stringify(sort)(bi);
59
+ const result = serializer.stringify(sort)(bi);
60
60
  if (result !== '1234567890n') {
61
61
  throw result;
62
62
  }
@@ -65,7 +65,7 @@ export default {
65
65
  {
66
66
  stringify: () => {
67
67
  const arr = [0n, 1, 2n];
68
- const result = djs.stringify(sort)(arr);
68
+ const result = serializer.stringify(sort)(arr);
69
69
  if (result !== '[0n,1,2n]') {
70
70
  throw result;
71
71
  }
@@ -74,7 +74,7 @@ export default {
74
74
  {
75
75
  stringify: () => {
76
76
  const obj = { "a": 0n, "b": 1, "c": 2n };
77
- const result = djs.stringify(sort)(obj);
77
+ const result = serializer.stringify(sort)(obj);
78
78
  if (result !== '{"a":0n,"b":1,"c":2n}') {
79
79
  throw result;
80
80
  }
@@ -1,12 +1,12 @@
1
1
  import * as tokenizer from "./module.f.js";
2
2
  import * as list from "../../types/list/module.f.js";
3
3
  const { toArray } = list;
4
- import * as djs from "../module.f.js";
4
+ import * as serializer from "../serializer/module.f.js";
5
5
  import * as o from "../../types/object/module.f.js";
6
6
  const { sort } = o;
7
7
  import * as encoding from "../../text/utf16/module.f.js";
8
8
  const tokenizeString = s => toArray(tokenizer.tokenize(encoding.stringToList(s)));
9
- const stringify = djs.stringify(sort);
9
+ const stringify = serializer.stringify(sort);
10
10
  export default {
11
11
  djs: [
12
12
  () => {
@@ -0,0 +1,15 @@
1
+ import type * as djs from '../module.f.ts';
2
+ import { type Result } from '../../types/result/module.f.ts';
3
+ import { type List } from '../../types/list/module.f.ts';
4
+ import { type Map } from '../../types/map/module.f.ts';
5
+ import type { Fs } from '../../io/module.f.ts';
6
+ export type ParseContext = {
7
+ readonly fs: Fs;
8
+ readonly complete: Map<djsResult>;
9
+ readonly stack: List<string>;
10
+ readonly error: string | null;
11
+ };
12
+ export type djsResult = {
13
+ djs: djs.Unknown;
14
+ };
15
+ export declare const transpile: (fs: Fs) => (path: string) => Result<djs.Unknown, string>;
@@ -0,0 +1,58 @@
1
+ import { error, ok } from "../../types/result/module.f.js";
2
+ import { fold, drop, map as listMap, toArray, includes } from "../../types/list/module.f.js";
3
+ import { tokenize } from "../tokenizer/module.f.js";
4
+ import { setReplace, at } from "../../types/map/module.f.js";
5
+ import { stringToList } from "../../text/utf16/module.f.js";
6
+ import { concat as pathConcat } from "../../path/module.f.js";
7
+ import { parseFromTokens } from "../parser/module.f.js";
8
+ import { run } from "../ast/module.f.js";
9
+ const mapDjs = context => path => {
10
+ const res = at(path)(context.complete);
11
+ if (res === null) {
12
+ throw 'unexpected behaviour';
13
+ }
14
+ return res.djs;
15
+ };
16
+ const transpileWithImports = path => parseModuleResult => context => {
17
+ if (parseModuleResult[0] === 'ok') {
18
+ const dir = pathConcat(path)('..');
19
+ const pathsCombine = listMap(pathConcat(dir))(parseModuleResult[1][0]);
20
+ const contextWithImports = fold(foldNextModuleOp)({ ...context, stack: { first: path, tail: context.stack } })(pathsCombine);
21
+ if (contextWithImports.error !== null) {
22
+ return contextWithImports;
23
+ }
24
+ const args = toArray(listMap(mapDjs(contextWithImports))(pathsCombine));
25
+ const djs = { djs: run(parseModuleResult[1][1])(args) };
26
+ return { ...contextWithImports, stack: drop(1)(contextWithImports.stack), complete: setReplace(path)(djs)(contextWithImports.complete) };
27
+ }
28
+ return { ...context, error: parseModuleResult[1] };
29
+ };
30
+ const parseModule = path => context => {
31
+ const content = context.fs.readFileSync(path, 'utf8');
32
+ if (content === null) {
33
+ return error('file not found');
34
+ }
35
+ const tokens = tokenize(stringToList(content));
36
+ return parseFromTokens(tokens);
37
+ };
38
+ const foldNextModuleOp = path => context => {
39
+ if (context.error !== null) {
40
+ return context;
41
+ }
42
+ if (includes(path)(context.stack)) {
43
+ return { ...context, error: 'circular dependency' };
44
+ }
45
+ if (at(path)(context.complete) !== null) {
46
+ return context;
47
+ }
48
+ const parseModuleResult = parseModule(path)(context);
49
+ return transpileWithImports(path)(parseModuleResult)(context);
50
+ };
51
+ export const transpile = fs => path => {
52
+ const context = foldNextModuleOp(path)({ fs, stack: null, complete: null, error: null });
53
+ if (context.error !== null) {
54
+ return error(context.error);
55
+ }
56
+ const result = at(path)(context.complete)?.djs;
57
+ return ok(result);
58
+ };
@@ -0,0 +1,8 @@
1
+ declare const _default: {
2
+ parse: () => void;
3
+ parseWithSubModule: () => void;
4
+ parseWithSubModules: () => void;
5
+ parseWithFileNotFoundError: () => void;
6
+ parseWithCycleError: () => void;
7
+ };
8
+ export default _default;
@@ -0,0 +1,74 @@
1
+ import { sort } from "../../types/object/module.f.js";
2
+ import { setReplace } from "../../types/map/module.f.js";
3
+ import { transpile } from "./module.f.js";
4
+ import { stringify } from "../serializer/module.f.js";
5
+ import { createVirtualIo } from "../../io/virtual-io.f.js";
6
+ const virtualFs = map => {
7
+ return createVirtualIo(map).fs;
8
+ };
9
+ export default {
10
+ parse: () => {
11
+ const map = setReplace('a')('export default 1')(null);
12
+ const fs = virtualFs(map);
13
+ const result = transpile(fs)('a');
14
+ if (result[0] === 'error') {
15
+ throw result[1];
16
+ }
17
+ const s = stringify(sort)(result[1]);
18
+ if (s !== '1') {
19
+ throw s;
20
+ }
21
+ },
22
+ parseWithSubModule: () => {
23
+ const map = setReplace('a/b')('import c from "c"\nexport default c')(null);
24
+ const map2 = setReplace('a/c')('export default 2')(map);
25
+ const fs = virtualFs(map2);
26
+ const result = transpile(fs)('a/b');
27
+ if (result[0] === 'error') {
28
+ throw result[1];
29
+ }
30
+ const s = stringify(sort)(result[1]);
31
+ if (s !== '2') {
32
+ throw s;
33
+ }
34
+ },
35
+ parseWithSubModules: () => {
36
+ const map = setReplace('a')('import b from "b"\nimport c from "c"\nexport default [b,c,b]')(null);
37
+ const map2 = setReplace('b')('import d from "d"\nexport default [0,d]')(map);
38
+ const map3 = setReplace('c')('import d from "d"\nexport default [1,d]')(map2);
39
+ const map4 = setReplace('d')('export default 2')(map3);
40
+ const fs = virtualFs(map4);
41
+ const result = transpile(fs)('a');
42
+ if (result[0] === 'error') {
43
+ throw result[1];
44
+ }
45
+ const s = stringify(sort)(result[1]);
46
+ if (s !== '[[0,2],[1,2],[0,2]]') {
47
+ throw s;
48
+ }
49
+ },
50
+ parseWithFileNotFoundError: () => {
51
+ const map = setReplace('a')('import b from "b"\nexport default b')(null);
52
+ const fs = virtualFs(map);
53
+ const result = transpile(fs)('a');
54
+ if (result[0] !== 'error') {
55
+ throw result;
56
+ }
57
+ if (result[1] !== 'file not found') {
58
+ throw result;
59
+ }
60
+ },
61
+ parseWithCycleError: () => {
62
+ const map = setReplace('a')('import b from "b"\nimport c from "c"\nexport default [b,c,b]')(null);
63
+ const map2 = setReplace('b')('import c from "c"\nexport default c')(map);
64
+ const map3 = setReplace('c')('import b from "b"\nexport default b')(map2);
65
+ const fs = virtualFs(map3);
66
+ const result = transpile(fs)('a');
67
+ if (result[0] !== 'error') {
68
+ throw result;
69
+ }
70
+ if (result[1] !== 'circular dependency') {
71
+ throw result;
72
+ }
73
+ },
74
+ };
package/fsc.js ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import io from "./io/node-io.js";
3
+ import { run } from "./djs/module.f.js";
4
+ run(io);
@@ -0,0 +1,17 @@
1
+ export type BufferEncoding = 'utf8';
2
+ export type Fs = {
3
+ readonly writeFileSync: (file: string, data: string) => void;
4
+ readonly readFileSync: (path: string, options: BufferEncoding) => string | null;
5
+ };
6
+ export type Console = {
7
+ readonly log: (...d: unknown[]) => void;
8
+ readonly error: (...d: unknown[]) => void;
9
+ };
10
+ export type Io = {
11
+ readonly console: Console;
12
+ readonly fs: Fs;
13
+ readonly process: Process;
14
+ };
15
+ export type Process = {
16
+ readonly argv: string[];
17
+ };
package/io/node-io.js ADDED
@@ -0,0 +1,7 @@
1
+ import fs from 'node:fs';
2
+ import process from "node:process";
3
+ export default {
4
+ console,
5
+ fs,
6
+ process
7
+ };
@@ -0,0 +1,3 @@
1
+ import type { Io } from './module.f.ts';
2
+ import { type Map } from '../types/map/module.f.ts';
3
+ export declare const createVirtualIo: (files: Map<string>) => Io;
@@ -0,0 +1,14 @@
1
+ import { at } from "../types/map/module.f.js";
2
+ export const createVirtualIo = (files) => ({
3
+ console: {
4
+ log: (..._d) => { },
5
+ error: (..._d) => { }
6
+ },
7
+ fs: {
8
+ writeFileSync: (_file, _data) => { },
9
+ readFileSync: (path, _options) => { return at(path)(files); }
10
+ },
11
+ process: {
12
+ argv: []
13
+ }
14
+ });
@@ -1,12 +1,12 @@
1
1
  import * as tokenizer from "./module.f.js";
2
2
  import * as list from "../../types/list/module.f.js";
3
3
  const { toArray } = list;
4
- import * as djs from "../../djs/module.f.js";
4
+ import * as serializer from "../../djs/serializer/module.f.js";
5
5
  import * as o from "../../types/object/module.f.js";
6
6
  const { sort } = o;
7
7
  import * as encoding from "../../text/utf16/module.f.js";
8
8
  const tokenizeString = s => toArray(tokenizer.tokenize(encoding.stringToList(s)));
9
- const stringify = djs.stringify(sort);
9
+ const stringify = serializer.stringify(sort);
10
10
  export default {
11
11
  djs: [
12
12
  () => {
@@ -4,7 +4,8 @@ type Object = {
4
4
  readonly [k in string]: Unknown;
5
5
  };
6
6
  type Array = readonly Unknown[];
7
- export type Unknown = Object | boolean | string | number | null | Array;
7
+ export type Primitive = boolean | string | number | null;
8
+ export type Unknown = Primitive | Object | Array;
8
9
  export declare const setProperty: (value: Unknown) => (path: list.List<string>) => (src: Unknown) => Unknown;
9
10
  export type Entry = object.Entry<Unknown>;
10
11
  type Entries = list.List<Entry>;
@@ -1,12 +1,12 @@
1
1
  import * as tokenizer from "./module.f.js";
2
2
  import * as list from "../../types/list/module.f.js";
3
3
  const { toArray } = list;
4
- import * as djs from "../../djs/module.f.js";
4
+ import * as serializer from "../../djs/serializer/module.f.js";
5
5
  import * as o from "../../types/object/module.f.js";
6
6
  const { sort } = o;
7
7
  import * as encoding from "../../text/utf16/module.f.js";
8
8
  const tokenizeString = s => toArray(tokenizer.tokenize(encoding.stringToList(s)));
9
- const stringify = djs.stringify(sort);
9
+ const stringify = serializer.stringify(sort);
10
10
  export default {
11
11
  json: [
12
12
  () => {
@@ -1,17 +1,17 @@
1
- const e = a => b => {
1
+ const e = (a) => (b) => {
2
2
  if (a === b) { }
3
3
  else {
4
4
  throw [a, '===', b];
5
5
  }
6
6
  };
7
- const n = a => b => {
7
+ const n = (a) => (b) => {
8
8
  if (a !== b) { }
9
9
  else {
10
10
  throw [a, '!==', b];
11
11
  }
12
12
  };
13
- const nan_res = op => n => {
14
- let result = op(n);
13
+ const nan_res = (op) => (n) => {
14
+ const result = op(n);
15
15
  if (!Number.isNaN(result)) {
16
16
  throw result;
17
17
  }
package/package.json CHANGED
@@ -1,23 +1,30 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.4.3",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
5
  "files": [
6
+ "fsc.js",
7
+ "io/node-io.js",
6
8
  "**/*.f.d.ts",
7
9
  "**/*.f.js"
8
10
  ],
9
11
  "description": "FunctionalScript is a functional subset of JavaScript",
10
12
  "scripts": {
11
13
  "tsc-emit": "tsc --NoEmit false",
14
+ "n": "node --frozen-intrinsics --trace-uncaught",
12
15
  "prepack": "npm run tsc-emit",
13
- "test20": "npm run prepack && node --trace-uncaught ./dev/test.js",
14
- "test22": "tsc && node --experimental-strip-types --trace-uncaught ./dev/test.ts",
15
- "test": "tsc && node --trace-uncaught ./dev/test.ts",
16
- "index": "node ./dev/index.ts",
17
- "version": "node ./nodejs/version/main.ts",
18
- "fsc": "node ./main.ts",
16
+ "git-clean": "git clean -xf",
17
+ "test20": "npm run tsc-emit && npm run n ./dev/test.js",
18
+ "test22": "tsc && npm run n -- --experimental-strip-types ./dev/test.ts",
19
+ "test": "tsc && npm run n ./dev/test.ts",
20
+ "index": "npm run n ./dev/index.ts",
21
+ "version": "npm run n ./nodejs/version/main.ts",
22
+ "fsc": "npm run n ./fsc.ts",
19
23
  "update": "npm run version && npm run index && npm install"
20
24
  },
25
+ "bin": {
26
+ "fsc": "fsc.js"
27
+ },
21
28
  "repository": {
22
29
  "type": "git",
23
30
  "url": "git+https://github.com/functionalscript/functionalscript.git"
@@ -38,7 +45,7 @@
38
45
  },
39
46
  "homepage": "https://github.com/functionalscript/functionalscript#readme",
40
47
  "devDependencies": {
41
- "@types/node": "^22.10.5",
42
- "typescript": "^5.7.3"
48
+ "@types/node": "^22.13.10",
49
+ "typescript": "^5.8.2"
43
50
  }
44
51
  }
@@ -0,0 +1,2 @@
1
+ export declare const normalize: (path: string) => string;
2
+ export declare const concat: (a: string) => (b: string) => string;
@@ -0,0 +1,31 @@
1
+ import { fold, last, take, length, concat as listConcat } from "../types/list/module.f.js";
2
+ import { join } from "../types/string/module.f.js";
3
+ import { concat as stringConcat } from "../types/string/module.f.js";
4
+ const foldNormalizeOp = input => state => {
5
+ switch (input) {
6
+ case '': {
7
+ return state;
8
+ }
9
+ case '..': {
10
+ switch (last(undefined)(state)) {
11
+ case undefined:
12
+ case '..': {
13
+ return listConcat(state)([input]);
14
+ }
15
+ }
16
+ return take(length(state) - 1)(state);
17
+ }
18
+ default: {
19
+ return listConcat(state)([input]);
20
+ }
21
+ }
22
+ };
23
+ export const normalize = path => {
24
+ const split = path.replaceAll('\\', '/').split('/');
25
+ const foldResult = fold(foldNormalizeOp)([])(split);
26
+ return join('/')(foldResult);
27
+ };
28
+ export const concat = a => b => {
29
+ const s = stringConcat([a, '/', b]);
30
+ return normalize(s);
31
+ };
@@ -0,0 +1,5 @@
1
+ declare const _default: {
2
+ normalize: (() => void)[];
3
+ concat: (() => void)[];
4
+ };
5
+ export default _default;
package/path/test.f.js ADDED
@@ -0,0 +1,49 @@
1
+ import { concat, normalize } from "./module.f.js";
2
+ export default {
3
+ normalize: [
4
+ () => {
5
+ const norm = normalize("dir/file.json");
6
+ if (norm !== "dir/file.json") {
7
+ throw norm;
8
+ }
9
+ },
10
+ () => {
11
+ const norm = normalize("dir//file.json");
12
+ if (norm !== "dir/file.json") {
13
+ throw norm;
14
+ }
15
+ },
16
+ () => {
17
+ const norm = normalize("../../dir/file.json");
18
+ if (norm !== "../../dir/file.json") {
19
+ throw norm;
20
+ }
21
+ },
22
+ () => {
23
+ const norm = normalize("../../dir/../file.json");
24
+ if (norm !== "../../file.json") {
25
+ throw norm;
26
+ }
27
+ },
28
+ ],
29
+ concat: [
30
+ () => {
31
+ const c = concat("a")("b");
32
+ if (c !== "a/b") {
33
+ throw c;
34
+ }
35
+ },
36
+ () => {
37
+ const c = concat("a///b/")("c");
38
+ if (c !== "a/b/c") {
39
+ throw c;
40
+ }
41
+ },
42
+ () => {
43
+ const c = concat("a/../b/..")("c");
44
+ if (c !== "c") {
45
+ throw c;
46
+ }
47
+ },
48
+ ]
49
+ };
@@ -1,8 +1,26 @@
1
+ export declare const backspace: string;
2
+ type End = 'm';
3
+ type Csi = (code: number | string) => string;
1
4
  /**
5
+ * Control Sequence Introducer (CSI) escape sequence.
6
+ * https://en.wikipedia.org/wiki/ANSI_escape_code#Control_Sequence_Introducer_commands
7
+ *
8
+ * @param end - The final character that indicates the type of sequence.
9
+ * @returns A function that takes a code (number or string) and returns the complete ANSI escape sequence.
10
+ */
11
+ export declare const csi: (end: End) => Csi;
12
+ /**
13
+ * Specialization of CSI for Select Graphic Rendition (SGR) sequences.
2
14
  * https://en.wikipedia.org/wiki/ANSI_escape_code#SGR
3
15
  */
4
- export declare const sgr: (c: number) => string;
16
+ export declare const sgr: Csi;
5
17
  export declare const reset: string;
6
18
  export declare const bold: string;
7
19
  export declare const fgRed: string;
8
20
  export declare const fgGreen: string;
21
+ export type Stdout = {
22
+ readonly write: (s: string) => void;
23
+ };
24
+ export type WriteText = (text: string) => WriteText;
25
+ export declare const createConsoleText: (stdout: Stdout) => WriteText;
26
+ export {};