functionalscript
Advanced tools
Comparing version
import * as list from "../../types/object/module.f.js"; | ||
const { sort } = list; | ||
import * as shared from "./module.f.js"; | ||
import { stringify } from "../serializer/module.f.js"; | ||
import { stringify } from "../serializer-old/module.f.js"; | ||
export default { | ||
@@ -6,0 +6,0 @@ test: () => { |
@@ -16,2 +16,7 @@ import { transpile } from "./transpiler/module.f.js"; | ||
case 'ok': { | ||
if (outputFileName.endsWith('.json')) { | ||
const output = JSON.stringify(result[1]); | ||
fs.writeFileSync(outputFileName, output); | ||
break; | ||
} | ||
const output = stringifyUnknown(result[1]); | ||
@@ -18,0 +23,0 @@ fs.writeFileSync(outputFileName, output); |
@@ -19,3 +19,3 @@ import * as result from "../../types/result/module.f.js"; | ||
} | ||
return { state: 'error', message: 'unexpected token' }; | ||
return foldOp(token)({ ...state, state: 'exportValue', valueState: '', top: null, stack: null }); | ||
}; | ||
@@ -22,0 +22,0 @@ const parseNewLineRequiredOp = token => state => { |
@@ -5,2 +5,3 @@ declare const _default: { | ||
validWhiteSpaces: (() => void)[]; | ||
validJson: (() => void)[]; | ||
invalidModule: (() => void)[]; | ||
@@ -7,0 +8,0 @@ validWithConst: (() => void)[]; |
@@ -6,3 +6,3 @@ import * as parser from "./module.f.js"; | ||
import * as encoding from "../../text/utf16/module.f.js"; | ||
import { stringify } from "../serializer/module.f.js"; | ||
import { stringify } from "../serializer-old/module.f.js"; | ||
const tokenizeString = s => toArray(tokenizer.tokenize(encoding.stringToList(s))); | ||
@@ -488,14 +488,50 @@ const stringifyDjsModule = stringify(sort); | ||
], | ||
invalidModule: [ | ||
validJson: [ | ||
() => { | ||
const tokenList = tokenizeString('null'); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
if (obj[0] !== 'ok') { | ||
throw obj; | ||
} | ||
if (obj[1] !== 'unexpected token') { | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== '[[],[null]]') { | ||
throw result; | ||
} | ||
}, | ||
() => { | ||
const tokenList = tokenizeString('1'); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
throw obj; | ||
} | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== '[[],[1]]') { | ||
throw result; | ||
} | ||
}, | ||
() => { | ||
const tokenList = tokenizeString('[]'); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
throw obj; | ||
} | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== '[[],[["array",[]]]]') { | ||
throw result; | ||
} | ||
}, | ||
() => { | ||
const tokenList = tokenizeString('{"valid":"json"}'); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
throw obj; | ||
} | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== '[[],[{"valid":"json"}]]') { | ||
throw result; | ||
} | ||
} | ||
], | ||
invalidModule: [ | ||
() => { | ||
const tokenList = tokenizeString('module=null'); | ||
@@ -506,3 +542,3 @@ const obj = parser.parseFromTokens(tokenList); | ||
} | ||
if (obj[1] !== 'unexpected token') { | ||
if (obj[1] !== 'const not found') { | ||
throw obj; | ||
@@ -509,0 +545,0 @@ } |
@@ -1,13 +0,12 @@ | ||
import * as list from '../../types/list/module.f.ts'; | ||
import type * as djs from '../module.f.ts'; | ||
import type * as O from '../../types/object/module.f.ts'; | ||
import type { Unknown } from '../module.f.ts'; | ||
type Entry = O.Entry<Unknown>; | ||
type Entries = list.List<Entry>; | ||
import { type List } from '../../types/list/module.f.ts'; | ||
export declare const undefinedSerialize: string[]; | ||
type RefCounter = [number, number, boolean]; | ||
type Entry = O.Entry<djs.Unknown>; | ||
type Entries = List<Entry>; | ||
type MapEntries = (entries: Entries) => Entries; | ||
export declare const serialize: (mapEntries: MapEntries) => (value: Unknown) => list.List<string>; | ||
/** | ||
* The standard `JSON.stringify` rules determined by | ||
* https://262.ecma-international.org/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys | ||
*/ | ||
export declare const stringify: (mapEntries: MapEntries) => (value: Unknown) => string; | ||
type Refs = Map<djs.Unknown, RefCounter>; | ||
export declare const stringify: (sort: MapEntries) => (djs: djs.Unknown) => string; | ||
export declare const countRefs: (djs: djs.Unknown) => Refs; | ||
export {}; |
@@ -1,15 +0,53 @@ | ||
import * as list from "../../types/list/module.f.js"; | ||
const { flat, map } = list; | ||
import { fold } from "../../types/list/module.f.js"; | ||
import * as string from "../../types/string/module.f.js"; | ||
const { concat } = string; | ||
import { flat, flatMap, map, concat as listConcat } from "../../types/list/module.f.js"; | ||
const { entries } = Object; | ||
import * as f from "../../types/function/module.f.js"; | ||
const { compose, fn } = f; | ||
const { entries } = Object; | ||
import * as bi from "../../types/bigint/module.f.js"; | ||
const { serialize: bigintSerialize } = bi; | ||
import * as j from "../../json/serializer/module.f.js"; | ||
const { objectWrap, arrayWrap, stringSerialize, numberSerialize, nullSerialize, boolSerialize } = j; | ||
import * as serializer from "../../json/serializer/module.f.js"; | ||
const { objectWrap, arrayWrap, stringSerialize, numberSerialize, nullSerialize, boolSerialize } = serializer; | ||
const colon = [':']; | ||
const undefinedSerialize = ['undefined']; | ||
export const serialize = sort => { | ||
export const undefinedSerialize = ['undefined']; | ||
const getConstantsOp = djs => state => { | ||
switch (typeof djs) { | ||
case 'boolean': { | ||
return state; | ||
} | ||
case 'number': | ||
case 'string': | ||
case 'bigint': { | ||
return getConstantSelf(djs)(state); | ||
} | ||
default: { | ||
if (djs === null) { | ||
return state; | ||
} | ||
if (djs === undefined) { | ||
return state; | ||
} | ||
if (djs instanceof Array) { | ||
return getConstantSelf(djs)(fold(getConstantsOp)(state)(djs)); | ||
} | ||
return getConstantSelf(djs)(fold(getConstantsOp)(state)(map(entryValue)(entries(djs)))); | ||
} | ||
} | ||
}; | ||
const getConstantSelf = djs => state => { | ||
const refs = state.refs; | ||
const refCounter = refs.get(djs); | ||
if (refCounter !== undefined && refCounter[1] > 1 && !refCounter[2]) { | ||
refCounter[2] = true; | ||
refs.set(djs, refCounter); | ||
return { refs, consts: { head: state.consts, tail: [djs] } }; | ||
} | ||
return state; | ||
}; | ||
const getConstants = djs => refs => { | ||
return getConstantsOp(djs)(refs); | ||
}; | ||
const entryValue = kv => kv[1]; | ||
const serialize = sort => refs => root => { | ||
const propertySerialize = ([k, v]) => flat([ | ||
@@ -27,2 +65,8 @@ stringSerialize(k), | ||
const f = value => { | ||
if (value !== root) { | ||
const refCounter = refs.get(value); | ||
if (refCounter !== undefined && refCounter[1] > 1) { | ||
return [`c${refCounter[0]}`]; | ||
} | ||
} | ||
switch (typeof value) { | ||
@@ -58,6 +102,53 @@ case 'boolean': { | ||
}; | ||
/** | ||
* The standard `JSON.stringify` rules determined by | ||
* https://262.ecma-international.org/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys | ||
*/ | ||
export const stringify = sort => compose(serialize(sort))(concat); | ||
const countRefsOp = djs => refs => { | ||
switch (typeof djs) { | ||
case 'boolean': | ||
case 'number': { | ||
return refs; | ||
} | ||
case 'string': | ||
case 'bigint': { | ||
return addRef(djs)(refs); | ||
} | ||
default: { | ||
switch (djs) { | ||
case null: | ||
case undefined: { | ||
return refs; | ||
} | ||
} | ||
if (djs instanceof Array) { | ||
if (refs.has(djs)) | ||
return addRef(djs)(refs); | ||
return addRef(djs)(fold(countRefsOp)(refs)(djs)); | ||
} | ||
if (refs.has(djs)) | ||
return addRef(djs)(refs); | ||
return addRef(djs)(fold(countRefsOp)(refs)(map(entryValue)(entries(djs)))); | ||
} | ||
} | ||
}; | ||
const addRef = djs => refs => { | ||
const refCounter = refs.get(djs); | ||
if (refCounter === undefined) { | ||
return refs.set(djs, [refs.size, 1, false]); | ||
} | ||
return refs.set(djs, [refCounter[0], refCounter[1] + 1, false]); | ||
}; | ||
export const stringify = sort => djs => { | ||
const refs = countRefs(djs); | ||
const consts = getConstants(djs)({ refs, consts: [] }).consts; | ||
const constSerialize = entry => { | ||
const refCounter = refs.get(entry); | ||
if (refCounter === undefined) { | ||
throw 'unexpected behaviour'; | ||
} | ||
return flat([['const c'], numberSerialize(refCounter[0]), [' = '], serialize(sort)(refs)(entry)(entry), ['\n']]); | ||
}; | ||
const constStrings = flatMap(constSerialize)(consts); | ||
const rootStrings = listConcat(['export default '])(serialize(sort)(refs)(djs)(djs)); | ||
return concat(listConcat(constStrings)(rootStrings)); | ||
}; | ||
export const countRefs = djs => { | ||
return countRefsOp(djs)(new Map()); | ||
}; |
declare const _default: { | ||
stringify: ({ | ||
sort: () => void; | ||
identity: () => void; | ||
stringify?: never; | ||
} | { | ||
stringify: () => void; | ||
sort?: never; | ||
identity?: never; | ||
})[]; | ||
testPrimitives: () => void; | ||
testArray: () => void; | ||
testObj: () => void; | ||
testSort: () => void; | ||
testIdentity: () => void; | ||
}; | ||
export default _default; |
@@ -1,84 +0,78 @@ | ||
import * as json from "../../json/module.f.js"; | ||
import { countRefs, stringify } from "./module.f.js"; | ||
import * as list from "../../types/object/module.f.js"; | ||
const { sort } = list; | ||
import * as f from "../../types/function/module.f.js"; | ||
const { identity } = f; | ||
import * as serializer from "./module.f.js"; | ||
import * as serializer from "../serializer-old/module.f.js"; | ||
import { identity } from "../../types/function/module.f.js"; | ||
const stringifyOld = serializer.stringify(sort); | ||
export default { | ||
stringify: [ | ||
{ | ||
sort: () => { | ||
const r = json.setProperty("Hello")(['a'])({}); | ||
const x = serializer.stringify(sort)(r); | ||
if (x !== '{"a":"Hello"}') { | ||
throw x; | ||
} | ||
}, | ||
identity: () => { | ||
const x = serializer.stringify(identity)(json.setProperty("Hello")(['a'])({})); | ||
if (x !== '{"a":"Hello"}') { | ||
throw x; | ||
} | ||
}, | ||
}, | ||
{ | ||
sort: () => { | ||
const x = serializer.stringify(sort)(json.setProperty("Hello")(['a'])({ c: [], b: 12 })); | ||
if (x !== '{"a":"Hello","b":12,"c":[]}') { | ||
throw x; | ||
} | ||
}, | ||
identity: () => { | ||
const x = serializer.stringify(identity)(json.setProperty("Hello")(['a'])({ c: [], b: 12 })); | ||
if (x !== '{"c":[],"b":12,"a":"Hello"}') { | ||
throw x; | ||
} | ||
}, | ||
}, | ||
{ | ||
sort: () => { | ||
const _0 = { a: { y: [24] }, c: [], b: 12 }; | ||
const _1 = json.setProperty("Hello")(['a', 'x'])(_0); | ||
const _2 = serializer.stringify(sort)(_1); | ||
if (_2 !== '{"a":{"x":"Hello","y":[24]},"b":12,"c":[]}') { | ||
throw _2; | ||
} | ||
}, | ||
identity: () => { | ||
const _0 = { a: { y: [24] }, c: [], b: 12 }; | ||
const _1 = json.setProperty("Hello")(['a', 'x'])(_0); | ||
const _2 = serializer.stringify(identity)(_1); | ||
if (_2 !== '{"a":{"y":[24],"x":"Hello"},"c":[],"b":12}') { | ||
throw _2; | ||
} | ||
} | ||
}, | ||
{ | ||
stringify: () => { | ||
const bi = 1234567890n; | ||
const result = serializer.stringify(sort)(bi); | ||
if (result !== '1234567890n') { | ||
throw result; | ||
} | ||
} | ||
}, | ||
{ | ||
stringify: () => { | ||
const arr = [0n, 1, 2n]; | ||
const result = serializer.stringify(sort)(arr); | ||
if (result !== '[0n,1,2n]') { | ||
throw result; | ||
} | ||
} | ||
}, | ||
{ | ||
stringify: () => { | ||
const obj = { "a": 0n, "b": 1, "c": 2n }; | ||
const result = serializer.stringify(sort)(obj); | ||
if (result !== '{"a":0n,"b":1,"c":2n}') { | ||
throw result; | ||
} | ||
} | ||
testPrimitives: () => { | ||
const djs = [1, 2, 2, 2, true, false, undefined, null, 3n, "str"]; | ||
const refs = countRefs(djs); | ||
if (refs.size !== 3) { | ||
throw refs.size; | ||
} | ||
] | ||
const refsBigInt = stringifyOld(refs.get(3n)); | ||
if (refsBigInt !== '[0,1,false]') { | ||
throw refsBigInt; | ||
} | ||
const refsString = stringifyOld(refs.get("str")); | ||
if (refsString !== '[1,1,false]') { | ||
throw refsString; | ||
} | ||
const refsRoot = stringifyOld(refs.get(djs)); | ||
if (refsRoot !== '[2,1,false]') { | ||
throw refsRoot; | ||
} | ||
if (refs.get(null) !== undefined) { | ||
throw refs.get(null); | ||
} | ||
}, | ||
testArray: () => { | ||
const array = [null]; | ||
const djs = [array, array, array]; | ||
const refs = countRefs(djs); | ||
if (refs.size !== 2) { | ||
throw refs.size; | ||
} | ||
const refsArray = stringifyOld(refs.get(array)); | ||
if (refsArray !== '[0,3,false]') { | ||
throw refsArray; | ||
} | ||
const refsRoot = stringifyOld(refs.get(djs)); | ||
if (refsRoot !== '[1,1,false]') { | ||
throw refsRoot; | ||
} | ||
}, | ||
testObj: () => { | ||
const obj = { "a": 1, "b": 2 }; | ||
const djs = [obj, obj, 1]; | ||
const refs = countRefs(djs); | ||
if (refs.size !== 2) { | ||
throw refs.size; | ||
} | ||
const refsObj = stringifyOld(refs.get(obj)); | ||
if (refsObj !== '[0,2,false]') { | ||
throw refsObj; | ||
} | ||
const refsRoot = stringifyOld(refs.get(djs)); | ||
if (refsRoot !== '[1,1,false]') { | ||
throw refsRoot; | ||
} | ||
}, | ||
testSort: () => { | ||
const obj = { "a": 1, "c": 2n, "b": [undefined, null, true, false] }; | ||
const djs = [obj, obj, 1]; | ||
const res = stringify(sort)(djs); | ||
if (res !== 'const c2 = {"a":1,"b":[undefined,null,true,false],"c":2n}\nexport default [c2,c2,1]') { | ||
throw res; | ||
} | ||
}, | ||
testIdentity: () => { | ||
const obj = { "a": 1, "c": 2n, "b": [undefined, null, true, false] }; | ||
const djs = [obj, obj, 1]; | ||
const res = stringify(identity)(djs); | ||
if (res !== 'const c2 = {"a":1,"c":2n,"b":[undefined,null,true,false]}\nexport default [c2,c2,1]') { | ||
throw res; | ||
} | ||
} | ||
}; |
import c from "./m.f.js"; | ||
const a = 1; | ||
const b = 2; | ||
export default [a, b, c]; | ||
export default [a, a, b, c, c]; |
import * as tokenizer from "./module.f.js"; | ||
import * as list from "../../types/list/module.f.js"; | ||
const { toArray } = list; | ||
import * as serializer from "../serializer/module.f.js"; | ||
import * as serializer from "../serializer-old/module.f.js"; | ||
import * as o from "../../types/object/module.f.js"; | ||
@@ -6,0 +6,0 @@ const { sort } = o; |
import { sort } from "../../types/object/module.f.js"; | ||
import { setReplace } from "../../types/ordered_map/module.f.js"; | ||
import { transpile } from "./module.f.js"; | ||
import { stringify } from "../serializer/module.f.js"; | ||
import { stringify } from "../serializer-old/module.f.js"; | ||
import { createVirtualIo } from "../../io/virtual/module.f.js"; | ||
@@ -6,0 +6,0 @@ const virtualFs = map => { |
import * as tokenizer from "./module.f.js"; | ||
import * as list from "../../types/list/module.f.js"; | ||
const { toArray } = list; | ||
import * as serializer from "../../djs/serializer/module.f.js"; | ||
import * as serializer from "../../djs/serializer-old/module.f.js"; | ||
import * as o from "../../types/object/module.f.js"; | ||
@@ -6,0 +6,0 @@ const { sort } = o; |
import * as tokenizer from "./module.f.js"; | ||
import * as list from "../../types/list/module.f.js"; | ||
const { toArray } = list; | ||
import * as serializer from "../../djs/serializer/module.f.js"; | ||
import * as serializer from "../../djs/serializer-old/module.f.js"; | ||
import * as o from "../../types/object/module.f.js"; | ||
@@ -6,0 +6,0 @@ const { sort } = o; |
{ | ||
"name": "functionalscript", | ||
"version": "0.6.6", | ||
"version": "0.6.7", | ||
"type": "module", | ||
@@ -49,5 +49,5 @@ "files": [ | ||
"devDependencies": { | ||
"@types/node": "^22.14.1", | ||
"@types/node": "^22.15.17", | ||
"typescript": "^5.8.3" | ||
} | ||
} |
629468
1.61%267
1.52%17980
1.65%