Skip to content

Commit

Permalink
Merge pull request #1197 from samchon/feature/random
Browse files Browse the repository at this point in the history
Optimize `random()` and `clone()` functions.
  • Loading branch information
samchon authored Aug 4, 2024
2 parents 033eac5 + bb398ba commit 253a1de
Show file tree
Hide file tree
Showing 28 changed files with 235 additions and 138 deletions.
2 changes: 1 addition & 1 deletion benchmark/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,6 @@
"suppress-warnings": "^1.0.2",
"tstl": "^3.0.0",
"uuid": "^9.0.1",
"typia": "../typia-6.7.0.tgz"
"typia": "../typia-6.7.1.tgz"
}
}
2 changes: 1 addition & 1 deletion debug/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
},
"dependencies": {
"tstl": "^3.0.0",
"typia": "../typia-6.7.0-dev.20240803-4.tgz",
"typia": "../typia-6.7.1-dev.20240805.tgz",
"uuid": "^10.0.0"
}
}
18 changes: 18 additions & 0 deletions debug/src/clone.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import typia from "typia";

export type ConstantAtomicUnion = ConstantAtomicUnion.Union[];
export namespace ConstantAtomicUnion {
export type Union = false | 1 | 2 | "three" | "four" | { key: "key" };
}
typia.misc.createClone<ConstantAtomicUnion>();

// export type ConstantAtomicUnion = ConstantAtomicUnion.Union[];
// export namespace ConstantAtomicUnion {
// export type Union =
// | false
// | 1
// | 2
// | "three"
// | "four"
// | { key: "key" };
// }
2 changes: 1 addition & 1 deletion errors/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@
"typescript": "^5.3.2"
},
"dependencies": {
"typia": "../typia-6.7.0.tgz"
"typia": "../typia-6.7.1.tgz"
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "typia",
"version": "6.7.0",
"version": "6.7.1",
"description": "Superfast runtime validators with only one line",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
Expand Down
4 changes: 2 additions & 2 deletions packages/typescript-json/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "typescript-json",
"version": "6.7.0",
"version": "6.7.1",
"description": "Superfast runtime validators with only one line",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
Expand Down Expand Up @@ -63,7 +63,7 @@
},
"homepage": "https://typia.io",
"dependencies": {
"typia": "6.7.0"
"typia": "6.7.1"
},
"peerDependencies": {
"typescript": ">=4.8.0 <5.6.0"
Expand Down
1 change: 0 additions & 1 deletion src/programmers/AssertProgrammer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ export namespace AssertProgrammer {
type: ts.Type;
name: string | undefined;
init: ts.Expression | undefined;
inline?: boolean;
}): FeatureProgrammer.IDecomposed => {
const is: FeatureProgrammer.IDecomposed = IsProgrammer.decompose(props);
const composed: FeatureProgrammer.IComposed = CheckerProgrammer.compose({
Expand Down
2 changes: 1 addition & 1 deletion src/programmers/CheckerProgrammer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export namespace CheckerProgrammer {
config: IConfig;
importer: FunctionImporter;
type: ts.Type;
name?: string;
name: string | undefined;
}) =>
FeatureProgrammer.compose({
...props,
Expand Down
2 changes: 1 addition & 1 deletion src/programmers/FeatureProgrammer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ export namespace FeatureProgrammer {
config: IConfig;
importer: FunctionImporter;
type: ts.Type;
name?: string;
name: string | undefined;
}): IComposed => {
const [collection, meta] = props.config.initializer(props.project)(
props.importer,
Expand Down
2 changes: 1 addition & 1 deletion src/programmers/IsProgrammer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export namespace IsProgrammer {
importer: FunctionImporter;
equals: boolean;
type: ts.Type;
name?: string;
name: string | undefined;
}): FeatureProgrammer.IDecomposed => {
// CONFIGURATION
const config: CheckerProgrammer.IConfig = {
Expand Down
189 changes: 112 additions & 77 deletions src/programmers/RandomProgrammer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,91 +23,126 @@ import { TransformerError } from "../transformers/TransformerError";
import { Escaper } from "../utils/Escaper";

import { Format } from "../tags";
import { FeatureProgrammer } from "./FeatureProgrammer";
import { FunctionImporter } from "./helpers/FunctionImporter";
import { RandomJoiner } from "./helpers/RandomJoiner";
import { RandomRanger } from "./helpers/RandomRanger";
import { random_custom } from "./internal/random_custom";

export namespace RandomProgrammer {
export const write =
(project: IProject) =>
(modulo: ts.LeftHandSideExpression) =>
(init?: ts.Expression) => {
const importer: FunctionImporter = new FunctionImporter(modulo.getText());
return (type: ts.Type, name?: string) => {
// INITIALIZE METADATA
const collection: MetadataCollection = new MetadataCollection();
const result = MetadataFactory.analyze(
project.checker,
project.context,
)({
escape: false,
constant: true,
absorb: true,
validate: (meta) => {
const output: string[] = [];
if (meta.natives.some((n) => n === "WeakSet"))
output.push(`WeakSet is not supported.`);
else if (meta.natives.some((n) => n === "WeakMap"))
output.push(`WeakMap is not supported.`);
return output;
},
})(collection)(type);
if (result.success === false)
throw TransformerError.from(`typia.${importer.method}`)(
result.errors,
);

// GENERATE FUNCTION
const functions = {
objects: write_object_functions(importer)(collection),
arrays: write_array_functions(importer)(collection),
tuples: write_tuple_functions(importer)(collection),
};

const output: ts.Expression = decode(importer)({
function: false,
recursive: false,
})(result.data);
export const decompose = (props: {
project: IProject;
importer: FunctionImporter;
type: ts.Type;
name: string | undefined;
init: ts.Expression | undefined;
}): FeatureProgrammer.IDecomposed => {
const collection: MetadataCollection = new MetadataCollection();
const result = MetadataFactory.analyze(
props.project.checker,
props.project.context,
)({
escape: false,
constant: true,
absorb: true,
validate: (meta) => {
const output: string[] = [];
if (meta.natives.some((n) => n === "WeakSet"))
output.push(`WeakSet is not supported.`);
else if (meta.natives.some((n) => n === "WeakMap"))
output.push(`WeakMap is not supported.`);
return output;
},
})(collection)(props.type);
if (result.success === false)
throw TransformerError.from(`typia.${props.importer.method}`)(
result.errors,
);

return ts.factory.createArrowFunction(
undefined,
undefined,
[
IdentifierFactory.parameter(
"generator",
ts.factory.createTypeReferenceNode(
"Partial<typia.IRandomGenerator>",
),
init ?? ts.factory.createToken(ts.SyntaxKind.QuestionToken),
),
],
ts.factory.createImportTypeNode(
ts.factory.createLiteralTypeNode(
ts.factory.createStringLiteral("typia"),
// GENERATE FUNCTION
const functions: Record<string, ts.VariableStatement> = Object.fromEntries([
...write_object_functions(props.importer)(collection).map((v, i) => [
Prefix.object(i),
v,
]),
...write_array_functions(props.importer)(collection).map((v, i) => [
Prefix.array(i),
v,
]),
...write_tuple_functions(props.importer)(collection).map((v, i) => [
Prefix.tuple(i),
v,
]),
]);
const arrow: ts.ArrowFunction = ts.factory.createArrowFunction(
undefined,
undefined,
[
IdentifierFactory.parameter(
"generator",
ts.factory.createTypeReferenceNode("Partial<typia.IRandomGenerator>"),
props.init ?? ts.factory.createToken(ts.SyntaxKind.QuestionToken),
),
],
ts.factory.createImportTypeNode(
ts.factory.createLiteralTypeNode(
ts.factory.createStringLiteral("typia"),
),
undefined,
ts.factory.createIdentifier("Resolved"),
[
ts.factory.createTypeReferenceNode(
props.name ??
TypeFactory.getFullName(props.project.checker)(props.type),
),
],
false,
),
undefined,
ts.factory.createBlock(
[
ts.factory.createExpressionStatement(
ts.factory.createBinaryExpression(
ts.factory.createIdentifier("_generator"),
ts.SyntaxKind.EqualsToken,
ts.factory.createIdentifier("generator"),
),
undefined,
ts.factory.createIdentifier("Resolved"),
[
ts.factory.createTypeReferenceNode(
name ?? TypeFactory.getFullName(project.checker)(type),
),
],
false,
),
undefined,
ts.factory.createBlock(
[
...importer.declare(modulo),
...functions.objects,
...functions.arrays,
...functions.tuples,
ts.factory.createReturnStatement(output),
],
true,
ts.factory.createReturnStatement(
decode(props.importer)({
function: false,
recursive: false,
})(result.data),
),
);
};
],
true,
),
);
return {
functions,
statements: [StatementFactory.mut("_generator")],
arrow,
};
};

export const write =
(project: IProject) =>
(modulo: ts.LeftHandSideExpression) =>
(init?: ts.Expression) =>
(type: ts.Type, name?: string) => {
const importer: FunctionImporter = new FunctionImporter(modulo.getText());
const result: FeatureProgrammer.IDecomposed = decompose({
project,
importer,
type,
name,
init,
});
return FeatureProgrammer.writeDecomposed({
modulo,
importer,
result,
});
};

const write_object_functions =
Expand Down Expand Up @@ -892,12 +927,12 @@ const COALESCE = (importer: FunctionImporter) => (name: string) =>
ExpressionFactory.coalesce(
Escaper.variable(name)
? ts.factory.createPropertyAccessChain(
ts.factory.createIdentifier("generator"),
ts.factory.createIdentifier("_generator"),
ts.factory.createToken(ts.SyntaxKind.QuestionDotToken),
ts.factory.createIdentifier(name),
)
: ts.factory.createElementAccessChain(
ts.factory.createIdentifier("generator"),
ts.factory.createIdentifier("_generator"),
ts.factory.createToken(ts.SyntaxKind.QuestionDotToken),
ts.factory.createStringLiteral(name),
),
Expand Down
2 changes: 1 addition & 1 deletion src/programmers/ValidateProgrammer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export namespace ValidateProgrammer {
importer: FunctionImporter;
equals: boolean;
type: ts.Type;
name?: string;
name: string | undefined;
}): FeatureProgrammer.IDecomposed => {
const is: FeatureProgrammer.IDecomposed = IsProgrammer.decompose(props);
const composed: FeatureProgrammer.IComposed = CheckerProgrammer.compose({
Expand Down
2 changes: 1 addition & 1 deletion src/programmers/json/JsonIsParseProgrammer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export namespace JsonIsParseProgrammer {
project: IProject;
importer: FunctionImporter;
type: ts.Type;
name?: string;
name: string | undefined;
}): FeatureProgrammer.IDecomposed => {
const is: FeatureProgrammer.IDecomposed = IsProgrammer.decompose({
...props,
Expand Down
2 changes: 1 addition & 1 deletion src/programmers/json/JsonIsStringifyProgrammer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export namespace JsonIsStringifyProgrammer {
project: IProject;
importer: FunctionImporter;
type: ts.Type;
name?: string;
name: string | undefined;
}): FeatureProgrammer.IDecomposed => {
const is: FeatureProgrammer.IDecomposed = IsProgrammer.decompose({
...props,
Expand Down
5 changes: 2 additions & 3 deletions src/programmers/json/JsonStringifyProgrammer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export namespace JsonStringifyProgrammer {
project: IProject;
importer: FunctionImporter;
type: ts.Type;
name?: string;
name: string | undefined;
}): FeatureProgrammer.IDecomposed => {
const config: FeatureProgrammer.IConfig = configure(props.project)(
props.importer,
Expand Down Expand Up @@ -852,8 +852,7 @@ export namespace JsonStringifyProgrammer {
initializer,
decoder: () => decode(project)(config)(importer),
objector: {
checker: () => (input, meta, explore) =>
IsProgrammer.decode(project)(importer)(input, meta, explore),
checker: () => IsProgrammer.decode(project)(importer),
decoder: () => decode_object(importer),
joiner: StringifyJoiner.object(importer),
unionizer: decode_union_object(
Expand Down
2 changes: 1 addition & 1 deletion src/programmers/json/JsonValidateParseProgrammer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export namespace JsonValidateParseProgrammer {
modulo: ts.LeftHandSideExpression;
importer: FunctionImporter;
type: ts.Type;
name?: string;
name: string | undefined;
}): FeatureProgrammer.IDecomposed => {
const validate: FeatureProgrammer.IDecomposed =
ValidateProgrammer.decompose({
Expand Down
2 changes: 1 addition & 1 deletion src/programmers/json/JsonValidateStringifyProgrammer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export namespace JsonValidateStringifyProgrammer {
modulo: ts.LeftHandSideExpression;
importer: FunctionImporter;
type: ts.Type;
name?: string;
name: string | undefined;
}): FeatureProgrammer.IDecomposed => {
const validate: FeatureProgrammer.IDecomposed =
ValidateProgrammer.decompose({
Expand Down
Loading

0 comments on commit 253a1de

Please sign in to comment.