├── .gitignore ├── .travis.yml ├── Cargo.toml ├── README.md ├── src ├── loader.rs ├── hasher.rs ├── trie │ ├── mod.rs │ ├── last_ancestor.rs │ ├── trie_common.rs │ ├── subtrie.rs │ ├── keys.rs │ ├── iter.rs │ ├── trie.rs │ ├── trie_node.rs │ └── traversal.rs ├── main.rs ├── leanpath.rs ├── args.rs ├── tokens.rs ├── rough_parser.rs ├── types.rs ├── lexer.rs └── deserialize.rs ├── Cargo.lock └── olean.lean /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | 2 | language: rust 3 | rust: 4 | - nightly 5 | 6 | script: cargo build 7 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "olean-rs" 3 | version = "0.1.0" 4 | authors = ["Mario Carneiro "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | num = "0.2" 9 | num-traits = "0.2.6" 10 | num-derive = "0.2.3" 11 | byteorder = "1.2.7" 12 | getopts = "0.2" 13 | nibble_vec = "~0.0.3" 14 | endian-type = "0.1.2" 15 | unicode_reader = "0.1.1" 16 | take_mut = "0.2.2" 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/cipher1024/olean-rs.svg?branch=master)](https://travis-ci.org/cipher1024/olean-rs) 2 | 3 | # olean-rs 4 | Parser/viewer for olean files, written in Rust and Lean. 5 | 6 | See `olean.lean` for the lean version, and build with `cargo` for the Rust version. Currently the Rust version is faster by a factor of a hundred or so, so I don't know if I will continue to keep the Lean version up to speed. 7 | 8 | Why look at olean files? The `olean` file format is an unstable binary format used by lean for caching successfully parsed files. As such, it is much easier to parse from a third party position than a `lean` file. Second, although lean supports an export format, the format is quite lossy, essentially only representing the expressions that are defined in the file. By contrast, the `olean` file contains lots of other information like notation declarations, attributes, `protected` status and namespace locations (which are not accessible through lean metaprogramming), and VM code. So `olean` parsing is the first step to a number of other processing or analysis passes. 9 | 10 | ## Building the Rust project 11 | 12 | ```shell 13 | rustup toolchain install nightly 14 | rustup override set nightly 15 | cargo build 16 | ``` 17 | 18 | ## Getting Started 19 | 20 | ``` 21 | Usage: target/debug/olean-rs path/to/file.olean [options] 22 | 23 | Options: 24 | -D, --dump FILE dump olean parse 25 | -L give location of lean library 26 | -d, --deps lean.name view all dependents of the target file 27 | -p DIR set current working directory 28 | -l lean.name test lexer 29 | -t lean.name testing 30 | -h, --help print this help menu 31 | ``` 32 | -------------------------------------------------------------------------------- /src/loader.rs: -------------------------------------------------------------------------------- 1 | use std::collections::hash_map::HashMap; 2 | use std::io; 3 | use std::fs::File; 4 | use crate::types::*; 5 | use crate::deserialize; 6 | use crate::leanpath::*; 7 | 8 | pub struct Loader { 9 | pub map: HashMap>)>, 10 | pub order: Vec 11 | } 12 | 13 | fn load_olean(lp: &LeanPath, n: Name) -> io::Result> { 14 | Ok(if let Some((n2, file)) = lp.find(n.clone(), "olean") { 15 | Some((n2, deserialize::read_olean(File::open(file)?)?)) 16 | } else { None }) 17 | } 18 | 19 | impl Loader { 20 | pub fn new() -> Loader { Loader { map: HashMap::new(), order: Vec::new() } } 21 | 22 | pub fn load(&mut self, lp: &LeanPath, start: Name) -> io::Result<()> { 23 | if let Some((n2, ol)) = load_olean(lp, start.clone())? { 24 | for mp in &ol.imports { 25 | let other = mp.resolve(n2.clone()); 26 | if !self.map.contains_key(&other) { 27 | self.load(lp, other)? 28 | } 29 | } 30 | self.order.push(n2.clone()); 31 | self.map.insert(n2, (ol, None)); 32 | } else { println!("can't find {}\npath = {:?}", start, lp.0) } 33 | Ok(()) 34 | } 35 | 36 | pub fn get_mods(map: &mut HashMap>)>, n: Name) -> io::Result<&[Modification]> { 37 | let (ol, o) = map.get_mut(&n).expect("should already be loaded"); 38 | if let Some(mods) = o { return Ok(mods) } 39 | let mods = deserialize::read_olean_modifications(&ol.code).map_err(|err| { 40 | io::Error::new(io::ErrorKind::InvalidData, format!("error parsing {}: {}", n, err)) 41 | })?; 42 | Ok(o.get_or_insert(mods)) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/hasher.rs: -------------------------------------------------------------------------------- 1 | use std::num::Wrapping; 2 | 3 | fn mix(a: &mut Wrapping, b: &mut Wrapping, c: &mut Wrapping) { 4 | *a -= *b; *a -= *c; *a ^= *c >> 13; 5 | *b -= *c; *b -= *a; *b ^= *a << 8; 6 | *c -= *a; *c -= *b; *c ^= *b >> 13; 7 | *a -= *b; *a -= *c; *a ^= *c >> 12; 8 | *b -= *c; *b -= *a; *b ^= *a << 16; 9 | *c -= *a; *c -= *b; *c ^= *b >> 5; 10 | *a -= *b; *a -= *c; *a ^= *c >> 3; 11 | *b -= *c; *b -= *a; *b ^= *a << 10; 12 | *c -= *a; *c -= *b; *c ^= *b >> 15; 13 | } 14 | 15 | pub fn hash>(arr: &[T]) -> u32 { 16 | hash_with(arr, |u| Wrapping((*u).into()), Wrapping(31)) 17 | } 18 | 19 | pub fn hash_with Wrapping>(arr: &[T], h: H, init_value: Wrapping) -> u32 { 20 | let mut a: Wrapping = Wrapping(0x9e3779b9); 21 | let mut b = a; 22 | let mut c: Wrapping = Wrapping(11); 23 | let mut n = arr.len(); 24 | match n { 25 | 1 => { 26 | a += init_value; 27 | b = h(&arr[0]); 28 | mix(&mut a, &mut b, &mut c); c.0 }, 29 | 2 => { 30 | a += init_value; 31 | b += h(&arr[0]); 32 | c += h(&arr[1]); 33 | mix(&mut a, &mut b, &mut c); c.0 }, 34 | 3 => { 35 | a += h(&arr[0]); 36 | b += h(&arr[1]); 37 | c += h(&arr[2]); 38 | mix(&mut a, &mut b, &mut c); 39 | a += init_value; 40 | mix(&mut a, &mut b, &mut c); c.0 }, 41 | _ => { 42 | while n >= 3 { 43 | n -= 1; a += h(&arr[n]); 44 | n -= 1; b += h(&arr[n]); 45 | n -= 1; c += h(&arr[n]); 46 | mix(&mut a, &mut b, &mut c); 47 | } 48 | a += init_value; 49 | match n { 50 | 2 => { b += h(&arr[1]); c += h(&arr[0]); }, 51 | 1 => c += h(&arr[0]), 52 | _ => () 53 | }; 54 | mix(&mut a, &mut b, &mut c); c.0 } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/trie/mod.rs: -------------------------------------------------------------------------------- 1 | // Note: this module is adapted from `radix_trie`, available on crates.io. 2 | 3 | //! A wonderful, fast, safe, generic radix trie implementation. 4 | //! 5 | //! To get started, see the docs for `Trie` below. 6 | 7 | // #![warn(missing_docs)] 8 | 9 | pub use self::keys::TrieKey; 10 | pub use nibble_vec::NibbleVec; 11 | pub use self::trie_common::TrieCommon; 12 | pub use self::last_ancestor::LastAncestorIter; 13 | use self::trie_node::TrieNode; 14 | 15 | pub mod iter; 16 | mod keys; 17 | mod subtrie; 18 | mod traversal; 19 | mod trie; 20 | mod trie_common; 21 | mod trie_node; 22 | pub mod last_ancestor; 23 | 24 | const BRANCH_FACTOR: usize = 16; 25 | 26 | /// Data-structure for storing and querying string-like keys and associated values. 27 | /// 28 | /// Any keys which share a common *prefix* are stored below a single copy of that prefix. 29 | /// This saves space, and also allows the longest prefix of any given key to be found. 30 | /// 31 | /// You can read more about Radix Tries on [Wikipedia][radix-wiki]. 32 | /// 33 | /// Lots of the methods on `Trie` return optional values - they can be composed 34 | /// nicely using `Option::and_then`. 35 | /// 36 | /// [radix-wiki]: http://en.wikipedia.org/wiki/Radix_tree 37 | #[derive(Debug)] 38 | pub struct Trie { 39 | /// The number of values stored in this sub-trie (this node and all descendants). 40 | length: usize, 41 | /// The main content of this trie. 42 | node: TrieNode, 43 | } 44 | 45 | /// Immutable view of a sub-tree a larger trie. 46 | #[derive(Debug)] 47 | pub struct SubTrie<'a, V: 'a> { 48 | prefix: NibbleVec, 49 | node: &'a TrieNode, 50 | } 51 | 52 | /// Mutable view of a sub-tree of a larger trie. 53 | #[derive(Debug)] 54 | pub struct SubTrieMut<'a, V: 'a> { 55 | prefix: NibbleVec, 56 | length: &'a mut usize, 57 | node: &'a mut TrieNode, 58 | } 59 | 60 | /// Wrapper for subtrie lookup results. 61 | /// 62 | /// When fetching from a subtrie, if the prefix is wrong you'll get an `Err(())`. 63 | /// Otherwise you'll get an `Ok(_)`, where the contained option value is what would ordinarily 64 | /// be returned by get/insert/whatever. 65 | pub type SubTrieResult = Result, ()>; 66 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] mod types; 2 | mod deserialize; 3 | mod hasher; 4 | mod args; 5 | mod leanpath; 6 | mod loader; 7 | mod tokens; 8 | mod lexer; 9 | mod rough_parser; 10 | #[allow(dead_code)] mod trie; 11 | 12 | use std::io; 13 | use std::fs::File; 14 | use self::args::*; 15 | use self::leanpath::LeanPath; 16 | use self::loader::Loader; 17 | use self::tokens::TokenTable; 18 | use self::rough_parser::RoughParser; 19 | 20 | #[macro_use] extern crate num_derive; 21 | extern crate getopts; 22 | extern crate endian_type; 23 | extern crate nibble_vec; 24 | 25 | fn main() -> io::Result<()> { 26 | let args = args()?; 27 | match &args.act { 28 | Action::Dump(file) => { 29 | let ol = deserialize::read_olean(File::open(&file)?)?; 30 | println!("{}", ol); 31 | println!("==================="); 32 | let mods = deserialize::read_olean_modifications(&ol.code)?; 33 | for m in mods { 34 | println!("{:?}", m); 35 | } 36 | }, 37 | Action::Dependents(name) => { 38 | let lp = LeanPath::new(&args)?; 39 | let mut load = Loader::new(); 40 | load.load(&lp, name.clone())?; 41 | for s in load.order { println!("{}", s) } 42 | }, 43 | Action::Lex(name) => { 44 | let lp = LeanPath::new(&args)?; 45 | let mut load = Loader::new(); 46 | load.load(&lp, name.clone())?; 47 | let n2 = load.order.pop().unwrap(); 48 | let mut table = TokenTable::new(); 49 | table.load(&mut load)?; 50 | let path = lp.find(n2, "lean").unwrap().1; 51 | let lex = lexer::from_file(&path, table)?; 52 | for tk in lex { 53 | println!("{:?}", tk?) 54 | } 55 | }, 56 | Action::Test(name) => { 57 | let lp = LeanPath::new(&args)?; 58 | let path = lp.find(name.clone(), "lean").unwrap().1; 59 | let mut load = Loader::new(); 60 | let lexer = lexer::from_file(&path, TokenTable::new())?; 61 | let mut rp = RoughParser::new(lexer); 62 | let rl = rp.parse_lean(&mut load, &lp, name.clone())?; 63 | for tk in rl.cmds { println!("{}", tk) } 64 | }, 65 | Action::None => args.print_usage_and_exit(1) 66 | } 67 | Ok(()) 68 | } 69 | -------------------------------------------------------------------------------- /src/leanpath.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | use std::io::{BufRead, BufReader}; 3 | use std::env; 4 | use std::path::{Path, PathBuf}; 5 | use std::fs::File; 6 | use crate::args; 7 | use crate::types::{Name, Name2}; 8 | 9 | fn get_leanpkg_path_file() -> Option { 10 | let mut path: &Path = &env::current_dir().ok()?; 11 | loop { 12 | let mut path2: PathBuf = path.to_path_buf(); 13 | path2.push("leanpkg.path"); 14 | if path2.exists() { return Some(path2) } 15 | path = path.parent()? 16 | } 17 | } 18 | 19 | pub struct LeanPath(pub Vec); 20 | 21 | fn name_to_path(n: &Name2) -> Option { 22 | match n { 23 | Name2::Anon => Some(PathBuf::new()), 24 | Name2::Str(ref n, ref s) => name_to_path(n).map(|mut p| {p.push(s.clone()); p}), 25 | Name2::Num{..} => None 26 | } 27 | } 28 | 29 | impl LeanPath { 30 | 31 | pub fn new(args: &args::Args) -> io::Result { 32 | let path = get_leanpkg_path_file().unwrap_or_else(|| 33 | panic!("can't find leanpkg.path; make sure you are in a lean project")); 34 | let mut res = Vec::new(); 35 | for l in BufReader::new(File::open(&path)?).lines() { 36 | let l = l?; 37 | if l.starts_with("path ") { 38 | res.push(path.parent().unwrap().join(&l[5..])); 39 | } else if l == "builtin_path" { 40 | let lib = args.library().unwrap_or_else(|| 41 | panic!("can't find lean; use the -L switch to say where the lean root is")); 42 | let mut lib1 = lib.clone(); lib1.push("library"); res.push(lib1); 43 | let mut lib2 = lib.clone(); lib2.push("lib"); lib2.push("lean"); lib2.push("library"); res.push(lib2); 44 | } 45 | } 46 | Ok(LeanPath(res)) 47 | } 48 | 49 | pub fn find_path(&self, p: &Path) -> Option { 50 | for ref dir in &self.0 { 51 | let f = dir.join(p); 52 | if f.exists() { return Some(f) } 53 | } 54 | None 55 | } 56 | 57 | pub fn find_inner(&self, n: Name, ext: &str) -> Option<(Name, PathBuf)> { 58 | self.find_path(&name_to_path(&n)?.with_extension(ext)).map(|p| (n, p)) 59 | } 60 | 61 | pub fn find(&self, n: Name, ext: &str) -> Option<(Name, PathBuf)> { 62 | self.find_inner(n.clone(), ext).or_else(|| 63 | self.find_inner(name![n; default], ext)) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/args.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | use std::env; 3 | use std::path::{Path, PathBuf}; 4 | use getopts::Options; 5 | use std::process::exit; 6 | use crate::types; 7 | 8 | fn find_it

(exe_name: P) -> Option 9 | where P: AsRef { 10 | env::var_os("PATH").and_then(|paths| { 11 | env::split_paths(&paths).filter_map(|dir| { 12 | let mut full_path = dir.join(&exe_name); 13 | if cfg!(windows) { 14 | full_path.set_extension("exe"); 15 | } 16 | if full_path.is_file() { 17 | Some(full_path) 18 | } else { 19 | None 20 | } 21 | }).next() 22 | }) 23 | } 24 | 25 | pub enum Action { 26 | Dump(PathBuf), 27 | Dependents(types::Name), 28 | Lex(types::Name), 29 | Test(types::Name), 30 | None 31 | } 32 | 33 | pub struct Args { 34 | pub act: Action, 35 | program: String, 36 | opts: Options, 37 | library: Option 38 | } 39 | 40 | impl Args { 41 | pub fn print_usage_and_exit(&self, code: i32) -> ! { 42 | let brief = format!("Usage: {} path/to/file.olean [options]", self.program); 43 | print!("{}", self.opts.usage(&brief)); 44 | exit(code) 45 | } 46 | 47 | pub fn library(&self) -> Option { 48 | self.library.clone().or_else(|| 49 | Some(find_it("lean")?.parent()?.parent()?.to_path_buf())) 50 | } 51 | } 52 | 53 | pub fn args() -> io::Result { 54 | let args: Vec = env::args().collect(); 55 | 56 | let mut opts = Options::new(); 57 | opts.optopt("D", "dump", "dump olean parse", "FILE"); 58 | opts.optflag("L", "", "give location of lean library"); 59 | opts.optopt("d", "deps", "view all dependents of the target file", "lean.name"); 60 | opts.optopt("p", "", "set current working directory", "DIR"); 61 | opts.optopt("l", "", "test lexer", "lean.name"); 62 | opts.optopt("t", "", "testing", "lean.name"); 63 | opts.optflag("h", "help", "print this help menu"); 64 | let matches = opts.parse(&args[1..]).unwrap(); 65 | let mut args = Args { 66 | act: Action::None, 67 | program: args[0].clone(), 68 | opts, library: None }; 69 | if matches.opt_present("h") { args.print_usage_and_exit(0) } 70 | if let Some(s) = matches.opt_str("p") { env::set_current_dir(&s)? } 71 | if let Some(s) = matches.opt_str("D") { 72 | args.act = Action::Dump(PathBuf::from(s)) 73 | } 74 | if let Some(s) = matches.opt_str("L") { 75 | args.library = Some(PathBuf::from(s)) 76 | } 77 | if let Some(s) = matches.opt_str("d") { 78 | args.act = Action::Dependents(types::parse_name(&s)) 79 | } 80 | if let Some(s) = matches.opt_str("l") { 81 | args.act = Action::Lex(types::parse_name(&s)) 82 | } 83 | if let Some(s) = matches.opt_str("t") { 84 | args.act = Action::Test(types::parse_name(&s)) 85 | } 86 | if matches.opt_present("h") { 87 | args.print_usage_and_exit(0) 88 | } 89 | Ok(args) 90 | } 91 | -------------------------------------------------------------------------------- /src/trie/last_ancestor.rs: -------------------------------------------------------------------------------- 1 | //! This module contains an iterator-like interface to a longest-key search. 2 | //! 3 | //! Given a fixed Trie representing a set of keys, we want to find the longest 4 | //! key in the Trie that matches an initial sequence of the input key stream. 5 | //! The input key is fed piecemeal, though; we keep track of the search in progress 6 | //! and report whether we have seen enough of the stream to determine the answer, 7 | //! or if we need more data. 8 | 9 | use super::{NibbleVec, TrieNode, TrieKey}; 10 | use super::keys::{match_keys, KeyMatch}; 11 | 12 | #[derive(Debug)] 13 | pub struct LastAncestorIter<'a, V> { 14 | trie: &'a TrieNode, 15 | best: Option<(&'a V, usize)>, 16 | depth: usize, 17 | progress: usize 18 | } 19 | 20 | type SearchResult<'a, V> = Result, LastAncestorIter<'a, V>>; 21 | 22 | impl<'a, V> LastAncestorIter<'a, V> { 23 | /// Create a new iterator. 24 | pub fn new(trie: &TrieNode) -> LastAncestorIter { 25 | LastAncestorIter { trie, best: None, depth: trie.key.len(), progress: 0 } 26 | } 27 | 28 | /// Input some key data into the iterator. Returns either `Done(res)` 29 | /// if the search is finished, and `res` is the value and length of the 30 | /// longest initial sequence of the key stream with a value, or `Next(iter)` 31 | /// to request more data from the stream with `iter` as the continuation. 32 | pub fn next(self, key: &K) -> SearchResult<'a, V> { 33 | self.next_nv(&key.encode()) 34 | } 35 | 36 | /// Input some key data into the iterator. Returns either `Done(res)` 37 | /// if the search is finished, and `res` is the value and length of the 38 | /// longest initial sequence of the key stream with a value, or `Next(iter)` 39 | /// to request more data from the stream with `iter` as the continuation. 40 | pub fn next_nv(mut self, key: &NibbleVec) -> SearchResult<'a, V> { 41 | match match_keys(self.progress, &self.trie.key, key) { 42 | KeyMatch::Partial(_) => return Ok(self.best), 43 | KeyMatch::SecondPrefix | KeyMatch::Full => { 44 | self.progress += key.len(); 45 | return Err(self) 46 | }, 47 | KeyMatch::FirstPrefix => { 48 | let mut depth = self.trie.key.len() - self.progress; 49 | loop { 50 | if let Some(v) = self.trie.value() { 51 | self.best = Some((v, self.depth)); 52 | } 53 | let bucket = key.get(depth) as usize; 54 | if let Some(ref child) = self.trie.children[bucket] { 55 | self.trie = child; 56 | self.depth += child.key.len(); 57 | match match_keys(depth, key, &child.key) { 58 | KeyMatch::SecondPrefix => { 59 | depth += child.key.len(); 60 | } 61 | KeyMatch::FirstPrefix | KeyMatch::Full => { 62 | self.progress = key.len() - depth; 63 | return Err(self) 64 | } 65 | KeyMatch::Partial(_) => return Ok(self.best), 66 | } 67 | } else { 68 | return Ok(self.best) 69 | } 70 | } 71 | } 72 | } 73 | } 74 | 75 | /// Input an EOF to the iterator, forcing it to give the best result it 76 | /// has found so far. 77 | pub fn finish(mut self) -> Option<(&'a V, usize)> { 78 | if self.trie.key.len() == self.progress { 79 | if let Some(v) = self.trie.value() { 80 | self.best = Some((v, self.depth)) 81 | } 82 | } 83 | self.best 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/trie/trie_common.rs: -------------------------------------------------------------------------------- 1 | use super::iter::*; 2 | use super::trie_node::TrieNode; 3 | use super::{NibbleVec, SubTrie, SubTrieMut, Trie}; 4 | 5 | /// Common functionality available for tries and subtries. 6 | pub trait TrieCommon<'a, V: 'a>: ContainsTrieNode<'a, V> 7 | where 8 | Self: Sized, 9 | { 10 | /// Get the key stored at this node, if any. 11 | fn key(self) -> &'a NibbleVec { 12 | &self.trie_node().key 13 | } 14 | 15 | /// Get the value stored at this node, if any. 16 | fn value(self) -> Option<&'a V> { 17 | self.trie_node().value() 18 | } 19 | 20 | /// Number of key/value pairs stored in this trie. 21 | fn len(self) -> usize; 22 | 23 | /// Determine if the Trie contains 0 key-value pairs. 24 | fn is_empty(self) -> bool { 25 | self.len() == 0 26 | } 27 | 28 | /// Determine if the trie is a leaf node (has no children). 29 | fn is_leaf(self) -> bool { 30 | self.trie_node().child_count == 0 31 | } 32 | 33 | /// Return an iterator over the keys and values of the Trie. 34 | fn iter(self) -> Iter<'a, V> { 35 | Iter::new(self.trie_node()) 36 | } 37 | 38 | /// Return an iterator over the keys of the Trie. 39 | fn keys(self) -> Keys<'a, V> { 40 | Keys::new(self.iter()) 41 | } 42 | 43 | /// Return an iterator over the values of the Trie. 44 | fn values(self) -> Values<'a, V> { 45 | Values::new(self.trie_node()) 46 | } 47 | 48 | /// Return an iterator over the child subtries of this node. 49 | fn children(self) -> Children<'a, V>; 50 | 51 | /// Get the prefix of this node. 52 | fn prefix(self) -> &'a NibbleVec { 53 | &self.trie_node().key 54 | } 55 | } 56 | 57 | /// Helper trait for Trie/SubTrie/SubTrieMut, which all contain a trie node. 58 | pub trait ContainsTrieNode<'a, V: 'a> { 59 | fn trie_node(self) -> &'a TrieNode; 60 | } 61 | 62 | /// Regular trie. 63 | impl<'a, V: 'a> ContainsTrieNode<'a, V> for &'a Trie { 64 | fn trie_node(self) -> &'a TrieNode { 65 | &self.node 66 | } 67 | } 68 | 69 | impl<'a, V: 'a> TrieCommon<'a, V> for &'a Trie { 70 | fn len(self) -> usize { 71 | self.length 72 | } 73 | 74 | fn children(self) -> Children<'a, V> { 75 | Children::new(self.node.key.clone(), &self.node) 76 | } 77 | } 78 | 79 | /// Subtrie. 80 | impl<'a: 'b, 'b, V: 'a> ContainsTrieNode<'a, V> for &'b SubTrie<'a, V> { 81 | fn trie_node(self) -> &'a TrieNode { 82 | self.node 83 | } 84 | } 85 | 86 | impl<'a: 'b, 'b, V: 'a> TrieCommon<'a, V> for &'b SubTrie<'a, V> { 87 | fn len(self) -> usize { 88 | self.node.compute_size() 89 | } 90 | 91 | fn children(self) -> Children<'a, V> { 92 | Children::new(self.prefix.clone(), self.node) 93 | } 94 | } 95 | 96 | /// Mutable subtrie *by value* (consumes the subtrie). 97 | impl<'a, V: 'a> ContainsTrieNode<'a, V> for SubTrieMut<'a, V> { 98 | fn trie_node(self) -> &'a TrieNode { 99 | self.node 100 | } 101 | } 102 | 103 | impl<'a, V: 'a> TrieCommon<'a, V> for SubTrieMut<'a, V> { 104 | /// **Computes** from scratch. 105 | fn len(self) -> usize { 106 | self.node.compute_size() 107 | } 108 | 109 | fn children(self) -> Children<'a, V> { 110 | Children::new(self.prefix.clone(), self.node) 111 | } 112 | } 113 | 114 | /// Mutable subtrie *by reference* (doesn't consume the subtrie, but limited). 115 | impl<'a: 'b, 'b, V: 'a> ContainsTrieNode<'b, V> for &'b SubTrieMut<'a, V> { 116 | fn trie_node(self) -> &'b TrieNode { 117 | self.node 118 | } 119 | } 120 | 121 | impl<'a: 'b, 'b, V: 'a> TrieCommon<'b, V> for &'b SubTrieMut<'a, V> { 122 | fn len(self) -> usize { 123 | self.node.compute_size() 124 | } 125 | 126 | fn children(self) -> Children<'b, V> { 127 | Children::new(self.prefix.clone(), self.node) 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/tokens.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | use crate::trie::{Trie, TrieCommon, iter::Values, TrieKey, LastAncestorIter}; 3 | use crate::loader::Loader; 4 | use crate::types::{Modification, KToken}; 5 | 6 | static MAX_PREC: u32 = 1024; 7 | static ARROW_PREC: u32 = 25; 8 | static PLUS_PREC: u32 = 65; 9 | static TOKENS: &[(&str, u32)] = &[ 10 | ("fun", 0), ("Pi", 0), ("let", 0), ("in", 0), ("at", 0), 11 | ("have", 0), ("assume", 0), ("show", 0), ("suffices", 0), 12 | ("do", 0), ("if", 0), ("then", 0), ("else", 0), ("by", 0), 13 | ("hiding", 0), ("replacing", 0), ("renaming", 0), 14 | ("from", 0), ("(", MAX_PREC), ("`(", MAX_PREC), ("``(", MAX_PREC), 15 | ("```(", MAX_PREC), ("`[", MAX_PREC), ("`", MAX_PREC), 16 | ("%%", MAX_PREC), ("()", MAX_PREC), ("(::)", MAX_PREC), (")", 0), ("'", 0), 17 | ("{", MAX_PREC), ("}", 0), ("_", MAX_PREC), 18 | ("[", MAX_PREC), ("#[", MAX_PREC), ("]", 0), ("⦃", MAX_PREC), ("⦄", 0), (".(", 0), 19 | ("{!", MAX_PREC), ("!}", 0), 20 | ("Type", MAX_PREC), ("Type*", MAX_PREC), ("Sort", MAX_PREC), ("Sort*", MAX_PREC), 21 | ("(:", MAX_PREC), (":)", 0), (".(", MAX_PREC), ("._", MAX_PREC), 22 | ("⟨", MAX_PREC), ("⟩", 0), ("^", 0), 23 | ("//", 0), ("|", 0), ("with", 0), ("without", 0), ("..", 0), ("...", 0), (",", 0), 24 | (".", 0), (":", 0), ("!", 0), ("calc", 0), (":=", 0), ("--", 0), ("#", MAX_PREC), 25 | ("/-", 0), ("/--", 0), ("/-!", 0), ("begin", MAX_PREC), ("using", 0), 26 | ("@@", MAX_PREC), ("@", MAX_PREC), 27 | ("sorry", MAX_PREC), ("+", PLUS_PREC), ("->", ARROW_PREC), ("<-", 0), 28 | ("match", 0), ("^.", MAX_PREC+1), 29 | ("renaming", 0), ("extends", 0)]; 30 | 31 | static COMMANDS: &[&str] = &[ 32 | "theorem", "axiom", "axioms", "variable", "protected", "private", "hide", 33 | "definition", "meta", "mutual", "example", "noncomputable", "abbreviation", 34 | "variables", "parameter", "parameters", "constant", "constants", 35 | "using_well_founded", "[whnf]", 36 | "end", "namespace", "section", "prelude", 37 | "import", "inductive", "coinductive", "structure", "class", "universe", "universes", "local", 38 | "precedence", "reserve", "infixl", "infixr", "infix", "postfix", "prefix", "notation", 39 | "set_option", "open", "export", "@[", 40 | "attribute", "instance", "include", "omit", "init_quotient", 41 | "declare_trace", "add_key_equivalence", 42 | "run_cmd", "#check", "#reduce", "#eval", "#print", "#help", "#exit", 43 | "#compile", "#unify"]; 44 | 45 | static ALIASES: &[(&str, &str, Option)] = &[ 46 | ("λ", "fun", Some(0)), 47 | ("forall", "Pi", Some(0)), ("∀", "Pi", Some(0)), ("Π", "Pi", Some(0)), 48 | ("(|", "⟨", Some(MAX_PREC)), ("|)", "⟩", Some(0)), 49 | ("→", "->", Some(ARROW_PREC)), ("←", "<-", Some(0)), 50 | ("lemma", "theorem", None), ("def", "definition", None)]; 51 | 52 | #[derive(Debug)] pub struct TokenTable(Trie); 53 | 54 | impl TokenTable { 55 | pub fn new() -> TokenTable { 56 | let mut table = TokenTable(Trie::new()); 57 | for (s, prec) in TOKENS { 58 | table.insert(KToken{tk: s.to_string(), prec: Some(*prec)}) } 59 | for s in COMMANDS { 60 | table.insert(KToken{tk: s.to_string(), prec: None}) } 61 | for (s1, s2, prec) in ALIASES { 62 | table.0.insert(s1, KToken{tk: s2.to_string(), prec: *prec}); } 63 | table 64 | } 65 | 66 | fn insert(&mut self, tk: KToken) { 67 | self.0.insert_nv(tk.tk.encode(), tk); 68 | } 69 | 70 | pub fn search(&self) -> TokenSearch { self.0.last_ancestor_iter() } 71 | 72 | pub fn load(&mut self, load: &mut Loader) -> io::Result<()> { 73 | for n in &load.order { 74 | let mods = Loader::get_mods(&mut load.map, n.clone())?; 75 | for m in mods { 76 | match m { 77 | Modification::Token(tk) => self.insert(tk.clone()), 78 | _ => () 79 | } 80 | } 81 | } 82 | Ok(()) 83 | } 84 | } 85 | 86 | impl<'a> IntoIterator for &'a TokenTable { 87 | type Item = &'a KToken; 88 | type IntoIter = Values<'a, KToken>; 89 | fn into_iter(self) -> Self::IntoIter { self.0.values() } 90 | } 91 | 92 | type TokenSearch<'a> = LastAncestorIter<'a, KToken>; 93 | -------------------------------------------------------------------------------- /src/trie/subtrie.rs: -------------------------------------------------------------------------------- 1 | use super::keys::*; 2 | use super::trie_node::TrieNode; 3 | use super::{NibbleVec, SubTrie, SubTrieMut, SubTrieResult}; 4 | 5 | impl<'a, V> SubTrie<'a, V> { 6 | /// Look up the value for the given key, which should be an extension of this subtrie's key. 7 | /// 8 | /// The key may be any borrowed form of the trie's key type, but TrieKey on the borrowed 9 | /// form *must* match those for the key type 10 | pub fn get(&self, key: &K) -> SubTrieResult<&V> { 11 | subtrie_get(&self.prefix, self.node, key) 12 | } 13 | 14 | /// Move the view to a subkey. The new view will be looking at the original key with 15 | /// the encoding of this subkey appended. 16 | pub fn to_subkey(self, subkey: &K) -> Option> { 17 | self.to_subkey_nv(&subkey.encode()) 18 | } 19 | 20 | /// Move the view to a subkey, specified directly by its `NibbleVec` encoding. 21 | /// The input view is consumed. 22 | pub fn to_subkey_nv(self, subkey: &NibbleVec) -> Option> { 23 | match self { 24 | SubTrie {prefix, node} => 25 | node.get(subkey).map(|node| 26 | SubTrie { 27 | prefix: prefix.join(subkey), 28 | node 29 | }) 30 | } 31 | } 32 | } 33 | 34 | fn subtrie_get<'a, K: TrieKey + ?Sized, V>( 35 | prefix: &NibbleVec, 36 | node: &'a TrieNode, 37 | key: &K, 38 | ) -> SubTrieResult<&'a V> { 39 | let key_enc = key.encode(); 40 | match match_keys(0, prefix, &key_enc) { 41 | KeyMatch::Full => Ok(node.value()), 42 | KeyMatch::FirstPrefix => Ok(node 43 | .get(&stripped(key_enc, prefix)) 44 | .and_then(TrieNode::value)), 45 | _ => Err(()), 46 | } 47 | } 48 | 49 | impl<'a, V> SubTrieMut<'a, V> { 50 | /// Mutable reference to the node's value. 51 | pub fn value_mut(&mut self) -> Option<&mut V> { 52 | self.node.value_mut() 53 | } 54 | 55 | /// Look up the value for the given key, which should be an extension of this subtrie's key. 56 | /// 57 | /// The key may be any borrowed form of the trie's key type, but TrieKey on the borrowed 58 | /// form *must* match those for the key type 59 | pub fn get(&self, key: &K) -> SubTrieResult<&V> { 60 | subtrie_get(&self.prefix, &*self.node, key) 61 | } 62 | 63 | /// Move the view to a subkey. The new view will be looking at the original key with 64 | /// the encoding of this subkey appended. 65 | pub fn to_subkey(self, subkey: &K) -> Option> { 66 | self.to_subkey_nv(&subkey.encode()) 67 | } 68 | 69 | /// Move the view to a subkey, specified directly by its `NibbleVec` encoding. 70 | /// The input view is consumed. 71 | pub fn to_subkey_nv(self, subkey: &NibbleVec) -> Option> { 72 | match self { 73 | SubTrieMut {length, prefix, node} => 74 | node.get_mut(subkey).map(move |node| 75 | SubTrieMut { 76 | length, 77 | prefix: prefix.join(subkey), 78 | node 79 | }) 80 | } 81 | } 82 | 83 | /// Insert a value in this subtrie. The key should be an extension of this subtrie's key. 84 | pub fn insert(&mut self, key: &K, value: V) -> SubTrieResult { 85 | let key_enc = key.encode(); 86 | let previous = match match_keys(0, &self.prefix, &key_enc) { 87 | KeyMatch::Full => self.node.replace_value(value), 88 | KeyMatch::FirstPrefix => self 89 | .node 90 | .insert(stripped(key_enc, &self.prefix), value), 91 | _ => { 92 | return Err(()); 93 | } 94 | }; 95 | 96 | if previous.is_none() { 97 | *self.length += 1; 98 | } 99 | 100 | Ok(previous) 101 | } 102 | 103 | /// Remove a value from this subtrie. The key should be an extension of this subtrie's key. 104 | pub fn remove(&mut self, key: &K) -> SubTrieResult { 105 | self.remove_nv(&key.encode()) 106 | } 107 | 108 | /// Remove a value from this subtrie. The key should be an extension of this subtrie's key. 109 | pub fn remove_nv(&mut self, key: &NibbleVec) -> SubTrieResult { 110 | let removed = match match_keys(0, &self.prefix, key) { 111 | KeyMatch::Full => self.node.take_value(), 112 | KeyMatch::FirstPrefix => self.node.remove(key), 113 | _ => { 114 | return Err(()); 115 | } 116 | }; 117 | 118 | if removed.is_some() { 119 | *self.length -= 1; 120 | } 121 | 122 | Ok(removed) 123 | } 124 | } 125 | 126 | fn stripped(mut key: NibbleVec, prefix: &NibbleVec) -> NibbleVec { 127 | key.split(prefix.len()) 128 | } 129 | -------------------------------------------------------------------------------- /src/trie/keys.rs: -------------------------------------------------------------------------------- 1 | use endian_type::{BigEndian, LittleEndian}; 2 | use super::NibbleVec; 3 | use std::path::PathBuf; 4 | use std::path::Path; 5 | use std::ffi::OsString; 6 | 7 | /// Trait for types which can be used to key a Radix Trie. 8 | /// 9 | /// Types that implement this trait should be convertible to a vector of half-bytes (nibbles) 10 | /// such that no two instances of the type convert to the same vector. 11 | /// To protect against faulty behaviour, the trie will **panic** if it finds two distinct keys 12 | /// of type `K` which encode to the same `NibbleVec`, so be careful! 13 | /// 14 | /// If you would like to implement this trait for your own type, you need to implement 15 | /// *either* `encode_bytes` or `encode`. You only need to implement one of the two. 16 | /// If you don't implement one, your code will **panic** as soon you use the trie. 17 | /// There is no performance penalty for implementing `encode_bytes` instead of `encode`, 18 | /// so it is preferred except in the case where you require half-byte precision. 19 | /// 20 | /// Many standard types implement this trait already. Integer types are encoded *big-endian* 21 | /// by default but can be encoded little-endian using the `LittleEndian` wrapper type. 22 | pub trait TrieKey: PartialEq + Eq { 23 | /// Encode a value as a vector of bytes. 24 | fn encode_bytes(&self) -> Vec { 25 | panic!("implement this method or TrieKey::encode"); 26 | } 27 | 28 | /// Encode a value as a NibbleVec. 29 | fn encode(&self) -> NibbleVec { 30 | NibbleVec::from_byte_vec(self.encode_bytes()) 31 | } 32 | } 33 | 34 | /// Key comparison result. 35 | #[derive(Debug)] 36 | pub enum KeyMatch { 37 | /// The keys match up to the given index. 38 | Partial(usize), 39 | /// The first key is a prefix of the second. 40 | FirstPrefix, 41 | /// The second key is a prefix of the first. 42 | SecondPrefix, 43 | /// The keys match exactly. 44 | Full, 45 | } 46 | 47 | /// Compare two Trie keys. 48 | /// 49 | /// Compares `first[start_idx .. ]` to `second`, i.e. only looks at a slice of the first key. 50 | pub fn match_keys(start_idx: usize, first: &NibbleVec, second: &NibbleVec) -> KeyMatch { 51 | let first_len = first.len() - start_idx; 52 | let min_length = ::std::cmp::min(first_len, second.len()); 53 | 54 | for i in 0..min_length { 55 | if first.get(start_idx + i) != second.get(i) { 56 | return KeyMatch::Partial(i); 57 | } 58 | } 59 | 60 | match (first_len, second.len()) { 61 | (x, y) if x < y => KeyMatch::FirstPrefix, 62 | (x, y) if x == y => KeyMatch::Full, 63 | _ => KeyMatch::SecondPrefix, 64 | } 65 | } 66 | 67 | // --- TrieKey Implementations for standard types --- /// 68 | 69 | // This blanket implementation goes into play when specialization is stabilized 70 | // impl TrieKey for T where T: Into> + Clone + Eq + PartialEq { 71 | // fn encode_bytes(&self) -> Vec { 72 | // self.clone().into() 73 | // } 74 | // } 75 | 76 | impl TrieKey for Vec { 77 | fn encode_bytes(&self) -> Vec { 78 | self.clone() 79 | } 80 | } 81 | 82 | impl TrieKey for [u8] { 83 | fn encode_bytes(&self) -> Vec { 84 | self.to_vec() 85 | } 86 | } 87 | 88 | impl TrieKey for String { 89 | fn encode_bytes(&self) -> Vec { 90 | self.as_bytes().encode_bytes() 91 | } 92 | } 93 | 94 | impl TrieKey for str { 95 | fn encode_bytes(&self) -> Vec { 96 | self.as_bytes().encode_bytes() 97 | } 98 | } 99 | 100 | impl<'a, T: ?Sized + TrieKey> TrieKey for &'a T { 101 | fn encode_bytes(&self) -> Vec { 102 | (**self).encode_bytes() 103 | } 104 | } 105 | 106 | impl<'a, T: ?Sized + TrieKey> TrieKey for &'a mut T { 107 | fn encode_bytes(&self) -> Vec { 108 | (**self).encode_bytes() 109 | } 110 | } 111 | 112 | impl TrieKey for i8 { 113 | fn encode_bytes(&self) -> Vec { 114 | let mut v: Vec = Vec::with_capacity(1); 115 | v.push(*self as u8); 116 | v 117 | } 118 | } 119 | 120 | impl TrieKey for u8 { 121 | fn encode_bytes(&self) -> Vec { 122 | let mut v: Vec = Vec::with_capacity(1); 123 | v.push(*self); 124 | v 125 | } 126 | } 127 | 128 | #[cfg(unix)] 129 | impl TrieKey for PathBuf { 130 | fn encode_bytes(&self) -> Vec { 131 | use std::os::unix::ffi::OsStringExt; 132 | let str: OsString = self.clone().into(); 133 | str.into_vec() 134 | } 135 | } 136 | 137 | #[cfg(unix)] 138 | impl TrieKey for Path { 139 | fn encode_bytes(&self) -> Vec { 140 | use std::os::unix::ffi::OsStrExt; 141 | self.as_os_str().as_bytes().encode_bytes() 142 | } 143 | } 144 | 145 | impl TrieKey for LittleEndian 146 | where 147 | T: Eq + Copy, 148 | { 149 | fn encode_bytes(&self) -> Vec { 150 | self.as_bytes().encode_bytes() 151 | } 152 | } 153 | 154 | impl TrieKey for BigEndian 155 | where 156 | T: Eq + Copy, 157 | { 158 | fn encode_bytes(&self) -> Vec { 159 | self.as_bytes().to_vec() 160 | } 161 | } 162 | 163 | macro_rules! int_keys { 164 | ( $( $t:ty ),* ) => { 165 | $( 166 | impl TrieKey for $t { 167 | fn encode_bytes(&self) -> Vec { 168 | let be: BigEndian<$t> = From::from(*self); 169 | be.encode_bytes() 170 | } 171 | } 172 | )* 173 | }; 174 | } 175 | 176 | int_keys!(u16, u32, u64, i16, i32, i64, usize, isize); 177 | -------------------------------------------------------------------------------- /src/trie/iter.rs: -------------------------------------------------------------------------------- 1 | //! Iterators over key-value pairs, keys, values and child subtries. 2 | 3 | use std::iter::{FilterMap, FromIterator, Map}; 4 | use std::slice; 5 | 6 | use super::trie_node::TrieNode; 7 | use super::{NibbleVec, SubTrie, Trie, TrieKey}; 8 | 9 | // MY EYES. 10 | type Child = Box>; 11 | type RawChildIter<'a, V> = slice::Iter<'a, Option>>; 12 | type ChildMapFn<'a, V> = fn(&'a Option>) -> Option<&'a Child>; 13 | type ChildIter<'a, V> = FilterMap, ChildMapFn<'a, V>>; 14 | 15 | /// Iterator over the keys and values of a Trie. 16 | pub struct Iter<'a, V: 'a> { 17 | root: &'a TrieNode, 18 | root_visited: bool, 19 | key: NibbleVec, 20 | stack: Vec<(usize, RawChildIter<'a, V>)>, 21 | } 22 | 23 | impl<'a, V> Iter<'a, V> { 24 | // TODO: make this private somehow (and same for the other iterators). 25 | pub fn new(root: &'a TrieNode) -> Iter<'a, V> { 26 | Iter { 27 | root, 28 | root_visited: false, 29 | key: NibbleVec::new(), 30 | stack: vec![], 31 | } 32 | } 33 | } 34 | 35 | /// Iterator over the keys of a Trie. 36 | pub struct Keys<'a, V: 'a> { 37 | inner: Map, KeyMapFn<'a, V>>, 38 | } 39 | 40 | type KeyMapFn<'a, V> = fn((NibbleVec, &'a V)) -> NibbleVec; 41 | 42 | impl<'a, V> Keys<'a, V> { 43 | pub fn new(iter: Iter<'a, V>) -> Keys<'a, V> { 44 | Keys { 45 | inner: iter.map(|kv| kv.0), 46 | } 47 | } 48 | } 49 | 50 | impl<'a, V> Iterator for Keys<'a, V> { 51 | type Item = NibbleVec; 52 | 53 | fn next(&mut self) -> Option { 54 | self.inner.next() 55 | } 56 | } 57 | 58 | /// Iterator over the values of a Trie. 59 | pub struct Values<'a, V: 'a> { 60 | root: &'a TrieNode, 61 | root_visited: bool, 62 | stack: Vec>, 63 | } 64 | 65 | impl<'a, V> Values<'a, V> { 66 | pub fn new(root: &'a TrieNode) -> Values<'a, V> { 67 | Values { 68 | root, 69 | root_visited: false, 70 | stack: vec![], 71 | } 72 | } 73 | } 74 | 75 | impl<'a, V> Iterator for Values<'a, V> { 76 | type Item = &'a V; 77 | 78 | fn next(&mut self) -> Option { 79 | // Visit each node as it is reached from its parent (with special root handling). 80 | if !self.root_visited { 81 | self.root_visited = true; 82 | self.stack.push(self.root.children.iter()); 83 | if let Some(v) = self.root.value() { 84 | return Some(v); 85 | } 86 | } 87 | 88 | loop { 89 | let action = match self.stack.last_mut() { 90 | Some(stack_top) => stack_top.next(), 91 | None => return None, 92 | }; 93 | 94 | match action { 95 | Some(Some(trie)) => { 96 | self.stack.push(trie.children.iter()); 97 | if let Some(v) = trie.value() { 98 | return Some(v); 99 | } 100 | } 101 | Some(None) => (), 102 | None => { 103 | self.stack.pop(); 104 | } 105 | } 106 | } 107 | } 108 | } 109 | 110 | /// Iterator over the child subtries of a trie. 111 | pub struct Children<'a, V: 'a> { 112 | prefix: NibbleVec, 113 | inner: ChildIter<'a, V>, 114 | } 115 | 116 | impl<'a, V> Children<'a, V> { 117 | pub fn new(key: NibbleVec, node: &'a TrieNode) -> Self { 118 | Children { 119 | prefix: key, 120 | inner: node.child_iter(), 121 | } 122 | } 123 | } 124 | 125 | impl<'a, V> Iterator for Children<'a, V> { 126 | type Item = SubTrie<'a, V>; 127 | 128 | fn next(&mut self) -> Option> { 129 | self.inner.next().map(|node| SubTrie { 130 | prefix: self.prefix.clone().join(&node.key), 131 | node: node, 132 | }) 133 | } 134 | } 135 | 136 | impl TrieNode { 137 | /// Helper function to get all the non-empty children of a node. 138 | fn child_iter(&self) -> ChildIter { 139 | fn id(x: &Option>) -> Option<&Child> { 140 | x.as_ref() 141 | } 142 | 143 | self.children.iter().filter_map(id) 144 | } 145 | } 146 | 147 | impl<'a, V> Iterator for Iter<'a, V> { 148 | type Item = (NibbleVec, &'a V); 149 | 150 | fn next(&mut self) -> Option { 151 | // Visit each node as it is reached from its parent (with special root handling). 152 | if !self.root_visited { 153 | self.root_visited = true; 154 | self.stack.push((self.key.len(), self.root.children.iter())); 155 | self.key = self.root.key.clone(); 156 | if let Some(v) = self.root.value() { 157 | return Some((self.key.clone(), v)); 158 | } 159 | } 160 | 161 | loop { 162 | let (n, action) = match self.stack.last_mut() { 163 | Some((n, stack_top)) => (*n, stack_top.next()), 164 | None => return None, 165 | }; 166 | 167 | match action { 168 | Some(Some(trie)) => { 169 | self.stack.push((n, trie.children.iter())); 170 | take_mut::take(&mut self.key, |k| k.join(&trie.key)); 171 | if let Some(v) = trie.value() { 172 | return Some((self.key.clone(), v)); 173 | } 174 | } 175 | Some(None) => (), 176 | None => { 177 | self.key.split(self.key.len() - n); 178 | self.stack.pop(); 179 | } 180 | } 181 | } 182 | } 183 | } 184 | 185 | impl FromIterator<(K, V)> for Trie { 186 | fn from_iter(iter: T) -> Trie 187 | where 188 | T: IntoIterator, 189 | { 190 | let mut trie: Trie = Trie::new(); 191 | for (k, v) in iter { 192 | trie.insert(&k, v); 193 | } 194 | trie 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /src/trie/trie.rs: -------------------------------------------------------------------------------- 1 | use super::traversal::DescendantResult::*; 2 | use super::trie_node::TrieNode; 3 | use super::{NibbleVec, SubTrie, SubTrieMut, Trie, TrieCommon, TrieKey, LastAncestorIter}; 4 | 5 | impl Trie { 6 | /// Create an empty Trie. 7 | pub fn new() -> Trie { 8 | Trie { 9 | length: 0, 10 | node: TrieNode::new(), 11 | } 12 | } 13 | 14 | /// View the root of this trie as a SubTrie. 15 | pub fn root(&self) -> SubTrie { 16 | SubTrie { 17 | prefix: NibbleVec::new(), 18 | node: &self.node, 19 | } 20 | } 21 | 22 | /// View the root of this trie as a SubTrieMut. 23 | pub fn root_mut(&mut self) -> SubTrieMut { 24 | SubTrieMut { 25 | prefix: NibbleVec::new(), 26 | length: &mut self.length, 27 | node: &mut self.node, 28 | } 29 | } 30 | 31 | /// Fetch a reference to the given key's corresponding value, if any. 32 | pub fn get(&self, key: &K) -> Option<&V> { 33 | self.get_nv(&key.encode()) 34 | } 35 | 36 | /// Fetch a reference to the given key's corresponding value, if any. 37 | pub fn get_nv(&self, key: &NibbleVec) -> Option<&V> { 38 | self.node 39 | .get(&key) 40 | .and_then(|t| t.value()) 41 | } 42 | 43 | /// Fetch a mutable reference to the given key's corresponding value, if any. 44 | pub fn get_mut(&mut self, key: &K) -> Option<&mut V> { 45 | self.get_mut_nv(&key.encode()) 46 | } 47 | 48 | /// Fetch a mutable reference to the given key's corresponding value, if any. 49 | pub fn get_mut_nv(&mut self, key: &NibbleVec) -> Option<&mut V> { 50 | self.node 51 | .get_mut(&key) 52 | .and_then(|t| t.value_mut()) 53 | } 54 | 55 | /// Insert the given key-value pair, returning any previous value associated with the key. 56 | pub fn insert(&mut self, key: &K, value: V) -> Option { 57 | self.insert_nv(key.encode(), value) 58 | } 59 | 60 | /// Insert the given key-value pair, returning any previous value associated with the key. 61 | pub fn insert_nv(&mut self, key: NibbleVec, value: V) -> Option { 62 | let result = self.node.insert(key, value); 63 | if result.is_none() { 64 | self.length += 1; 65 | } 66 | result 67 | } 68 | 69 | /// Remove the value associated with the given key. 70 | pub fn remove(&mut self, key: &K) -> Option { 71 | self.remove_nv(&key.encode()) 72 | } 73 | 74 | /// Remove the value associated with the given key. 75 | pub fn remove_nv(&mut self, key: &NibbleVec) -> Option { 76 | let removed = self.node.remove(key); 77 | if removed.is_some() { 78 | self.length -= 1; 79 | } 80 | removed 81 | } 82 | 83 | /// Get a mutable reference to the value stored at this node, if any. 84 | pub fn value_mut(&mut self) -> Option<&mut V> { 85 | self.node.value_mut() 86 | } 87 | 88 | /// Fetch a reference to the subtrie for a given key. 89 | pub fn subtrie<'a, K: TrieKey + ?Sized>(&'a self, key: &K) -> Option> { 90 | let key_fragments = key.encode(); 91 | self.node 92 | .get(&key_fragments) 93 | .map(|node| node.as_subtrie(key_fragments)) 94 | } 95 | 96 | /// Fetch a mutable reference to the subtrie for a given key. 97 | pub fn subtrie_mut<'a, K: TrieKey + ?Sized>(&'a mut self, key: &K) -> Option> { 98 | let key_fragments = key.encode(); 99 | let length_ref = &mut self.length; 100 | self.node 101 | .get_mut(&key_fragments) 102 | .map(move |node| node.as_subtrie_mut(key_fragments, length_ref)) 103 | } 104 | 105 | /// Fetch a reference to the closest ancestor node of the given key. 106 | /// 107 | /// If `key` is encoded as byte-vector `b`, return the node `n` in the tree 108 | /// such that `n`'s key's byte-vector is the longest possible prefix of `b`, and `n` 109 | /// has a value. 110 | /// 111 | /// Invariant: `result.is_some() => result.key_value.is_some()`. 112 | /// 113 | /// The key may be any borrowed form of the trie's key type, but TrieKey on the borrowed 114 | /// form *must* match those for the key type 115 | pub fn get_ancestor<'a, K: TrieKey + ?Sized>(&'a self, key: &K) -> Option> { 116 | let mut key_fragments = key.encode(); 117 | self.node 118 | .get_ancestor(&key_fragments) 119 | .map(|(node, node_key_len)| { 120 | key_fragments.split(node_key_len); 121 | node.as_subtrie(key_fragments) 122 | }) 123 | } 124 | 125 | /// Fetch the closest ancestor *value* for a given key. 126 | /// 127 | /// See `get_ancestor` for precise semantics, this is just a shortcut. 128 | /// 129 | /// The key may be any borrowed form of the trie's key type, but TrieKey on the borrowed 130 | /// form *must* match those for the key type 131 | pub fn get_ancestor_value(&self, key: &K) -> Option<&V> { 132 | self.get_ancestor(key).and_then(|t| t.node.value()) 133 | } 134 | 135 | /// The key may be any borrowed form of the trie's key type, but TrieKey on the borrowed 136 | /// form *must* match those for the key type 137 | pub fn get_raw_ancestor<'a, K: TrieKey + ?Sized>(&'a self, key: &K) -> SubTrie<'a, V> { 138 | let mut nv = key.encode(); 139 | let (ancestor_node, depth) = self.node.get_raw_ancestor(&nv); 140 | nv.split(depth); 141 | ancestor_node.as_subtrie(nv) 142 | } 143 | 144 | /// Fetch the closest descendant for a given key. 145 | /// 146 | /// If the key is in the trie, this is the same as `subtrie`. 147 | /// 148 | /// The key may be any borrowed form of the trie's key type, but TrieKey on the borrowed 149 | /// form *must* match those for the key type 150 | pub fn get_raw_descendant<'a, K: TrieKey + ?Sized>(&'a self, key: &K) -> Option> { 151 | let mut nv = key.encode(); 152 | self.node.get_raw_descendant(&nv).map(|desc| { 153 | let (node, prefix) = match desc { 154 | NoModification(node) => (node, nv), 155 | ExtendKey(node, depth, extension) => { 156 | nv.split(depth); 157 | (node, nv.join(extension)) 158 | } 159 | }; 160 | node.as_subtrie(prefix) 161 | }) 162 | } 163 | 164 | /// Return a stream consumer that searches for the longest key in the trie that 165 | /// is an initial sequence of the stream, and has a value. 166 | /// 167 | /// Use `LastAncestorIter::next` and `LastAncestorIter::finish` to input key data 168 | /// to the iterator. 169 | pub fn last_ancestor_iter(&self) -> LastAncestorIter { 170 | LastAncestorIter::new(&self.node) 171 | } 172 | 173 | /// Take a function `f` and apply it to the value stored at `key`. 174 | /// 175 | /// If no value is stored at `key`, store `default`. 176 | pub fn map_with_default(&mut self, key: &K, f: F, default: V) { 177 | if let Some(v) = self.get_mut(key) { 178 | f(v); 179 | return; 180 | } 181 | self.insert(key, default); 182 | } 183 | 184 | /// Check that the Trie invariants are satisfied - you shouldn't ever have to call this! 185 | /// Quite slow! 186 | #[doc(hidden)] 187 | pub fn check_integrity(&self) -> bool { 188 | let (ok, length) = self.node.check_integrity_recursive(0); 189 | ok && length == self.length 190 | } 191 | } 192 | 193 | impl PartialEq for Trie { 194 | fn eq(&self, other: &Trie) -> bool { 195 | if self.len() != other.len() { 196 | return false; 197 | } 198 | 199 | self.iter() 200 | .all(|(key, value)| other.get_nv(&key).map_or(false, |v| *value == *v)) 201 | } 202 | } 203 | 204 | impl Default for Trie { 205 | fn default() -> Self { 206 | Self::new() 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /src/trie/trie_node.rs: -------------------------------------------------------------------------------- 1 | use std::ops::{Deref, DerefMut}; 2 | use std::default::Default; 3 | use super::{NibbleVec, SubTrie, SubTrieMut, BRANCH_FACTOR}; 4 | 5 | #[derive(Debug)] 6 | pub struct TrieNode { 7 | /// Key fragments/bits associated with this node, such that joining the keys from all 8 | /// parent nodes and this node is equal to the bit-encoding of this node's key. 9 | pub key: NibbleVec, 10 | 11 | /// The value stored at this node. 12 | pub value: Option>, 13 | 14 | /// The number of children which are Some rather than None. 15 | pub child_count: usize, 16 | 17 | /// The children of this node stored such that the first nibble of each child key 18 | /// dictates the child's bucket. 19 | pub children: [Option>>; BRANCH_FACTOR], 20 | } 21 | 22 | macro_rules! no_children { 23 | () => { 24 | [ 25 | None, None, None, None, None, None, None, None, None, None, None, None, None, None, 26 | None, None, 27 | ] 28 | }; 29 | } 30 | 31 | impl TrieNode { 32 | /// Create a value-less, child-less TrieNode. 33 | pub fn new() -> TrieNode { 34 | TrieNode { 35 | key: NibbleVec::new(), 36 | value: None, 37 | children: no_children![], 38 | child_count: 0, 39 | } 40 | } 41 | 42 | /// Create a TrieNode with no children. 43 | pub fn with_key_value(key_fragments: NibbleVec, value: V) -> TrieNode { 44 | TrieNode { 45 | key: key_fragments, 46 | value: Some(Box::new(value)), 47 | children: no_children![], 48 | child_count: 0, 49 | } 50 | } 51 | 52 | /// Get the value stored at this node, if any. 53 | pub fn value(&self) -> Option<&V> { 54 | self.value.as_ref().map(|v| v.deref()) 55 | } 56 | 57 | /// Get a mutable reference to the value stored at this node, if any. 58 | pub fn value_mut(&mut self) -> Option<&mut V> { 59 | self.value.as_mut().map(|v| v.deref_mut()) 60 | } 61 | 62 | /// Compute the number of keys and values in this node's subtrie. 63 | pub fn compute_size(&self) -> usize { 64 | let mut size = if self.value.is_some() { 1 } else { 0 }; 65 | 66 | for child in &self.children { 67 | if let Some(ref child) = *child { 68 | // TODO: could unroll this recursion 69 | size += child.compute_size(); 70 | } 71 | } 72 | 73 | size 74 | } 75 | 76 | /// Add a child at the given index, given that none exists there already. 77 | pub fn add_child(&mut self, idx: usize, node: Box>) { 78 | debug_assert!(self.children[idx].is_none()); 79 | self.child_count += 1; 80 | self.children[idx] = Some(node); 81 | } 82 | 83 | /// Remove a child at the given index, if it exists. 84 | pub fn take_child(&mut self, idx: usize) -> Option>> { 85 | self.children[idx].take().map(|node| { 86 | self.child_count -= 1; 87 | node 88 | }) 89 | } 90 | 91 | /// Helper function for removing the single child of a node. 92 | pub fn take_only_child(&mut self) -> Box> { 93 | debug_assert_eq!(self.child_count, 1); 94 | for i in 0..BRANCH_FACTOR { 95 | if let Some(child) = self.take_child(i) { 96 | return child; 97 | } 98 | } 99 | unreachable!("node with child_count 1 has no actual children"); 100 | } 101 | 102 | /// Set the value of a node, given that it currently lacks one. 103 | pub fn add_value(&mut self, value: V) { 104 | debug_assert!(self.value.is_none()); 105 | self.value = Some(Box::new(value)); 106 | } 107 | 108 | /// Move the value out of a node. 109 | pub fn take_value(&mut self) -> Option { 110 | self.value.take().map(|v| *v) 111 | } 112 | 113 | /// Replace a value, returning the previous value if there was one. 114 | pub fn replace_value(&mut self, value: V) -> Option { 115 | // TODO: optimise this? 116 | let previous = self.take_value(); 117 | self.add_value(value); 118 | previous 119 | } 120 | 121 | /// Get a reference to this node if it has a value. 122 | pub fn as_value_node(&self) -> Option<&TrieNode> { 123 | self.value.as_ref().map(|_| self) 124 | } 125 | 126 | /// Split a node at a given index in its key, transforming it into a prefix node of its 127 | /// previous self. 128 | pub fn split(&mut self, idx: usize) { 129 | // Extract all the parts of the suffix node, starting with the key. 130 | let key = self.key.split(idx); 131 | 132 | // Key-value. 133 | let value = self.value.take(); 134 | 135 | // Children. 136 | let mut children = no_children![]; 137 | 138 | for (i, child) in self.children.iter_mut().enumerate() { 139 | if child.is_some() { 140 | children[i] = child.take(); 141 | } 142 | } 143 | 144 | // Child count. 145 | let child_count = self.child_count; 146 | self.child_count = 1; 147 | 148 | // Insert the collected items below what is now an empty prefix node. 149 | let bucket = key.get(0) as usize; 150 | self.children[bucket] = Some(Box::new(TrieNode { 151 | key: key, 152 | value: value, 153 | children: children, 154 | child_count: child_count, 155 | })); 156 | } 157 | 158 | pub fn as_subtrie(&self, prefix: NibbleVec) -> SubTrie { 159 | SubTrie { 160 | prefix: prefix, 161 | node: self, 162 | } 163 | } 164 | 165 | pub fn as_subtrie_mut<'a>( 166 | &'a mut self, 167 | prefix: NibbleVec, 168 | length: &'a mut usize, 169 | ) -> SubTrieMut<'a, V> { 170 | SubTrieMut { 171 | prefix: prefix, 172 | length: length, 173 | node: self, 174 | } 175 | } 176 | 177 | /// Check the integrity of a trie subtree (quite costly). 178 | /// Return true and the size of the subtree if all checks are successful, 179 | /// or false and a junk value if any test fails. 180 | pub fn check_integrity_recursive(&self, depth: usize) -> (bool, usize) { 181 | let mut sub_tree_size = 0; 182 | let is_root = depth == 0; 183 | 184 | // Check that no value-less, non-root nodes have only 1 child. 185 | if !is_root && self.child_count == 1 && self.value.is_none() { 186 | println!("Value-less node with a single child."); 187 | return (false, sub_tree_size); 188 | } 189 | 190 | // Check that all non-root key vector's have length > 1. 191 | if !is_root && self.key.len() == 0 { 192 | println!("Key length is 0 at non-root node."); 193 | return (false, sub_tree_size); 194 | } 195 | 196 | // Check that the child count matches the actual number of children. 197 | let child_count = self 198 | .children 199 | .iter() 200 | .fold(0, |acc, e| acc + (e.is_some() as usize)); 201 | 202 | if child_count != self.child_count { 203 | println!( 204 | "Child count error, recorded: {}, actual: {}", 205 | self.child_count, child_count 206 | ); 207 | return (false, sub_tree_size); 208 | } 209 | 210 | // Compute the depth of the children of this node. 211 | let child_depth = depth + self.key.len(); 212 | 213 | // Account for this node in the size check. 214 | if self.value.is_some() { 215 | sub_tree_size += 1; 216 | } 217 | 218 | // Recursively check children. 219 | for i in 0..BRANCH_FACTOR { 220 | if let Some(ref child) = self.children[i] { 221 | match child.check_integrity_recursive(child_depth) { 222 | (false, _) => return (false, sub_tree_size), 223 | (true, child_size) => sub_tree_size += child_size, 224 | } 225 | } 226 | } 227 | 228 | (true, sub_tree_size) 229 | } 230 | } 231 | 232 | impl Default for TrieNode { 233 | fn default() -> Self { 234 | Self::new() 235 | } 236 | } 237 | -------------------------------------------------------------------------------- /src/rough_parser.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | use std::mem; 3 | use std::fmt; 4 | use std::ops::Deref; 5 | use crate::lexer::{Lexer, Token}; 6 | use crate::lexer::Token::*; 7 | use crate::loader::Loader; 8 | use crate::leanpath::LeanPath; 9 | use crate::types::*; 10 | 11 | fn invalid(s: &str) -> io::Error { io::Error::new(io::ErrorKind::InvalidData, s) } 12 | fn throw(s: &str) -> io::Result { Err(invalid(s)) } 13 | fn guard(b: bool, s: &str) -> io::Result<()> { if b {Ok(())} else {throw(s)} } 14 | 15 | #[derive(Debug)] pub struct Attributes; 16 | #[derive(Debug)] pub struct Modifiers; 17 | 18 | #[derive(Debug)] pub struct CmdMeta { 19 | pub attr: Attributes, 20 | pub mods: Modifiers, 21 | pub doc: Option 22 | } 23 | 24 | impl CmdMeta { 25 | fn new(doc: Option) -> CmdMeta { 26 | CmdMeta {attr: Attributes, mods: Modifiers, doc} 27 | } 28 | 29 | fn check_empty(&self) -> io::Result<()> { 30 | guard(true, "command does not take attributes")?; 31 | guard(true, "command does not take modifiers")?; 32 | guard(self.doc.is_none(), "command does not take doc string") 33 | } 34 | } 35 | 36 | #[derive(Debug)] pub enum Command { 37 | Namespace(Name, Vec), 38 | Section(Option, Vec), 39 | Other(String, CmdMeta, Vec) 40 | } 41 | 42 | impl Command { 43 | pub fn write(&self, f: &mut fmt::Formatter, depth: usize) -> fmt::Result { 44 | match self { 45 | Command::Namespace(n, cmds) => { 46 | writeln!(f, "{:indent$}namespace {}", "", n, indent=depth)?; 47 | Command::write_vec(cmds, f, depth+2) 48 | }, 49 | Command::Section(None, cmds) => { 50 | writeln!(f, "{:indent$}section", "", indent=depth)?; 51 | Command::write_vec(cmds, f, depth+2) 52 | }, 53 | Command::Section(Some(n), cmds) => { 54 | writeln!(f, "{:indent$}section {}", "", n, indent=depth)?; 55 | Command::write_vec(cmds, f, depth+2) 56 | }, 57 | Command::Other(s, _, _) => writeln!(f, "{:indent$}{} [...]", "", s, indent=depth) 58 | } 59 | } 60 | 61 | pub fn write_vec(cmds: &Vec, f: &mut fmt::Formatter, depth: usize) -> fmt::Result { 62 | Ok(for cmd in cmds { cmd.write(f, depth)? }) 63 | } 64 | } 65 | 66 | impl fmt::Display for Command { 67 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.write(f, 0) } 68 | } 69 | 70 | #[derive(PartialEq, Debug)] enum CmdEnd { 71 | End(Option), 72 | Eof 73 | } 74 | 75 | #[derive(Debug)] pub struct RoughLean { 76 | pub name: Name, 77 | pub imports: Vec, 78 | pub doc: Vec, 79 | pub cmds: Vec 80 | } 81 | 82 | impl RoughLean { 83 | fn new(name: Name, imports: Vec) -> RoughLean { 84 | RoughLean { name, imports, doc: Vec::new(), cmds: Vec::new() } 85 | } 86 | } 87 | 88 | pub struct RoughParser { 89 | lexer: Lexer, 90 | back: Option, 91 | mdoc: Vec 92 | } 93 | 94 | impl RoughParser { 95 | pub fn new(lexer: Lexer) -> Self { 96 | RoughParser {lexer, back: None, mdoc: Vec::new()} 97 | } 98 | 99 | fn get(&mut self) -> io::Result { 100 | Ok(match self.back.take() { 101 | Some(tk) => tk, 102 | None => self.lexer.lex()? 103 | }) 104 | } 105 | 106 | fn load(&mut self) -> io::Result<&Token> { 107 | if self.back.is_none() { 108 | self.back = Some(self.lexer.lex()?) 109 | } 110 | Ok(&self.back.as_ref().unwrap()) 111 | } 112 | 113 | fn pushback(&mut self, tk: Token) { self.back = Some(tk) } 114 | 115 | fn lex_ident(&mut self) -> io::Result> { 116 | Ok(match self.get()? { 117 | Identifier(s) => Some(s), 118 | tk => {self.pushback(tk); None} 119 | }) 120 | } 121 | 122 | fn lex_tk(&mut self, s: &str) -> io::Result { 123 | let tk = self.get()?; 124 | if tk.is_tk(s) { Ok(true) } else { self.pushback(tk); Ok(false) } 125 | } 126 | 127 | pub fn parse_imports(&mut self) -> io::Result> { 128 | let old = self.lexer.allow_field_notation(false); 129 | let mut imports = Vec::new(); 130 | if !self.lex_tk("prelude")? { 131 | imports.push(ModuleName{name: name!(init), relative: None}) 132 | } 133 | while self.lex_tk("import")? { 134 | loop { 135 | let mut relative: Option = None; 136 | loop { 137 | let d = if let Some(s) = self.load()?.tk() { 138 | if s.bytes().all(|c| c == ('.' as u8)) { s.len() as u32 } 139 | else {break} 140 | } else {break}; 141 | self.back = None; 142 | if let Some(k) = &mut relative { *k += d } 143 | else { relative = Some(d-1) } 144 | } 145 | if let Some(name) = self.lex_ident()? { 146 | imports.push(ModuleName {name, relative}) 147 | } else {break} 148 | } 149 | } 150 | self.lexer.allow_field_notation(old); 151 | Ok(imports) 152 | } 153 | 154 | fn parse_cmd(&mut self, meta: CmdMeta, s: String) -> io::Result { 155 | match s.deref() { 156 | "namespace" => { meta.check_empty()?; match self.lex_ident()? { 157 | Some(ns) => Ok(Command::Namespace(ns.clone(), self.parse_cmds(CmdEnd::End(Some(ns)))?)), 158 | None => throw("invalid namespace declaration, identifier expected") 159 | } }, 160 | "section" => { 161 | meta.check_empty()?; 162 | let n = self.lex_ident()?; 163 | Ok(Command::Section(n.clone(), self.parse_cmds(CmdEnd::End(n))?)) 164 | }, 165 | _ => { 166 | let mut tks = Vec::new(); 167 | let mut begins: u32 = 1; 168 | loop { 169 | match self.get()? { 170 | Token::Eof => break, 171 | Token::Keyword(s, prec) => { 172 | if s == "begin" || s == "match" {begins += 1} 173 | tks.push(Token::Keyword(s, prec)) }, 174 | Token::CommandKeyword(s) => 175 | if if s == "end" {begins -= 1; begins == 0} else {true} { 176 | self.pushback(Token::CommandKeyword(s)); break 177 | } else {tks.push(Token::CommandKeyword(s))}, 178 | tk => tks.push(tk) 179 | } 180 | } 181 | Ok(Command::Other(s, meta, tks)) 182 | } 183 | } 184 | } 185 | 186 | fn parse_cmds(&mut self, expect: CmdEnd) -> io::Result> { 187 | let mut cmds = Vec::new(); 188 | loop { 189 | match self.get()? { 190 | CommandKeyword(s) => 191 | if s == "end" { 192 | return match &expect { 193 | CmdEnd::Eof => throw("unexpected 'end'"), 194 | CmdEnd::End(None) => Ok(cmds), 195 | CmdEnd::End(Some(n)) => 196 | if self.lex_ident()? == Some(n.clone()) {Ok(cmds)} 197 | else {throw(&format!("expected 'end {}'", n))} 198 | } 199 | } else { cmds.push(self.parse_cmd(CmdMeta::new(None), s)?) }, 200 | DocBlock(true, s) => self.mdoc.push(s), 201 | DocBlock(false, s) => 202 | if let CommandKeyword(cmd) = self.get()? { 203 | cmds.push(self.parse_cmd(CmdMeta::new(Some(s)), cmd)?) 204 | } else { return throw("command expected") } 205 | Eof => return if expect == CmdEnd::Eof { Ok(cmds) } else { throw("unclosed namespace/section") }, 206 | _ => return throw("command expected") 207 | } 208 | } 209 | } 210 | 211 | pub fn parse_lean(&mut self, load: &mut Loader, lp: &LeanPath, name: Name) -> io::Result { 212 | let mut rl = RoughLean::new(name.clone(), self.parse_imports()?); 213 | for m in &rl.imports { load.load(lp, m.resolve(name.clone()))? } 214 | self.lexer.token_table.load(load)?; 215 | rl.cmds = self.parse_cmds(CmdEnd::Eof)?; 216 | rl.doc = mem::replace(&mut self.mdoc, Vec::new()); 217 | Ok(rl) 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "byteorder" 3 | version = "1.2.7" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | 6 | [[package]] 7 | name = "endian-type" 8 | version = "0.1.2" 9 | source = "registry+https://github.com/rust-lang/crates.io-index" 10 | 11 | [[package]] 12 | name = "getopts" 13 | version = "0.2.18" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | dependencies = [ 16 | "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 17 | ] 18 | 19 | [[package]] 20 | name = "nibble_vec" 21 | version = "0.0.4" 22 | source = "registry+https://github.com/rust-lang/crates.io-index" 23 | 24 | [[package]] 25 | name = "num" 26 | version = "0.2.0" 27 | source = "registry+https://github.com/rust-lang/crates.io-index" 28 | dependencies = [ 29 | "num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 30 | "num-complex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 31 | "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", 32 | "num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", 33 | "num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 34 | "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 35 | ] 36 | 37 | [[package]] 38 | name = "num-bigint" 39 | version = "0.2.2" 40 | source = "registry+https://github.com/rust-lang/crates.io-index" 41 | dependencies = [ 42 | "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", 43 | "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 44 | ] 45 | 46 | [[package]] 47 | name = "num-complex" 48 | version = "0.2.1" 49 | source = "registry+https://github.com/rust-lang/crates.io-index" 50 | dependencies = [ 51 | "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 52 | ] 53 | 54 | [[package]] 55 | name = "num-derive" 56 | version = "0.2.3" 57 | source = "registry+https://github.com/rust-lang/crates.io-index" 58 | dependencies = [ 59 | "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 60 | "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", 61 | "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", 62 | "syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)", 63 | ] 64 | 65 | [[package]] 66 | name = "num-integer" 67 | version = "0.1.39" 68 | source = "registry+https://github.com/rust-lang/crates.io-index" 69 | dependencies = [ 70 | "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 71 | ] 72 | 73 | [[package]] 74 | name = "num-iter" 75 | version = "0.1.37" 76 | source = "registry+https://github.com/rust-lang/crates.io-index" 77 | dependencies = [ 78 | "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", 79 | "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 80 | ] 81 | 82 | [[package]] 83 | name = "num-rational" 84 | version = "0.2.1" 85 | source = "registry+https://github.com/rust-lang/crates.io-index" 86 | dependencies = [ 87 | "num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 88 | "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", 89 | "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 90 | ] 91 | 92 | [[package]] 93 | name = "num-traits" 94 | version = "0.2.6" 95 | source = "registry+https://github.com/rust-lang/crates.io-index" 96 | 97 | [[package]] 98 | name = "olean-rs" 99 | version = "0.1.0" 100 | dependencies = [ 101 | "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", 102 | "endian-type 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 103 | "getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", 104 | "nibble_vec 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 105 | "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 106 | "num-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 107 | "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 108 | "take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 109 | "unicode_reader 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 110 | ] 111 | 112 | [[package]] 113 | name = "proc-macro2" 114 | version = "0.4.24" 115 | source = "registry+https://github.com/rust-lang/crates.io-index" 116 | dependencies = [ 117 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 118 | ] 119 | 120 | [[package]] 121 | name = "quote" 122 | version = "0.6.10" 123 | source = "registry+https://github.com/rust-lang/crates.io-index" 124 | dependencies = [ 125 | "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", 126 | ] 127 | 128 | [[package]] 129 | name = "syn" 130 | version = "0.15.23" 131 | source = "registry+https://github.com/rust-lang/crates.io-index" 132 | dependencies = [ 133 | "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", 134 | "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", 135 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 136 | ] 137 | 138 | [[package]] 139 | name = "take_mut" 140 | version = "0.2.2" 141 | source = "registry+https://github.com/rust-lang/crates.io-index" 142 | 143 | [[package]] 144 | name = "unicode-segmentation" 145 | version = "1.2.1" 146 | source = "registry+https://github.com/rust-lang/crates.io-index" 147 | 148 | [[package]] 149 | name = "unicode-width" 150 | version = "0.1.5" 151 | source = "registry+https://github.com/rust-lang/crates.io-index" 152 | 153 | [[package]] 154 | name = "unicode-xid" 155 | version = "0.1.0" 156 | source = "registry+https://github.com/rust-lang/crates.io-index" 157 | 158 | [[package]] 159 | name = "unicode_reader" 160 | version = "0.1.1" 161 | source = "registry+https://github.com/rust-lang/crates.io-index" 162 | dependencies = [ 163 | "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 164 | ] 165 | 166 | [metadata] 167 | "checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" 168 | "checksum endian-type 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" 169 | "checksum getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0a7292d30132fb5424b354f5dc02512a86e4c516fe544bb7a25e7f266951b797" 170 | "checksum nibble_vec 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c8d77f3db4bce033f4d04db08079b2ef1c3d02b44e86f25d08886fafa7756ffa" 171 | "checksum num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db" 172 | "checksum num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "57450397855d951f1a41305e54851b1a7b8f5d2e349543a02a2effe25459f718" 173 | "checksum num-complex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "107b9be86cd2481930688277b675b0114578227f034674726605b8a482d8baf8" 174 | "checksum num-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8af1847c907c2f04d7bfd572fb25bbb4385c637fe5be163cf2f8c5d778fe1e7d" 175 | "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" 176 | "checksum num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124" 177 | "checksum num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e96f040177bb3da242b5b1ecf3f54b5d5af3efbbfb18608977a5d2767b22f10" 178 | "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" 179 | "checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" 180 | "checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" 181 | "checksum syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9545a6a093a3f0bd59adb472700acc08cad3776f860f16a897dfce8c88721cbc" 182 | "checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" 183 | "checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" 184 | "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" 185 | "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" 186 | "checksum unicode_reader 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "001b27e8f5e9da465b3584051a3a3d2ebefee4f8595c49e96cc1deec9667e4cc" 187 | -------------------------------------------------------------------------------- /src/trie/traversal.rs: -------------------------------------------------------------------------------- 1 | //! This module contains the core algorithms. 2 | 3 | use super::keys::{match_keys, KeyMatch}; 4 | use super::trie_node::TrieNode; 5 | use super::NibbleVec; 6 | 7 | use self::DescendantResult::*; 8 | 9 | impl TrieNode { 10 | pub fn get(&self, key: &NibbleVec) -> Option<&TrieNode> { 11 | iterative_get(self, key) 12 | } 13 | 14 | pub fn get_mut(&mut self, key: &NibbleVec) -> Option<&mut TrieNode> { 15 | iterative_get_mut(self, key) 16 | } 17 | 18 | pub fn insert(&mut self, key: NibbleVec, value: V) -> Option { 19 | iterative_insert(self, key, value) 20 | } 21 | 22 | pub fn remove(&mut self, key: &NibbleVec) -> Option { 23 | recursive_remove(self, key) 24 | } 25 | 26 | pub fn get_ancestor(&self, key: &NibbleVec) -> Option<(&TrieNode, usize)> { 27 | get_ancestor(self, key) 28 | } 29 | 30 | pub fn get_raw_ancestor(&self, key: &NibbleVec) -> (&TrieNode, usize) { 31 | get_raw_ancestor(self, key) 32 | } 33 | 34 | pub fn get_raw_descendant<'a>(&'a self, key: &NibbleVec) -> Option> { 35 | get_raw_descendant(self, key) 36 | } 37 | } 38 | 39 | macro_rules! id { 40 | ($e:item) => { 41 | $e 42 | }; 43 | } 44 | 45 | macro_rules! get_func { 46 | ( 47 | name: $name:ident, 48 | trie_type: $trie_type:ty, 49 | mutability: $($mut_:tt)* 50 | ) => {id!{ 51 | fn $name<'a, V>(trie: $trie_type, key: &NibbleVec) -> Option<$trie_type> { 52 | if key.len() == 0 { 53 | return Some(trie); 54 | } 55 | 56 | let mut prev = trie; 57 | let mut depth = 0; 58 | 59 | loop { 60 | let bucket = key.get(depth) as usize; 61 | let current = prev; 62 | if let Some(ref $($mut_)* child) = current.children[bucket] { 63 | match match_keys(depth, key, &child.key) { 64 | KeyMatch::Full => { 65 | return Some(child); 66 | } 67 | KeyMatch::SecondPrefix => { 68 | depth += child.key.len(); 69 | prev = child; 70 | } 71 | _ => { 72 | return None; 73 | } 74 | } 75 | } else { 76 | return None; 77 | } 78 | } 79 | } 80 | }} 81 | } 82 | 83 | get_func!(name: iterative_get, trie_type: &'a TrieNode, mutability: ); 84 | get_func!(name: iterative_get_mut, trie_type: &'a mut TrieNode, mutability: mut); 85 | 86 | fn iterative_insert( 87 | trie: &mut TrieNode, 88 | mut key: NibbleVec, 89 | value: V, 90 | ) -> Option { 91 | if key.len() == 0 { 92 | return trie.replace_value(value); 93 | } 94 | 95 | let mut prev = trie; 96 | let mut depth = 0; 97 | 98 | loop { 99 | let bucket = key.get(depth) as usize; 100 | let current = prev; 101 | if let Some(ref mut child) = current.children[bucket] { 102 | match match_keys(depth, &key, &child.key) { 103 | KeyMatch::Full => { 104 | return child.replace_value(value); 105 | } 106 | KeyMatch::Partial(idx) => { 107 | // Split the existing child. 108 | child.split(idx); 109 | 110 | // Insert the new key below the prefix node. 111 | let new_key = key.split(depth + idx); 112 | let new_key_bucket = new_key.get(0) as usize; 113 | 114 | child.add_child( 115 | new_key_bucket, 116 | Box::new(TrieNode::with_key_value(new_key, value)), 117 | ); 118 | 119 | return None; 120 | } 121 | KeyMatch::FirstPrefix => { 122 | child.split(key.len() - depth); 123 | child.add_value(value); 124 | return None; 125 | } 126 | KeyMatch::SecondPrefix => { 127 | depth += child.key.len(); 128 | prev = child; 129 | } 130 | } 131 | } else { 132 | let node_key = key.split(depth); 133 | current.add_child( 134 | bucket, 135 | Box::new(TrieNode::with_key_value(node_key, value)), 136 | ); 137 | return None; 138 | } 139 | } 140 | } 141 | 142 | // TODO: clean this up and make it iterative. 143 | fn recursive_remove(trie: &mut TrieNode, key: &NibbleVec) -> Option { 144 | if key.len() == 0 { 145 | return trie.take_value(); 146 | } 147 | 148 | let bucket = key.get(0) as usize; 149 | 150 | let child = trie.take_child(bucket); 151 | 152 | match child { 153 | Some(mut child) => { 154 | match match_keys(0, &key, &child.key) { 155 | KeyMatch::Full => { 156 | let result = child.take_value(); 157 | if child.child_count != 0 { 158 | // If removing this node's value has made it a value-less node with a 159 | // single child, then merge its child. 160 | let repl = if child.child_count == 1 { 161 | get_merge_child(&mut child) 162 | } else { 163 | child 164 | }; 165 | trie.add_child(bucket, repl); 166 | } 167 | result 168 | } 169 | KeyMatch::SecondPrefix => { 170 | let depth = child.key.len(); 171 | rec_remove(trie, child, bucket, key, depth) 172 | } 173 | _ => None, 174 | } 175 | } 176 | None => None, 177 | } 178 | } 179 | 180 | fn get_merge_child(trie: &mut TrieNode) -> Box> { 181 | let mut child = trie.take_only_child(); 182 | 183 | // Join the child's key onto the existing one. 184 | child.key = trie.key.clone().join(&child.key); 185 | 186 | child 187 | } 188 | 189 | // Tail-recursive remove function used by `recursive_remove`. 190 | fn rec_remove( 191 | parent: &mut TrieNode, 192 | mut middle: Box>, 193 | prev_bucket: usize, 194 | key: &NibbleVec, 195 | depth: usize, 196 | ) -> Option { 197 | let bucket = key.get(depth) as usize; 198 | 199 | let child = middle.take_child(bucket); 200 | parent.add_child(prev_bucket, middle); 201 | 202 | match child { 203 | Some(mut child) => { 204 | let middle = parent.children[prev_bucket].as_mut().unwrap(); 205 | match match_keys(depth, key, &child.key) { 206 | KeyMatch::Full => { 207 | let result = child.take_value(); 208 | 209 | // If this node has children, keep it. 210 | if child.child_count != 0 { 211 | // If removing this node's value has made it a value-less node with a 212 | // single child, then merge its child. 213 | let repl = if child.child_count == 1 { 214 | get_merge_child(&mut *child) 215 | } else { 216 | child 217 | }; 218 | middle.add_child(bucket, repl); 219 | } 220 | // Otherwise, if the parent node now only has a single child, merge it. 221 | else if middle.child_count == 1 && middle.value.is_none() { 222 | let repl = get_merge_child(middle); 223 | *middle = repl; 224 | } 225 | 226 | result 227 | } 228 | KeyMatch::SecondPrefix => { 229 | let new_depth = depth + child.key.len(); 230 | rec_remove(middle, child, bucket, key, new_depth) 231 | } 232 | _ => None, 233 | } 234 | } 235 | None => None, 236 | } 237 | } 238 | 239 | fn get_ancestor<'a, V>( 240 | trie: &'a TrieNode, 241 | key: &NibbleVec, 242 | ) -> Option<(&'a TrieNode, usize)> { 243 | if key.len() == 0 { 244 | return trie.as_value_node().map(|node| (node, 0)); 245 | } 246 | 247 | let mut prev = trie; 248 | // The ancestor is such that all nodes upto and including `prev` have 249 | // already been considered. 250 | let mut ancestor = prev.as_value_node(); 251 | let mut depth = 0; 252 | 253 | loop { 254 | let bucket = key.get(depth) as usize; 255 | let current = prev; 256 | if let Some(ref child) = current.children[bucket] { 257 | match match_keys(depth, key, &child.key) { 258 | KeyMatch::Full => { 259 | return child 260 | .as_value_node() 261 | .map(|node| (node, depth + node.key.len())) 262 | .or_else(|| ancestor.map(|anc| (anc, depth))); 263 | } 264 | KeyMatch::FirstPrefix | KeyMatch::Partial(_) => { 265 | return ancestor.map(|anc| (anc, depth)); 266 | } 267 | KeyMatch::SecondPrefix => { 268 | depth += child.key.len(); 269 | ancestor = child.as_value_node().or(ancestor); 270 | prev = child; 271 | } 272 | } 273 | } else { 274 | return ancestor.map(|anc| (anc, depth)); 275 | } 276 | } 277 | } 278 | 279 | fn get_raw_ancestor<'a, V>( 280 | trie: &'a TrieNode, 281 | key: &NibbleVec, 282 | ) -> (&'a TrieNode, usize) { 283 | if key.len() == 0 { 284 | return (trie, 0); 285 | } 286 | 287 | let mut prev = trie; 288 | // The ancestor is such that all nodes upto and including `prev` have 289 | // already been considered. 290 | let mut ancestor = prev; 291 | let mut depth = 0; 292 | 293 | loop { 294 | let bucket = key.get(depth) as usize; 295 | let current = prev; 296 | if let Some(ref child) = current.children[bucket] { 297 | match match_keys(depth, key, &child.key) { 298 | KeyMatch::Full => { 299 | return (child, depth + child.key.len()); 300 | } 301 | KeyMatch::FirstPrefix | KeyMatch::Partial(_) => { 302 | return (ancestor, depth); 303 | } 304 | KeyMatch::SecondPrefix => { 305 | depth += child.key.len(); 306 | ancestor = child; 307 | prev = child; 308 | } 309 | } 310 | } else { 311 | return (ancestor, depth); 312 | } 313 | } 314 | } 315 | 316 | // Type used to propogate subtrie construction instructions to the top-level `get_raw_descendant` 317 | // method. 318 | pub enum DescendantResult<'a, V: 'a> { 319 | NoModification(&'a TrieNode), 320 | ExtendKey(&'a TrieNode, usize, &'a NibbleVec), 321 | } 322 | 323 | fn get_raw_descendant<'a, V>( 324 | trie: &'a TrieNode, 325 | key: &NibbleVec, 326 | ) -> Option> { 327 | if key.len() == 0 { 328 | return Some(NoModification(trie)); 329 | } 330 | 331 | let mut prev = trie; 332 | let mut depth = 0; 333 | 334 | loop { 335 | let bucket = key.get(depth) as usize; 336 | let current = prev; 337 | if let Some(ref child) = current.children[bucket] { 338 | match match_keys(depth, key, &child.key) { 339 | KeyMatch::Full => { 340 | return Some(NoModification(child)); 341 | } 342 | KeyMatch::FirstPrefix => { 343 | return Some(ExtendKey(child, depth, &child.key)); 344 | } 345 | KeyMatch::SecondPrefix => { 346 | depth += child.key.len(); 347 | prev = child; 348 | } 349 | _ => { 350 | return None; 351 | } 352 | } 353 | } else { 354 | return None; 355 | } 356 | } 357 | } 358 | -------------------------------------------------------------------------------- /src/types.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | use std::fmt; 3 | use std::fmt::{Debug, Display, Formatter}; 4 | use std::ops::Deref; 5 | use num::bigint::BigInt; 6 | 7 | #[derive(PartialEq, Eq, Hash, Clone)] pub struct Name(Rc); 8 | 9 | #[derive(PartialEq, Eq, Hash)] pub enum Name2 { 10 | Anon, 11 | Str(Name, String), 12 | Num(Name, u32) 13 | } 14 | 15 | impl Name2 { 16 | pub fn is_anon(&self) -> bool { 17 | if let Name2::Anon = self { true } else { false } 18 | } 19 | 20 | pub fn to_simple_name(&self) -> Option<&str> { 21 | if let Name2::Str(n2, ref s) = self { 22 | if n2.0.is_anon() {Some(s)} else {None} 23 | } else {None} 24 | } 25 | 26 | pub fn parent(&self) -> Name { 27 | match self { 28 | Name2::Anon => Name::anon(), 29 | Name2::Str(n, _) => n.clone(), 30 | Name2::Num(n, _) => n.clone() 31 | } 32 | } 33 | } 34 | 35 | impl Name { 36 | pub fn new(n: Name2) -> Name { Name(Rc::new(n)) } 37 | pub fn anon() -> Name { Name::new(Name2::Anon) } 38 | pub fn is_anon(&self) -> bool { self.0.is_anon() } 39 | pub fn parent(&self) -> Name { self.0.parent() } 40 | pub fn str(self, s: String) -> Name { Name::new(Name2::Str(self, s)) } 41 | pub fn num(self, s: u32) -> Name { Name::new(Name2::Num(self, s)) } 42 | 43 | pub fn append(self, other: &Name2) -> Name { 44 | match other { 45 | Name2::Anon => self, 46 | Name2::Str(n, s) => self.append(n).str(s.clone()), 47 | Name2::Num(n, s) => self.append(n).num(s.clone()) 48 | } 49 | } 50 | } 51 | 52 | impl Deref for Name { 53 | type Target = Name2; 54 | fn deref(&self) -> &Name2 { self.0.deref() } 55 | } 56 | 57 | impl From<&[&str]> for Name { 58 | fn from(ns: &[&str]) -> Name { 59 | match ns.split_last() { 60 | None => Name::anon(), 61 | Some((&s, ns)) => Name::str(ns.into(), String::from(s)) 62 | } 63 | } 64 | } 65 | 66 | impl From<&str> for Name { 67 | fn from(n: &str) -> Name { Name::str(Name::anon(), String::from(n)) } 68 | } 69 | 70 | macro_rules! name { 71 | [$e:expr; $x:ident] => { 72 | Name::str($e, stringify!($x).to_string()) 73 | }; 74 | [$e:expr; $x:ident . $($rest:tt).*] => { 75 | name![Name::str($e, stringify!($x).to_string()); $($rest).*] 76 | }; 77 | [$($ns:tt).*] => { name![Name::anon(); $($ns).*] }; 78 | } 79 | 80 | pub fn parse_name(ns: &str) -> Name { 81 | let mut n = Name::anon(); 82 | for s in ns.split('.') { n = Name::str(n, s.to_string()) } 83 | n 84 | } 85 | 86 | impl Display for Name2 { 87 | fn fmt(&self, f: &mut Formatter) -> fmt::Result { 88 | match self { 89 | Name2::Anon => write!(f, "[anonymous]"), 90 | Name2::Str(n, s) => 91 | if n.is_anon() { f.write_str(&s) } 92 | else { write!(f, "{}.{}", n, s) }, 93 | Name2::Num(ref n, s) => 94 | if n.is_anon() { write!(f, "{}", s) } 95 | else { write!(f, "{}.{}", n, s) } 96 | } 97 | } 98 | } 99 | 100 | impl Debug for Name2 { 101 | fn fmt(&self, f: &mut Formatter) -> fmt::Result { Display::fmt(self, f) } 102 | } 103 | 104 | impl Display for Name { 105 | fn fmt(&self, f: &mut Formatter) -> fmt::Result { Display::fmt(self.deref(), f) } 106 | } 107 | 108 | impl fmt::Debug for Name { 109 | fn fmt(&self, f: &mut Formatter) -> fmt::Result { Debug::fmt(self.deref(), f) } 110 | } 111 | 112 | pub type Level = Rc; 113 | #[derive(Debug)] pub enum Level2 { 114 | Zero, 115 | Succ(Level), 116 | Max(Level, Level), 117 | IMax(Level, Level), 118 | Param(Name), 119 | Meta(Name) 120 | } 121 | 122 | #[derive(Debug)] pub enum BinderInfo { 123 | Default, 124 | Implicit, 125 | StrictImplicit, 126 | InstImplicit, 127 | AuxDecl 128 | } 129 | 130 | pub type Expr = Rc; 131 | #[derive(Debug)] pub enum Expr2 { 132 | Var(u32), 133 | Sort(Level), 134 | Const(Name, Vec), 135 | MVar(Name, Name, Expr), 136 | Local(Name, Name, BinderInfo, Expr), 137 | App(Expr, Expr), 138 | Lam(Name, BinderInfo, Expr, Expr), 139 | Pi(Name, BinderInfo, Expr, Expr), 140 | Let(Name, Expr, Expr, Expr), 141 | Macro(MacroDef, Vec) 142 | } 143 | 144 | #[derive(Debug)] pub struct EquationsHeader { 145 | pub num_fns: u32, 146 | pub is_private: bool, 147 | pub is_meta: bool, 148 | pub is_ncomp: bool, 149 | pub is_lemma: bool, 150 | pub is_aux_lemmas: bool, 151 | pub prev_errors: bool, 152 | pub gen_code: bool, 153 | pub fn_names: Vec, 154 | pub fn_actual_names: Vec 155 | } 156 | 157 | #[derive(Debug)] pub enum MacroDef { 158 | Prenum(BigInt), 159 | StructureInstance {struct_: Name, catchall: bool, fields: Vec}, 160 | FieldNotation(Name, u32), 161 | Annot(Name), 162 | Choice, 163 | NatValue(BigInt), 164 | RecFn(Name), 165 | Proj { 166 | i_name: Name, c_name: Name, proj_name: Name, 167 | idx: u32, ps: Vec, ty: Expr, val: Expr }, 168 | Equations(EquationsHeader), 169 | Equation{ignore_if_unused: bool}, 170 | NoEquation, 171 | EquationsResult, 172 | AsPattern, 173 | ExprQuote{val: Expr, reflected: bool}, 174 | Sorry{synth: bool}, 175 | String(String), 176 | ACApp, 177 | PermAC, 178 | TypedExpr, 179 | } 180 | 181 | pub fn check_macro(m: &MacroDef, args: &Vec) -> bool { 182 | match m { 183 | MacroDef::StructureInstance {fields, ..} => args.len() >= fields.len(), 184 | MacroDef::FieldNotation{..} => args.len() == 1, 185 | MacroDef::Annot{..} => args.len() == 1, 186 | MacroDef::Choice => args.len() > 1, 187 | MacroDef::NatValue{..} => args.len() == 0, 188 | MacroDef::RecFn{..} => args.len() == 1, 189 | MacroDef::Proj{..} => args.len() == 1, 190 | MacroDef::Equation{..} => args.len() == 2, 191 | MacroDef::NoEquation => args.len() == 0, 192 | MacroDef::AsPattern => args.len() == 2, 193 | MacroDef::ExprQuote{..} => args.len() == 0, 194 | MacroDef::Sorry{..} => args.len() == 1, 195 | MacroDef::String{..} => args.len() == 0, 196 | MacroDef::PermAC => args.len() == 4, 197 | MacroDef::TypedExpr => args.len() == 2, 198 | _ => true 199 | } 200 | } 201 | 202 | pub struct ModuleName { 203 | pub relative: Option, 204 | pub name: Name 205 | } 206 | 207 | impl ModuleName { 208 | pub fn resolve(&self, mut base: Name) -> Name { 209 | match &self.relative { 210 | None => self.name.clone(), 211 | Some(n) => { 212 | for _ in 0..n+1 { base = base.parent() } 213 | base.append(&self.name) 214 | } 215 | } 216 | } 217 | } 218 | 219 | impl Display for ModuleName { 220 | fn fmt(&self, f: &mut Formatter) -> fmt::Result { 221 | write!(f, "{}{}", ".".repeat(self.relative.map_or(0, |n| (n+1) as usize)), self.name) 222 | } 223 | } 224 | 225 | impl Debug for ModuleName { 226 | fn fmt(&self, f: &mut Formatter) -> fmt::Result { Display::fmt(self, f) } 227 | } 228 | 229 | #[derive(Debug)] pub struct ExportDecl { 230 | pub ns: Name, 231 | pub as_: Name, 232 | pub had_explicit: bool, 233 | pub except_names: Vec, 234 | pub renames: Vec<(Name, Name)> 235 | } 236 | 237 | #[derive(Debug)] pub enum ReducibilityHints { 238 | Regular(u32, bool), 239 | Opaque, 240 | Abbrev 241 | } 242 | 243 | #[derive(Debug)] pub enum Declaration { 244 | Defn{name: Name, ps: Vec, ty: Expr, val: Expr, hints: ReducibilityHints, is_trusted: bool}, 245 | Thm{name: Name, ps: Vec, ty: Expr, val: Expr}, 246 | Cnst{name: Name, ps: Vec, ty: Expr, is_trusted: bool}, 247 | Ax{name: Name, ps: Vec, ty: Expr} 248 | } 249 | 250 | #[derive(Debug)] pub struct PosInfo { pub line: u32, pub col: u32 } 251 | 252 | #[derive(Debug, FromPrimitive)] 253 | pub enum ReducibleStatus { Reducible, Semireducible, Irreducible } 254 | 255 | #[derive(Debug, FromPrimitive)] 256 | pub enum ElabStrategy { Simple, WithExpectedType, AsEliminator } 257 | 258 | #[derive(Debug)] pub enum AttrData { 259 | Basic, 260 | Reducibility(ReducibleStatus), 261 | ElabStrategy(ElabStrategy), 262 | Intro{eager: bool}, 263 | Indices(Vec), 264 | User(Expr) 265 | } 266 | 267 | #[derive(Debug)] pub struct AttrRecord(pub Name, pub Option); 268 | 269 | #[derive(Debug)] pub struct AttrEntry { 270 | pub attr: Name, 271 | pub prio: u32, 272 | pub record: AttrRecord 273 | } 274 | 275 | #[derive(Debug)] pub struct InductiveDecl { 276 | pub name: Name, 277 | pub level_params: Vec, 278 | pub nparams: u32, 279 | pub ty: Expr, 280 | pub rules: Vec<(Name, Expr)> 281 | } 282 | 283 | #[derive(Debug)] pub struct CompRule { 284 | pub num_bu: u32, 285 | pub comp_rhs: Expr 286 | } 287 | 288 | #[derive(Debug)] pub struct InductiveDefn { 289 | pub num_ac_e: u32, 290 | pub elim_prop: bool, 291 | pub dep_elim: bool, 292 | pub level_params: Vec, 293 | pub elim_type: Expr, 294 | pub decl: InductiveDecl, 295 | pub is_k: bool, 296 | pub num_indices: u32, 297 | pub is_trusted: bool, 298 | pub comp_rules: Vec 299 | } 300 | 301 | #[derive(Debug, FromPrimitive)] 302 | pub enum GInductiveKind { Basic, Mutual, Nested } 303 | 304 | #[derive(Debug)] pub struct GInductiveEntry { 305 | pub kind: GInductiveKind, 306 | pub inner: bool, 307 | pub num_params: u32, 308 | pub num_indices: Vec, 309 | pub inds: Vec, 310 | pub intro_rules: Vec>, 311 | pub offsets: Vec, 312 | pub idx_to_ir_range: Vec<(u32, u32)>, 313 | pub packs: Vec, 314 | pub unpacks: Vec 315 | } 316 | 317 | #[derive(Debug)] pub struct VMLocalInfo { 318 | pub id: Name, 319 | pub ty: Option 320 | } 321 | 322 | #[derive(Debug)] pub enum VMInstr { 323 | Push(u32), 324 | Move(u32), 325 | Ret, 326 | Drop(u32), 327 | Goto(u32), 328 | SConstr(u32), 329 | Constr(u32, u32), 330 | Num(BigInt), 331 | Destruct, 332 | Cases2(u32, u32), 333 | CasesN(Vec), 334 | NatCases(u32, u32), 335 | BuiltinCases(Name, Vec), 336 | Proj(u32), 337 | Apply, 338 | InvokeGlobal(Name), 339 | InvokeBuiltin(Name), 340 | InvokeCFun(Name), 341 | Closure(Name, u32), 342 | Unreachable, 343 | Expr(Expr), 344 | LocalInfo(u32, VMLocalInfo) 345 | } 346 | 347 | #[derive(Debug)] pub enum VMDeclKind { 348 | Bytecode(Vec), 349 | // Builtin, 350 | // CFun 351 | } 352 | 353 | #[derive(Debug)] pub struct VMDecl { 354 | pub kind: VMDeclKind, 355 | pub name: Name, 356 | pub arity: u32, 357 | pub args_info: Vec, 358 | pub pos_info: Option, 359 | pub olean: Option 360 | } 361 | 362 | #[derive(Debug)] pub enum ClassEntry { 363 | Class(Name), 364 | Instance(Name, Name, u32), 365 | Tracker(Name, Name), 366 | } 367 | 368 | #[derive(Debug)] pub struct ProjectionInfo { 369 | pub constr: Name, 370 | pub nparams: u32, 371 | pub i: u32, 372 | pub inst_implicit: bool 373 | } 374 | 375 | #[derive(Debug)] pub enum Action { 376 | Skip, 377 | Expr{rbp: u32}, 378 | Exprs { 379 | sep: Name, 380 | rec: Expr, 381 | ini: Option, 382 | is_foldr: bool, 383 | rbp: u32, 384 | terminator: Option }, 385 | Binder{rbp: u32}, 386 | Binders{rbp: u32}, 387 | ScopedExpr { 388 | rec: Expr, 389 | rbp: u32, 390 | use_lambda: bool } 391 | } 392 | 393 | #[derive(Debug)] pub struct Transition { 394 | pub tk: Name, 395 | pub pp: Name, 396 | pub act: Action 397 | } 398 | 399 | #[derive(Debug)] pub enum NotationEntryKind { 400 | Reg { 401 | is_nud: bool, 402 | transitions: Vec, 403 | prio: u32 404 | }, 405 | Numeral(BigInt) 406 | } 407 | 408 | #[derive(Debug, FromPrimitive)] pub enum NotationEntryGroup { Main, Reserve } 409 | 410 | #[derive(Debug)] pub struct NotationEntry { 411 | pub kind: NotationEntryKind, 412 | pub expr: Expr, 413 | pub overload: bool, 414 | pub group: NotationEntryGroup, 415 | pub parse_only: bool 416 | } 417 | 418 | #[derive(Debug)] pub struct InverseEntry { 419 | pub decl: Name, 420 | pub arity: u32, 421 | pub inv: Name, 422 | pub inv_arity: u32, 423 | pub lemma: Name 424 | } 425 | 426 | #[derive(Debug, FromPrimitive)] pub enum OpKind { Relation, Subst, Trans, Refl, Symm } 427 | 428 | #[derive(Debug)] pub struct RecursorInfo { 429 | pub rec: Name, 430 | pub ty: Name, 431 | pub dep_elim: bool, 432 | pub recursive: bool, 433 | pub num_args: u32, 434 | pub major_pos: u32, 435 | pub univ_pos: Vec, 436 | pub params_pos: Vec>, 437 | pub indices_pos: Vec, 438 | pub produce_motive: Vec 439 | } 440 | 441 | #[derive(Clone, Debug)] pub struct KToken { 442 | pub tk: String, 443 | pub prec: Option 444 | } 445 | 446 | #[derive(Debug)] pub enum Modification { 447 | ExportDecl(Name, ExportDecl), 448 | Decl {decl: Declaration, trust_lvl: u32}, 449 | PosInfo(Name, PosInfo), 450 | Inductive{defn: InductiveDefn, trust_lvl: u32}, 451 | AuxRec(Name), 452 | Protected(Name), 453 | Private{name: Name, real: Name}, 454 | GInd(GInductiveEntry), 455 | NewNS(Name), 456 | VMReserve(Name, u32), 457 | VMCode(VMDecl), 458 | VMMonitor(Name), 459 | EqnLemmas(Name), 460 | HasSimpleEqnLemma(Name), 461 | NoConf(Name), 462 | Doc(Name, String), 463 | Noncomputable(Name), 464 | Proj(Name, ProjectionInfo), 465 | DeclTrace(Name), 466 | UserCommand(Name), 467 | UserNotation(Name), 468 | UserAttribute(Name), 469 | HoleCommand(Name), 470 | Quot, 471 | NativeModulePath(Name), 472 | KeyEquivalence(Name, Name), 473 | 474 | Token(KToken), 475 | Notation(NotationEntry), 476 | Attr(AttrEntry), 477 | Class(ClassEntry), 478 | Inverse(InverseEntry), 479 | Relation(OpKind, Name), 480 | UnificationHint(Name, u32), 481 | UserRecursor(RecursorInfo) 482 | } 483 | 484 | #[derive(Debug)] pub struct OLean { 485 | pub version: String, 486 | pub uses_sorry: bool, 487 | pub imports: Vec, 488 | pub code: Box<[u8]> 489 | } 490 | 491 | impl fmt::Display for OLean { 492 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 493 | writeln!(f, "version: {}", self.version)?; 494 | writeln!(f, "uses sorry: {}", self.uses_sorry)?; 495 | writeln!(f, "imports: {:?}", self.imports) 496 | } 497 | } 498 | -------------------------------------------------------------------------------- /src/lexer.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | use std::fs::File; 3 | use std::mem; 4 | use std::path::Path; 5 | use num::{rational::Ratio, BigInt, BigRational}; 6 | use unicode_reader::CodePoints; 7 | use crate::tokens::TokenTable; 8 | use crate::types::{KToken, Name}; 9 | 10 | fn is_letter_like_unicode(c: char) -> bool { 11 | ('α' <= c && c <= 'ω' && c != 'λ') || // Lower greek, except lambda 12 | ('Α' <= c && c <= 'Ω' && c != 'Π' && c != 'Σ') || // Upper greek, except Pi and Sigma 13 | ('ϊ' <= c && c <= 'ϻ') || // Coptic letters 14 | ('ἀ' <= c && c <= '῾') || // Polytonic Greek Extended Character Set 15 | ('℀' <= c && c <= '⅏') || // Letter like block 16 | ('𝒜' <= c && c <= '𝖟') // Latin letters, Script, Double-struck, Fractur 17 | } 18 | 19 | fn is_sub_script_alnum_unicode(c: char) -> bool { 20 | ('ⁿ' <= c && c <= '₉') || // n superscript and numberic subscripts 21 | ('ₐ' <= c && c <= 'ₜ') || // letter-like subscripts 22 | ('ᵢ' <= c && c <= 'ᵪ') // letter-like subscripts 23 | } 24 | 25 | fn is_id_first(c: char) -> bool { 26 | c.is_alphabetic() || c == '_' || c == '«' || is_letter_like_unicode(c) 27 | } 28 | 29 | fn is_id_rest(c: char) -> bool { 30 | c.is_alphanumeric() || c == '_' || c == '\'' || 31 | is_letter_like_unicode(c) || is_sub_script_alnum_unicode(c) 32 | } 33 | 34 | #[derive(Debug, PartialEq)] pub enum Token { 35 | Keyword(String, u32), 36 | CommandKeyword(String), 37 | Identifier(Name), 38 | Numeral(BigInt), 39 | Decimal(BigRational), 40 | StringTk(String), 41 | Char(char), 42 | QuotedSymbol(String), 43 | DocBlock(bool, String), 44 | FieldNum(u32), 45 | FieldName(Name), 46 | Eof 47 | } 48 | 49 | impl Token { 50 | pub fn is_tk(&self, s: &str) -> bool { 51 | match self { 52 | Token::Keyword(s2, _) => s == s2, 53 | Token::CommandKeyword(s2) => s == s2, 54 | _ => false 55 | } 56 | } 57 | 58 | pub fn tk(&self) -> Option<&str> { 59 | match self { 60 | Token::Keyword(s, _) => Some(s), 61 | Token::CommandKeyword(s) => Some(s), 62 | _ => None 63 | } 64 | } 65 | } 66 | 67 | fn invalid(s: &str) -> io::Error { io::Error::new(io::ErrorKind::InvalidData, s) } 68 | fn throw(s: &str) -> io::Result { Err(invalid(s)) } 69 | 70 | struct LexerCore>> { 71 | source: T, 72 | pushback: Vec, 73 | curr: char, 74 | in_notation: bool, 75 | allow_field_notation: bool 76 | } 77 | 78 | impl>> LexerCore { 79 | fn next(&mut self) -> io::Result { 80 | self.curr = 81 | if let Some(pb) = self.pushback.pop() {pb} 82 | else if let Some(ch) = self.source.next() {ch?} 83 | else {'\0'}; 84 | Ok(self.curr) 85 | } 86 | 87 | pub fn new(mut source: T) -> io::Result { 88 | let curr = if let Some(ch) = source.next() {ch?} else {'\0'}; 89 | Ok(LexerCore {source, pushback: Vec::new(), 90 | curr, in_notation: false, allow_field_notation: true}) 91 | } 92 | 93 | fn pushback(&mut self, last: char) { 94 | self.pushback.push(self.curr); 95 | self.curr = last; 96 | } 97 | 98 | fn read_number(&mut self) -> io::Result { 99 | let mut num = (self.curr as u32) - ('0' as u32); 100 | 101 | let base = if num == 0 { 102 | let base = match self.next()? { 103 | 'B' | 'b' => 2, 104 | 'O' | 'o' => 8, 105 | 'X' | 'x' => 16, 106 | _ => 10 107 | }; 108 | if base != 10 { 109 | num = self.next()?.to_digit(base) 110 | .ok_or_else(|| invalid("invalid numeral, expected digit after base prefix"))?; 111 | } 112 | base 113 | } else {10}; 114 | 115 | let mut num: BigInt = num.into(); 116 | let mut denom: Option = None; 117 | loop { 118 | if let Some(val) = self.curr.to_digit(base) { 119 | num = base*num + val; 120 | match &mut denom { Some(q) => *q *= 10, None => () }; 121 | self.next()?; 122 | } else if base == 10 && self.curr == '.' { 123 | if !self.next()?.is_digit(base) || denom.is_some() { 124 | self.pushback('.'); break 125 | } 126 | denom = Some(1.into()); 127 | } else {break} 128 | } 129 | match denom { 130 | Some(denom) => Ok(Token::Decimal(Ratio::new(num, denom))), 131 | None => Ok(Token::Numeral(num)) 132 | } 133 | } 134 | 135 | fn read_line_comment(&mut self) -> io::Result<()> { 136 | loop { 137 | match self.curr { 138 | '\0' => return Ok(()), 139 | '\n' => {self.next()?; return Ok(())}, 140 | _ => self.next()? 141 | }; 142 | } 143 | } 144 | 145 | fn read_block_comment(&mut self) -> io::Result<()> { 146 | let mut nest = 1; 147 | loop { 148 | match self.curr { 149 | '\0' => return throw("unexpected end of comment block"), 150 | '/' => if self.next()? == '-' { 151 | self.next()?; nest += 1; 152 | }, 153 | '-' => if self.next()? == '/' { 154 | nest -= 1; 155 | if nest == 0 { self.next()?; return Ok(()) } 156 | }, 157 | _ => { self.next()?; } 158 | } 159 | } 160 | } 161 | 162 | fn read_doc_block(&mut self, modd: bool) -> io::Result { 163 | let mut buf = String::new(); 164 | loop { 165 | let c = self.curr; 166 | match c { 167 | '\0' => return throw("unexpected end of documentation block"), 168 | '-' => if self.next()? == '/' { 169 | self.next()?; return Ok(Token::DocBlock(modd, buf)) 170 | }, 171 | _ => { self.next()?; } 172 | }; 173 | buf.push(c); 174 | } 175 | } 176 | 177 | fn read_single_char(&mut self, err_msg: &str) -> io::Result { 178 | match self.curr { 179 | '\0' => { throw(err_msg) }, 180 | '\\' => match self.next()? { 181 | '\0' => { throw(err_msg) }, 182 | 'n' => { self.next()?; Ok('\n') }, 183 | 't' => { self.next()?; Ok('\t') }, 184 | '\'' => { self.next()?; Ok('\'') }, 185 | '\"' => { self.next()?; Ok('\"') }, 186 | '\\' => { self.next()?; Ok('\\') }, 187 | 'x' => { 188 | let hex = self.next()?.to_digit(16).ok_or_else(|| invalid("invalid hex char in escape sequence"))?; 189 | let hex = 16*hex + self.next()?.to_digit(16).ok_or_else(|| invalid("invalid hex char in escape sequence"))?; 190 | std::char::from_u32(hex).ok_or_else(|| invalid("invalid utf-8")) }, 191 | 'u' => { 192 | let hex = self.next()?.to_digit(16).ok_or_else(|| invalid("invalid hex char in escape sequence"))?; 193 | let hex = 16*hex + self.next()?.to_digit(16).ok_or_else(|| invalid("invalid hex char in escape sequence"))?; 194 | let hex = 16*hex + self.next()?.to_digit(16).ok_or_else(|| invalid("invalid hex char in escape sequence"))?; 195 | let hex = 16*hex + self.next()?.to_digit(16).ok_or_else(|| invalid("invalid hex char in escape sequence"))?; 196 | std::char::from_u32(hex).ok_or_else(|| invalid("invalid utf-8")) }, 197 | _ => throw("invalid escape sequence") 198 | }, 199 | c => { self.next()?; Ok(c) } 200 | } 201 | } 202 | 203 | fn read_char(&mut self) -> io::Result { 204 | let c = self.read_single_char("unexpected end of character")?; 205 | if self.curr != '\'' {return throw("invalid character, ' expected")} 206 | self.next()?; Ok(Token::Char(c)) 207 | } 208 | 209 | fn read_string(&mut self) -> io::Result { 210 | let mut s = String::new(); self.next()?; 211 | loop { 212 | if self.curr == '\"' { 213 | self.next()?; return Ok(Token::StringTk(s)) } 214 | s.push(self.read_single_char("unexpected end of string")?); 215 | } 216 | } 217 | 218 | fn read_quoted_symbol(&mut self) -> io::Result { 219 | let mut s = String::new(); self.next()?; 220 | let mut start = false; 221 | let mut trailing_space = false; 222 | loop { 223 | match self.curr { 224 | '\0' => return throw("unexpected quoted identifier"), 225 | '`' if start => return throw("empty quoted identifier"), 226 | '`' => return Ok(Token::QuotedSymbol(s)), 227 | '\"' | '\n' | '\t' => return throw("invalid character in quoted identifier"), 228 | ' ' => { if !start {trailing_space = true}; s.push(' ') }, 229 | c if start && c.is_digit(10) => return throw("quoted identifier can't start with digit"), 230 | _ if trailing_space => return throw("unexpected space inside of quoted symbol"), 231 | c => { start = false; s.push(c) }, 232 | } 233 | self.next()?; 234 | } 235 | } 236 | 237 | fn read_field_idx(&mut self) -> io::Result { 238 | let mut num: u32 = 0; 239 | while let Some(m) = self.curr.to_digit(10) { 240 | num = num.checked_mul(10).and_then(|n| n.checked_add(m)) 241 | .ok_or_else(|| invalid("field notation index too large"))?; 242 | self.next()?; 243 | } 244 | Ok(Token::FieldNum(num)) 245 | } 246 | 247 | fn read_id_part(&mut self, cs: &mut String) -> io::Result<()> { 248 | let mut escaped = false; 249 | loop { 250 | if escaped { 251 | match self.curr { 252 | '»' => escaped = false, 253 | '\r' | '\t' | '\n' | '«' => return throw("illegal character in escaped identifier"), 254 | _ => () 255 | } 256 | } else { 257 | match self.curr { 258 | '«' => escaped = true, 259 | c if is_id_rest(c) => (), 260 | _ => return Ok(()) 261 | } 262 | } 263 | cs.push(self.curr); 264 | self.next()?; 265 | } 266 | } 267 | 268 | fn munch<'a>(&mut self, tt: &'a TokenTable, cs: &mut String) -> io::Result> { 269 | let mut res = tt.search().next(cs); 270 | loop { 271 | match res { 272 | Ok(tk) => return Ok(tk), 273 | Err(iter) => { 274 | let len = cs.len(); 275 | let c = self.next()?; 276 | if c == '\0' {return Ok(iter.finish())} 277 | cs.push(c); 278 | res = iter.next(&cs[len..]); 279 | } 280 | } 281 | } 282 | } 283 | 284 | fn read_key_cmd_id(&mut self, tt: &TokenTable) -> io::Result { 285 | let mut cs = String::new(); 286 | 287 | fn cs_to_name(cs: &str) -> Name { 288 | let mut n: Name = Name::anon(); 289 | let mut part = String::new(); 290 | let mut escaped = false; 291 | for c in cs.chars() { 292 | match c { 293 | '«' => escaped = true, 294 | '»' => escaped = false, 295 | '.' if !escaped => 296 | n = n.str(mem::replace(&mut part, String::new())), 297 | c => part.push(c) 298 | } 299 | } 300 | n.str(part) 301 | } 302 | 303 | let mut id_sz = 0; 304 | if self.allow_field_notation && self.curr == '.' { 305 | if self.next()?.is_digit(10) {return self.read_field_idx()} 306 | if is_id_first(self.curr) && self.curr != '_' { 307 | self.read_id_part(&mut cs)?; 308 | return Ok(Token::FieldName(cs_to_name(&cs))) 309 | } 310 | cs.push('.'); 311 | } else { 312 | while is_id_first(self.curr) { 313 | self.read_id_part(&mut cs)?; 314 | id_sz = cs.len(); 315 | if self.curr != '.' {break} 316 | cs.push('.'); 317 | self.next()?; 318 | } 319 | } 320 | cs.push(self.curr); 321 | 322 | let (tk, n) = match self.munch(tt, &mut cs)?.and_then(|(tk, n)| { 323 | if n/2 < id_sz {None} else {Some((tk, n/2))} 324 | }) { 325 | None => (Token::Identifier(cs_to_name(&cs[0..id_sz])), id_sz), 326 | Some((KToken {tk, prec: None}, n)) => (Token::CommandKeyword(tk.clone()), n), 327 | Some((KToken {tk, prec: Some(prec)}, n)) => (Token::Keyword(tk.clone(), *prec), n) 328 | }; 329 | if n == 0 {return throw("unexpected token")} 330 | for c in cs.split_at(n).1.chars().rev().skip(1) { self.pushback(c) } 331 | Ok(tk) 332 | } 333 | 334 | pub fn lex(&mut self, tt: &TokenTable) -> io::Result { 335 | loop { 336 | match self.curr { 337 | '\0' => return Ok(Token::Eof), 338 | ' ' | '\r' | '\t' | '\n' => (), 339 | '\"' => return self.read_string(), 340 | '`' if self.in_notation => return self.read_quoted_symbol(), 341 | c if c.is_digit(10) => return self.read_number(), 342 | _ => { 343 | match self.read_key_cmd_id(tt)? { 344 | Token::Keyword(s, prec) => match s.as_ref() { 345 | "--" => self.read_line_comment()?, 346 | "/-" => self.read_block_comment()?, 347 | "/--" => return self.read_doc_block(false), 348 | "/-!" => return self.read_doc_block(true), 349 | "\'" => return self.read_char(), 350 | _ => return Ok(Token::Keyword(s, prec)) }, 351 | k => return Ok(k) } 352 | } } 353 | self.next()?; 354 | } 355 | } 356 | } 357 | 358 | pub struct Lexer { 359 | pub token_table: TokenTable, 360 | data: LexerCore>> 361 | } 362 | 363 | pub fn from_file(path: &Path, tt: TokenTable) -> io::Result>> { 364 | Lexer::new(io::BufReader::new(File::open(path)?), tt) 365 | } 366 | 367 | impl Lexer { 368 | pub fn new(source: T, token_table: TokenTable) -> io::Result { 369 | Ok(Lexer {token_table, data: LexerCore::new(CodePoints::from(source))?}) 370 | } 371 | 372 | pub fn curr(&self) -> char { self.data.curr } 373 | 374 | pub fn lex(&mut self) -> io::Result { self.data.lex(&self.token_table) } 375 | 376 | pub fn allow_field_notation(&mut self, flag: bool) -> bool { 377 | mem::replace(&mut self.data.allow_field_notation, flag) 378 | } 379 | } 380 | 381 | impl Iterator for Lexer { 382 | type Item = io::Result; 383 | 384 | fn next(&mut self) -> Option> { 385 | if self.curr() == '\0' {return None} 386 | match self.lex() { 387 | Err(err) => Some(Err(err)), 388 | Ok(Token::Eof) => None, 389 | Ok(tk) => Some(Ok(tk)) 390 | } 391 | } 392 | } 393 | -------------------------------------------------------------------------------- /src/deserialize.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | use std::fs::File; 3 | use std::rc::Rc; 4 | use std::fmt; 5 | use std::cell::RefCell; 6 | use byteorder::{ReadBytesExt, BigEndian}; 7 | use num_traits::cast::FromPrimitive; 8 | use num::bigint::BigInt; 9 | use crate::types::*; 10 | use crate::hasher; 11 | 12 | fn invalid(s: &str) -> io::Error { 13 | io::Error::new(io::ErrorKind::InvalidInput, s) 14 | } 15 | 16 | fn throw(s: &str) -> io::Result { Err(invalid(s)) } 17 | 18 | fn guard(b: bool, s: &str) -> io::Result<()> { 19 | if b { Ok(()) } else { throw(s) } 20 | } 21 | 22 | trait Deserialize { 23 | fn read(&self, d: &mut T) -> io::Result; 24 | } 25 | 26 | impl Deserialize for S { 27 | fn read(&self, d: &mut T) -> io::Result { 28 | d.read_u8() 29 | } 30 | } 31 | 32 | impl Deserialize for S { 33 | fn read(&self, d: &mut T) -> io::Result { 34 | let x: u8 = ().read(d)?; 35 | if x < 255 { Ok(x.into()) } 36 | else { d.read_u32::() } 37 | } 38 | } 39 | 40 | impl Deserialize for S { 41 | fn read(&self, d: &mut T) -> io::Result { 42 | let c: u32 = ().read(d)?; 43 | Ok(c as usize) 44 | } 45 | } 46 | 47 | impl Deserialize for S { 48 | fn read(&self, d: &mut T) -> io::Result { 49 | let hi: u32 = ().read(d)?; 50 | let lo: u32 = ().read(d)?; 51 | Ok(((hi as u64) << 32) | (lo as u64)) 52 | } 53 | } 54 | 55 | fn readn(n: usize, mut f: F) -> io::Result> 56 | where F: FnMut() -> io::Result { 57 | let mut vec = Vec::with_capacity(n); 58 | for _ in 0..n { vec.push(f()?) } 59 | Ok(vec) 60 | } 61 | 62 | impl> Deserialize> for S { 63 | fn read(&self, d: &mut T) -> io::Result> { 64 | readn(().read(d)?, || self.read(d)) 65 | } 66 | } 67 | 68 | fn read_blob(d: &mut T) -> io::Result> { 69 | let n: usize = ().read(d)?; 70 | let mut buf: Vec = vec![0; n]; 71 | d.read_exact(buf.as_mut_slice())?; 72 | Ok(buf.into_boxed_slice()) 73 | } 74 | 75 | impl + Deserialize> Deserialize<(A, B)> for S { 76 | fn read(&self, d: &mut T) -> io::Result<(A, B)> { 77 | Ok((self.read(d)?, self.read(d)?)) 78 | } 79 | } 80 | 81 | impl> Deserialize> for S { 82 | fn read(&self, d: &mut T) -> io::Result> { 83 | Ok(>>::read(self, d)?.into_boxed_slice()) 84 | } 85 | } 86 | 87 | impl Deserialize for S { 88 | fn read(&self, d: &mut T) -> io::Result { 89 | let mut vec = Vec::new(); 90 | loop { 91 | let c: u8 = ().read(d)?; 92 | if c == 0 { 93 | return String::from_utf8(vec) 94 | .map_err(|s| invalid(&format!("bad utf8, got {:?}", s.into_bytes()))) 95 | } else { vec.push(c) } 96 | } 97 | } 98 | } 99 | 100 | impl Deserialize for S { 101 | fn read(&self, d: &mut T) -> io::Result { 102 | let c: u8 = ().read(d)?; 103 | Ok(c != 0) 104 | } 105 | } 106 | 107 | impl Deserialize for S { 108 | fn read(&self, d: &mut T) -> io::Result { 109 | let s: String = ().read(d)?; 110 | s.parse().map_err(|_| invalid("bad bignum")) 111 | } 112 | } 113 | 114 | impl> Deserialize> for S { 115 | fn read(&self, d: &mut T) -> io::Result> { 116 | Ok(if >::read(self, d)? { 117 | Some(self.read(d)?) 118 | } else { None }) 119 | } 120 | } 121 | 122 | struct ObjectReader{table: RefCell>} 123 | 124 | impl ObjectReader { 125 | fn new() -> ObjectReader { ObjectReader{table: RefCell::new(Vec::new())} } 126 | 127 | fn read_core(&self, d: &mut T, f: F) -> io::Result 128 | where F: FnOnce(&mut T, u8) -> io::Result { 129 | let c: u8 = ().read(d)?; 130 | if c == 0 { 131 | let table = self.table.borrow_mut(); 132 | let n: usize = table.read(d)?; 133 | let a = table.get(n).ok_or(invalid("out of range"))?; 134 | Ok(a.clone()) 135 | } else { 136 | let x = f(d, c-1)?; 137 | let mut table = self.table.borrow_mut(); 138 | table.push(x); 139 | Ok(table.last().unwrap().clone()) 140 | } 141 | } 142 | } 143 | 144 | impl Deserialize for ObjectReader { 145 | fn read(&self, d: &mut T) -> io::Result { 146 | ObjectReader::read_core(self, d, |d, n| { 147 | match n { 148 | 0 => Ok(Name::anon()), 149 | 1 => Ok(Name::str(Name::anon(), self.read(d)?)), 150 | 2 => Ok(Name::num(Name::anon(), self.read(d)?)), 151 | 3 => Ok(Name::str(self.read(d)?, self.read(d)?)), 152 | 4 => Ok(Name::num(self.read(d)?, self.read(d)?)), 153 | _ => throw(&format!("bad name {}", n)) 154 | } 155 | }) 156 | } 157 | } 158 | 159 | impl Deserialize for S { 160 | fn read(&self, d: &mut T) -> io::Result { 161 | let c: u8 = self.read(d)?; 162 | Ok(if c & 4 != 0 { BinderInfo::Implicit } 163 | else if c & 2 != 0 { BinderInfo::StrictImplicit } 164 | else if c & 1 != 0 { BinderInfo::InstImplicit } 165 | else if c & 8 != 0 { BinderInfo::AuxDecl } 166 | else { BinderInfo::Default }) 167 | } 168 | } 169 | 170 | struct Deserializer { 171 | name_reader: ObjectReader, 172 | lvl_reader: ObjectReader, 173 | expr_reader: ObjectReader 174 | } 175 | 176 | impl Deserializer { 177 | fn new() -> Deserializer { 178 | Deserializer { 179 | name_reader: ObjectReader::new(), 180 | lvl_reader: ObjectReader::new(), 181 | expr_reader: ObjectReader::new(), 182 | } 183 | } 184 | } 185 | 186 | impl Deserialize for Deserializer { 187 | fn read(&self, d: &mut T) -> io::Result { 188 | self.name_reader.read(d) 189 | } 190 | } 191 | 192 | impl Deserialize for Deserializer { 193 | fn read(&self, d: &mut T) -> io::Result { 194 | ObjectReader::read_core(&self.lvl_reader, d, |d, _| { 195 | let n: u8 = self.read(d)?; 196 | match n { 197 | 0 => Ok(Rc::new(Level2::Zero)), 198 | 1 => Ok(Rc::new(Level2::Succ(self.read(d)?))), 199 | 2 => Ok(Rc::new(Level2::Max(self.read(d)?, self.read(d)?))), 200 | 3 => Ok(Rc::new(Level2::IMax(self.read(d)?, self.read(d)?))), 201 | 4 => Ok(Rc::new(Level2::Param(self.name_reader.read(d)?))), 202 | 5 => Ok(Rc::new(Level2::Meta(self.name_reader.read(d)?))), 203 | _ => throw(&format!("bad name {}", n)) 204 | } 205 | }) 206 | } 207 | } 208 | 209 | impl Deserialize for Deserializer { 210 | fn read(&self, d: &mut T) -> io::Result { 211 | Ok(EquationsHeader { 212 | num_fns: self.read(d)?, 213 | is_private: self.read(d)?, 214 | is_meta: self.read(d)?, 215 | is_ncomp: self.read(d)?, 216 | is_lemma: self.read(d)?, 217 | is_aux_lemmas: self.read(d)?, 218 | prev_errors: self.read(d)?, 219 | gen_code: self.read(d)?, 220 | fn_names: self.read(d)?, 221 | fn_actual_names: self.read(d)? }) 222 | } 223 | } 224 | 225 | fn read_macro(s: &Deserializer, d: &mut T, args: Vec) -> io::Result { 226 | let k: String = s.read(d)?; 227 | let m = match &*k { 228 | "Prenum" => MacroDef::Prenum(s.read(d)?), 229 | "STI" => MacroDef::StructureInstance { 230 | struct_: s.read(d)?, catchall: s.read(d)?, fields: s.read(d)? }, 231 | "fieldN" => MacroDef::FieldNotation(s.read(d)?, s.read(d)?), 232 | "Annot" => MacroDef::Annot(s.read(d)?), 233 | "Choice" => MacroDef::Choice, 234 | "CNatM" => MacroDef::NatValue(s.read(d)?), 235 | "RecFn" => MacroDef::RecFn(s.read(d)?), 236 | "Proj" => MacroDef::Proj { 237 | i_name: s.read(d)?, c_name: s.read(d)?, proj_name: s.read(d)?, 238 | idx: s.read(d)?, ps: s.read(d)?, ty: s.read(d)?, val: s.read(d)? }, 239 | "Eqns" => MacroDef::Equations(s.read(d)?), 240 | "Eqn" => MacroDef::Equation { ignore_if_unused: s.read(d)? }, 241 | "NEqn" => MacroDef::NoEquation, 242 | "EqnR" => MacroDef::EquationsResult, 243 | "AsPat" => MacroDef::AsPattern, 244 | "Quote" => MacroDef::ExprQuote { val: s.read(d)?, reflected: s.read(d)? }, 245 | "Sorry" => MacroDef::Sorry { synth: s.read(d)? }, 246 | "Str" => MacroDef::String(s.read(d)?), 247 | "ACApp" => MacroDef::ACApp, 248 | "PermAC" => MacroDef::PermAC, 249 | "TyE" => MacroDef::TypedExpr, 250 | _ => unimplemented!("unknown macro {}", k) 251 | }; 252 | guard(check_macro(&m, &args), "bad macro args")?; 253 | Ok(Rc::new(Expr2::Macro(m, args))) 254 | } 255 | 256 | // These are un-inlined from Deserialize because the intermediates 257 | // in all the match branches bloat the stack frame, and this function is called deeply 258 | fn read_var(d: &mut T) -> io::Result { 259 | Ok(Rc::new(Expr2::Var(().read(d)?))) } 260 | fn read_sort(s: &Deserializer, d: &mut T) -> io::Result { 261 | Ok(Rc::new(Expr2::Sort(s.read(d)?))) } 262 | fn read_const(s: &Deserializer, d: &mut T) -> io::Result { 263 | Ok(Rc::new(Expr2::Const(s.read(d)?, s.read(d)?))) } 264 | fn read_mvar(s: &Deserializer, d: &mut T) -> io::Result { 265 | Ok(Rc::new(Expr2::MVar(s.read(d)?, s.read(d)?, s.read(d)?))) } 266 | fn read_local(s: &Deserializer, d: &mut T) -> io::Result { 267 | Ok(Rc::new(Expr2::Local(s.read(d)?, s.read(d)?, s.read(d)?, s.read(d)?))) } 268 | fn read_app(s: &Deserializer, d: &mut T) -> io::Result { 269 | Ok(Rc::new(Expr2::App(s.read(d)?, s.read(d)?))) } 270 | fn read_lam(s: &Deserializer, d: &mut T) -> io::Result { 271 | Ok(Rc::new(Expr2::Lam(s.read(d)?, s.read(d)?, s.read(d)?, s.read(d)?))) } 272 | fn read_pi(s: &Deserializer, d: &mut T) -> io::Result { 273 | Ok(Rc::new(Expr2::Pi(s.read(d)?, s.read(d)?, s.read(d)?, s.read(d)?))) } 274 | fn read_let(s: &Deserializer, d: &mut T) -> io::Result { 275 | Ok(Rc::new(Expr2::Let(s.read(d)?, s.read(d)?, s.read(d)?, s.read(d)?))) } 276 | fn read_macro_expr(s: &Deserializer, d: &mut T) -> io::Result { 277 | let args = s.read(d)?; Ok(read_macro(s, d, args)?) } 278 | 279 | impl Deserialize for Deserializer { 280 | fn read(&self, d: &mut T) -> io::Result { 281 | ObjectReader::read_core(&self.expr_reader, d, |d, n| { 282 | match n { 283 | 0 => read_var(d), 284 | 1 => read_sort(self, d), 285 | 2 => read_const(self, d), 286 | 3 => read_mvar(self, d), 287 | 4 => read_local(self, d), 288 | 5 => read_app(self, d), 289 | 6 => read_lam(self, d), 290 | 7 => read_pi(self, d), 291 | 8 => read_let(self, d), 292 | 9 => read_macro_expr(self, d), 293 | _ => throw(&format!("bad name {}", n)) 294 | } 295 | }) 296 | } 297 | } 298 | 299 | impl Deserialize for Deserializer { 300 | fn read(&self, d: &mut T) -> io::Result { 301 | Ok(ModuleName{relative: self.read(d)?, name: self.read(d)?}) 302 | } 303 | } 304 | 305 | impl Deserialize for Deserializer { 306 | fn read(&self, d: &mut T) -> io::Result { 307 | Ok(ExportDecl { 308 | ns: self.read(d)?, 309 | as_: self.read(d)?, 310 | had_explicit: self.read(d)?, 311 | except_names: self.read(d)?, 312 | renames: self.read(d)? 313 | }) 314 | } 315 | } 316 | 317 | impl Deserialize for Deserializer { 318 | fn read(&self, d: &mut T) -> io::Result { 319 | let k: u8 = self.read(d)?; 320 | Ok(match k { 321 | 0 => { let b = self.read(d)?; ReducibilityHints::Regular(self.read(d)?, b) }, 322 | 1 => ReducibilityHints::Opaque, 323 | 2 => ReducibilityHints::Abbrev, 324 | _ => throw("bad reducibility hints")? 325 | }) 326 | } 327 | } 328 | 329 | impl Deserialize for Deserializer { 330 | fn read(&self, d: &mut T) -> io::Result { 331 | let k: u8 = self.read(d)?; 332 | let has_value = k & 1 != 0; 333 | let is_th_ax = k & 2 != 0; 334 | let is_trusted = k & 4 != 0; 335 | let n = self.read(d)?; 336 | let ps = self.read(d)?; 337 | let ty = self.read(d)?; 338 | Ok(if has_value { 339 | let val = self.read(d)?; 340 | if is_th_ax { 341 | Declaration::Thm{name: n, ps, ty, val} 342 | } else { 343 | Declaration::Defn{name: n, ps, ty, val, hints: self.read(d)?, is_trusted} 344 | } 345 | } else if is_th_ax { Declaration::Ax{name: n, ps, ty} } 346 | else { Declaration::Cnst{name: n, ps, ty, is_trusted} }) 347 | } 348 | } 349 | 350 | impl Deserialize for S { 351 | fn read(&self, d: &mut T) -> io::Result { 352 | Ok(PosInfo{line: ().read(d)?, col: ().read(d)?}) 353 | } 354 | } 355 | 356 | impl Deserialize for S { 357 | fn read(&self, d: &mut T) -> io::Result { 358 | FromPrimitive::from_u8(self.read(d)?).ok_or(invalid("bad reducible")) 359 | } 360 | } 361 | 362 | impl Deserialize for S { 363 | fn read(&self, d: &mut T) -> io::Result { 364 | Ok(FromPrimitive::from_u8(self.read(d)?).unwrap_or(ElabStrategy::Simple)) 365 | } 366 | } 367 | 368 | fn read_attr_ext(s: &Deserializer, d: &mut T, n: Name) -> io::Result { 369 | Ok(match n.to_simple_name() { 370 | Some("_refl_lemma") => AttrData::Basic, 371 | Some("simp") => AttrData::Basic, 372 | Some("wrapper_eq") => AttrData::Basic, 373 | Some("congr") => AttrData::Basic, 374 | Some("elab_strategy") => AttrData::ElabStrategy(s.read(d)?), 375 | Some("elab_with_expected_type") => AttrData::Basic, 376 | Some("elab_as_eliminator") => AttrData::Basic, 377 | Some("elab_simple") => AttrData::Basic, 378 | Some("parsing_only") => AttrData::Basic, 379 | Some("pp_using_anonymous_constructor") => AttrData::Basic, 380 | Some("user_command") => AttrData::Basic, 381 | Some("user_notation") => AttrData::Basic, 382 | Some("user_attribute") => AttrData::Basic, 383 | Some("algebra") => AttrData::Basic, 384 | Some("class") => AttrData::Basic, 385 | Some("instance") => AttrData::Basic, 386 | Some("inline") => AttrData::Basic, 387 | Some("inverse") => AttrData::Basic, 388 | Some("pattern") => AttrData::Basic, 389 | Some("reducibility") => AttrData::Reducibility(().read(d)?), 390 | Some("reducible") => AttrData::Basic, 391 | Some("semireducible") => AttrData::Basic, 392 | Some("irreducible") => AttrData::Basic, 393 | Some("refl") => AttrData::Basic, 394 | Some("symm") => AttrData::Basic, 395 | Some("trans") => AttrData::Basic, 396 | Some("subst") => AttrData::Basic, 397 | Some("intro") => AttrData::Intro{eager: ().read(d)?}, 398 | Some("hole_command") => AttrData::Basic, 399 | Some("no_inst_pattern") => AttrData::Basic, 400 | Some("vm_monitor") => AttrData::Basic, 401 | Some("unify") => AttrData::Basic, 402 | Some("recursor") => AttrData::Indices(().read(d)?), 403 | _ => 404 | if n == name![_simp.sizeof] { AttrData::Basic } 405 | else { AttrData::User(s.read(d)?) } 406 | }) 407 | } 408 | 409 | impl Deserialize for Deserializer { 410 | fn read(&self, d: &mut T) -> io::Result { 411 | let attr = self.read(d)?; 412 | let prio = self.read(d)?; 413 | let decl = self.read(d)?; 414 | let deleted = self.read(d)?; 415 | Ok(if deleted { 416 | AttrEntry{attr, prio, record: AttrRecord(decl, None)} } 417 | else { AttrEntry { 418 | attr: attr.clone(), prio, 419 | record: AttrRecord(decl, Some(read_attr_ext(self, d, attr)?)) } }) 420 | } 421 | } 422 | 423 | impl Deserialize for Deserializer { 424 | fn read(&self, d: &mut T) -> io::Result { 425 | Ok(InductiveDecl { 426 | name: self.read(d)?, 427 | level_params: self.read(d)?, 428 | nparams: self.read(d)?, 429 | ty: self.read(d)?, 430 | rules: self.read(d)? }) 431 | } 432 | } 433 | 434 | impl Deserialize for Deserializer { 435 | fn read(&self, d: &mut T) -> io::Result { 436 | Ok(CompRule { num_bu: self.read(d)?, comp_rhs: self.read(d)? }) 437 | } 438 | } 439 | 440 | impl Deserialize for Deserializer { 441 | fn read(&self, d: &mut T) -> io::Result { 442 | Ok(InductiveDefn { 443 | num_ac_e: self.read(d)?, 444 | elim_prop: self.read(d)?, 445 | dep_elim: self.read(d)?, 446 | level_params: self.read(d)?, 447 | elim_type: self.read(d)?, 448 | decl: self.read(d)?, 449 | is_k: self.read(d)?, 450 | num_indices: self.read(d)?, 451 | is_trusted: self.read(d)?, 452 | comp_rules: self.read(d)? }) 453 | } 454 | } 455 | 456 | impl Deserialize for S { 457 | fn read(&self, d: &mut T) -> io::Result { 458 | FromPrimitive::from_u8(self.read(d)?).ok_or(invalid("bad ginductive kind")) 459 | } 460 | } 461 | 462 | impl Deserialize for Deserializer { 463 | fn read(&self, d: &mut T) -> io::Result { 464 | let kind = self.read(d)?; 465 | let inner = self.read(d)?; 466 | let num_params = self.read(d)?; 467 | let num_indices = self.read(d)?; 468 | let inds: Vec = self.read(d)?; 469 | let mut intro_rules = readn(inds.len(), || self.read(d))?; 470 | intro_rules.reverse(); 471 | Ok(GInductiveEntry { 472 | kind, inner, num_params, num_indices, inds, intro_rules, 473 | offsets: self.read(d)?, 474 | idx_to_ir_range: self.read(d)?, 475 | packs: self.read(d)?, 476 | unpacks: self.read(d)? }) 477 | } 478 | } 479 | 480 | impl Deserialize for Deserializer { 481 | fn read(&self, d: &mut T) -> io::Result { 482 | Ok(VMLocalInfo {id: self.read(d)?, ty: self.read(d)?}) 483 | } 484 | } 485 | 486 | impl Deserialize for Deserializer { 487 | fn read(&self, d: &mut T) -> io::Result { 488 | let k: u8 = self.read(d)?; 489 | Ok(match k { 490 | 0 => VMInstr::Push(self.read(d)?), 491 | 1 => VMInstr::Move(self.read(d)?), 492 | 2 => VMInstr::Ret, 493 | 3 => VMInstr::Drop(self.read(d)?), 494 | 4 => VMInstr::Goto(self.read(d)?), 495 | 5 => VMInstr::SConstr(self.read(d)?), 496 | 6 => VMInstr::Constr(self.read(d)?, self.read(d)?), 497 | 7 => VMInstr::Num(self.read(d)?), 498 | 8 => VMInstr::Destruct, 499 | 9 => VMInstr::Cases2(self.read(d)?, self.read(d)?), 500 | 10 => VMInstr::CasesN(self.read(d)?), 501 | 11 => VMInstr::NatCases(self.read(d)?, self.read(d)?), 502 | 12 => VMInstr::BuiltinCases(self.read(d)?, self.read(d)?), 503 | 13 => VMInstr::Proj(self.read(d)?), 504 | 14 => VMInstr::Apply, 505 | 15 => VMInstr::InvokeGlobal(self.read(d)?), 506 | 16 => VMInstr::InvokeBuiltin(self.read(d)?), 507 | 17 => VMInstr::InvokeCFun(self.read(d)?), 508 | 18 => VMInstr::Closure(self.read(d)?, self.read(d)?), 509 | 19 => VMInstr::Unreachable, 510 | 20 => VMInstr::Expr(self.read(d)?), 511 | 21 => VMInstr::LocalInfo(self.read(d)?, self.read(d)?), 512 | _ => throw("bad opcode")? 513 | }) 514 | } 515 | } 516 | 517 | impl Deserialize for Deserializer { 518 | fn read(&self, d: &mut T) -> io::Result { 519 | let name = self.read(d)?; 520 | let arity = self.read(d)?; 521 | let code_sz = self.read(d)?; 522 | let pos_info = self.read(d)?; 523 | let args_info = self.read(d)?; 524 | let code = readn(code_sz, || self.read(d))?; 525 | Ok(VMDecl { kind: VMDeclKind::Bytecode(code), 526 | name, arity, args_info, pos_info, olean: None }) 527 | } 528 | } 529 | 530 | impl Deserialize for Deserializer { 531 | fn read(&self, d: &mut T) -> io::Result { 532 | Ok(ProjectionInfo { 533 | constr: self.read(d)?, 534 | nparams: self.read(d)?, 535 | i: self.read(d)?, 536 | inst_implicit: self.read(d)? }) 537 | } 538 | } 539 | 540 | impl Deserialize for Deserializer { 541 | fn read(&self, d: &mut T) -> io::Result { 542 | let k: u8 = self.read(d)?; 543 | Ok(match k { 544 | 0 => ClassEntry::Class(self.read(d)?), 545 | 1 => ClassEntry::Instance(self.read(d)?, self.read(d)?, self.read(d)?), 546 | 2 => ClassEntry::Tracker(self.read(d)?, self.read(d)?), 547 | _ => throw("bad class entry")? 548 | }) 549 | } 550 | } 551 | 552 | impl Deserialize for Deserializer { 553 | fn read(&self, d: &mut T) -> io::Result { 554 | let k: u8 = self.read(d)?; 555 | Ok(match k { 556 | 0 => Action::Skip, 557 | 1 => Action::Expr{rbp: self.read(d)?}, 558 | 2 => Action::Exprs { 559 | sep: self.read(d)?, 560 | rec: self.read(d)?, 561 | ini: self.read(d)?, 562 | is_foldr: self.read(d)?, 563 | rbp: self.read(d)?, 564 | terminator: self.read(d)? }, 565 | 3 => Action::Binder{rbp: self.read(d)?}, 566 | 4 => Action::Binders{rbp: self.read(d)?}, 567 | 5 => Action::ScopedExpr { 568 | rec: self.read(d)?, 569 | rbp: self.read(d)?, 570 | use_lambda: self.read(d)? }, 571 | 6 => throw("Ext actions never appear in olean files")?, 572 | _ => throw("bad action")? 573 | }) 574 | } 575 | } 576 | 577 | impl Deserialize for Deserializer { 578 | fn read(&self, d: &mut T) -> io::Result { 579 | Ok(Transition{tk: self.read(d)?, pp: self.read(d)?, act: self.read(d)?}) 580 | } 581 | } 582 | 583 | impl Deserialize for S { 584 | fn read(&self, d: &mut T) -> io::Result { 585 | FromPrimitive::from_u8(self.read(d)?).ok_or(invalid("bad notation entry group")) 586 | } 587 | } 588 | 589 | impl Deserialize for Deserializer { 590 | fn read(&self, d: &mut T) -> io::Result { 591 | let k: u8 = self.read(d)?; 592 | let overload = self.read(d)?; 593 | let parse_only = self.read(d)?; 594 | let expr = self.read(d)?; 595 | Ok(if k == 2 { 596 | NotationEntry { 597 | kind: NotationEntryKind::Numeral(self.read(d)?), 598 | expr, overload, parse_only, 599 | group: NotationEntryGroup::Main } 600 | } else { 601 | NotationEntry { 602 | group: self.read(d)?, 603 | kind: NotationEntryKind::Reg { 604 | is_nud: match k { 0 => true, 1 => false, _ => throw("bad notation entry")? }, 605 | transitions: self.read(d)?, 606 | prio: self.read(d)? }, 607 | expr, overload, parse_only } 608 | }) 609 | } 610 | } 611 | 612 | impl Deserialize for Deserializer { 613 | fn read(&self, d: &mut T) -> io::Result { 614 | Ok(InverseEntry { 615 | decl: self.read(d)?, 616 | arity: self.read(d)?, 617 | inv: self.read(d)?, 618 | inv_arity: self.read(d)?, 619 | lemma: self.read(d)? }) 620 | } 621 | } 622 | 623 | impl Deserialize for S { 624 | fn read(&self, d: &mut T) -> io::Result { 625 | FromPrimitive::from_u8(self.read(d)?).ok_or(invalid("bad op kind")) 626 | } 627 | } 628 | 629 | impl Deserialize for Deserializer { 630 | fn read(&self, d: &mut T) -> io::Result { 631 | Ok(RecursorInfo { 632 | rec: self.read(d)?, 633 | ty: self.read(d)?, 634 | dep_elim: self.read(d)?, 635 | recursive: self.read(d)?, 636 | num_args: self.read(d)?, 637 | major_pos: self.read(d)?, 638 | univ_pos: self.read(d)?, 639 | params_pos: self.read(d)?, 640 | indices_pos: self.read(d)?, 641 | produce_motive: self.read(d)? }) 642 | } 643 | } 644 | 645 | pub fn read_olean(mut f: File) -> io::Result { 646 | let ds = Deserializer::new(); 647 | let header: String = ds.read(&mut f)?; 648 | guard(header == "oleanfile", "incorrect header")?; 649 | let version: String = ds.read(&mut f)?; 650 | let claimed_hash: u32 = ds.read(&mut f)?; 651 | let uses_sorry = ds.read(&mut f)?; 652 | let imports = ds.read(&mut f)?; 653 | let code = read_blob(&mut f)?; 654 | guard(claimed_hash == hasher::hash(&code), "incorrect hash")?; 655 | Ok(OLean { version, uses_sorry, imports, code }) 656 | } 657 | 658 | pub fn read_olean_modifications(mut d: &[u8]) -> io::Result> { 659 | let ds = Deserializer::new(); 660 | let mut mods = Vec::new(); 661 | loop { 662 | let k: String = ds.read(&mut d)?; 663 | mods.push(match &*k { 664 | "EndFile" => return Ok(mods), 665 | "export_decl" => Modification::ExportDecl(ds.read(&mut d)?, ds.read(&mut d)?), 666 | "decl" => Modification::Decl { decl: ds.read(&mut d)?, trust_lvl: ds.read(&mut d)? }, 667 | "PInfo" => Modification::PosInfo(ds.read(&mut d)?, ds.read(&mut d)?), 668 | "ind" => Modification::Inductive { defn: ds.read(&mut d)?, trust_lvl: ds.read(&mut d)? }, 669 | "auxrec" => Modification::AuxRec(ds.read(&mut d)?), 670 | "prt" => Modification::Protected(ds.read(&mut d)?), 671 | "prv" => Modification::Private { name: ds.read(&mut d)?, real: ds.read(&mut d)? }, 672 | "gind" => Modification::GInd(ds.read(&mut d)?), 673 | "nspace" => Modification::NewNS(ds.read(&mut d)?), 674 | "VMR" => Modification::VMReserve(ds.read(&mut d)?, ds.read(&mut d)?), 675 | "VMC" => Modification::VMCode(ds.read(&mut d)?), 676 | "VMMonitor" => Modification::VMMonitor(ds.read(&mut d)?), 677 | "EqnL" => Modification::EqnLemmas(ds.read(&mut d)?), 678 | "SEqnL" => Modification::HasSimpleEqnLemma(ds.read(&mut d)?), 679 | "no_conf" => Modification::NoConf(ds.read(&mut d)?), 680 | "doc" => Modification::Doc(ds.read(&mut d)?, ds.read(&mut d)?), 681 | "ncomp" => Modification::Noncomputable(ds.read(&mut d)?), 682 | "proj" => Modification::Proj(ds.read(&mut d)?, ds.read(&mut d)?), 683 | "decl_trace" => Modification::DeclTrace(ds.read(&mut d)?), 684 | "USR_CMD" => Modification::UserCommand(ds.read(&mut d)?), 685 | "USR_NOTATION" => Modification::UserNotation(ds.read(&mut d)?), 686 | "USR_ATTR" => Modification::UserAttribute(ds.read(&mut d)?), 687 | "HOLE_CMD" => Modification::HoleCommand(ds.read(&mut d)?), 688 | "quot" => Modification::Quot, 689 | "native_module_path" => Modification::NativeModulePath(ds.read(&mut d)?), 690 | "key_eqv" => Modification::KeyEquivalence(ds.read(&mut d)?, ds.read(&mut d)?), 691 | 692 | "TK" => Modification::Token(KToken{tk: ds.read(&mut d)?, prec: ds.read(&mut d)?}), 693 | "NOTA" => Modification::Notation(ds.read(&mut d)?), 694 | "ATTR" => Modification::Attr(ds.read(&mut d)?), 695 | "class" => Modification::Class(ds.read(&mut d)?), 696 | "inverse" => Modification::Inverse(ds.read(&mut d)?), 697 | "REL" => Modification::Relation(ds.read(&mut d)?, ds.read(&mut d)?), 698 | "UNIFICATION_HINT" => Modification::UnificationHint(ds.read(&mut d)?, ds.read(&mut d)?), 699 | "UREC" => Modification::UserRecursor(ds.read(&mut d)?), 700 | "active_export_decls" => return throw("active_export_decls should not appear in olean files"), 701 | _ => return throw(&format!("unknown modification {}", k)) 702 | }) 703 | } 704 | } 705 | -------------------------------------------------------------------------------- /olean.lean: -------------------------------------------------------------------------------- 1 | import system.io 2 | open io 3 | 4 | structure equations_header := 5 | (num_fns : unsigned) 6 | (is_private : bool) 7 | (is_meta : bool) 8 | (is_ncomp : bool) 9 | (is_lemma : bool) 10 | (is_aux_lemmas : bool) 11 | (prev_errors : bool) 12 | (gen_code : bool) 13 | (fn_names : list name) 14 | (fn_actual_names : list name) 15 | 16 | meta mutual inductive macro_def', expr' 17 | with macro_def' : Type 18 | | prenum (n : ℤ) 19 | | struct_inst (struct : name) (catchall : bool) (fields : list name) 20 | | field_notation (name : name) (idx : unsigned) 21 | | annot (name : name) 22 | | choice 23 | | nat_value (n : ℤ) 24 | | rec_fn (name : name) 25 | | proj (i c proj : name) (idx : unsigned) (ps : list name) (ty val : expr') 26 | | equations (header : equations_header) 27 | | equation (ignore_if_unused : bool) 28 | | no_equation 29 | | equations_result 30 | | as_pattern 31 | | expr_quote (val : expr') (reflected : bool) 32 | | sorry_ (synth : bool) 33 | | string (s : string) 34 | | ac_app 35 | | perm_ac 36 | | typed_expr 37 | 38 | with expr' : Type 39 | | var {} : nat → expr' 40 | | sort {} : level → expr' 41 | | const {} : name → list level → expr' 42 | | mvar : name → name → expr' → expr' 43 | | local_const : name → name → binder_info → expr' → expr' 44 | | app : expr' → expr' → expr' 45 | | lam : name → binder_info → expr' → expr' → expr' 46 | | pi : name → binder_info → expr' → expr' → expr' 47 | | elet : name → expr' → expr' → expr' → expr' 48 | | macro : macro_def' → list expr' → expr' 49 | 50 | private meta def ls := λ xs, format.join (list.intersperse " " xs) 51 | private meta def p := format.paren ∘ ls 52 | private meta def br : list format → format 53 | | [] := to_fmt "⟨⟩" 54 | | xs := to_fmt "⟨" ++ 55 | format.group (format.nest 1 $ format.join $ 56 | list.intersperse ("," ++ format.line) $ xs.map to_fmt) ++ to_fmt "⟩" 57 | 58 | meta instance : has_to_format equations_header := 59 | ⟨λ ⟨e1,e2,e3,e4,e5,e6,e7,e8,e9,e10⟩, br [ 60 | to_fmt e1, to_fmt e2, to_fmt e3, to_fmt e4, to_fmt e5, 61 | to_fmt e6, to_fmt e7, to_fmt e8, to_fmt e9, to_fmt e10]⟩ 62 | 63 | section 64 | open macro_def' expr' 65 | 66 | meta mutual def macro_def'.to_fmt, expr'.to_fmt 67 | with macro_def'.to_fmt : macro_def' → format 68 | | (prenum n) := ls ["prenum", to_string n] 69 | | (struct_inst n c f) := ls ["struct_inst", to_fmt n, to_fmt c, to_fmt f] 70 | | (field_notation n i) := ls ["field_notation", to_fmt n, to_fmt i] 71 | | (annot n) := ls ["annot", to_fmt n] 72 | | choice := "choice" 73 | | (nat_value n) := ls ["nat_value", to_string n] 74 | | (rec_fn n) := ls ["rec_fn", to_fmt n] 75 | | (proj i c pj ix ps ty v) := ls ["proj", to_fmt i, to_fmt c, 76 | to_fmt pj, to_fmt ix, to_fmt ps, ty.to_fmt, v.to_fmt] 77 | | (equations h) := ls ["equations", to_fmt h] 78 | | (equation i) := ls ["equation", to_fmt i] 79 | | no_equation := "no_equation" 80 | | equations_result := "equations_result" 81 | | as_pattern := "as_pattern" 82 | | (expr_quote v r) := ls ["expr_quote", v.to_fmt, to_fmt r] 83 | | (sorry_ s) := ls ["sorry", to_fmt s] 84 | | (string s) := ls ["string", to_fmt s] 85 | | ac_app := "ac_app" 86 | | perm_ac := "perm_ac" 87 | | typed_expr := "typed_expr" 88 | 89 | with expr'.to_fmt : expr' → format 90 | | (var n) := p ["var", to_fmt n] 91 | | (sort l) := p ["sort", to_fmt l] 92 | | (const n ls) := p ["const", to_fmt n, to_fmt ls] 93 | | (mvar n m t) := p ["mvar", to_fmt n, to_fmt m, t.to_fmt] 94 | | (local_const n m bi t) := p ["local_const", to_fmt n, to_fmt m, t.to_fmt] 95 | | (app e f) := p ["app", e.to_fmt, f.to_fmt] 96 | | (lam n bi e t) := p ["lam", to_fmt n, repr bi, e.to_fmt, t.to_fmt] 97 | | (pi n bi e t) := p ["pi", to_fmt n, repr bi, e.to_fmt, t.to_fmt] 98 | | (elet n g e f) := p ["elet", to_fmt n, g.to_fmt, e.to_fmt, f.to_fmt] 99 | | (macro d args) := p ("macro" :: d.to_fmt :: args.map expr'.to_fmt) 100 | 101 | meta instance : has_to_format macro_def' := ⟨macro_def'.to_fmt⟩ 102 | meta instance : has_to_format expr' := ⟨expr'.to_fmt⟩ 103 | 104 | meta instance : has_to_string macro_def' := ⟨format.to_string ∘ to_fmt⟩ 105 | meta instance : has_to_string expr' := ⟨format.to_string ∘ to_fmt⟩ 106 | 107 | end 108 | meta structure deserializer_data := 109 | (seek : ℕ) 110 | (readn : ℕ → ℕ → io char_buffer) 111 | (name_table : buffer name) 112 | (level_table : buffer level) 113 | (expr'_table : buffer expr') 114 | 115 | meta def mk_data (f : ℕ → ℕ → io char_buffer) : deserializer_data := 116 | ⟨0, f, mk_buffer, mk_buffer, mk_buffer⟩ 117 | 118 | @[reducible] meta def deserializer := state_t deserializer_data io 119 | 120 | namespace deserializer 121 | open deserializer_data 122 | 123 | meta def from_file {α} (s : string) (m : deserializer α) : io α := 124 | do h ← mk_file_handle s mode.read tt, 125 | prod.fst <$> m.run (mk_data $ λ _, monad_io_file_system.read h) 126 | 127 | meta def from_buffer {α} (buf : char_buffer) (m : deserializer α) : io α := 128 | prod.fst <$> m.run (mk_data $ λ s n, 129 | return ⟨min n (buf.size - s), ⟨λ i, buf.read' (s+i.1)⟩⟩) 130 | 131 | meta class readable (α : Type*) := (read1 {} : deserializer α) 132 | 133 | meta def view {α} [readable α] : deserializer α := readable.read1 134 | 135 | meta def viewa (α) [H : readable α] : deserializer α := readable.read1 136 | 137 | meta def read_buf (n : ℕ) : deserializer char_buffer := 138 | do d ← get, 139 | buf ← monad_lift $ d.readn d.seek n, 140 | put {seek := d.seek + buf.size, ..d}, 141 | return buf 142 | 143 | meta def corrupted {α} (s : string := "corrupted stream"): deserializer α := 144 | do d ← get, monad_lift $ do 145 | buf ← d.readn (d.seek - 10) 11, 146 | io.fail (s ++ " at " ++ to_string d.seek ++ 147 | "\n" ++ to_string (char_to_hex <$> buf.to_list) ++ 148 | "\n" ++ to_string (buf.to_list)) 149 | 150 | meta instance char.readable : readable char := 151 | ⟨do ⟨1, a⟩ ← read_buf 1 | corrupted "EOF", 152 | return (a.read 0)⟩ 153 | 154 | meta def readb : deserializer ℕ := char.val <$> viewa char 155 | 156 | meta def read_unsigned_ext : deserializer unsigned := 157 | do ⟨4, a⟩ ← read_buf 4 | corrupted "EOF", 158 | return $ unsigned.of_nat' $ 159 | (a.read 0).1.shiftl 24 + 160 | (a.read 1).1.shiftl 16 + 161 | (a.read 2).1.shiftl 8 + 162 | (a.read 3).1 163 | 164 | meta instance unsigned.readable : readable unsigned := 165 | ⟨do c ← readb, if c < 255 then 166 | return (unsigned.of_nat' c) else read_unsigned_ext⟩ 167 | 168 | meta instance nat.readable : readable ℕ := 169 | ⟨unsigned.to_nat <$> view⟩ 170 | 171 | meta def read64 : deserializer ℕ := 172 | do hi ← view, lo ← view, 173 | return (nat.shiftl hi 32 + lo) 174 | 175 | meta def read_blob : deserializer char_buffer := 176 | view >>= read_buf 177 | 178 | meta instance bool.readable : readable bool := 179 | ⟨(λ n, n ≠ 0) <$> readb⟩ 180 | 181 | meta def iterate {α} (a : α) (f : α → deserializer (option α)) : deserializer α := 182 | ⟨λ d, io.iterate (a, d) (λ ⟨a', d'⟩, do 183 | (some a', d') ← (f a').run d' | return none, 184 | return (a', d'))⟩ 185 | 186 | meta def read_string_aux : char_buffer → deserializer char_buffer 187 | | buf := do 188 | c ← viewa char, 189 | if c.1 = 0 then return buf else read_string_aux (buf.push_back c) 190 | 191 | meta instance string.readable : readable string := 192 | ⟨buffer.to_string <$> read_string_aux mk_buffer⟩ 193 | 194 | def string.to_int (s : string) : ℤ := 195 | if s.front = '-' then -s.mk_iterator.next.next_to_string.to_nat else s.to_nat 196 | 197 | meta instance int.readable : readable ℤ := 198 | ⟨string.to_int <$> view⟩ 199 | 200 | meta instance pair.readable {α β} [readable α] [readable β] : readable (α × β) := 201 | ⟨prod.mk <$> view <*> view⟩ 202 | 203 | meta def readn_list {α} [readable α] : ℕ → deserializer (list α) 204 | | 0 := return [] 205 | | (n+1) := list.cons <$> view <*> readn_list n 206 | 207 | meta def readn_list_rev {α} [readable α] : ℕ → deserializer (list α) 208 | | 0 := return [] 209 | | (n+1) := do l ← readn_list_rev n, a ← view, return (a :: l) 210 | 211 | meta instance list.readable {α} [readable α] : readable (list α) := 212 | ⟨do len ← viewa unsigned, readn_list len.1⟩ 213 | 214 | meta instance option.readable {α} [readable α] : readable (option α) := 215 | ⟨mcond view (some <$> view) (return none)⟩ 216 | 217 | -- meta def trase {α} [has_to_string α] (a : α) (s : option string := none) : deserializer unit := 218 | -- trace ((option.rec_on s "" (++ ": ")) ++ to_string a) (return ()) 219 | 220 | meta def obj_read_core {α} [has_to_string α] (fld : deserializer_data → buffer α) 221 | (put : buffer α → deserializer_data → deserializer_data) 222 | (f : ℕ → deserializer α) : deserializer α := 223 | do c ← readb, 224 | match c with 225 | | 0 := do 226 | i ← viewa unsigned, 227 | table ← fld <$> get, 228 | if h : i.1 < table.size then 229 | return $ table.read ⟨i.1, h⟩ 230 | else corrupted ("not in table " ++ to_string i.1 ++ " ≥ " ++ to_string table.size ++ "\n" ++ 231 | to_string table.to_list) 232 | | c+1 := do 233 | r ← f c, 234 | table ← fld <$> get, 235 | modify (put $ table.push_back r), 236 | return r 237 | end 238 | 239 | end deserializer 240 | 241 | open deserializer deserializer_data 242 | 243 | -- meta def tsh {α} [has_to_string α] (m : deserializer α) (s : option string := none) : deserializer α := 244 | -- do a ← m, trase a s, return a 245 | 246 | meta instance name.readable : readable name := 247 | ⟨obj_read_core name_table (λ t d, {name_table := t, ..d}) $ λ c, 248 | match c with 249 | | 0 /- LL_ANON -/ := return name.anonymous 250 | | 1 /- LL_STRING -/ := mk_simple_name <$> viewa string 251 | | 2 /- LL_INT -/ := do n ← view, return (name.anonymous.mk_numeral n) 252 | | 3 /- LL_STRING_PREFIX -/ := mk_str_name <$> name.readable.read1 <*> viewa string 253 | | 4 /- LL_INT_PREFIX -/ := do nm ← name.readable.read1, i ← view, return (nm.mk_numeral i) 254 | | _ := corrupted ("bad name" ++ to_string c) 255 | end⟩ 256 | 257 | meta instance level.readable : readable level := 258 | ⟨obj_read_core level_table (λ t d, {level_table := t, ..d}) $ λ _, 259 | do c ← readb, 260 | let lread := level.readable.read1 in 261 | match c with 262 | | 0 /- Zero -/ := return level.zero 263 | | 1 /- Succ -/ := level.succ <$> lread 264 | | 2 /- Max -/ := level.max <$> lread <*> lread 265 | | 3 /- IMax -/ := level.imax <$> lread <*> lread 266 | | 4 /- Param -/ := level.param <$> view 267 | | 5 /- Meta -/ := level.mvar <$> view 268 | | _ := corrupted "bad level" 269 | end⟩ 270 | 271 | meta instance : readable binder_info := 272 | ⟨do c ← readb, return $ 273 | if c.test_bit 2 then binder_info.implicit else 274 | if c.test_bit 1 then binder_info.strict_implicit else 275 | if c.test_bit 0 then binder_info.inst_implicit else 276 | if c.test_bit 3 then binder_info.aux_decl else 277 | binder_info.default⟩ 278 | 279 | meta instance : readable equations_header := 280 | ⟨equations_header.mk <$> view <*> view <*> view <*> view <*> 281 | view <*> view <*> view <*> view <*> view <*> view⟩ 282 | 283 | meta def macro_def'.check : macro_def' → list expr' → bool 284 | | (macro_def'.struct_inst _ _ fs) args := fs.length ≤ args.length 285 | | (macro_def'.annot _) args := args.length = 1 286 | | macro_def'.choice args := args.length > 1 287 | | (macro_def'.nat_value _) args := args.length = 0 288 | | (macro_def'.rec_fn _) args := args.length = 1 289 | | (macro_def'.proj _ _ _ _ _ _ _) args := args.length = 1 290 | | (macro_def'.equation _) args := args.length = 2 291 | | macro_def'.no_equation args := args.length = 0 292 | | macro_def'.as_pattern args := args.length = 2 293 | | (macro_def'.expr_quote _ _) args := args.length = 0 294 | | (macro_def'.sorry_ _) args := args.length = 1 295 | | (macro_def'.string _) args := args.length = 0 296 | | macro_def'.perm_ac args := args.length = 4 297 | | macro_def'.typed_expr args := args.length = 2 298 | | _ args := tt 299 | 300 | meta def read_macro1 [readable expr'] (args : list expr') : string → deserializer macro_def' 301 | | "Prenum" := macro_def'.prenum <$> view 302 | | "STI" := macro_def'.struct_inst <$> view <*> view <*> view 303 | | "fieldN" := macro_def'.field_notation <$> view <*> view 304 | | "Annot" := macro_def'.annot <$> view 305 | | "Choice" := return macro_def'.choice 306 | | "CNatM" := macro_def'.nat_value <$> view 307 | | "RecFn" := macro_def'.rec_fn <$> view 308 | | "Proj" := macro_def'.proj <$> view <*> view <*> view <*> view <*> view <*> view <*> view 309 | | "Eqns" := macro_def'.equations <$> view 310 | | "Eqn" := macro_def'.equation <$> view 311 | | "NEqn" := return macro_def'.no_equation 312 | | "EqnR" := return macro_def'.equations_result 313 | | "AsPat" := return macro_def'.as_pattern 314 | | "Quote" := macro_def'.expr_quote <$> view <*> view 315 | | "Sorry" := macro_def'.sorry_ <$> view 316 | | "Str" := macro_def'.string <$> view 317 | | "ACApp" := return macro_def'.ac_app 318 | | "PermAC" := return macro_def'.perm_ac 319 | | "TyE" := return macro_def'.typed_expr 320 | | m := corrupted ("unknown macro " ++ m) 321 | 322 | meta instance expr'.readable : readable expr' := 323 | ⟨obj_read_core expr'_table (λ t d, {expr'_table := t, ..d}) $ λ c, 324 | let eread := expr'.readable.read1 in 325 | match c with 326 | | 0 /- Var -/ := expr'.var <$> view 327 | | 1 /- Sort -/ := expr'.sort <$> view 328 | | 2 /- Constant -/ := expr'.const <$> view <*> view 329 | | 3 /- Meta -/ := expr'.mvar <$> view <*> view <*> eread 330 | | 4 /- Local -/ := expr'.local_const <$> view <*> view <*> view <*> eread 331 | | 5 /- App -/ := expr'.app <$> eread <*> eread 332 | | 6 /- Lambda -/ := expr'.lam <$> view <*> view <*> eread <*> eread 333 | | 7 /- Pi -/ := expr'.pi <$> view <*> view <*> eread <*> eread 334 | | 8 /- Let -/ := expr'.elet <$> view <*> eread <*> eread <*> eread 335 | | 9 /- Macro -/ := do 336 | args ← @view _ (@list.readable _ expr'.readable), 337 | m ← view >>= @read_macro1 expr'.readable args, 338 | if m.check args 339 | then return (expr'.macro m args) 340 | else corrupted "bad macro args" 341 | | _ := corrupted "bad expr'" 342 | end⟩ 343 | 344 | structure module_name := 345 | (relative : option unsigned) 346 | (name : name) 347 | 348 | instance : has_to_string module_name := 349 | ⟨λ m, match m with 350 | | ⟨some r, n⟩ := to_string n ++ " - relative " ++ to_string r 351 | | ⟨none, n⟩ := to_string n 352 | end⟩ 353 | 354 | structure olean_data := 355 | (imports : list module_name) 356 | (code : char_buffer) 357 | (uses_sorry : bool) 358 | 359 | meta instance module_name.readable : readable module_name := 360 | ⟨module_name.mk <$> view <*> view⟩ 361 | 362 | meta def read_olean (s : string) : io olean_data := 363 | from_file s $ do 364 | header ← viewa string, 365 | guard (header = "oleanfile"), 366 | version ← viewa string, 367 | -- trase version "version", 368 | claimed_hash ← viewa unsigned, 369 | -- trase claimed_hash "claimed_hash", 370 | uses_sorry ← viewa bool, 371 | -- trase uses_sorry "uses_sorry", 372 | imports ← viewa (list module_name), 373 | -- trase imports "imports", 374 | code ← read_blob, 375 | -- guard (claimed_hash = hash code), 376 | return ⟨imports, code, uses_sorry⟩ 377 | 378 | structure export_decl := 379 | (ns : name) (as : name) 380 | (had_explicit : bool) 381 | (except_names : list name) 382 | (renames : list (name × name)) 383 | 384 | meta instance : has_to_format export_decl := 385 | ⟨λ ⟨ns, as, he, en, rn⟩, br 386 | [to_fmt ns, to_fmt as, to_fmt he, to_fmt en, to_fmt rn]⟩ 387 | 388 | meta structure inductive_decl := 389 | (d_name : name) 390 | (level_params : list name) 391 | (nparams : unsigned) 392 | (type : expr') 393 | (rules : list (name × expr')) 394 | 395 | meta instance : has_to_format inductive_decl := 396 | ⟨λ ⟨n, ps, np, ty, r⟩, br [to_fmt n, to_fmt ps, to_fmt np, to_fmt ty, to_fmt r]⟩ 397 | 398 | meta instance : readable inductive_decl := 399 | ⟨inductive_decl.mk <$> view <*> view <*> view <*> view <*> view⟩ 400 | 401 | meta structure comp_rule := 402 | (num_bu : unsigned) 403 | (comp_rhs : expr') 404 | 405 | meta instance : has_to_format comp_rule := 406 | ⟨λ ⟨n, rhs⟩, br [to_fmt n, to_fmt rhs]⟩ 407 | 408 | meta instance : readable comp_rule := 409 | ⟨comp_rule.mk <$> view <*> view⟩ 410 | 411 | meta structure inductive_defn := 412 | (num_ACe : unsigned) 413 | (elim_prop : bool) 414 | (dep_elim : bool) 415 | (level_param_names : list name) 416 | (elim_type : expr') 417 | (decl : inductive_decl) 418 | (is_K_target : bool) 419 | (num_indices : unsigned) 420 | (is_trusted : bool) 421 | (comp_rules : list comp_rule) 422 | 423 | meta instance : has_to_format inductive_defn := 424 | ⟨λ ⟨e1,e2,e3,e4,e5,e6,e7,e8,e9,e10⟩, br [ 425 | to_fmt e1, to_fmt e2, to_fmt e3, to_fmt e4, to_fmt e5, 426 | to_fmt e6, to_fmt e7, to_fmt e8, to_fmt e9, to_fmt e10]⟩ 427 | 428 | meta instance : readable inductive_defn := 429 | ⟨inductive_defn.mk <$> view <*> view <*> view <*> view <*> 430 | view <*> view <*> view <*> view <*> view <*> view⟩ 431 | 432 | meta instance : has_to_format reducibility_hints := 433 | ⟨λ n, match n with 434 | | reducibility_hints.regular n b := br ["regular", to_fmt n, to_fmt b] 435 | | reducibility_hints.opaque := "opaque" 436 | | reducibility_hints.abbrev := "abbrev" 437 | end⟩ 438 | 439 | meta instance : readable reducibility_hints := 440 | ⟨do k ← readb, 441 | match k with 442 | | 0 /- Regular -/ := flip reducibility_hints.regular <$> view <*> view 443 | | 1 /- Opaque -/ := return reducibility_hints.opaque 444 | | 2 /- Abbrev -/ := return reducibility_hints.abbrev 445 | | _ := corrupted "bad reducibility_hints" 446 | end⟩ 447 | 448 | meta inductive declaration' 449 | | defn : name → list name → expr' → expr' → reducibility_hints → bool → declaration' 450 | | thm : name → list name → expr' → expr' → declaration' 451 | | cnst : name → list name → expr' → bool → declaration' 452 | | ax : name → list name → expr' → declaration' 453 | 454 | section 455 | open declaration' 456 | 457 | meta instance : has_to_format declaration' := 458 | ⟨λ d, match d with 459 | | defn n ps t v h tr := ls ["defn", 460 | to_fmt n, to_fmt ps, to_fmt t, to_fmt v, to_fmt h, to_fmt tr] 461 | | thm n ps t v := ls ["thm", to_fmt n, to_fmt ps, to_fmt t, to_fmt v] 462 | | cnst n ps t tr := ls ["cnst", to_fmt n, to_fmt ps, to_fmt t, to_fmt tr] 463 | | ax n ps t := ls ["ax", to_fmt n, to_fmt ps, to_fmt t] 464 | end⟩ 465 | 466 | end 467 | 468 | meta instance : readable declaration' := 469 | ⟨do k ← readb, 470 | let has_value := k.test_bit 0, 471 | let is_th_ax := k.test_bit 1, 472 | let is_trusted := k.test_bit 2, 473 | n ← view, ps ← view, t ← view, 474 | if has_value then do 475 | v ← view, 476 | if is_th_ax then return $ declaration'.thm n ps t v 477 | else do 478 | hints ← view, 479 | return $ declaration'.defn n ps t v hints is_trusted 480 | else if is_th_ax then return $ declaration'.ax n ps t 481 | else return $ declaration'.cnst n ps t is_trusted⟩ 482 | 483 | inductive reducible_status 484 | | reducible 485 | | semireducible 486 | | irreducible 487 | 488 | meta instance : has_to_string reducible_status := 489 | ⟨λ n, match n with 490 | | reducible_status.reducible := "reducible" 491 | | reducible_status.semireducible := "semireducible" 492 | | reducible_status.irreducible := "irreducible" 493 | end⟩ 494 | 495 | meta instance : has_to_format reducible_status := ⟨format.of_string ∘ to_string⟩ 496 | 497 | meta instance : readable reducible_status := 498 | ⟨do c ← readb, 499 | match c with 500 | | 0 := return reducible_status.reducible 501 | | 1 := return reducible_status.semireducible 502 | | 2 := return reducible_status.irreducible 503 | | _ := corrupted 504 | end⟩ 505 | 506 | inductive elab_strategy 507 | | simple 508 | | with_expected_type 509 | | as_eliminator 510 | 511 | meta instance : has_to_string elab_strategy := 512 | ⟨λ n, match n with 513 | | elab_strategy.simple := "simple" 514 | | elab_strategy.with_expected_type := "with_expected_type" 515 | | elab_strategy.as_eliminator := "as_eliminator" 516 | end⟩ 517 | 518 | meta instance : has_to_format elab_strategy := ⟨format.of_string ∘ to_string⟩ 519 | 520 | meta instance : readable elab_strategy := 521 | ⟨do c ← readb, 522 | match c with 523 | | 0 := return elab_strategy.simple 524 | | 1 := return elab_strategy.with_expected_type 525 | | 2 := return elab_strategy.as_eliminator 526 | | _ := corrupted 527 | end⟩ 528 | 529 | meta inductive attr_data : Type 530 | | basic : attr_data 531 | | reducibility : reducible_status → attr_data 532 | | elab_strategy : elab_strategy → attr_data 533 | | intro (eager : bool) : attr_data 534 | | indices (idxs : list unsigned) : attr_data 535 | | user : expr' → attr_data 536 | 537 | meta structure attr_record := 538 | (decl : name) 539 | (data : option attr_data) 540 | 541 | meta instance : has_to_format attr_record := 542 | ⟨λ d, match d with 543 | | ⟨decl, none⟩ := br [to_fmt decl, "deleted"] 544 | | ⟨decl, some attr_data.basic⟩ := to_fmt decl 545 | | ⟨decl, some (attr_data.reducibility r)⟩ := br [to_fmt decl, to_fmt r] 546 | | ⟨decl, some (attr_data.elab_strategy s)⟩ := br [to_fmt decl, to_fmt s] 547 | | ⟨decl, some (attr_data.intro b)⟩ := br [to_fmt decl, to_fmt b] 548 | | ⟨decl, some (attr_data.indices ix)⟩ := br [to_fmt decl, to_fmt ix] 549 | | ⟨decl, some (attr_data.user e)⟩ := br [to_fmt decl, to_fmt e] 550 | end⟩ 551 | 552 | meta structure attr_entry := 553 | (attr : name) 554 | (prio : unsigned) 555 | (record : attr_record) 556 | 557 | meta instance : has_to_format attr_entry := 558 | ⟨λ ⟨a, p, r⟩, br [to_fmt a, to_fmt p, to_fmt r]⟩ 559 | 560 | meta def read_attr_ext : name → deserializer attr_data 561 | | `_refl_lemma := return attr_data.basic 562 | | `simp := return attr_data.basic 563 | | `wrapper_eq := return attr_data.basic 564 | | `congr := return attr_data.basic 565 | | `elab_strategy := attr_data.elab_strategy <$> view 566 | | `elab_with_expected_type := return attr_data.basic 567 | | `elab_as_eliminator := return attr_data.basic 568 | | `elab_simple := return attr_data.basic 569 | | `parsing_only := return attr_data.basic 570 | | `pp_using_anonymous_constructor := return attr_data.basic 571 | | `user_command := return attr_data.basic 572 | | `user_notation := return attr_data.basic 573 | | `user_attribute := return attr_data.basic 574 | | `algebra := return attr_data.basic 575 | | `class := return attr_data.basic 576 | | `instance := return attr_data.basic 577 | | `inline := return attr_data.basic 578 | | `inverse := return attr_data.basic 579 | | `pattern := return attr_data.basic 580 | | `reducibility := attr_data.reducibility <$> view 581 | | `reducible := return attr_data.basic 582 | | `semireducible := return attr_data.basic 583 | | `irreducible := return attr_data.basic 584 | | `refl := return attr_data.basic 585 | | `symm := return attr_data.basic 586 | | `trans := return attr_data.basic 587 | | `subst := return attr_data.basic 588 | | `intro := attr_data.intro <$> view 589 | | `hole_command := return attr_data.basic 590 | | `no_inst_pattern := return attr_data.basic 591 | | `vm_monitor := return attr_data.basic 592 | | `unify := return attr_data.basic 593 | | `recursor := attr_data.indices <$> view 594 | | `_simp.sizeof := return attr_data.basic 595 | | n := attr_data.user <$> view 596 | -- | n := corrupted ("unsupported attr " ++ to_string n) 597 | 598 | meta instance : readable attr_entry := 599 | ⟨do attr ← view, 600 | prio ← view, 601 | decl ← view, 602 | deleted ← viewa bool, 603 | if deleted then 604 | return ⟨attr, prio, ⟨decl, none⟩⟩ 605 | else do 606 | dat ← read_attr_ext attr, 607 | return ⟨attr, prio, ⟨decl, some dat⟩⟩⟩ 608 | 609 | inductive ginductive_kind | basic | mutual_ | nested 610 | 611 | meta instance : has_to_string ginductive_kind := 612 | ⟨λ n, match n with 613 | | ginductive_kind.basic := "basic" 614 | | ginductive_kind.mutual_ := "mutual" 615 | | ginductive_kind.nested := "nested" 616 | end⟩ 617 | 618 | meta instance : has_to_format ginductive_kind := ⟨format.of_string ∘ to_string⟩ 619 | 620 | meta instance : readable ginductive_kind := 621 | ⟨do c ← readb, 622 | match c with 623 | | 0 := return ginductive_kind.basic 624 | | 1 := return ginductive_kind.mutual_ 625 | | 2 := return ginductive_kind.nested 626 | | _ := corrupted 627 | end⟩ 628 | 629 | structure ginductive_entry := 630 | (kind : ginductive_kind) 631 | (inner : bool) 632 | (num_params : unsigned) 633 | (num_indices : list unsigned) 634 | (inds : list name) 635 | (intro_rules : list (list name)) 636 | (offsets : list unsigned) 637 | (idx_to_ir_range : list (unsigned × unsigned)) 638 | (packs : list name) 639 | (unpacks : list name) 640 | 641 | meta instance : has_to_format ginductive_entry := 642 | ⟨λ ⟨e1,e2,e3,e4,e5,e6,e7,e8,e9,e10⟩, br [ 643 | to_fmt e1, to_fmt e2, to_fmt e3, to_fmt e4, to_fmt e5, 644 | to_fmt e6, to_fmt e7, to_fmt e8, to_fmt e9, to_fmt e10]⟩ 645 | 646 | meta instance : readable ginductive_entry := 647 | ⟨do k ← view, inner ← view, np ← view, ni ← view, 648 | inds ← viewa (list name), 649 | intro_rules ← readn_list_rev inds.length, 650 | ginductive_entry.mk k inner np ni inds intro_rules <$> 651 | view <*> view <*> view <*> view⟩ 652 | 653 | @[reducible] def pos_info := unsigned × unsigned 654 | 655 | meta structure vm_local_info' := 656 | (id : name) (type : option expr') 657 | 658 | meta instance : readable vm_local_info' := 659 | ⟨vm_local_info'.mk <$> view <*> view⟩ 660 | 661 | meta instance : has_to_format vm_local_info' := 662 | ⟨λ ⟨id, t⟩, br [to_fmt id, to_fmt t]⟩ 663 | 664 | meta inductive vm_instr 665 | | push (idx : unsigned) 666 | | move (idx : unsigned) 667 | | ret 668 | | drop (num : unsigned) 669 | | goto (tgt : unsigned) 670 | | sconstr (idx : unsigned) 671 | | constr (idx : unsigned) (nfields : unsigned) 672 | | num (n : ℤ) 673 | | destruct 674 | | cases2 (one : unsigned) (two : unsigned) 675 | | casesN (npcs : list unsigned) 676 | | nat_cases (z : unsigned) (s : unsigned) 677 | | builtin_cases (fn : name) (npcs : list unsigned) 678 | | proj (idx : unsigned) 679 | | apply 680 | | invoke_global (fn : name) 681 | | invoke_builtin (fn : name) 682 | | invoke_cfun (fn : name) 683 | | closure (fn : name) (nargs : unsigned) 684 | | unreachable 685 | | expr (e : expr') 686 | | local_info (idx : unsigned) (info : vm_local_info') 687 | 688 | section 689 | open vm_instr 690 | 691 | meta instance : has_to_format vm_instr := 692 | ⟨λ i, match i with 693 | | push i := ls ["push", to_fmt i] 694 | | move i := ls ["move", to_fmt i] 695 | | ret := "ret" 696 | | drop i := ls ["drop", to_fmt i] 697 | | goto tgt := ls ["goto", to_fmt tgt] 698 | | sconstr i := ls ["sconstr", to_fmt i] 699 | | constr i n := ls ["constr", to_fmt i, to_fmt n] 700 | | num n := ls ["num", to_string n] 701 | | destruct := "destruct" 702 | | cases2 l1 l2 := ls ["cases2", to_fmt l1, to_fmt l2] 703 | | casesN ll := ls ["casesN", to_fmt ll] 704 | | nat_cases l1 l2 := ls ["nat_cases", to_fmt l1, to_fmt l2] 705 | | builtin_cases f npcs := ls ["builtin_cases", to_fmt f, to_fmt npcs] 706 | | proj i := ls ["proj", to_fmt i] 707 | | apply := "apply" 708 | | invoke_global fn := ls ["invoke_global", to_fmt fn] 709 | | invoke_builtin fn := ls ["invoke_builtin", to_fmt fn] 710 | | invoke_cfun fn := ls ["invoke_cfun", to_fmt fn] 711 | | closure fn n := ls ["closure", to_fmt fn, to_fmt n] 712 | | unreachable := "unreachable" 713 | | expr e := ls ["expr", to_fmt e] 714 | | local_info i info := ls ["local_info", to_fmt i, to_fmt info] 715 | end⟩ 716 | 717 | end 718 | 719 | meta instance : readable vm_instr := 720 | ⟨do opcode ← readb, 721 | match opcode with 722 | | 0 := vm_instr.push <$> view 723 | | 1 := vm_instr.move <$> view 724 | | 2 := return vm_instr.ret 725 | | 3 := vm_instr.drop <$> view 726 | | 4 := vm_instr.goto <$> view 727 | | 5 := vm_instr.sconstr <$> view 728 | | 6 := vm_instr.constr <$> view <*> view 729 | | 7 := vm_instr.num <$> view 730 | | 8 := return vm_instr.destruct 731 | | 9 := vm_instr.cases2 <$> view <*> view 732 | | 10 := vm_instr.casesN <$> view 733 | | 11 := vm_instr.nat_cases <$> view <*> view 734 | | 12 := vm_instr.builtin_cases <$> view <*> view 735 | | 13 := vm_instr.proj <$> view 736 | | 14 := return vm_instr.apply 737 | | 15 := vm_instr.invoke_global <$> view 738 | | 16 := vm_instr.invoke_builtin <$> view 739 | | 17 := vm_instr.invoke_cfun <$> view 740 | | 18 := vm_instr.closure <$> view <*> view 741 | | 19 := return vm_instr.unreachable 742 | | 20 := vm_instr.expr <$> view 743 | | 21 := vm_instr.local_info <$> view <*> view 744 | | _ := corrupted 745 | end⟩ 746 | 747 | meta instance : has_to_string vm_decl_kind := 748 | ⟨λ n, match n with 749 | | vm_decl_kind.bytecode := "bytecode" 750 | | vm_decl_kind.builtin := "builtin" 751 | | vm_decl_kind.cfun := "cfun" 752 | end⟩ 753 | 754 | meta instance : has_to_format vm_decl_kind := ⟨format.of_string ∘ to_string⟩ 755 | 756 | meta def vm_decl_data : vm_decl_kind → Type 757 | | vm_decl_kind.bytecode := list vm_instr 758 | | vm_decl_kind.builtin := empty 759 | | vm_decl_kind.cfun := empty 760 | 761 | meta instance : ∀ k, has_to_format (vm_decl_data k) 762 | | vm_decl_kind.bytecode := ⟨λ l : list _, to_fmt l⟩ 763 | | vm_decl_kind.builtin := ⟨λ _, ↑"()"⟩ 764 | | vm_decl_kind.cfun := ⟨λ _, ↑"()"⟩ 765 | 766 | meta structure vm_decl' := 767 | (kind : vm_decl_kind) 768 | (name : name) 769 | (arity : unsigned) 770 | (args_info : list vm_local_info') 771 | (pos_info : option pos_info) 772 | (olean : option string) 773 | (dat : vm_decl_data kind) 774 | 775 | meta instance : has_to_format vm_decl' := 776 | ⟨λ ⟨e1,e2,e3,e4,e5,e6,e7⟩, br [ 777 | to_fmt e1, to_fmt e2, to_fmt e3, to_fmt e4, to_fmt e5, to_fmt e6, to_fmt e7]⟩ 778 | 779 | meta instance : readable vm_decl' := 780 | ⟨do fn ← view, 781 | arity ← view, 782 | code_sz ← view, 783 | pos ← view, 784 | args_info ← view, 785 | code ← readn_list code_sz, 786 | return ⟨vm_decl_kind.bytecode, fn, arity, args_info, pos, none, code⟩⟩ 787 | 788 | inductive class_entry 789 | | class_ (n : name) 790 | | inst (n : name) (inst : name) (prio : unsigned) 791 | | tracker (n : name) (track : name) 792 | 793 | meta instance : has_to_format class_entry := 794 | ⟨λ n, match n with 795 | | class_entry.class_ n := p ["class", to_fmt n] 796 | | class_entry.inst n i pr := p ["inst", to_fmt n, to_fmt i, to_fmt pr] 797 | | class_entry.tracker n t := p ["tracker", to_fmt n, to_fmt t] 798 | end⟩ 799 | 800 | meta instance : readable class_entry := 801 | ⟨do k ← readb, 802 | match k with 803 | | 0 := class_entry.class_ <$> view 804 | | 1 := class_entry.inst <$> view <*> view <*> view 805 | | 2 := class_entry.tracker <$> view <*> view 806 | | _ := corrupted 807 | end⟩ 808 | 809 | structure proj_info := 810 | (constr : name) 811 | (nparams : unsigned) 812 | (i : unsigned) 813 | (inst_implicit : bool) 814 | 815 | meta instance : has_to_format proj_info := 816 | ⟨λ ⟨c,n,i,ii⟩, br [to_fmt c, to_fmt n, to_fmt i, to_fmt ii]⟩ 817 | 818 | meta instance : readable proj_info := 819 | ⟨proj_info.mk <$> view <*> view <*> view <*> view⟩ 820 | 821 | meta inductive action 822 | | skip 823 | | expr (rbp : unsigned) 824 | | exprs (sep : name) (rec : expr') (ini : option expr') 825 | (is_foldr : bool) (rbp : unsigned) (terminator : option name) 826 | | binder (rbp : unsigned) 827 | | binders (rbp : unsigned) 828 | | scoped_expr (rec : expr') (rbp : unsigned) (use_lambda : bool) 829 | | ext (impossible : empty) 830 | 831 | meta instance : has_to_format action := 832 | ⟨λ n, match n with 833 | | action.skip := "skip" 834 | | action.expr rbp := p ["expr", to_fmt rbp] 835 | | action.exprs sep rec ini fold rbp tm := p ["exprs", 836 | to_fmt sep, to_fmt rec, to_fmt ini, to_fmt rbp, to_fmt tm] 837 | | action.binder rbp := p ["binder", to_fmt rbp] 838 | | action.binders rbp := p ["binders", to_fmt rbp] 839 | | action.scoped_expr rec rbp lam := 840 | p ["scoped_expr", to_fmt rec, to_fmt rbp, to_fmt lam] 841 | end⟩ 842 | 843 | meta instance : readable action := 844 | ⟨do k ← readb, 845 | match k with 846 | | 0 := return action.skip 847 | | 1 := action.expr <$> view 848 | | 2 := action.exprs <$> view <*> view <*> view <*> view <*> view <*> view 849 | | 3 := action.binder <$> view 850 | | 4 := action.binders <$> view 851 | | 5 := action.scoped_expr <$> view <*> view <*> view 852 | | 6 := corrupted "Ext actions never appear in olean files" 853 | | _ := corrupted 854 | end⟩ 855 | 856 | meta structure transition := 857 | (tk : name) (pp : name) (act : action) 858 | 859 | meta instance : readable transition := 860 | ⟨transition.mk <$> view <*> view <*> view⟩ 861 | 862 | meta instance : has_to_format transition := 863 | ⟨λ ⟨tk, pp, act⟩, br [to_fmt tk, to_fmt pp, to_fmt act]⟩ 864 | 865 | meta inductive notation_entry_kind 866 | | reg (is_nud : bool) (transitions : list transition) (prio : unsigned) 867 | | numeral (n : ℤ) 868 | 869 | meta instance : has_to_format notation_entry_kind := 870 | ⟨λ n, match n with 871 | | notation_entry_kind.reg tt tr prio := p ["nud", to_fmt tr, to_fmt prio] 872 | | notation_entry_kind.reg ff tr prio := p ["led", to_fmt tr, to_fmt prio] 873 | | notation_entry_kind.numeral n := p ["numeral", to_string n] 874 | end⟩ 875 | 876 | inductive notation_entry_group | main | reserve_ 877 | 878 | meta instance : has_to_string notation_entry_group := 879 | ⟨λ n, match n with 880 | | notation_entry_group.main := "main" 881 | | notation_entry_group.reserve_ := "reserve" 882 | end⟩ 883 | 884 | meta instance : has_to_format notation_entry_group := ⟨format.of_string ∘ to_string⟩ 885 | 886 | meta instance : readable notation_entry_group := 887 | ⟨do c ← readb, 888 | match c with 889 | | 0 := return notation_entry_group.main 890 | | 1 := return notation_entry_group.reserve_ 891 | | _ := corrupted 892 | end⟩ 893 | 894 | meta structure notation_entry := 895 | (kind : notation_entry_kind) 896 | (expr : expr') 897 | (overload : bool) 898 | (group : notation_entry_group) 899 | (parse_only : bool) 900 | 901 | meta instance : has_to_format notation_entry := 902 | ⟨λ ⟨k, pe, ol, g, po⟩, br [to_fmt k, to_fmt pe, to_fmt ol, to_fmt g, to_fmt po]⟩ 903 | 904 | meta instance : readable notation_entry := 905 | ⟨do k ← readb, 906 | ol ← view, 907 | po ← view, 908 | e ← view, 909 | if k = 2 then do 910 | n ← view, 911 | return ⟨notation_entry_kind.numeral n, e, ol, notation_entry_group.main, po⟩ 912 | else do 913 | g ← view, 914 | nud ← match k with 915 | | 0 := return tt 916 | | 1 := return ff 917 | | _ := corrupted 918 | end, 919 | tr ← view, 920 | prio ← view, 921 | return ⟨notation_entry_kind.reg nud tr prio, e, ol, g, po⟩⟩ 922 | 923 | meta structure inverse_entry := 924 | (decl : name) (arity : unsigned) (inv : name) (inv_arity : unsigned) (lemma_ : name) 925 | 926 | meta instance : readable inverse_entry := 927 | ⟨inverse_entry.mk <$> view <*> view <*> view <*> view <*> view⟩ 928 | 929 | meta instance : has_to_format inverse_entry := 930 | ⟨λ ⟨d, a, i, ia, l⟩, br [to_fmt d, to_fmt a, to_fmt i, to_fmt ia, to_fmt l]⟩ 931 | 932 | inductive op_kind | relation | subst | trans | refl | symm 933 | 934 | meta instance : has_to_string op_kind := 935 | ⟨λ n, match n with 936 | | op_kind.relation := "relation" 937 | | op_kind.subst := "subst" 938 | | op_kind.trans := "trans" 939 | | op_kind.refl := "refl" 940 | | op_kind.symm := "symm" 941 | end⟩ 942 | 943 | meta instance : has_to_format op_kind := ⟨format.of_string ∘ to_string⟩ 944 | 945 | meta instance : readable op_kind := 946 | ⟨do c ← readb, 947 | match c with 948 | | 0 := return op_kind.relation 949 | | 1 := return op_kind.subst 950 | | 2 := return op_kind.trans 951 | | 3 := return op_kind.refl 952 | | 4 := return op_kind.symm 953 | | _ := corrupted 954 | end⟩ 955 | 956 | meta structure recursor_info := 957 | (rec_ : name) 958 | (ty : name) 959 | (dep_elim : bool) 960 | (recursive : bool) 961 | (num_args : unsigned) 962 | (major_pos : unsigned) 963 | (univ_pos : list unsigned) 964 | (params_pos : list (option unsigned)) 965 | (indices_pos : list unsigned) 966 | (produce_motive : list bool) 967 | 968 | meta instance : has_to_format recursor_info := 969 | ⟨λ ⟨r, t, de, rc, na, mp, up, pp, ip, pm⟩, br [to_fmt r, to_fmt t, to_fmt de, 970 | to_fmt rc, to_fmt na, to_fmt mp, to_fmt up, to_fmt pp, to_fmt ip, to_fmt pm]⟩ 971 | 972 | meta instance : readable recursor_info := 973 | ⟨recursor_info.mk <$> view <*> view <*> view <*> view <*> view <*> 974 | view <*> view <*> view <*> view <*> view⟩ 975 | 976 | meta inductive modification 977 | | export_decl (in_ns : name) (decl : export_decl) 978 | | pos_info (decl_name : name) (pos_info : pos_info) 979 | | inductive_ (defn : inductive_defn) (trust_lvl : unsigned) 980 | | decl (decl : declaration') (trust_lvl : unsigned) 981 | | aux_rec (decl : name) 982 | | protected_ (name : name) 983 | | private_ (name : name) (real : _root_.name) 984 | | gind (entry : ginductive_entry) 985 | | new_ns (ns : name) 986 | | vm_reserve (fn : name) (arity : unsigned) 987 | | vm_code (decl : vm_decl') 988 | | vm_monitor (decl : name) 989 | | eqn_lemmas (lem : name) 990 | | has_simple_eqn_lemma (decl : name) 991 | | no_conf (decl : name) 992 | | doc (decl : name) (doc : string) 993 | | ncomp (decl : name) 994 | | proj (decl : name) (info : proj_info) 995 | | decl_trace (decl : name) 996 | | user_command (decl : name) 997 | | user_notation (decl : name) 998 | | user_attr (decl : name) 999 | | hole_command (decl : name) 1000 | | quot 1001 | | native_module_path (decl : name) 1002 | | key_eqv (n1 : name) (n2 : name) 1003 | 1004 | -- scoped extensions, not sure if these need to be separated out 1005 | | token (tk : string) (prec : option unsigned) 1006 | | notation_ (entry : notation_entry) 1007 | | attr (entry : attr_entry) 1008 | | class_ (entry : class_entry) 1009 | | inverse (entry : inverse_entry) 1010 | | relation (kind : op_kind) (decl : name) 1011 | | unification_hint (decl : name) (prio : unsigned) 1012 | | user_recursor (info : recursor_info) 1013 | 1014 | section 1015 | open modification 1016 | 1017 | meta def modification.to_fmt : modification → format 1018 | | (export_decl ns d) := ls ["export_decl", to_fmt ns, to_fmt d] 1019 | | (pos_info d info) := ls ["pos_info", to_fmt d, to_fmt info] 1020 | | (inductive_ d l) := ls ["inductive", to_fmt d, to_fmt l] 1021 | | (decl d l) := ls ["decl", to_fmt d, to_fmt l] 1022 | | (aux_rec d) := ls ["aux_rec", to_fmt d] 1023 | | (protected_ d) := ls ["protected", to_fmt d] 1024 | | (private_ d r) := ls ["private", to_fmt d, to_fmt r] 1025 | | (gind e) := ls ["gind", to_fmt e] 1026 | | (new_ns ns) := ls ["new_ns", to_fmt ns] 1027 | | (vm_reserve fn ar) := ls ["vm_reserve", to_fmt fn, to_fmt ar] 1028 | | (vm_code d) := ls ["vm_code", to_fmt d] 1029 | | (vm_monitor d) := ls ["vm_monitor", to_fmt d] 1030 | | (eqn_lemmas lem) := ls ["eqn_lemmas", to_fmt lem] 1031 | | (has_simple_eqn_lemma d) := ls ["has_simple_eqn_lemma", to_fmt d] 1032 | | (no_conf d) := ls ["no_conf", to_fmt d] 1033 | | (doc d s) := ls ["doc", to_fmt d, to_fmt s] 1034 | | (ncomp d) := ls ["ncomp", to_fmt d] 1035 | | (proj d i) := ls ["proj", to_fmt d, to_fmt i] 1036 | | (decl_trace d) := ls ["decl_trace", to_fmt d] 1037 | | (user_command d) := ls ["user_command", to_fmt d] 1038 | | (user_notation d) := ls ["user_notation", to_fmt d] 1039 | | (user_attr d) := ls ["user_attr", to_fmt d] 1040 | | (hole_command d) := ls ["hole_command", to_fmt d] 1041 | | quot := "quot" 1042 | | (native_module_path d) := ls ["native_module_path", to_fmt d] 1043 | | (key_eqv n1 n2) := ls ["key_eqv", to_fmt n1, to_fmt n2] 1044 | 1045 | | (token tk prec) := ls ["token", to_fmt tk, to_fmt prec] 1046 | | (notation_ e) := ls ["notation", to_fmt e] 1047 | | (attr e) := ls ["attr", to_fmt e] 1048 | | (class_ e) := ls ["class", to_fmt e] 1049 | | (inverse e) := ls ["inverse", to_fmt e] 1050 | | (relation k d) := ls ["relation", to_fmt k, to_fmt d] 1051 | | (unification_hint d pr) := ls ["unification_hint", to_fmt d, to_fmt pr] 1052 | | (user_recursor e) := ls ["user_recursor", to_fmt e] 1053 | 1054 | meta instance : has_to_format modification := ⟨modification.to_fmt⟩ 1055 | 1056 | end 1057 | 1058 | meta def modification_readers : rbmap string (deserializer modification) := 1059 | rbmap.from_list [ 1060 | ("export_decl", modification.export_decl <$> view <*> 1061 | (export_decl.mk <$> view <*> view <*> view <*> view <*> view)), 1062 | ("PInfo", modification.pos_info <$> view <*> view), 1063 | ("ind", modification.inductive_ <$> view <*> view), 1064 | ("decl", modification.decl <$> view <*> view), 1065 | ("auxrec", modification.aux_rec <$> view), 1066 | ("prt", modification.protected_ <$> view), 1067 | ("prv", modification.private_ <$> view <*> view), 1068 | ("gind", modification.gind <$> view), 1069 | ("nspace", modification.new_ns <$> view), 1070 | ("VMR", modification.vm_reserve <$> view <*> view), 1071 | ("VMC", modification.vm_code <$> view), 1072 | ("VMMonitor", modification.vm_monitor <$> view), 1073 | ("EqnL", modification.eqn_lemmas <$> view), 1074 | ("SEqnL", modification.has_simple_eqn_lemma <$> view), 1075 | ("no_conf", modification.no_conf <$> view), 1076 | ("doc", modification.doc <$> view <*> view), 1077 | ("ncomp", modification.ncomp <$> view), 1078 | ("proj", modification.proj <$> view <*> view), 1079 | ("decl_trace", modification.decl_trace <$> view), 1080 | ("USR_CMD", modification.user_command <$> view), 1081 | ("USR_NOTATION", modification.user_notation <$> view), 1082 | ("USR_ATTR", modification.user_attr <$> view), 1083 | ("HOLE_CMD", modification.hole_command <$> view), 1084 | ("quot", return modification.quot), 1085 | ("native_module_path", modification.native_module_path <$> view), 1086 | ("key_eqv", modification.key_eqv <$> view <*> view), 1087 | 1088 | ("TK", modification.token <$> view <*> view), 1089 | ("NOTA", modification.notation_ <$> view), 1090 | ("ATTR", modification.attr <$> view), 1091 | ("class", modification.class_ <$> view), 1092 | ("inverse", modification.inverse <$> view), 1093 | ("REL", modification.relation <$> view <*> view), 1094 | ("UNIFICATION_HINT", modification.unification_hint <$> view <*> view), 1095 | ("UREC", modification.user_recursor <$> view), 1096 | ("active_export_decls", corrupted "active_export_decls should not appear in olean files") ] 1097 | 1098 | meta def read_modifications : buffer modification → deserializer (buffer modification) 1099 | | buf := do k ← viewa string, 1100 | if k = "EndFile" then return mk_buffer 1101 | else match modification_readers.find k with 1102 | | some m := do mod ← m, read_modifications (buf.push_back mod) 1103 | | none := corrupted $ "unknown modification " ++ k 1104 | end 1105 | 1106 | #eval do 1107 | -- ol ← read_olean "src/olean.dat", 1108 | -- ol ← read_olean "../lean/library/init/core.olean", 1109 | ol ← read_olean "../mathlib/logic/basic.olean", 1110 | -- ol ← read_olean "../mathlib/test.olean", 1111 | from_buffer ol.code $ do 1112 | mods ← read_modifications mk_buffer, 1113 | return $ mods.iterate () (λ _ mod r, 1114 | let x := r in trace (to_fmt mod).to_string x) 1115 | --------------------------------------------------------------------------------