Decide on an optimization strategy for the VM
This commit is contained in:
parent
5030171bb6
commit
07f8b36c99
204
Cargo.lock
generated
204
Cargo.lock
generated
@ -11,6 +11,12 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anes"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "annotate-snippets"
|
name = "annotate-snippets"
|
||||||
version = "0.11.5"
|
version = "0.11.5"
|
||||||
@ -18,7 +24,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "710e8eae58854cdc1790fcb56cca04d712a17be849eeb81da2a724bf4bae2bc4"
|
checksum = "710e8eae58854cdc1790fcb56cca04d712a17be849eeb81da2a724bf4bae2bc4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstyle",
|
"anstyle",
|
||||||
"unicode-width 0.2.0",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -80,17 +86,6 @@ dependencies = [
|
|||||||
"critical-section",
|
"critical-section",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "atty"
|
|
||||||
version = "0.2.14"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
|
||||||
dependencies = [
|
|
||||||
"hermit-abi",
|
|
||||||
"libc",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
@ -103,12 +98,6 @@ version = "0.21.7"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bitflags"
|
|
||||||
version = "1.3.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.8.0"
|
version = "2.8.0"
|
||||||
@ -143,21 +132,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "ciborium"
|
||||||
version = "2.34.0"
|
version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
|
checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"ciborium-io",
|
||||||
"textwrap",
|
"ciborium-ll",
|
||||||
"unicode-width 0.1.14",
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ciborium-io"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ciborium-ll"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9"
|
||||||
|
dependencies = [
|
||||||
|
"ciborium-io",
|
||||||
|
"half",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.5.28"
|
version = "4.5.29"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3e77c3243bd94243c03672cb5154667347c457ca271254724f9f393aee1c05ff"
|
checksum = "8acebd8ad879283633b343856142139f2da2317c96b05b4dd6181c61e2480184"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap_builder",
|
"clap_builder",
|
||||||
"clap_derive",
|
"clap_derive",
|
||||||
@ -165,9 +170,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_builder"
|
name = "clap_builder"
|
||||||
version = "4.5.27"
|
version = "4.5.29"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1b26884eb4b57140e4d2d93652abfa49498b938b3c9179f9fc487b0acc3edad7"
|
checksum = "f6ba32cbda51c7e1dfd49acc1457ba1a7dec5b64fe360e828acb13ca8dc9c2f9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstream",
|
"anstream",
|
||||||
"anstyle",
|
"anstyle",
|
||||||
@ -218,24 +223,24 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "criterion"
|
name = "criterion"
|
||||||
version = "0.3.6"
|
version = "0.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f"
|
checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atty",
|
"anes",
|
||||||
"cast",
|
"cast",
|
||||||
"clap 2.34.0",
|
"ciborium",
|
||||||
|
"clap",
|
||||||
"criterion-plot",
|
"criterion-plot",
|
||||||
"csv",
|
"is-terminal",
|
||||||
"itertools",
|
"itertools",
|
||||||
"lazy_static",
|
|
||||||
"num-traits",
|
"num-traits",
|
||||||
|
"once_cell",
|
||||||
"oorandom",
|
"oorandom",
|
||||||
"plotters",
|
"plotters",
|
||||||
"rayon",
|
"rayon",
|
||||||
"regex",
|
"regex",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_cbor",
|
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tinytemplate",
|
"tinytemplate",
|
||||||
@ -244,9 +249,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "criterion-plot"
|
name = "criterion-plot"
|
||||||
version = "0.4.5"
|
version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876"
|
checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cast",
|
"cast",
|
||||||
"itertools",
|
"itertools",
|
||||||
@ -293,31 +298,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "csv"
|
name = "crunchy"
|
||||||
version = "1.3.1"
|
version = "0.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf"
|
checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929"
|
||||||
dependencies = [
|
|
||||||
"csv-core",
|
|
||||||
"itoa",
|
|
||||||
"ryu",
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "csv-core"
|
name = "deranged"
|
||||||
version = "0.1.11"
|
version = "0.3.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70"
|
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"powerfmt",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dust-cli"
|
name = "dust-cli"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap 4.5.28",
|
"clap",
|
||||||
"dust-lang",
|
"dust-lang",
|
||||||
"postcard",
|
"postcard",
|
||||||
"ron",
|
"ron",
|
||||||
@ -381,9 +380,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "half"
|
name = "half"
|
||||||
version = "1.8.3"
|
version = "2.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403"
|
checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crunchy",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hash32"
|
name = "hash32"
|
||||||
@ -422,12 +425,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.1.19"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
@ -439,6 +439,17 @@ dependencies = [
|
|||||||
"hashbrown",
|
"hashbrown",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "is-terminal"
|
||||||
|
version = "0.4.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e19b23d53f35ce9f56aebc7d1bb4e6ac1e9c0db7ac85c8d1760c04379edced37"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
|
"libc",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "is_terminal_polyfill"
|
name = "is_terminal_polyfill"
|
||||||
version = "1.70.1"
|
version = "1.70.1"
|
||||||
@ -520,6 +531,12 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-conv"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.19"
|
version = "0.2.19"
|
||||||
@ -592,6 +609,12 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "powerfmt"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.20"
|
version = "0.2.20"
|
||||||
@ -705,7 +728,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94"
|
checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"bitflags 2.8.0",
|
"bitflags",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
@ -725,7 +748,7 @@ version = "0.38.44"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
|
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.8.0",
|
"bitflags",
|
||||||
"errno",
|
"errno",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys",
|
"linux-raw-sys",
|
||||||
@ -774,16 +797,6 @@ dependencies = [
|
|||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_cbor"
|
|
||||||
version = "0.11.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5"
|
|
||||||
dependencies = [
|
|
||||||
"half",
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.217"
|
version = "1.0.217"
|
||||||
@ -831,9 +844,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.13.2"
|
version = "1.14.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
@ -898,15 +911,6 @@ dependencies = [
|
|||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "textwrap"
|
|
||||||
version = "0.11.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
|
||||||
dependencies = [
|
|
||||||
"unicode-width 0.1.14",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thread_local"
|
name = "thread_local"
|
||||||
version = "1.1.8"
|
version = "1.1.8"
|
||||||
@ -917,6 +921,37 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time"
|
||||||
|
version = "0.3.37"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21"
|
||||||
|
dependencies = [
|
||||||
|
"deranged",
|
||||||
|
"itoa",
|
||||||
|
"num-conv",
|
||||||
|
"powerfmt",
|
||||||
|
"serde",
|
||||||
|
"time-core",
|
||||||
|
"time-macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time-core"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time-macros"
|
||||||
|
version = "0.2.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de"
|
||||||
|
dependencies = [
|
||||||
|
"num-conv",
|
||||||
|
"time-core",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinytemplate"
|
name = "tinytemplate"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
@ -980,6 +1015,7 @@ dependencies = [
|
|||||||
"sharded-slab",
|
"sharded-slab",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"thread_local",
|
"thread_local",
|
||||||
|
"time",
|
||||||
"tracing-core",
|
"tracing-core",
|
||||||
"tracing-log",
|
"tracing-log",
|
||||||
]
|
]
|
||||||
@ -990,12 +1026,6 @@ version = "1.0.16"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034"
|
checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-width"
|
|
||||||
version = "0.1.14"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-width"
|
name = "unicode-width"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
@ -13,7 +13,7 @@ name = "dust"
|
|||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "4.5.14", features = [
|
clap = { version = "4.5.29", features = [
|
||||||
"cargo",
|
"cargo",
|
||||||
"color",
|
"color",
|
||||||
"derive",
|
"derive",
|
||||||
@ -21,9 +21,9 @@ clap = { version = "4.5.14", features = [
|
|||||||
"wrap_help",
|
"wrap_help",
|
||||||
] }
|
] }
|
||||||
dust-lang = { path = "../dust-lang" }
|
dust-lang = { path = "../dust-lang" }
|
||||||
postcard = "1.0.10"
|
postcard = "1.1.1"
|
||||||
ron = "0.8.1"
|
ron = "0.8.1"
|
||||||
serde_json = "1.0.133"
|
serde_json = "1.0.138"
|
||||||
serde_yaml = "0.9.34"
|
serde_yaml = "0.9.34"
|
||||||
tracing = "0.1.41"
|
tracing = "0.1.41"
|
||||||
tracing-subscriber = "0.3.19"
|
tracing-subscriber = { version = "0.3.19", features = ["time"] }
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
use std::{
|
use std::{
|
||||||
fs::read_to_string,
|
fs::read_to_string,
|
||||||
io::{self, Read, stdout},
|
io::{self, stdout, Read},
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
use clap::{
|
use clap::{
|
||||||
Args, ColorChoice, Error, Parser, Subcommand, ValueEnum, ValueHint,
|
builder::{styling::AnsiColor, Styles},
|
||||||
builder::{Styles, styling::AnsiColor},
|
|
||||||
crate_authors, crate_description, crate_version,
|
crate_authors, crate_description, crate_version,
|
||||||
error::ErrorKind,
|
error::ErrorKind,
|
||||||
|
Args, ColorChoice, Error, Parser, Subcommand, ValueEnum, ValueHint,
|
||||||
};
|
};
|
||||||
use dust_lang::{CompileError, Compiler, DustError, DustString, Lexer, Span, Token, Vm};
|
use dust_lang::{CompileError, Compiler, DustError, DustString, Lexer, Span, Token, Vm};
|
||||||
use tracing::{Level, subscriber::set_global_default};
|
use tracing::{subscriber::set_global_default, Level};
|
||||||
use tracing_subscriber::FmtSubscriber;
|
use tracing_subscriber::{fmt::time::Uptime, FmtSubscriber};
|
||||||
|
|
||||||
const STYLES: Styles = Styles::styled()
|
const STYLES: Styles = Styles::styled()
|
||||||
.header(AnsiColor::BrightMagenta.on_default().bold().underline())
|
.header(AnsiColor::BrightMagenta.on_default().bold().underline())
|
||||||
@ -180,9 +180,11 @@ fn main() {
|
|||||||
let mode = mode.unwrap_or(Command::Run(run));
|
let mode = mode.unwrap_or(Command::Run(run));
|
||||||
let subscriber = FmtSubscriber::builder()
|
let subscriber = FmtSubscriber::builder()
|
||||||
.with_max_level(log_level)
|
.with_max_level(log_level)
|
||||||
.with_thread_names(true)
|
.with_ansi(true)
|
||||||
.with_file(false)
|
.with_file(false)
|
||||||
.without_time()
|
.with_line_number(false)
|
||||||
|
.with_thread_names(true)
|
||||||
|
.with_timer(Uptime::from(start_time))
|
||||||
.finish();
|
.finish();
|
||||||
|
|
||||||
set_global_default(subscriber).expect("Failed to set tracing subscriber");
|
set_global_default(subscriber).expect("Failed to set tracing subscriber");
|
||||||
|
@ -9,11 +9,11 @@ repository.workspace = true
|
|||||||
version.workspace = true
|
version.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
annotate-snippets = "0.11.4"
|
annotate-snippets = "0.11.5"
|
||||||
colored = "2.1.0"
|
colored = "2.2.0"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
serde = { version = "1.0.203", features = ["derive", "rc"] }
|
serde = { version = "1.0.217", features = ["derive", "rc"] }
|
||||||
serde_json = "1.0.117"
|
serde_json = "1.0.138"
|
||||||
getrandom = { version = "0.2", features = [
|
getrandom = { version = "0.2", features = [
|
||||||
"js",
|
"js",
|
||||||
] } # Indirect dependency, for WASM builds
|
] } # Indirect dependency, for WASM builds
|
||||||
@ -22,10 +22,10 @@ smartstring = { version = "1.0.1", features = [
|
|||||||
], default-features = false }
|
], default-features = false }
|
||||||
tracing = "0.1.41"
|
tracing = "0.1.41"
|
||||||
crossbeam-channel = "0.5.14"
|
crossbeam-channel = "0.5.14"
|
||||||
smallvec = { version = "1.13.2", features = ["serde", "const_generics"] }
|
smallvec = { version = "1.14.0", features = ["serde", "const_generics"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
criterion = { version = "0.3.4", features = ["html_reports"] }
|
criterion = { version = "0.5.1", features = ["html_reports"] }
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
name = "addictive_addition"
|
name = "addictive_addition"
|
||||||
|
@ -41,7 +41,7 @@ use std::io::{self, Write};
|
|||||||
|
|
||||||
use colored::{ColoredString, Colorize};
|
use colored::{ColoredString, Colorize};
|
||||||
|
|
||||||
use crate::{Chunk, Local};
|
use crate::{Chunk, Local, Type};
|
||||||
|
|
||||||
const INSTRUCTION_COLUMNS: [(&str, usize); 4] =
|
const INSTRUCTION_COLUMNS: [(&str, usize); 4] =
|
||||||
[("i", 5), ("POSITION", 12), ("OPERATION", 17), ("INFO", 41)];
|
[("i", 5), ("POSITION", 12), ("OPERATION", 17), ("INFO", 41)];
|
||||||
@ -321,7 +321,7 @@ impl<'a, W: Write> Disassembler<'a, W> {
|
|||||||
{
|
{
|
||||||
let identifier_display = self
|
let identifier_display = self
|
||||||
.chunk
|
.chunk
|
||||||
.constants
|
.string_constants
|
||||||
.get(*identifier_index as usize)
|
.get(*identifier_index as usize)
|
||||||
.map(|value| value.to_string())
|
.map(|value| value.to_string())
|
||||||
.unwrap_or_else(|| "unknown".to_string());
|
.unwrap_or_else(|| "unknown".to_string());
|
||||||
@ -354,8 +354,56 @@ impl<'a, W: Write> Disassembler<'a, W> {
|
|||||||
self.write_center_border(&column_name_line)?;
|
self.write_center_border(&column_name_line)?;
|
||||||
self.write_center_border(CONSTANT_BORDERS[1])?;
|
self.write_center_border(CONSTANT_BORDERS[1])?;
|
||||||
|
|
||||||
for (index, value) in self.chunk.constants.iter().enumerate() {
|
for (index, value) in self.chunk.character_constants.iter().enumerate() {
|
||||||
let type_display = value.r#type().to_string();
|
let type_display = Type::Character.to_string();
|
||||||
|
let value_display = {
|
||||||
|
let mut value_string = value.to_string();
|
||||||
|
|
||||||
|
if value_string.len() > 26 {
|
||||||
|
value_string = format!("{value_string:.23}...");
|
||||||
|
}
|
||||||
|
|
||||||
|
value_string
|
||||||
|
};
|
||||||
|
let constant_display = format!("│{index:^5}│{type_display:^26}│{value_display:^26}│");
|
||||||
|
|
||||||
|
self.write_center_border(&constant_display)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (index, value) in self.chunk.float_constants.iter().enumerate() {
|
||||||
|
let type_display = Type::Float.to_string();
|
||||||
|
let value_display = {
|
||||||
|
let mut value_string = value.to_string();
|
||||||
|
|
||||||
|
if value_string.len() > 26 {
|
||||||
|
value_string = format!("{value_string:.23}...");
|
||||||
|
}
|
||||||
|
|
||||||
|
value_string
|
||||||
|
};
|
||||||
|
let constant_display = format!("│{index:^5}│{type_display:^26}│{value_display:^26}│");
|
||||||
|
|
||||||
|
self.write_center_border(&constant_display)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (index, value) in self.chunk.integer_constants.iter().enumerate() {
|
||||||
|
let type_display = Type::Integer.to_string();
|
||||||
|
let value_display = {
|
||||||
|
let mut value_string = value.to_string();
|
||||||
|
|
||||||
|
if value_string.len() > 26 {
|
||||||
|
value_string = format!("{value_string:.23}...");
|
||||||
|
}
|
||||||
|
|
||||||
|
value_string
|
||||||
|
};
|
||||||
|
let constant_display = format!("│{index:^5}│{type_display:^26}│{value_display:^26}│");
|
||||||
|
|
||||||
|
self.write_center_border(&constant_display)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (index, value) in self.chunk.string_constants.iter().enumerate() {
|
||||||
|
let type_display = Type::String.to_string();
|
||||||
let value_display = {
|
let value_display = {
|
||||||
let mut value_string = value.to_string();
|
let mut value_string = value.to_string();
|
||||||
|
|
||||||
@ -420,7 +468,10 @@ impl<'a, W: Write> Disassembler<'a, W> {
|
|||||||
let info_line = format!(
|
let info_line = format!(
|
||||||
"{} instructions, {} constants, {} locals, returns {}",
|
"{} instructions, {} constants, {} locals, returns {}",
|
||||||
self.chunk.instructions.len(),
|
self.chunk.instructions.len(),
|
||||||
self.chunk.constants.len(),
|
self.chunk.character_constants.len()
|
||||||
|
+ self.chunk.float_constants.len()
|
||||||
|
+ self.chunk.integer_constants.len()
|
||||||
|
+ self.chunk.string_constants.len(),
|
||||||
self.chunk.locals.len(),
|
self.chunk.locals.len(),
|
||||||
self.chunk.r#type.return_type
|
self.chunk.r#type.return_type
|
||||||
);
|
);
|
||||||
@ -436,7 +487,11 @@ impl<'a, W: Write> Disassembler<'a, W> {
|
|||||||
self.write_local_section()?;
|
self.write_local_section()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.chunk.constants.is_empty() {
|
if !self.chunk.character_constants.is_empty()
|
||||||
|
|| !self.chunk.float_constants.is_empty()
|
||||||
|
|| !self.chunk.integer_constants.is_empty()
|
||||||
|
|| !self.chunk.string_constants.is_empty()
|
||||||
|
{
|
||||||
self.write_constant_section()?;
|
self.write_constant_section()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{ConcreteValue, DustString, Function, FunctionType, Instruction, Span};
|
use crate::{DustString, Function, FunctionType, Instruction, Span};
|
||||||
|
|
||||||
/// Representation of a Dust program or function.
|
/// Representation of a Dust program or function.
|
||||||
///
|
///
|
||||||
@ -36,7 +36,10 @@ pub struct Chunk {
|
|||||||
|
|
||||||
pub instructions: Vec<Instruction>,
|
pub instructions: Vec<Instruction>,
|
||||||
pub positions: Vec<Span>,
|
pub positions: Vec<Span>,
|
||||||
pub constants: Vec<ConcreteValue>,
|
pub character_constants: Vec<char>,
|
||||||
|
pub float_constants: Vec<f64>,
|
||||||
|
pub integer_constants: Vec<i64>,
|
||||||
|
pub string_constants: Vec<DustString>,
|
||||||
pub locals: Vec<Local>,
|
pub locals: Vec<Local>,
|
||||||
pub prototypes: Vec<Arc<Chunk>>,
|
pub prototypes: Vec<Arc<Chunk>>,
|
||||||
|
|
||||||
@ -107,7 +110,10 @@ impl PartialEq for Chunk {
|
|||||||
&& self.r#type == other.r#type
|
&& self.r#type == other.r#type
|
||||||
&& self.instructions == other.instructions
|
&& self.instructions == other.instructions
|
||||||
&& self.positions == other.positions
|
&& self.positions == other.positions
|
||||||
&& self.constants == other.constants
|
&& self.character_constants == other.character_constants
|
||||||
|
&& self.float_constants == other.float_constants
|
||||||
|
&& self.integer_constants == other.integer_constants
|
||||||
|
&& self.string_constants == other.string_constants
|
||||||
&& self.locals == other.locals
|
&& self.locals == other.locals
|
||||||
&& self.prototypes == other.prototypes
|
&& self.prototypes == other.prototypes
|
||||||
}
|
}
|
||||||
|
@ -24,15 +24,15 @@ mod type_checks;
|
|||||||
|
|
||||||
pub use error::CompileError;
|
pub use error::CompileError;
|
||||||
use parse_rule::{ParseRule, Precedence};
|
use parse_rule::{ParseRule, Precedence};
|
||||||
use tracing::{Level, debug, info, span};
|
use tracing::{debug, info, span, Level};
|
||||||
use type_checks::{check_math_type, check_math_types};
|
use type_checks::{check_math_type, check_math_types};
|
||||||
|
|
||||||
use std::{mem::replace, sync::Arc};
|
use std::{mem::replace, sync::Arc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Chunk, ConcreteValue, DustError, DustString, FunctionType, Instruction, Lexer, Local,
|
|
||||||
NativeFunction, Operand, Operation, Scope, Span, Token, TokenKind, Type,
|
|
||||||
instruction::{Jump, Point, Return, TypeCode},
|
instruction::{Jump, Point, Return, TypeCode},
|
||||||
|
Chunk, DustError, DustString, FunctionType, Instruction, Lexer, Local, NativeFunction, Operand,
|
||||||
|
Operation, Scope, Span, Token, TokenKind, Type,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Compiles the input and returns a chunk.
|
/// Compiles the input and returns a chunk.
|
||||||
@ -83,9 +83,21 @@ pub struct Compiler<'src> {
|
|||||||
/// The types are discarded after compilation.
|
/// The types are discarded after compilation.
|
||||||
instructions: Vec<(Instruction, Type, Span)>,
|
instructions: Vec<(Instruction, Type, Span)>,
|
||||||
|
|
||||||
/// Constants that have been compiled. These are assigned to the chunk when [`Compiler::finish`]
|
/// Character constants that have been compiled. These are assigned to the chunk when
|
||||||
/// is called.
|
/// [`Compiler::finish`] is called.
|
||||||
constants: Vec<ConcreteValue>,
|
character_constants: Vec<char>,
|
||||||
|
|
||||||
|
/// Float constants that have been compiled. These are assigned to the chunk when
|
||||||
|
/// [`Compiler::finish`] is called.
|
||||||
|
float_constants: Vec<f64>,
|
||||||
|
|
||||||
|
/// Integer constants that have been compiled. These are assigned to the chunk when
|
||||||
|
/// [`Compiler::finish`] is called.
|
||||||
|
integer_constants: Vec<i64>,
|
||||||
|
|
||||||
|
/// String constants that have been compiled. These are assigned to the chunk when
|
||||||
|
/// [`Compiler::finish`] is called.
|
||||||
|
string_constants: Vec<DustString>,
|
||||||
|
|
||||||
/// Block-local variables and their types. The locals are assigned to the chunk when
|
/// Block-local variables and their types. The locals are assigned to the chunk when
|
||||||
/// [`Compiler::finish`] is called. The types are discarded after compilation.
|
/// [`Compiler::finish`] is called. The types are discarded after compilation.
|
||||||
@ -161,7 +173,10 @@ impl<'src> Compiler<'src> {
|
|||||||
function_name,
|
function_name,
|
||||||
r#type: FunctionType::default(),
|
r#type: FunctionType::default(),
|
||||||
instructions: Vec::new(),
|
instructions: Vec::new(),
|
||||||
constants: Vec::new(),
|
character_constants: Vec::new(),
|
||||||
|
float_constants: Vec::new(),
|
||||||
|
integer_constants: Vec::new(),
|
||||||
|
string_constants: Vec::new(),
|
||||||
locals: Vec::new(),
|
locals: Vec::new(),
|
||||||
prototypes: Vec::new(),
|
prototypes: Vec::new(),
|
||||||
lexer,
|
lexer,
|
||||||
@ -241,7 +256,10 @@ impl<'src> Compiler<'src> {
|
|||||||
r#type: self.r#type,
|
r#type: self.r#type,
|
||||||
instructions,
|
instructions,
|
||||||
positions,
|
positions,
|
||||||
constants: self.constants,
|
character_constants: self.character_constants,
|
||||||
|
float_constants: self.float_constants,
|
||||||
|
integer_constants: self.integer_constants,
|
||||||
|
string_constants: self.string_constants,
|
||||||
locals: self.locals,
|
locals: self.locals,
|
||||||
prototypes: self.prototypes,
|
prototypes: self.prototypes,
|
||||||
boolean_register_count,
|
boolean_register_count,
|
||||||
@ -329,7 +347,10 @@ impl<'src> Compiler<'src> {
|
|||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
.find_map(|(instruction, r#type, _)| {
|
.find_map(|(instruction, r#type, _)| {
|
||||||
if r#type == &Type::Integer {
|
if (instruction.operation() == Operation::LOAD_CONSTANT
|
||||||
|
&& instruction.b_type() == TypeCode::INTEGER)
|
||||||
|
|| r#type == &Type::Integer
|
||||||
|
{
|
||||||
Some(instruction.a_field() + 1)
|
Some(instruction.a_field() + 1)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -416,12 +437,7 @@ impl<'src> Compiler<'src> {
|
|||||||
.enumerate()
|
.enumerate()
|
||||||
.rev()
|
.rev()
|
||||||
.find_map(|(index, local)| {
|
.find_map(|(index, local)| {
|
||||||
let constant = self.constants.get(local.identifier_index as usize)?;
|
let identifier = self.string_constants.get(local.identifier_index as usize)?;
|
||||||
let identifier = if let ConcreteValue::String(identifier) = constant {
|
|
||||||
identifier
|
|
||||||
} else {
|
|
||||||
return None;
|
|
||||||
};
|
|
||||||
|
|
||||||
if identifier == identifier_text {
|
if identifier == identifier_text {
|
||||||
Some(index as u16)
|
Some(index as u16)
|
||||||
@ -445,8 +461,8 @@ impl<'src> Compiler<'src> {
|
|||||||
) -> (u16, u16) {
|
) -> (u16, u16) {
|
||||||
info!("Declaring local {identifier}");
|
info!("Declaring local {identifier}");
|
||||||
|
|
||||||
let identifier = ConcreteValue::string(identifier);
|
let identifier = DustString::from(identifier);
|
||||||
let identifier_index = self.push_or_get_constant(identifier);
|
let identifier_index = self.push_or_get_constant_string(identifier);
|
||||||
let local_index = self.locals.len() as u16;
|
let local_index = self.locals.len() as u16;
|
||||||
|
|
||||||
self.locals.push(Local::new(
|
self.locals.push(Local::new(
|
||||||
@ -462,23 +478,23 @@ impl<'src> Compiler<'src> {
|
|||||||
|
|
||||||
fn get_identifier(&self, local_index: u16) -> Option<String> {
|
fn get_identifier(&self, local_index: u16) -> Option<String> {
|
||||||
self.locals.get(local_index as usize).and_then(|local| {
|
self.locals.get(local_index as usize).and_then(|local| {
|
||||||
self.constants
|
self.string_constants
|
||||||
.get(local.identifier_index as usize)
|
.get(local.identifier_index as usize)
|
||||||
.map(|value| value.to_string())
|
.map(|value| value.to_string())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_or_get_constant(&mut self, value: ConcreteValue) -> u16 {
|
fn push_or_get_constant_string(&mut self, string: DustString) -> u16 {
|
||||||
if let Some(index) = self
|
if let Some(index) = self
|
||||||
.constants
|
.string_constants
|
||||||
.iter()
|
.iter()
|
||||||
.position(|constant| constant == &value)
|
.position(|constant| constant == &string)
|
||||||
{
|
{
|
||||||
index as u16
|
index as u16
|
||||||
} else {
|
} else {
|
||||||
let index = self.constants.len() as u16;
|
let index = self.string_constants.len() as u16;
|
||||||
|
|
||||||
self.constants.push(value);
|
self.string_constants.push(string);
|
||||||
|
|
||||||
index
|
index
|
||||||
}
|
}
|
||||||
@ -563,28 +579,6 @@ impl<'src> Compiler<'src> {
|
|||||||
self.instructions.push((instruction, r#type, position));
|
self.instructions.push((instruction, r#type, position));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_constant(
|
|
||||||
&mut self,
|
|
||||||
constant: ConcreteValue,
|
|
||||||
position: Span,
|
|
||||||
) -> Result<(), CompileError> {
|
|
||||||
let r#type = constant.r#type();
|
|
||||||
let constant_index = self.push_or_get_constant(constant);
|
|
||||||
let destination = match r#type {
|
|
||||||
Type::Character => self.next_character_register(),
|
|
||||||
Type::Float => self.next_float_register(),
|
|
||||||
Type::Integer => self.next_integer_register(),
|
|
||||||
Type::String => self.next_string_register(),
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
let load_constant =
|
|
||||||
Instruction::load_constant(destination, constant_index, r#type.type_code(), false);
|
|
||||||
|
|
||||||
self.emit_instruction(load_constant, r#type, position);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_boolean(&mut self) -> Result<(), CompileError> {
|
fn parse_boolean(&mut self) -> Result<(), CompileError> {
|
||||||
let position = self.current_position;
|
let position = self.current_position;
|
||||||
|
|
||||||
@ -637,9 +631,13 @@ impl<'src> Compiler<'src> {
|
|||||||
if let Token::Character(character) = self.current_token {
|
if let Token::Character(character) = self.current_token {
|
||||||
self.advance()?;
|
self.advance()?;
|
||||||
|
|
||||||
let value = ConcreteValue::Character(character);
|
let destination = self.next_character_register();
|
||||||
|
let constant_index = self.character_constants.len() as u16;
|
||||||
|
let load_constant =
|
||||||
|
Instruction::load_constant(destination, constant_index, TypeCode::CHARACTER, false);
|
||||||
|
|
||||||
self.emit_constant(value, position)?;
|
self.character_constants.push(character);
|
||||||
|
self.emit_instruction(load_constant, Type::Character, position);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
@ -663,9 +661,13 @@ impl<'src> Compiler<'src> {
|
|||||||
error,
|
error,
|
||||||
position: self.previous_position,
|
position: self.previous_position,
|
||||||
})?;
|
})?;
|
||||||
let value = ConcreteValue::Float(float);
|
let destination = self.next_float_register();
|
||||||
|
let constant_index = self.float_constants.len() as u16;
|
||||||
|
let load_constant =
|
||||||
|
Instruction::load_constant(destination, constant_index, TypeCode::FLOAT, false);
|
||||||
|
|
||||||
self.emit_constant(value, position)?;
|
self.float_constants.push(float);
|
||||||
|
self.emit_instruction(load_constant, Type::Float, position);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
@ -683,7 +685,7 @@ impl<'src> Compiler<'src> {
|
|||||||
if let Token::Integer(text) = self.current_token {
|
if let Token::Integer(text) = self.current_token {
|
||||||
self.advance()?;
|
self.advance()?;
|
||||||
|
|
||||||
let mut integer_value = 0_i64;
|
let mut integer = 0_i64;
|
||||||
|
|
||||||
for digit in text.chars() {
|
for digit in text.chars() {
|
||||||
let digit = if let Some(digit) = digit.to_digit(10) {
|
let digit = if let Some(digit) = digit.to_digit(10) {
|
||||||
@ -692,12 +694,16 @@ impl<'src> Compiler<'src> {
|
|||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
integer_value = integer_value * 10 + digit;
|
integer = integer * 10 + digit;
|
||||||
}
|
}
|
||||||
|
|
||||||
let value = ConcreteValue::Integer(integer_value);
|
let constant_index = self.integer_constants.len() as u16;
|
||||||
|
let destination = self.next_integer_register();
|
||||||
|
let load_constant =
|
||||||
|
Instruction::load_constant(destination, constant_index, TypeCode::INTEGER, false);
|
||||||
|
|
||||||
self.emit_constant(value, position)?;
|
self.integer_constants.push(integer);
|
||||||
|
self.emit_instruction(load_constant, Type::Integer, position);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
@ -715,9 +721,13 @@ impl<'src> Compiler<'src> {
|
|||||||
if let Token::String(text) = self.current_token {
|
if let Token::String(text) = self.current_token {
|
||||||
self.advance()?;
|
self.advance()?;
|
||||||
|
|
||||||
let value = ConcreteValue::string(text);
|
let string = DustString::from(text);
|
||||||
|
let constant_index = self.push_or_get_constant_string(string);
|
||||||
|
let destination = self.next_string_register();
|
||||||
|
let load_constant =
|
||||||
|
Instruction::load_constant(destination, constant_index, TypeCode::STRING, false);
|
||||||
|
|
||||||
self.emit_constant(value, position)?;
|
self.emit_instruction(load_constant, Type::String, position);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
@ -932,13 +942,8 @@ impl<'src> Compiler<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_comparison_binary(&mut self) -> Result<(), CompileError> {
|
fn parse_comparison_binary(&mut self) -> Result<(), CompileError> {
|
||||||
if let Some(
|
if let Some([Operation::EQUAL | Operation::LESS | Operation::LESS_EQUAL, _, _]) =
|
||||||
[
|
self.get_last_operations()
|
||||||
Operation::EQUAL | Operation::LESS | Operation::LESS_EQUAL,
|
|
||||||
_,
|
|
||||||
_,
|
|
||||||
],
|
|
||||||
) = self.get_last_operations()
|
|
||||||
{
|
{
|
||||||
return Err(CompileError::ComparisonChain {
|
return Err(CompileError::ComparisonChain {
|
||||||
position: self.current_position,
|
position: self.current_position,
|
||||||
|
@ -1,15 +1,27 @@
|
|||||||
use std::{ops::Range, panic};
|
use std::{ops::Range, panic};
|
||||||
|
|
||||||
use crate::vm::Thread;
|
use crate::vm::{RuntimeValue, Thread};
|
||||||
|
|
||||||
pub fn panic(data: &mut Thread, _: usize, argument_range: Range<usize>) {
|
pub fn panic(data: &mut Thread, _: usize, argument_range: Range<usize>) {
|
||||||
|
let current_frame = data.current_frame();
|
||||||
let position = data.current_position();
|
let position = data.current_position();
|
||||||
let mut message = format!("Dust panic at {position}!");
|
let mut message = format!("Dust panic at {position}!");
|
||||||
|
|
||||||
for register_index in argument_range {
|
for register_index in argument_range {
|
||||||
let string = data.get_string_register(register_index);
|
let string_value = current_frame.get_string_from_register(register_index);
|
||||||
|
|
||||||
|
match string_value {
|
||||||
|
RuntimeValue::Raw(value) => {
|
||||||
|
message.push_str(value.as_str());
|
||||||
|
}
|
||||||
|
RuntimeValue::Rc(rc) => {
|
||||||
|
message.push_str(rc.as_str());
|
||||||
|
}
|
||||||
|
RuntimeValue::RefCell(ref_cell) => {
|
||||||
|
message.push_str(ref_cell.borrow().as_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
message.push_str(string);
|
|
||||||
message.push('\n');
|
message.push('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
use std::io::{Write, stdin, stdout};
|
use std::io::{stdin, stdout, Write};
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
|
use crate::vm::{Register, RuntimeValue, Thread};
|
||||||
use crate::DustString;
|
use crate::DustString;
|
||||||
use crate::vm::{Register, Thread};
|
|
||||||
|
|
||||||
pub fn read_line(data: &mut Thread, destination: usize, _argument_range: Range<usize>) {
|
pub fn read_line(data: &mut Thread, destination: usize, _argument_range: Range<usize>) {
|
||||||
|
let current_frame = data.current_frame_mut();
|
||||||
let mut buffer = String::new();
|
let mut buffer = String::new();
|
||||||
|
|
||||||
if stdin().read_line(&mut buffer).is_ok() {
|
if stdin().read_line(&mut buffer).is_ok() {
|
||||||
@ -12,30 +13,53 @@ pub fn read_line(data: &mut Thread, destination: usize, _argument_range: Range<u
|
|||||||
|
|
||||||
buffer.truncate(length.saturating_sub(1));
|
buffer.truncate(length.saturating_sub(1));
|
||||||
|
|
||||||
let string = DustString::from(buffer);
|
let string = RuntimeValue::Raw(DustString::from(buffer));
|
||||||
let register = Register::Value(string);
|
|
||||||
|
|
||||||
data.set_string_register(destination, register);
|
current_frame.registers.strings[destination].set(string);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(data: &mut Thread, _: usize, argument_range: Range<usize>) {
|
pub fn write(data: &mut Thread, _: usize, argument_range: Range<usize>) {
|
||||||
|
let current_frame = data.current_frame();
|
||||||
let mut stdout = stdout();
|
let mut stdout = stdout();
|
||||||
|
|
||||||
for register_index in argument_range {
|
for register_index in argument_range {
|
||||||
let value = data.get_string_register(register_index);
|
let value = current_frame.get_string_from_register(register_index);
|
||||||
let _ = stdout.write(value.to_string().as_bytes());
|
|
||||||
|
match value {
|
||||||
|
RuntimeValue::Raw(value) => {
|
||||||
|
let _ = stdout.write(value.as_bytes());
|
||||||
|
}
|
||||||
|
RuntimeValue::Rc(value) => {
|
||||||
|
let _ = stdout.write(value.as_bytes());
|
||||||
|
}
|
||||||
|
RuntimeValue::RefCell(ref_cell) => {
|
||||||
|
let _ = stdout.write(ref_cell.borrow().as_bytes());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = stdout.flush();
|
let _ = stdout.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_line(data: &mut Thread, _: usize, argument_range: Range<usize>) {
|
pub fn write_line(data: &mut Thread, _: usize, argument_range: Range<usize>) {
|
||||||
|
let current_frame = data.current_frame();
|
||||||
let mut stdout = stdout().lock();
|
let mut stdout = stdout().lock();
|
||||||
|
|
||||||
for register_index in argument_range {
|
for register_index in argument_range {
|
||||||
let value = data.get_string_register(register_index);
|
let value = current_frame.get_string_from_register(register_index);
|
||||||
let _ = stdout.write(value.to_string().as_bytes());
|
|
||||||
|
match value {
|
||||||
|
RuntimeValue::Raw(value) => {
|
||||||
|
let _ = stdout.write(value.as_bytes());
|
||||||
|
}
|
||||||
|
RuntimeValue::Rc(value) => {
|
||||||
|
let _ = stdout.write(value.as_bytes());
|
||||||
|
}
|
||||||
|
RuntimeValue::RefCell(ref_cell) => {
|
||||||
|
let _ = stdout.write(ref_cell.borrow().as_bytes());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = stdout.write(b"\n");
|
let _ = stdout.write(b"\n");
|
||||||
|
@ -2,9 +2,10 @@ use std::ops::Range;
|
|||||||
|
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
use crate::vm::{Register, Thread};
|
use crate::vm::{Register, RuntimeValue, Thread};
|
||||||
|
|
||||||
pub fn random_int(data: &mut Thread, destination: usize, argument_range: Range<usize>) {
|
pub fn random_int(data: &mut Thread, destination: usize, argument_range: Range<usize>) {
|
||||||
|
let current_frame = data.current_frame_mut();
|
||||||
let mut argument_range_iter = argument_range.into_iter();
|
let mut argument_range_iter = argument_range.into_iter();
|
||||||
let (min, max) = {
|
let (min, max) = {
|
||||||
let mut min = None;
|
let mut min = None;
|
||||||
@ -13,18 +14,23 @@ pub fn random_int(data: &mut Thread, destination: usize, argument_range: Range<u
|
|||||||
let register_index = argument_range_iter
|
let register_index = argument_range_iter
|
||||||
.next()
|
.next()
|
||||||
.unwrap_or_else(|| panic!("No argument was passed to \"random_int\""));
|
.unwrap_or_else(|| panic!("No argument was passed to \"random_int\""));
|
||||||
let integer = data.get_integer_register(register_index);
|
let integer = current_frame
|
||||||
|
.get_integer_from_register(register_index)
|
||||||
|
.clone_inner();
|
||||||
|
|
||||||
if min.is_none() {
|
if min.is_none() {
|
||||||
min = Some(*integer);
|
min = Some(integer);
|
||||||
} else {
|
} else {
|
||||||
break (min, *integer);
|
break (min, integer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let random_integer = rand::thread_rng().gen_range(min.unwrap()..max);
|
let random_integer = rand::thread_rng().gen_range(min.unwrap()..max);
|
||||||
let register = Register::Value(random_integer);
|
|
||||||
|
|
||||||
data.set_integer_register(destination, register);
|
current_frame
|
||||||
|
.registers
|
||||||
|
.integers
|
||||||
|
.get_mut(destination)
|
||||||
|
.set(RuntimeValue::Raw(random_integer));
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ pub struct AbstractList {
|
|||||||
|
|
||||||
impl AbstractList {
|
impl AbstractList {
|
||||||
pub fn display(&self, thread: &Thread) -> DustString {
|
pub fn display(&self, thread: &Thread) -> DustString {
|
||||||
|
let current_frame = thread.current_frame();
|
||||||
let mut display = DustString::new();
|
let mut display = DustString::new();
|
||||||
|
|
||||||
display.push('[');
|
display.push('[');
|
||||||
@ -25,12 +26,14 @@ impl AbstractList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let item_display = match self.item_type {
|
let item_display = match self.item_type {
|
||||||
TypeCode::BOOLEAN => thread.get_pointer_to_boolean(pointer).to_string(),
|
TypeCode::BOOLEAN => current_frame.get_boolean_from_pointer(pointer).to_string(),
|
||||||
TypeCode::BYTE => thread.get_pointer_to_byte(pointer).to_string(),
|
TypeCode::BYTE => current_frame.get_byte_from_pointer(pointer).to_string(),
|
||||||
TypeCode::CHARACTER => thread.get_pointer_to_character(pointer).to_string(),
|
TypeCode::CHARACTER => current_frame
|
||||||
TypeCode::FLOAT => thread.get_pointer_to_float(pointer).to_string(),
|
.get_character_from_pointer(pointer)
|
||||||
TypeCode::INTEGER => thread.get_pointer_to_integer(pointer).to_string(),
|
.to_string(),
|
||||||
TypeCode::STRING => thread.get_pointer_to_string(pointer).to_string(),
|
TypeCode::FLOAT => current_frame.get_float_from_pointer(pointer).to_string(),
|
||||||
|
TypeCode::INTEGER => current_frame.get_integer_from_pointer(pointer).to_string(),
|
||||||
|
TypeCode::STRING => current_frame.get_string_from_pointer(pointer).to_string(),
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -57,7 +60,7 @@ impl Display for AbstractList {
|
|||||||
write!(f, "[")?;
|
write!(f, "[")?;
|
||||||
|
|
||||||
for pointer in &self.item_pointers {
|
for pointer in &self.item_pointers {
|
||||||
write!(f, "{}", pointer)?;
|
write!(f, "{:?}", pointer)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(f, "]")
|
write!(f, "]")
|
||||||
|
@ -1,68 +1,63 @@
|
|||||||
|
use std::ops::Add;
|
||||||
|
|
||||||
|
use tracing::trace;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
instruction::InstructionFields,
|
instruction::InstructionFields,
|
||||||
vm::{Register, Thread},
|
vm::{call_frame::RuntimeValue, Thread},
|
||||||
DustString,
|
DustString,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn add_bytes(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn add_bytes(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
||||||
let destination = instruction.a_field as usize;
|
let destination_index = instruction.a_field as usize;
|
||||||
let left = instruction.b_field as usize;
|
let left_index = instruction.b_field as usize;
|
||||||
let left_is_constant = instruction.b_is_constant;
|
let right_index = instruction.c_field as usize;
|
||||||
let right = instruction.c_field as usize;
|
|
||||||
let right_is_constant = instruction.c_is_constant;
|
|
||||||
let left_value = if left_is_constant {
|
|
||||||
if cfg!(debug_assertions) {
|
|
||||||
thread.get_constant(left).as_byte().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { thread.get_constant(left).as_byte().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
thread.get_byte_register(left)
|
|
||||||
};
|
|
||||||
let right_value = if right_is_constant {
|
|
||||||
if cfg!(debug_assertions) {
|
|
||||||
thread.get_constant(right).as_byte().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { thread.get_constant(right).as_byte().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
thread.get_byte_register(right)
|
|
||||||
};
|
|
||||||
let sum = left_value.saturating_add(*right_value);
|
|
||||||
|
|
||||||
thread.set_byte_register(destination, Register::Value(sum));
|
let current_frame = thread.current_frame_mut();
|
||||||
|
let left_value = current_frame.get_byte_from_register(left_index);
|
||||||
|
let right_value = current_frame.get_byte_from_register(right_index);
|
||||||
|
let sum = left_value.add(right_value);
|
||||||
|
|
||||||
|
current_frame
|
||||||
|
.registers
|
||||||
|
.bytes
|
||||||
|
.get_mut(destination_index)
|
||||||
|
.as_value_mut()
|
||||||
|
.set_inner(sum);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_characters(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn add_characters(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
||||||
let destination = instruction.a_field as usize;
|
let destination_index = instruction.a_field as usize;
|
||||||
let left = instruction.b_field as usize;
|
let left_index = instruction.b_field as usize;
|
||||||
let left_is_constant = instruction.b_is_constant;
|
let left_is_constant = instruction.b_is_constant;
|
||||||
let right = instruction.c_field as usize;
|
let right = instruction.c_field as usize;
|
||||||
let right_is_constant = instruction.c_is_constant;
|
let right_is_constant = instruction.c_is_constant;
|
||||||
|
|
||||||
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
if cfg!(debug_assertions) {
|
current_frame.get_character_constant(left_index)
|
||||||
thread.get_constant(left).as_character().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { thread.get_constant(left).as_character().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
thread.get_character_register(left)
|
current_frame.get_character_from_register(left_index)
|
||||||
};
|
};
|
||||||
let right_value = if right_is_constant {
|
let right_value = if right_is_constant {
|
||||||
if cfg!(debug_assertions) {
|
current_frame.get_character_constant(right)
|
||||||
thread.get_constant(right).as_character().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { thread.get_constant(right).as_character().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
thread.get_character_register(right)
|
current_frame.get_character_from_register(right)
|
||||||
};
|
};
|
||||||
let mut concatenated = DustString::from(String::with_capacity(2));
|
let concatenated = {
|
||||||
|
let mut concatenated = DustString::from(String::with_capacity(2));
|
||||||
|
|
||||||
concatenated.push(*left_value);
|
concatenated.push(left_value.clone_inner());
|
||||||
concatenated.push(*right_value);
|
concatenated.push(right_value.clone_inner());
|
||||||
|
|
||||||
thread.set_string_register(destination, Register::Value(concatenated));
|
RuntimeValue::Raw(concatenated)
|
||||||
|
};
|
||||||
|
|
||||||
|
current_frame
|
||||||
|
.registers
|
||||||
|
.strings
|
||||||
|
.get_mut(destination_index)
|
||||||
|
.set(concatenated);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_floats(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn add_floats(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
||||||
@ -71,27 +66,26 @@ pub fn add_floats(_: &mut usize, instruction: &InstructionFields, thread: &mut T
|
|||||||
let left_is_constant = instruction.b_is_constant;
|
let left_is_constant = instruction.b_is_constant;
|
||||||
let right = instruction.c_field as usize;
|
let right = instruction.c_field as usize;
|
||||||
let right_is_constant = instruction.c_is_constant;
|
let right_is_constant = instruction.c_is_constant;
|
||||||
|
|
||||||
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
if cfg!(debug_assertions) {
|
current_frame.get_float_constant(left)
|
||||||
thread.get_constant(left).as_float().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { thread.get_constant(left).as_float().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
thread.get_float_register(left)
|
current_frame.get_float_from_register(left)
|
||||||
};
|
};
|
||||||
let right_value = if right_is_constant {
|
let right_value = if right_is_constant {
|
||||||
if cfg!(debug_assertions) {
|
current_frame.get_float_constant(right)
|
||||||
thread.get_constant(right).as_float().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { thread.get_constant(right).as_float().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
thread.get_float_register(right)
|
current_frame.get_float_from_register(right)
|
||||||
};
|
};
|
||||||
let sum = left_value + *right_value;
|
let sum = left_value.add(right_value);
|
||||||
|
|
||||||
thread.set_float_register(destination, Register::Value(sum));
|
current_frame
|
||||||
|
.registers
|
||||||
|
.floats
|
||||||
|
.get_mut(destination)
|
||||||
|
.as_value_mut()
|
||||||
|
.set_inner(sum);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_integers(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn add_integers(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
||||||
@ -100,27 +94,26 @@ pub fn add_integers(_: &mut usize, instruction: &InstructionFields, thread: &mut
|
|||||||
let left_is_constant = instruction.b_is_constant;
|
let left_is_constant = instruction.b_is_constant;
|
||||||
let right = instruction.c_field as usize;
|
let right = instruction.c_field as usize;
|
||||||
let right_is_constant = instruction.c_is_constant;
|
let right_is_constant = instruction.c_is_constant;
|
||||||
|
|
||||||
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
if cfg!(debug_assertions) {
|
current_frame.get_integer_constant(left)
|
||||||
thread.get_constant(left).as_integer().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { thread.get_constant(left).as_integer().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
thread.get_integer_register(left)
|
current_frame.get_integer_from_register(left)
|
||||||
};
|
};
|
||||||
let right_value = if right_is_constant {
|
let right_value = if right_is_constant {
|
||||||
if cfg!(debug_assertions) {
|
current_frame.get_integer_constant(right)
|
||||||
thread.get_constant(right).as_integer().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { thread.get_constant(right).as_integer().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
thread.get_integer_register(right)
|
current_frame.get_integer_from_register(right)
|
||||||
};
|
};
|
||||||
let sum = left_value.saturating_add(*right_value);
|
let sum = left_value.add(right_value);
|
||||||
|
|
||||||
thread.set_integer_register(destination, Register::Value(sum));
|
current_frame
|
||||||
|
.registers
|
||||||
|
.integers
|
||||||
|
.get_mut(destination)
|
||||||
|
.as_value_mut()
|
||||||
|
.set_inner(sum);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_strings(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn add_strings(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
||||||
@ -129,31 +122,26 @@ pub fn add_strings(_: &mut usize, instruction: &InstructionFields, thread: &mut
|
|||||||
let left_is_constant = instruction.b_is_constant;
|
let left_is_constant = instruction.b_is_constant;
|
||||||
let right = instruction.c_field as usize;
|
let right = instruction.c_field as usize;
|
||||||
let right_is_constant = instruction.c_is_constant;
|
let right_is_constant = instruction.c_is_constant;
|
||||||
|
|
||||||
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
if cfg!(debug_assertions) {
|
current_frame.get_string_constant(left)
|
||||||
thread.get_constant(left).as_string().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { thread.get_constant(left).as_string().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
thread.get_string_register(left)
|
current_frame.get_string_from_register(left)
|
||||||
};
|
};
|
||||||
let right_value = if right_is_constant {
|
let right_value = if right_is_constant {
|
||||||
if cfg!(debug_assertions) {
|
current_frame.get_string_constant(right)
|
||||||
thread.get_constant(right).as_string().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { thread.get_constant(right).as_string().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
thread.get_string_register(right)
|
current_frame.get_string_from_register(right)
|
||||||
};
|
};
|
||||||
let mut concatenated =
|
let concatenated = DustString::from(format!("{left_value}{right_value}"));
|
||||||
DustString::from(String::with_capacity(left_value.len() + right_value.len()));
|
|
||||||
|
|
||||||
concatenated.push_str(left_value);
|
current_frame
|
||||||
concatenated.push_str(right_value);
|
.registers
|
||||||
|
.strings
|
||||||
thread.set_string_register(destination, Register::Value(concatenated));
|
.get_mut(destination)
|
||||||
|
.as_value_mut()
|
||||||
|
.set_inner(concatenated);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_character_string(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn add_character_string(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
||||||
@ -162,30 +150,26 @@ pub fn add_character_string(_: &mut usize, instruction: &InstructionFields, thre
|
|||||||
let left_is_constant = instruction.b_is_constant;
|
let left_is_constant = instruction.b_is_constant;
|
||||||
let right = instruction.c_field as usize;
|
let right = instruction.c_field as usize;
|
||||||
let right_is_constant = instruction.c_is_constant;
|
let right_is_constant = instruction.c_is_constant;
|
||||||
|
|
||||||
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
if cfg!(debug_assertions) {
|
current_frame.get_character_constant(left)
|
||||||
thread.get_constant(left).as_character().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { thread.get_constant(left).as_character().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
thread.get_character_register(left)
|
current_frame.get_character_from_register(left)
|
||||||
};
|
};
|
||||||
let right_value = if right_is_constant {
|
let right_value = if right_is_constant {
|
||||||
if cfg!(debug_assertions) {
|
current_frame.get_string_constant(right)
|
||||||
thread.get_constant(right).as_string().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { thread.get_constant(right).as_string().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
thread.get_string_register(right)
|
current_frame.get_string_from_register(right)
|
||||||
};
|
};
|
||||||
let mut concatenated = DustString::from(String::with_capacity(right_value.len() + 1));
|
let concatenated = DustString::from(format!("{left_value}{right_value}"));
|
||||||
|
|
||||||
concatenated.push(*left_value);
|
current_frame
|
||||||
concatenated.push_str(right_value);
|
.registers
|
||||||
|
.strings
|
||||||
thread.set_string_register(destination, Register::Value(concatenated));
|
.get_mut(destination)
|
||||||
|
.as_value_mut()
|
||||||
|
.set_inner(concatenated);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_string_character(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn add_string_character(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
||||||
@ -194,28 +178,89 @@ pub fn add_string_character(_: &mut usize, instruction: &InstructionFields, thre
|
|||||||
let left_is_constant = instruction.b_is_constant;
|
let left_is_constant = instruction.b_is_constant;
|
||||||
let right = instruction.c_field as usize;
|
let right = instruction.c_field as usize;
|
||||||
let right_is_constant = instruction.c_is_constant;
|
let right_is_constant = instruction.c_is_constant;
|
||||||
|
|
||||||
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
if cfg!(debug_assertions) {
|
current_frame.get_string_constant(left)
|
||||||
thread.get_constant(left).as_string().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { thread.get_constant(left).as_string().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
thread.get_string_register(left)
|
current_frame.get_string_from_register(left)
|
||||||
};
|
};
|
||||||
let right_value = if right_is_constant {
|
let right_value = if right_is_constant {
|
||||||
if cfg!(debug_assertions) {
|
current_frame.get_character_constant(right)
|
||||||
thread.get_constant(right).as_character().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { thread.get_constant(right).as_character().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
thread.get_character_register(right)
|
current_frame.get_character_from_register(right)
|
||||||
};
|
};
|
||||||
let mut concatenated = DustString::from(String::with_capacity(left_value.len() + 1));
|
let concatenated = DustString::from(format!("{left_value}{right_value}"));
|
||||||
|
|
||||||
concatenated.push_str(left_value);
|
current_frame
|
||||||
concatenated.push(*right_value);
|
.registers
|
||||||
|
.strings
|
||||||
thread.set_string_register(destination, Register::Value(concatenated));
|
.get_mut(destination)
|
||||||
|
.as_value_mut()
|
||||||
|
.set_inner(concatenated);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn optimized_add_integer(
|
||||||
|
instruction: &InstructionFields,
|
||||||
|
thread: &mut Thread,
|
||||||
|
cache: &mut Option<[RuntimeValue<i64>; 3]>,
|
||||||
|
) {
|
||||||
|
if let Some([destination, left, right]) = cache {
|
||||||
|
trace!("ADD_INTEGERS_OPTIMIZED using cache");
|
||||||
|
|
||||||
|
let sum = left.add(right);
|
||||||
|
|
||||||
|
*destination.borrow_mut() = sum;
|
||||||
|
} else {
|
||||||
|
let destination_index = instruction.a_field as usize;
|
||||||
|
let left_index = instruction.b_field as usize;
|
||||||
|
let left_is_constant = instruction.b_is_constant;
|
||||||
|
let right_index = instruction.c_field as usize;
|
||||||
|
let right_is_constant = instruction.c_is_constant;
|
||||||
|
let current_frame = thread.current_frame_mut();
|
||||||
|
let left_value = if left_is_constant {
|
||||||
|
let value = current_frame.get_integer_constant_mut(left_index).to_rc();
|
||||||
|
|
||||||
|
current_frame.constants.integers[left_index] = value.clone();
|
||||||
|
|
||||||
|
value
|
||||||
|
} else {
|
||||||
|
let value = current_frame
|
||||||
|
.get_integer_from_register_mut(left_index)
|
||||||
|
.to_ref_cell();
|
||||||
|
|
||||||
|
current_frame.registers.integers[left_index].set(value.clone());
|
||||||
|
|
||||||
|
value
|
||||||
|
};
|
||||||
|
let right_value = if right_is_constant {
|
||||||
|
let value = current_frame.get_integer_constant_mut(right_index).to_rc();
|
||||||
|
|
||||||
|
current_frame.constants.integers[right_index] = value.clone();
|
||||||
|
|
||||||
|
value
|
||||||
|
} else {
|
||||||
|
let value = current_frame
|
||||||
|
.get_integer_from_register_mut(right_index)
|
||||||
|
.to_ref_cell();
|
||||||
|
|
||||||
|
current_frame.registers.integers[right_index].set(value.clone());
|
||||||
|
|
||||||
|
value
|
||||||
|
};
|
||||||
|
let sum = left_value.add(&right_value);
|
||||||
|
let destination = {
|
||||||
|
let mut value = current_frame
|
||||||
|
.get_integer_from_register_mut(destination_index)
|
||||||
|
.to_ref_cell();
|
||||||
|
|
||||||
|
value.set_inner(sum);
|
||||||
|
|
||||||
|
current_frame.registers.integers[destination_index].set(value.clone());
|
||||||
|
|
||||||
|
value
|
||||||
|
};
|
||||||
|
|
||||||
|
*cache = Some([destination, left_value, right_value]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,31 +1,20 @@
|
|||||||
use crate::{instruction::InstructionFields, vm::Thread};
|
use tracing::trace;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
instruction::InstructionFields,
|
||||||
|
vm::{RuntimeValue, Thread},
|
||||||
|
};
|
||||||
|
|
||||||
pub fn less_booleans(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn less_booleans(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
||||||
let left = instruction.b_field as usize;
|
let left_index = instruction.b_field as usize;
|
||||||
let left_is_constant = instruction.b_is_constant;
|
let right_index = instruction.c_field as usize;
|
||||||
let right = instruction.c_field as usize;
|
|
||||||
let right_is_constant = instruction.c_is_constant;
|
|
||||||
let left_value = if left_is_constant {
|
|
||||||
if cfg!(debug_assertions) {
|
|
||||||
thread.get_constant(left).as_boolean().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { thread.get_constant(left).as_boolean().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
thread.get_boolean_register(left)
|
|
||||||
};
|
|
||||||
let right_value = if right_is_constant {
|
|
||||||
if cfg!(debug_assertions) {
|
|
||||||
thread.get_constant(right).as_boolean().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { thread.get_constant(right).as_boolean().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
thread.get_boolean_register(right)
|
|
||||||
};
|
|
||||||
let is_less_than = left_value < right_value;
|
|
||||||
let comparator = instruction.d_field;
|
let comparator = instruction.d_field;
|
||||||
|
|
||||||
|
let current_frame = thread.current_frame_mut();
|
||||||
|
let left_value = current_frame.get_boolean_from_register(left_index);
|
||||||
|
let right_value = current_frame.get_boolean_from_register(right_index);
|
||||||
|
let is_less_than = left_value < right_value;
|
||||||
|
|
||||||
if is_less_than == comparator {
|
if is_less_than == comparator {
|
||||||
*ip += 1;
|
*ip += 1;
|
||||||
}
|
}
|
||||||
@ -33,60 +22,38 @@ pub fn less_booleans(ip: &mut usize, instruction: &InstructionFields, thread: &m
|
|||||||
|
|
||||||
pub fn less_bytes(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn less_bytes(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
||||||
let left = instruction.b_field as usize;
|
let left = instruction.b_field as usize;
|
||||||
let left_is_constant = instruction.b_is_constant;
|
|
||||||
let right = instruction.c_field as usize;
|
let right = instruction.c_field as usize;
|
||||||
let right_is_constant = instruction.c_is_constant;
|
|
||||||
let left_value = if left_is_constant {
|
|
||||||
if cfg!(debug_assertions) {
|
|
||||||
thread.get_constant(left).as_byte().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { thread.get_constant(left).as_byte().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
thread.get_byte_register(left)
|
|
||||||
};
|
|
||||||
let right_value = if right_is_constant {
|
|
||||||
if cfg!(debug_assertions) {
|
|
||||||
thread.get_constant(right).as_byte().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { thread.get_constant(right).as_byte().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
thread.get_byte_register(right)
|
|
||||||
};
|
|
||||||
let is_less_than = left_value < right_value;
|
|
||||||
let comparator = instruction.d_field;
|
let comparator = instruction.d_field;
|
||||||
|
|
||||||
|
let current_frame = thread.current_frame_mut();
|
||||||
|
let left_value = current_frame.get_byte_from_register(left);
|
||||||
|
let right_value = current_frame.get_byte_from_register(right);
|
||||||
|
let is_less_than = left_value < right_value;
|
||||||
|
|
||||||
if is_less_than == comparator {
|
if is_less_than == comparator {
|
||||||
*ip += 1;
|
*ip += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn less_characters(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn less_characters(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
||||||
let left = instruction.b_field as usize;
|
let left_index = instruction.b_field as usize;
|
||||||
let left_is_constant = instruction.b_is_constant;
|
let left_is_constant = instruction.b_is_constant;
|
||||||
let right = instruction.c_field as usize;
|
let right_index = instruction.c_field as usize;
|
||||||
let right_is_constant = instruction.c_is_constant;
|
let right_is_constant = instruction.c_is_constant;
|
||||||
|
let comparator = instruction.d_field;
|
||||||
|
|
||||||
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
if cfg!(debug_assertions) {
|
current_frame.get_character_constant(left_index)
|
||||||
thread.get_constant(left).as_character().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { thread.get_constant(left).as_character().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
thread.get_character_register(left)
|
current_frame.get_character_from_register(left_index)
|
||||||
};
|
};
|
||||||
let right_value = if right_is_constant {
|
let right_value = if right_is_constant {
|
||||||
if cfg!(debug_assertions) {
|
current_frame.get_character_constant(right_index)
|
||||||
thread.get_constant(right).as_character().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { thread.get_constant(right).as_character().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
thread.get_character_register(right)
|
current_frame.get_character_from_register(right_index)
|
||||||
};
|
};
|
||||||
let is_less_than = left_value < right_value;
|
let is_less_than = left_value < right_value;
|
||||||
let comparator = instruction.d_field;
|
|
||||||
|
|
||||||
if is_less_than == comparator {
|
if is_less_than == comparator {
|
||||||
*ip += 1;
|
*ip += 1;
|
||||||
@ -98,26 +65,20 @@ pub fn less_floats(ip: &mut usize, instruction: &InstructionFields, thread: &mut
|
|||||||
let left_is_constant = instruction.b_is_constant;
|
let left_is_constant = instruction.b_is_constant;
|
||||||
let right = instruction.c_field as usize;
|
let right = instruction.c_field as usize;
|
||||||
let right_is_constant = instruction.c_is_constant;
|
let right_is_constant = instruction.c_is_constant;
|
||||||
|
let comparator = instruction.d_field;
|
||||||
|
|
||||||
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
if cfg!(debug_assertions) {
|
current_frame.get_float_constant(left)
|
||||||
thread.get_constant(left).as_float().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { thread.get_constant(left).as_float().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
thread.get_float_register(left)
|
current_frame.get_float_from_register(left)
|
||||||
};
|
};
|
||||||
let right_value = if right_is_constant {
|
let right_value = if right_is_constant {
|
||||||
if cfg!(debug_assertions) {
|
current_frame.get_float_constant(right)
|
||||||
thread.get_constant(right).as_float().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { thread.get_constant(right).as_float().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
thread.get_float_register(right)
|
current_frame.get_float_from_register(right)
|
||||||
};
|
};
|
||||||
let is_less_than = left_value < right_value;
|
let is_less_than = left_value < right_value;
|
||||||
let comparator = instruction.d_field;
|
|
||||||
|
|
||||||
if is_less_than == comparator {
|
if is_less_than == comparator {
|
||||||
*ip += 1;
|
*ip += 1;
|
||||||
@ -129,26 +90,20 @@ pub fn less_integers(ip: &mut usize, instruction: &InstructionFields, thread: &m
|
|||||||
let left_is_constant = instruction.b_is_constant;
|
let left_is_constant = instruction.b_is_constant;
|
||||||
let right = instruction.c_field as usize;
|
let right = instruction.c_field as usize;
|
||||||
let right_is_constant = instruction.c_is_constant;
|
let right_is_constant = instruction.c_is_constant;
|
||||||
|
let comparator = instruction.d_field;
|
||||||
|
|
||||||
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
if cfg!(debug_assertions) {
|
current_frame.get_integer_constant(left)
|
||||||
thread.get_constant(left).as_integer().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { thread.get_constant(left).as_integer().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
thread.get_integer_register(left)
|
current_frame.get_integer_from_register(left)
|
||||||
};
|
};
|
||||||
let right_value = if right_is_constant {
|
let right_value = if right_is_constant {
|
||||||
if cfg!(debug_assertions) {
|
current_frame.get_integer_constant(right)
|
||||||
thread.get_constant(right).as_integer().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { thread.get_constant(right).as_integer().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
thread.get_integer_register(right)
|
current_frame.get_integer_from_register(right)
|
||||||
};
|
};
|
||||||
let is_less_than = left_value < right_value;
|
let is_less_than = left_value < right_value;
|
||||||
let comparator = instruction.d_field;
|
|
||||||
|
|
||||||
if is_less_than == comparator {
|
if is_less_than == comparator {
|
||||||
*ip += 1;
|
*ip += 1;
|
||||||
@ -160,28 +115,84 @@ pub fn less_strings(ip: &mut usize, instruction: &InstructionFields, thread: &mu
|
|||||||
let left_is_constant = instruction.b_is_constant;
|
let left_is_constant = instruction.b_is_constant;
|
||||||
let right = instruction.c_field as usize;
|
let right = instruction.c_field as usize;
|
||||||
let right_is_constant = instruction.c_is_constant;
|
let right_is_constant = instruction.c_is_constant;
|
||||||
|
let comparator = instruction.d_field;
|
||||||
|
|
||||||
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
if cfg!(debug_assertions) {
|
current_frame.get_string_constant(left)
|
||||||
thread.get_constant(left).as_string().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { thread.get_constant(left).as_string().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
thread.get_string_register(left)
|
current_frame.get_string_from_register(left)
|
||||||
};
|
};
|
||||||
let right_value = if right_is_constant {
|
let right_value = if right_is_constant {
|
||||||
if cfg!(debug_assertions) {
|
current_frame.get_string_constant(right)
|
||||||
thread.get_constant(right).as_string().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { thread.get_constant(right).as_string().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
thread.get_string_register(right)
|
current_frame.get_string_from_register(right)
|
||||||
};
|
};
|
||||||
let is_less_than = left_value < right_value;
|
let is_less_than = left_value < right_value;
|
||||||
let comparator = instruction.d_field;
|
|
||||||
|
|
||||||
if is_less_than == comparator {
|
if is_less_than == comparator {
|
||||||
*ip += 1;
|
*ip += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn optimized_less_integers(
|
||||||
|
ip: &mut usize,
|
||||||
|
instruction: &InstructionFields,
|
||||||
|
thread: &mut Thread,
|
||||||
|
cache: &mut Option<[RuntimeValue<i64>; 2]>,
|
||||||
|
) {
|
||||||
|
if let Some([left, right]) = cache {
|
||||||
|
trace!("LESS_INTEGERS_OPTIMIZED using cache");
|
||||||
|
|
||||||
|
let is_less_than = left < right;
|
||||||
|
|
||||||
|
if is_less_than {
|
||||||
|
*ip += 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let left_index = instruction.b_field as usize;
|
||||||
|
let left_is_constant = instruction.b_is_constant;
|
||||||
|
let right_index = instruction.c_field as usize;
|
||||||
|
let right_is_constant = instruction.c_is_constant;
|
||||||
|
let comparator = instruction.d_field;
|
||||||
|
|
||||||
|
let current_frame = thread.current_frame_mut();
|
||||||
|
let left_value = if left_is_constant {
|
||||||
|
let value = current_frame.get_integer_constant_mut(left_index).to_rc();
|
||||||
|
|
||||||
|
current_frame.constants.integers[left_index] = value.clone();
|
||||||
|
|
||||||
|
value
|
||||||
|
} else {
|
||||||
|
let value = current_frame
|
||||||
|
.get_integer_from_register_mut(left_index)
|
||||||
|
.to_ref_cell();
|
||||||
|
|
||||||
|
current_frame.registers.integers[left_index].set(value.clone());
|
||||||
|
|
||||||
|
value
|
||||||
|
};
|
||||||
|
let right_value = if right_is_constant {
|
||||||
|
let value = current_frame.get_integer_constant_mut(right_index).to_rc();
|
||||||
|
|
||||||
|
current_frame.constants.integers[right_index] = value.clone();
|
||||||
|
|
||||||
|
value
|
||||||
|
} else {
|
||||||
|
let value = current_frame
|
||||||
|
.get_integer_from_register_mut(right_index)
|
||||||
|
.to_ref_cell();
|
||||||
|
|
||||||
|
current_frame.registers.integers[right_index].set(value.clone());
|
||||||
|
|
||||||
|
value
|
||||||
|
};
|
||||||
|
let is_less_than = left_value < right_value;
|
||||||
|
|
||||||
|
if is_less_than == comparator {
|
||||||
|
*ip += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*cache = Some([left_value, right_value]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,9 +1,11 @@
|
|||||||
use std::{
|
use std::{
|
||||||
|
cell::{RefCell, RefMut},
|
||||||
fmt::{self, Debug, Display, Formatter},
|
fmt::{self, Debug, Display, Formatter},
|
||||||
|
ops::{Add, Index, IndexMut},
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
};
|
};
|
||||||
|
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use crate::{AbstractList, Chunk, DustString, Function};
|
use crate::{AbstractList, Chunk, DustString, Function};
|
||||||
|
|
||||||
@ -13,17 +15,220 @@ pub struct CallFrame {
|
|||||||
pub ip: usize,
|
pub ip: usize,
|
||||||
pub return_register: u16,
|
pub return_register: u16,
|
||||||
pub registers: RegisterTable,
|
pub registers: RegisterTable,
|
||||||
|
pub constants: ConstantTable,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CallFrame {
|
impl CallFrame {
|
||||||
pub fn new(chunk: Rc<Chunk>, return_register: u16) -> Self {
|
pub fn new(chunk: Rc<Chunk>, return_register: u16) -> Self {
|
||||||
let registers = RegisterTable::new();
|
let registers = RegisterTable {
|
||||||
|
booleans: RegisterList::new(chunk.boolean_register_count as usize),
|
||||||
|
bytes: RegisterList::new(chunk.byte_register_count as usize),
|
||||||
|
characters: RegisterList::new(chunk.character_register_count as usize),
|
||||||
|
floats: RegisterList::new(chunk.float_register_count as usize),
|
||||||
|
integers: RegisterList::new(chunk.integer_register_count as usize),
|
||||||
|
strings: RegisterList::new(chunk.string_register_count as usize),
|
||||||
|
lists: RegisterList::new(chunk.list_register_count as usize),
|
||||||
|
functions: RegisterList::new(chunk.function_register_count as usize),
|
||||||
|
};
|
||||||
|
let constants = ConstantTable {
|
||||||
|
characters: chunk
|
||||||
|
.character_constants
|
||||||
|
.iter()
|
||||||
|
.map(|&character| RuntimeValue::Raw(character))
|
||||||
|
.collect(),
|
||||||
|
floats: chunk
|
||||||
|
.float_constants
|
||||||
|
.iter()
|
||||||
|
.map(|&float| RuntimeValue::Raw(float))
|
||||||
|
.collect(),
|
||||||
|
integers: chunk
|
||||||
|
.integer_constants
|
||||||
|
.iter()
|
||||||
|
.map(|&integer| RuntimeValue::Raw(integer))
|
||||||
|
.collect(),
|
||||||
|
strings: chunk
|
||||||
|
.string_constants
|
||||||
|
.iter()
|
||||||
|
.map(|string| RuntimeValue::Raw(string.clone()))
|
||||||
|
.collect(),
|
||||||
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
chunk,
|
chunk,
|
||||||
ip: 0,
|
ip: 0,
|
||||||
return_register,
|
return_register,
|
||||||
registers,
|
registers,
|
||||||
|
constants,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_boolean_from_register(&self, register_index: usize) -> &RuntimeValue<bool> {
|
||||||
|
let register = self.registers.booleans.get(register_index);
|
||||||
|
|
||||||
|
match register {
|
||||||
|
Register::Value { value, .. } => value,
|
||||||
|
Register::Pointer { pointer, .. } => self.get_boolean_from_pointer(pointer),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_boolean_from_pointer(&self, pointer: &Pointer) -> &RuntimeValue<bool> {
|
||||||
|
match pointer {
|
||||||
|
Pointer::Register(register_index) => self.get_boolean_from_register(*register_index),
|
||||||
|
Pointer::Constant(_) => panic!("Attempted to get boolean from constant pointer"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_byte_from_register(&self, register_index: usize) -> &RuntimeValue<u8> {
|
||||||
|
let register = self.registers.bytes.get(register_index);
|
||||||
|
|
||||||
|
match register {
|
||||||
|
Register::Value { value, .. } => value,
|
||||||
|
Register::Pointer { pointer, .. } => self.get_byte_from_pointer(pointer),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_byte_from_pointer(&self, pointer: &Pointer) -> &RuntimeValue<u8> {
|
||||||
|
match pointer {
|
||||||
|
Pointer::Register(register_index) => self.get_byte_from_register(*register_index),
|
||||||
|
Pointer::Constant(_) => panic!("Attempted to get byte from constant pointer"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_character_from_register(&self, register_index: usize) -> &RuntimeValue<char> {
|
||||||
|
let register = self.registers.characters.get(register_index);
|
||||||
|
|
||||||
|
match register {
|
||||||
|
Register::Value { value, .. } => value,
|
||||||
|
Register::Pointer { pointer, .. } => self.get_character_from_pointer(pointer),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_character_from_pointer(&self, pointer: &Pointer) -> &RuntimeValue<char> {
|
||||||
|
match pointer {
|
||||||
|
Pointer::Register(register_index) => self.get_character_from_register(*register_index),
|
||||||
|
Pointer::Constant(constant_index) => self.get_character_constant(*constant_index),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_character_constant(&self, constant_index: usize) -> &RuntimeValue<char> {
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
self.constants.characters.get(constant_index).unwrap()
|
||||||
|
} else {
|
||||||
|
unsafe { self.constants.characters.get_unchecked(constant_index) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_float_from_register(&self, register_index: usize) -> &RuntimeValue<f64> {
|
||||||
|
let register = self.registers.floats.get(register_index);
|
||||||
|
|
||||||
|
match register {
|
||||||
|
Register::Value { value, .. } => value,
|
||||||
|
Register::Pointer { pointer, .. } => self.get_float_from_pointer(pointer),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_float_from_pointer(&self, pointer: &Pointer) -> &RuntimeValue<f64> {
|
||||||
|
match pointer {
|
||||||
|
Pointer::Register(register_index) => self.get_float_from_register(*register_index),
|
||||||
|
Pointer::Constant(constant_index) => self.get_float_constant(*constant_index),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_float_constant(&self, constant_index: usize) -> &RuntimeValue<f64> {
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
self.constants.floats.get(constant_index).unwrap()
|
||||||
|
} else {
|
||||||
|
unsafe { self.constants.floats.get_unchecked(constant_index) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_integer_from_register(&self, register_index: usize) -> &RuntimeValue<i64> {
|
||||||
|
let register = self.registers.integers.get(register_index);
|
||||||
|
|
||||||
|
match register {
|
||||||
|
Register::Value { value, .. } => value,
|
||||||
|
Register::Pointer { pointer, .. } => self.get_integer_from_pointer(pointer),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_integer_from_register_mut(
|
||||||
|
&mut self,
|
||||||
|
register_index: usize,
|
||||||
|
) -> &mut RuntimeValue<i64> {
|
||||||
|
let register = self.registers.integers.get_mut(register_index);
|
||||||
|
|
||||||
|
match register {
|
||||||
|
Register::Value { value, .. } => value,
|
||||||
|
Register::Pointer { .. } => {
|
||||||
|
panic!("Attempted to get mutable integer from pointer")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_integer_from_pointer(&self, pointer: &Pointer) -> &RuntimeValue<i64> {
|
||||||
|
match pointer {
|
||||||
|
Pointer::Register(register_index) => self.get_integer_from_register(*register_index),
|
||||||
|
Pointer::Constant(constant_index) => self.get_integer_constant(*constant_index),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_integer_from_pointer_mut(&mut self, pointer: &Pointer) -> &mut RuntimeValue<i64> {
|
||||||
|
match pointer {
|
||||||
|
Pointer::Register(register_index) => {
|
||||||
|
self.get_integer_from_register_mut(*register_index)
|
||||||
|
}
|
||||||
|
Pointer::Constant(constant_index) => self.get_integer_constant_mut(*constant_index),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_integer_constant(&self, constant_index: usize) -> &RuntimeValue<i64> {
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
self.constants.integers.get(constant_index).unwrap()
|
||||||
|
} else {
|
||||||
|
unsafe { self.constants.integers.get_unchecked(constant_index) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_integer_constant_mut(&mut self, constant_index: usize) -> &mut RuntimeValue<i64> {
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
self.constants.integers.get_mut(constant_index).unwrap()
|
||||||
|
} else {
|
||||||
|
unsafe { self.constants.integers.get_unchecked_mut(constant_index) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_string_from_register(&self, register_index: usize) -> &RuntimeValue<DustString> {
|
||||||
|
let register = self.registers.strings.get(register_index);
|
||||||
|
|
||||||
|
match register {
|
||||||
|
Register::Value { value, .. } => value,
|
||||||
|
Register::Pointer { pointer, .. } => self.get_string_from_pointer(pointer),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_string_from_pointer(&self, pointer: &Pointer) -> &RuntimeValue<DustString> {
|
||||||
|
match pointer {
|
||||||
|
Pointer::Register(register_index) => self.get_string_from_register(*register_index),
|
||||||
|
Pointer::Constant(constant_index) => self.get_string_constant(*constant_index),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_string_constant(&self, constant_index: usize) -> &RuntimeValue<DustString> {
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
self.constants.strings.get(constant_index).unwrap()
|
||||||
|
} else {
|
||||||
|
unsafe { self.constants.strings.get_unchecked(constant_index) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_string_constant_mut(
|
||||||
|
&mut self,
|
||||||
|
constant_index: usize,
|
||||||
|
) -> &mut RuntimeValue<DustString> {
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
self.constants.strings.get_mut(constant_index).unwrap()
|
||||||
|
} else {
|
||||||
|
unsafe { self.constants.strings.get_unchecked_mut(constant_index) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -42,103 +247,348 @@ impl Display for CallFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Default)]
|
||||||
pub struct RegisterTable {
|
pub struct ConstantTable {
|
||||||
pub booleans: SmallVec<[Register<bool>; 64]>,
|
pub characters: Vec<RuntimeValue<char>>,
|
||||||
pub bytes: SmallVec<[Register<u8>; 64]>,
|
pub floats: Vec<RuntimeValue<f64>>,
|
||||||
pub characters: SmallVec<[Register<char>; 64]>,
|
pub integers: Vec<RuntimeValue<i64>>,
|
||||||
pub floats: SmallVec<[Register<f64>; 64]>,
|
pub strings: Vec<RuntimeValue<DustString>>,
|
||||||
pub integers: SmallVec<[Register<i64>; 64]>,
|
|
||||||
pub strings: SmallVec<[Register<DustString>; 64]>,
|
|
||||||
pub lists: SmallVec<[Register<AbstractList>; 64]>,
|
|
||||||
pub functions: SmallVec<[Register<Function>; 64]>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RegisterTable {
|
#[derive(Debug)]
|
||||||
pub fn new() -> Self {
|
pub struct RegisterTable {
|
||||||
Self {
|
pub booleans: RegisterList<bool>,
|
||||||
booleans: smallvec![Register::default(); 64],
|
pub bytes: RegisterList<u8>,
|
||||||
bytes: smallvec![Register::default(); 64],
|
pub characters: RegisterList<char>,
|
||||||
characters: smallvec![Register::default(); 64],
|
pub floats: RegisterList<f64>,
|
||||||
floats: smallvec![Register::default(); 64],
|
pub integers: RegisterList<i64>,
|
||||||
integers: smallvec![Register::default(); 64],
|
pub strings: RegisterList<DustString>,
|
||||||
strings: smallvec![Register::default(); 64],
|
pub lists: RegisterList<AbstractList>,
|
||||||
lists: smallvec![Register::default(); 64],
|
pub functions: RegisterList<Function>,
|
||||||
functions: smallvec![Register::default(); 64],
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct RegisterList<T, const STACK_LEN: usize = 64> {
|
||||||
|
pub registers: SmallVec<[Register<T>; STACK_LEN]>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, const STACK_LEN: usize> RegisterList<T, STACK_LEN>
|
||||||
|
where
|
||||||
|
T: Clone + Default,
|
||||||
|
{
|
||||||
|
pub fn new(length: usize) -> Self {
|
||||||
|
let mut registers = SmallVec::with_capacity(length);
|
||||||
|
|
||||||
|
for _ in 0..length {
|
||||||
|
registers.push(Register::default());
|
||||||
|
}
|
||||||
|
|
||||||
|
Self { registers }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(&self, index: usize) -> &Register<T> {
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
self.registers.get(index).unwrap()
|
||||||
|
} else {
|
||||||
|
unsafe { self.registers.get_unchecked(index) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_mut(&mut self, index: usize) -> &mut Register<T> {
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
let length = self.registers.len();
|
||||||
|
|
||||||
|
self.registers
|
||||||
|
.get_mut(index)
|
||||||
|
.unwrap_or_else(|| panic!("Index out of bounds: {index}. Length is {length}"))
|
||||||
|
} else {
|
||||||
|
unsafe { self.registers.get_unchecked_mut(index) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn close(&mut self, index: usize) {
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
self.registers.get_mut(index).unwrap().close()
|
||||||
|
} else {
|
||||||
|
unsafe { self.registers.get_unchecked_mut(index).close() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_closed(&self, index: usize) -> bool {
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
self.registers.get(index).unwrap().is_closed()
|
||||||
|
} else {
|
||||||
|
unsafe { self.registers.get_unchecked(index).is_closed() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for RegisterTable {
|
impl<T> Index<usize> for RegisterList<T> {
|
||||||
fn default() -> Self {
|
type Output = Register<T>;
|
||||||
Self::new()
|
|
||||||
|
fn index(&self, index: usize) -> &Self::Output {
|
||||||
|
&self.registers[index]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
impl<T> IndexMut<usize> for RegisterList<T> {
|
||||||
pub enum Register<T: Default> {
|
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
||||||
Value(T),
|
&mut self.registers[index]
|
||||||
Closed(T),
|
}
|
||||||
Pointer(Pointer),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Default> Register<T> {
|
#[derive(Clone, Debug)]
|
||||||
pub fn contained_value_mut(&mut self) -> Option<&mut T> {
|
pub enum Register<T> {
|
||||||
|
Value {
|
||||||
|
value: RuntimeValue<T>,
|
||||||
|
is_closed: bool,
|
||||||
|
},
|
||||||
|
Pointer {
|
||||||
|
pointer: Pointer,
|
||||||
|
is_closed: bool,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Register<T> {
|
||||||
|
pub fn is_closed(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::Value(value) => Some(value),
|
Self::Value { is_closed, .. } => *is_closed,
|
||||||
Self::Closed(value) => Some(value),
|
Self::Pointer { is_closed, .. } => *is_closed,
|
||||||
Self::Pointer(_) => None,
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn close(&mut self) {
|
||||||
|
match self {
|
||||||
|
Self::Value { is_closed, .. } => *is_closed = true,
|
||||||
|
Self::Pointer { is_closed, .. } => *is_closed = true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set(&mut self, new_value: RuntimeValue<T>) {
|
||||||
|
match self {
|
||||||
|
Self::Value {
|
||||||
|
value: old_value, ..
|
||||||
|
} => *old_value = new_value,
|
||||||
|
Self::Pointer { is_closed, .. } => {
|
||||||
|
*self = Self::Value {
|
||||||
|
value: new_value,
|
||||||
|
is_closed: *is_closed,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_value(&self) -> &RuntimeValue<T> {
|
||||||
|
match self {
|
||||||
|
Self::Value { value, .. } => value,
|
||||||
|
Self::Pointer { .. } => panic!("Attempted to use pointer as value"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_value_mut(&mut self) -> &mut RuntimeValue<T> {
|
||||||
|
match self {
|
||||||
|
Self::Value { value, .. } => value,
|
||||||
|
Self::Pointer { .. } => panic!("Attempted to use pointer as value"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Default> Default for Register<T> {
|
impl<T: Default> Default for Register<T> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::Value(T::default())
|
Self::Value {
|
||||||
|
value: RuntimeValue::Raw(Default::default()),
|
||||||
|
is_closed: false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Default + Display> Display for Register<T> {
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum RuntimeValue<T> {
|
||||||
|
Raw(T),
|
||||||
|
Rc(Rc<T>),
|
||||||
|
RefCell(Rc<RefCell<T>>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Clone> RuntimeValue<T> {
|
||||||
|
pub fn ref_cell(value: T) -> Self {
|
||||||
|
Self::RefCell(Rc::new(RefCell::new(value)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rc(value: T) -> Self {
|
||||||
|
Self::Rc(Rc::new(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_ref_cell(&mut self) -> Self {
|
||||||
|
match self {
|
||||||
|
Self::Raw(value) => RuntimeValue::ref_cell(value.clone()),
|
||||||
|
Self::Rc(value) => RuntimeValue::ref_cell(value.as_ref().clone()),
|
||||||
|
Self::RefCell(_) => self.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_rc(&mut self) -> Self {
|
||||||
|
match self {
|
||||||
|
Self::Raw(value) => RuntimeValue::rc(value.clone()),
|
||||||
|
Self::Rc(_) => self.clone(),
|
||||||
|
Self::RefCell(value) => RuntimeValue::rc(value.borrow().clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_inner(&mut self, new_value: T) {
|
||||||
|
match self {
|
||||||
|
Self::Raw(value) => *value = new_value,
|
||||||
|
Self::Rc(value) => {
|
||||||
|
if let Some(mutable) = Rc::get_mut(value) {
|
||||||
|
*mutable = new_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self::RefCell(value) => {
|
||||||
|
let _ = value.replace(new_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clone_inner(&self) -> T {
|
||||||
|
match self {
|
||||||
|
Self::Raw(value) => value.clone(),
|
||||||
|
Self::Rc(value) => value.as_ref().clone(),
|
||||||
|
Self::RefCell(value) => value.borrow().clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn borrow_mut(&self) -> RefMut<T> {
|
||||||
|
match self {
|
||||||
|
Self::RefCell(value) => value.borrow_mut(),
|
||||||
|
_ => panic!("Attempted to borrow mutable reference from immutable register value"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Add<Output = T> + Copy> Add for &RuntimeValue<T> {
|
||||||
|
type Output = T;
|
||||||
|
|
||||||
|
fn add(self, other: Self) -> Self::Output {
|
||||||
|
match (self, other) {
|
||||||
|
(RuntimeValue::Raw(left), RuntimeValue::Raw(right)) => *left + *right,
|
||||||
|
(RuntimeValue::Raw(left), RuntimeValue::Rc(right)) => *left + **right,
|
||||||
|
(RuntimeValue::Raw(left), RuntimeValue::RefCell(right)) => {
|
||||||
|
let right = right.borrow();
|
||||||
|
|
||||||
|
*left + *right
|
||||||
|
}
|
||||||
|
(RuntimeValue::Rc(left), RuntimeValue::Raw(right)) => **left + *right,
|
||||||
|
(RuntimeValue::Rc(left), RuntimeValue::Rc(right)) => **left + **right,
|
||||||
|
(RuntimeValue::Rc(left), RuntimeValue::RefCell(right)) => {
|
||||||
|
let right = right.borrow();
|
||||||
|
|
||||||
|
**left + *right
|
||||||
|
}
|
||||||
|
(RuntimeValue::RefCell(left), RuntimeValue::RefCell(right)) => {
|
||||||
|
let left = left.borrow();
|
||||||
|
let right = right.borrow();
|
||||||
|
|
||||||
|
*left + *right
|
||||||
|
}
|
||||||
|
(RuntimeValue::RefCell(left), RuntimeValue::Raw(right)) => {
|
||||||
|
let left = left.borrow();
|
||||||
|
|
||||||
|
*left + *right
|
||||||
|
}
|
||||||
|
(RuntimeValue::RefCell(left), RuntimeValue::Rc(right)) => {
|
||||||
|
let left = left.borrow();
|
||||||
|
|
||||||
|
*left + **right
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: PartialEq> PartialEq for RuntimeValue<T> {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
match (self, other) {
|
||||||
|
(RuntimeValue::Raw(left), RuntimeValue::Raw(right)) => left == right,
|
||||||
|
(RuntimeValue::Raw(left), RuntimeValue::Rc(right)) => left == &**right,
|
||||||
|
(RuntimeValue::Raw(left), RuntimeValue::RefCell(right)) => {
|
||||||
|
let right = right.borrow();
|
||||||
|
|
||||||
|
left == &*right
|
||||||
|
}
|
||||||
|
(RuntimeValue::Rc(left), RuntimeValue::Raw(right)) => **left == *right,
|
||||||
|
(RuntimeValue::Rc(left), RuntimeValue::Rc(right)) => **left == **right,
|
||||||
|
(RuntimeValue::Rc(left), RuntimeValue::RefCell(right)) => {
|
||||||
|
let right = right.borrow();
|
||||||
|
|
||||||
|
**left == *right
|
||||||
|
}
|
||||||
|
(RuntimeValue::RefCell(left), RuntimeValue::RefCell(right)) => {
|
||||||
|
let left = left.borrow();
|
||||||
|
let right = right.borrow();
|
||||||
|
|
||||||
|
*left == *right
|
||||||
|
}
|
||||||
|
(RuntimeValue::RefCell(left), RuntimeValue::Raw(right)) => {
|
||||||
|
let left = left.borrow();
|
||||||
|
|
||||||
|
*left == *right
|
||||||
|
}
|
||||||
|
(RuntimeValue::RefCell(left), RuntimeValue::Rc(right)) => {
|
||||||
|
let left = left.borrow();
|
||||||
|
|
||||||
|
*left == **right
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: PartialOrd> PartialOrd for RuntimeValue<T> {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||||
|
match (self, other) {
|
||||||
|
(RuntimeValue::Raw(left), RuntimeValue::Raw(right)) => left.partial_cmp(right),
|
||||||
|
(RuntimeValue::Raw(left), RuntimeValue::Rc(right)) => left.partial_cmp(&**right),
|
||||||
|
(RuntimeValue::Raw(left), RuntimeValue::RefCell(right)) => {
|
||||||
|
let right = right.borrow();
|
||||||
|
|
||||||
|
left.partial_cmp(&*right)
|
||||||
|
}
|
||||||
|
(RuntimeValue::Rc(left), RuntimeValue::Raw(right)) => (**left).partial_cmp(right),
|
||||||
|
(RuntimeValue::Rc(left), RuntimeValue::Rc(right)) => left.partial_cmp(right),
|
||||||
|
(RuntimeValue::Rc(left), RuntimeValue::RefCell(right)) => {
|
||||||
|
let right = right.borrow();
|
||||||
|
|
||||||
|
(**left).partial_cmp(&right)
|
||||||
|
}
|
||||||
|
(RuntimeValue::RefCell(left), RuntimeValue::RefCell(right)) => {
|
||||||
|
let left = left.borrow();
|
||||||
|
let right = right.borrow();
|
||||||
|
|
||||||
|
left.partial_cmp(&*right)
|
||||||
|
}
|
||||||
|
(RuntimeValue::RefCell(left), RuntimeValue::Raw(right)) => {
|
||||||
|
let left = left.borrow();
|
||||||
|
|
||||||
|
left.partial_cmp(right)
|
||||||
|
}
|
||||||
|
(RuntimeValue::RefCell(left), RuntimeValue::Rc(right)) => {
|
||||||
|
let left = left.borrow();
|
||||||
|
|
||||||
|
left.partial_cmp(&**right)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Display> Display for RuntimeValue<T> {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::Closed(value) => write!(f, "Closed({value})"),
|
Self::Raw(value) => write!(f, "{}", value),
|
||||||
Self::Value(value) => write!(f, "Value({value})"),
|
Self::Rc(value) => write!(f, "{}", value),
|
||||||
Self::Pointer(pointer) => write!(f, "Pointer({pointer:?})"),
|
Self::RefCell(value) => write!(f, "{}", value.borrow()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub enum Pointer {
|
pub enum Pointer {
|
||||||
RegisterBoolean(usize),
|
Register(usize),
|
||||||
RegisterByte(usize),
|
Constant(usize),
|
||||||
RegisterCharacter(usize),
|
|
||||||
RegisterFloat(usize),
|
|
||||||
RegisterInteger(usize),
|
|
||||||
RegisterString(usize),
|
|
||||||
RegisterList(usize),
|
|
||||||
RegisterFunction(usize),
|
|
||||||
ConstantCharacter(usize),
|
|
||||||
ConstantFloat(usize),
|
|
||||||
ConstantInteger(usize),
|
|
||||||
ConstantString(usize),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for Pointer {
|
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::RegisterBoolean(index) => write!(f, "P_R_BOOL_{index}"),
|
|
||||||
Self::RegisterByte(index) => write!(f, "P_R_BYTE_{index}"),
|
|
||||||
Self::RegisterCharacter(index) => write!(f, "P_R_CHAR_{index}"),
|
|
||||||
Self::RegisterFloat(index) => write!(f, "P_R_FLOAT_{index}"),
|
|
||||||
Self::RegisterInteger(index) => write!(f, "P_R_INT_{index}"),
|
|
||||||
Self::RegisterString(index) => write!(f, "P_R_STR_{index}"),
|
|
||||||
Self::RegisterList(index) => write!(f, "P_R_LIST_{index}"),
|
|
||||||
Self::RegisterFunction(index) => write!(f, "P_R_FN_{index}"),
|
|
||||||
Self::ConstantCharacter(index) => write!(f, "P_C_CHAR_{index}"),
|
|
||||||
Self::ConstantFloat(index) => write!(f, "P_C_FLOAT_{index}"),
|
|
||||||
Self::ConstantInteger(index) => write!(f, "P_C_INT_{index}"),
|
|
||||||
Self::ConstantString(index) => write!(f, "P_C_STR_{index}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -5,14 +5,13 @@ mod thread;
|
|||||||
|
|
||||||
use std::{rc::Rc, thread::Builder};
|
use std::{rc::Rc, thread::Builder};
|
||||||
|
|
||||||
pub use action::Action;
|
pub use call_frame::{CallFrame, Pointer, Register, RegisterTable, RuntimeValue};
|
||||||
pub use call_frame::{CallFrame, Pointer, Register, RegisterTable};
|
|
||||||
pub use thread::Thread;
|
pub use thread::Thread;
|
||||||
|
|
||||||
use crossbeam_channel::bounded;
|
use crossbeam_channel::bounded;
|
||||||
use tracing::{Level, span};
|
use tracing::{span, Level};
|
||||||
|
|
||||||
use crate::{Chunk, DustError, Value, compile};
|
use crate::{compile, Chunk, DustError, Value};
|
||||||
|
|
||||||
pub fn run(source: &str) -> Result<Option<Value>, DustError> {
|
pub fn run(source: &str) -> Result<Option<Value>, DustError> {
|
||||||
let chunk = compile(source)?;
|
let chunk = compile(source)?;
|
||||||
|
@ -5,11 +5,9 @@ use tracing::{info, trace};
|
|||||||
use crate::{
|
use crate::{
|
||||||
instruction::InstructionFields,
|
instruction::InstructionFields,
|
||||||
vm::{action::ActionSequence, CallFrame},
|
vm::{action::ActionSequence, CallFrame},
|
||||||
AbstractList, Chunk, ConcreteValue, DustString, Span, Value,
|
Chunk, DustString, Span, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::call_frame::{Pointer, Register};
|
|
||||||
|
|
||||||
pub struct Thread {
|
pub struct Thread {
|
||||||
chunk: Rc<Chunk>,
|
chunk: Rc<Chunk>,
|
||||||
call_stack: Vec<CallFrame>,
|
call_stack: Vec<CallFrame>,
|
||||||
@ -77,811 +75,4 @@ impl Thread {
|
|||||||
unsafe { self.call_stack.last_mut().unwrap_unchecked() }
|
unsafe { self.call_stack.last_mut().unwrap_unchecked() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_value_from_pointer(&self, pointer: &Pointer) -> ConcreteValue {
|
|
||||||
match pointer {
|
|
||||||
Pointer::RegisterBoolean(register_index) => {
|
|
||||||
let boolean = *self.get_boolean_register(*register_index);
|
|
||||||
|
|
||||||
ConcreteValue::Boolean(boolean)
|
|
||||||
}
|
|
||||||
Pointer::RegisterByte(register_index) => {
|
|
||||||
let byte = *self.get_byte_register(*register_index);
|
|
||||||
|
|
||||||
ConcreteValue::Byte(byte)
|
|
||||||
}
|
|
||||||
Pointer::RegisterCharacter(register_index) => {
|
|
||||||
let character = *self.get_character_register(*register_index);
|
|
||||||
|
|
||||||
ConcreteValue::Character(character)
|
|
||||||
}
|
|
||||||
Pointer::RegisterFloat(register_index) => {
|
|
||||||
let float = *self.get_float_register(*register_index);
|
|
||||||
|
|
||||||
ConcreteValue::Float(float)
|
|
||||||
}
|
|
||||||
Pointer::RegisterInteger(register_index) => {
|
|
||||||
let integer = *self.get_integer_register(*register_index);
|
|
||||||
|
|
||||||
ConcreteValue::Integer(integer)
|
|
||||||
}
|
|
||||||
Pointer::RegisterString(register_index) => {
|
|
||||||
let string = self.get_string_register(*register_index).clone();
|
|
||||||
|
|
||||||
ConcreteValue::String(string)
|
|
||||||
}
|
|
||||||
Pointer::RegisterList(register_index) => {
|
|
||||||
let abstract_list = self.get_list_register(*register_index).clone();
|
|
||||||
let mut items = Vec::with_capacity(abstract_list.item_pointers.len());
|
|
||||||
|
|
||||||
for pointer in &abstract_list.item_pointers {
|
|
||||||
let value = self.get_value_from_pointer(pointer);
|
|
||||||
|
|
||||||
items.push(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
ConcreteValue::List {
|
|
||||||
items,
|
|
||||||
item_type: abstract_list.item_type,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Pointer::RegisterFunction(_) => unimplemented!(),
|
|
||||||
Pointer::ConstantCharacter(constant_index) => {
|
|
||||||
let character = *self.get_constant(*constant_index).as_character().unwrap();
|
|
||||||
|
|
||||||
ConcreteValue::Character(character)
|
|
||||||
}
|
|
||||||
Pointer::ConstantFloat(constant_index) => {
|
|
||||||
let float = *self.get_constant(*constant_index).as_float().unwrap();
|
|
||||||
|
|
||||||
ConcreteValue::Float(float)
|
|
||||||
}
|
|
||||||
Pointer::ConstantInteger(constant_index) => {
|
|
||||||
let integer = *self.get_constant(*constant_index).as_integer().unwrap();
|
|
||||||
|
|
||||||
ConcreteValue::Integer(integer)
|
|
||||||
}
|
|
||||||
Pointer::ConstantString(constant_index) => {
|
|
||||||
let string = self
|
|
||||||
.get_constant(*constant_index)
|
|
||||||
.as_string()
|
|
||||||
.unwrap()
|
|
||||||
.clone();
|
|
||||||
|
|
||||||
ConcreteValue::String(string)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_boolean_register(&self, register_index: usize) -> &bool {
|
|
||||||
let register = if cfg!(debug_assertions) {
|
|
||||||
self.call_stack
|
|
||||||
.last()
|
|
||||||
.unwrap()
|
|
||||||
.registers
|
|
||||||
.booleans
|
|
||||||
.get(register_index)
|
|
||||||
.unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe {
|
|
||||||
self.call_stack
|
|
||||||
.last()
|
|
||||||
.unwrap_unchecked()
|
|
||||||
.registers
|
|
||||||
.booleans
|
|
||||||
.get_unchecked(register_index)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match register {
|
|
||||||
Register::Value(value) => value,
|
|
||||||
Register::Closed(value) => value,
|
|
||||||
Register::Pointer(pointer) => self.get_pointer_to_boolean(pointer),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_pointer_to_boolean(&self, pointer: &Pointer) -> &bool {
|
|
||||||
match pointer {
|
|
||||||
Pointer::RegisterBoolean(register_index) => self.get_boolean_register(*register_index),
|
|
||||||
_ => panic!("Attempted to get boolean from non-boolean pointer"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_boolean_register(&mut self, register_index: usize, new_register: Register<bool>) {
|
|
||||||
let old_register = if cfg!(debug_assertions) {
|
|
||||||
self.call_stack
|
|
||||||
.last_mut()
|
|
||||||
.unwrap()
|
|
||||||
.registers
|
|
||||||
.booleans
|
|
||||||
.get_mut(register_index)
|
|
||||||
.unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe {
|
|
||||||
self.call_stack
|
|
||||||
.last_mut()
|
|
||||||
.unwrap_unchecked()
|
|
||||||
.registers
|
|
||||||
.booleans
|
|
||||||
.get_unchecked_mut(register_index)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
*old_register = new_register;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_boolean_register_closed(&self, register_index: usize) -> bool {
|
|
||||||
let register = if cfg!(debug_assertions) {
|
|
||||||
self.call_stack
|
|
||||||
.last()
|
|
||||||
.unwrap()
|
|
||||||
.registers
|
|
||||||
.booleans
|
|
||||||
.get(register_index)
|
|
||||||
.unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe {
|
|
||||||
self.call_stack
|
|
||||||
.last()
|
|
||||||
.unwrap_unchecked()
|
|
||||||
.registers
|
|
||||||
.booleans
|
|
||||||
.get_unchecked(register_index)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
matches!(register, Register::Closed(_))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn close_boolean_register(&mut self, register_index: usize) {
|
|
||||||
let register = self
|
|
||||||
.current_frame_mut()
|
|
||||||
.registers
|
|
||||||
.booleans
|
|
||||||
.get_mut(register_index)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
*register = match register {
|
|
||||||
Register::Value(value) => Register::Closed(*value),
|
|
||||||
_ => panic!("Attempted to close non-value register"),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_byte_register(&self, register_index: usize) -> &u8 {
|
|
||||||
let register = if cfg!(debug_assertions) {
|
|
||||||
self.call_stack
|
|
||||||
.last()
|
|
||||||
.unwrap()
|
|
||||||
.registers
|
|
||||||
.bytes
|
|
||||||
.get(register_index)
|
|
||||||
.unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe {
|
|
||||||
self.call_stack
|
|
||||||
.last()
|
|
||||||
.unwrap_unchecked()
|
|
||||||
.registers
|
|
||||||
.bytes
|
|
||||||
.get_unchecked(register_index)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match register {
|
|
||||||
Register::Value(value) => value,
|
|
||||||
Register::Closed(value) => value,
|
|
||||||
Register::Pointer(pointer) => self.get_pointer_to_byte(pointer),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_pointer_to_byte(&self, pointer: &Pointer) -> &u8 {
|
|
||||||
match pointer {
|
|
||||||
Pointer::RegisterByte(register_index) => self.get_byte_register(*register_index),
|
|
||||||
_ => panic!("Attempted to get byte from non-byte pointer"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_byte_register(&mut self, register_index: usize, new_register: Register<u8>) {
|
|
||||||
let old_register = if cfg!(debug_assertions) {
|
|
||||||
self.call_stack
|
|
||||||
.last_mut()
|
|
||||||
.unwrap()
|
|
||||||
.registers
|
|
||||||
.bytes
|
|
||||||
.get_mut(register_index)
|
|
||||||
.unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe {
|
|
||||||
self.call_stack
|
|
||||||
.last_mut()
|
|
||||||
.unwrap_unchecked()
|
|
||||||
.registers
|
|
||||||
.bytes
|
|
||||||
.get_unchecked_mut(register_index)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
*old_register = new_register;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_byte_register_closed(&self, register_index: usize) -> bool {
|
|
||||||
let register = if cfg!(debug_assertions) {
|
|
||||||
self.call_stack
|
|
||||||
.last()
|
|
||||||
.unwrap()
|
|
||||||
.registers
|
|
||||||
.bytes
|
|
||||||
.get(register_index)
|
|
||||||
.unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe {
|
|
||||||
self.call_stack
|
|
||||||
.last()
|
|
||||||
.unwrap_unchecked()
|
|
||||||
.registers
|
|
||||||
.bytes
|
|
||||||
.get_unchecked(register_index)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
matches!(register, Register::Closed(_))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn close_byte_register(&mut self, register_index: usize) {
|
|
||||||
let register = self
|
|
||||||
.current_frame_mut()
|
|
||||||
.registers
|
|
||||||
.bytes
|
|
||||||
.get_mut(register_index)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
*register = match register {
|
|
||||||
Register::Value(value) => Register::Closed(*value),
|
|
||||||
_ => panic!("Attempted to close non-value register"),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_character_register(&self, register_index: usize) -> &char {
|
|
||||||
let register = if cfg!(debug_assertions) {
|
|
||||||
self.call_stack
|
|
||||||
.last()
|
|
||||||
.unwrap()
|
|
||||||
.registers
|
|
||||||
.characters
|
|
||||||
.get(register_index)
|
|
||||||
.unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe {
|
|
||||||
self.call_stack
|
|
||||||
.last()
|
|
||||||
.unwrap_unchecked()
|
|
||||||
.registers
|
|
||||||
.characters
|
|
||||||
.get_unchecked(register_index)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match register {
|
|
||||||
Register::Value(value) => value,
|
|
||||||
Register::Closed(value) => value,
|
|
||||||
Register::Pointer(pointer) => self.get_pointer_to_character(pointer),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_pointer_to_character(&self, pointer: &Pointer) -> &char {
|
|
||||||
match pointer {
|
|
||||||
Pointer::RegisterCharacter(register_index) => {
|
|
||||||
self.get_character_register(*register_index)
|
|
||||||
}
|
|
||||||
Pointer::ConstantCharacter(constant_index) => {
|
|
||||||
self.get_constant(*constant_index).as_character().unwrap()
|
|
||||||
}
|
|
||||||
_ => panic!("Attempted to get character from non-character pointer"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_character_register(&mut self, register_index: usize, new_register: Register<char>) {
|
|
||||||
let old_register = if cfg!(debug_assertions) {
|
|
||||||
self.call_stack
|
|
||||||
.last_mut()
|
|
||||||
.unwrap()
|
|
||||||
.registers
|
|
||||||
.characters
|
|
||||||
.get_mut(register_index)
|
|
||||||
.unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe {
|
|
||||||
self.call_stack
|
|
||||||
.last_mut()
|
|
||||||
.unwrap_unchecked()
|
|
||||||
.registers
|
|
||||||
.characters
|
|
||||||
.get_unchecked_mut(register_index)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
*old_register = new_register;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_character_register_closed(&self, register_index: usize) -> bool {
|
|
||||||
let register = if cfg!(debug_assertions) {
|
|
||||||
self.call_stack
|
|
||||||
.last()
|
|
||||||
.unwrap()
|
|
||||||
.registers
|
|
||||||
.characters
|
|
||||||
.get(register_index)
|
|
||||||
.unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe {
|
|
||||||
self.call_stack
|
|
||||||
.last()
|
|
||||||
.unwrap_unchecked()
|
|
||||||
.registers
|
|
||||||
.characters
|
|
||||||
.get_unchecked(register_index)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
matches!(register, Register::Closed(_))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn close_character_register(&mut self, register_index: usize) {
|
|
||||||
let register = self
|
|
||||||
.current_frame_mut()
|
|
||||||
.registers
|
|
||||||
.characters
|
|
||||||
.get_mut(register_index)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
*register = match register {
|
|
||||||
Register::Value(value) => Register::Closed(*value),
|
|
||||||
_ => panic!("Attempted to close non-value register"),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_float_register(&self, register_index: usize) -> &f64 {
|
|
||||||
let register = if cfg!(debug_assertions) {
|
|
||||||
self.call_stack
|
|
||||||
.last()
|
|
||||||
.unwrap()
|
|
||||||
.registers
|
|
||||||
.floats
|
|
||||||
.get(register_index)
|
|
||||||
.unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe {
|
|
||||||
self.call_stack
|
|
||||||
.last()
|
|
||||||
.unwrap_unchecked()
|
|
||||||
.registers
|
|
||||||
.floats
|
|
||||||
.get_unchecked(register_index)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match register {
|
|
||||||
Register::Value(value) => value,
|
|
||||||
Register::Closed(value) => value,
|
|
||||||
Register::Pointer(pointer) => self.get_pointer_to_float(pointer),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_pointer_to_float(&self, pointer: &Pointer) -> &f64 {
|
|
||||||
match pointer {
|
|
||||||
Pointer::RegisterFloat(register_index) => self.get_float_register(*register_index),
|
|
||||||
Pointer::ConstantFloat(constant_index) => {
|
|
||||||
self.get_constant(*constant_index).as_float().unwrap()
|
|
||||||
}
|
|
||||||
_ => panic!("Attempted to get float from non-float pointer"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_float_register(&mut self, register_index: usize, new_register: Register<f64>) {
|
|
||||||
let old_register = if cfg!(debug_assertions) {
|
|
||||||
self.call_stack
|
|
||||||
.last_mut()
|
|
||||||
.unwrap()
|
|
||||||
.registers
|
|
||||||
.floats
|
|
||||||
.get_mut(register_index)
|
|
||||||
.unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe {
|
|
||||||
self.call_stack
|
|
||||||
.last_mut()
|
|
||||||
.unwrap_unchecked()
|
|
||||||
.registers
|
|
||||||
.floats
|
|
||||||
.get_unchecked_mut(register_index)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
*old_register = new_register;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_float_register_closed(&self, register_index: usize) -> bool {
|
|
||||||
let register = if cfg!(debug_assertions) {
|
|
||||||
self.call_stack
|
|
||||||
.last()
|
|
||||||
.unwrap()
|
|
||||||
.registers
|
|
||||||
.floats
|
|
||||||
.get(register_index)
|
|
||||||
.unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe {
|
|
||||||
self.call_stack
|
|
||||||
.last()
|
|
||||||
.unwrap_unchecked()
|
|
||||||
.registers
|
|
||||||
.floats
|
|
||||||
.get_unchecked(register_index)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
matches!(register, Register::Closed(_))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn close_float_register(&mut self, register_index: usize) {
|
|
||||||
let register = self
|
|
||||||
.current_frame_mut()
|
|
||||||
.registers
|
|
||||||
.floats
|
|
||||||
.get_mut(register_index)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
*register = match register {
|
|
||||||
Register::Value(value) => Register::Closed(*value),
|
|
||||||
_ => panic!("Attempted to close non-value register"),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_integer(&self, index: usize, is_constant: bool) -> &i64 {
|
|
||||||
if is_constant {
|
|
||||||
if cfg!(debug_assertions) {
|
|
||||||
self.get_constant(index).as_integer().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { self.get_constant(index).as_integer().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.get_integer_register(index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_integer_register(&self, register_index: usize) -> &i64 {
|
|
||||||
let register = if cfg!(debug_assertions) {
|
|
||||||
self.call_stack
|
|
||||||
.last()
|
|
||||||
.unwrap()
|
|
||||||
.registers
|
|
||||||
.integers
|
|
||||||
.get(register_index)
|
|
||||||
.unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe {
|
|
||||||
self.call_stack
|
|
||||||
.last()
|
|
||||||
.unwrap_unchecked()
|
|
||||||
.registers
|
|
||||||
.integers
|
|
||||||
.get_unchecked(register_index)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match register {
|
|
||||||
Register::Value(value) => value,
|
|
||||||
Register::Closed(value) => value,
|
|
||||||
Register::Pointer(pointer) => self.get_pointer_to_integer(pointer),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_integer_register_mut_allow_empty(&mut self, register_index: usize) -> &mut i64 {
|
|
||||||
if cfg!(debug_assertions) {
|
|
||||||
self.call_stack
|
|
||||||
.last_mut()
|
|
||||||
.unwrap()
|
|
||||||
.registers
|
|
||||||
.integers
|
|
||||||
.get_mut(register_index)
|
|
||||||
.unwrap()
|
|
||||||
.contained_value_mut()
|
|
||||||
.unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe {
|
|
||||||
self.call_stack
|
|
||||||
.last_mut()
|
|
||||||
.unwrap_unchecked()
|
|
||||||
.registers
|
|
||||||
.integers
|
|
||||||
.get_unchecked_mut(register_index)
|
|
||||||
.contained_value_mut()
|
|
||||||
.unwrap_unchecked()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_pointer_to_integer(&self, pointer: &Pointer) -> &i64 {
|
|
||||||
match pointer {
|
|
||||||
Pointer::RegisterInteger(register_index) => self.get_integer_register(*register_index),
|
|
||||||
Pointer::ConstantInteger(constant_index) => {
|
|
||||||
self.get_constant(*constant_index).as_integer().unwrap()
|
|
||||||
}
|
|
||||||
_ => panic!("Attempted to get integer from non-integer pointer"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_integer_register(&mut self, register_index: usize, new_register: Register<i64>) {
|
|
||||||
let old_register = if cfg!(debug_assertions) {
|
|
||||||
self.call_stack
|
|
||||||
.last_mut()
|
|
||||||
.unwrap()
|
|
||||||
.registers
|
|
||||||
.integers
|
|
||||||
.get_mut(register_index)
|
|
||||||
.unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe {
|
|
||||||
self.call_stack
|
|
||||||
.last_mut()
|
|
||||||
.unwrap_unchecked()
|
|
||||||
.registers
|
|
||||||
.integers
|
|
||||||
.get_unchecked_mut(register_index)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
*old_register = new_register;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_integer_register_closed(&self, register_index: usize) -> bool {
|
|
||||||
let register = if cfg!(debug_assertions) {
|
|
||||||
self.call_stack
|
|
||||||
.last()
|
|
||||||
.unwrap()
|
|
||||||
.registers
|
|
||||||
.integers
|
|
||||||
.get(register_index)
|
|
||||||
.unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe {
|
|
||||||
self.call_stack
|
|
||||||
.last()
|
|
||||||
.unwrap_unchecked()
|
|
||||||
.registers
|
|
||||||
.integers
|
|
||||||
.get_unchecked(register_index)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
matches!(register, Register::Closed(_))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn close_integer_register(&mut self, register_index: usize) {
|
|
||||||
let register = self
|
|
||||||
.current_frame_mut()
|
|
||||||
.registers
|
|
||||||
.integers
|
|
||||||
.get_mut(register_index)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
*register = match register {
|
|
||||||
Register::Value(value) => Register::Closed(*value),
|
|
||||||
_ => panic!("Attempted to close non-value register"),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_string_register(&self, register_index: usize) -> &DustString {
|
|
||||||
let register = if cfg!(debug_assertions) {
|
|
||||||
self.call_stack
|
|
||||||
.last()
|
|
||||||
.unwrap()
|
|
||||||
.registers
|
|
||||||
.strings
|
|
||||||
.get(register_index)
|
|
||||||
.unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe {
|
|
||||||
self.call_stack
|
|
||||||
.last()
|
|
||||||
.unwrap_unchecked()
|
|
||||||
.registers
|
|
||||||
.strings
|
|
||||||
.get_unchecked(register_index)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match register {
|
|
||||||
Register::Value(value) => value,
|
|
||||||
Register::Closed(value) => value,
|
|
||||||
Register::Pointer(pointer) => self.get_pointer_to_string(pointer),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_pointer_to_string(&self, pointer: &Pointer) -> &DustString {
|
|
||||||
match pointer {
|
|
||||||
Pointer::RegisterString(register_index) => self.get_string_register(*register_index),
|
|
||||||
Pointer::ConstantString(constant_index) => {
|
|
||||||
self.get_constant(*constant_index).as_string().unwrap()
|
|
||||||
}
|
|
||||||
_ => panic!("Attempted to get string from non-string pointer"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_string_register(
|
|
||||||
&mut self,
|
|
||||||
register_index: usize,
|
|
||||||
new_register: Register<DustString>,
|
|
||||||
) {
|
|
||||||
let old_register = if cfg!(debug_assertions) {
|
|
||||||
self.call_stack
|
|
||||||
.last_mut()
|
|
||||||
.unwrap()
|
|
||||||
.registers
|
|
||||||
.strings
|
|
||||||
.get_mut(register_index)
|
|
||||||
.unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe {
|
|
||||||
self.call_stack
|
|
||||||
.last_mut()
|
|
||||||
.unwrap_unchecked()
|
|
||||||
.registers
|
|
||||||
.strings
|
|
||||||
.get_unchecked_mut(register_index)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
*old_register = new_register;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_string_register_closed(&self, register_index: usize) -> bool {
|
|
||||||
let register = if cfg!(debug_assertions) {
|
|
||||||
self.call_stack
|
|
||||||
.last()
|
|
||||||
.unwrap()
|
|
||||||
.registers
|
|
||||||
.strings
|
|
||||||
.get(register_index)
|
|
||||||
.unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe {
|
|
||||||
self.call_stack
|
|
||||||
.last()
|
|
||||||
.unwrap_unchecked()
|
|
||||||
.registers
|
|
||||||
.strings
|
|
||||||
.get_unchecked(register_index)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
matches!(register, Register::Closed(_))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn close_string_register(&mut self, register_index: usize) {
|
|
||||||
let current_frame = self.current_frame_mut();
|
|
||||||
|
|
||||||
current_frame.registers.strings.push(Register::default());
|
|
||||||
|
|
||||||
let old_register = current_frame.registers.strings.swap_remove(register_index);
|
|
||||||
|
|
||||||
if let Register::Value(value) = old_register {
|
|
||||||
current_frame
|
|
||||||
.registers
|
|
||||||
.strings
|
|
||||||
.push(Register::Closed(value));
|
|
||||||
|
|
||||||
let _ = current_frame.registers.strings.swap_remove(register_index);
|
|
||||||
} else {
|
|
||||||
panic!("Attempted to close non-value register");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_list_register(&self, register_index: usize) -> &AbstractList {
|
|
||||||
let register = if cfg!(debug_assertions) {
|
|
||||||
self.call_stack
|
|
||||||
.last()
|
|
||||||
.unwrap()
|
|
||||||
.registers
|
|
||||||
.lists
|
|
||||||
.get(register_index)
|
|
||||||
.unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe {
|
|
||||||
self.call_stack
|
|
||||||
.last()
|
|
||||||
.unwrap_unchecked()
|
|
||||||
.registers
|
|
||||||
.lists
|
|
||||||
.get_unchecked(register_index)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match register {
|
|
||||||
Register::Value(value) => value,
|
|
||||||
Register::Closed(value) => value,
|
|
||||||
Register::Pointer(pointer) => self.get_pointer_to_list(pointer),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_pointer_to_list(&self, pointer: &Pointer) -> &AbstractList {
|
|
||||||
match pointer {
|
|
||||||
Pointer::RegisterList(register_index) => self.get_list_register(*register_index),
|
|
||||||
_ => panic!("Attempted to get list from non-list pointer"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_list_register(
|
|
||||||
&mut self,
|
|
||||||
register_index: usize,
|
|
||||||
new_register: Register<AbstractList>,
|
|
||||||
) {
|
|
||||||
let old_register = if cfg!(debug_assertions) {
|
|
||||||
self.call_stack
|
|
||||||
.last_mut()
|
|
||||||
.unwrap()
|
|
||||||
.registers
|
|
||||||
.lists
|
|
||||||
.get_mut(register_index)
|
|
||||||
.unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe {
|
|
||||||
self.call_stack
|
|
||||||
.last_mut()
|
|
||||||
.unwrap_unchecked()
|
|
||||||
.registers
|
|
||||||
.lists
|
|
||||||
.get_unchecked_mut(register_index)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
*old_register = new_register;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_list_register_closed(&self, register_index: usize) -> bool {
|
|
||||||
let register = if cfg!(debug_assertions) {
|
|
||||||
self.call_stack
|
|
||||||
.last()
|
|
||||||
.unwrap()
|
|
||||||
.registers
|
|
||||||
.lists
|
|
||||||
.get(register_index)
|
|
||||||
.unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe {
|
|
||||||
self.call_stack
|
|
||||||
.last()
|
|
||||||
.unwrap_unchecked()
|
|
||||||
.registers
|
|
||||||
.lists
|
|
||||||
.get_unchecked(register_index)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
matches!(register, Register::Closed(_))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn close_list_register(&mut self, register_index: usize) {
|
|
||||||
let current_frame = self.current_frame_mut();
|
|
||||||
|
|
||||||
current_frame.registers.lists.push(Register::default());
|
|
||||||
|
|
||||||
let old_register = current_frame.registers.lists.swap_remove(register_index);
|
|
||||||
|
|
||||||
if let Register::Value(value) = old_register {
|
|
||||||
current_frame.registers.lists.push(Register::Closed(value));
|
|
||||||
|
|
||||||
let _ = current_frame.registers.lists.swap_remove(register_index);
|
|
||||||
} else {
|
|
||||||
panic!("Attempted to close non-value register");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_constant(&self, constant_index: usize) -> &ConcreteValue {
|
|
||||||
if cfg!(debug_assertions) {
|
|
||||||
self.chunk.constants.get(constant_index).unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { self.chunk.constants.get_unchecked(constant_index) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user