Rotth is a stack based concatenative language highly inspired by Porth
0

Configure Feed

Select the types of activity you want to include in your feed.

Slate-the-non-cringe

Ivan Chinenov (Mar 29, 2024, 7:02 PM +0300) eb8992cd 1f32c569

+2042 -186
+60 -58
Cargo.lock
··· 127 127 128 128 [[package]] 129 129 name = "async-trait" 130 - version = "0.1.78" 130 + version = "0.1.79" 131 131 source = "registry+https://github.com/rust-lang/crates.io-index" 132 - checksum = "461abc97219de0eaaf81fe3ef974a540158f3d079c2ab200f891f1a2ef201e85" 132 + checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" 133 133 dependencies = [ 134 134 "proc-macro2", 135 135 "quote", ··· 149 149 150 150 [[package]] 151 151 name = "autocfg" 152 - version = "1.1.0" 152 + version = "1.2.0" 153 153 source = "registry+https://github.com/rust-lang/crates.io-index" 154 - checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 154 + checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" 155 155 156 156 [[package]] 157 157 name = "axum" 158 - version = "0.7.4" 158 + version = "0.7.5" 159 159 source = "registry+https://github.com/rust-lang/crates.io-index" 160 - checksum = "1236b4b292f6c4d6dc34604bb5120d85c3fe1d1aa596bd5cc52ca054d13e7b9e" 160 + checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" 161 161 dependencies = [ 162 162 "async-trait", 163 163 "axum-core", ··· 179 179 "serde_json", 180 180 "serde_path_to_error", 181 181 "serde_urlencoded", 182 - "sync_wrapper", 182 + "sync_wrapper 1.0.0", 183 183 "tokio", 184 184 "tower", 185 185 "tower-layer", ··· 202 202 "mime", 203 203 "pin-project-lite", 204 204 "rustversion", 205 - "sync_wrapper", 205 + "sync_wrapper 0.1.2", 206 206 "tower-layer", 207 207 "tower-service", 208 208 "tracing", ··· 222 222 223 223 [[package]] 224 224 name = "backtrace" 225 - version = "0.3.69" 225 + version = "0.3.71" 226 226 source = "registry+https://github.com/rust-lang/crates.io-index" 227 - checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" 227 + checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" 228 228 dependencies = [ 229 229 "addr2line", 230 230 "cc", ··· 261 261 262 262 [[package]] 263 263 name = "bytes" 264 - version = "1.5.0" 264 + version = "1.6.0" 265 265 source = "registry+https://github.com/rust-lang/crates.io-index" 266 - checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" 266 + checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" 267 267 268 268 [[package]] 269 269 name = "capstone" ··· 327 327 328 328 [[package]] 329 329 name = "clap" 330 - version = "4.5.3" 330 + version = "4.5.4" 331 331 source = "registry+https://github.com/rust-lang/crates.io-index" 332 - checksum = "949626d00e063efc93b6dca932419ceb5432f99769911c0b995f7e884c778813" 332 + checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" 333 333 dependencies = [ 334 334 "clap_builder", 335 335 "clap_derive", ··· 349 349 350 350 [[package]] 351 351 name = "clap_derive" 352 - version = "4.5.3" 352 + version = "4.5.4" 353 353 source = "registry+https://github.com/rust-lang/crates.io-index" 354 - checksum = "90239a040c80f5e14809ca132ddc4176ab33d5e17e49691793296e3fcb34d72f" 354 + checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" 355 355 dependencies = [ 356 356 "heck 0.5.0", 357 357 "proc-macro2", ··· 640 640 ] 641 641 642 642 [[package]] 643 - name = "h2" 644 - version = "0.4.3" 645 - source = "registry+https://github.com/rust-lang/crates.io-index" 646 - checksum = "51ee2dd2e4f378392eeff5d51618cd9a63166a2513846bbc55f21cfacd9199d4" 647 - dependencies = [ 648 - "bytes", 649 - "fnv", 650 - "futures-core", 651 - "futures-sink", 652 - "futures-util", 653 - "http", 654 - "indexmap", 655 - "slab", 656 - "tokio", 657 - "tokio-util", 658 - "tracing", 659 - ] 660 - 661 - [[package]] 662 643 name = "hashbrown" 663 644 version = "0.12.3" 664 645 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 759 740 "bytes", 760 741 "futures-channel", 761 742 "futures-util", 762 - "h2", 763 743 "http", 764 744 "http-body", 765 745 "httparse", ··· 798 778 799 779 [[package]] 800 780 name = "indexmap" 801 - version = "2.2.5" 781 + version = "2.2.6" 802 782 source = "registry+https://github.com/rust-lang/crates.io-index" 803 - checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" 783 + checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" 804 784 dependencies = [ 805 785 "equivalent", 806 786 "hashbrown 0.14.3", ··· 808 788 809 789 [[package]] 810 790 name = "indoc" 811 - version = "2.0.4" 791 + version = "2.0.5" 812 792 source = "registry+https://github.com/rust-lang/crates.io-index" 813 - checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" 793 + checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" 814 794 815 795 [[package]] 816 796 name = "inkwell" ··· 849 829 name = "itempath" 850 830 version = "0.1.0" 851 831 dependencies = [ 832 + "internment", 852 833 "serde", 853 - "smol_str", 854 834 ] 855 835 856 836 [[package]] 857 837 name = "itoa" 858 - version = "1.0.10" 838 + version = "1.0.11" 859 839 source = "registry+https://github.com/rust-lang/crates.io-index" 860 - checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" 840 + checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" 861 841 862 842 [[package]] 863 843 name = "lazy_static" ··· 920 900 "lazy_static", 921 901 "proc-macro2", 922 902 "quote", 923 - "regex-syntax 0.8.2", 903 + "regex-syntax 0.8.3", 924 904 "syn", 925 905 ] 926 906 ··· 963 943 964 944 [[package]] 965 945 name = "memchr" 966 - version = "2.7.1" 946 + version = "2.7.2" 967 947 source = "registry+https://github.com/rust-lang/crates.io-index" 968 - checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" 948 + checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" 969 949 970 950 [[package]] 971 951 name = "mime" ··· 1149 1129 1150 1130 [[package]] 1151 1131 name = "regex" 1152 - version = "1.10.3" 1132 + version = "1.10.4" 1153 1133 source = "registry+https://github.com/rust-lang/crates.io-index" 1154 - checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" 1134 + checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" 1155 1135 dependencies = [ 1156 1136 "aho-corasick", 1157 1137 "memchr", 1158 1138 "regex-automata 0.4.6", 1159 - "regex-syntax 0.8.2", 1139 + "regex-syntax 0.8.3", 1160 1140 ] 1161 1141 1162 1142 [[package]] ··· 1187 1167 dependencies = [ 1188 1168 "aho-corasick", 1189 1169 "memchr", 1190 - "regex-syntax 0.8.2", 1170 + "regex-syntax 0.8.3", 1191 1171 ] 1192 1172 1193 1173 [[package]] ··· 1204 1184 1205 1185 [[package]] 1206 1186 name = "regex-syntax" 1207 - version = "0.8.2" 1187 + version = "0.8.3" 1208 1188 source = "registry+https://github.com/rust-lang/crates.io-index" 1209 - checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" 1189 + checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" 1210 1190 1211 1191 [[package]] 1212 1192 name = "ropey" ··· 1360 1340 1361 1341 [[package]] 1362 1342 name = "serde_json" 1363 - version = "1.0.114" 1343 + version = "1.0.115" 1364 1344 source = "registry+https://github.com/rust-lang/crates.io-index" 1365 - checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" 1345 + checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" 1366 1346 dependencies = [ 1367 1347 "itoa", 1368 1348 "ryu", ··· 1434 1414 ] 1435 1415 1436 1416 [[package]] 1417 + name = "slate-frontend" 1418 + version = "0.1.0" 1419 + dependencies = [ 1420 + "chumsky", 1421 + "clap", 1422 + "fnv", 1423 + "internment", 1424 + "itempath", 1425 + "logos", 1426 + "smol_str", 1427 + "somok", 1428 + "spanner", 1429 + "thiserror", 1430 + ] 1431 + 1432 + [[package]] 1437 1433 name = "slice-group-by" 1438 1434 version = "0.3.1" 1439 1435 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1512 1508 1513 1509 [[package]] 1514 1510 name = "syn" 1515 - version = "2.0.53" 1511 + version = "2.0.55" 1516 1512 source = "registry+https://github.com/rust-lang/crates.io-index" 1517 - checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" 1513 + checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0" 1518 1514 dependencies = [ 1519 1515 "proc-macro2", 1520 1516 "quote", ··· 1526 1522 version = "0.1.2" 1527 1523 source = "registry+https://github.com/rust-lang/crates.io-index" 1528 1524 checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" 1525 + 1526 + [[package]] 1527 + name = "sync_wrapper" 1528 + version = "1.0.0" 1529 + source = "registry+https://github.com/rust-lang/crates.io-index" 1530 + checksum = "384595c11a4e2969895cad5a8c4029115f5ab956a9e5ef4de79d11a426e5f20c" 1529 1531 1530 1532 [[package]] 1531 1533 name = "target-lexicon" ··· 1580 1582 1581 1583 [[package]] 1582 1584 name = "tokio" 1583 - version = "1.36.0" 1585 + version = "1.37.0" 1584 1586 source = "registry+https://github.com/rust-lang/crates.io-index" 1585 - checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" 1587 + checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" 1586 1588 dependencies = [ 1587 1589 "backtrace", 1588 1590 "bytes",
+4 -1
Cargo.toml
··· 10 10 "simplearena", 11 11 "chisel", 12 12 "itempath", 13 + "slate-frontend", 13 14 ] 14 15 15 16 [workspace.dependencies] 16 - chumsky = "1.0.0-alpha.6" 17 + chumsky = { version = "1.0.0-alpha.6", features = ["pratt"] } 17 18 logos = "0.14" 18 19 ariadne = "0.4" 19 20 clap = { version = "4", features = ["derive"] } ··· 22 23 serde = { version = "1.0.197", features = ["derive"] } 23 24 tokio = { version = "1.36.0", features = ["fs", "rt-multi-thread"] } 24 25 internment = "0.7.4" 26 + somok = "1.5.0" 27 + fnv = "1.0.7"
+1 -1
itempath/Cargo.toml
··· 4 4 edition = "2021" 5 5 6 6 [dependencies] 7 - smol_str.workspace = true 7 + internment.workspace = true 8 8 serde.workspace = true
+26 -31
itempath/src/lib.rs
··· 6 6 ops::{Deref, DerefMut}, 7 7 }; 8 8 9 + use internment::Intern; 9 10 use serde::{de::Visitor, Deserialize, Serialize}; 10 - use smol_str::SmolStr; 11 11 12 12 #[derive(PartialEq, Eq, Hash)] 13 13 #[repr(transparent)] 14 14 pub struct ItemPath { 15 - segments: [SmolStr], 15 + segments: [Intern<String>], 16 16 } 17 17 18 18 impl PartialEq<&ItemPath> for ItemPathBuf { ··· 34 34 } 35 35 36 36 impl ItemPath { 37 - pub fn iter(&'_ self) -> impl Iterator<Item = &'_ SmolStr> { 37 + pub fn iter(&'_ self) -> impl Iterator<Item = &'_ Intern<String>> { 38 38 self.segments.iter() 39 39 } 40 40 41 41 pub fn only(&self) -> Option<&str> { 42 - self.segments.first().map(SmolStr::as_str) 42 + self.segments.first().map(|s| (**s).as_str()) 43 43 } 44 44 45 - pub fn last(&self) -> Option<SmolStr> { 45 + pub fn last(&self) -> Option<Intern<String>> { 46 46 self.segments.last().cloned() 47 - } 48 - 49 - pub fn segment_mut(&mut self, n: usize) -> Option<&mut SmolStr> { 50 - self.segments.get_mut(n) 51 47 } 52 48 53 49 pub fn drop_first(&self) -> Option<&Self> { 54 50 self.segments 55 51 .split_first() 56 52 .and_then(|(_, b)| if b.is_empty() { None } else { Some(b) }) 57 - .map(|s| unsafe { std::mem::transmute::<&[SmolStr], &ItemPath>(s) }) 53 + .map(|s| unsafe { std::mem::transmute::<&[Intern<String>], &ItemPath>(s) }) 58 54 } 59 55 60 56 pub fn parent(&self) -> Option<&ItemPath> { ··· 62 58 None 63 59 } else { 64 60 let segments = &self.segments[..self.segments.len() - 1]; 65 - let parent = unsafe { std::mem::transmute::<&[SmolStr], &ItemPath>(segments) }; 61 + let parent = unsafe { std::mem::transmute::<&[Intern<String>], &ItemPath>(segments) }; 66 62 Some(parent) 67 63 } 68 64 } ··· 73 69 ItemPathBuf { segments } 74 70 } 75 71 76 - pub fn child(&self, segment: impl Into<SmolStr>) -> ItemPathBuf { 72 + pub fn child(&self, segment: impl Into<Intern<String>>) -> ItemPathBuf { 77 73 let mut segments = self.segments.to_owned(); 78 74 segments.push(segment.into()); 79 75 ItemPathBuf { segments } 80 76 } 77 + 78 + pub fn segment_mut(&mut self, segment: usize) -> Option<&mut Intern<String>> { 79 + self.segments.get_mut(segment) 80 + } 81 81 } 82 82 83 83 #[macro_export] 84 84 macro_rules! path { 85 85 ( $( $s:tt )::+ ) => {{ 86 86 let mut path = $crate::ItemPathBuf::new(); 87 - $(path.push(stringify!($s));)* 87 + $(path.push(stringify!($s).to_string());)* 88 88 path 89 89 }}; 90 90 () => {{ ··· 95 95 #[derive(PartialEq, Eq, Hash, Default, Clone)] 96 96 #[repr(transparent)] 97 97 pub struct ItemPathBuf { 98 - segments: Vec<SmolStr>, 98 + segments: Vec<Intern<String>>, 99 99 } 100 100 101 101 struct ITPVisitor; ··· 147 147 where 148 148 S: serde::Serializer, 149 149 { 150 - let separator = SmolStr::from("::"); 150 + let separator = Intern::from("::".to_string()); 151 151 let segments = self.segments.iter(); 152 152 let iter: String = segments 153 153 .intersperse(&separator) ··· 161 161 type Target = ItemPath; 162 162 163 163 fn deref(&self) -> &Self::Target { 164 - unsafe { std::mem::transmute::<&[SmolStr], &ItemPath>(&*self.segments) } 164 + unsafe { std::mem::transmute::<&[Intern<String>], &ItemPath>(&*self.segments) } 165 165 } 166 166 } 167 167 168 168 impl DerefMut for ItemPathBuf { 169 169 fn deref_mut(&mut self) -> &mut Self::Target { 170 - unsafe { std::mem::transmute::<&mut [SmolStr], &mut ItemPath>(&mut *self.segments) } 171 - } 172 - } 173 - 174 - impl<T: Into<SmolStr>> From<Vec<T>> for ItemPathBuf { 175 - fn from(segments: Vec<T>) -> Self { 176 - Self { 177 - segments: segments.into_iter().map(Into::into).collect(), 178 - } 170 + unsafe { std::mem::transmute::<&mut [Intern<String>], &mut ItemPath>(&mut *self.segments) } 179 171 } 180 172 } 181 173 182 - impl From<SmolStr> for ItemPathBuf { 183 - fn from(segment: SmolStr) -> Self { 174 + impl From<Vec<Intern<String>>> for ItemPathBuf { 175 + fn from(segments: Vec<Intern<String>>) -> Self { 184 176 Self { 185 - segments: vec![segment], 177 + segments: segments 178 + .into_iter() 179 + .map(|s| Intern::new(s.as_ref().into())) 180 + .collect(), 186 181 } 187 182 } 188 183 } ··· 207 202 Self::default() 208 203 } 209 204 210 - pub fn push(&mut self, segment: impl Into<SmolStr>) { 211 - self.segments.push(segment.into()) 205 + pub fn push(&mut self, segment: impl AsRef<str>) { 206 + self.segments.push(Intern::new(segment.as_ref().into())) 212 207 } 213 208 } 214 209 215 210 impl Debug for ItemPath { 216 211 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 217 - let separator = SmolStr::from("::"); 212 + let separator = Intern::from("::".to_string()); 218 213 let segments = self.segments.iter(); 219 214 let iter = segments.intersperse(&separator); 220 215 for s in iter {
+1 -1
rotth-analysis/Cargo.toml
··· 8 8 [dependencies] 9 9 somok = "1.5.0" 10 10 simplearena = { path = "../simplearena" } 11 - fnv = "1.0" 11 + fnv.workspace = true 12 12 rotth-lexer = { path = "../rotth-lexer" } 13 13 rotth-parser = { path = "../rotth-parser" } 14 14 spanner = { path = "../spanner" }
+1 -1
rotth-lsp/Cargo.toml
··· 13 13 tokio = { version = "1.17.0", features = ["full"] } 14 14 tower-lsp = { version = "0.20.0" } 15 15 dashmap = "5.1.0" 16 - somok = "1.3.0" 16 + somok.workspace = true 17 17 rotth-parser = { path = "../rotth-parser" } 18 18 rotth-lexer = { path = "../rotth-lexer" } 19 19 spanner = { path = "../spanner" }
+2 -2
rotth-parser/Cargo.toml
··· 11 11 12 12 spanner = { path = "../spanner" } 13 13 rotth-lexer = { path = "../rotth-lexer" } 14 - somok = "1.5.0" 15 - fnv = "1.0" 14 + somok.workspace = true 15 + fnv.workspace = true 16 16 smol_str.workspace = true 17 17 internment.workspace = true 18 18 thiserror.workspace = true
+4 -4
rotth-parser/src/ast.rs
··· 23 23 } 24 24 25 25 #[derive(Debug, Clone)] 26 - pub struct Word(pub SmolStr); 26 + pub struct Word(pub Intern<String>); 27 27 28 28 #[derive(Debug, Clone, Eq, PartialEq)] 29 29 pub enum Punctuation { ··· 44 44 } 45 45 46 46 impl TopLevel { 47 - pub fn name(&self) -> SmolStr { 47 + pub fn name(&self) -> Intern<String> { 48 48 match self { 49 49 TopLevel::Proc(Proc { 50 50 name: ··· 418 418 #[derive(Debug, Clone)] 419 419 pub struct ResolvedFile { 420 420 pub path: ItemPathBuf, 421 - pub ast: FnvHashMap<SmolStr, Spanned<ResolvedItem>>, 421 + pub ast: FnvHashMap<Intern<String>, Spanned<ResolvedItem>>, 422 422 } 423 423 424 424 impl ResolvedFile { ··· 514 514 { 515 515 let name = name.inner.0.clone(); 516 516 let mut path = path.inner; 517 - path.push(name.clone()); 517 + path.push(name); 518 518 if let Some(Spanned { span: _, inner: _ }) = ast.find(&path) { 519 519 if let Some(redefined) = ast.ast.get(&name) { 520 520 errors.push(Error::Redefinition(Redefinition {
+42 -61
rotth-parser/src/ast/parsers.rs
··· 88 88 }) 89 89 } 90 90 91 - pub(super) fn parse_string( 92 - s: &str, 93 - path: Intern<PathBuf>, 94 - ) -> Result<SmolStr, Rich<'_, Token, Span>> { 91 + fn parse_string(s: &str, path: Intern<PathBuf>) -> Result<SmolStr, Rich<'_, Token, Span>> { 95 92 #[derive(Logos)] 96 93 pub enum StrToken { 97 94 #[regex(r"\\.", |l| l.slice().chars().nth(1))] ··· 142 139 } 143 140 } 144 141 145 - pub(super) fn literal_expr<'i, I>( 142 + fn literal_expr<'i, I>( 146 143 ) -> impl Parser<'i, I, Spanned<Expr>, extra::Err<Rich<'i, Token, Span>>> + Clone 147 144 where 148 145 I: ValueInput<'i, Token = Token, Span = Span>, ··· 153 150 }) 154 151 } 155 152 156 - pub(super) fn kw_module<'i, I>( 153 + fn kw_module<'i, I>( 157 154 ) -> impl Parser<'i, I, Spanned<Keyword>, extra::Err<Rich<'i, Token, Span>>> + Clone 158 155 where 159 156 I: ValueInput<'i, Token = Token, Span = Span>, ··· 163 160 } 164 161 } 165 162 166 - pub(super) fn kw_use<'i, I>( 167 - ) -> impl Parser<'i, I, Spanned<Keyword>, extra::Err<Rich<'i, Token, Span>>> + Clone 163 + fn kw_use<'i, I>() -> impl Parser<'i, I, Spanned<Keyword>, extra::Err<Rich<'i, Token, Span>>> + Clone 168 164 where 169 165 I: ValueInput<'i, Token = Token, Span = Span>, 170 166 { ··· 173 169 } 174 170 } 175 171 176 - pub(super) fn kw_from<'i, I>( 172 + fn kw_from<'i, I>( 177 173 ) -> impl Parser<'i, I, Spanned<Keyword>, extra::Err<Rich<'i, Token, Span>>> + Clone 178 174 where 179 175 I: ValueInput<'i, Token = Token, Span = Span>, ··· 183 179 } 184 180 } 185 181 186 - pub(super) fn kw_bind<'i, I>( 182 + fn kw_bind<'i, I>( 187 183 ) -> impl Parser<'i, I, Spanned<Keyword>, extra::Err<Rich<'i, Token, Span>>> + Clone 188 184 where 189 185 I: ValueInput<'i, Token = Token, Span = Span>, ··· 192 188 Token::KwBind = span => Spanned { span: span.span(), inner: Keyword::Bind }, 193 189 } 194 190 } 195 - pub(super) fn kw_while<'i, I>( 191 + fn kw_while<'i, I>( 196 192 ) -> impl Parser<'i, I, Spanned<Keyword>, extra::Err<Rich<'i, Token, Span>>> + Clone 197 193 where 198 194 I: ValueInput<'i, Token = Token, Span = Span>, ··· 201 197 Token::KwWhile = span => Spanned { span: span.span(), inner: Keyword::While }, 202 198 } 203 199 } 204 - pub(super) fn kw_cond<'i, I>( 200 + fn kw_cond<'i, I>( 205 201 ) -> impl Parser<'i, I, Spanned<Keyword>, extra::Err<Rich<'i, Token, Span>>> + Clone 206 202 where 207 203 I: ValueInput<'i, Token = Token, Span = Span>, ··· 210 206 Token::KwCond = span => Spanned { span: span.span(), inner: Keyword::Cond }, 211 207 } 212 208 } 213 - pub(super) fn kw_if<'i, I>( 214 - ) -> impl Parser<'i, I, Spanned<Keyword>, extra::Err<Rich<'i, Token, Span>>> + Clone 209 + fn kw_if<'i, I>() -> impl Parser<'i, I, Spanned<Keyword>, extra::Err<Rich<'i, Token, Span>>> + Clone 215 210 where 216 211 I: ValueInput<'i, Token = Token, Span = Span>, 217 212 { ··· 219 214 Token::KwIf = span => Spanned { span: span.span(), inner: Keyword::If }, 220 215 } 221 216 } 222 - pub(super) fn kw_else<'i, I>( 217 + fn kw_else<'i, I>( 223 218 ) -> impl Parser<'i, I, Spanned<Keyword>, extra::Err<Rich<'i, Token, Span>>> + Clone 224 219 where 225 220 I: ValueInput<'i, Token = Token, Span = Span>, ··· 228 223 Token::KwElse = span => Spanned { span: span.span(), inner: Keyword::Else }, 229 224 } 230 225 } 231 - pub(super) fn kw_do<'i, I>( 232 - ) -> impl Parser<'i, I, Spanned<Keyword>, extra::Err<Rich<'i, Token, Span>>> + Clone 226 + fn kw_do<'i, I>() -> impl Parser<'i, I, Spanned<Keyword>, extra::Err<Rich<'i, Token, Span>>> + Clone 233 227 where 234 228 I: ValueInput<'i, Token = Token, Span = Span>, 235 229 { ··· 237 231 Token::KwDo = span => Spanned { span: span.span(), inner: Keyword::Do }, 238 232 } 239 233 } 240 - pub(super) fn kw_end<'i, I>( 241 - ) -> impl Parser<'i, I, Spanned<Keyword>, extra::Err<Rich<'i, Token, Span>>> + Clone 234 + fn kw_end<'i, I>() -> impl Parser<'i, I, Spanned<Keyword>, extra::Err<Rich<'i, Token, Span>>> + Clone 242 235 where 243 236 I: ValueInput<'i, Token = Token, Span = Span>, 244 237 { ··· 246 239 Token::KwEnd = span => Spanned { span: span.span(), inner: Keyword::End }, 247 240 } 248 241 } 249 - pub(super) fn kw_ret<'i, I>( 250 - ) -> impl Parser<'i, I, Spanned<Keyword>, extra::Err<Rich<'i, Token, Span>>> + Clone 242 + fn kw_ret<'i, I>() -> impl Parser<'i, I, Spanned<Keyword>, extra::Err<Rich<'i, Token, Span>>> + Clone 251 243 where 252 244 I: ValueInput<'i, Token = Token, Span = Span>, 253 245 { ··· 255 247 Token::KwReturn = span => Spanned { span: span.span(), inner: Keyword::Return }, 256 248 } 257 249 } 258 - pub(super) fn kw_cast<'i, I>( 250 + fn kw_cast<'i, I>( 259 251 ) -> impl Parser<'i, I, Spanned<Keyword>, extra::Err<Rich<'i, Token, Span>>> + Clone 260 252 where 261 253 I: ValueInput<'i, Token = Token, Span = Span>, ··· 264 256 Token::KwCast = span => Spanned { span: span.span(), inner: Keyword::Cast }, 265 257 } 266 258 } 267 - pub(super) fn kw_proc<'i, I>( 259 + fn kw_proc<'i, I>( 268 260 ) -> impl Parser<'i, I, Spanned<Keyword>, extra::Err<Rich<'i, Token, Span>>> + Clone 269 261 where 270 262 I: ValueInput<'i, Token = Token, Span = Span>, ··· 274 266 } 275 267 } 276 268 277 - pub(super) fn kw_const<'i, I>( 269 + fn kw_const<'i, I>( 278 270 ) -> impl Parser<'i, I, Spanned<Keyword>, extra::Err<Rich<'i, Token, Span>>> + Clone 279 271 where 280 272 I: ValueInput<'i, Token = Token, Span = Span>, ··· 284 276 } 285 277 } 286 278 287 - pub(super) fn kw_var<'i, I>( 288 - ) -> impl Parser<'i, I, Spanned<Keyword>, extra::Err<Rich<'i, Token, Span>>> + Clone 279 + fn kw_var<'i, I>() -> impl Parser<'i, I, Spanned<Keyword>, extra::Err<Rich<'i, Token, Span>>> + Clone 289 280 where 290 281 I: ValueInput<'i, Token = Token, Span = Span>, 291 282 { ··· 294 285 } 295 286 } 296 287 297 - pub(super) fn kw_struct<'i, I>( 288 + fn kw_struct<'i, I>( 298 289 ) -> impl Parser<'i, I, Spanned<Keyword>, extra::Err<Rich<'i, Token, Span>>> + Clone 299 290 where 300 291 I: ValueInput<'i, Token = Token, Span = Span>, ··· 304 295 } 305 296 } 306 297 307 - pub(super) fn word<'i, I>( 308 - ) -> impl Parser<'i, I, Spanned<Word>, extra::Err<Rich<'i, Token, Span>>> + Clone 298 + fn word<'i, I>() -> impl Parser<'i, I, Spanned<Word>, extra::Err<Rich<'i, Token, Span>>> + Clone 309 299 where 310 300 I: ValueInput<'i, Token = Token, Span = Span>, 311 301 { ··· 315 305 } 316 306 } 317 307 318 - pub(super) fn word_expr<'i, I>( 319 - ) -> impl Parser<'i, I, Spanned<Expr>, extra::Err<Rich<'i, Token, Span>>> + Clone 308 + fn word_expr<'i, I>() -> impl Parser<'i, I, Spanned<Expr>, extra::Err<Rich<'i, Token, Span>>> + Clone 320 309 where 321 310 I: ValueInput<'i, Token = Token, Span = Span>, 322 311 { ··· 326 315 } 327 316 } 328 317 329 - pub(super) fn path<'i, I>( 318 + fn path<'i, I>( 330 319 ) -> impl Parser<'i, I, Spanned<ItemPathBuf>, extra::Err<Rich<'i, Token, Span>>> + Clone 331 320 where 332 321 I: ValueInput<'i, Token = Token, Span = Span>, ··· 344 333 }) 345 334 } 346 335 347 - pub(super) fn path_expr<'i, I>( 348 - ) -> impl Parser<'i, I, Spanned<Expr>, extra::Err<Rich<'i, Token, Span>>> + Clone 336 + fn path_expr<'i, I>() -> impl Parser<'i, I, Spanned<Expr>, extra::Err<Rich<'i, Token, Span>>> + Clone 349 337 where 350 338 I: ValueInput<'i, Token = Token, Span = Span>, 351 339 { ··· 362 350 }) 363 351 } 364 352 365 - pub(super) fn separator<'i, I>( 353 + fn separator<'i, I>( 366 354 ) -> impl Parser<'i, I, Spanned<Punctuation>, extra::Err<Rich<'i, Token, Span>>> + Clone 367 355 where 368 356 I: ValueInput<'i, Token = Token, Span = Span>, ··· 372 360 } 373 361 } 374 362 375 - pub(super) fn read_expr<'i, I>( 376 - ) -> impl Parser<'i, I, Spanned<Expr>, extra::Err<Rich<'i, Token, Span>>> + Clone 363 + fn read_expr<'i, I>() -> impl Parser<'i, I, Spanned<Expr>, extra::Err<Rich<'i, Token, Span>>> + Clone 377 364 where 378 365 I: ValueInput<'i, Token = Token, Span = Span>, 379 366 { ··· 387 374 }) 388 375 } 389 376 390 - pub(super) fn write_expr<'i, I>( 377 + fn write_expr<'i, I>( 391 378 ) -> impl Parser<'i, I, Spanned<Expr>, extra::Err<Rich<'i, Token, Span>>> + Clone 392 379 where 393 380 I: ValueInput<'i, Token = Token, Span = Span>, ··· 402 389 }) 403 390 } 404 391 405 - pub(super) fn var<'i, I>( 406 - ) -> impl Parser<'i, I, Spanned<Var>, extra::Err<Rich<'i, Token, Span>>> + Clone 392 + fn var<'i, I>() -> impl Parser<'i, I, Spanned<Var>, extra::Err<Rich<'i, Token, Span>>> + Clone 407 393 where 408 394 I: ValueInput<'i, Token = Token, Span = Span>, 409 395 { ··· 417 403 }) 418 404 } 419 405 420 - pub(super) fn var_toplevel<'i, I>( 406 + fn var_toplevel<'i, I>( 421 407 ) -> impl Parser<'i, I, Spanned<TopLevel>, extra::Err<Rich<'i, Token, Span>>> + Clone 422 408 where 423 409 I: ValueInput<'i, Token = Token, Span = Span>, ··· 428 414 }) 429 415 } 430 416 431 - pub(super) fn var_expr<'i, I>( 432 - ) -> impl Parser<'i, I, Spanned<Expr>, extra::Err<Rich<'i, Token, Span>>> + Clone 417 + fn var_expr<'i, I>() -> impl Parser<'i, I, Spanned<Expr>, extra::Err<Rich<'i, Token, Span>>> + Clone 433 418 where 434 419 I: ValueInput<'i, Token = Token, Span = Span>, 435 420 { ··· 439 424 }) 440 425 } 441 426 442 - pub(super) fn accessor<'i, I>( 427 + fn accessor<'i, I>( 443 428 ) -> impl Parser<'i, I, Spanned<Punctuation>, extra::Err<Rich<'i, Token, Span>>> + Clone 444 429 where 445 430 I: ValueInput<'i, Token = Token, Span = Span>, ··· 450 435 }) 451 436 } 452 437 453 - pub(super) fn expr<'i: 'd, 'd, I>( 438 + fn expr<'i: 'd, 'd, I>( 454 439 ) -> impl Parser<'i, I, Spanned<Expr>, extra::Err<Rich<'i, Token, Span>>> + Clone + 'd 455 440 where 456 441 I: ValueInput<'i, Token = Token, Span = Span>, ··· 583 568 }) 584 569 } 585 570 586 - pub(super) fn proc_signature<'i, I>( 571 + fn proc_signature<'i, I>( 587 572 ) -> impl Parser<'i, I, Spanned<ProcSignature>, extra::Err<Rich<'i, Token, Span>>> + Clone 588 573 where 589 574 I: ValueInput<'i, Token = Token, Span = Span>, ··· 608 593 }) 609 594 } 610 595 611 - pub(super) fn lbracket<'i, I>( 596 + fn lbracket<'i, I>( 612 597 ) -> impl Parser<'i, I, Spanned<Punctuation>, extra::Err<Rich<'i, Token, Span>>> + Clone 613 598 where 614 599 I: ValueInput<'i, Token = Token, Span = Span>, ··· 618 603 inner: Punctuation::LBracket, 619 604 }) 620 605 } 621 - pub(super) fn rbracket<'i, I>( 606 + fn rbracket<'i, I>( 622 607 ) -> impl Parser<'i, I, Spanned<Punctuation>, extra::Err<Rich<'i, Token, Span>>> + Clone 623 608 where 624 609 I: ValueInput<'i, Token = Token, Span = Span>, ··· 629 614 }) 630 615 } 631 616 632 - pub(super) fn generics<'i, I>( 633 - ) -> impl Parser<'i, I, Spanned<Generics>, extra::Err<Rich<'i, Token, Span>>> 617 + fn generics<'i, I>() -> impl Parser<'i, I, Spanned<Generics>, extra::Err<Rich<'i, Token, Span>>> 634 618 where 635 619 I: ValueInput<'i, Token = Token, Span = Span>, 636 620 { ··· 647 631 }) 648 632 } 649 633 650 - pub(super) fn proc<'i: 'd, 'd, I>( 634 + fn proc<'i: 'd, 'd, I>( 651 635 ) -> impl Parser<'i, I, Spanned<TopLevel>, extra::Err<Rich<'i, Token, Span>>> + 'd 652 636 where 653 637 I: ValueInput<'i, Token = Token, Span = Span>, ··· 675 659 ) 676 660 } 677 661 678 - pub(super) fn const_signature<'i, I>( 662 + fn const_signature<'i, I>( 679 663 ) -> impl Parser<'i, I, Spanned<ConstSignature>, extra::Err<Rich<'i, Token, Span>>> + Clone 680 664 where 681 665 I: ValueInput<'i, Token = Token, Span = Span>, ··· 688 672 }) 689 673 } 690 674 691 - pub(super) fn const_<'i: 'd, 'd, I>( 675 + fn const_<'i: 'd, 'd, I>( 692 676 ) -> impl Parser<'i, I, Spanned<TopLevel>, extra::Err<Rich<'i, Token, Span>>> + Clone + 'd 693 677 where 694 678 I: ValueInput<'i, Token = Token, Span = Span>, ··· 714 698 ) 715 699 } 716 700 717 - pub(super) fn name_type_pair<'i, I>( 701 + fn name_type_pair<'i, I>( 718 702 ) -> impl Parser<'i, I, Spanned<NameTypePair>, extra::Err<Rich<'i, Token, Span>>> + Clone 719 703 where 720 704 I: ValueInput<'i, Token = Token, Span = Span>, ··· 728 712 }) 729 713 } 730 714 731 - pub(super) fn struct_<'i, I>( 732 - ) -> impl Parser<'i, I, Spanned<TopLevel>, extra::Err<Rich<'i, Token, Span>>> 715 + fn struct_<'i, I>() -> impl Parser<'i, I, Spanned<TopLevel>, extra::Err<Rich<'i, Token, Span>>> 733 716 where 734 717 I: ValueInput<'i, Token = Token, Span = Span>, 735 718 { ··· 754 737 ) 755 738 } 756 739 757 - pub(super) fn module<'i, I>( 740 + fn module<'i, I>( 758 741 ) -> impl Parser<'i, I, Spanned<TopLevel>, extra::Err<Rich<'i, Token, Span>>> + Clone 759 742 where 760 743 I: ValueInput<'i, Token = Token, Span = Span>, ··· 767 750 }) 768 751 } 769 752 770 - pub(super) fn use_<'i, I>( 771 - ) -> impl Parser<'i, I, Spanned<TopLevel>, extra::Err<Rich<'i, Token, Span>>> + Clone 753 + fn use_<'i, I>() -> impl Parser<'i, I, Spanned<TopLevel>, extra::Err<Rich<'i, Token, Span>>> + Clone 772 754 where 773 755 I: ValueInput<'i, Token = Token, Span = Span>, 774 756 { ··· 785 767 ) 786 768 } 787 769 788 - pub(super) fn file<'i: 'd, 'd, I>( 789 - ) -> impl Parser<'i, I, Module, extra::Err<Rich<'i, Token, Span>>> + 'd 770 + pub fn file<'i: 'd, 'd, I>() -> impl Parser<'i, I, Module, extra::Err<Rich<'i, Token, Span>>> + 'd 790 771 where 791 772 I: ValueInput<'i, Token = Token, Span = Span>, 792 773 {
+4 -5
rotth-src/examples/simple_bind.rh
··· 1 - proc main: u64 do 2 - 1 bind i: u64 do 3 - i i print print 1 + proc main: i64 do 2 + 1 bind i do 3 + i i + 4 4 end 5 - 0 6 - end 5 + end
+1 -1
rotth/Cargo.toml
··· 9 9 clap.workspace = true 10 10 simplearena = { path = "../simplearena" } 11 11 indoc = "2.0" 12 - fnv = "1.0" 12 + fnv.workspace = true 13 13 rotth-lexer = { path = "../rotth-lexer" } 14 14 rotth-parser = { path = "../rotth-parser" } 15 15 rotth-analysis = { path = "../rotth-analysis" }
+77 -17
rotth/src/emit/cranelift2.rs
··· 4 4 use fnv::FnvHashMap; 5 5 use itempath::ItemPathBuf; 6 6 use rotth_analysis::{ 7 - ctir::{CProc, ConcreteProgram, Intrinsic}, 7 + ctir::{CProc, ConcreteNode, ConcreteProgram, Intrinsic}, 8 8 inference::ReifiedType, 9 - tir::TypedIr, 9 + tir::{Bind, If, TypedIr}, 10 10 }; 11 - use rotth_parser::{ast::Literal, types::Primitive}; 11 + use rotth_parser::{ast::Literal, hir::Binding, types::Primitive}; 12 12 use smol_str::ToSmolStr; 13 + use spanner::Spanned; 13 14 use target_lexicon::Triple; 14 15 15 16 use std::sync::Arc; ··· 105 106 106 107 fn compile_proc( 107 108 path: ItemPathBuf, 108 - proc: CProc, 109 + CProc { 110 + generics: _, 111 + vars, 112 + ins, 113 + outs, 114 + body, 115 + callees, 116 + }: CProc, 109 117 path_to_fid: &FnvHashMap<ItemPathBuf, (FuncId, Signature)>, 110 118 module: &mut ObjectModule, 111 119 ctx: &mut codegen::Context, ··· 116 124 let (fid, sig) = path_to_fid[&path].clone(); 117 125 ctx.func.signature = sig; 118 126 119 - let callees_frefs = proc 120 - .callees 127 + let callees_frefs = callees 121 128 .into_iter() 122 129 .map(|(callee, (ins, outs))| { 123 130 let (fid, _) = &path_to_fid[&callee]; ··· 134 141 135 142 let mut stack: Vec<Value> = Vec::new(); 136 143 stack.extend_from_slice(builder.block_params(entry_b)); 144 + let mut bound_stack = Vec::new(); 137 145 138 - for node in proc.body { 146 + compile_body( 147 + body, 148 + &callees_frefs, 149 + &mut stack, 150 + &mut bound_stack, 151 + &mut builder, 152 + ); 153 + builder.ins().return_(&stack); 154 + builder.finalize(); 155 + 156 + module.define_function(fid, ctx)?; 157 + Ok(()) 158 + } 159 + 160 + fn compile_body( 161 + body: Vec<ConcreteNode>, 162 + callees_frefs: &FnvHashMap<ItemPathBuf, (codegen::ir::FuncRef, usize, usize)>, 163 + stack: &mut Vec<Value>, 164 + bound_stack: &mut Vec<FnvHashMap<ItemPathBuf, Value>>, 165 + builder: &mut FunctionBuilder<'_>, 166 + ) { 167 + for node in body { 139 168 match node.node { 140 169 TypedIr::GVarUse(_) => todo!(), 141 170 TypedIr::LVarUse(_) => todo!(), 142 - TypedIr::BindingUse(_) => todo!(), 171 + TypedIr::BindingUse(name) => { 172 + let val = bound_stack.last().unwrap()[&name]; 173 + stack.push(val); 174 + } 143 175 TypedIr::ConstUse(_) => todo!(), 144 176 TypedIr::Call(path) => { 145 - let (fref, ins, outs) = callees_frefs[&path]; 177 + let (fref, ins, _outs) = callees_frefs[&path]; 146 178 let ins = (0..ins).map(|_| stack.pop().unwrap()).collect::<Vec<_>>(); 147 179 let call = builder.ins().call(fref, &ins); 148 180 for &val in builder.inst_results(call) { ··· 215 247 Intrinsic::Gt => todo!(), 216 248 Intrinsic::Ge => todo!(), 217 249 }, 218 - TypedIr::Bind(_) => todo!(), 250 + TypedIr::Bind(Bind { bindings, body }) => { 251 + let mut bound = FnvHashMap::default(); 252 + for binding in bindings { 253 + match binding.inner { 254 + Binding::Ignore => { 255 + stack.pop(); 256 + } 257 + Binding::Bind { name, ty: _ } => { 258 + let val = stack.pop().unwrap(); 259 + bound.insert(name, val); 260 + } 261 + } 262 + } 263 + bound_stack.push(bound); 264 + compile_body(body, callees_frefs, stack, bound_stack, builder); 265 + bound_stack.pop(); 266 + } 219 267 TypedIr::While(_) => todo!(), 220 - TypedIr::If(_) => todo!(), 268 + TypedIr::If(If { truth, lie }) => { 269 + let val = stack.pop().unwrap(); 270 + let truth_b = builder.create_block(); 271 + let lie_b = builder.create_block(); 272 + let after_b = builder.create_block(); 273 + let mut args = stack.clone(); 274 + args.extend(bound_stack.iter().flat_map(|m| m.values().copied())); 275 + builder.ins().brif(val, truth_b, stack, lie_b, stack); 276 + builder.switch_to_block(truth_b); 277 + let mut stack_t = stack.clone(); 278 + compile_body(truth, callees_frefs, &mut stack_t, bound_stack, builder); 279 + builder.ins().jump(after_b, stack); 280 + if let Some(lie) = lie { 281 + builder.switch_to_block(lie_b); 282 + let mut stack_l = stack.clone(); 283 + compile_body(lie, callees_frefs, &mut stack_l, bound_stack, builder); 284 + } 285 + } 221 286 TypedIr::Cond(_) => todo!(), 222 287 TypedIr::Literal(lit) => { 223 288 let val = match lit { ··· 233 298 } 234 299 TypedIr::IgnorePattern => todo!(), 235 300 TypedIr::Return => { 236 - builder.ins().return_(&stack); 301 + builder.ins().return_(&*stack); 237 302 } 238 303 TypedIr::FieldAccess(_) => todo!(), 239 304 } 240 305 } 241 - builder.ins().return_(&stack); 242 - builder.finalize(); 243 - 244 - module.define_function(fid, ctx)?; 245 - Ok(()) 246 306 }
+17
slate-frontend/Cargo.toml
··· 1 + [package] 2 + name = "slate-frontend" 3 + version = "0.1.0" 4 + edition = "2021" 5 + 6 + [dependencies] 7 + logos.workspace = true 8 + smol_str.workspace = true 9 + internment.workspace = true 10 + somok.workspace = true 11 + fnv.workspace = true 12 + chumsky.workspace = true 13 + thiserror.workspace = true 14 + clap.workspace = true 15 + 16 + spanner = { path = "../spanner" } 17 + itempath = { path = "../itempath" }
+178
slate-frontend/src/lexer.rs
··· 1 + use internment::Intern; 2 + use logos::{Lexer, Logos}; 3 + use smol_str::SmolStr; 4 + use spanner::Span; 5 + use std::path::PathBuf; 6 + 7 + fn to_char(l: &'_ mut Lexer<'_, Token>) -> Option<char> { 8 + l.slice().chars().nth(1) 9 + } 10 + 11 + fn to_bool(l: &'_ mut Lexer<'_, Token>) -> Option<bool> { 12 + match l.slice() { 13 + "true" => Some(true), 14 + "false" => Some(false), 15 + _ => None, 16 + } 17 + } 18 + 19 + fn to_interned_string(l: &'_ mut Lexer<'_, Token>) -> Intern<String> { 20 + Intern::new(l.slice().to_string()) 21 + } 22 + 23 + fn to_smol_str(l: &'_ mut Lexer<'_, Token>) -> SmolStr { 24 + SmolStr::from(l.slice()) 25 + } 26 + 27 + #[derive(Clone, Hash, PartialEq, Eq, Logos)] 28 + pub enum Token { 29 + #[token("&")] 30 + OpAnd, 31 + #[token("*")] 32 + OpMul, 33 + #[token("/")] 34 + OpDiv, 35 + #[token("+")] 36 + OpPlus, 37 + #[token("-")] 38 + OpMinus, 39 + #[token("=")] 40 + OpAssign, 41 + #[token("==")] 42 + OpEq, 43 + #[token(".")] 44 + OpDot, 45 + 46 + #[token(";")] 47 + Semicolon, 48 + #[token(":")] 49 + Colon, 50 + #[token("::")] 51 + DoubleColon, 52 + #[token(",")] 53 + Comma, 54 + 55 + #[regex(r"[_A-Za-z][_A-Za-z0-9]*", to_interned_string)] 56 + Word(Intern<String>), 57 + #[regex("false|true", to_bool)] 58 + Bool(bool), 59 + #[regex(r#""(?:[^"]|\\")*""#, to_smol_str)] 60 + String(SmolStr), 61 + #[regex(r"'.'", to_char)] 62 + Char(char), 63 + #[regex(r"(-?[1-9][0-9]*)|0", to_smol_str)] 64 + Num(SmolStr), 65 + #[token("[")] 66 + LBracket, 67 + #[token("]")] 68 + RBracket, 69 + #[token("(")] 70 + LParen, 71 + #[token(")")] 72 + RParen, 73 + 74 + #[token("module")] 75 + KwModule, 76 + #[token("use")] 77 + KwUse, 78 + #[token("from")] 79 + KwFrom, 80 + #[token("return")] 81 + KwReturn, 82 + #[token("match")] 83 + KwMatch, 84 + #[token("if")] 85 + KwIf, 86 + #[token("else")] 87 + KwElse, 88 + #[token("proc")] 89 + KwProc, 90 + #[token("while")] 91 + KwWhile, 92 + #[token("do")] 93 + KwDo, 94 + #[token("const")] 95 + KwConst, 96 + #[token("static")] 97 + KwStatic, 98 + #[token("let")] 99 + KwLet, 100 + #[token("struct")] 101 + KwStruct, 102 + #[token("cast")] 103 + KwCast, 104 + #[token("end")] 105 + KwEnd, 106 + 107 + #[regex(r";.*\n", logos::skip)] 108 + Comment, 109 + 110 + #[regex(r"\p{Whitespace}+", logos::skip)] 111 + Whitespace, 112 + 113 + Error, 114 + } 115 + 116 + impl std::fmt::Debug for Token { 117 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 118 + match self { 119 + Token::OpAnd => write!(f, "&"), 120 + Token::OpMul => write!(f, "*"), 121 + Token::OpDiv => write!(f, "/"), 122 + Token::OpPlus => write!(f, "+"), 123 + Token::OpMinus => write!(f, "-"), 124 + Token::OpAssign => write!(f, "="), 125 + Token::OpEq => write!(f, "=="), 126 + Token::Semicolon => write!(f, ";"), 127 + Token::Colon => write!(f, ":"), 128 + Token::DoubleColon => write!(f, "::"), 129 + Token::OpDot => write!(f, "."), 130 + Token::Comma => write!(f, ","), 131 + 132 + Token::Word(word) => write!(f, "W({word})"), 133 + Token::Bool(b) => write!(f, "{b}"), 134 + Token::String(str) => write!(f, "{str:?}"), 135 + Token::Char(c) => write!(f, "{c:?}"), 136 + Token::Num(num) => write!(f, "{num}"), 137 + Token::LBracket => write!(f, "["), 138 + Token::RBracket => write!(f, "]"), 139 + Token::LParen => write!(f, "("), 140 + Token::RParen => write!(f, ")"), 141 + Token::KwUse => write!(f, "use"), 142 + Token::KwModule => write!(f, "module"), 143 + Token::KwFrom => write!(f, "from"), 144 + Token::KwReturn => write!(f, "return"), 145 + Token::KwMatch => write!(f, "match"), 146 + Token::KwIf => write!(f, "if"), 147 + Token::KwElse => write!(f, "else"), 148 + Token::KwProc => write!(f, "proc"), 149 + Token::KwWhile => write!(f, "while"), 150 + Token::KwDo => write!(f, "do"), 151 + Token::KwConst => write!(f, "const"), 152 + Token::KwStatic => write!(f, "static"), 153 + Token::KwLet => write!(f, "let"), 154 + Token::KwStruct => write!(f, "struct"), 155 + Token::KwCast => write!(f, "cast"), 156 + Token::KwEnd => write!(f, "end"), 157 + Token::Comment => write!(f, "<comment>"), 158 + Token::Whitespace => write!(f, "<whitespace>"), 159 + Token::Error => write!(f, "<error>"), 160 + } 161 + } 162 + } 163 + 164 + impl std::fmt::Display for Token { 165 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 166 + <Self as std::fmt::Debug>::fmt(self, f) 167 + } 168 + } 169 + 170 + pub fn lex(src: &str, path: Intern<PathBuf>) -> Vec<(Token, Span)> { 171 + Token::lexer(src) 172 + .spanned() 173 + .map(|(t, s)| match t { 174 + Ok(t) => (t, Span::new(path, s.start, s.end)), 175 + Err(()) => (Token::Error, Span::new(path, s.start, s.end)), 176 + }) 177 + .collect() 178 + }
+41
slate-frontend/src/lib.rs
··· 1 + #![feature(box_patterns)] 2 + 3 + pub mod lexer; 4 + pub mod parser; 5 + 6 + use chumsky::error::Rich; 7 + use lexer::Token; 8 + use spanner::Span; 9 + use thiserror::Error; 10 + 11 + #[derive(Debug, Error)] 12 + #[error("{0:?}")] 13 + pub struct ParserError<'i>(pub Vec<Error<'i>>); 14 + 15 + impl<'i> From<Vec<Rich<'i, Token, Span>>> for ParserError<'i> { 16 + fn from(es: Vec<Rich<'i, Token, Span>>) -> Self { 17 + Self(es.into_iter().map(Error::from).collect()) 18 + } 19 + } 20 + #[derive(Debug, Error)] 21 + pub enum Error<'i> { 22 + #[error("{0:?}")] 23 + Parser(Rich<'i, Token, Span>), 24 + #[error("{0:?}")] 25 + Redefinition(#[from] Redefinition), 26 + #[error("UnresolvedInclude {0:?}")] 27 + UnresolvedInclude(Span), 28 + } 29 + 30 + impl<'i> From<Rich<'i, Token, Span>> for Error<'i> { 31 + fn from(e: Rich<'i, Token, Span>) -> Self { 32 + Self::Parser(e) 33 + } 34 + } 35 + 36 + #[derive(Debug, Error)] 37 + #[error("RedefinitionError")] 38 + pub struct Redefinition { 39 + pub redefining_item: Span, 40 + pub redefined_item: Span, 41 + }
+20
slate-frontend/src/main.rs
··· 1 + use std::path::PathBuf; 2 + 3 + use clap::Parser; 4 + use internment::Intern; 5 + 6 + #[derive(Parser)] 7 + struct Args { 8 + source: PathBuf, 9 + } 10 + 11 + fn main() -> std::io::Result<()> { 12 + let args = Args::parse(); 13 + let src = std::fs::read_to_string(&args.source)?; 14 + let tokens = slate_frontend::lexer::lex(&src, Intern::new(args.source)); 15 + println!("{tokens:?}"); 16 + let ast = slate_frontend::parser::parse(tokens).unwrap(); 17 + dbg!(ast); 18 + 19 + Ok(()) 20 + }
+22
slate-frontend/src/parser.rs
··· 1 + use chumsky::{ 2 + input::{Input, Stream}, 3 + Parser, 4 + }; 5 + use spanner::Span; 6 + 7 + use crate::{lexer::Token, ParserError}; 8 + 9 + pub use self::ast::Module; 10 + 11 + mod ast; 12 + mod parsers; 13 + mod types; 14 + 15 + pub fn parse(tokens: Vec<(Token, Span)>) -> Result<Module, ParserError<'static>> { 16 + let len = tokens.len(); 17 + let path = tokens.first().unwrap().1.file; 18 + parsers::file() 19 + .parse(Stream::from_iter(tokens).spanned(Span::point(path, len))) 20 + .into_result() 21 + .map_err(|e| e.into()) 22 + }
+426
slate-frontend/src/parser/ast.rs
··· 1 + use std::fmt::Debug; 2 + 3 + use internment::Intern; 4 + use itempath::ItemPathBuf; 5 + use somok::Either; 6 + use spanner::Spanned; 7 + 8 + use crate::lexer::Token; 9 + 10 + use super::types::Type; 11 + 12 + #[derive(Debug, Clone)] 13 + pub struct Module { 14 + pub procs: Vec<Spanned<Proc>>, 15 + pub consts: Vec<Spanned<Const>>, 16 + pub vars: Vec<Spanned<Static>>, 17 + pub structs: Vec<Spanned<Struct>>, 18 + pub modules: Vec<Spanned<ModuleDef>>, 19 + pub uses: Vec<Spanned<Use>>, 20 + } 21 + 22 + #[derive(Clone)] 23 + pub struct Word(pub Intern<String>); 24 + 25 + impl Debug for Word { 26 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 27 + write!(f, "Word({})", self.0) 28 + } 29 + } 30 + 31 + #[derive(Debug, Clone, Eq, PartialEq)] 32 + pub enum Punctuation { 33 + LBracket, 34 + RBracket, 35 + LParen, 36 + RParen, 37 + And, 38 + Mul, 39 + Div, 40 + Plus, 41 + Minus, 42 + Assign, 43 + Eq, 44 + Semicolon, 45 + Colon, 46 + DoubleColon, 47 + Dot, 48 + } 49 + 50 + #[derive(Clone)] 51 + pub enum TopLevel { 52 + Proc(Proc), 53 + Const(Const), 54 + Var(Static), 55 + Struct(Struct), 56 + Use(Use), 57 + Module(ModuleDef), 58 + } 59 + 60 + impl TopLevel { 61 + pub fn name(&self) -> Intern<String> { 62 + match self { 63 + TopLevel::Proc(Proc { 64 + name: 65 + Spanned { 66 + span: _, 67 + inner: Word(name), 68 + }, 69 + .. 70 + }) => *name, 71 + TopLevel::Const(Const { 72 + name: 73 + Spanned { 74 + span: _, 75 + inner: Word(name), 76 + }, 77 + .. 78 + }) => *name, 79 + TopLevel::Var(Static { 80 + name: 81 + Spanned { 82 + span: _, 83 + inner: Word(name), 84 + }, 85 + .. 86 + }) => *name, 87 + TopLevel::Struct(Struct { 88 + name: 89 + Spanned { 90 + span: _, 91 + inner: Word(name), 92 + }, 93 + .. 94 + }) => *name, 95 + TopLevel::Use(Use { 96 + use_: _, 97 + name: 98 + Spanned { 99 + span: _, 100 + inner: Word(name), 101 + }, 102 + from: _, 103 + path: _, 104 + }) => *name, 105 + TopLevel::Module(ModuleDef { 106 + module: _, 107 + name: 108 + Spanned { 109 + span: _, 110 + inner: Word(name), 111 + }, 112 + }) => *name, 113 + } 114 + } 115 + } 116 + 117 + impl Debug for TopLevel { 118 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 119 + match self { 120 + TopLevel::Proc(arg0) => arg0.fmt(f), 121 + TopLevel::Const(arg0) => arg0.fmt(f), 122 + TopLevel::Var(arg0) => arg0.fmt(f), 123 + TopLevel::Struct(arg0) => arg0.fmt(f), 124 + TopLevel::Use(arg0) => arg0.fmt(f), 125 + TopLevel::Module(arg0) => arg0.fmt(f), 126 + } 127 + } 128 + } 129 + 130 + #[derive(Debug, Clone)] 131 + pub struct Proc { 132 + pub proc: Spanned<Keyword>, 133 + pub generics: Option<Spanned<Generics>>, 134 + pub name: Spanned<Word>, 135 + pub signature: Spanned<ProcSignature>, 136 + pub do_: Spanned<Keyword>, 137 + pub body: Vec<Spanned<Expr>>, 138 + pub end: Spanned<Keyword>, 139 + } 140 + 141 + #[derive(Debug, Clone, Hash, PartialEq, Eq)] 142 + pub enum Keyword { 143 + Module, 144 + Use, 145 + From, 146 + Return, 147 + Match, 148 + If, 149 + Else, 150 + Proc, 151 + While, 152 + Do, 153 + Let, 154 + Const, 155 + Static, 156 + Struct, 157 + Cast, 158 + End, 159 + } 160 + 161 + impl std::fmt::Display for Keyword { 162 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 163 + Debug::fmt(self, f) 164 + } 165 + } 166 + 167 + #[derive(Debug, Clone)] 168 + pub struct Struct { 169 + pub struct_: Spanned<Keyword>, 170 + pub generics: Option<Spanned<Generics>>, 171 + pub name: Spanned<Word>, 172 + pub do_: Spanned<Keyword>, 173 + pub body: Vec<Spanned<NameTypePair>>, 174 + pub end: Spanned<Keyword>, 175 + } 176 + 177 + #[derive(Debug, Clone)] 178 + pub struct Const { 179 + pub const_: Spanned<Keyword>, 180 + pub name: Spanned<Word>, 181 + pub signature: Spanned<ConstSignature>, 182 + pub do_: Spanned<Keyword>, 183 + pub body: Vec<Spanned<Expr>>, 184 + pub end: Spanned<Keyword>, 185 + } 186 + 187 + #[derive(Debug, Clone)] 188 + pub struct ModuleDef { 189 + pub module: Spanned<Keyword>, 190 + pub name: Spanned<Word>, 191 + } 192 + 193 + #[derive(Debug, Clone)] 194 + pub struct Use { 195 + pub use_: Spanned<Keyword>, 196 + pub name: Spanned<Word>, 197 + pub from: Spanned<Keyword>, 198 + pub path: Spanned<ItemPathBuf>, 199 + } 200 + 201 + #[derive(Debug, Clone)] 202 + pub struct Qualifiers { 203 + pub items: Vec<Spanned<ItemPathBuf>>, 204 + pub from: Spanned<Keyword>, 205 + } 206 + 207 + #[derive(Debug, Clone)] 208 + pub struct Read { 209 + pub read: Spanned<Token>, 210 + pub ty: Spanned<Type>, 211 + } 212 + 213 + #[derive(Debug, Clone)] 214 + pub struct Write { 215 + pub write: Spanned<Token>, 216 + pub ty: Spanned<Type>, 217 + } 218 + 219 + #[derive(Clone)] 220 + pub enum Expr { 221 + Keyword(Keyword), 222 + Type(Type), 223 + 224 + Let(Box<Let>), 225 + 226 + While(While), 227 + 228 + If(If), 229 + Cond(Box<Cond>), 230 + 231 + Cast(Cast), 232 + Read(Read), 233 + Write(Write), 234 + Ref(Box<Unary>), 235 + Deref(Box<Unary>), 236 + 237 + Word(Word), 238 + Path(ItemPathBuf), 239 + 240 + Literal(Literal), 241 + FieldAccess(Box<FieldAccess>), 242 + Add(Box<Binary>), 243 + Sub(Box<Binary>), 244 + Mul(Box<Binary>), 245 + Div(Box<Binary>), 246 + Eq(Box<Binary>), 247 + Assign(Box<Binary>), 248 + Call(Box<Call>), 249 + 250 + Static(Static), 251 + } 252 + 253 + impl Debug for Expr { 254 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 255 + match self { 256 + Expr::Read(r) => write!(f, "@{:?}", r.ty), 257 + Expr::Write(w) => write!(f, "@{:?}", w.ty), 258 + Expr::Keyword(arg0) => arg0.fmt(f), 259 + Expr::Type(arg0) => arg0.fmt(f), 260 + Expr::Let(arg0) => arg0.fmt(f), 261 + Expr::While(arg0) => arg0.fmt(f), 262 + Expr::If(arg0) => arg0.fmt(f), 263 + Expr::Cond(arg0) => arg0.fmt(f), 264 + Expr::Cast(arg0) => arg0.fmt(f), 265 + Expr::Word(arg0) => arg0.fmt(f), 266 + Expr::Path(arg0) => arg0.fmt(f), 267 + Expr::Literal(arg0) => arg0.fmt(f), 268 + Expr::FieldAccess(arg0) => arg0.fmt(f), 269 + Expr::Add(arg0) => arg0.fmt(f), 270 + Expr::Sub(arg0) => arg0.fmt(f), 271 + Expr::Mul(arg0) => arg0.fmt(f), 272 + Expr::Div(arg0) => arg0.fmt(f), 273 + Expr::Eq(arg0) => arg0.fmt(f), 274 + Expr::Assign(arg0) => arg0.fmt(f), 275 + Expr::Static(arg0) => arg0.fmt(f), 276 + Expr::Deref(arg0) => arg0.fmt(f), 277 + Expr::Ref(arg0) => arg0.fmt(f), 278 + Expr::Call(arg0) => arg0.fmt(f), 279 + } 280 + } 281 + } 282 + 283 + #[derive(Debug, Clone)] 284 + pub struct Call { 285 + pub callee: Spanned<Expr>, 286 + pub lparen: Spanned<Punctuation>, 287 + pub args: Vec<Spanned<Expr>>, 288 + pub rparen: Spanned<Punctuation>, 289 + } 290 + 291 + #[derive(Debug, Clone)] 292 + pub struct Binary { 293 + pub left: Spanned<Expr>, 294 + pub op: Spanned<Punctuation>, 295 + pub right: Spanned<Expr>, 296 + } 297 + 298 + #[derive(Debug, Clone)] 299 + pub struct Unary { 300 + pub op: Spanned<Punctuation>, 301 + pub expr: Spanned<Expr>, 302 + } 303 + 304 + #[derive(Debug, Clone)] 305 + pub struct Generics { 306 + pub left_bracket: Spanned<Punctuation>, 307 + pub tys: Vec<Spanned<Word>>, 308 + pub right_bracket: Spanned<Punctuation>, 309 + } 310 + 311 + #[derive(Debug, Clone, Eq, PartialEq)] 312 + pub struct GenericParams { 313 + pub left_bracket: Spanned<Punctuation>, 314 + pub tys: Vec<Spanned<Type>>, 315 + pub right_bracket: Spanned<Punctuation>, 316 + } 317 + 318 + #[derive(Debug, Clone)] 319 + pub struct FieldAccess { 320 + pub reciever: Spanned<Expr>, 321 + pub access: Spanned<Punctuation>, 322 + pub field: Spanned<Word>, 323 + } 324 + 325 + #[derive(Debug, Clone)] 326 + pub struct Static { 327 + pub static_: Spanned<Keyword>, 328 + pub name: Spanned<Word>, 329 + pub sep: Spanned<Punctuation>, 330 + pub ty: Spanned<Type>, 331 + } 332 + 333 + #[derive(Debug, Clone)] 334 + pub struct ConstSignature { 335 + pub sep: Spanned<Punctuation>, 336 + pub tys: Vec<Spanned<Type>>, 337 + } 338 + 339 + #[derive(Debug, Clone)] 340 + pub struct ProcSignature { 341 + pub ins: Vec<Spanned<Type>>, 342 + pub sep: Option<Spanned<Punctuation>>, 343 + pub outs: Option<Vec<Spanned<Type>>>, 344 + } 345 + 346 + #[derive(Debug, Clone)] 347 + pub struct NameTypePair { 348 + pub name: Spanned<Word>, 349 + pub sep: Spanned<Punctuation>, 350 + pub ty: Spanned<Type>, 351 + } 352 + 353 + #[derive(Debug, Clone)] 354 + pub struct While { 355 + pub while_: Spanned<Keyword>, 356 + pub cond: Vec<Spanned<Expr>>, 357 + pub do_: Spanned<Keyword>, 358 + pub body: Vec<Spanned<Expr>>, 359 + pub end: Spanned<Keyword>, 360 + } 361 + 362 + #[derive(Debug, Clone)] 363 + pub struct Cast { 364 + pub cast: Spanned<Keyword>, 365 + pub ty: Spanned<Type>, 366 + } 367 + 368 + #[derive(Debug, Clone)] 369 + pub struct If { 370 + pub if_: Spanned<Keyword>, 371 + pub truth: Vec<Spanned<Expr>>, 372 + pub lie: Option<Else>, 373 + pub end: Spanned<Keyword>, 374 + } 375 + 376 + #[derive(Debug, Clone)] 377 + pub struct Else { 378 + pub else_: Spanned<Keyword>, 379 + pub body: Vec<Spanned<Expr>>, 380 + } 381 + 382 + #[derive(Debug, Clone)] 383 + pub struct Cond { 384 + pub cond: Spanned<Keyword>, 385 + pub pat: Spanned<Expr>, 386 + pub do_: Spanned<Keyword>, 387 + pub body: Vec<Spanned<Expr>>, 388 + pub branches: Vec<Spanned<CondBranch>>, 389 + pub end: Spanned<Keyword>, 390 + } 391 + 392 + #[derive(Debug, Clone)] 393 + pub struct CondBranch { 394 + pub else_: Spanned<Keyword>, 395 + pub pat: Spanned<Expr>, 396 + pub do_: Spanned<Keyword>, 397 + pub body: Vec<Spanned<Expr>>, 398 + } 399 + 400 + #[derive(Debug, Clone)] 401 + pub struct Let { 402 + pub let_: Spanned<Keyword>, 403 + pub pat: Spanned<Word>, 404 + pub assign: Spanned<Punctuation>, 405 + pub body: Spanned<Expr>, 406 + } 407 + #[derive(Clone)] 408 + pub enum Literal { 409 + Bool(bool), 410 + Int(i64), 411 + UInt(u64), 412 + String(Intern<String>), 413 + Char(char), 414 + } 415 + 416 + impl Debug for Literal { 417 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 418 + match self { 419 + Self::Bool(arg0) => arg0.fmt(f), 420 + Self::Int(arg0) => arg0.fmt(f), 421 + Self::UInt(arg0) => arg0.fmt(f), 422 + Self::String(arg0) => arg0.fmt(f), 423 + Self::Char(arg0) => arg0.fmt(f), 424 + } 425 + } 426 + }
+924
slate-frontend/src/parser/parsers.rs
··· 1 + use std::path::PathBuf; 2 + 3 + use chumsky::{input::ValueInput, pratt, prelude::*}; 4 + use internment::Intern; 5 + use itempath::ItemPathBuf; 6 + use logos::Logos; 7 + use spanner::{Span, Spanned}; 8 + 9 + use crate::lexer::Token; 10 + 11 + use super::{ 12 + ast::{ 13 + Binary, Call, Cast, Cond, CondBranch, Const, ConstSignature, Else, Expr, FieldAccess, 14 + GenericParams, Generics, If, Keyword, Let, Literal, Module, ModuleDef, NameTypePair, Proc, 15 + ProcSignature, Punctuation, Read, Static, Struct, TopLevel, Unary, Use, While, Word, 16 + }, 17 + types::{Custom, Primitive, Type}, 18 + }; 19 + 20 + trait RParser<'i, I, O> 21 + where 22 + I: Input<'i, Token = Token, Span = Span>, 23 + Self: Parser<'i, I, Spanned<O>, extra::Err<Rich<'i, Token, Span>>> + Clone, 24 + { 25 + } 26 + 27 + impl<'i, I, O, T> RParser<'i, I, O> for T 28 + where 29 + T: Parser<'i, I, Spanned<O>, extra::Err<Rich<'i, Token, Span>>> + Clone, 30 + I: ValueInput<'i, Token = Token, Span = Span>, 31 + { 32 + } 33 + 34 + fn ty<'i, I>() -> impl RParser<'i, I, Type> 35 + where 36 + I: ValueInput<'i, Token = Token, Span = Span>, 37 + { 38 + recursive(|ty| { 39 + let generic_params = lbracket() 40 + .then(ty.repeated().at_least(1).collect()) 41 + .then(rbracket()) 42 + .map_with(|((left_bracket, tys), right_bracket), span| Spanned { 43 + span: span.span(), 44 + inner: GenericParams { 45 + left_bracket, 46 + tys, 47 + right_bracket, 48 + }, 49 + }); 50 + just(Token::OpAnd) 51 + .repeated() 52 + .collect::<Vec<_>>() 53 + .then(path().then(generic_params.or_not())) 54 + .map_with(|(ptr, (ty, params)), span| { 55 + let mut ty = if let Some(type_name) = ty.inner.only() { 56 + match type_name { 57 + "void" => Type::Primitive(Primitive::Void), 58 + "bool" => Type::Primitive(Primitive::Bool), 59 + "char" => Type::Primitive(Primitive::Char), 60 + 61 + "u64" => Type::Primitive(Primitive::U64), 62 + "u32" => Type::Primitive(Primitive::U32), 63 + "u16" => Type::Primitive(Primitive::U16), 64 + "u8" => Type::Primitive(Primitive::U8), 65 + 66 + "i64" => Type::Primitive(Primitive::I64), 67 + "i32" => Type::Primitive(Primitive::I32), 68 + "i16" => Type::Primitive(Primitive::I16), 69 + "i8" => Type::Primitive(Primitive::I8), 70 + _ => Type::Custom(Custom { 71 + name: ty.inner, 72 + params, 73 + }), 74 + } 75 + } else { 76 + Type::Custom(Custom { 77 + name: ty.inner, 78 + params, 79 + }) 80 + }; 81 + for _ in ptr { 82 + ty = Type::Ptr(Box::new(ty)) 83 + } 84 + 85 + Spanned { 86 + span: span.span(), 87 + inner: ty, 88 + } 89 + }) 90 + }) 91 + } 92 + 93 + fn parse_string(s: &str, path: Intern<PathBuf>) -> Result<Intern<String>, Rich<'_, Token, Span>> { 94 + #[derive(Logos)] 95 + pub enum StrToken { 96 + #[regex(r"\\.", |l| l.slice().chars().nth(1))] 97 + Escaped(char), 98 + #[regex(r#"[^\\"]"#, |l| l.slice().chars().next())] 99 + Char(char), 100 + #[token(r#"""#)] 101 + End, 102 + } 103 + 104 + StrToken::lexer(s) 105 + .spanned() 106 + .filter_map(|(t, s)| match t.ok()? { 107 + StrToken::Escaped(c) => match c { 108 + 'n' => Some(Ok('\n')), 109 + 't' => Some(Ok('\t')), 110 + '"' => Some(Ok('"')), 111 + _ => Some(Err(Rich::custom( 112 + Span::new(path, s.start, s.end), 113 + "Invalid character escape", 114 + ))), 115 + }, 116 + StrToken::Char(c) => Some(Ok(c)), 117 + StrToken::End => None, 118 + }) 119 + .collect::<Result<String, _>>() 120 + .map(Into::into) 121 + } 122 + 123 + fn literal<'i, I>() -> impl RParser<'i, I, Literal> 124 + where 125 + I: ValueInput<'i, Token = Token, Span = Span>, 126 + { 127 + select! { 128 + Token::Bool(b) = span => Spanned { span: span.span(), inner: Literal::Bool(b)}, 129 + Token::Num(n) = span => { 130 + if let Ok(i) = n.parse::<i64>(){ 131 + Spanned{ span: span.span(),inner: Literal::Int(i) } 132 + } 133 + else { 134 + Spanned{ span: span.span(), inner: Literal::UInt(n.parse().unwrap()) } 135 + } 136 + }, 137 + Token::String(s) = span => { 138 + let span: spanner::Span = span.span(); 139 + let s = parse_string(&s, span.context()).ok()?; 140 + Spanned{ span, inner: Literal::String(s) }}, 141 + Token::Char(c) = span => Spanned { span: span.span(), inner: Literal::Char(c) }, 142 + } 143 + } 144 + 145 + fn literal_expr<'i, I>() -> impl RParser<'i, I, Expr> 146 + where 147 + I: ValueInput<'i, Token = Token, Span = Span>, 148 + { 149 + literal().map(|Spanned { span, inner }| Spanned { 150 + span, 151 + inner: Expr::Literal(inner), 152 + }) 153 + } 154 + 155 + fn kw_module<'i, I>() -> impl RParser<'i, I, Keyword> 156 + where 157 + I: ValueInput<'i, Token = Token, Span = Span>, 158 + { 159 + select! { 160 + Token::KwModule = span => Spanned { span: span.span(), inner: Keyword::Module }, 161 + } 162 + } 163 + 164 + fn kw_use<'i, I>() -> impl RParser<'i, I, Keyword> 165 + where 166 + I: ValueInput<'i, Token = Token, Span = Span>, 167 + { 168 + select! { 169 + Token::KwUse= span => Spanned { span: span.span(), inner: Keyword::Use }, 170 + } 171 + } 172 + 173 + fn kw_from<'i, I>() -> impl RParser<'i, I, Keyword> 174 + where 175 + I: ValueInput<'i, Token = Token, Span = Span>, 176 + { 177 + select! { 178 + Token::KwFrom = span => Spanned { span: span.span(), inner: Keyword::From }, 179 + } 180 + } 181 + 182 + fn kw_let<'i, I>() -> impl RParser<'i, I, Keyword> 183 + where 184 + I: ValueInput<'i, Token = Token, Span = Span>, 185 + { 186 + select! { 187 + Token::KwLet = span => Spanned { span: span.span(), inner: Keyword::Let }, 188 + } 189 + } 190 + 191 + fn kw_while<'i, I>() -> impl RParser<'i, I, Keyword> 192 + where 193 + I: ValueInput<'i, Token = Token, Span = Span>, 194 + { 195 + select! { 196 + Token::KwWhile = span => Spanned { span: span.span(), inner: Keyword::While }, 197 + } 198 + } 199 + fn kw_cond<'i, I>() -> impl RParser<'i, I, Keyword> 200 + where 201 + I: ValueInput<'i, Token = Token, Span = Span>, 202 + { 203 + select! { 204 + Token::KwMatch = span => Spanned { span: span.span(), inner: Keyword::Match }, 205 + } 206 + } 207 + fn kw_if<'i, I>() -> impl RParser<'i, I, Keyword> 208 + where 209 + I: ValueInput<'i, Token = Token, Span = Span>, 210 + { 211 + select! { 212 + Token::KwIf = span => Spanned { span: span.span(), inner: Keyword::If }, 213 + } 214 + } 215 + fn kw_else<'i, I>() -> impl RParser<'i, I, Keyword> 216 + where 217 + I: ValueInput<'i, Token = Token, Span = Span>, 218 + { 219 + select! { 220 + Token::KwElse = span => Spanned { span: span.span(), inner: Keyword::Else }, 221 + } 222 + } 223 + fn kw_do<'i, I>() -> impl RParser<'i, I, Keyword> 224 + where 225 + I: ValueInput<'i, Token = Token, Span = Span>, 226 + { 227 + select! { 228 + Token::KwDo = span => Spanned { span: span.span(), inner: Keyword::Do }, 229 + } 230 + } 231 + fn kw_end<'i, I>() -> impl RParser<'i, I, Keyword> 232 + where 233 + I: ValueInput<'i, Token = Token, Span = Span>, 234 + { 235 + select! { 236 + Token::KwEnd = span => Spanned { span: span.span(), inner: Keyword::End }, 237 + } 238 + } 239 + fn kw_ret<'i, I>() -> impl RParser<'i, I, Keyword> 240 + where 241 + I: ValueInput<'i, Token = Token, Span = Span>, 242 + { 243 + select! { 244 + Token::KwReturn = span => Spanned { span: span.span(), inner: Keyword::Return }, 245 + } 246 + } 247 + fn kw_cast<'i, I>() -> impl RParser<'i, I, Keyword> 248 + where 249 + I: ValueInput<'i, Token = Token, Span = Span>, 250 + { 251 + select! { 252 + Token::KwCast = span => Spanned { span: span.span(), inner: Keyword::Cast }, 253 + } 254 + } 255 + fn kw_proc<'i, I>() -> impl RParser<'i, I, Keyword> 256 + where 257 + I: ValueInput<'i, Token = Token, Span = Span>, 258 + { 259 + select! { 260 + Token::KwProc = span => Spanned { span: span.span(), inner: Keyword::Proc }, 261 + } 262 + } 263 + 264 + fn kw_const<'i, I>() -> impl RParser<'i, I, Keyword> 265 + where 266 + I: ValueInput<'i, Token = Token, Span = Span>, 267 + { 268 + select! { 269 + Token::KwConst = span => Spanned { span: span.span(), inner: Keyword::Const }, 270 + } 271 + } 272 + 273 + fn kw_static<'i, I>() -> impl RParser<'i, I, Keyword> 274 + where 275 + I: ValueInput<'i, Token = Token, Span = Span>, 276 + { 277 + select! { 278 + Token::KwStatic = span => Spanned { span: span.span(), inner: Keyword::Static }, 279 + } 280 + } 281 + 282 + fn kw_struct<'i, I>() -> impl RParser<'i, I, Keyword> 283 + where 284 + I: ValueInput<'i, Token = Token, Span = Span>, 285 + { 286 + select! { 287 + Token::KwStruct = span => Spanned { span: span.span(), inner: Keyword::Struct }, 288 + } 289 + } 290 + 291 + fn op_and<'i, I>() -> impl RParser<'i, I, Punctuation> 292 + where 293 + I: ValueInput<'i, Token = Token, Span = Span>, 294 + { 295 + select! { 296 + Token::OpAnd = span => Spanned { span: span.span(), inner: Punctuation::And }, 297 + } 298 + } 299 + 300 + fn op_mul<'i, I>() -> impl RParser<'i, I, Punctuation> 301 + where 302 + I: ValueInput<'i, Token = Token, Span = Span>, 303 + { 304 + select! { 305 + Token::OpMul = span => Spanned { span: span.span(), inner: Punctuation::Mul }, 306 + } 307 + } 308 + 309 + fn op_div<'i, I>() -> impl RParser<'i, I, Punctuation> 310 + where 311 + I: ValueInput<'i, Token = Token, Span = Span>, 312 + { 313 + select! { 314 + Token::OpDiv = span => Spanned { span: span.span(), inner: Punctuation::Div }, 315 + } 316 + } 317 + 318 + fn op_plus<'i, I>() -> impl RParser<'i, I, Punctuation> 319 + where 320 + I: ValueInput<'i, Token = Token, Span = Span>, 321 + { 322 + select! { 323 + Token::OpPlus = span => Spanned { span: span.span(), inner: Punctuation::Plus }, 324 + } 325 + } 326 + 327 + fn op_minus<'i, I>() -> impl RParser<'i, I, Punctuation> 328 + where 329 + I: ValueInput<'i, Token = Token, Span = Span>, 330 + { 331 + select! { 332 + Token::OpMinus = span => Spanned { span: span.span(), inner: Punctuation::Minus }, 333 + } 334 + } 335 + 336 + fn op_assign<'i, I>() -> impl RParser<'i, I, Punctuation> 337 + where 338 + I: ValueInput<'i, Token = Token, Span = Span>, 339 + { 340 + select! { 341 + Token::OpAssign = span => Spanned { span: span.span(), inner: Punctuation::Assign }, 342 + } 343 + } 344 + 345 + fn op_eq<'i, I>() -> impl RParser<'i, I, Punctuation> 346 + where 347 + I: ValueInput<'i, Token = Token, Span = Span>, 348 + { 349 + select! { 350 + Token::OpEq = span => Spanned { span: span.span(), inner: Punctuation::Eq }, 351 + } 352 + } 353 + 354 + fn op_dot<'i, I>() -> impl RParser<'i, I, Punctuation> 355 + where 356 + I: ValueInput<'i, Token = Token, Span = Span>, 357 + { 358 + select! { 359 + Token::OpDot = span => Spanned { span: span.span(), inner: Punctuation::Dot }, 360 + } 361 + } 362 + 363 + fn word<'i, I>() -> impl RParser<'i, I, Word> 364 + where 365 + I: ValueInput<'i, Token = Token, Span = Span>, 366 + { 367 + select! { 368 + Token::Word(w) = span => Spanned { span: span.span(), inner: Word(w) }, 369 + } 370 + } 371 + 372 + fn word_expr<'i, I>() -> impl RParser<'i, I, Expr> 373 + where 374 + I: ValueInput<'i, Token = Token, Span = Span>, 375 + { 376 + select! { 377 + Token::Word(w) = span => Spanned { span: span.span(), inner: Expr::Word(Word(w)) }, 378 + } 379 + } 380 + 381 + fn path<'i, I>() -> impl RParser<'i, I, ItemPathBuf> 382 + where 383 + I: ValueInput<'i, Token = Token, Span = Span>, 384 + { 385 + select! { 386 + Token::Word(w) => w, 387 + } 388 + .separated_by(just(Token::DoubleColon)) 389 + .at_least(1) 390 + .collect::<Vec<_>>() 391 + .map_with(|ws, span| Spanned { 392 + span: span.span(), 393 + inner: ItemPathBuf::from(ws), 394 + }) 395 + } 396 + 397 + fn path_expr<'i, I>() -> impl RParser<'i, I, Expr> 398 + where 399 + I: ValueInput<'i, Token = Token, Span = Span>, 400 + { 401 + select! { 402 + Token::Word(w) => w, 403 + } 404 + .separated_by(just(Token::DoubleColon)) 405 + .at_least(1) 406 + .collect::<Vec<_>>() 407 + .map_with(|ws, span| Spanned { 408 + span: span.span(), 409 + inner: Expr::Path(ItemPathBuf::from(ws)), 410 + }) 411 + } 412 + 413 + fn separator<'i, I>() -> impl RParser<'i, I, Punctuation> 414 + where 415 + I: ValueInput<'i, Token = Token, Span = Span>, 416 + { 417 + select! { 418 + Token::Colon = span => Spanned { span: span.span(), inner: Punctuation::Colon }, 419 + } 420 + } 421 + 422 + fn read_expr<'i, I>() -> impl RParser<'i, I, Expr> 423 + where 424 + I: ValueInput<'i, Token = Token, Span = Span>, 425 + { 426 + select! { 427 + t @ Token::OpMul = span => Spanned { span: span.span(), inner: t }, 428 + } 429 + .then(ty()) 430 + .map_with(|(read, ty), span| Spanned { 431 + span: span.span(), 432 + inner: Expr::Read(Read { read, ty }), 433 + }) 434 + } 435 + 436 + fn static_<'i, I>() -> impl RParser<'i, I, Static> 437 + where 438 + I: ValueInput<'i, Token = Token, Span = Span>, 439 + { 440 + kw_static() 441 + .then(word()) 442 + .then(separator()) 443 + .then(ty()) 444 + .map_with(|(((static_, name), sep), ty), span| Spanned { 445 + span: span.span(), 446 + inner: Static { 447 + static_, 448 + name, 449 + sep, 450 + ty, 451 + }, 452 + }) 453 + } 454 + 455 + fn static_toplevel<'i, I>() -> impl RParser<'i, I, TopLevel> 456 + where 457 + I: ValueInput<'i, Token = Token, Span = Span>, 458 + { 459 + static_().map(|Spanned { span, inner }| Spanned { 460 + span, 461 + inner: TopLevel::Var(inner), 462 + }) 463 + } 464 + 465 + fn static_expr<'i, I>() -> impl RParser<'i, I, Expr> 466 + where 467 + I: ValueInput<'i, Token = Token, Span = Span>, 468 + { 469 + static_().map(|Spanned { span, inner }| Spanned { 470 + span, 471 + inner: Expr::Static(inner), 472 + }) 473 + } 474 + 475 + fn expr<'i: 'd, 'd, I>() -> impl RParser<'i, I, Expr> 476 + where 477 + I: ValueInput<'i, Token = Token, Span = Span>, 478 + { 479 + recursive(|expr| { 480 + let while_ = kw_while() 481 + .then(expr.clone().repeated().collect()) 482 + .then(kw_do()) 483 + .then(expr.clone().repeated().collect()) 484 + .then(kw_end()) 485 + .map_with(|((((while_, cond), do_), body), end), span| Spanned { 486 + span: span.span(), 487 + inner: Expr::While(While { 488 + while_, 489 + cond, 490 + do_, 491 + body, 492 + end, 493 + }), 494 + }); 495 + 496 + let lie = kw_else() 497 + .then(expr.clone().repeated().collect()) 498 + .map(|(else_, body)| Else { else_, body }); 499 + 500 + let if_ = kw_if() 501 + .then(expr.clone().repeated().collect()) 502 + .then(lie.or_not()) 503 + .then(kw_end()) 504 + .map_with(|(((if_, truth), lie), end), span| Spanned { 505 + span: span.span(), 506 + inner: Expr::If(If { 507 + if_, 508 + truth, 509 + lie, 510 + end, 511 + }), 512 + }); 513 + 514 + let cast = kw_cast().then(ty()).map_with(|(cast, ty), span| Spanned { 515 + span: span.span(), 516 + inner: Expr::Cast(Cast { cast, ty }), 517 + }); 518 + 519 + let pat = choice((literal_expr(), word_expr(), path_expr())); 520 + let cond_branch = kw_else() 521 + .then(pat.clone()) 522 + .then(kw_do()) 523 + .then(expr.clone().repeated().collect()) 524 + .map_with(|(((else_, pat), do_), body), span| Spanned { 525 + span: span.span(), 526 + inner: CondBranch { 527 + else_, 528 + pat, 529 + do_, 530 + body, 531 + }, 532 + }); 533 + 534 + let cond = kw_cond() 535 + .then(pat) 536 + .then(kw_do()) 537 + .then(expr.clone().repeated().collect()) 538 + .then(cond_branch.repeated().collect()) 539 + .then(kw_end()) 540 + .map_with( 541 + |(((((cond, pat), do_), body), branches), end), span| Spanned { 542 + span: span.span(), 543 + inner: Expr::Cond(Box::new(Cond { 544 + cond, 545 + pat, 546 + do_, 547 + body, 548 + branches, 549 + end, 550 + })), 551 + }, 552 + ); 553 + 554 + let ret_expr = kw_ret().map(|Spanned { span, inner }| Spanned { 555 + span, 556 + inner: Expr::Keyword(inner), 557 + }); 558 + 559 + let let_ = kw_let() 560 + .then(word()) 561 + .then(op_assign()) 562 + .then(expr.clone()) 563 + .map_with(|(((let_, pat), assign), body), extra| Spanned { 564 + span: extra.span(), 565 + inner: Expr::Let(Box::new(Let { 566 + let_, 567 + pat, 568 + assign, 569 + body, 570 + })), 571 + }); 572 + 573 + let call = lparen() 574 + .then(expr.separated_by(just(Token::Comma)).collect::<Vec<_>>()) 575 + .then(rparen()); 576 + choice(( 577 + literal_expr(), 578 + static_expr(), 579 + path_expr(), 580 + word_expr(), 581 + read_expr(), 582 + let_, 583 + while_, 584 + if_, 585 + cond, 586 + cast, 587 + ret_expr, 588 + )) 589 + .pratt(( 590 + pratt::prefix(1, op_and::<I>(), |op, expr, span| Spanned { 591 + span, 592 + inner: Expr::Ref(Box::new(Unary { op, expr })), 593 + }), 594 + pratt::infix(pratt::left(5), op_mul::<I>(), |left, op, right, span| { 595 + Spanned { 596 + span, 597 + inner: Expr::Mul(Box::new(Binary { left, op, right })), 598 + } 599 + }), 600 + pratt::prefix(1, op_mul::<I>(), |op, expr, span| Spanned { 601 + span, 602 + inner: Expr::Deref(Box::new(Unary { op, expr })), 603 + }), 604 + pratt::infix(pratt::left(5), op_div::<I>(), |left, op, right, span| { 605 + Spanned { 606 + span, 607 + inner: Expr::Div(Box::new(Binary { left, op, right })), 608 + } 609 + }), 610 + pratt::infix(pratt::left(4), op_plus::<I>(), |left, op, right, span| { 611 + Spanned { 612 + span, 613 + inner: Expr::Add(Box::new(Binary { left, op, right })), 614 + } 615 + }), 616 + pratt::infix(pratt::left(4), op_minus::<I>(), |left, op, right, span| { 617 + Spanned { 618 + span, 619 + inner: Expr::Sub(Box::new(Binary { left, op, right })), 620 + } 621 + }), 622 + pratt::infix(pratt::left(3), op_eq::<I>(), |left, op, right, span| { 623 + Spanned { 624 + span, 625 + inner: Expr::Eq(Box::new(Binary { left, op, right })), 626 + } 627 + }), 628 + pratt::infix(pratt::left(3), op_assign::<I>(), |left, op, right, span| { 629 + Spanned { 630 + span, 631 + inner: Expr::Assign(Box::new(Binary { left, op, right })), 632 + } 633 + }), 634 + pratt::postfix(6, op_dot::<I>().then(word()), |expr, (op, field), span| { 635 + Spanned { 636 + span, 637 + inner: Expr::FieldAccess(Box::new(FieldAccess { 638 + reciever: expr, 639 + access: op, 640 + field, 641 + })), 642 + } 643 + }), 644 + pratt::postfix(6, call, |callee, ((lparen, args), rparen), span| Spanned { 645 + span, 646 + inner: Expr::Call(Box::new(Call { 647 + callee, 648 + lparen, 649 + args, 650 + rparen, 651 + })), 652 + }), 653 + )) 654 + }) 655 + } 656 + 657 + fn proc_signature<'i, I>() -> impl RParser<'i, I, ProcSignature> 658 + where 659 + I: ValueInput<'i, Token = Token, Span = Span>, 660 + { 661 + ty().repeated() 662 + .collect::<Vec<_>>() 663 + .then( 664 + separator() 665 + .then(ty().repeated().at_least(1).collect::<Vec<_>>()) 666 + .or_not(), 667 + ) 668 + .map_with(|(ins, maybe_outs), span| { 669 + let (sep, outs) = if let Some((sep, outs)) = maybe_outs { 670 + (Some(sep), Some(outs)) 671 + } else { 672 + (None, None) 673 + }; 674 + Spanned { 675 + span: span.span(), 676 + inner: ProcSignature { ins, sep, outs }, 677 + } 678 + }) 679 + } 680 + 681 + fn lbracket<'i, I>() -> impl RParser<'i, I, Punctuation> 682 + where 683 + I: ValueInput<'i, Token = Token, Span = Span>, 684 + { 685 + just(Token::LBracket).map_with(|_, span| Spanned { 686 + span: span.span(), 687 + inner: Punctuation::LBracket, 688 + }) 689 + } 690 + fn rbracket<'i, I>() -> impl RParser<'i, I, Punctuation> 691 + where 692 + I: ValueInput<'i, Token = Token, Span = Span>, 693 + { 694 + just(Token::RBracket).map_with(|_, span| Spanned { 695 + span: span.span(), 696 + inner: Punctuation::RBracket, 697 + }) 698 + } 699 + 700 + fn lparen<'i, I>() -> impl RParser<'i, I, Punctuation> 701 + where 702 + I: ValueInput<'i, Token = Token, Span = Span>, 703 + { 704 + just(Token::LParen).map_with(|_, span| Spanned { 705 + span: span.span(), 706 + inner: Punctuation::RParen, 707 + }) 708 + } 709 + fn rparen<'i, I>() -> impl RParser<'i, I, Punctuation> 710 + where 711 + I: ValueInput<'i, Token = Token, Span = Span>, 712 + { 713 + just(Token::RParen).map_with(|_, span| Spanned { 714 + span: span.span(), 715 + inner: Punctuation::RParen, 716 + }) 717 + } 718 + 719 + fn generics<'i, I>() -> impl RParser<'i, I, Generics> 720 + where 721 + I: ValueInput<'i, Token = Token, Span = Span>, 722 + { 723 + lbracket() 724 + .then(word().repeated().at_least(1).collect::<Vec<_>>()) 725 + .then(rbracket()) 726 + .map_with(|((left_bracket, tys), right_bracket), span| Spanned { 727 + span: span.span(), 728 + inner: Generics { 729 + left_bracket, 730 + tys, 731 + right_bracket, 732 + }, 733 + }) 734 + } 735 + 736 + fn proc<'i: 'd, 'd, I>() -> impl RParser<'i, I, TopLevel> 737 + where 738 + I: ValueInput<'i, Token = Token, Span = Span>, 739 + { 740 + kw_proc() 741 + .then(generics().or_not()) 742 + .then(word()) 743 + .then(proc_signature()) 744 + .then(kw_do()) 745 + .then(expr().repeated().collect::<Vec<_>>()) 746 + .then(kw_end()) 747 + .map_with( 748 + |((((((proc, generics), name), signature), do_), body), end), span| Spanned { 749 + span: span.span(), 750 + inner: TopLevel::Proc(Proc { 751 + proc, 752 + generics, 753 + name, 754 + signature, 755 + do_, 756 + body, 757 + end, 758 + }), 759 + }, 760 + ) 761 + } 762 + 763 + fn const_signature<'i, I>() -> impl RParser<'i, I, ConstSignature> 764 + where 765 + I: ValueInput<'i, Token = Token, Span = Span>, 766 + { 767 + separator() 768 + .then(ty().repeated().at_least(1).collect()) 769 + .map_with(|(sep, tys), span| Spanned { 770 + span: span.span(), 771 + inner: ConstSignature { sep, tys }, 772 + }) 773 + } 774 + 775 + fn const_<'i: 'd, 'd, I>() -> impl RParser<'i, I, TopLevel> 776 + where 777 + I: ValueInput<'i, Token = Token, Span = Span>, 778 + { 779 + kw_const() 780 + .then(word()) 781 + .then(const_signature()) 782 + .then(kw_do()) 783 + .then(expr().repeated().collect()) 784 + .then(kw_end()) 785 + .map_with( 786 + |(((((const_, name), signature), do_), body), end), span| Spanned { 787 + span: span.span(), 788 + inner: TopLevel::Const(Const { 789 + const_, 790 + name, 791 + signature, 792 + do_, 793 + body, 794 + end, 795 + }), 796 + }, 797 + ) 798 + } 799 + 800 + fn name_type_pair<'i, I>() -> impl RParser<'i, I, NameTypePair> 801 + where 802 + I: ValueInput<'i, Token = Token, Span = Span>, 803 + { 804 + word() 805 + .then(separator()) 806 + .then(ty()) 807 + .map_with(|((name, sep), ty), span| Spanned { 808 + span: span.span(), 809 + inner: NameTypePair { name, sep, ty }, 810 + }) 811 + } 812 + 813 + fn struct_<'i, I>() -> impl RParser<'i, I, TopLevel> 814 + where 815 + I: ValueInput<'i, Token = Token, Span = Span>, 816 + { 817 + kw_struct() 818 + .then(generics().or_not()) 819 + .then(word()) 820 + .then(kw_do()) 821 + .then(name_type_pair().repeated().collect()) 822 + .then(kw_end()) 823 + .map_with( 824 + |(((((struct_, generics), name), do_), body), end), span| Spanned { 825 + span: span.span(), 826 + inner: TopLevel::Struct(Struct { 827 + struct_, 828 + generics, 829 + name, 830 + do_, 831 + body, 832 + end, 833 + }), 834 + }, 835 + ) 836 + } 837 + 838 + fn module<'i, I>() -> impl RParser<'i, I, TopLevel> 839 + where 840 + I: ValueInput<'i, Token = Token, Span = Span>, 841 + { 842 + kw_module() 843 + .then(word()) 844 + .map_with(|(module, name), span| Spanned { 845 + span: span.span(), 846 + inner: TopLevel::Module(ModuleDef { module, name }), 847 + }) 848 + } 849 + 850 + fn use_<'i, I>() -> impl RParser<'i, I, TopLevel> 851 + where 852 + I: ValueInput<'i, Token = Token, Span = Span>, 853 + { 854 + kw_use().then(word().then(kw_from())).then(path()).map_with( 855 + |((use_, (name, from)), path), span| Spanned { 856 + span: span.span(), 857 + inner: TopLevel::Use(Use { 858 + use_, 859 + name, 860 + from, 861 + path, 862 + }), 863 + }, 864 + ) 865 + } 866 + 867 + pub fn file<'i: 'd, 'd, I>() -> impl Parser<'i, I, Module, extra::Err<Rich<'i, Token, Span>>> + 'd 868 + where 869 + I: ValueInput<'i, Token = Token, Span = Span>, 870 + { 871 + choice(( 872 + module(), 873 + proc(), 874 + const_(), 875 + static_toplevel(), 876 + struct_(), 877 + use_(), 878 + )) 879 + .repeated() 880 + .collect() 881 + .then_ignore(end()) 882 + .or(end().to(vec![])) 883 + .map(|items| { 884 + let mut module = Module { 885 + procs: Vec::new(), 886 + consts: Vec::new(), 887 + vars: Vec::new(), 888 + structs: Vec::new(), 889 + modules: Vec::new(), 890 + uses: Vec::new(), 891 + }; 892 + 893 + for item in items { 894 + match item.inner { 895 + TopLevel::Proc(p) => module.procs.push(Spanned { 896 + span: item.span, 897 + inner: p, 898 + }), 899 + TopLevel::Const(c) => module.consts.push(Spanned { 900 + span: item.span, 901 + inner: c, 902 + }), 903 + TopLevel::Var(v) => module.vars.push(Spanned { 904 + span: item.span, 905 + inner: v, 906 + }), 907 + TopLevel::Struct(s) => module.structs.push(Spanned { 908 + span: item.span, 909 + inner: s, 910 + }), 911 + TopLevel::Use(u) => module.uses.push(Spanned { 912 + span: item.span, 913 + inner: u, 914 + }), 915 + TopLevel::Module(m) => module.modules.push(Spanned { 916 + span: item.span, 917 + inner: m, 918 + }), 919 + } 920 + } 921 + 922 + module 923 + }) 924 + }
+178
slate-frontend/src/parser/types.rs
··· 1 + use crate::parser::ast::GenericParams; 2 + use fnv::FnvHashMap; 3 + use itempath::{path, ItemPath, ItemPathBuf}; 4 + use smol_str::SmolStr; 5 + use spanner::Spanned; 6 + use std::fmt::Write; 7 + 8 + #[derive(Clone, Eq, PartialEq)] 9 + pub enum Type { 10 + Ptr(Box<Self>), 11 + Primitive(Primitive), 12 + Custom(Custom), 13 + } 14 + 15 + impl std::fmt::Debug for Type { 16 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 17 + self.type_name().fmt(f) 18 + } 19 + } 20 + 21 + impl Type { 22 + pub fn type_name(&self) -> ItemPathBuf { 23 + match self { 24 + Type::Ptr(box ty) => { 25 + let mut name = ty.type_name(); 26 + if let Some(s) = name.segment_mut(0) { 27 + *s = format!("&>{s}").into(); 28 + } 29 + name 30 + } 31 + Type::Primitive(p) => match p { 32 + Primitive::Void => path!(void), 33 + Primitive::Bool => path!(bool), 34 + Primitive::Char => path!(char), 35 + Primitive::U64 => path!(u64), 36 + Primitive::U32 => path!(u32), 37 + Primitive::U16 => path!(u16), 38 + Primitive::U8 => path!(u8), 39 + Primitive::I64 => path!(i64), 40 + Primitive::I32 => path!(i32), 41 + Primitive::I16 => path!(i16), 42 + Primitive::I8 => path!(i8), 43 + }, 44 + Type::Custom(Custom { name, params }) => { 45 + let mut base = name.clone(); 46 + if let Some(params) = params { 47 + let mut paramstr = String::from("["); 48 + for (i, param) in params.inner.tys.iter().enumerate() { 49 + if i == 0 { 50 + write!(paramstr, "{:?}", param.inner.type_name()).unwrap(); 51 + } else { 52 + write!(paramstr, " {:?}", param.inner.type_name()).unwrap(); 53 + } 54 + } 55 + write!(paramstr, "]").unwrap(); 56 + base.push(paramstr); 57 + } 58 + base 59 + } 60 + } 61 + } 62 + } 63 + 64 + #[derive(Clone, Eq, PartialEq)] 65 + pub struct Custom { 66 + pub name: ItemPathBuf, 67 + pub params: Option<Spanned<GenericParams>>, 68 + } 69 + 70 + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 71 + pub enum Primitive { 72 + Void, 73 + 74 + Bool, 75 + Char, 76 + 77 + U64, 78 + U32, 79 + U16, 80 + U8, 81 + 82 + I64, 83 + I32, 84 + I16, 85 + I8, 86 + } 87 + 88 + impl Primitive { 89 + pub fn size(&self) -> usize { 90 + match self { 91 + Primitive::Void => 0, 92 + Primitive::Bool => 1, 93 + Primitive::Char => 1, 94 + Primitive::U64 => 8, 95 + Primitive::U32 => 4, 96 + Primitive::U16 => 2, 97 + Primitive::U8 => 1, 98 + Primitive::I64 => 8, 99 + Primitive::I32 => 4, 100 + Primitive::I16 => 2, 101 + Primitive::I8 => 1, 102 + } 103 + } 104 + } 105 + 106 + pub struct StructBuilder<'i> { 107 + index: &'i mut StructIndex, 108 + generics: Vec<Spanned<SmolStr>>, 109 + fields: FnvHashMap<SmolStr, Spanned<Type>>, 110 + name: ItemPathBuf, 111 + } 112 + 113 + impl<'i> StructBuilder<'i> { 114 + pub fn field(&mut self, name: SmolStr, ty: Spanned<Type>) -> &mut Self { 115 + self.fields.insert(name, ty); 116 + self 117 + } 118 + 119 + pub fn finish(self) { 120 + let struct_ = Struct { 121 + name: self.name, 122 + generics: self.generics, 123 + fields: self.fields, 124 + }; 125 + self.index.structs.push(struct_); 126 + } 127 + } 128 + 129 + #[derive(Default, Debug, Clone)] 130 + pub struct StructIndex { 131 + structs: Vec<Struct>, 132 + } 133 + 134 + impl StructIndex { 135 + pub fn new_struct( 136 + &'_ mut self, 137 + name: ItemPathBuf, 138 + generics: Vec<Spanned<SmolStr>>, 139 + ) -> StructBuilder<'_> { 140 + StructBuilder { 141 + index: self, 142 + fields: Default::default(), 143 + generics, 144 + name, 145 + } 146 + } 147 + 148 + pub fn get(&self, name: &ItemPath) -> Option<&Struct> { 149 + self.structs.iter().find(|s| s.name == name) 150 + } 151 + } 152 + 153 + impl IntoIterator for StructIndex { 154 + type Item = Struct; 155 + 156 + type IntoIter = std::vec::IntoIter<Self::Item>; 157 + 158 + fn into_iter(self) -> Self::IntoIter { 159 + self.structs.into_iter() 160 + } 161 + } 162 + 163 + impl<'s> IntoIterator for &'s StructIndex { 164 + type Item = &'s Struct; 165 + 166 + type IntoIter = std::slice::Iter<'s, Struct>; 167 + 168 + fn into_iter(self) -> Self::IntoIter { 169 + self.structs.iter() 170 + } 171 + } 172 + 173 + #[derive(Debug, PartialEq, Eq, Clone)] 174 + pub struct Struct { 175 + pub name: ItemPathBuf, 176 + pub generics: Vec<Spanned<SmolStr>>, 177 + pub fields: FnvHashMap<SmolStr, Spanned<Type>>, 178 + }
+9 -3
spanner/src/lib.rs
··· 79 79 impl Debug for Span { 80 80 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 81 81 if f.alternate() { 82 - write!(f, "{:?}[{}..{}]", &self.file, &self.start, &self.end) 82 + write!( 83 + f, 84 + "{}[{}..{}]", 85 + self.file.to_string_lossy(), 86 + &self.start, 87 + &self.end 88 + ) 83 89 } else { 84 90 write!( 85 91 f, 86 - "{:?}[{}..{}]", 87 - self.file.file_name().unwrap(), 92 + "{}[{}..{}]", 93 + self.file.file_name().unwrap().to_string_lossy(), 88 94 &self.start, 89 95 &self.end 90 96 )
+4
test.sl
··· 1 + proc main: i64 do 2 + let foo = 1 + 2.add(3.sub(4 + 5)) 3 + foo = 69 4 + end