diff --git a/benchmark/compiler/compiler.mjs b/benchmark/compiler/compiler.mjs new file mode 100644 index 0000000..9bcf3ec --- /dev/null +++ b/benchmark/compiler/compiler.mjs @@ -0,0 +1,82 @@ +import { printTree } from "./utils.mjs" + +/** + * Child { + * char: 'a', + * children: [Child, Child], + * path: null / 'full/path', + * count: 0 + * } + */ +function Child(char) { + this.char = char + this.children = [] + this.path = null + this.count = 0 +} + +function buildChild(i, arr) { + let letter = new Child(arr[0][i]) + let consume = [] + if (arr[0].length === i + 1) { + letter.path = arr[0] + letter.count += 1 + } else { + consume = [arr[0]] + } + + for (let y = 1; y < arr.length; y++) { + if (arr[y][i] !== letter.char) break + consume.push(arr[y]) + } + + letter.count += consume.length + while (consume.length) { + letter.children.push(buildChild(i + 1, consume)) + consume.splice(0, letter.children[letter.children.length - 1].count) + } + return letter +} + +export function buildTree(all) { + let paths = Array.from(new Set(all)).sort() + let builder = [] + while (paths.length) { + builder.push(buildChild(0, paths)) + paths.splice(0, builder[builder.length - 1].count) + } + printTree(builder) + return builder +} + +function IfTreeBranch(branches, indent = 0) { + let output = '' + let indentation = ''.padStart(indent * 2) + + for (let i = 0; i < branches.length; i++) { + let branch = branches[i] + output += `${i > 0 ? 'else ': ''}if (str.charCodeAt(${indent}) === ${branch.char.charCodeAt(0)}) {` + + if (branch.path) { + output += '\n' + indentation + ` if (str.length === ${branch.path.length}) {` + output += '\n' + indentation + ` return "${branch.path}"` + output += '\n' + indentation + ` }` + } + if (branch.children.length) { + if (branch.path) { + output += ' else ' + } else { + output += '\n' + indentation + ' ' + } + output += IfTreeBranch(branch.children, indent + 1) + } + output += '\n' + indentation + '} ' + } + return output +} + +export function compileTreeIntoIfs(tree) { + let output = IfTreeBranch(tree) + output += '\nreturn null' + return new Function(output) +} diff --git a/benchmark/compiler/utils.mjs b/benchmark/compiler/utils.mjs new file mode 100644 index 0000000..3b17afb --- /dev/null +++ b/benchmark/compiler/utils.mjs @@ -0,0 +1,8 @@ +export function printTree(children, indent = 0) { + if (!children.length) return + + for (let child of children) { + console.log(child.char.padStart(1 + indent * 2)) + printTree(child.children, indent + 1) + } +} diff --git a/benchmark/strings.mjs b/benchmark/strings.mjs new file mode 100644 index 0000000..6b3233c --- /dev/null +++ b/benchmark/strings.mjs @@ -0,0 +1,19 @@ +import { buildTree, compileTreeIntoIfs } from "./compiler/compiler.mjs" + +let paths = [ + 'test1', + 'test', + 'test3', + 'test5', + 'something', + 'sometimes', + 'else', + 'goes', + 'here', + 'too', +] + +let tree = buildTree(paths) + +const ifTree = compileTreeIntoIfs(tree) +console.log(ifTree.toString()) \ No newline at end of file