lab 7
This commit is contained in:
369
Cargo.lock
generated
369
Cargo.lock
generated
@@ -38,7 +38,7 @@ version = "1.1.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
|
checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -48,7 +48,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
|
checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstyle",
|
"anstyle",
|
||||||
"windows-sys",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -57,6 +57,36 @@ version = "1.0.89"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6"
|
checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.5.19"
|
version = "4.5.19"
|
||||||
@@ -103,28 +133,96 @@ version = "1.0.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
|
checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossterm"
|
||||||
|
version = "0.25.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"crossterm_winapi",
|
||||||
|
"libc",
|
||||||
|
"mio",
|
||||||
|
"parking_lot",
|
||||||
|
"signal-hook",
|
||||||
|
"signal-hook-mio",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossterm_winapi"
|
||||||
|
version = "0.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "developing-compilers"
|
name = "developing-compilers"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"byteorder",
|
||||||
"clap",
|
"clap",
|
||||||
|
"inquire",
|
||||||
"itertools",
|
"itertools",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dyn-clone"
|
||||||
|
version = "1.0.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.13.0"
|
version = "1.13.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fuzzy-matcher"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "54614a3312934d066701a80f20f15fa3b56d67ac7722b39eea5b4c9dd1d66c94"
|
||||||
|
dependencies = [
|
||||||
|
"thread_local",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fxhash"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
version = "0.5.0"
|
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 = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inquire"
|
||||||
|
version = "0.7.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fddf93031af70e75410a2511ec04d49e758ed2f26dad3404a934e0fb45cc12a"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.6.0",
|
||||||
|
"crossterm",
|
||||||
|
"dyn-clone",
|
||||||
|
"fuzzy-matcher",
|
||||||
|
"fxhash",
|
||||||
|
"newline-converter",
|
||||||
|
"once_cell",
|
||||||
|
"unicode-segmentation",
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "is_terminal_polyfill"
|
name = "is_terminal_polyfill"
|
||||||
version = "1.70.1"
|
version = "1.70.1"
|
||||||
@@ -140,6 +238,78 @@ dependencies = [
|
|||||||
"either",
|
"either",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.162"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mio"
|
||||||
|
version = "0.8.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"wasi",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "newline-converter"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "47b6b097ecb1cbfed438542d16e84fd7ad9b0c76c8a65b7f9039212a3d14dc7f"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-segmentation",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.20.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot"
|
||||||
|
version = "0.12.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
"parking_lot_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.9.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall",
|
||||||
|
"smallvec",
|
||||||
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.86"
|
version = "1.0.86"
|
||||||
@@ -158,6 +328,57 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.5.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.6.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signal-hook"
|
||||||
|
version = "0.3.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"signal-hook-registry",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signal-hook-mio"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"mio",
|
||||||
|
"signal-hook",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signal-hook-registry"
|
||||||
|
version = "1.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smallvec"
|
||||||
|
version = "1.13.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.11.1"
|
version = "0.11.1"
|
||||||
@@ -166,9 +387,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.86"
|
version = "2.0.87"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e89275301d38033efb81a6e60e3497e734dfcc62571f2854bf4b16690398824c"
|
checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -177,43 +398,117 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.66"
|
version = "2.0.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5d171f59dbaa811dbbb1aee1e73db92ec2b122911a48e1390dfe327a821ddede"
|
checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl",
|
"thiserror-impl",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror-impl"
|
name = "thiserror-impl"
|
||||||
version = "1.0.66"
|
version = "2.0.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b08be0f17bd307950653ce45db00cd31200d82b624b36e181337d9c7d92765b5"
|
checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thread_local"
|
||||||
|
version = "1.1.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"once_cell",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.13"
|
version = "1.0.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
|
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-segmentation"
|
||||||
|
version = "1.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-width"
|
||||||
|
version = "0.1.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf8parse"
|
name = "utf8parse"
|
||||||
version = "0.2.2"
|
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 = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.48.5",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.52.0"
|
version = "0.52.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-targets",
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm 0.48.5",
|
||||||
|
"windows_aarch64_msvc 0.48.5",
|
||||||
|
"windows_i686_gnu 0.48.5",
|
||||||
|
"windows_i686_msvc 0.48.5",
|
||||||
|
"windows_x86_64_gnu 0.48.5",
|
||||||
|
"windows_x86_64_gnullvm 0.48.5",
|
||||||
|
"windows_x86_64_msvc 0.48.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -222,28 +517,46 @@ version = "0.52.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows_aarch64_gnullvm",
|
"windows_aarch64_gnullvm 0.52.6",
|
||||||
"windows_aarch64_msvc",
|
"windows_aarch64_msvc 0.52.6",
|
||||||
"windows_i686_gnu",
|
"windows_i686_gnu 0.52.6",
|
||||||
"windows_i686_gnullvm",
|
"windows_i686_gnullvm",
|
||||||
"windows_i686_msvc",
|
"windows_i686_msvc 0.52.6",
|
||||||
"windows_x86_64_gnu",
|
"windows_x86_64_gnu 0.52.6",
|
||||||
"windows_x86_64_gnullvm",
|
"windows_x86_64_gnullvm 0.52.6",
|
||||||
"windows_x86_64_msvc",
|
"windows_x86_64_msvc 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_gnullvm"
|
name = "windows_aarch64_gnullvm"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
@@ -256,24 +569,48 @@ version = "0.52.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnullvm"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
|
|||||||
16
Cargo.toml
16
Cargo.toml
@@ -1,10 +1,12 @@
|
|||||||
[package]
|
[package]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
name = "developing-compilers"
|
name = "developing-compilers"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.89"
|
anyhow = "1.0.89"
|
||||||
clap = { version = "4.5.19", features = [ "derive" ] }
|
byteorder = "1.5.0"
|
||||||
itertools = "0.13.0"
|
clap = { version = "4.5.19", features = ["derive"] }
|
||||||
thiserror = "1.0.66"
|
inquire = "0.7.5"
|
||||||
|
itertools = "0.13.0"
|
||||||
|
thiserror = "2.0.3"
|
||||||
|
|||||||
7
rustfmt.toml
Normal file
7
rustfmt.toml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
match_block_trailing_comma = true
|
||||||
|
newline_style = "Unix"
|
||||||
|
style_edition = "2024"
|
||||||
|
|
||||||
|
group_imports = "StdExternalCrate"
|
||||||
|
imports_granularity = "Module"
|
||||||
|
unstable_features = true
|
||||||
@@ -7,10 +7,8 @@ use std::str::FromStr;
|
|||||||
use typed::{Type, TypedExpr};
|
use typed::{Type, TypedExpr};
|
||||||
pub use untyped::UntypedExpr;
|
pub use untyped::UntypedExpr;
|
||||||
|
|
||||||
use crate::{
|
use crate::error::{self, SemanticError, SemanticErrorKind};
|
||||||
error::{self, SemanticError, SemanticErrorKind},
|
use crate::symbols::SymbolsTable;
|
||||||
symbols::SymbolsTable,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct Span {
|
pub struct Span {
|
||||||
@@ -43,6 +41,31 @@ impl BinOp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<&BinOp> for u8 {
|
||||||
|
fn from(value: &BinOp) -> Self {
|
||||||
|
match value {
|
||||||
|
BinOp::Add => 1,
|
||||||
|
BinOp::Sub => 2,
|
||||||
|
BinOp::Mul => 3,
|
||||||
|
BinOp::Div => 4,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<u8> for BinOp {
|
||||||
|
type Error = u8;
|
||||||
|
|
||||||
|
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||||
|
match value {
|
||||||
|
1 => Ok(BinOp::Add),
|
||||||
|
2 => Ok(BinOp::Sub),
|
||||||
|
3 => Ok(BinOp::Mul),
|
||||||
|
4 => Ok(BinOp::Div),
|
||||||
|
b => Err(b),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for BinOp {
|
impl fmt::Display for BinOp {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
if f.alternate() {
|
if f.alternate() {
|
||||||
@@ -92,7 +115,7 @@ fn optimize_expr(expr: TypedExpr) -> TypedExpr {
|
|||||||
BinOp::Div => lhs / rhs,
|
BinOp::Div => lhs / rhs,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
(TypedExpr::Float { value: lhs, .. }, TypedExpr::Float { value: rhs, .. }) => {
|
(TypedExpr::Float { value: lhs, .. }, TypedExpr::Float { value: rhs, .. }) => {
|
||||||
TypedExpr::Float {
|
TypedExpr::Float {
|
||||||
span,
|
span,
|
||||||
@@ -103,42 +126,42 @@ fn optimize_expr(expr: TypedExpr) -> TypedExpr {
|
|||||||
BinOp::Div => lhs / rhs,
|
BinOp::Div => lhs / rhs,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
(lhs, TypedExpr::Int { value: 0, .. })
|
(lhs, TypedExpr::Int { value: 0, .. })
|
||||||
| (TypedExpr::Float { value: 0.0, .. }, lhs)
|
| (TypedExpr::Float { value: 0.0, .. }, lhs)
|
||||||
if matches!(op, BinOp::Add | BinOp::Sub) =>
|
if matches!(op, BinOp::Add | BinOp::Sub) =>
|
||||||
{
|
{
|
||||||
lhs
|
lhs
|
||||||
}
|
},
|
||||||
(lhs, TypedExpr::Int { value: 1, .. })
|
(lhs, TypedExpr::Int { value: 1, .. })
|
||||||
| (lhs, TypedExpr::Float { value: 1.0, .. })
|
| (lhs, TypedExpr::Float { value: 1.0, .. })
|
||||||
if matches!(op, BinOp::Mul | BinOp::Div) =>
|
if matches!(op, BinOp::Mul | BinOp::Div) =>
|
||||||
{
|
{
|
||||||
lhs
|
lhs
|
||||||
}
|
},
|
||||||
(TypedExpr::Int { value: 0, .. }, rhs)
|
(TypedExpr::Int { value: 0, .. }, rhs)
|
||||||
| (TypedExpr::Float { value: 0.0, .. }, rhs)
|
| (TypedExpr::Float { value: 0.0, .. }, rhs)
|
||||||
if matches!(op, BinOp::Add) =>
|
if matches!(op, BinOp::Add) =>
|
||||||
{
|
{
|
||||||
rhs
|
rhs
|
||||||
}
|
},
|
||||||
(TypedExpr::Int { value: 1, .. }, rhs)
|
(TypedExpr::Int { value: 1, .. }, rhs)
|
||||||
| (TypedExpr::Float { value: 1.0, .. }, rhs)
|
| (TypedExpr::Float { value: 1.0, .. }, rhs)
|
||||||
if matches!(op, BinOp::Mul) =>
|
if matches!(op, BinOp::Mul) =>
|
||||||
{
|
{
|
||||||
rhs
|
rhs
|
||||||
}
|
},
|
||||||
(TypedExpr::Int { value: 0, .. }, _) | (_, TypedExpr::Int { value: 0, .. })
|
(TypedExpr::Int { value: 0, .. }, _) | (_, TypedExpr::Int { value: 0, .. })
|
||||||
if matches!(op, BinOp::Mul) =>
|
if matches!(op, BinOp::Mul) =>
|
||||||
{
|
{
|
||||||
TypedExpr::Int { span, value: 0 }
|
TypedExpr::Int { span, value: 0 }
|
||||||
}
|
},
|
||||||
(TypedExpr::Float { value: 0.0, .. }, _)
|
(TypedExpr::Float { value: 0.0, .. }, _)
|
||||||
| (_, TypedExpr::Float { value: 0.0, .. })
|
| (_, TypedExpr::Float { value: 0.0, .. })
|
||||||
if matches!(op, BinOp::Mul) =>
|
if matches!(op, BinOp::Mul) =>
|
||||||
{
|
{
|
||||||
TypedExpr::Float { span, value: 0.0 }
|
TypedExpr::Float { span, value: 0.0 }
|
||||||
}
|
},
|
||||||
(lhs, rhs) => TypedExpr::BinOp {
|
(lhs, rhs) => TypedExpr::BinOp {
|
||||||
span,
|
span,
|
||||||
lhs: Box::new(lhs),
|
lhs: Box::new(lhs),
|
||||||
@@ -146,7 +169,7 @@ fn optimize_expr(expr: TypedExpr) -> TypedExpr {
|
|||||||
rhs: Box::new(rhs),
|
rhs: Box::new(rhs),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
TypedExpr::IntToFloat { value } => {
|
TypedExpr::IntToFloat { value } => {
|
||||||
let value = optimize_expr(*value);
|
let value = optimize_expr(*value);
|
||||||
if let TypedExpr::Int { value, span } = value {
|
if let TypedExpr::Int { value, span } = value {
|
||||||
@@ -159,7 +182,7 @@ fn optimize_expr(expr: TypedExpr) -> TypedExpr {
|
|||||||
value: Box::new(value),
|
value: Box::new(value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
expr => expr,
|
expr => expr,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -192,17 +215,17 @@ fn convert_to_typed_expr(
|
|||||||
span,
|
span,
|
||||||
SemanticErrorKind::DuplicateSymbol(symbol.name.clone()),
|
SemanticErrorKind::DuplicateSymbol(symbol.name.clone()),
|
||||||
)
|
)
|
||||||
.into())
|
.into());
|
||||||
}
|
},
|
||||||
(None, Some(ty)) => {
|
(None, Some(ty)) => {
|
||||||
symbol.ty = Some(ty);
|
symbol.ty = Some(ty);
|
||||||
}
|
},
|
||||||
_ => {}
|
_ => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TypedExpr::Var { span, name }
|
TypedExpr::Var { span, name }
|
||||||
}
|
},
|
||||||
UntypedExpr::BinOp { span, lhs, op, rhs } => {
|
UntypedExpr::BinOp { span, lhs, op, rhs } => {
|
||||||
let rhs = *rhs;
|
let rhs = *rhs;
|
||||||
let lhs = *lhs;
|
let lhs = *lhs;
|
||||||
@@ -217,19 +240,19 @@ fn convert_to_typed_expr(
|
|||||||
*span,
|
*span,
|
||||||
SemanticErrorKind::DivisionByZero,
|
SemanticErrorKind::DivisionByZero,
|
||||||
)
|
)
|
||||||
.into())
|
.into());
|
||||||
}
|
},
|
||||||
UntypedExpr::Float { span, value } if *value == 0.0 => {
|
UntypedExpr::Float { span, value } if *value == 0.0 => {
|
||||||
return Err(SemanticError::new(
|
return Err(SemanticError::new(
|
||||||
*span,
|
*span,
|
||||||
SemanticErrorKind::DivisionByZero,
|
SemanticErrorKind::DivisionByZero,
|
||||||
)
|
)
|
||||||
.into())
|
.into());
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
}
|
}
|
||||||
_ => {}
|
},
|
||||||
}
|
_ => {},
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let lhs = convert_to_typed_expr(lhs, symbols)?;
|
let lhs = convert_to_typed_expr(lhs, symbols)?;
|
||||||
@@ -241,7 +264,7 @@ fn convert_to_typed_expr(
|
|||||||
op,
|
op,
|
||||||
rhs: Box::new(rhs),
|
rhs: Box::new(rhs),
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(expr)
|
Ok(expr)
|
||||||
@@ -259,7 +282,7 @@ fn coerce_types(expr: TypedExpr, symbols: &mut SymbolsTable) -> error::Result<Ty
|
|||||||
}
|
}
|
||||||
|
|
||||||
expr
|
expr
|
||||||
}
|
},
|
||||||
TypedExpr::BinOp { lhs, rhs, op, span } => {
|
TypedExpr::BinOp { lhs, rhs, op, span } => {
|
||||||
let lhs = coerce_types(*lhs, symbols)?;
|
let lhs = coerce_types(*lhs, symbols)?;
|
||||||
let rhs = coerce_types(*rhs, symbols)?;
|
let rhs = coerce_types(*rhs, symbols)?;
|
||||||
@@ -270,11 +293,11 @@ fn coerce_types(expr: TypedExpr, symbols: &mut SymbolsTable) -> error::Result<Ty
|
|||||||
(Type::Int, Type::Float) => {
|
(Type::Int, Type::Float) => {
|
||||||
let lhs = TypedExpr::cast_to_float(lhs);
|
let lhs = TypedExpr::cast_to_float(lhs);
|
||||||
(lhs, rhs)
|
(lhs, rhs)
|
||||||
}
|
},
|
||||||
(Type::Float, Type::Int) => {
|
(Type::Float, Type::Int) => {
|
||||||
let rhs = TypedExpr::cast_to_float(rhs);
|
let rhs = TypedExpr::cast_to_float(rhs);
|
||||||
(lhs, rhs)
|
(lhs, rhs)
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
TypedExpr::BinOp {
|
TypedExpr::BinOp {
|
||||||
@@ -283,7 +306,7 @@ fn coerce_types(expr: TypedExpr, symbols: &mut SymbolsTable) -> error::Result<Ty
|
|||||||
op,
|
op,
|
||||||
rhs: Box::new(rhs),
|
rhs: Box::new(rhs),
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
TypedExpr::IntToFloat { .. } => expr,
|
TypedExpr::IntToFloat { .. } => expr,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
use std::{fmt, str::FromStr};
|
use std::fmt;
|
||||||
|
use std::str::FromStr;
|
||||||
use crate::{
|
|
||||||
error::SemanticErrorKind,
|
|
||||||
symbols::{Symbol, SymbolsTable},
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{BinOp, Span};
|
use super::{BinOp, Span};
|
||||||
|
use crate::error::SemanticErrorKind;
|
||||||
|
use crate::symbols::{Symbol, SymbolsTable};
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum Type {
|
pub enum Type {
|
||||||
@@ -13,6 +11,27 @@ pub enum Type {
|
|||||||
Float,
|
Float,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Type> for u8 {
|
||||||
|
fn from(value: Type) -> Self {
|
||||||
|
match value {
|
||||||
|
Type::Int => 1,
|
||||||
|
Type::Float => 2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<u8> for Type {
|
||||||
|
type Error = u8;
|
||||||
|
|
||||||
|
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||||
|
match value {
|
||||||
|
1 => Ok(Type::Int),
|
||||||
|
2 => Ok(Type::Float),
|
||||||
|
b => Err(b),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl FromStr for Type {
|
impl FromStr for Type {
|
||||||
type Err = SemanticErrorKind;
|
type Err = SemanticErrorKind;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use crate::symbols::Symbol;
|
|
||||||
|
|
||||||
use super::{BinOp, Span};
|
use super::{BinOp, Span};
|
||||||
|
use crate::symbols::Symbol;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum UntypedExpr {
|
pub enum UntypedExpr {
|
||||||
|
|||||||
45
src/cli.rs
45
src/cli.rs
@@ -1,4 +1,5 @@
|
|||||||
use std::{ops::Deref, path::PathBuf};
|
use std::ops::Deref;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use clap::{CommandFactory, Parser, Subcommand};
|
use clap::{CommandFactory, Parser, Subcommand};
|
||||||
|
|
||||||
@@ -35,6 +36,15 @@ pub enum Command {
|
|||||||
output: PathBuf,
|
output: PathBuf,
|
||||||
output_symbols: PathBuf,
|
output_symbols: PathBuf,
|
||||||
},
|
},
|
||||||
|
Com {
|
||||||
|
#[clap(short, long, default_value_t = false)]
|
||||||
|
optimize: bool,
|
||||||
|
input: PathBuf,
|
||||||
|
output: PathBuf,
|
||||||
|
},
|
||||||
|
Int {
|
||||||
|
input: PathBuf,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, clap::ValueEnum)]
|
#[derive(Copy, Clone, PartialEq, Eq, clap::ValueEnum)]
|
||||||
@@ -52,7 +62,7 @@ impl Args {
|
|||||||
Err(err) => {
|
Err(err) => {
|
||||||
let mut command = ArgsInner::command();
|
let mut command = ArgsInner::command();
|
||||||
err.format(&mut command).exit();
|
err.format(&mut command).exit();
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
Self { inner }
|
Self { inner }
|
||||||
@@ -82,6 +92,8 @@ fn validate_inner(args: ArgsInner) -> Result<ArgsInner, clap::Error> {
|
|||||||
output_symbols,
|
output_symbols,
|
||||||
..
|
..
|
||||||
} => validate_gen(input, output, output_symbols)?,
|
} => validate_gen(input, output, output_symbols)?,
|
||||||
|
Command::Com { input, output, .. } => validate_com(input, output)?,
|
||||||
|
Command::Int { input } => validate_int(input)?,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(args)
|
Ok(args)
|
||||||
@@ -180,3 +192,32 @@ fn validate_gen(
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn validate_com(input: &PathBuf, output: &PathBuf) -> Result<(), clap::Error> {
|
||||||
|
if !input.is_file() {
|
||||||
|
return Err(clap::Error::raw(
|
||||||
|
clap::error::ErrorKind::InvalidValue,
|
||||||
|
format!("Input file '{}' does not exist", input.display()),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if input == output {
|
||||||
|
return Err(clap::Error::raw(
|
||||||
|
clap::error::ErrorKind::InvalidValue,
|
||||||
|
"Input and output files cannot be the same",
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate_int(input: &PathBuf) -> Result<(), clap::Error> {
|
||||||
|
if !input.is_file() {
|
||||||
|
return Err(clap::Error::raw(
|
||||||
|
clap::error::ErrorKind::InvalidValue,
|
||||||
|
format!("Input file '{}' does not exist", input.display()),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
6
src/lib.rs
Normal file
6
src/lib.rs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
pub mod ast;
|
||||||
|
pub mod error;
|
||||||
|
pub mod parse;
|
||||||
|
pub mod representation;
|
||||||
|
pub mod symbols;
|
||||||
|
pub mod util;
|
||||||
301
src/main.rs
301
src/main.rs
@@ -1,45 +1,252 @@
|
|||||||
mod ast;
|
|
||||||
mod cli;
|
mod cli;
|
||||||
mod error;
|
|
||||||
mod parse;
|
|
||||||
mod representation;
|
|
||||||
mod symbols;
|
|
||||||
mod util;
|
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::io::{self, Write};
|
||||||
|
use std::path::Path;
|
||||||
|
use std::{fmt, fs};
|
||||||
|
|
||||||
|
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
||||||
use cli::GenMode;
|
use cli::GenMode;
|
||||||
|
use developing_compilers::ast::BinOp;
|
||||||
|
use developing_compilers::ast::typed::Type;
|
||||||
|
use developing_compilers::representation::intermediate::{IntermediateExpr, IntermediateValue};
|
||||||
|
use developing_compilers::symbols::Symbol;
|
||||||
|
use developing_compilers::*;
|
||||||
|
use inquire::CustomType;
|
||||||
use parse::parser::Parser;
|
use parse::parser::Parser;
|
||||||
use std::{
|
|
||||||
io::{self, Write},
|
|
||||||
path::Path,
|
|
||||||
};
|
|
||||||
use symbols::SymbolsTable;
|
use symbols::SymbolsTable;
|
||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
let args = cli::Args::parse();
|
let args = cli::Args::parse();
|
||||||
|
|
||||||
match &args.command {
|
let result = match &args.command {
|
||||||
cli::Command::Lex {
|
cli::Command::Lex {
|
||||||
input,
|
input,
|
||||||
output_tokens,
|
output_tokens,
|
||||||
output_symbols,
|
output_symbols,
|
||||||
} => {
|
} => lex_command(input, output_tokens, output_symbols),
|
||||||
lex_command(input, output_tokens, output_symbols)?;
|
cli::Command::Syn { input, output_tree } => syn_command(input, output_tree),
|
||||||
}
|
cli::Command::Sem { input, output_tree } => sem_command(input, output_tree),
|
||||||
cli::Command::Syn { input, output_tree } => {
|
|
||||||
syn_command(input, output_tree)?;
|
|
||||||
}
|
|
||||||
cli::Command::Sem { input, output_tree } => {
|
|
||||||
sem_command(input, output_tree)?;
|
|
||||||
}
|
|
||||||
cli::Command::Gen {
|
cli::Command::Gen {
|
||||||
mode,
|
mode,
|
||||||
optimize,
|
optimize,
|
||||||
input,
|
input,
|
||||||
output,
|
output,
|
||||||
output_symbols,
|
output_symbols,
|
||||||
} => {
|
} => gen_command(mode, *optimize, input, output, output_symbols),
|
||||||
gen_command(mode, *optimize, input, output, output_symbols)?;
|
cli::Command::Com {
|
||||||
|
optimize,
|
||||||
|
input,
|
||||||
|
output,
|
||||||
|
} => com_command(*optimize, input, output),
|
||||||
|
cli::Command::Int { input } => int_command(input),
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(e) = result {
|
||||||
|
eprintln!("error: {}", e);
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn int_command(input: &Path) -> Result<(), anyhow::Error> {
|
||||||
|
enum VarValue {
|
||||||
|
Int(i64),
|
||||||
|
Float(f64),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for VarValue {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
VarValue::Int(v) => write!(f, "{}", v),
|
||||||
|
VarValue::Float(v) => {
|
||||||
|
if v == &v.trunc() {
|
||||||
|
write!(f, "{}.0", v)
|
||||||
|
} else {
|
||||||
|
write!(f, "{}", v)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn value_as_i64(value: &IntermediateValue, vars: &HashMap<Symbol, VarValue>) -> i64 {
|
||||||
|
match value {
|
||||||
|
IntermediateValue::Int { value } => *value,
|
||||||
|
IntermediateValue::Var { name } => match vars.get(name) {
|
||||||
|
Some(VarValue::Int(v)) => *v,
|
||||||
|
_ => unreachable!(),
|
||||||
|
},
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn value_as_f64(value: &IntermediateValue, vars: &HashMap<Symbol, VarValue>) -> f64 {
|
||||||
|
match value {
|
||||||
|
IntermediateValue::Float { value } => *value,
|
||||||
|
IntermediateValue::Var { name } => match vars.get(name) {
|
||||||
|
Some(VarValue::Float(v)) => *v,
|
||||||
|
_ => unreachable!(),
|
||||||
|
},
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let (symbols, ir) = {
|
||||||
|
let mut reader = io::BufReader::new(fs::File::open(input)?);
|
||||||
|
let symbols = SymbolsTable::from_reader(&mut reader)?;
|
||||||
|
let n = reader.read_u64::<BigEndian>()?;
|
||||||
|
let mut ir = Vec::with_capacity(n as usize);
|
||||||
|
for _ in 0..n {
|
||||||
|
ir.push(IntermediateExpr::from_reader(&mut reader)?);
|
||||||
|
}
|
||||||
|
(symbols, ir)
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut vars = HashMap::new();
|
||||||
|
for (_, data) in &symbols {
|
||||||
|
let value = match data.ty {
|
||||||
|
Some(Type::Int) if !data.temporary => VarValue::Int(
|
||||||
|
CustomType::new(&format!("Input int {}", data.name))
|
||||||
|
.with_default(0)
|
||||||
|
.prompt()?,
|
||||||
|
),
|
||||||
|
Some(Type::Float) if !data.temporary => VarValue::Float(
|
||||||
|
CustomType::new(&format!("Input float {}", data.name))
|
||||||
|
.with_default(0.0)
|
||||||
|
.prompt()?,
|
||||||
|
),
|
||||||
|
Some(Type::Int) => VarValue::Int(0),
|
||||||
|
Some(Type::Float) => VarValue::Float(0.0),
|
||||||
|
None => continue,
|
||||||
|
};
|
||||||
|
vars.insert(data.id, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut last_result = None;
|
||||||
|
for expr in ir {
|
||||||
|
match expr {
|
||||||
|
IntermediateExpr::IntToFloat { result, value } => {
|
||||||
|
let value = value_as_i64(&value, &vars) as f64;
|
||||||
|
|
||||||
|
match vars.get_mut(&result) {
|
||||||
|
Some(VarValue::Float(v)) => *v = value,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
last_result = Some(result);
|
||||||
|
},
|
||||||
|
IntermediateExpr::BinOp {
|
||||||
|
result,
|
||||||
|
lhs,
|
||||||
|
op,
|
||||||
|
rhs,
|
||||||
|
} if symbols.type_of(&result) == Some(Type::Int) => {
|
||||||
|
let lhs = value_as_i64(&lhs, &vars);
|
||||||
|
let rhs = value_as_i64(&rhs, &vars);
|
||||||
|
|
||||||
|
let value = match op {
|
||||||
|
BinOp::Add => lhs + rhs,
|
||||||
|
BinOp::Sub => lhs - rhs,
|
||||||
|
BinOp::Mul => lhs * rhs,
|
||||||
|
BinOp::Div => lhs / rhs,
|
||||||
|
};
|
||||||
|
|
||||||
|
match vars.get_mut(&result) {
|
||||||
|
Some(VarValue::Int(v)) => *v = value,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
last_result = Some(result);
|
||||||
|
},
|
||||||
|
IntermediateExpr::BinOp {
|
||||||
|
result,
|
||||||
|
lhs,
|
||||||
|
op,
|
||||||
|
rhs,
|
||||||
|
} if symbols.type_of(&result) == Some(Type::Float) => {
|
||||||
|
let lhs = value_as_f64(&lhs, &vars);
|
||||||
|
let rhs = value_as_f64(&rhs, &vars);
|
||||||
|
|
||||||
|
let value = match op {
|
||||||
|
BinOp::Add => lhs + rhs,
|
||||||
|
BinOp::Sub => lhs - rhs,
|
||||||
|
BinOp::Mul => lhs * rhs,
|
||||||
|
BinOp::Div => lhs / rhs,
|
||||||
|
};
|
||||||
|
|
||||||
|
match vars.get_mut(&result) {
|
||||||
|
Some(VarValue::Float(v)) => *v = value,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
last_result = Some(result);
|
||||||
|
},
|
||||||
|
IntermediateExpr::Identity { result, value }
|
||||||
|
if symbols.type_of(&result) == Some(Type::Float) =>
|
||||||
|
{
|
||||||
|
let value = value_as_f64(&value, &vars);
|
||||||
|
|
||||||
|
match vars.get_mut(&result) {
|
||||||
|
Some(VarValue::Float(v)) => *v = value,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
last_result = Some(result);
|
||||||
|
},
|
||||||
|
IntermediateExpr::Identity { result, value }
|
||||||
|
if symbols.type_of(&result) == Some(Type::Int) =>
|
||||||
|
{
|
||||||
|
let value = value_as_i64(&value, &vars);
|
||||||
|
|
||||||
|
match vars.get_mut(&result) {
|
||||||
|
Some(VarValue::Int(v)) => *v = value,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
last_result = Some(result);
|
||||||
|
},
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(result) = last_result {
|
||||||
|
println!("Result: {}", vars.get(&result).unwrap());
|
||||||
|
} else {
|
||||||
|
println!("No result");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn com_command(optimize: bool, input: &Path, output: &Path) -> Result<(), anyhow::Error> {
|
||||||
|
let input = fs::read_to_string(input)?;
|
||||||
|
let mut symbols = SymbolsTable::default();
|
||||||
|
let typed_expr = match {
|
||||||
|
let tokens = parse::lexer::make_tokenizer(&input, &mut symbols);
|
||||||
|
let mut parser = Parser::new(tokens);
|
||||||
|
parser.parse()
|
||||||
|
}
|
||||||
|
.and_then(|expr| ast::to_typed_expr(expr, optimize, &mut symbols))
|
||||||
|
{
|
||||||
|
Ok(expr) => expr,
|
||||||
|
Err(e) => {
|
||||||
|
return Err(e.into());
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let ir = IntermediateExpr::from_typed_expr(typed_expr, optimize, &mut symbols);
|
||||||
|
{
|
||||||
|
let used_symbols = util::collect_used_symbols(&ir);
|
||||||
|
symbols.retain(&used_symbols);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut writer = io::BufWriter::new(fs::File::create(output)?);
|
||||||
|
symbols.to_writer(&mut writer)?;
|
||||||
|
writer.write_u64::<BigEndian>(ir.len() as u64)?;
|
||||||
|
for expr in ir {
|
||||||
|
expr.to_writer(&mut writer)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -52,7 +259,7 @@ fn gen_command(
|
|||||||
output: &Path,
|
output: &Path,
|
||||||
output_symbols: &Path,
|
output_symbols: &Path,
|
||||||
) -> Result<(), anyhow::Error> {
|
) -> Result<(), anyhow::Error> {
|
||||||
let input = std::fs::read_to_string(input)?;
|
let input = fs::read_to_string(input)?;
|
||||||
let mut symbols = SymbolsTable::default();
|
let mut symbols = SymbolsTable::default();
|
||||||
let typed_expr = match {
|
let typed_expr = match {
|
||||||
let tokens = parse::lexer::make_tokenizer(&input, &mut symbols);
|
let tokens = parse::lexer::make_tokenizer(&input, &mut symbols);
|
||||||
@@ -63,32 +270,28 @@ fn gen_command(
|
|||||||
{
|
{
|
||||||
Ok(expr) => expr,
|
Ok(expr) => expr,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("error: {}", e);
|
return Err(e.into());
|
||||||
return Ok(());
|
},
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut writer = io::BufWriter::new(std::fs::File::create(output)?);
|
let mut writer = io::BufWriter::new(fs::File::create(output)?);
|
||||||
|
|
||||||
match mode {
|
match mode {
|
||||||
GenMode::Intermediate => {
|
GenMode::Intermediate => {
|
||||||
let intermediate_exprs = representation::intermediate::to_intermediate_expr(
|
let intermediate_exprs =
|
||||||
typed_expr,
|
IntermediateExpr::from_typed_expr(typed_expr, optimize, &mut symbols);
|
||||||
optimize,
|
|
||||||
&mut symbols,
|
|
||||||
);
|
|
||||||
|
|
||||||
let used_symbols = util::collect_used_symbols(&intermediate_exprs);
|
let used_symbols = util::collect_used_symbols(&intermediate_exprs);
|
||||||
symbols.retain(&used_symbols);
|
symbols.retain(&used_symbols);
|
||||||
|
|
||||||
util::print_intermediate_exprs(&intermediate_exprs, &mut writer)?;
|
util::print_intermediate_exprs(&intermediate_exprs, &mut writer)?;
|
||||||
}
|
},
|
||||||
GenMode::Postfix => {
|
GenMode::Postfix => {
|
||||||
util::print_postfix_expr(&typed_expr, &mut writer)?;
|
util::print_postfix_expr(&typed_expr, &mut writer)?;
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut writer_symbols = io::BufWriter::new(std::fs::File::create(output_symbols)?);
|
let mut writer_symbols = io::BufWriter::new(fs::File::create(output_symbols)?);
|
||||||
for (name, data) in &symbols {
|
for (name, data) in &symbols {
|
||||||
writeln!(writer_symbols, "{name} -> {}", data)?;
|
writeln!(writer_symbols, "{name} -> {}", data)?;
|
||||||
}
|
}
|
||||||
@@ -97,7 +300,7 @@ fn gen_command(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn sem_command(input: &Path, output_tree: &Path) -> Result<(), anyhow::Error> {
|
fn sem_command(input: &Path, output_tree: &Path) -> Result<(), anyhow::Error> {
|
||||||
let input = std::fs::read_to_string(input)?;
|
let input = fs::read_to_string(input)?;
|
||||||
let mut symbols = SymbolsTable::default();
|
let mut symbols = SymbolsTable::default();
|
||||||
|
|
||||||
let res = {
|
let res = {
|
||||||
@@ -109,17 +312,17 @@ fn sem_command(input: &Path, output_tree: &Path) -> Result<(), anyhow::Error> {
|
|||||||
|
|
||||||
match res {
|
match res {
|
||||||
Ok(expr) => {
|
Ok(expr) => {
|
||||||
let mut writer_tree = io::BufWriter::new(std::fs::File::create(output_tree)?);
|
let mut writer_tree = io::BufWriter::new(fs::File::create(output_tree)?);
|
||||||
util::print_typed_expr(&expr, &symbols, &mut writer_tree)?;
|
util::print_typed_expr(&expr, &symbols, &mut writer_tree)?;
|
||||||
}
|
},
|
||||||
Err(e) => eprintln!("error: {}", e),
|
Err(e) => return Err(e.into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn syn_command(input: &Path, output_tree: &Path) -> Result<(), anyhow::Error> {
|
fn syn_command(input: &Path, output_tree: &Path) -> Result<(), anyhow::Error> {
|
||||||
let input = std::fs::read_to_string(input)?;
|
let input = fs::read_to_string(input)?;
|
||||||
let mut symbols = SymbolsTable::default();
|
let mut symbols = SymbolsTable::default();
|
||||||
|
|
||||||
let tokens = parse::lexer::make_tokenizer(&input, &mut symbols);
|
let tokens = parse::lexer::make_tokenizer(&input, &mut symbols);
|
||||||
@@ -128,10 +331,10 @@ fn syn_command(input: &Path, output_tree: &Path) -> Result<(), anyhow::Error> {
|
|||||||
|
|
||||||
match res {
|
match res {
|
||||||
Ok(expr) => {
|
Ok(expr) => {
|
||||||
let mut writer_tree = io::BufWriter::new(std::fs::File::create(output_tree)?);
|
let mut writer_tree = io::BufWriter::new(fs::File::create(output_tree)?);
|
||||||
util::print_untyped_expr(&expr, &mut writer_tree)?;
|
util::print_untyped_expr(&expr, &mut writer_tree)?;
|
||||||
}
|
},
|
||||||
Err(e) => eprintln!("error: {}", e),
|
Err(e) => return Err(e.into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -142,26 +345,26 @@ fn lex_command(
|
|||||||
output_tokens: &Path,
|
output_tokens: &Path,
|
||||||
output_symbols: &Path,
|
output_symbols: &Path,
|
||||||
) -> Result<(), anyhow::Error> {
|
) -> Result<(), anyhow::Error> {
|
||||||
let input = std::fs::read_to_string(input)?;
|
let input = fs::read_to_string(input)?;
|
||||||
let mut symbols = SymbolsTable::default();
|
let mut symbols = SymbolsTable::default();
|
||||||
let tokens = parse::lexer::make_tokenizer(&input, &mut symbols).collect::<Result<Vec<_>, _>>();
|
let tokens = parse::lexer::make_tokenizer(&input, &mut symbols).collect::<Result<Vec<_>, _>>();
|
||||||
|
|
||||||
match tokens {
|
match tokens {
|
||||||
Ok(tokens) => {
|
Ok(tokens) => {
|
||||||
let mut writer_tokens = io::BufWriter::new(std::fs::File::create(output_tokens)?);
|
let mut writer_tokens = io::BufWriter::new(fs::File::create(output_tokens)?);
|
||||||
|
|
||||||
for (_, token, _) in tokens {
|
for (_, token, _) in tokens {
|
||||||
writeln!(writer_tokens, "{token:>6} - {}", token.as_str())?;
|
writeln!(writer_tokens, "{token:>6} - {}", token.as_str())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut writer_symbols = io::BufWriter::new(std::fs::File::create(output_symbols)?);
|
let mut writer_symbols = io::BufWriter::new(fs::File::create(output_symbols)?);
|
||||||
for (name, data) in &symbols {
|
for (name, data) in &symbols {
|
||||||
writeln!(writer_symbols, "{name} -> {}", data)?;
|
writeln!(writer_symbols, "{name} -> {}", data)?;
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("error: {}", e);
|
return Err(e.into());
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -1,21 +1,20 @@
|
|||||||
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
use itertools::PeekNth;
|
use itertools::PeekNth;
|
||||||
|
|
||||||
use crate::{
|
|
||||||
ast::Span,
|
|
||||||
error::{LexicalError, LexicalErrorKind},
|
|
||||||
symbols::SymbolsTable,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::token::Token;
|
use super::token::Token;
|
||||||
|
use crate::ast::Span;
|
||||||
|
use crate::error::{LexicalError, LexicalErrorKind};
|
||||||
|
use crate::symbols::SymbolsTable;
|
||||||
|
|
||||||
pub type SpannedToken = (usize, Token, usize);
|
pub type SpannedToken = (usize, Token, usize);
|
||||||
pub type LexerResult = Result<SpannedToken, LexicalError>;
|
pub type LexerResult = Result<SpannedToken, LexicalError>;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Lexer<'s, T: Iterator<Item = (usize, char)>> {
|
pub struct Lexer<'s, T: Iterator<Item = char>> {
|
||||||
chars: PeekNth<T>,
|
chars: PeekNth<T>,
|
||||||
pos: usize,
|
pos: usize,
|
||||||
pending: Vec<SpannedToken>,
|
pending: VecDeque<SpannedToken>,
|
||||||
symbols: &'s mut SymbolsTable,
|
symbols: &'s mut SymbolsTable,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,16 +22,16 @@ pub fn make_tokenizer<'s>(
|
|||||||
input: &'s str,
|
input: &'s str,
|
||||||
symbols: &'s mut SymbolsTable,
|
symbols: &'s mut SymbolsTable,
|
||||||
) -> impl Iterator<Item = LexerResult> + 's {
|
) -> impl Iterator<Item = LexerResult> + 's {
|
||||||
let chars = input.char_indices();
|
let chars = input.chars();
|
||||||
Lexer::new(chars, symbols)
|
Lexer::new(chars, symbols)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s, T: Iterator<Item = (usize, char)>> Lexer<'s, T> {
|
impl<'s, T: Iterator<Item = char>> Lexer<'s, T> {
|
||||||
pub fn new(chars: T, symbols: &'s mut SymbolsTable) -> Self {
|
pub fn new(chars: T, symbols: &'s mut SymbolsTable) -> Self {
|
||||||
Self {
|
Self {
|
||||||
chars: itertools::peek_nth(chars),
|
chars: itertools::peek_nth(chars),
|
||||||
pos: 0,
|
pos: 0,
|
||||||
pending: vec![],
|
pending: VecDeque::new(),
|
||||||
symbols,
|
symbols,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -42,16 +41,15 @@ impl<'s, T: Iterator<Item = (usize, char)>> Lexer<'s, T> {
|
|||||||
self.consume_token()?;
|
self.consume_token()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(self.pending.remove(0))
|
Ok(self.pending.pop_front().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn consume_token(&mut self) -> Result<(), LexicalError> {
|
fn consume_token(&mut self) -> Result<(), LexicalError> {
|
||||||
if let Some(c) = self.peek_char_nth(0) {
|
if let Some(c) = self.peek_char_nth(0) {
|
||||||
let c1 = self.peek_char_nth(1);
|
|
||||||
if self.is_name_start(c) {
|
if self.is_name_start(c) {
|
||||||
let name = self.lex_name()?;
|
let name = self.lex_name()?;
|
||||||
self.emit(name);
|
self.emit(name);
|
||||||
} else if self.is_number_start(c, c1) {
|
} else if self.is_number_start(c) {
|
||||||
let number = self.lex_number()?;
|
let number = self.lex_number()?;
|
||||||
self.emit(number);
|
self.emit(number);
|
||||||
} else {
|
} else {
|
||||||
@@ -98,7 +96,10 @@ impl<'s, T: Iterator<Item = (usize, char)>> Lexer<'s, T> {
|
|||||||
while let Some(c) = self.peek_char_nth(0) {
|
while let Some(c) = self.peek_char_nth(0) {
|
||||||
if self.is_digit(c) {
|
if self.is_digit(c) {
|
||||||
number.push(self.next_char().expect("lex_number: no more characters"));
|
number.push(self.next_char().expect("lex_number: no more characters"));
|
||||||
} else if !passed_dot && c == '.' {
|
} else if !passed_dot
|
||||||
|
&& c == '.'
|
||||||
|
&& self.peek_char_nth(1).map_or(false, |c| self.is_digit(c))
|
||||||
|
{
|
||||||
passed_dot = true;
|
passed_dot = true;
|
||||||
number.push(self.next_char().expect("lex_number: no more characters"));
|
number.push(self.next_char().expect("lex_number: no more characters"));
|
||||||
} else {
|
} else {
|
||||||
@@ -118,8 +119,8 @@ impl<'s, T: Iterator<Item = (usize, char)>> Lexer<'s, T> {
|
|||||||
return Err(LexicalError::new(
|
return Err(LexicalError::new(
|
||||||
Span::new(start, end),
|
Span::new(start, end),
|
||||||
LexicalErrorKind::BadNumber(number),
|
LexicalErrorKind::BadNumber(number),
|
||||||
))
|
));
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
end,
|
end,
|
||||||
@@ -144,7 +145,7 @@ impl<'s, T: Iterator<Item = (usize, char)>> Lexer<'s, T> {
|
|||||||
// if c == '\n' {
|
// if c == '\n' {
|
||||||
// self.emit((start, Token::NewLine, end));
|
// self.emit((start, Token::NewLine, end));
|
||||||
// }
|
// }
|
||||||
}
|
},
|
||||||
_ => {
|
_ => {
|
||||||
let pos = self.get_pos();
|
let pos = self.get_pos();
|
||||||
let _ = self.next_char();
|
let _ = self.next_char();
|
||||||
@@ -152,7 +153,7 @@ impl<'s, T: Iterator<Item = (usize, char)>> Lexer<'s, T> {
|
|||||||
Span::new(pos, self.get_pos()),
|
Span::new(pos, self.get_pos()),
|
||||||
LexicalErrorKind::UnrecognizedToken,
|
LexicalErrorKind::UnrecognizedToken,
|
||||||
));
|
));
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -166,9 +167,8 @@ impl<'s, T: Iterator<Item = (usize, char)>> Lexer<'s, T> {
|
|||||||
self.emit((start, token, end));
|
self.emit((start, token, end));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_number_start(&self, c: char, c1: Option<char>) -> bool {
|
fn is_number_start(&self, c: char) -> bool {
|
||||||
c.is_ascii_digit()
|
c.is_ascii_digit()
|
||||||
// || (c == '-' && c1.map_or(false, |c| c.is_ascii_digit()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_digit(&self, c: char) -> bool {
|
fn is_digit(&self, c: char) -> bool {
|
||||||
@@ -184,14 +184,14 @@ impl<'s, T: Iterator<Item = (usize, char)>> Lexer<'s, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn next_char(&mut self) -> Option<char> {
|
fn next_char(&mut self) -> Option<char> {
|
||||||
let (pos, char) = self.chars.next()?;
|
let char = self.chars.next()?;
|
||||||
self.pos = pos + 1;
|
self.pos += char.len_utf8();
|
||||||
|
|
||||||
Some(char)
|
Some(char)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit(&mut self, token: SpannedToken) {
|
fn emit(&mut self, token: SpannedToken) {
|
||||||
self.pending.push(token);
|
self.pending.push_back(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_pos(&self) -> usize {
|
fn get_pos(&self) -> usize {
|
||||||
@@ -199,11 +199,11 @@ impl<'s, T: Iterator<Item = (usize, char)>> Lexer<'s, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn peek_char_nth(&mut self, n: usize) -> Option<char> {
|
fn peek_char_nth(&mut self, n: usize) -> Option<char> {
|
||||||
self.chars.peek_nth(n).map(|(_, c)| *c)
|
self.chars.peek_nth(n).cloned()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s, T: Iterator<Item = (usize, char)>> Iterator for Lexer<'s, T> {
|
impl<'s, T: Iterator<Item = char>> Iterator for Lexer<'s, T> {
|
||||||
type Item = LexerResult;
|
type Item = LexerResult;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
|||||||
@@ -1,14 +1,9 @@
|
|||||||
use itertools::PeekNth;
|
use itertools::PeekNth;
|
||||||
|
|
||||||
use crate::{
|
use super::lexer::{LexerResult, SpannedToken};
|
||||||
ast::{Span, UntypedExpr},
|
use super::token::Token;
|
||||||
error::{self, ParseError, ParseErrorKind},
|
use crate::ast::{Span, UntypedExpr};
|
||||||
};
|
use crate::error::{self, ParseError, ParseErrorKind};
|
||||||
|
|
||||||
use super::{
|
|
||||||
lexer::{LexerResult, SpannedToken},
|
|
||||||
token::Token,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Parser<T: Iterator<Item = LexerResult>> {
|
pub struct Parser<T: Iterator<Item = LexerResult>> {
|
||||||
@@ -68,7 +63,7 @@ where
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
rhs = self.parse_expr_inner(rhs, op1.precedence() + 1)?;
|
rhs = self.parse_expr_inner(rhs, op2.precedence())?;
|
||||||
|
|
||||||
op = self.peek_token_nth(0).and_then(|token| token.as_bin_op());
|
op = self.peek_token_nth(0).and_then(|token| token.as_bin_op());
|
||||||
}
|
}
|
||||||
@@ -97,21 +92,21 @@ where
|
|||||||
value,
|
value,
|
||||||
}),
|
}),
|
||||||
(start, Token::Name(name), end) => {
|
(start, Token::Name(name), end) => {
|
||||||
let typename = match self.peek_token_nth(0) {
|
let (typename, end) = match self.peek_token_nth(0) {
|
||||||
Some(Token::LBracket) => {
|
Some(Token::LBracket) => {
|
||||||
let _ = self.next_token()?;
|
let _ = self.next_token()?;
|
||||||
let typename =
|
let (_, typename, _) =
|
||||||
self.expect_token_predicate(|t| matches!(t, Token::Name(_)))?;
|
self.expect_token_predicate(|t| matches!(t, Token::Name(_)))?;
|
||||||
let _ = self.expect_token(Token::RBracket)?;
|
let (_, end) = self.expect_token(Token::RBracket)?;
|
||||||
|
|
||||||
let typename = match typename.1 {
|
let typename = match typename {
|
||||||
Token::Name(id) => id,
|
Token::Name(id) => id,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(typename)
|
(Some(typename), end)
|
||||||
}
|
},
|
||||||
_ => None,
|
_ => (None, end),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(UntypedExpr::Var {
|
Ok(UntypedExpr::Var {
|
||||||
@@ -119,13 +114,13 @@ where
|
|||||||
name,
|
name,
|
||||||
typename,
|
typename,
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
(_, Token::LParen, _) => {
|
(_, Token::LParen, _) => {
|
||||||
let expr = self.parse_expr()?;
|
let expr = self.parse_expr()?;
|
||||||
let _ = self.expect_token(Token::RParen)?;
|
let _ = self.expect_token(Token::RParen)?;
|
||||||
|
|
||||||
Ok(expr)
|
Ok(expr)
|
||||||
}
|
},
|
||||||
(start, _, end) => Err(ParseError::new(
|
(start, _, end) => Err(ParseError::new(
|
||||||
Span::new(start, end),
|
Span::new(start, end),
|
||||||
ParseErrorKind::ExpectedExpr,
|
ParseErrorKind::ExpectedExpr,
|
||||||
@@ -139,7 +134,7 @@ where
|
|||||||
Some(Ok((start, token, end))) => {
|
Some(Ok((start, token, end))) => {
|
||||||
self.last_span = Span::new(start, end);
|
self.last_span = Span::new(start, end);
|
||||||
Ok((start, token, end))
|
Ok((start, token, end))
|
||||||
}
|
},
|
||||||
Some(Err(e)) => Err(e.into()),
|
Some(Err(e)) => Err(e.into()),
|
||||||
None => Err(ParseError::new(self.last_span, ParseErrorKind::UnexpectedEOF).into()),
|
None => Err(ParseError::new(self.last_span, ParseErrorKind::UnexpectedEOF).into()),
|
||||||
}
|
}
|
||||||
@@ -162,7 +157,7 @@ where
|
|||||||
(start, t, end) if t == token => Ok((start, end)),
|
(start, t, end) if t == token => Ok((start, end)),
|
||||||
(start, _, end) => {
|
(start, _, end) => {
|
||||||
Err(ParseError::new(Span::new(start, end), ParseErrorKind::UnexpectedToken).into())
|
Err(ParseError::new(Span::new(start, end), ParseErrorKind::UnexpectedToken).into())
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,7 +170,7 @@ where
|
|||||||
(start, t, end) if pred(&t) => Ok((start, t, end)),
|
(start, t, end) if pred(&t) => Ok((start, t, end)),
|
||||||
(start, _, end) => {
|
(start, _, end) => {
|
||||||
Err(ParseError::new(Span::new(start, end), ParseErrorKind::UnexpectedToken).into())
|
Err(ParseError::new(Span::new(start, end), ParseErrorKind::UnexpectedToken).into())
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use crate::{ast::BinOp, symbols::Symbol};
|
use crate::ast::BinOp;
|
||||||
|
use crate::symbols::Symbol;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Token {
|
pub enum Token {
|
||||||
@@ -56,7 +57,13 @@ impl fmt::Display for Token {
|
|||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Token::Name(id) => write!(f, "<id,{id}>"),
|
Token::Name(id) => write!(f, "<id,{id}>"),
|
||||||
Token::Float(number) => write!(f, "<{number}>"),
|
Token::Float(number) => {
|
||||||
|
if number == &number.trunc() {
|
||||||
|
write!(f, "<{number}.0>")
|
||||||
|
} else {
|
||||||
|
write!(f, "<{number}>")
|
||||||
|
}
|
||||||
|
},
|
||||||
Token::Int(number) => write!(f, "<{number}>"),
|
Token::Int(number) => write!(f, "<{number}>"),
|
||||||
Token::Plus => write!(f, "<+>"),
|
Token::Plus => write!(f, "<+>"),
|
||||||
Token::Minus => write!(f, "<->"),
|
Token::Minus => write!(f, "<->"),
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
use std::fmt;
|
use std::{fmt, io};
|
||||||
|
|
||||||
use crate::ast::typed::Type;
|
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
||||||
use crate::{
|
|
||||||
ast::{typed::TypedExpr, BinOp},
|
use crate::ast::BinOp;
|
||||||
symbols::{Symbol, SymbolsTable},
|
use crate::ast::typed::TypedExpr;
|
||||||
};
|
use crate::representation::util::TempVarContext;
|
||||||
|
use crate::symbols::{Symbol, SymbolsTable};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum IntermediateValue {
|
pub enum IntermediateValue {
|
||||||
@@ -13,11 +14,58 @@ pub enum IntermediateValue {
|
|||||||
Var { name: Symbol },
|
Var { name: Symbol },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl IntermediateValue {
|
||||||
|
pub fn as_u8(&self) -> u8 {
|
||||||
|
match self {
|
||||||
|
IntermediateValue::Int { .. } => b'i',
|
||||||
|
IntermediateValue::Float { .. } => b'f',
|
||||||
|
IntermediateValue::Var { .. } => b'v',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_writer(&self, writer: &mut impl io::Write) -> io::Result<()> {
|
||||||
|
writer.write_u8(self.as_u8())?;
|
||||||
|
|
||||||
|
match self {
|
||||||
|
IntermediateValue::Int { value } => writer.write_i64::<BigEndian>(*value)?,
|
||||||
|
IntermediateValue::Float { value } => writer.write_f64::<BigEndian>(*value)?,
|
||||||
|
IntermediateValue::Var { name } => writer.write_u64::<BigEndian>(name.into())?,
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_reader(reader: &mut impl io::Read) -> io::Result<Self> {
|
||||||
|
let b = reader.read_u8()?;
|
||||||
|
match b {
|
||||||
|
b'i' => Ok(IntermediateValue::Int {
|
||||||
|
value: reader.read_i64::<BigEndian>()?,
|
||||||
|
}),
|
||||||
|
b'f' => Ok(IntermediateValue::Float {
|
||||||
|
value: reader.read_f64::<BigEndian>()?,
|
||||||
|
}),
|
||||||
|
b'v' => Ok(IntermediateValue::Var {
|
||||||
|
name: reader.read_u64::<BigEndian>()?.into(),
|
||||||
|
}),
|
||||||
|
b => Err(io::Error::new(
|
||||||
|
io::ErrorKind::InvalidData,
|
||||||
|
format!("invalid byte: {b}"),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for IntermediateValue {
|
impl fmt::Display for IntermediateValue {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
IntermediateValue::Int { value } => write!(f, "{}", value),
|
IntermediateValue::Int { value } => write!(f, "{}", value),
|
||||||
IntermediateValue::Float { value } => write!(f, "{:.2}", value),
|
IntermediateValue::Float { value } => {
|
||||||
|
if *value == value.trunc() {
|
||||||
|
write!(f, "{value}.0")
|
||||||
|
} else {
|
||||||
|
write!(f, "{value}")
|
||||||
|
}
|
||||||
|
},
|
||||||
IntermediateValue::Var { name } => write!(f, "<id,{}>", name),
|
IntermediateValue::Var { name } => write!(f, "<id,{}>", name),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -35,71 +83,141 @@ pub enum IntermediateExpr {
|
|||||||
op: BinOp,
|
op: BinOp,
|
||||||
rhs: IntermediateValue,
|
rhs: IntermediateValue,
|
||||||
},
|
},
|
||||||
|
Identity {
|
||||||
|
result: Symbol,
|
||||||
|
value: IntermediateValue,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_temp_var(temp_var_counter: &mut usize, ty: Type, symbols: &mut SymbolsTable) -> Symbol {
|
impl fmt::Display for IntermediateExpr {
|
||||||
let result = symbols.add(format!("#T{}", temp_var_counter));
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
{
|
match self {
|
||||||
let data = symbols.resolve_mut(&result).unwrap();
|
IntermediateExpr::IntToFloat { result, value } => {
|
||||||
data.ty = Some(ty);
|
write!(f, "i2f <id,{}>, {}", result, value)
|
||||||
data.temporary = true;
|
},
|
||||||
|
IntermediateExpr::BinOp {
|
||||||
|
result,
|
||||||
|
lhs,
|
||||||
|
op,
|
||||||
|
rhs,
|
||||||
|
} => {
|
||||||
|
write!(f, "{:#} <id,{}>, {}, {}", op, result, lhs, rhs)
|
||||||
|
},
|
||||||
|
IntermediateExpr::Identity { result, value } => {
|
||||||
|
write!(f, "idt <id,{}>, {}", result, value)
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*temp_var_counter += 1;
|
|
||||||
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_intermediate_expr_inner(
|
impl IntermediateExpr {
|
||||||
|
pub fn as_u8(&self) -> u8 {
|
||||||
|
match self {
|
||||||
|
IntermediateExpr::IntToFloat { .. } => 0x01,
|
||||||
|
IntermediateExpr::BinOp { .. } => 0x02,
|
||||||
|
IntermediateExpr::Identity { .. } => 0x03,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_writer(&self, writer: &mut impl io::Write) -> io::Result<()> {
|
||||||
|
writer.write_u8(self.as_u8())?;
|
||||||
|
|
||||||
|
match self {
|
||||||
|
IntermediateExpr::IntToFloat { result, value } => {
|
||||||
|
writer.write_u64::<BigEndian>(result.into())?;
|
||||||
|
value.to_writer(writer)?;
|
||||||
|
},
|
||||||
|
IntermediateExpr::BinOp {
|
||||||
|
result,
|
||||||
|
lhs,
|
||||||
|
op,
|
||||||
|
rhs,
|
||||||
|
} => {
|
||||||
|
writer.write_u64::<BigEndian>(result.into())?;
|
||||||
|
lhs.to_writer(writer)?;
|
||||||
|
writer.write_u8(op.into())?;
|
||||||
|
rhs.to_writer(writer)?;
|
||||||
|
},
|
||||||
|
IntermediateExpr::Identity { result, value } => {
|
||||||
|
writer.write_u64::<BigEndian>(result.into())?;
|
||||||
|
value.to_writer(writer)?;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_reader(reader: &mut impl io::Read) -> io::Result<Self> {
|
||||||
|
let b = reader.read_u8()?;
|
||||||
|
match b {
|
||||||
|
0x01 => Ok(IntermediateExpr::IntToFloat {
|
||||||
|
result: reader.read_u64::<BigEndian>()?.into(),
|
||||||
|
value: IntermediateValue::from_reader(reader)?,
|
||||||
|
}),
|
||||||
|
0x02 => Ok(IntermediateExpr::BinOp {
|
||||||
|
result: reader.read_u64::<BigEndian>()?.into(),
|
||||||
|
lhs: IntermediateValue::from_reader(reader)?,
|
||||||
|
op: BinOp::try_from(reader.read_u8()?)
|
||||||
|
.map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "invalid bin op"))?,
|
||||||
|
rhs: IntermediateValue::from_reader(reader)?,
|
||||||
|
}),
|
||||||
|
0x03 => Ok(IntermediateExpr::Identity {
|
||||||
|
result: reader.read_u64::<BigEndian>()?.into(),
|
||||||
|
value: IntermediateValue::from_reader(reader)?,
|
||||||
|
}),
|
||||||
|
b => Err(io::Error::new(
|
||||||
|
io::ErrorKind::InvalidData,
|
||||||
|
format!("invalid byte: {b}"),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_typed_expr(
|
||||||
expr: TypedExpr,
|
expr: TypedExpr,
|
||||||
reuse_symbols: bool,
|
reuse_symbols: bool,
|
||||||
symbols: &mut SymbolsTable,
|
symbols: &mut SymbolsTable,
|
||||||
temp_var_counter: &mut usize,
|
) -> Vec<IntermediateExpr> {
|
||||||
exprs: &mut Vec<IntermediateExpr>,
|
|
||||||
temp_float_vars: &mut Vec<Symbol>,
|
|
||||||
temp_int_vars: &mut Vec<Symbol>,
|
|
||||||
) -> IntermediateValue {
|
|
||||||
let ty = expr.ty(symbols);
|
let ty = expr.ty(symbols);
|
||||||
|
|
||||||
|
let mut exprs = Vec::new();
|
||||||
|
let mut temp_var_context = TempVarContext::new(reuse_symbols, symbols);
|
||||||
|
|
||||||
|
let value = Self::from_typed_expr_inner(expr, &mut exprs, &mut temp_var_context);
|
||||||
|
|
||||||
|
if exprs.is_empty() {
|
||||||
|
return vec![IntermediateExpr::Identity {
|
||||||
|
result: temp_var_context.get_temp_var(ty),
|
||||||
|
value,
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
exprs
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_typed_expr_inner(
|
||||||
|
expr: TypedExpr,
|
||||||
|
exprs: &mut Vec<IntermediateExpr>,
|
||||||
|
temp_var_context: &mut TempVarContext,
|
||||||
|
) -> IntermediateValue {
|
||||||
|
let ty = expr.ty(temp_var_context.symbols());
|
||||||
|
|
||||||
match expr {
|
match expr {
|
||||||
TypedExpr::Int { value, .. } => IntermediateValue::Int { value },
|
TypedExpr::Int { value, .. } => IntermediateValue::Int { value },
|
||||||
TypedExpr::Float { value, .. } => IntermediateValue::Float { value },
|
TypedExpr::Float { value, .. } => IntermediateValue::Float { value },
|
||||||
TypedExpr::Var { name, .. } => IntermediateValue::Var { name },
|
TypedExpr::Var { name, .. } => IntermediateValue::Var { name },
|
||||||
TypedExpr::BinOp { lhs, op, rhs, .. } => {
|
TypedExpr::BinOp { lhs, op, rhs, .. } => {
|
||||||
let lhs = to_intermediate_expr_inner(
|
let lhs = Self::from_typed_expr_inner(*lhs, exprs, temp_var_context);
|
||||||
*lhs,
|
let rhs = Self::from_typed_expr_inner(*rhs, exprs, temp_var_context);
|
||||||
reuse_symbols,
|
|
||||||
symbols,
|
|
||||||
temp_var_counter,
|
|
||||||
exprs,
|
|
||||||
temp_float_vars,
|
|
||||||
temp_int_vars,
|
|
||||||
);
|
|
||||||
let rhs = to_intermediate_expr_inner(
|
|
||||||
*rhs,
|
|
||||||
reuse_symbols,
|
|
||||||
symbols,
|
|
||||||
temp_var_counter,
|
|
||||||
exprs,
|
|
||||||
temp_float_vars,
|
|
||||||
temp_int_vars,
|
|
||||||
);
|
|
||||||
|
|
||||||
if let IntermediateValue::Var { name } = lhs {
|
if let IntermediateValue::Var { name } = lhs {
|
||||||
free_temp_var(name, ty, temp_int_vars, temp_float_vars, symbols)
|
temp_var_context.free_temp_var(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let IntermediateValue::Var { name } = rhs {
|
if let IntermediateValue::Var { name } = rhs {
|
||||||
free_temp_var(name, ty, temp_int_vars, temp_float_vars, symbols)
|
temp_var_context.free_temp_var(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = allocate_temp_var(
|
let result = temp_var_context.get_temp_var(ty);
|
||||||
ty,
|
|
||||||
reuse_symbols,
|
|
||||||
temp_var_counter,
|
|
||||||
temp_float_vars,
|
|
||||||
temp_int_vars,
|
|
||||||
symbols,
|
|
||||||
);
|
|
||||||
|
|
||||||
exprs.push(IntermediateExpr::BinOp {
|
exprs.push(IntermediateExpr::BinOp {
|
||||||
result,
|
result,
|
||||||
@@ -109,95 +227,20 @@ fn to_intermediate_expr_inner(
|
|||||||
});
|
});
|
||||||
|
|
||||||
IntermediateValue::Var { name: result }
|
IntermediateValue::Var { name: result }
|
||||||
}
|
},
|
||||||
TypedExpr::IntToFloat { value, .. } => {
|
TypedExpr::IntToFloat { value, .. } => {
|
||||||
let value = to_intermediate_expr_inner(
|
let value = Self::from_typed_expr_inner(*value, exprs, temp_var_context);
|
||||||
*value,
|
|
||||||
reuse_symbols,
|
|
||||||
symbols,
|
|
||||||
temp_var_counter,
|
|
||||||
exprs,
|
|
||||||
temp_float_vars,
|
|
||||||
temp_int_vars,
|
|
||||||
);
|
|
||||||
|
|
||||||
if let IntermediateValue::Var { name: value } = value {
|
if let IntermediateValue::Var { name: value } = value {
|
||||||
free_temp_var(value, Type::Int, temp_int_vars, temp_float_vars, symbols)
|
temp_var_context.free_temp_var(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = allocate_temp_var(
|
let result = temp_var_context.get_temp_var(ty);
|
||||||
ty,
|
|
||||||
reuse_symbols,
|
|
||||||
temp_var_counter,
|
|
||||||
temp_float_vars,
|
|
||||||
temp_int_vars,
|
|
||||||
symbols,
|
|
||||||
);
|
|
||||||
|
|
||||||
exprs.push(IntermediateExpr::IntToFloat { result, value });
|
exprs.push(IntermediateExpr::IntToFloat { result, value });
|
||||||
|
|
||||||
IntermediateValue::Var { name: result }
|
IntermediateValue::Var { name: result }
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn allocate_temp_var(
|
|
||||||
ty: Type,
|
|
||||||
reuse_symbols: bool,
|
|
||||||
temp_var_counter: &mut usize,
|
|
||||||
temp_float_vars: &mut Vec<Symbol>,
|
|
||||||
temp_int_vars: &mut Vec<Symbol>,
|
|
||||||
symbols: &mut SymbolsTable,
|
|
||||||
) -> Symbol {
|
|
||||||
if reuse_symbols {
|
|
||||||
match ty {
|
|
||||||
Type::Int if !temp_int_vars.is_empty() => temp_int_vars.pop().unwrap(),
|
|
||||||
Type::Float if !temp_float_vars.is_empty() => temp_float_vars.pop().unwrap(),
|
|
||||||
_ => add_temp_var(temp_var_counter, ty, symbols),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
add_temp_var(temp_var_counter, ty, symbols)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn free_temp_var(
|
|
||||||
name: Symbol,
|
|
||||||
ty: Type,
|
|
||||||
temp_int_vars: &mut Vec<Symbol>,
|
|
||||||
temp_float_vars: &mut Vec<Symbol>,
|
|
||||||
symbols: &mut SymbolsTable,
|
|
||||||
) {
|
|
||||||
let temporary = symbols.temporary(&name).unwrap();
|
|
||||||
if !temporary {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ty == Type::Int {
|
|
||||||
temp_int_vars.push(name);
|
|
||||||
} else {
|
|
||||||
temp_float_vars.push(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_intermediate_expr(
|
|
||||||
expr: TypedExpr,
|
|
||||||
reuse_symbols: bool,
|
|
||||||
symbols: &mut SymbolsTable,
|
|
||||||
) -> Vec<IntermediateExpr> {
|
|
||||||
let mut exprs = Vec::new();
|
|
||||||
let mut intermediate_var_counter = 0;
|
|
||||||
let mut temp_float_vars = Vec::new();
|
|
||||||
let mut temp_int_vars = Vec::new();
|
|
||||||
|
|
||||||
to_intermediate_expr_inner(
|
|
||||||
expr,
|
|
||||||
reuse_symbols,
|
|
||||||
symbols,
|
|
||||||
&mut intermediate_var_counter,
|
|
||||||
&mut exprs,
|
|
||||||
&mut temp_float_vars,
|
|
||||||
&mut temp_int_vars,
|
|
||||||
);
|
|
||||||
|
|
||||||
exprs
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
pub mod intermediate;
|
pub mod intermediate;
|
||||||
|
mod util;
|
||||||
|
|||||||
71
src/representation/util.rs
Normal file
71
src/representation/util.rs
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
use crate::ast::typed::Type;
|
||||||
|
use crate::symbols::{Symbol, SymbolsTable};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct TempVarContext<'t> {
|
||||||
|
counter: usize,
|
||||||
|
floats: Vec<Symbol>,
|
||||||
|
ints: Vec<Symbol>,
|
||||||
|
reuse_symbols: bool,
|
||||||
|
symbols: &'t mut SymbolsTable,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'t> TempVarContext<'t> {
|
||||||
|
pub fn new(reuse_symbols: bool, symbols: &'t mut SymbolsTable) -> Self {
|
||||||
|
Self {
|
||||||
|
counter: 0,
|
||||||
|
floats: Vec::new(),
|
||||||
|
ints: Vec::new(),
|
||||||
|
reuse_symbols,
|
||||||
|
symbols,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_temp_var(&mut self, ty: Type) -> Symbol {
|
||||||
|
if self.reuse_symbols {
|
||||||
|
match ty {
|
||||||
|
Type::Int if !self.ints.is_empty() => self.ints.pop().unwrap(),
|
||||||
|
Type::Float if !self.floats.is_empty() => self.floats.pop().unwrap(),
|
||||||
|
_ => self.allocate_temp_var(ty),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.allocate_temp_var(ty)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn symbols(&self) -> &SymbolsTable {
|
||||||
|
self.symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
fn allocate_temp_var(&mut self, ty: Type) -> Symbol {
|
||||||
|
let result = self.symbols.add(format!("#T{}", self.counter));
|
||||||
|
{
|
||||||
|
let data = self.symbols.resolve_mut(&result).unwrap();
|
||||||
|
data.ty = Some(ty);
|
||||||
|
data.temporary = true;
|
||||||
|
}
|
||||||
|
self.counter += 1;
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn free_temp_var(&mut self, name: Symbol) {
|
||||||
|
let Some(data) = self.symbols.resolve(&name) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if !data.temporary {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let Some(ty) = data.ty else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if ty == Type::Int {
|
||||||
|
self.ints.push(name);
|
||||||
|
} else {
|
||||||
|
self.floats.push(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,25 @@
|
|||||||
pub mod builtin;
|
use std::collections::{HashMap, hash_map};
|
||||||
|
use std::fmt::Display;
|
||||||
|
use std::io;
|
||||||
|
|
||||||
use std::{
|
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
||||||
collections::{hash_map, HashMap},
|
|
||||||
fmt::Display,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::ast::typed::Type;
|
use crate::ast::typed::Type;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct Symbol(usize);
|
pub struct Symbol(u64);
|
||||||
|
|
||||||
|
impl From<&Symbol> for u64 {
|
||||||
|
fn from(value: &Symbol) -> Self {
|
||||||
|
value.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u64> for Symbol {
|
||||||
|
fn from(value: u64) -> Self {
|
||||||
|
Self(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SymbolData {
|
pub struct SymbolData {
|
||||||
@@ -18,6 +29,43 @@ pub struct SymbolData {
|
|||||||
pub temporary: bool,
|
pub temporary: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SymbolData {
|
||||||
|
fn from_reader(reader: &mut impl io::Read) -> io::Result<Self> {
|
||||||
|
let id = reader.read_u64::<BigEndian>()?;
|
||||||
|
let name = {
|
||||||
|
let n = reader.read_u64::<BigEndian>()?;
|
||||||
|
let mut buf = vec![0; n as usize];
|
||||||
|
reader.read_exact(&mut buf)?;
|
||||||
|
String::from_utf8(buf)
|
||||||
|
.map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "invalid utf-8"))?
|
||||||
|
};
|
||||||
|
|
||||||
|
let ty = {
|
||||||
|
let b = reader.read_u8()?;
|
||||||
|
Type::try_from(b).ok()
|
||||||
|
};
|
||||||
|
|
||||||
|
let temporary = reader.read_u8()? != 0;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
id: Symbol(id),
|
||||||
|
name,
|
||||||
|
ty,
|
||||||
|
temporary,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_writer(&self, writer: &mut impl io::Write) -> io::Result<()> {
|
||||||
|
writer.write_u64::<BigEndian>(self.id.0)?;
|
||||||
|
writer.write_u64::<BigEndian>(self.name.len() as u64)?;
|
||||||
|
writer.write_all(self.name.as_bytes())?;
|
||||||
|
writer.write_u8(self.ty.map_or(0, |ty| ty.into()))?;
|
||||||
|
writer.write_u8(self.temporary as u8)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Display for SymbolData {
|
impl Display for SymbolData {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
let mut builder = f.debug_struct("symbol");
|
let mut builder = f.debug_struct("symbol");
|
||||||
@@ -44,7 +92,7 @@ impl Display for Symbol {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SymbolsTable {
|
pub struct SymbolsTable {
|
||||||
symbols: HashMap<String, SymbolData>,
|
symbols: HashMap<String, SymbolData>,
|
||||||
next_id: usize,
|
next_id: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SymbolsTable {
|
impl SymbolsTable {
|
||||||
@@ -55,6 +103,36 @@ impl SymbolsTable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_reader(reader: &mut impl io::Read) -> io::Result<Self> {
|
||||||
|
let n = reader.read_u64::<BigEndian>()?;
|
||||||
|
|
||||||
|
let mut max_id = 0;
|
||||||
|
let mut symbols = Vec::with_capacity(n as usize);
|
||||||
|
for _ in 0..n {
|
||||||
|
let data = SymbolData::from_reader(reader)?;
|
||||||
|
max_id = max_id.max(data.id.0);
|
||||||
|
symbols.push(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
symbols: symbols
|
||||||
|
.into_iter()
|
||||||
|
.map(|data| (data.name.clone(), data))
|
||||||
|
.collect(),
|
||||||
|
next_id: max_id + 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_writer(&self, writer: &mut impl io::Write) -> io::Result<()> {
|
||||||
|
writer.write_u64::<BigEndian>(self.symbols.len() as u64)?;
|
||||||
|
|
||||||
|
for data in self.symbols.values() {
|
||||||
|
data.to_writer(writer)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn retain(&mut self, symbols: &[Symbol]) {
|
pub fn retain(&mut self, symbols: &[Symbol]) {
|
||||||
self.symbols.retain(|_, data| symbols.contains(&data.id));
|
self.symbols.retain(|_, data| symbols.contains(&data.id));
|
||||||
}
|
}
|
||||||
@@ -81,34 +159,18 @@ impl SymbolsTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve(&self, symbol: &Symbol) -> Option<&SymbolData> {
|
pub fn resolve(&self, symbol: &Symbol) -> Option<&SymbolData> {
|
||||||
self.symbols.iter().find_map(
|
self.symbols.values().find(|data| &data.id == symbol)
|
||||||
|(_name, data)| {
|
|
||||||
if &data.id == symbol {
|
|
||||||
Some(data)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve_mut(&mut self, symbol: &Symbol) -> Option<&mut SymbolData> {
|
pub fn resolve_mut(&mut self, symbol: &Symbol) -> Option<&mut SymbolData> {
|
||||||
self.symbols.iter_mut().find_map(
|
self.symbols.values_mut().find(|data| &data.id == symbol)
|
||||||
|(_name, data)| {
|
|
||||||
if &data.id == symbol {
|
|
||||||
Some(data)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_of(&self, symbol: &Symbol) -> Option<Type> {
|
pub fn type_of(&self, symbol: &Symbol) -> Option<Type> {
|
||||||
self.resolve(symbol).and_then(|data| data.ty)
|
self.resolve(symbol).and_then(|data| data.ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn temporary(&self, symbol: &Symbol) -> Option<bool> {
|
pub fn is_temporary(&self, symbol: &Symbol) -> Option<bool> {
|
||||||
self.resolve(symbol).map(|data| data.temporary)
|
self.resolve(symbol).map(|data| data.temporary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
67
src/util.rs
67
src/util.rs
@@ -1,13 +1,10 @@
|
|||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
use crate::representation::intermediate::IntermediateValue;
|
use crate::ast::UntypedExpr;
|
||||||
use crate::symbols::Symbol;
|
use crate::ast::typed::TypedExpr;
|
||||||
use crate::{
|
use crate::representation::intermediate::{IntermediateExpr, IntermediateValue};
|
||||||
ast::{typed::TypedExpr, UntypedExpr},
|
use crate::symbols::{Symbol, SymbolsTable};
|
||||||
representation::intermediate::IntermediateExpr,
|
|
||||||
symbols::SymbolsTable,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn collect_used_symbols(expr: &[IntermediateExpr]) -> Vec<Symbol> {
|
pub fn collect_used_symbols(expr: &[IntermediateExpr]) -> Vec<Symbol> {
|
||||||
let mut used_symbols = HashSet::new();
|
let mut used_symbols = HashSet::new();
|
||||||
@@ -16,21 +13,31 @@ pub fn collect_used_symbols(expr: &[IntermediateExpr]) -> Vec<Symbol> {
|
|||||||
match expr {
|
match expr {
|
||||||
IntermediateExpr::IntToFloat { result, value } => {
|
IntermediateExpr::IntToFloat { result, value } => {
|
||||||
used_symbols.insert(*result);
|
used_symbols.insert(*result);
|
||||||
|
|
||||||
if let IntermediateValue::Var { name } = value {
|
if let IntermediateValue::Var { name } = value {
|
||||||
used_symbols.insert(*name);
|
used_symbols.insert(*name);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
IntermediateExpr::BinOp {
|
IntermediateExpr::BinOp {
|
||||||
result, lhs, rhs, ..
|
result, lhs, rhs, ..
|
||||||
} => {
|
} => {
|
||||||
used_symbols.insert(*result);
|
used_symbols.insert(*result);
|
||||||
|
|
||||||
if let IntermediateValue::Var { name } = lhs {
|
if let IntermediateValue::Var { name } = lhs {
|
||||||
used_symbols.insert(*name);
|
used_symbols.insert(*name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let IntermediateValue::Var { name } = rhs {
|
if let IntermediateValue::Var { name } = rhs {
|
||||||
used_symbols.insert(*name);
|
used_symbols.insert(*name);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
IntermediateExpr::Identity { result, value } => {
|
||||||
|
used_symbols.insert(*result);
|
||||||
|
|
||||||
|
if let IntermediateValue::Var { name } = value {
|
||||||
|
used_symbols.insert(*name);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,19 +49,7 @@ pub fn print_intermediate_exprs(
|
|||||||
writer: &mut impl io::Write,
|
writer: &mut impl io::Write,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
for expr in exprs {
|
for expr in exprs {
|
||||||
match expr {
|
writeln!(writer, "{}", expr)?;
|
||||||
IntermediateExpr::IntToFloat { result, value } => {
|
|
||||||
writeln!(writer, "i2f <id,{}>, {}", result, value)?;
|
|
||||||
}
|
|
||||||
IntermediateExpr::BinOp {
|
|
||||||
result,
|
|
||||||
lhs,
|
|
||||||
op,
|
|
||||||
rhs,
|
|
||||||
} => {
|
|
||||||
writeln!(writer, "{:#} <id,{}>, {}, {}", op, result, lhs, rhs)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -69,11 +64,11 @@ pub fn print_postfix_expr(expr: &TypedExpr, writer: &mut impl io::Write) -> io::
|
|||||||
print_postfix_expr(lhs, writer)?;
|
print_postfix_expr(lhs, writer)?;
|
||||||
print_postfix_expr(rhs, writer)?;
|
print_postfix_expr(rhs, writer)?;
|
||||||
write!(writer, "{} ", op)?;
|
write!(writer, "{} ", op)?;
|
||||||
}
|
},
|
||||||
TypedExpr::IntToFloat { value, .. } => {
|
TypedExpr::IntToFloat { value, .. } => {
|
||||||
print_postfix_expr(value, writer)?;
|
print_postfix_expr(value, writer)?;
|
||||||
write!(writer, "i2f ")?;
|
write!(writer, "i2f ")?;
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -92,11 +87,17 @@ fn write_typed_expr(
|
|||||||
|
|
||||||
match expr {
|
match expr {
|
||||||
TypedExpr::Int { value, .. } => writeln!(writer, "<{}>", value),
|
TypedExpr::Int { value, .. } => writeln!(writer, "<{}>", value),
|
||||||
TypedExpr::Float { value, .. } => writeln!(writer, "<{}>", value),
|
TypedExpr::Float { value, .. } => {
|
||||||
|
if value == &value.trunc() {
|
||||||
|
writeln!(writer, "<{}.0>", value)
|
||||||
|
} else {
|
||||||
|
writeln!(writer, "<{}>", value)
|
||||||
|
}
|
||||||
|
},
|
||||||
TypedExpr::Var { name, .. } => {
|
TypedExpr::Var { name, .. } => {
|
||||||
let ty = symbols.resolve(name).unwrap().ty.unwrap();
|
let ty = symbols.resolve(name).unwrap().ty.unwrap();
|
||||||
writeln!(writer, "<id,{},{}>", name, ty)
|
writeln!(writer, "<id,{},{}>", name, ty)
|
||||||
}
|
},
|
||||||
TypedExpr::BinOp { lhs, op, rhs, .. } => {
|
TypedExpr::BinOp { lhs, op, rhs, .. } => {
|
||||||
writeln!(writer, "<{}>", op)?;
|
writeln!(writer, "<{}>", op)?;
|
||||||
|
|
||||||
@@ -108,7 +109,7 @@ fn write_typed_expr(
|
|||||||
|
|
||||||
write_typed_expr(lhs, symbols, writer, &new_prefix, false)?;
|
write_typed_expr(lhs, symbols, writer, &new_prefix, false)?;
|
||||||
write_typed_expr(rhs, symbols, writer, &new_prefix, true)
|
write_typed_expr(rhs, symbols, writer, &new_prefix, true)
|
||||||
}
|
},
|
||||||
TypedExpr::IntToFloat { value, .. } => {
|
TypedExpr::IntToFloat { value, .. } => {
|
||||||
writeln!(writer, "i2f")?;
|
writeln!(writer, "i2f")?;
|
||||||
|
|
||||||
@@ -119,7 +120,7 @@ fn write_typed_expr(
|
|||||||
};
|
};
|
||||||
|
|
||||||
write_typed_expr(value, symbols, writer, &new_prefix, true)
|
write_typed_expr(value, symbols, writer, &new_prefix, true)
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,7 +144,13 @@ fn write_untyped_expr(
|
|||||||
|
|
||||||
match expr {
|
match expr {
|
||||||
UntypedExpr::Int { value, .. } => writeln!(writer, "<{}>", value),
|
UntypedExpr::Int { value, .. } => writeln!(writer, "<{}>", value),
|
||||||
UntypedExpr::Float { value, .. } => writeln!(writer, "<{}>", value),
|
UntypedExpr::Float { value, .. } => {
|
||||||
|
if value == &value.trunc() {
|
||||||
|
writeln!(writer, "<{}.0>", value)
|
||||||
|
} else {
|
||||||
|
writeln!(writer, "<{}>", value)
|
||||||
|
}
|
||||||
|
},
|
||||||
UntypedExpr::Var {
|
UntypedExpr::Var {
|
||||||
name: id, typename, ..
|
name: id, typename, ..
|
||||||
} => {
|
} => {
|
||||||
@@ -152,7 +159,7 @@ fn write_untyped_expr(
|
|||||||
write!(writer, ",{}", typename)?;
|
write!(writer, ",{}", typename)?;
|
||||||
}
|
}
|
||||||
writeln!(writer, ">")
|
writeln!(writer, ">")
|
||||||
}
|
},
|
||||||
UntypedExpr::BinOp { lhs, op, rhs, .. } => {
|
UntypedExpr::BinOp { lhs, op, rhs, .. } => {
|
||||||
writeln!(writer, "<{}>", op)?;
|
writeln!(writer, "<{}>", op)?;
|
||||||
|
|
||||||
@@ -164,7 +171,7 @@ fn write_untyped_expr(
|
|||||||
|
|
||||||
write_untyped_expr(lhs, writer, &new_prefix, false)?;
|
write_untyped_expr(lhs, writer, &new_prefix, false)?;
|
||||||
write_untyped_expr(rhs, writer, &new_prefix, true)
|
write_untyped_expr(rhs, writer, &new_prefix, true)
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user