summaryrefslogtreecommitdiffstats
path: root/source/compiler-core/slang-perfect-hash-codegen.cpp
blob: 611b34c54b86d3e77ec6a5ff311ff8d34c045ea3 (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
81
#include "slang-perfect-hash-codegen.h"
#include "../core/slang-io.h"

namespace Slang
{
    SlangResult writeHashFile(
        String outCppPath,
        String valueType,
        const List<String> includes,
        const HashParams& hashParams,
        const List<String> values)
    {
        StringBuilder sb;
        StringWriter writer(&sb, WriterFlags(0));
        WriterHelper w(&writer);

        w.print("// Hash function for %s\n", valueType.getBuffer());
        w.print("//\n");
        w.print("// This file was thoughtfully generated by a machine,\n");
        w.print("// don't even think about modifying it yourself!\n");
        w.print("//\n");
        w.print("\n");
        for (const auto& i : includes)
        {
            if (i.getLength())
                w.print("#include \"%s\"\n", i.getBuffer());
        }
        w.print("\n");
        w.print("\n");
        w.print("namespace Slang\n");
        w.print("{\n");
        w.print("\n");

        w.put(perfectHashToEmbeddableCpp(
            hashParams,
            valueType.getUnownedSlice(),
            (String("lookup") + valueType).getUnownedSlice(),
            values
        ).getBuffer());

        w.print("}\n");

        return File::writeAllTextIfChanged(outCppPath, sb.getUnownedSlice());
    }

    SlangResult writePerfectHashLookupCppFile(String fileName, List<String> opnames, String enumName, String enumerantPrefix, String enumHeaderFile, DiagnosticSink* sink)
    {
        HashParams hashParams;
        auto r = minimalPerfectHash(opnames, hashParams);
        switch (r)
        {
        case HashFindResult::UnavoidableHashCollision:
        {
            sink->diagnoseRaw(
                Severity::Error,
                "Unable to find a non-overlapping hash function.\n"
                "The hash function probably has a unavoidable "
                "collision for some input words\n");
            return SLANG_FAIL;
        }
        case HashFindResult::NonUniqueKeys:
        {
            sink->diagnoseRaw(Severity::Error, "Input word list has duplicates\n");
            return SLANG_FAIL;
        }
        case HashFindResult::Success:;
        }

        List<String> values;
        values.reserve(hashParams.destTable.getCount());
        for (const auto& v : hashParams.destTable)
            values.add(enumerantPrefix + v);
        return writeHashFile(
            fileName,
            enumName,
            { "../core/slang-common.h", "../core/slang-string.h", enumHeaderFile },
            hashParams,
            values);
    }

}