├── .gitignore ├── .travis.yml ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md └── src ├── core ├── error.rs ├── mod.rs ├── object.rs └── runtime.rs ├── lib.rs └── objects ├── class.rs ├── mod.rs └── thread.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | 4 | .vscode/* 5 | !.vscode/settings.json 6 | !.vscode/tasks.json 7 | !.vscode/launch.json 8 | !.vscode/extensions.json -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # 2 | 3 | language: rust 4 | install: 5 | - rustup component add clippy 6 | script: 7 | - cargo clippy 8 | - cargo test 9 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "arrayvec" 5 | version = "0.4.10" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | dependencies = [ 8 | "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", 9 | ] 10 | 11 | [[package]] 12 | name = "autocfg" 13 | version = "0.1.2" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | 16 | [[package]] 17 | name = "backtrace" 18 | version = "0.3.30" 19 | source = "registry+https://github.com/rust-lang/crates.io-index" 20 | dependencies = [ 21 | "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 22 | "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", 23 | "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 24 | "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", 25 | "rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", 26 | ] 27 | 28 | [[package]] 29 | name = "backtrace-sys" 30 | version = "0.1.28" 31 | source = "registry+https://github.com/rust-lang/crates.io-index" 32 | dependencies = [ 33 | "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", 34 | "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", 35 | ] 36 | 37 | [[package]] 38 | name = "bitflags" 39 | version = "1.1.0" 40 | source = "registry+https://github.com/rust-lang/crates.io-index" 41 | 42 | [[package]] 43 | name = "cc" 44 | version = "1.0.37" 45 | source = "registry+https://github.com/rust-lang/crates.io-index" 46 | 47 | [[package]] 48 | name = "cfg-if" 49 | version = "0.1.9" 50 | source = "registry+https://github.com/rust-lang/crates.io-index" 51 | 52 | [[package]] 53 | name = "cloudabi" 54 | version = "0.0.3" 55 | source = "registry+https://github.com/rust-lang/crates.io-index" 56 | dependencies = [ 57 | "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 58 | ] 59 | 60 | [[package]] 61 | name = "crossbeam" 62 | version = "0.7.2" 63 | source = "registry+https://github.com/rust-lang/crates.io-index" 64 | dependencies = [ 65 | "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 66 | "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 67 | "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 68 | "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 69 | "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 70 | "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", 71 | ] 72 | 73 | [[package]] 74 | name = "crossbeam-channel" 75 | version = "0.3.9" 76 | source = "registry+https://github.com/rust-lang/crates.io-index" 77 | dependencies = [ 78 | "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", 79 | ] 80 | 81 | [[package]] 82 | name = "crossbeam-deque" 83 | version = "0.7.1" 84 | source = "registry+https://github.com/rust-lang/crates.io-index" 85 | dependencies = [ 86 | "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 87 | "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", 88 | ] 89 | 90 | [[package]] 91 | name = "crossbeam-epoch" 92 | version = "0.7.2" 93 | source = "registry+https://github.com/rust-lang/crates.io-index" 94 | dependencies = [ 95 | "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", 96 | "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 97 | "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", 98 | "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 99 | "memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 100 | "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 101 | ] 102 | 103 | [[package]] 104 | name = "crossbeam-queue" 105 | version = "0.1.2" 106 | source = "registry+https://github.com/rust-lang/crates.io-index" 107 | dependencies = [ 108 | "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", 109 | ] 110 | 111 | [[package]] 112 | name = "crossbeam-utils" 113 | version = "0.6.6" 114 | source = "registry+https://github.com/rust-lang/crates.io-index" 115 | dependencies = [ 116 | "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 117 | "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 118 | ] 119 | 120 | [[package]] 121 | name = "failure" 122 | version = "0.1.5" 123 | source = "registry+https://github.com/rust-lang/crates.io-index" 124 | dependencies = [ 125 | "backtrace 0.3.30 (registry+https://github.com/rust-lang/crates.io-index)", 126 | "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 127 | ] 128 | 129 | [[package]] 130 | name = "failure_derive" 131 | version = "0.1.5" 132 | source = "registry+https://github.com/rust-lang/crates.io-index" 133 | dependencies = [ 134 | "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", 135 | "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", 136 | "syn 0.15.36 (registry+https://github.com/rust-lang/crates.io-index)", 137 | "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", 138 | ] 139 | 140 | [[package]] 141 | name = "hulunbuir" 142 | version = "0.2.4" 143 | source = "registry+https://github.com/rust-lang/crates.io-index" 144 | dependencies = [ 145 | "crossbeam 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 146 | "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 147 | "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 148 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 149 | ] 150 | 151 | [[package]] 152 | name = "lazy_static" 153 | version = "1.3.0" 154 | source = "registry+https://github.com/rust-lang/crates.io-index" 155 | 156 | [[package]] 157 | name = "libc" 158 | version = "0.2.60" 159 | source = "registry+https://github.com/rust-lang/crates.io-index" 160 | 161 | [[package]] 162 | name = "lock_api" 163 | version = "0.3.1" 164 | source = "registry+https://github.com/rust-lang/crates.io-index" 165 | dependencies = [ 166 | "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 167 | ] 168 | 169 | [[package]] 170 | name = "log" 171 | version = "0.4.8" 172 | source = "registry+https://github.com/rust-lang/crates.io-index" 173 | dependencies = [ 174 | "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 175 | ] 176 | 177 | [[package]] 178 | name = "memoffset" 179 | version = "0.5.1" 180 | source = "registry+https://github.com/rust-lang/crates.io-index" 181 | dependencies = [ 182 | "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 183 | ] 184 | 185 | [[package]] 186 | name = "nodrop" 187 | version = "0.1.13" 188 | source = "registry+https://github.com/rust-lang/crates.io-index" 189 | 190 | [[package]] 191 | name = "parking_lot" 192 | version = "0.9.0" 193 | source = "registry+https://github.com/rust-lang/crates.io-index" 194 | dependencies = [ 195 | "lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 196 | "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", 197 | "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 198 | ] 199 | 200 | [[package]] 201 | name = "parking_lot_core" 202 | version = "0.6.2" 203 | source = "registry+https://github.com/rust-lang/crates.io-index" 204 | dependencies = [ 205 | "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 206 | "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 207 | "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", 208 | "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", 209 | "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 210 | "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", 211 | "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", 212 | ] 213 | 214 | [[package]] 215 | name = "proc-macro2" 216 | version = "0.4.30" 217 | source = "registry+https://github.com/rust-lang/crates.io-index" 218 | dependencies = [ 219 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 220 | ] 221 | 222 | [[package]] 223 | name = "quote" 224 | version = "0.6.12" 225 | source = "registry+https://github.com/rust-lang/crates.io-index" 226 | dependencies = [ 227 | "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", 228 | ] 229 | 230 | [[package]] 231 | name = "redox_syscall" 232 | version = "0.1.56" 233 | source = "registry+https://github.com/rust-lang/crates.io-index" 234 | 235 | [[package]] 236 | name = "rustc-demangle" 237 | version = "0.1.15" 238 | source = "registry+https://github.com/rust-lang/crates.io-index" 239 | 240 | [[package]] 241 | name = "rustc_version" 242 | version = "0.2.3" 243 | source = "registry+https://github.com/rust-lang/crates.io-index" 244 | dependencies = [ 245 | "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 246 | ] 247 | 248 | [[package]] 249 | name = "scopeguard" 250 | version = "1.0.0" 251 | source = "registry+https://github.com/rust-lang/crates.io-index" 252 | 253 | [[package]] 254 | name = "semver" 255 | version = "0.9.0" 256 | source = "registry+https://github.com/rust-lang/crates.io-index" 257 | dependencies = [ 258 | "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 259 | ] 260 | 261 | [[package]] 262 | name = "semver-parser" 263 | version = "0.7.0" 264 | source = "registry+https://github.com/rust-lang/crates.io-index" 265 | 266 | [[package]] 267 | name = "shattuck" 268 | version = "0.2.0" 269 | dependencies = [ 270 | "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 271 | "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 272 | "hulunbuir 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", 273 | "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 274 | ] 275 | 276 | [[package]] 277 | name = "smallvec" 278 | version = "0.6.10" 279 | source = "registry+https://github.com/rust-lang/crates.io-index" 280 | 281 | [[package]] 282 | name = "syn" 283 | version = "0.15.36" 284 | source = "registry+https://github.com/rust-lang/crates.io-index" 285 | dependencies = [ 286 | "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", 287 | "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", 288 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 289 | ] 290 | 291 | [[package]] 292 | name = "synstructure" 293 | version = "0.10.2" 294 | source = "registry+https://github.com/rust-lang/crates.io-index" 295 | dependencies = [ 296 | "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", 297 | "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", 298 | "syn 0.15.36 (registry+https://github.com/rust-lang/crates.io-index)", 299 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 300 | ] 301 | 302 | [[package]] 303 | name = "unicode-xid" 304 | version = "0.1.0" 305 | source = "registry+https://github.com/rust-lang/crates.io-index" 306 | 307 | [[package]] 308 | name = "winapi" 309 | version = "0.3.7" 310 | source = "registry+https://github.com/rust-lang/crates.io-index" 311 | dependencies = [ 312 | "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 313 | "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 314 | ] 315 | 316 | [[package]] 317 | name = "winapi-i686-pc-windows-gnu" 318 | version = "0.4.0" 319 | source = "registry+https://github.com/rust-lang/crates.io-index" 320 | 321 | [[package]] 322 | name = "winapi-x86_64-pc-windows-gnu" 323 | version = "0.4.0" 324 | source = "registry+https://github.com/rust-lang/crates.io-index" 325 | 326 | [metadata] 327 | "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" 328 | "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" 329 | "checksum backtrace 0.3.30 (registry+https://github.com/rust-lang/crates.io-index)" = "ada4c783bb7e7443c14e0480f429ae2cc99da95065aeab7ee1b81ada0419404f" 330 | "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" 331 | "checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" 332 | "checksum cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "39f75544d7bbaf57560d2168f28fd649ff9c76153874db88bdbdfd839b1a7e7d" 333 | "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" 334 | "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" 335 | "checksum crossbeam 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2d818a4990769aac0c7ff1360e233ef3a41adcb009ebb2036bf6915eb0f6b23c" 336 | "checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" 337 | "checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" 338 | "checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" 339 | "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" 340 | "checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" 341 | "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" 342 | "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" 343 | "checksum hulunbuir 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6503cbaa83b084e1a1f1705d5b87f6ab2b81ff671514a52b05755bcf8a8539be" 344 | "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" 345 | "checksum libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d44e80633f007889c7eff624b709ab43c92d708caad982295768a7b13ca3b5eb" 346 | "checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" 347 | "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" 348 | "checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" 349 | "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" 350 | "checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" 351 | "checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" 352 | "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" 353 | "checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db" 354 | "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" 355 | "checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af" 356 | "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 357 | "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" 358 | "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 359 | "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 360 | "checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" 361 | "checksum syn 0.15.36 (registry+https://github.com/rust-lang/crates.io-index)" = "8b4f551a91e2e3848aeef8751d0d4eec9489b6474c720fd4c55958d8d31a430c" 362 | "checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" 363 | "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" 364 | "checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" 365 | "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 366 | "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 367 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "shattuck" 3 | version = "0.2.0" 4 | authors = ["cowsay"] 5 | edition = "2018" 6 | 7 | description = "Rust-based script programming language." 8 | license = "MIT" 9 | readme = "README.md" 10 | documentation = "https://docs.rs/shattuck" 11 | homepage = "https://github.com/whoiscc/shattuck" 12 | repository = "https://github.com/whoiscc/shattuck" 13 | 14 | [dependencies] 15 | failure = "^0.1.5" 16 | failure_derive = "^0.1.1" 17 | hulunbuir = "^0.2.4" 18 | parking_lot = "^0.9" 19 | 20 | [dev-dependencies] 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2019 Correctizer 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Shattuck 2 | 3 | [![Build Status](https://travis-ci.com/whoiscc/shattuck.svg?branch=master)](https://travis-ci.com/whoiscc/shattuck) 4 | [![Doc](https://docs.rs/shattuck/badge.svg)](https://docs.rs/shattuck) 5 | 6 | Shattuck is a script programming language powered by Rust. Have a look at `examples/main.rs` to find out some basic usage. 7 | 8 | Check out [article series on Zhihu][1] (in Chinese and few in terrible English). 9 | 10 | [1]: https://zhuanlan.zhihu.com/p/65376093 11 | -------------------------------------------------------------------------------- /src/core/error.rs: -------------------------------------------------------------------------------- 1 | // 2 | 3 | #[derive(Debug, Fail)] 4 | pub enum Error { 5 | #[fail(display = "type mismatch")] 6 | TypeMismatch, 7 | #[fail(display = "object is used by others")] 8 | BusyObject, 9 | #[fail(display = "not callable")] 10 | NotCallable, 11 | #[fail(display = "pop empty stack")] 12 | ExhaustedFrame, 13 | #[fail(display = "no parent frame")] 14 | NoParentFrame, 15 | } 16 | -------------------------------------------------------------------------------- /src/core/mod.rs: -------------------------------------------------------------------------------- 1 | // 2 | 3 | pub mod error; 4 | // pub mod memory; 5 | pub mod object; 6 | pub mod runtime; 7 | -------------------------------------------------------------------------------- /src/core/object.rs: -------------------------------------------------------------------------------- 1 | // 2 | 3 | use std::any::Any; 4 | 5 | use crate::core::error::Error; 6 | 7 | use hulunbuir::{Keep, Address}; 8 | 9 | pub struct Object { 10 | content: Box, 11 | keep: fn(&Object) -> Vec
, 12 | } 13 | 14 | impl Keep for Object { 15 | fn with_keep(&self, f: F) { 16 | f(&(self.keep)(self)) 17 | } 18 | } 19 | 20 | fn keep_helper(object: &Object) -> Vec
{ 21 | let mut keep_list = Vec::new(); 22 | object.downcast_ref::().unwrap().with_keep(|list| keep_list = list.to_vec()); 23 | keep_list 24 | } 25 | 26 | impl Object { 27 | pub fn new(content: T) -> Self { 28 | Object { 29 | content: Box::new(content), 30 | keep: keep_helper::, 31 | } 32 | } 33 | } 34 | 35 | impl Object { 36 | pub fn downcast_ref(&self) -> Result<&T, Error> { 37 | (&self.content as &dyn Any).downcast_ref().ok_or(Error::TypeMismatch) 38 | } 39 | 40 | pub fn downcast_mut(&mut self) -> Result<&mut T, Error> { 41 | (&mut self.content as &mut dyn Any).downcast_mut().ok_or(Error::TypeMismatch) 42 | } 43 | 44 | pub fn downcast(self) -> Result { 45 | Ok(*self.content.downcast().map_err(|_| Error::TypeMismatch)?) 46 | } 47 | } -------------------------------------------------------------------------------- /src/core/runtime.rs: -------------------------------------------------------------------------------- 1 | // 2 | 3 | use std::sync::Arc; 4 | 5 | use crate::core::error::Error as ShattuckError; 6 | use crate::core::object::Object; 7 | 8 | use failure::Error; 9 | use hulunbuir::{ 10 | slot::{Slot, Take}, 11 | Address, Collector as RawCollector, Keep, 12 | }; 13 | use parking_lot::Mutex; 14 | 15 | pub type Collector = Arc>>>; 16 | 17 | pub struct Runtime { 18 | memory: Collector, 19 | frame_stack: Vec
, 20 | } 21 | 22 | struct Frame { 23 | context: Address, 24 | address_stack: Vec
, 25 | parent: Option
, 26 | } 27 | 28 | impl Keep for Frame { 29 | fn with_keep(&self, mut f: F) { 30 | f(&[self.context.to_owned()]); 31 | f(&self.address_stack); 32 | if let Some(addr) = &self.parent { 33 | f(&[addr.to_owned()]); 34 | } 35 | } 36 | } 37 | 38 | impl Frame { 39 | fn new(context: Address, parent: Option
) -> Self { 40 | Self { 41 | context, 42 | address_stack: Vec::new(), 43 | parent, 44 | } 45 | } 46 | 47 | fn push_address(&mut self, address: Address) { 48 | self.address_stack.push(address); 49 | } 50 | 51 | fn pop_address(&mut self) -> Result<(), ShattuckError> { 52 | self.address_stack 53 | .pop() 54 | .ok_or(ShattuckError::ExhaustedFrame)?; 55 | Ok(()) 56 | } 57 | 58 | fn get_address(&self, index: usize) -> Result<&Address, ShattuckError> { 59 | if index == 0 || self.address_stack.len() < index { 60 | return Err(ShattuckError::ExhaustedFrame); 61 | } 62 | Ok(self 63 | .address_stack 64 | .get(self.address_stack.len() - index) 65 | .unwrap()) 66 | } 67 | 68 | fn stack_len(&self) -> usize { 69 | self.address_stack.len() 70 | } 71 | } 72 | 73 | pub struct RuntimeBuilder { 74 | collector: Collector, 75 | frame_object: Frame, 76 | } 77 | 78 | impl RuntimeBuilder { 79 | pub fn new(collector: Collector, context: Address) -> Self { 80 | let frame_object = Frame::new(context, None); 81 | Self { 82 | collector, 83 | frame_object, 84 | } 85 | } 86 | 87 | pub fn boot(self) -> Result { 88 | let frame = self 89 | .collector 90 | .lock() 91 | .allocate(Slot::new(Object::new(self.frame_object)))?; 92 | Ok(Runtime { 93 | memory: self.collector, 94 | frame_stack: vec![frame], 95 | }) 96 | } 97 | } 98 | 99 | impl Runtime { 100 | pub fn push(&mut self, object: Object) -> Result<(), Error> { 101 | let addr = self.memory.lock().allocate(Slot::new(object))?; 102 | self.with_current_frame_mut(|frame| frame.push_address(addr)); 103 | Ok(()) 104 | } 105 | 106 | pub fn pop(&mut self) -> Result<(), Error> { 107 | self.with_current_frame_mut(|frame| frame.pop_address().map_err(Into::into)) 108 | } 109 | 110 | pub fn take(&mut self, index: usize) -> Result { 111 | let addr = self.clone_address(index)?; 112 | match self.memory.lock().take(&addr)? { 113 | Take::Free(object) => Ok(object), 114 | Take::Busy(_) => Err(ShattuckError::BusyObject.into()), 115 | } 116 | } 117 | 118 | pub fn wait(&mut self, index: usize) -> Result { 119 | let addr = self.clone_address(index)?; 120 | self.wait_object(&addr) 121 | } 122 | 123 | pub fn fill(&mut self, index: usize, object: Object) -> Result<(), Error> { 124 | let addr = self.clone_address(index)?; 125 | self.memory.lock().fill(&addr, object).map_err(Into::into) 126 | } 127 | 128 | fn clone_address(&mut self, index: usize) -> Result { 129 | self.with_current_frame_mut(|frame| { 130 | frame 131 | .get_address(index) 132 | .map(ToOwned::to_owned) 133 | .map_err(Into::into) 134 | }) 135 | } 136 | 137 | fn wait_object(&self, address: &Address) -> Result { 138 | loop { 139 | let take = self.memory.lock().take(address)?; 140 | match take { 141 | Take::Free(object) => return Ok(object), 142 | Take::Busy(parker) => parker.park(), 143 | } 144 | } 145 | } 146 | 147 | fn with_current_frame_ref(&self, f: F) -> R 148 | where 149 | F: FnOnce(&Frame) -> R, 150 | { 151 | let frame = self.frame_stack.last().unwrap().to_owned(); 152 | let mut frame_object = self.wait_object(&frame).unwrap().downcast().unwrap(); 153 | let result = f(&mut frame_object); 154 | self.memory 155 | .lock() 156 | .fill(&frame, Object::new(frame_object)) 157 | .unwrap(); 158 | result 159 | } 160 | 161 | fn with_current_frame_mut(&mut self, f: F) -> R 162 | where 163 | F: FnOnce(&mut Frame) -> R, 164 | { 165 | let frame = self.frame_stack.last().unwrap().to_owned(); 166 | let mut frame_object = self.wait_object(&frame).unwrap().downcast().unwrap(); 167 | let result = f(&mut frame_object); 168 | self.memory 169 | .lock() 170 | .fill(&frame, Object::new(frame_object)) 171 | .unwrap(); 172 | result 173 | } 174 | 175 | pub fn stack_len(&self) -> usize { 176 | self.with_current_frame_ref(|frame| frame.stack_len()) 177 | } 178 | 179 | pub fn call(&mut self, context: usize, arguments: &[usize]) -> Result<(), Error> { 180 | let caller_frame = self.frame_stack.last().unwrap().to_owned(); 181 | let callee_frame_object = 182 | self.with_current_frame_ref::<_, Result<_, Error>>(|caller_frame_object| { 183 | let context = caller_frame_object.get_address(context)?.to_owned(); 184 | let mut frame = Frame::new(context, Some(caller_frame.clone())); 185 | for arg in arguments.iter().rev() { 186 | let addr = caller_frame_object.get_address(*arg)?.to_owned(); 187 | frame.push_address(addr); 188 | } 189 | Ok(frame) 190 | })?; 191 | let callee_frame = self 192 | .memory 193 | .lock() 194 | .allocate(Slot::new(Object::new(callee_frame_object)))?; 195 | self.frame_stack.push(callee_frame); 196 | Ok(()) 197 | } 198 | 199 | pub fn back(&mut self, returned: &[usize]) -> Result<(), Error> { 200 | if self.frame_stack.len() == 1 { 201 | return Err(ShattuckError::NoParentFrame.into()); 202 | } 203 | let callee_frame = self.frame_stack.last().unwrap(); 204 | let callee_frame_object: Frame = 205 | self.wait_object(callee_frame).unwrap().downcast().unwrap(); 206 | self.frame_stack.pop().unwrap(); 207 | self.with_current_frame_mut::<_, Result<_, Error>>(|caller_frame_object| { 208 | for ret in returned.iter().rev() { 209 | let addr = callee_frame_object.get_address(*ret)?.to_owned(); 210 | caller_frame_object.push_address(addr); 211 | } 212 | Ok(()) 213 | })?; 214 | Ok(()) 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | // 2 | 3 | extern crate failure; 4 | #[macro_use] extern crate failure_derive; 5 | 6 | pub mod core; 7 | // pub mod objects; 8 | -------------------------------------------------------------------------------- /src/objects/class.rs: -------------------------------------------------------------------------------- 1 | // 2 | 3 | use std::collections::HashMap; 4 | 5 | use crate::core::memory::Address; 6 | 7 | pub struct Class { 8 | props: HashMap, 9 | } -------------------------------------------------------------------------------- /src/objects/mod.rs: -------------------------------------------------------------------------------- 1 | // 2 | 3 | pub mod thread; 4 | // pub mod class; 5 | -------------------------------------------------------------------------------- /src/objects/thread.rs: -------------------------------------------------------------------------------- 1 | // 2 | 3 | use std::thread::{spawn, JoinHandle}; 4 | 5 | use crate::core::error::Result; 6 | use crate::core::memory::{Address, Memory}; 7 | use crate::core::object::{GetHoldee, Object, SyncObject, ToSync}; 8 | use crate::core::runtime::{Method, RuntimeBuilder}; 9 | 10 | pub fn make_thread(method: Address) -> Method { 11 | Method::new( 12 | |runtime| { 13 | let sync_method = runtime.context().share()?; 14 | let mut args: Vec = Vec::new(); 15 | while let Ok(mut address) = runtime.get(1) { 16 | runtime.pop()?; 17 | args.push(address.share()?); 18 | } 19 | let handle: JoinHandle> = spawn(move || { 20 | let mut memory = Memory::new(1024); 21 | let method = memory.insert_shared(sync_method)?; 22 | let mut runtime = RuntimeBuilder::new(memory, method).boot()?; 23 | let arg_count = args.len(); 24 | // `runtime` stack keeps arguments in reverse order 25 | for arg in args.into_iter().rev() { 26 | let shared_arg = runtime.memory.insert_shared(arg)?; 27 | runtime.push(shared_arg); 28 | } 29 | let result_count = runtime.call(method, &(1..=arg_count).collect::>())?; 30 | let mut shared_results: Vec = Vec::new(); 31 | for _ in 0..result_count { 32 | shared_results.push(runtime.get(1)?.share()?); 33 | runtime.pop()?; 34 | } 35 | Ok(shared_results) 36 | }); 37 | let join = runtime 38 | .memory 39 | .insert_local(Object::new(Join(Some(handle))))?; 40 | let join_method = runtime.memory.insert_local(Object::new(make_join(join)))?; 41 | runtime.push(join_method); 42 | runtime.push_parent(1)?; 43 | Ok(()) 44 | }, 45 | method, 46 | ) 47 | } 48 | 49 | type JoinT = JoinHandle>>; 50 | 51 | struct Join(Option); 52 | 53 | unsafe impl GetHoldee for Join { 54 | fn get_holdee(&self) -> Vec
{ 55 | Vec::new() 56 | } 57 | } 58 | 59 | impl ToSync for Join { 60 | type Target = Join; 61 | 62 | fn to_sync(self) -> Result { 63 | Ok(self) 64 | } 65 | } 66 | 67 | fn make_join(join: Address) -> Method { 68 | Method::new( 69 | |runtime| { 70 | let mut get_context = runtime.context(); 71 | let mut get_mut_option_join = get_context.get_mut()?; 72 | let option_handle = &mut get_mut_option_join.as_mut::()?.0; 73 | if option_handle.is_none() { 74 | unimplemented!(); 75 | } 76 | let handle = option_handle.take().unwrap(); 77 | let results = handle.join().unwrap()?; 78 | for result_object in results.into_iter().rev() { 79 | let result = runtime.memory.insert_shared(result_object)?; 80 | runtime.push(result); 81 | runtime.push_parent(1)?; 82 | } 83 | Ok(()) 84 | }, 85 | join, 86 | ) 87 | } 88 | --------------------------------------------------------------------------------