From 8c131c035bf563bc70a42ec4dbd350876156277e Mon Sep 17 00:00:00 2001 From: Andrew Segavac Date: Sun, 12 Sep 2021 14:36:36 -0600 Subject: [PATCH] added error handling to type checker --- Cargo.lock | 365 ++++++++++++++------------- Cargo.toml | 1 + src/errors.rs | 36 +++ src/main.rs | 21 +- src/type_checking.rs | 586 +++++++++++++++++++++++-------------------- 5 files changed, 558 insertions(+), 451 deletions(-) create mode 100644 src/errors.rs diff --git a/Cargo.lock b/Cargo.lock index 4371c96..78eebd3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,174 +1,199 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "aho-corasick" version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" dependencies = [ - "memchr 2.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", ] [[package]] name = "ansi_term" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" dependencies = [ - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi", ] [[package]] name = "ascii-canvas" version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" dependencies = [ - "term 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "term", ] [[package]] name = "atty" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.88 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "hermit-abi", + "libc", + "winapi", ] [[package]] name = "autocfg" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "bit-set" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de" dependencies = [ - "bit-vec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bit-vec", ] [[package]] name = "bit-vec" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" [[package]] name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" [[package]] name = "boring-lang" version = "0.0.1" dependencies = [ - "clap 2.33.3 (registry+https://github.com/rust-lang/crates.io-index)", - "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", - "lalrpop 0.19.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lalrpop-util 0.19.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "clap", + "inkwell", + "lalrpop", + "lalrpop-util", + "regex", + "thiserror", ] [[package]] name = "cc" version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" version = "2.33.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ansi_term", + "atty", + "bitflags", + "strsim", + "textwrap", + "unicode-width", + "vec_map", ] [[package]] name = "crunchy" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "diff" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499" [[package]] name = "dirs-next" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" dependencies = [ - "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "dirs-sys-next 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "dirs-sys-next", ] [[package]] name = "dirs-sys-next" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ - "libc 0.2.88 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_users 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "redox_users", + "winapi", ] [[package]] name = "either" version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "ena" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7402b94a93c24e742487327a7cd839dc9d36fec9de9fb25b09f2dae459f36c3" dependencies = [ - "log 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)", + "log", ] [[package]] name = "fixedbitset" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" [[package]] name = "getrandom" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ - "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.88 (registry+https://github.com/rust-lang/crates.io-index)", - "wasi 0.10.2+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "wasi", ] [[package]] name = "hashbrown" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" [[package]] name = "hermit-abi" version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" dependencies = [ - "libc 0.2.88 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", ] [[package]] name = "indexmap" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" dependencies = [ - "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hashbrown 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg", + "hashbrown", ] [[package]] @@ -176,13 +201,13 @@ name = "inkwell" version = "0.1.0" source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#ef1f5e491fd599d84ba67f82b87e55cb7be4b0b8" dependencies = [ - "either 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "inkwell_internals 0.2.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", - "libc 0.2.88 (registry+https://github.com/rust-lang/crates.io-index)", - "llvm-sys 70.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "once_cell 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "either", + "inkwell_internals", + "libc", + "llvm-sys", + "once_cell", + "parking_lot", + "regex", ] [[package]] @@ -190,407 +215,401 @@ name = "inkwell_internals" version = "0.2.0" source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#ef1f5e491fd599d84ba67f82b87e55cb7be4b0b8" dependencies = [ - "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.62 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "instant" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" dependencies = [ - "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] [[package]] name = "itertools" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf" dependencies = [ - "either 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "either", ] [[package]] name = "lalrpop" version = "0.19.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15174f1c529af5bf1283c3bc0058266b483a67156f79589fab2a25e23cf8988" dependencies = [ - "ascii-canvas 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "bit-set 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "diff 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "ena 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lalrpop-util 0.19.6 (registry+https://github.com/rust-lang/crates.io-index)", - "petgraph 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pico-args 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ascii-canvas", + "atty", + "bit-set", + "diff", + "ena", + "itertools", + "lalrpop-util", + "petgraph", + "pico-args", + "regex", + "regex-syntax", + "string_cache", + "term", + "tiny-keccak", + "unicode-xid", ] [[package]] name = "lalrpop-util" version = "0.19.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e58cce361efcc90ba8a0a5f982c741ff86b603495bb15a998412e957dcd278" dependencies = [ - "regex 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "regex", ] [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03b07a082330a35e43f63177cc01689da34fbffa0105e1246cf0311472cac73a" [[package]] name = "llvm-sys" version = "70.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673300127ec17878e6f7fee4e851ba6fd36b08c26b2d6258732d699d1b3e3fcd" dependencies = [ - "cc 1.0.67 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.88 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "lazy_static", + "libc", + "regex", + "semver", ] [[package]] name = "lock_api" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312" dependencies = [ - "scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard", ] [[package]] name = "log" version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ - "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] [[package]] name = "memchr" version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" [[package]] name = "new_debug_unreachable" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" [[package]] name = "once_cell" version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" [[package]] name = "parking_lot" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" dependencies = [ - "instant 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "lock_api 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", + "instant", + "lock_api", + "parking_lot_core", ] [[package]] name = "parking_lot_core" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" dependencies = [ - "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "instant 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.88 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", ] [[package]] name = "petgraph" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" dependencies = [ - "fixedbitset 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fixedbitset", + "indexmap", ] [[package]] name = "phf_shared" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" dependencies = [ - "siphasher 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "siphasher", ] [[package]] name = "pico-args" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db8bcd96cb740d03149cbad5518db9fd87126a10ab519c011893b1754134c468" [[package]] name = "precomputed-hash" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "proc-macro2" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" dependencies = [ - "unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid", ] [[package]] name = "quote" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" dependencies = [ - "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", ] [[package]] name = "redox_syscall" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", ] [[package]] name = "redox_users" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" dependencies = [ - "getrandom 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom", + "redox_syscall", ] [[package]] name = "regex" version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a" dependencies = [ - "aho-corasick 0.7.15 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local", ] [[package]] name = "regex-syntax" version = "0.6.22" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" [[package]] name = "rustversion" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088" [[package]] name = "scopeguard" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "semver" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver-parser", ] [[package]] name = "semver-parser" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "siphasher" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "729a25c17d72b06c68cb47955d44fda88ad2d3e7d77e025663fdd69b93dd71a1" [[package]] name = "smallvec" version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" [[package]] name = "string_cache" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ddb1139b5353f96e429e1a5e19fbaf663bddedaa06d1dbd49f82e352601209a" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "new_debug_unreachable 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_shared 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static", + "new_debug_unreachable", + "phf_shared", + "precomputed-hash", ] [[package]] name = "strsim" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "syn" version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123a78a3596b24fee53a6464ce52d8ecbf62241e6294c7e7fe12086cd161f512" dependencies = [ - "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "unicode-xid", ] [[package]] name = "term" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" dependencies = [ - "dirs-next 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustversion 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "dirs-next", + "rustversion", + "winapi", ] [[package]] name = "textwrap" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" dependencies = [ - "unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width", +] + +[[package]] +name = "thiserror" +version = "1.0.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "602eca064b2d83369e2b2f34b09c70b605402801927c65c11071ac911d299b88" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad553cc2c78e8de258400763a647e80e6d1b31ee237275d756f6836d204494c" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] name = "thread_local" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" dependencies = [ - "once_cell 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell", ] [[package]] name = "tiny-keccak" version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" dependencies = [ - "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crunchy", ] [[package]] name = "unicode-width" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" [[package]] name = "unicode-xid" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" [[package]] name = "vec_map" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[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 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "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" - -[metadata] -"checksum aho-corasick 0.7.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" -"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum ascii-canvas 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" -"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -"checksum autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" -"checksum bit-set 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de" -"checksum bit-vec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" -"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" -"checksum cc 1.0.67 (registry+https://github.com/rust-lang/crates.io-index)" = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" -"checksum cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -"checksum clap 2.33.3 (registry+https://github.com/rust-lang/crates.io-index)" = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" -"checksum crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" -"checksum diff 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499" -"checksum dirs-next 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -"checksum dirs-sys-next 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -"checksum either 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" -"checksum ena 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d7402b94a93c24e742487327a7cd839dc9d36fec9de9fb25b09f2dae459f36c3" -"checksum fixedbitset 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" -"checksum getrandom 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" -"checksum hashbrown 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -"checksum hermit-abi 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" -"checksum indexmap 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" -"checksum inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)" = "" -"checksum inkwell_internals 0.2.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)" = "" -"checksum instant 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" -"checksum itertools 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf" -"checksum lalrpop 0.19.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b15174f1c529af5bf1283c3bc0058266b483a67156f79589fab2a25e23cf8988" -"checksum lalrpop-util 0.19.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d3e58cce361efcc90ba8a0a5f982c741ff86b603495bb15a998412e957dcd278" -"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -"checksum libc 0.2.88 (registry+https://github.com/rust-lang/crates.io-index)" = "03b07a082330a35e43f63177cc01689da34fbffa0105e1246cf0311472cac73a" -"checksum llvm-sys 70.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "673300127ec17878e6f7fee4e851ba6fd36b08c26b2d6258732d699d1b3e3fcd" -"checksum lock_api 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312" -"checksum log 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" -"checksum memchr 2.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" -"checksum new_debug_unreachable 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" -"checksum once_cell 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" -"checksum parking_lot 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" -"checksum parking_lot_core 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" -"checksum petgraph 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" -"checksum phf_shared 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" -"checksum pico-args 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "db8bcd96cb740d03149cbad5518db9fd87126a10ab519c011893b1754134c468" -"checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" -"checksum proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" -"checksum quote 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" -"checksum redox_syscall 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9" -"checksum redox_users 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" -"checksum regex 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a" -"checksum regex-syntax 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)" = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" -"checksum rustversion 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088" -"checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" -"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum siphasher 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "729a25c17d72b06c68cb47955d44fda88ad2d3e7d77e025663fdd69b93dd71a1" -"checksum smallvec 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" -"checksum string_cache 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8ddb1139b5353f96e429e1a5e19fbaf663bddedaa06d1dbd49f82e352601209a" -"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum syn 1.0.62 (registry+https://github.com/rust-lang/crates.io-index)" = "123a78a3596b24fee53a6464ce52d8ecbf62241e6294c7e7fe12086cd161f512" -"checksum term 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" -"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -"checksum thread_local 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" -"checksum tiny-keccak 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -"checksum unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" -"checksum unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" -"checksum vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" -"checksum wasi 0.10.2+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" -"checksum winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index 4d249f5..1d3631a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,3 +15,4 @@ lalrpop-util = "0.19.6" regex = "1" inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm7-0" } clap = "2.33.0" +thiserror = "1" diff --git a/src/errors.rs b/src/errors.rs new file mode 100644 index 0000000..0a15041 --- /dev/null +++ b/src/errors.rs @@ -0,0 +1,36 @@ +use crate::ast; +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum TypingError { + #[error("unknown named type")] + TypeDoesNotExist { identifier: ast::Identifier }, + #[error("identifier is not type")] + IdentifierIsNotType { identifier: ast::Identifier }, + #[error("argument length mismatch")] + ArgumentLengthMismatch { + // TODO: add position + }, + #[error("type mismatch")] + TypeMismatch { + type_one: ast::TypeUsage, + type_two: ast::TypeUsage, + }, + #[error("unknown field name")] + UnknownFieldName { identifier: ast::Identifier }, + #[error("attribute gotten of non-struct")] + AttributeOfNonstruct { identifier: ast::Identifier }, + #[error("name is not a struct, cannot instaniate")] + NotAStructLiteral { identifier: ast::Identifier }, + #[error("struct literal fields mismatch")] + StructLiteralFieldsMismatch { + struct_name: ast::Identifier, + struct_definition_name: ast::Identifier, + }, + #[error("function call used with non-function")] + FunctionCallNotAFunction { + // TODO: add position + }, + #[error("multiple errors")] + MultipleErrors { errors: Vec }, +} diff --git a/src/main.rs b/src/main.rs index fd02cac..4c216e4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ // mod types; mod ast; +mod errors; mod type_alias_resolution; mod type_checking; #[macro_use] @@ -60,9 +61,16 @@ fn main() { let resolved_ast = alias_resolver.with_module(&module_ast); println!("resolved ast: {:#?}", &resolved_ast); let type_checker = type_checking::TypeChecker {}; - let (checked_ast, subst) = type_checker.with_module(&resolved_ast); - println!("checked ast: {:#?}", &checked_ast); - println!("substitutions: {:#?}", &subst); + let type_checking_result = type_checker.with_module(&resolved_ast); + match &type_checking_result { + Ok((checked_ast, subst)) => { + println!("checked ast: {:#?}", &checked_ast); + println!("substitutions: {:#?}", &subst); + } + Err(err) => { + println!("type checking error: {:#?}", &err); + } + } // let context = Context::create(); // let mut code_gen = compiler::ModuleCodeGen::new(&context, "main".to_string()); @@ -137,5 +145,10 @@ fn grammar() { assert!(grammar::ModuleParser::new() .parse(&id_gen, "fn add(a: i32, b: i32): i32 { a + b }") .is_ok()); - assert!(grammar::ModuleParser::new().parse(&id_gen, "fn add(a: i32, b: i32): i32 { a + b } fn subtract(a: i32, b: i32): i32 { a - b }").is_ok()); + assert!(grammar::ModuleParser::new() + .parse( + &id_gen, + "fn add(a: i32, b: i32): i32 { a + b } fn subtract(a: i32, b: i32): i32 { a - b }" + ) + .is_ok()); } diff --git a/src/type_checking.rs b/src/type_checking.rs index abd58b2..469d231 100644 --- a/src/type_checking.rs +++ b/src/type_checking.rs @@ -1,8 +1,11 @@ use crate::ast; +use crate::errors; use std::collections::HashMap; pub type SubstitutionMap = HashMap; +pub type Result = std::result::Result; + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum NamedEntity { TypeDeclaration(ast::TypeDeclaration), @@ -161,37 +164,51 @@ impl Context { } } -fn type_exists(ctx: &Context, type_: &ast::TypeUsage) { - // TODO: error handling - match type_ { +fn type_exists(ctx: &Context, type_: &ast::TypeUsage) -> Result<()> { + let result = match type_ { ast::TypeUsage::Named(named) => { if !ctx.environment.contains_key(&named.name.name.value) { - panic!("unknown type: {}", &named.name.name.value); + return Err(errors::TypingError::TypeDoesNotExist { + identifier: named.name.clone(), + }); } match ctx.environment[&named.name.name.value] { NamedEntity::TypeDeclaration(_) => { // is a type } _ => { - panic!("unknown type") + return Err(errors::TypingError::IdentifierIsNotType { + identifier: named.name.clone(), + }); } } } ast::TypeUsage::Unknown(unknown) => {} // do nothing ast::TypeUsage::Function(function) => { + let mut errs = vec![]; for arg in function.arguments.iter() { - type_exists(ctx, arg); + match type_exists(ctx, arg) { + Ok(_) => {} + Err(err) => errs.push(err), + }; + } + match type_exists(ctx, &function.return_type) { + Ok(_) => {} + Err(err) => errs.push(err), + } + if errs.len() > 0 { + return Err(errors::TypingError::MultipleErrors { errors: errs }); } - type_exists(ctx, &function.return_type); } - } + }; + return Ok(result); } fn apply_substitution( ctx: &Context, substitution: &SubstitutionMap, type_: &ast::TypeUsage, -) -> ast::TypeUsage { +) -> Result { let result = match type_ { ast::TypeUsage::Named(named) => ast::TypeUsage::Named(named.clone()), ast::TypeUsage::Unknown(unknown) => { @@ -201,62 +218,65 @@ fn apply_substitution( ast::TypeUsage::Unknown(unknown.clone()) } } - ast::TypeUsage::Function(function) => ast::TypeUsage::Function(ast::FunctionTypeUsage { - arguments: function - .arguments - .iter() - .map(|arg| apply_substitution(ctx, substitution, arg)) - .collect(), - return_type: Box::new(apply_substitution(ctx, substitution, &function.return_type)), - }), + ast::TypeUsage::Function(function) => { + let mut arguments = vec![]; + for arg in function.arguments.iter() { + arguments.push(apply_substitution(ctx, substitution, arg)?); + } + ast::TypeUsage::Function(ast::FunctionTypeUsage { + arguments: arguments, + return_type: Box::new(apply_substitution( + ctx, + substitution, + &function.return_type, + )?), + }) + } }; - type_exists(ctx, &result); - return result; + type_exists(ctx, &result)?; + return Ok(result); } fn compose_substitutions( ctx: &Context, s1: &SubstitutionMap, s2: &SubstitutionMap, -) -> SubstitutionMap { +) -> Result { let mut result = SubstitutionMap::new(); for k in s2.keys() { - result.insert(k.to_string(), apply_substitution(ctx, s1, &s2[k])); + result.insert(k.to_string(), apply_substitution(ctx, s1, &s2[k])?); } - return s1 + return Ok(s1 .into_iter() .map(|(k, v)| (k.clone(), v.clone())) .chain(result) - .collect(); + .collect()); } -fn unify(ctx: &Context, t1: &ast::TypeUsage, t2: &ast::TypeUsage) -> SubstitutionMap { +fn unify(ctx: &Context, t1: &ast::TypeUsage, t2: &ast::TypeUsage) -> Result { match (t1, t2) { (ast::TypeUsage::Named(named1), ast::TypeUsage::Named(named2)) => { - // if named1.name.name.value == "!" || named2.name.name.value == "!" { - // return SubstitutionMap::new(); // never matches with everything - // } if named1.name.name.value == named2.name.name.value { - return SubstitutionMap::new(); + return Ok(SubstitutionMap::new()); } } _ => {} } match t1 { ast::TypeUsage::Unknown(unknown) => { - return var_bind(&unknown.name, t2); + return Ok(var_bind(&unknown.name, t2)); } _ => {} } match t2 { ast::TypeUsage::Unknown(unknown) => { - return var_bind(&unknown.name, t1); + return Ok(var_bind(&unknown.name, t1)); } _ => {} } match (t1, t2) { (ast::TypeUsage::Function(f1), ast::TypeUsage::Function(f2)) => { - let mut result = unify(ctx, &*f1.return_type, &*f2.return_type); + let mut result = unify(ctx, &*f1.return_type, &*f2.return_type)?; if f1.arguments.len() != f2.arguments.len() { panic!("Argument lengths don't match"); } @@ -266,17 +286,19 @@ fn unify(ctx: &Context, t1: &ast::TypeUsage, t2: &ast::TypeUsage) -> Substitutio &result, &unify( ctx, - &apply_substitution(ctx, &result, &f1.arguments[i]), - &apply_substitution(ctx, &result, &f2.arguments[i]), - ), - ); + &apply_substitution(ctx, &result, &f1.arguments[i])?, + &apply_substitution(ctx, &result, &f2.arguments[i])?, + )?, + )?; } - return result; + return Ok(result); } _ => {} } - println!("problem:\n{:?}\n{:?}", t1, t2); - panic!("Mismatched unification types"); + return Err(errors::TypingError::TypeMismatch { + type_one: t1.clone(), + type_two: t2.clone(), + }); } fn var_bind(name: &str, t: &ast::TypeUsage) -> SubstitutionMap { @@ -317,7 +339,10 @@ fn contains(t: &ast::TypeUsage, name: &str) -> bool { pub struct TypeChecker {} impl TypeChecker { - pub fn with_module(self: &Self, module: &ast::Module) -> (ast::Module, SubstitutionMap) { + pub fn with_module( + self: &Self, + module: &ast::Module, + ) -> Result<(ast::Module, SubstitutionMap)> { let mut ctx = Context { environment: create_builtins(), impls: HashMap::new(), @@ -362,31 +387,28 @@ impl TypeChecker { } let mut subst = SubstitutionMap::new(); - let result = ast::Module { - items: module - .items - .iter() - .map(|item| match item { - ast::ModuleItem::Function(function) => { - let (func, fn_subst) = self.with_function(&ctx, &subst, function); - subst = compose_substitutions(&ctx, &subst, &fn_subst); - ast::ModuleItem::Function(func) - } - ast::ModuleItem::TypeDeclaration(type_declaration) => { - let (ty_decl, ty_subst) = - self.with_type_declaration(&ctx, type_declaration); - subst = compose_substitutions(&ctx, &subst, &ty_subst); - ast::ModuleItem::TypeDeclaration(ty_decl) - } - ast::ModuleItem::Impl(impl_) => { - let (impl_result, impl_subst) = self.with_impl(&ctx, &subst, impl_); - subst = compose_substitutions(&ctx, &subst, &impl_subst); - ast::ModuleItem::Impl(impl_result) - } - }) - .collect(), - }; - return (result, subst); + let mut items = vec![]; + for item in module.items.iter() { + items.push(match item { + ast::ModuleItem::Function(function) => { + let (func, fn_subst) = self.with_function(&ctx, &subst, function)?; + subst = compose_substitutions(&ctx, &subst, &fn_subst)?; + ast::ModuleItem::Function(func) + } + ast::ModuleItem::TypeDeclaration(type_declaration) => { + let (ty_decl, ty_subst) = self.with_type_declaration(&ctx, type_declaration)?; + subst = compose_substitutions(&ctx, &subst, &ty_subst)?; + ast::ModuleItem::TypeDeclaration(ty_decl) + } + ast::ModuleItem::Impl(impl_) => { + let (impl_result, impl_subst) = self.with_impl(&ctx, &subst, impl_)?; + subst = compose_substitutions(&ctx, &subst, &impl_subst)?; + ast::ModuleItem::Impl(impl_result) + } + }); + } + let result = ast::Module { items: items }; + return Ok((result, subst)); } fn with_function( @@ -394,21 +416,21 @@ impl TypeChecker { ctx: &Context, incoming_substitutions: &SubstitutionMap, function: &ast::Function, - ) -> (ast::Function, SubstitutionMap) { + ) -> Result<(ast::Function, SubstitutionMap)> { // add args to env let mut function_ctx = ctx.set_current_function_return(&function.declaration.return_type.clone()); for arg in function.declaration.arguments.iter() { - type_exists(ctx, &arg.type_); + type_exists(ctx, &arg.type_)?; function_ctx = function_ctx.add_variable(arg.name.name.value.to_string(), &arg.type_.clone()); } - type_exists(ctx, &function.declaration.return_type); + type_exists(ctx, &function.declaration.return_type)?; let (block, substitution) = - self.with_block(&function_ctx, incoming_substitutions, &function.block); + self.with_block(&function_ctx, incoming_substitutions, &function.block)?; let mut substitution = - compose_substitutions(&function_ctx, incoming_substitutions, &substitution); + compose_substitutions(&function_ctx, incoming_substitutions, &substitution)?; match &block.type_ { ast::TypeUsage::Named(named) => { if named.name.name.value != "!" { @@ -419,8 +441,8 @@ impl TypeChecker { &function_ctx, &function.declaration.return_type, &block.type_, - ), - ); + )?, + )?; } } _ => { @@ -431,12 +453,12 @@ impl TypeChecker { &function_ctx, &function.declaration.return_type, &block.type_, - ), - ); + )?, + )?; } } - return ( + return Ok(( ast::Function { declaration: ast::FunctionDeclaration { name: function.declaration.name.clone(), @@ -451,30 +473,30 @@ impl TypeChecker { block: block, }, substitution, - ); + )); } fn with_type_declaration( self: &Self, ctx: &Context, type_declaration: &ast::TypeDeclaration, - ) -> (ast::TypeDeclaration, SubstitutionMap) { + ) -> Result<(ast::TypeDeclaration, SubstitutionMap)> { match type_declaration { ast::TypeDeclaration::Struct(struct_) => { - let result = self.with_struct_declaration(ctx, struct_); - return (ast::TypeDeclaration::Struct(result), SubstitutionMap::new()); + let result = self.with_struct_declaration(ctx, struct_)?; + return Ok((ast::TypeDeclaration::Struct(result), SubstitutionMap::new())); } ast::TypeDeclaration::Primitive(primitive) => { - return ( + return Ok(( ast::TypeDeclaration::Primitive(primitive.clone()), SubstitutionMap::new(), - ); + )); } ast::TypeDeclaration::Alias(alias) => { - return ( + return Ok(( ast::TypeDeclaration::Alias(alias.clone()), SubstitutionMap::new(), - ); + )); } } } @@ -483,21 +505,19 @@ impl TypeChecker { self: &Self, ctx: &Context, struct_: &ast::StructTypeDeclaration, - ) -> ast::StructTypeDeclaration { - return ast::StructTypeDeclaration { + ) -> Result { + let mut fields = vec![]; + for field in struct_.fields.iter() { + type_exists(ctx, &field.type_)?; + fields.push(ast::StructField { + name: field.name.clone(), + type_: field.type_.clone(), + }); + } + return Ok(ast::StructTypeDeclaration { name: struct_.name.clone(), - fields: struct_ - .fields - .iter() - .map(|field| { - type_exists(ctx, &field.type_); - ast::StructField { - name: field.name.clone(), - type_: field.type_.clone(), - } - }) - .collect(), - }; + fields: fields, + }); } fn with_impl( @@ -505,24 +525,22 @@ impl TypeChecker { ctx: &Context, incoming_substitutions: &SubstitutionMap, impl_: &ast::Impl, - ) -> (ast::Impl, SubstitutionMap) { + ) -> Result<(ast::Impl, SubstitutionMap)> { let mut substitutions = incoming_substitutions.clone(); - type_exists(ctx, &ast::TypeUsage::new_named(impl_.struct_name.clone())); - return ( + type_exists(ctx, &ast::TypeUsage::new_named(impl_.struct_name.clone()))?; + let mut functions = vec![]; + for function in impl_.functions.iter() { + let (result, function_subs) = self.with_function(&ctx, &substitutions, function)?; + substitutions = compose_substitutions(ctx, &substitutions, &function_subs)?; + functions.push(result); + } + return Ok(( ast::Impl { struct_name: impl_.struct_name.clone(), - functions: impl_ - .functions - .iter() - .map(|f| { - let (result, function_subs) = self.with_function(&ctx, &substitutions, f); - substitutions = compose_substitutions(ctx, &substitutions, &function_subs); - result - }) - .collect(), + functions: functions, }, substitutions, - ); + )); } fn with_block( @@ -530,7 +548,7 @@ impl TypeChecker { ctx: &Context, incoming_substitutions: &SubstitutionMap, block: &ast::Block, - ) -> (ast::Block, SubstitutionMap) { + ) -> Result<(ast::Block, SubstitutionMap)> { let mut substitutions = incoming_substitutions.clone(); let mut block_ctx = ctx.clone(); // if return it's always never @@ -544,46 +562,43 @@ impl TypeChecker { _ => {} } } - let statements = block - .statements - .iter() - .map(|s| { - let (statement_ctx, result, statement_substitutions) = - self.with_statement(&block_ctx, &substitutions, s); - block_ctx = statement_ctx; - substitutions = - compose_substitutions(&block_ctx, &substitutions, &statement_substitutions); - result - }) - .collect(); + let mut statements = vec![]; + for s in block.statements.iter() { + let (statement_ctx, result, statement_substitutions) = + self.with_statement(&block_ctx, &substitutions, s)?; + block_ctx = statement_ctx; + substitutions = + compose_substitutions(&block_ctx, &substitutions, &statement_substitutions)?; + statements.push(result); + } if !has_return { match block.statements.last().unwrap() { ast::Statement::Expression(expr) => { substitutions = compose_substitutions( &block_ctx, &substitutions, - &unify(&block_ctx, &block.type_, &expr.type_), - ); + &unify(&block_ctx, &block.type_, &expr.type_)?, + )?; } _ => { substitutions = compose_substitutions( &block_ctx, &substitutions, - &unify(&block_ctx, &block.type_, &ast::new_unit()), - ); + &unify(&block_ctx, &block.type_, &ast::new_unit())?, + )?; } } } let result_type = if has_return { ast::new_never() } else { - apply_substitution(&block_ctx, &substitutions, &block.type_) + apply_substitution(&block_ctx, &substitutions, &block.type_)? }; let block_result = ast::Block { statements: statements, type_: result_type, }; - return (block_result, substitutions); + return Ok((block_result, substitutions)); } fn with_statement( @@ -591,33 +606,34 @@ impl TypeChecker { ctx: &Context, incoming_substitutions: &SubstitutionMap, statement: &ast::Statement, - ) -> (Context, ast::Statement, SubstitutionMap) { + ) -> Result<(Context, ast::Statement, SubstitutionMap)> { match statement { ast::Statement::Return(return_statement) => { let (result, subst) = - self.with_return_statement(ctx, incoming_substitutions, return_statement); - let subst = compose_substitutions(ctx, &incoming_substitutions, &subst); - return (ctx.clone(), ast::Statement::Return(result), subst); + self.with_return_statement(ctx, incoming_substitutions, return_statement)?; + let subst = compose_substitutions(ctx, &incoming_substitutions, &subst)?; + return Ok((ctx.clone(), ast::Statement::Return(result), subst)); } ast::Statement::Let(let_statement) => { let (let_ctx, result, subst) = - self.with_let_statement(ctx, incoming_substitutions, let_statement); - let subst = compose_substitutions(ctx, &incoming_substitutions, &subst); - return (let_ctx, ast::Statement::Let(result), subst); + self.with_let_statement(ctx, incoming_substitutions, let_statement)?; + let subst = compose_substitutions(ctx, &incoming_substitutions, &subst)?; + return Ok((let_ctx, ast::Statement::Let(result), subst)); } ast::Statement::Assignment(assignment_statement) => { let (result, subst) = self.with_assignment_statement( ctx, incoming_substitutions, assignment_statement, - ); - let subst = compose_substitutions(ctx, &incoming_substitutions, &subst); - return (ctx.clone(), ast::Statement::Assignment(result), subst); + )?; + let subst = compose_substitutions(ctx, &incoming_substitutions, &subst)?; + return Ok((ctx.clone(), ast::Statement::Assignment(result), subst)); } ast::Statement::Expression(expression) => { - let (result, subst) = self.with_expression(ctx, incoming_substitutions, expression); - let subst = compose_substitutions(ctx, &incoming_substitutions, &subst); - return (ctx.clone(), ast::Statement::Expression(result), subst); + let (result, subst) = + self.with_expression(ctx, incoming_substitutions, expression)?; + let subst = compose_substitutions(ctx, &incoming_substitutions, &subst)?; + return Ok((ctx.clone(), ast::Statement::Expression(result), subst)); } } } @@ -627,9 +643,10 @@ impl TypeChecker { ctx: &Context, incoming_substitutions: &SubstitutionMap, statement: &ast::ReturnStatement, - ) -> (ast::ReturnStatement, SubstitutionMap) { - let (result, subst) = self.with_expression(ctx, incoming_substitutions, &statement.source); - let mut substitution = compose_substitutions(ctx, &incoming_substitutions, &subst); + ) -> Result<(ast::ReturnStatement, SubstitutionMap)> { + let (result, subst) = + self.with_expression(ctx, incoming_substitutions, &statement.source)?; + let mut substitution = compose_substitutions(ctx, &incoming_substitutions, &subst)?; let mut is_never = false; match &result.type_ { ast::TypeUsage::Named(named) => { @@ -647,11 +664,11 @@ impl TypeChecker { ctx, &ctx.current_function_return.as_ref().unwrap(), &result.type_, - ), - ); + )?, + )?; } - return (ast::ReturnStatement { source: result }, substitution); + return Ok((ast::ReturnStatement { source: result }, substitution)); } fn with_let_statement( @@ -659,21 +676,21 @@ impl TypeChecker { ctx: &Context, incoming_substitutions: &SubstitutionMap, statement: &ast::LetStatement, - ) -> (Context, ast::LetStatement, SubstitutionMap) { + ) -> Result<(Context, ast::LetStatement, SubstitutionMap)> { let (result, subst) = - self.with_expression(ctx, incoming_substitutions, &statement.expression); + self.with_expression(ctx, incoming_substitutions, &statement.expression)?; let let_ctx = ctx.add_variable(statement.variable_name.name.value.clone(), &result.type_); let substitution = - compose_substitutions(ctx, &subst, &unify(ctx, &statement.type_, &result.type_)); - return ( + compose_substitutions(ctx, &subst, &unify(ctx, &statement.type_, &result.type_)?)?; + return Ok(( let_ctx, ast::LetStatement { variable_name: statement.variable_name.clone(), expression: result, - type_: apply_substitution(ctx, &substitution, &statement.type_), + type_: apply_substitution(ctx, &substitution, &statement.type_)?, }, substitution, - ); + )); } fn with_assignment_statement( @@ -681,10 +698,10 @@ impl TypeChecker { ctx: &Context, incoming_substitutions: &SubstitutionMap, statement: &ast::AssignmentStatement, - ) -> (ast::AssignmentStatement, SubstitutionMap) { + ) -> Result<(ast::AssignmentStatement, SubstitutionMap)> { let (expr, subst) = - self.with_expression(ctx, incoming_substitutions, &statement.expression); - let mut substitution = compose_substitutions(ctx, &incoming_substitutions, &subst); + self.with_expression(ctx, incoming_substitutions, &statement.expression)?; + let mut substitution = compose_substitutions(ctx, &incoming_substitutions, &subst)?; let result_as = ast::AssignmentStatement { source: match &statement.source { @@ -692,16 +709,16 @@ impl TypeChecker { substitution = compose_substitutions( ctx, &substitution, - &unify(ctx, &variable.type_, &expr.type_), - ); + &unify(ctx, &variable.type_, &expr.type_)?, + )?; ast::AssignmentTarget::Variable(ast::VariableUsage { name: variable.name.clone(), - type_: apply_substitution(ctx, &substitution, &variable.type_), + type_: apply_substitution(ctx, &substitution, &variable.type_)?, }) } ast::AssignmentTarget::StructAttr(struct_attr) => { let (source, subst) = - self.with_expression(ctx, &substitution, &struct_attr.source); + self.with_expression(ctx, &substitution, &struct_attr.source)?; let mut subst = subst.clone(); match &source.type_ { @@ -718,38 +735,46 @@ impl TypeChecker { subst = compose_substitutions( ctx, &subst, - &unify(ctx, &struct_attr.type_, &field.type_), - ); + &unify(ctx, &struct_attr.type_, &field.type_)?, + )?; } } if !found { - panic!("unknown field name") + return Err(errors::TypingError::UnknownFieldName { + identifier: struct_attr.attribute.clone(), + }); } } - _ => panic!("struct getter being used on non-struct"), + _ => { + return Err(errors::TypingError::AttributeOfNonstruct { + identifier: struct_attr.attribute.clone(), + }); + } } } ast::TypeUsage::Function(_) => { - panic!("function used with attr") + return Err(errors::TypingError::NotAStructLiteral { + identifier: struct_attr.attribute.clone(), + }); } _ => {} // skip unifying if struct type is unknown1 } let substitution = compose_substitutions( ctx, - &compose_substitutions(ctx, &substitution, &subst), - &unify(ctx, &struct_attr.type_, &expr.type_), - ); + &compose_substitutions(ctx, &substitution, &subst)?, + &unify(ctx, &struct_attr.type_, &expr.type_)?, + )?; ast::AssignmentTarget::StructAttr(ast::StructGetter { source: source, attribute: struct_attr.attribute.clone(), - type_: apply_substitution(ctx, &substitution, &struct_attr.type_), + type_: apply_substitution(ctx, &substitution, &struct_attr.type_)?, }) } }, expression: expr, }; - return (result_as, substitution); + return Ok((result_as, substitution)); } fn with_expression( @@ -757,130 +782,134 @@ impl TypeChecker { ctx: &Context, incoming_substitutions: &SubstitutionMap, expression: &ast::Expression, - ) -> (ast::Expression, SubstitutionMap) { + ) -> Result<(ast::Expression, SubstitutionMap)> { let mut substitution = incoming_substitutions.clone(); let subexpression = Box::new(match &*expression.subexpression { ast::Subexpression::LiteralInt(literal_int) => { substitution = compose_substitutions( ctx, &substitution, - &unify(ctx, &expression.type_, &literal_int.type_), - ); + &unify(ctx, &expression.type_, &literal_int.type_)?, + )?; ast::Subexpression::LiteralInt(ast::LiteralInt { value: literal_int.value.clone(), - type_: apply_substitution(ctx, &substitution, &literal_int.type_), + type_: apply_substitution(ctx, &substitution, &literal_int.type_)?, }) } ast::Subexpression::LiteralFloat(literal_float) => { substitution = compose_substitutions( ctx, &substitution, - &unify(ctx, &expression.type_, &literal_float.type_), - ); + &unify(ctx, &expression.type_, &literal_float.type_)?, + )?; ast::Subexpression::LiteralFloat(ast::LiteralFloat { value: literal_float.value.clone(), - type_: apply_substitution(ctx, &substitution, &literal_float.type_), + type_: apply_substitution(ctx, &substitution, &literal_float.type_)?, }) } ast::Subexpression::LiteralStruct(literal_struct) => { substitution = compose_substitutions( ctx, &substitution, - &unify(ctx, &expression.type_, &literal_struct.type_), - ); + &unify(ctx, &expression.type_, &literal_struct.type_)?, + )?; let type_declaration = match &ctx.environment[&literal_struct.name.name.value] { NamedEntity::TypeDeclaration(ast::TypeDeclaration::Struct( type_declaration, )) => type_declaration, _ => { - panic!("literal struct used with non struct name") + return Err(errors::TypingError::NotAStructLiteral { + identifier: literal_struct.name.clone(), + }); } }; if type_declaration.fields.len() != literal_struct.fields.len() { - panic!("literal type declaration has mismatched fields"); + return Err(errors::TypingError::StructLiteralFieldsMismatch { + struct_name: literal_struct.name.clone(), + struct_definition_name: type_declaration.name.clone(), + }); + } + let mut fields = vec![]; + for type_field in type_declaration.fields.iter() { + let mut found = false; + let mut field_expression: Option = None; + for field in literal_struct.fields.iter() { + if type_field.name.name.value == field.0.name.value { + found = true; + let (result, subst) = + self.with_expression(ctx, &substitution, &field.1)?; + substitution = compose_substitutions(ctx, &substitution, &subst)?; + substitution = compose_substitutions( + ctx, + &substitution, + &unify(ctx, &type_field.type_, &result.type_)?, + )?; + field_expression = Some(result); + } + } + if !found { + return Err(errors::TypingError::StructLiteralFieldsMismatch { + struct_name: literal_struct.name.clone(), + struct_definition_name: type_field.name.clone(), + }); + } + fields.push((type_field.name.clone(), field_expression.unwrap())); } ast::Subexpression::LiteralStruct(ast::LiteralStruct { name: literal_struct.name.clone(), - fields: type_declaration - .fields - .iter() - .map(|type_field| { - let mut found = false; - let mut field_expression: Option = None; - for field in literal_struct.fields.iter() { - if type_field.name.name.value == field.0.name.value { - found = true; - let (result, subst) = - self.with_expression(ctx, &substitution, &field.1); - substitution = - compose_substitutions(ctx, &substitution, &subst); - substitution = compose_substitutions( - ctx, - &substitution, - &unify(ctx, &type_field.type_, &result.type_), - ); - field_expression = Some(result); - } - } - if !found { - panic!("missing field: {}", &type_field.name.name.value); - } - (type_field.name.clone(), field_expression.unwrap()) - }) - .collect(), - type_: apply_substitution(ctx, &substitution, &literal_struct.type_), + fields: fields, + type_: apply_substitution(ctx, &substitution, &literal_struct.type_)?, }) } ast::Subexpression::FunctionCall(function_call) => { let (source, subst) = - self.with_expression(ctx, &substitution, &function_call.source); - substitution = compose_substitutions(ctx, &substitution, &subst); + self.with_expression(ctx, &substitution, &function_call.source)?; + substitution = compose_substitutions(ctx, &substitution, &subst)?; match &source.type_ { ast::TypeUsage::Function(fn_type) => { substitution = compose_substitutions( ctx, &substitution, - &unify(ctx, &function_call.type_, &*fn_type.return_type), - ); + &unify(ctx, &function_call.type_, &*fn_type.return_type)?, + )?; if function_call.arguments.len() != fn_type.arguments.len() { - panic!("mismatched function argument count"); + return Err(errors::TypingError::ArgumentLengthMismatch {}); } } - ast::TypeUsage::Named(_) => panic!("FunctionCall doesn't have function type."), + ast::TypeUsage::Named(_) => { + return Err(errors::TypingError::FunctionCallNotAFunction {}); + } _ => {} } substitution = compose_substitutions( ctx, &substitution, - &unify(ctx, &expression.type_, &function_call.type_), - ); + &unify(ctx, &expression.type_, &function_call.type_)?, + )?; + let mut arguments = vec![]; + for (i, arg) in function_call.arguments.iter().enumerate() { + let (result, subst) = self.with_expression(ctx, &substitution, arg)?; + substitution = compose_substitutions(ctx, &substitution, &subst)?; + + match &source.type_ { + ast::TypeUsage::Function(fn_type) => { + substitution = compose_substitutions( + ctx, + &substitution, + &unify(ctx, &fn_type.arguments[i], &result.type_)?, + )?; + } + ast::TypeUsage::Named(_) => { + return Err(errors::TypingError::FunctionCallNotAFunction {}); + } + _ => {} + } + arguments.push(result); + } ast::Subexpression::FunctionCall(ast::FunctionCall { source: source.clone(), - arguments: function_call - .arguments - .iter() - .enumerate() - .map(|(i, arg)| { - let (result, subst) = self.with_expression(ctx, &substitution, arg); - substitution = compose_substitutions(ctx, &substitution, &subst); - - match &source.type_ { - ast::TypeUsage::Function(fn_type) => { - substitution = compose_substitutions( - ctx, - &substitution, - &unify(ctx, &fn_type.arguments[i], &result.type_), - ); - } - ast::TypeUsage::Named(_) => { - panic!("FunctionCall doesn't have function type.") - } - _ => {} - } - result - }) - .collect(), - type_: apply_substitution(ctx, &substitution, &function_call.type_), + arguments: arguments, + type_: apply_substitution(ctx, &substitution, &function_call.type_)?, }) } ast::Subexpression::VariableUsage(variable_usage) => { @@ -892,24 +921,24 @@ impl TypeChecker { substitution = compose_substitutions( ctx, &substitution, - &unify(ctx, &variable_usage.type_, &variable), - ); + &unify(ctx, &variable_usage.type_, &variable)?, + )?; substitution = compose_substitutions( ctx, &substitution, - &unify(ctx, &expression.type_, &variable_usage.type_), - ); + &unify(ctx, &expression.type_, &variable_usage.type_)?, + )?; } } ast::Subexpression::VariableUsage(ast::VariableUsage { name: variable_usage.name.clone(), - type_: apply_substitution(ctx, &substitution, &variable_usage.type_), + type_: apply_substitution(ctx, &substitution, &variable_usage.type_)?, }) } ast::Subexpression::StructGetter(struct_getter) => { let (source, subst) = - self.with_expression(ctx, &substitution, &struct_getter.source); - substitution = compose_substitutions(ctx, &substitution, &subst); + self.with_expression(ctx, &substitution, &struct_getter.source)?; + substitution = compose_substitutions(ctx, &substitution, &subst)?; match &source.type_ { ast::TypeUsage::Named(named) => { @@ -924,8 +953,8 @@ impl TypeChecker { substitution = compose_substitutions( ctx, &substitution, - &unify(ctx, &struct_getter.type_, &field.type_), - ); + &unify(ctx, &struct_getter.type_, &field.type_)?, + )?; } } if !found { @@ -981,7 +1010,6 @@ impl TypeChecker { }; } - println!("found: {:?}", &function_type); substitution = compose_substitutions( ctx, &substitution, @@ -989,21 +1017,30 @@ impl TypeChecker { ctx, &struct_getter.type_, &ast::TypeUsage::Function(function_type), - ), - ); + )?, + )?; found = true; } } } if !found { - panic!("unknown field name") + return Err(errors::TypingError::UnknownFieldName { + identifier: struct_getter.attribute.clone(), + }); } } - _ => panic!("struct getter being used on non-struct"), + _ => { + return Err(errors::TypingError::AttributeOfNonstruct { + identifier: struct_getter.attribute.clone(), + }); + // TODO: support builtins + } } } ast::TypeUsage::Function(_) => { - panic!("function used with attr") + return Err(errors::TypingError::NotAStructLiteral { + identifier: struct_getter.attribute.clone(), + }); } _ => {} // skip unifying if struct type is unknown1 } @@ -1011,40 +1048,41 @@ impl TypeChecker { substitution = compose_substitutions( ctx, &substitution, - &unify(ctx, &expression.type_, &struct_getter.type_), - ); + &unify(ctx, &expression.type_, &struct_getter.type_)?, + )?; ast::Subexpression::StructGetter(ast::StructGetter { source: source, attribute: struct_getter.attribute.clone(), - type_: apply_substitution(ctx, &substitution, &struct_getter.type_), + type_: apply_substitution(ctx, &substitution, &struct_getter.type_)?, }) } ast::Subexpression::Block(block) => { - let (result, subst) = self.with_block(ctx, &substitution, &block); - substitution = compose_substitutions(ctx, &substitution, &subst); + let (result, subst) = self.with_block(ctx, &substitution, &block)?; + substitution = compose_substitutions(ctx, &substitution, &subst)?; substitution = compose_substitutions( ctx, &substitution, - &unify(ctx, &expression.type_, &result.type_), - ); + &unify(ctx, &expression.type_, &result.type_)?, + )?; ast::Subexpression::Block(result) } ast::Subexpression::Op(op) => { - let (expr_left, subst_left) = self.with_expression(ctx, &substitution, &op.left); - let (expr_right, subst_right) = self.with_expression(ctx, &substitution, &op.right); - substitution = compose_substitutions(ctx, &substitution, &subst_left); - substitution = compose_substitutions(ctx, &substitution, &subst_right); + let (expr_left, subst_left) = self.with_expression(ctx, &substitution, &op.left)?; + let (expr_right, subst_right) = + self.with_expression(ctx, &substitution, &op.right)?; + substitution = compose_substitutions(ctx, &substitution, &subst_left)?; + substitution = compose_substitutions(ctx, &substitution, &subst_right)?; substitution = compose_substitutions( ctx, &substitution, - &unify(ctx, &expression.type_, &expr_left.type_), - ); + &unify(ctx, &expression.type_, &expr_left.type_)?, + )?; substitution = compose_substitutions( ctx, &substitution, - &unify(ctx, &expression.type_, &expr_right.type_), - ); + &unify(ctx, &expression.type_, &expr_right.type_)?, + )?; ast::Subexpression::Op(ast::Operation { left: expr_left, op: op.op.clone(), @@ -1055,8 +1093,8 @@ impl TypeChecker { let expr = ast::Expression { subexpression: subexpression, - type_: apply_substitution(ctx, &substitution, &expression.type_), + type_: apply_substitution(ctx, &substitution, &expression.type_)?, }; - return (expr, substitution); + return Ok((expr, substitution)); } }