Remove shared libraries from the IDE repo (https://github.com/enso-org/ide/pull/626)

1.  Removes `prelude`, and renames it to `enso-prelude`.
2.  Removes `shapely`, and renames it to `enso-shapely`.
3.  Removes `macro-utils` and renames it to `enso-macro-utils`.

Original commit: a5069c1ae5
This commit is contained in:
Ara Adkins 2020-07-01 16:26:24 +01:00 committed by GitHub
parent 0df765dcd5
commit 566a318a91
73 changed files with 166 additions and 4366 deletions

1
gui/.gitignore vendored
View File

@ -19,3 +19,4 @@ wasm-pack.log
# JavaScript
node_modules
.nvmrc

142
gui/src/rust/Cargo.lock generated
View File

@ -47,13 +47,13 @@ dependencies = [
"ast-macros 0.1.0",
"data 0.1.0",
"derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
"enso-prelude 0.1.0",
"enso-prelude 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"enso-shapely 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.51 (registry+https://github.com/rust-lang/crates.io-index)",
"shapely 0.1.0",
"shrinkwraprs 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"utils 0.1.0",
"uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -64,8 +64,8 @@ name = "ast-macros"
version = "0.1.0"
dependencies = [
"Inflector 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)",
"enso-prelude 0.1.0",
"macro-utils 0.1.0",
"enso-macro-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"enso-prelude 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
@ -308,7 +308,7 @@ dependencies = [
name = "code-builder"
version = "0.1.0"
dependencies = [
"enso-prelude 0.1.0",
"enso-prelude 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -439,7 +439,7 @@ dependencies = [
name = "data"
version = "0.1.0"
dependencies = [
"enso-prelude 0.1.0",
"enso-prelude 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -547,7 +547,7 @@ dependencies = [
name = "enso-callback"
version = "0.1.0"
dependencies = [
"enso-prelude 0.1.0",
"enso-prelude 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -556,7 +556,7 @@ version = "0.1.0"
dependencies = [
"enso-callback 0.1.0",
"enso-generics 0.1.0",
"enso-prelude 0.1.0",
"enso-prelude 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ensogl-system-web 0.1.0",
"keyboard-types 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"nalgebra 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -570,6 +570,16 @@ dependencies = [
"nalgebra 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "enso-macro-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "enso-math"
version = "0.1.0"
@ -582,11 +592,13 @@ dependencies = [
[[package]]
name = "enso-prelude"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"boolinator 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"derivative 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"derive_more 0.99.5 (registry+https://github.com/rust-lang/crates.io-index)",
"enclose 1.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"enso-shapely 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"ifmt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -594,7 +606,6 @@ dependencies = [
"nalgebra 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"paste 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"shapely 0.1.0",
"shrinkwraprs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
@ -609,7 +620,8 @@ dependencies = [
"bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"data 0.1.0",
"enso-prelude 0.1.0",
"enso-prelude 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"enso-shapely 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ensogl-build-utilities 0.1.0",
"ensogl-system-web 0.1.0",
"failure 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
@ -624,7 +636,6 @@ dependencies = [
"serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.51 (registry+https://github.com/rust-lang/crates.io-index)",
"sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"shapely 0.1.0",
"tokio 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
"utils 0.1.0",
"uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -633,6 +644,31 @@ dependencies = [
"zip-extensions 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "enso-shapely"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"derivative 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"enso-shapely-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"paste 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"shrinkwraprs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "enso-shapely-macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"Inflector 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)",
"boolinator 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"enso-macro-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ensogl"
version = "0.1.0"
@ -647,7 +683,8 @@ dependencies = [
"enso-frp 0.1.0",
"enso-generics 0.1.0",
"enso-math 0.1.0",
"enso-prelude 0.1.0",
"enso-prelude 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"enso-shapely 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ensogl-core-embedded-fonts 0.1.0",
"ensogl-core-msdf-sys 0.1.0",
"ensogl-system-web 0.1.0",
@ -663,7 +700,6 @@ dependencies = [
"optics 0.1.0",
"paste 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"shapely 0.1.0",
"shrinkwraprs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -685,7 +721,7 @@ dependencies = [
name = "ensogl-core-embedded-fonts"
version = "0.1.0"
dependencies = [
"enso-prelude 0.1.0",
"enso-prelude 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ensogl-build-utilities 0.1.0",
"zip 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -694,7 +730,7 @@ dependencies = [
name = "ensogl-core-msdf-sys"
version = "0.1.0"
dependencies = [
"enso-prelude 0.1.0",
"enso-prelude 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ensogl-build-utilities 0.1.0",
"ensogl-core-embedded-fonts 0.1.0",
"futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -711,7 +747,7 @@ dependencies = [
"async-std 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"console_error_panic_hook 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"data 0.1.0",
"enso-prelude 0.1.0",
"enso-prelude 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"gloo-timers 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"js-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
@ -795,13 +831,6 @@ dependencies = [
"miniz_oxide 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "flexer"
version = "0.1.0"
dependencies = [
"itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "flo_stream"
version = "0.4.0"
@ -1011,14 +1040,14 @@ version = "0.1.0"
dependencies = [
"ast 0.1.0",
"enso-frp 0.1.0",
"enso-prelude 0.1.0",
"enso-prelude 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"enso-shapely 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ensogl 0.1.0",
"js-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
"logger 0.1.0",
"nalgebra 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.51 (registry+https://github.com/rust-lang/crates.io-index)",
"shapely 0.1.0",
"span-tree 0.1.0",
"wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
"web-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1030,7 +1059,8 @@ version = "0.1.0"
dependencies = [
"ast 0.1.0",
"enso-frp 0.1.0",
"enso-prelude 0.1.0",
"enso-prelude 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"enso-shapely 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ensogl 0.1.0",
"ensogl-core-msdf-sys 0.1.0",
"ensogl-system-web 0.1.0",
@ -1040,7 +1070,6 @@ dependencies = [
"js-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
"nalgebra 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.51 (registry+https://github.com/rust-lang/crates.io-index)",
"shapely 0.1.0",
"span-tree 0.1.0",
"wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
"web-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1251,8 +1280,9 @@ dependencies = [
"data 0.1.0",
"enso-callback 0.1.0",
"enso-frp 0.1.0",
"enso-prelude 0.1.0",
"enso-prelude 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"enso-protocol 0.1.0",
"enso-shapely 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ensogl 0.1.0",
"ensogl-core-msdf-sys 0.1.0",
"ensogl-system-web 0.1.0",
@ -1268,7 +1298,6 @@ dependencies = [
"regex 1.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.51 (registry+https://github.com/rust-lang/crates.io-index)",
"shapely 0.1.0",
"span-tree 0.1.0",
"utils 0.1.0",
"uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1386,13 +1415,13 @@ dependencies = [
name = "json-rpc"
version = "0.1.0"
dependencies = [
"enso-prelude 0.1.0",
"enso-prelude 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"enso-shapely 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ensogl-system-web 0.1.0",
"failure 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.51 (registry+https://github.com/rust-lang/crates.io-index)",
"shapely 0.1.0",
"shrinkwraprs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"utils 0.1.0",
]
@ -1477,21 +1506,12 @@ dependencies = [
name = "logger"
version = "0.1.0"
dependencies = [
"enso-prelude 0.1.0",
"shapely 0.1.0",
"enso-prelude 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"enso-shapely 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
"web-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "macro-utils"
version = "0.1.0"
dependencies = [
"proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "matches"
version = "0.1.8"
@ -1830,7 +1850,7 @@ dependencies = [
name = "optics"
version = "0.1.0"
dependencies = [
"enso-prelude 0.1.0",
"enso-prelude 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -1887,7 +1907,7 @@ dependencies = [
"bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
"console_error_panic_hook 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"data 0.1.0",
"enso-prelude 0.1.0",
"enso-prelude 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ensogl-build-utilities 0.1.0",
"failure 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2477,30 +2497,6 @@ dependencies = [
"opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "shapely"
version = "0.1.0"
dependencies = [
"derivative 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"enso-prelude 0.1.0",
"paste 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"shapely-macros 0.1.0",
"shrinkwraprs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "shapely-macros"
version = "0.1.0"
dependencies = [
"Inflector 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)",
"boolinator 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"macro-utils 0.1.0",
"proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "shrinkwraprs"
version = "0.2.3"
@ -2574,7 +2570,7 @@ version = "0.1.0"
dependencies = [
"ast 0.1.0",
"data 0.1.0",
"enso-prelude 0.1.0",
"enso-prelude 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"parser 0.1.0",
"utils 0.1.0",
@ -2973,7 +2969,7 @@ dependencies = [
name = "utils"
version = "0.1.0"
dependencies = [
"enso-prelude 0.1.0",
"enso-prelude 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"pin-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3156,7 +3152,7 @@ dependencies = [
name = "web-test"
version = "0.1.0"
dependencies = [
"enso-prelude 0.1.0",
"enso-prelude 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ensogl 0.1.0",
"ensogl-system-web 0.1.0",
"js-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3335,6 +3331,10 @@ dependencies = [
"checksum enclose 1.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1056f553da426e9c025a662efa48b52e62e0a3a7648aa2d15aeaaf7f0d329357"
"checksum encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
"checksum encoding_rs 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8d03faa7fe0c1431609dfad7bbe827af30f82e1e2ae6f7ee4fca6bd764bc28"
"checksum enso-macro-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "87d75170551105f0c13e78f403f38173e428f04b921228deabb53367bb968dfa"
"checksum enso-prelude 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "663f055d5fa5e359d81069ff69d31a74da59086d0fa8ec7ef933bb9fdf0a07e2"
"checksum enso-shapely 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a1741af8785f986ba930c9dc052c1a7bc6c223b573801e33667467615dddf09b"
"checksum enso-shapely-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddab3b8e1a9a16e57fe49e25afbbe2e3215208ab040831bc004d78208227ca14"
"checksum enum_dispatch 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "733967190e01b0dcb64f2f42687a78af0e418e064489e993e16445643d088560"
"checksum error-chain 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d371106cc88ffdfb1eabd7111e432da544f16f3e2d7bf1dfe8bf575f1df045cd"
"checksum failure 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86"

View File

@ -20,16 +20,11 @@ members = [
"lib/debug-scenes",
"lib/graph-editor",
"lib/eval-tt",
"lib/flexer",
"lib/frp",
"lib/generics",
"lib/logger",
"lib/macro-utils",
"lib/math",
"lib/optics",
"lib/prelude",
"lib/shapely/impl",
"lib/shapely/macros",
"lib/system/web",
]

View File

@ -17,7 +17,7 @@ enso-callback = { version = "0.1.0" , path = "../lib/callback"
ensogl-core-embedded-fonts = { version = "0.1.0" , path = "embedded-fonts" }
ensogl-core-msdf-sys = { version = "0.1.0" , path = "msdf-sys" }
enso-generics = { version = "0.1.0" , path = "../lib/generics" }
enso-prelude = { version = "0.1.0" , path = "../lib/prelude" }
enso-prelude = { version = "0.1.0" }
ensogl-system-web = { version = "0.1.0" , path = "../lib/system/web" }
code-builder = { version = "0.1.0" , path = "../lib/code-builder" }
data = { version = "0.1.0" , path = "../lib/data" }
@ -26,7 +26,7 @@ enso-math = { version = "0.1.0" , path = "../lib/math"
eval-tt = { version = "0.1.0" , path = "../lib/eval-tt" }
logger = { version = "0.1.0" , path = "../lib/logger" }
optics = { version = "0.1.0" , path = "../lib/optics" }
shapely = { version = "0.1.0" , path = "../lib/shapely/impl" }
enso-shapely = { version = "0.1.0" }
bit_field = { version = "0.10.0" }
console_error_panic_hook = { version = "0.1.6" }

View File

@ -10,7 +10,7 @@ crate-type = ["cdylib", "rlib"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
enso-prelude = { version = "0.1.0", path="../../lib/prelude"}
enso-prelude = { version = "0.1.0" }
[build-dependencies]
ensogl-build-utilities = { version = "0.1.0", path = "../../build" }

View File

@ -11,7 +11,7 @@ crate-type = ["cdylib", "rlib"]
wasm-bindgen = { version = "=0.2.58" }
js-sys = { version = "0.3.30" }
nalgebra = { version = "0.21.1" }
enso-prelude = { version = "0.1.0", path="../../lib/prelude" }
enso-prelude = { version = "0.1.0" }
[dev-dependencies]
wasm-bindgen-test = { version = "0.3.8" }

View File

@ -49,7 +49,7 @@ macro_rules! define_color_space {
}
impl HasComponentsRepr for $data_name{
type ComponentsRepr = ($(shapely::replace!($comp,f32)),*,);
type ComponentsRepr = ($(enso_shapely::replace!($comp,f32)),*,);
}
impl From<$data_name> for ComponentsOf<$data_name> {

View File

@ -10,7 +10,7 @@ use crate::system::gpu::shader::Context;
use num_enum::IntoPrimitive;
use shapely::shared;
use enso_shapely::shared;

View File

@ -18,7 +18,7 @@ use crate::control::callback::CallbackFn;
use web_sys::WebGlProgram;
use shapely::shared;
use enso_shapely::shared;

View File

@ -67,9 +67,9 @@ pub mod prelude {
pub use logger::*;
pub use logger::AnyLogger;
pub use logger::disabled::Logger;
pub use shapely::CloneRef;
pub use shapely::newtype_copy;
pub use shapely::shared;
pub use enso_shapely::CloneRef;
pub use enso_shapely::newtype_copy;
pub use enso_shapely::shared;
pub use super::display::traits::*;
pub use super::data::container::AddMut;
pub use super::math::types::*;

View File

@ -26,7 +26,7 @@ use nalgebra::Matrix4;
use nalgebra::Vector2;
use nalgebra::Vector3;
use nalgebra::Vector4;
use shapely::shared;
use enso_shapely::shared;
use std::iter::Extend;
use std::ops::RangeInclusive;
use web_sys::WebGlBuffer;

View File

@ -65,7 +65,7 @@ pub mod traits {
#[macro_export]
macro_rules! define_singletons_gl {
( $target:tt $( $(#$meta:tt)* $name:ident = $expr:expr ),* $(,)? ) => {
shapely::define_singletons!{ $( $(#$meta)* $name),* }
enso_shapely::define_singletons!{ $( $(#$meta)* $name),* }
$crate::define_gl_enum_conversions!{ $target $( $(#$meta)* $name = $expr ),* }
}
}
@ -127,7 +127,7 @@ macro_rules! define_singleton_enum_gl_from {
$( $(#$field_meta:tt)* $field:ident),* $(,)?
}
) => {
shapely::define_singleton_enum_from! { $(#$meta)* $name {$($(#$field_meta)* $field),*}}
enso_shapely::define_singleton_enum_from! { $(#$meta)* $name {$($(#$field_meta)* $field),*}}
impl From<&$name> for $($target)* {
fn from(t:&$name) -> Self {

View File

@ -28,6 +28,6 @@ pub trait StorageRelation<InternalFormat,ElemType>: Storage {
type Storage: Debug;
}
shapely::define_singleton_enum! {
enso_shapely::define_singleton_enum! {
AnyStorage {RemoteImage,GpuOnly,Owned}
}

View File

@ -5,7 +5,7 @@ pub mod upload;
use crate::prelude::*;
use enum_dispatch::*;
use shapely::shared;
use enso_shapely::shared;
use upload::UniformUpload;
use web_sys::WebGlUniformLocation;

View File

@ -11,7 +11,7 @@ use crate::math::topology::unit::*;
use code_builder::CodeBuilder;
use code_builder::HasCodeRepr;
use shapely::derive_clone_plus;
use enso_shapely::derive_clone_plus;

View File

@ -14,10 +14,10 @@ ensogl-core-msdf-sys = { version = "0.1.0" , path = "../ensogl/msdf-sys"
ensogl-system-web = { version = "0.1.0" , path = "../lib/system/web" }
data = { version = "0.1.0" , path = "../lib/data" }
enso-frp = { version = "0.1.0" , path = "../lib/frp" }
enso-prelude = { version = "0.1.0" , path = "../lib/prelude" }
enso-prelude = { version = "0.1.0" }
graph-editor = { version = "0.1.0" , path = "../lib/graph-editor" }
logger = { version = "0.1.0" , path = "../lib/logger" }
shapely = { version = "0.1.0" , path = "../lib/shapely/impl" }
enso-shapely = { version = "0.1.0" }
ast = { version = "0.1.0" , path = "ast/impl" }
enso-protocol = { version = "0.1.0" , path = "enso-protocol" }

View File

@ -19,6 +19,6 @@ uuid = { version = "0.8.1", features = ["serde","v4","wasm-bindgen"] }
ast-macros = { version = "0.1.0", path = "../macros" }
data = { version = "0.1.0", path = "../../../lib/data" }
enso-prelude = { version = "0.1.0", path = "../../../lib/prelude" }
shapely = { version = "0.1.0", path = "../../../lib/shapely/impl" }
enso-prelude = { version = "0.1.0" }
enso-shapely = { version = "0.1.0" }
utils = { version = "0.1.0", path = "../../utils" }

View File

@ -13,5 +13,5 @@ pub fn iterate_subtree<T>(ast:T) -> impl Iterator<Item=T::Item>
}
};
shapely::GeneratingIterator(generator)
enso_shapely::GeneratingIterator(generator)
}

View File

@ -52,7 +52,7 @@ use serde::Deserialize;
use serde::ser::Serializer;
use serde::ser::SerializeStruct;
use serde::Serialize;
use shapely::*;
use enso_shapely::*;
use uuid::Uuid;
/// A sequence of AST nodes, typically the "token soup".

View File

@ -15,8 +15,8 @@ proc-macro2 = "1.0"
quote = "1.0"
Inflector = "0.11.4"
macro-utils = { version = "0.1.0" , path = "../../../lib/macro-utils" }
enso-prelude = { version = "0.1.0" , path = "../../../lib/prelude" }
enso-macro-utils = { version = "0.1.0" }
enso-prelude = { version = "0.1.0" }
[dependencies.syn]
version = "1.0"

View File

@ -10,8 +10,8 @@ use crate::prelude::*;
use crate::token::TokenDescription;
use enso_prelude as prelude;
use macro_utils::gather_all_type_reprs;
use macro_utils::repr;
use enso_macro_utils::gather_all_type_reprs;
use enso_macro_utils::repr;
use proc_macro2::TokenStream;
use proc_macro2::Ident;
use proc_macro2::Span;

View File

@ -1,6 +1,6 @@
use crate::prelude::*;
use macro_utils::path_segment_generic_args;
use enso_macro_utils::path_segment_generic_args;
use proc_macro2::TokenStream;
use quote::quote;
use syn::Expr;

View File

@ -10,8 +10,8 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
data = { version = "0.1.0" , path = "../../lib/data" }
json-rpc = { version = "0.1.0" , path = "../json-rpc" }
enso-prelude = { version = "0.1.0" , path = "../../lib/prelude" }
shapely = { version = "0.1.0" , path = "../../lib/shapely/impl" }
enso-prelude = { version = "0.1.0" }
enso-shapely = { version = "0.1.0" }
logger = { version = "0.1.0" , path = "../../lib/logger" }
utils = { version = "0.1.0" , path = "../utils" }

View File

@ -8,13 +8,13 @@ edition = "2018"
crate-type = ["cdylib", "rlib"]
[dependencies]
enso-prelude = { version = "0.1.0" , path = "../../lib/prelude" }
enso-prelude = { version = "0.1.0" }
ensogl-system-web = { version = "0.1.0" , path = "../../lib/system/web" }
futures = { version = "0.3.1" }
failure = { version = "0.1.6" }
serde = { version = "1.0.0" , features = ["derive"] }
serde_json = { version = "1.0.0" }
shapely = { version = "0.1.0" , path = "../../lib/shapely/impl" }
enso-shapely = { version = "0.1.0" }
shrinkwraprs = { version = "0.3.0" }
utils = { version = "0.1.0" , path = "../utils" }

View File

@ -132,7 +132,7 @@ pub type OngoingCalls = HashMap<Id,oneshot::Sender<ReplyMessage>>;
/// `DeserializeOwned` and deserialize from JSON maps with `method` and `params`
/// fields.
pub use shapely::shared;
pub use enso_shapely::shared;
shared! { Handler

View File

@ -11,7 +11,7 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
ast = { version = "0.1.0", path = "../ast/impl" }
data = { version = "0.1.0", path = "../../lib/data" }
enso-prelude = { version = "0.1.0", path = "../../lib/prelude" }
enso-prelude = { version = "0.1.0" }
utils = { version = "0.1.0", path = "../utils" }
console_error_panic_hook = { version = "0.1.6" }

View File

@ -7,7 +7,7 @@ edition = "2018"
[dependencies]
ast = { version = "0.1.0", path = "../ast/impl" }
data = { version = "0.1.0", path = "../../lib/data" }
enso-prelude = { version = "0.1.0", path = "../../lib/prelude" }
enso-prelude = { version = "0.1.0" }
utils = { version = "0.1.0", path = "../utils" }
failure = { version = "0.1.6" }

View File

@ -43,6 +43,7 @@ pub mod prelude {
pub use utils::fail::FallibleResult;
}
use traits::*;
use prelude::*;

View File

@ -17,7 +17,7 @@ use ensogl::system::web;
use enso_frp::io::keyboard::Keyboard;
use enso_frp::io::keyboard;
use nalgebra::Vector2;
use shapely::shared;
use enso_shapely::shared;

View File

@ -8,7 +8,7 @@ edition = "2018"
crate-type = ["cdylib", "rlib"]
[dependencies]
enso-prelude = { version = "0.1.0" , path = "../../lib/prelude" }
enso-prelude = { version = "0.1.0" }
failure = "0.1.5"
futures = "0.3.1"

View File

@ -7,4 +7,4 @@ edition = "2018"
[lib]
[dependencies]
enso-prelude = { version = "0.1.0" , path = "../prelude" }
enso-prelude = { version = "0.1.0" }

View File

@ -9,4 +9,4 @@ edition = "2018"
[features]
[dependencies]
enso-prelude = { version = "0.1.0", path = "../prelude" }
enso-prelude = { version = "0.1.0" }

View File

@ -8,6 +8,6 @@ edition = "2018"
crate-type = ["rlib", "cdylib"]
[dependencies]
enso-prelude = { version = "0.1.0" , path = "../prelude" }
enso-prelude = { version = "0.1.0" }
serde = { version = "1.0" , features = ["derive"] }

View File

@ -8,7 +8,7 @@ edition = "2018"
crate-type = ["cdylib"]
[dependencies]
shapely = { version = "0.1.0" , path = "../shapely/impl" }
enso-shapely = { version = "0.1.0" }
ensogl = { version = "0.1.0" , path = "../../ensogl" }
ensogl-core-msdf-sys = { version = "0.1.0" , path = "../../ensogl/msdf-sys" }
ensogl-system-web = { version = "0.1.0" , path = "../system/web" }
@ -18,7 +18,7 @@ ide = { version = "0.1.0" , path = "../../ide" }
span-tree = { version = "0.1.0" , path = "../../ide/span-tree" }
ast = { version = "0.1.0" , path = "../../ide/ast/impl" }
enso-prelude = { version = "0.1.0" , path = "../prelude" }
enso-prelude = { version = "0.1.0" }
js-sys = { version = "0.3.28" }
nalgebra = { version = "0.21.1" }

View File

@ -9,7 +9,7 @@ edition = "2018"
[dependencies]
enso-callback = { version = "0.1.0" , path = "../callback" }
enso-generics = { version = "0.1.0" , path = "../generics" }
enso-prelude = { version = "0.1.0" , path = "../prelude" }
enso-prelude = { version = "0.1.0" }
ensogl-system-web = { version = "0.1.0" , path = "../system/web" }
keyboard-types = { version = "0.5.0" }
nalgebra = { version = "0.21.1" }

View File

@ -7,9 +7,9 @@ edition = "2018"
[dependencies]
ast = { version = "0.1.0" , path = "../../ide/ast/impl" }
span-tree = { version = "0.1.0" , path = "../../ide/span-tree" }
shapely = { version = "0.1.0" , path = "../shapely/impl" }
enso-shapely = { version = "0.1.0" }
ensogl = { version = "0.1.0" , path = "../../ensogl" }
enso-prelude = { version = "0.1.0" , path = "../prelude" }
enso-prelude = { version = "0.1.0" }
logger = { version = "0.1.0" , path = "../logger" }
enso-frp = { version = "0.1.0" , path = "../frp" }

View File

@ -10,8 +10,8 @@ edition = "2018"
default = []
[dependencies]
enso-prelude = { version = "0.1.0", path = "../prelude" }
shapely = { version = "0.1.0", path = "../shapely/impl" }
enso-prelude = { version = "0.1.0" }
enso-shapely = { version = "0.1.0" }
wasm-bindgen = { version = "=0.2.58", features = ["nightly"] }
[dependencies.web-sys]

View File

@ -6,7 +6,7 @@ use crate::Message;
use crate::AnyLogger;
use crate::enabled;
use shapely::CloneRef;
use enso_shapely::CloneRef;
use std::fmt::Debug;

View File

@ -5,7 +5,7 @@ use enso_prelude::*;
use crate::AnyLogger;
use crate::Message;
use shapely::CloneRef;
use enso_shapely::CloneRef;
use std::fmt::Debug;
#[cfg(target_arch = "wasm32")]

View File

@ -1,17 +0,0 @@
[package]
name = "macro-utils"
version = "0.1.0"
authors = ["Enso Team <contact@luna-lang.org>"]
edition = "2018"
[dependencies]
proc-macro2 = "1.0"
quote = "1.0"
[dependencies.syn]
version = "1.0"
features = [
'extra-traits',
'full', # for syn::ItemStruct
'visit'
]

View File

@ -1,358 +0,0 @@
//! A number of helper functions meant to be used in the procedural macros
//! definitions.
#![warn(missing_docs)]
#![feature(trait_alias)]
use proc_macro2::TokenStream;
use proc_macro2::TokenTree;
use quote::quote;
use std::iter::FromIterator;
use syn::visit::Visit;
use syn::WhereClause;
use syn::WherePredicate;
use syn;
// =====================
// === Trait Aliases ===
// =====================
pub trait Str = Into<String> + AsRef<str>;
// ==========================
// === Token Stream Utils ===
// ==========================
/// Maps all the tokens in the stream using a given function.
pub fn map_tokens<F:Fn(TokenTree) -> TokenTree>
(input:TokenStream, f:F) -> TokenStream {
let ret_iter = input.into_iter().map(f);
TokenStream::from_iter(ret_iter)
}
/// Rewrites stream replacing each token with a sequence of tokens returned by
/// the given function. The groups (e.g. token tree within braces) are unpacked,
/// rewritten and repacked into groups -- the function is applied recursively.
pub fn rewrite_stream
<F:Fn(TokenTree) -> TokenStream + Copy>
(input:TokenStream, f:F) -> TokenStream {
let mut ret = TokenStream::new();
for token in input.into_iter() {
match token {
proc_macro2::TokenTree::Group(group) => {
let delim = group.delimiter();
let span = group.span();
let rewritten = rewrite_stream(group.stream(), f);
let mut new_group = proc_macro2::Group::new(delim,rewritten);
new_group.set_span(span);
let new_group = vec![TokenTree::from(new_group)];
ret.extend(new_group.into_iter())
}
_ => ret.extend(f(token)),
}
}
ret
}
// ===================
// === Token Utils ===
// ===================
/// Is the given token an identifier matching to a given string?
pub fn matching_ident(token:&TokenTree, name:&str) -> bool {
match token {
TokenTree::Ident(ident) => *ident == name,
_ => false,
}
}
// ============
// === Repr ===
// ============
/// Obtains text representation of given `ToTokens`-compatible input.
pub fn repr<T: quote::ToTokens>(t:&T) -> String {
quote!(#t).to_string()
}
// ===================
// === Field Utils ===
// ===================
/// Collects all fields, named or not.
pub fn fields_list(fields:&syn::Fields) -> Vec<&syn::Field> {
match fields {
syn::Fields::Named (ref f) => f.named .iter().collect(),
syn::Fields::Unnamed(ref f) => f.unnamed.iter().collect(),
syn::Fields::Unit => Default::default(),
}
}
/// Returns token that refers to the field.
///
/// It is the field name for named field and field index for unnamed fields.
pub fn field_ident_token(field:&syn::Field, index:syn::Index) -> TokenStream {
match &field.ident {
Some(ident) => quote!(#ident),
None => quote!(#index),
}
}
/// Returns names of the named fields.
pub fn field_names(fields:&syn::FieldsNamed) -> Vec<&syn::Ident> {
fields.named.iter().map(|field| {
field.ident.as_ref().expect("Impossible: no name on a named field.")
}).collect()
}
// ==================
// === Path Utils ===
// ==================
/// Checks if a given `Path` consists of a single identifier same as given string.
pub fn path_matching_ident(path:&syn::Path, str:impl Str) -> bool {
path.get_ident().map_or(false, |ident| ident == str.as_ref())
}
// ======================
// === Index Sequence ===
// ======================
/// For given length, returns a sequence of Literals like `[0,1,2…]`. These are unsuffixed
/// usize literals, so e.g. can be used to identify the tuple unnamed fields.
pub fn index_sequence(len:usize) -> Vec<syn::Index> {
(0..len).map(syn::Index::from).collect()
}
/// For given length returns sequence of identifiers like `[field0,field1,…]`.
pub fn identifier_sequence(len:usize) -> Vec<syn::Ident> {
let format_field = |ix| quote::format_ident!("field{}",ix);
(0..len).map(format_field).collect()
}
// =======================
// === Type Path Utils ===
// =======================
/// Obtain list of generic arguments on the path's segment.
pub fn path_segment_generic_args
(segment:&syn::PathSegment) -> Vec<&syn::GenericArgument> {
match segment.arguments {
syn::PathArguments::AngleBracketed(ref args) =>
args.args.iter().collect(),
_ =>
Vec::new(),
}
}
/// Obtain list of generic arguments on the path's last segment.
///
/// Empty, if path contains no segments.
pub fn ty_path_generic_args
(ty_path:&syn::TypePath) -> Vec<&syn::GenericArgument> {
ty_path.path.segments.last().map_or(Vec::new(), path_segment_generic_args)
}
/// Obtain list of type arguments on the path's last segment.
pub fn ty_path_type_args
(ty_path:&syn::TypePath) -> Vec<&syn::Type> {
ty_path_generic_args(ty_path).iter().filter_map( |generic_arg| {
match generic_arg {
syn::GenericArgument::Type(t) => Some(t),
_ => None,
}
}).collect()
}
/// Last type argument of the last segment on the type path.
pub fn last_type_arg(ty_path:&syn::TypePath) -> Option<&syn::GenericArgument> {
ty_path_generic_args(ty_path).last().copied()
}
// =====================
// === Collect Types ===
// =====================
/// Visitor that accumulates all visited `syn::TypePath`.
#[derive(Default)]
pub struct TypeGatherer<'ast> {
/// Observed types accumulator.
pub types: Vec<&'ast syn::TypePath>
}
impl<'ast> Visit<'ast> for TypeGatherer<'ast> {
fn visit_type_path(&mut self, node:&'ast syn::TypePath) {
self.types.push(node);
syn::visit::visit_type_path(self, node);
}
}
/// All `TypePath`s in the given's `Type` subtree.
pub fn gather_all_types(node:&syn::Type) -> Vec<&syn::TypePath> {
let mut type_gather = TypeGatherer::default();
type_gather.visit_type(node);
type_gather.types
}
/// All text representations of `TypePath`s in the given's `Type` subtree.
pub fn gather_all_type_reprs(node:&syn::Type) -> Vec<String> {
gather_all_types(node).iter().map(|t| repr(t)).collect()
}
// =======================
// === Type Dependency ===
// =======================
/// Naive type equality test by comparing its representation with a string.
pub fn type_matches_repr(ty:&syn::Type, target_repr:&str) -> bool {
repr(ty) == target_repr
}
/// Naive type equality test by comparing their text representations.
pub fn type_matches(ty:&syn::Type, target_param:&syn::GenericParam) -> bool {
type_matches_repr(ty, &repr(target_param))
}
/// Does type depends on the given type parameter.
pub fn type_depends_on(ty:&syn::Type, target_param:&syn::GenericParam) -> bool {
let target_param = repr(target_param);
let relevant_types = gather_all_types(ty);
relevant_types.iter().any(|ty| repr(ty) == target_param)
}
/// Does enum variant depend on the given type parameter.
pub fn variant_depends_on
(var:&syn::Variant, target_param:&syn::GenericParam) -> bool {
var.fields.iter().any(|field| type_depends_on(&field.ty, target_param))
}
// ===================
// === WhereClause ===
// ===================
/// Creates a new where clause from provided sequence of where predicates.
pub fn new_where_clause(predicates:impl IntoIterator<Item=WherePredicate>) -> WhereClause {
let predicates = syn::punctuated::Punctuated::from_iter(predicates);
WhereClause {where_token:Default::default(),predicates}
}
// =============
// === Tests ===
// =============
#[cfg(test)]
mod tests {
use super::*;
use proc_macro2::TokenStream;
fn parse<T:syn::parse::Parse>(code:&str) -> T {
syn::parse_str(code).unwrap()
}
#[test]
fn repr_round_trips() {
let program = "pub fn repr<T: quote::ToTokens>(t: &T) -> String {}";
let tokens = parse::<TokenStream>(program);
let quoted_program = repr(&tokens);
let tokens2 = parse::<TokenStream>(&quoted_program);
// check only second round-trip, first is allowed to break whitespace
assert_eq!(repr(&tokens), repr(&tokens2));
}
#[test]
fn fields_list_test() {
let tuple_like = "struct Unnamed(i32, String, T);";
let proper_struct = "struct Named{i: i32, s: String, t: T}";
let expected_types = vec!["i32", "String", "T"];
fn assert_field_types(program:&str, expected_types:&[&str]) {
let tokens = parse::<syn::ItemStruct>(program);
let fields = fields_list(&tokens.fields);
let types = fields.iter().map(|f| repr(&f.ty));
assert_eq!(Vec::from_iter(types), expected_types);
}
assert_field_types(tuple_like, &expected_types);
assert_field_types(proper_struct, &expected_types);
}
#[test]
fn type_dependency() {
let param:syn::GenericParam = parse("T");
let depends = |code| {
let ty:syn::Type = parse(code);
type_depends_on(&ty, &param)
};
// sample types that depend on `T`
let dependents = vec!{
"T",
"Option<T>",
"Pair<T, U>",
"Pair<U, T>",
"Pair<U, (T,)>",
"&T",
"&'t mut T",
};
// sample types that do not depend on `T`
let independents = vec!{
"Tt",
"Option<Tt>",
"Pair<Tt, U>",
"Pair<U, Tt>",
"Pair<U, Tt>",
"i32",
"&str",
};
for dependent in dependents {
assert!(depends(dependent), "{} must depend on {}"
, repr(&dependent), repr(&param));
}
for independent in independents {
assert!(!depends(independent), "{} must not depend on {}"
, repr(&independent), repr(&param));
}
}
#[test]
fn collecting_type_path_args() {
fn check(expected_type_args:Vec<&str>, ty_path:&str) {
let ty_path = parse(ty_path);
let args = super::ty_path_type_args(&ty_path);
assert_eq!(expected_type_args.len(), args.len());
let zipped = expected_type_args.iter().zip(args.iter());
for (expected,got) in zipped {
assert_eq!(expected, &repr(got));
}
}
check(vec!["T"] , "std::Option<T>");
check(vec!["U"] , "std::Option<U>");
check(vec!["A", "B"], "Either<A,B>");
assert_eq!(super::last_type_arg(&parse("i32")), None);
assert_eq!(repr(&super::last_type_arg(&parse("Foo<C>"))), "C");
}
}

View File

@ -9,4 +9,4 @@ edition = "2018"
[features]
[dependencies]
enso-prelude = { version = "0.1.0", path = "../prelude" }
enso-prelude = { version = "0.1.0" }

View File

@ -1,68 +0,0 @@
[package]
name = "enso-prelude"
version = "0.1.0"
authors = ["Enso Team <contact@luna-lang.org>"]
edition = "2018"
[lib]
[dependencies]
shapely = { version = "0.1.0" , path = "../shapely/impl" }
boolinator = "2.4.0"
derivative = "1.0.3"
derive_more = "0.99.2"
enclose = "1.1.8"
failure = "0.1.5"
ifmt = "0.2.0"
itertools = "0.8"
lazy_static = "1.4"
num = "0.2.0"
paste = "0.1"
shrinkwraprs = "0.3.0"
smallvec = "1.0.0"
weak-table = "0.2.3"
wasm-bindgen = { version = "=0.2.58" , features = ["nightly"] }
# TODO: should be behind a flag, as the `nalgebra` package is pretty big and this crate would be
# also useful for projects which do not require `nalgebra`.
nalgebra = "0.21.1"
[dependencies.web-sys]
version = "0.3.4"
features = [
'CanvasRenderingContext2d',
'CssStyleDeclaration',
'Document',
'Element',
'EventTarget',
'KeyboardEvent',
'HtmlCanvasElement',
'HtmlCollection',
'HtmlDivElement',
'HtmlElement',
'HtmlImageElement',
'Location',
'Node',
'Url',
'WebGlBuffer',
'WebGlFramebuffer',
'WebGlProgram',
'WebGlRenderingContext',
'WebGlShader',
'WebGlSync',
'WebGlTexture',
'WebGl2RenderingContext',
'WebGlUniformLocation',
'WebGlUniformLocation',
'WebGlVertexArrayObject',
'Window',
'console',
'EventTarget',
'Event',
'MouseEvent',
'Performance',
'WheelEvent',
'DomRect',
'AddEventListenerOptions'
]

View File

@ -1,56 +0,0 @@
use crate::*;
pub use shapely::CloneRef;
// ================
// === CloneRef ===
// ================
/// Clone for internal-mutable structures. This trait can be implemented only if mutating one
/// structure will be reflected in all of its clones. Please note that it does not mean that all the
/// fields needs to provide internal mutability as well. For example, a structure can remember it's
/// creation time and store it as `f32`. As long as it cannot be mutated, the structure can
/// implement `CloneRef`. In order to guide the auto-deriving mechanism, it is advised to wrap all
/// immutable fields in the `Immutable` newtype.
pub trait CloneRef: Sized {
fn clone_ref(&self) -> Self;
}
#[macro_export]
macro_rules! impl_clone_ref_as_clone {
([$($bounds:tt)*] $($toks:tt)*) => {
impl <$($bounds)*> CloneRef for $($toks)* {
fn clone_ref(&self) -> Self {
self.clone()
}
}
};
($($toks:tt)*) => {
impl CloneRef for $($toks)* {
fn clone_ref(&self) -> Self {
self.clone()
}
}
};
}
impl_clone_ref_as_clone!(());
impl_clone_ref_as_clone!(f32);
impl_clone_ref_as_clone!(f64);
impl_clone_ref_as_clone!(i32);
impl_clone_ref_as_clone!(i64);
impl_clone_ref_as_clone!(usize);
impl_clone_ref_as_clone!([T] PhantomData<T>);
impl_clone_ref_as_clone!([T:?Sized] Rc<T>);
impl_clone_ref_as_clone!([T:?Sized] Weak<T>);
impl_clone_ref_as_clone!(wasm_bindgen::JsValue);
impl_clone_ref_as_clone!(web_sys::HtmlDivElement);
impl_clone_ref_as_clone!(web_sys::HtmlElement);
impl_clone_ref_as_clone!(web_sys::Performance);
impl_clone_ref_as_clone!(web_sys::WebGl2RenderingContext);
impl_clone_ref_as_clone!(web_sys::HtmlCanvasElement);
impl_clone_ref_as_clone!(web_sys::EventTarget);

View File

@ -1,6 +0,0 @@
//! This module exports collections which are popular enough to be available everywhere.
pub use smallvec::SmallVec;
pub use std::collections::BTreeMap;
pub use std::collections::HashMap;
pub use std::collections::HashSet;

View File

@ -1,9 +0,0 @@
//! Generic data types and utilities.
pub mod at_least_one_of_two;
pub mod monoid;
pub mod semigroup;
pub use at_least_one_of_two::*;
pub use monoid::*;
pub use semigroup::*;

View File

@ -1,55 +0,0 @@
//! Definition of `AtLeastOneOfTwo`.
// =======================
// === AtLeastOneOfTwo ===
// =======================
/// A struct similar to `Option` and `Either`. It can contain the first value, or the second value,
/// or both of them at the same time.
#[derive(Debug,Clone,Copy)]
#[allow(missing_docs)]
pub enum AtLeastOneOfTwo<T1,T2> {
First(T1),
Second(T2),
Both(T1,T2)
}
impl<T:PartialEq> AtLeastOneOfTwo<T,T> {
/// Checks whether the values are equal.
pub fn same(&self) -> bool {
match self {
Self::Both(t1,t2) => t1 == t2,
_ => false
}
}
}
impl<T1,T2> AtLeastOneOfTwo<T1,T2> {
/// Extracts the first value if exists.
pub fn first(&self) -> Option<&T1> {
match self {
Self::Both(t1,_) => Some(t1),
Self::First(t1) => Some(t1),
_ => None
}
}
/// Extracts the second value if exists.
pub fn second(&self) -> Option<&T2> {
match self {
Self::Both(_,t2) => Some(t2),
Self::Second(t2) => Some(t2),
_ => None
}
}
/// Extracts both of the value if exist.
pub fn both(&self) -> Option<(&T1,&T2)> {
match self {
Self::Both(t1,t2) => Some((t1,t2)),
_ => None
}
}
}

View File

@ -1,107 +0,0 @@
//! A class for monoids (types with an associative binary operation that has an identity) with
//! various general-purpose instances.
use super::semigroup::Semigroup;
// ===============
// === Monoid ====
// ===============
/// Mutable Monoid definition.
pub trait Monoid : Default + Semigroup {
/// Repeat a value n times. Given that this works on a Monoid it will not fail if you request 0
/// or fewer repetitions.
fn times_mut(&mut self, n:usize) {
if n == 0 {
*self = Default::default()
} else {
let val = self.clone();
for _ in 0..n-1 {
self.concat_mut(&val)
}
}
}
fn times(&self, n:usize) -> Self {
std::iter::repeat(self).take(n).fold(Default::default(),|l,r| l.concat_ref(r))
}
}
// === Default Impls ===
impl<T> Monoid for T where T : Default + Semigroup {}
// =============
// === Tests ===
// =============
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn option() {
let vec_nop : Vec<usize> = vec![];
let vec_1_2 : Vec<usize> = vec![1,2];
let vec_1_2_times_3 : Vec<usize> = vec![1,2,1,2,1,2];
assert_eq!(vec_1_2.times(0) , vec_nop);
assert_eq!(vec_1_2.times(1) , vec_1_2);
assert_eq!(vec_1_2.times(3) , vec_1_2_times_3);
}
}
// TODO: Think what to do with this. It would not be needed if tuples implement Iter. Alternatively
// we could immplement own tuple type.
//trait Foldable {
// type Item : Monoid;
// fn fold(self) -> Self::Item;
//}
//
//
//
//macro_rules! replace {
// ($a:tt,$b:tt) => {$b};
//}
//
//
//macro_rules! define_foldable_for_tuple {
// (0$(,$num:tt)*) => {
// impl<T:Monoid> Foldable for (T,$(replace!{$num,T}),*) {
// type Item = T;
// fn fold(self) -> Self::Item {
// self.0$(.concat(self.$num))*
// }
// }
//
// impl<T:Monoid> Foldable for &(T,$(replace!{$num,T}),*) {
// type Item = T;
// fn fold(self) -> Self::Item {
// self.0.clone()$(.concat(&self.$num))*
// }
// }
// };
//}
//
//define_foldable_for_tuple![0];
//define_foldable_for_tuple![0,1];
//define_foldable_for_tuple![0,1,2];
//define_foldable_for_tuple![0,1,2,3];
//define_foldable_for_tuple![0,1,2,3,4];
//define_foldable_for_tuple![0,1,2,3,4,5];
//define_foldable_for_tuple![0,1,2,3,4,5,6];
//define_foldable_for_tuple![0,1,2,3,4,5,6,7];
//define_foldable_for_tuple![0,1,2,3,4,5,6,7,8];
//define_foldable_for_tuple![0,1,2,3,4,5,6,7,8,9];
//define_foldable_for_tuple![0,1,2,3,4,5,6,7,8,9,10];
//define_foldable_for_tuple![0,1,2,3,4,5,6,7,8,9,10,11];
//define_foldable_for_tuple![0,1,2,3,4,5,6,7,8,9,10,11,12];
//define_foldable_for_tuple![0,1,2,3,4,5,6,7,8,9,10,11,12,13];
//define_foldable_for_tuple![0,1,2,3,4,5,6,7,8,9,10,11,12,13,14];
//define_foldable_for_tuple![0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];

View File

@ -1,143 +0,0 @@
//! In mathematics, a semigroup is an algebraic structure consisting of a set together with an
//! associative binary operation. A semigroup generalizes a monoid in that there might not exist an
//! identity element. It also (originally) generalized a group (a monoid with all inverses) to a
//! type where every element did not have to have an inverse, thus the name semigroup.
use std::collections::HashMap;
use std::hash::BuildHasher;
use std::hash::Hash;
use std::iter::Extend;
// =================
// === Semigroup ===
// =================
/// Mutable Semigroup definition. Impls should satisfy the associativity law:
/// `x.concat(y.concat(z)) = x.concat(y).concat(z)`, in symbolic form:
/// `x <> (y <> z) = (x <> y) <> z`
pub trait PartialSemigroup<T> : Clone {
/// An associative operation.
fn concat_mut(&mut self, other:T);
/// An associative operation.
fn concat_ref(&self, other:T) -> Self where Self:Clone {
self.clone().concat(other)
}
/// An associative operation.
fn concat(mut self, other:T) -> Self {
self.concat_mut(other);
self
}
}
impl<T> Semigroup for T where T : PartialSemigroup<T> + for<'t> PartialSemigroup<&'t T> {}
pub trait Semigroup : PartialSemigroup<Self> + for<'t> PartialSemigroup<&'t Self> {
fn partial_times_mut(&mut self, n:usize) {
let val = self.clone();
for _ in 0..n-1 {
self.concat_mut(&val)
}
}
fn partial_times(mut self, n:usize) -> Self {
self.partial_times_mut(n);
self
}
}
// ====================
// === Stdlib Impls ===
// ====================
// === Option ===
impl<T:Semigroup> PartialSemigroup<&Option<T>> for Option<T> {
fn concat_mut(&mut self, other:&Self) {
if let Some(r) = other {
match self {
None => *self = Some(r.clone()),
Some(l) => l.concat_mut(r)
}
}
}
}
impl<T:Semigroup> PartialSemigroup<Option<T>> for Option<T> {
fn concat_mut(&mut self, other:Self) {
if let Some(r) = other {
match self {
None => *self = Some(r),
Some(l) => l.concat_mut(r)
}
}
}
}
// === HashMap ===
impl<K,V,S> PartialSemigroup<&HashMap<K,V,S>> for HashMap<K,V,S>
where K : Eq + Hash + Clone,
V : Semigroup,
S : Clone + BuildHasher {
fn concat_mut(&mut self, other:&Self) {
for (key,new_val) in other {
let key = key.clone();
self.entry(key)
.and_modify(|val| val.concat_mut(new_val))
.or_insert_with(|| new_val.clone());
}
}
}
impl<K,V,S> PartialSemigroup<HashMap<K,V,S>> for HashMap<K,V,S>
where K : Eq + Hash + Clone,
V : Semigroup,
S : Clone + BuildHasher {
fn concat_mut(&mut self, other:Self) {
for (key,new_val) in other {
self.entry(key)
.and_modify(|val| val.concat_mut(&new_val))
.or_insert(new_val);
}
}
}
// === Vec ===
impl<T:Clone> PartialSemigroup<&Vec<T>> for Vec<T> {
fn concat_mut(&mut self, other:&Self) {
self.extend(other.iter().cloned())
}
}
impl<T:Clone> PartialSemigroup<Vec<T>> for Vec<T> {
fn concat_mut(&mut self, other:Self) {
self.extend(other.into_iter())
}
}
// =============
// === Tests ===
// =============
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn option() {
assert_eq!(None::<Vec<usize>>.concat(&None) , None);
assert_eq!(Some(vec![1]).concat(&None) , Some(vec![1]));
assert_eq!(None.concat(&Some(vec![1])) , Some(vec![1]));
assert_eq!(Some(vec![1]).concat(&Some(vec![2])) , Some(vec![1,2]));
}
}

View File

@ -1,326 +0,0 @@
//! This module re-exports a lot of useful stuff. It is not meant to be used
//! by libraries, but it is definitely usefull for bigger projects. It also
//! defines several aliases and utils which may find their place in new
//! libraries in the future.
#![warn(unsafe_code)]
#![warn(missing_copy_implementations)]
#![warn(missing_debug_implementations)]
#![feature(specialization)]
#![feature(trait_alias)]
mod clone;
mod collections;
mod data;
mod macros;
mod option;
mod phantom;
mod reference;
mod std_reexports;
mod string;
mod tp;
mod wrapper;
pub use clone::*;
pub use collections::*;
pub use data::*;
pub use macros::*;
pub use option::*;
pub use phantom::*;
pub use reference::*;
pub use std_reexports::*;
pub use string::*;
pub use tp::*;
pub use wrapper::*;
pub use boolinator::Boolinator;
pub use derivative::Derivative;
pub use derive_more::*;
pub use enclose::enclose;
pub use failure::Fail;
pub use ifmt::*;
pub use itertools::Itertools;
pub use lazy_static::lazy_static;
pub use num::Num;
pub use paste;
pub use shrinkwraprs::Shrinkwrap;
pub use weak_table::traits::WeakElement;
pub use weak_table::traits::WeakKey;
pub use weak_table::WeakKeyHashMap;
pub use weak_table::WeakValueHashMap;
pub use weak_table;
use std::cell::UnsafeCell;
// =================
// === Immutable ===
// =================
/// A zero-overhead newtype which provides immutable access to its content. Of course this does not
/// apply to internal mutability of the wrapped data. A good use case of this structure is when you
/// want to pass an ownership to a structure, allow access all its public fields, but do not allow
/// their modification.
#[derive(Clone,Copy,Default)]
pub struct Immutable<T> {
data : T
}
/// Constructor of the `Immutable` struct.
#[allow(non_snake_case)]
pub fn Immutable<T>(data:T) -> Immutable<T> {
Immutable {data}
}
impl<T:Debug> Debug for Immutable<T> {
fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.data.fmt(f)
}
}
impl<T:Display> Display for Immutable<T> {
fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.data.fmt(f)
}
}
impl<T:Clone> CloneRef for Immutable<T> {
fn clone_ref(&self) -> Self {
Self {data:self.data.clone()}
}
}
impl<T> AsRef<T> for Immutable<T> {
fn as_ref(&self) -> &T {
&self.data
}
}
impl<T> std::borrow::Borrow<T> for Immutable<T> {
fn borrow(&self) -> &T {
&self.data
}
}
impl<T> Deref for Immutable<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.data
}
}
// ==============
// === ToImpl ===
// ==============
/// Provides method `to`, which is just like `into` but allows fo superfish syntax.
pub trait ToImpl: Sized {
fn to<P>(self) -> P where Self:Into<P> {
self.into()
}
}
impl<T> ToImpl for T {}
// TODO
// This impl should be hidden behind a flag. Not everybody using prelude want to import nalgebra.
impl <T,R,C,S> TypeDisplay for nalgebra::Matrix<T,R,C,S>
where T:nalgebra::Scalar, R:nalgebra::DimName, C:nalgebra::DimName {
fn type_display() -> String {
let cols = <C as nalgebra::DimName>::dim();
let rows = <R as nalgebra::DimName>::dim();
let item = type_name::<T>();
match cols {
1 => format!("Vector{}<{}>" , rows, item),
_ => format!("Matrix{}x{}<{}>" , rows, cols, item)
}
}
}
#[macro_export]
macro_rules! clone_boxed {
( $name:ident ) => { paste::item! {
#[allow(missing_docs)]
pub trait [<CloneBoxedFor $name>] {
fn clone_boxed(&self) -> Box<dyn $name>;
}
impl<T:Clone+$name+'static> [<CloneBoxedFor $name>] for T {
fn clone_boxed(&self) -> Box<dyn $name> {
Box::new(self.clone())
}
}
impl Clone for Box<dyn $name> {
fn clone(&self) -> Self {
self.clone_boxed()
}
}
}}
}
/// Alias for `for<'t> &'t Self : Into<T>`.
pub trait RefInto<T> = where for<'t> &'t Self : Into<T>;
// =================
// === CloneCell ===
// =================
#[derive(Debug)]
pub struct CloneCell<T> {
data : UnsafeCell<T>
}
impl<T> CloneCell<T> {
pub fn new(elem:T) -> CloneCell<T> {
CloneCell { data:UnsafeCell::new(elem) }
}
#[allow(unsafe_code)]
pub fn get(&self) -> T where T:Clone {
unsafe {(*self.data.get()).clone()}
}
#[allow(unsafe_code)]
pub fn set(&self, elem:T) {
unsafe { *self.data.get() = elem; }
}
#[allow(unsafe_code)]
pub fn take(&self) -> T where T:Default {
let ptr:&mut T = unsafe { &mut *self.data.get() };
std::mem::take(ptr)
}
}
impl<T:Clone> Clone for CloneCell<T> {
fn clone(&self) -> Self {
Self::new(self.get())
}
}
impl<T:Default> Default for CloneCell<T> {
fn default() -> Self {
Self::new(default())
}
}
// =================
// === CloneCell ===
// =================
#[derive(Debug)]
pub struct CloneRefCell<T> {
data : UnsafeCell<T>
}
impl<T> CloneRefCell<T> {
pub fn new(elem:T) -> CloneRefCell<T> {
CloneRefCell { data:UnsafeCell::new(elem) }
}
#[allow(unsafe_code)]
pub fn get(&self) -> T where T:CloneRef {
unsafe {(*self.data.get()).clone_ref()}
}
#[allow(unsafe_code)]
pub fn set(&self, elem:T) {
unsafe { *self.data.get() = elem; }
}
#[allow(unsafe_code)]
pub fn take(&self) -> T where T:Default {
let ptr:&mut T = unsafe { &mut *self.data.get() };
std::mem::take(ptr)
}
}
impl<T:CloneRef> Clone for CloneRefCell<T> {
fn clone(&self) -> Self {
Self::new(self.get())
}
}
impl<T:CloneRef> CloneRef for CloneRefCell<T> {
fn clone_ref(&self) -> Self {
Self::new(self.get())
}
}
impl<T:Default> Default for CloneRefCell<T> {
fn default() -> Self {
Self::new(default())
}
}
// ================================
// === RefCell<Option<T>> Utils ===
// ================================
pub trait RefcellOptionOps<T> {
fn clear(&self);
fn set(&self, val:T);
fn set_if_none(&self, val:T);
}
impl<T> RefcellOptionOps<T> for RefCell<Option<T>> {
fn clear(&self) {
*self.borrow_mut() = None;
}
fn set(&self, val:T) {
*self.borrow_mut() = Some(val);
}
fn set_if_none(&self, val:T) {
let mut ptr = self.borrow_mut();
if ptr.is_some() { panic!("The value was already set.") }
*ptr = Some(val)
}
}
// ================================
// === Strong / Weak References ===
// ================================
/// Abstraction for a strong reference like `Rc` or newtypes over it.
pub trait StrongRef : CloneRef {
/// Downgraded reference type.
type WeakRef : WeakRef<StrongRef=Self>;
/// Creates a new weak reference of this allocation.
fn downgrade(&self) -> Self::WeakRef;
}
/// Abstraction for a weak reference like `Weak` or newtypes over it.
pub trait WeakRef : CloneRef {
/// Upgraded reference type.
type StrongRef : StrongRef<WeakRef=Self>;
/// Attempts to upgrade the weak referenc to a strong one, delaying dropping of the inner value
/// if successful.
fn upgrade(&self) -> Option<Self::StrongRef>;
}
impl<T:?Sized> StrongRef for Rc<T> {
type WeakRef = Weak<T>;
fn downgrade(&self) -> Self::WeakRef {
Rc::downgrade(&self)
}
}
impl<T:?Sized> WeakRef for Weak<T> {
type StrongRef = Rc<T>;
fn upgrade(&self) -> Option<Self::StrongRef> {
Weak::upgrade(self)
}
}

View File

@ -1,173 +0,0 @@
//! This macro defines set of common macros which are useful across different projects.
/// Allows for nicer definition of impls, similar to what Haskell or Scala does. Reduces the needed
/// boilerplate. For example, the following usage:
///
/// ```compile_fail
/// struct A { name:String };
/// impls! { From<A> for String { |t| t.name.clone() } }
/// ```
///
/// compiles to:
/// ```
/// struct A { name:String };
/// impl From<A> for String {
/// fn from(t:A) -> Self {
/// t.name.clone()
/// }
/// }
/// ```
///
/// This macro is meant to support many standard traits (like From) and should grow in the future.
/// Currently supported ones are:
/// * From<…>
/// * From + &From<…>
/// * Into + &Into<…>
/// * PhantomFrom<…>
#[macro_export]
macro_rules! impls {
($([$($impl_params:tt)*])? From<$ty:ty> for $target:ty $(where [$($bounds:tt)*])? {
|$arg:tt| $($result:tt)*
} ) => {
#[allow(clippy::redundant_closure_call)]
impl <$($($impl_params)*)?> From <$ty> for $target $(where $($bounds)*)? {
fn from (arg:$ty) -> Self {
(|$arg:$ty| $($result)*)(arg)
}
}
};
($([$($impl_params:tt)*])? From + &From <$ty:ty> for $target:ty $(where [$($bounds:tt)*])? {
|$arg:tt| $($result:tt)*
} ) => {
#[allow(clippy::redundant_closure_call)]
#[allow(clippy::identity_conversion)]
impl <$($($impl_params)*)?> From <$ty> for $target $(where $($bounds)*)? {
fn from (arg:$ty) -> Self {
(|$arg:$ty| $($result)*)(arg)
}
}
#[allow(clippy::redundant_closure_call)]
#[allow(clippy::identity_conversion)]
impl <$($($impl_params)*)?> From <&$ty> for $target $(where $($bounds)*)? {
fn from (arg:&$ty) -> Self {
(|$arg:&$ty| $($result)*)(arg)
}
}
};
($([$($impl_params:tt)*])? Into + &Into <$ty:ty> for $target:ty $(where [$($bounds:tt)*])? {
|$arg:tt| $($result:tt)*
} ) => {
#[allow(clippy::redundant_closure_call)]
#[allow(clippy::identity_conversion)]
impl <$($($impl_params)*)?> Into <$ty> for $target $(where $($bounds)*)? {
fn into(self) -> $ty {
(|$arg:Self| $($result)*)(self)
}
}
#[allow(clippy::redundant_closure_call)]
#[allow(clippy::identity_conversion)]
impl <$($($impl_params)*)?> Into <$ty> for &$target $(where $($bounds)*)? {
fn into(self) -> $ty {
(|$arg:Self| $($result)*)(self)
}
}
};
($([$($impl_params:tt)*])? PhantomFrom<$ty:ty> for $target:ty {
$($result:tt)*
} ) => {
impl <$($($impl_params)*)?> From <PhantomData<$ty>> for $target {
fn from (_:PhantomData<$ty>) -> Self {
$($result)*
}
}
};
}
#[macro_export]
macro_rules! alias {
($( $(#$meta:tt)* $name:ident = {$($tok:tt)*} )*) => {$(
$(#$meta)*
pub trait $name: $($tok)* {}
impl<T:$($tok)*> $name for T {}
)*};
(no_docs $( $(#$meta:tt)* $name:ident = {$($tok:tt)*} )*) => {$(
$(#$meta)*
#[allow(missing_docs)]
pub trait $name: $($tok)* {}
impl<T:$($tok)*> $name for T {}
)*};
}
// ==============
// === Lambda ===
// ==============
/// Clones all arguments from the first argument list by using `CloneRef` and defines lambda with
/// arguments from the second argument list (if present). For example, the following usage
///
/// ```compile_fail
/// f! { (a,b)(c) a + b + c }
/// ```
///
/// is equivalent to:
///
/// ```compile_fail
/// {
/// let a = a.clone_ref();
/// let b = b.clone_ref();
/// move |c| { a + b + c }
/// }
/// ```
#[macro_export]
macro_rules! f {
([$($name:ident),*] ($($args:tt)*) $($expr:tt)*) => {
{
$(let $name = $name.clone_ref();)*
move |$($args)*| { $($expr)* }
}
};
([$($name:ident),*] $($expr:tt)*) => {
{
$(let $name = $name.clone_ref();)*
move || { $($expr)* }
}
};
(($($args:tt)*) $name:ident . $($toks:tt)*) => {
f! { [$name] ($($args)*) $name . $($toks)* }
};
(($($args:tt)*) { $name:ident . $($toks:tt)* }) => {
f! { [$name] ($($args)*) { $name . $($toks)* } }
};
($name:ident . $($toks:tt)*) => {
f! { [$name] $name . $($toks)* }
};
}
/// Variant of the `f` macro producing a lambda which drops its first argument.
#[macro_export]
macro_rules! f_ {
([$($name:ident),*] $($expr:tt)*) => {
f! { [$($name),*] (_) $($expr)* }
};
($name:ident . $($toks:tt)*) => {
f_! { [$name] $name . $($toks)* }
};
( { $name:ident . $($toks:tt)* } ) => {
f_! { [$name] { $name . $($toks)* } }
};
}

View File

@ -1,25 +0,0 @@
//! This module defines utilities for working with the `Option` type.
/// Adds mapping methods to the `Option` type.
pub trait OptionOps {
type Item;
fn map_ref <U,F> (&self , f:F) -> Option<U> where F : FnOnce(&Self::Item) -> U;
fn for_each <U,F> (self , f:F) where F : FnOnce(Self::Item) -> U;
fn for_each_ref <U,F> (&self , f:F) where F : FnOnce(&Self::Item) -> U;
}
impl<T> OptionOps for Option<T> {
type Item = T;
fn map_ref<U,F>(&self, f:F) -> Option<U> where F : FnOnce(&Self::Item) -> U {
self.as_ref().map(f)
}
fn for_each<U,F>(self, f:F) where F : FnOnce(Self::Item) -> U {
if let Some(x) = self { f(x); }
}
fn for_each_ref<U,F>(&self, f:F) where F : FnOnce(&Self::Item) -> U {
if let Some(x) = self { f(x); }
}
}

View File

@ -1,94 +0,0 @@
//! This module defines utilities for working with PhantomData.
use super::std_reexports::*;
use derivative::Derivative;
use shrinkwraprs::Shrinkwrap;
// ===================
// === PhantomData ===
// ===================
/// The following `PhantomData` implementations allow each argument to be non
/// Sized. Unfortunately, this is not equivalent to `PhantomData<(T1,T2,...)>`,
/// as tuple requires each arg to implement `Sized`.
pub type PhantomData2<T1,T2> = PhantomData<(PhantomData <T1>, PhantomData<T2>)>;
pub type PhantomData3<T1,T2,T3> = PhantomData2<PhantomData2<T1,T2>, PhantomData<T3>>;
pub type PhantomData4<T1,T2,T3,T4> = PhantomData2<PhantomData3<T1,T2,T3>, PhantomData<T4>>;
pub type PhantomData5<T1,T2,T3,T4,T5> = PhantomData2<PhantomData4<T1,T2,T3,T4>, PhantomData<T5>>;
pub type PhantomData6<T1,T2,T3,T4,T5,T6> = PhantomData2<PhantomData5<T1,T2,T3,T4,T5>, PhantomData<T6>>;
pub type PhantomData7<T1,T2,T3,T4,T5,T6,T7> = PhantomData2<PhantomData6<T1,T2,T3,T4,T5,T6>, PhantomData<T7>>;
pub type PhantomData8<T1,T2,T3,T4,T5,T6,T7,T8> = PhantomData2<PhantomData7<T1,T2,T3,T4,T5,T6,T7>, PhantomData<T8>>;
pub type PhantomData9<T1,T2,T3,T4,T5,T6,T7,T8,T9> = PhantomData2<PhantomData8<T1,T2,T3,T4,T5,T6,T7,T8>, PhantomData<T9>>;
// ===================
// === WithPhantom ===
// ===================
/// A wrapper adding a phantom type to a structure.
#[derive(Derivative)]
#[derive(Shrinkwrap)]
#[shrinkwrap(mutable)]
#[derivative(Clone (bound="T:Clone"))]
#[derivative(Default (bound="T:Default"))]
#[derivative(Debug (bound="T:Debug"))]
pub struct WithPhantom<T, P=()> {
#[shrinkwrap(main_field)]
pub without_phantom: T,
phantom: PhantomData<P>
}
impl<T, P> WithPhantom<T, P> {
pub fn new(without_phantom: T) -> Self {
let phantom = PhantomData;
Self { without_phantom, phantom }
}
}
// ==========================
// === PhantomConversions ===
// ==========================
/// A utility for easy driving of type-level computations from value level. Often we've got some
/// type level relations, like a few singleton types, and for each such type we've got an associated
/// value. For example, we can define types `Int` and `Float` and associate with them
/// `WebGlContext::Int` and `WebGlContext::Float` constants encoded as `GlEnum`. In order to convert
/// `Int` or `Float` to the `GlEnum` we do not need the instance of the types, only the information
/// what type it was. So we can define:
///
/// ```compile_fail
/// impl From<PhantomData<Int>> for u32 {
/// from(_:PhantomData<Int>>) {
/// GlEnum(WebGlContext::Int)
/// }
/// }
/// ```
///
/// And use it like:
///
/// ```compile_fail
/// let val = GlEnum::from(PhantomData::<Int>)
/// ```
///
/// Using this utility we can always write the following code instead:
///
/// ```compile_fail
/// let val = GlEnum::phantom_from::<Int>()
/// ```
pub trait PhantomConversions: Sized {
fn phantom_into<P>() -> P where Self:PhantomInto<P> {
PhantomData::<Self>.into()
}
fn phantom_from<P:PhantomInto<Self>>() -> Self {
PhantomData::<P>.into()
}
}
impl<T> PhantomConversions for T {}
/// Like `Into` but for phantom types.
pub trait PhantomInto<T> = where PhantomData<Self>: Into<T>;

View File

@ -1,78 +0,0 @@
//! This module defines helpers and utilities for working with references.
// ============
// === With ===
// ============
/// Surprisingly useful function. Consider the following code:
///
/// ```compile_fail
/// fn init(self) -> Self {
/// let mut data = self.borrow_mut();
/// ...
/// self
/// }
/// ```
///
/// It may not compile telling that the last line moves self out, however,
/// borrow might be used there, when `data` is dropped and runs the destructor.
///
/// We can use this function to narrow-down the lifetimes. The following code
/// compiles just fine:
///
/// ```compile_fail
/// fn init(self) -> Self {
/// with(self.borrow_mut(), |mut data| {
/// ...
/// });
/// self
/// }
/// ```
pub fn with<T, F: FnOnce(T) -> Out, Out>(t: T, f: F) -> Out { f(t) }
// =============
// === ToRef ===
// =============
/// Similar to `AsRef` but more specific and automatically implemented for every type. Allows for
/// conversion `&T` to `&T` (identity) and `T` to `&T` for any type `T`. In contrast, `AsRef`
/// requires explicit impls, so for example you cannot do `let t:&() = ().as_ref()`
pub trait ToRef<T> where T:?Sized { fn to_ref(&self) -> &T; }
impl<T> ToRef<T> for T where T:?Sized { fn to_ref(&self) -> &T { self } }
impl<T> ToRef<T> for &T where T:?Sized { fn to_ref(&self) -> &T { self } }
// pub trait ToRef = ?Sized + HasRefValue + ToRef__<RefValue<Self>>;
pub trait HasRefValue where { type RefValue:?Sized; }
impl <T> HasRefValue for T where T:?Sized { default type RefValue=T; }
impl <T> HasRefValue for &T where T:?Sized { type RefValue=T; }
pub type RefValue<T> = <T as HasRefValue>::RefValue;
// =============
// === Owned ===
// =============
/// The owned version of a type. It would be super cool if Rust would allow us to automatically
/// implement it for every type: `Owned<&T> = T` and `Owned<T> = T` if `T` was not a reference.
/// Unfortunately, we need to implement it by hand for every type now.
pub trait AsOwned {
type Owned;
}
/// Owned type family.
pub type Owned<T> = <T as AsOwned>::Owned;
/// Converts type to its owned version.
pub trait IntoOwned = AsOwned + Into<Owned<Self>>;
// === Default Impls ===
impl<T> AsOwned for &T {
type Owned = T;
}

View File

@ -1,65 +0,0 @@
//! This module reexports several commonly used types defined in the standard library.
// === Data ===
pub use std::any::Any;
pub use std::borrow::Cow;
pub use std::hash::Hash;
pub use std::marker::PhantomData;
pub use std::ops::Range;
// === Format ===
pub use core::any::type_name;
pub use core::fmt::Debug;
pub use std::fmt::Display;
pub use std::fmt;
pub use std::iter::FromIterator;
pub use std::iter;
// === Data Operations ===
pub use std::ops::Deref;
pub use std::ops::DerefMut;
pub use std::ops::Index;
pub use std::ops::IndexMut;
// === Conversion ===
pub use std::convert::identity;
pub use std::convert::TryFrom;
pub use std::convert::TryInto;
// === References ===
pub use std::cell::Cell;
pub use std::cell::Ref;
pub use std::cell::RefCell;
pub use std::cell::RefMut;
pub use std::rc::Rc;
pub use std::rc::Weak;
pub use std::slice::SliceIndex;
pub use std::slice;
// === Operators ===
pub use std::ops::Add;
pub use std::ops::Div;
pub use std::ops::Mul;
pub use std::ops::Neg;
pub use std::ops::Sub;
// === Utils ===
pub use std::mem;
/// Alias for `Default::default()`.
pub fn default<T:Default>() -> T {
Default::default()
}

View File

@ -1,247 +0,0 @@
//! This module defines several useful string variants, including copy-on-write and immutable
//! implementations.
use std::borrow::Cow;
use crate::impls;
use crate::clone::*;
use std::ops::Deref;
use std::rc::Rc;
use derive_more::*;
// ===========
// === Str ===
// ===========
/// Abstraction for any kind of string as an argument. Functions defined as
/// `fn test<S:Str>(s: Str) { ... }` can be called with `String`, `&String`, and `&str` without
/// requiring caller to know the implementation details. Moreover, the definition can decide if it
/// needs allocation or not. Calling `s.as_ref()` will never allocate, while `s.into()` will
/// allocate only when necessary.
pub trait Str = Into<String> + AsRef<str>;
// =================
// === CowString ===
// =================
// === Definition ===
/// A copy-on-write String implementation. It is a newtype wrapper for `Cow<'static,str>` and
/// provides many useful impls for efficient workflow. Use it whenever you want to store a string
/// but you are not sure if the string will be allocated or not. This way you can store a static
/// slice as long as you can and switch to allocated String on demand.
#[derive(Clone,Debug,Default,Display)]
pub struct CowString(Cow<'static,str>);
// === Conversions From CowString ===
impls!{ From <&CowString> for String { |t| t.clone().into() } }
impls!{ From <CowString> for String { |t| t.0.into() } }
// === Conversions To CowString ===
impls!{ From <Cow<'static,str>> for CowString { |t| Self(t) } }
impls!{ From <&Cow<'static,str>> for CowString { |t| Self(t.clone()) } }
impls!{ From <&'static str> for CowString { |t| Self(t.into()) } }
impls!{ From <String> for CowString { |t| Self(t.into()) } }
impls!{ From <&String> for CowString { |t| t.to_string().into() } }
impls!{ From <&CowString> for CowString { |t| t.clone() } }
// === Instances ===
impl Deref for CowString {
type Target = str;
fn deref(&self) -> &str {
self.0.deref()
}
}
impl AsRef<str> for CowString {
fn as_ref(&self) -> &str {
self.deref()
}
}
// ================
// === ImString ===
// ================
/// Immutable string implementation with a fast clone implementation.
#[derive(Clone,CloneRef,Debug,Default,Eq,Hash,PartialEq)]
pub struct ImString {
content : Rc<String>
}
impl ImString {
/// Constructor.
pub fn new(content:impl Into<String>) -> Self {
let content = Rc::new(content.into());
Self {content}
}
}
impl std::fmt::Display for ImString {
fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f,"{}",self.content)
}
}
impl Deref for ImString {
type Target = str;
fn deref(&self) -> &Self::Target {
&self.content
}
}
impl AsRef<ImString> for ImString {
fn as_ref(&self) -> &ImString {
self
}
}
impl AsRef<String> for ImString {
fn as_ref(&self) -> &String {
self.content.as_ref()
}
}
impl AsRef<str> for ImString {
fn as_ref(&self) -> &str {
self.content.as_ref()
}
}
impl From<String> for ImString {
fn from(t:String) -> Self {
Self::new(t)
}
}
impl From<&String> for ImString {
fn from(t:&String) -> Self {
Self::new(t)
}
}
impl From<&&String> for ImString {
fn from(t:&&String) -> Self {
Self::new(*t)
}
}
impl From<&str> for ImString {
fn from(t:&str) -> Self {
Self::new(t)
}
}
impl From<&&str> for ImString {
fn from(t:&&str) -> Self {
Self::new(*t)
}
}
impl PartialEq<String> for ImString {
fn eq(&self, other:&String) -> bool {
self.content.as_ref().eq(other)
}
}
impl PartialEq<ImString> for String {
fn eq(&self, other:&ImString) -> bool {
self.eq(other.content.as_ref())
}
}
// === Macros ===
/// Defines a newtype for `ImString`.
#[macro_export]
macro_rules! im_string_newtype {
($($(#$meta:tt)* $name:ident),* $(,)?) => {$(
$(#$meta)*
#[derive(Clone,CloneRef,Debug,Default,Eq,Hash,PartialEq)]
pub struct $name {
content : ImString
}
impl $name {
/// Constructor.
pub fn new(content:impl Into<ImString>) -> Self {
let content = content.into();
Self {content}
}
}
impl Deref for $name {
type Target = str;
fn deref(&self) -> &Self::Target {
&self.content
}
}
impl AsRef<$name> for $name {
fn as_ref(&self) -> &$name {
self
}
}
impl AsRef<ImString> for $name {
fn as_ref(&self) -> &ImString {
self.content.as_ref()
}
}
impl AsRef<String> for $name {
fn as_ref(&self) -> &String {
self.content.as_ref()
}
}
impl AsRef<str> for $name {
fn as_ref(&self) -> &str {
self.content.as_ref()
}
}
impl From<String> for $name {
fn from(t:String) -> Self {
Self::new(t)
}
}
impl From<&String> for $name {
fn from(t:&String) -> Self {
Self::new(t)
}
}
impl From<&&String> for $name {
fn from(t:&&String) -> Self {
Self::new(t)
}
}
impl From<&str> for $name {
fn from(t:&str) -> Self {
Self::new(t)
}
}
impl From<&&str> for $name {
fn from(t:&&str) -> Self {
Self::new(t)
}
}
)*};
}

View File

@ -1,80 +0,0 @@
//! Type related utilities.
use super::std_reexports::*;
// ================
// === Anything ===
// ================
/// Placeholder type used to represent any value type. It is useful to define type-level relations
/// like defining an unit with any quantity, let it be distance or mass.
#[derive(Clone,Copy,Debug,PartialEq)]
pub struct Anything {}
// ===================
// === TypeDisplay ===
// ===================
/// Like `Display` trait but for types. However, unlike `Display` it defaults to
/// `impl::any::type_name` if not provided with explicit implementation.
pub trait TypeDisplay {
fn type_display() -> String;
}
impl<T> TypeDisplay for T {
default fn type_display() -> String {
type_name::<Self>().to_string()
}
}
/// Formats the type for the user-facing output.
pub fn type_display<T:TypeDisplay>() -> String {
<T as TypeDisplay>::type_display()
}
// =============
// === Value ===
// =============
/// Defines relation between types and values, like between `True` and `true`.
pub trait KnownTypeValue {
/// The value-level counterpart of this type-value.
type Value;
/// The value of this type-value.
fn value() -> Self::Value;
}
pub type TypeValue<T> = <T as KnownTypeValue>::Value;
// =======================
// === Type-level Bool ===
// =======================
/// Type level `true` value.
#[derive(Clone,Copy,Debug)]
pub struct True {}
/// Type level `false` value.
#[derive(Clone,Copy,Debug)]
pub struct False {}
impl KnownTypeValue for True {
type Value = bool;
fn value() -> Self::Value {
true
}
}
impl KnownTypeValue for False {
type Value = bool;
fn value() -> Self::Value {
false
}
}

View File

@ -1,133 +0,0 @@
//! This type defines Wrap / Unwrap utilities. Unwrap is like `Deref` but does not implement
//! `impl<'a, T> Unwrap for &'a T` in order to make it less error prone. `Wrap` is like `pure` in
//! applicative functors if lifts a value to the specific type.
use crate::std_reexports::*;
// ===============
// === Wrapper ===
// ===============
/// Trait for any type which wraps other type. See docs of `Wrapper` to learn more.
pub trait HasContent {
type Content : ?Sized;
}
/// Accessor for the wrapped value.
pub type Content<T> = <T as HasContent>::Content;
/// Trait which enables `Sized` super-bound on the `Content` type.
pub trait HasSizedContent = HasContent where Content<Self> : Sized;
/// Trait for objects which wrap values. Please note that this implements safe wrappers, so the
/// object - value relation must be bijective.
pub trait Wrapper = Wrap + ContentRef;
/// Wrapping utility for values.
pub trait Wrap : HasSizedContent {
/// Wraps the value and returns the wrapped type.
fn wrap(t:Self::Content) -> Self;
}
/// Unwrapping utility for wrapped types.
///
/// Please note that this trait is very similar to the Deref trait. However, there is a very
/// important difference. Unlike `Deref`, there is no `impl<'a, T> Unwrap for &'a T` defined. The
/// existence of such impl is very error prone when writing complex impls. The `Deref` docs warn
/// about it explicitly: "[...] Because of this, Deref should only be implemented for smart pointers
/// to avoid confusion.". As an example, consider the following code which contains infinite loop:
///
/// ```compile_fail
/// pub trait HasId {
/// fn id(&self) -> usize;
/// }
///
/// // Notice the lack of bound `<T as Deref>::Target : HasId`
/// impl<T:Deref> HasId for T {
/// fn id(&self) -> usize {
/// self.deref().id()
/// }
/// }
/// ```
///
/// And the correct version:
///
/// ```compile_fail
/// pub trait HasId {
/// fn id(&self) -> usize;
/// }
///
/// // Notice the lack of bound `<T as Deref>::Target : HasId`
/// impl<T:Deref> HasId for T where <T as Deref>::Target : HasId {
/// fn id(&self) -> usize {
/// self.deref().id()
/// }
/// }
/// ```
///
/// Both versions compile fine, but the former loops for ever.
pub trait ContentRef : HasContent {
/// Unwraps this type to get the inner value.
fn content(&self) -> &Self::Content;
}
/// Runs a function on the reference to the content.
pub trait WithContent : HasSizedContent {
/// Runs a function on the reference to the content.
fn with_content<F,T>(&self,f:F) -> T where F : FnOnce(&Content<Self>) -> T;
}
/// Unwraps the content by consuming this value.
pub trait Unwrap : HasSizedContent {
/// Unwraps the content by consuming this value.
fn unwrap(self) -> Self::Content;
}
// === Utils ===
/// Wraps the value and returns the wrapped type.
pub fn wrap<T:Wrap>(t:T::Content) -> T {
T::wrap(t)
}
/// Provides reference to the content of this value.
pub fn content<T:ContentRef>(t:&T) -> &T::Content {
T::content(t)
}
/// Unwrap the content by consuming this value.
pub fn unwrap<T:Unwrap>(t:T) -> T::Content {
T::unwrap(t)
}
// === Default Impls ===
impl<T:ContentRef + HasSizedContent> WithContent for T {
fn with_content<F,S>(&self,f:F) -> S
where F : FnOnce(&Content<Self>) -> S {
f(self.content())
}
}
// TODO: This should be implemented with the marker trait overlapping rules magic.
// impl<T:Deref> Unwrap for T
// where <T as Deref>::Target: Unwrap {
// default fn unwrap(&self) -> &Self::Content {
// self.deref().unwrap()
// }
// }
// === Impls ===
impl<T:?Sized> HasContent for Rc<T> { type Content = T; }
impl<T> Wrap for Rc<T> { fn wrap(t:T) -> Self { Rc::new(t) } }
impl<T:?Sized> ContentRef for Rc<T> { fn content(&self) -> &Self::Content { self.deref() }}
impl HasContent for String { type Content = char; }
impl Wrap for String { fn wrap(t:char) -> Self { t.to_string() } }
impl<T> HasContent for Vec<T> { type Content = T; }
impl<T> Wrap for Vec<T> { fn wrap(t:T) -> Self { vec![t] } }

View File

@ -1,19 +0,0 @@
[package]
name = "shapely"
version = "0.1.0"
authors = ["Enso Team <contact@luna-lang.org>"]
edition = "2018"
[lib]
[features]
default = []
[dependencies]
shapely-macros = { version = "0.1.0" , path = "../macros" }
paste = { version = "0.1" }
derivative = { version = "1.0.3" }
shrinkwraprs = { version = "0.3.0" }
[dev-dependencies]
enso-prelude = { version = "0.1.0" , path ="../../prelude" }

View File

@ -1,45 +0,0 @@
/// Computes a cartesian product of the provided input.
///
/// For the following expression:
/// ```compile_fail
/// cartesian!(f [g] [a b c] [x y z]);
/// ```
///
/// It expands to:
/// ```compile_fail
/// f! { [g] [ [a x] [a y] [a z] [b x] [b y] [b z] [c x] [c y] [c z] ] }
/// ```
///
/// If you provide underscore as second argument, it is skipped in the ouput macro:
///
/// ```compile_fail
/// cartesian!(f _ [a b c] [x y z]);
/// ```
///
/// Expands to:
/// ```compile_fail
/// f! { [ [a x] [a y] [a z] [b x] [b y] [b z] [c x] [c y] [c z] ] }
/// ```
#[macro_export]
macro_rules! cartesian {
($f:tt [$($a:tt)*] [$($b:tt)*]) => {
$crate::_cartesian_impl!{ $f [] [$($a)*] [$($b)*] [$($b)*] }
};
}
/// Internal helper for `cartesian` macro.
#[macro_export]
macro_rules! _cartesian_impl {
([[$f:path]] $out:tt [] $b:tt $init_b:tt) => {
$f!{ $out }
};
([[$f:path] $args:tt] $out:tt [] $b:tt $init_b:tt) => {
$f!{ $args $out }
};
($f:tt $out:tt [$a:tt $($at:tt)*] [] $init_b:tt) => {
$crate::_cartesian_impl!{ $f $out [$($at)*] $init_b $init_b }
};
($f:tt [$($out:tt)*] [$a:tt $($at:tt)*] [$b:tt $($bt:tt)*] $init_b:tt) => {
$crate::_cartesian_impl!{ $f [$($out)* [$a $b]] [$a $($at)*] [$($bt)*] $init_b }
};
}

View File

@ -1,90 +0,0 @@
//! Helper code meant to be used by the code generated through usage of macros
//! from `shapely-macros` crate.
pub use shapely_macros::*;
use derivative::Derivative;
use std::ops::Generator;
use std::ops::GeneratorState;
use std::pin::Pin;
use std::marker::PhantomData;
// ==========================
// === GeneratingIterator ===
// ==========================
/// Iterates over values yielded from the wrapped `Generator`.
#[derive(Debug)]
pub struct GeneratingIterator<G: Generator>(pub G);
impl<G> Iterator for GeneratingIterator<G>
where G: Generator<Return = ()> + Unpin {
type Item = G::Yield;
fn next(&mut self) -> Option<Self::Item> {
match Pin::new(&mut self.0).resume() {
GeneratorState::Yielded(element) => Some(element),
_ => None,
}
}
}
// =====================
// === EmptyIterator ===
// =====================
/// An `Iterator` type that yields no values of the given type `T`.
#[derive(Derivative)]
#[derivative(Debug,Default(bound=""))]
pub struct EmptyIterator<T>(PhantomData<T>);
impl<T> EmptyIterator<T> {
/// Create a new empty iterator.
pub fn new() -> Self {
Default::default()
}
}
impl<T> Iterator for EmptyIterator<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
None
}
}
// =============
// === Tests ===
// =============
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn empty_iterator_works_for_any_type() {
for elem in EmptyIterator::new() {
elem: i32;
}
for elem in EmptyIterator::new() {
elem: String;
}
}
#[test]
fn generating_iterator_works() {
let generator = || {
yield 0;
yield 1;
yield 2;
};
let expected_numbers = vec!(0, 1, 2);
let generator_iter = GeneratingIterator(generator);
let collected_result: Vec<_> = generator_iter.collect();
assert_eq!(collected_result, expected_numbers);
}
}

View File

@ -1,405 +0,0 @@
// README README README README README README README README README README README
// README README README README README README README README README README README
// README README README README README README README README README README README
// This library is in a very early stage. It will be refactored and improved
// soon. It should not be reviewed now.
#![warn(unsafe_code)]
#![warn(missing_copy_implementations)]
#![warn(missing_debug_implementations)]
#![feature(generators, generator_trait)]
#![feature(specialization)]
#![feature(type_ascription)]
#![feature(overlapping_marker_traits)]
pub mod generator;
pub mod shared;
pub mod singleton;
pub mod cartesian;
pub use shapely_macros::*;
pub use generator::EmptyIterator;
pub use generator::GeneratingIterator;
use shrinkwraprs::Shrinkwrap;
/// Replaces the first argument with the second one. It is useful when creating macros which match
/// a pattern and you want to generate as many repetitions of a token as there was matches. For
/// example, when matching `$($name:ident)*`, you may want to generate as many empty tuples as
/// the number of names matched. You can do it by using `$(replace!{$name,()})*`.
#[macro_export]
macro_rules! replace {
($a:tt,$b:tt) => {$b}
}
/// Generates a newtype wrapper for the provided types. It also generates a lot of impls,
/// including Copy, Clone, Debug, Default, Display, From, Into, Deref, and DerefMut.
///
/// For the following input:
/// ```compile_fail
/// newtype_copy! {
/// AttributeIndex(usize)
/// }
/// ```
///
/// The following code is generated:
/// ```compile_fail
/// #[derive(Copy, Clone, Debug, Default, Display, From, Into)]
/// pub struct AttributeIndex(usize);
/// impl Deref for AttributeIndex {
/// type Target = usize;
/// fn deref(&self) -> &Self::Target {
/// &self.0
/// }
/// }
/// impl DerefMut for AttributeIndex {
/// fn deref_mut(&mut self) -> &mut Self::Target {
/// &mut self.0
/// }
/// }
/// ```
#[macro_export]
macro_rules! newtype_copy {
($( $(#$meta:tt)* $name:ident($type:ty); )*) => {$(
$(#$meta)*
#[derive(Copy,Clone,CloneRef,Debug,Default,Display,From,Into)]
pub struct $name($type);
impl Deref for $name {
type Target = $type;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for $name {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
)*}
}
#[macro_export]
macro_rules! derive_clone_plus {
($name:ident) => {
impl<T:Clone+Into<$name>> From<&T> for $name {
fn from(t: &T) -> Self {
t.clone().into()
}
}
}
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
use std::ops::Deref;
macro_rules! extension_struct {
($name:ident { $($field:ident : $field_type:ty),* }) => { paste::item! {
////// With_NAME_ //////
#[derive(Shrinkwrap)]
#[shrinkwrap(mutable)]
struct [<With $name>]<T>($($field_type),*, #[shrinkwrap(main_field)] T);
////// Has_NAME_ //////
pub trait [<Has $name>] {
$(fn $field(&self) -> &$field_type;)*
}
impl<T: [<Has $name Indirect>]>
[<Has $name>] for T {
$(fn $field(&self) -> &$field_type {
[<Has $name Spec1>]::$field(self)
})*
}
////// Has_NAME_Indirect //////
pub trait [<Has $name Indirect>] {}
impl<T>
[<Has $name Indirect>] for [<With $name>]<T> {}
impl<T>
[<Has $name Indirect>] for T
where T: Deref, <Self as Deref>::Target : [<Has $name>] {}
////// Has_NAME_Spec1 //////
trait [<Has $name Spec1>] {
$(fn $field(&self) -> &$field_type;)*
}
impl<T>
[<Has $name Spec1>] for [<With $name>]<T> {
$(fn $field(&self) -> &$field_type {
&self.0
})*
}
impl<T: [<Has $name Indirect>]>
[<Has $name Spec1>] for T {
$(default fn $field(&self) -> &$field_type {
[<Has $name Spec2>]::$field(self)
})*
}
////// Has_NAME_Spec2 //////
trait [<Has $name Spec2>] {
$(fn $field(&self) -> &$field_type;)*
}
impl<T: [<Has $name Indirect>]>
[<Has $name Spec2>] for T {
$(default fn $field(&self) -> &$field_type {
unreachable!();
})*
}
impl<T>
[<Has $name Spec2>] for T
where T: Deref, <Self as Deref>::Target : [<Has $name>] {
$(fn $field(&self) -> &$field_type {
self.deref().$field()
})*
}
}};
}
extension_struct!(Label {
label: String
});
extension_struct!(Foo {
t1: String
});
// ==============
// === WithID ===
// ==============
struct WithID<T>(i32, T);
impl<T> Deref for WithID<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.1
}
}
struct WithID2<T>(i32, T);
impl<T> Deref for WithID2<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.1
}
}
//// === HasID ===
//
//pub trait HasID {
// fn id(&self) -> &i32;
//}
//
//impl<T: MarkerCtxForHasID> HasID for T {
// fn id(&self) -> &i32 {
// HasIDForVariantOrAny::id(self)
// }
//}
//
//// === MarkerCtxForHasID ===
//
//pub trait MarkerCtxForHasID {}
//
//impl<T> MarkerCtxForHasID for WithID<T> {}
//
//impl<T> MarkerCtxForHasID for T
//where T: Deref, <T as Deref>::Target : HasID {}
//
//
//// === HasIDForVariantOrAny ===
//
//trait HasIDForVariantOrAny {
// fn id(&self) -> &i32;
//}
//impl<T> HasIDForVariantOrAny for WithID<T> {
// fn id(&self) -> &i32 {
// &self.0
// }
//}
//impl<T: MarkerCtxForHasID> HasIDForVariantOrAny for T {
// default fn id(&self) -> &i32 {
// HasIDForDerefOrAny::id(self)
// }
//}
//
//// === HasIDForDerefOrAny ===
//
//trait HasIDForDerefOrAny {
// fn id(&self) -> &i32;
//}
//impl<T> HasIDForDerefOrAny for T
//where T: Deref, <Self as Deref>::Target : HasID {
// fn id(&self) -> &i32 {
// self.deref().id()
// }
//}
//impl<T> HasIDForDerefOrAny for T {
// default fn id(&self) -> &i32 {
// unreachable!();
// }
//}
// === HasID ===
pub trait HasID {
fn id(&self) -> &i32;
}
//////////////////////////////////
#[overlappable]
impl<T> HasID for T
where T: Deref, <Self as Deref>::Target : HasID {
fn id(&self) -> &i32 {
self.deref().id()
}
}
impl<T: MarkerCtx_HasID> HasID for T {
fn id(&self) -> &i32 {
VariantOrAny_HasID::id(self)
}
}
// === MarkerCtx_HasID ===
#[allow(non_camel_case_types)]
pub trait MarkerCtx_HasID {}
impl<T> MarkerCtx_HasID for T
where T: Deref, <T as Deref>::Target : HasID {}
// === VariantOrAny_HasID ===
#[allow(non_camel_case_types)]
trait VariantOrAny_HasID {
fn id(&self) -> &i32;
}
impl<T: MarkerCtx_HasID> VariantOrAny_HasID for T {
default fn id(&self) -> &i32 {
DerefOrAny_HasID::id(self)
}
}
// === DerefOrAny_HasID ===
#[allow(non_camel_case_types)]
trait DerefOrAny_HasID {
fn id(&self) -> &i32;
}
impl<T> DerefOrAny_HasID for T
where T: Deref, <Self as Deref>::Target : HasID {
fn id(&self) -> &i32 {
self.deref().id()
}
}
impl<T> DerefOrAny_HasID for T {
default fn id(&self) -> &i32 {
unreachable!();
}
}
/////////////////////////////////////////////
//#[overlapping]
//impl<T> HasID for WithID<T> {
// fn id(&self) -> &i32 {
// &self.0
// }
//}
impl<T> MarkerCtx_HasID for WithID<T> {}
impl<T> VariantOrAny_HasID for WithID<T> {
fn id(&self) -> &i32 {
&self.0
}
}
//// NON-CONFLICTING:
//
//trait HasFoo2 {
// fn foo(&self) -> i32;
//}
//impl<T> HasFoo2 for T {
// default fn foo(&self) -> i32 {
// 7
// }
//}
//impl<T> HasFoo2 for WithID<T> {
// default fn foo(&self) -> i32 {
// 8
// }
//}
//
//// CONFLICTING
//
//trait HasFoo3 {
// fn foo(&self) -> i32;
//}
//impl<T> HasFoo3 for T
// where T: Deref,
// <T as Deref>::Target: HasFoo3 {
// default fn foo(&self) -> i32 {
// self.deref().foo()
// }
//}
//impl<T> HasFoo3 for WithID<T> {
// default fn foo(&self) -> i32 {
// 8
// }
//}
// =============
// === Usage ===
// =============
struct _A(i32);
type _X = WithLabel<WithID<_A>>;
fn _test<T: HasID + HasLabel> (t: T) {
println!("{:?}", t.label());
println!("{:?}", t.id());
}
fn _main() {
let v1 = WithLabel("label1".to_string(), WithID(0, _A(1)));
_test(v1); // THIS IS EXAMPLE USE CASE WHICH DOES NOT COMPILE
// println!("{}", 7.foo());
}

View File

@ -1,381 +0,0 @@
/// This module implements the `shared` macro, an utility allowing for easy definition of
/// `Rc<RefCell<...>>` wrappers.
/// This macro provides an easy way to define secure `Rc<RefCell<...>>` wrappers for a given struct.
///
/// This macro accepts a body which is very similar to normal struct definition. There are a few
/// notable differences:
/// - The first token this macro accepts should be the name of the wrapped structure.
/// - The implementation block does not have a name. It is always implemented for the struct.
/// You are allowed to provide multiple impl blocks.
///
/// This macro traverses the definition and for each function, it generates a borrowing counterpart.
/// It also handles the `new` function in a special way. Please note, that this macro generates
/// only safe bindings. If your original function returns a reference, the generated code will fail.
/// If you want to return references with some custom guard system, implement that outside of this
/// macro usage.
///
/// For the given input:
/// ```compile_fail
/// shared! { Uniform
///
/// #[derive(Clone,Copy,Debug)]
/// pub struct UniformData<Value> {
/// value: Value,
/// dirty: bool,
/// }
///
/// impl<Value:UniformValue> {
/// /// Constructor.
/// pub fn new(value:Value) -> Self {
/// let dirty = false;
/// Self {value,dirty}
/// }
///
/// /// Checks whether the uniform was changed and not yet updated.
/// pub fn check_dirty(&self) -> bool {
/// self.dirty
/// }
///
/// /// Modifies the value stored by the uniform.
/// pub fn modify<F:FnOnce(&mut Value)>(&mut self, f:F) {
/// self.set_dirty();
/// f(&mut self.value);
/// }
/// }}
/// ```
///
/// The following output will be generated:
///
/// ```compile_fail
/// #[derive(Clone,Copy,Debug)]
/// pub struct UniformData<Value> {
/// value: Value,
/// dirty: bool,
/// }
///
/// impl<Value:UniformValue> for UniformData<Value> {
/// #[doc = r###"Constructor."###]
/// pub fn new(value:Value) -> Self {
/// let dirty = false;
/// Self {value,dirty}
/// }
///
/// #[doc = r###"Checks whether the uniform was changed and not yet updated."###]
/// pub fn check_dirty(&self) -> bool {
/// self.dirty
/// }
///
/// #[doc = r###"Modifies the value stored by the uniform."###]
/// pub fn modify<F:FnOnce(&mut Value)>(&mut self, f:F) {
/// self.set_dirty();
/// f(&mut self.value);
/// }
/// }
///
/// #[derive(Clone,Copy,Debug)]
/// pub struct Uniform<Value> {
/// rc: Rc<RefCell<UniformData<Value>>>
/// }
///
/// impl<Value:UniformValue> for Uniform<Value> {
/// #[doc = r###"Constructor."###]
/// pub fn new(value:Value) -> Self {
/// let rc = Rc::new(RefCell::new(UniformData::new(value)));
/// Self {rc}
/// }
///
/// #[doc = r###"Checks whether the uniform was changed and not yet updated."###]
/// pub fn check_dirty(&self) -> bool {
/// self.rc.borrow.check_dirty()
/// }
///
/// #[doc = r###"Modifies the value stored by the uniform."###]
/// pub fn modify<F:FnOnce(&mut Value)>(&self, f:F) {
/// self.borrow_mut().modify(f)
/// }
/// }
/// ```
///
/// **Note**
/// Both the implementation as well as usage syntax of this macro will be nicer if it was
/// implemented as procedural macro. However, no IDE supports expansion of procedural macros
/// currently, so it was implemented as macro rules instead.
#[macro_export]
macro_rules! shared {
($name:ident $($in:tt)*) => {
$crate::angles_to_brackets_shallow! { shared_bracket [$name] $($in)* }
}
}
#[macro_export]
macro_rules! shared_bracket_impl {
([impl [$($impl_params:tt)*] $name:ident $name_mut:ident $([$($params:tt)*])?] [
$(
$(#[$($meta:tt)*])*
$acc:vis fn $fn_name:ident
$([$($fn_params:tt)*])? ($($fn_args:tt)*) $(-> $fn_type:ty)? $(where $($wt1:ty : $wt2:path),* )? {
$($fn_body:tt)*
}
)*
]) => {
impl <$($impl_params)*> $name_mut $(<$($params)*>)? {
$(
$(#[$($meta)*])*
$acc fn $fn_name $(<$($fn_params)*>)*
($($fn_args)*) $(-> $fn_type)? $(where $($wt1 : $wt2),* )? {$($fn_body)*}
)*
}
impl <$($impl_params)*> $name $(<$($params)*>)? {
$($crate::shared_bracket_fn! {
$name_mut :: $(#[$($meta)*])*
$acc fn $fn_name [$($($fn_params)*)*] ($($fn_args)*) $(-> $fn_type)? $(where $($wt1 : $wt2),* )?
})*
}
};
}
#[macro_export]
macro_rules! shared_bracket_fn {
( $base:ident :: $(#[$($meta:tt)*])* $acc:vis fn new $([$($params:tt)*])?
($($arg:ident : $arg_type:ty),*) $(-> $type:ty)? $(where $($wt1:ty : $wt2:path),* )? ) => {
$(#[$($meta)*])*
$acc fn new $(<$($params)*>)* ($($arg : $arg_type),*) $(-> $type)? $(where $($wt1 : $wt2),* )? {
Self { rc: Rc::new(RefCell::new($base::new($($arg),*))) }
}
};
( $base:ident :: $(#[$($meta:tt)*])* $acc:vis fn $name:ident $([$($params:tt)*])?
(&self $(,$($arg:ident : $arg_type:ty),+)?) $(-> $type:ty)? $(where $($wt1:ty : $wt2:path),* )? ) => {
$(#[$($meta)*])*
$acc fn $name $(<$($params)*>)* (&self $(,$($arg : $arg_type),*)?) $(-> $type)? $(where $($wt1 : $wt2),* )? {
self.rc.borrow().$name($($($arg),*)?)
}
};
( $base:ident :: $(#[$($meta:tt)*])* $acc:vis fn $name:ident $([$($params:tt)*])?
(&mut self $(,$($arg:ident : $arg_type:ty),+)?) $(-> $type:ty)? $(where $($wt1:ty : $wt2:path),* )? ) => {
$(#[$($meta)*])*
$acc fn $name $(<$($params)*>)* (&self $(,$($arg : $arg_type),*)?) $(-> $type)? $(where $($wt1 : $wt2),* )? {
self.rc.borrow_mut().$name($($($arg),*)?)
}
};
}
#[macro_export]
macro_rules! shared_bracket_normalized {
( [$name:ident] [
$(#[$($meta:tt)*])*
$(##[$($imeta:tt)*])*
pub struct $name_mut:ident $params:tt {
$($(#[$($field_meta:tt)*])* $field:ident : $field_type:ty),* $(,)?
}
$(impl $([$($impl_params:tt)*])? {$($impl_body:tt)*})*
]) => {
$crate::shared_struct! {
$(#[$($meta)*])*
$(##[$($imeta)*])*
pub struct $name $name_mut $params {
$($(#[$($field_meta)*])* $field : $field_type),*
}
}
$($crate::angles_to_brackets_shallow! {shared_bracket_impl
[impl [$($($impl_params)*)?] $name $name_mut $params] $($impl_body)*
})*
};
}
#[macro_export]
macro_rules! shared_struct {
(
$(#[$($meta:tt)*])*
$(##[$($imeta:tt)*])*
pub struct $name:ident $name_mut:ident [$($params:tt)*] {
$($(#[$($field_meta:tt)*])* $field:ident : $field_type:ty),* $(,)?
}
) => {
$(#[$($meta)*])*
#[derive(CloneRef)]
pub struct $name <$($params)*> { rc: Rc<RefCell<$name_mut<$($params)*>>> }
$(#[$($meta)*])*
$(#[$($imeta)*])*
pub struct $name_mut <$($params)*> { $($(#[$($field_meta)*])* $field : $field_type),* }
impl<$($params)*> Clone for $name <$($params)*> {
fn clone(&self) -> Self {
let rc = self.rc.clone();
Self {rc}
}
}
paste::item! {
$(#[$($meta)*])*
#[derive(CloneRef)]
pub struct [<Weak $name>] <$($params)*> { weak: Weak<RefCell<$name_mut<$($params)*>>> }
impl<$($params)*> Clone for [<Weak $name>] <$($params)*> {
fn clone(&self) -> Self {
let weak = self.weak.clone();
Self {weak}
}
}
impl<$($params)*> [<Weak $name>] <$($params)*> {
/// Attempts to upgrade the weak pointer to an rc, delaying dropping of the inner
/// value if successful.
pub fn upgrade(&self) -> Option<$name <$($params)*>> {
self.weak.upgrade().map(|rc| $name {rc})
}
}
impl<$($params)*> WeakElement for [<Weak $name>] <$($params)*> {
type Strong = $name <$($params)*> ;
fn new(view: &Self::Strong) -> Self {
view.downgrade()
}
fn view(&self) -> Option<Self::Strong> {
self.upgrade()
}
}
impl<$($params)*> $name <$($params)*> {
/// Downgrade the reference to weak ref.
pub fn downgrade(&self) -> [<Weak $name>] <$($params)*> {
let weak = Rc::downgrade(&self.rc);
[<Weak $name>] {weak}
}
/// Call operation with borrowed data. Should be use in implementation of wrapper
/// only.
fn with_borrowed<F,R>(&self, operation:F) -> R
where F : FnOnce(&mut $name_mut<$($params)*>) -> R {
operation(&mut self.rc.borrow_mut())
}
/// Wraps given data object into a shared handle.
pub fn new_from_data(data:$name_mut<$($params)*>) -> Self {
Self {rc:Rc::new(RefCell::new(data))}
}
/// Check if the shared pointer points to the same struct as `other`.
pub fn identity_equals(&self, other:&Self) -> bool {
Rc::ptr_eq(&self.rc,&other.rc)
}
}
}
};
}
#[macro_export]
macro_rules! angles_to_brackets_shallow {
($f:ident $f_arg:tt $($in:tt)*) => {
$crate::_angles_to_brackets_shallow! { $f $f_arg [] [] [] $($in)* }
}
}
#[macro_export]
macro_rules! _angles_to_brackets_shallow {
( $f:ident $f_arg:tt [] [$($out:tt)*] [] ) => { $crate::$f! { $f_arg [$($out)*] } };
( $f:ident $f_arg:tt [] [$($out:tt)*] [$($cout:tt)*] ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] [$($out)* $($cout)*] [] } };
( $f:ident $f_arg:tt [] [$($out:tt)*] [$($cout:tt)*] < $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [.] [$($out)* $($cout)*] [] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] << $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [. .] $out [$($cout)* <] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] <<< $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [. . .] $out [$($cout)* <<] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] <<<< $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [. . . .] $out [$($cout)* <<<] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] <<<<< $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [. . . . .] $out [$($cout)* <<<<] $($rest)* } };
( $f:ident $f_arg:tt [$($depth:tt)*] $out:tt [$($cout:tt)*] < $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [$($depth)* .] $out [$($cout)* <] $($rest)* } };
( $f:ident $f_arg:tt [$($depth:tt)*] $out:tt [$($cout:tt)*] << $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [$($depth)* . .] $out [$($cout)* <<] $($rest)* } };
( $f:ident $f_arg:tt [$($depth:tt)*] $out:tt [$($cout:tt)*] <<< $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [$($depth)* . . .] $out [$($cout)* <<<] $($rest)* } };
( $f:ident $f_arg:tt [$($depth:tt)*] $out:tt [$($cout:tt)*] <<<< $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [$($depth)* . . . .] $out [$($cout)* <<<<] $($rest)* } };
( $f:ident $f_arg:tt [$($depth:tt)*] $out:tt [$($cout:tt)*] <<<<< $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [$($depth)* . . . . .] $out [$($cout)* <<<<<] $($rest)* } };
( $f:ident $f_arg:tt [. $($depth:tt)*] $out:tt [$($cout:tt)*] -> $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [. $($depth)*] $out [$($cout)* ->] $($rest)* } };
( $f:ident $f_arg:tt [.] [$($out:tt)*] $cout:tt > $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] [$($out)* $cout] [] $($rest)* } };
( $f:ident $f_arg:tt [. .] [$($out:tt)*] [$($cout:tt)*] >> $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] [$($out)* [$($cout)* >]] [] $($rest)* } };
( $f:ident $f_arg:tt [. . .] [$($out:tt)*] [$($cout:tt)*] >>> $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] [$($out)* [$($cout)* >>]] [] $($rest)* } };
( $f:ident $f_arg:tt [. . . .] [$($out:tt)*] [$($cout:tt)*] >>>> $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] [$($out)* [$($cout)* >>>]] [] $($rest)* } };
( $f:ident $f_arg:tt [. . . . .] [$($out:tt)*] [$($cout:tt)*] >>>>> $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] [$($out)* [$($cout)* >>>>]] [] $($rest)* } };
( $f:ident $f_arg:tt [. $($depth:tt)*] $out:tt [$($cout:tt)*] > $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [$($depth)*] $out [$($cout)* >] $($rest)* } };
( $f:ident $f_arg:tt [. . $($depth:tt)*] $out:tt [$($cout:tt)*] >> $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [$($depth)*] $out [$($cout)* >>] $($rest)* } };
( $f:ident $f_arg:tt [. . . $($depth:tt)*] $out:tt [$($cout:tt)*] >>> $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [$($depth)*] $out [$($cout)* >>>] $($rest)* } };
( $f:ident $f_arg:tt [. . . . $($depth:tt)*] $out:tt [$($cout:tt)*] >>>> $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [$($depth)*] $out [$($cout)* >>>>] $($rest)* } };
( $f:ident $f_arg:tt [. . . . . $($depth:tt)*] $out:tt [$($cout:tt)*] >>>>> $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [$($depth)*] $out [$($cout)* >>>>>] $($rest)* } };
// Function output handling
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 {$($b)*}] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 {$($b)*}] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 {$($b)*}] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 {$($b)*}] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 {$($b)*}] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 {$($b)*}] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 {$($b)*}] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 {$($b)*}] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 {$($b)*}] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 {$($b)*}] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 {$($b)*}] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 {$($b)*}] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 {$($b)*}] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 {$($b)*}] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 {$($b)*}] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 {$($b)*}] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $t17:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17 {$($b)*}] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $t17:tt $t18:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17 $t18 {$($b)*}] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $t17:tt $t18:tt $t19:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17 $t18 $t19 {$($b)*}] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $t17:tt $t18:tt $t19:tt $t20:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17 $t18 $t19 $t20 {$($b)*}] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $t17:tt $t18:tt $t19:tt $t20:tt $t21:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17 $t18 $t19 $t20 $t21 {$($b)*}] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $t17:tt $t18:tt $t19:tt $t20:tt $t21:tt $t22:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17 $t18 $t19 $t20 $t21 $t22 {$($b)*}] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $t17:tt $t18:tt $t19:tt $t20:tt $t21:tt $t22:tt $t23:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17 $t18 $t19 $t20 $t21 $t22 $t23 {$($b)*}] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $t17:tt $t18:tt $t19:tt $t20:tt $t21:tt $t22:tt $t23:tt $t24:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17 $t18 $t19 $t20 $t21 $t22 $t23 $t24 {$($b)*}] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $t17:tt $t18:tt $t19:tt $t20:tt $t21:tt $t22:tt $t23:tt $t24:tt $t25:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17 $t18 $t19 $t20 $t21 $t22 $t23 $t24 $t25 {$($b)*}] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $t17:tt $t18:tt $t19:tt $t20:tt $t21:tt $t22:tt $t23:tt $t24:tt $t25:tt $t26:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17 $t18 $t19 $t20 $t21 $t22 $t23 $t24 $t25 $t26 {$($b)*}] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $t17:tt $t18:tt $t19:tt $t20:tt $t21:tt $t22:tt $t23:tt $t24:tt $t25:tt $t26:tt $t27:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17 $t18 $t19 $t20 $t21 $t22 $t23 $t24 $t25 $t26 $t27 {$($b)*}] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $t17:tt $t18:tt $t19:tt $t20:tt $t21:tt $t22:tt $t23:tt $t24:tt $t25:tt $t26:tt $t27:tt $t28:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17 $t18 $t19 $t20 $t21 $t22 $t23 $t24 $t25 $t26 $t27 $t28 {$($b)*}] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $t17:tt $t18:tt $t19:tt $t20:tt $t21:tt $t22:tt $t23:tt $t24:tt $t25:tt $t26:tt $t27:tt $t28:tt $t29:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17 $t18 $t19 $t20 $t21 $t22 $t23 $t24 $t25 $t26 $t27 $t28 $t29 {$($b)*}] $($rest)* } };
( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $t17:tt $t18:tt $t19:tt $t20:tt $t21:tt $t22:tt $t23:tt $t24:tt $t25:tt $t26:tt $t27:tt $t28:tt $t29:tt $t30:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17 $t18 $t19 $t20 $t21 $t22 $t23 $t24 $t25 $t26 $t27 $t28 $t29 $t30 {$($b)*}] $($rest)* } };
// Any token handling
( $f:ident $f_arg:tt $depth:tt $out:tt [$($cout:tt)*] $t:tt $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg $depth $out [$($cout)* $t] $($rest)* } };
}
#[macro_export]
macro_rules! shared_bracket {
([$name:ident] [$($in:tt)*]) => {
$crate::normalize_input! { shared_bracket_normalized [$name] $($in)* }
}
}
#[macro_export]
macro_rules! normalize_input {
($f:ident $f_args:tt $($in:tt)*) => {
$crate::_normalize_input! { $f $f_args [] $($in)* }
}
}
#[macro_export]
macro_rules! _normalize_input {
// Finish.
( $f:ident $f_args:tt $out:tt ) => {
$crate::$f! { $f_args $out }
};
// Structs.
( $f:ident $f_args:tt [$($out:tt)*]
$(#[$($meta:tt)*])*
pub struct $name:tt $([$($params:tt)*])? {$($body:tt)*}
$($rest:tt)*
) => {
$crate::_normalize_input! { $f $f_args
[$($out)*
$(#[$($meta)*])*
pub struct $name [$($($params)*)?] {$($body)*}
] $($rest)* }
};
// Any token.
( $f:ident $f_args:tt [$($out:tt)*] $in:tt $($rest:tt)* ) => {
$crate::_normalize_input! { $f $f_args [$($out)* $in] $($rest)* }
};
}

View File

@ -1,143 +0,0 @@
//! This module defines helpers for defining singletons and associated enum types. A singleton is
//! a type with one possible value. It is used mainly for a type level programming purposes.
/// Defines singleton types. For the following input:
/// ```compile_fail
/// define_singletons!{
/// /// A Foo!
/// Foo,
/// /// A Bar!
/// Bar,
/// }
/// ```
///
/// It expands to:
///
/// ```
/// #[allow(missing_docs)]
/// #[derive(Copy, Clone, Debug)]
/// #[doc = r###"A Foo!"###]
/// pub struct Foo;
/// impl Default for Foo {
/// fn default() -> Self {
/// Self
/// }
/// }
/// #[allow(missing_docs)]
/// #[derive(Copy, Clone, Debug)]
/// #[doc = r###"A Bar!"###]
/// pub struct Bar;
/// impl Default for Bar {
/// fn default() -> Self {
/// Self
/// }
/// }
///
/// ```
#[macro_export]
macro_rules! define_singletons {
( $( $(#$meta:tt)* $name:ident ),* $(,)? ) => {$(
#[allow(missing_docs)]
#[derive(Copy,Clone,Debug,PartialEq,Eq)]
$(#$meta)*
pub struct $name;
impl Default for $name {
fn default() -> Self {
Self
}
}
)*}
}
/// Defines an associated enum type for predefined singletons.
///
/// For the following input:
/// ```compile_fail
/// define_singleton_enum!{
/// MyEnum {
/// /// A Foo!
/// Foo,
/// /// A Bar!
/// Bar,
/// }
/// }
/// ```
///
/// It expands to:
///
/// ```compile_fail
/// #[allow(missing_docs)]
/// #[derive(Copy, Clone, Debug)]
/// pub enum MyEnum {
/// #[doc = r###"A Foo!"###]
/// Foo,
/// #[doc = r###"A Bar!"###]
/// Bar,
/// }
/// impl From<Foo> for MyEnum {
/// fn from(_: Foo) -> Self {
/// Self::Foo
/// }
/// }
/// impl From<PhantomData<Foo>> for MyEnum {
/// fn from(_: PhantomData<Foo>) -> Self {
/// Self::Foo
/// }
/// }
/// impl From<Bar> for MyEnum {
/// fn from(_: Bar) -> Self {
/// Self::Bar
/// }
/// }
/// impl From<PhantomData<Bar>> for MyEnum {
/// fn from(_: PhantomData<Bar>) -> Self {
/// Self::Bar
/// }
/// }
/// ```
#[macro_export]
macro_rules! define_singleton_enum_from {
(
$(#$meta:tt)*
$name:ident {
$( $(#$field_meta:tt)* $field:ident ),* $(,)?
}
) => {
#[allow(missing_docs)]
#[derive(Copy,Clone,Debug,PartialEq,Eq)]
$(#$meta)*
pub enum $name {
$( $(#$field_meta)* $field ),*
}
$(
impl From<$field> for $name {
fn from(_:$field) -> Self {
Self::$field
}
}
impl From<PhantomData<$field>> for $name {
fn from(_:PhantomData<$field>) -> Self {
Self::$field
}
}
)*
}
}
/// Defines singletons and an associated enum type.
/// It expands to the same as `define_singletons` and `define_singleton_enum_from`.
#[macro_export]
macro_rules! define_singleton_enum {
(
$(#$meta:tt)*
$name:ident {
$( $(#$field_meta:tt)* $field:ident ),* $(,)?
}
) => {
$crate::define_singletons! { $($(#$field_meta)* $field),* }
$crate::define_singleton_enum_from! { $(#$meta)* $name {$($(#$field_meta)* $field),*}}
}
}

View File

@ -1,174 +0,0 @@
#![feature(generators)]
#![feature(type_alias_impl_trait)]
use shapely::*;
// =============
// === Utils ===
// =============
/// To fail compilation if `T` is not `IntoIterator`.
fn is_into_iterator<T: IntoIterator>(){}
fn to_vector<T>(t: T) -> Vec<T::Item>
where T : IntoIterator,
T::Item: Copy {
t.into_iter().collect()
}
// =====================================
// === Struct with single type param ===
// =====================================
#[derive(Iterator, IteratorMut, Eq, PartialEq, Debug)]
pub struct PairTT<T>(T, T);
#[test]
fn derive_iterator_single_t() {
is_into_iterator::<& PairTT<i32>>();
is_into_iterator::<&mut PairTT<i32>>();
let get_pair = || PairTT(4, 49);
// just collect values
let pair = get_pair();
let collected = pair.iter().copied().collect::<Vec<i32>>();
assert_eq!(collected, vec![4, 49]);
// IntoIterator for &mut Val
let mut pair = get_pair();
for i in &mut pair {
*i = *i + 1
}
assert_eq!(pair, PairTT(5, 50));
// iter_mut
for i in pair.iter_mut() {
*i = *i + 1
}
assert_eq!(pair, PairTT(6, 51));
// IntoIterator for & Val
let pair = get_pair(); // not mut anymore
let mut sum = 0;
for i in &pair {
sum += i;
}
assert_eq!(sum, pair.0 + pair.1)
}
// ===================================
// === Struct with two type params ===
// ===================================
#[derive(Iterator, IteratorMut, Eq, PartialEq, Debug)]
pub struct PairUV<U,V>(U,V);
#[test]
fn two_params() {
// verify that iter uses only the last type param field
let pair = PairUV(5, 10);
assert_eq!(to_vector(pair.iter().copied()), vec![10]);
}
// ======================================
// === Struct without any type params ===
// ======================================
#[derive(Iterator, Eq, PartialEq, Debug)]
pub struct Monomorphic(i32);
#[test]
fn no_params() {
// `derive(Iterator)` is no-op for structures with no type parameters.
// We just make sure that it does not cause compilation error.
}
// ========================
// === Enumeration Type ===
// ========================
#[derive(Iterator)]
#[warn(dead_code)] // value is never read and shouldn't be
pub struct Unrecognized{ pub value : String }
#[derive(Iterator)]
pub enum Foo<U, T> {
Con1(PairUV<U, T>),
Con2(PairTT<T>),
Con3(Unrecognized)
}
#[test]
fn enum_is_into_iterator() {
is_into_iterator::<&Foo<i32, i32>>();
}
#[test]
fn enum_iter1() {
let v = Foo::Con1(PairUV(4, 50));
let mut v_iter = v.into_iter();
assert_eq!(*v_iter.next().unwrap(),50);
assert!(v_iter.next().is_none());
}
#[test]
fn enum_iter2() {
let v: Foo<i32, i32> = Foo::Con2(PairTT(6,60));
let mut v_iter = v.into_iter();
assert_eq!(*v_iter.next().unwrap(),6);
assert_eq!(*v_iter.next().unwrap(),60);
assert!(v_iter.next().is_none());
}
#[test]
fn enum_iter3() {
let v: Foo<i32, i32> = Foo::Con3(Unrecognized{value:"foo".into()});
let mut v_iter = v.into_iter();
assert!(v_iter.next().is_none());
}
// =======================
// === Dependent Types ===
// =======================
#[derive(Iterator)]
#[derive(IteratorMut)]
pub struct DependentTest<U, T> {
a:T,
b:(T,U,PairUV<U, T>),
// is never used, as it doesn't depend on `T` (last param)
#[allow(dead_code)]
c:PairTT<U>,
d:(i32, Option<Vec<T>>),
}
#[test]
fn dependent_test_iter() {
let val = DependentTest{
a : 1,
b : (2,3,PairUV(4,5)),
c : PairTT(6,6),
d : (7, Some(vec![8,9])),
};
let mut v_iter = val.into_iter();
assert_eq!(*v_iter.next().unwrap(), 1);
assert_eq!(*v_iter.next().unwrap(), 2);
// 3 is `U` in tuple
// 4 is `U` in <U,T> pair
assert_eq!(*v_iter.next().unwrap(), 5);
// 7 is `i32` in tuple
assert_eq!(*v_iter.next().unwrap(), 8);
assert_eq!(*v_iter.next().unwrap(), 9);
assert!(v_iter.next().is_none());
}

View File

@ -1,54 +0,0 @@
// This module contains dead code. Its purpose is making sure that it compiles
#![allow(dead_code)]
use enso_prelude::*;
#[derive(Clone,CloneRef)] struct StructUnit;
#[derive(Clone,CloneRef)] struct StructUnnamedEmpty();
#[derive(Clone,CloneRef)] struct StructUnnamed(Rc<i32>,Rc<String>);
#[derive(Clone,CloneRef)] struct StructNamedEmpty{}
#[derive(Clone,CloneRef)] struct StructNamed{named0:Rc<i32>,named1:Rc<String>}
#[derive(Clone,CloneRef)] enum EnumEmpty {}
#[derive(Clone,CloneRef)] enum Enum {
VariantUnit,
VariantNamedEmpty {},
VariantNamed {named0:Rc<i32>,named1:Rc<String>},
VariantUnnamedEmpty(),
VariantUnnamed(Rc<i32>,Rc<String>),
}
#[derive(CloneRef,Derivative)]
#[derivative(Clone(bound=""))]
struct StructUnnamedUnbound<T>(Rc<T>);
#[derive(CloneRef,Clone)]
#[clone_ref(bound="T:CloneRef")]
struct StructUnnamedBound<T>(T);
#[derive(CloneRef,Clone)]
#[clone_ref(bound="T:CloneRef,U:CloneRef")]
struct StructUnnamedBoundTwoPatams<T,U>(T,U);
#[derive(Clone,CloneRef)]
#[clone_ref(bound="T:Clone+Display")]
struct StructBoundGeneric<T:Display>(Rc<T>);
#[derive(CloneRef,Derivative)]
#[derivative(Clone(bound=""))]
// Note: CloneRef "knows" about `Display` bound.
struct StructGenericLifetime<'t>(Rc<&'t String>);
#[derive(CloneRef,Derivative)]
#[derivative(Clone(bound=""))]
struct StructWhereClause<T>(Rc<T>) where T:Debug;
#[derive(CloneRef,Clone)]
#[clone_ref(bound="T:CloneRef")]
// Here derive macro must correctly merge user-provided bound, generics list bound and where clause.
struct StructVariousBounds<T:Display>(T) where T:Debug;

View File

@ -1,25 +0,0 @@
[package]
name = "shapely-macros"
version = "0.1.0"
authors = ["Enso Team <contact@luna-lang.org>"]
edition = "2018"
[lib]
proc-macro = true
[features]
default = []
[dependencies]
macro-utils = { version = "0.1.0" , path = "../../macro-utils" }
proc-macro2 = "1.0"
quote = "1.0"
Inflector = "0.11.4"
itertools = "0.8.1"
boolinator = "2.4.0"
[dependencies.syn]
version = "1.0"
features = [
'extra-traits', 'visit', 'full'
]

View File

@ -1,224 +0,0 @@
use crate::prelude::*;
use macro_utils::field_names;
use macro_utils::identifier_sequence;
use macro_utils::index_sequence;
use macro_utils::path_matching_ident;
use syn::Attribute;
use syn::DeriveInput;
use syn::Data;
use syn::DataEnum;
use syn::DataStruct;
use syn::Fields;
use syn::Ident;
use syn::Lit;
use syn::Meta;
use syn::MetaNameValue;
use syn::NestedMeta;
use syn::Variant;
use syn::WhereClause;
use syn::WherePredicate;
// ==============
// === Consts ===
// ==============
/// Name of the custom attribute allowing customizing behavior of the generated `CloneRef`
/// implementation.
const CLONE_REF_ATTR:&str = "clone_ref";
/// Name of the property within customization attribute that allows defining custom bounds for
/// the generated `CloneRef` implementation.
const BOUND_NAME:&str = "bound";
// ============================
// === CloneRef for structs ===
// ============================
/// `clone_ref` function body for a given `struct` definition.
pub fn body_for_struct(ident:&Ident, data:&DataStruct) -> TokenStream {
match data.fields {
Fields::Unit =>
// Foo
quote!( #ident ),
Fields::Unnamed(ref fields) => {
let indices = index_sequence(fields.unnamed.len());
// Foo(self.0.clone_ref())
quote!(
#ident(#(self.#indices.clone_ref()),*)
)
}
Fields::Named(ref fields) => {
let names = field_names(fields);
// Foo { field0 : self.field0.clone_ref() }
quote!(
#ident {
#(#names : self.#names.clone_ref()),*
}
)
}
}
}
// ==========================
// === CloneRef for enums ===
// ==========================
/// Prepares a match arm for a single variant that `clone_ref`s such value.
pub fn arm_for_variant(data_ident:&Ident,variant:&Variant) -> TokenStream {
let fields = &variant.fields;
let variant_ident = &variant.ident;
match fields {
Fields::Unit => {
// Enum::Var => Enum::Var
quote!(
#data_ident::#variant_ident => #data_ident::#variant_ident
)
}
Fields::Named(fields) => {
let names = field_names(fields);
// Enum::Var {field0} => Enum::Var {field0 : field0.clone_ref()}
quote!(
#data_ident::#variant_ident { #(#names),* } =>
#data_ident::#variant_ident {
#( #names : #names.clone_ref() ),*
}
)
}
Fields::Unnamed(fields) => {
let names = identifier_sequence(fields.unnamed.len());
// Enum::Var(field0) => Enum::Var(field0.clone_ref())
quote!(
#data_ident::#variant_ident(#(#names),*) =>
#data_ident::#variant_ident(
#( #names.clone_ref() ),*
)
)
}
}
}
/// `clone_ref` function body for a given `enum` definition.
pub fn body_for_enum(ident:&Ident, data:&DataEnum) -> TokenStream {
if data.variants.is_empty() {
quote!(panic!("There cannot exist value of empty enum, so its clone_ref must not be called."))
} else {
let make_arm = |variant| arm_for_variant(ident,variant);
let arms = data.variants.iter().map(make_arm);
quote!(
match self { #(#arms),* }
)
}
}
// ============================
// === Bounds customization ===
// ============================
/// Checks if the given attribute is our customization attribute.
pub fn is_clone_ref_customization(attr:&Attribute) -> bool {
path_matching_ident(&attr.path,CLONE_REF_ATTR)
}
/// Checks if the given Meta name-val pair defines user-provided bounds.
pub fn is_custom_bound(name_val:&MetaNameValue) -> bool {
path_matching_ident(&name_val.path,BOUND_NAME)
}
/// If this is our customization attribute, we retrieve user-provided bounds for the generated
/// `CloneRef` implementation.
///
/// Returns `None` is this is third-party attribute.
/// Panics if this is our attribute but the syntax is not correct.
pub fn clone_ref_bounds(attr:&Attribute) -> Option<Vec<WherePredicate>> {
// Silently ignore foreign attributes. Be picky only about our one.
is_clone_ref_customization(attr).then(())?;
let meta = attr.parse_meta().expect("Failed to parse attribute contents.");
let list = match meta {
Meta::List(ml) => ml.nested,
_ => panic!("Attribute contents does not conform to meta item."),
};
if list.len() > 1 {
panic!("Only a single entry within `{}` attribute is allowed.",CLONE_REF_ATTR);
}
let bound_value = match list.first() {
Some(NestedMeta::Meta(Meta::NameValue(name_val))) => {
if is_custom_bound(name_val) {
&name_val.lit
} else {
panic!("`{}` attribute can define value only for `{}`.",CLONE_REF_ATTR,BOUND_NAME)
}
}
Some(_) =>
panic!("`{}` attribute must contain a single name=value assignment.",CLONE_REF_ATTR),
None =>
panic!("`{}` attribute must not be empty.",CLONE_REF_ATTR),
};
let bound_str = if let Lit::Str(lit_str) = bound_value {
lit_str
} else {
panic!("`{}` value must be a string literal describing `where` predicates.",BOUND_NAME)
};
let bounds_text = format!("where {}", bound_str.value());
let bounds = syn::parse_str::<WhereClause>(&bounds_text);
let bounds = bounds.unwrap_or_else(|_| {
panic!("Failed to parse user-provided where clause: `{}`.",bounds_text)
});
let ret = bounds.predicates.into_iter().collect();
Some(ret)
}
// ===================
// === Entry Point ===
// ===================
/// Derives `CloneRef` implementation, refer to `crate::derive_clone_ref` for details.
pub fn derive
(input:proc_macro::TokenStream) -> proc_macro::TokenStream {
let decl = syn::parse_macro_input!(input as DeriveInput);
let ident = &decl.ident;
let body = match &decl.data {
Data::Struct(data_struct) => body_for_struct(ident,data_struct),
Data::Enum(data_enum) => body_for_enum(ident,data_enum),
Data::Union(_) =>
panic!("CloneRef cannot be derived for an untagged union input."),
};
let (impl_generics, ty_generics, inherent_where_clause_opt) = &decl.generics.split_for_impl();
// Where clause must contain both user-provided bounds and bounds inherent due to type
// declaration-level where clause.
let user_requested_bounds = decl.attrs.iter().filter_map(clone_ref_bounds).flatten();
let mut where_clause = macro_utils::new_where_clause(user_requested_bounds);
for inherent_where_clause in inherent_where_clause_opt {
where_clause.predicates.extend(inherent_where_clause.predicates.iter().cloned())
}
let output = quote!{
impl #impl_generics CloneRef for #ident #ty_generics
#where_clause {
fn clone_ref(&self) -> Self {
#body
}
}
impl #impl_generics From<& #ident #ty_generics> for #ident #ty_generics
#where_clause {
fn from(t:& #ident #ty_generics) -> Self {
t.clone_ref()
}
}
};
output.into()
}

View File

@ -1,449 +0,0 @@
use crate::prelude::*;
use macro_utils::fields_list;
use macro_utils::field_ident_token;
use macro_utils::type_depends_on;
use macro_utils::type_matches;
use macro_utils::ty_path_type_args;
use macro_utils::variant_depends_on;
use boolinator::Boolinator;
use inflector::Inflector;
use itertools::Itertools;
// =============
// === IsMut ===
// =============
/// Describes whether a mutable or immutable iterator is being derived.
#[derive(Clone,Copy,Debug,PartialEq)]
pub enum IsMut {
Mutable,
Immutable,
}
impl IsMut {
fn is_mut(self) -> bool {
self == IsMut::Mutable
}
/// Returns `mut` token for mutable iterator derivation.
fn to_token(self) -> Option<syn::Token![mut]> {
self.is_mut().as_some(<syn::Token![mut]>::default())
}
/// Name of method for generating iterator.
fn iter_method(self) -> TokenStream {
if self.is_mut() {
quote!(iter_mut)
} else {
quote!(iter)
}
}
}
// ======================
// === DependentValue ===
// ======================
/// A value dependent on out target parameter.
///
/// Helper methods can be used to generate code yielding values from this.
pub struct DependentValue<'t> {
/// Type of the value (ref-stripped).
pub ty : &'t syn::Type,
/// Tokens yielding the value.
pub value : TokenStream,
/// Parameter type we want to iterate over.
pub target_param: &'t syn::GenericParam,
/// Are the value yielded as reference.
pub through_ref : bool
}
impl<'t> DependentValue<'t> {
/// Returns Some when type is dependent and None otherwise.
pub fn try_new
(ty: &'t syn::Type, value:TokenStream, target_param:&'t syn::GenericParam)
-> Option<DependentValue<'t>> {
if type_depends_on(ty, target_param) {
Some(DependentValue{ty,value,target_param,through_ref:false})
} else {
None
}
}
/// Collects dependent sub-values from the tuple value.
pub fn collect_tuple
(tuple:&'t syn::TypeTuple, target_param:&'t syn::GenericParam)
-> Vec<DependentValue<'t>> {
tuple.elems.iter().enumerate().filter_map(|(ix,ty)| {
let ix = syn::Index::from(ix);
let ident = quote!(t.#ix);
DependentValue::try_new(ty,ident,target_param)
}).collect()
}
/// Generates code yielding all values of target type accessible from this
/// value.
pub fn yield_value(&self, is_mut:IsMut) -> TokenStream {
match self.ty {
syn::Type::Tuple(tuple) => self.yield_tuple_value(tuple, is_mut),
syn::Type::Path(path) => {
if type_matches(&self.ty, &self.target_param) {
self.yield_direct_value(is_mut)
} else {
self.yield_dependent_ty_path_value(path,is_mut)
}
}
_ =>
panic!("Don't know how to yield value of type {} from type {}"
, repr(&self.target_param), repr(&self.ty)),
}
}
/// Code yielding value that directly matches the target parameter type.
pub fn yield_direct_value
(&self, is_mut:IsMut) -> TokenStream {
let value = &self.value;
let opt_mut = is_mut.to_token();
let opt_ref = (!self.through_ref).as_some(quote!( & #opt_mut ));
// yield &mut value;
quote!( yield #opt_ref #value; )
}
/// Code yielding values from tuple dependent on the target parameter type.
pub fn yield_tuple_value
(&self, ty:&syn::TypeTuple,is_mut:IsMut)
-> TokenStream {
let value = &self.value;
let mut_kwd = is_mut.to_token();
let subfields = DependentValue::collect_tuple(ty, self.target_param);
let yield_sub = subfields.iter().map(|f| {
f.yield_value(is_mut)
}).collect_vec();
// yield &mut t.0;
// yield &mut t.2;
quote!( {
let t = & #mut_kwd #value;
#(#yield_sub)*
})
}
/// Obtain the type of iterator-yielded value.
///
/// Panics when given a type which is not supported for derivation, like
/// having dependent type on the non-last position.
pub fn type_path_elem_type(&self, ty_path:&'t syn::TypePath) -> &syn::Type {
let mut type_args = ty_path_type_args(ty_path);
let last_arg = match type_args.pop() {
Some(arg) => arg,
None => panic!("Type {} has no segments!", repr(&ty_path))
};
// Last and only last type argument is dependent.
for non_last_segment in type_args {
assert!(!type_depends_on(non_last_segment, self.target_param)
, "Type {} has non-last argument {} that depends on {}"
, repr(ty_path)
, repr(non_last_segment)
, repr(self.target_param)
);
}
assert!(type_depends_on(last_arg, self.target_param));
last_arg
}
/// Code yielding values from data dependent on the target parameter type.
pub fn yield_dependent_ty_path_value
(&self, ty_path:&'t syn::TypePath, is_mut:IsMut)
-> TokenStream {
let opt_mut = is_mut.to_token();
let elem_ty = self.type_path_elem_type(ty_path);
let elem = quote!(t);
let elem_info = DependentValue{
value : elem.clone(),
target_param : self.target_param,
ty : elem_ty,
through_ref : true,
};
let yield_elem = elem_info.yield_value(is_mut);
let value = &self.value;
let iter_method = if is_mut.is_mut() {
quote!(iter_mut)
} else {
quote!(iter)
};
quote! {
for #opt_mut #elem in #value.#iter_method() {
#yield_elem
}
}
}
/// Describe relevant fields of the struct definition.
pub fn collect_struct
(data:&'t syn::DataStruct, target_param:&'t syn::GenericParam)
-> Vec<DependentValue<'t>> {
let fields = fields_list(&data.fields);
let dep_field = fields.iter().enumerate().filter_map(|(i,f)| {
let ident = field_ident_token(f,i.into());
let value = quote!(t.#ident);
DependentValue::try_new(&f.ty,value,target_param)
});
dep_field.collect()
}
}
/// Parts of derivation output that are specific to enum- or struct- target.
pub struct OutputParts<'ast> {
pub iterator_tydefs : TokenStream,
pub iter_body : TokenStream,
pub iterator_params : Vec<&'ast syn::GenericParam>,
}
/// Common data used when generating derived Iterator impls.
///
/// Examples are given for `pub struct Foo<S, T> { foo: T }`
pub struct DerivingIterator<'ast> {
pub data : &'ast syn::Data, // { foo: T }
pub ident : &'ast syn::Ident, // Foo
pub params : Vec<&'ast syn::GenericParam>, // <S, T>
pub t_iterator : syn::Ident, // FooIterator{Mut}
pub iterator : syn::Ident, // foo_iterator{_mut}
pub target_param : &'ast syn::GenericParam, // T
pub is_mut : IsMut, // are we mutable iterator?
}
impl DerivingIterator<'_> {
pub fn new<'ast>
( decl :&'ast syn::DeriveInput
, target_param:&'ast syn::GenericParam
, is_mut :IsMut
) -> DerivingIterator<'ast> {
let mut_or_not = if is_mut.is_mut() { "Mut" } else { "" };
let data = &decl.data;
let params = decl.generics.params.iter().collect();
let ident = &decl.ident;
let t_iterator = format!("{}Iterator{}", ident, mut_or_not);
let iterator = t_iterator.to_snake_case();
let t_iterator = syn::Ident::new(&t_iterator, Span::call_site());
let iterator = syn::Ident::new(&iterator , Span::call_site());
DerivingIterator {
data,
ident,
params,
t_iterator,
iterator,
target_param,
is_mut,
}
}
/// Handles all enum-specific parts.
pub fn prepare_parts_enum(&self, data:&syn::DataEnum) -> OutputParts {
let opt_mut = &self.is_mut.to_token();
let t_iterator = &self.t_iterator;
let ident = &self.ident;
let target_param = &self.target_param;
let iterator_params = vec!(self.target_param);
let iterator_tydefs = quote!(
// type FooIterator<'t, U> =
// Box<dyn Iterator<Item=&'t U> + 't>;
// type FooIteratorMut<'t, U> =
// Box<dyn Iterator<Item=&'t mut U> + 't>;
type #t_iterator<'t, #(#iterator_params),*> =
Box<dyn Iterator<Item=&'t #opt_mut #target_param> + 't>;
);
// For types that use target type parameter, refer to their
// `IntoIterator` implementation. Otherwise, use `EmptyIterator`.
let arms = data.variants.iter().map(|var| {
let con = &var.ident;
let iter = if variant_depends_on(var, target_param) {
quote!(elem.into_iter())
} else {
quote!(shapely::EmptyIterator::new())
};
quote!(#ident::#con(elem) => Box::new(#iter))
});
// match t {
// Foo::Con1(elem) => Box::new(elem.into_iter()),
// Foo::Con2(elem) => Box::new(shapely::EmptyIterator::new()),
// }
let iter_body = quote!( match t { #(#arms,)* } );
OutputParts{iterator_tydefs,iter_body,iterator_params}
}
/// Handles all struct-specific parts.
pub fn prepare_parts_struct(&self, data:&syn::DataStruct) -> OutputParts {
let opt_mut = &self.is_mut.to_token();
let t_iterator = &self.t_iterator;
let target_param = &self.target_param;
let iterator_params = self.params.clone();
let iterator_tydefs = quote!(
// type FooIterator<'t, T> = impl Iterator<Item = &'t T>;
// type FooIteratorMut<'t, T> = impl Iterator<Item = &'t mut T>;
type #t_iterator<'t, #(#iterator_params),*> =
impl Iterator<Item = &'t #opt_mut #target_param>;
);
let matched_fields = DependentValue::collect_struct(data, target_param);
let yield_fields = matched_fields.iter().map(|field| {
field.yield_value(self.is_mut)
}).collect_vec();
// shapely::EmptyIterator::new()
let empty_body = quote! { shapely::EmptyIterator::new() };
// shapely::GeneratingIterator(move || {
// yield &t.foo;
// })
// shapely::GeneratingIterator(move || {
// yield &mut t.foo;
// })
let body = quote! {
shapely::GeneratingIterator
(move || { #(#yield_fields)* })
};
let iter_body = if matched_fields.is_empty() {
empty_body
} else {
body
};
OutputParts{iterator_tydefs,iter_body,iterator_params}
}
/// Handles common (between enum and struct) code and assembles it all
/// into a final derivation output.
#[allow(clippy::cognitive_complexity)]
pub fn assemble_output(&self, parts:OutputParts) -> TokenStream {
let iterator_tydefs = &parts.iterator_tydefs;
let iter_body = &parts.iter_body;
let iterator_params = &parts.iterator_params;
let opt_mut = &self.is_mut.to_token();
let iterator = &self.iterator;
let t_iterator = &self.t_iterator;
let params = &self.params;
let ident = &self.ident;
let target_param = &self.target_param;
let iter_method = &self.is_mut.iter_method();
quote!{
#iterator_tydefs
// pub fn foo_iterator<'t, T>
// (t: &'t Foo<T>) -> FooIterator<'t, T> {
// shapely::GeneratingIterator(move || {
// yield &t.foo;
// })
// }
// pub fn foo_iterator_mut<'t, T>
// (t: &'t mut Foo<T>) -> FooIteratorMut<'t, T> {
// shapely::GeneratingIterator(move || {
// yield &t.foo;
// })
// }
pub fn #iterator<'t, #(#params),*>
(t: &'t #opt_mut #ident<#(#params),*>)
-> #t_iterator<'t, #(#iterator_params),*> {
#iter_body
}
// impl<'t, T>
// IntoIterator for &'t Foo<T> {
// type Item = &'t T;
// type IntoIter = FooIterator<'t, T>;
// fn into_iter(self) -> FooIterator<'t, T> {
// foo_iterator(self)
// }
// }
//
// impl<'t, T>
// IntoIterator for &'t mut Foo<T> {
// type Item = &'t mut T;
// type IntoIter = FooIteratorMut<'t, T>;
// fn into_iter(self) -> FooIteratorMut<'t, T> {
// foo_iterator_mut(self)
// }
// }
impl<'t, #(#params),*>
IntoIterator for &'t #opt_mut #ident<#(#params),*> {
type Item = &'t #opt_mut #target_param;
type IntoIter = #t_iterator<'t, #(#iterator_params),*>;
fn into_iter(self) -> #t_iterator<'t, #(#iterator_params),*> {
#iterator(self)
}
}
// impl Foo<T> {
// pub fn iter(&self) -> FooIterator<'_, T> {
// #foo_iterator(self)
// }
// pub fn iter_mut(&mut self) -> FooIteratorMut<'_, T> {
// #foo_iterator_mut (self)
// }
// }
impl<#(#params),*> #ident<#(#params),*> {
pub fn #iter_method
(& #opt_mut self) -> #t_iterator<'_, #(#iterator_params),*> {
#iterator(self)
}
}
}
}
/// Generates the code that derives desired iterator.
pub fn output(&self) -> TokenStream {
let parts = match self.data {
syn::Data::Struct(data) => self.prepare_parts_struct(data),
syn::Data::Enum (data) => self.prepare_parts_enum (data),
_ =>
panic!("Only Structs and Enums can derive(Iterator)!"),
};
self.assemble_output(parts)
}
}
/// Common implementation for deriving iterator through `derive(Iterator)` and
/// `derive(IteratorMut)`.
pub fn derive
(input:proc_macro::TokenStream, is_mut:IsMut) -> proc_macro::TokenStream {
let decl = syn::parse_macro_input!(input as syn::DeriveInput);
let params = &decl.generics.params.iter().collect::<Vec<_>>();
let output = match params.last() {
Some(last_param) => {
let der = DerivingIterator::new(&decl,last_param,is_mut);
der.output()
}
None =>
TokenStream::new(),
};
output.into()
}
// Note [Expansion Example]
// ~~~~~~~~~~~~~~~~~~~~~~~~
// In order to make the definition easier to read, an example expansion of the
// following definition was provided for each quotation:
//
// #[derive(Iterator)]
// pub struct Foo<S, T> { foo: T }
//
// When different output is generated for mutable and immutable content, both
// expansions are presented.
//
// For examples that are enum-specific rather than struct-specific, the
// following definition is assumed:
//
// #[derive(Iterator)]
// pub enum Foo<T> {
// Con1(Bar<T>),
// Con2(Baz),
// }

View File

@ -1,98 +0,0 @@
//! This crate defines a custom derive macro `Iterator`. Should not be used
//! directly, but only through `shapely` crate, as it provides utilities
//! necessary for the generated code to compile.
#![feature(bool_to_option)]
#![feature(exact_size_is_empty)]
#![warn(missing_docs)]
#![warn(trivial_casts)]
#![warn(trivial_numeric_casts)]
#![warn(unused_import_braces)]
#![warn(unused_qualifications)]
#![warn(unsafe_code)]
#![warn(missing_copy_implementations)]
#![warn(missing_debug_implementations)]
extern crate proc_macro;
mod derive_clone_ref;
mod derive_iterator;
mod overlappable;
mod prelude {
pub use macro_utils::repr;
pub use proc_macro2::Span;
pub use proc_macro2::TokenStream;
pub use quote::quote;
}
use crate::derive_iterator::IsMut;
/// For `struct Foo<T>` or `enum Foo<T>` provides:
/// * `IntoIterator` implementations for `&'t Foo<T>`, `iter` and `into_iter`
/// methods.
///
/// The iterators will:
/// * for structs: go over each field that declared type is same as the
/// struct's last type parameter.
/// * enums: delegate to current constructor's nested value's iterator.
///
/// Enums are required to use only a single element tuple-like variant. This
/// limitation should be lifted in the future.
///
/// Any dependent type stored in struct, tuple or wrapped in enum should have
/// dependency only in its last type parameter. All dependent types that are not
/// tuples nor directly the yielded type, are required to provide `iter` method
/// that returns a compatible iterator (possible also derived).
///
/// Caller must have the following features enabled:
/// ```
/// #![feature(generators)]
/// #![feature(type_alias_impl_trait)]
/// ```
///
/// When used on type that takes no type parameters, like `struct Foo`, does
/// nothing but yields no errors.
#[proc_macro_derive(Iterator)]
pub fn derive_iterator
(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
derive_iterator::derive(input,IsMut::Immutable)
}
/// Same as `derive(Iterator)` but generates mutable iterator.
///
/// It is separate, as some types allow deriving immutable iterator but ont the
/// mutable one.
#[proc_macro_derive(IteratorMut)]
pub fn derive_iterator_mut
(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
derive_iterator::derive(input,IsMut::Mutable)
}
/// Derives `CloneRef` implementation for given type. It performs `clone_ref` on every member
/// field. The input type must implement `Clone` and its every field must implement `CloneRef`.
///
/// For generic types no bounds are introduced in the generated implementation. To customize this
/// behavior user might add `#[clone_ref(bound="…")]` attribute. Then the generated implementation
/// will use the provided bounds.
///
/// Moreover, for a given struct `X` this macro generates also `impl From<&X> for X` which uses
/// `CloneRef` under the hood. The semantics of `CloneRef` makes each object to naturally provide
/// transformation from reference to an owned type.
///
/// Supported inputs are structs (unit, named, unnamed), enums (with unit, named, unnamed and no
/// variants at all). Unions are currently not supported.
#[proc_macro_derive(CloneRef, attributes(clone_ref))]
pub fn derive_clone_ref
(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
derive_clone_ref::derive(input)
}
#[allow(missing_docs)]
#[proc_macro_attribute]
pub fn overlappable
( attrs : proc_macro::TokenStream
, input : proc_macro::TokenStream
) -> proc_macro::TokenStream {
overlappable::overlappable(attrs,input)
}

View File

@ -1,50 +0,0 @@
use crate::prelude::*;
use proc_macro2::Ident;
pub fn overlappable
( attrs : proc_macro::TokenStream
, input : proc_macro::TokenStream
) -> proc_macro::TokenStream {
let _attrs: TokenStream = attrs.into();
let decl = syn::parse_macro_input!(input as syn::ItemImpl);
// let mut path = decl.trait_.unwrap().1.clone();
// let path = path.segments.last_mut().iter().map(|ident| {
// Ident::new(&format!("MarketCtx_{}", repr(ident)) , Span::call_site());
// });
let mut marker_ctx_impl = decl;
let mut trait_ = marker_ctx_impl.trait_.as_mut();
trait_.iter_mut().for_each(|t| {
let path = &mut t.1;
path.segments.last_mut().iter_mut().for_each(|s| {
let rr = repr(&s);
s.ident = Ident::new(&format!("MarketCtx_{}", rr) , Span::call_site());
});
});
// let mut marker_ctx_impl = decl.clone();
// let path = &mut marker_ctx_impl.trait_.as_mut().unwrap().1;
// path.segments.last_mut().iter_mut().for_each(|s| {
// let rr = repr(&s);
// s.ident = Ident::new(&format!("MarketCtx_{}", rr) , Span::call_site());
// });
// let name = repr(path);
// let marker_ctx_impl = syn::ItemImpl {
// .. decl
// };
let _output_tmp = quote! {
#marker_ctx_impl
};
let output = quote! {
};
// println!("------------------");
// println!("{}", output_tmp);
output.into()
}

View File

@ -11,7 +11,7 @@ default = ["console_error_panic_hook"]
[dependencies]
data = { version = "0.1.0" , path = "../../data" }
enso-prelude = { version = "0.1.0" , path = "../../prelude" }
enso-prelude = { version = "0.1.0" }
logger = { version = "0.1.0" , path = "../../logger" }
console_error_panic_hook = { version = "0.1.1" , optional = true }

View File

@ -9,7 +9,7 @@ edition = "2018"
[dependencies]
web-test-proc-macro = { version = "0.1.0" , path = "../web-test-proc-macro" }
ensogl = { version = "0.1.0" , path = "../../ensogl" }
enso-prelude = { version = "0.1.0" , path = "../prelude" }
enso-prelude = { version = "0.1.0" }
ensogl-system-web = { version = "0.1.0" , path = "../system/web" }
wasm-bindgen = { version = "=0.2.58", features = ["nightly"] }