Compact tries even more

This commit is contained in:
Wilson Lin 2020-06-19 18:12:55 +10:00
parent cefdc8fdd9
commit 9605c34e66
2 changed files with 12 additions and 4 deletions

View File

@ -139,14 +139,18 @@ export class TrieBuilder {
// Generate the code for a node's variable name and value, and return the name.
private generateNode (node: Node): string {
// Only generate elements up to the last non-undefined child to cut down on size of array.
// Only generate defined children to cut down on size of array, which would otherwise
// bog down compile time and binary size for large trees with lots of nodes.
// If array is empty, just use zero.
const firstIdx = node.children.length && node.children.findIndex(v => v);
const children = Array.from(
{length: node.children.length},
(_, i) => node.children[i] ? `Some(${this.generateNode(node.children[i])})` : 'None',
{length: node.children.length - firstIdx},
(_, i) => node.children[i + firstIdx] ? `Some(${this.generateNode(node.children[i + firstIdx])})` : 'None',
).join(', ');
const value = node.value === undefined ? 'None' : `Some(${node.value})`;
const varValue = `&crate::pattern::TrieNode {
offset: ${firstIdx},
value: ${value},
children: &[${children}],
}`;

View File

@ -33,6 +33,10 @@ impl SinglePattern {
// Can't use pub const fn constructor due to Copy trait, so allow directly creating struct publicly for now.
pub struct TrieNode<V: 'static + Copy> {
// Using a children array of size 256 would probably be fastest, but waste too much memory and cause slow compiles
// and large binaries. Instead, we only store the children between the first and last defined (see `gen/trie.ts`).
// When getting a child, use `index + offset`.
pub offset: usize,
pub value: Option<V>,
pub children: &'static [Option<&'static TrieNode<V>>],
}
@ -58,7 +62,7 @@ impl<V: 'static + Copy> TrieNode<V> {
let mut node: &TrieNode<V> = self;
let mut next_pos = from;
while let Some(&c) = text.get(next_pos) {
match node.children.get(c as usize) {
match node.children.get(c as usize + node.offset) {
Some(Some(child)) => node = child,
None | Some(None) => return None,
};