├── .gitignore ├── examples ├── wrong_type3.lang ├── correct3.lang ├── example.lang ├── wrong_type4.lang ├── wrong1.lang ├── wrong2.lang ├── fibb.lang ├── use_myfun.c ├── incr-twice.lang ├── incr.c ├── recurse.lang ├── incr.lang ├── wrong_type1.lang ├── correct2.lang ├── correct4.lang └── riscvasm.s ├── parser ├── Cargo.lock ├── Cargo.toml └── src │ └── lib.rs ├── src ├── main.rs ├── util │ ├── mod.rs │ ├── sheaf_table.rs │ └── union_find.rs ├── language.l ├── language.y ├── lib.rs └── parser.rs ├── rvshell.nix ├── shell.nix ├── Cargo.toml ├── spec.bnf ├── README.md ├── .licensure.yml ├── proptest-regressions └── ir.txt ├── LICENSE ├── resources ├── allocated.svg ├── linear.svg ├── opt.svg └── ssa.svg └── Cargo.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /parser/target 3 | .z3-trace 4 | /build/ -------------------------------------------------------------------------------- /examples/wrong_type3.lang: -------------------------------------------------------------------------------- 1 | lambda myfun() :: Int { 2 | while 3 do { 3 | 4 | } 5 | return 0; 6 | } -------------------------------------------------------------------------------- /examples/correct3.lang: -------------------------------------------------------------------------------- 1 | lambda fun1() :: Int { 2 | return fun2(); 3 | } 4 | lambda fun2() :: Int { 5 | return 5; 6 | } -------------------------------------------------------------------------------- /examples/example.lang: -------------------------------------------------------------------------------- 1 | myvar :: Int; 2 | 3 | lambda myfun (var1 :: Int, var2 :: Int) :: Int { 4 | return myfun(3, var2); 5 | } -------------------------------------------------------------------------------- /examples/wrong_type4.lang: -------------------------------------------------------------------------------- 1 | lambda myfun() :: Int { 2 | return myfun2(); 3 | } 4 | lambda myfun2() :: Bool { 5 | return 3; 6 | } -------------------------------------------------------------------------------- /examples/wrong1.lang: -------------------------------------------------------------------------------- 1 | lambda myfun() :: Int { 2 | while true do { 3 | myvar :: Int = 0; 4 | } 5 | return myvar; 6 | } -------------------------------------------------------------------------------- /examples/wrong2.lang: -------------------------------------------------------------------------------- 1 | lambda fun1(arg1::Bool) :: Int { 2 | return fun2(); 3 | 4 | } 5 | lambda fun2() :: Int { 6 | return true; 7 | } -------------------------------------------------------------------------------- /examples/fibb.lang: -------------------------------------------------------------------------------- 1 | lambda fibb(n :: Int) :: Int { 2 | if n < 2 then { 3 | return n; 4 | } else {} 5 | return fibb(n - 2) + fibb(n - 1); 6 | } -------------------------------------------------------------------------------- /examples/use_myfun.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | extern int64_t fib(int64_t); 4 | 5 | int main(void) { 6 | printf("myfun result: %d", fib(6)); 7 | } -------------------------------------------------------------------------------- /parser/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "parser" 7 | version = "0.1.0" 8 | -------------------------------------------------------------------------------- /examples/incr-twice.lang: -------------------------------------------------------------------------------- 1 | lambda increment() :: Int ; 2 | mycounter :: Int; 3 | lambda incrtwice() :: Int { 4 | unused :: Int = increment(); 5 | unused = increment(); 6 | return mycounter + 1; 7 | } -------------------------------------------------------------------------------- /examples/incr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | extern int64_t init(); 4 | extern int64_t incrtwice(); 5 | 6 | int main(void) { 7 | init(); 8 | printf("incr 2 result: %d", incrtwice()); 9 | } -------------------------------------------------------------------------------- /examples/recurse.lang: -------------------------------------------------------------------------------- 1 | lambda odd(n::Int) :: Bool { 2 | return even(n - 1); 3 | } 4 | 5 | lambda even(n::Int) :: Bool { 6 | if n == 0 then { 7 | return true; 8 | } else { 9 | return odd(n - 1); 10 | } 11 | } -------------------------------------------------------------------------------- /examples/incr.lang: -------------------------------------------------------------------------------- 1 | mycounter :: Int; 2 | lambda init() :: Int { 3 | mycounter = 0; 4 | return 0; 5 | } 6 | lambda increment() :: Int { 7 | result :: Int = mycounter; 8 | mycounter = mycounter + 1; 9 | return result; 10 | } -------------------------------------------------------------------------------- /examples/wrong_type1.lang: -------------------------------------------------------------------------------- 1 | lambda odd(n::Int) :: Bool { 2 | return even(n - 1); 3 | } 4 | 5 | lambda even(n::Int) :: Int { 6 | if n == 0 then { 7 | return true; 8 | } else { 9 | return odd(n - 1); 10 | } 11 | } -------------------------------------------------------------------------------- /parser/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "parser_defs" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | 10 | lrpar = "0.13.1" -------------------------------------------------------------------------------- /examples/correct2.lang: -------------------------------------------------------------------------------- 1 | 2 | myvar3 :: Bool; 3 | lambda myfun(myvar3 :: Int) :: Int { 4 | myvar4 :: Int = 0; 5 | if myvar2 then { 6 | myvar4 = myvar3; 7 | } else { 8 | myvar4 = 33; 9 | } 10 | return myvar4; 11 | } 12 | myvar2 :: Bool; 13 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 2 | // 3 | use ssa_comp::lib_main; 4 | fn main() { 5 | lib_main(); 6 | } 7 | -------------------------------------------------------------------------------- /src/util/mod.rs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 2 | // 3 | mod sheaf_table; 4 | mod union_find; 5 | pub use sheaf_table::*; 6 | pub use union_find::*; 7 | -------------------------------------------------------------------------------- /examples/correct4.lang: -------------------------------------------------------------------------------- 1 | myvar3 :: Bool; 2 | lambda myfun(myvar3 :: Int) :: Int { 3 | myvar4 :: Int = 0; 4 | i :: Int = 100; 5 | while (i >= 0) do { 6 | if 1 == 1 then { 7 | myvar4 = myvar4 * 3; 8 | } else { 9 | myvar4 = myvar4 / 2; 10 | } 11 | } 12 | return myvar4; 13 | } 14 | myvar2 :: Bool; -------------------------------------------------------------------------------- /src/language.l: -------------------------------------------------------------------------------- 1 | %% 2 | Int "INT" 3 | Bool "BOOL" 4 | :: "::" 5 | \=\= "==" 6 | \= "=" 7 | - "-" 8 | \+ "+" 9 | , "," 10 | \* "*" 11 | / "/" 12 | \>\= ">=" 13 | \< "<" 14 | lambda "LAMBDA" 15 | \{ "{" 16 | \} "}" 17 | \( "(" 18 | \) ")" 19 | \; ";" 20 | true "TRUE" 21 | false "FALSE" 22 | or "OR" 23 | and "AND" 24 | not "NOT" 25 | xor "XOR" 26 | if "IF" 27 | then "THEN" 28 | else "ELSE" 29 | while "WHILE" 30 | do "DO" 31 | return "RETURN" 32 | [A-Za-z][A-Za-z0-9]* "IDENT" 33 | [0-9]+ "DIGIT" 34 | [\t\n ]+ ; -------------------------------------------------------------------------------- /rvshell.nix: -------------------------------------------------------------------------------- 1 | {pkgs ? import {}, lib ? import , rv64 ? import { 2 | crossSystem = { 3 | config = "riscv64-unknown-linux-gnu"; 4 | }; 5 | }} : 6 | 7 | let 8 | z3 = pkgs.z3.overrideAttrs (oldAttrs: { 9 | meta = oldAttrs.meta // {outputsToInstall = [ "dev" ]; }; 10 | }); 11 | in 12 | rv64.callPackage ( 13 | {mkShell, stdenv, gcc}: 14 | mkShell { 15 | buildInputs = [ stdenv ]; 16 | nativeBuildInputs = [ gcc ]; 17 | } 18 | ) {} -------------------------------------------------------------------------------- /examples/riscvasm.s: -------------------------------------------------------------------------------- 1 | .globl fib 2 | .attribute arch, "rv64im" 3 | 4 | fib: 5 | .ENTRY: 6 | addi x2,x2,-32 7 | sd x1,24(x2) 8 | sd x10,0(x2) 9 | li x5,2 10 | sd x5,8(x2) 11 | ld x6,0(x2) 12 | ld x10,8(x2) 13 | slt x5,x6,x10 14 | li x10,1 15 | beq x5,x10,._LABEL_0 16 | ._LABEL_1: 17 | ld x7,0(x2) 18 | sub x10,x7,x10 19 | ._LABEL_5: 20 | call fib 21 | sd x10,16(x2) 22 | ._LABEL_6: 23 | ld x28,0(x2) 24 | ld x10,8(x2) 25 | sub x10,x28,x10 26 | ._LABEL_7: 27 | call fib 28 | ._LABEL_8: 29 | ld x29,16(x2) 30 | add x10,x29,x10 31 | .EXIT: 32 | ld x1,24(x2) 33 | addi x2,x2,32 34 | ret 35 | ._LABEL_0: 36 | j .EXIT -------------------------------------------------------------------------------- /shell.nix: -------------------------------------------------------------------------------- 1 | {pkgs ? import {}, lib ? import , rv64 ? import { 2 | crossSystem = { 3 | config = "riscv64-unknown-linux-gnu"; 4 | }; 5 | }} : 6 | 7 | let 8 | z3 = pkgs.z3.overrideAttrs (oldAttrs: { 9 | meta = oldAttrs.meta // {outputsToInstall = [ "dev" ]; }; 10 | }); 11 | in 12 | pkgs.callPackage ( 13 | {mkShell}: 14 | mkShell { 15 | buildInputs = [ pkgs.llvmPackages.libclang pkgs.stdenv z3.dev]; 16 | nativeBuildInputs = [ pkgs.cmake pkgs.clang pkgs.stdenv ]; 17 | shellHook = " 18 | export LIBCLANG_PATH=${pkgs.llvmPackages.libclang.lib}/lib 19 | "; 20 | } 21 | ) {} -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ssa-comp" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cfgrammar = "0.13.1" 10 | lrlex = "0.13.1" 11 | lrpar = "0.13.1" 12 | z3 = {version="0.11.2", features = ["static-link-z3"]} 13 | clap = { version = "4.2.0", features = ["derive"] } 14 | 15 | [dependencies.parser_defs] 16 | path = "parser" 17 | 18 | [dev-dependencies] 19 | proptest = "1.1.0" 20 | 21 | [build-dependencies] 22 | cfgrammar = "0.13.1" 23 | lrlex = "0.13.1" 24 | lrpar = "0.13.1" 25 | 26 | [build-dependencies.parser_defs] 27 | path = "parser" 28 | 29 | [features] 30 | 31 | print-cfgs = [] 32 | print-gvn = [] 33 | print-linear = [] 34 | -------------------------------------------------------------------------------- /spec.bnf: -------------------------------------------------------------------------------- 1 | program = { global_decl | function_def | function_decl } ; 2 | 3 | var_def = identifier "::" type "=" expr ; 4 | global_decl = identifier "::" type ; 5 | function_decl = "lambda " identifier parameter_list :: type ; 6 | 7 | number = ["-"] digit { digit } ; 8 | digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ; 9 | 10 | identifier = (* {A-z | 0-9 } *) ; 11 | call = identifier argument_list ; 12 | 13 | type = "Int" | "Bool" 14 | 15 | function_def = "lambda " identifier parameter_list "::" type body; 16 | parameter_list = "(" [identifier "::" type] {"," identifier "::" type} ")" ; 17 | argument_list = "(" [expr] {"," expr} ")" ; 18 | body = "{" [stmt] {";" stmt} "}" ; 19 | stmt = var_def 20 | | assign 21 | | ifelse 22 | | while 23 | | return ; 24 | assign = identifier "=" expr ; 25 | ifelse = "if" expr "then" body "else" body ; 26 | while = "while" expr "do" body ; 27 | return = "return" expr ; 28 | 29 | expr = expr "or" expr 30 | | expr "xor" expr 31 | | term ; 32 | term = term "and" bterm 33 | | bterm ; 34 | bterm = "not" cterm 35 | | cterm ; 36 | cterm = cterm ">=" factor 37 | | cterm "<" factor 38 | | cterm "==" factor 39 | | factor ; 40 | factor = factor "+" atom 41 | | factor "-" atom 42 | | atom ; 43 | atom = atom "*" unit 44 | | atom "/" unit 45 | | unit ; 46 | unit = identifier | "true" | "false" | call | "(" expr ")" | number ; -------------------------------------------------------------------------------- /src/util/sheaf_table.rs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 2 | // 3 | use std::borrow::Borrow; 4 | use std::collections::hash_map::RandomState; 5 | 6 | use std::collections::HashMap; 7 | use std::hash::BuildHasher; 8 | use std::hash::Hash; 9 | pub struct SheafTable { 10 | parent: Option>>, 11 | current: HashMap, 12 | } 13 | 14 | impl SheafTable { 15 | pub fn new() -> Self { 16 | Self { 17 | parent: None, 18 | current: HashMap::::new(), 19 | } 20 | } 21 | pub fn push(&mut self) { 22 | let mut new = Self::new(); 23 | std::mem::swap(self, &mut new); 24 | self.parent = Some(Box::new(new)); 25 | } 26 | pub fn pop(&mut self) { 27 | if let Some(parent) = self.parent.take() { 28 | *self = *parent; 29 | } 30 | } 31 | } 32 | 33 | impl Default for SheafTable { 34 | fn default() -> Self { 35 | Self::new() 36 | } 37 | } 38 | 39 | impl SheafTable 40 | where 41 | K: Eq + Hash, 42 | S: BuildHasher, 43 | { 44 | pub fn insert(&mut self, k: K, v: V) -> Option { 45 | self.current.insert(k, v) 46 | } 47 | pub fn get(&self, k: &Q) -> Option<&V> 48 | where 49 | K: Borrow, 50 | Q: Hash + Eq + ?Sized, 51 | { 52 | self.current 53 | .get(k) 54 | .or_else(|| self.parent.as_deref().and_then(|p| p.get(k))) 55 | } 56 | pub fn get_mut(&mut self, k: &Q) -> Option<&mut V> 57 | where 58 | K: Borrow, 59 | Q: Hash + Eq + ?Sized, 60 | { 61 | self.current 62 | .get_mut(k) 63 | .or_else(|| self.parent.as_deref_mut().and_then(|p| p.get_mut(k))) 64 | } 65 | pub fn remove(&mut self, k: &Q) -> Option 66 | where 67 | K: Borrow, 68 | Q: Hash + Eq + ?Sized, 69 | { 70 | self.current 71 | .remove(k) 72 | .or_else(|| self.parent.as_deref_mut().and_then(|p| p.remove(k))) 73 | } 74 | pub fn get_key_value(&self, k: &Q) -> Option<(&K, &V)> 75 | where 76 | K: Borrow, 77 | Q: Hash + Eq + ?Sized, 78 | { 79 | self.current 80 | .get_key_value(k) 81 | .or_else(|| self.parent.as_deref().and_then(|p| p.get_key_value(k))) 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rust 🦀 SSA Compiler 2 | 3 | A compiler that uses SSA (single static assignment form) as its definitive IR, written entirely in Rust! 4 | 5 | The compiler hosts an optimization pipeline and native assembly generation. 6 | 7 | ## Usage 8 | 9 | Show information about available CLI commands: 10 | 11 | Display Options: 12 | ```sh 13 | $ cargo run -- --help 14 | ``` 15 | 16 | Compile `correct3.lang` into RISCV assembly: 17 | ```sh 18 | $ mkdir build 19 | $ cargo run -- examples/correct3.lang -o build 20 | ``` 21 | 22 | Disable optimization: 23 | ```sh 24 | $ mkdir build 25 | $ cargo run -- examples/correct3.lang -o build --no-optimize 26 | ``` 27 | 28 | Use the output to generate a rv64 elf: 29 | ```sh 30 | $ cargo run --release -- examples/incr-twice.lang examples/incr.lang -o build 31 | $ riscv64-linux-gnu-gcc -mabi=lp64d examples/incr.c build/incrtwice.s build/increment.s build/init.s build/_globals.s -o build/increment.elf 32 | $ qemu-riscv64 build/increment.elf 33 | ``` 34 | 35 | ## Roadmap 36 | 37 | - [x] Parser (DONE) 38 | - [x] Intermediate Representation (DONE) 39 | - [x] Definition (DONE) 40 | - [x] Translation from AST (DONE) 41 | - [x] CFG construction (DONE) 42 | - [x] SSA transformation (DONE) 43 | - [x] Optimization passes (DONE) 44 | - [x] GVN-PRE (DONE) 45 | - [x] Copy propagation (DONE) 46 | - [x] Backend (DONE) 47 | - [x] Register allocation (DONE) 48 | - [x] Instruction selection (DONE) 49 | - [x] Global data (DONE) 50 | 51 | ## Cargo features 52 | 53 | | Feature | Description | 54 | | --- | --- | 55 | | `print-cfgs` | Displays every constructed CFG as a [dot](https://graphviz.org/doc/info/lang.html) graph. | 56 | | `print-gvn` | Displays debug information of the GVN-PRE pass. | 57 | | `print-linear` | Displays generated linear code. | 58 | 59 | ## Language features 60 | 61 | The syntax of the supported language is described in [spec.bnf](./spec.bnf). 62 | Global functions and global variables have to be forward declared, undefined but declared symbols are left to resolve by the linker. 63 | You can call your functions from C code, see this [example](./examples/incr.c). 64 | The compiler generates optimized riscv64 gnu assembly files, which can then be linked with any other objects. 65 | 66 | ## Further reading 67 | 68 | I go into some implementation details in my [medium article](https://medium.com/@mikn/implementing-ssa-compilers-with-rust-7ef702720bc)! 69 | 70 | Viewing the control flow graphs after each step helps one understand and debug the code: 71 | 72 | Initial CFG: ![](./resources/linear.svg) 73 | SSA CFG: ![](./resources/ssa.svg) 74 | Optimized CFG: ![](./resources/opt.svg) 75 | Register-allocated CFG: ![](./resources/allocated.svg) -------------------------------------------------------------------------------- /src/util/union_find.rs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 2 | // 3 | use std::collections::HashMap; 4 | use std::hash::Hash; 5 | 6 | pub struct UnionFind { 7 | nodes: Vec>, 8 | indices: HashMap, 9 | } 10 | 11 | type Index = usize; 12 | struct Node { 13 | content: V, 14 | p: Option, 15 | size: usize, 16 | } 17 | 18 | impl Node { 19 | fn parent<'a, 'b>(&'a self, nodes: &'b [Node]) -> Option<&Node> 20 | where 21 | 'b: 'a, 22 | { 23 | if let Some(p) = self.p { 24 | Some(&nodes[p]) 25 | } else { 26 | None 27 | } 28 | } 29 | fn parent_mut<'a, 'b>(&'a self, nodes: &'b mut [Node]) -> Option<&mut Node> 30 | where 31 | 'b: 'a, 32 | { 33 | if let Some(p) = self.p { 34 | Some(&mut nodes[p]) 35 | } else { 36 | None 37 | } 38 | } 39 | } 40 | impl From for Node { 41 | fn from(v: V) -> Self { 42 | Self { 43 | content: v, 44 | p: None, 45 | size: 1, 46 | } 47 | } 48 | } 49 | 50 | impl UnionFind { 51 | pub fn new() -> Self { 52 | Self { 53 | nodes: Vec::new(), 54 | indices: HashMap::new(), 55 | } 56 | } 57 | } 58 | 59 | impl Default for UnionFind { 60 | fn default() -> Self { 61 | Self::new() 62 | } 63 | } 64 | 65 | impl UnionFind 66 | where 67 | V: Eq + Hash + Clone, 68 | { 69 | pub fn new_set(&mut self, node: V) { 70 | if self.indices.contains_key(&node) { 71 | return; 72 | } 73 | self.nodes.push(Node::from(node.clone())); 74 | self.indices.insert(node, self.nodes.len() - 1); 75 | } 76 | pub fn find(&mut self, node: &V) -> Option<&V> { 77 | if let Some(&i) = self.indices.get(node) { 78 | let res = self.find_rec(i); 79 | Some(&self.nodes[res].content) 80 | } else { 81 | None 82 | } 83 | } 84 | pub fn union(&mut self, node1: &V, node2: &V) { 85 | if let (Some(&n1), Some(&n2)) = (self.indices.get(node1), self.indices.get(node2)) { 86 | let p1_i = self.find_rec(n1); 87 | let p2_i = self.find_rec(n2); 88 | if p1_i == p2_i { 89 | return; 90 | } 91 | let p1 = &self.nodes[p1_i]; 92 | let p2 = &self.nodes[p2_i]; 93 | let p2_size = p2.size; 94 | let p1_size = p1.size; 95 | if p1.size > p2_size { 96 | self.nodes[p2_i].p = Some(p1_i); 97 | self.nodes[p1_i].size += p2_size; 98 | } else { 99 | self.nodes[p1_i].p = Some(p2_i); 100 | self.nodes[p2_i].size += p1_size; 101 | } 102 | } 103 | } 104 | fn find_rec(&mut self, index: Index) -> Index { 105 | let node = &self.nodes[index]; 106 | let parent_index = node.p; 107 | if let Some(p) = parent_index { 108 | let new_parent = Some(self.find_rec(p)); 109 | let node = &mut self.nodes[index]; 110 | node.p = new_parent; 111 | node.p.unwrap() 112 | } else { 113 | index 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /parser/src/lib.rs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 2 | // 3 | #![allow(dead_code)] 4 | use std::{ 5 | error::Error, 6 | fmt::{Debug, Display}, 7 | }; 8 | 9 | pub use self::{ 10 | Atom::*, BTerm::*, CTerm::*, Defs::*, Expr::*, Factor::*, Statement::*, Term::*, Type::*, 11 | Unit::*, 12 | }; 13 | pub fn do_nothing() {} 14 | pub struct ParseErr { 15 | message: Box, 16 | span: Option, 17 | } 18 | impl From for ParseErr 19 | where 20 | E: Into>, 21 | { 22 | fn from(v: E) -> Self { 23 | Self { 24 | message: v.into(), 25 | span: None, 26 | } 27 | } 28 | } 29 | impl Debug for ParseErr { 30 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 31 | write!(f, "{}", self.message) 32 | } 33 | } 34 | impl Display for ParseErr { 35 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 36 | ::fmt(&self, f) 37 | } 38 | } 39 | impl Display for Type { 40 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 41 | ::fmt(self, f) 42 | } 43 | } 44 | pub type Ident = String; 45 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 46 | pub enum Type { 47 | Int, 48 | Bool, 49 | Never, 50 | } 51 | #[derive(Debug)] 52 | pub enum Expr { 53 | Or(Box, Term), 54 | Xor(Box, Term), 55 | ETerm(Term), 56 | } 57 | #[derive(Debug)] 58 | pub enum Term { 59 | And(Box, BTerm), 60 | TCTerm(BTerm), 61 | } 62 | #[derive(Debug)] 63 | pub enum BTerm { 64 | Not(CTerm), 65 | BCTerm(CTerm), 66 | } 67 | #[derive(Debug)] 68 | pub enum CTerm { 69 | GEq(Box, Factor), 70 | LT(Box, Factor), 71 | EQ(Box, Factor), 72 | CTFactor(Factor), 73 | } 74 | #[derive(Debug)] 75 | pub enum Factor { 76 | Plus(Box, Atom), 77 | Minus(Box, Atom), 78 | FAtom(Atom), 79 | } 80 | #[derive(Debug)] 81 | pub enum Atom { 82 | Mult(Box, Unit), 83 | Div(Box, Unit), 84 | AUnit(Unit), 85 | } 86 | #[derive(Debug)] 87 | pub enum Unit { 88 | Identifier(Ident), 89 | True, 90 | False, 91 | Call(Ident, Args), 92 | Grouping(Box), 93 | Number(i64), 94 | } 95 | 96 | #[derive(Debug, PartialEq, Eq)] 97 | pub struct Parameter(pub Ident, pub Type); 98 | #[derive(Debug, PartialEq, Eq)] 99 | pub struct Params(pub Vec); 100 | #[derive(Debug)] 101 | pub struct Args(pub Vec); 102 | #[derive(Debug)] 103 | pub struct Body(pub Vec); 104 | #[derive(Debug)] 105 | pub enum Statement { 106 | Def(Defs), 107 | Assign(Ident, Expr), 108 | IfElse(Expr, Body, Body), 109 | While(Expr, Body), 110 | Return(Expr), 111 | } 112 | #[derive(Debug)] 113 | pub enum Defs { 114 | LocalVarDef(Ident, Type, Expr), 115 | GlobalDecl(Ident, Type), 116 | FunctionDef(Ident, Params, Type, Body), 117 | FunctionDecl(Ident, Params, Type), 118 | } 119 | #[derive(Debug)] 120 | pub struct Program(pub Vec); 121 | 122 | #[derive(Debug, Clone, Copy)] 123 | pub enum Any<'a> { 124 | Ty(&'a Type), 125 | E(&'a Expr), 126 | S(&'a Statement), 127 | D(&'a Defs), 128 | B(&'a Body), 129 | As(&'a Args), 130 | Ps(&'a Params), 131 | P(&'a Parameter), 132 | A(&'a Atom), 133 | U(&'a Unit), 134 | F(&'a Factor), 135 | BT(&'a BTerm), 136 | CT(&'a CTerm), 137 | T(&'a Term), 138 | PR(&'a Program), 139 | } 140 | 141 | pub fn append(lhs: Result, E>, rhs: Result) -> Result, ParseErr> 142 | where 143 | E: Into + Debug + 'static, 144 | { 145 | let mut lhs_: Vec = lhs.map_err(|err| err.into())?; 146 | lhs_.push(rhs.map_err(|err| err.into())?); 147 | Ok(lhs_) 148 | } 149 | -------------------------------------------------------------------------------- /src/language.y: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 3 | * 4 | */ 5 | %start Program 6 | %% 7 | Digit -> Result : 8 | 'DIGIT' { 9 | Ok($lexer.span_str($1?.span()).parse()?) 10 | } ; 11 | Number -> Result : 12 | Digit {$1} 13 | | '-' Digit { 14 | $2.map(|v| -1 * v) 15 | } ; 16 | Identifier -> Result : 17 | 'IDENT' { 18 | Ok($lexer.span_str($1?.span()).into()) 19 | } ; 20 | Arguments -> Result : 21 | '(' ')' { 22 | Ok(Args(Vec::new())) 23 | } 24 | | '(' ArgList ')' { 25 | Ok(Args($2?)) 26 | } ; 27 | ArgList -> Result, ParseErr> : 28 | Expr { 29 | Ok(vec![$1?]) 30 | } 31 | | ArgList ',' Expr { 32 | append($1, $3) 33 | } ; 34 | Parameters -> Result : 35 | '(' ')' { 36 | Ok(Params(Vec::new())) 37 | } 38 | | '(' ParamList ')' { 39 | Ok(Params($2?)) 40 | } ; 41 | ParamList -> Result, ParseErr> : 42 | Identifier '::' Type { 43 | Ok(vec![Parameter($1?, $3?)]) 44 | } 45 | | ParamList ',' Identifier '::' Type { 46 | append($1, Ok(Parameter($3?, $5?))) 47 | } ; 48 | Unit -> Result : 49 | Number { 50 | Ok(Number($1?)) 51 | } 52 | | Identifier { 53 | Ok(Identifier($1?)) 54 | } 55 | | Identifier Arguments { 56 | Ok(Call($1?, $2?)) 57 | } 58 | | "(" Expr ")" { 59 | Ok(Grouping($2?.into())) 60 | } 61 | | "TRUE" { 62 | Ok(True) 63 | } 64 | | "FALSE" { 65 | Ok(False) 66 | } ; 67 | Atom -> Result : 68 | Atom '*' Unit { 69 | Ok(Mult($1?.into(), $3?.into())) 70 | } 71 | | Atom '/' Unit { 72 | Ok(Div($1?.into(), $3?.into())) 73 | } 74 | | Unit { 75 | Ok(AUnit($1?)) 76 | } ; 77 | Factor -> Result : 78 | Factor '+' Atom { 79 | Ok(Plus($1?.into(), $3?)) 80 | } 81 | | Factor '-' Atom { 82 | Ok(Minus($1?.into(), $3?)) 83 | } 84 | | Atom { 85 | Ok(FAtom($1?)) 86 | } ; 87 | CTerm -> Result : 88 | CTerm ">=" Factor { 89 | Ok(GEq($1?.into(), $3?)) 90 | } 91 | | CTerm "<" Factor { 92 | Ok(LT($1?.into(), $3?)) 93 | } 94 | | CTerm "==" Factor { 95 | Ok(EQ($1?.into(), $3?)) 96 | } 97 | | Factor { 98 | Ok(CTFactor($1?)) 99 | } ; 100 | BTerm -> Result : 101 | 'NOT' CTerm { 102 | Ok(Not($2?)) 103 | } 104 | | CTerm { 105 | Ok(BCTerm($1?)) 106 | } ; 107 | Term -> Result : 108 | Term "AND" BTerm { 109 | Ok(And($1?.into(), $3?)) 110 | } 111 | | BTerm { 112 | Ok(TCTerm($1?)) 113 | } ; 114 | Expr -> Result : 115 | Expr "OR" Term { 116 | Ok(Or($1?.into(), $3?)) 117 | } 118 | | Expr "XOR" Term { 119 | Ok(Xor($1?.into(), $3?)) 120 | } 121 | | Term { 122 | Ok(ETerm($1?)) 123 | } ; 124 | Type -> Result : 125 | 'INT' { 126 | Ok(Int) 127 | } 128 | | 'BOOL' { 129 | Ok(Bool) 130 | } ; 131 | VarDef -> Result : 132 | Identifier '::' Type '=' Expr ';' { 133 | Ok(LocalVarDef($1?, $3?, $5?)) 134 | } ; 135 | Body -> Result : 136 | '{' '}' { 137 | Ok(Body(Vec::new())) 138 | } 139 | | '{' StatementList '}' { 140 | Ok(Body($2?)) 141 | } ; 142 | Statement -> Result : 143 | VarDef {Ok(Def($1?))} 144 | | Identifier '=' Expr ';' { 145 | Ok(Assign($1?, $3?)) 146 | } 147 | | 'IF' Expr 'THEN' Body 'ELSE' Body { 148 | Ok(IfElse($2?, $4?, $6?)) 149 | } 150 | | 'WHILE' Expr 'DO' Body { 151 | Ok(While($2?, $4?)) 152 | } 153 | | 'RETURN' Expr ';' { 154 | Ok(Return($2?)) 155 | } ; 156 | StatementList -> Result, ParseErr> : 157 | Statement { 158 | Ok(vec![$1?]) 159 | } 160 | | StatementList Statement { 161 | append($1, $2) 162 | } ; 163 | FunctionDef -> Result : 164 | 'LAMBDA' Identifier Parameters '::' Type Body { 165 | Ok(FunctionDef($2?, $3?, $5?, $6?)) 166 | } ; 167 | FunctionDecl -> Result : 168 | 'LAMBDA' Identifier Parameters '::' Type ';' { 169 | Ok(FunctionDecl($2?, $3?, $5?)) 170 | } ; 171 | GlobalDecl -> Result : 172 | Identifier '::' Type ';' { 173 | Ok(GlobalDecl($1?, $3?)) 174 | } ; 175 | DefList -> Result, ParseErr> : 176 | GlobalDecl { 177 | Ok(vec![$1?]) 178 | } 179 | | FunctionDef { 180 | Ok(vec![$1?]) 181 | } 182 | | FunctionDecl { 183 | Ok(vec![$1?]) 184 | } 185 | | DefList FunctionDecl { 186 | append($1, $2) 187 | } 188 | | DefList GlobalDecl { 189 | append($1, $2) 190 | } 191 | | DefList FunctionDef { 192 | append($1, $2) 193 | } ; 194 | Program -> Result : 195 | {Ok(Program(Vec::new()))} 196 | | DefList { 197 | Ok(Program($1?)) 198 | } ; 199 | %% 200 | use parser_defs::*; -------------------------------------------------------------------------------- /.licensure.yml: -------------------------------------------------------------------------------- 1 | 2 | # Regexes which if matched by a file path will always be excluded from 3 | # getting a license header 4 | excludes: 5 | - \.gitignore 6 | - .*lock 7 | - \.git/.* 8 | - \.licensure\.yml 9 | - README.* 10 | - LICENSE.* 11 | - .*\.(md|rst|txt) 12 | # Definition of the licenses used on this project and to what files 13 | # they should apply. 14 | # 15 | # No default license configuration is provided. This section must be 16 | # configured by the user. 17 | licenses: 18 | - files: (.*\.rs$)|(.*\.y$) 19 | ident: MPL-2.0 20 | authors: 21 | - name: I-mikan-I 22 | email: 67881102+I-mikan-I@users.noreply.github.com 23 | auto_template: true 24 | # Either a regex or the string "any" to determine to what files this 25 | # license should apply. It is common for projects to have files 26 | # under multiple licenses or with multiple copyright holders. This 27 | # provides the ability to automatically license files correctly 28 | # based on their file paths. 29 | # 30 | # If "any" is provided all files will match this license. 31 | # - files: any 32 | # 33 | # The license identifier, a list of common identifiers can be 34 | # found at: https://spdx.org/licenses/ but existence of the ident 35 | # in this list it is not enforced unless auto_template is set to 36 | # true. 37 | # ident: MIT 38 | # 39 | # A list of authors who hold copyright over these files 40 | # authors: 41 | # Provide either your full name or company name for copyright purposes 42 | # - name: Your Name Here 43 | # Optionally provide email for copyright purposes 44 | # email: you@yourdomain.com 45 | # 46 | # The template that will be rendered to generate the header before 47 | # comment characters are applied. Available variables are: 48 | # - [year]: substituted with the current year. 49 | # - [name of author]: Substituted with name of the author and email 50 | # if provided. If email is provided the output appears as Full 51 | # Name . If multiple authors are provided the 52 | # list is concatenated together with commas. 53 | # template: | 54 | # Copyright [year] [name of author]. All rights reserved. Use of 55 | # this source code is governed by the [ident] license that can be 56 | # found in the LICENSE file. 57 | # 58 | # If auto_template is true then template is ignored and the SPDX 59 | # API will be queried with the ident value to automatically 60 | # determine the license header template. auto_template works best 61 | # with licenses that have a standardLicenseHeader field defined in 62 | # their license info JSON, if it is not then we will use the full 63 | # licenseText to generate the header which works fine for short 64 | # licenses like MIT but can be quite lengthy for other licenses 65 | # like BSD-4-Clause. The above default template is valid for most 66 | # licenses and is recommended for MIT, and BSD licenses. Common 67 | # licenses that work well with the auto_template feature are GPL 68 | # variants, and the Apache 2.0 license. 69 | # 70 | # Important Note: this means the ident must be a valid SPDX identifier 71 | # auto_template: true 72 | 73 | # Define type of comment characters to apply based on file extensions. 74 | comments: 75 | # The extensions (or singular extension) field defines which file 76 | # extensions to apply the commenter to. 77 | - extensions: 78 | - js 79 | - rs 80 | - go 81 | # The commenter field defines the kind of commenter to 82 | # generate. There are two types of commenters: line and block. 83 | # 84 | # This demonstrates a line commenter configuration. A line 85 | # commenter type will apply the comment_char to the beginning of 86 | # each line in the license header. It will then apply a number of 87 | # empty newlines to the end of the header equal to trailing_lines. 88 | # 89 | # If trailing_lines is omitted it is assumed to be 0. 90 | commenter: 91 | type: line 92 | comment_char: "//" 93 | trailing_lines: 0 94 | - extensions: 95 | - css 96 | - cpp 97 | - c 98 | - y 99 | # This demonstrates a block commenter configuration. A block 100 | # commenter type will add start_block_char as the first character 101 | # in the license header and add end_block_char as the last character 102 | # in the license header. If per_line_char is provided each line of 103 | # the header between the block start and end characters will be 104 | # line commented with the per_line_char 105 | # 106 | # trailing_lines works the same for both block and line commenter 107 | # types 108 | commenter: 109 | type: block 110 | start_block_char: "/*\n" 111 | end_block_char: "*/" 112 | per_line_char: "*" 113 | trailing_lines: 1 114 | # In this case extension is singular and a single string extension is provided. 115 | - extension: html 116 | commenter: 117 | type: block 118 | start_block_char: "" 120 | - extensions: 121 | - el 122 | - lisp 123 | commenter: 124 | type: line 125 | comment_char: ";;;" 126 | trailing_lines: 0 127 | # The extension string "any" is special and so will match any file 128 | # extensions. Commenter configurations are always checked in the 129 | # order they are defined, so if any is used it should be the last 130 | # commenter configuration or else it will override all others. 131 | # 132 | # In this configuration if we can't match the file extension we fall 133 | # back to the popular "#" line comment used in most scripting 134 | # languages. 135 | - extension: any 136 | commenter: 137 | type: line 138 | comment_char: "#" 139 | trailing_lines: 0 140 | 141 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 2 | // 3 | #![allow(dead_code)] 4 | mod backend; 5 | mod ir; 6 | mod parser; 7 | mod ssa; 8 | mod util; 9 | 10 | use std::{collections::HashMap, error::Error, path::PathBuf}; 11 | 12 | use clap::Parser; 13 | 14 | #[derive(Parser, Debug)] 15 | #[command(author, version, about)] 16 | struct Args { 17 | input_files: Vec, 18 | #[arg(short = 'o', long = "outdir")] 19 | output_dir: PathBuf, 20 | #[arg(short = 'g', long, default_value_t = false)] 21 | no_optimize: bool, 22 | } 23 | 24 | pub fn lib_main() { 25 | let args = Args::parse(); 26 | if let Err(e) = { validate_input(&args.input_files) } { 27 | eprintln!("Error during argument validation: {}", e); 28 | return; 29 | } 30 | let outdir = if let Some(s) = args.output_dir.to_str() { 31 | s 32 | } else { 33 | eprintln!("'outdir' parsing error"); 34 | return; 35 | }; 36 | let strings = args 37 | .input_files 38 | .iter() 39 | .map(std::fs::read_to_string) 40 | .map(|res| { 41 | res.map_err(|e| -> Box { 42 | format!("cannot read from input file: {e}").into() 43 | }) 44 | }) 45 | .collect::, _>>(); 46 | if let Err(e) = strings { 47 | eprintln!("Error during parsing: {e}"); 48 | return; 49 | } 50 | let strings = strings.unwrap(); 51 | 52 | let parsed: Result, _> = strings 53 | .iter() 54 | .map(|s| parser::parse_and_validate(s)) 55 | .collect(); 56 | if let Err(e) = parsed { 57 | eprintln!("Error during parsing: {e}"); 58 | return; 59 | } 60 | let mut globals = HashMap::new(); 61 | let mut dual = false; 62 | let linearized: Vec<_> = parsed 63 | .unwrap() 64 | .into_iter() 65 | .map(|p| { 66 | let mut ctx = ir::Context::default(); 67 | ir::translate_program(&mut ctx, &p); 68 | for (name, ty) in &ctx.globals { 69 | if globals.get(name).map_or(false, |t| t != ty) { 70 | eprintln!("dual declaration with different types for {}.", name); 71 | dual = true; 72 | } 73 | globals.insert(name.clone(), *ty); 74 | } 75 | ctx 76 | }) 77 | .collect(); 78 | if dual { 79 | return; 80 | } 81 | let funs_iter = linearized 82 | .into_iter() 83 | .flat_map(|ctx| ctx.functions.into_iter()); 84 | let mut funs = HashMap::new(); 85 | for (name, fun) in funs_iter { 86 | if funs.contains_key(&name) { 87 | eprintln!("Two functions with conflicting names {name}"); 88 | return; 89 | } 90 | funs.insert(name, fun.into_cfg().into_ssa()); 91 | } 92 | 93 | for v in funs.values_mut() { 94 | if !args.no_optimize { 95 | ssa::optimization_sequence(v.get_body_mut()) 96 | .unwrap_or_else(|_| panic!("Bug found, please open an issue")); 97 | } 98 | } 99 | let funs = funs.into_iter().map(|(k, v)| { 100 | let v = backend::to_assembly(v.into_body(), &k); 101 | (k, v) 102 | }); 103 | for (name, body) in funs { 104 | let out_path = format!("{outdir}/{name}.s"); 105 | let res = std::fs::write(&out_path, body); 106 | if let Err(e) = res { 107 | eprintln!("Error writing output file: {out_path}\n{e}"); 108 | return; 109 | } 110 | } 111 | let global_asm = backend::globals_to_assembly(globals); 112 | let res = std::fs::write(format!("{outdir}/_globals.s"), global_asm); 113 | if let Err(e) = res { 114 | eprintln!("Error writing output file: {outdir}/_globals.s\n{e}"); 115 | } 116 | } 117 | 118 | fn validate_input(input: &[PathBuf]) -> Result<(), Box> { 119 | for input in input { 120 | if !input.is_file() { 121 | return Err(format!( 122 | "input {} is not a valid file", 123 | input.to_str().unwrap_or("INVALID_UTF8") 124 | ) 125 | .into()); 126 | } 127 | } 128 | Ok(()) 129 | } 130 | 131 | #[cfg(test)] 132 | mod tests { 133 | use super::ir::*; 134 | 135 | #[test] 136 | fn test_ir() { 137 | let input = " 138 | myvar3 :: Bool; 139 | lambda myfun(myvar3 :: Int) :: Int { 140 | myvar4 :: Int = 0; 141 | if myvar2 then { 142 | myvar4 = myvar3; 143 | } else { 144 | myvar4 = 33; 145 | } 146 | return myvar4; 147 | } 148 | myvar2 :: Bool; 149 | "; 150 | 151 | let p = super::parser::parse_and_validate(input).unwrap(); 152 | 153 | let mut context = Context::new(); 154 | translate_program(&mut context, &p); 155 | let funs = context.get_functions(); 156 | let fun = funs.get("myfun").unwrap(); 157 | let body = fun.get_body(); 158 | let params = fun.get_params(); 159 | let expected = " 160 | li rd1, #0 161 | li rd2, #0 162 | la rd3, @myvar2 163 | load rd4, rd2, rd3 164 | li rd5, #1 165 | beq rd4, rd5, @_LABEL_0, @_LABEL_1 166 | @_LABEL_0: 167 | mv rd1, rd0 168 | j @_LABEL_2 169 | @_LABEL_1: 170 | li rd6, #33 171 | mv rd1, rd6 172 | j @_LABEL_2 173 | @_LABEL_2: 174 | return rd1 175 | @_LABEL_3:"; 176 | assert_eq!( 177 | expected 178 | .chars() 179 | .filter(|c| !c.is_whitespace()) 180 | .collect::(), 181 | Displayable(&body[..]) 182 | .to_string() 183 | .chars() 184 | .filter(|c| !c.is_whitespace()) 185 | .collect::() 186 | ); 187 | assert_eq!(¶ms[..], &[0][..]) 188 | } 189 | 190 | #[test] 191 | fn test_cfg() { 192 | let input = " 193 | myvar3 :: Bool; 194 | lambda myfun(myvar3 :: Int) :: Int { 195 | myvar4 :: Int = 0; 196 | i :: Int = 100; 197 | while (i >= 0) do { 198 | if i / 2 / 2 / 2 < 2 then { 199 | myvar4 = myvar4 * 3; 200 | } else { 201 | myvar4 = myvar4 / 2; 202 | } 203 | } 204 | return myvar4; 205 | } 206 | myvar2 :: Bool; 207 | "; 208 | 209 | let p = super::parser::parse_and_validate(input).unwrap(); 210 | let mut context = Context::new(); 211 | translate_program(&mut context, &p); 212 | let funs = context.get_functions(); 213 | let fun = funs.get("myfun").unwrap(); 214 | let body = fun.get_body(); 215 | println!("{}", Displayable(&body[..])); 216 | let params = fun.get_params(); 217 | /* 218 | rd1 = myvar4 219 | rd2 = i 220 | */ 221 | let expected = " 222 | li rd1, #0 223 | li rd2, #100 224 | j @_LABEL_0 225 | @_LABEL_0: 226 | li rd4, #0 227 | slt rd5, rd2, rd4 228 | li rd6, #1 229 | xor rd7, rd6, rd5 230 | li rd3, #0 231 | beq rd7, rd3, @_LABEL_1, @_LABEL_2 232 | @_LABEL_2: 233 | li rd8, #2 234 | div rd9, rd2, rd8 235 | li rd10, #2 236 | div rd11, rd9, rd10 237 | li rd12, #2 238 | div rd13, rd11, rd12 239 | li rd14, #2 240 | slt rd15, rd13, rd14 241 | li rd16, #1 242 | beq rd15, rd16, @_LABEL_3, @_LABEL_4 243 | @_LABEL_3: 244 | li rd17, #3 245 | mult rd18, rd1, rd17 246 | mv rd1, rd18 247 | j @_LABEL_5 248 | @_LABEL_4: 249 | li rd19, #2 250 | div rd20, rd1, rd19 251 | mv rd1, rd20 252 | j @_LABEL_5 253 | @_LABEL_5: 254 | j @_LABEL_0 255 | @_LABEL_1: 256 | return rd1 257 | @_LABEL_6:"; 258 | assert_eq!( 259 | expected 260 | .chars() 261 | .filter(|c| !c.is_whitespace()) 262 | .collect::(), 263 | Displayable(&body[..]) 264 | .to_string() 265 | .chars() 266 | .filter(|c| !c.is_whitespace()) 267 | .collect::() 268 | ); 269 | assert_eq!(¶ms[..], &[0][..]); 270 | 271 | let cfg = CFG::from_linear(body, fun.get_params(), fun.get_max_reg()); 272 | println!("{:?}", cfg); 273 | assert_eq!( 274 | cfg.get_block(0).body, 275 | vec![ 276 | Operator::GetParameter(0, 0), 277 | Operator::Li(1, 0), 278 | Operator::Li(2, 100), 279 | Operator::J(std::rc::Rc::from("_LABEL_0")) 280 | ] 281 | ); 282 | assert_eq!(cfg.get_block(0).children, vec![1]); 283 | assert_eq!(cfg.get_block(0).idom, None); 284 | assert_eq!(cfg.get_block(1).children, vec![6, 2]); 285 | assert_eq!(cfg.get_block(1).idom.unwrap(), 0); 286 | assert_eq!(cfg.get_block(2).children, vec![3, 4]); 287 | assert_eq!(cfg.get_block(2).idom.unwrap(), 1); 288 | assert_eq!(cfg.get_block(3).children, vec![5]); 289 | assert_eq!(cfg.get_block(3).idom.unwrap(), 2); 290 | assert_eq!(cfg.get_block(4).children, vec![5]); 291 | assert_eq!(cfg.get_block(4).idom.unwrap(), 2); 292 | assert_eq!(cfg.get_block(5).children, vec![1]); 293 | assert_eq!(cfg.get_block(5).idom.unwrap(), 2); 294 | assert_eq!(cfg.get_block(6).children, vec![7]); 295 | assert_eq!(cfg.get_block(6).idom.unwrap(), 1); 296 | assert_eq!(cfg.get_block(7).children, vec![]); 297 | assert_eq!(cfg.get_block(7).idom.unwrap(), 6); 298 | cfg.into_ssa(); 299 | } 300 | 301 | #[test] 302 | fn test_cfg_empty() { 303 | let input = " 304 | lambda myfun() :: Int { 305 | 306 | } 307 | "; 308 | 309 | let p = super::parser::parse_and_validate(input).unwrap(); 310 | let mut context = Context::new(); 311 | translate_program(&mut context, &p); 312 | let funs = context.get_functions(); 313 | let fun = funs.get("myfun").unwrap(); 314 | let body = fun.get_body(); 315 | println!("{}", Displayable(&body[..])); 316 | let params = fun.get_params(); 317 | /* 318 | rd1 = myvar4 319 | rd2 = i 320 | */ 321 | let expected = ""; 322 | assert_eq!( 323 | expected 324 | .chars() 325 | .filter(|c| !c.is_whitespace()) 326 | .collect::(), 327 | Displayable(&body[..]) 328 | .to_string() 329 | .chars() 330 | .filter(|c| !c.is_whitespace()) 331 | .collect::() 332 | ); 333 | assert_eq!(¶ms[..], &[][..]); 334 | 335 | let cfg = CFG::from_linear(body, fun.get_params(), fun.get_max_reg()); 336 | println!("{:?}", cfg); 337 | assert_eq!(cfg.get_block(0).children, vec![]); 338 | assert_eq!(cfg.get_block(0).idom, None); 339 | } 340 | } 341 | -------------------------------------------------------------------------------- /proptest-regressions/ir.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc 4834516e2c85be8ba07c2e7ba34cf8a57eec7a278c62140c8777d2ed1ec5c9e7 # shrinks to cfg = CFG { blocks: [Block { label: "ENTRY", body: [GetParameter(0, 0), GetParameter(1, 1), GetParameter(2, 2), GetParameter(3, 3), GetParameter(4, 4), GetParameter(5, 5), GetParameter(6, 6), GetParameter(7, 7), GetParameter(8, 8), GetParameter(9, 9), GetParameter(10, 10), GetParameter(11, 11), GetParameter(12, 12), GetParameter(13, 13), GetParameter(14, 14), GetParameter(15, 15), GetParameter(16, 16), GetParameter(17, 17), GetParameter(18, 18), GetParameter(19, 19), GetParameter(20, 20), Nop, Nop, Nop, Mult(0, 0, 0), La(9, "yboaberwybqrzskur"), Load(7, 7, 13), Load(12, 4, 4), Mv(4, 8), Store(16, 4, 18), Load(14, 19, 18), Nop, Slt(7, 19, 19), Load(16, 14, 6), Load(0, 0, 8), Load(6, 14, 18), Div(7, 2, 19), Slt(7, 9, 4), Slt(19, 15, 11), Store(6, 19, 13), Div(13, 7, 15)], preds: [], children: [], idom: None, idom_of: [], mark: false }], entry: 0, max_reg: 21 } 8 | cc 2faafc3c1f934e83d6a936872e1b3938788024267e46ba884f31c05cf9307dd4 # shrinks to cfg = CFG { blocks: [Block { label: "ENTRY", body: [GetParameter(0, 0), GetParameter(1, 1), GetParameter(2, 2), GetParameter(3, 3), GetParameter(4, 4), GetParameter(5, 5), GetParameter(6, 6), GetParameter(7, 7), GetParameter(8, 8), GetParameter(9, 9), GetParameter(10, 10), GetParameter(11, 11), GetParameter(12, 12), GetParameter(13, 13), GetParameter(14, 14), GetParameter(15, 15), GetParameter(16, 16), GetParameter(17, 17), GetParameter(18, 18), GetParameter(19, 19), GetParameter(20, 20), Nop, Sub(17, 11, 19), Sub(0, 1, 3), Div(17, 10, 19), Li(9, 7722038524963882165), And(4, 0, 6), Nop, La(13, "tofkaql"), Load(4, 13, 3), Xor(9, 9, 16), Xor(10, 8, 2), Mv(5, 14), Slt(9, 0, 1), Load(3, 6, 11), Add(8, 17, 10), Div(10, 3, 15), Store(3, 15, 16), Sub(8, 8, 3), Sub(5, 13, 8), Add(0, 8, 18), Beq(5, 5, "LABEL_17", "LABEL_5")], preds: [], children: [1, 2], idom: None, idom_of: [1, 2, 6, 9, 10, 11], mark: false }, Block { label: "LABEL_17", body: [Li(6, -4035776331892128310), Mult(18, 6, 11), Load(17, 2, 4), Load(19, 12, 10), Sub(7, 4, 8), La(9, "vrprdb"), Slt(6, 11, 0), Or(11, 13, 18), Load(17, 5, 4), Load(1, 5, 0), Li(8, 6939287583546163966), Add(13, 4, 6), Li(13, 4992712065944961093), Load(17, 15, 0), Load(13, 19, 11), And(5, 1, 1), La(2, "ghyc"), Nop, Add(2, 9, 8), Nop, Bl(8, 12, "LABEL_19", "LABEL_15")], preds: [0, 4], children: [3, 4], idom: Some(0), idom_of: [3, 4], mark: false }, Block { label: "LABEL_5", body: [Add(2, 19, 15), Load(7, 9, 11), Div(17, 5, 15), Nop, Mult(10, 2, 19), Load(7, 6, 1), Load(8, 7, 7), Div(3, 11, 19), Nop, Load(11, 6, 1), Load(5, 6, 18), Load(10, 14, 18), Sub(8, 16, 16), Nop, Nop, Nop, Nop, Or(8, 19, 5), And(15, 18, 4), Store(0, 16, 12), Beq(13, 19, "LABEL_4", "LABEL_3")], preds: [0, 3], children: [5, 6], idom: Some(0), idom_of: [5], mark: false }, Block { label: "LABEL_19", body: [Load(8, 2, 17), Or(18, 1, 2), La(5, "jeg"), Load(3, 4, 18), Div(15, 6, 17), And(9, 17, 14), Load(5, 15, 13), Add(8, 19, 4), Xor(11, 12, 18), Mult(16, 15, 8), Store(8, 10, 7), La(18, "dpmgqaipmn"), Load(18, 10, 11), Li(2, -2087490506786693938), Mult(5, 9, 10), Mv(14, 14), Load(3, 9, 10), Nop, Xor(3, 14, 2), Xor(0, 18, 5), Beq(18, 4, "LABEL_12", "LABEL_5")], preds: [1], children: [7, 2], idom: Some(1), idom_of: [7], mark: false }, Block { label: "LABEL_15", body: [Or(0, 11, 3), Mv(16, 16), Load(15, 8, 12), Or(12, 12, 9), Slt(3, 18, 11), Load(4, 7, 19), Mv(12, 8), Slt(2, 7, 10), And(1, 16, 13), Or(16, 8, 18), Load(10, 10, 18), Slt(2, 4, 19), Load(7, 2, 16), Mv(13, 14), Div(2, 7, 3), Or(13, 19, 2), Sub(6, 17, 3), Li(13, -7854753388367394194), Div(13, 8, 10), Slt(10, 1, 2), Bgt(5, 2, "LABEL_18", "LABEL_17")], preds: [1], children: [8, 1], idom: Some(1), idom_of: [8], mark: false }, Block { label: "LABEL_4", body: [Mv(3, 5), Load(16, 17, 2), Mult(10, 18, 6), Mult(2, 19, 19), Load(12, 5, 13), Nop, Nop, Load(11, 0, 0), Nop, Store(12, 18, 11), Add(17, 4, 13), La(0, "rvracqtysgbozezcgajzt"), La(12, "mjlwphzbncuoeeibyoryhfgqb"), Xor(10, 4, 14), Nop, Load(8, 15, 6), Nop, Load(10, 6, 3), And(4, 8, 2), Div(6, 10, 12), Bgt(9, 6, "LABEL_2", "LABEL_8")], preds: [2], children: [9, 10], idom: Some(2), idom_of: [], mark: false }, Block { label: "LABEL_3", body: [Load(15, 0, 1), Li(4, -8810048091969778113), Add(18, 6, 9), Load(18, 11, 8), Mult(18, 9, 7), Load(0, 15, 4), Or(11, 16, 18), Mv(5, 6), Load(2, 4, 1), Mv(13, 16), Load(10, 15, 2), Or(19, 2, 11), Add(16, 7, 18), And(6, 5, 16), Div(2, 15, 15), Xor(15, 18, 1), La(4, "fslvkvngbcpllzmvhm"), La(2, "msaz"), Load(6, 17, 10), Add(6, 10, 4), J("LABEL_6")], preds: [2, 7, 12], children: [11], idom: Some(0), idom_of: [], mark: false }, Block { label: "LABEL_12", body: [Div(12, 13, 6), And(12, 15, 9), Or(13, 2, 1), Li(10, 4565455626140719918), Li(0, -3310199092271001831), Sub(18, 15, 13), Mv(12, 11), Load(19, 1, 18), Mv(13, 12), Add(1, 2, 18), And(4, 1, 1), Li(18, 7726797952948408908), Load(16, 5, 6), Mult(9, 11, 12), Store(10, 12, 7), Add(17, 6, 18), Or(7, 0, 9), Load(18, 5, 17), And(3, 8, 12), Li(19, 9006533882141826872), Beq(19, 11, "LABEL_6", "LABEL_3")], preds: [3], children: [11, 6], idom: Some(3), idom_of: [], mark: false }, Block { label: "LABEL_18", body: [Add(5, 14, 8), Nop, Load(11, 3, 2), Load(15, 7, 3), Li(16, 1404209791990127858), Li(7, 7229496386222774996), Xor(4, 17, 7), Xor(3, 3, 7), Load(12, 11, 14), Or(7, 14, 19), Mult(0, 2, 18), Add(7, 6, 16), Sub(18, 13, 6), Sub(2, 14, 19), Load(3, 3, 19), Load(18, 12, 13), Add(2, 12, 19), Load(8, 4, 14), Load(4, 5, 4), And(13, 11, 2)], preds: [4], children: [], idom: Some(4), idom_of: [], mark: false }, Block { label: "LABEL_2", body: [Xor(7, 10, 16), And(11, 15, 9), Load(18, 0, 13), Li(0, -8835767566988797842), Mult(11, 14, 13), Li(6, -6911745092644422351), Mv(0, 2), Mult(13, 5, 11), Load(14, 8, 19), Div(6, 12, 2), Xor(15, 7, 18), La(4, "zsqrdqdxbodtumzchdyumpgfhthm"), And(9, 2, 16), Slt(5, 15, 0), Or(10, 2, 10), Load(14, 9, 10), Load(1, 0, 15), Load(8, 5, 1), Li(11, -1838527178457655024), Load(1, 15, 8)], preds: [5, 13], children: [], idom: Some(0), idom_of: [], mark: false }, Block { label: "LABEL_8", body: [Xor(0, 7, 9), Mv(3, 19), Mv(17, 16), Sub(8, 15, 7), Slt(17, 13, 9), Div(6, 6, 18), Nop, Load(0, 7, 3), Li(16, 4471305455223087827), Sub(9, 15, 15), Add(6, 3, 5), Sub(3, 9, 18), Store(18, 9, 11), Load(12, 12, 6), And(17, 3, 13), Nop, Load(9, 5, 6), And(4, 1, 6), Load(5, 16, 12), And(13, 7, 11), J("LABEL_11")], preds: [5, 11], children: [12], idom: Some(0), idom_of: [12], mark: false }, Block { label: "LABEL_6", body: [Xor(9, 4, 13), Load(19, 10, 14), Load(5, 11, 10), Div(7, 2, 14), Load(11, 9, 13), Li(8, -208475280132290720), Nop, Load(7, 14, 17), Li(4, -1642747558444112175), Store(12, 1, 19), Load(9, 3, 17), Nop, Div(11, 16, 7), Load(16, 6, 12), Li(8, 2370851020436532771), Mv(12, 16), Li(0, 1857588232652736636), Div(6, 3, 10), La(15, "rsa"), Load(15, 7, 6), Beq(8, 2, "LABEL_9", "LABEL_8")], preds: [6, 7], children: [13, 10], idom: Some(0), idom_of: [13], mark: false }, Block { label: "LABEL_11", body: [Load(5, 16, 8), Div(15, 6, 2), Div(0, 15, 10), Li(10, 6882811357428695730), Or(1, 4, 4), Load(17, 11, 11), Sub(18, 11, 15), Load(7, 1, 5), Mv(0, 8), Slt(6, 9, 7), Load(4, 4, 8), Mult(0, 19, 4), Nop, Or(2, 2, 16), Load(5, 5, 8), Load(4, 18, 7), And(1, 5, 11), Mult(1, 1, 4), Add(7, 1, 7), Load(12, 19, 10), Bl(5, 10, "LABEL_1", "LABEL_3")], preds: [10], children: [14, 6], idom: Some(10), idom_of: [14], mark: false }, Block { label: "LABEL_9", body: [And(15, 16, 17), And(8, 18, 1), Mv(19, 19), Slt(17, 10, 5), And(15, 4, 11), Add(15, 3, 10), Load(8, 4, 7), Load(5, 13, 5), Nop, Store(9, 14, 2), Load(13, 14, 18), Mult(1, 2, 12), Sub(5, 5, 9), And(9, 3, 6), Div(14, 2, 7), Load(8, 6, 1), Li(6, 2218954350413474604), And(4, 18, 6), Div(8, 3, 12), Load(1, 0, 5), J("LABEL_2")], preds: [11], children: [9], idom: Some(11), idom_of: [], mark: false }, Block { label: "LABEL_1", body: [Nop, Nop, Li(0, 6), Sub(3, 13, 5), Mult(17, 17, 5), Sub(13, 7, 16), La(7, "boxmzoiqfgpblxwacvqowcyfwpzoxte"), Store(14, 5, 12), Add(6, 18, 13), Div(2, 19, 15), And(12, 8, 1), Load(8, 8, 14), Or(19, 18, 2), Slt(12, 5, 7), Xor(18, 16, 17), Add(17, 10, 18), Store(2, 4, 9), Div(14, 19, 14), Xor(0, 11, 12), Load(1, 9, 14)], preds: [12], children: [], idom: Some(12), idom_of: [], mark: false }], entry: 0, max_reg: 21 } 9 | cc b546b4ef08487c5b263a38bb0ef03ba5c5ffdc52dae1a73759e429689b56b433 # shrinks to cfg = CFG { blocks: [Block { label: "ENTRY", body: [GetParameter(0, 0), GetParameter(1, 1), GetParameter(2, 2), GetParameter(3, 3), GetParameter(4, 4), GetParameter(5, 5), GetParameter(6, 6), GetParameter(7, 7), GetParameter(8, 8), GetParameter(9, 9), GetParameter(10, 10), GetParameter(11, 11), GetParameter(12, 12), GetParameter(13, 13), GetParameter(14, 14), GetParameter(15, 15), GetParameter(16, 16), GetParameter(17, 17), GetParameter(18, 18), GetParameter(19, 19), GetParameter(20, 20), La(2, "zofvjxovvyhji"), Mv(19, 12), Slt(9, 13, 8), Mult(3, 11, 9), Xor(7, 7, 2), Load(19, 18, 16), Load(6, 8, 3), Load(18, 1, 6), La(14, "dnuhzlfaidyg"), Load(17, 16, 12), Sub(6, 9, 0), Load(18, 13, 17), Xor(15, 14, 6), Or(11, 7, 15), Mv(15, 0), Div(19, 5, 16), And(9, 0, 0), And(10, 14, 19), Mv(12, 18), Load(0, 6, 7), Beq(17, 12, "LABEL_0", "_CRITICAL_0")], preds: [], children: [1, 11], idom: None, idom_of: [1, 3, 9, 11] }, Block { label: "LABEL_0", body: [Mult(8, 8, 1), Mult(0, 3, 19), Or(19, 19, 19), Nop, Load(18, 7, 11), Sub(1, 2, 16), Sub(6, 4, 10), Store(4, 10, 10), Mv(5, 18), La(15, "zpmtgjvauzdflfkcqcavmakjof"), Slt(12, 14, 1), Add(12, 13, 1), Add(11, 13, 19), And(13, 18, 12), Slt(0, 9, 10), Add(18, 12, 15), Div(15, 7, 14), Xor(5, 7, 16), Mv(9, 1), Div(5, 15, 16), Beq(11, 1, "_CRITICAL_1", "LABEL_17")], preds: [0], children: [12, 4], idom: Some(0), idom_of: [4, 12] }, Block { label: "LABEL_1", body: [Nop, Xor(16, 17, 12), Load(11, 1, 6), Store(9, 1, 12), And(8, 12, 19), Store(14, 17, 13), Xor(1, 18, 2), Load(2, 17, 4), Add(14, 7, 14), Add(5, 5, 7), Store(2, 9, 9), Sub(5, 10, 7), Add(4, 0, 4), Xor(6, 18, 14), Load(4, 14, 7), Xor(3, 4, 18), Nop, Mult(10, 11, 12), Slt(14, 1, 3), Nop, Bl(7, 19, "LABEL_15", "LABEL_13")], preds: [11, 13, 6], children: [5, 6], idom: Some(11), idom_of: [5, 6] }, Block { label: "LABEL_3", body: [La(3, "qbkhqcocslradsoeozncig"), Mult(0, 0, 16), And(14, 10, 5), Load(14, 7, 15), Load(11, 0, 3), Mult(16, 8, 9), Mv(13, 13), Load(1, 4, 16), Sub(3, 13, 6), Div(2, 15, 12), Sub(18, 11, 10), Or(17, 15, 1), Div(9, 10, 11), And(11, 5, 19), Store(14, 1, 3), Store(3, 19, 14), Nop, Slt(17, 5, 10), Mult(17, 10, 3), Li(3, 2136001563825269657), J("LABEL_4")], preds: [12, 14, 10], children: [7], idom: Some(0), idom_of: [7] }, Block { label: "LABEL_17", body: [Li(2, 4649470537239729807), Store(1, 1, 4), Div(3, 14, 12), Sub(0, 13, 0), Load(4, 4, 0), Load(17, 6, 10), Nop, And(4, 16, 0), Add(17, 6, 16), Slt(0, 7, 14), Li(12, 4277945939454452942), Slt(11, 4, 13), Xor(12, 5, 14), Slt(6, 18, 9), Store(3, 14, 15), Load(7, 8, 13), And(13, 19, 19), Mult(18, 16, 5), Li(18, -8624524942189448231), Or(5, 11, 12)], preds: [1], children: [], idom: Some(1), idom_of: [] }, Block { label: "LABEL_15", body: [Mult(6, 8, 4), And(0, 19, 18), Store(12, 1, 11), Xor(3, 15, 5), Or(3, 13, 11), Mv(19, 8), Load(17, 3, 0), Mult(2, 6, 3), Div(4, 0, 7), Or(19, 2, 18), Xor(8, 3, 3), Nop, Nop, Div(1, 17, 11), Div(6, 12, 16), Load(5, 7, 1), Load(12, 13, 9), Li(19, -2047325496777433367), Store(6, 8, 4), Load(1, 7, 9), Bgt(2, 4, "LABEL_8", "_CRITICAL_2")], preds: [2], children: [8, 13], idom: Some(2), idom_of: [8, 13] }, Block { label: "LABEL_13", body: [La(10, "ef"), Add(3, 4, 9), Store(1, 8, 5), Mult(2, 7, 3), Mult(11, 6, 18), Sub(10, 2, 11), Mv(3, 0), Mv(3, 14), Load(6, 14, 4), Xor(7, 11, 1), Li(0, -6265127113780331929), Mult(5, 1, 4), Slt(14, 19, 10), Add(11, 16, 17), Slt(17, 8, 18), Store(18, 16, 4), Mv(2, 6), Sub(13, 13, 10), Store(9, 15, 11), Xor(6, 12, 3), Bgt(0, 12, "LABEL_1", "LABEL_1")], preds: [2], children: [2], idom: Some(2), idom_of: [] }, Block { label: "LABEL_4", body: [Store(11, 10, 12), Li(8, 2974830274477721723), La(3, "vdpqyutnkhbz"), Mult(3, 1, 6), Div(13, 16, 2), Mv(2, 17), Mv(2, 10), Load(12, 3, 3), Store(15, 4, 10), Mult(2, 4, 16), Store(0, 10, 6), Nop, Add(16, 16, 13), Xor(4, 1, 1), Slt(19, 1, 8), Load(4, 8, 4), Load(8, 14, 0), Nop, La(13, "ffpldpwjtybmrajucgialxbgdktoanot"), Mult(1, 19, 18), J("LABEL_2")], preds: [3], children: [9], idom: Some(3), idom_of: [] }, Block { label: "LABEL_8", body: [Sub(5, 6, 6), Slt(7, 11, 5), Add(7, 2, 15), Nop, Div(9, 3, 15), Mv(3, 17), Xor(2, 10, 12), Or(8, 13, 0), Load(18, 2, 7), Sub(19, 3, 19), Add(14, 2, 14), Add(15, 10, 12), Load(17, 7, 10), Slt(16, 3, 6), Div(5, 19, 17), Div(16, 2, 5), Div(16, 8, 6), Mv(7, 13), Div(18, 3, 4), Mv(4, 14), Bl(15, 0, "_CRITICAL_3", "_CRITICAL_4")], preds: [5], children: [14, 15], idom: Some(5), idom_of: [14, 15] }, Block { label: "LABEL_2", body: [Store(3, 11, 19), Load(2, 11, 18), Or(19, 19, 13), Load(14, 4, 7), Load(4, 13, 1), Xor(11, 6, 13), Nop, Mv(5, 18), Mv(11, 8), Div(13, 8, 8), Store(17, 13, 11), Load(12, 2, 17), La(0, "nxyqjsogxqtniytyy"), La(19, "tossenpymbayniufkeg"), Mult(9, 17, 17), Store(8, 16, 14), Nop, Li(13, 8830452514214098434), And(11, 16, 16), Nop, J("LABEL_12")], preds: [7, 15], children: [10], idom: Some(0), idom_of: [10] }, Block { label: "LABEL_12", body: [Nop, Nop, Nop, Nop, Load(6, 3, 4), Slt(14, 5, 6), La(11, ""), Mult(5, 13, 9), Div(17, 14, 16), Load(18, 14, 14), Nop, Mult(5, 8, 10), Add(4, 7, 14), And(7, 13, 9), Mv(18, 3), Xor(14, 16, 12), And(7, 11, 3), La(0, "dwetfnemdguluovb"), Mv(8, 10), Mult(10, 4, 2), J("LABEL_3")], preds: [9], children: [3], idom: Some(9), idom_of: [] }, Block { label: "_CRITICAL_0", body: [J("LABEL_1")], preds: [0], children: [2], idom: Some(0), idom_of: [2] }, Block { label: "_CRITICAL_1", body: [J("LABEL_3")], preds: [1], children: [3], idom: Some(1), idom_of: [] }, Block { label: "_CRITICAL_2", body: [J("LABEL_1")], preds: [5], children: [2], idom: Some(5), idom_of: [] }, Block { label: "_CRITICAL_3", body: [J("LABEL_3")], preds: [8], children: [3], idom: Some(8), idom_of: [] }, Block { label: "_CRITICAL_4", body: [J("LABEL_2")], preds: [8], children: [9], idom: Some(8), idom_of: [] }], entry: 0, max_reg: 21 } 10 | -------------------------------------------------------------------------------- /src/parser.rs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 2 | // 3 | use std::error::Error; 4 | 5 | use lrlex::{lrlex_mod, DefaultLexerTypes}; 6 | use lrpar::{lrpar_mod, LexParseError}; 7 | use parser_defs::{ 8 | Defs, Parameter, Params, ParseErr, Program, 9 | Type::{self, Bool, Never}, 10 | }; 11 | 12 | use crate::util::SheafTable; 13 | lrlex_mod!("language.l"); 14 | lrpar_mod!("language.y"); 15 | 16 | fn validate(program: &parser_defs::Program) -> Option> { 17 | let mut sheaf = SheafTable::new(); 18 | resolution(parser_defs::Any::PR(program), &mut sheaf).err() 19 | } 20 | 21 | enum ResolutionState<'a> { 22 | Variable(Type), 23 | Function(&'a [Parameter], Type, bool), 24 | } 25 | 26 | fn resolution<'a, 'b>( 27 | program: parser_defs::Any<'a>, 28 | state: &mut SheafTable<&'b str, ResolutionState<'a>>, 29 | ) -> Result> 30 | where 31 | 'a: 'b, 32 | { 33 | use parser_defs::Any; 34 | match program { 35 | parser_defs::Any::E(expr) => match expr { 36 | parser_defs::Expr::Or(l, r) | parser_defs::Expr::Xor(l, r) => { 37 | let l = resolution(Any::E(l), state)?; 38 | let r = resolution(Any::T(r), state)?; 39 | if l == Bool && r == Bool { 40 | Ok(Bool) 41 | } else { 42 | Err(format!("'OR': Type mismatch. Expected: Bool. Got: {l}, {r}.").into()) 43 | } 44 | } 45 | parser_defs::Expr::ETerm(t) => resolution(Any::T(t), state), 46 | }, 47 | parser_defs::Any::S(s) => match s { 48 | parser_defs::Statement::Def(d) => resolution(Any::D(d), state), 49 | parser_defs::Statement::Assign(l, e) => { 50 | if let Some(ResolutionState::Variable(t)) = state.get(l.as_str()) { 51 | let t = *t; 52 | let te = resolution(Any::E(e), state)?; 53 | if t == te { 54 | Ok(t) 55 | } else { 56 | Err(format!("'=': Type mismatch. Expected: {t}. Got: {te}.").into()) 57 | } 58 | } else { 59 | Err(format!("Undeclared variable {l}.").into()) 60 | } 61 | } 62 | parser_defs::Statement::IfElse(c, t, e) => { 63 | if Bool != resolution(Any::E(c), state)? { 64 | return Err("'IF': Type mismatch. Expected: Bool.".to_string().into()); 65 | } 66 | state.push(); 67 | resolution(Any::B(t), state)?; 68 | state.pop(); 69 | state.push(); 70 | resolution(Any::B(e), state)?; 71 | state.pop(); 72 | Ok(Type::Never) 73 | } 74 | parser_defs::Statement::While(c, b) => { 75 | if Bool != resolution(Any::E(c), state)? { 76 | return Err("'WHILE': Type mismatch. Expected: Bool.".to_string().into()); 77 | } 78 | state.push(); 79 | resolution(Any::B(b), state)?; 80 | state.pop(); 81 | Ok(Type::Never) 82 | } 83 | parser_defs::Statement::Return(e) => { 84 | let tr = resolution(Any::E(e), state)?; 85 | if let Some(ResolutionState::Function(_, t, _)) = state.get("0CUR_FUN") { 86 | if *t == tr { 87 | return Ok(Type::Never); 88 | } 89 | } 90 | Err("'RETURN': Type mismatch.".to_string().into()) 91 | } 92 | }, 93 | parser_defs::Any::D(d) => match d { 94 | parser_defs::Defs::LocalVarDef(i, t, e) => { 95 | if state.get(i.as_str()).is_some() { 96 | Err(format!("Dual declaration for {i}").into()) 97 | } else { 98 | let te = resolution(Any::E(e), state)?; 99 | if te != *t { 100 | return Err(format!("'=': Type mismatch. Expected: {t}. Got: {te}.").into()); 101 | } 102 | state.insert(i, ResolutionState::Variable(*t)); 103 | Ok(Never) 104 | } 105 | } 106 | parser_defs::Defs::GlobalDecl(i, t) => { 107 | if state.get(i.as_str()).is_some() { 108 | Err(format!("Dual declaration for {i}").into()) 109 | } else { 110 | state.insert(i, ResolutionState::Variable(*t)); 111 | Ok(Never) 112 | } 113 | } 114 | parser_defs::Defs::FunctionDef(i, Params(vec), t, b) => { 115 | match state.get(i.as_str()) { 116 | Some(ResolutionState::Variable(..)) => { 117 | return Err(format!( 118 | "Trying to define a function for declared variable {i}" 119 | ) 120 | .into()) 121 | } 122 | Some(ResolutionState::Function(args, ty, d)) => { 123 | if *args != vec.as_slice() || t != ty { 124 | return Err(format!( 125 | "Trying to define function with non-matching signature {i}" 126 | ) 127 | .into()); 128 | } else if *d { 129 | return Err(format!("Dual definition for function {i}").into()); 130 | } 131 | state.remove(i.as_str()); 132 | } 133 | None => {} 134 | } 135 | state.insert(i, ResolutionState::Function(vec.as_slice(), *t, true)); 136 | state.push(); 137 | state.insert( 138 | "0CUR_FUN", 139 | ResolutionState::Function(vec.as_slice(), *t, true), 140 | ); 141 | for p in vec { 142 | state.insert(&p.0, ResolutionState::Variable(p.1)); 143 | } 144 | resolution(Any::B(b), state)?; 145 | state.pop(); 146 | Ok(Never) 147 | } 148 | parser_defs::Defs::FunctionDecl(i, Params(vec), t) => { 149 | if state.get(i.as_str()).is_some() { 150 | return Err(format!("Dual declaration for {i}").into()); 151 | } 152 | state.insert(i, ResolutionState::Function(vec.as_slice(), *t, false)); 153 | Ok(Never) 154 | } 155 | }, 156 | parser_defs::Any::B(parser_defs::Body(vec)) => vec 157 | .iter() 158 | .map(|s| resolution(Any::S(s), state)) 159 | .find(|res| res.is_err()) 160 | .unwrap_or(Ok(Never)), 161 | parser_defs::Any::A(a) => match a { 162 | parser_defs::Atom::Mult(l, r) | parser_defs::Atom::Div(l, r) => { 163 | let l = resolution(Any::A(l), state)?; 164 | let r = resolution(Any::U(r), state)?; 165 | if l == Type::Int && r == Type::Int { 166 | Ok(Type::Int) 167 | } else { 168 | Err(format!("'*//': Type mismatch. Expected: Int. Got: {l}, {r}.").into()) 169 | } 170 | } 171 | parser_defs::Atom::AUnit(u) => resolution(Any::U(u), state), 172 | }, 173 | parser_defs::Any::U(u) => match u { 174 | parser_defs::Unit::Identifier(i) => { 175 | if let Some(ResolutionState::Variable(t)) = state.get(i.as_str()) { 176 | Ok(*t) 177 | } else { 178 | Err(format!("Undeclared variable {i}.").into()) 179 | } 180 | } 181 | parser_defs::Unit::Call(i, a) => { 182 | if let Some(ResolutionState::Function(p, t, ..)) = state.get(i.as_str()) { 183 | let t = *t; 184 | if p.len() == a.0.len() { 185 | a.0.iter() 186 | .zip(p.iter()) 187 | .map(|(e, p)| -> Result> { 188 | let ta = resolution(Any::E(e), state)?; 189 | if ta != p.1 { 190 | Err(format!( 191 | "'CALL': Typ mismatch. Expected: {}. Got: {ta}.", 192 | p.1 193 | ) 194 | .into()) 195 | } else { 196 | Ok(t) 197 | } 198 | }) 199 | .find(|res| res.is_err()) 200 | .unwrap_or(Ok(t)) 201 | } else { 202 | Err(format!("Wrong number of arguments in call to {i}.").into()) 203 | } 204 | } else { 205 | Err(format!("Undeclared function {i}.").into()) 206 | } 207 | } 208 | parser_defs::Unit::Grouping(e) => resolution(Any::E(e), state), 209 | parser_defs::Unit::True | parser_defs::Unit::False => Ok(Bool), 210 | parser_defs::Unit::Number(_) => Ok(Type::Int), 211 | }, 212 | parser_defs::Any::F(f) => match f { 213 | parser_defs::Factor::Plus(l, r) | parser_defs::Factor::Minus(l, r) => { 214 | let l = resolution(Any::F(l), state)?; 215 | let r = resolution(Any::A(r), state)?; 216 | if l == Type::Int && r == Type::Int { 217 | Ok(Type::Int) 218 | } else { 219 | Err(format!("'+/-': Type mismatch. Expected: Int. Got: {l}, {r}.").into()) 220 | } 221 | } 222 | parser_defs::Factor::FAtom(a) => resolution(Any::A(a), state), 223 | }, 224 | parser_defs::Any::CT(ct) => match ct { 225 | parser_defs::CTerm::GEq(l, r) 226 | | parser_defs::CTerm::LT(l, r) 227 | | parser_defs::CTerm::EQ(l, r) => { 228 | let l = resolution(Any::CT(l), state)?; 229 | let r = resolution(Any::F(r), state)?; 230 | if l == Type::Int && r == Type::Int { 231 | Ok(Type::Bool) 232 | } else { 233 | Err(format!("'>=/ resolution(Any::F(f), state), 237 | }, 238 | parser_defs::Any::T(t) => match t { 239 | parser_defs::Term::And(l, r) => { 240 | let l = resolution(Any::T(l), state)?; 241 | let r = resolution(Any::BT(r), state)?; 242 | if l == Type::Bool && r == Type::Bool { 243 | Ok(Type::Bool) 244 | } else { 245 | Err(format!("'AND': Type mismatch. Expected: Bool. Got: {l}, {r}.").into()) 246 | } 247 | } 248 | parser_defs::Term::TCTerm(ct) => resolution(Any::BT(ct), state), 249 | }, 250 | parser_defs::Any::BT(bt) => match bt { 251 | parser_defs::BTerm::Not(ct) => { 252 | let t = resolution(Any::CT(ct), state)?; 253 | if t != Bool { 254 | Err(format!("'NOT': Type mismatch. Expected: Bool. Got: {t}.").into()) 255 | } else { 256 | Ok(Bool) 257 | } 258 | } 259 | parser_defs::BTerm::BCTerm(ct) => resolution(Any::CT(ct), state), 260 | }, 261 | parser_defs::Any::PR(Program(defs)) => { 262 | for v in defs.iter().filter(|&d| matches!(d, Defs::GlobalDecl(..))) { 263 | resolution(Any::D(v), state)?; 264 | } 265 | for f in defs.iter() { 266 | if let Defs::FunctionDef(ident, params, t, ..) 267 | | Defs::FunctionDecl(ident, params, t) = f 268 | { 269 | state.insert( 270 | ident.as_str(), 271 | ResolutionState::Function(¶ms.0[..], *t, false), 272 | ); 273 | } 274 | } 275 | for f in defs.iter() { 276 | if let Defs::FunctionDef(_, params, t, b) = f { 277 | state.push(); 278 | state.insert( 279 | "0CUR_FUN", 280 | ResolutionState::Function(params.0.as_slice(), *t, true), 281 | ); 282 | for p in ¶ms.0 { 283 | state.insert(&p.0, ResolutionState::Variable(p.1)); 284 | } 285 | resolution(Any::B(b), state)?; 286 | state.pop(); 287 | } 288 | } 289 | Ok(Never) 290 | } 291 | _ => Ok(Never), 292 | } 293 | } 294 | 295 | type GRMResult = ( 296 | Option>, 297 | Vec>, 298 | ); 299 | 300 | fn parse(s: &str) -> GRMResult { 301 | let lexerdef = language_l::lexerdef(); 302 | let lexer = lexerdef.lexer(s); 303 | language_y::parse(&lexer) 304 | } 305 | 306 | pub fn parse_and_validate(s: &str) -> Result> { 307 | let (res, errors) = parse(s); 308 | let mut err_str = String::new(); 309 | for err in errors.iter() { 310 | err_str.push_str(&err.pp(&language_l::lexerdef().lexer(s), &language_y::token_epp)); 311 | } 312 | if !errors.is_empty() { 313 | return Err(err_str.into()); 314 | } 315 | let program_unverified = match res { 316 | Some(Ok(p)) => p, 317 | Some(Err(e)) => return Err(format!("parse error: {}", e).into()), 318 | None => return Err("unknown parse error".into()), 319 | }; 320 | let res = validate(&program_unverified); 321 | if let Some(err) = res { 322 | return Err(format!("type/resolution/binding error: {err}").into()); 323 | } 324 | Ok(program_unverified) 325 | } 326 | 327 | #[cfg(test)] 328 | mod tests { 329 | use crate::parser::validate; 330 | 331 | macro_rules! expect_correct { 332 | ($path:expr, $($name:ident),+) => { 333 | $( 334 | #[test] 335 | fn $name() { 336 | let input = std::fs::read_to_string( 337 | concat!($path, "/", stringify!($name), ".lang")).unwrap(); 338 | let result = super::parse(&input); 339 | assert!(result.1.is_empty()); 340 | assert!(result.0.is_some()); 341 | assert!(result.0.as_ref().unwrap().is_ok()); 342 | let p = result.0.unwrap().unwrap(); 343 | let res = validate(&p); 344 | assert!(res.is_none(), "{}", res.unwrap()); 345 | } 346 | )+ 347 | }; 348 | } 349 | macro_rules! expect_wrong_semantics { 350 | ($path:expr, $($name:ident),+) => { 351 | $( 352 | #[test] 353 | fn $name() { 354 | let input = std::fs::read_to_string( 355 | concat!($path, "/", stringify!($name), ".lang")).unwrap(); 356 | let result = super::parse(&input); 357 | assert!(result.1.is_empty()); 358 | assert!(result.0.is_some()); 359 | assert!(result.0.as_ref().unwrap().is_ok()); 360 | let p = result.0.unwrap().unwrap(); 361 | let res = validate(&p); 362 | assert!(res.is_some(), "Expected validate error, but found None"); 363 | } 364 | )+ 365 | }; 366 | } 367 | 368 | expect_correct!("examples", correct2, example, fibb, recurse, correct3, correct4); 369 | expect_wrong_semantics!( 370 | "examples", 371 | wrong1, 372 | wrong_type1, 373 | wrong2, 374 | wrong_type3, 375 | wrong_type4 376 | ); 377 | } 378 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | -------------------------------------------------------------------------------- /resources/allocated.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | G 9 | 10 | 11 | cluster_dominance 12 | 13 | dom tree 14 | 15 | 16 | cluster_postdominance 17 | 18 | postdom tree 19 | 20 | 21 | 22 | 0 23 | 24 | ENTRY 25 | 26 | getParam rd10, 0 27 | getParam rd11, 1 28 | li rd7, #0 29 | li rd5, #100 30 | li rd6, #1 31 | mv rd10, rd7 32 | j @_LABEL_0 33 | 34 | 35 | 36 | 1 37 | 38 | _LABEL_0 39 | 40 | slt rd29, rd5, rd7 41 | xor rd28, rd6, rd29 42 | beq rd28, rd7, @_LABEL_1, @_LABEL_2 43 | 44 | 45 | 46 | 0->1 47 | 48 | 49 | 50 | 51 | 52 | 5 53 | 54 | _LABEL_1 55 | 56 | return rd10 57 | 58 | 59 | 60 | 1->5 61 | 62 | 63 | 64 | 65 | 66 | 2 67 | 68 | _LABEL_2 69 | 70 | li rd30, #3 71 | j @_LABEL_3 72 | 73 | 74 | 75 | 1->2 76 | 77 | 78 | 79 | 80 | 81 | 6 82 | 83 | EXIT 84 | 85 | 86 | 87 | 88 | 89 | 5->6 90 | 91 | 92 | 93 | 94 | 95 | 3 96 | 97 | _LABEL_3 98 | 99 | mv rd11, rd10 100 | mv rd10, rd30 101 | call rd10, @myfun, ( 10 11 ) 102 | j @_LABEL_4 103 | 104 | 105 | 106 | 2->3 107 | 108 | 109 | 110 | 111 | 112 | 4 113 | 114 | _LABEL_4 115 | 116 | sub rd5, rd5, rd6 117 | j @_LABEL_0 118 | 119 | 120 | 121 | 3->4 122 | 123 | 124 | 125 | 126 | 127 | 4->1 128 | 129 | 130 | 131 | 132 | 133 | dom0 134 | 135 | ENTRY 136 | 137 | 138 | 139 | dom1 140 | 141 | _LABEL_0 142 | 143 | 144 | 145 | dom0->dom1 146 | 147 | 148 | 149 | 150 | 151 | dom2 152 | 153 | _LABEL_2 154 | 155 | 156 | 157 | dom1->dom2 158 | 159 | 160 | 161 | 162 | 163 | dom5 164 | 165 | _LABEL_1 166 | 167 | 168 | 169 | dom1->dom5 170 | 171 | 172 | 173 | 174 | 175 | dom3 176 | 177 | _LABEL_3 178 | 179 | 180 | 181 | dom2->dom3 182 | 183 | 184 | 185 | 186 | 187 | dom4 188 | 189 | _LABEL_4 190 | 191 | 192 | 193 | dom3->dom4 194 | 195 | 196 | 197 | 198 | 199 | dom6 200 | 201 | EXIT 202 | 203 | 204 | 205 | dom5->dom6 206 | 207 | 208 | 209 | 210 | 211 | pdom1 212 | 213 | _LABEL_0 214 | 215 | 216 | 217 | pdom0 218 | 219 | ENTRY 220 | 221 | 222 | 223 | pdom1->pdom0 224 | 225 | 226 | 227 | 228 | 229 | pdom4 230 | 231 | _LABEL_4 232 | 233 | 234 | 235 | pdom1->pdom4 236 | 237 | 238 | 239 | 240 | 241 | pdom5 242 | 243 | _LABEL_1 244 | 245 | 246 | 247 | pdom5->pdom1 248 | 249 | 250 | 251 | 252 | 253 | pdom3 254 | 255 | _LABEL_3 256 | 257 | 258 | 259 | pdom2 260 | 261 | _LABEL_2 262 | 263 | 264 | 265 | pdom3->pdom2 266 | 267 | 268 | 269 | 270 | 271 | pdom4->pdom3 272 | 273 | 274 | 275 | 276 | 277 | pdom6 278 | 279 | EXIT 280 | 281 | 282 | 283 | pdom6->pdom5 284 | 285 | 286 | 287 | 288 | -------------------------------------------------------------------------------- /resources/linear.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | G 9 | 10 | 11 | cluster_dominance 12 | 13 | dom tree 14 | 15 | 16 | cluster_postdominance 17 | 18 | postdom tree 19 | 20 | 21 | 22 | 0 23 | 24 | ENTRY 25 | 26 | getParam rd0, 0 27 | getParam rd1, 1 28 | li rd2, #0 29 | li rd3, #100 30 | j @_LABEL_0 31 | 32 | 33 | 34 | 1 35 | 36 | _LABEL_0 37 | 38 | li rd5, #0 39 | slt rd6, rd3, rd5 40 | li rd7, #1 41 | xor rd8, rd7, rd6 42 | li rd4, #0 43 | beq rd8, rd4, @_LABEL_1, @_LABEL_2 44 | 45 | 46 | 47 | 0->1 48 | 49 | 50 | 51 | 52 | 53 | 5 54 | 55 | _LABEL_1 56 | 57 | return rd2 58 | 59 | 60 | 61 | 1->5 62 | 63 | 64 | 65 | 66 | 67 | 2 68 | 69 | _LABEL_2 70 | 71 | li rd9, #3 72 | j @_LABEL_3 73 | 74 | 75 | 76 | 1->2 77 | 78 | 79 | 80 | 81 | 82 | 6 83 | 84 | EXIT 85 | 86 | 87 | 88 | 89 | 90 | 5->6 91 | 92 | 93 | 94 | 95 | 96 | 3 97 | 98 | _LABEL_3 99 | 100 | call rd10, @myfun, ( 9 2 ) 101 | j @_LABEL_4 102 | 103 | 104 | 105 | 2->3 106 | 107 | 108 | 109 | 110 | 111 | 4 112 | 113 | _LABEL_4 114 | 115 | mv rd2, rd10 116 | li rd11, #1 117 | sub rd12, rd3, rd11 118 | mv rd3, rd12 119 | j @_LABEL_0 120 | 121 | 122 | 123 | 3->4 124 | 125 | 126 | 127 | 128 | 129 | 4->1 130 | 131 | 132 | 133 | 134 | 135 | dom0 136 | 137 | ENTRY 138 | 139 | 140 | 141 | dom1 142 | 143 | _LABEL_0 144 | 145 | 146 | 147 | dom0->dom1 148 | 149 | 150 | 151 | 152 | 153 | dom2 154 | 155 | _LABEL_2 156 | 157 | 158 | 159 | dom1->dom2 160 | 161 | 162 | 163 | 164 | 165 | dom5 166 | 167 | _LABEL_1 168 | 169 | 170 | 171 | dom1->dom5 172 | 173 | 174 | 175 | 176 | 177 | dom3 178 | 179 | _LABEL_3 180 | 181 | 182 | 183 | dom2->dom3 184 | 185 | 186 | 187 | 188 | 189 | dom4 190 | 191 | _LABEL_4 192 | 193 | 194 | 195 | dom3->dom4 196 | 197 | 198 | 199 | 200 | 201 | dom6 202 | 203 | EXIT 204 | 205 | 206 | 207 | dom5->dom6 208 | 209 | 210 | 211 | 212 | 213 | pdom1 214 | 215 | _LABEL_0 216 | 217 | 218 | 219 | pdom0 220 | 221 | ENTRY 222 | 223 | 224 | 225 | pdom1->pdom0 226 | 227 | 228 | 229 | 230 | 231 | pdom4 232 | 233 | _LABEL_4 234 | 235 | 236 | 237 | pdom1->pdom4 238 | 239 | 240 | 241 | 242 | 243 | pdom5 244 | 245 | _LABEL_1 246 | 247 | 248 | 249 | pdom5->pdom1 250 | 251 | 252 | 253 | 254 | 255 | pdom3 256 | 257 | _LABEL_3 258 | 259 | 260 | 261 | pdom2 262 | 263 | _LABEL_2 264 | 265 | 266 | 267 | pdom3->pdom2 268 | 269 | 270 | 271 | 272 | 273 | pdom4->pdom3 274 | 275 | 276 | 277 | 278 | 279 | pdom6 280 | 281 | EXIT 282 | 283 | 284 | 285 | pdom6->pdom5 286 | 287 | 288 | 289 | 290 | -------------------------------------------------------------------------------- /resources/opt.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | G 9 | 10 | 11 | cluster_dominance 12 | 13 | dom tree 14 | 15 | 16 | cluster_postdominance 17 | 18 | postdom tree 19 | 20 | 21 | 22 | 0 23 | 24 | ENTRY 25 | 26 | getParam rd14, 0 27 | getParam rd15, 1 28 | li rd16, #0 29 | li rd17, #100 30 | li rd33, #1 31 | j @_LABEL_0 32 | 33 | 34 | 35 | 1 36 | 37 | _LABEL_0 38 | 39 | rd34 <- ϕ ( 16 16 ) 40 | rd18 <- ϕ ( 16 28 ) 41 | rd19 <- ϕ ( 17 31 ) 42 | rd20 <- ϕ ( ⊥ 28 ) 43 | rd21 <- ϕ ( ⊥ 27 ) 44 | slt rd23, rd19, rd16 45 | xor rd25, rd33, rd23 46 | beq rd25, rd16, @_LABEL_1, @_LABEL_2 47 | 48 | 49 | 50 | 0->1 51 | 52 | 53 | 54 | 55 | 56 | 5 57 | 58 | _LABEL_1 59 | 60 | return rd18 61 | 62 | 63 | 64 | 1->5 65 | 66 | 67 | 68 | 69 | 70 | 2 71 | 72 | _LABEL_2 73 | 74 | li rd27, #3 75 | j @_LABEL_3 76 | 77 | 78 | 79 | 1->2 80 | 81 | 82 | 83 | 84 | 85 | 6 86 | 87 | EXIT 88 | 89 | 90 | 91 | 92 | 93 | 5->6 94 | 95 | 96 | 97 | 98 | 99 | 3 100 | 101 | _LABEL_3 102 | 103 | call rd28, @myfun, ( 27 18 ) 104 | j @_LABEL_4 105 | 106 | 107 | 108 | 2->3 109 | 110 | 111 | 112 | 113 | 114 | 4 115 | 116 | _LABEL_4 117 | 118 | sub rd31, rd19, rd33 119 | j @_LABEL_0 120 | 121 | 122 | 123 | 3->4 124 | 125 | 126 | 127 | 128 | 129 | 4->1 130 | 131 | 132 | 133 | 134 | 135 | dom0 136 | 137 | ENTRY 138 | 139 | 140 | 141 | dom1 142 | 143 | _LABEL_0 144 | 145 | 146 | 147 | dom0->dom1 148 | 149 | 150 | 151 | 152 | 153 | dom2 154 | 155 | _LABEL_2 156 | 157 | 158 | 159 | dom1->dom2 160 | 161 | 162 | 163 | 164 | 165 | dom5 166 | 167 | _LABEL_1 168 | 169 | 170 | 171 | dom1->dom5 172 | 173 | 174 | 175 | 176 | 177 | dom3 178 | 179 | _LABEL_3 180 | 181 | 182 | 183 | dom2->dom3 184 | 185 | 186 | 187 | 188 | 189 | dom4 190 | 191 | _LABEL_4 192 | 193 | 194 | 195 | dom3->dom4 196 | 197 | 198 | 199 | 200 | 201 | dom6 202 | 203 | EXIT 204 | 205 | 206 | 207 | dom5->dom6 208 | 209 | 210 | 211 | 212 | 213 | pdom1 214 | 215 | _LABEL_0 216 | 217 | 218 | 219 | pdom0 220 | 221 | ENTRY 222 | 223 | 224 | 225 | pdom1->pdom0 226 | 227 | 228 | 229 | 230 | 231 | pdom4 232 | 233 | _LABEL_4 234 | 235 | 236 | 237 | pdom1->pdom4 238 | 239 | 240 | 241 | 242 | 243 | pdom5 244 | 245 | _LABEL_1 246 | 247 | 248 | 249 | pdom5->pdom1 250 | 251 | 252 | 253 | 254 | 255 | pdom3 256 | 257 | _LABEL_3 258 | 259 | 260 | 261 | pdom2 262 | 263 | _LABEL_2 264 | 265 | 266 | 267 | pdom3->pdom2 268 | 269 | 270 | 271 | 272 | 273 | pdom4->pdom3 274 | 275 | 276 | 277 | 278 | 279 | pdom6 280 | 281 | EXIT 282 | 283 | 284 | 285 | pdom6->pdom5 286 | 287 | 288 | 289 | 290 | -------------------------------------------------------------------------------- /resources/ssa.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | G 9 | 10 | 11 | cluster_dominance 12 | 13 | dom tree 14 | 15 | 16 | cluster_postdominance 17 | 18 | postdom tree 19 | 20 | 21 | 22 | 0 23 | 24 | ENTRY 25 | 26 | getParam rd14, 0 27 | getParam rd15, 1 28 | li rd16, #0 29 | li rd17, #100 30 | j @_LABEL_0 31 | 32 | 33 | 34 | 1 35 | 36 | _LABEL_0 37 | 38 | rd18 <- ϕ ( 16 29 ) 39 | rd19 <- ϕ ( 17 32 ) 40 | rd20 <- ϕ ( ⊥ 28 ) 41 | rd21 <- ϕ ( ⊥ 27 ) 42 | li rd22, #0 43 | slt rd23, rd19, rd22 44 | li rd24, #1 45 | xor rd25, rd24, rd23 46 | li rd26, #0 47 | beq rd25, rd26, @_LABEL_1, @_LABEL_2 48 | 49 | 50 | 51 | 0->1 52 | 53 | 54 | 55 | 56 | 57 | 5 58 | 59 | _LABEL_1 60 | 61 | return rd18 62 | 63 | 64 | 65 | 1->5 66 | 67 | 68 | 69 | 70 | 71 | 2 72 | 73 | _LABEL_2 74 | 75 | li rd27, #3 76 | j @_LABEL_3 77 | 78 | 79 | 80 | 1->2 81 | 82 | 83 | 84 | 85 | 86 | 6 87 | 88 | EXIT 89 | 90 | 91 | 92 | 93 | 94 | 5->6 95 | 96 | 97 | 98 | 99 | 100 | 3 101 | 102 | _LABEL_3 103 | 104 | call rd28, @myfun, ( 27 18 ) 105 | j @_LABEL_4 106 | 107 | 108 | 109 | 2->3 110 | 111 | 112 | 113 | 114 | 115 | 4 116 | 117 | _LABEL_4 118 | 119 | mv rd29, rd28 120 | li rd30, #1 121 | sub rd31, rd19, rd30 122 | mv rd32, rd31 123 | j @_LABEL_0 124 | 125 | 126 | 127 | 3->4 128 | 129 | 130 | 131 | 132 | 133 | 4->1 134 | 135 | 136 | 137 | 138 | 139 | dom0 140 | 141 | ENTRY 142 | 143 | 144 | 145 | dom1 146 | 147 | _LABEL_0 148 | 149 | 150 | 151 | dom0->dom1 152 | 153 | 154 | 155 | 156 | 157 | dom2 158 | 159 | _LABEL_2 160 | 161 | 162 | 163 | dom1->dom2 164 | 165 | 166 | 167 | 168 | 169 | dom5 170 | 171 | _LABEL_1 172 | 173 | 174 | 175 | dom1->dom5 176 | 177 | 178 | 179 | 180 | 181 | dom3 182 | 183 | _LABEL_3 184 | 185 | 186 | 187 | dom2->dom3 188 | 189 | 190 | 191 | 192 | 193 | dom4 194 | 195 | _LABEL_4 196 | 197 | 198 | 199 | dom3->dom4 200 | 201 | 202 | 203 | 204 | 205 | dom6 206 | 207 | EXIT 208 | 209 | 210 | 211 | dom5->dom6 212 | 213 | 214 | 215 | 216 | 217 | pdom1 218 | 219 | _LABEL_0 220 | 221 | 222 | 223 | pdom0 224 | 225 | ENTRY 226 | 227 | 228 | 229 | pdom1->pdom0 230 | 231 | 232 | 233 | 234 | 235 | pdom4 236 | 237 | _LABEL_4 238 | 239 | 240 | 241 | pdom1->pdom4 242 | 243 | 244 | 245 | 246 | 247 | pdom5 248 | 249 | _LABEL_1 250 | 251 | 252 | 253 | pdom5->pdom1 254 | 255 | 256 | 257 | 258 | 259 | pdom3 260 | 261 | _LABEL_3 262 | 263 | 264 | 265 | pdom2 266 | 267 | _LABEL_2 268 | 269 | 270 | 271 | pdom3->pdom2 272 | 273 | 274 | 275 | 276 | 277 | pdom4->pdom3 278 | 279 | 280 | 281 | 282 | 283 | pdom6 284 | 285 | EXIT 286 | 287 | 288 | 289 | pdom6->pdom5 290 | 291 | 292 | 293 | 294 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "aho-corasick" 7 | version = "0.7.20" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" 10 | dependencies = [ 11 | "memchr", 12 | ] 13 | 14 | [[package]] 15 | name = "ansi_term" 16 | version = "0.12.1" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" 19 | dependencies = [ 20 | "winapi", 21 | ] 22 | 23 | [[package]] 24 | name = "anstream" 25 | version = "0.2.6" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "342258dd14006105c2b75ab1bd7543a03bdf0cfc94383303ac212a04939dff6f" 28 | dependencies = [ 29 | "anstyle", 30 | "anstyle-parse", 31 | "anstyle-wincon", 32 | "concolor-override", 33 | "concolor-query", 34 | "is-terminal", 35 | "utf8parse", 36 | ] 37 | 38 | [[package]] 39 | name = "anstyle" 40 | version = "0.3.5" 41 | source = "registry+https://github.com/rust-lang/crates.io-index" 42 | checksum = "23ea9e81bd02e310c216d080f6223c179012256e5151c41db88d12c88a1684d2" 43 | 44 | [[package]] 45 | name = "anstyle-parse" 46 | version = "0.1.1" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | checksum = "a7d1bb534e9efed14f3e5f44e7dd1a4f709384023a4165199a4241e18dff0116" 49 | dependencies = [ 50 | "utf8parse", 51 | ] 52 | 53 | [[package]] 54 | name = "anstyle-wincon" 55 | version = "0.2.0" 56 | source = "registry+https://github.com/rust-lang/crates.io-index" 57 | checksum = "c3127af6145b149f3287bb9a0d10ad9c5692dba8c53ad48285e5bec4063834fa" 58 | dependencies = [ 59 | "anstyle", 60 | "windows-sys 0.45.0", 61 | ] 62 | 63 | [[package]] 64 | name = "anyhow" 65 | version = "1.0.68" 66 | source = "registry+https://github.com/rust-lang/crates.io-index" 67 | checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" 68 | 69 | [[package]] 70 | name = "atty" 71 | version = "0.2.14" 72 | source = "registry+https://github.com/rust-lang/crates.io-index" 73 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 74 | dependencies = [ 75 | "hermit-abi 0.1.19", 76 | "libc", 77 | "winapi", 78 | ] 79 | 80 | [[package]] 81 | name = "autocfg" 82 | version = "1.1.0" 83 | source = "registry+https://github.com/rust-lang/crates.io-index" 84 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 85 | 86 | [[package]] 87 | name = "bincode" 88 | version = "1.3.3" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" 91 | dependencies = [ 92 | "serde", 93 | ] 94 | 95 | [[package]] 96 | name = "bindgen" 97 | version = "0.58.1" 98 | source = "registry+https://github.com/rust-lang/crates.io-index" 99 | checksum = "0f8523b410d7187a43085e7e064416ea32ded16bd0a4e6fc025e21616d01258f" 100 | dependencies = [ 101 | "bitflags", 102 | "cexpr", 103 | "clang-sys", 104 | "clap 2.34.0", 105 | "env_logger", 106 | "lazy_static", 107 | "lazycell", 108 | "log", 109 | "peeking_take_while", 110 | "proc-macro2", 111 | "quote", 112 | "regex", 113 | "rustc-hash", 114 | "shlex", 115 | "which", 116 | ] 117 | 118 | [[package]] 119 | name = "bit-set" 120 | version = "0.5.3" 121 | source = "registry+https://github.com/rust-lang/crates.io-index" 122 | checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" 123 | dependencies = [ 124 | "bit-vec", 125 | ] 126 | 127 | [[package]] 128 | name = "bit-vec" 129 | version = "0.6.3" 130 | source = "registry+https://github.com/rust-lang/crates.io-index" 131 | checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" 132 | 133 | [[package]] 134 | name = "bitflags" 135 | version = "1.3.2" 136 | source = "registry+https://github.com/rust-lang/crates.io-index" 137 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 138 | 139 | [[package]] 140 | name = "byteorder" 141 | version = "1.4.3" 142 | source = "registry+https://github.com/rust-lang/crates.io-index" 143 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 144 | 145 | [[package]] 146 | name = "cactus" 147 | version = "1.0.6" 148 | source = "registry+https://github.com/rust-lang/crates.io-index" 149 | checksum = "cf034765b7d19a011c6d619e880582bf95e8186b580e6fab56589872dd87dcf5" 150 | 151 | [[package]] 152 | name = "cc" 153 | version = "1.0.79" 154 | source = "registry+https://github.com/rust-lang/crates.io-index" 155 | checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" 156 | 157 | [[package]] 158 | name = "cexpr" 159 | version = "0.4.0" 160 | source = "registry+https://github.com/rust-lang/crates.io-index" 161 | checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27" 162 | dependencies = [ 163 | "nom", 164 | ] 165 | 166 | [[package]] 167 | name = "cfg-if" 168 | version = "1.0.0" 169 | source = "registry+https://github.com/rust-lang/crates.io-index" 170 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 171 | 172 | [[package]] 173 | name = "cfgrammar" 174 | version = "0.13.1" 175 | source = "registry+https://github.com/rust-lang/crates.io-index" 176 | checksum = "f1a6ae4d80de7ec1154cc0ad78b63aafce4dea1c28b94101ab697042d768ad10" 177 | dependencies = [ 178 | "indexmap", 179 | "lazy_static", 180 | "num-traits", 181 | "regex", 182 | "serde", 183 | "vob", 184 | ] 185 | 186 | [[package]] 187 | name = "clang-sys" 188 | version = "1.6.0" 189 | source = "registry+https://github.com/rust-lang/crates.io-index" 190 | checksum = "77ed9a53e5d4d9c573ae844bfac6872b159cb1d1585a83b29e7a64b7eef7332a" 191 | dependencies = [ 192 | "glob", 193 | "libc", 194 | "libloading", 195 | ] 196 | 197 | [[package]] 198 | name = "clap" 199 | version = "2.34.0" 200 | source = "registry+https://github.com/rust-lang/crates.io-index" 201 | checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" 202 | dependencies = [ 203 | "ansi_term", 204 | "atty", 205 | "bitflags", 206 | "strsim 0.8.0", 207 | "textwrap", 208 | "unicode-width", 209 | "vec_map", 210 | ] 211 | 212 | [[package]] 213 | name = "clap" 214 | version = "4.2.0" 215 | source = "registry+https://github.com/rust-lang/crates.io-index" 216 | checksum = "6efb5f0a41b5ef5b50c5da28c07609c20091df0c1fc33d418fa2a7e693c2b624" 217 | dependencies = [ 218 | "clap_builder", 219 | "clap_derive", 220 | "once_cell", 221 | ] 222 | 223 | [[package]] 224 | name = "clap_builder" 225 | version = "4.2.0" 226 | source = "registry+https://github.com/rust-lang/crates.io-index" 227 | checksum = "671fcaa5debda4b9a84aa7fde49c907c8986c0e6ab927e04217c9cb74e7c8bc9" 228 | dependencies = [ 229 | "anstream", 230 | "anstyle", 231 | "bitflags", 232 | "clap_lex", 233 | "strsim 0.10.0", 234 | ] 235 | 236 | [[package]] 237 | name = "clap_derive" 238 | version = "4.2.0" 239 | source = "registry+https://github.com/rust-lang/crates.io-index" 240 | checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4" 241 | dependencies = [ 242 | "heck", 243 | "proc-macro2", 244 | "quote", 245 | "syn 2.0.11", 246 | ] 247 | 248 | [[package]] 249 | name = "clap_lex" 250 | version = "0.4.1" 251 | source = "registry+https://github.com/rust-lang/crates.io-index" 252 | checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" 253 | 254 | [[package]] 255 | name = "cmake" 256 | version = "0.1.49" 257 | source = "registry+https://github.com/rust-lang/crates.io-index" 258 | checksum = "db34956e100b30725f2eb215f90d4871051239535632f84fea3bc92722c66b7c" 259 | dependencies = [ 260 | "cc", 261 | ] 262 | 263 | [[package]] 264 | name = "concolor-override" 265 | version = "1.0.0" 266 | source = "registry+https://github.com/rust-lang/crates.io-index" 267 | checksum = "a855d4a1978dc52fb0536a04d384c2c0c1aa273597f08b77c8c4d3b2eec6037f" 268 | 269 | [[package]] 270 | name = "concolor-query" 271 | version = "0.3.3" 272 | source = "registry+https://github.com/rust-lang/crates.io-index" 273 | checksum = "88d11d52c3d7ca2e6d0040212be9e4dbbcd78b6447f535b6b561f449427944cf" 274 | dependencies = [ 275 | "windows-sys 0.45.0", 276 | ] 277 | 278 | [[package]] 279 | name = "enum-iterator" 280 | version = "1.2.0" 281 | source = "registry+https://github.com/rust-lang/crates.io-index" 282 | checksum = "91a4ec26efacf4aeff80887a175a419493cb6f8b5480d26387eb0bd038976187" 283 | dependencies = [ 284 | "enum-iterator-derive", 285 | ] 286 | 287 | [[package]] 288 | name = "enum-iterator-derive" 289 | version = "1.1.0" 290 | source = "registry+https://github.com/rust-lang/crates.io-index" 291 | checksum = "828de45d0ca18782232dfb8f3ea9cc428e8ced380eb26a520baaacfc70de39ce" 292 | dependencies = [ 293 | "proc-macro2", 294 | "quote", 295 | "syn 1.0.107", 296 | ] 297 | 298 | [[package]] 299 | name = "env_logger" 300 | version = "0.8.4" 301 | source = "registry+https://github.com/rust-lang/crates.io-index" 302 | checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" 303 | dependencies = [ 304 | "atty", 305 | "humantime", 306 | "log", 307 | "regex", 308 | "termcolor", 309 | ] 310 | 311 | [[package]] 312 | name = "errno" 313 | version = "0.2.8" 314 | source = "registry+https://github.com/rust-lang/crates.io-index" 315 | checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" 316 | dependencies = [ 317 | "errno-dragonfly", 318 | "libc", 319 | "winapi", 320 | ] 321 | 322 | [[package]] 323 | name = "errno" 324 | version = "0.3.0" 325 | source = "registry+https://github.com/rust-lang/crates.io-index" 326 | checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0" 327 | dependencies = [ 328 | "errno-dragonfly", 329 | "libc", 330 | "windows-sys 0.45.0", 331 | ] 332 | 333 | [[package]] 334 | name = "errno-dragonfly" 335 | version = "0.1.2" 336 | source = "registry+https://github.com/rust-lang/crates.io-index" 337 | checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" 338 | dependencies = [ 339 | "cc", 340 | "libc", 341 | ] 342 | 343 | [[package]] 344 | name = "fastrand" 345 | version = "1.9.0" 346 | source = "registry+https://github.com/rust-lang/crates.io-index" 347 | checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" 348 | dependencies = [ 349 | "instant", 350 | ] 351 | 352 | [[package]] 353 | name = "filetime" 354 | version = "0.2.19" 355 | source = "registry+https://github.com/rust-lang/crates.io-index" 356 | checksum = "4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9" 357 | dependencies = [ 358 | "cfg-if", 359 | "libc", 360 | "redox_syscall", 361 | "windows-sys 0.42.0", 362 | ] 363 | 364 | [[package]] 365 | name = "fnv" 366 | version = "1.0.7" 367 | source = "registry+https://github.com/rust-lang/crates.io-index" 368 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 369 | 370 | [[package]] 371 | name = "getopts" 372 | version = "0.2.21" 373 | source = "registry+https://github.com/rust-lang/crates.io-index" 374 | checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" 375 | dependencies = [ 376 | "unicode-width", 377 | ] 378 | 379 | [[package]] 380 | name = "getrandom" 381 | version = "0.2.8" 382 | source = "registry+https://github.com/rust-lang/crates.io-index" 383 | checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" 384 | dependencies = [ 385 | "cfg-if", 386 | "libc", 387 | "wasi", 388 | ] 389 | 390 | [[package]] 391 | name = "getset" 392 | version = "0.1.2" 393 | source = "registry+https://github.com/rust-lang/crates.io-index" 394 | checksum = "e45727250e75cc04ff2846a66397da8ef2b3db8e40e0cef4df67950a07621eb9" 395 | dependencies = [ 396 | "proc-macro-error", 397 | "proc-macro2", 398 | "quote", 399 | "syn 1.0.107", 400 | ] 401 | 402 | [[package]] 403 | name = "glob" 404 | version = "0.3.1" 405 | source = "registry+https://github.com/rust-lang/crates.io-index" 406 | checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" 407 | 408 | [[package]] 409 | name = "hashbrown" 410 | version = "0.12.3" 411 | source = "registry+https://github.com/rust-lang/crates.io-index" 412 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 413 | 414 | [[package]] 415 | name = "heck" 416 | version = "0.4.1" 417 | source = "registry+https://github.com/rust-lang/crates.io-index" 418 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 419 | 420 | [[package]] 421 | name = "hermit-abi" 422 | version = "0.1.19" 423 | source = "registry+https://github.com/rust-lang/crates.io-index" 424 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 425 | dependencies = [ 426 | "libc", 427 | ] 428 | 429 | [[package]] 430 | name = "hermit-abi" 431 | version = "0.3.1" 432 | source = "registry+https://github.com/rust-lang/crates.io-index" 433 | checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" 434 | 435 | [[package]] 436 | name = "humantime" 437 | version = "2.1.0" 438 | source = "registry+https://github.com/rust-lang/crates.io-index" 439 | checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" 440 | 441 | [[package]] 442 | name = "indexmap" 443 | version = "1.9.2" 444 | source = "registry+https://github.com/rust-lang/crates.io-index" 445 | checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" 446 | dependencies = [ 447 | "autocfg", 448 | "hashbrown", 449 | ] 450 | 451 | [[package]] 452 | name = "instant" 453 | version = "0.1.12" 454 | source = "registry+https://github.com/rust-lang/crates.io-index" 455 | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" 456 | dependencies = [ 457 | "cfg-if", 458 | ] 459 | 460 | [[package]] 461 | name = "io-lifetimes" 462 | version = "1.0.5" 463 | source = "registry+https://github.com/rust-lang/crates.io-index" 464 | checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3" 465 | dependencies = [ 466 | "libc", 467 | "windows-sys 0.45.0", 468 | ] 469 | 470 | [[package]] 471 | name = "is-terminal" 472 | version = "0.4.6" 473 | source = "registry+https://github.com/rust-lang/crates.io-index" 474 | checksum = "256017f749ab3117e93acb91063009e1f1bb56d03965b14c2c8df4eb02c524d8" 475 | dependencies = [ 476 | "hermit-abi 0.3.1", 477 | "io-lifetimes", 478 | "rustix 0.37.4", 479 | "windows-sys 0.45.0", 480 | ] 481 | 482 | [[package]] 483 | name = "itoa" 484 | version = "1.0.5" 485 | source = "registry+https://github.com/rust-lang/crates.io-index" 486 | checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" 487 | 488 | [[package]] 489 | name = "lazy_static" 490 | version = "1.4.0" 491 | source = "registry+https://github.com/rust-lang/crates.io-index" 492 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 493 | 494 | [[package]] 495 | name = "lazycell" 496 | version = "1.3.0" 497 | source = "registry+https://github.com/rust-lang/crates.io-index" 498 | checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" 499 | 500 | [[package]] 501 | name = "libc" 502 | version = "0.2.140" 503 | source = "registry+https://github.com/rust-lang/crates.io-index" 504 | checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" 505 | 506 | [[package]] 507 | name = "libloading" 508 | version = "0.7.4" 509 | source = "registry+https://github.com/rust-lang/crates.io-index" 510 | checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" 511 | dependencies = [ 512 | "cfg-if", 513 | "winapi", 514 | ] 515 | 516 | [[package]] 517 | name = "libm" 518 | version = "0.2.6" 519 | source = "registry+https://github.com/rust-lang/crates.io-index" 520 | checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" 521 | 522 | [[package]] 523 | name = "linux-raw-sys" 524 | version = "0.1.4" 525 | source = "registry+https://github.com/rust-lang/crates.io-index" 526 | checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" 527 | 528 | [[package]] 529 | name = "linux-raw-sys" 530 | version = "0.3.0" 531 | source = "registry+https://github.com/rust-lang/crates.io-index" 532 | checksum = "cd550e73688e6d578f0ac2119e32b797a327631a42f9433e59d02e139c8df60d" 533 | 534 | [[package]] 535 | name = "log" 536 | version = "0.4.17" 537 | source = "registry+https://github.com/rust-lang/crates.io-index" 538 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" 539 | dependencies = [ 540 | "cfg-if", 541 | ] 542 | 543 | [[package]] 544 | name = "lrlex" 545 | version = "0.13.1" 546 | source = "registry+https://github.com/rust-lang/crates.io-index" 547 | checksum = "139466c7000629ac9366297f14137fb25b27a1823865cd000b8a70c092fcb88a" 548 | dependencies = [ 549 | "cfgrammar", 550 | "getopts", 551 | "lazy_static", 552 | "lrpar", 553 | "num-traits", 554 | "quote", 555 | "regex", 556 | "regex-syntax", 557 | "serde", 558 | "vergen", 559 | ] 560 | 561 | [[package]] 562 | name = "lrpar" 563 | version = "0.13.1" 564 | source = "registry+https://github.com/rust-lang/crates.io-index" 565 | checksum = "96fb488710f2fb58de7d3f09a19b501b7222aa461ae2607749612bd5bc04cf38" 566 | dependencies = [ 567 | "bincode", 568 | "cactus", 569 | "cfgrammar", 570 | "filetime", 571 | "indexmap", 572 | "lazy_static", 573 | "lrtable", 574 | "num-traits", 575 | "packedvec", 576 | "regex", 577 | "serde", 578 | "static_assertions", 579 | "vergen", 580 | "vob", 581 | ] 582 | 583 | [[package]] 584 | name = "lrtable" 585 | version = "0.13.1" 586 | source = "registry+https://github.com/rust-lang/crates.io-index" 587 | checksum = "aa8e2dca0cc90f4137a72e176412644beebeda10fd99a4f94a3e984bda256283" 588 | dependencies = [ 589 | "cfgrammar", 590 | "fnv", 591 | "num-traits", 592 | "serde", 593 | "sparsevec", 594 | "vob", 595 | ] 596 | 597 | [[package]] 598 | name = "memchr" 599 | version = "2.5.0" 600 | source = "registry+https://github.com/rust-lang/crates.io-index" 601 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 602 | 603 | [[package]] 604 | name = "nom" 605 | version = "5.1.2" 606 | source = "registry+https://github.com/rust-lang/crates.io-index" 607 | checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" 608 | dependencies = [ 609 | "memchr", 610 | "version_check", 611 | ] 612 | 613 | [[package]] 614 | name = "num-traits" 615 | version = "0.2.15" 616 | source = "registry+https://github.com/rust-lang/crates.io-index" 617 | checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" 618 | dependencies = [ 619 | "autocfg", 620 | "libm", 621 | ] 622 | 623 | [[package]] 624 | name = "once_cell" 625 | version = "1.17.1" 626 | source = "registry+https://github.com/rust-lang/crates.io-index" 627 | checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" 628 | 629 | [[package]] 630 | name = "packedvec" 631 | version = "1.2.4" 632 | source = "registry+https://github.com/rust-lang/crates.io-index" 633 | checksum = "bde3c690ec20e4a2b4fb46f0289a451181eb50011a1e2acc8d85e2fde9062a45" 634 | dependencies = [ 635 | "num-traits", 636 | "serde", 637 | ] 638 | 639 | [[package]] 640 | name = "parser_defs" 641 | version = "0.1.0" 642 | dependencies = [ 643 | "lrpar", 644 | ] 645 | 646 | [[package]] 647 | name = "peeking_take_while" 648 | version = "0.1.2" 649 | source = "registry+https://github.com/rust-lang/crates.io-index" 650 | checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" 651 | 652 | [[package]] 653 | name = "pest" 654 | version = "2.5.4" 655 | source = "registry+https://github.com/rust-lang/crates.io-index" 656 | checksum = "4ab62d2fa33726dbe6321cc97ef96d8cde531e3eeaf858a058de53a8a6d40d8f" 657 | dependencies = [ 658 | "thiserror", 659 | "ucd-trie", 660 | ] 661 | 662 | [[package]] 663 | name = "ppv-lite86" 664 | version = "0.2.17" 665 | source = "registry+https://github.com/rust-lang/crates.io-index" 666 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" 667 | 668 | [[package]] 669 | name = "proc-macro-error" 670 | version = "1.0.4" 671 | source = "registry+https://github.com/rust-lang/crates.io-index" 672 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 673 | dependencies = [ 674 | "proc-macro-error-attr", 675 | "proc-macro2", 676 | "quote", 677 | "syn 1.0.107", 678 | "version_check", 679 | ] 680 | 681 | [[package]] 682 | name = "proc-macro-error-attr" 683 | version = "1.0.4" 684 | source = "registry+https://github.com/rust-lang/crates.io-index" 685 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 686 | dependencies = [ 687 | "proc-macro2", 688 | "quote", 689 | "version_check", 690 | ] 691 | 692 | [[package]] 693 | name = "proc-macro2" 694 | version = "1.0.54" 695 | source = "registry+https://github.com/rust-lang/crates.io-index" 696 | checksum = "e472a104799c74b514a57226160104aa483546de37e839ec50e3c2e41dd87534" 697 | dependencies = [ 698 | "unicode-ident", 699 | ] 700 | 701 | [[package]] 702 | name = "proptest" 703 | version = "1.1.0" 704 | source = "registry+https://github.com/rust-lang/crates.io-index" 705 | checksum = "29f1b898011ce9595050a68e60f90bad083ff2987a695a42357134c8381fba70" 706 | dependencies = [ 707 | "bit-set", 708 | "bitflags", 709 | "byteorder", 710 | "lazy_static", 711 | "num-traits", 712 | "quick-error 2.0.1", 713 | "rand", 714 | "rand_chacha", 715 | "rand_xorshift", 716 | "regex-syntax", 717 | "rusty-fork", 718 | "tempfile", 719 | "unarray", 720 | ] 721 | 722 | [[package]] 723 | name = "quick-error" 724 | version = "1.2.3" 725 | source = "registry+https://github.com/rust-lang/crates.io-index" 726 | checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" 727 | 728 | [[package]] 729 | name = "quick-error" 730 | version = "2.0.1" 731 | source = "registry+https://github.com/rust-lang/crates.io-index" 732 | checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" 733 | 734 | [[package]] 735 | name = "quote" 736 | version = "1.0.26" 737 | source = "registry+https://github.com/rust-lang/crates.io-index" 738 | checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" 739 | dependencies = [ 740 | "proc-macro2", 741 | ] 742 | 743 | [[package]] 744 | name = "rand" 745 | version = "0.8.5" 746 | source = "registry+https://github.com/rust-lang/crates.io-index" 747 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 748 | dependencies = [ 749 | "libc", 750 | "rand_chacha", 751 | "rand_core", 752 | ] 753 | 754 | [[package]] 755 | name = "rand_chacha" 756 | version = "0.3.1" 757 | source = "registry+https://github.com/rust-lang/crates.io-index" 758 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 759 | dependencies = [ 760 | "ppv-lite86", 761 | "rand_core", 762 | ] 763 | 764 | [[package]] 765 | name = "rand_core" 766 | version = "0.6.4" 767 | source = "registry+https://github.com/rust-lang/crates.io-index" 768 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 769 | dependencies = [ 770 | "getrandom", 771 | ] 772 | 773 | [[package]] 774 | name = "rand_xorshift" 775 | version = "0.3.0" 776 | source = "registry+https://github.com/rust-lang/crates.io-index" 777 | checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" 778 | dependencies = [ 779 | "rand_core", 780 | ] 781 | 782 | [[package]] 783 | name = "redox_syscall" 784 | version = "0.2.16" 785 | source = "registry+https://github.com/rust-lang/crates.io-index" 786 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 787 | dependencies = [ 788 | "bitflags", 789 | ] 790 | 791 | [[package]] 792 | name = "regex" 793 | version = "1.7.1" 794 | source = "registry+https://github.com/rust-lang/crates.io-index" 795 | checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" 796 | dependencies = [ 797 | "aho-corasick", 798 | "memchr", 799 | "regex-syntax", 800 | ] 801 | 802 | [[package]] 803 | name = "regex-syntax" 804 | version = "0.6.28" 805 | source = "registry+https://github.com/rust-lang/crates.io-index" 806 | checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" 807 | 808 | [[package]] 809 | name = "rustc-hash" 810 | version = "1.1.0" 811 | source = "registry+https://github.com/rust-lang/crates.io-index" 812 | checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" 813 | 814 | [[package]] 815 | name = "rustc_version" 816 | version = "0.3.3" 817 | source = "registry+https://github.com/rust-lang/crates.io-index" 818 | checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" 819 | dependencies = [ 820 | "semver", 821 | ] 822 | 823 | [[package]] 824 | name = "rustix" 825 | version = "0.36.8" 826 | source = "registry+https://github.com/rust-lang/crates.io-index" 827 | checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644" 828 | dependencies = [ 829 | "bitflags", 830 | "errno 0.2.8", 831 | "io-lifetimes", 832 | "libc", 833 | "linux-raw-sys 0.1.4", 834 | "windows-sys 0.45.0", 835 | ] 836 | 837 | [[package]] 838 | name = "rustix" 839 | version = "0.37.4" 840 | source = "registry+https://github.com/rust-lang/crates.io-index" 841 | checksum = "c348b5dc624ecee40108aa2922fed8bad89d7fcc2b9f8cb18f632898ac4a37f9" 842 | dependencies = [ 843 | "bitflags", 844 | "errno 0.3.0", 845 | "io-lifetimes", 846 | "libc", 847 | "linux-raw-sys 0.3.0", 848 | "windows-sys 0.45.0", 849 | ] 850 | 851 | [[package]] 852 | name = "rustversion" 853 | version = "1.0.11" 854 | source = "registry+https://github.com/rust-lang/crates.io-index" 855 | checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" 856 | 857 | [[package]] 858 | name = "rusty-fork" 859 | version = "0.3.0" 860 | source = "registry+https://github.com/rust-lang/crates.io-index" 861 | checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" 862 | dependencies = [ 863 | "fnv", 864 | "quick-error 1.2.3", 865 | "tempfile", 866 | "wait-timeout", 867 | ] 868 | 869 | [[package]] 870 | name = "semver" 871 | version = "0.11.0" 872 | source = "registry+https://github.com/rust-lang/crates.io-index" 873 | checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" 874 | dependencies = [ 875 | "semver-parser", 876 | ] 877 | 878 | [[package]] 879 | name = "semver-parser" 880 | version = "0.10.2" 881 | source = "registry+https://github.com/rust-lang/crates.io-index" 882 | checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" 883 | dependencies = [ 884 | "pest", 885 | ] 886 | 887 | [[package]] 888 | name = "serde" 889 | version = "1.0.152" 890 | source = "registry+https://github.com/rust-lang/crates.io-index" 891 | checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" 892 | dependencies = [ 893 | "serde_derive", 894 | ] 895 | 896 | [[package]] 897 | name = "serde_derive" 898 | version = "1.0.152" 899 | source = "registry+https://github.com/rust-lang/crates.io-index" 900 | checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" 901 | dependencies = [ 902 | "proc-macro2", 903 | "quote", 904 | "syn 1.0.107", 905 | ] 906 | 907 | [[package]] 908 | name = "shlex" 909 | version = "1.1.0" 910 | source = "registry+https://github.com/rust-lang/crates.io-index" 911 | checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" 912 | 913 | [[package]] 914 | name = "sparsevec" 915 | version = "0.2.0" 916 | source = "registry+https://github.com/rust-lang/crates.io-index" 917 | checksum = "35df5d2e580b29f3f7ec5b4ed49b0ab3acf7f3624122b3e823cafb9630f293b8" 918 | dependencies = [ 919 | "num-traits", 920 | "packedvec", 921 | "serde", 922 | "vob", 923 | ] 924 | 925 | [[package]] 926 | name = "ssa-comp" 927 | version = "0.1.0" 928 | dependencies = [ 929 | "cfgrammar", 930 | "clap 4.2.0", 931 | "lrlex", 932 | "lrpar", 933 | "parser_defs", 934 | "proptest", 935 | "z3", 936 | ] 937 | 938 | [[package]] 939 | name = "static_assertions" 940 | version = "1.1.0" 941 | source = "registry+https://github.com/rust-lang/crates.io-index" 942 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" 943 | 944 | [[package]] 945 | name = "strsim" 946 | version = "0.8.0" 947 | source = "registry+https://github.com/rust-lang/crates.io-index" 948 | checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" 949 | 950 | [[package]] 951 | name = "strsim" 952 | version = "0.10.0" 953 | source = "registry+https://github.com/rust-lang/crates.io-index" 954 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 955 | 956 | [[package]] 957 | name = "syn" 958 | version = "1.0.107" 959 | source = "registry+https://github.com/rust-lang/crates.io-index" 960 | checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" 961 | dependencies = [ 962 | "proc-macro2", 963 | "quote", 964 | "unicode-ident", 965 | ] 966 | 967 | [[package]] 968 | name = "syn" 969 | version = "2.0.11" 970 | source = "registry+https://github.com/rust-lang/crates.io-index" 971 | checksum = "21e3787bb71465627110e7d87ed4faaa36c1f61042ee67badb9e2ef173accc40" 972 | dependencies = [ 973 | "proc-macro2", 974 | "quote", 975 | "unicode-ident", 976 | ] 977 | 978 | [[package]] 979 | name = "tempfile" 980 | version = "3.4.0" 981 | source = "registry+https://github.com/rust-lang/crates.io-index" 982 | checksum = "af18f7ae1acd354b992402e9ec5864359d693cd8a79dcbef59f76891701c1e95" 983 | dependencies = [ 984 | "cfg-if", 985 | "fastrand", 986 | "redox_syscall", 987 | "rustix 0.36.8", 988 | "windows-sys 0.42.0", 989 | ] 990 | 991 | [[package]] 992 | name = "termcolor" 993 | version = "1.2.0" 994 | source = "registry+https://github.com/rust-lang/crates.io-index" 995 | checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" 996 | dependencies = [ 997 | "winapi-util", 998 | ] 999 | 1000 | [[package]] 1001 | name = "textwrap" 1002 | version = "0.11.0" 1003 | source = "registry+https://github.com/rust-lang/crates.io-index" 1004 | checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" 1005 | dependencies = [ 1006 | "unicode-width", 1007 | ] 1008 | 1009 | [[package]] 1010 | name = "thiserror" 1011 | version = "1.0.38" 1012 | source = "registry+https://github.com/rust-lang/crates.io-index" 1013 | checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" 1014 | dependencies = [ 1015 | "thiserror-impl", 1016 | ] 1017 | 1018 | [[package]] 1019 | name = "thiserror-impl" 1020 | version = "1.0.38" 1021 | source = "registry+https://github.com/rust-lang/crates.io-index" 1022 | checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" 1023 | dependencies = [ 1024 | "proc-macro2", 1025 | "quote", 1026 | "syn 1.0.107", 1027 | ] 1028 | 1029 | [[package]] 1030 | name = "time" 1031 | version = "0.3.17" 1032 | source = "registry+https://github.com/rust-lang/crates.io-index" 1033 | checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" 1034 | dependencies = [ 1035 | "itoa", 1036 | "serde", 1037 | "time-core", 1038 | "time-macros", 1039 | ] 1040 | 1041 | [[package]] 1042 | name = "time-core" 1043 | version = "0.1.0" 1044 | source = "registry+https://github.com/rust-lang/crates.io-index" 1045 | checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" 1046 | 1047 | [[package]] 1048 | name = "time-macros" 1049 | version = "0.2.6" 1050 | source = "registry+https://github.com/rust-lang/crates.io-index" 1051 | checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" 1052 | dependencies = [ 1053 | "time-core", 1054 | ] 1055 | 1056 | [[package]] 1057 | name = "ucd-trie" 1058 | version = "0.1.5" 1059 | source = "registry+https://github.com/rust-lang/crates.io-index" 1060 | checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" 1061 | 1062 | [[package]] 1063 | name = "unarray" 1064 | version = "0.1.4" 1065 | source = "registry+https://github.com/rust-lang/crates.io-index" 1066 | checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" 1067 | 1068 | [[package]] 1069 | name = "unicode-ident" 1070 | version = "1.0.6" 1071 | source = "registry+https://github.com/rust-lang/crates.io-index" 1072 | checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" 1073 | 1074 | [[package]] 1075 | name = "unicode-width" 1076 | version = "0.1.10" 1077 | source = "registry+https://github.com/rust-lang/crates.io-index" 1078 | checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" 1079 | 1080 | [[package]] 1081 | name = "utf8parse" 1082 | version = "0.2.1" 1083 | source = "registry+https://github.com/rust-lang/crates.io-index" 1084 | checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" 1085 | 1086 | [[package]] 1087 | name = "vec_map" 1088 | version = "0.8.2" 1089 | source = "registry+https://github.com/rust-lang/crates.io-index" 1090 | checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" 1091 | 1092 | [[package]] 1093 | name = "vergen" 1094 | version = "7.5.0" 1095 | source = "registry+https://github.com/rust-lang/crates.io-index" 1096 | checksum = "571b69f690c855821462709b6f41d42ceccc316fbd17b60bd06d06928cfe6a99" 1097 | dependencies = [ 1098 | "anyhow", 1099 | "cfg-if", 1100 | "enum-iterator", 1101 | "getset", 1102 | "rustversion", 1103 | "thiserror", 1104 | "time", 1105 | ] 1106 | 1107 | [[package]] 1108 | name = "version_check" 1109 | version = "0.9.4" 1110 | source = "registry+https://github.com/rust-lang/crates.io-index" 1111 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 1112 | 1113 | [[package]] 1114 | name = "vob" 1115 | version = "3.0.2" 1116 | source = "registry+https://github.com/rust-lang/crates.io-index" 1117 | checksum = "cbdb3eee5dd38a27129832bca4a3171888e699a6ac36de86547975466997986f" 1118 | dependencies = [ 1119 | "num-traits", 1120 | "rustc_version", 1121 | "serde", 1122 | ] 1123 | 1124 | [[package]] 1125 | name = "wait-timeout" 1126 | version = "0.2.0" 1127 | source = "registry+https://github.com/rust-lang/crates.io-index" 1128 | checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" 1129 | dependencies = [ 1130 | "libc", 1131 | ] 1132 | 1133 | [[package]] 1134 | name = "wasi" 1135 | version = "0.11.0+wasi-snapshot-preview1" 1136 | source = "registry+https://github.com/rust-lang/crates.io-index" 1137 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1138 | 1139 | [[package]] 1140 | name = "which" 1141 | version = "3.1.1" 1142 | source = "registry+https://github.com/rust-lang/crates.io-index" 1143 | checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724" 1144 | dependencies = [ 1145 | "libc", 1146 | ] 1147 | 1148 | [[package]] 1149 | name = "winapi" 1150 | version = "0.3.9" 1151 | source = "registry+https://github.com/rust-lang/crates.io-index" 1152 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1153 | dependencies = [ 1154 | "winapi-i686-pc-windows-gnu", 1155 | "winapi-x86_64-pc-windows-gnu", 1156 | ] 1157 | 1158 | [[package]] 1159 | name = "winapi-i686-pc-windows-gnu" 1160 | version = "0.4.0" 1161 | source = "registry+https://github.com/rust-lang/crates.io-index" 1162 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1163 | 1164 | [[package]] 1165 | name = "winapi-util" 1166 | version = "0.1.5" 1167 | source = "registry+https://github.com/rust-lang/crates.io-index" 1168 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" 1169 | dependencies = [ 1170 | "winapi", 1171 | ] 1172 | 1173 | [[package]] 1174 | name = "winapi-x86_64-pc-windows-gnu" 1175 | version = "0.4.0" 1176 | source = "registry+https://github.com/rust-lang/crates.io-index" 1177 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1178 | 1179 | [[package]] 1180 | name = "windows-sys" 1181 | version = "0.42.0" 1182 | source = "registry+https://github.com/rust-lang/crates.io-index" 1183 | checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" 1184 | dependencies = [ 1185 | "windows_aarch64_gnullvm", 1186 | "windows_aarch64_msvc", 1187 | "windows_i686_gnu", 1188 | "windows_i686_msvc", 1189 | "windows_x86_64_gnu", 1190 | "windows_x86_64_gnullvm", 1191 | "windows_x86_64_msvc", 1192 | ] 1193 | 1194 | [[package]] 1195 | name = "windows-sys" 1196 | version = "0.45.0" 1197 | source = "registry+https://github.com/rust-lang/crates.io-index" 1198 | checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" 1199 | dependencies = [ 1200 | "windows-targets", 1201 | ] 1202 | 1203 | [[package]] 1204 | name = "windows-targets" 1205 | version = "0.42.1" 1206 | source = "registry+https://github.com/rust-lang/crates.io-index" 1207 | checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" 1208 | dependencies = [ 1209 | "windows_aarch64_gnullvm", 1210 | "windows_aarch64_msvc", 1211 | "windows_i686_gnu", 1212 | "windows_i686_msvc", 1213 | "windows_x86_64_gnu", 1214 | "windows_x86_64_gnullvm", 1215 | "windows_x86_64_msvc", 1216 | ] 1217 | 1218 | [[package]] 1219 | name = "windows_aarch64_gnullvm" 1220 | version = "0.42.1" 1221 | source = "registry+https://github.com/rust-lang/crates.io-index" 1222 | checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" 1223 | 1224 | [[package]] 1225 | name = "windows_aarch64_msvc" 1226 | version = "0.42.1" 1227 | source = "registry+https://github.com/rust-lang/crates.io-index" 1228 | checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" 1229 | 1230 | [[package]] 1231 | name = "windows_i686_gnu" 1232 | version = "0.42.1" 1233 | source = "registry+https://github.com/rust-lang/crates.io-index" 1234 | checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" 1235 | 1236 | [[package]] 1237 | name = "windows_i686_msvc" 1238 | version = "0.42.1" 1239 | source = "registry+https://github.com/rust-lang/crates.io-index" 1240 | checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" 1241 | 1242 | [[package]] 1243 | name = "windows_x86_64_gnu" 1244 | version = "0.42.1" 1245 | source = "registry+https://github.com/rust-lang/crates.io-index" 1246 | checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" 1247 | 1248 | [[package]] 1249 | name = "windows_x86_64_gnullvm" 1250 | version = "0.42.1" 1251 | source = "registry+https://github.com/rust-lang/crates.io-index" 1252 | checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" 1253 | 1254 | [[package]] 1255 | name = "windows_x86_64_msvc" 1256 | version = "0.42.1" 1257 | source = "registry+https://github.com/rust-lang/crates.io-index" 1258 | checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" 1259 | 1260 | [[package]] 1261 | name = "z3" 1262 | version = "0.11.2" 1263 | source = "registry+https://github.com/rust-lang/crates.io-index" 1264 | checksum = "d25754b4bf4516a65d0e596ea9c1f0082224bdf20823a37fdd9111fa08d5bf48" 1265 | dependencies = [ 1266 | "lazy_static", 1267 | "log", 1268 | "z3-sys", 1269 | ] 1270 | 1271 | [[package]] 1272 | name = "z3-sys" 1273 | version = "0.7.1" 1274 | source = "registry+https://github.com/rust-lang/crates.io-index" 1275 | checksum = "1c82dcbc58be4bf1994c520066cb2bd6c3d36aed0fdc57244f34d277421986a6" 1276 | dependencies = [ 1277 | "bindgen", 1278 | "cmake", 1279 | ] 1280 | --------------------------------------------------------------------------------