diff --git a/Cargo.lock b/Cargo.lock index 9057ee9..6a78493 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,20 +1,11 @@ -[[package]] -name = "afl" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. [[package]] name = "aho-corasick" -version = "0.6.9" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -22,12 +13,17 @@ name = "ansi_term" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "arrayref" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "arrayvec" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -35,136 +31,156 @@ dependencies = [ [[package]] name = "ascii-canvas" -version = "1.0.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "atom" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "atty" -version = "0.2.11" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)", - "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "autocfg" -version = "0.1.2" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "backtrace" -version = "0.3.13" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace-sys" -version = "0.1.28" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "base64" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "bit-set" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bit-vec 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "bit-vec" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bitflags" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "blake2b_simd" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "block-buffer" -version = "0.7.0" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-padding 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "block-padding" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "byte-tools" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "byteorder" -version = "1.2.7" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "c2-chacha" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "cargo-husky" -version = "1.2.2-alpha.0" -source = "git+https://github.com/dflemstr/cargo-husky.git?branch=run-for-all#1048516a597ac7982e4ccb28d7f9602ed5307ab2" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cc" -version = "1.0.28" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.6" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "chrono" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "clap" -version = "2.32.0" +version = "2.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -174,227 +190,199 @@ name = "cloudabi" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "codespan" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "codespan-reporting" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "codespan 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "codespan 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "constant_time_eq" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "cranelift" -version = "0.26.0" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cranelift-frontend 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-frontend 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cranelift-bforest" -version = "0.26.0" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cranelift-codegen" -version = "0.26.0" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cranelift-bforest 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cranelift-codegen-meta 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-bforest 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen-meta 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cranelift-codegen-meta" -version = "0.26.0" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cranelift-entity" -version = "0.26.0" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cranelift-frontend" -version = "0.26.0" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cranelift-module" -version = "0.26.0" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cranelift-native" -version = "0.26.0" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)", "raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cranelift-simplejit" -version = "0.26.0" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cranelift-module 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-module 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-native 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)", "errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)", - "region 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "region 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam" -version = "0.4.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-deque 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-epoch 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-channel" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-deque" -version = "0.2.0" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-deque" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-epoch 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.3.1" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-epoch" -version = "0.5.2" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "crossbeam-epoch" -version = "0.6.1" +name = "crossbeam-queue" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-utils" -version = "0.2.2" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "crossbeam-utils" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "crossbeam-utils" -version = "0.6.3" +name = "ctor" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "derivative" -version = "1.0.2" +name = "derive-new" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -409,22 +397,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "digest" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "dirs" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "docopt" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -434,15 +431,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "either" -version = "1.5.0" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ena" -version = "0.10.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -457,14 +454,14 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -473,8 +470,8 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -483,7 +480,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -491,7 +488,7 @@ name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -500,10 +497,10 @@ name = "failure_derive" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -517,32 +514,10 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "fnv" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" +name = "fuchsia-cprng" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "gcc" version = "0.3.55" @@ -550,27 +525,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "generic-array" -version = "0.12.0" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "heck" -version = "0.3.1" +name = "getrandom" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "wasi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "hibitset" -version = "0.5.4" +name = "heck" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "atom 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -582,89 +558,76 @@ dependencies = [ ] [[package]] -name = "itertools" -version = "0.7.11" +name = "indexmap" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "itertools" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "itoa" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "lalrpop" -version = "0.16.2" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ascii-canvas 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "bit-set 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ascii-canvas 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "bit-set 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "docopt 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ena 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)", - "lalrpop-util 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)", + "docopt 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lalrpop-util 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", "petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "lalrpop-util" -version = "0.16.2" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lazy_static" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.47" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lock_api" -version = "0.1.5" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "log" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -672,53 +635,39 @@ name = "mach" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "memchr" -version = "2.1.2" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "memoffset" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "mopa" -version = "0.2.2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "new_debug_unreachable" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "nodrop" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "nonzero_signed" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "num-integer" -version = "0.1.39" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -726,87 +675,65 @@ name = "num-traits" version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "num_cpus" -version = "1.9.0" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "opaque-debug" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "ordermap" -version = "0.3.5" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "owning_ref" -version = "0.3.3" +name = "ordered-float" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "owning_ref" -version = "0.4.0" +name = "ordermap" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "parking_lot" -version = "0.5.5" +name = "output_vt100" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parking_lot" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot_core" -version = "0.2.14" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parking_lot_core" -version = "0.3.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -824,7 +751,7 @@ version = "0.7.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -835,6 +762,11 @@ dependencies = [ "siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ppv-lite86" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "precomputed-hash" version = "0.1.1" @@ -842,31 +774,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "pretty_assertions" -version = "0.5.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ctor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "pretty_env_logger" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "proc-macro2" -version = "0.4.25" +version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "proc-macro2" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quick-error" version = "1.2.2" @@ -879,51 +821,49 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "quote" -version = "0.6.10" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rand" -version = "0.4.5" +name = "quote" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.5.5" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.6.4" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_pcg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -931,29 +871,54 @@ name = "rand_chacha" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_chacha" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.2.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.3.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rand_core" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand_hc" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -961,68 +926,66 @@ name = "rand_isaac" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rand_os" -version = "0.1.1" +name = "rand_jitter" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rand_pcg" -version = "0.1.1" +name = "rand_os" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rand_xorshift" -version = "0.1.1" +name = "rand_pcg" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "raw-cpuid" -version = "6.1.0" +name = "rand_pcg" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rayon" -version = "1.0.3" +name = "rand_xorshift" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rayon-core" -version = "1.4.1" +name = "raw-cpuid" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1030,228 +993,193 @@ name = "rdrand" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "redox_syscall" -version = "0.1.50" +version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "redox_termios" -version = "0.1.1" +name = "redox_users" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.6.4" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "region" -version = "1.0.0" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "mach 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rustc-demangle" -version = "0.1.13" +name = "relative-path" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "rustc_version" -version = "0.2.3" +name = "rust-argon2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2b_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "ryu" -version = "0.2.7" +name = "rustc-demangle" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "same-file" -version = "1.0.4" +name = "rustc-hash" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "scopeguard" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "semver" -version = "0.9.0" +name = "rustc_version" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "serde" -version = "1.0.84" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "serde_derive" -version = "1.0.84" +name = "ryu" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "serde_json" -version = "1.0.36" +name = "salsa" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "derive-new 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "salsa-macros 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "sha2" -version = "0.8.0" +name = "salsa-macros" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "shred" -version = "0.7.1" +name = "same-file" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "mopa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "shred-derive" -version = "0.5.1" +name = "scopeguard" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "shrev" -version = "1.0.1" +name = "semver" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "derivative 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "siphasher" -version = "0.2.3" +name = "semver-parser" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "smallvec" -version = "0.6.7" +name = "serde" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "specs" -version = "0.14.3" +name = "serde_derive" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "derivative 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "hibitset 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mopa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "nonzero_signed 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "shred 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "shred-derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "shrev 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tuple_utils 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "specs-derive" -version = "0.4.0" +name = "serde_json" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "specs-visitor" -version = "0.3.0" +name = "sha2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "specs 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)", + "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "specs-visitor-derive" -version = "0.3.0" -dependencies = [ - "proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "specs 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)", - "specs-visitor 0.3.0", - "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", -] +name = "siphasher" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "stable_deref_trait" -version = "1.1.1" +name = "smallvec" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1259,11 +1187,11 @@ name = "string_cache" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1275,8 +1203,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1287,27 +1215,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "strsim" -version = "0.7.0" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "strsim" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "structopt" -version = "0.2.14" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt-derive 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "structopt-derive" -version = "0.2.14" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1322,14 +1255,24 @@ dependencies = [ [[package]] name = "syn" -version = "0.15.26" +version = "0.15.44" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "syn" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "synom" version = "0.11.3" @@ -1340,55 +1283,46 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "target-lexicon" -version = "0.2.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "term" -version = "0.4.6" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "termcolor" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "termion" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "textwrap" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1399,7 +1333,7 @@ name = "thread_local" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1407,70 +1341,51 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tin" version = "0.3.0" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo-husky 1.2.2-alpha.0 (git+https://github.com/dflemstr/cargo-husky.git?branch=run-for-all)", - "codespan 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "codespan-reporting 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cranelift 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cranelift-module 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cranelift-simplejit 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo-husky 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "codespan 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "codespan-reporting 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-module 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-native 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-simplejit 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)", "dot 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "enum-primitive-derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lalrpop 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lalrpop-util 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "specs 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)", - "specs-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "specs-visitor 0.3.0", - "specs-visitor-derive 0.3.0", - "structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tin-fuzz-target" -version = "0.1.0" -dependencies = [ - "afl 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tin 0.3.0", + "lalrpop 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lalrpop-util 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "salsa 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "tuple_utils" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "typenum" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "ucd-util" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "unicode-segmentation" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1489,16 +1404,8 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "unreachable" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "utf8-ranges" -version = "1.0.2" +name = "unicode-xid" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1506,45 +1413,30 @@ name = "vec_map" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "version_check" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "walkdir" -version = "2.2.7" +version = "2.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "winapi" -version = "0.2.8" +name = "wasi" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -1552,10 +1444,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi-util" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1565,201 +1457,186 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wincolor" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "xdg" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [metadata] -"checksum afl 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf91d62aed05ac9b289ba6c5412e7ac61404254c20ed040ecf8448902834c3c" -"checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" +"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" -"checksum ascii-canvas 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b385d69402821a1c254533a011a312531cbcc0e3e24f19bbb4747a5a2daf37e2" -"checksum atom 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3c86699c3f02778ec07158376991c8f783dd1f2f95c579ffaf0738dc984b2fe2" -"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" -"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" -"checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5" -"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" -"checksum bit-set 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6f1efcc46c18245a69c38fcc5cc650f16d3a59d034f3106e9ed63748f695730a" -"checksum bit-vec 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4440d5cb623bb7390ae27fec0bb6c61111969860f8e3ae198bfa0663645e67cf" -"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" -"checksum block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d" -"checksum block-padding 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc4358306e344bf9775d0197fd00d2603e5afb0771bb353538630f022068ea3" -"checksum byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "980479e6fde23246dfb54d47580d66b4e99202e7579c5eaa9fe10ecb5ebd2182" -"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" -"checksum cargo-husky 1.2.2-alpha.0 (git+https://github.com/dflemstr/cargo-husky.git?branch=run-for-all)" = "" -"checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749" -"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" -"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" -"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" +"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" +"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" +"checksum ascii-canvas 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff8eb72df928aafb99fe5d37b383f2fe25bd2a765e3e5f7c365916b6f2463a29" +"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" +"checksum autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "22130e92352b948e7e82a49cdb0aa94f2211761117f29e052dd397c1ac33542b" +"checksum backtrace 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)" = "b5164d292487f037ece34ec0de2fcede2faa162f085dd96d2385ab81b12765ba" +"checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" +"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" +"checksum bit-set 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e84c238982c4b1e1ee668d136c510c67a13465279c0cb367ea6baf6310620a80" +"checksum bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb" +"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" +"checksum blake2b_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "461f4b879a8eb70c1debf7d0788a9a5ff15f1ea9d25925fea264ef4258bed6b2" +"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +"checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" +"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" +"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" +"checksum cargo-husky 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee1f6a41bcc9d0aeff394d58275742a53beb62da685d8046c4756a8e4a507bbf" +"checksum cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "b548a4ee81fccb95919d4e22cfea83c7693ebfd78f0495493178db20b3139da7" +"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" +"checksum chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "77d81f58b7301084de3b958691458a53c3f7e0b1d702f77e550b6a88e3a88abe" +"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum codespan 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "172b4fa8eec616659e19bdd41d33a3c29cd6913b9b747054c0429865c1f210ec" -"checksum codespan-reporting 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b329932b380f719f861e2844dcafea53e31821a53b76a1218364d3433cb472" -"checksum cranelift 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9927ebe8175752af7db402c19664df375df4ad254f1f0ac292a30b3d700ffd22" -"checksum cranelift-bforest 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "40f8ff24e9a6c89b8a846b14df9a34d2cac17cea7bdb5c81ed6b4744ee0e38bf" -"checksum cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "42f5b809bd885c368e01aeec8fe04f21dcb07569834b907d75b4a7bed8d067eb" -"checksum cranelift-codegen-meta 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "014c23ed3ebdc8377d41540af638245207dd169f421df042dfccc867465734ed" -"checksum cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4df40e26c0cf7b4d86919cb995bb412ee3001cc18e4f3c83a903f30b7007d8b" -"checksum cranelift-frontend 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "789907218eeebebcea8122c2053d71affac91c96ce72cea35ebfdbbf547e82af" -"checksum cranelift-module 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e78b62689c0615e242fbdd1b61a097a7b96da09b3e653f64f0052062da4ee" -"checksum cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "474bee81d620a473bf43411a3d6f10ffbf7965141dc5e5b76d8d2151dde3285d" -"checksum cranelift-simplejit 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc9176eff6c1730eb193e10fac5c2ae5d04564ff21d3916d72eb9680ced977b5" -"checksum crossbeam 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d7408247b1b87f480890f28b670c5f8d9a8a4274833433fe74dc0dfd46d33650" -"checksum crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7b85741761b7f160bc5e7e0c14986ef685b7f8bf9b7ad081c60c604bb4649827" -"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" -"checksum crossbeam-deque 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7792c4a9b5a4222f654e3728a3dd945aacc24d2c3a1a096ed265d80e4929cb9a" -"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" -"checksum crossbeam-epoch 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30fecfcac6abfef8771151f8be4abc9e4edc112c2bcb233314cafde2680536e9" -"checksum crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2449aaa4ec7ef96e5fb24db16024b935df718e9ae1cec0a1e68feeca2efca7b8" -"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" -"checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015" -"checksum crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "41ee4864f4797060e52044376f7d107429ce1fb43460021b126424b7180ee21a" -"checksum derivative 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6073e9676dbebdddeabaeb63e3b7cefd23c86f5c41d381ee1237cc77b1079898" +"checksum codespan 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "03ed0fdf823b4a01c3b6a3e086b4d0a2def8d3cb75b110ec5c988fe2790860a9" +"checksum codespan-reporting 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2ae73f6c4b3803dc2a0fe08ed1ce40e8f3f94ecc8394a82e0696bbc86d4e4fc3" +"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" +"checksum cranelift 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0773a83655dd8abf9a0bcfa139eddb083dd101bd6b2fe7feb51b11c73883ba3" +"checksum cranelift-bforest 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4775737968254a3616d260c08249c9e01187b48b01fd0ef5df2edfb24fe0923" +"checksum cranelift-codegen 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)" = "86df46c579467ac304b60eed476d73a5369e356ef438753dd559b23fca9876dc" +"checksum cranelift-codegen-meta 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e910e577db63abe6d7ff26db9c7856baa99040f517c7fdbf65b8d44464fb9adb" +"checksum cranelift-entity 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71db53666f5819b71e672cfba8e669e50d81e3b741188829bab9d7348c35a508" +"checksum cranelift-frontend 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9ab1585400abfee0d2a70bb28544cbcbffb47c51071f56b553d62c702febf858" +"checksum cranelift-module 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ea12b34e62a4e066158d226b7a5efb0a3ab39676da4406731faa6813a974c98" +"checksum cranelift-native 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7233c2e94db0e70969da23a87c61659322004ad35f8dc3dd4d7b0330b33ea993" +"checksum cranelift-simplejit 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)" = "884b7bc4b34be33290579d9d5c2583eb36718304f7bacac0d347650e89d6ab94" +"checksum crossbeam 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2d818a4990769aac0c7ff1360e233ef3a41adcb009ebb2036bf6915eb0f6b23c" +"checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" +"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" +"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" +"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" +"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" +"checksum ctor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5b6b2f4752cc29efbfd03474c532ce8f916f2d44ec5bb8c21f93bc76e5365528" +"checksum derive-new 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "71f31892cd5c62e414316f2963c5689242c43d8e7bbcaaeca97e5e28c95d91d9" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" -"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" -"checksum docopt 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "db2906c2579b5b7207fc1e328796a9a8835dc44e22dbe8e460b1d636f9a7b225" +"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +"checksum dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" +"checksum docopt 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f525a586d310c87df72ebcd98009e57f1cc030c8c268305287a476beb653969" "checksum dot 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a74b6c4d4a1cff5f454164363c16b72fa12463ca6b31f4b5f2035a65fa3d5906" -"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" -"checksum ena 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "25b4e5febb25f08c49f1b07dc33a182729a6b21edfb562b5aef95f78e0dbe5bb" +"checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" +"checksum ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dc01d68e08ca384955a3aeba9217102ca1aa85b6e168639bf27739f1d749d87" "checksum enum-primitive-derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b90e520ec62c1864c8c78d637acbfe8baf5f63240f2fb8165b8325c07812dd" -"checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" +"checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" "checksum errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e" "checksum errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" -"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" -"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" -"checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" +"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" +"checksum getrandom 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "6171a6cc63fbabbe27c2b5ee268e8b7fe5dc1eb0dd2dfad537c1dfed6f69117e" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" -"checksum hibitset 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6527bc88f32e0d3926c7572874b2bf17a19b36978aacd0aacf75f7d27a5992d0" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" -"checksum itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0d47946d458e94a1b7bcabbf6521ea7c037062c81f534615abcad76e84d4970d" +"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" "checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" -"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" -"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum lalrpop 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02888049e197dff0c5c9fd503bd2458ea373c5e845c2f5460db1f9e43050d55e" -"checksum lalrpop-util 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)" = "488da0d45c65af229321623c62660627d02b0e7fbc768a4c3fcd121815404ef1" -"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" -"checksum libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)" = "48450664a984b25d5b479554c29cc04e3150c97aa4c01da5604a2d4ed9151476" -"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" -"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" +"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" +"checksum lalrpop 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a3d111d79a3b76457aa1bcc699a736b6c623d14da0ec75737c01edb657469aef" +"checksum lalrpop-util 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6ab5dfdd35d987c6d328e371764cb6e4b6c63220db9364c291aa14d6fe50099a" +"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" +"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" +"checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" +"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum mach 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "86dd2487cdfea56def77b88438a2c915fb45113c5319bfe7e14306ca4cd0b0e1" -"checksum memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "db4c41318937f6e76648f42826b1d9ade5c09cafb5aef7e351240a70f39206e9" -"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" -"checksum mopa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a785740271256c230f57462d3b83e52f998433a7062fc18f96d5999474a9f915" -"checksum new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4" +"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" +"checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" +"checksum new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f40f005c60db6e03bae699e414c58bf9aa7ea02a2d0b9bfbcf19286cc4c82b30" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" -"checksum nonzero_signed 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d9813c459ba38abf9c40eecc8d59738eb7ebcfc45a857030967372dcb83e18de" -"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" +"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" "checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" -"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" -"checksum num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5a69d464bdc213aaaff628444e99578ede64e9c854025aa43b9796530afa9238" -"checksum opaque-debug 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "51ecbcb821e1bd256d456fe858aaa7f380b63863eab2eb86eee1bd9f33dd6682" +"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" +"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" +"checksum ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "18869315e81473c951eb56ad5558bbc56978562d3ecfb87abb7a1e944cea4518" "checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063" -"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" -"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" -"checksum parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d05f1349491390b1730afba60bb20d55761bef489a954546b58b4b34e1e2ac" -"checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" -"checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa" -"checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" +"checksum output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" +"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" +"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" "checksum petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f" "checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" "checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" +"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" -"checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6" -"checksum pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df8b3f4e0475def7d9c2e5de8e5a1306949849761e107b360d03e98eafaffd61" -"checksum proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)" = "d3797b7142c9aa74954e351fc089bbee7958cebbff6bf2815e7ffff0b19f547d" +"checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" +"checksum pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "717ee476b1690853d222af4634056d830b5197ffd747726a9a1eee6da9f49074" +"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +"checksum proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c5c2380ae88876faae57698be9e9775e3544decad214599c3a6266cca6ac802" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" -"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" -"checksum rand 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "dee497e66d8d76bf08ce20c8d36e16f93749ab0bf89975b4f8ae5cee660c2da2" -"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" -"checksum rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3906503e80ac6cbcacb2c2973fa8e473f24d7e2747c8c92bb230c2441cad96b5" +"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" +"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +"checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -"checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" -"checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" +"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" +"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" +"checksum rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "615e683324e75af5d43d8f7a39ffe3ee4a9dc42c5c701167a71dc59c3a493aca" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46fbd5550acf75b0c2730f5dd1873751daf9beb8f11b44027778fae50d7feca" -"checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" +"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" +"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +"checksum rand_pcg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e196346cbbc5c70c77e7b4926147ee8e383a38ee4d15d58a08098b169e492b6" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "30a9d219c32c9132f7be513c18be77c9881c7107d2ab5569d205a6a0f0e6dc7d" -"checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473" -"checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)" = "52ee9a534dc1301776eff45b4fa92d2c39b1d8c3d3357e6eb593e0d795506fc2" -"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f" -"checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1" -"checksum region 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cff177f64744f6f2a2054d231279383e59b0857b4d58dc2e8881e60b58aec8e5" -"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" +"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" +"checksum redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecedbca3bf205f8d8f5c2b44d83cd0690e39ee84b951ed649e9f1841132b66d" +"checksum regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88c3d9193984285d544df4a30c23a4e62ead42edf70a4452ceb76dac1ce05c26" +"checksum regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b143cceb2ca5e56d5671988ef8b15615733e7ee16cd348e064333b251b89343f" +"checksum region 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "448e868c6e4cfddfa49b6a72c95906c04e8547465e9536575b95c70a4044f856" +"checksum relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7790c7f1cc73d831d28dc5a7deb316a006e7848e6a7f467cdb10a0a9e0fb1c" +"checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" +"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" +"checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" -"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" -"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" +"checksum salsa 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3265a2a9bbd384bd2a9f9511c2c18fb41f62c412516052e8934517dc8ff64f1" +"checksum salsa-macros 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "377ce29c5660dcc5c3f66660a7e49940b8328e3d940255ef9d4c2be1f7b474a9" +"checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" +"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)" = "0e732ed5a5592c17d961555e3b552985baf98d50ce418b7b655f31f6ba7eb1b7" -"checksum serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d6115a3ca25c224e409185325afc16a0d5aaaabc15c42b09587d6f1ba39a5b" -"checksum serde_json 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)" = "574378d957d6dcdf1bbb5d562a15cbd5e644159432f84634b94e485267abbcc7" +"checksum serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "fec2851eb56d010dc9a21b89ca53ee75e6528bab60c11e89d38390904982da9f" +"checksum serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "cb4dc18c61206b08dc98216c98faa0232f4337e1e1b8574551d5bad29ea1b425" +"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" -"checksum shred 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c75ec29e8d2959ad96a1087fe4cadb926c6fc17cbae9812314fa8efe720aa2a" -"checksum shred-derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fcf34e5e5302d3024aba7afc291f6d1ca7573ed035d3c0796976ba3f10691a1" -"checksum shrev 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ec60ed6f60a4b3cdc2ceacf57215db3408fbd8990f66a38686a31558cd9da482" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" -"checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db" -"checksum specs 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)" = "de65613ada4338aa7ba71eca60eca24c60483433eec0077bc4f33cfc31f4bdf0" -"checksum specs-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a63549fa0d4a6f76e99e6634c328f25d0c9fa8ad6f8498aef74f6c35c0b269e5" -"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" +"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" "checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423" "checksum string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eea1eee654ef80933142157fdad9dd8bc43cf7c74e999e369263496f04ff4da" "checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc" -"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" -"checksum structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "670ad348dc73012fcf78c71f06f9d942232cdd4c859d4b6975e27836c3efc0c3" -"checksum structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ef98172b1a00b0bec738508d3726540edcbd186d50dfd326f2b1febbb3559f04" +"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +"checksum strsim 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "032c03039aae92b350aad2e3779c352e104d919cb192ba2fabbd7b831ce4f0f6" +"checksum structopt 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "16c2cdbf9cc375f15d1b4141bc48aeef444806655cd0e904207edc8d68d86ed7" +"checksum structopt-derive 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "53010261a84b37689f9ed7d395165029f9cc7abb9f56bbfe86bee2597ed25107" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" -"checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" +"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +"checksum syn 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "158521e6f544e7e3dcfc370ac180794aa38cb34a1b1e07609376d4adcf429b93" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" -"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" -"checksum target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4af5e2227f0b887d591d3724b796a96eff04226104d872f5b3883fcd427d64b9" -"checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" -"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" -"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" -"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" +"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" +"checksum target-lexicon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b0ab4982b8945c35cc1c46a83a9094c414f6828a099ce5dcaa8ee2b04642dcb" +"checksum term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "edd106a334b7657c10b7c540a0106114feadeb4dc314513e97df481d5d966f42" +"checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" +"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" -"checksum tuple_utils 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cbfecd7bb8f0a3e96b3b31c46af2677a55a588767c0091f484601424fcb20e7e" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" -"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" -"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" +"checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" -"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" +"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" -"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" -"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" -"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" +"checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" +"checksum wasi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fd5442abcac6525a045cc8c795aedb60da7a2e5e89c7bf18a0d5357849bb23c7" +"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab" +"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -"checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" -"checksum xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57" +"checksum wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96f5016b18804d24db43cebf3c77269e7569b8954a8464501c216cc5e070eaa9" diff --git a/Cargo.toml b/Cargo.toml index 9b4734d..963bb27 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,40 +8,39 @@ repository = "https://github.com/dflemstr/tin" edition = "2018" [build-dependencies] -lalrpop = "0.16.2" +lalrpop = "0.17.1" failure = "0.1.5" -regex = "1.1.0" -walkdir = "2.2.7" +regex = "1.2.1" +walkdir = "2.2.9" [dependencies] -cranelift = "0.26.0" -cranelift-module = "0.26.0" -cranelift-simplejit = "0.26.0" +cranelift = "0.38.0" +cranelift-module = "0.38.0" +cranelift-simplejit = "0.38.0" dot = "0.1.4" -env_logger = "0.6.0" +env_logger = "0.6.2" failure = "0.1.5" -lalrpop-util = "0.16.2" -log = "0.4.6" -regex = "1.1.0" -specs = { version = "0.14.3", default_features = false } -specs-derive = "0.4.0" -specs-visitor-derive = { version = "0.3.0", path = "specs-visitor-derive" } -specs-visitor = { version = "0.3.0", path = "specs-visitor", default_features = false } -pretty_env_logger = "0.3.0" -structopt = "0.2.14" -lazy_static = "1.2.0" -byteorder = "1.2.7" -rayon = { version = "1.0.3", optional = true } +lalrpop-util = "0.17.1" +log = "0.4.8" +regex = "1.2.1" +pretty_env_logger = "0.3.1" +structopt = "0.2.18" +lazy_static = "1.3.0" +byteorder = "1.3.2" itertools = "0.8.0" -codespan = "0.2.0" -codespan-reporting = "0.2.0" +codespan = "0.3.0" +codespan-reporting = "0.3.0" enum-primitive-derive = "0.1.2" -num-traits = "0.2.6" +num-traits = "0.2.8" +salsa = "0.13.0" +relative-path = "0.4.0" +ordered-float = "1.0.2" +cranelift-native = "0.38.0" [features] default = ["parallel"] -nightly = ["specs/nightly"] -parallel = ["rayon", "specs/parallel", "specs-visitor/parallel"] +nightly = [] +parallel = [] test-render-graphs = [] [profile.release] @@ -49,13 +48,12 @@ debug = true lto = true codegen-units = 1 -[workspace] -members = ["specs-visitor", "specs-visitor-derive", "tin-fuzz-target"] +#[workspace] +#members = ["syntax"] [dev-dependencies] -pretty_assertions = "0.5.1" +pretty_assertions = "0.6.1" [dev-dependencies.cargo-husky] -git = "https://github.com/dflemstr/cargo-husky.git" -branch = "run-for-all" +version = "1.4.0" features = ["prepush-hook", "precommit-hook", "run-for-all", "run-cargo-test", "run-cargo-check", "run-cargo-clippy", "run-cargo-fmt"] diff --git a/build.rs b/build.rs index 0725f23..aedba6d 100644 --- a/build.rs +++ b/build.rs @@ -5,7 +5,7 @@ use std::path; fn main() -> Result<(), failure::Error> { use std::io::Write; - println!("cargo:rerun-if-changed=src/parser/tin.lalrpop"); + println!("cargo:rerun-if-changed=src/syntax/parser/grammar.lalrpop"); lalrpop::process_root().unwrap(); let out_dir_str = env::var_os("OUT_DIR").unwrap(); diff --git a/specs-visitor-derive/Cargo.toml b/specs-visitor-derive/Cargo.toml deleted file mode 100644 index 3010a17..0000000 --- a/specs-visitor-derive/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "specs-visitor-derive" -description = "A procedural macro for deriving traits in specs-derive." -license = "MIT" -version = "0.3.0" -authors = ["David Flemström "] -repository = "https://github.com/dflemstr/tin" -edition = "2018" - -[lib] -proc-macro = true - -[dependencies] -synstructure = "0.10.1" -quote = "0.6.10" -proc-macro2 = "0.4.25" - -[dev-dependencies] -specs = "0.14.3" -specs-visitor = { version = "0.3.0", path = "../specs-visitor" } diff --git a/specs-visitor-derive/release.toml b/specs-visitor-derive/release.toml deleted file mode 100644 index 0533e2d..0000000 --- a/specs-visitor-derive/release.toml +++ /dev/null @@ -1 +0,0 @@ -no-dev-version = true diff --git a/specs-visitor-derive/src/lib.rs b/specs-visitor-derive/src/lib.rs deleted file mode 100644 index 2e3832e..0000000 --- a/specs-visitor-derive/src/lib.rs +++ /dev/null @@ -1,78 +0,0 @@ -//! Procedural macros for deriving specs entity visitors. -//! -//! These visitors can be used to implement generic transformations of ECS graphs that compile down -//! to very effective code. -//! -//! See the [`specs-visitor`](https://crates.io/crates/specs-visitor) crate for API documentation -//! for the actual types derived by this crate. -#![deny(nonstandard_style, warnings, unused)] -#![deny( - missing_debug_implementations, - missing_copy_implementations, - trivial_casts, - trivial_numeric_casts, - unstable_features, - unused_import_braces, - unused_qualifications -)] -#![cfg_attr(feature = "cargo-clippy", deny(clippy::all, clippy::pedantic))] -#![recursion_limit = "128"] - -#[macro_use] -extern crate synstructure; -#[macro_use] -extern crate quote; - -#[cfg(test)] -mod tests; - -fn visit_entities_derive(mut s: synstructure::Structure) -> proc_macro2::TokenStream { - let accept_body = s.each(|bi| { - quote! { - ::specs_visitor::VisitEntities::accept(#bi, visitor); - } - }); - - s.add_bounds(synstructure::AddBounds::Generics); - - s.gen_impl(quote! { - gen impl ::specs_visitor::VisitEntities for @Self { - fn accept(&self, visitor: &V) - where - V: ::specs_visitor::EntityVisitor, - { - match *self { - #accept_body - } - } - } - }) -} - -fn visit_entities_mut_derive(mut s: synstructure::Structure) -> proc_macro2::TokenStream { - s.bind_with(|_| synstructure::BindStyle::RefMut); - - let accept_mut_body = s.each(|bi| { - quote! { - ::specs_visitor::VisitEntitiesMut::accept_mut(#bi, visitor); - } - }); - - s.add_bounds(synstructure::AddBounds::Generics); - - s.gen_impl(quote! { - gen impl ::specs_visitor::VisitEntitiesMut for @Self { - fn accept_mut(&mut self, visitor: &V) - where - V: ::specs_visitor::EntityVisitorMut, - { - match *self { - #accept_mut_body - } - } - } - }) -} - -decl_derive!([VisitEntities] => visit_entities_derive); -decl_derive!([VisitEntitiesMut] => visit_entities_mut_derive); diff --git a/specs-visitor-derive/src/tests.rs b/specs-visitor-derive/src/tests.rs deleted file mode 100644 index 992bf54..0000000 --- a/specs-visitor-derive/src/tests.rs +++ /dev/null @@ -1,130 +0,0 @@ -use specs; - -use super::visit_entities_derive; -use super::visit_entities_mut_derive; - -#[test] -fn simple() { - test_derive! { - visit_entities_derive { - struct Foo { - entity: specs::Entity, - } - } - expands to { - #[allow(non_upper_case_globals)] - const _DERIVE_specs_visitor_VisitEntities_FOR_Foo: () = { - impl ::specs_visitor::VisitEntities for Foo { - fn accept(&self, visitor: &V) - where - V: ::specs_visitor::EntityVisitor, - { - match *self { - Foo { - entity: ref __binding_0, - } => {{ - ::specs_visitor::VisitEntities::accept(__binding_0, visitor); - }} - } - } - } - }; - } - } -} - -#[test] -fn simple_mut() { - test_derive! { - visit_entities_mut_derive { - struct Foo { - entity: specs::Entity, - } - } - expands to { - #[allow(non_upper_case_globals)] - const _DERIVE_specs_visitor_VisitEntitiesMut_FOR_Foo: () = { - impl ::specs_visitor::VisitEntitiesMut for Foo { - fn accept_mut(&mut self, visitor: &V) - where - V: ::specs_visitor::EntityVisitorMut, - { - match *self { - Foo { - entity: ref mut __binding_0, - } => {{ - ::specs_visitor::VisitEntitiesMut::accept_mut(__binding_0, visitor); - }} - } - } - } - }; - } - } -} - -#[test] -fn generic() { - test_derive! { - visit_entities_derive { - struct Foo { - entity_stuff: T, - } - } - expands to { - #[allow(non_upper_case_globals)] - const _DERIVE_specs_visitor_VisitEntities_FOR_Foo: () = { - impl ::specs_visitor::VisitEntities for Foo - where - T: ::specs_visitor::VisitEntities - { - fn accept(&self, visitor: &V) - where - V: ::specs_visitor::EntityVisitor, - { - match *self { - Foo { - entity_stuff: ref __binding_0, - } => {{ - ::specs_visitor::VisitEntities::accept(__binding_0, visitor); - }} - } - } - } - }; - } - } -} - -#[test] -fn generic_mut() { - test_derive! { - visit_entities_mut_derive { - struct Foo { - entity_stuff: T, - } - } - expands to { - #[allow(non_upper_case_globals)] - const _DERIVE_specs_visitor_VisitEntitiesMut_FOR_Foo: () = { - impl ::specs_visitor::VisitEntitiesMut for Foo - where - T: ::specs_visitor::VisitEntitiesMut - { - fn accept_mut(&mut self, visitor: &V) - where - V: ::specs_visitor::EntityVisitorMut, - { - match *self { - Foo { - entity_stuff: ref mut __binding_0, - } => {{ - ::specs_visitor::VisitEntitiesMut::accept_mut(__binding_0, visitor); - }} - } - } - } - }; - } - } -} diff --git a/specs-visitor/Cargo.toml b/specs-visitor/Cargo.toml deleted file mode 100644 index 3c45fac..0000000 --- a/specs-visitor/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "specs-visitor" -description = "Utilities for visiting entities in an ECS that is using the specs library." -license = "MIT" -version = "0.3.0" -authors = ["David Flemström "] -repository = "https://github.com/dflemstr/tin" -edition = "2018" - -[dependencies] -specs = { version = "0.14.3", default_features = false } -rayon = { version = "1.0.3", optional = true } - -[features] -default = ["parallel"] -parallel = ["rayon", "specs/parallel"] -test-render-graphs = [] diff --git a/specs-visitor/release.toml b/specs-visitor/release.toml deleted file mode 100644 index 0533e2d..0000000 --- a/specs-visitor/release.toml +++ /dev/null @@ -1 +0,0 @@ -no-dev-version = true diff --git a/specs-visitor/src/lib.rs b/specs-visitor/src/lib.rs deleted file mode 100644 index 51cc093..0000000 --- a/specs-visitor/src/lib.rs +++ /dev/null @@ -1,284 +0,0 @@ -//! Utilities for visiting specs components and resources very efficiently. -//! -//! This can be used to implement generic transformations of ECS graphs that compile down to very -//! effective code. -//! -//! Use the [`specs-visitor-derive`](https://crates.io/crates/specs-visitor-derive) crate to -//! automatically derive the traits in this crate. -#![deny(nonstandard_style, warnings, unused)] -#![deny( - missing_docs, - missing_debug_implementations, - missing_copy_implementations, - trivial_casts, - trivial_numeric_casts, - unstable_features, - unused_import_braces, - unused_qualifications -)] -#![cfg_attr(feature = "cargo-clippy", deny(clippy::all, clippy::pedantic))] - -use std::collections; -use std::hash; -use std::sync; - -/// Support for generically visiting all `specs` entities of a type with a -/// visitor. -/// -/// This trait can be derived automatically with `#[derive(VisitEntities)]` using the -/// [`specs-visitor-derive`](https://crates.io/crates/specs-visitor-derive) crate. -pub trait VisitEntities { - /// Accepts the given visitor. - /// - /// The visitor's `visit_entity` method will be called for every entity contained within this - /// type. The visitor could potentially be called in parallel. - fn accept(&self, visitor: &V) - where - V: EntityVisitor; -} - -/// Support for generically mutably visiting all `specs` entities of a type with a -/// visitor. -/// -/// This trait can be derived automatically with `#[derive(VisitEntitiesMut)]` using the -/// [`specs-visitor-derive`](https://crates.io/crates/specs-visitor-derive) crate. -pub trait VisitEntitiesMut { - /// Accepts the given visitor. - /// - /// The visitor's `visit_entity_mut` method will be called for every entity contained within - /// this type. This gives the visitor mutable references to each entity, allowing them to be - /// changed. Note that the visitor itself has a shared borrow instead of a mutable borrow, - /// because it might potentially be called in parallel. - fn accept_mut(&mut self, visitor: &V) - where - V: EntityVisitorMut; -} - -/// A visitor for visiting entities in a read-only fashion. -/// -/// Types implementing this trait are compatible with the `accept` method on the `VisitEntities` -/// trait. -pub trait EntityVisitor: Send + Sync { - /// Allows the visitor to visit the specified entity. - /// - /// This method could potentially be called in parallel. - fn visit_entity(&self, entity: specs::Entity); -} - -/// A visitor for visiting entities mutably. -/// -/// Types implementing this trait are compatible with the `accept_mut` method on the -/// `VisitEntitiesMut` trait. -pub trait EntityVisitorMut: Send + Sync { - /// Allows the visitor to visit the specified entity mutably. - /// - /// This method could potentially be called in parallel. - fn visit_entity_mut(&self, entity: &mut specs::Entity); -} - -#[cfg(feature = "parallel")] -fn for_each<'a, A, I, F>(iter: &'a I, action: F) -where - A: 'a + Send + Sync, - I: rayon::iter::IntoParallelRefIterator<'a, Item = A>, - F: Fn(A) + Send + Sync, -{ - use rayon::iter::ParallelIterator; - iter.par_iter().for_each(action) -} - -#[cfg(feature = "parallel")] -fn for_each_mut<'a, A, I, F>(iter: &'a mut I, action: F) -where - A: 'a + Send + Sync, - I: rayon::iter::IntoParallelRefMutIterator<'a, Item = A>, - F: Fn(A) + Send + Sync, -{ - use rayon::iter::ParallelIterator; - iter.par_iter_mut().for_each(action) -} - -#[cfg(not(feature = "parallel"))] -fn for_each(iter: I, action: F) -where - I: IntoIterator, - F: FnMut(A), -{ - iter.into_iter().for_each(action) -} - -#[cfg(not(feature = "parallel"))] -fn for_each_mut(iter: I, action: F) -where - I: IntoIterator, - F: FnMut(A), -{ - iter.into_iter().for_each(action) -} - -impl VisitEntities for specs::Entity { - fn accept(&self, visitor: &V) - where - V: EntityVisitor, - { - visitor.visit_entity(*self) - } -} - -impl VisitEntitiesMut for specs::Entity { - fn accept_mut(&mut self, visitor: &V) - where - V: EntityVisitorMut, - { - visitor.visit_entity_mut(self) - } -} - -impl VisitEntities for Option -where - A: VisitEntities + Send + Sync, -{ - fn accept(&self, visitor: &V) - where - V: EntityVisitor, - { - for_each(self, |element| element.accept(visitor)) - } -} - -impl VisitEntitiesMut for Option -where - A: VisitEntitiesMut + Send + Sync, -{ - fn accept_mut(&mut self, visitor: &V) - where - V: EntityVisitorMut, - { - for_each_mut(self, |element| element.accept_mut(visitor)) - } -} - -impl VisitEntities for Vec -where - A: VisitEntities + Send + Sync, -{ - fn accept(&self, visitor: &V) - where - V: EntityVisitor, - { - for_each(self, |element| element.accept(visitor)) - } -} - -impl VisitEntitiesMut for Vec -where - A: VisitEntitiesMut + Send + Sync, -{ - fn accept_mut(&mut self, visitor: &V) - where - V: EntityVisitorMut, - { - for_each_mut(self, |element| element.accept_mut(visitor)) - } -} - -impl VisitEntities for Box -where - A: VisitEntities + Send + Sync, -{ - fn accept(&self, visitor: &V) - where - V: EntityVisitor, - { - (**self).accept(visitor) - } -} - -impl VisitEntitiesMut for Box -where - A: VisitEntitiesMut + Send + Sync, -{ - fn accept_mut(&mut self, visitor: &V) - where - V: EntityVisitorMut, - { - (**self).accept_mut(visitor) - } -} - -impl VisitEntities for collections::HashMap -where - A: Eq + hash::Hash + Send + Sync, - B: VisitEntities + Send + Sync, -{ - fn accept(&self, visitor: &V) - where - V: EntityVisitor, - { - for_each(self, |(_, element)| element.accept(visitor)) - } -} - -impl VisitEntitiesMut for collections::HashMap -where - A: Eq + hash::Hash + Send + Sync, - B: VisitEntitiesMut + Send + Sync, -{ - fn accept_mut(&mut self, visitor: &V) - where - V: EntityVisitorMut, - { - for_each_mut(self, |(_, element)| element.accept_mut(visitor)) - } -} - -impl VisitEntities for sync::Arc -where - A: VisitEntities, -{ - fn accept(&self, visitor: &V) - where - V: EntityVisitor, - { - (**self).accept(visitor) - } -} - -macro_rules! impl_visit_entities_empty { - ($t:ty) => { - impl VisitEntities for $t { - #[inline(always)] - fn accept(&self, _visitor: &V) - where - V: EntityVisitor, - { - } - } - - impl VisitEntitiesMut for $t { - #[inline(always)] - fn accept_mut(&mut self, _visitor: &V) - where - V: EntityVisitorMut, - { - } - } - }; -} - -impl_visit_entities_empty!(i8); -impl_visit_entities_empty!(i16); -impl_visit_entities_empty!(i32); -impl_visit_entities_empty!(i64); -impl_visit_entities_empty!(isize); -impl_visit_entities_empty!(u8); -impl_visit_entities_empty!(u16); -impl_visit_entities_empty!(u32); -impl_visit_entities_empty!(u64); -impl_visit_entities_empty!(usize); -impl_visit_entities_empty!(f32); -impl_visit_entities_empty!(f64); -impl_visit_entities_empty!(bool); -impl_visit_entities_empty!(char); - -impl_visit_entities_empty!(String); diff --git a/src/best_iter.rs b/src/best_iter.rs deleted file mode 100644 index 8cc91bb..0000000 --- a/src/best_iter.rs +++ /dev/null @@ -1,184 +0,0 @@ -pub trait BestJoin { - type Iter: BestIterator; - - fn best_join(self) -> Self::Iter - where - Self: Sized; -} - -pub trait BestIterator { - type Item: Send; - - fn best_for_each(self, op: F) - where - F: Fn(Self::Item) + Sync + Send; -} - -pub trait BestIteratorMap: BestIterator -where - F: Fn(Self::Item) -> R + Sync + Send, - R: Send, -{ - type Map; - - fn best_map(self, map_op: F) -> Self::Map; -} - -pub trait BestIteratorFlatMap: BestIterator -where - F: Fn(Self::Item) -> II + Sync + Send, -{ - type FlatMap; - - fn best_flat_map(self, map_op: F) -> Self::FlatMap; -} - -pub trait BestIteratorCollect: BestIterator { - fn best_collect(self) -> C; -} - -#[cfg(feature = "parallel")] -impl BestJoin for J -where - J: specs::Join + specs::ParJoin + Send, - J::Mask: Send + Sync, - J::Type: Send, - J::Value: Send, -{ - type Iter = specs::join::JoinParIter; - - fn best_join(self) -> Self::Iter - where - Self: Sized, - { - specs::join::ParJoin::par_join(self) - } -} - -#[cfg(not(feature = "parallel"))] -impl BestJoin for J -where - J: specs::Join, - J::Type: Send, -{ - type Iter = specs::join::JoinIter; - - fn best_join(self) -> Self::Iter - where - Self: Sized, - { - specs::join::Join::join(self) - } -} - -#[cfg(feature = "parallel")] -impl BestIterator for I -where - I: rayon::iter::ParallelIterator, -{ - type Item = I::Item; - - fn best_for_each(self, op: F) - where - F: Fn(Self::Item) + Sync + Send, - { - rayon::iter::ParallelIterator::for_each(self, op) - } -} - -#[cfg(not(feature = "parallel"))] -impl BestIterator for I -where - I: Iterator, - I::Item: Send, -{ - type Item = I::Item; - - fn best_for_each(self, op: F) - where - F: Fn(Self::Item) + Sync + Send, - { - Iterator::for_each(self, op) - } -} - -#[cfg(feature = "parallel")] -impl BestIteratorMap for I -where - I: rayon::iter::ParallelIterator, - F: Fn(Self::Item) -> R + Sync + Send, - R: Send, -{ - type Map = rayon::iter::Map; - - fn best_map(self, map_op: F) -> Self::Map { - rayon::iter::ParallelIterator::map(self, map_op) - } -} - -#[cfg(not(feature = "parallel"))] -impl BestIteratorMap for I -where - I: Iterator, - I::Item: Send, - F: Fn(Self::Item) -> R + Sync + Send, - R: Send, -{ - type Map = ::std::iter::Map; - - fn best_map(self, map_op: F) -> Self::Map { - Iterator::map(self, map_op) - } -} - -#[cfg(feature = "parallel")] -impl BestIteratorFlatMap for I -where - I: rayon::iter::ParallelIterator, - II: rayon::iter::IntoParallelIterator, - F: Fn(Self::Item) -> II + Sync + Send, -{ - type FlatMap = rayon::iter::FlatMap; - - fn best_flat_map(self, map_op: F) -> Self::FlatMap { - rayon::iter::ParallelIterator::flat_map(self, map_op) - } -} - -#[cfg(not(feature = "parallel"))] -impl BestIteratorFlatMap for I -where - I: Iterator, - I::Item: Send, - II: ::std::iter::IntoIterator, - F: Fn(Self::Item) -> II + Sync + Send, -{ - type FlatMap = std::iter::FlatMap; - - fn best_flat_map(self, map_op: F) -> Self::FlatMap { - Iterator::flat_map(self, map_op) - } -} - -#[cfg(feature = "parallel")] -impl BestIteratorCollect for I -where - I: rayon::iter::ParallelIterator, - C: rayon::iter::FromParallelIterator + Send, -{ - fn best_collect(self) -> C { - rayon::iter::ParallelIterator::collect(self) - } -} - -#[cfg(not(feature = "parallel"))] -impl BestIteratorCollect for I -where - I: Iterator, - I::Item: Send, - C: ::std::iter::FromIterator + Send, -{ - fn best_collect(self) -> C { - Iterator::collect(self) - } -} diff --git a/src/bin/tin.rs b/src/bin/tin.rs index ae8bfab..ae0ece2 100644 --- a/src/bin/tin.rs +++ b/src/bin/tin.rs @@ -1,11 +1,4 @@ -extern crate failure; -#[macro_use] -extern crate log; -extern crate pretty_env_logger; -#[macro_use] -extern crate structopt; -extern crate tin; - +use log::error; use std::fs; use std::io; use std::path; @@ -14,7 +7,7 @@ use std::sync::atomic; static REPORTED_DIAGNOSTICS: atomic::AtomicBool = atomic::AtomicBool::new(false); -#[derive(Debug, StructOpt)] +#[derive(Debug, structopt::StructOpt)] #[structopt(name = "tin")] struct Options { /// Source file to compile (that contains a main function); will use stdin if omitted. @@ -67,7 +60,7 @@ fn run() -> Result { .map_err(|e| report_diagnostics(tin.codemap(), e))?; let entrypoint = module - .function::>("main") + .function::, _>("TODO", "main") .ok_or_else(|| failure::err_msg("missing a main function"))?; let result = entrypoint.call()?; diff --git a/src/codegen/abi_type.rs b/src/codegen/abi_type.rs index 078d21a..0507e96 100644 --- a/src/codegen/abi_type.rs +++ b/src/codegen/abi_type.rs @@ -4,13 +4,11 @@ use std::u32; use std::u64; use std::u8; -use crate::ir::component::ty; - -use cranelift::prelude::*; +use crate::ty; #[derive(Clone, Copy, Debug)] pub enum AbiType { - Scalar(Type), + Scalar(cranelift::codegen::ir::Type), Ptr, } @@ -28,29 +26,33 @@ impl AbiType { ty::Type::String | ty::Type::Tuple(_) | ty::Type::Record(_) | ty::Type::Function(_) => { AbiType::Ptr } - ty::Type::Symbol(_) => AbiType::Scalar(types::I8), + ty::Type::Symbol(_) => AbiType::Scalar(cranelift::codegen::ir::types::I8), ty::Type::Union(ty::Union { ref alternatives }) => { let n = alternatives.len(); // Assumes unions only store symbols for now if n <= 2 { - AbiType::Scalar(types::B1) + AbiType::Scalar(cranelift::codegen::ir::types::B1) } else if n as u64 <= u64::from(u8::max_value()) { - AbiType::Scalar(types::I8) + AbiType::Scalar(cranelift::codegen::ir::types::I8) } else if n as u64 <= u64::from(u16::max_value()) { - AbiType::Scalar(types::I16) + AbiType::Scalar(cranelift::codegen::ir::types::I16) } else if n as u64 <= u64::from(u32::max_value()) { - AbiType::Scalar(types::I32) + AbiType::Scalar(cranelift::codegen::ir::types::I32) } else if n as u64 <= u64::max_value() { - AbiType::Scalar(types::I64) + AbiType::Scalar(cranelift::codegen::ir::types::I64) } else { unimplemented!() } } + ty::Type::Placeholder => panic!("cannot lower placeholder type"), } } - pub fn into_specific(self, ptr_type: Type) -> Type { + pub fn into_specific( + self, + ptr_type: cranelift::codegen::ir::Type, + ) -> cranelift::codegen::ir::Type { match self { AbiType::Scalar(ty) => ty, AbiType::Ptr => ptr_type, @@ -59,12 +61,18 @@ impl AbiType { fn from_ir_number_type(ir_type: ty::Number) -> AbiType { match ir_type { - ty::Number::U8 | ty::Number::I8 => AbiType::Scalar(types::I8), - ty::Number::U16 | ty::Number::I16 => AbiType::Scalar(types::I16), - ty::Number::U32 | ty::Number::I32 => AbiType::Scalar(types::I32), - ty::Number::U64 | ty::Number::I64 => AbiType::Scalar(types::I64), - ty::Number::F32 => AbiType::Scalar(types::F32), - ty::Number::F64 => AbiType::Scalar(types::F64), + ty::Number::U8 | ty::Number::I8 => AbiType::Scalar(cranelift::codegen::ir::types::I8), + ty::Number::U16 | ty::Number::I16 => { + AbiType::Scalar(cranelift::codegen::ir::types::I16) + } + ty::Number::U32 | ty::Number::I32 => { + AbiType::Scalar(cranelift::codegen::ir::types::I32) + } + ty::Number::U64 | ty::Number::I64 => { + AbiType::Scalar(cranelift::codegen::ir::types::I64) + } + ty::Number::F32 => AbiType::Scalar(cranelift::codegen::ir::types::F32), + ty::Number::F64 => AbiType::Scalar(cranelift::codegen::ir::types::F64), } } } diff --git a/src/codegen/builtin.rs b/src/codegen/builtin.rs index 568ade6..2ca8e77 100644 --- a/src/codegen/builtin.rs +++ b/src/codegen/builtin.rs @@ -4,6 +4,7 @@ use std::slice; use std::str; use cranelift::prelude::types; +use log::debug; use crate::codegen::abi_type; use crate::module; diff --git a/src/codegen/data.rs b/src/codegen/data.rs index d42f38a..0479e68 100644 --- a/src/codegen/data.rs +++ b/src/codegen/data.rs @@ -2,7 +2,7 @@ use std::fmt; use cranelift::prelude::*; -use crate::ir::component::layout; +use crate::layout; use crate::value; pub struct Translator<'a> { @@ -58,11 +58,11 @@ impl<'a> Translator<'a> { .unwrap(), value::Number::F32(v) => self .storage - .write_f32::(v) + .write_f32::(v.into_inner()) .unwrap(), value::Number::F64(v) => self .storage - .write_f64::(v) + .write_f64::(v.into_inner()) .unwrap(), } } diff --git a/src/codegen/error.rs b/src/codegen/error.rs new file mode 100644 index 0000000..007a086 --- /dev/null +++ b/src/codegen/error.rs @@ -0,0 +1,59 @@ +use std::result; + +use crate::interpreter; +use crate::ir; +use crate::layout; +use crate::ty; + +/// Errors that may occur while building and interacting with an [`Ir`]. +#[derive(Clone, Debug, Eq, failure::Fail, PartialEq)] +pub enum Error { + /// Semantic error. + #[fail(display = "semantic error")] + Ir(#[cause] ir::error::Error), + + /// Type error. + #[fail(display = "type error")] + Ty(#[cause] ty::error::Error), + + /// Constexpr interpreter evaluation failed. + #[fail(display = "failed to evaluate constexpr")] + Constexpr(#[cause] interpreter::error::Error), + + /// Failed to determine data layout. + #[fail(display = "failed to determine data layout")] + Layout(#[cause] layout::error::Error), + + /// There were multiple codegen errors. + #[fail(display = "multiple codegen errors")] + Multiple { + /// The errors, in the order they were encountered in the codegen. + errors: Vec, + }, +} + +pub type Result = result::Result; + +impl From for Error { + fn from(error: ir::error::Error) -> Self { + Error::Ir(error) + } +} + +impl From for Error { + fn from(error: ty::error::Error) -> Self { + Error::Ty(error) + } +} + +impl From for Error { + fn from(error: interpreter::error::Error) -> Self { + Error::Constexpr(error) + } +} + +impl From for Error { + fn from(error: layout::error::Error) -> Self { + Error::Layout(error) + } +} diff --git a/src/codegen/function.rs b/src/codegen/function.rs index 8d19a45..bf933e0 100644 --- a/src/codegen/function.rs +++ b/src/codegen/function.rs @@ -1,97 +1,101 @@ use std::collections; use std::fmt; -use specs; - use cranelift::prelude::*; use cranelift_module; use cranelift_simplejit; use crate::codegen::abi_type; use crate::codegen::builtin; +use crate::codegen::error; use crate::codegen::util; -use crate::ir::component::constexpr; -use crate::ir::component::element; -use crate::ir::component::layout; -use crate::ir::component::location; -use crate::ir::component::symbol; -use crate::ir::component::ty; +use crate::db; +use crate::ir; +use crate::ir::element; +use crate::ir::location; +use crate::layout; use crate::module; +use crate::ty; use crate::value; -pub struct Translator<'a, 'f> +pub struct Translator<'a, 'f, B, D> where 'f: 'a, + B: cranelift_module::Backend, { - module: &'a mut cranelift_module::Module, + module: &'a mut cranelift_module::Module, builder: &'a mut FunctionBuilder<'f>, - constexprs: &'a specs::ReadStorage<'a, constexpr::Constexpr>, - elements: &'a specs::ReadStorage<'a, element::Element>, - layouts: &'a specs::ReadStorage<'a, layout::Layout>, - locations: &'a specs::ReadStorage<'a, location::Location>, - symbols: &'a specs::ReadStorage<'a, symbol::Symbol>, - types: &'a specs::ReadStorage<'a, ty::Type>, + db: &'a D, ptr_type: Type, error_throw_ebb: Ebb, error_unwind_ebb: Ebb, - variables: &'a collections::HashMap, + variables: &'a collections::HashMap, defined_strings: &'a mut collections::HashMap, - codemap: &'a codespan::CodeMap, } -impl<'a, 'f> Translator<'a, 'f> { +impl<'a, 'f, B, D> Translator<'a, 'f, B, D> +where + B: cranelift_module::Backend, + D: super::Db, +{ #[cfg_attr(feature = "cargo-clippy", allow(clippy::too_many_arguments))] pub fn new( - module: &'a mut cranelift_module::Module, + module: &'a mut cranelift_module::Module, builder: &'a mut FunctionBuilder<'f>, - constexprs: &'a specs::ReadStorage<'a, constexpr::Constexpr>, - elements: &'a specs::ReadStorage<'a, element::Element>, - layouts: &'a specs::ReadStorage<'a, layout::Layout>, - locations: &'a specs::ReadStorage<'a, location::Location>, - symbols: &'a specs::ReadStorage<'a, symbol::Symbol>, - types: &'a specs::ReadStorage<'a, ty::Type>, + db: &'a D, ptr_type: Type, error_throw_ebb: Ebb, error_unwind_ebb: Ebb, - variables: &'a collections::HashMap, + variables: &'a collections::HashMap, defined_strings: &'a mut collections::HashMap, - codemap: &'a codespan::CodeMap, ) -> Self { Translator { module, builder, - constexprs, - elements, - layouts, - locations, - symbols, - types, + db, ptr_type, error_throw_ebb, error_unwind_ebb, variables, defined_strings, - codemap, } } - pub fn exec_element(&mut self, entity: specs::Entity, element: &element::Element) { + pub fn exec_element( + &mut self, + entity: ir::Entity, + element: &element::Element, + ) -> error::Result<()> { if let element::Element::Variable(ref v) = element { - self.exec_variable(entity, v); + self.exec_variable(entity, v)?; } else { - self.eval_element(entity, element); + self.eval_element(entity, element)?; } + Ok(()) } - pub fn exec_variable(&mut self, entity: specs::Entity, variable: &element::Variable) { - let initializer_element = self.elements.get(variable.initializer).unwrap(); - let value = self.eval_element(variable.initializer, initializer_element); + pub fn exec_variable( + &mut self, + entity: ir::Entity, + variable: &element::Variable, + ) -> error::Result<()> { + use crate::ir::Db as _; + + let initializer_element = self.db.element(variable.initializer)?; + let value = self.eval_element(variable.initializer, &*initializer_element)?; self.builder.def_var(self.variables[&entity], value); + Ok(()) } - pub fn eval_element(&mut self, entity: specs::Entity, element: &element::Element) -> Value { - if let Some(constexpr) = self.constexprs.get(entity) { - self.eval_constexpr(entity, constexpr) + pub fn eval_element( + &mut self, + entity: ir::Entity, + element: &element::Element, + ) -> error::Result { + use crate::interpreter::Db as _; + + if let Some(value) = self.db.value(entity)? { + self.eval_value(entity, &value) } else { match *element { element::Element::Number(ref v) => self.eval_number_value(entity, v), @@ -111,34 +115,55 @@ impl<'a, 'f> Translator<'a, 'f> { element::Element::Capture(ref v) => self.eval_capture(entity, v), element::Element::Closure(ref v) => self.eval_closure(entity, v), element::Element::Module(ref v) => self.eval_module(entity, v), + element::Element::Reference(entity) => { + self.eval_element(entity, &*self.db.element(entity)?) + } } } } - fn eval_constexpr(&mut self, entity: specs::Entity, constexpr: &constexpr::Constexpr) -> Value { - if let value::Case::Number(ref n) = *constexpr.value.case() { + fn eval_value(&mut self, entity: ir::Entity, value: &value::Value) -> error::Result { + use crate::layout::Db as _; + use crate::ty::Db as _; + + if let value::Case::Number(ref n) = *value.case() { match *n { - value::Number::U8(ref v) => self.builder.ins().iconst(types::I8, i64::from(*v)), - value::Number::U16(ref v) => self.builder.ins().iconst(types::I16, i64::from(*v)), - value::Number::U32(ref v) => self.builder.ins().iconst(types::I32, i64::from(*v)), + value::Number::U8(ref v) => Ok(self.builder.ins().iconst(types::I8, i64::from(*v))), + value::Number::U16(ref v) => { + Ok(self.builder.ins().iconst(types::I16, i64::from(*v))) + } + value::Number::U32(ref v) => { + Ok(self.builder.ins().iconst(types::I32, i64::from(*v))) + } value::Number::U64(ref v) => { #[cfg_attr( feature = "cargo-clippy", allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap) )] let value = *v as i64; - self.builder.ins().iconst(types::I64, value) + Ok(self.builder.ins().iconst(types::I64, value)) } - value::Number::I8(ref v) => self.builder.ins().iconst(types::I8, i64::from(*v)), - value::Number::I16(ref v) => self.builder.ins().iconst(types::I16, i64::from(*v)), - value::Number::I32(ref v) => self.builder.ins().iconst(types::I32, i64::from(*v)), - value::Number::I64(ref v) => self.builder.ins().iconst(types::I64, *v), - value::Number::F32(ref v) => self.builder.ins().f32const(Ieee32::with_float(*v)), - value::Number::F64(ref v) => self.builder.ins().f64const(Ieee64::with_float(*v)), + value::Number::I8(ref v) => Ok(self.builder.ins().iconst(types::I8, i64::from(*v))), + value::Number::I16(ref v) => { + Ok(self.builder.ins().iconst(types::I16, i64::from(*v))) + } + value::Number::I32(ref v) => { + Ok(self.builder.ins().iconst(types::I32, i64::from(*v))) + } + value::Number::I64(ref v) => Ok(self.builder.ins().iconst(types::I64, *v)), + value::Number::F32(ref v) => Ok(self + .builder + .ins() + .f32const(Ieee32::with_float(v.into_inner()))), + value::Number::F64(ref v) => Ok(self + .builder + .ins() + .f64const(Ieee64::with_float(v.into_inner()))), } } else { - let ty = self.types.get(entity).unwrap(); - let abi_type = abi_type::AbiType::from_ir_type(ty).into_specific(self.ptr_type); + let ty = self.db.ty(entity)?; + let layout = self.db.layout(entity)?; + let abi_type = abi_type::AbiType::from_ir_type(&*ty).into_specific(self.ptr_type); assert_eq!(self.ptr_type, abi_type); @@ -148,58 +173,80 @@ impl<'a, 'f> Translator<'a, 'f> { &entity.id().to_string(), cranelift_module::Linkage::Local, false, + Some(layout.alignment as u8), ) .unwrap(); let global_value = self .module .declare_data_in_func(data_id, &mut self.builder.func); - self.builder.ins().global_value(self.ptr_type, global_value) + Ok(self.builder.ins().global_value(self.ptr_type, global_value)) } } #[cfg_attr(feature = "cargo-clippy", allow(clippy::cast_possible_wrap))] pub fn eval_number_value( &mut self, - _entity: specs::Entity, + _entity: ir::Entity, number_value: &element::Number, - ) -> Value { + ) -> error::Result { match *number_value { - element::Number::U8(v) => self.builder.ins().iconst(types::I8, i64::from(v)), - element::Number::U16(v) => self.builder.ins().iconst(types::I16, i64::from(v)), - element::Number::U32(v) => self.builder.ins().iconst(types::I32, i64::from(v)), - element::Number::U64(v) => self.builder.ins().iconst(types::I64, v as i64), - element::Number::I8(v) => self.builder.ins().iconst(types::I8, i64::from(v)), - element::Number::I16(v) => self.builder.ins().iconst(types::I16, i64::from(v)), - element::Number::I32(v) => self.builder.ins().iconst(types::I32, i64::from(v)), - element::Number::I64(v) => self.builder.ins().iconst(types::I64, v), - element::Number::F32(v) => self.builder.ins().f32const(Ieee32::with_float(v)), - element::Number::F64(v) => self.builder.ins().f64const(Ieee64::with_float(v)), + element::Number::U8(v) => Ok(self.builder.ins().iconst(types::I8, i64::from(v))), + element::Number::U16(v) => Ok(self.builder.ins().iconst(types::I16, i64::from(v))), + element::Number::U32(v) => Ok(self.builder.ins().iconst(types::I32, i64::from(v))), + element::Number::U64(v) => Ok(self.builder.ins().iconst(types::I64, v as i64)), + element::Number::I8(v) => Ok(self.builder.ins().iconst(types::I8, i64::from(v))), + element::Number::I16(v) => Ok(self.builder.ins().iconst(types::I16, i64::from(v))), + element::Number::I32(v) => Ok(self.builder.ins().iconst(types::I32, i64::from(v))), + element::Number::I64(v) => Ok(self.builder.ins().iconst(types::I64, v)), + element::Number::F32(v) => Ok(self + .builder + .ins() + .f32const(Ieee32::with_float(v.into_inner()))), + element::Number::F64(v) => Ok(self + .builder + .ins() + .f64const(Ieee64::with_float(v.into_inner()))), } } - pub fn eval_string_value(&mut self, entity: specs::Entity, _string_value: &str) -> Value { + pub fn eval_string_value( + &mut self, + entity: ir::Entity, + _string_value: &str, + ) -> error::Result { + use crate::layout::Db as _; + // TODO: create data symbol + let layout = self.db.layout(entity)?; let symbol = self .module .declare_data( &format!("__data_{}", entity.id()), cranelift_module::Linkage::Local, false, + Some(layout.alignment as u8), ) .unwrap(); let local_id = self .module .declare_data_in_func(symbol, &mut self.builder.func); - self.builder.ins().symbol_value(self.ptr_type, local_id) + Ok(self.builder.ins().symbol_value(self.ptr_type, local_id)) } #[cfg_attr( feature = "cargo-clippy", allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap) )] - pub fn eval_tuple(&mut self, entity: specs::Entity, tuple: &element::Tuple) -> Value { - let layout = self.layouts.get(entity).unwrap(); + pub fn eval_tuple( + &mut self, + entity: ir::Entity, + tuple: &element::Tuple, + ) -> error::Result { + use crate::ir::Db as _; + use crate::layout::Db as _; + + let layout = self.db.layout(entity)?; let alloc_size = self.builder.ins().iconst(self.ptr_type, layout.size as i64); let alloc_align = self .builder @@ -213,16 +260,23 @@ impl<'a, 'f> Translator<'a, 'f> { for (idx, offset_layout) in layout.unnamed_fields.iter().enumerate() { let value = tuple.fields[idx]; - let value = self.eval_element(value, self.elements.get(value).unwrap()); + let value = self.eval_element(value, &*self.db.element(value)?)?; let offset = offset_layout.offset as i32; self.builder.ins().store(mem_flags, value, result, offset); } - result + Ok(result) } - pub fn eval_record(&mut self, entity: specs::Entity, record: &element::Record) -> Value { - let layout = self.layouts.get(entity).unwrap(); + pub fn eval_record( + &mut self, + entity: ir::Entity, + record: &element::Record, + ) -> error::Result { + use crate::ir::Db as _; + use crate::layout::Db as _; + + let layout = self.db.layout(entity)?; #[cfg_attr( feature = "cargo-clippy", @@ -246,7 +300,7 @@ impl<'a, 'f> Translator<'a, 'f> { for named_field in &layout.named_fields { let value = record.fields[&named_field.field]; - let value = self.eval_element(value, self.elements.get(value).unwrap()); + let value = self.eval_element(value, &*self.db.element(value)?)?; #[cfg_attr( feature = "cargo-clippy", @@ -256,47 +310,59 @@ impl<'a, 'f> Translator<'a, 'f> { self.builder.ins().store(mem_flags, value, result, offset); } - result + Ok(result) } - pub fn eval_un_op(&mut self, _entity: specs::Entity, un_op: &element::UnOp) -> Value { + pub fn eval_un_op( + &mut self, + _entity: ir::Entity, + un_op: &element::UnOp, + ) -> error::Result { + use crate::ir::Db as _; + let element::UnOp { operator, operand } = un_op; - let operand = *operand; - let operand_value = self.eval_element(operand, self.elements.get(operand).unwrap()); + let operand_value = self.eval_element(*operand, &*self.db.element(*operand)?)?; match operator { element::UnOperator::Not | element::UnOperator::BNot => { - self.builder.ins().bnot(operand_value) + Ok(self.builder.ins().bnot(operand_value)) } - element::UnOperator::Cl0 => self.builder.ins().clz(operand_value), + element::UnOperator::Cl0 => Ok(self.builder.ins().clz(operand_value)), element::UnOperator::Cl1 => { let inverted = self.builder.ins().bnot(operand_value); - self.builder.ins().clz(inverted) + Ok(self.builder.ins().clz(inverted)) } - element::UnOperator::Cls => self.builder.ins().cls(operand_value), - element::UnOperator::Ct0 => self.builder.ins().ctz(operand_value), + element::UnOperator::Cls => Ok(self.builder.ins().cls(operand_value)), + element::UnOperator::Ct0 => Ok(self.builder.ins().ctz(operand_value)), element::UnOperator::Ct1 => { let inverted = self.builder.ins().bnot(operand_value); - self.builder.ins().ctz(inverted) + Ok(self.builder.ins().ctz(inverted)) } element::UnOperator::C0 => { let inverted = self.builder.ins().bnot(operand_value); - self.builder.ins().popcnt(inverted) + Ok(self.builder.ins().popcnt(inverted)) } - element::UnOperator::C1 => self.builder.ins().popcnt(operand_value), - element::UnOperator::Sqrt => self.builder.ins().sqrt(operand_value), + element::UnOperator::C1 => Ok(self.builder.ins().popcnt(operand_value)), + element::UnOperator::Sqrt => Ok(self.builder.ins().sqrt(operand_value)), } } - pub fn eval_bi_op(&mut self, entity: specs::Entity, bi_op: &element::BiOp) -> Value { + pub fn eval_bi_op( + &mut self, + entity: ir::Entity, + bi_op: &element::BiOp, + ) -> error::Result { + use crate::ir::Db as _; + use crate::ty::Db as _; + let element::BiOp { lhs, operator, rhs } = bi_op; let lhs = *lhs; let rhs = *rhs; // TODO: support lazy evaluation - let lhs_value = self.eval_element(lhs, self.elements.get(lhs).unwrap()); - let rhs_value = self.eval_element(rhs, self.elements.get(rhs).unwrap()); + let lhs_value = self.eval_element(lhs, &*self.db.element(lhs)?)?; + let rhs_value = self.eval_element(rhs, &*self.db.element(rhs)?)?; match operator { element::BiOperator::Eq => unimplemented!(), @@ -306,84 +372,97 @@ impl<'a, 'f> Translator<'a, 'f> { element::BiOperator::Gt => unimplemented!(), element::BiOperator::Le => unimplemented!(), element::BiOperator::Cmp => unimplemented!(), - element::BiOperator::Add => match self.types.get(lhs).unwrap().scalar_class() { - ty::class::Scalar::Integral(_) => self.builder.ins().iadd(lhs_value, rhs_value), - ty::class::Scalar::Fractional => self.builder.ins().fadd(lhs_value, rhs_value), + element::BiOperator::Add => match self.db.ty(lhs)?.scalar_class() { + ty::class::Scalar::Integral(_) => Ok(self.builder.ins().iadd(lhs_value, rhs_value)), + ty::class::Scalar::Fractional => Ok(self.builder.ins().fadd(lhs_value, rhs_value)), _ => unreachable!(), }, - element::BiOperator::Sub => match self.types.get(lhs).unwrap().scalar_class() { - ty::class::Scalar::Integral(_) => self.builder.ins().isub(lhs_value, rhs_value), - ty::class::Scalar::Fractional => self.builder.ins().fsub(lhs_value, rhs_value), + element::BiOperator::Sub => match self.db.ty(lhs)?.scalar_class() { + ty::class::Scalar::Integral(_) => Ok(self.builder.ins().isub(lhs_value, rhs_value)), + ty::class::Scalar::Fractional => Ok(self.builder.ins().fsub(lhs_value, rhs_value)), _ => unreachable!(), }, - element::BiOperator::Mul => match self.types.get(lhs).unwrap().scalar_class() { - ty::class::Scalar::Integral(_) => self.builder.ins().imul(lhs_value, rhs_value), - ty::class::Scalar::Fractional => self.builder.ins().fmul(lhs_value, rhs_value), + element::BiOperator::Mul => match self.db.ty(lhs)?.scalar_class() { + ty::class::Scalar::Integral(_) => Ok(self.builder.ins().imul(lhs_value, rhs_value)), + ty::class::Scalar::Fractional => Ok(self.builder.ins().fmul(lhs_value, rhs_value)), _ => unreachable!(), }, - element::BiOperator::Div => match self.types.get(lhs).unwrap().scalar_class() { + element::BiOperator::Div => match self.db.ty(lhs)?.scalar_class() { ty::class::Scalar::Integral(ty::class::IntegralScalar::Unsigned) => { - self.error_if_zero(entity, rhs_value, module::ErrorKind::IntegerDivisonByZero); - self.builder.ins().udiv(lhs_value, rhs_value) + self.error_if_zero(entity, rhs_value, module::ErrorKind::IntegerDivisonByZero)?; + Ok(self.builder.ins().udiv(lhs_value, rhs_value)) } ty::class::Scalar::Integral(ty::class::IntegralScalar::Signed) => { - self.error_if_zero(entity, rhs_value, module::ErrorKind::IntegerDivisonByZero); - self.builder.ins().sdiv(lhs_value, rhs_value) + self.error_if_zero(entity, rhs_value, module::ErrorKind::IntegerDivisonByZero)?; + Ok(self.builder.ins().sdiv(lhs_value, rhs_value)) } - ty::class::Scalar::Fractional => self.builder.ins().fdiv(lhs_value, rhs_value), + ty::class::Scalar::Fractional => Ok(self.builder.ins().fdiv(lhs_value, rhs_value)), _ => unreachable!(), }, - element::BiOperator::Rem => match self.types.get(lhs).unwrap().scalar_class() { + element::BiOperator::Rem => match self.db.ty(lhs)?.scalar_class() { ty::class::Scalar::Integral(ty::class::IntegralScalar::Unsigned) => { - self.error_if_zero(entity, rhs_value, module::ErrorKind::IntegerDivisonByZero); - self.builder.ins().urem(lhs_value, rhs_value) + self.error_if_zero(entity, rhs_value, module::ErrorKind::IntegerDivisonByZero)?; + Ok(self.builder.ins().urem(lhs_value, rhs_value)) } ty::class::Scalar::Integral(ty::class::IntegralScalar::Signed) => { - self.error_if_zero(entity, rhs_value, module::ErrorKind::IntegerDivisonByZero); - self.builder.ins().srem(lhs_value, rhs_value) + self.error_if_zero(entity, rhs_value, module::ErrorKind::IntegerDivisonByZero)?; + Ok(self.builder.ins().srem(lhs_value, rhs_value)) } _ => unreachable!(), }, element::BiOperator::And | element::BiOperator::BAnd => { - self.builder.ins().band(lhs_value, rhs_value) + Ok(self.builder.ins().band(lhs_value, rhs_value)) } element::BiOperator::Or | element::BiOperator::BOr => { - self.builder.ins().bor(lhs_value, rhs_value) + Ok(self.builder.ins().bor(lhs_value, rhs_value)) } element::BiOperator::Xor | element::BiOperator::BXor => { - self.builder.ins().bxor(lhs_value, rhs_value) + Ok(self.builder.ins().bxor(lhs_value, rhs_value)) } element::BiOperator::AndNot | element::BiOperator::BAndNot => { - self.builder.ins().band_not(lhs_value, rhs_value) + Ok(self.builder.ins().band_not(lhs_value, rhs_value)) } element::BiOperator::OrNot | element::BiOperator::BOrNot => { - self.builder.ins().bor_not(lhs_value, rhs_value) + Ok(self.builder.ins().bor_not(lhs_value, rhs_value)) } element::BiOperator::XorNot | element::BiOperator::BXorNot => { - self.builder.ins().bxor_not(lhs_value, rhs_value) + Ok(self.builder.ins().bxor_not(lhs_value, rhs_value)) } - element::BiOperator::RotL => self.builder.ins().rotl(lhs_value, rhs_value), - element::BiOperator::RotR => self.builder.ins().rotr(lhs_value, rhs_value), - element::BiOperator::ShL => self.builder.ins().ishl(lhs_value, rhs_value), - element::BiOperator::ShR => match self.types.get(lhs).unwrap().scalar_class() { + element::BiOperator::RotL => Ok(self.builder.ins().rotl(lhs_value, rhs_value)), + element::BiOperator::RotR => Ok(self.builder.ins().rotr(lhs_value, rhs_value)), + element::BiOperator::ShL => Ok(self.builder.ins().ishl(lhs_value, rhs_value)), + element::BiOperator::ShR => match self.db.ty(lhs)?.scalar_class() { ty::class::Scalar::Integral(ty::class::IntegralScalar::Unsigned) => { - self.builder.ins().ushr(lhs_value, rhs_value) + Ok(self.builder.ins().ushr(lhs_value, rhs_value)) } ty::class::Scalar::Integral(ty::class::IntegralScalar::Signed) => { - self.builder.ins().sshr(lhs_value, rhs_value) + Ok(self.builder.ins().sshr(lhs_value, rhs_value)) } _ => unreachable!(), }, } } - pub fn eval_variable(&mut self, entity: specs::Entity, _variable: &element::Variable) -> Value { - self.builder.use_var(self.variables[&entity]) + pub fn eval_variable( + &mut self, + entity: ir::Entity, + _variable: &element::Variable, + ) -> error::Result { + Ok(self.builder.use_var(self.variables[&entity])) } - pub fn eval_select(&mut self, _entity: specs::Entity, select: &element::Select) -> Value { - let record_layout = self.layouts.get(select.record).unwrap(); - let record_type = match self.types.get(select.record).unwrap() { + pub fn eval_select( + &mut self, + _entity: ir::Entity, + select: &element::Select, + ) -> error::Result { + use crate::ir::Db as _; + use crate::layout::Db as _; + use crate::ty::Db as _; + + let record_layout = self.db.layout(select.record)?; + let ty = self.db.ty(select.record)?; + let record_type = match &*ty { ty::Type::Record(r) => r, _ => unreachable!(), }; @@ -399,7 +478,7 @@ impl<'a, 'f> Translator<'a, 'f> { let field_offset = record_layout .named_fields .iter() - .find(|f| *f.field == select.field) + .find(|f| f.field == select.field) .unwrap() .offset_layout .offset as i32; @@ -409,39 +488,46 @@ impl<'a, 'f> Translator<'a, 'f> { mem_flags.set_aligned(); mem_flags.set_readonly(); - let record = self.eval_element(select.record, self.elements.get(select.record).unwrap()); + let record = self.eval_element(select.record, &*self.db.element(select.record)?)?; - self.builder + Ok(self + .builder .ins() - .load(field_abi_type, mem_flags, record, field_offset) + .load(field_abi_type, mem_flags, record, field_offset)) } pub fn eval_parameter( &mut self, - entity: specs::Entity, + entity: ir::Entity, _parameter: &element::Parameter, - ) -> Value { - self.builder.use_var(self.variables[&entity]) + ) -> error::Result { + Ok(self.builder.use_var(self.variables[&entity])) } - pub fn eval_apply(&mut self, entity: specs::Entity, apply: &element::Apply) -> Value { + pub fn eval_apply( + &mut self, + entity: ir::Entity, + apply: &element::Apply, + ) -> error::Result { + use crate::ir::Db as _; + use crate::ty::Db as _; + let mut sig = self.module.make_signature(); for parameter in &apply.parameters { sig.params.push(AbiParam::new( - abi_type::AbiType::from_ir_type(self.types.get(*parameter).unwrap()) + abi_type::AbiType::from_ir_type(&*self.db.ty(*parameter)?) .into_specific(self.ptr_type), )); } // Result sig.returns.push(AbiParam::new( - abi_type::AbiType::from_ir_type(self.types.get(entity).unwrap()) - .into_specific(self.ptr_type), + abi_type::AbiType::from_ir_type(&*self.db.ty(entity)?).into_specific(self.ptr_type), )); // Error sig.returns.push(AbiParam::new(self.ptr_type)); - let name = self.get_symbol(apply.function).unwrap().to_string(); + let name = super::Symbol(self.db, apply.function).to_string(); let callee = self .module .declare_function(&name, cranelift_module::Linkage::Import, &sig) @@ -453,8 +539,8 @@ impl<'a, 'f> Translator<'a, 'f> { let parameter_values = apply .parameters .iter() - .map(|p| self.eval_element(*p, self.elements.get(*p).unwrap())) - .collect::>(); + .map(|p| Ok(self.eval_element(*p, &*self.db.element(*p)?)?)) + .collect::>>()?; let call = self.builder.ins().call(local_callee, ¶meter_values); @@ -462,7 +548,7 @@ impl<'a, 'f> Translator<'a, 'f> { let result = results[0]; let error = results[1]; - let location = self.locations.get(entity).unwrap().0; + let location = self.db.location(entity)?; let (filename, filename_len, line, col) = self.immediate_location(location); self.builder.ins().brnz( @@ -470,22 +556,41 @@ impl<'a, 'f> Translator<'a, 'f> { self.error_unwind_ebb, &[error, filename, filename_len, line, col], ); - result + + Ok(result) } - pub fn eval_capture(&mut self, entity: specs::Entity, _capture: &element::Capture) -> Value { - self.builder.use_var(self.variables[&entity]) + pub fn eval_capture( + &mut self, + entity: ir::Entity, + _capture: &element::Capture, + ) -> error::Result { + Ok(self.builder.use_var(self.variables[&entity])) } - pub fn eval_closure(&mut self, _entity: specs::Entity, _closure: &element::Closure) -> Value { + pub fn eval_closure( + &mut self, + _entity: ir::Entity, + _closure: &element::Closure, + ) -> error::Result { unimplemented!() } - pub fn eval_module(&mut self, _entity: specs::Entity, _module: &element::Module) -> Value { + pub fn eval_module( + &mut self, + _entity: ir::Entity, + _module: &element::Module, + ) -> error::Result { unimplemented!() } - pub fn error_if_zero(&mut self, entity: specs::Entity, value: Value, kind: module::ErrorKind) { + pub fn error_if_zero( + &mut self, + entity: ir::Entity, + value: Value, + kind: module::ErrorKind, + ) -> error::Result<()> { + use crate::ir::Db as _; use num_traits::cast::ToPrimitive; let kind = self @@ -493,7 +598,7 @@ impl<'a, 'f> Translator<'a, 'f> { .ins() .iconst(types::I32, i64::from(kind.to_u32().unwrap())); - let location = self.locations.get(entity).unwrap().0; + let location = self.db.location(entity)?; let (filename, filename_len, line, col) = self.immediate_location(location); @@ -502,13 +607,23 @@ impl<'a, 'f> Translator<'a, 'f> { self.error_throw_ebb, &[kind, filename, filename_len, line, col], ); + + Ok(()) } pub fn immediate_location( &mut self, - location: codespan::ByteSpan, + location: location::Location, ) -> (Value, Value, Value, Value) { - let filemap = self.codemap.find_file(location.start()).unwrap(); + let location = location.0; + + let filemap = self + .db + .code_map() + .raw + .find_file(location.start()) + .unwrap() + .clone(); let (line, col) = filemap.location(location.start()).unwrap(); let filename = filemap.name().to_string(); let filename_len = filename.len(); @@ -535,21 +650,6 @@ impl<'a, 'f> Translator<'a, 'f> { (filename, filename_len, line, col) } - fn get_symbol(&self, entity: specs::Entity) -> Option<&symbol::Symbol> { - if let Some(symbol) = self.symbols.get(entity) { - Some(symbol) - } else if let Some(element) = self.elements.get(entity) { - match element { - element::Element::Capture(element::Capture { captured, .. }) => { - self.get_symbol(*captured) - } - _ => None, - } - } else { - None - } - } - pub fn builtin_alloc(&mut self, size: Value, align: Value) -> Value { let local_callee = self.declare_builtin(&builtin::ALLOC); @@ -614,7 +714,10 @@ impl<'a, 'f> Translator<'a, 'f> { } } -impl<'a, 'f> fmt::Debug for Translator<'a, 'f> { +impl<'a, 'f, B, D> fmt::Debug for Translator<'a, 'f, B, D> +where + B: cranelift_module::Backend, +{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Translator").finish() } diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index e917738..59b677a 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -1,517 +1,609 @@ //! A JIT compiler implementation based on the IR. +use log::debug; +use log::trace; use std::collections; use std::fmt; +use std::mem; +use std::ops; +use std::sync; use cranelift::codegen; +use cranelift::codegen::ir::immediates; +use cranelift::codegen::ir::types; +use cranelift::frontend; use cranelift_module; use cranelift_simplejit; -use specs; +use crate::db; +use crate::interpreter; use crate::ir; -use crate::ir::component::constexpr; -use crate::ir::component::element; -use crate::ir::component::layout; -use crate::ir::component::location; -use crate::ir::component::symbol; -use crate::ir::component::ty; +use crate::ir::element; +use crate::layout; use crate::module; - -use cranelift::prelude::*; +use crate::ty; mod abi_type; mod builtin; mod data; +pub mod error; mod function; #[cfg(test)] mod tests; mod util; /// A codegen system, that can be used for JIT compilation. -pub struct Codegen<'a> { - entities: specs::Entities<'a>, - constexprs: specs::ReadStorage<'a, constexpr::Constexpr>, - elements: specs::ReadStorage<'a, element::Element>, - layouts: specs::ReadStorage<'a, layout::Layout>, - locations: specs::ReadStorage<'a, location::Location>, - symbols: specs::ReadStorage<'a, symbol::Symbol>, - types: specs::ReadStorage<'a, ty::Type>, - codemap: &'a codespan::CodeMap, +#[salsa::query_group(CodegenStorage)] +pub trait Db: salsa::Database + interpreter::Db + ir::Db + layout::Db + ty::Db { + #[salsa::dependencies] + fn codegen(&self) -> error::Result>; +} + +pub struct Data { + ctx: cranelift_module::DataContext, +} + +struct Symbol<'d, D>(&'d D, ir::Entity); + +struct Function { + ctx: codegen::Context, + name: String, + entity: ir::Entity, + is_public: bool, +} + +struct Codegen<'m, 'd, B, D> +where + B: cranelift_module::Backend, +{ + ptr_type: codegen::ir::Type, + module: &'m mut cranelift_module::Module, + db: &'d D, + functions: Vec, + defined_strings: collections::HashMap, + exposed_functions: + collections::HashMap<(relative_path::RelativePathBuf, String), cranelift_module::FuncId>, +} + +fn codegen(db: &impl Db) -> error::Result> { + let ptr_type = codegen_ptr_type(db); + let mut builder = + cranelift_simplejit::SimpleJITBuilder::new(cranelift_module::default_libcall_names()); + builder.symbols(builtin::BUILTINS.iter().map(|b| (b.symbol, b.ptr))); + let mut module: cranelift_module::Module = + cranelift_module::Module::new(builder); + let mut codegen = Codegen::new(ptr_type, &mut module, db); + codegen.codegen_all()?; + let function_ids = codegen.exposed_functions; + + Ok(sync::Arc::new(module::Module::new(module, function_ids))) +} + +fn codegen_ptr_type(db: &impl Db) -> codegen::ir::Type { + match db.ptr_size() { + layout::PtrSize::Size8 => codegen::ir::types::I8, + layout::PtrSize::Size16 => codegen::ir::types::I16, + layout::PtrSize::Size32 => codegen::ir::types::I32, + layout::PtrSize::Size64 => codegen::ir::types::I64, + } } -impl<'a> Codegen<'a> { - /// Creates a new codegen instance around the specified IR. - pub fn new(ir: &'a ir::Ir, codemap: &'a codespan::CodeMap) -> Self { - let entities = ir.world.entities(); - let constexprs = ir.world.read_storage(); - let elements = ir.world.read_storage(); - let layouts = ir.world.read_storage(); - let locations = ir.world.read_storage(); - let symbols = ir.world.read_storage(); - let types = ir.world.read_storage(); - - Codegen { - entities, - constexprs, - elements, - layouts, - locations, - symbols, - types, - codemap, +impl<'m, 'd, B, D> Codegen<'m, 'd, B, D> +where + B: cranelift_module::Backend, + D: Db, +{ + fn new( + ptr_type: codegen::ir::Type, + module: &'m mut cranelift_module::Module, + db: &'d D, + ) -> Self { + let defined_strings = collections::HashMap::new(); + let exposed_functions = collections::HashMap::new(); + let functions = Vec::new(); + Self { + ptr_type, + module, + db, + defined_strings, + exposed_functions, + functions, } } - /// Compiles the captured IR into a module. - pub fn compile(&self) -> module::Module { - use crate::best_iter::BestIteratorCollect; - use crate::best_iter::BestIteratorMap; - use crate::best_iter::BestJoin; - use specs::Join; - - let Codegen { - ref entities, - ref constexprs, - ref elements, - ref layouts, - ref locations, - ref symbols, - ref types, - ref codemap, - } = *self; - - let mut builder = cranelift_simplejit::SimpleJITBuilder::new(); - - builder.symbols(builtin::BUILTINS.iter().map(|b| (b.symbol, b.ptr))); - - let mut module: cranelift_module::Module = - cranelift_module::Module::new(builder); - let ptr_type = module.target_config().pointer_type(); - - let data_ctxs: Vec<_> = (entities, layouts, constexprs) - .best_join() - .best_map(|(entity, layout, constexpr)| { - let mut ctx = cranelift_module::DataContext::new(); - let mut data = Vec::new(); - data::Translator::new(&mut data, ptr_type).store_value(layout, &constexpr.value); - ctx.define(data.into_boxed_slice()); - (entity, ctx) - }) - .best_collect(); - - let mut defined_strings = collections::HashMap::new(); - - let function_ctxs = (elements, symbols, types) - .join() - .flat_map(|(el, sy, ty)| { - if let Some((closure, ty)) = as_closure(el, ty) { - let mut ctx: codegen::Context = module.make_context(); - let mut builder_context = FunctionBuilderContext::new(); - - for parameter in &ty.parameters { - ctx.func.signature.params.push(AbiParam::new( - abi_type::AbiType::from_ir_type(parameter).into_specific(ptr_type), - )); - } - let ret_type = - abi_type::AbiType::from_ir_type(&ty.result).into_specific(ptr_type); - // Result - ctx.func.signature.returns.push(AbiParam::new(ret_type)); - // Error - ctx.func.signature.returns.push(AbiParam::new(ptr_type)); - - { - let mut builder = FunctionBuilder::new(&mut ctx.func, &mut builder_context); - - let name = sy.to_string(); - let name_len = name.len(); - let name_data_id = util::define_string( - &mut module, - &mut defined_strings, - &format!("funcname:{}", sy), - name, - ); - let name_global_value = - module.declare_data_in_func(name_data_id, builder.func); - - let entry_ebb = builder.create_ebb(); - builder.append_ebb_params_for_function_params(entry_ebb); - - let error_throw_ebb = builder.create_ebb(); - let error_unwind_ebb = builder.create_ebb(); - - builder.switch_to_block(entry_ebb); - builder.seal_block(entry_ebb); - - let variables = declare_variables( - elements, - types, - ptr_type, - &mut builder, - &closure.parameters, - &closure.statements, - entry_ebb, - ); - - let result = { - let mut translation_ctx = function::Translator::new( - &mut module, - &mut builder, - constexprs, - elements, - layouts, - locations, - symbols, - types, - ptr_type, - error_throw_ebb, - error_unwind_ebb, - &variables, - &mut defined_strings, - codemap, - ); + fn codegen_all(&mut self) -> error::Result<()> { + for entity in self.db.entities()?.all() { + self.codegen_entity(entity)?; + } - for stmt in &closure.statements { - translation_ctx - .exec_element(*stmt, self.elements.get(*stmt).unwrap()); - } - - translation_ctx.eval_element( - closure.result, - self.elements.get(closure.result).unwrap(), - ) - }; - - let null_error = builder.ins().iconst(ptr_type, 0); - builder.ins().return_(&[result, null_error]); - - let error_kind = builder.append_ebb_param(error_throw_ebb, types::I32); - let error_filename = builder.append_ebb_param(error_throw_ebb, ptr_type); - let error_filename_len = - builder.append_ebb_param(error_throw_ebb, ptr_type); - let error_line = builder.append_ebb_param(error_throw_ebb, types::I32); - let error_col = builder.append_ebb_param(error_throw_ebb, types::I32); - builder.switch_to_block(error_throw_ebb); - builder.seal_block(error_throw_ebb); - - let error = { - let mut translation_ctx = function::Translator::new( - &mut module, - &mut builder, - constexprs, - elements, - layouts, - locations, - symbols, - types, - ptr_type, - error_throw_ebb, - error_unwind_ebb, - &variables, - &mut defined_strings, - codemap, - ); - translation_ctx.builtin_error(error_kind) - }; - builder.ins().jump( - error_unwind_ebb, - &[ - error, - error_filename, - error_filename_len, - error_line, - error_col, - ], - ); - - let error = builder.append_ebb_param(error_unwind_ebb, ptr_type); - let error_filename = builder.append_ebb_param(error_unwind_ebb, ptr_type); - let error_filename_len = - builder.append_ebb_param(error_unwind_ebb, ptr_type); - let error_line = builder.append_ebb_param(error_unwind_ebb, types::I32); - let error_col = builder.append_ebb_param(error_unwind_ebb, types::I32); - builder.switch_to_block(error_unwind_ebb); - builder.seal_block(error_unwind_ebb); - - let name = builder.ins().global_value(ptr_type, name_global_value); - let name_len = builder.ins().iconst(ptr_type, name_len as i64); - - { - let mut translation_ctx = function::Translator::new( - &mut module, - &mut builder, - constexprs, - elements, - layouts, - locations, - symbols, - types, - ptr_type, - error_throw_ebb, - error_unwind_ebb, - &variables, - &mut defined_strings, - codemap, - ); - translation_ctx.builtin_unwind_frame( - error, + for Function { + name, + entity, + ctx, + is_public, + } in &mut self.functions + { + let linkage = if *is_public { + cranelift_module::Linkage::Export + } else { + cranelift_module::Linkage::Local + }; + let func_id = self + .module + .declare_function(name, linkage, &ctx.func.signature) + .unwrap(); + + self.module.define_function(func_id, ctx).unwrap(); + self.module.clear_context(ctx); + + if *is_public { + if let (Some(parent_id), ir::EntityRole::VariableDefinition(func_ident)) = + self.db.lookup_entity(*entity) + { + let (_, parent_role) = self.db.lookup_entity(parent_id); + if let ir::EntityRole::File(file_id) = parent_role { + let func_ident = (*self.db.lookup_ident(func_ident)).clone(); + let file_path = (*self.db.file_relative_path(file_id)).to_owned(); + self.exposed_functions + .insert((file_path, func_ident), func_id); + } else { + debug!( + "not exposing function `{}` because it is not at module level (parent role is {:?})", name, - name_len, - error_filename, - error_filename_len, - error_line, - error_col, + parent_role, ); - }; - - let null_result = if ret_type.is_int() { - builder.ins().iconst(ret_type, 0) - } else if ret_type == types::F32 { - builder.ins().f32const(Ieee32::with_float(0.0)) - } else if ret_type == types::F64 { - builder.ins().f64const(Ieee64::with_float(0.0)) - } else { - unimplemented!() - }; - builder.ins().return_(&[null_result, error]); - - builder.finalize(); - - debug!("generated function: {}", builder.display(None)); } + } else { + debug!("not exposing function `{}` because it is not directly a variable definition", name); + } + } + } + self.module.finalize_definitions(); - let mut result = Vec::new(); + Ok(()) + } - if sy.is_top_level() { - let mut public_ctx: codegen::Context = module.make_context(); - let mut public_builder_context = FunctionBuilderContext::new(); + fn codegen_entity(&mut self, entity: ir::Entity) -> error::Result<()> { + match &*self.db.element(entity)? { + ir::element::Element::Module(ir::element::Module { variables }) => { + for value in variables.values() { + self.codegen_definition(*value, true)?; + } + } + ir::element::Element::Closure(ir::element::Closure { statements, .. }) => { + for statement in statements { + self.codegen_definition(*statement, false)?; + } + } + _ => (), + } + Ok(()) + } - for i in 0..ty.parameters.len() { - public_ctx - .func - .signature - .params - .push(ctx.func.signature.params[i]); - } - // Error pointer - public_ctx - .func - .signature - .params - .push(AbiParam::new(ptr_type)); - - // Result - public_ctx - .func - .signature - .returns - .push(AbiParam::new(ret_type)); - - { - let mut builder = FunctionBuilder::new( - &mut public_ctx.func, - &mut public_builder_context, - ); - let entry_ebb = builder.create_ebb(); - builder.append_ebb_params_for_function_params(entry_ebb); - - let error_ebb = builder.create_ebb(); - - builder.switch_to_block(entry_ebb); - builder.seal_block(entry_ebb); - - let fn_name = sy.to_string(); - let callee = module - .declare_function( - &fn_name, - cranelift_module::Linkage::Local, - &ctx.func.signature, - ) - .unwrap(); - let local_callee = - module.declare_func_in_func(callee, &mut builder.func); - - let (error_out_ptr, parameter_values) = - builder.ebb_params(entry_ebb).split_last().unwrap(); - let error_out_ptr = *error_out_ptr; - let parameter_values = parameter_values.to_vec(); - - let call = builder.ins().call(local_callee, ¶meter_values); - - let results = builder.inst_results(call); - let result = results[0]; - let error = results[1]; - - builder - .ins() - .brnz(error, error_ebb, &[error, error_out_ptr]); - builder.ins().return_(&[result]); - - let error = builder.append_ebb_param(error_ebb, ptr_type); - let error_out_ptr = builder.append_ebb_param(error_ebb, ptr_type); - builder.switch_to_block(error_ebb); - builder.seal_block(error_ebb); - - let null_result = if ret_type.is_int() { - builder.ins().iconst(ret_type, 0) - } else if ret_type == types::F32 { - builder.ins().f32const(Ieee32::with_float(0.0)) - } else if ret_type == types::F64 { - builder.ins().f64const(Ieee64::with_float(0.0)) - } else { - unimplemented!() - }; - - let mut mem_flags = MemFlags::new(); - mem_flags.set_notrap(); - mem_flags.set_aligned(); - builder.ins().store(mem_flags, error, error_out_ptr, 0_i32); - builder.ins().return_(&[null_result]); - - builder.finalize(); + fn codegen_definition(&mut self, entity: ir::Entity, top_level: bool) -> error::Result<()> { + match &*self.db.element(entity)? { + element::Element::Variable(ref variable) => { + let initializer = self.db.element(variable.initializer)?; + match (&*initializer, &*self.db.ty(entity)?) { + (element::Element::Closure(ref closure), ty::Type::Function(ref ty)) => { + let (name, ctx) = self.codegen_function(entity, closure, ty)?; + + if top_level { + let (name, ctx) = self.codegen_public_wrapper_function( + entity, closure, ty, &name, &ctx, + )?; + let is_public = true; + self.functions.push(Function { + name, + entity, + ctx, + is_public, + }); } - result.push((sy.clone().into_public(), public_ctx)); + let is_public = false; + self.functions.push(Function { + name, + entity, + ctx, + is_public, + }); } - result.push((sy.clone(), ctx)); - - result - } else { - Vec::new() + _ => (), } - }) - .collect::>(); - - let mut declared_functions = Vec::new(); - let mut declared_data = Vec::new(); - let mut function_ids = collections::HashMap::new(); - - for (entity, ctx) in data_ctxs { - let data_name = entity.id().to_string(); - let data_id = module - .declare_data(&data_name, cranelift_module::Linkage::Local, false) - .unwrap(); - declared_data.push((data_id, ctx)); + } + _ => (), } - for (sy, ctx) in function_ctxs { - let fn_name = sy.to_string(); - let fn_id = module - .declare_function( - &fn_name, - if sy.is_public() { - cranelift_module::Linkage::Export - } else { - cranelift_module::Linkage::Local - }, - &ctx.func.signature, - ) - .unwrap(); - declared_functions.push((fn_id, ctx)); - if sy.is_public() { - function_ids.insert(fn_name["public:".len()..].to_owned(), fn_id); + Ok(()) + } + + fn codegen_function( + &mut self, + entity: ir::Entity, + closure: &element::Closure, + ty: &ty::Function, + ) -> error::Result<(String, codegen::Context)> { + use cranelift::codegen::ir::InstBuilder; + + let mut ctx = self.module.make_context(); + let ret_type = self.populate_function_signature(ty, &mut ctx, false); + + let mut builder_context = frontend::FunctionBuilderContext::new(); + let mut builder = + cranelift::frontend::FunctionBuilder::new(&mut ctx.func, &mut builder_context); + + let name = Symbol(self.db, entity).to_string(); + let name_len = name.len(); + let name_data_id = util::define_string( + self.module, + &mut self.defined_strings, + &format!("funcname:{}", name), + name.clone(), + ); + let name_global_value = self.module.declare_data_in_func(name_data_id, builder.func); + + let entry_ebb = builder.create_ebb(); + builder.append_ebb_params_for_function_params(entry_ebb); + + let error_throw_ebb = builder.create_ebb(); + let error_unwind_ebb = builder.create_ebb(); + + builder.switch_to_block(entry_ebb); + builder.seal_block(entry_ebb); + + let variables = self.declare_variables( + &mut builder, + &closure.parameters, + &closure.statements, + entry_ebb, + )?; + + let result = { + let mut translation_ctx = function::Translator::new( + self.module, + &mut builder, + self.db, + self.ptr_type, + error_throw_ebb, + error_unwind_ebb, + &variables, + &mut self.defined_strings, + ); + + for stmt in &closure.statements { + translation_ctx.exec_element(*stmt, &*self.db.element(*stmt)?)?; } + + translation_ctx.eval_element(closure.result, &*self.db.element(closure.result)?)? + }; + + let null_error = builder.ins().iconst(self.ptr_type, 0); + builder.ins().return_(&[result, null_error]); + + let error_kind = builder.append_ebb_param(error_throw_ebb, types::I32); + let error_filename = builder.append_ebb_param(error_throw_ebb, self.ptr_type); + let error_filename_len = builder.append_ebb_param(error_throw_ebb, self.ptr_type); + let error_line = builder.append_ebb_param(error_throw_ebb, types::I32); + let error_col = builder.append_ebb_param(error_throw_ebb, types::I32); + builder.switch_to_block(error_throw_ebb); + builder.seal_block(error_throw_ebb); + + let error = { + let mut translation_ctx = function::Translator::new( + self.module, + &mut builder, + self.db, + self.ptr_type, + error_throw_ebb, + error_unwind_ebb, + &variables, + &mut self.defined_strings, + ); + translation_ctx.builtin_error(error_kind) + }; + builder.ins().jump( + error_unwind_ebb, + &[ + error, + error_filename, + error_filename_len, + error_line, + error_col, + ], + ); + + let error = builder.append_ebb_param(error_unwind_ebb, self.ptr_type); + let error_filename = builder.append_ebb_param(error_unwind_ebb, self.ptr_type); + let error_filename_len = builder.append_ebb_param(error_unwind_ebb, self.ptr_type); + let error_line = builder.append_ebb_param(error_unwind_ebb, types::I32); + let error_col = builder.append_ebb_param(error_unwind_ebb, types::I32); + builder.switch_to_block(error_unwind_ebb); + builder.seal_block(error_unwind_ebb); + + let name_value = builder.ins().global_value(self.ptr_type, name_global_value); + let name_len_value = builder.ins().iconst(self.ptr_type, name_len as i64); + + { + let mut translation_ctx = function::Translator::new( + self.module, + &mut builder, + self.db, + self.ptr_type, + error_throw_ebb, + error_unwind_ebb, + &variables, + &mut self.defined_strings, + ); + translation_ctx.builtin_unwind_frame( + error, + name_value, + name_len_value, + error_filename, + error_filename_len, + error_line, + error_col, + ); + }; + + let null_result = >::default_value(ret_type, &mut builder); + builder.ins().return_(&[null_result, error]); + + builder.finalize(); + + debug!( + "generated function `{}`:\n\n{}", + name, + builder.display(None) + ); + Ok((name, ctx)) + } + + fn codegen_public_wrapper_function( + &mut self, + entity: ir::Entity, + closure: &element::Closure, + ty: &ty::Function, + wrapped_name: &str, + wrapped: &codegen::Context, + ) -> error::Result<(String, codegen::Context)> { + use cranelift::codegen::ir::InstBuilder; + + let mut ctx: codegen::Context = self.module.make_context(); + let mut builder_context = frontend::FunctionBuilderContext::new(); + + let name = format!("public:{}", Symbol(self.db, entity)); + let ret_type = self.populate_function_signature(ty, &mut ctx, true); + + let mut builder = + cranelift::frontend::FunctionBuilder::new(&mut ctx.func, &mut builder_context); + let entry_ebb = builder.create_ebb(); + builder.append_ebb_params_for_function_params(entry_ebb); + + let error_ebb = builder.create_ebb(); + + builder.switch_to_block(entry_ebb); + builder.seal_block(entry_ebb); + + let callee = self + .module + .declare_function( + wrapped_name, + cranelift_module::Linkage::Local, + &wrapped.func.signature, + ) + .unwrap(); + let local_callee = self.module.declare_func_in_func(callee, &mut builder.func); + + let (error_out_ptr, parameter_values) = builder.ebb_params(entry_ebb).split_last().unwrap(); + let error_out_ptr = *error_out_ptr; + let parameter_values = parameter_values.to_vec(); + + let call = builder.ins().call(local_callee, ¶meter_values); + + let results = builder.inst_results(call); + let result = results[0]; + let error = results[1]; + + builder + .ins() + .brnz(error, error_ebb, &[error, error_out_ptr]); + builder.ins().return_(&[result]); + + let error = builder.append_ebb_param(error_ebb, self.ptr_type); + let error_out_ptr = builder.append_ebb_param(error_ebb, self.ptr_type); + builder.switch_to_block(error_ebb); + builder.seal_block(error_ebb); + + let null_result = >::default_value(ret_type, &mut builder); + + let mut mem_flags = codegen::ir::MemFlags::new(); + mem_flags.set_notrap(); + mem_flags.set_aligned(); + builder.ins().store(mem_flags, error, error_out_ptr, 0_i32); + builder.ins().return_(&[null_result]); + + builder.finalize(); + + debug!( + "generated public wrapper function `{}`:\n\n{}", + name, + builder.display(None) + ); + + Ok((name, ctx)) + } + + fn default_value( + ret_type: codegen::ir::Type, + builder: &mut frontend::FunctionBuilder, + ) -> codegen::ir::Value { + use cranelift::codegen::ir::InstBuilder; + + if ret_type.is_int() { + builder.ins().iconst(ret_type, 0) + } else if ret_type == types::F32 { + builder.ins().f32const(immediates::Ieee32::with_float(0.0)) + } else if ret_type == types::F64 { + builder.ins().f64const(immediates::Ieee64::with_float(0.0)) + } else { + unimplemented!() } + } - for (id, data_ctx) in declared_data { - module.define_data(id, &data_ctx).unwrap(); + fn populate_function_signature( + &mut self, + ty: &ty::Function, + ctx: &mut codegen::Context, + is_public: bool, + ) -> codegen::ir::Type { + for parameter in &ty.parameters { + ctx.func.signature.params.push(codegen::ir::AbiParam::new( + abi_type::AbiType::from_ir_type(parameter).into_specific(self.ptr_type), + )); } - for (id, mut function_ctx) in declared_functions { - module.define_function(id, &mut function_ctx).unwrap(); - module.clear_context(&mut function_ctx); + let ret_type = abi_type::AbiType::from_ir_type(&ty.result).into_specific(self.ptr_type); + // Result + ctx.func + .signature + .returns + .push(codegen::ir::AbiParam::new(ret_type)); + + // Error: if the function is public, pass in error pointer; else, use multiple return values + if is_public { + ctx.func + .signature + .params + .push(codegen::ir::AbiParam::new(self.ptr_type)); + } else { + ctx.func + .signature + .returns + .push(codegen::ir::AbiParam::new(self.ptr_type)) } - module.finalize_definitions(); + ret_type + } - module::Module::new(module, function_ids) + fn codegen_data(&mut self, entity: ir::Entity) -> error::Result>> { + if let Some(value) = self.db.value(entity)? { + let layout = self.db.layout(entity)?; + let mut ctx = cranelift_module::DataContext::new(); + let mut data = Vec::new(); + data::Translator::new(&mut data, self.ptr_type).store_value(&*layout, &value); + ctx.define(data.into_boxed_slice()); + Ok(Some(sync::Arc::new(Data { ctx }))) + } else { + Ok(None) + } } -} -impl<'a> fmt::Debug for Codegen<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Codegen").finish() + fn declare_variables( + &mut self, + builder: &mut cranelift::frontend::FunctionBuilder, + params: &[ir::Entity], + statements: &[ir::Entity], + entry_ebb: codegen::ir::Ebb, + ) -> error::Result> { + let mut next_var = 0; + let mut variables = collections::HashMap::new(); + + for (i, param) in params.iter().enumerate() { + let param_initializer = builder.ebb_params(entry_ebb)[i]; + let var = self.declare_variable(builder, &mut variables, &mut next_var, *param)?; + builder.def_var(var, param_initializer); + } + + for statement in statements { + self.declare_variables_in_element(builder, &mut variables, &mut next_var, *statement)?; + } + + Ok(variables) } -} -fn declare_variables( - elements: &specs::ReadStorage, - types: &specs::ReadStorage, - ptr_type: Type, - builder: &mut FunctionBuilder, - params: &[specs::Entity], - statements: &[specs::Entity], - entry_ebb: Ebb, -) -> collections::HashMap { - let mut next_var = 0; - let mut variables = collections::HashMap::new(); - - for (i, param) in params.iter().enumerate() { - let param_initializer = builder.ebb_params(entry_ebb)[i]; - let var = declare_variable( - types, - ptr_type, - builder, - &mut variables, - &mut next_var, - *param, - ); - builder.def_var(var, param_initializer); + fn declare_variables_in_element( + &mut self, + builder: &mut cranelift::frontend::FunctionBuilder, + variables: &mut collections::HashMap, + next_var: &mut u32, + entity: ir::Entity, + ) -> error::Result<()> { + if let element::Element::Variable(_) = *self.db.element(entity)? { + self.declare_variable(builder, variables, next_var, entity)?; + } + Ok(()) } - for statement in statements { - declare_variables_in_element( - elements, - types, - ptr_type, - builder, - &mut variables, - &mut next_var, - *statement, - ); + fn declare_variable( + &mut self, + builder: &mut cranelift::frontend::FunctionBuilder, + variables: &mut collections::HashMap, + next_var: &mut u32, + entity: ir::Entity, + ) -> error::Result { + let ty = self.db.ty(entity)?; + Ok(*variables.entry(entity).or_insert_with(|| { + let var = cranelift::frontend::Variable::with_u32(*next_var); + *next_var += 1; + builder.declare_var( + var, + abi_type::AbiType::from_ir_type(&*ty).into_specific(self.ptr_type), + ); + var + })) } +} - variables +impl fmt::Debug for Function { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Function").finish() + } } -fn declare_variables_in_element( - elements: &specs::ReadStorage, - types: &specs::ReadStorage, - ptr_type: Type, - builder: &mut FunctionBuilder, - variables: &mut collections::HashMap, - next_var: &mut usize, - entity: specs::Entity, -) { - if let element::Element::Variable(_) = *elements.get(entity).unwrap() { - declare_variable(types, ptr_type, builder, variables, next_var, entity); +impl fmt::Debug for Data { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Data").finish() } } -fn declare_variable( - types: &specs::ReadStorage, - ptr_type: Type, - builder: &mut FunctionBuilder, - variables: &mut collections::HashMap, - next_var: &mut usize, - entity: specs::Entity, -) -> Variable { - *variables.entry(entity).or_insert_with(|| { - let var = Variable::new(*next_var); - *next_var += 1; - builder.declare_var( - var, - abi_type::AbiType::from_ir_type(types.get(entity).unwrap()).into_specific(ptr_type), - ); - var - }) +impl<'d, D> fmt::Display for Symbol<'d, D> +where + D: Db, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + symbol_fmt_impl(self.1, f, self.0) + } } -fn as_closure<'a, 'b>( - element: &'a element::Element, - ty: &'b ty::Type, -) -> Option<(&'a element::Closure, &'b ty::Function)> { - match (element, ty) { - (element::Element::Closure(c), ty::Type::Function(f)) => Some((c, f)), - _ => None, +fn symbol_fmt_impl(entity: ir::Entity, f: &mut fmt::Formatter, db: &impl Db) -> fmt::Result { + let (parent, role) = db.lookup_entity(entity); + + if let Some(parent) = parent { + symbol_fmt_impl(parent, f, db)?; + write!(f, ".")?; + } + + match role { + ir::EntityRole::File(file_id) => write!(f, "{:?}", db.file_relative_path(file_id)), + ir::EntityRole::RecordField(ident) => write!(f, "{}", db.lookup_ident(ident)), + ir::EntityRole::TupleField(idx) => write!(f, "{}", idx), + ir::EntityRole::VariableDefinition(ident) => write!(f, "{}", db.lookup_ident(ident)), + ir::EntityRole::VariableInitializer => write!(f, "(initializer)"), + ir::EntityRole::SelectField(ident) => write!(f, "{}", db.lookup_ident(ident)), + ir::EntityRole::AppliedFunction => write!(f, "(applied function)"), + ir::EntityRole::AppliedParameter(idx) => write!(f, "(parameter {})", idx), + ir::EntityRole::ParameterSignature => write!(f, "(signature)"), + ir::EntityRole::ClosureCaptureDefinition(ident) => { + write!(f, "(capture definition {})", db.lookup_ident(ident)) + } + ir::EntityRole::ClosureParameter(ident) => { + write!(f, "(parameter definition {})", db.lookup_ident(ident)) + } + ir::EntityRole::ClosureStatement(idx) => write!(f, "(statement {})", idx), + ir::EntityRole::ClosureSignature => write!(f, "(signature)"), + ir::EntityRole::ClosureResult => write!(f, "(result expression)"), + ir::EntityRole::UnOperand => write!(f, "(operand)"), + ir::EntityRole::BiLhs => write!(f, "(left operand)"), + ir::EntityRole::BiRhs => write!(f, "(right operand)"), } } diff --git a/src/codegen/tests.rs b/src/codegen/tests.rs index 4f6bdff..d4c7b52 100644 --- a/src/codegen/tests.rs +++ b/src/codegen/tests.rs @@ -2,8 +2,9 @@ use env_logger; use failure; use super::*; -use crate::ast; use crate::ir; +use crate::source; +use crate::syntax::ast; use crate::test_util; #[test] @@ -16,7 +17,9 @@ main = || -> u32 { 42u32 }; let mut module = compile_module("immediate", source)?; - let main = module.function::>("main").unwrap(); + let main = module + .function::, _>("immediate", "main") + .unwrap(); let result = main.call(); assert_eq!(Ok(42), result); @@ -33,7 +36,9 @@ main = || -> u32 { a = 43u32; a }; let mut module = compile_module("variable", source)?; - let main = module.function::>("main").unwrap(); + let main = module + .function::, _>("variable", "main") + .unwrap(); let result = main.call(); assert_eq!(Ok(43), result); @@ -51,7 +56,7 @@ main = |a: u32| -> u32 { a }; let mut module = compile_module("parameter1", source)?; let main = module - .function::>("main") + .function::, _>("parameter1", "main") .unwrap(); let result = main.call(43); @@ -70,7 +75,7 @@ main = |a: u32, b: u32| -> u32 { b }; let mut module = compile_module("parameter2", source)?; let main = module - .function::>("main") + .function::, _>("parameter2", "main") .unwrap(); let result = main.call(1, 43); @@ -89,7 +94,7 @@ main = |a: u32, b: u32, c: u32| -> u32 { c }; let mut module = compile_module("parameter3", source)?; let main = module - .function::>("main") + .function::, _>("parameter3", "main") .unwrap(); let result = main.call(1, 2, 43); @@ -108,7 +113,7 @@ main = |a: u32, b: u32, c: u32, d: u32| -> u32 { d }; let mut module = compile_module("parameter4", source)?; let main = module - .function::>("main") + .function::, _>("parameter4", "main") .unwrap(); let result = main.call(1, 2, 3, 43); @@ -127,7 +132,7 @@ main = |a: u32, b: u32, c: u32, d: u32, e: u32| -> u32 { e }; let mut module = compile_module("parameter5", source)?; let main = module - .function::>("main") + .function::, _>("parameter5", "main") .unwrap(); let result = main.call(1, 2, 3, 4, 43); @@ -146,7 +151,7 @@ main = |a: u32, b: u32, c: u32, d: u32, e: u32, f: u32| -> u32 { f }; let mut module = compile_module("parameter6", source)?; let main = module - .function::>("main") + .function::, _>("parameter6", "main") .unwrap(); let result = main.call(1, 2, 3, 4, 5, 43); @@ -166,7 +171,7 @@ main = |y: u32| -> u32 { a = other(y); other(other(a)) }; let mut module = compile_module("apply", source)?; let main = module - .function::>("main") + .function::, _>("apply", "main") .unwrap(); let result = main.call(43); @@ -184,7 +189,9 @@ main = || -> u32 { a = { x: 1u32, y: 2u32, z: 3u32}; a.y }; let mut module = compile_module("record", source)?; - let main = module.function::>("main").unwrap(); + let main = module + .function::, _>("record", "main") + .unwrap(); let result = main.call(); assert_eq!(Ok(2), result); @@ -201,7 +208,9 @@ main = || -> u32 { a = 1u32; b = 2u32; (a * 24u32 + b * 3u32) / 10u32 }; let mut module = compile_module("operators_u32", source)?; - let main = module.function::>("main").unwrap(); + let main = module + .function::, _>("operators_u32", "main") + .unwrap(); let result = main.call(); assert_eq!(Ok(3), result); @@ -218,7 +227,9 @@ main = || -> f32 { a = 1f32; b = 2f32; (a * 24f32 + b * 3f32) / 10f32 }; let mut module = compile_module("operators_f32", source)?; - let main = module.function::>("main").unwrap(); + let main = module + .function::, _>("operators_f32", "main") + .unwrap(); let result = main.call(); assert_eq!(Ok(3.0), result); @@ -235,7 +246,9 @@ main = || -> f64 { a = 1f64; b = 2f64; (a * 24f64 + b * 3f64) / 10f64 }; let mut module = compile_module("operators_f64", source)?; - let main = module.function::>("main").unwrap(); + let main = module + .function::, _>("operators_f64", "main") + .unwrap(); let result = main.call(); assert_eq!(Ok(3.0), result); @@ -252,7 +265,9 @@ main = || -> u32 { a = 1u32; b = 2u32; a + b }; let mut module = compile_module("add_u32", source)?; - let main = module.function::>("main").unwrap(); + let main = module + .function::, _>("add_u32", "main") + .unwrap(); let result = main.call(); assert_eq!(Ok(3), result); @@ -269,7 +284,9 @@ main = || -> i32 { a = 1i32; b = 2i32; a + b }; let mut module = compile_module("add_i32", source)?; - let main = module.function::>("main").unwrap(); + let main = module + .function::, _>("add_i32", "main") + .unwrap(); let result = main.call(); assert_eq!(Ok(3), result); @@ -286,7 +303,9 @@ main = || -> f32 { a = 1f32; b = 2f32; a + b }; let mut module = compile_module("add_f32", source)?; - let main = module.function::>("main").unwrap(); + let main = module + .function::, _>("add_f32", "main") + .unwrap(); let result = main.call(); assert_eq!(Ok(3.0), result); @@ -303,7 +322,9 @@ main = || -> u32 { a = 2u32; b = 1u32; a - b }; let mut module = compile_module("sub_u32", source)?; - let main = module.function::>("main").unwrap(); + let main = module + .function::, _>("sub_u32", "main") + .unwrap(); let result = main.call(); assert_eq!(Ok(1), result); @@ -320,7 +341,9 @@ main = || -> i32 { a = 1i32; b = 2i32; a - b }; let mut module = compile_module("sub_i32", source)?; - let main = module.function::>("main").unwrap(); + let main = module + .function::, _>("sub_i32", "main") + .unwrap(); let result = main.call(); assert_eq!(Ok(-1), result); @@ -337,7 +360,9 @@ main = || -> f32 { a = 2f32; b = 1f32; a - b }; let mut module = compile_module("sub_f32", source)?; - let main = module.function::>("main").unwrap(); + let main = module + .function::, _>("sub_f32", "main") + .unwrap(); let result = main.call(); assert_eq!(Ok(1.0), result); @@ -345,19 +370,34 @@ main = || -> f32 { a = 2f32; b = 1f32; a - b }; } fn compile_module(name: &'static str, source: &str) -> Result { - use crate::parser::Parse; + use crate::codegen::Db as _; + use crate::codegen::Db as _; + use crate::layout::Db as _; + use crate::source::Db as _; + use crate::ty::Db as _; let mut codemap = codespan::CodeMap::new(); - let span = codemap - .add_filemap(codespan::FileName::Virtual(name.into()), source.to_owned()) - .span(); - let ast_module = ast::Module::parse(span, source)?; - let mut ir = ir::Ir::new(); - ir.load(&ast_module)?; - ir.check_types()?; - test_util::render_graph(&format!(concat!(module_path!(), "::{}"), name), &ir)?; - let compiler = Codegen::new(&ir, &codemap); - let module = compiler.compile(); + codemap.add_filemap(codespan::FileName::Virtual(name.into()), source.to_owned()); + + let root_id = source::RootId(1); + let file_id = source::FileId(1); + let path = relative_path::RelativePath::new(name).to_owned(); + let mut files = collections::HashMap::new(); + files.insert(path.clone(), file_id); + let root = source::Root { files }; + + let mut db = db::Db::new(); + + db.set_file_text(file_id, sync::Arc::new(source.to_owned())); + db.set_file_relative_path(file_id, path); + db.set_file_source_root(file_id, root_id); + db.set_source_root(root_id, sync::Arc::new(root)); + db.set_all_source_roots(sync::Arc::new(vec![root_id])); + db.set_ptr_size(layout::PtrSize::Size64); + + let module = (*db.codegen()?).clone(); + + test_util::render_graph(&format!(concat!(module_path!(), "::{}"), name), &db).unwrap(); Ok(module) } diff --git a/src/codegen/util.rs b/src/codegen/util.rs index d641d33..a595824 100644 --- a/src/codegen/util.rs +++ b/src/codegen/util.rs @@ -1,14 +1,17 @@ use std::collections; -pub fn define_string( - module: &mut cranelift_module::Module, +pub fn define_string( + module: &mut cranelift_module::Module, defined_strings: &mut collections::HashMap, name: &str, string: String, -) -> cranelift_module::DataId { +) -> cranelift_module::DataId +where + B: cranelift_module::Backend, +{ *defined_strings.entry(name.to_owned()).or_insert_with(|| { let data_id = module - .declare_data(&name, cranelift_module::Linkage::Local, false) + .declare_data(&name, cranelift_module::Linkage::Local, false, None) .unwrap(); let mut ctx = cranelift_module::DataContext::new(); diff --git a/src/db.rs b/src/db.rs new file mode 100644 index 0000000..e88a2a2 --- /dev/null +++ b/src/db.rs @@ -0,0 +1,33 @@ +use crate::codegen; +use crate::interpreter; +use crate::ir; +use crate::layout; +use crate::source; +use crate::syntax; +use crate::ty; + +#[salsa::database( + codegen::CodegenStorage, + interpreter::InterpreterStorage, + ir::IrStorage, + layout::LayoutStorage, + source::SourceStorage, + syntax::SyntaxStorage, + ty::TyStorage +)] +#[derive(Debug, Default)] +pub struct Db { + runtime: salsa::Runtime, +} + +impl Db { + pub fn new() -> Self { + Self::default() + } +} + +impl salsa::Database for Db { + fn salsa_runtime(&self) -> &salsa::Runtime { + &self.runtime + } +} diff --git a/src/error.rs b/src/error.rs index d6d93a4..694ef14 100644 --- a/src/error.rs +++ b/src/error.rs @@ -4,10 +4,10 @@ use std::result; use crate::diagnostic; use crate::interpreter; use crate::ir; -use crate::parser; +use crate::syntax::parser; /// An error that occurs while interacting with Tin. -#[derive(Clone, Debug, Fail, PartialEq)] +#[derive(Clone, Debug, failure::Fail, PartialEq)] pub enum Error { /// Interpreting the code failed. /// @@ -19,7 +19,7 @@ pub enum Error { #[fail(display = "IR error")] Ir(#[cause] ir::error::Error), /// Parsing the source code failed. - #[fail(display = "parser error")] + #[fail(display = "syntax error")] Parser(#[cause] parser::Error), } diff --git a/src/graph.rs b/src/graph.rs index a4b8be7..130c570 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -6,234 +6,59 @@ use std::borrow; use std::fmt; use dot; -use specs; +use crate::db; use crate::ir; -use crate::ir::component::element; -use crate::ir::component::layout; -use crate::ir::component::symbol; -use crate::ir::component::ty; +use crate::ir::element; /// A graph representation of IR. pub struct Graph<'a> { - entities: specs::Entities<'a>, - elements: specs::ReadStorage<'a, element::Element>, - layouts: specs::ReadStorage<'a, layout::Layout>, - symbols: specs::ReadStorage<'a, symbol::Symbol>, - types: specs::ReadStorage<'a, ty::Type>, + db: &'a db::Db, } /// A node in the IR graph. #[derive(Clone, Copy, Debug)] -pub struct Node(specs::Entity); +pub struct Node(ir::Entity); /// An edge in the IR graph. #[derive(Clone, Copy, Debug)] -pub struct Edge<'a> { +pub struct Edge { source: Node, target: Node, - label: Label<'a>, -} - -#[derive(Clone, Copy, Debug)] -enum Label<'a> { - RecordField(&'a str), - TupleField(usize), - VariableInitializer, - SelectField(&'a str), - AppliedFunction, - AppliedParameter(usize), - ParameterSignature, - ClosureCaptureDefinition(&'a str), - ClosureCaptureUsage(&'a str), - ClosureParameter(usize), - ClosureStatement(usize), - ClosureSignature, - ClosureResult, - ModuleDefinition(&'a str), - UnOperand, - BiLhs, - BiRhs, + role: ir::EntityRole, } impl<'a> Graph<'a> { /// Creates a new IR graph based on the supplied intermediate representation. - pub(crate) fn new(ir: &'a ir::Ir) -> Graph<'a> { - let world = &ir.world; - let entities = world.entities(); - let elements = world.read_storage(); - let layouts = world.read_storage(); - let symbols = world.read_storage(); - let types = world.read_storage(); - - Graph { - entities, - elements, - layouts, - symbols, - types, - } + pub(crate) fn new(db: &'a db::Db) -> Graph<'a> { + Graph { db } } } -impl<'a> dot::GraphWalk<'a, Node, Edge<'a>> for Graph<'a> { +impl<'a> dot::GraphWalk<'a, Node, Edge> for Graph<'a> { fn nodes(&'a self) -> borrow::Cow<'a, [Node]> { - use specs::Join; + use crate::ir::Db; - borrow::Cow::Owned( - self.entities - .join() - .filter_map(|e| { - if self.elements.contains(e) { - Some(Node(e)) - } else { - None - } - }) - .collect::>(), - ) + let entities = self.db.entities().unwrap(); + borrow::Cow::Owned(entities.all().map(Node).collect()) } - fn edges(&'a self) -> borrow::Cow<'a, [Edge<'a>]> { - use specs::Join; + fn edges(&'a self) -> borrow::Cow<'a, [Edge]> { + use crate::ir::Db; let mut edges = Vec::new(); - for entity in self.entities.join() { - if let Some(element) = self.elements.get(entity) { - match element { - element::Element::Number(_) - | element::Element::String(_) - | element::Element::Symbol(_) => {} - element::Element::Tuple(element::Tuple { fields }) => { - for (idx, field) in fields.iter().enumerate() { - edges.push(Edge { - source: Node(entity), - target: Node(*field), - label: Label::TupleField(idx), - }); - } - } - element::Element::Record(element::Record { fields }) => { - for (name, field) in fields { - edges.push(Edge { - source: Node(entity), - target: Node(*field), - label: Label::RecordField(name), - }); - } - } - element::Element::UnOp(element::UnOp { operand, .. }) => { - edges.push(Edge { - source: Node(entity), - target: Node(*operand), - label: Label::UnOperand, - }); - } - element::Element::BiOp(element::BiOp { lhs, rhs, .. }) => { - edges.push(Edge { - source: Node(entity), - target: Node(*lhs), - label: Label::BiLhs, - }); - edges.push(Edge { - source: Node(entity), - target: Node(*rhs), - label: Label::BiRhs, - }); - } - element::Element::Variable(element::Variable { initializer, .. }) => edges - .push(Edge { - source: Node(entity), - target: Node(*initializer), - label: Label::VariableInitializer, - }), - element::Element::Select(element::Select { record, field }) => { - edges.push(Edge { - source: Node(entity), - target: Node(*record), - label: Label::SelectField(field), - }); - } - element::Element::Apply(element::Apply { - function, - parameters, - }) => { - edges.push(Edge { - source: Node(entity), - target: Node(*function), - label: Label::AppliedFunction, - }); - for (idx, parameter) in parameters.iter().enumerate() { - edges.push(Edge { - source: Node(entity), - target: Node(*parameter), - label: Label::AppliedParameter(idx), - }); - } - } - element::Element::Parameter(element::Parameter { signature, .. }) => { - edges.push(Edge { - source: Node(entity), - target: Node(*signature), - label: Label::ParameterSignature, - }); - } - element::Element::Capture(element::Capture { ref name, captured }) => edges - .push(Edge { - source: Node(entity), - target: Node(*captured), - label: Label::ClosureCaptureDefinition(name), - }), - element::Element::Closure(element::Closure { - captures, - parameters, - statements, - signature, - result, - }) => { - for (name, capture) in captures { - edges.push(Edge { - source: Node(entity), - target: Node(*capture), - label: Label::ClosureCaptureUsage(name), - }); - } - for (idx, parameter) in parameters.iter().enumerate() { - edges.push(Edge { - source: Node(entity), - target: Node(*parameter), - label: Label::ClosureParameter(idx), - }); - } - for (idx, statement) in statements.iter().enumerate() { - edges.push(Edge { - source: Node(entity), - target: Node(*statement), - label: Label::ClosureStatement(idx), - }); - } - edges.push(Edge { - source: Node(entity), - target: Node(*signature), - label: Label::ClosureSignature, - }); - edges.push(Edge { - source: Node(entity), - target: Node(*result), - label: Label::ClosureResult, - }); - } - element::Element::Module(element::Module { variables }) => { - for (name, variable) in variables { - edges.push(Edge { - source: Node(entity), - target: Node(*variable), - label: Label::ModuleDefinition(name), - }); - } - } - } + let entities = self.db.entities().unwrap(); + for child in entities.all() { + let (parent, role) = self.db.lookup_entity(child); + if let Some(parent) = parent { + let source = Node(parent); + let target = Node(child); + edges.push(Edge { + source, + target, + role, + }); } } @@ -249,7 +74,7 @@ impl<'a> dot::GraphWalk<'a, Node, Edge<'a>> for Graph<'a> { } } -impl<'a> dot::Labeller<'a, Node, Edge<'a>> for Graph<'a> { +impl<'a> dot::Labeller<'a, Node, Edge> for Graph<'a> { fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("ir").unwrap() } @@ -263,16 +88,20 @@ impl<'a> dot::Labeller<'a, Node, Edge<'a>> for Graph<'a> { } fn node_label(&'a self, n: &Node) -> dot::LabelText<'a> { + use crate::ir::Db as _; + use crate::layout::Db as _; + use crate::ty::Db as _; use std::fmt::Write; let mut result = format!("({}) ", n.0.id()); - if let Some(element) = self.elements.get(n.0) { - match element { + if let Ok(element) = self.db.element(n.0) { + match &*element { + element::Element::Reference(e) => write!(result, "ref {:?}", e).unwrap(), element::Element::Number(n) => write!(result, "num {:?}", n).unwrap(), element::Element::String(s) => write!(result, "str {:?}", s).unwrap(), - element::Element::Symbol(element::Symbol { ref label }) => { - write!(result, "sym {:?}", label).unwrap() + element::Element::Symbol(element::Symbol { label }) => { + write!(result, "sym {:?}", self.db.lookup_ident(*label)).unwrap() } element::Element::Tuple(element::Tuple { fields }) => { write!(result, "tuple
{:?} fields", fields.len()).unwrap() @@ -287,7 +116,7 @@ impl<'a> dot::Labeller<'a, Node, Edge<'a>> for Graph<'a> { write!(result, "bi op {}", operator).unwrap() } element::Element::Variable(element::Variable { name, .. }) => { - write!(result, "variable {:?}", name).unwrap() + write!(result, "variable {:?}", self.db.lookup_ident(*name)).unwrap() } element::Element::Select(element::Select { .. }) => { write!(result, "select").unwrap() @@ -296,10 +125,10 @@ impl<'a> dot::Labeller<'a, Node, Edge<'a>> for Graph<'a> { write!(result, "apply
{:?} params", parameters.len()).unwrap() } element::Element::Parameter(element::Parameter { name, .. }) => { - write!(result, "param {:?}", name).unwrap() + write!(result, "param {:?}", self.db.lookup_ident(*name)).unwrap() } element::Element::Capture(element::Capture { name, .. }) => { - write!(result, "capture {:?}", name).unwrap() + write!(result, "capture {:?}", self.db.lookup_ident(*name)).unwrap() } element::Element::Closure(element::Closure { captures, @@ -324,82 +153,69 @@ impl<'a> dot::Labeller<'a, Node, Edge<'a>> for Graph<'a> { write!(result, "(unknown)").unwrap(); }; - if let Some(ty) = self.types.get(n.0) { + if let Ok(ty) = self.db.ty(n.0) { write!(result, "
{}", ty).unwrap(); } - if let Some(layout) = self.layouts.get(n.0) { + if let Ok(layout) = self.db.layout(n.0) { write!(result, "
{}", layout).unwrap(); } - if let Some(symbol) = self.symbols.get(n.0) { - if symbol.is_empty() { - write!(result, "
(root)").unwrap(); - } else { - write!(result, "
{}", symbol).unwrap(); - } - } - dot::LabelText::HtmlStr(result.into()) } - fn edge_label(&'a self, e: &Edge<'a>) -> dot::LabelText<'a> { - match e.label { - Label::RecordField(ref name) => { - dot::LabelText::HtmlStr(format!("field {}", name).into()) + fn edge_label(&'a self, e: &Edge) -> dot::LabelText<'a> { + use crate::ir::Db as _; + use crate::source::Db as _; + + match e.role { + ir::EntityRole::File(file_id) => dot::LabelText::HtmlStr( + format!("file {:?}", self.db.file_relative_path(file_id)).into(), + ), + ir::EntityRole::RecordField(ident) => dot::LabelText::HtmlStr( + format!("field {:?}", self.db.lookup_ident(ident)).into(), + ), + ir::EntityRole::TupleField(idx) => { + dot::LabelText::HtmlStr(format!("field {:?}", idx).into()) } - Label::TupleField(idx) => { - dot::LabelText::HtmlStr(format!("field {}", idx).into()) + ir::EntityRole::VariableDefinition(ident) => dot::LabelText::HtmlStr( + format!("def {:?}", self.db.lookup_ident(ident)).into(), + ), + ir::EntityRole::VariableInitializer => dot::LabelText::HtmlStr("init".into()), + ir::EntityRole::SelectField(ident) => dot::LabelText::HtmlStr( + format!("select {:?}", self.db.lookup_ident(ident)).into(), + ), + ir::EntityRole::AppliedFunction => dot::LabelText::HtmlStr("fun".into()), + ir::EntityRole::AppliedParameter(idx) => { + dot::LabelText::HtmlStr(format!("param {:?}", idx).into()) } - Label::VariableInitializer => dot::LabelText::LabelStr("initializer".into()), - Label::SelectField(ref name) => { - dot::LabelText::HtmlStr(format!("select {}", name).into()) + ir::EntityRole::ParameterSignature => dot::LabelText::HtmlStr("sig".into()), + ir::EntityRole::ClosureCaptureDefinition(ident) => dot::LabelText::HtmlStr( + format!("capture {:?}", self.db.lookup_ident(ident)).into(), + ), + ir::EntityRole::ClosureParameter(ident) => dot::LabelText::HtmlStr( + format!("param {:?}", self.db.lookup_ident(ident)).into(), + ), + ir::EntityRole::ClosureStatement(idx) => { + dot::LabelText::HtmlStr(format!("stmt {:?}", idx).into()) } - Label::AppliedFunction => dot::LabelText::LabelStr("func".into()), - Label::AppliedParameter(idx) => { - dot::LabelText::HtmlStr(format!("apply param {}", idx).into()) - } - Label::ParameterSignature => dot::LabelText::LabelStr("param sig".into()), - Label::ClosureCaptureDefinition(ref name) => { - dot::LabelText::HtmlStr(format!("capture definition {}", name).into()) - } - Label::ClosureCaptureUsage(idx) => { - dot::LabelText::HtmlStr(format!("capture usage {}", idx).into()) - } - Label::ClosureParameter(idx) => { - dot::LabelText::HtmlStr(format!("closure param {}", idx).into()) - } - Label::ClosureStatement(idx) => { - dot::LabelText::HtmlStr(format!("closure stmt {}", idx).into()) - } - Label::ClosureResult => dot::LabelText::HtmlStr("closure result".into()), - Label::ClosureSignature => dot::LabelText::LabelStr("closure sig".into()), - Label::ModuleDefinition(ref name) => { - dot::LabelText::HtmlStr(format!("def {}", name).into()) - } - Label::UnOperand => dot::LabelText::LabelStr("operand".into()), - Label::BiLhs => dot::LabelText::LabelStr("lhs".into()), - Label::BiRhs => dot::LabelText::LabelStr("rhs".into()), + ir::EntityRole::ClosureSignature => dot::LabelText::HtmlStr("sig".into()), + ir::EntityRole::ClosureResult => dot::LabelText::HtmlStr("result".into()), + ir::EntityRole::UnOperand => dot::LabelText::HtmlStr("op".into()), + ir::EntityRole::BiLhs => dot::LabelText::HtmlStr("lhs".into()), + ir::EntityRole::BiRhs => dot::LabelText::HtmlStr("rhs".into()), } } - fn edge_style(&'a self, e: &Edge<'a>) -> dot::Style { - match e.label { - Label::RecordField(_) - | Label::TupleField(_) - | Label::VariableInitializer - | Label::SelectField(_) - | Label::AppliedFunction - | Label::AppliedParameter(_) - | Label::ClosureCaptureUsage(_) - | Label::ClosureParameter(_) - | Label::ClosureResult - | Label::ModuleDefinition(_) - | Label::UnOperand - | Label::BiLhs - | Label::BiRhs => dot::Style::None, - Label::ParameterSignature | Label::ClosureSignature => dot::Style::Dotted, - Label::ClosureCaptureDefinition(_) | Label::ClosureStatement(_) => dot::Style::Dashed, + fn edge_style(&'a self, e: &Edge) -> dot::Style { + match e.role { + ir::EntityRole::ParameterSignature | ir::EntityRole::ClosureSignature => { + dot::Style::Dotted + } + ir::EntityRole::ClosureCaptureDefinition(_) | ir::EntityRole::ClosureStatement(_) => { + dot::Style::Dashed + } + _ => dot::Style::None, } } } diff --git a/src/interpreter/error.rs b/src/interpreter/error.rs index f5d88a5..05ca8a0 100644 --- a/src/interpreter/error.rs +++ b/src/interpreter/error.rs @@ -1,21 +1,28 @@ use crate::diagnostic; +use crate::ir; use crate::module; +use std::result; -#[derive(Clone, Debug, Fail, PartialEq)] +#[derive(Clone, Debug, Eq, failure::Fail, PartialEq)] pub enum Error { + #[fail(display = "semantic error: {}", _0)] + Ir(#[cause] ir::error::Error), #[fail(display = "type conflict: {}", _0)] RuntimeTypeConflict(String), #[fail(display = "evaluation error: {}", _0)] - EvaluationError(#[cause] module::Error), + Evaluation(#[cause] module::Error), } +pub type Result
= result::Result; + impl diagnostic::Diagnostics for Error { fn to_diagnostics(&self, builder: &mut diagnostic::DiagnosticsBuilder) { match *self { + Error::Ir(_) => {} Error::RuntimeTypeConflict(ref cause) => { builder.add_diagnostic(codespan_reporting::Severity::Bug, None, cause); } - Error::EvaluationError(ref cause) => { + Error::Evaluation(ref cause) => { builder.add_diagnostic( codespan_reporting::Severity::Error, None, @@ -25,3 +32,9 @@ impl diagnostic::Diagnostics for Error { } } } + +impl From for Error { + fn from(error: ir::error::Error) -> Self { + Error::Ir(error) + } +} diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index 0ce0387..0cd7b76 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -1,9 +1,9 @@ use std::cmp; use std::collections; -use specs; - -use crate::ir::component::element; +use crate::interpreter; +use crate::ir; +use crate::ir::element; use crate::module; use crate::value; @@ -11,47 +11,57 @@ pub mod error; #[macro_use] mod macros; -pub fn eval<'a, F>( - element: &element::Element, - lookup: F, -) -> Result, error::Error> -where - F: Fn(specs::Entity) -> Option<&'a value::Value>, -{ +#[salsa::query_group(InterpreterStorage)] +pub trait Db: salsa::Database + ir::Db { + fn value(&self, entity: ir::Entity) -> error::Result>; +} + +fn value(db: &impl Db, entity: ir::Entity) -> error::Result> { + let element = db.element(entity)?; + let value = eval(db, &*element)?; + Ok(value) +} + +fn eval(db: &impl Db, element: &element::Element) -> error::Result> { match element { element::Element::Number(v) => Ok(Some(value::Value::number(eval_number(v)))), element::Element::String(ref v) => Ok(Some(value::Value::string(v.as_str()))), - element::Element::Symbol(element::Symbol { ref label }) => { - Ok(Some(value::Value::symbol(label.as_str()))) + element::Element::Symbol(element::Symbol { label }) => { + Ok(Some(value::Value::symbol(db.lookup_ident(*label)))) } element::Element::Tuple(element::Tuple { ref fields }) => Ok(fields .iter() - .map(|f| lookup(*f).cloned()) - .collect::>>() + .map(|f| db.value(*f)) + .collect::>, error::Error>>()? .map(|fields| value::Value::tuple(value::Tuple { fields }))), element::Element::Record(element::Record { ref fields }) => Ok(fields .iter() - .map(|(k, f)| lookup(*f).map(|v| (k.clone(), v.clone()))) - .collect::>>() + .map(|(k, f)| Ok(db.value(*f)?.map(|v| (db.lookup_ident(*k), v)))) + .collect::>, error::Error>>()? .map(|fields| value::Value::record(value::Record { fields }))), - element::Element::UnOp(element::UnOp { operator, operand }) => { - transpose(lookup(*operand).map(|operand| eval_un_op(*operator, &operand))) - } - element::Element::BiOp(element::BiOp { lhs, operator, rhs }) => transpose( - lookup(*lhs).and_then(|lhs| lookup(*rhs).map(|rhs| eval_bi_op(&lhs, *operator, &rhs))), - ), - element::Element::Variable(element::Variable { initializer, .. }) => { - Ok(lookup(*initializer).cloned()) + element::Element::UnOp(element::UnOp { operator, operand }) => db + .value(*operand)? + .map(|operand| eval_un_op(*operator, &operand)) + .transpose(), + element::Element::BiOp(element::BiOp { lhs, operator, rhs }) => { + let lhs_value = db.value(*lhs)?; + let rhs_value = db.value(*rhs)?; + match (lhs_value, rhs_value) { + (Some(ref lhs), Some(ref rhs)) => eval_bi_op(lhs, *operator, rhs).map(Some), + _ => Ok(None), + } } - element::Element::Select(element::Select { record, field }) => { - transpose(lookup(*record).map(|record| match record.case() { - value::Case::Record(r) => Ok(r.fields[field].clone()), + element::Element::Variable(element::Variable { initializer, .. }) => db.value(*initializer), + element::Element::Select(element::Select { record, field }) => db + .value(*record)? + .map(|record| match record.case() { + value::Case::Record(r) => Ok(r.fields[&db.lookup_ident(*field)].clone()), other => Err(error::Error::RuntimeTypeConflict(format!( "not a record: {:?}", other ))), - })) - } + }) + .transpose(), _ => Ok(None), // TODO } } @@ -103,7 +113,7 @@ fn eval_un_op( } } -#[cfg_attr(feature = "cargo-clippy", allow(clippy::cyclomatic_complexity))] +#[allow(clippy::cognitive_complexity)] fn eval_bi_op( lhs: &value::Value, operator: element::BiOperator, @@ -133,25 +143,25 @@ fn eval_bi_op( element::BiOperator::Sub => match_number_value!("-", (lhs, rhs), |l, r| int: Ok( (l.wrapping_sub(*r)).into() ), frac: Ok( - (l - r).into() + (l.into_inner() - r.into_inner()).into() )), element::BiOperator::Mul => match_number_value!("*", (lhs, rhs), |l, r| int: Ok( (l.wrapping_mul(*r)).into() ), frac: Ok( - (l * r).into() + (l.into_inner() * r.into_inner()).into() )), element::BiOperator::Div => match_number_value!("/", (lhs, rhs), |l, r| int: if *r == 0 { - Err(error::Error::EvaluationError(module::Error::new(module::ErrorKind::IntegerDivisonByZero))) + Err(error::Error::Evaluation(module::Error::new(module::ErrorKind::IntegerDivisonByZero))) } else { Ok((l.wrapping_div(*r)).into()) - }, frac: Ok((l / r).into() + }, frac: Ok((l.into_inner() / r.into_inner()).into() )), element::BiOperator::Rem => match_number_value!("%", (lhs, rhs), |l, r| int: if *r == 0 { - Err(error::Error::EvaluationError(module::Error::new(module::ErrorKind::IntegerDivisonByZero))) + Err(error::Error::Evaluation(module::Error::new(module::ErrorKind::IntegerDivisonByZero))) } else { Ok((l.wrapping_rem(*r)).into()) }, frac: Ok( - (l % r).into() + (l.into_inner() % r.into_inner()).into() )), element::BiOperator::And => bool_op("&", lhs, rhs, |l, r| l & r), element::BiOperator::BAnd => { @@ -315,9 +325,7 @@ fn add(lhs: &value::Value, rhs: &value::Value) -> Result { - match_number!("+", (lhs, rhs), |l, r| int: Ok((l.wrapping_add(*r)).into()), frac: Ok((l + r).into())) - } + (value::Case::Number(lhs), value::Case::Number(rhs)) => match_number!("+", (lhs, rhs), |l, r| int: Ok((l.wrapping_add(*r)).into()), frac: Ok((l.into_inner() + r.into_inner()).into())), other => Err(error::Error::RuntimeTypeConflict(format!( "operation + not supported on values {:?}", other @@ -339,12 +347,3 @@ where Ok(op(lhs, rhs).into()) } - -// TODO: awaits https://github.com/rust-lang/rust/issues/47338 -fn transpose(option: Option>) -> Result, E> { - match option { - Some(Ok(x)) => Ok(Some(x)), - Some(Err(e)) => Err(e), - None => Ok(None), - } -} diff --git a/src/ir/builder.rs b/src/ir/builder.rs index 3e09f09..c57f943 100644 --- a/src/ir/builder.rs +++ b/src/ir/builder.rs @@ -1,149 +1,112 @@ use std::collections; use std::mem; +use std::sync; -use specs; - -use crate::ast; -use crate::ir::component::element; -use crate::ir::component::location; -use crate::ir::component::replacement; -use crate::ir::component::symbol; +use crate::ir; +use crate::ir::element; use crate::ir::error; -use crate::parser; - -pub struct Builder<'a> { - world: &'a mut specs::World, - symbol: Vec, - current_scope: collections::HashMap, - scopes: Vec>, - current_captures: collections::HashMap, - captures: Vec>, +use crate::ir::location; +use crate::syntax::ast; +use crate::syntax::parser; + +pub struct Builder<'a, Db> { + db: &'a Db, + scope: Scope, + infos: &'a mut collections::HashMap, } -impl<'a> Builder<'a> { - pub fn new(world: &'a mut specs::World) -> Builder<'a> { - let symbol = Vec::new(); - let current_scope = collections::HashMap::new(); - let scopes = Vec::new(); - let current_captures = collections::HashMap::new(); - let captures = Vec::new(); - - Builder { - world, - symbol, - current_scope, - scopes, - current_captures, - captures, - } +#[derive(Debug)] +struct Scope { + parent: Option>, + entity: ir::Entity, + is_static: bool, + locals: collections::HashMap, + captures: collections::HashMap, +} + +enum CaptureStrategy { + Capture, + StaticRef, +} + +impl<'a, Db> Builder<'a, Db> +where + Db: ir::Db, +{ + pub fn new( + db: &'a Db, + root: ir::Entity, + infos: &'a mut collections::HashMap, + ) -> Self { + let scope = Scope::new(root); + + Builder { db, scope, infos } } - pub fn add_module( + pub fn build_module(mut self, ast: &ast::Module) -> Result<(), error::Error> { + self.scope.is_static = true; + self.add_module(self.scope.entity, ast)?; + + Ok(()) + } + + fn add_module( &mut self, - entity: specs::Entity, + entity: ir::Entity, ast: &ast::Module, ) -> Result<(), error::Error> { - use specs::world::Builder; - let mut variables = collections::HashMap::new(); + for variable in &ast.variables { - let var_entity = self.world.create_entity().build(); + let ident = self.db.ident(variable.name.clone()); + let var_entity = self + .db + .entity(Some(entity), ir::EntityRole::VariableDefinition(ident)); - self.current_scope - .insert(variable.name.value.clone(), var_entity); + self.scope.locals.insert(ident, var_entity); - variables.insert(variable.name.value.clone(), var_entity); + variables.insert(ident, var_entity); } for variable in &ast.variables { - let name = &variable.name.value; - self.add_variable(variables[name], variable)?; + let ident = self.db.ident(variable.name.clone()); + self.add_variable(variables[&ident], variable)?; } - self.world - .write_storage() - .insert( - entity, - element::Element::Module(element::Module { variables }), - ) - .unwrap(); - - self.world - .write_storage() - .insert(entity, symbol::Symbol::new(self.symbol.clone())) - .unwrap(); + let element = element::Element::Module(element::Module { variables }); + let location = location::Location(ast.context.span); - self.world - .write_storage() - .insert(entity, location::Location(ast.context.span)) - .unwrap(); + self.infos + .insert(entity, ir::EntityInfo::new(element, location)); Ok(()) } - fn add_identifier( + fn add_reference( &mut self, - entity: specs::Entity, - identifier: &ast::Identifier, + entity: ir::Entity, + ast: &ast::Reference, ) -> Result<(), error::Error> { - let name = &identifier.value; - - let definition = self.current_scope.get(name).cloned().or_else(|| { - self.scopes - .iter() - .rev() - .flat_map(|scope| scope.get(name).cloned().into_iter()) - .next() - .map(|e| { - use specs::world::Builder; - - let capture = self.world.create_entity().build(); - self.world - .write_storage() - .insert( - capture, - element::Element::Capture(element::Capture { - name: name.clone(), - captured: e, - }), - ) - .unwrap(); - - self.world - .write_storage() - .insert(capture, location::Location(identifier.context.span)) - .unwrap(); - - self.current_captures.insert(name.clone(), capture); - - capture - }) - }); - - let definition = definition.ok_or_else(|| error::Error::UndefinedReference { - reference: name.clone(), - location: identifier.context.span, - })?; + let ident = self.db.ident(ast.value.clone()); + let (target, _) = self + .scope + .resolve_capture(self.db, ident, ast.context.span)?; - self.world - .write_storage() - .insert(entity, replacement::Replacement { to: definition }) - .unwrap(); + let element = element::Element::Reference(target); + let location = location::Location(ast.context.span); - self.world - .write_storage() - .insert(entity, location::Location(identifier.context.span)) - .unwrap(); + self.infos + .insert(entity, ir::EntityInfo::new(element, location)); Ok(()) } fn add_expression( &mut self, - entity: specs::Entity, - expression: &ast::Expression, + entity: ir::Entity, + ast: &ast::Expression, ) -> Result<(), error::Error> { - match *expression { + match *ast { ast::Expression::NumberLiteral(ref v) => self.add_number(entity, v), ast::Expression::StringLiteral(ref v) => self.add_string(entity, v), ast::Expression::Symbol(ref v) => self.add_symbol(entity, v), @@ -151,7 +114,7 @@ impl<'a> Builder<'a> { ast::Expression::Record(ref v) => self.add_record(entity, v), ast::Expression::UnOp(ref v) => self.add_un_op(entity, v), ast::Expression::BiOp(ref v) => self.add_bi_op(entity, v), - ast::Expression::Identifier(ref v) => self.add_identifier(entity, v), + ast::Expression::Reference(ref v) => self.add_reference(entity, v), ast::Expression::Lambda(ref v) => self.add_lambda(entity, v), ast::Expression::Select(ref v) => self.add_select(entity, v), ast::Expression::Apply(ref v) => self.add_apply(entity, v), @@ -161,493 +124,481 @@ impl<'a> Builder<'a> { fn add_number( &mut self, - entity: specs::Entity, - number: &ast::NumberLiteral, + entity: ir::Entity, + ast: &ast::NumberLiteral, ) -> Result<(), error::Error> { - self.world - .write_storage() - .insert( - entity, - element::Element::Number(Builder::from_ast_number(number.value)), - ) - .unwrap(); - - self.world - .write_storage() - .insert(entity, location::Location(number.context.span)) - .unwrap(); + let element = element::Element::Number(translate_number(ast.value)); + let location = location::Location(ast.context.span); - Ok(()) - } + self.infos + .insert(entity, ir::EntityInfo::new(element, location)); - fn from_ast_number(number: ast::NumberValue) -> element::Number { - match number { - ast::NumberValue::U8(n) => element::Number::U8(n), - ast::NumberValue::U16(n) => element::Number::U16(n), - ast::NumberValue::U32(n) => element::Number::U32(n), - ast::NumberValue::U64(n) => element::Number::U64(n), - ast::NumberValue::I8(n) => element::Number::I8(n), - ast::NumberValue::I16(n) => element::Number::I16(n), - ast::NumberValue::I32(n) => element::Number::I32(n), - ast::NumberValue::I64(n) => element::Number::I64(n), - ast::NumberValue::F32(n) => element::Number::F32(n), - ast::NumberValue::F64(n) => element::Number::F64(n), - ast::NumberValue::Invalid => panic!("'invalid' AST nodes should not escape the parser"), - } + Ok(()) } fn add_string( &mut self, - entity: specs::Entity, - string: &ast::StringLiteral, + entity: ir::Entity, + ast: &ast::StringLiteral, ) -> Result<(), error::Error> { - self.world - .write_storage() - .insert( - entity, - element::Element::String(match string.value { - ast::StringValue::String(ref s) => s.clone(), - ast::StringValue::Invalid => { - panic!("'invalid' AST nodes should not escape the parser") - } - }), - ) - .unwrap(); + let element = element::Element::String(match &ast.value { + ast::StringValue::String(str) => str.clone(), + ast::StringValue::Invalid => { + panic!("'invalid' string values should not escape the parser") + } + }); + let location = location::Location(ast.context.span); - self.world - .write_storage() - .insert(entity, location::Location(string.context.span)) - .unwrap(); + self.infos + .insert(entity, ir::EntityInfo::new(element, location)); Ok(()) } fn add_tuple( &mut self, - entity: specs::Entity, + entity: ir::Entity, tuple: &ast::Tuple, ) -> Result<(), error::Error> { - use specs::world::Builder; - let fields = tuple .fields .iter() - .map(|f| { - let e = self.world.create_entity().build(); - self.add_expression(e, f)?; - Ok(e) + .enumerate() + .map(|(index, ast)| { + let entity = self + .db + .entity(Some(entity), ir::EntityRole::TupleField(index)); + self.add_expression(entity, &*ast)?; + Ok(entity) }) .collect::>()?; - self.world - .write_storage() - .insert(entity, element::Element::Tuple(element::Tuple { fields })) - .unwrap(); + let element = element::Element::Tuple(element::Tuple { fields }); + let location = location::Location(tuple.context.span); - self.world - .write_storage() - .insert(entity, location::Location(tuple.context.span)) - .unwrap(); + self.infos + .insert(entity, ir::EntityInfo::new(element, location)); Ok(()) } fn add_symbol( &mut self, - entity: specs::Entity, + entity: ir::Entity, symbol: &ast::Symbol, ) -> Result<(), error::Error> { - let label = symbol.label.clone(); + let label = self.db.ident(symbol.label.clone()); - self.world - .write_storage() - .insert(entity, element::Element::Symbol(element::Symbol { label })) - .unwrap(); + let element = element::Element::Symbol(element::Symbol { label }); + let location = location::Location(symbol.context.span); - self.world - .write_storage() - .insert(entity, location::Location(symbol.context.span)) - .unwrap(); + self.infos + .insert(entity, ir::EntityInfo::new(element, location)); Ok(()) } fn add_record( &mut self, - entity: specs::Entity, + entity: ir::Entity, record: &ast::Record, ) -> Result<(), error::Error> { - use specs::world::Builder; - let fields = record .fields .iter() - .map(|(i, e)| { - let en = self.world.create_entity().build(); - self.add_expression(en, e)?; - Ok((i.value.clone(), en)) + .map(|(field, value)| { + let ident = self.db.ident(field.clone()); + let entity = self + .db + .entity(Some(entity), ir::EntityRole::RecordField(ident)); + self.add_expression(entity, value)?; + Ok((ident, entity)) }) .collect::>()?; - self.world - .write_storage() - .insert(entity, element::Element::Record(element::Record { fields })) - .unwrap(); + let element = element::Element::Record(element::Record { fields }); + let location = location::Location(record.context.span); - self.world - .write_storage() - .insert(entity, location::Location(record.context.span)) - .unwrap(); + self.infos + .insert(entity, ir::EntityInfo::new(element, location)); Ok(()) } fn add_un_op( &mut self, - entity: specs::Entity, + entity: ir::Entity, un_op: &ast::UnOp, ) -> Result<(), error::Error> { - use specs::world::Builder; - - let operator = self::Builder::translate_un_operator(un_op.operator); + let operator = translate_un_operator(un_op.operator); - let operand = self.world.create_entity().build(); + let operand = self.db.entity(Some(entity), ir::EntityRole::UnOperand); self.add_expression(operand, &*un_op.operand)?; - self.world - .write_storage() - .insert( - entity, - element::Element::UnOp(element::UnOp { operator, operand }), - ) - .unwrap(); + let element = element::Element::UnOp(element::UnOp { operator, operand }); + let location = location::Location(un_op.context.span); - self.world - .write_storage() - .insert(entity, location::Location(un_op.context.span)) - .unwrap(); + self.infos + .insert(entity, ir::EntityInfo::new(element, location)); Ok(()) } fn add_bi_op( &mut self, - entity: specs::Entity, + entity: ir::Entity, bi_op: &ast::BiOp, ) -> Result<(), error::Error> { - use specs::world::Builder; - - let lhs = self.world.create_entity().build(); + let lhs = self.db.entity(Some(entity), ir::EntityRole::BiLhs); self.add_expression(lhs, &*bi_op.lhs)?; - let operator = self::Builder::translate_bi_operator(bi_op.operator); + let operator = translate_bi_operator(bi_op.operator); - let rhs = self.world.create_entity().build(); + let rhs = self.db.entity(Some(entity), ir::EntityRole::BiRhs); self.add_expression(rhs, &*bi_op.rhs)?; - self.world - .write_storage() - .insert( - entity, - element::Element::BiOp(element::BiOp { lhs, operator, rhs }), - ) - .unwrap(); + let element = element::Element::BiOp(element::BiOp { lhs, operator, rhs }); + let location = location::Location(bi_op.context.span); - self.world - .write_storage() - .insert(entity, location::Location(bi_op.context.span)) - .unwrap(); + self.infos + .insert(entity, ir::EntityInfo::new(element, location)); Ok(()) } fn add_lambda( &mut self, - entity: specs::Entity, + entity: ir::Entity, lambda: &ast::Lambda, ) -> Result<(), error::Error> { - use specs::world::Builder; - // TODO generate unique symbol for anonymous lambdas - self.push_scope(Some(lambda.parameters.len()), None); + self.push_scope(entity); let parameters = lambda .parameters .iter() - .map(|p| { - let e = self.world.create_entity().build(); - self.add_parameter(e, p)?; - Ok(e) + .map(|parameter| { + let ident = self.db.ident(parameter.name.clone()); + let entity = self + .db + .entity(Some(entity), ir::EntityRole::ClosureParameter(ident)); + self.add_parameter(entity, &*parameter)?; + Ok(entity) }) .collect::, error::Error>>()?; // Defer inserting parameters as variables until here to ensure that one parameter can't // depend on another one. for (entity, parameter) in parameters.iter().zip(lambda.parameters.iter()) { - self.current_scope - .insert(parameter.name.value.clone(), *entity); + let ident = self.db.ident(parameter.name.clone()); + self.scope.locals.insert(ident, *entity); } let statements = lambda .statements .iter() - .map(|s| { - let e = self.world.create_entity().build(); + .enumerate() + .map(|(index, statement)| { + let entity = self + .db + .entity(Some(entity), ir::EntityRole::ClosureStatement(index)); - match s { + match &**statement { ast::Statement::Variable(ref variable) => { - self.current_scope.insert(variable.name.value.clone(), e); - self.add_variable(e, variable)?; + let ident = self.db.ident(variable.name.clone()); + self.scope.locals.insert(ident, entity); + self.add_variable(entity, variable)?; } ast::Statement::Expression(ref expression) => { - self.add_expression(e, expression)?; + self.add_expression(entity, expression)?; } } - Ok(e) + Ok(entity) }) .collect::, error::Error>>()?; - let signature = self.world.create_entity().build(); + let signature = self + .db + .entity(Some(entity), ir::EntityRole::ClosureSignature); self.add_expression(signature, &*lambda.signature)?; let result = if let Some(ref result) = lambda.result { - let e = self.world.create_entity().build(); + let e = self.db.entity(Some(entity), ir::EntityRole::ClosureResult); self.add_expression(e, &*result)?; e } else { signature }; - self.world - .write_storage() - .insert( - entity, - element::Element::Closure(element::Closure { - captures: self.current_captures.clone(), - parameters, - statements, - signature, - result, - }), - ) - .unwrap(); - - self.world - .write_storage() - .insert(entity, symbol::Symbol::new(self.symbol.clone())) - .unwrap(); - - self.world - .write_storage() - .insert(entity, location::Location(lambda.context.span)) - .unwrap(); - - self.pop_scope(); + let location = location::Location(lambda.context.span); + + let scope = self.pop_scope(); + let captures = scope + .captures + .into_iter() + .map(|(entity, capture)| { + let ident = capture.name; + self.infos.insert( + entity, + ir::EntityInfo::new(element::Element::Capture(capture), location), + ); + (ident, entity) + }) + .collect(); + + let element = element::Element::Closure(element::Closure { + captures, + parameters, + statements, + signature, + result, + }); + + self.infos + .insert(entity, ir::EntityInfo::new(element, location)); Ok(()) } fn add_variable( &mut self, - entity: specs::Entity, + entity: ir::Entity, variable: &ast::Variable, ) -> Result<(), error::Error> { - use specs::world::Builder; + let name = self.db.ident(variable.name.clone()); - self.symbol - .push(symbol::Part::Named(variable.name.value.clone())); - - let name = variable.name.value.clone(); - let initializer = self.world.create_entity().build(); + let initializer = self + .db + .entity(Some(entity), ir::EntityRole::VariableInitializer); self.add_expression(initializer, &variable.initializer)?; - self.world - .write_storage() - .insert( - entity, - element::Element::Variable(element::Variable { name, initializer }), - ) - .unwrap(); - - self.world - .write_storage() - .insert(entity, symbol::Symbol::new(self.symbol.clone())) - .unwrap(); - - self.world - .write_storage() - .insert(entity, location::Location(variable.context.span)) - .unwrap(); + let element = element::Element::Variable(element::Variable { name, initializer }); + let location = location::Location(variable.context.span); - self.symbol.pop(); + self.infos + .insert(entity, ir::EntityInfo::new(element, location)); Ok(()) } fn add_select( &mut self, - entity: specs::Entity, + entity: ir::Entity, select: &ast::Select, ) -> Result<(), error::Error> { - use specs::world::Builder; - - let record = self.world.create_entity().build(); + let field = self.db.ident(select.field.clone()); + let record = self + .db + .entity(Some(entity), ir::EntityRole::SelectField(field)); self.add_expression(record, &*select.record)?; - let field = select.field.value.clone(); - - self.world - .write_storage() - .insert( - entity, - element::Element::Select(element::Select { record, field }), - ) - .unwrap(); + let element = element::Element::Select(element::Select { record, field }); + let location = location::Location(select.context.span); - self.world - .write_storage() - .insert(entity, location::Location(select.context.span)) - .unwrap(); + self.infos + .insert(entity, ir::EntityInfo::new(element, location)); Ok(()) } fn add_apply( &mut self, - entity: specs::Entity, + entity: ir::Entity, apply: &ast::Apply, ) -> Result<(), error::Error> { - use specs::world::Builder; - - let function = self.world.create_entity().build(); + let function = self + .db + .entity(Some(entity), ir::EntityRole::AppliedFunction); self.add_expression(function, &*apply.function)?; let parameters = apply .parameters .iter() - .map(|p| { - let e = self.world.create_entity().build(); - self.add_expression(e, p)?; - Ok(e) + .enumerate() + .map(|(index, parameter)| { + let entity = self + .db + .entity(Some(entity), ir::EntityRole::AppliedParameter(index)); + self.add_expression(entity, &*parameter)?; + Ok(entity) }) .collect::>()?; - self.world - .write_storage() - .insert( - entity, - element::Element::Apply(element::Apply { - function, - parameters, - }), - ) - .unwrap(); - - self.world - .write_storage() - .insert(entity, location::Location(apply.context.span)) - .unwrap(); + let element = element::Element::Apply(element::Apply { + function, + parameters, + }); + let location = location::Location(apply.context.span); + + self.infos + .insert(entity, ir::EntityInfo::new(element, location)); Ok(()) } fn add_parameter( &mut self, - entity: specs::Entity, + entity: ir::Entity, parameter: &ast::Parameter, ) -> Result<(), error::Error> { - use specs::world::Builder; - - let name = parameter.name.value.clone(); - let signature = self.world.create_entity().build(); + let name = self.db.ident(parameter.name.clone()); + let signature = self + .db + .entity(Some(entity), ir::EntityRole::ParameterSignature); self.add_expression(signature, ¶meter.signature)?; - self.world - .write_storage() - .insert( - entity, - element::Element::Parameter(element::Parameter { name, signature }), - ) - .unwrap(); + let element = element::Element::Parameter(element::Parameter { name, signature }); + let location = location::Location(parameter.context.span); - self.world - .write_storage() - .insert(entity, location::Location(parameter.context.span)) - .unwrap(); + self.infos + .insert(entity, ir::EntityInfo::new(element, location)); Ok(()) } - fn push_scope(&mut self, scope_size_hint: Option, captures_size_hint: Option) { - self.scopes.push(mem::replace( - &mut self.current_scope, - scope_size_hint.map_or_else( - collections::HashMap::new, - collections::HashMap::with_capacity, - ), - )); - self.captures.push(mem::replace( - &mut self.current_captures, - captures_size_hint.map_or_else( - collections::HashMap::new, - collections::HashMap::with_capacity, - ), - )); + fn push_scope(&mut self, entity: ir::Entity) { + let scope = Scope::new(entity); + let parent_scope = mem::replace(&mut self.scope, scope); + self.scope.parent = Some(Box::new(parent_scope)); } - fn pop_scope(&mut self) { - self.current_scope = self.scopes.pop().unwrap(); - self.current_captures = self.captures.pop().unwrap(); + fn pop_scope(&mut self) -> Scope { + let parent = self + .scope + .parent + .take() + .expect("unbalanced push_scope/pop_scope calls"); + mem::replace(&mut self.scope, *parent) } +} - fn translate_un_operator(un_operator: ast::UnOperator) -> element::UnOperator { - match un_operator { - ast::UnOperator::Not => element::UnOperator::Not, - ast::UnOperator::BNot => element::UnOperator::BNot, - ast::UnOperator::Cl0 => element::UnOperator::Cl0, - ast::UnOperator::Cl1 => element::UnOperator::Cl1, - ast::UnOperator::Cls => element::UnOperator::Cls, - ast::UnOperator::Ct0 => element::UnOperator::Ct0, - ast::UnOperator::Ct1 => element::UnOperator::Ct1, - ast::UnOperator::C0 => element::UnOperator::C0, - ast::UnOperator::C1 => element::UnOperator::C1, - ast::UnOperator::Sqrt => element::UnOperator::Sqrt, +impl Scope { + fn new(entity: ir::Entity) -> Self { + let parent = None; + let is_static = false; + let locals = collections::HashMap::new(); + let captures = collections::HashMap::new(); + + Self { + parent, + is_static, + entity, + locals, + captures, } } - fn translate_bi_operator(bi_operator: ast::BiOperator) -> element::BiOperator { - match bi_operator { - ast::BiOperator::Eq => element::BiOperator::Eq, - ast::BiOperator::Ne => element::BiOperator::Ne, - ast::BiOperator::Lt => element::BiOperator::Lt, - ast::BiOperator::Ge => element::BiOperator::Ge, - ast::BiOperator::Gt => element::BiOperator::Gt, - ast::BiOperator::Le => element::BiOperator::Le, - ast::BiOperator::Cmp => element::BiOperator::Cmp, - ast::BiOperator::Add => element::BiOperator::Add, - ast::BiOperator::Sub => element::BiOperator::Sub, - ast::BiOperator::Mul => element::BiOperator::Mul, - ast::BiOperator::Div => element::BiOperator::Div, - ast::BiOperator::Rem => element::BiOperator::Rem, - ast::BiOperator::And => element::BiOperator::And, - ast::BiOperator::BAnd => element::BiOperator::BAnd, - ast::BiOperator::Or => element::BiOperator::Or, - ast::BiOperator::BOr => element::BiOperator::BOr, - ast::BiOperator::Xor => element::BiOperator::Xor, - ast::BiOperator::BXor => element::BiOperator::BXor, - ast::BiOperator::AndNot => element::BiOperator::AndNot, - ast::BiOperator::BAndNot => element::BiOperator::BAndNot, - ast::BiOperator::OrNot => element::BiOperator::OrNot, - ast::BiOperator::BOrNot => element::BiOperator::BOrNot, - ast::BiOperator::XorNot => element::BiOperator::XorNot, - ast::BiOperator::BXorNot => element::BiOperator::BXorNot, - ast::BiOperator::RotL => element::BiOperator::RotL, - ast::BiOperator::RotR => element::BiOperator::RotR, - ast::BiOperator::ShL => element::BiOperator::ShL, - ast::BiOperator::ShR => element::BiOperator::ShR, + fn resolve_capture( + &mut self, + db: &impl ir::Db, + ident: ir::Ident, + location: codespan::ByteSpan, + ) -> Result<(ir::Entity, CaptureStrategy), error::Error> { + match self.locals.entry(ident) { + collections::hash_map::Entry::Occupied(entry) => Ok(( + *entry.get(), + if self.is_static { + CaptureStrategy::StaticRef + } else { + CaptureStrategy::Capture + }, + )), + collections::hash_map::Entry::Vacant(entry) => { + if let Some(parent) = &mut self.parent { + let capture_entity = db.entity( + Some(self.entity), + ir::EntityRole::ClosureCaptureDefinition(ident), + ); + let (parent_entity, strategy) = parent.resolve_capture(db, ident, location)?; + + if let CaptureStrategy::Capture = strategy { + self.captures.insert( + capture_entity, + element::Capture { + name: ident, + captured: parent_entity, + }, + ); + entry.insert(capture_entity); + Ok((capture_entity, CaptureStrategy::Capture)) + } else { + Ok((parent_entity, CaptureStrategy::StaticRef)) + } + } else { + let reference = (*db.lookup_ident(ident)).clone(); + Err(error::Error::UndefinedReference { + reference, + location, + }) + } + } } } } + +fn translate_number(number: ast::NumberValue) -> element::Number { + match number { + ast::NumberValue::U8(n) => element::Number::U8(n), + ast::NumberValue::U16(n) => element::Number::U16(n), + ast::NumberValue::U32(n) => element::Number::U32(n), + ast::NumberValue::U64(n) => element::Number::U64(n), + ast::NumberValue::I8(n) => element::Number::I8(n), + ast::NumberValue::I16(n) => element::Number::I16(n), + ast::NumberValue::I32(n) => element::Number::I32(n), + ast::NumberValue::I64(n) => element::Number::I64(n), + ast::NumberValue::F32(n) => element::Number::F32(n), + ast::NumberValue::F64(n) => element::Number::F64(n), + ast::NumberValue::Invalid => panic!("'invalid' AST nodes should not escape the parser"), + } +} + +fn translate_un_operator(un_operator: ast::UnOperator) -> element::UnOperator { + match un_operator { + ast::UnOperator::Not => element::UnOperator::Not, + ast::UnOperator::BNot => element::UnOperator::BNot, + ast::UnOperator::Cl0 => element::UnOperator::Cl0, + ast::UnOperator::Cl1 => element::UnOperator::Cl1, + ast::UnOperator::Cls => element::UnOperator::Cls, + ast::UnOperator::Ct0 => element::UnOperator::Ct0, + ast::UnOperator::Ct1 => element::UnOperator::Ct1, + ast::UnOperator::C0 => element::UnOperator::C0, + ast::UnOperator::C1 => element::UnOperator::C1, + ast::UnOperator::Sqrt => element::UnOperator::Sqrt, + } +} + +fn translate_bi_operator(bi_operator: ast::BiOperator) -> element::BiOperator { + match bi_operator { + ast::BiOperator::Eq => element::BiOperator::Eq, + ast::BiOperator::Ne => element::BiOperator::Ne, + ast::BiOperator::Lt => element::BiOperator::Lt, + ast::BiOperator::Ge => element::BiOperator::Ge, + ast::BiOperator::Gt => element::BiOperator::Gt, + ast::BiOperator::Le => element::BiOperator::Le, + ast::BiOperator::Cmp => element::BiOperator::Cmp, + ast::BiOperator::Add => element::BiOperator::Add, + ast::BiOperator::Sub => element::BiOperator::Sub, + ast::BiOperator::Mul => element::BiOperator::Mul, + ast::BiOperator::Div => element::BiOperator::Div, + ast::BiOperator::Rem => element::BiOperator::Rem, + ast::BiOperator::And => element::BiOperator::And, + ast::BiOperator::BAnd => element::BiOperator::BAnd, + ast::BiOperator::Or => element::BiOperator::Or, + ast::BiOperator::BOr => element::BiOperator::BOr, + ast::BiOperator::Xor => element::BiOperator::Xor, + ast::BiOperator::BXor => element::BiOperator::BXor, + ast::BiOperator::AndNot => element::BiOperator::AndNot, + ast::BiOperator::BAndNot => element::BiOperator::BAndNot, + ast::BiOperator::OrNot => element::BiOperator::OrNot, + ast::BiOperator::BOrNot => element::BiOperator::BOrNot, + ast::BiOperator::XorNot => element::BiOperator::XorNot, + ast::BiOperator::BXorNot => element::BiOperator::BXorNot, + ast::BiOperator::RotL => element::BiOperator::RotL, + ast::BiOperator::RotR => element::BiOperator::RotR, + ast::BiOperator::ShL => element::BiOperator::ShL, + ast::BiOperator::ShR => element::BiOperator::ShR, + } +} diff --git a/src/ir/component/constexpr/error.rs b/src/ir/component/constexpr/error.rs deleted file mode 100644 index 2bfc629..0000000 --- a/src/ir/component/constexpr/error.rs +++ /dev/null @@ -1,11 +0,0 @@ -use specs::Component; -use specs::VecStorage; - -use crate::interpreter; - -#[derive(Component, Clone, Debug, Fail, PartialEq)] -#[storage(VecStorage)] -pub enum Error { - #[fail(display = "evaluation error")] - Evaluation(#[cause] interpreter::error::Error), -} diff --git a/src/ir/component/constexpr/mod.rs b/src/ir/component/constexpr/mod.rs deleted file mode 100644 index 1511850..0000000 --- a/src/ir/component/constexpr/mod.rs +++ /dev/null @@ -1,12 +0,0 @@ -use specs::Component; -use specs::VecStorage; - -use crate::value; - -pub mod error; - -#[derive(Component, Clone, Debug)] -#[storage(VecStorage)] -pub struct Constexpr { - pub value: value::Value, -} diff --git a/src/ir/component/layout.rs b/src/ir/component/layout.rs deleted file mode 100644 index 690eb2f..0000000 --- a/src/ir/component/layout.rs +++ /dev/null @@ -1,120 +0,0 @@ -use std::fmt; - -use specs::Component; -use specs::VecStorage; - -#[derive(Clone, Component, Debug, VisitEntities, VisitEntitiesMut)] -#[storage(VecStorage)] -pub struct Layout { - pub size: usize, - pub alignment: usize, - pub named_fields: Vec, - pub unnamed_fields: Vec, -} - -#[derive(Clone, Debug, VisitEntities, VisitEntitiesMut)] -pub struct NamedField { - pub field: String, - pub offset_layout: Offset, -} - -#[derive(Clone, Debug, VisitEntities, VisitEntitiesMut)] -pub struct Offset { - pub offset: usize, - pub layout: Layout, -} - -impl Layout { - pub const fn zero() -> Layout { - Layout { - size: 0, - alignment: 1, - named_fields: Vec::new(), - unnamed_fields: Vec::new(), - } - } - - pub const fn scalar(size: usize) -> Layout { - Layout { - size, - alignment: size, - named_fields: Vec::new(), - unnamed_fields: Vec::new(), - } - } - - pub fn named_fields(size: usize, alignment: usize, named_fields: Vec) -> Layout { - let unnamed_fields = Vec::new(); - - Layout { - size, - alignment, - named_fields, - unnamed_fields, - } - } - - pub fn unnamed_fields(size: usize, alignment: usize, unnamed_fields: Vec) -> Layout { - let named_fields = Vec::new(); - - Layout { - size, - alignment, - named_fields, - unnamed_fields, - } - } -} - -impl Offset { - pub const fn zero() -> Offset { - Offset { - offset: 0, - layout: Layout::zero(), - } - } -} - -impl fmt::Display for Layout { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}/{}", self.size, self.alignment)?; - - if !self.named_fields.is_empty() { - write!(f, "[")?; - - let mut needs_sep = false; - for named_field in &self.named_fields { - if needs_sep { - write!(f, ",")?; - } - write!(f, "{:?}:{}", named_field.field, named_field.offset_layout)?; - needs_sep = true; - } - - write!(f, "]")?; - } - - if !self.unnamed_fields.is_empty() { - write!(f, "{{")?; - - let mut needs_sep = false; - for (idx, offset) in self.unnamed_fields.iter().enumerate() { - if needs_sep { - write!(f, ",")?; - } - write!(f, "{}:{}", idx, offset)?; - needs_sep = true; - } - - write!(f, "}}")?; - } - - Ok(()) - } -} - -impl fmt::Display for Offset { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}({})", self.offset, self.layout) - } -} diff --git a/src/ir/component/location.rs b/src/ir/component/location.rs deleted file mode 100644 index 4b53e3d..0000000 --- a/src/ir/component/location.rs +++ /dev/null @@ -1,6 +0,0 @@ -use specs::Component; -use specs::VecStorage; - -#[derive(Clone, Component, Debug)] -#[storage(VecStorage)] -pub struct Location(pub codespan::ByteSpan); diff --git a/src/ir/component/mod.rs b/src/ir/component/mod.rs deleted file mode 100644 index 6f44b7d..0000000 --- a/src/ir/component/mod.rs +++ /dev/null @@ -1,34 +0,0 @@ -use specs; - -pub mod constexpr; -pub mod element; -pub mod layout; -pub mod location; -pub mod replacement; -pub mod symbol; -pub mod ty; - -macro_rules! for_each_component { - (|$name:ident| $body:expr) => { - apply_component!(constexpr::Constexpr, $name, $body); - apply_component!(constexpr::error::Error, $name, $body); - apply_component!(element::Element, $name, $body); - apply_component!(layout::Layout, $name, $body); - apply_component!(location::Location, $name, $body); - apply_component!(replacement::Replacement, $name, $body); - apply_component!(symbol::Symbol, $name, $body); - apply_component!(ty::Type, $name, $body); - apply_component!(ty::error::Error, $name, $body); - }; -} - -macro_rules! apply_component { - ($component:ty, $name:ident, $body:expr) => {{ - type $name = $component; - $body - }}; -} - -pub fn register_all(world: &mut specs::World) { - for_each_component!(|C| world.register::()); -} diff --git a/src/ir/component/replacement.rs b/src/ir/component/replacement.rs deleted file mode 100644 index 245d3ff..0000000 --- a/src/ir/component/replacement.rs +++ /dev/null @@ -1,10 +0,0 @@ -use specs; - -use specs::Component; -use specs::HashMapStorage; - -#[derive(Component, Debug, VisitEntities, VisitEntitiesMut)] -#[storage(HashMapStorage)] -pub struct Replacement { - pub to: specs::Entity, -} diff --git a/src/ir/component/symbol.rs b/src/ir/component/symbol.rs deleted file mode 100644 index 5ea9869..0000000 --- a/src/ir/component/symbol.rs +++ /dev/null @@ -1,72 +0,0 @@ -use std::fmt; - -use specs::Component; -use specs::VecStorage; - -#[derive(Component, Clone, Debug, VisitEntities, VisitEntitiesMut)] -#[storage(VecStorage)] -pub struct Symbol { - public: bool, - parts: Vec, -} - -#[derive(Clone, Debug, VisitEntities, VisitEntitiesMut)] -pub enum Part { - Named(String), - #[allow(unused)] - Unnamed(u64), -} - -impl Symbol { - pub fn new(parts: Vec) -> Self { - let public = false; - Symbol { public, parts } - } - - pub fn into_public(self) -> Self { - let public = true; - let parts = self.parts; - Symbol { public, parts } - } - - pub fn is_empty(&self) -> bool { - self.parts.is_empty() - } - - pub fn is_public(&self) -> bool { - self.public - } - - pub fn is_top_level(&self) -> bool { - self.parts.len() == 1 - } -} - -impl fmt::Display for Symbol { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.public { - f.write_str("public:")?; - } - - let mut needs_sep = false; - - for part in &self.parts { - if needs_sep { - f.write_str(".")?; - } - part.fmt(f)?; - needs_sep = true; - } - - Ok(()) - } -} - -impl fmt::Display for Part { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Part::Named(ref name) => name.fmt(f), - Part::Unnamed(ref id) => id.fmt(f), - } - } -} diff --git a/src/ir/component/ty/error.rs b/src/ir/component/ty/error.rs deleted file mode 100644 index 55f0655..0000000 --- a/src/ir/component/ty/error.rs +++ /dev/null @@ -1,69 +0,0 @@ -use std::fmt; - -use specs::Component; -use specs::VecStorage; - -use crate::ir::component::ty; -use crate::ir::component::ty::class; - -#[derive(Component, Clone, Debug, Eq, Fail, PartialEq, VisitEntities, VisitEntitiesMut)] -#[storage(VecStorage)] -pub struct Error -where - E: fmt::Debug + Send + Sync + 'static, -{ - pub expected: ExpectedType, - pub actual: ty::Type, - pub main_entity: E, - pub aux_entities: Vec>, -} - -#[derive(Clone, Debug, Eq, PartialEq, VisitEntities, VisitEntitiesMut)] -pub struct AuxEntity { - pub entity: E, - pub label: String, -} - -#[derive(Clone, Debug, Eq, PartialEq, VisitEntities, VisitEntitiesMut)] -pub enum ExpectedType { - Specific(ty::Type), - ScalarClass(class::Scalar), - AnyOf(Vec), - Union, -} - -impl fmt::Display for Error -where - E: fmt::Debug + Send + Sync, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "expected ")?; - self.expected.fmt(f)?; - write!(f, " but got `")?; - self.actual.fmt(f)?; - write!(f, "`")?; - Ok(()) - } -} - -impl fmt::Display for ExpectedType { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - ExpectedType::Specific(ref ty) => write!(f, "`{}`", ty), - ExpectedType::ScalarClass(ref class) => class.fmt(f), - ExpectedType::AnyOf(ref options) => { - let last = options.len() - 1; - for (i, option) in options.iter().enumerate() { - if i == last { - write!(f, " or ")?; - } else if i > 0 { - write!(f, ", ")?; - } - option.fmt(f)?; - } - Ok(()) - } - ExpectedType::Union => f.write_str("any union type"), - } - } -} diff --git a/src/ir/component/element.rs b/src/ir/element.rs similarity index 71% rename from src/ir/component/element.rs rename to src/ir/element.rs index eead12d..d35894f 100644 --- a/src/ir/component/element.rs +++ b/src/ir/element.rs @@ -1,16 +1,14 @@ use std::collections; use std::fmt; +use std::sync; -use specs; +use crate::ir; -use specs::Component; -use specs::VecStorage; - -#[derive(Component, Debug, VisitEntities, VisitEntitiesMut)] -#[storage(VecStorage)] +#[derive(Clone, Debug, Eq, PartialEq)] pub enum Element { + Reference(ir::Entity), Number(Number), - String(String), + String(sync::Arc), Symbol(Symbol), Tuple(Tuple), Record(Record), @@ -25,7 +23,7 @@ pub enum Element { Module(Module), } -#[derive(Clone, Copy, Debug, VisitEntities, VisitEntitiesMut)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum Number { U8(u8), U16(u16), @@ -35,27 +33,27 @@ pub enum Number { I16(i16), I32(i32), I64(i64), - F32(f32), - F64(f64), + F32(ordered_float::OrderedFloat), + F64(ordered_float::OrderedFloat), } -#[derive(Debug, VisitEntities, VisitEntitiesMut)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Symbol { - pub label: String, + pub label: ir::Ident, } -#[derive(Debug, VisitEntities, VisitEntitiesMut)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Tuple { - pub fields: Vec, + pub fields: Vec, } -#[derive(Debug, VisitEntities, VisitEntitiesMut)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Record { - pub fields: collections::HashMap, + pub fields: collections::HashMap, } /// An unary operator. -#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, VisitEntities, VisitEntitiesMut)] +#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] pub enum UnOperator { /// Logical not. Not, @@ -84,16 +82,16 @@ pub enum UnOperator { } /// An operator application with one operand. -#[derive(Clone, Copy, Debug, PartialEq, VisitEntities, VisitEntitiesMut)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct UnOp { /// The unary operator that is being applied. pub operator: UnOperator, /// The operand to the operator. - pub operand: specs::Entity, + pub operand: ir::Entity, } /// A binary operator. -#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, VisitEntities, VisitEntitiesMut)] +#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] pub enum BiOperator { /// The equal-to operator. Eq, @@ -157,58 +155,58 @@ pub enum BiOperator { } /// An operator application with two operands. -#[derive(Clone, Copy, Debug, PartialEq, VisitEntities, VisitEntitiesMut)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct BiOp { /// The left-hand-side operand of the operator. - pub lhs: specs::Entity, + pub lhs: ir::Entity, /// The binary operator that is being applied. pub operator: BiOperator, /// The right-hand-side operand of the operator. - pub rhs: specs::Entity, + pub rhs: ir::Entity, } -#[derive(Debug, VisitEntities, VisitEntitiesMut)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Variable { - pub name: String, - pub initializer: specs::Entity, + pub name: ir::Ident, + pub initializer: ir::Entity, } -#[derive(Debug, VisitEntities, VisitEntitiesMut)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Select { - pub record: specs::Entity, - pub field: String, + pub record: ir::Entity, + pub field: ir::Ident, } -#[derive(Debug, VisitEntities, VisitEntitiesMut)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Apply { - pub function: specs::Entity, - pub parameters: Vec, + pub function: ir::Entity, + pub parameters: Vec, } -#[derive(Debug, VisitEntities, VisitEntitiesMut)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Parameter { - pub name: String, - pub signature: specs::Entity, + pub name: ir::Ident, + pub signature: ir::Entity, } -#[derive(Debug, VisitEntities, VisitEntitiesMut)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Capture { - pub name: String, - pub captured: specs::Entity, + pub name: ir::Ident, + pub captured: ir::Entity, } -#[derive(Debug, VisitEntities, VisitEntitiesMut)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Closure { - pub captures: collections::HashMap, - pub parameters: Vec, - pub statements: Vec, - pub signature: specs::Entity, - pub result: specs::Entity, + pub captures: collections::HashMap, + pub parameters: Vec, + pub statements: Vec, + pub signature: ir::Entity, + pub result: ir::Entity, } -#[derive(Debug, VisitEntities, VisitEntitiesMut)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Module { - pub variables: collections::HashMap, + pub variables: collections::HashMap, } impl fmt::Display for UnOperator { diff --git a/src/ir/error.rs b/src/ir/error.rs index 9918472..19397ea 100644 --- a/src/ir/error.rs +++ b/src/ir/error.rs @@ -1,9 +1,8 @@ use crate::diagnostic; -use crate::ir::component::constexpr; -use crate::ir::component::ty; +use std::result; /// Errors that may occur while building and interacting with an [`Ir`]. -#[derive(Clone, Debug, Fail, PartialEq)] +#[derive(Clone, Debug, Eq, failure::Fail, PartialEq)] pub enum Error { /// The IR cannot be built because something refers to an identifier that is not defined. #[fail(display = "undefined reference to `{}`", reference)] @@ -14,17 +13,6 @@ pub enum Error { location: codespan::ByteSpan, }, - /// The IR has a type error. - #[fail(display = "type error")] - Type( - codespan::ByteSpan, - #[cause] ty::error::Error, - ), - - /// The IR has a constexpr that cannot be evaluated. - #[fail(display = "constexpr error")] - Constexpr(codespan::ByteSpan, #[cause] constexpr::error::Error), - /// There were multiple IR errors. #[fail(display = "multiple IR errors")] Multiple { @@ -33,6 +21,8 @@ pub enum Error { }, } +pub type Result = result::Result; + impl diagnostic::Diagnostics for Error { fn to_diagnostics(&self, builder: &mut diagnostic::DiagnosticsBuilder) { match *self { @@ -48,51 +38,6 @@ impl diagnostic::Diagnostics for Error { &self.to_string(), ); } - Error::Type(entity, ref type_error) => match type_error { - ty::error::Error { - ref main_entity, - ref aux_entities, - .. - } => { - builder.add_label(codespan_reporting::Label { - span: entity, - message: None, - style: codespan_reporting::LabelStyle::Primary, - }); - - builder.add_label(codespan_reporting::Label { - span: *main_entity, - message: Some(type_error.to_string()), - style: codespan_reporting::LabelStyle::Primary, - }); - - for aux_entity in aux_entities { - builder.add_label(codespan_reporting::Label { - span: aux_entity.entity, - message: Some(aux_entity.label.clone()), - style: codespan_reporting::LabelStyle::Secondary, - }); - } - - builder.add_diagnostic( - codespan_reporting::Severity::Error, - None, - &self.to_string(), - ); - } - }, - Error::Constexpr(entity, ref constexpr_error) => { - builder.add_label(codespan_reporting::Label { - span: entity, - message: Some("while evaluating this constexpr".to_owned()), - style: codespan_reporting::LabelStyle::Primary, - }); - match constexpr_error { - constexpr::error::Error::Evaluation(ref interpreter_error) => { - interpreter_error.to_diagnostics(builder); - } - } - } Error::Multiple { ref errors } => { for error in errors { error.to_diagnostics(builder); diff --git a/src/ir/location.rs b/src/ir/location.rs new file mode 100644 index 0000000..ba83bee --- /dev/null +++ b/src/ir/location.rs @@ -0,0 +1,2 @@ +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct Location(pub codespan::ByteSpan); diff --git a/src/ir/mod.rs b/src/ir/mod.rs index 95356e4..1c6d2aa 100644 --- a/src/ir/mod.rs +++ b/src/ir/mod.rs @@ -1,125 +1,159 @@ //! Intermediate representation variables for the compiler and interpreter. +use std::borrow; +use std::collections; use std::fmt; +use std::sync; -use specs; - -use crate::ast; -use crate::parser; +use crate::source; +use crate::syntax; pub mod builder; -pub mod component; +pub mod element; pub mod error; -mod system; +pub mod location; #[cfg(test)] mod tests; -/// A separate universe of the Tin intermediate representation. -pub struct Ir { - pub(crate) world: specs::World, +#[salsa::query_group(IrStorage)] +pub trait Db: salsa::Database + syntax::Db { + #[salsa::interned] + fn ident(&self, id: sync::Arc) -> Ident; + + #[salsa::interned] + fn entity(&self, parent: Option, role: EntityRole) -> Entity; + + fn element(&self, entity: Entity) -> error::Result>; + + fn location(&self, entity: Entity) -> error::Result; + + fn entities(&self) -> error::Result>; } -impl Ir { - /// Creates a new IR instance. - pub fn new() -> Ir { - let mut world = specs::World::new(); - component::register_all(&mut world); - Ir { world } - } +#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct Ident(salsa::InternId); - /// Adds the specified AST module to the IR world. - pub fn load(&mut self, module: &ast::Module) -> Result<(), error::Error> { - use specs::world::Builder; +#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct Entity(salsa::InternId); - let entity = self.world.create_entity().build(); - builder::Builder::new(&mut self.world).add_module(entity, module)?; +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Entities { + infos: collections::HashMap, + modules: Vec, +} - let mut dispatcher = specs::DispatcherBuilder::new() - .with( - system::apply_replacements::System, - "apply_replacements", - &[], - ) - .build(); +#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub enum EntityRole { + File(source::FileId), + RecordField(Ident), + TupleField(usize), + VariableDefinition(Ident), + VariableInitializer, + SelectField(Ident), + AppliedFunction, + AppliedParameter(usize), + ParameterSignature, + ClosureCaptureDefinition(Ident), + ClosureParameter(Ident), + ClosureStatement(usize), + ClosureSignature, + ClosureResult, + UnOperand, + BiLhs, + BiRhs, +} - dispatcher.dispatch(&self.world.res); +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct EntityInfo { + element: sync::Arc, + location: location::Location, +} - self.maintain()?; +impl Ident { + pub fn id(self) -> u32 { + u32::from(self.0) + } +} - Ok(()) +impl Entity { + pub fn id(self) -> u32 { + u32::from(self.0) } +} - /// Checks and infers types for all known variables. - /// - /// `resolve_references` should be called before this; types will not be inferred for unresolved - /// references. - pub fn check_types(&mut self) -> Result<(), error::Error> { - let mut dispatcher = specs::DispatcherBuilder::new() - .with(system::infer_types::System, "infer_types", &[]) - .with(system::infer_constexpr::System, "infer_constexpr", &[]) - .with(system::infer_layouts::System::new(8), "infer_layouts", &[]) - .build(); +impl salsa::InternKey for Ident { + fn from_intern_id(v: salsa::InternId) -> Self { + Ident(v) + } - dispatcher.dispatch(&self.world.res); + fn as_intern_id(&self) -> salsa::InternId { + self.0 + } +} - self.maintain()?; +impl salsa::InternKey for Entity { + fn from_intern_id(v: salsa::InternId) -> Self { + Entity(v) + } - Ok(()) + fn as_intern_id(&self) -> salsa::InternId { + self.0 } +} - fn maintain(&mut self) -> Result<(), error::Error> { - use specs::Join; - - self.world.maintain(); - - let mut errors = Vec::new(); - - let entities = self.world.entities(); - let locations = self.world.read_storage::(); - let type_errors = self - .world - .read_storage::>(); - let constexpr_errors = self - .world - .read_storage::(); - - for (entity, type_error) in (&entities, &type_errors).join() { - errors.push(error::Error::Type( - locations.get(entity).unwrap().0, - component::ty::error::Error { - expected: type_error.expected.clone(), - actual: type_error.actual.clone(), - main_entity: locations.get(type_error.main_entity).unwrap().0, - aux_entities: type_error - .aux_entities - .iter() - .map(|aux_entity| component::ty::error::AuxEntity { - entity: locations.get(aux_entity.entity).unwrap().0, - label: aux_entity.label.clone(), - }) - .collect(), - }, - )) - } +impl EntityInfo { + fn new(element: element::Element, location: location::Location) -> Self { + let element = sync::Arc::new(element); - for (entity, constexpr_error, _) in (&entities, &constexpr_errors, !&type_errors).join() { - errors.push(error::Error::Constexpr( - locations.get(entity).unwrap().0, - constexpr_error.clone(), - )); - } + Self { element, location } + } +} - if errors.is_empty() { - Ok(()) - } else { - Err(errors - .pop() - .unwrap_or_else(|| error::Error::Multiple { errors })) - } +impl Entities { + pub fn new() -> Self { + let infos = collections::HashMap::new(); + let modules = Vec::new(); + + Self { infos, modules } + } + + pub fn all(&self) -> impl Iterator + '_ { + self.infos.keys().cloned() + } + + pub fn modules(&self) -> impl Iterator + '_ { + self.modules.iter().cloned() } } -impl fmt::Debug for Ir { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Ir").finish() +impl EntityInfo { + pub fn element(&self) -> &element::Element { + &self.element + } + + pub fn location(&self) -> location::Location { + self.location + } +} + +fn element(db: &impl Db, entity: Entity) -> error::Result> { + Ok(db.entities()?.infos.get(&entity).unwrap().element.clone()) +} + +fn location(db: &impl Db, entity: Entity) -> error::Result { + Ok(db.entities()?.infos.get(&entity).unwrap().location) +} + +fn entities(db: &impl Db) -> error::Result> { + let mut entities = Entities::new(); + for source_root_id in &*db.all_source_roots() { + for file in db.source_root(*source_root_id).files.values() { + let result = db.parse(*file).unwrap(); + + let entity = db.entity(None, EntityRole::File(*file)); + let builder = builder::Builder::new(db, entity, &mut entities.infos); + builder.build_module(&*result)?; + entities.modules.push(entity); + } } + Ok(sync::Arc::new(entities)) } diff --git a/src/ir/system/apply_replacements.rs b/src/ir/system/apply_replacements.rs deleted file mode 100644 index 5e3933f..0000000 --- a/src/ir/system/apply_replacements.rs +++ /dev/null @@ -1,90 +0,0 @@ -use std::collections; - -use specs; -use specs_visitor; - -use crate::ir::component::element; -use crate::ir::component::layout; -use crate::ir::component::replacement; -use crate::ir::component::symbol; -use crate::ir::component::ty; - -pub struct System; - -struct ReplacementEntityVisitor { - replacements: collections::HashMap, -} - -impl<'a> specs::System<'a> for System { - #[cfg_attr(feature = "cargo-clippy", allow(clippy::type_complexity))] - type SystemData = ( - specs::Entities<'a>, - specs::ReadStorage<'a, replacement::Replacement>, - specs::WriteStorage<'a, element::Element>, - specs::WriteStorage<'a, layout::Layout>, - specs::WriteStorage<'a, symbol::Symbol>, - specs::WriteStorage<'a, ty::Type>, - specs::WriteStorage<'a, ty::error::Error>, - ); - - fn run( - &mut self, - ( - entities, - replacements, - mut elements, - mut layouts, - mut symbols, - mut types, - mut type_errors, - ): Self::SystemData, - ) { - use crate::best_iter::BestIterator; - use crate::best_iter::BestIteratorCollect; - use crate::best_iter::BestIteratorMap; - use crate::best_iter::BestJoin; - use specs_visitor::VisitEntitiesMut; - - (&entities, &replacements) - .best_join() - .best_for_each(|(entity, _)| { - entities.delete(entity).unwrap(); - }); - - let replacements = (&entities, &replacements) - .best_join() - .best_map(|(entity, replacement)| (entity, replacement.to)) - .best_collect(); - - let visitor = ReplacementEntityVisitor { replacements }; - - (&mut elements).best_join().best_for_each(|element| { - element.accept_mut(&visitor); - }); - - (&mut layouts).best_join().best_for_each(|layout| { - layout.accept_mut(&visitor); - }); - - (&mut symbols).best_join().best_for_each(|symbol| { - symbol.accept_mut(&visitor); - }); - - (&mut types).best_join().best_for_each(|ty| { - ty.accept_mut(&visitor); - }); - - (&mut type_errors).best_join().best_for_each(|type_error| { - type_error.accept_mut(&visitor); - }); - } -} - -impl specs_visitor::EntityVisitorMut for ReplacementEntityVisitor { - fn visit_entity_mut(&self, from: &mut specs::Entity) { - if let Some(to) = self.replacements.get(from) { - trace!("applying replacement from {:?} to {:?}", from, to); - *from = *to; - } - } -} diff --git a/src/ir/system/infer_constexpr.rs b/src/ir/system/infer_constexpr.rs deleted file mode 100644 index 5f8a3a3..0000000 --- a/src/ir/system/infer_constexpr.rs +++ /dev/null @@ -1,79 +0,0 @@ -use specs; - -use std::ops; - -use crate::interpreter; -use crate::ir::component::constexpr; -use crate::ir::component::element; - -pub struct System; - -impl<'a> specs::System<'a> for System { - type SystemData = ( - specs::Entities<'a>, - specs::ReadStorage<'a, element::Element>, - specs::WriteStorage<'a, constexpr::Constexpr>, - specs::WriteStorage<'a, constexpr::error::Error>, - ); - - fn run(&mut self, (entities, elements, mut constexprs, mut errors): Self::SystemData) { - use crate::best_iter::BestIteratorCollect; - use crate::best_iter::BestIteratorFlatMap; - use crate::best_iter::BestJoin; - - loop { - let new_constexprs: Vec<_> = (&entities, &elements, !&constexprs, !&errors) - .best_join() - .best_flat_map(|(entity, element, _, _)| { - transpose(System::infer_constexpr(element, &constexprs)).map(|r| (entity, r)) - }) - .best_collect(); - - debug!("inferred new constexprs: {:?}", new_constexprs); - if new_constexprs.is_empty() { - break; - } - - for (entity, constexpr) in new_constexprs { - match constexpr { - Ok(constexpr) => { - constexprs.insert(entity, constexpr).unwrap(); - } - Err(error) => { - errors.insert(entity, error).unwrap(); - } - } - } - } - } -} - -impl System { - fn infer_constexpr( - element: &element::Element, - constexprs: &specs::Storage, - ) -> Result, constexpr::error::Error> - where - D: ops::Deref>, - { - Ok( - interpreter::eval(element, |e| constexprs.get(e).map(|c| &c.value))? - .map(|value| constexpr::Constexpr { value }), - ) - } -} - -impl From for constexpr::error::Error { - fn from(e: interpreter::error::Error) -> Self { - constexpr::error::Error::Evaluation(e) - } -} - -// TODO: awaits https://github.com/rust-lang/rust/issues/47338 -pub fn transpose(result: Result, E>) -> Option> { - match result { - Ok(Some(x)) => Some(Ok(x)), - Ok(None) => None, - Err(e) => Some(Err(e)), - } -} diff --git a/src/ir/system/infer_layouts.rs b/src/ir/system/infer_layouts.rs deleted file mode 100644 index d164bc2..0000000 --- a/src/ir/system/infer_layouts.rs +++ /dev/null @@ -1,504 +0,0 @@ -use std::collections; -use std::usize; - -use specs; - -use crate::ir::component::element; -use crate::ir::component::layout; -use std::ops; - -pub struct System { - ptr_size: usize, -} - -const BOOL_LAYOUT: layout::Layout = layout::Layout::scalar(1); - -impl<'a> specs::System<'a> for System { - type SystemData = ( - specs::Entities<'a>, - specs::ReadStorage<'a, element::Element>, - specs::WriteStorage<'a, layout::Layout>, - ); - - fn run(&mut self, (entities, elements, mut layouts): Self::SystemData) { - use crate::best_iter::BestIteratorCollect; - use crate::best_iter::BestIteratorFlatMap; - use crate::best_iter::BestJoin; - - loop { - let new_layouts: Vec<_> = (&entities, &elements, !&layouts) - .best_join() - .best_flat_map(|(entity, element, _)| { - self.infer_layout(element, &elements, &layouts) - .map(|layout| (entity, layout)) - }) - .best_collect(); - debug!("inferred new layouts: {:?}", new_layouts); - if new_layouts.is_empty() { - break; - } - - for (entity, layout) in new_layouts { - layouts.insert(entity, layout).unwrap(); - } - } - } -} - -impl System { - pub fn new(ptr_size: usize) -> System { - System { ptr_size } - } - - fn infer_layout( - &self, - element: &element::Element, - elements: &specs::Storage, - layouts: &specs::Storage, - ) -> Option - where - DE: ops::Deref>, - DL: ops::Deref>, - { - match *element { - element::Element::Number(ref n) => self.infer_number_layout(n), - element::Element::String(_) => Some(layout::Layout::scalar(self.ptr_size)), - element::Element::Symbol(_) => Some(layout::Layout::zero()), - element::Element::Tuple(element::Tuple { ref fields }) => { - self.infer_tuple_layout(fields, layouts) - } - element::Element::Record(element::Record { ref fields }) => { - self.infer_record_layout(fields, layouts) - } - element::Element::UnOp(element::UnOp { operator, operand }) => { - self.infer_un_op_layout(operator, operand, layouts) - } - element::Element::BiOp(element::BiOp { lhs, operator, rhs }) => { - self.infer_bi_op_layout(lhs, operator, rhs, layouts) - } - element::Element::Variable(element::Variable { initializer, .. }) => { - self.infer_variable_layout(initializer, layouts) - } - element::Element::Select(element::Select { record, ref field }) => { - self.infer_select_layout(record, field, elements, layouts) - } - element::Element::Apply(element::Apply { - function, - ref parameters, - }) => self.infer_apply_layout(function, parameters, layouts), - element::Element::Parameter(element::Parameter { signature, .. }) => { - self.infer_parameter_layout(signature, layouts) - } - element::Element::Capture(element::Capture { captured, .. }) => { - self.infer_capture_layout(captured, layouts) - } - element::Element::Closure(element::Closure { ref captures, .. }) => { - self.infer_closure_layout(captures, layouts) - } - element::Element::Module(element::Module { ref variables }) => { - self.infer_module_layout(variables, layouts) - } - } - } - - fn infer_number_layout(&self, number: &element::Number) -> Option { - match *number { - element::Number::U8(_) | element::Number::I8(_) => Some(layout::Layout::scalar(1)), - element::Number::U16(_) | element::Number::I16(_) => Some(layout::Layout::scalar(2)), - element::Number::U32(_) | element::Number::I32(_) | element::Number::F32(_) => { - Some(layout::Layout::scalar(4)) - } - element::Number::U64(_) | element::Number::I64(_) | element::Number::F64(_) => { - Some(layout::Layout::scalar(8)) - } - } - } - - fn infer_tuple_layout( - &self, - fields: &[specs::Entity], - layouts: &specs::Storage, - ) -> Option - where - D: ops::Deref>, - { - if let Some(mut layouts) = fields - .iter() - .enumerate() - .map(|(i, f)| layouts.get(*f).map(|l| (i, l))) - .collect::>>() - { - if layouts.is_empty() { - Some(layout::Layout::zero()) - } else { - layouts.sort_unstable_by_key(|(i, l)| (usize::max_value() - l.size, *i)); - let alignment = layouts.iter().map(|(_, l)| l.alignment).max().unwrap(); - let mut size = 0; - - let mut unnamed_fields = vec![layout::Offset::zero(); layouts.len()]; - - for (i, layout) in layouts { - let offset = align_up(size, layout.alignment); - size = offset + layout.size; - let layout = layout.clone(); - unnamed_fields[i] = layout::Offset { offset, layout }; - } - - Some(layout::Layout::unnamed_fields( - size, - alignment, - unnamed_fields, - )) - } - } else { - None - } - } - - fn infer_record_layout( - &self, - fields: &collections::HashMap, - layouts: &specs::Storage, - ) -> Option - where - D: ops::Deref>, - { - if let Some(mut layouts) = fields - .iter() - .map(|(n, f)| layouts.get(*f).map(|l| (n, l))) - .collect::>>() - { - if layouts.is_empty() { - Some(layout::Layout::zero()) - } else { - layouts.sort_unstable_by_key(|(n, l)| (usize::max_value() - l.size, n.as_str())); - let alignment = layouts.iter().map(|(_, l)| l.alignment).max().unwrap(); - let mut size = 0; - - let named_fields = layouts - .into_iter() - .map(|(field, layout)| { - let offset = align_up(size, layout.alignment); - size = offset + layout.size; - let field = field.clone(); - let layout = layout.clone(); - let offset_layout = layout::Offset { offset, layout }; - - layout::NamedField { - field, - offset_layout, - } - }) - .collect::>(); - - Some(layout::Layout::named_fields(size, alignment, named_fields)) - } - } else { - None - } - } - - fn infer_un_op_layout( - &self, - operator: element::UnOperator, - operand: specs::Entity, - layouts: &specs::Storage, - ) -> Option - where - D: ops::Deref>, - { - let operand = layouts.get(operand).cloned(); - - match operator { - element::UnOperator::Not => Some(BOOL_LAYOUT), - element::UnOperator::BNot - | element::UnOperator::Cl0 - | element::UnOperator::Cl1 - | element::UnOperator::Cls - | element::UnOperator::Ct0 - | element::UnOperator::Ct1 - | element::UnOperator::C0 - | element::UnOperator::C1 - | element::UnOperator::Sqrt => operand, - } - } - - fn infer_bi_op_layout( - &self, - lhs: specs::Entity, - operator: element::BiOperator, - rhs: specs::Entity, - layouts: &specs::Storage, - ) -> Option - where - D: ops::Deref>, - { - let lhs = layouts.get(lhs).cloned(); - let rhs = layouts.get(rhs).cloned(); - - if let (Some(lhs), Some(rhs)) = (lhs.as_ref(), rhs.as_ref()) { - if lhs.size != rhs.size { - return None; - } - if lhs.alignment != rhs.alignment { - return None; - } - } - - match operator { - element::BiOperator::Eq - | element::BiOperator::Ne - | element::BiOperator::Lt - | element::BiOperator::Ge - | element::BiOperator::Gt - | element::BiOperator::Le - | element::BiOperator::And - | element::BiOperator::Or - | element::BiOperator::Xor - | element::BiOperator::AndNot - | element::BiOperator::OrNot - | element::BiOperator::XorNot => Some(BOOL_LAYOUT), - element::BiOperator::Cmp => unimplemented!(), - element::BiOperator::Add - | element::BiOperator::Sub - | element::BiOperator::Mul - | element::BiOperator::Div - | element::BiOperator::Rem - | element::BiOperator::BAnd - | element::BiOperator::BOr - | element::BiOperator::BXor - | element::BiOperator::BAndNot - | element::BiOperator::BOrNot - | element::BiOperator::BXorNot - | element::BiOperator::RotL - | element::BiOperator::RotR - | element::BiOperator::ShL - | element::BiOperator::ShR => lhs, - } - } - - fn infer_variable_layout( - &self, - initializer: specs::Entity, - layouts: &specs::Storage, - ) -> Option - where - D: ops::Deref>, - { - layouts.get(initializer).cloned() - } - - fn infer_select_layout( - &self, - record: specs::Entity, - field: &str, - elements: &specs::Storage, - layouts: &specs::Storage, - ) -> Option - where - DE: ops::Deref>, - DL: ops::Deref>, - { - match elements.get(record) { - None => None, - Some(t) => match t { - element::Element::Record(element::Record { ref fields }) => { - if let Some(f) = fields.get(field) { - layouts.get(*f).cloned() - } else { - None - } - } - _ => None, - }, - } - } - - fn infer_apply_layout( - &self, - _function: specs::Entity, - _parameters: &[specs::Entity], - _layouts: &specs::Storage, - ) -> Option - where - D: ops::Deref>, - { - // TODO - None - /* - match types.get(function) { - None => { - trace!("inference failure: missing function type for apply"); - None - } - Some(f) => match f { - ty::Type::Function(ty::Function { - parameters: ref formal_parameters, - result, - }) => { - if let Some(parameters) = parameters - .iter() - .map(|p| types.get(*p).cloned()) - .collect::>>() - { - if parameters == *formal_parameters { - Some((**result).clone()) - } else { - Some(ty::Type::Conflict(ty::Conflict { - expected: Box::new(ty::Type::Function(ty::Function { - parameters, - result: Box::new(ty::Type::Any), - })), - actual: Box::new(f.clone()), - })) - } - } else { - None - } - } - something => Some(ty::Type::Conflict(ty::Conflict { - expected: Box::new(ty::Type::Function(ty::Function { - parameters: vec![ty::Type::Any], - result: Box::new(ty::Type::Any), - })), - actual: Box::new(something.clone()), - })), - }, - } - */ - } - - fn infer_parameter_layout( - &self, - signature: specs::Entity, - layouts: &specs::Storage, - ) -> Option - where - D: ops::Deref>, - { - layouts.get(signature).cloned() - } - - fn infer_capture_layout( - &self, - capture: specs::Entity, - layouts: &specs::Storage, - ) -> Option - where - D: ops::Deref>, - { - layouts.get(capture).cloned() - } - - fn infer_closure_layout( - &self, - captures: &collections::HashMap, - layouts: &specs::Storage, - ) -> Option - where - D: ops::Deref>, - { - if let Some(mut capture_layouts) = captures - .iter() - .map(|(n, f)| layouts.get(*f).map(|l| (n, l))) - .collect::>>() - { - let unnamed_fields = vec![layout::Offset { - offset: 0, - layout: layout::Layout::scalar(self.ptr_size), - }]; - - capture_layouts - .sort_unstable_by_key(|(n, l)| (usize::max_value() - l.size, n.as_str())); - let alignment = capture_layouts - .iter() - .map(|(_, l)| l.alignment) - .max() - .unwrap_or(self.ptr_size); - let mut size = self.ptr_size; - - let named_fields = capture_layouts - .into_iter() - .map(|(field, layout)| { - let offset = align_up(size, layout.alignment); - size = offset + layout.size; - let field = field.clone(); - let layout = layout.clone(); - let offset_layout = layout::Offset { offset, layout }; - - layout::NamedField { - field, - offset_layout, - } - }) - .collect::>(); - - Some(layout::Layout { - size, - alignment, - named_fields, - unnamed_fields, - }) - } else { - None - } - } - - fn infer_module_layout( - &self, - _variables: &collections::HashMap, - _layouts: &specs::Storage, - ) -> Option - where - D: ops::Deref>, - { - // TODO - None - /* - variables - .iter() - .map(|(k, v)| types.get(*v).map(|t| (k.clone(), t.clone()))) - .collect::>>() - .map(|fields| ty::Type::Record(ty::Record { fields })) - */ - } -} - -#[allow(clippy::cast_sign_loss, clippy::cast_possible_wrap)] -fn align_up(offset: usize, alignment: usize) -> usize { - debug_assert!(alignment.is_power_of_two()); - offset + ((-(offset as isize)) & (alignment as isize - 1)) as usize -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn align_up_4() { - assert_eq!(0, align_up(0, 4)); - assert_eq!(4, align_up(1, 4)); - assert_eq!(4, align_up(2, 4)); - assert_eq!(4, align_up(3, 4)); - assert_eq!(4, align_up(4, 4)); - assert_eq!(8, align_up(5, 4)); - assert_eq!(8, align_up(6, 4)); - assert_eq!(8, align_up(7, 4)); - assert_eq!(8, align_up(8, 4)); - assert_eq!(12, align_up(9, 4)); - } - - #[test] - fn align_up_8() { - assert_eq!(0, align_up(0, 8)); - assert_eq!(8, align_up(1, 8)); - assert_eq!(8, align_up(2, 8)); - assert_eq!(8, align_up(3, 8)); - assert_eq!(8, align_up(4, 8)); - assert_eq!(8, align_up(5, 8)); - assert_eq!(8, align_up(6, 8)); - assert_eq!(8, align_up(7, 8)); - assert_eq!(8, align_up(8, 8)); - assert_eq!(16, align_up(9, 8)); - } -} diff --git a/src/ir/system/infer_types.rs b/src/ir/system/infer_types.rs deleted file mode 100644 index 2009dbb..0000000 --- a/src/ir/system/infer_types.rs +++ /dev/null @@ -1,636 +0,0 @@ -use std::collections; - -use specs; - -use crate::ir::component::element; -use crate::ir::component::ty; -use std::ops; - -lazy_static! { - static ref BOOL_TYPE: ty::Type = { - let alternatives = vec![ - ty::Symbol { - label: "f".to_owned(), - }, - ty::Symbol { - label: "t".to_owned(), - }, - ]; - ty::Type::Union(ty::Union { alternatives }) - }; -} - -pub struct System; - -#[derive(Clone, Debug)] -enum Inference { - Type(T), - Error(ty::error::Error), -} - -type InferenceResult = Option>; - -impl<'a> specs::System<'a> for System { - type SystemData = ( - specs::Entities<'a>, - specs::ReadStorage<'a, element::Element>, - specs::WriteStorage<'a, ty::Type>, - specs::WriteStorage<'a, ty::error::Error>, - ); - - fn run(&mut self, (entities, elements, mut types, mut errors): Self::SystemData) { - use crate::best_iter::BestIteratorCollect; - use crate::best_iter::BestIteratorFlatMap; - use crate::best_iter::BestJoin; - - loop { - let new_types: Vec<_> = (&entities, &elements, !&types, !&errors) - .best_join() - .best_flat_map(|(entity, element, _, _)| { - infer_type(element, &types).map(|ty| (entity, ty)) - }) - .best_collect(); - debug!("inferred new types: {:?}", new_types); - if new_types.is_empty() { - break; - } - - for (entity, inference) in new_types { - match inference { - Inference::Type(ty) => { - types.insert(entity, ty).unwrap(); - } - Inference::Error(error) => { - errors.insert(entity, error).unwrap(); - } - } - } - } - } -} - -fn infer_type( - element: &element::Element, - types: &specs::Storage, -) -> InferenceResult -where - D: ops::Deref>, -{ - match *element { - element::Element::Number(ref n) => { - Some(Inference::Type(ty::Type::Number(infer_number_type(n)))) - } - element::Element::String(_) => Some(Inference::Type(ty::Type::String)), - element::Element::Symbol(element::Symbol { ref label }) => { - Some(Inference::Type(ty::Type::Symbol(ty::Symbol { - label: label.clone(), - }))) - } - element::Element::Tuple(element::Tuple { ref fields }) => infer_tuple_type(fields, types), - element::Element::Record(element::Record { ref fields }) => { - infer_record_type(fields, types) - } - element::Element::UnOp(element::UnOp { operand, operator }) => { - infer_un_op_type(operand, operator, types) - } - element::Element::BiOp(element::BiOp { lhs, operator, rhs }) => { - infer_bi_op_type(lhs, operator, rhs, types) - } - element::Element::Variable(element::Variable { initializer, .. }) => { - infer_variable_type(initializer, types) - } - element::Element::Select(element::Select { record, ref field }) => { - infer_select_type(record, field, types) - } - element::Element::Apply(element::Apply { - function, - ref parameters, - }) => infer_apply_type(function, parameters, types), - element::Element::Parameter(element::Parameter { signature, .. }) => { - infer_parameter_type(signature, types) - } - element::Element::Capture(element::Capture { captured, .. }) => { - infer_capture_type(captured, types) - } - element::Element::Closure(element::Closure { - ref parameters, - signature, - result, - .. - }) => infer_closure_type(parameters, signature, result, types), - element::Element::Module(element::Module { ref variables }) => { - infer_module_type(variables, types) - } - } -} - -fn infer_number_type(number: &element::Number) -> ty::Number { - match *number { - element::Number::U8(_) => ty::Number::U8, - element::Number::U16(_) => ty::Number::U16, - element::Number::U32(_) => ty::Number::U32, - element::Number::U64(_) => ty::Number::U64, - element::Number::I8(_) => ty::Number::I8, - element::Number::I16(_) => ty::Number::I16, - element::Number::I32(_) => ty::Number::I32, - element::Number::I64(_) => ty::Number::I64, - element::Number::F32(_) => ty::Number::F32, - element::Number::F64(_) => ty::Number::F64, - } -} - -fn infer_tuple_type( - fields: &[specs::Entity], - types: &specs::Storage, -) -> InferenceResult -where - D: ops::Deref>, -{ - fields - .iter() - .map(|f| types.get(*f).cloned()) - .collect::>>() - .map(|fields| Inference::Type(ty::Type::Tuple(ty::Tuple { fields }))) -} - -fn infer_record_type( - fields: &collections::HashMap, - types: &specs::Storage, -) -> InferenceResult -where - D: ops::Deref>, -{ - fields - .iter() - .map(|(k, v)| types.get(*v).map(|t| (k.clone(), t.clone()))) - .collect::>>() - .map(|fields| Inference::Type(ty::Type::Record(ty::Record { fields }))) -} - -fn infer_un_op_type( - operand: specs::Entity, - operator: element::UnOperator, - types: &specs::Storage, -) -> InferenceResult -where - D: ops::Deref>, -{ - types.get(operand).map(|ty| match operator { - element::UnOperator::Not => { - if *ty == *BOOL_TYPE { - Inference::Type(BOOL_TYPE.clone()) - } else { - Inference::Error(ty::error::Error { - expected: ty::error::ExpectedType::Specific(BOOL_TYPE.clone()), - actual: ty.clone(), - main_entity: operand, - aux_entities: vec![], - }) - } - } - element::UnOperator::BNot => if_integral_then(operand, ty, ty), - element::UnOperator::Cl0 - | element::UnOperator::Cl1 - | element::UnOperator::Cls - | element::UnOperator::Ct0 - | element::UnOperator::Ct1 - | element::UnOperator::C0 - | element::UnOperator::C1 => { - if_integral_then(operand, ty, &ty::Type::Number(ty::Number::U32)) - } - element::UnOperator::Sqrt => if_fractional_then(operand, ty, ty), - }) -} - -fn infer_bi_op_type( - lhs: specs::Entity, - operator: element::BiOperator, - rhs: specs::Entity, - types: &specs::Storage, -) -> InferenceResult -where - D: ops::Deref>, -{ - // TODO: check scalar type semantics so e.g. records can't be divided. - match (types.get(lhs), types.get(rhs)) { - (Some(lhs_ty), Some(rhs_ty)) => { - let result = match operator { - element::BiOperator::Eq - | element::BiOperator::Ne - | element::BiOperator::Lt - | element::BiOperator::Ge - | element::BiOperator::Gt - | element::BiOperator::Le => if_eq_then(lhs, lhs_ty, rhs, rhs_ty, &*BOOL_TYPE), - element::BiOperator::Cmp => unimplemented!(), - element::BiOperator::Add - | element::BiOperator::Sub - | element::BiOperator::Mul - | element::BiOperator::Div - | element::BiOperator::Rem - // TODO: don't allow floats - | element::BiOperator::BAnd - | element::BiOperator::BOr - | element::BiOperator::BXor - | element::BiOperator::BAndNot - | element::BiOperator::BOrNot - | element::BiOperator::BXorNot => if_eq_then(lhs, lhs_ty, rhs, rhs_ty, lhs_ty), - element::BiOperator::Or => or_op(lhs, lhs_ty, rhs, rhs_ty), - element::BiOperator::And |element::BiOperator::Xor |element::BiOperator::AndNot |element::BiOperator::OrNot | element::BiOperator::XorNot => bool_op(lhs, lhs_ty, rhs, rhs_ty), - element::BiOperator::RotL | element::BiOperator::RotR |element::BiOperator::ShL |element::BiOperator::ShR => if_integral_and_eq_then( - lhs, - lhs_ty, - rhs, - rhs_ty, - &ty::Type::Number(ty::Number::U32), - lhs_ty, - ), - }; - Some(result) - } - _ => None, - } -} - -fn infer_variable_type( - initializer: specs::Entity, - types: &specs::Storage, -) -> InferenceResult -where - D: ops::Deref>, -{ - types.get(initializer).cloned().map(Inference::Type) -} - -fn infer_select_type( - record: specs::Entity, - field: &str, - types: &specs::Storage, -) -> InferenceResult -where - D: ops::Deref>, -{ - match types.get(record) { - None => None, - Some(t) => match t { - ty::Type::Record(ty::Record { ref fields }) => { - if let Some(t) = fields.get(field) { - Some(Inference::Type(t.clone())) - } else { - let mut expected_fields = collections::HashMap::new(); - expected_fields.insert( - field.to_owned(), - ty::Type::Symbol(ty::Symbol { - label: "something".to_owned(), - }), - ); - Some(Inference::Error(ty::error::Error { - expected: ty::error::ExpectedType::Specific(ty::Type::Record(ty::Record { - fields: expected_fields, - })), - actual: t.clone(), - main_entity: record, - aux_entities: vec![], - })) - } - } - something => { - let mut expected_fields = collections::HashMap::new(); - expected_fields.insert( - field.to_owned(), - ty::Type::Symbol(ty::Symbol { - label: "something".to_owned(), - }), - ); - Some(Inference::Error(ty::error::Error { - expected: ty::error::ExpectedType::Specific(ty::Type::Record(ty::Record { - fields: expected_fields, - })), - actual: something.clone(), - main_entity: record, - aux_entities: vec![], - })) - } - }, - } -} - -fn infer_apply_type( - function: specs::Entity, - parameters: &[specs::Entity], - types: &specs::Storage, -) -> InferenceResult -where - D: ops::Deref>, -{ - match types.get(function) { - None => { - trace!("inference failure: missing function type for apply"); - None - } - Some(f) => match f { - ty::Type::Function(ty::Function { - parameters: ref formal_parameters, - result, - }) => { - if let Some(parameters) = parameters - .iter() - .map(|p| types.get(*p).cloned()) - .collect::>>() - { - if parameters == *formal_parameters { - Some(Inference::Type((**result).clone())) - } else { - // TODO: create a diff of expected and actual parameters - Some(Inference::Error(ty::error::Error { - expected: ty::error::ExpectedType::Specific(ty::Type::Function( - ty::Function { - parameters, - result: Box::new(ty::Type::Symbol(ty::Symbol { - label: "something".to_owned(), - })), - }, - )), - actual: f.clone(), - main_entity: function, - aux_entities: vec![], - })) - } - } else { - None - } - } - something => Some(Inference::Error(ty::error::Error { - expected: ty::error::ExpectedType::Specific(ty::Type::Function(ty::Function { - parameters: vec![ty::Type::Symbol(ty::Symbol { - label: "something".to_owned(), - })], - result: Box::new(ty::Type::Symbol(ty::Symbol { - label: "something".to_owned(), - })), - })), - actual: something.clone(), - main_entity: function, - aux_entities: vec![], - })), - }, - } -} - -fn infer_parameter_type( - signature: specs::Entity, - types: &specs::Storage, -) -> InferenceResult -where - D: ops::Deref>, -{ - types.get(signature).cloned().map(Inference::Type) -} - -fn infer_capture_type( - capture: specs::Entity, - types: &specs::Storage, -) -> InferenceResult -where - D: ops::Deref>, -{ - types.get(capture).cloned().map(Inference::Type) -} - -fn infer_closure_type( - parameters: &[specs::Entity], - signature: specs::Entity, - result: specs::Entity, - types: &specs::Storage, -) -> InferenceResult -where - D: ops::Deref>, -{ - if let Some(parameters) = parameters - .iter() - .map(|p| types.get(*p).cloned()) - .collect::>>() - { - if let Some(result_ty) = types.get(result) { - if let Some(signature_ty) = types.get(signature) { - if signature_ty == result_ty { - let result = Box::new(signature_ty.clone()); - Some(Inference::Type(ty::Type::Function(ty::Function { - parameters, - result, - }))) - } else { - Some(Inference::Error(ty::error::Error { - expected: ty::error::ExpectedType::Specific(signature_ty.clone()), - actual: result_ty.clone(), - main_entity: result, - aux_entities: vec![ty::error::AuxEntity { - entity: signature, - label: format!("declared return type is `{}`", signature_ty), - }], - })) - } - } else { - trace!("inference failure: no signature for closure"); - None - } - } else { - trace!("inference failure: missing signature type for closure, and no inferrable result type"); - None - } - } else { - trace!("inference failure: missing parameter type(s) for closure"); - // TODO: implement surjective type inference - None - } -} - -fn infer_module_type( - variables: &collections::HashMap, - types: &specs::Storage, -) -> InferenceResult -where - D: ops::Deref>, -{ - variables - .iter() - .map(|(k, v)| types.get(*v).map(|t| (k.clone(), t.clone()))) - .collect::>>() - .map(|fields| Inference::Type(ty::Type::Record(ty::Record { fields }))) -} - -fn if_eq_then( - lhs_entity: specs::Entity, - lhs: &ty::Type, - rhs_entity: specs::Entity, - rhs: &ty::Type, - result: &ty::Type, -) -> Inference { - if lhs == rhs { - Inference::Type(result.clone()) - } else { - Inference::Error(ty::error::Error { - expected: ty::error::ExpectedType::Specific(lhs.clone()), - actual: rhs.clone(), - main_entity: rhs_entity, - aux_entities: vec![ty::error::AuxEntity { - entity: lhs_entity, - label: format!("other operand has type `{}`", lhs), - }], - }) - } -} - -fn bool_op( - lhs_entity: specs::Entity, - lhs: &ty::Type, - rhs_entity: specs::Entity, - rhs: &ty::Type, -) -> Inference { - if *lhs == *BOOL_TYPE { - if *rhs == *BOOL_TYPE { - Inference::Type(BOOL_TYPE.clone()) - } else { - Inference::Error(ty::error::Error { - expected: ty::error::ExpectedType::Specific(BOOL_TYPE.clone()), - actual: rhs.clone(), - main_entity: rhs_entity, - aux_entities: vec![ty::error::AuxEntity { - entity: lhs_entity, - label: format!("other operand has type `{}`", lhs), - }], - }) - } - } else { - Inference::Error(ty::error::Error { - expected: ty::error::ExpectedType::Specific(BOOL_TYPE.clone()), - actual: lhs.clone(), - main_entity: lhs_entity, - aux_entities: vec![ty::error::AuxEntity { - entity: rhs_entity, - label: format!("other operand has type `{}`", rhs), - }], - }) - } -} - -fn or_op( - lhs_entity: specs::Entity, - lhs: &ty::Type, - rhs_entity: specs::Entity, - rhs: &ty::Type, -) -> Inference { - if let ty::Type::Union(u) = lhs { - if let ty::Type::Symbol(ref symbol) = rhs { - Inference::Type(ty::Type::Union(u.clone().with(symbol))) - } else { - Inference::Error(ty::error::Error { - expected: ty::error::ExpectedType::ScalarClass(ty::class::Scalar::Symbol), - actual: rhs.clone(), - main_entity: rhs_entity, - aux_entities: vec![ty::error::AuxEntity { - entity: lhs_entity, - label: format!("other operand has type `{}`", lhs), - }], - }) - } - } else if *lhs == *BOOL_TYPE { - if *rhs == *BOOL_TYPE { - Inference::Type(BOOL_TYPE.clone()) - } else { - Inference::Error(ty::error::Error { - expected: ty::error::ExpectedType::Specific(BOOL_TYPE.clone()), - actual: rhs.clone(), - main_entity: rhs_entity, - aux_entities: vec![ty::error::AuxEntity { - entity: lhs_entity, - label: format!("other operand has type `{}`", lhs), - }], - }) - } - } else { - Inference::Error(ty::error::Error { - expected: ty::error::ExpectedType::AnyOf(vec![ - ty::error::ExpectedType::Specific(BOOL_TYPE.clone()), - ty::error::ExpectedType::Union, - ]), - actual: lhs.clone(), - main_entity: lhs_entity, - aux_entities: vec![ty::error::AuxEntity { - entity: rhs_entity, - label: format!("other operand has type `{}`", rhs), - }], - }) - } -} - -fn if_integral_then( - entity: specs::Entity, - ty: &ty::Type, - result: &ty::Type, -) -> Inference { - match ty.scalar_class() { - ty::class::Scalar::Integral(_) => Inference::Type(result.clone()), - _ => Inference::Error(ty::error::Error { - expected: ty::error::ExpectedType::ScalarClass(ty::class::Scalar::Integral( - ty::class::IntegralScalar::Any, - )), - actual: ty.clone(), - main_entity: entity, - aux_entities: vec![], - }), - } -} - -fn if_integral_and_eq_then( - lhs_entity: specs::Entity, - lhs: &ty::Type, - rhs_entity: specs::Entity, - rhs: &ty::Type, - expected: &ty::Type, - result: &ty::Type, -) -> Inference { - match lhs.scalar_class() { - ty::class::Scalar::Integral(_) => { - if rhs == expected { - Inference::Type(result.clone()) - } else { - Inference::Error(ty::error::Error { - expected: ty::error::ExpectedType::Specific(expected.clone()), - actual: rhs.clone(), - main_entity: rhs_entity, - aux_entities: vec![ty::error::AuxEntity { - entity: lhs_entity, - label: format!("other operand has type `{}`", lhs), - }], - }) - } - } - _ => Inference::Error(ty::error::Error { - expected: ty::error::ExpectedType::ScalarClass(ty::class::Scalar::Integral( - ty::class::IntegralScalar::Any, - )), - actual: lhs.clone(), - main_entity: lhs_entity, - aux_entities: vec![ty::error::AuxEntity { - entity: rhs_entity, - label: format!("other operand has type `{}`", rhs), - }], - }), - } -} - -fn if_fractional_then( - entity: specs::Entity, - ty: &ty::Type, - result: &ty::Type, -) -> Inference { - match ty.scalar_class() { - ty::class::Scalar::Fractional => Inference::Type(result.clone()), - _ => Inference::Error(ty::error::Error { - expected: ty::error::ExpectedType::ScalarClass(ty::class::Scalar::Fractional), - actual: ty.clone(), - main_entity: entity, - aux_entities: vec![], - }), - } -} diff --git a/src/ir/system/mod.rs b/src/ir/system/mod.rs deleted file mode 100644 index 87c5ee0..0000000 --- a/src/ir/system/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod apply_replacements; -pub mod infer_constexpr; -pub mod infer_layouts; -pub mod infer_types; diff --git a/src/ir/tests.rs b/src/ir/tests.rs index abbdd94..f208e7b 100644 --- a/src/ir/tests.rs +++ b/src/ir/tests.rs @@ -1,9 +1,13 @@ use env_logger; use failure; +use std::collections; +use std::sync; -use super::*; -use crate::ast; +use crate::db; +use crate::layout; +use crate::source; use crate::test_util; +use std::any::Any; #[test] fn entity_assignments() -> Result<(), failure::Error> { @@ -59,8 +63,10 @@ a = || -> u32 { "#; let expected = Err(r#"error: undefined reference to `c` - :7:3 + | 7 | c | ^ + | "# .to_owned()); let actual = check_module("lexically_scoped_closure_vars", source); @@ -83,8 +89,10 @@ a = || -> u32 { "#; let expected = Err(r#"error: undefined reference to `c` - :3:7 + | 3 | b = c; | ^ + | "# .to_owned()); let actual = check_module("ordered_local_vars", source); @@ -103,16 +111,17 @@ a = || -> u32 { 1f32 + 2f64 }; "#; - let expected = Err(r#"error: type error -- :3:3 -3 | 1f32 + 2f64 - | ^^^^^^^^^^^ + let expected = Err(r#"error: expected `f32` but got `f64` - :3:10 + | 3 | 1f32 + 2f64 | ^^^^ expected `f32` but got `f64` + | - :3:3 + | 3 | 1f32 + 2f64 | ---- other operand has type `f32` + | "# .to_owned()); let actual = check_module("type_error", source); @@ -123,22 +132,40 @@ a = || -> u32 { } fn check_module(name: &'static str, source: &str) -> Result<(), String> { - use crate::parser::Parse; + use crate::ir::Db as _; + use crate::layout::Db as _; + use crate::source::Db as _; + use crate::ty::Db as _; let mut codemap = codespan::CodeMap::new(); - let span = codemap - .add_filemap(codespan::FileName::Virtual(name.into()), source.to_owned()) - .span(); - let ast_module = - ast::Module::parse(span, source).map_err(|e| crate::diagnostic::to_string(&codemap, &e))?; - - let mut ir = Ir::new(); - ir.load(&ast_module) - .map_err(|e| crate::diagnostic::to_string(&codemap, &e))?; - ir.check_types() + codemap.add_filemap(codespan::FileName::Virtual(name.into()), source.to_owned()); + + let root_id = source::RootId(1); + let file_id = source::FileId(1); + let path = relative_path::RelativePath::new(name).to_owned(); + let mut files = collections::HashMap::new(); + files.insert(path.clone(), file_id); + let root = source::Root { files }; + + let mut db = db::Db::new(); + + db.set_file_text(file_id, sync::Arc::new(source.to_owned())); + db.set_file_relative_path(file_id, path); + db.set_file_source_root(file_id, root_id); + db.set_source_root(root_id, sync::Arc::new(root)); + db.set_all_source_roots(sync::Arc::new(vec![root_id])); + db.set_ptr_size(layout::PtrSize::Size64); + + let entities = db + .entities() .map_err(|e| crate::diagnostic::to_string(&codemap, &e))?; - test_util::render_graph(&format!(concat!(module_path!(), "::{}"), name), &ir).unwrap(); + for entity in entities.all() { + db.ty(entity) + .map_err(|e| crate::diagnostic::to_string(&codemap, &e))?; + } + + test_util::render_graph(&format!(concat!(module_path!(), "::{}"), name), &db).unwrap(); Ok(()) } diff --git a/src/layout/error.rs b/src/layout/error.rs new file mode 100644 index 0000000..3a9e4c4 --- /dev/null +++ b/src/layout/error.rs @@ -0,0 +1,19 @@ +use crate::ir; +use crate::ty; +use std::result; + +#[derive(Clone, Debug, Eq, failure::Fail, PartialEq)] +pub enum Error { + #[fail(display = "semantic error: {}", _0)] + Ir(#[cause] ir::error::Error), + #[fail(display = "unknown size")] + UnknownSize, +} + +pub type Result = result::Result; + +impl From for Error { + fn from(error: ir::error::Error) -> Self { + Error::Ir(error) + } +} diff --git a/src/layout/mod.rs b/src/layout/mod.rs new file mode 100644 index 0000000..424639b --- /dev/null +++ b/src/layout/mod.rs @@ -0,0 +1,475 @@ +use crate::ir; +use crate::ir::element; +use crate::ty; +use std::collections; +use std::fmt; +use std::sync; +use std::usize; + +pub mod error; + +#[salsa::query_group(LayoutStorage)] +pub trait Db: salsa::Database + ir::Db { + #[salsa::input] + fn ptr_size(&self) -> PtrSize; + + fn layout(&self, entity: ir::Entity) -> error::Result>; +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Layout { + pub size: usize, + pub alignment: usize, + pub named_fields: Vec, + pub unnamed_fields: Vec, +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct NamedField { + pub field: ir::Ident, + pub offset_layout: Offset, +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Offset { + pub offset: usize, + pub layout: Layout, +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum PtrSize { + Size8 = 8, + Size16 = 16, + Size32 = 32, + Size64 = 64, +} + +const BOOL_LAYOUT: Layout = Layout::scalar(1); + +impl Layout { + pub const fn zero() -> Layout { + Layout { + size: 0, + alignment: 1, + named_fields: Vec::new(), + unnamed_fields: Vec::new(), + } + } + + pub const fn pointer(size: PtrSize) -> Layout { + let size = size as usize; + Layout { + size, + alignment: size, + named_fields: Vec::new(), + unnamed_fields: Vec::new(), + } + } + + pub const fn scalar(size: usize) -> Layout { + Layout { + size, + alignment: size, + named_fields: Vec::new(), + unnamed_fields: Vec::new(), + } + } + + pub fn named_fields(size: usize, alignment: usize, named_fields: Vec) -> Layout { + let unnamed_fields = Vec::new(); + + Layout { + size, + alignment, + named_fields, + unnamed_fields, + } + } + + pub fn unnamed_fields(size: usize, alignment: usize, unnamed_fields: Vec) -> Layout { + let named_fields = Vec::new(); + + Layout { + size, + alignment, + named_fields, + unnamed_fields, + } + } +} + +impl Offset { + pub const fn zero() -> Offset { + Offset { + offset: 0, + layout: Layout::zero(), + } + } +} + +impl fmt::Display for Layout { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}/{}", self.size, self.alignment)?; + + if !self.named_fields.is_empty() { + write!(f, "[")?; + + let mut needs_sep = false; + for named_field in &self.named_fields { + if needs_sep { + write!(f, ",")?; + } + write!(f, "{:?}:{}", named_field.field, named_field.offset_layout)?; + needs_sep = true; + } + + write!(f, "]")?; + } + + if !self.unnamed_fields.is_empty() { + write!(f, "{{")?; + + let mut needs_sep = false; + for (idx, offset) in self.unnamed_fields.iter().enumerate() { + if needs_sep { + write!(f, ",")?; + } + write!(f, "{}:{}", idx, offset)?; + needs_sep = true; + } + + write!(f, "}}")?; + } + + Ok(()) + } +} + +impl fmt::Display for Offset { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}({})", self.offset, self.layout) + } +} + +fn layout(db: &impl Db, entity: ir::Entity) -> error::Result> { + let element = db.element(entity)?; + let layout = element_layout(db, &*element)?; + Ok(layout) +} + +fn element_layout(db: &impl Db, element: &element::Element) -> error::Result> { + match *element { + element::Element::Reference(entity) => element_layout(db, &*db.element(entity)?), + element::Element::Number(ref n) => number_layout(db, n), + element::Element::String(_) => Ok(sync::Arc::new(Layout::pointer(db.ptr_size()))), + element::Element::Symbol(_) => Ok(sync::Arc::new(Layout::zero())), + element::Element::Tuple(element::Tuple { ref fields }) => tuple_layout(db, fields), + element::Element::Record(element::Record { ref fields }) => record_layout(db, fields), + element::Element::UnOp(element::UnOp { operator, operand }) => { + un_op_layout(db, operator, operand) + } + element::Element::BiOp(element::BiOp { lhs, operator, rhs }) => { + bi_op_layout(db, lhs, operator, rhs) + } + element::Element::Variable(element::Variable { initializer, .. }) => { + variable_layout(db, initializer) + } + element::Element::Select(element::Select { record, field }) => { + select_layout(db, record, field) + } + element::Element::Apply(element::Apply { + function, + ref parameters, + }) => apply_layout(db, function, parameters), + element::Element::Parameter(element::Parameter { signature, .. }) => { + parameter_layout(db, signature) + } + element::Element::Capture(element::Capture { captured, .. }) => { + capture_layout(db, captured) + } + element::Element::Closure(element::Closure { ref captures, .. }) => { + closure_layout(db, captures) + } + element::Element::Module(element::Module { ref variables }) => module_layout(db, variables), + } +} + +fn number_layout(db: &impl Db, number: &element::Number) -> error::Result> { + match *number { + element::Number::U8(_) | element::Number::I8(_) => Ok(sync::Arc::new(Layout::scalar(1))), + element::Number::U16(_) | element::Number::I16(_) => Ok(sync::Arc::new(Layout::scalar(2))), + element::Number::U32(_) | element::Number::I32(_) | element::Number::F32(_) => { + Ok(sync::Arc::new(Layout::scalar(4))) + } + element::Number::U64(_) | element::Number::I64(_) | element::Number::F64(_) => { + Ok(sync::Arc::new(Layout::scalar(8))) + } + } +} + +fn tuple_layout(db: &impl Db, fields: &[ir::Entity]) -> error::Result> { + let mut layouts = fields + .iter() + .enumerate() + .map(|(i, f)| Ok((i, db.layout(*f)?))) + .collect::>>()?; + + if layouts.is_empty() { + Ok(sync::Arc::new(Layout::zero())) + } else { + layouts.sort_unstable_by_key(|(i, l)| (usize::max_value() - l.size, *i)); + let alignment = layouts.iter().map(|(_, l)| l.alignment).max().unwrap(); + let mut size = 0; + + let mut unnamed_fields = vec![Offset::zero(); layouts.len()]; + + for (i, layout) in layouts { + let offset = align_up(size, layout.alignment); + size = offset + layout.size; + let layout = (*layout).clone(); + unnamed_fields[i] = Offset { offset, layout }; + } + + Ok(sync::Arc::new(Layout::unnamed_fields( + size, + alignment, + unnamed_fields, + ))) + } +} + +fn record_layout( + db: &impl Db, + fields: &collections::HashMap, +) -> error::Result> { + let mut layouts = fields + .iter() + .map(|(n, f)| Ok((*n, db.layout(*f)?))) + .collect::>>()?; + + if layouts.is_empty() { + Ok(sync::Arc::new(Layout::zero())) + } else { + layouts.sort_unstable_by_key(|(n, l)| (usize::max_value() - l.size, db.lookup_ident(*n))); + let alignment = layouts.iter().map(|(_, l)| l.alignment).max().unwrap(); + let mut size = 0; + + let named_fields = layouts + .into_iter() + .map(|(field, layout)| { + let offset = align_up(size, layout.alignment); + size = offset + layout.size; + let layout = (*layout).clone(); + let offset_layout = Offset { offset, layout }; + + NamedField { + field, + offset_layout, + } + }) + .collect::>(); + + Ok(sync::Arc::new(Layout::named_fields( + size, + alignment, + named_fields, + ))) + } +} + +fn un_op_layout( + db: &impl Db, + operator: element::UnOperator, + operand: ir::Entity, +) -> error::Result> { + match operator { + element::UnOperator::Not => Ok(sync::Arc::new(BOOL_LAYOUT)), + element::UnOperator::BNot + | element::UnOperator::Cl0 + | element::UnOperator::Cl1 + | element::UnOperator::Cls + | element::UnOperator::Ct0 + | element::UnOperator::Ct1 + | element::UnOperator::C0 + | element::UnOperator::C1 + | element::UnOperator::Sqrt => db.layout(operand), + } +} + +fn bi_op_layout( + db: &impl Db, + lhs: ir::Entity, + operator: element::BiOperator, + rhs: ir::Entity, +) -> error::Result> { + let lhs = db.layout(lhs)?; + let rhs = db.layout(rhs)?; + + if lhs.size != rhs.size || lhs.alignment != rhs.alignment { + return Err(error::Error::UnknownSize); + } + + match operator { + element::BiOperator::Eq + | element::BiOperator::Ne + | element::BiOperator::Lt + | element::BiOperator::Ge + | element::BiOperator::Gt + | element::BiOperator::Le + | element::BiOperator::And + | element::BiOperator::Or + | element::BiOperator::Xor + | element::BiOperator::AndNot + | element::BiOperator::OrNot + | element::BiOperator::XorNot => Ok(sync::Arc::new(BOOL_LAYOUT)), + element::BiOperator::Cmp => unimplemented!(), + element::BiOperator::Add + | element::BiOperator::Sub + | element::BiOperator::Mul + | element::BiOperator::Div + | element::BiOperator::Rem + | element::BiOperator::BAnd + | element::BiOperator::BOr + | element::BiOperator::BXor + | element::BiOperator::BAndNot + | element::BiOperator::BOrNot + | element::BiOperator::BXorNot + | element::BiOperator::RotL + | element::BiOperator::RotR + | element::BiOperator::ShL + | element::BiOperator::ShR => Ok(lhs), + } +} + +fn variable_layout(db: &impl Db, initializer: ir::Entity) -> error::Result> { + db.layout(initializer) +} + +fn select_layout( + db: &impl Db, + record: ir::Entity, + field: ir::Ident, +) -> error::Result> { + match *db.element(record)? { + element::Element::Record(element::Record { ref fields }) => { + if let Some(f) = fields.get(&field) { + db.layout(*f) + } else { + Err(error::Error::UnknownSize) + } + } + _ => Err(error::Error::UnknownSize), + } +} + +fn apply_layout( + db: &impl Db, + function: ir::Entity, + _parameters: &[ir::Entity], +) -> error::Result> { + match *db.element(function)? { + element::Element::Closure(element::Closure { signature, .. }) => { + element_layout(db, &*db.element(signature)?) + } + _ => Err(error::Error::UnknownSize), + } +} + +fn parameter_layout(db: &impl Db, signature: ir::Entity) -> error::Result> { + db.layout(signature) +} + +fn capture_layout(db: &impl Db, capture: ir::Entity) -> error::Result> { + db.layout(capture) +} + +fn closure_layout( + db: &impl Db, + captures: &collections::HashMap, +) -> error::Result> { + let mut capture_layouts = captures + .iter() + .map(|(n, f)| Ok((*n, db.layout(*f)?))) + .collect::>>()?; + let unnamed_fields = vec![Offset { + offset: 0, + layout: Layout::pointer(db.ptr_size()), + }]; + + capture_layouts + .sort_unstable_by_key(|(n, l)| (usize::max_value() - l.size, db.lookup_ident(*n))); + let alignment = capture_layouts + .iter() + .map(|(_, l)| l.alignment) + .max() + .unwrap_or(db.ptr_size() as usize); + let mut size = db.ptr_size() as usize; + + let named_fields = capture_layouts + .into_iter() + .map(|(field, layout)| { + let offset = align_up(size, layout.alignment); + size = offset + layout.size; + let layout = (*layout).clone(); + let offset_layout = Offset { offset, layout }; + + NamedField { + field, + offset_layout, + } + }) + .collect::>(); + + Ok(sync::Arc::new(Layout { + size, + alignment, + named_fields, + unnamed_fields, + })) +} + +fn module_layout( + db: &impl Db, + variables: &collections::HashMap, +) -> error::Result> { + record_layout(db, variables) +} + +#[allow(clippy::cast_sign_loss, clippy::cast_possible_wrap)] +fn align_up(offset: usize, alignment: usize) -> usize { + debug_assert!(alignment.is_power_of_two()); + offset + ((-(offset as isize)) & (alignment as isize - 1)) as usize +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn align_up_4() { + assert_eq!(0, align_up(0, 4)); + assert_eq!(4, align_up(1, 4)); + assert_eq!(4, align_up(2, 4)); + assert_eq!(4, align_up(3, 4)); + assert_eq!(4, align_up(4, 4)); + assert_eq!(8, align_up(5, 4)); + assert_eq!(8, align_up(6, 4)); + assert_eq!(8, align_up(7, 4)); + assert_eq!(8, align_up(8, 4)); + assert_eq!(12, align_up(9, 4)); + } + + #[test] + fn align_up_8() { + assert_eq!(0, align_up(0, 8)); + assert_eq!(8, align_up(1, 8)); + assert_eq!(8, align_up(2, 8)); + assert_eq!(8, align_up(3, 8)); + assert_eq!(8, align_up(4, 8)); + assert_eq!(8, align_up(5, 8)); + assert_eq!(8, align_up(6, 8)); + assert_eq!(8, align_up(7, 8)); + assert_eq!(8, align_up(8, 8)); + assert_eq!(16, align_up(9, 8)); + } +} diff --git a/src/lib.rs b/src/lib.rs index a984efe..a440c06 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,7 +29,9 @@ //! # Ok(()) //! # } //! ``` -#![deny(nonstandard_style, warnings, unused)] +#![feature(const_fn, const_vec_new)] +#![deny(nonstandard_style, warnings)] +#![allow(unused)] #![deny( missing_docs, missing_debug_implementations, @@ -40,36 +42,17 @@ unused_import_braces, unused_qualifications )] -#![feature(const_vec_new)] -#![cfg_attr(feature = "cargo-clippy", deny(clippy::all, clippy::pedantic))] -#![cfg_attr(feature = "cargo-clippy", allow(clippy::use_self))] - -#[macro_use] -extern crate enum_primitive_derive; -#[macro_use] -extern crate failure; -#[macro_use] -extern crate lalrpop_util; -#[macro_use] -extern crate lazy_static; -#[macro_use] -extern crate log; -#[macro_use] -extern crate specs_derive; -#[macro_use] -extern crate specs_visitor_derive; -#[cfg(test)] -#[macro_use] -extern crate pretty_assertions; use std::fmt; -mod ast; -mod best_iter; mod codegen; +mod db; mod interpreter; mod ir; -mod parser; +mod layout; +mod source; +mod syntax; +mod ty; mod value; #[cfg(test)] @@ -85,25 +68,15 @@ pub use crate::error::Result; /// An instance of the Tin runtime. pub struct Tin { - ir: ir::Ir, - codemap: codespan::CodeMap, - parser: as parser::Parse>::Parser, + db: db::Db, } impl Tin { /// Creates a new instance of the Tin runtime. pub fn new() -> Tin { - use crate::parser::Parse; - - let ir = ir::Ir::new(); - let codemap = codespan::CodeMap::new(); - let parser = ast::Module::new_parser(); + let db = db::Db::new(); - Tin { - ir, - codemap, - parser, - } + Tin { db } } /// Loads the specified source code as a module. @@ -143,26 +116,31 @@ impl Tin { /// # Ok(()) /// # } /// ``` - pub fn load(&mut self, file_name: F, source: &str) -> Result<()> + pub fn load(&mut self, _file_name: F, _source: &str) -> Result<()> where F: Into, { + unimplemented!() + /* let span = self .codemap .add_filemap(file_name.into(), source.to_owned()) .span(); - let module = parser::Parser::parse(&mut self.parser, span, source)?; + let module = syntax::parser::Parser::parse(&mut self.parser, span, source)?; self.ir.load(&module)?; Ok(()) + */ } + /* /// Creates a graph representation of the current IR of this Tin instance. /// /// This can be used to for example visualize the code using GraphViz or other tools. pub fn graph(&self) -> graph::Graph { graph::Graph::new(&self.ir) } + */ /// Compiles the code loaded so far into a stand-alone module. /// @@ -190,15 +168,21 @@ impl Tin { /// # } /// ``` pub fn compile(&mut self) -> Result { + unimplemented!() + /* self.ir.check_types()?; let module = codegen::Codegen::new(&self.ir, &self.codemap).compile(); Ok(module) + */ } /// Returns a reference to the current code map, which contains location mapping for all source /// code loaded so far. pub fn codemap(&self) -> &codespan::CodeMap { + unimplemented!() + /* &self.codemap + */ } } diff --git a/src/module.rs b/src/module.rs index 70936c6..c8622a5 100644 --- a/src/module.rs +++ b/src/module.rs @@ -3,18 +3,22 @@ use std::collections; use std::fmt; use std::mem; use std::ptr; +use std::sync; use cranelift_module; use cranelift_simplejit; /// A compiled module, the result of an invocation of `Tin::compile`. +#[derive(Clone)] pub struct Module { - compiled: cranelift_module::Module, - function_ids: collections::HashMap, + compiled: + sync::Arc>>, + function_ids: + collections::HashMap<(relative_path::RelativePathBuf, String), cranelift_module::FuncId>, } /// An error that may happen at runtime. -#[derive(Clone, Debug, Fail, PartialEq)] +#[derive(Clone, Debug, Eq, failure::Fail, PartialEq)] #[fail(display = "{}{}", kind, backtrace)] pub struct Error { kind: ErrorKind, @@ -22,20 +26,20 @@ pub struct Error { } /// A trace, for example a backtrace for an error. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Trace { frames: Vec, } /// A call stack frame within a [`Trace`]. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Frame { name: String, location: Point, } /// A specific code point, with a file, line and column. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Point { path: String, line: u32, @@ -43,7 +47,7 @@ pub struct Point { } /// The various kinds of allowed errors. -#[derive(Clone, Copy, Debug, PartialEq, Primitive)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, enum_primitive_derive::Primitive)] pub enum ErrorKind { /// An unknown error has occurred. /// @@ -166,8 +170,12 @@ define_function!( impl Module { pub(crate) fn new( compiled: cranelift_module::Module, - function_ids: collections::HashMap, + function_ids: collections::HashMap< + (relative_path::RelativePathBuf, String), + cranelift_module::FuncId, + >, ) -> Self { + let compiled = sync::Arc::new(sync::Mutex::new(compiled)); Module { compiled, function_ids, @@ -177,13 +185,18 @@ impl Module { /// Fetches the specified function with the specified signature. /// /// Returns `None` if the signature does not match the compiled function. - pub fn function(&mut self, name: &str) -> Option + pub fn function(&mut self, module: P, name: &str) -> Option where F: Function, + P: AsRef, { - if let Some(id) = self.function_ids.get(name) { + if let Some(id) = self + .function_ids + .get(&(module.as_ref().to_owned(), name.to_owned())) + { + let mut compiled = self.compiled.lock().unwrap(); // TODO: type check - Some(unsafe { F::from_ptr(self.compiled.get_finalized_function(*id)) }) + Some(unsafe { F::from_ptr(compiled.get_finalized_function(*id)) }) } else { None } diff --git a/src/source/mod.rs b/src/source/mod.rs new file mode 100644 index 0000000..4e1cda4 --- /dev/null +++ b/src/source/mod.rs @@ -0,0 +1,101 @@ +// This code is largely copied from rust-analyzer + +//! This module specifies the input to the compiler. +//! +//! In some sense, this is **the** most important module, because all other fancy stuff is strictly +//! derived from this input. +//! +//! Note that neither this module, nor any other part of the compiler do actual IO. +//! +use std::collections; +use std::sync; + +#[salsa::query_group(SourceStorage)] +pub trait Db: salsa::Database { + /// Text of the file. + #[salsa::input] + fn file_text(&self, file_id: FileId) -> sync::Arc; + + /// Path to a file, relative to the root of its source root. + #[salsa::input] + fn file_relative_path(&self, file_id: FileId) -> relative_path::RelativePathBuf; + + /// Source root of the file. + #[salsa::input] + fn file_source_root(&self, file_id: FileId) -> RootId; + + /// Contents of the source root. + #[salsa::input] + fn source_root(&self, id: RootId) -> sync::Arc; + + /// All source roots. + #[salsa::input] + fn all_source_roots(&self) -> sync::Arc>; + + #[salsa::dependencies] + fn code_map(&self) -> sync::Arc; + + /// Span of the file. + fn file_span(&self, file_id: FileId) -> codespan::ByteSpan; +} + +/// `FileId` is an integer which uniquely identifies a file. +/// +/// File paths are messy and system-dependent, so most of the code should work directly with +/// `FileId`, without inspecting the path. The mapping between `FileId` and path and `SourceRoot` +/// is constant. A file rename is represented as a pair of deletion/creation. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct FileId(pub u32); + +/// Files are grouped into source roots. +/// +/// A source root is a directory on the file systems which is watched for changes. Source roots +/// *might* be nested: in this case, a file belongs to the nearest enclosing source root. Paths to +/// files are always relative to a source root, and the compiler does not know the root path of the +/// source root at all. So, a file from one source root can't refer to a file in another source root +/// by path. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct RootId(pub u32); + +#[derive(Default, Clone, Debug, PartialEq, Eq)] +pub struct Root { + pub files: collections::HashMap, +} + +#[derive(Default, Clone, Debug)] +pub struct CodeMap { + pub raw: codespan::CodeMap, + file_maps: collections::HashMap>>, +} + +#[derive(Default, Clone, Debug)] +pub struct Text(sync::Arc); + +fn code_map(db: &impl Db) -> sync::Arc { + let mut raw = codespan::CodeMap::new(); + let mut file_maps = collections::HashMap::new(); + + for root_id in &*db.all_source_roots() { + let source_root = db.source_root(*root_id); + for (path, file) in &source_root.files { + let text = db.file_text(*file); + let file_map = raw.add_filemap( + codespan::FileName::Virtual(path.as_str().to_owned().into()), + Text(text), + ); + file_maps.insert(*file, file_map); + } + } + + sync::Arc::new(CodeMap { raw, file_maps }) +} + +fn file_span(db: &impl Db, file_id: FileId) -> codespan::ByteSpan { + db.code_map().file_maps[&file_id].span() +} + +impl AsRef for Text { + fn as_ref(&self) -> &str { + &*self.0 + } +} diff --git a/src/ast/ast_node.rs b/src/syntax/ast/ast_node.rs similarity index 96% rename from src/ast/ast_node.rs rename to src/syntax/ast/ast_node.rs index 6571ece..6656233 100644 --- a/src/ast/ast_node.rs +++ b/src/syntax/ast/ast_node.rs @@ -1,7 +1,7 @@ //! Generic node manipulation of AST nodes. use std::fmt; -use crate::ast; +use crate::syntax::ast; /// A Tin AST node. pub trait AstNode: fmt::Debug + Sized { @@ -25,7 +25,7 @@ where } } -impl AstNode for ast::Identifier +impl AstNode for ast::Reference where C: fmt::Debug, { @@ -51,7 +51,7 @@ where ast::Expression::Record(ref v) => v.context(), ast::Expression::UnOp(ref v) => v.context(), ast::Expression::BiOp(ref v) => v.context(), - ast::Expression::Identifier(ref v) => v.context(), + ast::Expression::Reference(ref v) => v.context(), ast::Expression::Lambda(ref v) => v.context(), ast::Expression::Select(ref v) => v.context(), ast::Expression::Apply(ref v) => v.context(), @@ -68,7 +68,7 @@ where ast::Expression::Record(ref mut v) => v.context_mut(), ast::Expression::UnOp(ref mut v) => v.context_mut(), ast::Expression::BiOp(ref mut v) => v.context_mut(), - ast::Expression::Identifier(ref mut v) => v.context_mut(), + ast::Expression::Reference(ref mut v) => v.context_mut(), ast::Expression::Lambda(ref mut v) => v.context_mut(), ast::Expression::Select(ref mut v) => v.context_mut(), ast::Expression::Apply(ref mut v) => v.context_mut(), diff --git a/src/ast/map_context.rs b/src/syntax/ast/map_context.rs similarity index 73% rename from src/ast/map_context.rs rename to src/syntax/ast/map_context.rs index a01d335..0a2e53f 100644 --- a/src/ast/map_context.rs +++ b/src/syntax/ast/map_context.rs @@ -1,8 +1,9 @@ //! AST node context mapping helpers. use std::fmt; +use std::sync; -use crate::ast; -use crate::ast::ast_node; +use crate::syntax::ast; +use crate::syntax::ast::ast_node; /// A context mapping over some AST node. pub trait MapContext: ast_node::AstNode { @@ -20,8 +21,8 @@ pub trait MapContext: ast_node::AstNode { impl MapContext for ast::Module where - C1: fmt::Debug, - C2: fmt::Debug, + C1: Clone + fmt::Debug, + C2: Clone + fmt::Debug, { type Output = ast::Module; @@ -33,19 +34,19 @@ where let variables = self .variables .into_iter() - .map(|v| v.map_context(mapping)) + .map(|v| sync::Arc::new(own(v).map_context(mapping))) .collect(); ast::Module { context, variables } } } -impl MapContext for ast::Identifier +impl MapContext for ast::Reference where - C1: fmt::Debug, - C2: fmt::Debug, + C1: Clone + fmt::Debug, + C2: Clone + fmt::Debug, { - type Output = ast::Identifier; + type Output = ast::Reference; fn map_context(self, mapping: &mut F) -> Self::Output where @@ -54,14 +55,14 @@ where let context = mapping(self.context); let value = self.value; - ast::Identifier { context, value } + ast::Reference { context, value } } } impl MapContext for ast::Expression where - C1: fmt::Debug, - C2: fmt::Debug, + C1: Clone + fmt::Debug, + C2: Clone + fmt::Debug, { type Output = ast::Expression; @@ -81,7 +82,7 @@ where ast::Expression::Record(e) => ast::Expression::Record(e.map_context(mapping)), ast::Expression::UnOp(e) => ast::Expression::UnOp(e.map_context(mapping)), ast::Expression::BiOp(e) => ast::Expression::BiOp(e.map_context(mapping)), - ast::Expression::Identifier(e) => ast::Expression::Identifier(e.map_context(mapping)), + ast::Expression::Reference(e) => ast::Expression::Reference(e.map_context(mapping)), ast::Expression::Lambda(e) => ast::Expression::Lambda(e.map_context(mapping)), ast::Expression::Select(e) => ast::Expression::Select(e.map_context(mapping)), ast::Expression::Apply(e) => ast::Expression::Apply(e.map_context(mapping)), @@ -92,8 +93,8 @@ where impl MapContext for ast::NumberLiteral where - C1: fmt::Debug, - C2: fmt::Debug, + C1: Clone + fmt::Debug, + C2: Clone + fmt::Debug, { type Output = ast::NumberLiteral; @@ -109,8 +110,8 @@ where impl MapContext for ast::StringLiteral where - C1: fmt::Debug, - C2: fmt::Debug, + C1: Clone + fmt::Debug, + C2: Clone + fmt::Debug, { type Output = ast::StringLiteral; @@ -126,8 +127,8 @@ where impl MapContext for ast::Symbol where - C1: fmt::Debug, - C2: fmt::Debug, + C1: Clone + fmt::Debug, + C2: Clone + fmt::Debug, { type Output = ast::Symbol; @@ -143,8 +144,8 @@ where impl MapContext for ast::Tuple where - C1: fmt::Debug, - C2: fmt::Debug, + C1: Clone + fmt::Debug, + C2: Clone + fmt::Debug, { type Output = ast::Tuple; @@ -156,7 +157,7 @@ where let fields = self .fields .into_iter() - .map(|f| f.map_context(mapping)) + .map(|f| sync::Arc::new(own(f).map_context(mapping))) .collect(); ast::Tuple { context, fields } } @@ -164,8 +165,8 @@ where impl MapContext for ast::Record where - C1: fmt::Debug, - C2: fmt::Debug, + C1: Clone + fmt::Debug, + C2: Clone + fmt::Debug, { type Output = ast::Record; @@ -177,7 +178,12 @@ where let fields = self .fields .into_iter() - .map(|(i, f)| (i.map_context(mapping), f.map_context(mapping))) + .map(|(n, f)| { + ( + sync::Arc::new(own(n)), + sync::Arc::new(own(f).map_context(mapping)), + ) + }) .collect(); ast::Record { context, fields } } @@ -185,8 +191,8 @@ where impl MapContext for ast::UnOp where - C1: fmt::Debug, - C2: fmt::Debug, + C1: Clone + fmt::Debug, + C2: Clone + fmt::Debug, { type Output = ast::UnOp; @@ -196,7 +202,7 @@ where { let context = mapping(self.context); let operator = self.operator; - let operand = Box::new(self.operand.map_context(mapping)); + let operand = sync::Arc::new(own(self.operand).map_context(mapping)); ast::UnOp { context, operator, @@ -207,8 +213,8 @@ where impl MapContext for ast::BiOp where - C1: fmt::Debug, - C2: fmt::Debug, + C1: Clone + fmt::Debug, + C2: Clone + fmt::Debug, { type Output = ast::BiOp; @@ -217,9 +223,9 @@ where F: FnMut(C1) -> C2, { let context = mapping(self.context); - let lhs = Box::new(self.lhs.map_context(mapping)); + let lhs = sync::Arc::new(own(self.lhs).map_context(mapping)); let operator = self.operator; - let rhs = Box::new(self.rhs.map_context(mapping)); + let rhs = sync::Arc::new(own(self.rhs).map_context(mapping)); ast::BiOp { context, lhs, @@ -231,8 +237,8 @@ where impl MapContext for ast::Lambda where - C1: fmt::Debug, - C2: fmt::Debug, + C1: Clone + fmt::Debug, + C2: Clone + fmt::Debug, { type Output = ast::Lambda; @@ -244,15 +250,17 @@ where let parameters = self .parameters .into_iter() - .map(|p| p.map_context(mapping)) + .map(|p| sync::Arc::new(own(p).map_context(mapping))) .collect(); - let signature = Box::new(self.signature.map_context(mapping)); + let signature = sync::Arc::new(own(self.signature).map_context(mapping)); let statements = self .statements .into_iter() - .map(|s| s.map_context(mapping)) + .map(|s| sync::Arc::new(own(s).map_context(mapping))) .collect(); - let result = self.result.map(|r| Box::new(r.map_context(mapping))); + let result = self + .result + .map(|r| sync::Arc::new(own(r).map_context(mapping))); ast::Lambda { context, @@ -266,8 +274,8 @@ where impl MapContext for ast::Statement where - C1: fmt::Debug, - C2: fmt::Debug, + C1: Clone + fmt::Debug, + C2: Clone + fmt::Debug, { type Output = ast::Statement; @@ -284,8 +292,8 @@ where impl MapContext for ast::Variable where - C1: fmt::Debug, - C2: fmt::Debug, + C1: Clone + fmt::Debug, + C2: Clone + fmt::Debug, { type Output = ast::Variable; @@ -294,8 +302,8 @@ where F: FnMut(C1) -> C2, { let context = mapping(self.context); - let name = self.name.map_context(mapping); - let initializer = self.initializer.map_context(mapping); + let name = sync::Arc::new(own(self.name)); + let initializer = sync::Arc::new(own(self.initializer).map_context(mapping)); ast::Variable { context, @@ -307,8 +315,8 @@ where impl MapContext for ast::Select where - C1: fmt::Debug, - C2: fmt::Debug, + C1: Clone + fmt::Debug, + C2: Clone + fmt::Debug, { type Output = ast::Select; @@ -317,8 +325,8 @@ where F: FnMut(C1) -> C2, { let context = mapping(self.context); - let record = Box::new(self.record.map_context(mapping)); - let field = self.field.map_context(mapping); + let record = sync::Arc::new(own(self.record).map_context(mapping)); + let field = sync::Arc::new(own(self.field)); ast::Select { context, record, @@ -329,8 +337,8 @@ where impl MapContext for ast::Apply where - C1: fmt::Debug, - C2: fmt::Debug, + C1: Clone + fmt::Debug, + C2: Clone + fmt::Debug, { type Output = ast::Apply; @@ -339,11 +347,11 @@ where F: FnMut(C1) -> C2, { let context = mapping(self.context); - let function = Box::new(self.function.map_context(mapping)); + let function = sync::Arc::new(own(self.function).map_context(mapping)); let parameters = self .parameters .into_iter() - .map(|e| e.map_context(mapping)) + .map(|e| sync::Arc::new(own(e).map_context(mapping))) .collect(); ast::Apply { context, @@ -355,8 +363,8 @@ where impl MapContext for ast::Parameter where - C1: fmt::Debug, - C2: fmt::Debug, + C1: Clone + fmt::Debug, + C2: Clone + fmt::Debug, { type Output = ast::Parameter; @@ -365,8 +373,8 @@ where F: FnMut(C1) -> C2, { let context = mapping(self.context); - let name = self.name.map_context(mapping); - let signature = self.signature.map_context(mapping); + let name = sync::Arc::new(own(self.name)); + let signature = sync::Arc::new(own(self.signature).map_context(mapping)); ast::Parameter { context, name, @@ -374,3 +382,10 @@ where } } } + +fn own(arc: sync::Arc) -> A +where + A: Clone, +{ + sync::Arc::try_unwrap(arc).unwrap_or_else(|arc| (*arc).clone()) +} diff --git a/src/ast/mod.rs b/src/syntax/ast/mod.rs similarity index 79% rename from src/ast/mod.rs rename to src/syntax/ast/mod.rs index 2ac77c5..39f6a15 100644 --- a/src/ast/mod.rs +++ b/src/syntax/ast/mod.rs @@ -4,8 +4,10 @@ //! arbitrary metadata to every node; a common use is to store the source location for each node as //! parsed by a parser (see [`parser::Context`] for an example). //! -//! To generically interact with the context of a node, the [`AstNode`] trait can be used. All of -//! the contexts of an entire AST can additionally be transformed using the [`MapContext`] trait. +//! To generically interact with the context of a node, the `AstNode` trait can be used. All of +//! the contexts of an entire AST can additionally be transformed using the `MapContext` trait. +use std::sync; + mod ast_node; mod map_context; @@ -46,25 +48,25 @@ pub enum Kind { } /// A complete Tin module. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Module { /// This node's AST context. pub context: C, - /// Variable variables that are part of this module, in declaration order. - pub variables: Vec>, + /// Variables that are part of this module, in declaration order. + pub variables: Vec>>, } /// An identifier. -#[derive(Clone, Debug, PartialEq)] -pub struct Identifier { +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Reference { /// This node's AST context. pub context: C, /// The raw string name of the identifier. - pub value: String, + pub value: sync::Arc, } /// Any valid expression. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub enum Expression { /// A numeric literal. NumberLiteral(NumberLiteral), @@ -77,7 +79,7 @@ pub enum Expression { /// A record literal. Record(Record), /// A reference to an identifier. - Identifier(Identifier), + Reference(Reference), /// A unary operator application. UnOp(UnOp), /// A binary operator application. @@ -94,7 +96,7 @@ pub enum Expression { } /// A numeric literal. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct NumberLiteral { /// This node's AST context. pub context: C, @@ -103,7 +105,7 @@ pub struct NumberLiteral { } /// All syntactic number literal value variants. -#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd)] pub enum NumberValue { /// Unsigned 8-bit integer value. U8(u8), @@ -122,15 +124,15 @@ pub enum NumberValue { /// Signed 64-bit integer value. I64(i64), /// Floating point 32-bit value. - F32(f32), + F32(ordered_float::OrderedFloat), /// Floating point 64-bit value. - F64(f64), + F64(ordered_float::OrderedFloat), /// The number value is invalid (e.g. out of bounds). Invalid, } /// A string literal. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct StringLiteral { /// This node's AST context. pub context: C, @@ -139,39 +141,39 @@ pub struct StringLiteral { } /// All syntactic string literal value variants. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub enum StringValue { /// A plain string. - String(String), + String(sync::Arc), /// The string value is invalid (e.g. has an illegal character). Invalid, } /// A symbol. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Symbol { /// This node's AST context. pub context: C, /// The label of the symbol. - pub label: String, + pub label: sync::Arc, } /// A tuple expression. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Tuple { /// This node's AST context. pub context: C, /// The fields of the tuple, in declaration order. - pub fields: Vec>, + pub fields: Vec>>, } /// A record expression. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Record { /// This node's AST context. pub context: C, /// The fields of the record, in declaration order. - pub fields: Vec<(Identifier, Expression)>, + pub fields: Vec<(sync::Arc, sync::Arc>)>, } /// An unary operator. @@ -204,14 +206,14 @@ pub enum UnOperator { } /// An operator application with one operand. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct UnOp { /// This node's AST context. pub context: C, /// The unary operator that is being applied. pub operator: UnOperator, /// The operand to the operator. - pub operand: Box>, + pub operand: sync::Arc>, } /// A binary operator. @@ -279,35 +281,35 @@ pub enum BiOperator { } /// An operator application with two operands. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct BiOp { /// This node's AST context. pub context: C, /// The left-hand-side operand of the operator. - pub lhs: Box>, + pub lhs: sync::Arc>, /// The binary operator that is being applied. pub operator: BiOperator, /// The right-hand-side operand of the operator. - pub rhs: Box>, + pub rhs: sync::Arc>, } /// A lambda expression. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Lambda { /// This node's AST context. pub context: C, /// The parameters of the lambda. - pub parameters: Vec>, + pub parameters: Vec>>, /// The signature of the result of the lambda. - pub signature: Box>, + pub signature: sync::Arc>, /// The statements that constitute the lambda body. - pub statements: Vec>, + pub statements: Vec>>, /// The result ("return value") of the lambda. - pub result: Option>>, + pub result: Option>>, } /// A valid statement. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub enum Statement { /// A statement that defines a new identifier. Variable(Variable), @@ -316,46 +318,46 @@ pub enum Statement { } /// A variable definition. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Variable { /// This node's AST context. pub context: C, /// The name of the variable. - pub name: Identifier, + pub name: sync::Arc, /// The initializer expression of the variable. - pub initializer: Expression, + pub initializer: sync::Arc>, } /// A field selection expression. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Select { /// This node's AST context. pub context: C, /// The expression to select from; should evaluate to a record. - pub record: Box>, + pub record: sync::Arc>, /// The field to select. - pub field: Identifier, + pub field: sync::Arc, } /// A function application expression. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Apply { /// This node's AST context. pub context: C, /// The expression to apply; should evaluate to a function. - pub function: Box>, + pub function: sync::Arc>, /// The parameters to pass in to the function; should match the function's accepted number of /// arguments. - pub parameters: Vec>, + pub parameters: Vec>>, } /// A lambda parameter declaration. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Parameter { /// This node's AST context. pub context: C, /// The name of the parameter. - pub name: Identifier, - /// The signature of the parameter, if any. - pub signature: Expression, + pub name: sync::Arc, + /// The signature of the parameter. + pub signature: sync::Arc>, } diff --git a/src/syntax/mod.rs b/src/syntax/mod.rs new file mode 100644 index 0000000..edd02c1 --- /dev/null +++ b/src/syntax/mod.rs @@ -0,0 +1,27 @@ +use std::sync; + +use crate::source; + +pub mod ast; +pub mod parser; + +#[salsa::query_group(SyntaxStorage)] +pub trait Db: salsa::Database + source::Db { + /// Parses the file into an AST module. + fn parse( + &self, + file_id: source::FileId, + ) -> Result>, parser::Error>; +} + +fn parse( + db: &impl Db, + file_id: source::FileId, +) -> Result>, parser::Error> { + use crate::syntax::parser::Parse; + + let text = db.file_text(file_id); + let span = db.file_span(file_id); + + ast::Module::parse(span, &*text).map(sync::Arc::new) +} diff --git a/src/parser/tin.lalrpop b/src/syntax/parser/grammar.lalrpop similarity index 67% rename from src/parser/tin.lalrpop rename to src/syntax/parser/grammar.lalrpop index 25bd6f8..4661024 100644 --- a/src/parser/tin.lalrpop +++ b/src/syntax/parser/grammar.lalrpop @@ -1,7 +1,9 @@ +use std::sync; + use lalrpop_util; -use crate::ast; -use crate::parser; +use crate::syntax::ast; +use crate::syntax::parser; grammar<'err>(span: codespan::ByteSpan, errors: &'err mut Vec, parser::Error>>); @@ -18,7 +20,7 @@ match { )" => NumberValue, } else { r"/\*(\*[^/]|[^*])*\*/" => Comment, - r"\p{XID_Start}\p{XID_Continue}*" => IdentifierName, + r"\p{XID_Start}\p{XID_Continue}*" => Identifier, r":\p{XID_Start}\p{XID_Continue}*" => SymbolLabel, r#""(?:[^"\\]|\\.)*""# => StringValue, _ @@ -58,75 +60,38 @@ SemiRequired0: Vec = { pub Module: ast::Module = { )>> => - ast::Module { context: parser::Context::new(ast::Kind::Module, span, lo, hi), variables: ds }, + ast::Module { context: parser::Context::new(ast::Kind::Module, span, lo, hi), variables: ds.into_iter().map(sync::Arc::new).collect() }, } Definition: ast::Variable = { "=" => - ast::Variable { context: parser::Context::new(ast::Kind::Variable, span, lo, hi), name: n, initializer: i }, + ast::Variable { context: parser::Context::new(ast::Kind::Variable, span, lo, hi), name: sync::Arc::new(n.to_owned()), initializer: sync::Arc::new(i) }, } pub Expression = { } // Left-to-right evaluation -ExpressionBiOpOr: ast::Expression = { - BiOp => ast::Expression::BiOp(<>), - ExpressionBiOpXor => <>, -} - -// Left-to-right evaluation -ExpressionBiOpXor: ast::Expression = { - BiOp => ast::Expression::BiOp(<>), - ExpressionBiOpAnd => <>, -} - -// Left-to-right evaluation -ExpressionBiOpAnd: ast::Expression = { - BiOp => ast::Expression::BiOp(<>), - ExpressionBiOpCmp => <>, +LeftOp: ast::Expression = { + BiOp, Op, NextTier> => ast::Expression::BiOp(<>), + NextTier => <>, } // No associativity; require parenthesis -ExpressionBiOpCmp: ast::Expression = { - BiOp => ast::Expression::BiOp(<>), - ExpressionBiOpBOr => <>, -} - -// Left-to-right evaluation -ExpressionBiOpBOr: ast::Expression = { - BiOp => ast::Expression::BiOp(<>), - ExpressionBiOpBXor => <>, -} - -// Left-to-right evaluation -ExpressionBiOpBXor: ast::Expression = { - BiOp => ast::Expression::BiOp(<>), - ExpressionBiOpBAnd => <>, -} - -// Left-to-right evaluation -ExpressionBiOpBAnd: ast::Expression = { - BiOp => ast::Expression::BiOp(<>), - ExpressionBiOpShift => <>, -} - -// Left-to-right evaluation -ExpressionBiOpShift: ast::Expression = { - BiOp => ast::Expression::BiOp(<>), - ExpressionBiOpSum => <>, -} - -// Left-to-right evaluation -ExpressionBiOpSum: ast::Expression = { - BiOp => ast::Expression::BiOp(<>), - ExpressionBiOpFactor => <>, -} - -// Left-to-right evaluation -ExpressionBiOpFactor: ast::Expression = { - BiOp => ast::Expression::BiOp(<>), - ExpressionUnOp => <>, -} +InfixOp: ast::Expression = { + BiOp => ast::Expression::BiOp(<>), + NextTier => <>, +} + +ExpressionBiOpOr = LeftOp; +ExpressionBiOpXor = LeftOp; +ExpressionBiOpAnd = LeftOp; +ExpressionBiOpCmp = InfixOp; +ExpressionBiOpBOr = LeftOp; +ExpressionBiOpBXor = LeftOp; +ExpressionBiOpBAnd = LeftOp; +ExpressionBiOpShift = LeftOp; +ExpressionBiOpSum = LeftOp; +ExpressionBiOpFactor = LeftOp; ExpressionUnOp: ast::Expression = { UnOp => ast::Expression::UnOp(<>), @@ -141,7 +106,7 @@ ExpressionProjection: ast::Expression = { } ExpressionAtom: ast::Expression = { - Identifier => ast::Expression::Identifier(<>), + Reference => ast::Expression::Reference(<>), NumberLiteral => ast::Expression::NumberLiteral(<>), StringLiteral => ast::Expression::StringLiteral(<>), Symbol => ast::Expression::Symbol(<>), @@ -166,13 +131,13 @@ UnOperator: ast::UnOperator = { UnOp: ast::UnOp = { => - ast::UnOp { context: parser::Context::new(ast::Kind::UnOp, span, lo, hi), operator, operand: Box::new(operand) }, + ast::UnOp { context: parser::Context::new(ast::Kind::UnOp, span, lo, hi), operator, operand: sync::Arc::new(operand) }, } #[inline] BiOp: ast::BiOp = { => - ast::BiOp { context: parser::Context::new(ast::Kind::BiOp, span, lo, hi), lhs: Box::new(lhs), operator, rhs: Box::new(rhs) }, + ast::BiOp { context: parser::Context::new(ast::Kind::BiOp, span, lo, hi), lhs: sync::Arc::new(lhs), operator, rhs: sync::Arc::new(rhs) }, } BiOperatorFactor: ast::BiOperator = { @@ -233,25 +198,25 @@ BiOperatorCmp: ast::BiOperator = { "<=>" => ast::BiOperator::Cmp, } -Identifier: ast::Identifier = { - => - ast::Identifier { context: parser::Context::new(ast::Kind::Identifier, span, lo, hi), value: id.into() }, +Reference: ast::Reference = { + => + ast::Reference { context: parser::Context::new(ast::Kind::Identifier, span, lo, hi), value: sync::Arc::new(id.to_owned()) }, } Tuple: ast::Tuple = { "(" ")" => ast::Tuple { context: parser::Context::new(ast::Kind::Tuple, span, lo, hi), fields: vec![] }, "(" > ")" => - ast::Tuple { context: parser::Context::new(ast::Kind::Tuple, span, lo, hi), fields: fs }, + ast::Tuple { context: parser::Context::new(ast::Kind::Tuple, span, lo, hi), fields: fs.into_iter().map(sync::Arc::new).collect() }, } Record: ast::Record = { "{" > "}" => - ast::Record { context: parser::Context::new(ast::Kind::Record, span, lo, hi), fields: fs }, + ast::Record { context: parser::Context::new(ast::Kind::Record, span, lo, hi), fields: fs.into_iter().map(|(k, v)| (sync::Arc::new(k), sync::Arc::new(v))).collect() }, } -Field: (ast::Identifier, ast::Expression) = { - ":" => (<>), +Field: (String, ast::Expression) = { + ":" => (i.to_owned(), e), } NumberLiteral: ast::NumberLiteral = { @@ -269,17 +234,17 @@ StringLiteral: ast::StringLiteral = { Symbol: ast::Symbol = { => - ast::Symbol { context: parser::Context::new(ast::Kind::Symbol, span, lo, hi), label: (&label[1..]).to_owned() }, + ast::Symbol { context: parser::Context::new(ast::Kind::Symbol, span, lo, hi), label: sync::Arc::new((&label[1..]).to_owned()) }, } Lambda: ast::Lambda = { "|" )>> "|" "->" => ast::Lambda { context: parser::Context::new(ast::Kind::Lambda, span, lo, hi), - parameters: params, - signature: Box::new(sig), - statements: body.as_ref().map(|b| b.0.clone()).unwrap_or(vec![]), - result: body.as_ref().map(|b| Box::new(b.1.clone())) + parameters: params.into_iter().map(sync::Arc::new).collect(), + signature: sync::Arc::new(sig), + statements: body.as_ref().map(|b| b.0.iter().cloned().map(sync::Arc::new).collect()).unwrap_or(vec![]), + result: body.as_ref().map(|b| sync::Arc::new(b.1.clone())) }, } @@ -294,15 +259,15 @@ Statement: ast::Statement = { Select: ast::Select = { "." => - ast::Select { context: parser::Context::new(ast::Kind::Select, span, lo, hi), record: Box::new(r), field: f }, + ast::Select { context: parser::Context::new(ast::Kind::Select, span, lo, hi), record: sync::Arc::new(r), field: sync::Arc::new(f.to_owned()) }, } Apply: ast::Apply = { "(" > ")" => - ast::Apply { context: parser::Context::new(ast::Kind::Apply, span, lo, hi), function: Box::new(e), parameters: p }, + ast::Apply { context: parser::Context::new(ast::Kind::Apply, span, lo, hi), function: sync::Arc::new(e), parameters: p.into_iter().map(sync::Arc::new).collect() }, } Parameter: ast::Parameter = { ":" => - ast::Parameter { context: parser::Context::new(ast::Kind::Parameter, span, lo, hi), name, signature }, + ast::Parameter { context: parser::Context::new(ast::Kind::Parameter, span, lo, hi), name: sync::Arc::new(name.to_owned()), signature: sync::Arc::new(signature) }, } diff --git a/src/parser/mod.rs b/src/syntax/parser/mod.rs similarity index 69% rename from src/parser/mod.rs rename to src/syntax/parser/mod.rs index 1ede97f..584ef10 100644 --- a/src/parser/mod.rs +++ b/src/syntax/parser/mod.rs @@ -3,24 +3,24 @@ use std::num; use lalrpop_util; -use crate::ast; use crate::diagnostic; +use crate::syntax::ast; mod util; -lalrpop_mod!( +lalrpop_util::lalrpop_mod!( #[allow(clippy::all)] #[allow(clippy::pedantic)] #[allow(deprecated)] #[allow(missing_debug_implementations)] #[allow(trivial_numeric_casts)] #[allow(unused)] - tin, - "/parser/tin.rs" + grammar, + "/syntax/parser/grammar.rs" ); /// The context of a parsed AST node. -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct Context { /// The source code span that this AST was parsed from. pub span: codespan::ByteSpan, @@ -29,7 +29,7 @@ pub struct Context { } /// An error that occurs while parsing Tin. -#[derive(Clone, Debug, Fail, PartialEq)] +#[derive(Clone, Debug, Eq, failure::Fail, PartialEq)] pub enum Error { /// There was an invalid token in the code. #[fail(display = "invalid token")] @@ -166,22 +166,24 @@ fn handle_parse_result( macro_rules! parser_impl { ($stat:ident, $parser:ident, $result:ty) => { - lazy_static! { - static ref $stat: crate::parser::tin::$parser = { crate::parser::tin::$parser::new() }; + lazy_static::lazy_static! { + static ref $stat: crate::syntax::parser::grammar::$parser = + { crate::syntax::parser::grammar::$parser::new() }; } impl Parse for $result { - type Parser = &'static crate::parser::tin::$parser; + type Parser = &'static crate::syntax::parser::grammar::$parser; fn new_parser() -> Self::Parser { &*$stat } } - impl Parser<$result> for &'static crate::parser::tin::$parser { + impl Parser<$result> for &'static crate::syntax::parser::grammar::$parser { fn parse(&mut self, span: codespan::ByteSpan, source: &str) -> Result<$result, Error> { let mut errors = Vec::new(); - let result = crate::parser::tin::$parser::parse(self, span, &mut errors, source); + let result = + crate::syntax::parser::grammar::$parser::parse(self, span, &mut errors, source); handle_parse_result(source, span, result, errors) } } @@ -219,18 +221,13 @@ impl Error { ), } } - lalrpop_util::ParseError::UnrecognizedToken { token, expected } => { - let token = token.map_or( - codespan::Span::new( - span.end() - codespan::ByteOffset(1), - span.end() - codespan::ByteOffset(1), - ), - |(s, _, e)| { - span.subspan( - codespan::ByteOffset(s as codespan::RawOffset), - codespan::ByteOffset(e as codespan::RawOffset), - ) - }, + lalrpop_util::ParseError::UnrecognizedToken { + token: (s, _, e), + expected, + } => { + let token = span.subspan( + codespan::ByteOffset(s as codespan::RawOffset), + codespan::ByteOffset(e as codespan::RawOffset), ); Error::Unexpected { token, expected } } @@ -241,6 +238,13 @@ impl Error { ); Error::Extra { token } } + lalrpop_util::ParseError::UnrecognizedEOF { location, expected } => { + let token = span.subspan( + codespan::ByteOffset(location as codespan::RawOffset), + codespan::ByteOffset((location + 1) as codespan::RawOffset), + ); + Error::Unexpected { token, expected } + } lalrpop_util::ParseError::User { error } => error, } } @@ -387,10 +391,10 @@ impl diagnostic::Diagnostics for Error { #[cfg(test)] mod tests { - use env_logger; + use std::sync; - use crate::ast; - use crate::ast::MapContext; + use crate::syntax::ast; + use crate::syntax::ast::MapContext; #[test] fn e2e() { @@ -423,8 +427,10 @@ main = || -> i32 { let expected = Err(r#"error: invalid token - :1:1 + | 1 | #+- | ^ + | "# .to_owned()); let actual = parse_module("test", r#"#+-"#); @@ -437,9 +443,11 @@ main = || -> i32 { let expected = Err(r#"error: unexpected token - :1:28 + | 1 | main = || -> u32 { 0u32 }; <-< | ^^^ -help: valid tokens at this point: [Comment, IdentifierName] + | +help: valid tokens at this point: [Comment, Identifier] "# .to_owned()); let actual = parse_module("test", r#"main = || -> u32 { 0u32 }; <-<"#); @@ -450,9 +458,9 @@ help: valid tokens at this point: [Comment, IdentifierName] fn identifier() { let _ = env_logger::try_init(); - let expected = Ok(ast::Expression::Identifier(ast::Identifier { + let expected = Ok(ast::Expression::Reference(ast::Reference { context: (), - value: "whatever".to_owned(), + value: sync::Arc::new("whatever".to_owned()), })); let actual = parse_expression("test", r#"whatever"#); assert_eq!(expected, actual); @@ -462,9 +470,9 @@ help: valid tokens at this point: [Comment, IdentifierName] fn identifier_unicode() { let _ = env_logger::try_init(); - let expected = Ok(ast::Expression::Identifier(ast::Identifier { + let expected = Ok(ast::Expression::Reference(ast::Reference { context: (), - value: "なんでも".to_owned(), + value: sync::Arc::new("なんでも".to_owned()), })); let actual = parse_expression("test", r#"なんでも"#); assert_eq!(expected, actual); @@ -476,7 +484,7 @@ help: valid tokens at this point: [Comment, IdentifierName] let expected = Ok(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), - value: ast::NumberValue::F64(1.0), + value: ast::NumberValue::F64(1.0.into()), })); let actual = parse_expression("test", r#"1f64"#); assert_eq!(expected, actual); @@ -488,7 +496,7 @@ help: valid tokens at this point: [Comment, IdentifierName] let expected = Ok(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), - value: ast::NumberValue::F64(0.0), + value: ast::NumberValue::F64(0.0.into()), })); let actual = parse_expression("test", r#"f64"#); assert_eq!(expected, actual); @@ -500,7 +508,7 @@ help: valid tokens at this point: [Comment, IdentifierName] let expected = Ok(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), - value: ast::NumberValue::F64(-1.0), + value: ast::NumberValue::F64(ordered_float::OrderedFloat::from(-1.0)), })); let actual = parse_expression("test", r#"-1f64"#); assert_eq!(expected, actual); @@ -512,7 +520,7 @@ help: valid tokens at this point: [Comment, IdentifierName] let expected = Ok(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), - value: ast::NumberValue::F64(0.0), + value: ast::NumberValue::F64(ordered_float::OrderedFloat::from(0.0)), })); let actual = parse_expression("test", r#"0f64"#); assert_eq!(expected, actual); @@ -524,7 +532,7 @@ help: valid tokens at this point: [Comment, IdentifierName] let expected = Ok(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), - value: ast::NumberValue::F64(-0.0), + value: ast::NumberValue::F64(ordered_float::OrderedFloat::from(-0.0)), })); let actual = parse_expression("test", r#"-0f64"#); assert_eq!(expected, actual); @@ -536,7 +544,7 @@ help: valid tokens at this point: [Comment, IdentifierName] let expected = Ok(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), - value: ast::NumberValue::F64(1.5), + value: ast::NumberValue::F64(ordered_float::OrderedFloat::from(1.5)), })); let actual = parse_expression("test", r#"1.5f64"#); assert_eq!(expected, actual); @@ -548,7 +556,7 @@ help: valid tokens at this point: [Comment, IdentifierName] let expected = Ok(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), - value: ast::NumberValue::F64(-1.5), + value: ast::NumberValue::F64(ordered_float::OrderedFloat::from(-1.5)), })); let actual = parse_expression("test", r#"-1.5f64"#); assert_eq!(expected, actual); @@ -560,7 +568,7 @@ help: valid tokens at this point: [Comment, IdentifierName] let expected = Ok(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), - value: ast::NumberValue::F64(1500.0), + value: ast::NumberValue::F64(ordered_float::OrderedFloat::from(1500.0)), })); let actual = parse_expression("test", r#"1.5000e3f64"#); assert_eq!(expected, actual); @@ -572,7 +580,7 @@ help: valid tokens at this point: [Comment, IdentifierName] let expected = Ok(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), - value: ast::NumberValue::F64(-1500.0), + value: ast::NumberValue::F64(ordered_float::OrderedFloat::from(-1500.0)), })); let actual = parse_expression("test", r#"-1.5000e3f64"#); assert_eq!(expected, actual); @@ -584,7 +592,7 @@ help: valid tokens at this point: [Comment, IdentifierName] let expected = Ok(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), - value: ast::NumberValue::F64(1500.0), + value: ast::NumberValue::F64(ordered_float::OrderedFloat::from(1500.0)), })); let actual = parse_expression("test", r#"1.5000E3f64"#); assert_eq!(expected, actual); @@ -596,7 +604,7 @@ help: valid tokens at this point: [Comment, IdentifierName] let expected = Ok(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), - value: ast::NumberValue::F64(-1500.0), + value: ast::NumberValue::F64(ordered_float::OrderedFloat::from(-1500.0)), })); let actual = parse_expression("test", r#"-1.5000E3f64"#); assert_eq!(expected, actual); @@ -608,7 +616,7 @@ help: valid tokens at this point: [Comment, IdentifierName] let expected = Ok(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), - value: ast::NumberValue::F64(0.0015), + value: ast::NumberValue::F64(ordered_float::OrderedFloat::from(0.0015)), })); let actual = parse_expression("test", r#"1.5000e-3f64"#); assert_eq!(expected, actual); @@ -620,7 +628,7 @@ help: valid tokens at this point: [Comment, IdentifierName] let expected = Ok(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), - value: ast::NumberValue::F64(1500.0), + value: ast::NumberValue::F64(ordered_float::OrderedFloat::from(1500.0)), })); let actual = parse_expression("test", r#"1.5000e0003f64"#); assert_eq!(expected, actual); @@ -632,7 +640,7 @@ help: valid tokens at this point: [Comment, IdentifierName] let expected = Ok(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), - value: ast::NumberValue::F64(1500.0), + value: ast::NumberValue::F64(ordered_float::OrderedFloat::from(1500.0)), })); let actual = parse_expression("test", r#"1.5000e+3f64"#); assert_eq!(expected, actual); @@ -644,7 +652,7 @@ help: valid tokens at this point: [Comment, IdentifierName] let expected = Ok(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), - value: ast::NumberValue::F64(1.5), + value: ast::NumberValue::F64(ordered_float::OrderedFloat::from(1.5)), })); let actual = parse_expression("test", r#"1.5000e0f64"#); assert_eq!(expected, actual); @@ -656,7 +664,7 @@ help: valid tokens at this point: [Comment, IdentifierName] let expected = Ok(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), - value: ast::NumberValue::F64(1.5), + value: ast::NumberValue::F64(ordered_float::OrderedFloat::from(1.5)), })); let actual = parse_expression("test", r#"1.5000e+0f64"#); assert_eq!(expected, actual); @@ -668,7 +676,7 @@ help: valid tokens at this point: [Comment, IdentifierName] let expected = Ok(ast::Expression::StringLiteral(ast::StringLiteral { context: (), - value: ast::StringValue::String("abc".to_owned()), + value: ast::StringValue::String(sync::Arc::new("abc".to_owned())), })); let actual = parse_expression("test", r#""abc""#); assert_eq!(expected, actual); @@ -680,7 +688,7 @@ help: valid tokens at this point: [Comment, IdentifierName] let expected = Ok(ast::Expression::StringLiteral(ast::StringLiteral { context: (), - value: ast::StringValue::String("なんでも".to_owned()), + value: ast::StringValue::String(sync::Arc::new("なんでも".to_owned())), })); let actual = parse_expression("test", r#""なんでも""#); assert_eq!(expected, actual); @@ -692,7 +700,9 @@ help: valid tokens at this point: [Comment, IdentifierName] let expected = Ok(ast::Expression::StringLiteral(ast::StringLiteral { context: (), - value: ast::StringValue::String("\"\\/\u{0008}\u{000C}\n\r\t\u{1234}".to_owned()), + value: ast::StringValue::String(sync::Arc::new( + "\"\\/\u{0008}\u{000C}\n\r\t\u{1234}".to_owned(), + )), })); let actual = parse_expression("test", r#""\"\\/\b\f\n\r\t\u{1234}""#); assert_eq!(expected, actual); @@ -705,14 +715,14 @@ help: valid tokens at this point: [Comment, IdentifierName] let expected = Ok(ast::Expression::Tuple(ast::Tuple { context: (), fields: vec![ - ast::Expression::NumberLiteral(ast::NumberLiteral { + sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), - value: ast::NumberValue::F64(1.0), - }), - ast::Expression::NumberLiteral(ast::NumberLiteral { + value: ast::NumberValue::F64(ordered_float::OrderedFloat::from(1.0)), + })), + sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), - value: ast::NumberValue::F64(2.0), - }), + value: ast::NumberValue::F64(ordered_float::OrderedFloat::from(2.0)), + })), ], })); let actual = parse_expression("test", r#"(1f64, 2f64)"#); @@ -726,14 +736,14 @@ help: valid tokens at this point: [Comment, IdentifierName] let expected = Ok(ast::Expression::Tuple(ast::Tuple { context: (), fields: vec![ - ast::Expression::NumberLiteral(ast::NumberLiteral { + sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), - value: ast::NumberValue::F64(1.0), - }), - ast::Expression::NumberLiteral(ast::NumberLiteral { + value: ast::NumberValue::F64(ordered_float::OrderedFloat::from(1.0)), + })), + sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), - value: ast::NumberValue::F64(2.0), - }), + value: ast::NumberValue::F64(ordered_float::OrderedFloat::from(2.0)), + })), ], })); let actual = parse_expression("test", r#"(1f64, 2f64,)"#); @@ -746,10 +756,12 @@ help: valid tokens at this point: [Comment, IdentifierName] let expected = Ok(ast::Expression::Tuple(ast::Tuple { context: (), - fields: vec![ast::Expression::NumberLiteral(ast::NumberLiteral { - context: (), - value: ast::NumberValue::F64(1.0), - })], + fields: vec![sync::Arc::new(ast::Expression::NumberLiteral( + ast::NumberLiteral { + context: (), + value: ast::NumberValue::F64(ordered_float::OrderedFloat::from(1.0)), + }, + ))], })); let actual = parse_expression("test", r#"(1f64,)"#); assert_eq!(expected, actual); @@ -773,9 +785,11 @@ help: valid tokens at this point: [Comment, IdentifierName] let expected = Err(r##"error: unexpected token - :1:2 + | 1 | (,) | ^ -help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", "#^1", "(", ")", "^/", "{", "|", "~!", IdentifierName, NumberValue, StringValue, SymbolLabel] + | +help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", "#^1", "(", ")", "^/", "{", "|", "~!", Identifier, NumberValue, StringValue, SymbolLabel] "##.to_owned()); let actual = parse_expression("test", r#"(,)"#); assert_eq!(expected, actual); @@ -789,28 +803,20 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", context: (), fields: vec![ ( - ast::Identifier { - context: (), - value: "a".to_owned(), - }, - ast::Expression::NumberLiteral(ast::NumberLiteral { + sync::Arc::new("a".to_owned()), + sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), - value: ast::NumberValue::F64(1.0), - }), + value: ast::NumberValue::F64(ordered_float::OrderedFloat::from(1.0)), + })), ), ( - ast::Identifier { + sync::Arc::new("b".to_owned()), + sync::Arc::new(ast::Expression::StringLiteral(ast::StringLiteral { context: (), - value: "b".to_owned(), - }, - ast::Expression::StringLiteral(ast::StringLiteral { - context: (), - value: ast::StringValue::String("c".to_owned()), - }), + value: ast::StringValue::String(sync::Arc::new("c".to_owned())), + })), ), - ] - .into_iter() - .collect(), + ], })); let actual = parse_expression("test", r#"{a: 1f64, b: "c"}"#); assert_eq!(expected, actual); @@ -824,28 +830,20 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", context: (), fields: vec![ ( - ast::Identifier { + sync::Arc::new("a".to_owned()), + sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), - value: "a".to_owned(), - }, - ast::Expression::NumberLiteral(ast::NumberLiteral { - context: (), - value: ast::NumberValue::F64(1.0), - }), + value: ast::NumberValue::F64(ordered_float::OrderedFloat::from(1.0)), + })), ), ( - ast::Identifier { - context: (), - value: "b".to_owned(), - }, - ast::Expression::StringLiteral(ast::StringLiteral { + sync::Arc::new("b".to_owned()), + sync::Arc::new(ast::Expression::StringLiteral(ast::StringLiteral { context: (), - value: ast::StringValue::String("c".to_owned()), - }), + value: ast::StringValue::String(sync::Arc::new("c".to_owned())), + })), ), - ] - .into_iter() - .collect(), + ], })); let actual = parse_expression("test", r#"{a: 1f64, b: "c",}"#); assert_eq!(expected, actual); @@ -858,17 +856,12 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", let expected = Ok(ast::Expression::Record(ast::Record { context: (), fields: vec![( - ast::Identifier { - context: (), - value: "a".to_owned(), - }, - ast::Expression::NumberLiteral(ast::NumberLiteral { + sync::Arc::new("a".to_owned()), + sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), - value: ast::NumberValue::F64(1.0), - }), - )] - .into_iter() - .collect(), + value: ast::NumberValue::F64(ordered_float::OrderedFloat::from(1.0)), + })), + )], })); let actual = parse_expression("test", r#"{a: 1f64}"#); assert_eq!(expected, actual); @@ -881,17 +874,12 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", let expected = Ok(ast::Expression::Record(ast::Record { context: (), fields: vec![( - ast::Identifier { + sync::Arc::new("a".to_owned()), + sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), - value: "a".to_owned(), - }, - ast::Expression::NumberLiteral(ast::NumberLiteral { - context: (), - value: ast::NumberValue::F64(1.0), - }), - )] - .into_iter() - .collect(), + value: ast::NumberValue::F64(ordered_float::OrderedFloat::from(1.0)), + })), + )], })); let actual = parse_expression("test", r#"{a: 1f64,}"#); assert_eq!(expected, actual); @@ -924,7 +912,7 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", let expected = Ok(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::Not, - operand: Box::new(ast::Expression::NumberLiteral(ast::NumberLiteral { + operand: sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), value: ast::NumberValue::U32(0), })), @@ -940,10 +928,10 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", let expected = Ok(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::Not, - operand: Box::new(ast::Expression::UnOp(ast::UnOp { + operand: sync::Arc::new(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::Not, - operand: Box::new(ast::Expression::NumberLiteral(ast::NumberLiteral { + operand: sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), value: ast::NumberValue::U32(0), })), @@ -960,7 +948,7 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", let expected = Ok(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::BNot, - operand: Box::new(ast::Expression::NumberLiteral(ast::NumberLiteral { + operand: sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), value: ast::NumberValue::U32(0), })), @@ -976,10 +964,10 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", let expected = Ok(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::BNot, - operand: Box::new(ast::Expression::UnOp(ast::UnOp { + operand: sync::Arc::new(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::BNot, - operand: Box::new(ast::Expression::NumberLiteral(ast::NumberLiteral { + operand: sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), value: ast::NumberValue::U32(0), })), @@ -996,7 +984,7 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", let expected = Ok(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::Cl0, - operand: Box::new(ast::Expression::NumberLiteral(ast::NumberLiteral { + operand: sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), value: ast::NumberValue::U32(0), })), @@ -1012,10 +1000,10 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", let expected = Ok(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::Cl0, - operand: Box::new(ast::Expression::UnOp(ast::UnOp { + operand: sync::Arc::new(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::Cl0, - operand: Box::new(ast::Expression::NumberLiteral(ast::NumberLiteral { + operand: sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), value: ast::NumberValue::U32(0), })), @@ -1032,7 +1020,7 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", let expected = Ok(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::Cl1, - operand: Box::new(ast::Expression::NumberLiteral(ast::NumberLiteral { + operand: sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), value: ast::NumberValue::U32(0), })), @@ -1048,10 +1036,10 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", let expected = Ok(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::Cl1, - operand: Box::new(ast::Expression::UnOp(ast::UnOp { + operand: sync::Arc::new(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::Cl1, - operand: Box::new(ast::Expression::NumberLiteral(ast::NumberLiteral { + operand: sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), value: ast::NumberValue::U32(0), })), @@ -1068,7 +1056,7 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", let expected = Ok(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::Cls, - operand: Box::new(ast::Expression::NumberLiteral(ast::NumberLiteral { + operand: sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), value: ast::NumberValue::U32(0), })), @@ -1084,10 +1072,10 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", let expected = Ok(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::Cls, - operand: Box::new(ast::Expression::UnOp(ast::UnOp { + operand: sync::Arc::new(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::Cls, - operand: Box::new(ast::Expression::NumberLiteral(ast::NumberLiteral { + operand: sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), value: ast::NumberValue::U32(0), })), @@ -1104,7 +1092,7 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", let expected = Ok(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::Ct0, - operand: Box::new(ast::Expression::NumberLiteral(ast::NumberLiteral { + operand: sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), value: ast::NumberValue::U32(0), })), @@ -1120,10 +1108,10 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", let expected = Ok(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::Ct0, - operand: Box::new(ast::Expression::UnOp(ast::UnOp { + operand: sync::Arc::new(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::Ct0, - operand: Box::new(ast::Expression::NumberLiteral(ast::NumberLiteral { + operand: sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), value: ast::NumberValue::U32(0), })), @@ -1140,7 +1128,7 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", let expected = Ok(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::Ct1, - operand: Box::new(ast::Expression::NumberLiteral(ast::NumberLiteral { + operand: sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), value: ast::NumberValue::U32(0), })), @@ -1156,10 +1144,10 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", let expected = Ok(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::Ct1, - operand: Box::new(ast::Expression::UnOp(ast::UnOp { + operand: sync::Arc::new(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::Ct1, - operand: Box::new(ast::Expression::NumberLiteral(ast::NumberLiteral { + operand: sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), value: ast::NumberValue::U32(0), })), @@ -1176,7 +1164,7 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", let expected = Ok(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::C0, - operand: Box::new(ast::Expression::NumberLiteral(ast::NumberLiteral { + operand: sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), value: ast::NumberValue::U32(0), })), @@ -1192,10 +1180,10 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", let expected = Ok(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::C0, - operand: Box::new(ast::Expression::UnOp(ast::UnOp { + operand: sync::Arc::new(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::C0, - operand: Box::new(ast::Expression::NumberLiteral(ast::NumberLiteral { + operand: sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), value: ast::NumberValue::U32(0), })), @@ -1212,7 +1200,7 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", let expected = Ok(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::C1, - operand: Box::new(ast::Expression::NumberLiteral(ast::NumberLiteral { + operand: sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), value: ast::NumberValue::U32(0), })), @@ -1228,10 +1216,10 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", let expected = Ok(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::C1, - operand: Box::new(ast::Expression::UnOp(ast::UnOp { + operand: sync::Arc::new(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::C1, - operand: Box::new(ast::Expression::NumberLiteral(ast::NumberLiteral { + operand: sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), value: ast::NumberValue::U32(0), })), @@ -1248,7 +1236,7 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", let expected = Ok(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::Sqrt, - operand: Box::new(ast::Expression::NumberLiteral(ast::NumberLiteral { + operand: sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), value: ast::NumberValue::U32(0), })), @@ -1264,10 +1252,10 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", let expected = Ok(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::Sqrt, - operand: Box::new(ast::Expression::UnOp(ast::UnOp { + operand: sync::Arc::new(ast::Expression::UnOp(ast::UnOp { context: (), operator: ast::UnOperator::Sqrt, - operand: Box::new(ast::Expression::NumberLiteral(ast::NumberLiteral { + operand: sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), value: ast::NumberValue::U32(0), })), @@ -1284,44 +1272,38 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", let expected = Ok(ast::Expression::Lambda(ast::Lambda { context: (), parameters: vec![ - ast::Parameter { + sync::Arc::new(ast::Parameter { context: (), - name: ast::Identifier { - context: (), - value: "a".to_owned(), - }, - signature: ast::Expression::Identifier(ast::Identifier { + name: sync::Arc::new("a".to_owned()), + signature: sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "t1".to_owned(), - }), - }, - ast::Parameter { + value: sync::Arc::new("t1".to_owned()), + })), + }), + sync::Arc::new(ast::Parameter { context: (), - name: ast::Identifier { - context: (), - value: "b".to_owned(), - }, - signature: ast::Expression::Identifier(ast::Identifier { + name: sync::Arc::new("b".to_owned()), + signature: sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "t2".to_owned(), - }), - }, + value: sync::Arc::new("t2".to_owned()), + })), + }), ], - signature: Box::new(ast::Expression::Identifier(ast::Identifier { + signature: sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "t3".to_owned(), + value: sync::Arc::new("t3".to_owned()), })), statements: vec![], - result: Some(Box::new(ast::Expression::Apply(ast::Apply { + result: Some(sync::Arc::new(ast::Expression::Apply(ast::Apply { context: (), - function: Box::new(ast::Expression::Identifier(ast::Identifier { + function: sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "a".to_owned(), + value: sync::Arc::new("a".to_owned()), })), - parameters: vec![ast::Expression::Identifier(ast::Identifier { + parameters: vec![sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "b".to_owned(), - })], + value: sync::Arc::new("b".to_owned()), + }))], }))), })); let actual = parse_expression("test", r#"|a: t1, b: t2| -> t3 { a(b) }"#); @@ -1335,80 +1317,70 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", let expected = Ok(ast::Expression::Lambda(ast::Lambda { context: (), parameters: vec![ - ast::Parameter { + sync::Arc::new(ast::Parameter { context: (), - name: ast::Identifier { + name: sync::Arc::new("a".to_owned()), + signature: sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "a".to_owned(), - }, - signature: ast::Expression::Identifier(ast::Identifier { - context: (), - value: "t1".to_owned(), - }), - }, - ast::Parameter { + value: sync::Arc::new("t1".to_owned()), + })), + }), + sync::Arc::new(ast::Parameter { context: (), - name: ast::Identifier { - context: (), - value: "b".to_owned(), - }, - signature: ast::Expression::Identifier(ast::Identifier { + name: sync::Arc::new("b".to_owned()), + signature: sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "t2".to_owned(), - }), - }, + value: sync::Arc::new("t2".to_owned()), + })), + }), ], - signature: Box::new(ast::Expression::Identifier(ast::Identifier { + signature: sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "t3".to_owned(), + value: sync::Arc::new("t3".to_owned()), })), - statements: vec![ast::Statement::Variable(ast::Variable { + statements: vec![sync::Arc::new(ast::Statement::Variable(ast::Variable { context: (), - name: ast::Identifier { - context: (), - value: "c".to_owned(), - }, - initializer: ast::Expression::Lambda(ast::Lambda { + name: sync::Arc::new("c".to_owned()), + initializer: sync::Arc::new(ast::Expression::Lambda(ast::Lambda { context: (), - parameters: vec![ast::Parameter { + parameters: vec![sync::Arc::new(ast::Parameter { context: (), - name: ast::Identifier { - context: (), - value: "b".to_owned(), - }, - signature: ast::Expression::Identifier(ast::Identifier { + name: sync::Arc::new("b".to_owned()), + signature: sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "t4".to_owned(), - }), - }], - signature: Box::new(ast::Expression::Identifier(ast::Identifier { + value: sync::Arc::new("t4".to_owned()), + })), + })], + signature: sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "t5".to_owned(), + value: sync::Arc::new("t5".to_owned()), })), statements: vec![], - result: Some(Box::new(ast::Expression::Apply(ast::Apply { + result: Some(sync::Arc::new(ast::Expression::Apply(ast::Apply { context: (), - function: Box::new(ast::Expression::Identifier(ast::Identifier { + function: sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "a".to_owned(), + value: sync::Arc::new("a".to_owned()), })), - parameters: vec![ast::Expression::Identifier(ast::Identifier { - context: (), - value: "b".to_owned(), - })], + parameters: vec![sync::Arc::new(ast::Expression::Reference( + ast::Reference { + context: (), + value: sync::Arc::new("b".to_owned()), + }, + ))], }))), - }), - })], - result: Some(Box::new(ast::Expression::Apply(ast::Apply { + })), + }))], + result: Some(sync::Arc::new(ast::Expression::Apply(ast::Apply { context: (), - function: Box::new(ast::Expression::Identifier(ast::Identifier { + function: sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "c".to_owned(), + value: sync::Arc::new("c".to_owned()), })), - parameters: vec![ast::Expression::Identifier(ast::Identifier { + parameters: vec![sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "b".to_owned(), - })], + value: sync::Arc::new("b".to_owned()), + }))], }))), })); let actual = parse_expression( @@ -1425,80 +1397,70 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", let expected = Ok(ast::Expression::Lambda(ast::Lambda { context: (), parameters: vec![ - ast::Parameter { + sync::Arc::new(ast::Parameter { context: (), - name: ast::Identifier { - context: (), - value: "a".to_owned(), - }, - signature: ast::Expression::Identifier(ast::Identifier { + name: sync::Arc::new("a".to_owned()), + signature: sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "t1".to_owned(), - }), - }, - ast::Parameter { + value: sync::Arc::new("t1".to_owned()), + })), + }), + sync::Arc::new(ast::Parameter { context: (), - name: ast::Identifier { - context: (), - value: "b".to_owned(), - }, - signature: ast::Expression::Identifier(ast::Identifier { + name: sync::Arc::new("b".to_owned()), + signature: sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "t2".to_owned(), - }), - }, + value: sync::Arc::new("t2".to_owned()), + })), + }), ], - signature: Box::new(ast::Expression::Identifier(ast::Identifier { + signature: sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "t3".to_owned(), + value: sync::Arc::new("t3".to_owned()), })), - statements: vec![ast::Statement::Variable(ast::Variable { + statements: vec![sync::Arc::new(ast::Statement::Variable(ast::Variable { context: (), - name: ast::Identifier { + name: sync::Arc::new("c".to_owned()), + initializer: sync::Arc::new(ast::Expression::Lambda(ast::Lambda { context: (), - value: "c".to_owned(), - }, - initializer: ast::Expression::Lambda(ast::Lambda { - context: (), - parameters: vec![ast::Parameter { + parameters: vec![sync::Arc::new(ast::Parameter { context: (), - name: ast::Identifier { - context: (), - value: "b".to_owned(), - }, - signature: ast::Expression::Identifier(ast::Identifier { + name: sync::Arc::new("b".to_owned()), + signature: sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "t4".to_owned(), - }), - }], - signature: Box::new(ast::Expression::Identifier(ast::Identifier { + value: sync::Arc::new("t4".to_owned()), + })), + })], + signature: sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "t5".to_owned(), + value: sync::Arc::new("t5".to_owned()), })), statements: vec![], - result: Some(Box::new(ast::Expression::Apply(ast::Apply { + result: Some(sync::Arc::new(ast::Expression::Apply(ast::Apply { context: (), - function: Box::new(ast::Expression::Identifier(ast::Identifier { + function: sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "a".to_owned(), + value: sync::Arc::new("a".to_owned()), })), - parameters: vec![ast::Expression::Identifier(ast::Identifier { - context: (), - value: "b".to_owned(), - })], + parameters: vec![sync::Arc::new(ast::Expression::Reference( + ast::Reference { + context: (), + value: sync::Arc::new("b".to_owned()), + }, + ))], }))), - }), - })], - result: Some(Box::new(ast::Expression::Apply(ast::Apply { + })), + }))], + result: Some(sync::Arc::new(ast::Expression::Apply(ast::Apply { context: (), - function: Box::new(ast::Expression::Identifier(ast::Identifier { + function: sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "c".to_owned(), + value: sync::Arc::new("c".to_owned()), })), - parameters: vec![ast::Expression::Identifier(ast::Identifier { + parameters: vec![sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "b".to_owned(), - })], + value: sync::Arc::new("b".to_owned()), + }))], }))), })); let actual = parse_expression( @@ -1515,44 +1477,38 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", let expected = Ok(ast::Expression::Lambda(ast::Lambda { context: (), parameters: vec![ - ast::Parameter { + sync::Arc::new(ast::Parameter { context: (), - name: ast::Identifier { - context: (), - value: "a".to_owned(), - }, - signature: ast::Expression::NumberLiteral(ast::NumberLiteral { + name: sync::Arc::new("a".to_owned()), + signature: sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), value: ast::NumberValue::U32(0), - }), - }, - ast::Parameter { + })), + }), + sync::Arc::new(ast::Parameter { context: (), - name: ast::Identifier { - context: (), - value: "b".to_owned(), - }, - signature: ast::Expression::NumberLiteral(ast::NumberLiteral { + name: sync::Arc::new("b".to_owned()), + signature: sync::Arc::new(ast::Expression::NumberLiteral(ast::NumberLiteral { context: (), value: ast::NumberValue::U32(0), - }), - }, + })), + }), ], - signature: Box::new(ast::Expression::Identifier(ast::Identifier { + signature: sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "t1".to_owned(), + value: sync::Arc::new("t1".to_owned()), })), statements: vec![], - result: Some(Box::new(ast::Expression::Apply(ast::Apply { + result: Some(sync::Arc::new(ast::Expression::Apply(ast::Apply { context: (), - function: Box::new(ast::Expression::Identifier(ast::Identifier { + function: sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "a".to_owned(), + value: sync::Arc::new("a".to_owned()), })), - parameters: vec![ast::Expression::Identifier(ast::Identifier { + parameters: vec![sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "b".to_owned(), - })], + value: sync::Arc::new("b".to_owned()), + }))], }))), })); let actual = parse_expression("test", r#"|a: u32, b: u32| -> t1 { a(b) }"#); @@ -1566,56 +1522,50 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", let expected = Ok(ast::Expression::Lambda(ast::Lambda { context: (), parameters: vec![ - ast::Parameter { + sync::Arc::new(ast::Parameter { context: (), - name: ast::Identifier { - context: (), - value: "a".to_owned(), - }, - signature: ast::Expression::Identifier(ast::Identifier { + name: sync::Arc::new("a".to_owned()), + signature: sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "t1".to_owned(), - }), - }, - ast::Parameter { + value: sync::Arc::new("t1".to_owned()), + })), + }), + sync::Arc::new(ast::Parameter { context: (), - name: ast::Identifier { - context: (), - value: "b".to_owned(), - }, - signature: ast::Expression::Identifier(ast::Identifier { + name: sync::Arc::new("b".to_owned()), + signature: sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "t2".to_owned(), - }), - }, + value: sync::Arc::new("t2".to_owned()), + })), + }), ], - signature: Box::new(ast::Expression::Identifier(ast::Identifier { + signature: sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "t3".to_owned(), + value: sync::Arc::new("t3".to_owned()), })), - statements: vec![ast::Statement::Expression(ast::Expression::Apply( - ast::Apply { + statements: vec![sync::Arc::new(ast::Statement::Expression( + ast::Expression::Apply(ast::Apply { context: (), - function: Box::new(ast::Expression::Identifier(ast::Identifier { + function: sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "a".to_owned(), + value: sync::Arc::new("a".to_owned()), })), - parameters: vec![ast::Expression::Identifier(ast::Identifier { + parameters: vec![sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "b".to_owned(), - })], - }, + value: sync::Arc::new("b".to_owned()), + }))], + }), ))], - result: Some(Box::new(ast::Expression::Apply(ast::Apply { + result: Some(sync::Arc::new(ast::Expression::Apply(ast::Apply { context: (), - function: Box::new(ast::Expression::Identifier(ast::Identifier { + function: sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "a".to_owned(), + value: sync::Arc::new("a".to_owned()), })), - parameters: vec![ast::Expression::Identifier(ast::Identifier { + parameters: vec![sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "b".to_owned(), - })], + value: sync::Arc::new("b".to_owned()), + }))], }))), })); let actual = parse_expression("test", r#"|a: t1, b: t2| -> t3 { a(b); a(b) }"#); @@ -1628,21 +1578,21 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", let expected = Ok(ast::Expression::Apply(ast::Apply { context: (), - function: Box::new(ast::Expression::Identifier(ast::Identifier { + function: sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "a".to_owned(), + value: sync::Arc::new("a".to_owned()), })), - parameters: vec![ast::Expression::Identifier(ast::Identifier { + parameters: vec![sync::Arc::new(ast::Expression::Reference(ast::Reference { context: (), - value: "b".to_owned(), - })], + value: sync::Arc::new("b".to_owned()), + }))], })); let actual = parse_expression("test", r#"a(b)"#); assert_eq!(expected, actual); } fn parse_module(name: &'static str, source: &str) -> Result, String> { - use crate::parser::Parse; + use crate::syntax::parser::Parse; let mut code_map = codespan::CodeMap::new(); let span = code_map @@ -1650,14 +1600,14 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", .span(); let mut errors = Vec::new(); - let result = crate::ast::Module::new_parser().parse(span, &mut errors, source); + let result = crate::syntax::ast::Module::new_parser().parse(span, &mut errors, source); super::handle_parse_result(source, span, result, errors) .map(|r| r.map_context(&mut |_| ())) .map_err(|e| crate::diagnostic::to_string(&code_map, &e)) } fn parse_expression(name: &'static str, source: &str) -> Result, String> { - use crate::parser::Parse; + use crate::syntax::parser::Parse; let mut code_map = codespan::CodeMap::new(); let span = code_map @@ -1665,7 +1615,7 @@ help: valid tokens at this point: ["!", "#$0", "#$1", "#0", "#1", "#^-", "#^0", .span(); let mut errors = Vec::new(); - let result = crate::ast::Expression::new_parser().parse(span, &mut errors, source); + let result = crate::syntax::ast::Expression::new_parser().parse(span, &mut errors, source); super::handle_parse_result(source, span, result, errors) .map(|r| r.map_context(&mut |_| ())) .map_err(|e| crate::diagnostic::to_string(&code_map, &e)) diff --git a/src/parser/util.rs b/src/syntax/parser/util.rs similarity index 95% rename from src/parser/util.rs rename to src/syntax/parser/util.rs index 6f62fa9..5c52e1c 100644 --- a/src/parser/util.rs +++ b/src/syntax/parser/util.rs @@ -1,8 +1,9 @@ use std::char; use std::num; +use std::sync; -use crate::ast; -use crate::parser; +use crate::syntax::ast; +use crate::syntax::parser; fn parse_integer_literal( span: codespan::ByteSpan, @@ -34,26 +35,27 @@ where } } -fn parse_float_literal( +fn parse_float_literal( span: codespan::ByteSpan, input: &str, errors: &mut Vec>, suffix_len: usize, - default: I, + default: F, parser: P, ctor: C, ) -> ast::NumberValue where - P: FnOnce(&str) -> Result, - C: FnOnce(I) -> ast::NumberValue, + F: num_traits::float::Float, + P: FnOnce(&str) -> Result, + C: FnOnce(ordered_float::OrderedFloat) -> ast::NumberValue, { let input = &input[..input.len() - suffix_len]; if input.is_empty() { - ctor(default) + ctor(default.into()) } else { match parser(input) { - Ok(value) => ctor(value), + Ok(value) => ctor(value.into()), Err(cause) => { errors.push(lalrpop_util::ParseError::User { error: parser::Error::IllegalFloatLiteral { token: span, cause }, @@ -275,13 +277,13 @@ pub fn parse_escaped_string( // The +1 is for the initial quote char unicode_start = codespan::ByteOffset((i + 1) as codespan::RawOffset); } - 'a'...'f' => { + 'a'..='f' => { unicode = (c as u32 - 'a' as u32 + 10) + 16 * unicode; } - 'A'...'F' => { + 'A'..='F' => { unicode = (c as u32 - 'A' as u32 + 10) + 16 * unicode; } - '0'...'9' => { + '0'..='9' => { unicode = (c as u32 - '0' as u32) + 16 * unicode; } '}' => { @@ -355,9 +357,9 @@ pub fn parse_escaped_string( if is_invalid { ast::StringValue::Invalid } else { - ast::StringValue::String(result.to_owned()) + ast::StringValue::String(sync::Arc::new(result)) } } else { - ast::StringValue::String(input.to_owned()) + ast::StringValue::String(sync::Arc::new(input.to_owned())) } } diff --git a/src/test_util.rs b/src/test_util.rs index bbd1b3e..c2a6333 100644 --- a/src/test_util.rs +++ b/src/test_util.rs @@ -1,11 +1,11 @@ use failure; +use crate::db; use crate::graph; -use crate::ir; -pub fn render_graph(name: &str, ir: &ir::Ir) -> Result<(), failure::Error> { +pub fn render_graph(name: &str, db: &db::Db) -> Result<(), failure::Error> { if cfg!(feature = "test-render-graphs") { - let graph = graph::Graph::new(ir); + let graph = graph::Graph::new(db); let dot_path = format!("/tmp/{}.dot", name); let img_path = format!("/tmp/{}.svg", name); diff --git a/src/ir/component/ty/class.rs b/src/ty/class.rs similarity index 84% rename from src/ir/component/ty/class.rs rename to src/ty/class.rs index 56a08f8..e77369f 100644 --- a/src/ir/component/ty/class.rs +++ b/src/ty/class.rs @@ -1,6 +1,6 @@ use std::fmt; -#[derive(Clone, Copy, Debug, Eq, PartialEq, VisitEntities, VisitEntitiesMut)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum Scalar { Symbol, Integral(IntegralScalar), @@ -9,7 +9,7 @@ pub enum Scalar { Undefined, } -#[derive(Clone, Copy, Debug, Eq, PartialEq, VisitEntities, VisitEntitiesMut)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum IntegralScalar { Unsigned, Signed, diff --git a/src/ty/error.rs b/src/ty/error.rs new file mode 100644 index 0000000..b84a3ce --- /dev/null +++ b/src/ty/error.rs @@ -0,0 +1,111 @@ +use std::fmt; +use std::result; +use std::sync; + +use crate::diagnostic; +use crate::ir; +use crate::ty; +use crate::ty::class; + +#[derive(Clone, Debug, Eq, failure::Fail, PartialEq)] +pub enum Error { + #[fail(display = "type conflict: {}", _0)] + Conflict(Conflict), + #[fail(display = "semantic error")] + Ir(#[cause] ir::error::Error), +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Conflict { + pub expected: ExpectedType, + pub actual: sync::Arc, + pub main_entity: ir::location::Location, + pub aux_entities: Vec, +} + +pub type Result = result::Result; + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct AuxEntity { + pub entity: ir::location::Location, + pub label: String, +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum ExpectedType { + Specific(sync::Arc), + ScalarClass(class::Scalar), + AnyOf(Vec), + Union, +} + +impl From for Error { + fn from(error: ir::error::Error) -> Self { + Error::Ir(error) + } +} + +impl fmt::Display for Conflict { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "expected ")?; + self.expected.fmt(f)?; + write!(f, " but got `")?; + self.actual.fmt(f)?; + write!(f, "`")?; + Ok(()) + } +} + +impl fmt::Display for ExpectedType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + ExpectedType::Specific(ref ty) => write!(f, "`{}`", ty), + ExpectedType::ScalarClass(ref class) => class.fmt(f), + ExpectedType::AnyOf(ref options) => { + if options.is_empty() { + write!(f, "nothing")?; + } else { + for (i, option) in options.iter().enumerate() { + if i + 1 == options.len() { + write!(f, " or ")?; + } else if i > 0 { + write!(f, ", ")?; + } + option.fmt(f)?; + } + } + Ok(()) + } + ExpectedType::Union => f.write_str("any union type"), + } + } +} + +impl diagnostic::Diagnostics for Error { + fn to_diagnostics(&self, builder: &mut diagnostic::DiagnosticsBuilder) { + match self { + Error::Conflict(conflict) => conflict.to_diagnostics(builder), + Error::Ir(error) => error.to_diagnostics(builder), + } + } +} + +impl diagnostic::Diagnostics for Conflict { + fn to_diagnostics(&self, builder: &mut diagnostic::DiagnosticsBuilder) { + builder.add_label(codespan_reporting::Label { + span: self.main_entity.0, + message: Some(self.to_string()), + style: codespan_reporting::LabelStyle::Primary, + }); + + for aux_entity in &self.aux_entities { + builder.add_label(codespan_reporting::Label { + span: aux_entity.entity.0, + message: Some(aux_entity.label.clone()), + style: codespan_reporting::LabelStyle::Secondary, + }); + } + + builder.add_diagnostic(codespan_reporting::Severity::Error, None, &self.to_string()); + } +} diff --git a/src/ty/infer.rs b/src/ty/infer.rs new file mode 100644 index 0000000..5a2327f --- /dev/null +++ b/src/ty/infer.rs @@ -0,0 +1,496 @@ +use std::collections; +use std::result; +use std::sync; + +use crate::ir; +use crate::ir::element; +use crate::ty; + +type Result = result::Result, ty::error::Error>; + +pub fn element_type(element: &element::Element, db: &impl ty::Db) -> Result { + match *element { + element::Element::Reference(entity) => element_type(&*db.element(entity)?, db), + element::Element::Number(ref n) => Ok(sync::Arc::new(ty::Type::Number(number_type(n)))), + element::Element::String(_) => Ok(sync::Arc::new(ty::Type::String)), + element::Element::Symbol(element::Symbol { ref label }) => { + Ok(sync::Arc::new(ty::Type::Symbol(ty::Symbol { + label: *label, + }))) + } + element::Element::Tuple(element::Tuple { ref fields }) => tuple_type(fields, db), + element::Element::Record(element::Record { ref fields }) => record_type(fields, db), + element::Element::UnOp(element::UnOp { operand, operator }) => { + un_op_type(operand, operator, db) + } + element::Element::BiOp(element::BiOp { lhs, operator, rhs }) => { + bi_op_type(lhs, operator, rhs, db) + } + element::Element::Variable(element::Variable { initializer, .. }) => { + variable_type(initializer, db) + } + element::Element::Select(element::Select { record, field }) => { + select_type(record, field, db) + } + element::Element::Apply(element::Apply { + function, + ref parameters, + }) => apply_type(function, parameters, db), + element::Element::Parameter(element::Parameter { signature, .. }) => { + parameter_type(signature, db) + } + element::Element::Capture(element::Capture { captured, .. }) => capture_type(captured, db), + element::Element::Closure(element::Closure { + ref parameters, + signature, + result, + .. + }) => closure_type(parameters, signature, result, db), + element::Element::Module(element::Module { ref variables }) => module_type(variables, db), + } +} + +fn number_type(number: &element::Number) -> ty::Number { + match *number { + element::Number::U8(_) => ty::Number::U8, + element::Number::U16(_) => ty::Number::U16, + element::Number::U32(_) => ty::Number::U32, + element::Number::U64(_) => ty::Number::U64, + element::Number::I8(_) => ty::Number::I8, + element::Number::I16(_) => ty::Number::I16, + element::Number::I32(_) => ty::Number::I32, + element::Number::I64(_) => ty::Number::I64, + element::Number::F32(_) => ty::Number::F32, + element::Number::F64(_) => ty::Number::F64, + } +} + +fn tuple_type(fields: &[ir::Entity], db: &impl ty::Db) -> Result { + let fields = fields + .iter() + .map(|f| db.ty(*f)) + .collect::, ty::error::Error>>()?; + Ok(sync::Arc::new(ty::Type::Tuple(ty::Tuple { fields }))) +} + +fn record_type( + fields: &collections::HashMap, + db: &impl ty::Db, +) -> Result { + let fields = fields + .iter() + .map(|(k, v)| Ok((*k, db.ty(*v)?))) + .collect::, ty::error::Error>>()?; + Ok(sync::Arc::new(ty::Type::Record(ty::Record { fields }))) +} + +fn un_op_type( + operand: ir::Entity, + operator: element::UnOperator, + db: &impl ty::Db, +) -> Result { + let ty = db.ty(operand)?; + match operator { + element::UnOperator::Not => { + let bool_type = db.bool_ty(); + if ty == bool_type { + Ok(bool_type) + } else { + Err(ty::error::Error::Conflict(ty::error::Conflict { + expected: ty::error::ExpectedType::Specific(bool_type), + actual: ty, + main_entity: db.location(operand)?, + aux_entities: vec![], + })) + } + } + element::UnOperator::BNot => if_integral_then(operand, &ty, ty.clone(), db), + element::UnOperator::Cl0 + | element::UnOperator::Cl1 + | element::UnOperator::Cls + | element::UnOperator::Ct0 + | element::UnOperator::Ct1 + | element::UnOperator::C0 + | element::UnOperator::C1 => if_integral_then( + operand, + &ty, + sync::Arc::new(ty::Type::Number(ty::Number::U32)), + db, + ), + element::UnOperator::Sqrt => if_fractional_then(operand, &ty, ty.clone(), db), + } +} + +fn bi_op_type( + lhs: ir::Entity, + operator: element::BiOperator, + rhs: ir::Entity, + db: &impl ty::Db, +) -> Result { + // TODO: check scalar type semantics so e.g. records can't be divided. + let lhs_ty = db.ty(lhs)?; + let rhs_ty = db.ty(rhs)?; + match operator { + element::BiOperator::Eq + | element::BiOperator::Ne + | element::BiOperator::Lt + | element::BiOperator::Ge + | element::BiOperator::Gt + | element::BiOperator::Le => if_eq_then(lhs, &lhs_ty, rhs, &rhs_ty, &db.bool_ty(), db), + element::BiOperator::Cmp => unimplemented!(), + element::BiOperator::Add + | element::BiOperator::Sub + | element::BiOperator::Mul + | element::BiOperator::Div + | element::BiOperator::Rem + // TODO: don't allow floats + | element::BiOperator::BAnd + | element::BiOperator::BOr + | element::BiOperator::BXor + | element::BiOperator::BAndNot + | element::BiOperator::BOrNot + | element::BiOperator::BXorNot => if_eq_then(lhs, &lhs_ty, rhs, &rhs_ty, &lhs_ty, db), + element::BiOperator::Or => or_op(lhs, &lhs_ty, rhs, &rhs_ty, db), + element::BiOperator::And | element::BiOperator::Xor | element::BiOperator::AndNot | element::BiOperator::OrNot | element::BiOperator::XorNot => bool_op(lhs, &lhs_ty, rhs, &rhs_ty, db), + element::BiOperator::RotL | element::BiOperator::RotR | element::BiOperator::ShL | element::BiOperator::ShR => if_integral_and_eq_then( + lhs, + &lhs_ty, + rhs, + &rhs_ty, + &sync::Arc::new(ty::Type::Number(ty::Number::U32)), + lhs_ty.clone(), + db, + ), + } +} + +fn variable_type(initializer: ir::Entity, db: &impl ty::Db) -> Result { + db.ty(initializer) +} + +fn select_type(record: ir::Entity, field: ir::Ident, db: &impl ty::Db) -> Result { + let record_ty = db.ty(record)?; + match *record_ty { + ty::Type::Record(ty::Record { ref fields }) => { + if let Some(t) = fields.get(&field) { + Ok(t.clone()) + } else { + let mut expected_fields = collections::HashMap::new(); + expected_fields.insert(field.to_owned(), sync::Arc::new(ty::Type::Placeholder)); + Err(ty::error::Error::Conflict(ty::error::Conflict { + expected: ty::error::ExpectedType::Specific(sync::Arc::new(ty::Type::Record( + ty::Record { + fields: expected_fields, + }, + ))), + actual: record_ty.clone(), + main_entity: db.location(record)?, + aux_entities: vec![], + })) + } + } + _ => { + let mut expected_fields = collections::HashMap::new(); + expected_fields.insert(field.to_owned(), sync::Arc::new(ty::Type::Placeholder)); + Err(ty::error::Error::Conflict(ty::error::Conflict { + expected: ty::error::ExpectedType::Specific(sync::Arc::new(ty::Type::Record( + ty::Record { + fields: expected_fields, + }, + ))), + actual: record_ty, + main_entity: db.location(record)?, + aux_entities: vec![], + })) + } + } +} + +fn apply_type( + function: ir::Entity, + parameters: &[ir::Entity], + db: &impl ty::Db, +) -> Result { + let function_ty = db.ty(function)?; + match *function_ty { + ty::Type::Function(ty::Function { + parameters: ref formal_parameters, + ref result, + }) => { + let parameters = parameters + .iter() + .map(|p| db.ty(*p)) + .collect::, ty::error::Error>>()?; + + if parameters == *formal_parameters { + Ok(result.clone()) + } else { + // TODO: create a diff of expected and actual parameters + Err(ty::error::Error::Conflict(ty::error::Conflict { + expected: ty::error::ExpectedType::Specific(sync::Arc::new( + ty::Type::Function(ty::Function { + parameters, + result: sync::Arc::new(ty::Type::Placeholder), + }), + )), + actual: function_ty.clone(), + main_entity: db.location(function)?, + aux_entities: vec![], + })) + } + } + _ => Err(ty::error::Error::Conflict(ty::error::Conflict { + expected: ty::error::ExpectedType::Specific(sync::Arc::new(ty::Type::Function( + ty::Function { + parameters: vec![sync::Arc::new(ty::Type::Placeholder)], + result: sync::Arc::new(ty::Type::Placeholder), + }, + ))), + actual: function_ty, + main_entity: db.location(function)?, + aux_entities: vec![], + })), + } +} + +fn parameter_type(signature: ir::Entity, db: &impl ty::Db) -> Result { + db.ty(signature) +} + +fn capture_type(capture: ir::Entity, db: &impl ty::Db) -> Result { + db.ty(capture) +} + +fn closure_type( + parameters: &[ir::Entity], + signature: ir::Entity, + result: ir::Entity, + db: &impl ty::Db, +) -> Result { + let parameters = parameters + .iter() + .map(|p| db.ty(*p)) + .collect::, ty::error::Error>>()?; + let signature_ty = db.ty(signature)?; + let result = signature_ty.clone(); + + Ok(sync::Arc::new(ty::Type::Function(ty::Function { + parameters, + result, + }))) + // TODO: find a way to check result type + // let result_ty = db.ty(result)?; + // if signature_ty == result_ty { + // let result = signature_ty.clone(); + // Ok(sync::Arc::new(ty::Type::Function(ty::Function { + // parameters, + // result, + // }))) + // } else { + // Err(ty::error::Error::Conflict(ty::error::Conflict { + // expected: ty::error::ExpectedType::Specific(signature_ty.clone()), + // actual: result_ty.clone(), + // main_entity: db.location(result)?, + // aux_entities: vec![ty::error::AuxEntity { + // entity: db.location(signature)?, + // label: format!("declared return type is `{}`", signature_ty), + // }], + // })) + // } +} + +fn module_type( + variables: &collections::HashMap, + db: &impl ty::Db, +) -> Result { + let fields = variables + .iter() + .map(|(k, v)| Ok((*k, db.ty(*v)?))) + .collect::>()?; + Ok(sync::Arc::new(ty::Type::Record(ty::Record { fields }))) +} + +fn if_eq_then( + lhs_entity: ir::Entity, + lhs: &sync::Arc, + rhs_entity: ir::Entity, + rhs: &sync::Arc, + result: &sync::Arc, + db: &impl ty::Db, +) -> Result { + if lhs == rhs { + Ok(result.clone()) + } else { + Err(ty::error::Error::Conflict(ty::error::Conflict { + expected: ty::error::ExpectedType::Specific(lhs.clone()), + actual: rhs.clone(), + main_entity: db.location(rhs_entity)?, + aux_entities: vec![ty::error::AuxEntity { + entity: db.location(lhs_entity)?, + label: format!("other operand has type `{}`", lhs), + }], + })) + } +} + +fn bool_op( + lhs_entity: ir::Entity, + lhs: &sync::Arc, + rhs_entity: ir::Entity, + rhs: &sync::Arc, + db: &impl ty::Db, +) -> Result { + let bool_type = db.bool_ty(); + if *lhs == bool_type { + if *rhs == bool_type { + Ok(bool_type) + } else { + Err(ty::error::Error::Conflict(ty::error::Conflict { + expected: ty::error::ExpectedType::Specific(bool_type), + actual: rhs.clone(), + main_entity: db.location(rhs_entity)?, + aux_entities: vec![ty::error::AuxEntity { + entity: db.location(lhs_entity)?, + label: format!("other operand has type `{}`", lhs), + }], + })) + } + } else { + Err(ty::error::Error::Conflict(ty::error::Conflict { + expected: ty::error::ExpectedType::Specific(bool_type), + actual: lhs.clone(), + main_entity: db.location(lhs_entity)?, + aux_entities: vec![ty::error::AuxEntity { + entity: db.location(rhs_entity)?, + label: format!("other operand has type `{}`", rhs), + }], + })) + } +} + +fn or_op( + lhs_entity: ir::Entity, + lhs: &sync::Arc, + rhs_entity: ir::Entity, + rhs: &sync::Arc, + db: &impl ty::Db, +) -> Result { + let bool_type = db.bool_ty(); + if let ty::Type::Union(ref u) = **lhs { + if let ty::Type::Symbol(ref symbol) = **rhs { + Ok(sync::Arc::new(ty::Type::Union(u.clone().with(symbol)))) + } else { + Err(ty::error::Error::Conflict(ty::error::Conflict { + expected: ty::error::ExpectedType::ScalarClass(ty::class::Scalar::Symbol), + actual: rhs.clone(), + main_entity: db.location(rhs_entity)?, + aux_entities: vec![ty::error::AuxEntity { + entity: db.location(lhs_entity)?, + label: format!("other operand has type `{}`", lhs), + }], + })) + } + } else if *lhs == bool_type { + if *rhs == bool_type { + Ok(bool_type) + } else { + Err(ty::error::Error::Conflict(ty::error::Conflict { + expected: ty::error::ExpectedType::Specific(bool_type), + actual: rhs.clone(), + main_entity: db.location(rhs_entity)?, + aux_entities: vec![ty::error::AuxEntity { + entity: db.location(lhs_entity)?, + label: format!("other operand has type `{}`", lhs), + }], + })) + } + } else { + Err(ty::error::Error::Conflict(ty::error::Conflict { + expected: ty::error::ExpectedType::AnyOf(vec![ + ty::error::ExpectedType::Specific(bool_type), + ty::error::ExpectedType::Union, + ]), + actual: lhs.clone(), + main_entity: db.location(lhs_entity)?, + aux_entities: vec![ty::error::AuxEntity { + entity: db.location(rhs_entity)?, + label: format!("other operand has type `{}`", rhs), + }], + })) + } +} + +fn if_integral_then( + entity: ir::Entity, + ty: &sync::Arc, + result: sync::Arc, + db: &impl ty::Db, +) -> Result { + match ty.scalar_class() { + ty::class::Scalar::Integral(_) => Ok(result), + _ => Err(ty::error::Error::Conflict(ty::error::Conflict { + expected: ty::error::ExpectedType::ScalarClass(ty::class::Scalar::Integral( + ty::class::IntegralScalar::Any, + )), + actual: ty.clone(), + main_entity: db.location(entity)?, + aux_entities: vec![], + })), + } +} + +fn if_integral_and_eq_then( + lhs_entity: ir::Entity, + lhs: &sync::Arc, + rhs_entity: ir::Entity, + rhs: &sync::Arc, + expected: &sync::Arc, + result: sync::Arc, + db: &impl ty::Db, +) -> Result { + match lhs.scalar_class() { + ty::class::Scalar::Integral(_) => { + if rhs == expected { + Ok(result) + } else { + Err(ty::error::Error::Conflict(ty::error::Conflict { + expected: ty::error::ExpectedType::Specific(expected.clone()), + actual: rhs.clone(), + main_entity: db.location(rhs_entity)?, + aux_entities: vec![ty::error::AuxEntity { + entity: db.location(lhs_entity)?, + label: format!("other operand has type `{}`", lhs), + }], + })) + } + } + _ => Err(ty::error::Error::Conflict(ty::error::Conflict { + expected: ty::error::ExpectedType::ScalarClass(ty::class::Scalar::Integral( + ty::class::IntegralScalar::Any, + )), + actual: lhs.clone(), + main_entity: db.location(lhs_entity)?, + aux_entities: vec![ty::error::AuxEntity { + entity: db.location(rhs_entity)?, + label: format!("other operand has type `{}`", rhs), + }], + })), + } +} + +fn if_fractional_then( + entity: ir::Entity, + ty: &sync::Arc, + result: sync::Arc, + db: &impl ty::Db, +) -> Result { + match ty.scalar_class() { + ty::class::Scalar::Fractional => Ok(result), + _ => Err(ty::error::Error::Conflict(ty::error::Conflict { + expected: ty::error::ExpectedType::ScalarClass(ty::class::Scalar::Fractional), + actual: ty.clone(), + main_entity: db.location(entity)?, + aux_entities: vec![], + })), + } +} diff --git a/src/ir/component/ty/mod.rs b/src/ty/mod.rs similarity index 74% rename from src/ir/component/ty/mod.rs rename to src/ty/mod.rs index bc323da..17b6889 100644 --- a/src/ir/component/ty/mod.rs +++ b/src/ty/mod.rs @@ -1,14 +1,21 @@ use std::collections; use std::fmt; +use std::sync; -use specs::Component; -use specs::VecStorage; +use crate::ir; pub mod class; pub mod error; +pub mod infer; -#[derive(Component, Clone, Debug, Eq, PartialEq, VisitEntities, VisitEntitiesMut)] -#[storage(VecStorage)] +#[salsa::query_group(TyStorage)] +pub trait Db: salsa::Database + ir::Db { + fn ty(&self, entity: ir::Entity) -> error::Result>; + + fn bool_ty(&self) -> sync::Arc; +} + +#[derive(Clone, Debug, Eq, PartialEq)] pub enum Type { Number(Number), String, @@ -17,9 +24,10 @@ pub enum Type { Union(Union), Record(Record), Function(Function), + Placeholder, } -#[derive(Clone, Copy, Debug, Eq, PartialEq, VisitEntities, VisitEntitiesMut)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum Number { U8, U16, @@ -33,30 +41,30 @@ pub enum Number { F64, } -#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, VisitEntities, VisitEntitiesMut)] +#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] pub struct Symbol { - pub label: String, + pub label: ir::Ident, } -#[derive(Clone, Debug, Eq, PartialEq, VisitEntities, VisitEntitiesMut)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Tuple { - pub fields: Vec, + pub fields: Vec>, } -#[derive(Clone, Debug, Eq, PartialEq, VisitEntities, VisitEntitiesMut)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Union { pub alternatives: Vec, } -#[derive(Clone, Debug, Eq, PartialEq, VisitEntities, VisitEntitiesMut)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Record { - pub fields: collections::HashMap, + pub fields: collections::HashMap>, } -#[derive(Clone, Debug, Eq, PartialEq, VisitEntities, VisitEntitiesMut)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Function { - pub parameters: Vec, - pub result: Box, + pub parameters: Vec>, + pub result: sync::Arc, } impl Type { @@ -64,7 +72,7 @@ impl Type { match *self { Type::Number(ref n) => n.scalar_class(), Type::Symbol(_) => class::Scalar::Symbol, - Type::Union(_) | Type::Function(_) => class::Scalar::Undefined, + Type::Union(_) | Type::Function(_) | Type::Placeholder => class::Scalar::Undefined, Type::String | Type::Tuple(_) | Type::Record(_) => class::Scalar::Complex, } } @@ -105,6 +113,7 @@ impl fmt::Display for Type { Type::Union(ref union) => union.fmt(f), Type::Record(ref record) => record.fmt(f), Type::Function(ref function) => function.fmt(f), + Type::Placeholder => write!(f, "???"), } } } @@ -128,7 +137,7 @@ impl fmt::Display for Number { impl fmt::Display for Symbol { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, ":{}", self.label) + write!(f, ":{:?}", self.label) } } @@ -170,7 +179,7 @@ impl fmt::Display for Record { if needs_sep { write!(f, ", ")?; } - write!(f, "{}: ", id)?; + write!(f, "{:?}: ", id)?; ty.fmt(f)?; needs_sep = true; } @@ -195,3 +204,20 @@ impl fmt::Display for Function { Ok(()) } } + +fn ty(db: &impl Db, entity: ir::Entity) -> error::Result> { + let element = db.element(entity)?; + infer::element_type(&*element, db) +} + +fn bool_ty(db: &impl Db) -> sync::Arc { + let alternatives = vec![ + Symbol { + label: db.ident(sync::Arc::new("f".to_owned())), + }, + Symbol { + label: db.ident(sync::Arc::new("t".to_owned())), + }, + ]; + sync::Arc::new(Type::Union(Union { alternatives })) +} diff --git a/src/value.rs b/src/value.rs index a9355ab..77604a8 100644 --- a/src/value.rs +++ b/src/value.rs @@ -2,43 +2,43 @@ use std::cmp; use std::collections; use std::sync; -lazy_static! { +lazy_static::lazy_static! { pub static ref NIL: Value = { Value::new(Case::Symbol(Symbol { - label: "nil".to_owned(), + label: sync::Arc::new("nil".to_owned()), })) }; pub static ref FALSE: Value = { Value::new(Case::Symbol(Symbol { - label: "f".to_owned(), + label: sync::Arc::new("f".to_owned()), })) }; pub static ref TRUE: Value = { Value::new(Case::Symbol(Symbol { - label: "t".to_owned(), + label: sync::Arc::new("t".to_owned()), })) }; pub static ref LT: Value = { Value::new(Case::Symbol(Symbol { - label: "lt".to_owned(), + label: sync::Arc::new("lt".to_owned()), })) }; pub static ref EQ: Value = { Value::new(Case::Symbol(Symbol { - label: "eq".to_owned(), + label: sync::Arc::new("eq".to_owned()), })) }; pub static ref GT: Value = { Value::new(Case::Symbol(Symbol { - label: "gt".to_owned(), + label: sync::Arc::new("gt".to_owned()), })) }; } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Value(sync::Arc); -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub enum Case { Number(Number), String(String), @@ -47,7 +47,7 @@ pub enum Case { Record(Record), } -#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd)] pub enum Number { U8(u8), U16(u16), @@ -57,23 +57,23 @@ pub enum Number { I16(i16), I32(i32), I64(i64), - F32(f32), - F64(f64), + F32(ordered_float::OrderedFloat), + F64(ordered_float::OrderedFloat), } #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] pub struct Symbol { - pub label: String, + pub label: sync::Arc, } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Tuple { pub fields: Vec, } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Record { - pub fields: collections::HashMap, + pub fields: collections::HashMap, Value>, } impl Value { @@ -92,11 +92,7 @@ impl Value { Value(sync::Arc::new(Case::String(string.into()))) } - pub fn symbol(label: S) -> Self - where - S: Into, - { - let label = label.into(); + pub fn symbol(label: sync::Arc) -> Self { Value::new(Case::Symbol(Symbol { label })) } @@ -173,13 +169,13 @@ impl From for Value { impl From for Value { fn from(v: f32) -> Self { - Value::new(Case::Number(Number::F32(v))) + Value::new(Case::Number(Number::F32(ordered_float::OrderedFloat(v)))) } } impl From for Value { fn from(v: f64) -> Self { - Value::new(Case::Number(Number::F64(v))) + Value::new(Case::Number(Number::F64(ordered_float::OrderedFloat(v)))) } } diff --git a/syntax/Cargo.toml b/syntax/Cargo.toml new file mode 100644 index 0000000..798fc32 --- /dev/null +++ b/syntax/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "tin-syntax" +version = "0.1.0" +authors = ["David Flemström "] +edition = "2018" + +[dependencies] +enum-primitive-derive = "0.1.2" +rowan = "0.5.0" +num-traits = "0.2.6" diff --git a/syntax/src/ast.rs b/syntax/src/ast.rs new file mode 100644 index 0000000..d1e471e --- /dev/null +++ b/syntax/src/ast.rs @@ -0,0 +1,57 @@ +use crate::kind; + +pub trait Node: rowan::TransparentNewType { + fn from_rowan(node: &rowan::SyntaxNode) -> Option<&Self>; + + fn to_owned(&self) -> rowan::TreeArc; +} + +macro_rules! ast_node { + ($ast:ident) => { ast_node!($ast, $ast); }; + ($ast:ident, $kind:ident) => { + #[derive(Debug, Eq, Hash, PartialEq)] + #[repr(transparent)] + pub struct $ast(rowan::SyntaxNode); + + unsafe impl rowan::TransparentNewType for $ast { + type Repr = rowan::SyntaxNode; + } + + impl Node for $ast { + fn from_rowan(node: &rowan::SyntaxNode) -> Option<&Self> { + use rowan::TransparentNewType; + + if node.kind() == kind::Kind::$kind.to_rowan_kind() { + Some(Self::from_repr(node)) + } else { + None + } + } + + fn to_owned(&self) -> rowan::TreeArc { + rowan::TreeArc::cast(self.0.to_owned()) + } + } + + impl kind::HasKind for $ast { + fn kind(&self) -> kind::Kind { + kind::Kind::$kind + } + } + }; +} + +ast_node!(Reference); +ast_node!(Module); +ast_node!(Expression); +ast_node!(Statement); +ast_node!(Number); +ast_node!(String); +ast_node!(Symbol); +ast_node!(Tuple); +ast_node!(Record); +ast_node!(UnOp); +ast_node!(BiOp); +ast_node!(Lambda); +ast_node!(Parameter); +ast_node!(Apply); diff --git a/syntax/src/error.rs b/syntax/src/error.rs new file mode 100644 index 0000000..12fcaf2 --- /dev/null +++ b/syntax/src/error.rs @@ -0,0 +1 @@ +pub enum Error {} diff --git a/syntax/src/kind.rs b/syntax/src/kind.rs new file mode 100644 index 0000000..6d5d927 --- /dev/null +++ b/syntax/src/kind.rs @@ -0,0 +1,75 @@ +use enum_primitive_derive::Primitive; + +#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Primitive)] +pub enum Kind { + // The discriminants in this enum are not stable and can change between releases without notice + + Error = 0, + Whitespace = 1, + + // Simple tokens + Semi = 2, + Comma = 3, + ParenOpen = 4, + ParenClose = 5, + CurlyOpen = 6, + CurlyClose = 7, + BracketOpen = 8, + BracketClose = 9, + AngleOpen = 10, + AngleClose = 11, + Arrow = 12, + Dot = 13, + Colon = 14, + Is = 15, + + // Operator tokens + Add = 16, + Sub = 17, + Mul = 18, + Div = 19, + + // Complex tokens + Comment = 20, + Identifier = 21, + SymbolLiteral = 22, + StringLiteral = 23, + UnsignedIntLiteral = 24, + SignedIntLiteral = 25, + FloatLiteral = 26, + + // Nodes + Reference = 27, + Module = 28, + Variable = 29, + Expression = 30, + Statement = 31, + Number = 32, + String = 33, + Symbol = 34, + Tuple = 35, + Record = 36, + UnOp = 37, + BiOp = 38, + Lambda = 39, + Parameter = 40, + Apply = 41, +} + +pub trait HasKind { + fn kind(&self) -> Kind; +} + +impl Kind { + pub fn to_rowan_kind(self) -> rowan::SyntaxKind { + use num_traits::cast::ToPrimitive; + + rowan::SyntaxKind(self.to_u16().unwrap()) + } + + pub fn from_rowan_kind(syntax_kind: rowan::SyntaxKind) -> Option { + use num_traits::cast::FromPrimitive; + + Self::from_u16(syntax_kind.0) + } +} diff --git a/syntax/src/lib.rs b/syntax/src/lib.rs new file mode 100644 index 0000000..9a9f9ca --- /dev/null +++ b/syntax/src/lib.rs @@ -0,0 +1,9 @@ +mod ast; +mod error; +mod kind; +mod parser; +mod token; + +fn parse_module(text: &str) -> rowan::TreeArc { + unimplemented!() +} diff --git a/syntax/src/parser.rs b/syntax/src/parser.rs new file mode 100644 index 0000000..4a6ef82 --- /dev/null +++ b/syntax/src/parser.rs @@ -0,0 +1,86 @@ +use std::iter; +use std::result; +use crate::ast; +use crate::error; +use crate::kind; +use crate::token; + +pub struct Parser where I: Iterator { + tokens: iter::Peekable, + builder: rowan::GreenNodeBuilder, + errors: Vec, +} + +pub enum Error { + Expected(kind::Kind), +} + +impl Parser where I: Iterator { + fn into_module(mut self) -> rowan::TreeArc { + use crate::ast::Node; + + self.module(); + + let green = self.builder.finish(); + let node = rowan::SyntaxNode::new(green, None); + ast::Module::from_rowan(&node).unwrap().to_owned() + } + + fn module(&mut self) { + self.builder.start_node(kind::Kind::Module.to_rowan_kind()); + + while self.tokens.peek().is_some() { + self.variable(); + } + + self.builder.finish_node(); + } + + fn variable(&mut self) { + self.builder.start_node(kind::Kind::Variable.to_rowan_kind()); + self.identifier(); + self.expect_kind(kind::Kind::Is); + self.skip_ws(); + + self.builder.finish_node(); + } + + fn identifier(&mut self) { + if self.expect_kind(kind::Kind::Identifier) { + self.builder.start_node(kind::Kind::Identifier.to_rowan_kind()); + self.bump(); + self.builder.finish_node(); + } + } + + fn expect_kind(&mut self, kind: kind::Kind) -> bool { + if self.peek_kind() == Some(kind::Kind::Identifier) { + true + } else { + self.error(Error::Expected(kind::Kind::Identifier)); + self.bump(); + false + } + } + + fn error(&mut self, error: Error) {} + + fn bump(&mut self) { + let token = self.tokens.next().unwrap(); + self.builder.token(token.kind.to_rowan_kind(), token.contents); + } + + fn peek(&mut self) -> Option<&token::Token> { + self.tokens.peek() + } + + fn peek_kind(&mut self) -> Option { + self.peek().map(|t| t.kind) + } + + fn skip_ws(&mut self) { + while self.peek_kind() == Some(kind::Kind::Whitespace) { + self.bump(); + } + } +} diff --git a/syntax/src/token.rs b/syntax/src/token.rs new file mode 100644 index 0000000..1f43736 --- /dev/null +++ b/syntax/src/token.rs @@ -0,0 +1,6 @@ +use crate::kind; + +pub struct Token { + pub kind: kind::Kind, + pub contents: rowan::SmolStr +} diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index d4f9acd..e0681f4 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -35,7 +35,7 @@ fn test_ok(path: &str) -> Result<(), failure::Error> { let main = module .unwrap() - .function::>("main") + .function::, _>("TODO", "main") .unwrap(); assert_eq!(Ok(0), main.call()); @@ -68,7 +68,7 @@ fn test_err(path: &str, err: &str) -> Result<(), failure::Error> { .map_err(|e| report_diagnostics(tin.codemap(), e, &mut err_actual)) { let _ = module - .function::>("main") + .function::, _>("TODO", "main") .unwrap() .call() .map_err(|e| report_error(e, &mut err_actual));