summaryrefslogtreecommitdiff
path: root/gentuples.ts
blob: ba74c29a76b9f3a9c644ecba27b7cde2fdd9d816 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#!/usr/bin/env node --experimental-strip-types

function nameFor(va: string): string {
    return va.replace("E", "T").replace("T", "element")
}

function typArgs(a: string[]): string {
    if (a.length == 0) return ""
    return "<" + a.join(", ") + ">"
}

function genFunc(elementNumber: number, max: number) {
    console.log("\t@FunctionalInterface")
    const vars: string[] = [...new Array(elementNumber)].map((_, idx) => `T${idx}`)
    console.log(`\tinterface Func${elementNumber}${typArgs(['R', ...vars])} {`)
    console.log(`\t\tR apply(${vars.map(it => it + " " + it.replace("T", "arg")).join(", ")});`)
    console.log("\t}")
}

function genTuple(elementNumber: number, max: number) {
    const vars: string[] = [...new Array(elementNumber)].map((_, idx) => `T${idx}`)
    if (elementNumber == 0) {
        console.log("\tclass Tuple0 implements Tuple {")
    } else {
        console.log(`\trecord Tuple${elementNumber}${typArgs(vars)}(${vars.map(it => it + " " + nameFor(it)).join(", ")}) {`)
    }
    console.log(`\t\tpublic <R> R applyTo(Func${elementNumber}${typArgs(['R', ...vars])} func) {`)
    console.log(`\t\t\treturn func.apply(${vars.map(it => "this." + nameFor(it)).join(", ")});`)
    console.log("\t\t}")
    console.log(`\t\tpublic static ${typArgs(['R', ...vars])} Result<Tuple${elementNumber}${typArgs(vars)}, R> collect(`
        + `Tuple${elementNumber}${typArgs(vars.map(it => `Result<${it}, R>`))} tuple`
        + `) {`)
    console.log("\t\t\treturn")
    for (const tVar of vars) {
        console.log(`\t\t\t\ttuple.${nameFor(tVar)}.flatMap(${nameFor(tVar)} ->`)
    }
    console.log(`\t\t\t\t\tResult.ok(new Tuple${elementNumber}${elementNumber ? '<>' : ''}(${vars.map(it => nameFor(it)).join(", ")}))`)
    for (const tVar of vars) {
        console.log(`\t\t\t\t)`)
    }
    console.log("\t\t\t;")
    console.log("\t\t}")


    const newVars = vars.map(it => it.replace("T", "E"))
    console.log(`\t\tpublic ${typArgs(newVars)} Tuple${elementNumber}${typArgs(newVars)} map(`
        + newVars.map(it => `Func1<${it}, ${it.replace("E", "T")}> ${it.replace("E", "map")}`).join(", ")
        + `) {`)
    console.log(`\t\t\treturn new Tuple${elementNumber}${(elementNumber ? '<>' : '')}(${newVars.map(it => `${it.replace("E", "map")}.apply(this.${nameFor(it)})`).join(", ")});`)
    console.log("\t\t}")

    for (let extraElements = 0; extraElements < (max - elementNumber); extraElements++) {
        const extraVars = [...new Array(extraElements)].map((_, idx) => `E${idx}`)
        const sumElements = extraElements + elementNumber;
        console.log(`\t\tpublic ${typArgs(extraVars)} Tuple${sumElements}${typArgs([...vars, ...extraVars])} `
            + `join(Tuple${extraElements}${typArgs(extraVars)} other) {`)
        console.log(`\t\t\treturn new Tuple${sumElements}${sumElements ? '<>' : ''}(${[
            ...vars.map(it => "this." + nameFor(it)),
            ...extraVars.map(it => "other." + nameFor(it))].join(", ")});`)
        console.log("\t\t}")
    }
    console.log("\t}")
}


function genTuples(maxI: number) {
    console.log("// @gen" + "erated by gentuples.ts")
    console.log("package moe.nea.pcj;")
    console.log()
    console.log("@SuppressWarnings(\"unused\")")
    console.log("public interface Tuple {")
    for (let i = 0; i < maxI; i++) {
        genTuple(i, maxI);
        genFunc(i, maxI)
    }
    console.log("}")
}

genTuples(15)