diff --git a/Cargo.lock b/Cargo.lock index 86000f7..4745d31 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -171,6 +171,11 @@ dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "endian-type" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "failure" version = "0.1.5" @@ -346,6 +351,11 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "nibble_vec" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "nix" version = "0.14.1" @@ -517,6 +527,15 @@ dependencies = [ "proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "radix_trie" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "endian-type 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "nibble_vec 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand" version = "0.4.6" @@ -735,6 +754,7 @@ dependencies = [ "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "radix_trie 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "schala-lang-codegen 0.1.0", "schala-repl 0.1.0", "stopwatch 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1005,6 +1025,7 @@ dependencies = [ "checksum dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" "checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" "checksum ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f56c93cc076508c549d9bb747f79aa9b4eb098be7b8cad8830c3137ef52d1e00" +"checksum endian-type 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "e6234dd4468ae5d1e2dbb06fe2b058696fdc50a339c68a393aefbf00bc81e423" @@ -1027,6 +1048,7 @@ dependencies = [ "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum miniz-sys 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9e3ae51cea1576ceba0dde3d484d30e6e5b86dee0b2d412fe3a16a15c98202" "checksum mortal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d96ca97d37cb87ea3d658e71c8c2e2f2d420eca5deec047c5a283aa810a900ff" +"checksum nibble_vec 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c8d77f3db4bce033f4d04db08079b2ef1c3d02b44e86f25d08886fafa7756ffa" "checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" @@ -1046,6 +1068,7 @@ dependencies = [ "checksum proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afdc77cc74ec70ed262262942ebb7dac3d479e9e5cfa2da1841c0806f6cdabcc" "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" +"checksum radix_trie 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "deafbff7bda0a58975ce92723aa18be10eae2e9271f3c3f48de52d131d9f248c" "checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" diff --git a/schala-lang/language/Cargo.toml b/schala-lang/language/Cargo.toml index 0b64752..3a71603 100644 --- a/schala-lang/language/Cargo.toml +++ b/schala-lang/language/Cargo.toml @@ -14,6 +14,7 @@ ena = "0.11.0" stopwatch = "0.0.7" derivative = "1.0.3" colored = "1.8" +radix_trie = "0.1.5" schala-lang-codegen = { path = "../codegen" } schala-repl = { path = "../../schala-repl" } diff --git a/schala-lang/language/src/lib.rs b/schala-lang/language/src/lib.rs index 159685f..c32c464 100644 --- a/schala-lang/language/src/lib.rs +++ b/schala-lang/language/src/lib.rs @@ -18,6 +18,7 @@ extern crate schala_lang_codegen; extern crate ena; extern crate derivative; extern crate colored; +extern crate radix_trie; macro_rules! bx { diff --git a/schala-lang/language/src/symbol_table.rs b/schala-lang/language/src/symbol_table.rs index a88f072..02faea9 100644 --- a/schala-lang/language/src/symbol_table.rs +++ b/schala-lang/language/src/symbol_table.rs @@ -8,6 +8,7 @@ use crate::ast; use crate::ast::{ItemId, TypeBody, TypeSingletonName, Signature, Statement, StatementKind}; use crate::typechecking::TypeName; + #[allow(unused_macros)] macro_rules! sym_path_kind { (fn) => { ScopeSegmentKind::Function }; @@ -31,7 +32,8 @@ macro_rules! fqsn { }; } - +mod symbol_trie; +use symbol_trie::SymbolTrie; mod test; type LineNumber = u32; @@ -75,7 +77,7 @@ impl ScopeSegment { } } -#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)] +#[derive(Copy, Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)] pub enum ScopeSegmentKind { Function, Type, @@ -87,6 +89,7 @@ pub enum ScopeSegmentKind { pub struct SymbolTable { symbol_path_to_symbol: HashMap, id_to_fqsn: HashMap, + symbol_trie: SymbolTrie, } //TODO add various types of lookups here, maybe multiple hash tables internally? @@ -95,6 +98,7 @@ impl SymbolTable { SymbolTable { symbol_path_to_symbol: HashMap::new(), id_to_fqsn: HashMap::new(), + symbol_trie: SymbolTrie::new() } } diff --git a/schala-lang/language/src/symbol_table/symbol_trie.rs b/schala-lang/language/src/symbol_table/symbol_trie.rs new file mode 100644 index 0000000..2fd9bff --- /dev/null +++ b/schala-lang/language/src/symbol_table/symbol_trie.rs @@ -0,0 +1,51 @@ +use std::rc::Rc; +use radix_trie::{Trie, TrieCommon, TrieKey}; +use super::{ScopeSegmentKind, ScopeSegment, FullyQualifiedSymbolName}; +use std::hash::{Hasher, Hash}; +use std::collections::hash_map::DefaultHasher; + +pub struct SymbolTrie(Trie); + +impl TrieKey for FullyQualifiedSymbolName { + fn encode_bytes(&self) -> Vec { + let mut hasher = DefaultHasher::new(); + let mut output = vec![]; + let FullyQualifiedSymbolName(scopes) = self; + for segment in scopes.iter() { + segment.name.as_bytes().hash(&mut hasher); + output.extend_from_slice(&hasher.finish().to_be_bytes()); + } + output + } +} + +impl SymbolTrie { + pub fn new() -> SymbolTrie { + SymbolTrie(Trie::new()) + } + + pub fn insert(&mut self, fqsn: &FullyQualifiedSymbolName) { + self.0.insert(fqsn.clone(), ()); + } + + pub fn get_children(&self, fqsn: &FullyQualifiedSymbolName) -> Vec { + let subtrie = match self.0.subtrie(fqsn) { + Some(s) => s, + None => return vec![] + }; + let output: Vec = subtrie.keys().map(|fqsn| fqsn.clone()).collect(); + output + } +} + +#[test] +fn test_trie_insertion() { + let mut trie = SymbolTrie::new(); + + trie.insert(&fqsn!("unrelated"; ty, "thing"; tr)); + trie.insert(&fqsn!("outer"; ty, "inner"; tr)); + trie.insert(&fqsn!("outer"; ty, "inner"; ty, "still_inner"; tr)); + + let children = trie.get_children(&fqsn!("outer"; ty, "inner"; tr)); + assert_eq!(children.len(), 2); +}