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.

Absolutely what. Also a rewrite for parser, hir, and typechecker

Ivan Chinenov (Jun 15, 2022, 12:27 AM +0300) 7a992b71 6f4def00

+4043 -3020
+87 -4
Cargo.lock
··· 63 63 checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 64 64 65 65 [[package]] 66 + name = "beef" 67 + version = "0.5.2" 68 + source = "registry+https://github.com/rust-lang/crates.io-index" 69 + checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" 70 + 71 + [[package]] 66 72 name = "bitflags" 67 73 version = "1.3.2" 68 74 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 337 343 ] 338 344 339 345 [[package]] 346 + name = "logos" 347 + version = "0.12.1" 348 + source = "registry+https://github.com/rust-lang/crates.io-index" 349 + checksum = "bf8b031682c67a8e3d5446840f9573eb7fe26efe7ec8d195c9ac4c0647c502f1" 350 + dependencies = [ 351 + "logos-derive", 352 + ] 353 + 354 + [[package]] 355 + name = "logos-derive" 356 + version = "0.12.1" 357 + source = "registry+https://github.com/rust-lang/crates.io-index" 358 + checksum = "a1d849148dbaf9661a6151d1ca82b13bb4c4c128146a88d05253b38d4e2f496c" 359 + dependencies = [ 360 + "beef", 361 + "fnv", 362 + "proc-macro2", 363 + "quote", 364 + "regex-syntax", 365 + "syn", 366 + ] 367 + 368 + [[package]] 340 369 name = "lsp-types" 341 370 version = "0.92.0" 342 371 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 540 569 ] 541 570 542 571 [[package]] 572 + name = "regex-syntax" 573 + version = "0.6.26" 574 + source = "registry+https://github.com/rust-lang/crates.io-index" 575 + checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" 576 + 577 + [[package]] 543 578 name = "ropey" 544 579 version = "1.4.1" 545 580 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 558 593 "clap", 559 594 "fnv", 560 595 "indoc", 596 + "rotth-lexer", 597 + "rotth-parser", 561 598 "simplearena", 599 + "smol_str", 562 600 "somok", 601 + "spanner", 563 602 "thiserror", 564 603 ] 565 604 566 605 [[package]] 606 + name = "rotth-lexer" 607 + version = "0.1.0" 608 + dependencies = [ 609 + "logos", 610 + "smol_str", 611 + "spanner", 612 + ] 613 + 614 + [[package]] 567 615 name = "rotth-lsp" 568 616 version = "0.1.0" 569 617 dependencies = [ ··· 571 619 "dashmap", 572 620 "ropey", 573 621 "rotth", 622 + "rotth-lexer", 623 + "rotth-parser", 624 + "smol_str", 574 625 "somok", 626 + "spanner", 575 627 "tokio", 576 628 "tower-lsp", 629 + ] 630 + 631 + [[package]] 632 + name = "rotth-parser" 633 + version = "0.1.0" 634 + dependencies = [ 635 + "chumsky", 636 + "fnv", 637 + "logos", 638 + "rotth-lexer", 639 + "smol_str", 640 + "somok", 641 + "spanner", 642 + "thiserror", 577 643 ] 578 644 579 645 [[package]] ··· 656 722 checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" 657 723 658 724 [[package]] 725 + name = "smol_str" 726 + version = "0.1.23" 727 + source = "registry+https://github.com/rust-lang/crates.io-index" 728 + checksum = "7475118a28b7e3a2e157ce0131ba8c5526ea96e90ee601d9f6bb2e286a35ab44" 729 + dependencies = [ 730 + "serde", 731 + ] 732 + 733 + [[package]] 659 734 name = "socket2" 660 735 version = "0.4.4" 661 736 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 670 745 version = "1.5.0" 671 746 source = "registry+https://github.com/rust-lang/crates.io-index" 672 747 checksum = "c761262ff91894bf387ba89f6e8a7ea5adfa1bc643dbeb69b762be391355f1ff" 748 + 749 + [[package]] 750 + name = "spanner" 751 + version = "0.1.0" 752 + dependencies = [ 753 + "ariadne", 754 + "chumsky", 755 + ] 673 756 674 757 [[package]] 675 758 name = "stacker" ··· 724 807 725 808 [[package]] 726 809 name = "thiserror" 727 - version = "1.0.30" 810 + version = "1.0.31" 728 811 source = "registry+https://github.com/rust-lang/crates.io-index" 729 - checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" 812 + checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" 730 813 dependencies = [ 731 814 "thiserror-impl", 732 815 ] 733 816 734 817 [[package]] 735 818 name = "thiserror-impl" 736 - version = "1.0.30" 819 + version = "1.0.31" 737 820 source = "registry+https://github.com/rust-lang/crates.io-index" 738 - checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" 821 + checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" 739 822 dependencies = [ 740 823 "proc-macro2", 741 824 "quote",
+1 -1
Cargo.toml
··· 1 1 [workspace] 2 - members = ["rotth", "rotth-lsp", "simplearena"] 2 + members = ["rotth", "rotth-lexer", "rotth-lsp", "spanner", "simplearena"]
+4
includee.rh
··· 1 + ; struct String do 2 + ; len: u64 3 + ; buf: &>char 4 + ; end
+24
new_tokenizer.rh
··· 1 + ; include "includee.rh" 2 + 3 + ; struct Vec do 4 + ; len: u64 5 + ; buf: &>char 6 + ; end 7 + 8 + ; proc foo &>Vec : u64 do 9 + ; -> len @u64 10 + ; end 11 + 12 + ; proc bur do 13 + ; true if 1 else 2 end 14 + ; end 15 + 16 + const BAR: u64 do 60 9 + end 17 + 18 + proc foo: u64 do 19 + BAR bar 20 + end 21 + 22 + proc [T B] bar T : B do 23 + cast B 24 + end
+11
rotth-lexer/Cargo.toml
··· 1 + [package] 2 + name = "rotth-lexer" 3 + version = "0.1.0" 4 + edition = "2021" 5 + 6 + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 + 8 + [dependencies] 9 + logos = "0.12" 10 + smol_str = "0.1" 11 + spanner = { path = "../spanner" }
+138
rotth-lexer/src/lib.rs
··· 1 + use logos::{Lexer, Logos}; 2 + use smol_str::SmolStr; 3 + use spanner::Span; 4 + use std::path::Path; 5 + 6 + fn to_char(l: &'_ mut Lexer<'_, Token>) -> Option<char> { 7 + l.slice().chars().nth(1) 8 + } 9 + 10 + fn to_bool(l: &'_ mut Lexer<'_, Token>) -> Option<bool> { 11 + match l.slice() { 12 + "true" => Some(true), 13 + "false" => Some(false), 14 + _ => None, 15 + } 16 + } 17 + 18 + fn to_smol_str(l: &'_ mut Lexer<'_, Token>) -> SmolStr { 19 + SmolStr::from(l.slice()) 20 + } 21 + 22 + #[derive(Clone, Hash, PartialEq, Eq, Logos)] 23 + pub enum Token { 24 + #[token("&>")] 25 + Ptr, 26 + #[regex("false|true", to_bool)] 27 + Bool(bool), 28 + #[regex( 29 + r"[()\{\}<>\|\\/!@#$%^*\-=+_?A-Za-z][()\{\}<>\|\\/!@#$%^&*\-=+_?A-Za-z0-9]*", 30 + to_smol_str 31 + )] 32 + Word(SmolStr), 33 + #[regex(r#""(?:[^"]|\\")*""#, to_smol_str)] 34 + String(SmolStr), 35 + #[regex(r"'.'", to_char)] 36 + Char(char), 37 + #[regex(r"[1-9][0-9]*|0", to_smol_str)] 38 + Num(SmolStr), 39 + #[token(":")] 40 + SigSep, 41 + #[token("::")] 42 + PathSep, 43 + #[token("->")] 44 + FieldAccess, 45 + #[token("[")] 46 + LBracket, 47 + #[token("]")] 48 + RBracket, 49 + 50 + #[token("include")] 51 + KwInclude, 52 + #[token("return")] 53 + KwReturn, 54 + #[token("cond")] 55 + KwCond, 56 + #[token("if")] 57 + KwIf, 58 + #[token("else")] 59 + KwElse, 60 + #[token("proc")] 61 + KwProc, 62 + #[token("while")] 63 + KwWhile, 64 + #[token("do")] 65 + KwDo, 66 + #[token("bind")] 67 + KwBind, 68 + #[token("const")] 69 + KwConst, 70 + #[token("mem")] 71 + KwMem, 72 + #[token("var")] 73 + KwVar, 74 + #[token("struct")] 75 + KwStruct, 76 + #[token("cast")] 77 + KwCast, 78 + #[token("end")] 79 + KwEnd, 80 + 81 + #[regex(r";.*\n", logos::skip)] 82 + Comment, 83 + 84 + #[regex(r"\p{Whitespace}+", logos::skip)] 85 + Whitespace, 86 + 87 + #[error] 88 + Error, 89 + } 90 + 91 + impl std::fmt::Debug for Token { 92 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 93 + match self { 94 + Token::Bool(b) => write!(f, "{}", b), 95 + Token::Word(word) => write!(f, "{}", word), 96 + Token::String(str) => write!(f, "{:?}", str), 97 + Token::Char(c) => write!(f, "{:?}", c), 98 + Token::Num(num) => write!(f, "{}", num), 99 + Token::SigSep => write!(f, ":"), 100 + Token::PathSep => write!(f, "::"), 101 + Token::Ptr => write!(f, "&>"), 102 + Token::FieldAccess => write!(f, "->"), 103 + Token::LBracket => write!(f, "{{"), 104 + Token::RBracket => write!(f, "}}"), 105 + Token::KwInclude => write!(f, "include"), 106 + Token::KwReturn => write!(f, "return"), 107 + Token::KwCond => write!(f, "cond"), 108 + Token::KwIf => write!(f, "if"), 109 + Token::KwElse => write!(f, "else"), 110 + Token::KwProc => write!(f, "proc"), 111 + Token::KwWhile => write!(f, "while"), 112 + Token::KwDo => write!(f, "do"), 113 + Token::KwBind => write!(f, "bind"), 114 + Token::KwConst => write!(f, "const"), 115 + Token::KwMem => write!(f, "mem"), 116 + Token::KwVar => write!(f, "var"), 117 + Token::KwStruct => write!(f, "struct"), 118 + Token::KwCast => write!(f, "cast"), 119 + Token::KwEnd => write!(f, "end"), 120 + Token::Comment => write!(f, "Comment"), 121 + Token::Whitespace => write!(f, "WS"), 122 + Token::Error => write!(f, "Error"), 123 + } 124 + } 125 + } 126 + 127 + impl std::fmt::Display for Token { 128 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 129 + <Self as std::fmt::Debug>::fmt(self, f) 130 + } 131 + } 132 + 133 + pub fn lex(src: &str, path: &'static Path) -> Vec<(Token, Span)> { 134 + Token::lexer(src) 135 + .spanned() 136 + .map(|(t, s)| (t, Span::new(path, s.start, s.end))) 137 + .collect() 138 + }
+4
rotth-lsp/Cargo.toml
··· 13 13 tower-lsp = { version = "0.16.0" } 14 14 dashmap = "5.1.0" 15 15 somok = "1.3.0" 16 + rotth-parser = { path = "../rotth-parser" } 17 + rotth-lexer = { path = "../rotth-lexer" } 18 + spanner = { path = "../spanner" } 19 + smol_str = "0.1.23"
+29 -14
rotth-lsp/src/completion.rs
··· 1 - use rotth::ast::TopLevel; 1 + use rotth_parser::ast::*; 2 + use spanner::Spanned; 2 3 3 4 #[derive(Debug)] 4 5 pub enum CompleteCompletionItem { ··· 7 8 Proc(String), 8 9 } 9 10 /// return (need_to_continue_search, founded reference) 10 - pub fn completion(ast: &[TopLevel], ident_offset: usize) -> Vec<CompleteCompletionItem> { 11 + pub fn completion(ast: &[Spanned<TopLevel>], ident_offset: usize) -> Vec<CompleteCompletionItem> { 11 12 let mut res = Vec::default(); 12 13 for item in ast.iter() { 13 - if let TopLevel::Proc(p) = item { 14 - if p.name.span.end < ident_offset { 15 - let name = rotth::coerce_ast!(p.name => REF Word || unreachable!()); 16 - res.push(CompleteCompletionItem::Proc(name.clone())); 14 + match &**item { 15 + TopLevel::Proc(p) => { 16 + if p.name.span.end < ident_offset { 17 + let Spanned { 18 + span: _, 19 + inner: Word(name), 20 + } = &p.name; 21 + res.push(CompleteCompletionItem::Proc(name.to_string())); 22 + } 17 23 } 18 - } else if let TopLevel::Const(c) = item { 19 - if c.name.span.end < ident_offset { 20 - let name = rotth::coerce_ast!(c.name => REF Word || unreachable!()); 21 - res.push(CompleteCompletionItem::Proc(name.clone())); 24 + TopLevel::Const(c) => { 25 + if c.name.span.end < ident_offset { 26 + let Spanned { 27 + span: _, 28 + inner: Word(name), 29 + } = &c.name; 30 + res.push(CompleteCompletionItem::Proc(name.to_string())); 31 + } 22 32 } 23 - } else if let TopLevel::Mem(m) = item { 24 - if m.name.span.end < ident_offset { 25 - let name = rotth::coerce_ast!(m.name => REF Word || unreachable!()); 26 - res.push(CompleteCompletionItem::Proc(name.clone())); 33 + TopLevel::Mem(m) => { 34 + if m.name.span.end < ident_offset { 35 + let Spanned { 36 + span: _, 37 + inner: Word(name), 38 + } = &m.name; 39 + res.push(CompleteCompletionItem::Proc(name.to_string())); 40 + } 27 41 } 42 + _ => (), 28 43 } 29 44 } 30 45 res
+61 -87
rotth-lsp/src/main.rs
··· 1 1 use dashmap::DashMap; 2 2 use ropey::Rope; 3 - use rotth::ast::{parse_no_include, TopLevel}; 4 - use rotth::lexer::lex_string; 3 + use rotth_lexer::lex; 5 4 use rotth_lsp::completion::{completion, CompleteCompletionItem}; 6 5 use rotth_lsp::semantic_token::{semantic_token_from_ast, CompleteSemanticToken, LEGEND_TYPE}; 7 - use somok::Somok; 6 + use rotth_parser::ast::{parse, TopLevel}; 7 + use rotth_parser::ParserError; 8 + use somok::{Leaksome, Somok}; 9 + use spanner::Spanned; 8 10 use std::collections::HashSet; 9 11 use std::path::{Path, PathBuf}; 10 12 use tokio::io::AsyncReadExt; ··· 21 23 #[derive(Debug)] 22 24 struct Backend { 23 25 client: Client, 24 - ast_map: DashMap<PathBuf, Vec<TopLevel>>, 26 + ast_map: DashMap<PathBuf, Vec<Spanned<TopLevel>>>, 25 27 include_map: DashMap<PathBuf, HashSet<PathBuf>>, 26 28 semantic_token_map: DashMap<PathBuf, Vec<CompleteSemanticToken>>, 27 29 document_map: DashMap<PathBuf, Rope>, 28 30 } 29 31 30 - impl Backend { 32 + impl<'s> Backend { 31 33 async fn parse_file( 32 34 &self, 33 35 parent: Option<&Path>, ··· 58 60 let includes: Vec<(PathBuf, PathBuf)> = ast 59 61 .iter() 60 62 .filter_map(|i| { 61 - if let TopLevel::Include(inc) = &i { 62 - let parent = i.span().file; 63 - let path = parent.parent().unwrap().join(inc.path()); 63 + if let TopLevel::Include(inc) = &**i { 64 + let parent = i.span.file.to_owned(); 65 + let path = parent.parent().unwrap().join(&*inc.path); 64 66 self.include_map 65 - .entry(parent) 67 + .entry(parent.clone()) 66 68 .or_insert_with(Default::default) 67 - .insert(path); 68 - (i.span().file, inc.path().to_owned()).some() 69 + .insert(path.clone()); 70 + (parent, path).some() 69 71 } else { 70 72 None 71 73 } ··· 76 78 includes.okay() 77 79 } 78 80 79 - async fn parse_text(&self, params: TextDocument) -> Option<Vec<TopLevel>> { 81 + async fn parse_text(&self, params: TextDocument) -> Option<Vec<Spanned<TopLevel>>> { 80 82 let rope = ropey::Rope::from_str(&params.text); 81 83 self.document_map 82 84 .insert(params.uri.to_file_path().unwrap(), rope.clone()); 85 + let path = &*params.uri.to_file_path().unwrap().into_boxed_path().leak(); 83 86 84 - let tokens = match lex_string(params.text, params.uri.to_file_path().unwrap()) { 85 - Ok(tokens) => tokens, 86 - Err(_e) => { 87 - // self.client 88 - // .log_message(MessageType::ERROR, format!("{:?}", e)) 89 - // .await; 90 - return None; 91 - } // TODO! 92 - }; 93 - let ast = match parse_no_include(tokens) { 87 + let tokens = lex(&params.text, path); 88 + let ast = match parse(tokens) { 94 89 Ok(ast) => ast, 95 - Err(e) => { 96 - let _diagnostics = match e { 97 - rotth::Error::Parser(errors) => errors 98 - .into_iter() 99 - .filter_map(|item| { 100 - let (message, span) = match item.reason() { 90 + Err(ParserError(es)) => { 91 + let diagnostics = es 92 + .into_iter() 93 + .filter_map(|error| { 94 + let (message, span) = match error { 95 + rotth_parser::Error::Parser(e) => match e.reason() { 101 96 chumsky::error::SimpleReason::Unclosed { span, delimiter } => { 102 - (format!("Unclosed delimiter {}", delimiter), span.clone()) 97 + (format!("Unclosed delimiter {}", delimiter), *span) 103 98 } 104 99 chumsky::error::SimpleReason::Unexpected => ( 105 100 format!( 106 101 "{}, expected {}", 107 - if item.found().is_some() { 102 + if e.found().is_some() { 108 103 "Unexpected token in input" 109 104 } else { 110 105 "Unexpected end of input" 111 106 }, 112 - if item.expected().len() == 0 { 107 + if e.expected().len() == 0 { 113 108 "something else".to_string() 114 109 } else { 115 - item.expected() 110 + e.expected() 116 111 .map(|expected| match expected { 117 112 Some(expected) => expected.to_string(), 118 113 None => "end of input".to_string(), ··· 121 116 .join(", ") 122 117 } 123 118 ), 124 - item.span(), 119 + e.span(), 125 120 ), 126 121 chumsky::error::SimpleReason::Custom(msg) => { 127 - (msg.to_string(), item.span()) 122 + (msg.to_string(), e.span()) 128 123 } 129 - }; 124 + }, 125 + rotth_parser::Error::Redefinition(e) => { 126 + ("This item is redefined elsewhere".into(), e.redefined_item) 127 + } 128 + rotth_parser::Error::UnresolvedInclude(_) => todo!(), 129 + }; 130 130 131 - || -> Option<Diagnostic> { 132 - let start_position = offset_to_position(span.start, &rope)?; 133 - let end_position = offset_to_position(span.end, &rope)?; 134 - Some(Diagnostic::new_simple( 135 - Range::new(start_position, end_position), 136 - message, 137 - )) 138 - }() 139 - }) 140 - .collect::<Vec<_>>(), 141 - rotth::Error::Redefinition(errors) => errors 142 - .into_iter() 143 - .filter_map(|item| { 144 - let (message, span) = ( 145 - "This word redifines another word defined elsewhere".to_string(), 146 - item.redefining_item, 147 - ); 131 + || -> Option<Diagnostic> { 132 + let start_position = offset_to_position(span.start, &rope)?; 133 + let end_position = offset_to_position(span.end, &rope)?; 134 + Some(Diagnostic::new_simple( 135 + Range::new(start_position, end_position), 136 + message, 137 + )) 138 + }() 139 + }) 140 + .collect::<Vec<_>>(); 148 141 149 - || -> Option<Diagnostic> { 150 - let start_position = offset_to_position(span.start, &rope)?; 151 - let end_position = offset_to_position(span.end, &rope)?; 152 - Some(Diagnostic::new_simple( 153 - Range::new(start_position, end_position), 154 - message, 155 - )) 156 - }() 157 - }) 158 - .collect::<Vec<_>>(), 159 - _e => { 160 - // self.client 161 - // .log_message(MessageType::INFO, format!("{:?}", todo)) 162 - // .await; 163 - return None; 164 - } 165 - }; 166 142 // todo: unbreak diagnostics 167 - // self.client 168 - // .publish_diagnostics(params.uri.clone(), diagnostics, None) 169 - // .await; 143 + self.client 144 + .publish_diagnostics(params.uri.clone(), diagnostics, None) 145 + .await; 170 146 return None; 171 147 } // TODO! 172 148 }; 173 149 174 - ast.some() 150 + ast.0.some() 175 151 } 176 152 177 153 async fn on_change(&self, params: TextDocument) { ··· 189 165 let mut includes = ast 190 166 .iter() 191 167 .filter_map(|i| { 192 - if let TopLevel::Include(inc) = i { 193 - let parent = i.span().file; 194 - let path = parent.parent().unwrap().join(inc.path()); 168 + if let TopLevel::Include(inc) = &**i { 169 + let parent = i.span.file.to_owned(); 170 + let path = parent.parent().unwrap().join(&*inc.path); 195 171 self.include_map 196 - .entry(parent) 172 + .entry(parent.clone()) 197 173 .or_insert_with(Default::default) 198 - .insert(path); 199 - (i.span().file, inc.path().to_owned()).some() 174 + .insert(path.clone()); 175 + (parent, path).some() 200 176 } else { 201 177 None 202 178 } ··· 299 275 CompleteCompletionItem::Const(name) | CompleteCompletionItem::Mem(name) => { 300 276 ret.push(CompletionItem { 301 277 label: name.clone(), 302 - insert_text: Some(name.clone()), 303 278 kind: Some(CompletionItemKind::CONSTANT), 304 - detail: Some(name), 279 + detail: Some(name.clone()), 280 + insert_text: Some(name), 305 281 ..Default::default() 306 282 }); 307 283 } ··· 402 378 403 379 let item = self.ast_map.iter().find_map(|r| { 404 380 for item in r.value() { 405 - if let Some(name) = item.name() { 406 - if name == word { 407 - return item.clone().some(); 408 - } 381 + if item.name().unwrap() == word { 382 + return item.clone().some(); 409 383 } 410 384 } 411 385 None 412 386 }); 413 387 414 388 let definition = item.and_then(|item| { 415 - let span = &item.span(); 389 + let span = &item.span; 416 390 let uri = Url::from_file_path(&span.file).unwrap(); 417 391 418 - let rope = &*self.document_map.get(&span.file)?; 392 + let rope = &*self.document_map.get(span.file)?; 419 393 420 394 let start_position = offset_to_position(span.start, rope)?; 421 395 let end_position = offset_to_position(span.end, rope)?;
+94 -83
rotth-lsp/src/semantic_token.rs
··· 1 - use rotth::{ 2 - ast::AstKind, 3 - ast::{AstNode, Binding, TopLevel}, 4 - iconst::IConst, 5 - }; 1 + use rotth_parser::ast::*; 2 + use somok::Either; 3 + use spanner::Spanned; 6 4 use tower_lsp::lsp_types::SemanticTokenType; 7 5 8 6 pub const LEGEND_TYPE: &[SemanticTokenType] = &[ ··· 25 23 pub token_type: usize, 26 24 } 27 25 28 - pub fn semantic_token_from_ast(ast: &[TopLevel]) -> Vec<CompleteSemanticToken> { 26 + pub fn semantic_token_from_ast(ast: &[Spanned<TopLevel>]) -> Vec<CompleteSemanticToken> { 29 27 let mut semantic_tokens = vec![]; 30 28 31 29 for item in ast.iter() { 32 - match item { 30 + match &**item { 33 31 TopLevel::Include(i) => { 34 32 push_token(&i.include, &mut semantic_tokens, SemanticTokenType::KEYWORD); 35 33 push_token(&i.path, &mut semantic_tokens, SemanticTokenType::STRING); 36 34 } 37 35 TopLevel::Proc(p) => { 38 36 push_token(&p.proc, &mut semantic_tokens, SemanticTokenType::KEYWORD); 39 - if let Some(generics) = &p.generics { 40 - push_tokens_recursively(generics, &mut semantic_tokens); 37 + if let Some(Spanned { 38 + span: _, 39 + inner: 40 + Generics { 41 + left_bracket, 42 + tys, 43 + right_bracket, 44 + }, 45 + }) = &p.generics 46 + { 47 + push_token( 48 + left_bracket, 49 + &mut semantic_tokens, 50 + SemanticTokenType::KEYWORD, 51 + ); 52 + for ty in tys { 53 + push_token(ty, &mut semantic_tokens, SemanticTokenType::TYPE); 54 + } 55 + push_token( 56 + right_bracket, 57 + &mut semantic_tokens, 58 + SemanticTokenType::KEYWORD, 59 + ); 41 60 }; 42 61 push_token(&p.name, &mut semantic_tokens, SemanticTokenType::FUNCTION); 43 - let signature = 44 - rotth::coerce_ast!(p.signature => REF ProcSignature || unreachable!()); 62 + let signature = &p.signature; 45 63 for ty in &signature.ins { 46 64 push_token(ty, &mut semantic_tokens, SemanticTokenType::TYPE) 47 65 } ··· 54 72 } 55 73 } 56 74 push_token(&p.do_, &mut semantic_tokens, SemanticTokenType::KEYWORD); 57 - push_tokens_recursively(&p.body, &mut semantic_tokens); 75 + for e in &p.body { 76 + push_expr_tokens(e, &mut semantic_tokens); 77 + } 58 78 push_token(&p.end, &mut semantic_tokens, SemanticTokenType::KEYWORD); 59 79 } 60 80 TopLevel::Const(c) => { 61 81 push_token(&c.const_, &mut semantic_tokens, SemanticTokenType::KEYWORD); 62 82 push_token(&c.name, &mut semantic_tokens, SemanticTokenType::TYPE); 63 83 push_token(&c.do_, &mut semantic_tokens, SemanticTokenType::KEYWORD); 64 - push_tokens_recursively(&c.body, &mut semantic_tokens); 84 + for e in &c.body { 85 + push_expr_tokens(e, &mut semantic_tokens); 86 + } 65 87 push_token(&c.end, &mut semantic_tokens, SemanticTokenType::KEYWORD); 66 88 } 67 89 TopLevel::Mem(m) => { 68 90 push_token(&m.mem, &mut semantic_tokens, SemanticTokenType::KEYWORD); 69 91 push_token(&m.name, &mut semantic_tokens, SemanticTokenType::TYPE); 70 92 push_token(&m.do_, &mut semantic_tokens, SemanticTokenType::KEYWORD); 71 - push_tokens_recursively(&m.body, &mut semantic_tokens); 93 + for e in &m.body { 94 + push_expr_tokens(e, &mut semantic_tokens); 95 + } 72 96 push_token(&m.end, &mut semantic_tokens, SemanticTokenType::KEYWORD); 73 97 } 74 98 TopLevel::Var(v) => { ··· 81 105 push_token(&s.struct_, &mut semantic_tokens, SemanticTokenType::KEYWORD); 82 106 push_token(&s.name, &mut semantic_tokens, SemanticTokenType::TYPE); 83 107 push_token(&s.do_, &mut semantic_tokens, SemanticTokenType::KEYWORD); 84 - for field in &s.body { 85 - push_tokens_recursively(field, &mut semantic_tokens); 108 + for f in &s.body { 109 + push_token(&f.name, &mut semantic_tokens, SemanticTokenType::PARAMETER); 110 + push_token(&f.name, &mut semantic_tokens, SemanticTokenType::KEYWORD); 111 + push_token(&f.ty, &mut semantic_tokens, SemanticTokenType::TYPE); 86 112 } 87 113 push_token(&s.end, &mut semantic_tokens, SemanticTokenType::KEYWORD); 88 114 } ··· 92 118 semantic_tokens 93 119 } 94 120 95 - fn push_tokens_recursively(node: &AstNode, tokens: &mut Vec<CompleteSemanticToken>) { 96 - match &node.ast { 97 - AstKind::StructField(f) => { 98 - push_token(&*f.name, tokens, SemanticTokenType::PARAMETER); 99 - push_token(&*f.sep, tokens, SemanticTokenType::KEYWORD); 100 - push_token(&*f.ty, tokens, SemanticTokenType::TYPE); 101 - } 102 - AstKind::KeyWord(_) => push_token(node, tokens, SemanticTokenType::KEYWORD), 103 - AstKind::Type(_) => push_token(node, tokens, SemanticTokenType::TYPE), 104 - AstKind::Separator => push_token(node, tokens, SemanticTokenType::KEYWORD), 105 - AstKind::Bind(b) => { 121 + fn push_expr_tokens(node: &Spanned<Expr>, tokens: &mut Vec<CompleteSemanticToken>) { 122 + match &node.inner { 123 + Expr::Keyword(_) => push_token(node, tokens, SemanticTokenType::KEYWORD), 124 + Expr::Type(_) => push_token(node, tokens, SemanticTokenType::TYPE), 125 + Expr::Bind(b) => { 106 126 push_token(&b.bind, tokens, SemanticTokenType::KEYWORD); 107 127 for binding in &b.bindings { 108 - push_tokens_recursively(binding, tokens); 128 + match &**binding { 129 + Either::Left(_) => push_token(binding, tokens, SemanticTokenType::VARIABLE), 130 + Either::Right(NameTypePair { name, sep, ty }) => { 131 + push_token(name, tokens, SemanticTokenType::VARIABLE); 132 + push_token(sep, tokens, SemanticTokenType::KEYWORD); 133 + push_token(ty, tokens, SemanticTokenType::TYPE) 134 + } 135 + } 109 136 } 110 137 push_token(&b.do_, tokens, SemanticTokenType::KEYWORD); 111 - push_tokens_recursively(&b.body, tokens); 138 + for e in &b.body { 139 + push_expr_tokens(e, tokens) 140 + } 112 141 push_token(&b.end, tokens, SemanticTokenType::KEYWORD); 113 142 } 114 - AstKind::Binding(b) => { 115 - if let Binding::Bind { name, sep, ty } = b { 116 - push_token(name, tokens, SemanticTokenType::PARAMETER); 117 - push_token(sep, tokens, SemanticTokenType::KEYWORD); 118 - push_token(ty, tokens, SemanticTokenType::TYPE); 119 - } else { 120 - push_token(node, tokens, SemanticTokenType::PARAMETER); 143 + Expr::While(w) => { 144 + push_token(&w.while_, tokens, SemanticTokenType::KEYWORD); 145 + for e in &w.cond { 146 + push_expr_tokens(e, tokens); 121 147 } 122 - } 123 - AstKind::While(w) => { 124 - push_token(&w.while_, tokens, SemanticTokenType::KEYWORD); 125 - push_tokens_recursively(&w.cond, tokens); 126 148 push_token(&w.do_, tokens, SemanticTokenType::KEYWORD); 127 - push_tokens_recursively(&w.body, tokens); 149 + for e in &w.body { 150 + push_expr_tokens(e, tokens); 151 + } 128 152 push_token(&w.end, tokens, SemanticTokenType::KEYWORD); 129 153 } 130 - AstKind::If(i) => { 154 + Expr::If(i) => { 131 155 push_token(&i.if_, tokens, SemanticTokenType::KEYWORD); 132 - push_tokens_recursively(&i.truth, tokens); 156 + for e in &i.truth { 157 + push_expr_tokens(e, tokens); 158 + } 133 159 for e in &i.lie { 134 160 push_token(&e.else_, tokens, SemanticTokenType::KEYWORD); 135 - push_tokens_recursively(&e.body, tokens); 161 + for e in &e.body { 162 + push_expr_tokens(e, tokens); 163 + } 136 164 } 137 165 push_token(&i.end, tokens, SemanticTokenType::KEYWORD); 138 166 } 139 - AstKind::Cond(c) => { 167 + Expr::Cond(c) => { 140 168 push_token(&c.cond, tokens, SemanticTokenType::KEYWORD); 141 169 push_token(&c.pat, tokens, SemanticTokenType::REGEXP); 142 170 push_token(&c.do_, tokens, SemanticTokenType::KEYWORD); 143 - push_tokens_recursively(&c.body, tokens); 171 + for e in &c.body { 172 + push_expr_tokens(e, tokens); 173 + } 144 174 for b in &c.branches { 145 175 push_token(&b.else_, tokens, SemanticTokenType::KEYWORD); 146 176 push_token(&b.pat, tokens, SemanticTokenType::PARAMETER); 147 177 push_token(&b.do_, tokens, SemanticTokenType::KEYWORD); 148 - push_tokens_recursively(&b.body, tokens); 178 + for e in &b.body { 179 + push_expr_tokens(e, tokens); 180 + } 149 181 } 150 182 push_token(&c.end, tokens, SemanticTokenType::KEYWORD); 151 183 } 152 - AstKind::Cast(c) => { 184 + Expr::Cast(c) => { 153 185 push_token(&c.cast, tokens, SemanticTokenType::KEYWORD); 154 186 push_token(&c.ty, tokens, SemanticTokenType::TYPE); 155 187 } 156 - AstKind::Word(_) => push_token(node, tokens, SemanticTokenType::FUNCTION), 157 - AstKind::Path(_) => push_token(node, tokens, SemanticTokenType::STRING), 158 - AstKind::Literal(l) => { 188 + Expr::Word(_) => push_token(node, tokens, SemanticTokenType::FUNCTION), 189 + Expr::Path(_) => push_token(node, tokens, SemanticTokenType::FUNCTION), 190 + Expr::Literal(l) => { 159 191 let ty = match l { 160 - IConst::Bool(_) => SemanticTokenType::NUMBER, 161 - IConst::U64(_) => SemanticTokenType::NUMBER, 162 - IConst::I64(_) => SemanticTokenType::NUMBER, 163 - IConst::Char(_) => SemanticTokenType::STRING, 164 - IConst::Str(_) => SemanticTokenType::STRING, 165 - IConst::Ptr(_) => unreachable!(), 192 + Literal::Bool(_) => SemanticTokenType::NUMBER, 193 + Literal::Char(_) => SemanticTokenType::STRING, 194 + Literal::String(_) => SemanticTokenType::STRING, 195 + Literal::Num(_) => SemanticTokenType::NUMBER, 166 196 }; 167 197 push_token(node, tokens, ty); 168 198 } 169 - AstKind::Pattern(_) => unreachable!(), 170 - AstKind::ProcSignature(_) => unreachable!(), 171 - AstKind::ConstSignature(_) => unreachable!(), 172 - AstKind::Body(b) => { 173 - for binding in b { 174 - push_tokens_recursively(binding, tokens); 175 - } 176 - } 177 - AstKind::Var(v) => { 199 + Expr::Var(v) => { 178 200 push_token(&v.var, tokens, SemanticTokenType::KEYWORD); 179 - if let Some(ret) = &v.ret { 180 - push_token(ret, tokens, SemanticTokenType::KEYWORD); 181 - } 182 201 push_token(&v.name, tokens, SemanticTokenType::PARAMETER); 183 202 push_token(&v.sep, tokens, SemanticTokenType::KEYWORD); 184 203 push_token(&v.ty, tokens, SemanticTokenType::TYPE); 185 204 } 186 - AstKind::Accessor => { 187 - push_token(node, tokens, SemanticTokenType::KEYWORD); 188 - } 189 - AstKind::FieldAccess(a) => { 205 + Expr::FieldAccess(a) => { 190 206 push_token(&a.access, tokens, SemanticTokenType::KEYWORD); 191 207 push_token(&a.field, tokens, SemanticTokenType::PARAMETER); 192 208 } 193 - AstKind::Generics(g) => { 194 - push_token(&g.left_bracket, tokens, SemanticTokenType::KEYWORD); 195 - for node in &g.tys { 196 - push_token(node, tokens, SemanticTokenType::TYPE); 197 - } 198 - push_token(&g.right_bracket, tokens, SemanticTokenType::KEYWORD); 199 - } 200 - AstKind::LBracket => todo!(), 201 - AstKind::RBracket => todo!(), 202 209 } 203 210 } 204 211 205 - fn push_token(node: &AstNode, tokens: &mut Vec<CompleteSemanticToken>, typ: SemanticTokenType) { 212 + fn push_token<T>( 213 + node: &Spanned<T>, 214 + tokens: &mut Vec<CompleteSemanticToken>, 215 + typ: SemanticTokenType, 216 + ) { 206 217 tokens.push(CompleteSemanticToken { 207 218 start: node.span.start, 208 219 length: node.span.length(),
+16
rotth-parser/Cargo.toml
··· 1 + [package] 2 + name = "rotth-parser" 3 + version = "0.1.0" 4 + edition = "2021" 5 + 6 + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 + 8 + [dependencies] 9 + chumsky = { git = "https://github.com/zesterer/chumsky.git" } 10 + spanner = { path = "../spanner" } 11 + rotth-lexer = { path = "../rotth-lexer" } 12 + somok = "*" 13 + logos = "0.12" 14 + fnv = "1.0" 15 + smol_str = "0.1.23" 16 + thiserror = "1.0"
+656
rotth-parser/src/ast.rs
··· 1 + mod parsers; 2 + 3 + use chumsky::{prelude::Simple, Parser, Stream}; 4 + use fnv::FnvHashMap; 5 + use rotth_lexer::{lex, Token}; 6 + use smol_str::SmolStr; 7 + use somok::{Either, Leaksome}; 8 + use spanner::{Span, Spanned}; 9 + use std::{ 10 + borrow::Borrow, 11 + fmt::Debug, 12 + ops::{Deref, DerefMut}, 13 + path::PathBuf, 14 + }; 15 + 16 + use crate::{types::Type, Error, ParserError, Redefinition}; 17 + 18 + #[derive(Debug, Clone)] 19 + pub struct File(pub Vec<Spanned<TopLevel>>); 20 + 21 + #[derive(Debug, Clone)] 22 + pub struct Word(pub SmolStr); 23 + 24 + #[derive(Debug, Clone)] 25 + pub enum Punctuation { 26 + LBracket, 27 + RBracket, 28 + Colon, 29 + RArrow, 30 + } 31 + 32 + #[derive(Clone)] 33 + pub enum TopLevel { 34 + Proc(Proc), 35 + Const(Const), 36 + Mem(Mem), 37 + Var(Var), 38 + Struct(Struct), 39 + Include(Include), 40 + } 41 + 42 + impl TopLevel { 43 + pub fn name(&self) -> Result<SmolStr, Simple<Token, Span>> { 44 + match self { 45 + TopLevel::Proc(Proc { 46 + name: 47 + Spanned { 48 + span: _, 49 + inner: Word(name), 50 + }, 51 + .. 52 + }) => Ok(name.clone()), 53 + TopLevel::Const(Const { 54 + name: 55 + Spanned { 56 + span: _, 57 + inner: Word(name), 58 + }, 59 + .. 60 + }) => Ok(name.clone()), 61 + TopLevel::Mem(Mem { 62 + name: 63 + Spanned { 64 + span: _, 65 + inner: Word(name), 66 + }, 67 + .. 68 + }) => Ok(name.clone()), 69 + TopLevel::Var(Var { 70 + name: 71 + Spanned { 72 + span: _, 73 + inner: Word(name), 74 + }, 75 + .. 76 + }) => Ok(name.clone()), 77 + TopLevel::Struct(Struct { 78 + name: 79 + Spanned { 80 + span: _, 81 + inner: Word(name), 82 + }, 83 + .. 84 + }) => Ok(name.clone()), 85 + TopLevel::Include(Include { 86 + include: _, 87 + qualifiers: _, 88 + path: Spanned { span, inner: name }, 89 + }) => name 90 + .file_prefix() 91 + .and_then(|n| n.to_str()) 92 + .map(Into::into) 93 + .ok_or_else(|| Simple::custom(*span, "Invalid include path: not a file")), 94 + } 95 + } 96 + } 97 + 98 + impl Debug for TopLevel { 99 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 100 + match self { 101 + Self::Proc(arg0) => arg0.fmt(f), 102 + Self::Const(arg0) => arg0.fmt(f), 103 + Self::Mem(arg0) => arg0.fmt(f), 104 + Self::Var(arg0) => arg0.fmt(f), 105 + Self::Struct(arg0) => arg0.fmt(f), 106 + Self::Include(arg0) => arg0.fmt(f), 107 + } 108 + } 109 + } 110 + 111 + #[derive(Debug, Clone)] 112 + pub struct Proc { 113 + pub proc: Spanned<Keyword>, 114 + pub generics: Option<Spanned<Generics>>, 115 + pub name: Spanned<Word>, 116 + pub signature: Spanned<ProcSignature>, 117 + pub do_: Spanned<Keyword>, 118 + pub body: Vec<Spanned<Expr>>, 119 + pub end: Spanned<Keyword>, 120 + } 121 + 122 + // (T . (c . (T . ()))) 123 + // pub struct SeparatedList<V, S> { 124 + // val: V, 125 + // next: Option<Box<SeparatedList<S, V>>>, 126 + // } 127 + 128 + #[derive(Debug, Clone, Hash, PartialEq, Eq)] 129 + pub enum Keyword { 130 + Include, 131 + Return, 132 + Cond, 133 + If, 134 + Else, 135 + Proc, 136 + While, 137 + Do, 138 + Bind, 139 + Const, 140 + Mem, 141 + Var, 142 + Struct, 143 + Cast, 144 + End, 145 + } 146 + 147 + impl std::fmt::Display for Keyword { 148 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 149 + Debug::fmt(self, f) 150 + } 151 + } 152 + 153 + #[derive(Debug, Clone)] 154 + pub struct Mem { 155 + pub mem: Spanned<Keyword>, 156 + pub name: Spanned<Word>, 157 + pub do_: Spanned<Keyword>, 158 + pub body: Vec<Spanned<Expr>>, 159 + pub end: Spanned<Keyword>, 160 + } 161 + 162 + #[derive(Debug, Clone)] 163 + pub struct Struct { 164 + pub struct_: Spanned<Keyword>, 165 + pub name: Spanned<Word>, 166 + pub do_: Spanned<Keyword>, 167 + pub body: Vec<Spanned<NameTypePair>>, 168 + pub end: Spanned<Keyword>, 169 + } 170 + 171 + #[derive(Debug, Clone)] 172 + pub struct Const { 173 + pub const_: Spanned<Keyword>, 174 + pub name: Spanned<Word>, 175 + pub signature: Spanned<ConstSignature>, 176 + pub do_: Spanned<Keyword>, 177 + pub body: Vec<Spanned<Expr>>, 178 + pub end: Spanned<Keyword>, 179 + } 180 + 181 + #[derive(Debug, Clone)] 182 + pub struct Include { 183 + pub include: Spanned<Keyword>, 184 + pub qualifiers: Vec<Spanned<Word>>, 185 + pub path: Spanned<PathBuf>, 186 + } 187 + 188 + #[derive(Clone)] 189 + pub enum Expr { 190 + Keyword(Keyword), 191 + Type(Type), 192 + 193 + Bind(Bind), 194 + 195 + While(While), 196 + 197 + If(If), 198 + Cond(Box<Cond>), 199 + 200 + Cast(Cast), 201 + 202 + Word(Word), 203 + Path(ItemPathBuf), 204 + 205 + Literal(Literal), 206 + FieldAccess(Box<FieldAccess>), 207 + 208 + Var(Var), 209 + } 210 + 211 + impl Debug for Expr { 212 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 213 + match self { 214 + Expr::Keyword(arg0) => arg0.fmt(f), 215 + Expr::Type(arg0) => arg0.fmt(f), 216 + Expr::Bind(arg0) => arg0.fmt(f), 217 + Expr::While(arg0) => arg0.fmt(f), 218 + Expr::If(arg0) => arg0.fmt(f), 219 + Expr::Cond(arg0) => arg0.fmt(f), 220 + Expr::Cast(arg0) => arg0.fmt(f), 221 + Expr::Word(arg0) => arg0.fmt(f), 222 + Expr::Path(arg0) => arg0.fmt(f), 223 + Expr::Literal(arg0) => arg0.fmt(f), 224 + Expr::FieldAccess(arg0) => arg0.fmt(f), 225 + Expr::Var(arg0) => arg0.fmt(f), 226 + } 227 + } 228 + } 229 + 230 + #[derive(Debug, Clone)] 231 + pub struct Generics { 232 + pub left_bracket: Spanned<Punctuation>, 233 + pub tys: Vec<Spanned<Word>>, 234 + pub right_bracket: Spanned<Punctuation>, 235 + } 236 + 237 + #[derive(Debug, Clone)] 238 + pub struct FieldAccess { 239 + pub access: Spanned<Punctuation>, 240 + pub field: Spanned<Word>, 241 + } 242 + 243 + #[derive(Debug, Clone)] 244 + pub struct Var { 245 + pub var: Spanned<Keyword>, 246 + pub name: Spanned<Word>, 247 + pub sep: Spanned<Punctuation>, 248 + pub ty: Spanned<Type>, 249 + } 250 + 251 + #[derive(Debug, Clone)] 252 + pub struct ConstSignature { 253 + pub sep: Spanned<Punctuation>, 254 + pub tys: Vec<Spanned<Type>>, 255 + } 256 + 257 + #[derive(Debug, Clone)] 258 + pub struct ProcSignature { 259 + pub ins: Vec<Spanned<Type>>, 260 + pub sep: Option<Spanned<Punctuation>>, 261 + pub outs: Option<Vec<Spanned<Type>>>, 262 + } 263 + 264 + #[derive(Debug, Clone)] 265 + pub struct NameTypePair { 266 + pub name: Spanned<Word>, 267 + pub sep: Spanned<Punctuation>, 268 + pub ty: Spanned<Type>, 269 + } 270 + 271 + #[derive(Debug, Clone)] 272 + pub struct While { 273 + pub while_: Spanned<Keyword>, 274 + pub cond: Vec<Spanned<Expr>>, 275 + pub do_: Spanned<Keyword>, 276 + pub body: Vec<Spanned<Expr>>, 277 + pub end: Spanned<Keyword>, 278 + } 279 + 280 + #[derive(Debug, Clone)] 281 + pub struct Cast { 282 + pub cast: Spanned<Keyword>, 283 + pub ty: Spanned<Type>, 284 + } 285 + 286 + #[derive(Debug, Clone)] 287 + pub struct If { 288 + pub if_: Spanned<Keyword>, 289 + pub truth: Vec<Spanned<Expr>>, 290 + pub lie: Option<Else>, 291 + pub end: Spanned<Keyword>, 292 + } 293 + 294 + #[derive(Debug, Clone)] 295 + pub struct Else { 296 + pub else_: Spanned<Keyword>, 297 + pub body: Vec<Spanned<Expr>>, 298 + } 299 + 300 + #[derive(Debug, Clone)] 301 + pub struct Cond { 302 + pub cond: Spanned<Keyword>, 303 + pub pat: Spanned<Expr>, 304 + pub do_: Spanned<Keyword>, 305 + pub body: Vec<Spanned<Expr>>, 306 + pub branches: Vec<Spanned<CondBranch>>, 307 + pub end: Spanned<Keyword>, 308 + } 309 + 310 + #[derive(Debug, Clone)] 311 + pub struct CondBranch { 312 + pub else_: Spanned<Keyword>, 313 + pub pat: Spanned<Expr>, 314 + pub do_: Spanned<Keyword>, 315 + pub body: Vec<Spanned<Expr>>, 316 + } 317 + 318 + #[derive(Debug, Clone)] 319 + pub struct Bind { 320 + pub bind: Spanned<Keyword>, 321 + pub bindings: Vec<Spanned<Either<Word, NameTypePair>>>, 322 + pub do_: Spanned<Keyword>, 323 + pub body: Vec<Spanned<Expr>>, 324 + pub end: Spanned<Keyword>, 325 + } 326 + 327 + #[derive(Clone)] 328 + pub enum Literal { 329 + Bool(bool), 330 + Num(u64), 331 + String(String), 332 + Char(char), 333 + } 334 + 335 + impl Debug for Literal { 336 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 337 + match self { 338 + Self::Bool(arg0) => arg0.fmt(f), 339 + Self::Num(arg0) => arg0.fmt(f), 340 + Self::String(arg0) => arg0.fmt(f), 341 + Self::Char(arg0) => arg0.fmt(f), 342 + } 343 + } 344 + } 345 + 346 + pub fn parse(tokens: Vec<(Token, Span)>) -> Result<File, ParserError> { 347 + let stream = Stream::from_iter(tokens.last().unwrap().1, tokens.into_iter()); 348 + let (r, e) = parsers::file().parse_recovery(stream); 349 + r.ok_or_else(|| e.into()) 350 + } 351 + 352 + #[derive(PartialEq, Eq, Hash)] 353 + #[repr(transparent)] 354 + pub struct ItemPath { 355 + segments: [SmolStr], 356 + } 357 + 358 + impl PartialEq<&ItemPath> for ItemPathBuf { 359 + fn eq(&self, other: &&ItemPath) -> bool { 360 + self.segments == other.segments 361 + } 362 + } 363 + 364 + impl PartialEq<ItemPathBuf> for ItemPath { 365 + fn eq(&self, other: &ItemPathBuf) -> bool { 366 + self.segments == other.segments 367 + } 368 + } 369 + 370 + impl ItemPath { 371 + pub fn iter(&'_ self) -> impl Iterator<Item = &'_ SmolStr> { 372 + self.segments.iter() 373 + } 374 + 375 + pub fn only(&self) -> Option<&str> { 376 + self.segments.first().map(SmolStr::as_str) 377 + } 378 + 379 + pub fn drop_first(&self) -> Option<&Self> { 380 + self.segments 381 + .split_first() 382 + .and_then(|(_, b)| if b.is_empty() { None } else { Some(b) }) 383 + .map(|s| unsafe { std::mem::transmute::<&[SmolStr], &ItemPath>(s) }) 384 + } 385 + 386 + pub fn parent(&self) -> Option<&ItemPath> { 387 + if self.segments.is_empty() { 388 + None 389 + } else { 390 + let segments = &self.segments[..self.segments.len() - 1]; 391 + let parent = unsafe { std::mem::transmute::<&[SmolStr], &ItemPath>(segments) }; 392 + Some(parent) 393 + } 394 + } 395 + 396 + pub fn join(&self, other: &Self) -> ItemPathBuf { 397 + let mut segments = self.segments.to_owned(); 398 + segments.extend_from_slice(&other.segments); 399 + ItemPathBuf { segments } 400 + } 401 + 402 + pub fn child(&self, segment: impl Into<SmolStr>) -> ItemPathBuf { 403 + let mut segments = self.segments.to_owned(); 404 + segments.push(segment.into()); 405 + ItemPathBuf { segments } 406 + } 407 + } 408 + 409 + #[macro_export] 410 + macro_rules! path { 411 + ( $( $s:tt )::* ) => {{ 412 + let mut path = ItemPathBuf::new(); 413 + $(path.push(stringify!($s));)* 414 + path 415 + }}; 416 + } 417 + 418 + #[derive(PartialEq, Eq, Hash, Default, Clone)] 419 + #[repr(transparent)] 420 + pub struct ItemPathBuf { 421 + segments: Vec<SmolStr>, 422 + } 423 + 424 + impl Deref for ItemPathBuf { 425 + type Target = ItemPath; 426 + 427 + fn deref(&self) -> &Self::Target { 428 + unsafe { std::mem::transmute::<&[SmolStr], &ItemPath>(&*self.segments) } 429 + } 430 + } 431 + 432 + impl DerefMut for ItemPathBuf { 433 + fn deref_mut(&mut self) -> &mut Self::Target { 434 + unsafe { std::mem::transmute::<&mut [SmolStr], &mut ItemPath>(&mut *self.segments) } 435 + } 436 + } 437 + 438 + impl<T: Into<SmolStr>> From<Vec<T>> for ItemPathBuf { 439 + fn from(segments: Vec<T>) -> Self { 440 + Self { 441 + segments: segments.into_iter().map(Into::into).collect(), 442 + } 443 + } 444 + } 445 + 446 + impl Borrow<ItemPath> for ItemPathBuf { 447 + fn borrow(&self) -> &ItemPath { 448 + self.deref() 449 + } 450 + } 451 + 452 + impl ToOwned for ItemPath { 453 + type Owned = ItemPathBuf; 454 + 455 + fn to_owned(&self) -> Self::Owned { 456 + let segments = self.segments.to_owned(); 457 + Self::Owned { segments } 458 + } 459 + } 460 + 461 + impl ItemPathBuf { 462 + pub fn new() -> Self { 463 + Self::default() 464 + } 465 + 466 + pub fn push(&mut self, segment: impl Into<SmolStr>) { 467 + self.segments.push(segment.into()) 468 + } 469 + } 470 + 471 + impl Debug for ItemPath { 472 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 473 + let separator = SmolStr::from("::"); 474 + let segments = self.segments.iter(); 475 + let iter = segments.intersperse(&separator); 476 + for s in iter { 477 + write!(f, "{}", s)? 478 + } 479 + Ok(()) 480 + } 481 + } 482 + 483 + impl Debug for ItemPathBuf { 484 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 485 + self.deref().fmt(f) 486 + } 487 + } 488 + 489 + pub enum ResolvedItem { 490 + Proc(Proc), 491 + Const(Const), 492 + Mem(Mem), 493 + Var(Var), 494 + Struct(ResolvedStruct), 495 + Module(Box<ResolvedFile>), 496 + } 497 + 498 + impl Debug for ResolvedItem { 499 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 500 + match self { 501 + Self::Proc(arg0) => arg0.fmt(f), 502 + Self::Const(arg0) => arg0.fmt(f), 503 + Self::Mem(arg0) => arg0.fmt(f), 504 + Self::Var(arg0) => arg0.fmt(f), 505 + Self::Struct(arg0) => arg0.fmt(f), 506 + Self::Module(arg0) => arg0.fmt(f), 507 + } 508 + } 509 + } 510 + 511 + #[derive(Debug)] 512 + pub struct ResolvedFile { 513 + pub path: ItemPathBuf, 514 + pub ast: FnvHashMap<SmolStr, Spanned<ResolvedItem>>, 515 + } 516 + 517 + impl ResolvedFile { 518 + pub fn find(&self, path: &ItemPath) -> Option<&Spanned<ResolvedItem>> { 519 + let mut segments = path.iter(); 520 + let segment = segments.next(); 521 + let item = segment.and_then(|s| self.ast.get(s)); 522 + if let Some(path) = path.drop_first() { 523 + match item { 524 + Some(i) => match &**i { 525 + ResolvedItem::Proc(_) => return None, 526 + ResolvedItem::Const(_) => return None, 527 + ResolvedItem::Mem(_) => return None, 528 + ResolvedItem::Var(_) => return None, 529 + ResolvedItem::Struct(_) => return None, 530 + ResolvedItem::Module(f) => return f.find(path), 531 + }, 532 + None => return None, 533 + } 534 + } 535 + item 536 + } 537 + } 538 + 539 + #[derive(Debug)] 540 + pub struct ResolvedStruct { 541 + pub name: Spanned<Word>, 542 + pub fields: FnvHashMap<SmolStr, Spanned<NameTypePair>>, 543 + } 544 + 545 + pub fn resolve_includes(root: File) -> Result<ResolvedFile, ParserError> { 546 + let path = Default::default(); 547 + resolve_includes_from(path, root) 548 + } 549 + 550 + fn resolve_includes_from(path: ItemPathBuf, root: File) -> Result<ResolvedFile, ParserError> { 551 + let mut ast: FnvHashMap<SmolStr, Spanned<ResolvedItem>> = Default::default(); 552 + let mut errors = Vec::new(); 553 + for item in root.0 { 554 + let name = match item.name().map_err(Error::Parser) { 555 + Ok(name) => name, 556 + Err(e) => { 557 + errors.push(e); 558 + continue; 559 + } 560 + }; 561 + let resolved_item = match item.inner { 562 + TopLevel::Proc(p) => ResolvedItem::Proc(p), 563 + TopLevel::Const(c) => ResolvedItem::Const(c), 564 + TopLevel::Mem(m) => ResolvedItem::Mem(m), 565 + TopLevel::Var(v) => ResolvedItem::Var(v), 566 + TopLevel::Struct(s) => match make_struct(s) { 567 + Ok(s) => ResolvedItem::Struct(s), 568 + Err(mut es) => { 569 + errors.append(&mut es); 570 + continue; 571 + } 572 + }, 573 + TopLevel::Include(Include { 574 + include: _, 575 + qualifiers: _, 576 + path: file_path, 577 + }) => { 578 + let file_span = file_path.span; 579 + let file_name = match file_path 580 + .file_prefix() 581 + .and_then(|f| f.to_str()) 582 + .map(SmolStr::from) 583 + .ok_or(Error::UnresolvedInclude(file_span)) 584 + { 585 + Ok(n) => n, 586 + Err(e) => { 587 + errors.push(e); 588 + continue; 589 + } 590 + }; 591 + let parent = file_path.span.file; 592 + let file_path = parent.parent().unwrap().join(file_path.inner); 593 + let file_path = &*file_path.into_boxed_path().leak(); 594 + let src = match std::fs::read_to_string(file_path) 595 + .map_err(|_| Error::UnresolvedInclude(file_span)) 596 + { 597 + Ok(s) => s, 598 + Err(e) => { 599 + errors.push(e); 600 + continue; 601 + } 602 + }; 603 + let tokens = lex(&src, file_path); 604 + let module_ast = parse(tokens)?; 605 + let resolved = resolve_includes_from(path.child(file_name), module_ast)?; 606 + ResolvedItem::Module(box resolved) 607 + } 608 + }; 609 + 610 + if let Some(redefined) = ast.get(&name) { 611 + errors.push(Error::Redefinition(Redefinition { 612 + redefining_item: item.span, 613 + redefined_item: redefined.span, 614 + })) 615 + } else { 616 + ast.insert( 617 + name, 618 + Spanned { 619 + span: item.span, 620 + inner: resolved_item, 621 + }, 622 + ); 623 + } 624 + } 625 + 626 + if errors.is_empty() { 627 + Ok(ResolvedFile { path, ast }) 628 + } else { 629 + Err(ParserError(errors)) 630 + } 631 + } 632 + 633 + fn make_struct(s: Struct) -> Result<ResolvedStruct, Vec<Error>> { 634 + let mut errors = Vec::default(); 635 + let mut fields: FnvHashMap<SmolStr, Spanned<NameTypePair>> = Default::default(); 636 + for field in s.body { 637 + let Word(name) = &*field.name; 638 + 639 + if let Some(redefined) = fields.get(name) { 640 + errors.push(Error::Redefinition(Redefinition { 641 + redefining_item: field.span, 642 + redefined_item: redefined.span, 643 + })) 644 + } else { 645 + fields.insert(name.clone(), field); 646 + } 647 + } 648 + if errors.is_empty() { 649 + Ok(ResolvedStruct { 650 + name: s.name, 651 + fields, 652 + }) 653 + } else { 654 + Err(errors) 655 + } 656 + }
+599
rotth-parser/src/ast/parsers.rs
··· 1 + use chumsky::prelude::*; 2 + use logos::Logos; 3 + use rotth_lexer::Token; 4 + use somok::Either; 5 + use spanner::{Span, Spanned}; 6 + use std::path::{Path, PathBuf}; 7 + 8 + use crate::types::{Primitive, Type}; 9 + 10 + use super::{ 11 + Bind, Cast, Cond, CondBranch, Const, ConstSignature, Else, Expr, FieldAccess, File, Generics, 12 + If, Include, ItemPathBuf, Keyword, Literal, Mem, NameTypePair, Proc, ProcSignature, 13 + Punctuation, Struct, TopLevel, Var, While, Word, 14 + }; 15 + 16 + pub(super) fn ty() -> impl Parser<Token, Spanned<Type>, Error = Simple<Token, Span>> + Clone { 17 + just(Token::Ptr) 18 + .repeated() 19 + .then(path()) 20 + .map_with_span(|(ptr, ty), span| { 21 + let mut ty = if let Some(type_name) = ty.only() { 22 + match type_name { 23 + "()" => Type::Primitive(Primitive::Void), 24 + "bool" => Type::Primitive(Primitive::Bool), 25 + "char" => Type::Primitive(Primitive::Char), 26 + 27 + "u64" => Type::Primitive(Primitive::U64), 28 + "u32" => Type::Primitive(Primitive::U32), 29 + "u16" => Type::Primitive(Primitive::U16), 30 + "u8" => Type::Primitive(Primitive::U8), 31 + 32 + "i64" => Type::Primitive(Primitive::I64), 33 + "i32" => Type::Primitive(Primitive::I32), 34 + "i16" => Type::Primitive(Primitive::I16), 35 + "i8" => Type::Primitive(Primitive::I8), 36 + _ => Type::Custom(ty.inner), 37 + } 38 + } else { 39 + Type::Custom(ty.inner) 40 + }; 41 + for _ in ptr { 42 + ty = Type::Ptr(box ty) 43 + } 44 + 45 + Spanned { span, inner: ty } 46 + }) 47 + } 48 + 49 + pub(super) fn parse_string(s: &str, path: &'static Path) -> Result<String, Simple<Token, Span>> { 50 + #[derive(Logos)] 51 + pub enum StrToken { 52 + #[regex(r"\\.", |l| l.slice().chars().nth(1))] 53 + Escaped(char), 54 + #[regex(r"[^\\]", |l| l.slice().chars().next())] 55 + Char(char), 56 + #[token(r#"""#)] 57 + End, 58 + #[error] 59 + Error, 60 + } 61 + 62 + StrToken::lexer(s) 63 + .spanned() 64 + .filter_map(|(t, s)| match t { 65 + StrToken::Escaped(c) => match c { 66 + 'n' => Some(Ok('\n')), 67 + 't' => Some(Ok('\t')), 68 + '"' => Some(Ok('"')), 69 + _ => Some(Err(Simple::custom( 70 + Span::new(path, s.start, s.end), 71 + "Invalid character escape", 72 + ))), 73 + }, 74 + StrToken::Char(c) => Some(Ok(c)), 75 + StrToken::End => None, 76 + StrToken::Error => Some(Err(Simple::custom( 77 + Span::new(path, s.start, s.end), 78 + "Invalid string character", 79 + ))), 80 + }) 81 + .collect() 82 + } 83 + 84 + pub(super) fn literal() -> impl Parser<Token, Spanned<Literal>, Error = Simple<Token, Span>> + Clone 85 + { 86 + select! { 87 + Token::Bool(b), span => Spanned { span, inner: Literal::Bool(b)}, 88 + Token::Num(n), span => Spanned{ span, inner: Literal::Num(n.parse().unwrap()) }, 89 + Token::String(s), span => Spanned{ span, inner: Literal::String(parse_string(&*s, span.context())?) }, 90 + Token::Char(c), span => Spanned { span, inner: Literal::Char(c) }, 91 + } 92 + } 93 + 94 + pub(super) fn literal_expr( 95 + ) -> impl Parser<Token, Spanned<Expr>, Error = Simple<Token, Span>> + Clone { 96 + literal().map(|Spanned { span, inner }| Spanned { 97 + span, 98 + inner: Expr::Literal(inner), 99 + }) 100 + } 101 + 102 + pub(super) fn include_path( 103 + ) -> impl Parser<Token, Spanned<PathBuf>, Error = Simple<Token, Span>> + Clone { 104 + select! { 105 + Token::String(s), span => Spanned { 106 + span, 107 + inner: { 108 + let mut chars = (&*s).chars(); 109 + chars.next(); 110 + chars.next_back(); 111 + PathBuf::from(chars.as_str()) 112 + } 113 + }, 114 + } 115 + } 116 + 117 + pub(super) fn kw_include( 118 + ) -> impl Parser<Token, Spanned<Keyword>, Error = Simple<Token, Span>> + Clone { 119 + select! { 120 + Token::KwInclude, span => Spanned { span, inner: Keyword::Include }, 121 + } 122 + } 123 + 124 + pub(super) fn kw_bind() -> impl Parser<Token, Spanned<Keyword>, Error = Simple<Token, Span>> + Clone 125 + { 126 + select! { 127 + Token::KwBind, span => Spanned { span, inner: Keyword::Bind }, 128 + } 129 + } 130 + pub(super) fn kw_while() -> impl Parser<Token, Spanned<Keyword>, Error = Simple<Token, Span>> + Clone 131 + { 132 + select! { 133 + Token::KwWhile, span => Spanned { span, inner: Keyword::While }, 134 + } 135 + } 136 + pub(super) fn kw_cond() -> impl Parser<Token, Spanned<Keyword>, Error = Simple<Token, Span>> + Clone 137 + { 138 + select! { 139 + Token::KwCond, span => Spanned { span, inner: Keyword::Cond }, 140 + } 141 + } 142 + pub(super) fn kw_if() -> impl Parser<Token, Spanned<Keyword>, Error = Simple<Token, Span>> + Clone { 143 + select! { 144 + Token::KwIf, span => Spanned { span, inner: Keyword::If }, 145 + } 146 + } 147 + pub(super) fn kw_else() -> impl Parser<Token, Spanned<Keyword>, Error = Simple<Token, Span>> + Clone 148 + { 149 + select! { 150 + Token::KwElse, span => Spanned { span, inner: Keyword::Else }, 151 + } 152 + } 153 + pub(super) fn kw_do() -> impl Parser<Token, Spanned<Keyword>, Error = Simple<Token, Span>> + Clone { 154 + select! { 155 + Token::KwDo, span => Spanned { span, inner: Keyword::Do }, 156 + } 157 + } 158 + pub(super) fn kw_end() -> impl Parser<Token, Spanned<Keyword>, Error = Simple<Token, Span>> + Clone 159 + { 160 + select! { 161 + Token::KwEnd, span => Spanned { span, inner: Keyword::End }, 162 + } 163 + } 164 + pub(super) fn kw_ret() -> impl Parser<Token, Spanned<Keyword>, Error = Simple<Token, Span>> + Clone 165 + { 166 + select! { 167 + Token::KwReturn, span => Spanned { span, inner: Keyword::Return }, 168 + } 169 + } 170 + pub(super) fn kw_cast() -> impl Parser<Token, Spanned<Keyword>, Error = Simple<Token, Span>> + Clone 171 + { 172 + select! { 173 + Token::KwCast, span => Spanned { span, inner: Keyword::Cast }, 174 + } 175 + } 176 + pub(super) fn kw_proc() -> impl Parser<Token, Spanned<Keyword>, Error = Simple<Token, Span>> + Clone 177 + { 178 + select! { 179 + Token::KwProc, span => Spanned { span, inner: Keyword::Proc }, 180 + } 181 + } 182 + pub(super) fn kw_const() -> impl Parser<Token, Spanned<Keyword>, Error = Simple<Token, Span>> + Clone 183 + { 184 + select! { 185 + Token::KwConst, span => Spanned { span, inner: Keyword::Const }, 186 + } 187 + } 188 + pub(super) fn kw_mem() -> impl Parser<Token, Spanned<Keyword>, Error = Simple<Token, Span>> + Clone 189 + { 190 + select! { 191 + Token::KwMem, span => Spanned { span, inner: Keyword::Mem }, 192 + } 193 + } 194 + pub(super) fn kw_var() -> impl Parser<Token, Spanned<Keyword>, Error = Simple<Token, Span>> + Clone 195 + { 196 + select! { 197 + Token::KwVar, span => Spanned { span, inner: Keyword::Var }, 198 + } 199 + } 200 + pub(super) fn kw_struct( 201 + ) -> impl Parser<Token, Spanned<Keyword>, Error = Simple<Token, Span>> + Clone { 202 + select! { 203 + Token::KwStruct, span => Spanned { span, inner: Keyword::Struct }, 204 + } 205 + } 206 + 207 + pub(super) fn word() -> impl Parser<Token, Spanned<Word>, Error = Simple<Token, Span>> + Clone { 208 + select! { 209 + Token::Word(w), span => Spanned { span, inner: Word(w) }, 210 + } 211 + } 212 + 213 + pub(super) fn word_expr() -> impl Parser<Token, Spanned<Expr>, Error = Simple<Token, Span>> + Clone 214 + { 215 + select! { 216 + Token::Word(w), span => Spanned { span, inner: Expr::Word(Word(w)) }, 217 + } 218 + } 219 + 220 + pub(super) fn path() -> impl Parser<Token, Spanned<ItemPathBuf>, Error = Simple<Token, Span>> + Clone 221 + { 222 + select! { 223 + Token::Word(w) => w, 224 + } 225 + .separated_by(just(Token::PathSep)) 226 + .at_least(1) 227 + .map_with_span(|ws, span| Spanned { 228 + span, 229 + inner: ItemPathBuf::from(ws), 230 + }) 231 + } 232 + 233 + pub(super) fn path_expr() -> impl Parser<Token, Spanned<Expr>, Error = Simple<Token, Span>> + Clone 234 + { 235 + select! { 236 + Token::Word(w) => w, 237 + } 238 + .separated_by(just(Token::PathSep)) 239 + .at_least(1) 240 + .map_with_span(|ws, span| Spanned { 241 + span, 242 + inner: Expr::Path(ItemPathBuf::from(ws)), 243 + }) 244 + } 245 + 246 + pub(super) fn separator( 247 + ) -> impl Parser<Token, Spanned<Punctuation>, Error = Simple<Token, Span>> + Clone { 248 + select! { 249 + Token::SigSep, span => Spanned { span, inner: Punctuation::Colon }, 250 + } 251 + } 252 + 253 + pub(super) fn var() -> impl Parser<Token, Spanned<Var>, Error = Simple<Token, Span>> + Clone { 254 + kw_var() 255 + .then(word()) 256 + .then(separator()) 257 + .then(ty()) 258 + .map_with_span(|(((var, name), sep), ty), span| Spanned { 259 + span, 260 + inner: Var { var, name, sep, ty }, 261 + }) 262 + } 263 + 264 + pub(super) fn var_toplevel( 265 + ) -> impl Parser<Token, Spanned<TopLevel>, Error = Simple<Token, Span>> + Clone { 266 + var().map(|Spanned { span, inner }| Spanned { 267 + span, 268 + inner: TopLevel::Var(inner), 269 + }) 270 + } 271 + 272 + pub(super) fn var_expr() -> impl Parser<Token, Spanned<Expr>, Error = Simple<Token, Span>> + Clone { 273 + var().map(|Spanned { span, inner }| Spanned { 274 + span, 275 + inner: Expr::Var(inner), 276 + }) 277 + } 278 + 279 + pub(super) fn accessor( 280 + ) -> impl Parser<Token, Spanned<Punctuation>, Error = Simple<Token, Span>> + Clone { 281 + just(Token::FieldAccess).map_with_span(|_, span| Spanned { 282 + span, 283 + inner: Punctuation::RArrow, 284 + }) 285 + } 286 + 287 + pub(super) fn expr<'d>( 288 + ) -> impl Parser<Token, Spanned<Expr>, Error = Simple<Token, Span>> + Clone + 'd { 289 + recursive(|expr: Recursive<'_, Token, Spanned<Expr>, _>| { 290 + let bind = kw_bind() 291 + .then( 292 + name_type_pair() 293 + .map(|b| b.map(Either::Right)) 294 + .or(word().map(|b| b.map(Either::Left))) 295 + .repeated() 296 + .at_least(1), 297 + ) 298 + .then(kw_do()) 299 + .then(expr.clone().repeated()) 300 + .then(kw_end()) 301 + .map_with_span(|((((bind, bindings), do_), body), end), span| Spanned { 302 + span, 303 + inner: Expr::Bind(Bind { 304 + bind, 305 + bindings, 306 + do_, 307 + body, 308 + end, 309 + }), 310 + }); 311 + 312 + let while_ = kw_while() 313 + .then(expr.clone().repeated()) 314 + .then(kw_do()) 315 + .then(expr.clone().repeated()) 316 + .then(kw_end()) 317 + .map_with_span(|((((while_, cond), do_), body), end), span| Spanned { 318 + span, 319 + inner: Expr::While(While { 320 + while_, 321 + cond, 322 + do_, 323 + body, 324 + end, 325 + }), 326 + }); 327 + 328 + let lie = kw_else() 329 + .then(expr.clone().repeated()) 330 + .map(|(else_, body)| Else { else_, body }); 331 + 332 + let if_ = kw_if() 333 + .then(expr.clone().repeated()) 334 + .then(lie.or_not()) 335 + .then(kw_end()) 336 + .map_with_span(|(((if_, truth), lie), end), span| Spanned { 337 + span, 338 + inner: Expr::If(If { 339 + if_, 340 + truth, 341 + lie, 342 + end, 343 + }), 344 + }); 345 + 346 + let cast = kw_cast() 347 + .then(ty()) 348 + .map_with_span(|(cast, ty), span| Spanned { 349 + span, 350 + inner: Expr::Cast(Cast { cast, ty }), 351 + }); 352 + 353 + let pat = choice((literal_expr(), word_expr(), path_expr())); 354 + let cond_branch = kw_else() 355 + .then(pat.clone()) 356 + .then(kw_do()) 357 + .then(expr.clone().repeated()) 358 + .map_with_span(|(((else_, pat), do_), body), span| Spanned { 359 + span, 360 + inner: CondBranch { 361 + else_, 362 + pat, 363 + do_, 364 + body, 365 + }, 366 + }); 367 + 368 + let cond = kw_cond() 369 + .then(pat) 370 + .then(kw_do()) 371 + .then(expr.clone().repeated()) 372 + .then(cond_branch.repeated()) 373 + .then(kw_end()) 374 + .map_with_span( 375 + |(((((cond, pat), do_), body), branches), end), span| Spanned { 376 + span, 377 + inner: Expr::Cond(box Cond { 378 + cond, 379 + pat, 380 + do_, 381 + body, 382 + branches, 383 + end, 384 + }), 385 + }, 386 + ); 387 + 388 + let field_access = accessor() 389 + .then(word()) 390 + .map_with_span(|(access, field), span| Spanned { 391 + span, 392 + inner: Expr::FieldAccess(box FieldAccess { access, field }), 393 + }); 394 + 395 + let ret_expr = kw_ret().map(|Spanned { span, inner }| Spanned { 396 + span, 397 + inner: Expr::Keyword(inner), 398 + }); 399 + 400 + choice(( 401 + literal_expr(), 402 + var_expr(), 403 + path_expr(), 404 + word_expr(), 405 + bind, 406 + while_, 407 + if_, 408 + cond, 409 + cast, 410 + ret_expr, 411 + field_access, 412 + )) 413 + }) 414 + } 415 + 416 + pub(super) fn proc_signature( 417 + ) -> impl Parser<Token, Spanned<ProcSignature>, Error = Simple<Token, Span>> + Clone { 418 + ty().repeated() 419 + .then(separator().then(ty().repeated().at_least(1)).or_not()) 420 + .map_with_span(|(ins, maybe_outs), span| { 421 + let (sep, outs) = if let Some((sep, outs)) = maybe_outs { 422 + (Some(sep), Some(outs)) 423 + } else { 424 + (None, None) 425 + }; 426 + Spanned { 427 + span, 428 + inner: ProcSignature { ins, sep, outs }, 429 + } 430 + }) 431 + } 432 + 433 + pub(super) fn lbracket( 434 + ) -> impl Parser<Token, Spanned<Punctuation>, Error = Simple<Token, Span>> + Clone { 435 + just(Token::LBracket).map_with_span(|_, span| Spanned { 436 + span, 437 + inner: Punctuation::LBracket, 438 + }) 439 + } 440 + pub(super) fn rbracket( 441 + ) -> impl Parser<Token, Spanned<Punctuation>, Error = Simple<Token, Span>> + Clone { 442 + just(Token::RBracket).map_with_span(|_, span| Spanned { 443 + span, 444 + inner: Punctuation::RBracket, 445 + }) 446 + } 447 + 448 + pub(super) fn generics() -> impl Parser<Token, Spanned<Generics>, Error = Simple<Token, Span>> { 449 + lbracket() 450 + .then(word().repeated().at_least(1)) 451 + .then(rbracket()) 452 + .map_with_span(|((left_bracket, tys), right_bracket), span| Spanned { 453 + span, 454 + inner: Generics { 455 + left_bracket, 456 + tys, 457 + right_bracket, 458 + }, 459 + }) 460 + } 461 + 462 + pub(super) fn proc<'d>() -> impl Parser<Token, Spanned<TopLevel>, Error = Simple<Token, Span>> + 'd 463 + { 464 + kw_proc() 465 + .debug("kw_proc") 466 + .then(generics().or_not().debug("Generics")) 467 + .then(word().debug("Proc name")) 468 + .then(proc_signature().debug("Proc signature")) 469 + .then(kw_do().debug("kw_do")) 470 + .then(expr().debug("expr").repeated()) 471 + .then(kw_end().debug("kw_end")) 472 + .map_with_span( 473 + |((((((proc, generics), name), signature), do_), body), end), span| Spanned { 474 + span, 475 + inner: TopLevel::Proc(Proc { 476 + proc, 477 + generics, 478 + name, 479 + signature, 480 + do_, 481 + body, 482 + end, 483 + }), 484 + }, 485 + ) 486 + .debug("proc") 487 + } 488 + 489 + pub(super) fn const_signature( 490 + ) -> impl Parser<Token, Spanned<ConstSignature>, Error = Simple<Token, Span>> + Clone { 491 + separator() 492 + .then(ty().repeated().at_least(1)) 493 + .map_with_span(|(sep, tys), span| Spanned { 494 + span, 495 + inner: ConstSignature { sep, tys }, 496 + }) 497 + } 498 + 499 + pub(super) fn const_<'d>( 500 + ) -> impl Parser<Token, Spanned<TopLevel>, Error = Simple<Token, Span>> + Clone + 'd { 501 + kw_const() 502 + .then(word()) 503 + .then(const_signature()) 504 + .then(kw_do()) 505 + .then(expr().repeated()) 506 + .then(kw_end()) 507 + .map_with_span( 508 + |(((((const_, name), signature), do_), body), end), span| Spanned { 509 + span, 510 + inner: TopLevel::Const(Const { 511 + const_, 512 + name, 513 + signature, 514 + do_, 515 + body, 516 + end, 517 + }), 518 + }, 519 + ) 520 + } 521 + 522 + pub(super) fn mem<'d>( 523 + ) -> impl Parser<Token, Spanned<TopLevel>, Error = Simple<Token, Span>> + Clone + 'd { 524 + kw_mem() 525 + .then(word()) 526 + .then(kw_do()) 527 + .then(expr().repeated()) 528 + .then(kw_end()) 529 + .map_with_span(|((((mem, name), do_), body), end), span| Spanned { 530 + span, 531 + inner: TopLevel::Mem(Mem { 532 + mem, 533 + name, 534 + do_, 535 + body, 536 + end, 537 + }), 538 + }) 539 + } 540 + 541 + pub(super) fn name_type_pair( 542 + ) -> impl Parser<Token, Spanned<NameTypePair>, Error = Simple<Token, Span>> + Clone { 543 + word() 544 + .then(separator()) 545 + .then(ty()) 546 + .map_with_span(|((name, sep), ty), span| Spanned { 547 + span, 548 + inner: NameTypePair { name, sep, ty }, 549 + }) 550 + } 551 + 552 + pub(super) fn struct_() -> impl Parser<Token, Spanned<TopLevel>, Error = Simple<Token, Span>> + Clone 553 + { 554 + kw_struct() 555 + .then(word()) 556 + .then(kw_do()) 557 + .then(name_type_pair().repeated()) 558 + .then(kw_end()) 559 + .map_with_span(|((((struct_, name), do_), body), end), span| Spanned { 560 + span, 561 + inner: TopLevel::Struct(Struct { 562 + struct_, 563 + name, 564 + do_, 565 + body, 566 + end, 567 + }), 568 + }) 569 + } 570 + 571 + pub(super) fn include() -> impl Parser<Token, Spanned<TopLevel>, Error = Simple<Token, Span>> + Clone 572 + { 573 + kw_include() 574 + .then(word().repeated()) 575 + .then(include_path()) 576 + .map_with_span(|((include, qualifiers), path), span| Spanned { 577 + span, 578 + inner: TopLevel::Include(Include { 579 + include, 580 + qualifiers, 581 + path, 582 + }), 583 + }) 584 + } 585 + 586 + pub(super) fn file<'d>() -> impl Parser<Token, File, Error = Simple<Token, Span>> + 'd { 587 + choice(( 588 + include(), 589 + proc(), 590 + const_(), 591 + mem(), 592 + var_toplevel(), 593 + struct_(), 594 + )) 595 + .repeated() 596 + .then_ignore(end()) 597 + .or(end().to(vec![])) 598 + .map(File) 599 + }
+558
rotth-parser/src/hir.rs
··· 1 + use crate::{ 2 + ast::Keyword, 3 + ast::{ 4 + self, Cast, Expr, ItemPathBuf, Literal, ProcSignature, ResolvedFile, ResolvedItem, 5 + ResolvedStruct, Word, 6 + }, 7 + types::{StructIndex, Type}, 8 + }; 9 + use fnv::FnvHashMap; 10 + use smol_str::SmolStr; 11 + use somok::{Either, PartitionThree, Somok, Ternary}; 12 + use spanner::{Span, Spanned}; 13 + 14 + #[derive(Debug, Clone)] 15 + pub enum TopLevel { 16 + Proc(Proc), 17 + Const(Const), 18 + Mem(Mem), 19 + Var(Var), 20 + } 21 + impl TopLevel { 22 + pub fn as_proc(&self) -> Option<&Proc> { 23 + if let Self::Proc(v) = self { 24 + Some(v) 25 + } else { 26 + None 27 + } 28 + } 29 + 30 + pub fn as_const(&self) -> Option<&Const> { 31 + if let Self::Const(v) = self { 32 + Some(v) 33 + } else { 34 + None 35 + } 36 + } 37 + 38 + pub fn as_var(&self) -> Option<&Var> { 39 + if let Self::Var(v) = self { 40 + Some(v) 41 + } else { 42 + None 43 + } 44 + } 45 + pub fn span(&self) -> Span { 46 + match self { 47 + TopLevel::Proc(p) => p.span, 48 + TopLevel::Const(c) => c.span, 49 + TopLevel::Mem(m) => m.span, 50 + TopLevel::Var(v) => v.span, 51 + } 52 + } 53 + } 54 + 55 + #[derive(Debug, Clone)] 56 + pub struct Var { 57 + pub ty: Type, 58 + pub span: Span, 59 + } 60 + 61 + #[derive(Debug, Clone)] 62 + pub struct Proc { 63 + pub generics: Vec<SmolStr>, 64 + pub ins: Vec<Spanned<Type>>, 65 + pub outs: Vec<Spanned<Type>>, 66 + pub body: Vec<Spanned<Hir>>, 67 + pub span: Span, 68 + pub vars: FnvHashMap<SmolStr, Var>, 69 + } 70 + 71 + #[derive(Debug, Clone)] 72 + pub struct Const { 73 + pub outs: Vec<Spanned<Type>>, 74 + pub body: Vec<Spanned<Hir>>, 75 + pub span: Span, 76 + } 77 + 78 + #[derive(Debug, Clone)] 79 + pub struct Mem { 80 + pub body: Vec<Spanned<Hir>>, 81 + pub span: Span, 82 + } 83 + 84 + #[derive(Debug, Clone)] 85 + pub enum Hir { 86 + Path(ItemPathBuf), 87 + Intrinsic(Intrinsic), 88 + Bind(Bind), 89 + While(While), 90 + If(If), 91 + Cond(Cond), 92 + Literal(Literal), 93 + IgnorePattern, 94 + Return, 95 + FieldAccess(FieldAccess), 96 + } 97 + #[derive(Debug, Clone)] 98 + pub struct FieldAccess { 99 + pub field: SmolStr, 100 + } 101 + #[derive(Debug, Clone)] 102 + pub struct If { 103 + pub truth: Vec<Spanned<Hir>>, 104 + pub lie: Option<Vec<Spanned<Hir>>>, 105 + } 106 + 107 + #[derive(Debug, Clone)] 108 + pub struct Cond { 109 + pub branches: Vec<CondBranch>, 110 + } 111 + 112 + #[derive(Debug, Clone)] 113 + pub struct CondBranch { 114 + pub pattern: Spanned<Hir>, 115 + pub body: Vec<Spanned<Hir>>, 116 + } 117 + 118 + #[derive(Debug, Clone)] 119 + pub struct Bind { 120 + pub bindings: Vec<Spanned<Binding>>, 121 + pub body: Vec<Spanned<Hir>>, 122 + } 123 + #[derive(Debug, Clone)] 124 + pub struct While { 125 + pub cond: Vec<Spanned<Hir>>, 126 + pub body: Vec<Spanned<Hir>>, 127 + } 128 + 129 + #[derive(Debug, Clone)] 130 + pub enum Binding { 131 + Ignore, 132 + Bind { name: SmolStr, ty: Option<Type> }, 133 + } 134 + 135 + #[derive(Debug, Clone)] 136 + pub enum Intrinsic { 137 + Drop, 138 + Dup, 139 + Swap, 140 + Over, 141 + 142 + Cast(Spanned<Type>), 143 + 144 + ReadU64, 145 + ReadU8, 146 + WriteU64, 147 + WriteU8, 148 + 149 + CompStop, 150 + Dump, 151 + Print, 152 + 153 + Syscall0, 154 + Syscall1, 155 + Syscall2, 156 + Syscall3, 157 + Syscall4, 158 + Syscall5, 159 + Syscall6, 160 + 161 + Argc, 162 + Argv, 163 + 164 + Add, 165 + Sub, 166 + Divmod, 167 + Mul, 168 + 169 + Eq, 170 + Ne, 171 + Lt, 172 + Le, 173 + Gt, 174 + Ge, 175 + } 176 + 177 + #[derive(Default)] 178 + pub struct Walker { 179 + proc_vars: FnvHashMap<SmolStr, Var>, 180 + current_path: ItemPathBuf, 181 + items: FnvHashMap<ItemPathBuf, TopLevel>, 182 + types: StructIndex, 183 + } 184 + 185 + impl Walker { 186 + pub fn new() -> Self { 187 + Self { 188 + proc_vars: Default::default(), 189 + current_path: Default::default(), 190 + items: Default::default(), 191 + types: Default::default(), 192 + } 193 + } 194 + 195 + fn intrinsic(&mut self, ast: &Spanned<Expr>) -> Option<Spanned<Hir>> { 196 + let word = match &ast.inner { 197 + Expr::Cast(Cast { 198 + cast: _, 199 + ty: Spanned { span, inner: ty }, 200 + }) => { 201 + return Spanned { 202 + span: ast.span, 203 + inner: Hir::Intrinsic(Intrinsic::Cast(Spanned { 204 + span: *span, 205 + inner: ty.clone(), 206 + })), 207 + } 208 + .some() 209 + } 210 + Expr::Path(p) => p.only()?, 211 + Expr::Word(Word(w)) => w.as_str(), 212 + _ => return None, 213 + }; 214 + let intrinsic = match word { 215 + "drop" => Intrinsic::Drop, 216 + "dup" => Intrinsic::Dup, 217 + "swap" => Intrinsic::Swap, 218 + "over" => Intrinsic::Over, 219 + 220 + "@u64" => Intrinsic::ReadU64, 221 + "@u8" => Intrinsic::ReadU8, 222 + "!u64" => Intrinsic::WriteU64, 223 + "!u8" => Intrinsic::WriteU8, 224 + 225 + "&?&" => Intrinsic::CompStop, 226 + "&?" => Intrinsic::Dump, 227 + "print" => Intrinsic::Print, 228 + 229 + "syscall0" => Intrinsic::Syscall0, 230 + "syscall1" => Intrinsic::Syscall1, 231 + "syscall2" => Intrinsic::Syscall2, 232 + "syscall3" => Intrinsic::Syscall3, 233 + "syscall4" => Intrinsic::Syscall4, 234 + "syscall5" => Intrinsic::Syscall5, 235 + "syscall6" => Intrinsic::Syscall6, 236 + 237 + "argc" => Intrinsic::Argc, 238 + "argv" => Intrinsic::Argv, 239 + 240 + "+" => Intrinsic::Add, 241 + "-" => Intrinsic::Sub, 242 + "*" => Intrinsic::Mul, 243 + "divmod" => Intrinsic::Divmod, 244 + 245 + "=" => Intrinsic::Eq, 246 + "!=" => Intrinsic::Ne, 247 + "<" => Intrinsic::Lt, 248 + "<=" => Intrinsic::Le, 249 + ">" => Intrinsic::Gt, 250 + ">=" => Intrinsic::Ge, 251 + _ => return None, 252 + }; 253 + Spanned { 254 + span: ast.span, 255 + inner: Hir::Intrinsic(intrinsic), 256 + } 257 + .some() 258 + } 259 + 260 + pub fn walk_ast( 261 + mut self, 262 + ast: ResolvedFile, 263 + ) -> (FnvHashMap<ItemPathBuf, TopLevel>, StructIndex) { 264 + self.walk_module(ast); 265 + (self.items, self.types) 266 + } 267 + 268 + fn walk_module(&mut self, module: ResolvedFile) { 269 + let (items, structs, modules) = module 270 + .ast 271 + .into_iter() 272 + .partition_three::<FnvHashMap<_, _>, _>(|(_, item)| match &**item { 273 + ResolvedItem::Proc(_) => Ternary::First, 274 + ResolvedItem::Const(_) => Ternary::First, 275 + ResolvedItem::Mem(_) => Ternary::First, 276 + ResolvedItem::Var(_) => Ternary::First, 277 + ResolvedItem::Struct(_) => Ternary::Second, 278 + ResolvedItem::Module(_) => Ternary::Third, 279 + }); 280 + let modules = modules 281 + .into_iter() 282 + .map(|(n, m)| { 283 + ( 284 + n, 285 + match m.inner { 286 + ResolvedItem::Module(box m) => m, 287 + _ => unreachable!(), 288 + }, 289 + ) 290 + }) 291 + .collect::<FnvHashMap<_, _>>(); 292 + let structs = structs 293 + .into_iter() 294 + .map(|(n, m)| { 295 + ( 296 + n, 297 + match m.inner { 298 + ResolvedItem::Struct(s) => s, 299 + _ => unreachable!(), 300 + }, 301 + ) 302 + }) 303 + .collect::<FnvHashMap<_, _>>(); 304 + for (_, module) in modules { 305 + self.walk_module(module); 306 + } 307 + self.current_path = module.path; 308 + for (_, struct_) in structs { 309 + self.walk_struct(struct_); 310 + } 311 + for (name, item) in items { 312 + let item = self.walk_toplevel(item.inner); 313 + let name = self.current_path.child(name); 314 + self.items.insert(name, item); 315 + } 316 + } 317 + 318 + fn walk_struct(&mut self, struct_: ResolvedStruct) { 319 + let ResolvedStruct { name, fields } = struct_; 320 + let Word(name) = name.inner; 321 + let name = self.current_path.child(name); 322 + let mut builder = self.types.new_struct(name); 323 + for (name, ty) in fields { 324 + let span = ty.ty.span; 325 + let ty = ty.inner.ty.inner; 326 + let ty = match ty { 327 + ty @ Type::Primitive(_) | ty @ Type::Ptr(_) => ty, 328 + Type::Custom(type_name) => { 329 + let type_name = self.current_path.join(&type_name); 330 + Type::Custom(type_name) 331 + } 332 + }; 333 + let ty = Spanned { span, inner: ty }; 334 + builder.field(name, ty); 335 + } 336 + builder.finish(); 337 + } 338 + 339 + fn walk_toplevel(&mut self, item: ResolvedItem) -> TopLevel { 340 + match item { 341 + ResolvedItem::Proc(p) => TopLevel::Proc(self.walk_proc(p)), 342 + ResolvedItem::Const(c) => TopLevel::Const(self.walk_const(c)), 343 + ResolvedItem::Mem(m) => TopLevel::Mem(self.walk_mem(m)), 344 + ResolvedItem::Var(v) => { 345 + let ty = v.ty.inner; 346 + TopLevel::Var(Var { 347 + ty, 348 + span: v.name.span, 349 + }) 350 + } 351 + ResolvedItem::Struct(_) => unreachable!(), 352 + ResolvedItem::Module(_) => unreachable!(), 353 + } 354 + } 355 + 356 + fn walk_mem(&mut self, mem: ast::Mem) -> Mem { 357 + let body = mem 358 + .body 359 + .into_iter() 360 + .map(|ast| self.walk_node(ast).unwrap()) 361 + .collect::<Vec<_>>(); 362 + Mem { 363 + body, 364 + span: mem.mem.span.merge(mem.end.span), 365 + } 366 + } 367 + 368 + fn walk_const(&mut self, const_: ast::Const) -> Const { 369 + let outs = const_.signature.inner.tys; 370 + let body = const_ 371 + .body 372 + .into_iter() 373 + .map(|ast| self.walk_node(ast).unwrap()) 374 + .collect::<Vec<_>>(); 375 + Const { 376 + outs, 377 + body, 378 + span: const_.const_.span.merge(const_.end.span), 379 + } 380 + } 381 + 382 + fn walk_proc(&mut self, proc: ast::Proc) -> Proc { 383 + let generics = proc 384 + .generics 385 + .map(|g| { 386 + g.inner.tys.into_iter().map(|ty| { 387 + let Word(ty) = ty.inner; 388 + ty 389 + }) 390 + }) 391 + .into_iter() 392 + .flatten() 393 + .collect::<Vec<_>>(); 394 + 395 + let ProcSignature { ins, sep: _, outs } = proc.signature.inner; 396 + let ins = ins.into_iter().collect(); 397 + let outs = outs 398 + .map(|i| i.into_iter().collect()) 399 + .unwrap_or_else(Vec::new); 400 + 401 + let body = self.walk_body(proc.body); 402 + let mut vars = Default::default(); 403 + std::mem::swap(&mut vars, &mut self.proc_vars); 404 + 405 + Proc { 406 + ins, 407 + outs, 408 + generics, 409 + body, 410 + vars, 411 + span: proc.proc.span.merge(proc.end.span), 412 + } 413 + } 414 + 415 + fn walk_body(&mut self, body: Vec<Spanned<Expr>>) -> Vec<Spanned<Hir>> { 416 + body.into_iter() 417 + .filter_map(|ast| self.walk_node(ast)) 418 + .collect::<Vec<_>>() 419 + } 420 + 421 + fn walk_node(&mut self, node: Spanned<Expr>) -> Option<Spanned<Hir>> { 422 + if let Some(node) = self.intrinsic(&node) { 423 + return node.some(); 424 + } 425 + let hir = match node.inner { 426 + Expr::Bind(bind) => Hir::Bind(self.walk_bind(bind)), 427 + Expr::While(while_) => Hir::While(self.walk_while(while_)), 428 + Expr::If(if_) => Hir::If(self.walk_if(if_)), 429 + Expr::Cond(box cond) => Hir::Cond(self.walk_cond(cond)), 430 + Expr::Cast(_) => unreachable!(), 431 + Expr::Word(Word(w)) => Hir::Path(self.current_path.child(dbg!(w))), 432 + Expr::Literal(l) => Hir::Literal(l), 433 + Expr::Keyword(Keyword::Return) => Hir::Return, 434 + Expr::Var(var) => { 435 + self.walk_var(var); 436 + return None; 437 + } 438 + Expr::FieldAccess(box access) => { 439 + let Word(field) = access.field.inner; 440 + let access = FieldAccess { field }; 441 + Hir::FieldAccess(access) 442 + } 443 + Expr::Path(p) => Hir::Path(self.current_path.join(&p)), 444 + expr => unreachable!("{:?}", expr), 445 + }; 446 + Spanned { 447 + span: node.span, 448 + inner: hir, 449 + } 450 + .some() 451 + } 452 + 453 + fn walk_var(&mut self, var: ast::Var) { 454 + let name = var.name.map(|Word(w)| w); 455 + let ty = var.ty.inner; 456 + let var = Var { 457 + ty, 458 + span: name.span, 459 + }; 460 + self.proc_vars.insert(name.inner, var); 461 + } 462 + 463 + fn walk_bind(&mut self, bind: ast::Bind) -> Bind { 464 + let bindings = bind 465 + .bindings 466 + .into_iter() 467 + .map(|b| { 468 + b.map(|b| match b { 469 + Either::Left(Word(w)) if w == "_" => Binding::Ignore, 470 + Either::Left(Word(w)) => Binding::Bind { name: w, ty: None }, 471 + Either::Right(r) => Binding::Bind { 472 + name: r.name.map(|Word(n)| n).inner, 473 + ty: Some(r.ty.inner), 474 + }, 475 + }) 476 + }) 477 + .collect(); 478 + let body = bind 479 + .body 480 + .into_iter() 481 + .filter_map(|node| self.walk_node(node)) 482 + .collect(); 483 + Bind { bindings, body } 484 + } 485 + 486 + fn walk_cond(&mut self, cond: ast::Cond) -> Cond { 487 + let branches = cond 488 + .branches 489 + .into_iter() 490 + .map(|b| b.map(|b| self.walk_cond_branch(b)).inner) 491 + .collect(); 492 + Cond { branches } 493 + } 494 + 495 + fn walk_cond_branch(&mut self, branch: ast::CondBranch) -> CondBranch { 496 + let pattern = match branch.pat.inner { 497 + Expr::Word(Word(w)) if w == "_" => Spanned { 498 + span: branch.pat.span, 499 + inner: Hir::IgnorePattern, 500 + }, 501 + Expr::Path(p) => { 502 + let path = self.current_path.join(&p); 503 + Spanned { 504 + span: branch.pat.span, 505 + inner: Hir::Path(path), 506 + } 507 + } 508 + Expr::Word(Word(w)) => { 509 + let path = self.current_path.child(w); 510 + Spanned { 511 + span: branch.pat.span, 512 + inner: Hir::Path(path), 513 + } 514 + } 515 + Expr::Literal(l) => Spanned { 516 + span: branch.pat.span, 517 + inner: Hir::Literal(l), 518 + }, 519 + e => unreachable!("{:?}", e), 520 + }; 521 + let body = branch 522 + .body 523 + .into_iter() 524 + .filter_map(|node| self.walk_node(node)) 525 + .collect(); 526 + CondBranch { pattern, body } 527 + } 528 + 529 + fn walk_while(&mut self, while_: ast::While) -> While { 530 + let cond = while_ 531 + .cond 532 + .into_iter() 533 + .filter_map(|node| self.walk_node(node)) 534 + .collect(); 535 + let body = while_ 536 + .body 537 + .into_iter() 538 + .filter_map(|node| self.walk_node(node)) 539 + .collect(); 540 + While { cond, body } 541 + } 542 + 543 + fn walk_if(&mut self, if_: ast::If) -> If { 544 + let truth = if_ 545 + .truth 546 + .into_iter() 547 + .filter_map(|node| self.walk_node(node)) 548 + .collect(); 549 + let lie = if_.lie.map(|lie| { 550 + lie.body 551 + .into_iter() 552 + .filter_map(|node| self.walk_node(node)) 553 + .collect() 554 + }); 555 + 556 + If { truth, lie } 557 + } 558 + }
+45
rotth-parser/src/lib.rs
··· 1 + #![feature(box_patterns, box_syntax)] 2 + #![feature(iter_intersperse)] 3 + #![feature(generic_associated_types)] 4 + #![feature(path_file_prefix)] 5 + 6 + pub mod ast; 7 + pub mod hir; 8 + pub mod types; 9 + 10 + use chumsky::prelude::Simple; 11 + use rotth_lexer::Token; 12 + use spanner::Span; 13 + use thiserror::Error; 14 + 15 + #[derive(Debug, Error)] 16 + #[error("{0:?}")] 17 + pub struct ParserError(pub Vec<Error>); 18 + 19 + impl From<Vec<Simple<Token, Span>>> for ParserError { 20 + fn from(es: Vec<Simple<Token, Span>>) -> Self { 21 + Self(es.into_iter().map(Error::from).collect()) 22 + } 23 + } 24 + #[derive(Debug, Error)] 25 + pub enum Error { 26 + #[error("{0:?}")] 27 + Parser(Simple<Token, Span>), 28 + #[error("{0:?}")] 29 + Redefinition(#[from] Redefinition), 30 + #[error("UnresolvedInclude {0:?}")] 31 + UnresolvedInclude(Span), 32 + } 33 + 34 + impl From<Simple<Token, Span>> for Error { 35 + fn from(e: Simple<Token, Span>) -> Self { 36 + Self::Parser(e) 37 + } 38 + } 39 + 40 + #[derive(Debug, Error)] 41 + #[error("RedefinitionError")] 42 + pub struct Redefinition { 43 + pub redefining_item: Span, 44 + pub redefined_item: Span, 45 + }
+108
rotth-parser/src/types.rs
··· 1 + use crate::ast::{ItemPath, ItemPathBuf}; 2 + use fnv::FnvHashMap; 3 + use smol_str::SmolStr; 4 + use spanner::Spanned; 5 + 6 + #[derive(Clone, Eq, PartialEq)] 7 + pub enum Type { 8 + Ptr(Box<Self>), 9 + Primitive(Primitive), 10 + Custom(ItemPathBuf), 11 + } 12 + 13 + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 14 + pub enum Primitive { 15 + Void, 16 + 17 + Bool, 18 + Char, 19 + 20 + U64, 21 + U32, 22 + U16, 23 + U8, 24 + 25 + I64, 26 + I32, 27 + I16, 28 + I8, 29 + } 30 + 31 + impl std::fmt::Debug for Type { 32 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 33 + match self { 34 + Type::Ptr(box ty) => { 35 + let inner = ty.fmt(f)?; 36 + write!(f, "&>{:?}", inner) 37 + } 38 + Type::Primitive(p) => p.fmt(f), 39 + Type::Custom(s) => s.fmt(f), 40 + } 41 + } 42 + } 43 + 44 + pub struct StructBuilder<'i> { 45 + index: &'i mut StructIndex, 46 + fields: FnvHashMap<SmolStr, Spanned<Type>>, 47 + name: ItemPathBuf, 48 + } 49 + 50 + impl<'i> StructBuilder<'i> { 51 + pub fn field(&mut self, name: SmolStr, ty: Spanned<Type>) -> &mut Self { 52 + self.fields.insert(name, ty); 53 + self 54 + } 55 + 56 + pub fn finish(self) { 57 + let struct_ = Struct { 58 + name: self.name, 59 + fields: self.fields, 60 + }; 61 + self.index.structs.push(struct_); 62 + } 63 + } 64 + 65 + #[derive(Default, Debug, Clone)] 66 + pub struct StructIndex { 67 + structs: Vec<Struct>, 68 + } 69 + 70 + impl StructIndex { 71 + pub fn new_struct(&'_ mut self, name: ItemPathBuf) -> StructBuilder<'_> { 72 + StructBuilder { 73 + index: self, 74 + fields: Default::default(), 75 + name, 76 + } 77 + } 78 + 79 + pub fn get(&self, name: &ItemPath) -> Option<&Struct> { 80 + self.structs.iter().find(|s| s.name == name) 81 + } 82 + } 83 + 84 + impl IntoIterator for StructIndex { 85 + type Item = Struct; 86 + 87 + type IntoIter = std::vec::IntoIter<Self::Item>; 88 + 89 + fn into_iter(self) -> Self::IntoIter { 90 + self.structs.into_iter() 91 + } 92 + } 93 + 94 + impl<'s> IntoIterator for &'s StructIndex { 95 + type Item = &'s Struct; 96 + 97 + type IntoIter = std::slice::Iter<'s, Struct>; 98 + 99 + fn into_iter(self) -> Self::IntoIter { 100 + self.structs.iter() 101 + } 102 + } 103 + 104 + #[derive(Debug, PartialEq, Eq, Clone)] 105 + pub struct Struct { 106 + pub name: ItemPathBuf, 107 + pub fields: FnvHashMap<SmolStr, Spanned<Type>>, 108 + }
+3 -3
rotth-src/core.rh
··· 1 - proc ptr+ &>() u64 : &>() do 2 - swap cast u64 + cast &>() 3 - end 1 + proc [T] ptr+ &>T u64 : &>T do 2 + swap cast u64 + cast &>T 3 + end
+2 -2
rotth-src/examples/generic.rh
··· 1 - proc {T} incptr &>T : &>T do 1 + proc [T] incptr &>T : &>T do 2 2 cast u64 1 + cast &>T 3 3 end 4 4 ··· 7 7 foo cast u64 print 8 8 foo incptr cast u64 print 9 9 0 10 - end 10 + end
+2 -1
rotth-src/examples/redefinition.rh
··· 4 4 end 5 5 6 6 proc puts do 7 - end 7 + std::puts 8 + end
+8
rotth-src/examples/simplegeneric.rh
··· 1 + proc [T] inc T : T do 2 + cast u64 1 + cast T 3 + end 4 + 5 + proc main: u64 do 6 + 1 inc cast u64 print 7 + 0 8 + end
+2 -2
rotth-src/examples/struct.rh
··· 16 16 end 17 17 18 18 proc returns-string: &>String do 19 - var return str: String 19 + var str: String 20 20 "foobar" 21 21 bind n: u64 s: &>char do 22 22 n str -> len !u64 23 23 s cast u64 str -> buf cast &>u64 !u64 24 24 end 25 25 str 26 - end 26 + end
+7 -3
rotth/Cargo.toml
··· 7 7 8 8 [dependencies] 9 9 ariadne = "0.1.5" 10 - chumsky = { git = "https://github.com/zesterer/chumsky.git" } 11 10 somok = "1.5.0" 12 11 clap = { version = "3", features = ["derive"] } 13 12 simplearena = { path = "../simplearena" } 14 13 indoc = "1.0.4" 15 - thiserror = "1.0.30" 16 - fnv = "1.0.7" 14 + fnv = "1.0" 15 + rotth-lexer = { path = "../rotth-lexer" } 16 + rotth-parser = { path = "../rotth-parser" } 17 + spanner = { path = "../spanner" } 18 + chumsky = { git = "https://github.com/zesterer/chumsky.git" } 19 + thiserror = "1.0" 20 + smol_str = "0.1"
-832
rotth/src/ast.rs
··· 1 - #[cfg(test)] 2 - mod test; 3 - 4 - use std::{ 5 - collections::hash_map::Entry, 6 - path::{Path, PathBuf}, 7 - }; 8 - 9 - use crate::{ 10 - iconst::IConst, 11 - lexer::{KeyWord, Token}, 12 - resolver::resolve_include, 13 - span::Span, 14 - types::{self, Primitive, StructIndex, ValueType}, 15 - Error, RedefinitionError, 16 - }; 17 - use chumsky::{prelude::*, Stream}; 18 - use fnv::FnvHashMap; 19 - use somok::Somok; 20 - 21 - #[derive(Debug, Clone)] 22 - pub enum TopLevel { 23 - Proc(Proc), 24 - Const(Const), 25 - Mem(Mem), 26 - Var(ToplevelVar), 27 - Struct(Struct), 28 - Include(Include), 29 - } 30 - 31 - impl TopLevel { 32 - pub fn name(&self) -> Option<String> { 33 - let name_node = match self { 34 - TopLevel::Proc(i) => &i.name, 35 - TopLevel::Const(i) => &i.name, 36 - TopLevel::Mem(i) => &i.name, 37 - TopLevel::Var(i) => &i.name, 38 - TopLevel::Struct(i) => &i.name, 39 - TopLevel::Include(_) => return None, 40 - }; 41 - match &name_node.ast { 42 - AstKind::Word(n) => n.clone().some(), 43 - _ => unreachable!(), 44 - } 45 - } 46 - 47 - pub fn span(&self) -> Span { 48 - match self { 49 - TopLevel::Proc(i) => &i.name, 50 - TopLevel::Const(i) => &i.name, 51 - TopLevel::Mem(i) => &i.name, 52 - TopLevel::Var(i) => &i.name, 53 - TopLevel::Struct(i) => &i.name, 54 - TopLevel::Include(i) => &i.include, 55 - } 56 - .span 57 - .clone() 58 - } 59 - } 60 - 61 - #[derive(Debug, Clone)] 62 - pub struct Proc { 63 - pub proc: AstNode, 64 - pub generics: Option<AstNode>, 65 - pub name: AstNode, 66 - pub signature: AstNode, 67 - pub do_: AstNode, 68 - pub body: AstNode, 69 - pub end: AstNode, 70 - } 71 - 72 - #[derive(Debug, Clone)] 73 - pub struct Mem { 74 - pub mem: AstNode, 75 - pub name: AstNode, 76 - pub do_: AstNode, 77 - pub body: AstNode, 78 - pub end: AstNode, 79 - } 80 - 81 - #[derive(Debug, Clone)] 82 - pub struct ToplevelVar { 83 - pub var: AstNode, 84 - pub name: AstNode, 85 - pub sep: AstNode, 86 - pub ty: AstNode, 87 - } 88 - 89 - #[derive(Debug, Clone)] 90 - pub struct Struct { 91 - pub struct_: AstNode, 92 - pub name: AstNode, 93 - pub do_: AstNode, 94 - pub body: Vec<AstNode>, 95 - pub end: AstNode, 96 - } 97 - 98 - #[derive(Debug, Clone)] 99 - pub struct Const { 100 - pub const_: AstNode, 101 - pub name: AstNode, 102 - pub signature: AstNode, 103 - pub do_: AstNode, 104 - pub body: AstNode, 105 - pub end: AstNode, 106 - } 107 - 108 - #[derive(Debug, Clone)] 109 - pub struct Include { 110 - pub include: AstNode, 111 - pub path: AstNode, 112 - } 113 - 114 - impl Include { 115 - pub fn path(&self) -> &Path { 116 - match &self.path.ast { 117 - AstKind::Path(p) => p, 118 - _ => unreachable!(), 119 - } 120 - } 121 - } 122 - 123 - #[derive(Debug, Clone, PartialEq, Eq, Hash)] 124 - pub struct AstNode { 125 - pub span: Span, 126 - pub ast: AstKind, 127 - } 128 - 129 - #[derive(Debug, Clone, PartialEq, Eq, Hash)] 130 - pub enum AstKind { 131 - KeyWord(KeyWord), 132 - Type(Type), 133 - Separator, 134 - Accessor, 135 - 136 - Bind(Bind), 137 - Binding(Binding), 138 - 139 - While(While), 140 - 141 - If(If), 142 - Cond(Cond), 143 - 144 - Cast(Cast), 145 - 146 - Word(String), 147 - Path(PathBuf), 148 - Literal(IConst), 149 - Pattern(Box<AstNode>), 150 - 151 - LBracket, 152 - RBracket, 153 - Generics(Generics), 154 - ProcSignature(ProcSignature), 155 - ConstSignature(ConstSignature), 156 - 157 - Body(Vec<AstNode>), 158 - StructField(StructField), 159 - Var(Box<Var>), 160 - FieldAccess(Box<FieldAccess>), 161 - } 162 - 163 - #[derive(Debug, Clone, PartialEq, Eq, Hash)] 164 - pub struct Generics { 165 - pub left_bracket: Box<AstNode>, 166 - pub tys: Vec<AstNode>, 167 - pub right_bracket: Box<AstNode>, 168 - } 169 - 170 - #[derive(Debug, Clone, PartialEq, Eq, Hash)] 171 - pub struct FieldAccess { 172 - pub access: AstNode, 173 - pub field: AstNode, 174 - } 175 - 176 - #[derive(Debug, Clone, PartialEq, Eq, Hash)] 177 - pub struct Var { 178 - pub var: AstNode, 179 - pub ret: Option<AstNode>, 180 - pub name: AstNode, 181 - pub sep: AstNode, 182 - pub ty: AstNode, 183 - } 184 - 185 - #[derive(Debug, Clone, PartialEq, Eq, Hash)] 186 - pub struct Type { 187 - pub ptr_count: usize, 188 - pub type_name: String, 189 - } 190 - 191 - impl Type { 192 - pub fn to_primitive_type(self) -> types::Type { 193 - let primitive = match &*self.type_name { 194 - "bool" => Primitive::Bool, 195 - "char" => Primitive::Char, 196 - 197 - "u64" => Primitive::U64, 198 - "u32" => Primitive::U32, 199 - "u16" => Primitive::U16, 200 - "u8" => Primitive::U8, 201 - 202 - "i64" => Primitive::I64, 203 - "i32" => Primitive::I32, 204 - "i16" => Primitive::I16, 205 - "i8" => Primitive::I8, 206 - t => todo!( 207 - "Can only parse primitive types at this time! Type: {} is not primitive", 208 - t 209 - ), 210 - }; 211 - let value_type = ValueType::Primitive(primitive); 212 - let ptr_depth = self.ptr_count; 213 - types::Type { 214 - ptr_depth, 215 - value_type, 216 - } 217 - } 218 - 219 - pub fn to_type(self, structs: &StructIndex) -> Option<types::Type> { 220 - let value_type = match &*self.type_name { 221 - "bool" => ValueType::Primitive(Primitive::Bool), 222 - "char" => ValueType::Primitive(Primitive::Char), 223 - 224 - "u64" => ValueType::Primitive(Primitive::U64), 225 - "u32" => ValueType::Primitive(Primitive::U32), 226 - "u16" => ValueType::Primitive(Primitive::U16), 227 - "u8" => ValueType::Primitive(Primitive::U8), 228 - 229 - "i64" => ValueType::Primitive(Primitive::I64), 230 - "i32" => ValueType::Primitive(Primitive::I32), 231 - "i16" => ValueType::Primitive(Primitive::I16), 232 - "i8" => ValueType::Primitive(Primitive::I8), 233 - n => ValueType::Struct(structs.name_to_id(n)?), 234 - }; 235 - let ptr_depth = self.ptr_count; 236 - types::Type { 237 - ptr_depth, 238 - value_type, 239 - } 240 - .some() 241 - } 242 - } 243 - 244 - #[derive(Debug, Clone, PartialEq, Eq, Hash)] 245 - pub struct ConstSignature { 246 - pub sep: Box<AstNode>, 247 - pub tys: Vec<AstNode>, 248 - } 249 - 250 - #[derive(Debug, Clone, PartialEq, Eq, Hash)] 251 - pub struct ProcSignature { 252 - pub ins: Vec<AstNode>, 253 - pub sep: Option<Box<AstNode>>, 254 - pub outs: Option<Vec<AstNode>>, 255 - } 256 - 257 - #[derive(Debug, Clone, PartialEq, Eq, Hash)] 258 - pub struct StructField { 259 - pub name: Box<AstNode>, 260 - pub sep: Box<AstNode>, 261 - pub ty: Box<AstNode>, 262 - } 263 - 264 - #[derive(Debug, Clone, PartialEq, Eq, Hash)] 265 - pub struct While { 266 - pub while_: Box<AstNode>, 267 - pub cond: Box<AstNode>, 268 - pub do_: Box<AstNode>, 269 - pub body: Box<AstNode>, 270 - pub end: Box<AstNode>, 271 - } 272 - 273 - #[derive(Debug, Clone, PartialEq, Eq, Hash)] 274 - pub struct Cast { 275 - pub cast: Box<AstNode>, 276 - pub ty: Box<AstNode>, 277 - } 278 - 279 - #[derive(Debug, Clone, PartialEq, Eq, Hash)] 280 - pub struct If { 281 - pub if_: Box<AstNode>, 282 - pub truth: Box<AstNode>, 283 - pub lie: Option<Else>, 284 - pub end: Box<AstNode>, 285 - } 286 - 287 - #[derive(Debug, Clone, PartialEq, Eq, Hash)] 288 - pub struct Else { 289 - pub else_: Box<AstNode>, 290 - pub body: Box<AstNode>, 291 - } 292 - 293 - #[derive(Debug, Clone, PartialEq, Eq, Hash)] 294 - pub struct Cond { 295 - pub cond: Box<AstNode>, 296 - pub pat: Box<AstNode>, 297 - pub do_: Box<AstNode>, 298 - pub body: Box<AstNode>, 299 - pub branches: Vec<CondBranch>, 300 - pub end: Box<AstNode>, 301 - } 302 - 303 - #[derive(Debug, Clone, PartialEq, Eq, Hash)] 304 - pub struct CondBranch { 305 - pub else_: Box<AstNode>, 306 - pub pat: Box<AstNode>, 307 - pub do_: Box<AstNode>, 308 - pub body: Box<AstNode>, 309 - } 310 - 311 - #[derive(Debug, Clone, PartialEq, Eq, Hash)] 312 - pub struct Bind { 313 - pub bind: Box<AstNode>, 314 - pub bindings: Vec<AstNode>, 315 - pub do_: Box<AstNode>, 316 - pub body: Box<AstNode>, 317 - pub end: Box<AstNode>, 318 - } 319 - 320 - #[derive(Debug, Clone, PartialEq, Eq, Hash)] 321 - pub enum Binding { 322 - Ignore, 323 - Bind { 324 - name: Box<AstNode>, 325 - sep: Box<AstNode>, 326 - ty: Box<AstNode>, 327 - }, 328 - } 329 - 330 - fn ty() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 331 - just(Token::Ptr) 332 - .repeated() 333 - .then(word()) 334 - .map_with_span(|(ptr, ty), span| AstNode { 335 - span, 336 - ast: AstKind::Type(Type { 337 - ptr_count: ptr.len(), 338 - type_name: coerce_ast!(ty => Word || unreachable!()), 339 - }), 340 - }) 341 - } 342 - fn literal() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 343 - select! { 344 - Token::Bool(b), span => AstNode { span, ast: AstKind::Literal(IConst::Bool(b)) }, 345 - Token::Num(n), span => AstNode { span, ast: AstKind::Literal(IConst::U64(n.parse().unwrap())) }, 346 - Token::Str(s), span => AstNode { span, ast: AstKind::Literal(IConst::Str(s)) }, 347 - Token::Char(c), span => AstNode { span, ast: AstKind::Literal(IConst::Char(c)) }, 348 - } 349 - } 350 - fn include_path() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 351 - select! { 352 - Token::Str(s), span => AstNode { span, ast: AstKind::Path(PathBuf::from(s)) }, 353 - } 354 - } 355 - fn kw_include() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 356 - select! { 357 - Token::KeyWord(kw @ KeyWord::Include), span=> AstNode { span, ast: AstKind::KeyWord(kw) }, 358 - } 359 - } 360 - fn kw_bind() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 361 - select! { 362 - Token::KeyWord(kw @ KeyWord::Bind), span => AstNode { span, ast: AstKind::KeyWord(kw) }, 363 - } 364 - } 365 - fn kw_while() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 366 - select! { 367 - Token::KeyWord(kw @ KeyWord::While), span => AstNode { span, ast: AstKind::KeyWord(kw) }, 368 - } 369 - } 370 - fn kw_cond() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 371 - select! { 372 - Token::KeyWord(kw @ KeyWord::Cond), span => AstNode { span, ast: AstKind::KeyWord(kw) }, 373 - } 374 - } 375 - fn kw_if() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 376 - select! { 377 - Token::KeyWord(kw @ KeyWord::If), span => AstNode { span, ast: AstKind::KeyWord(kw) }, 378 - } 379 - } 380 - fn kw_else() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 381 - select! { 382 - Token::KeyWord(kw @ KeyWord::Else), span => AstNode { span, ast: AstKind::KeyWord(kw) }, 383 - } 384 - } 385 - fn kw_do() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 386 - select! { 387 - Token::KeyWord(kw @ KeyWord::Do), span => AstNode { span, ast: AstKind::KeyWord(kw) }, 388 - } 389 - } 390 - fn kw_end() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 391 - select! { 392 - Token::KeyWord(kw @ KeyWord::End), span => AstNode { span, ast: AstKind::KeyWord(kw) }, 393 - } 394 - } 395 - fn kw_ret() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 396 - select! { 397 - Token::KeyWord(kw @ KeyWord::Return), span => AstNode { span, ast: AstKind::KeyWord(kw) }, 398 - } 399 - } 400 - fn kw_cast() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 401 - select! { 402 - Token::KeyWord(kw @ KeyWord::Cast), span => AstNode { span, ast: AstKind::KeyWord(kw) }, 403 - } 404 - } 405 - fn kw_proc() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 406 - select! { 407 - Token::KeyWord(kw @ KeyWord::Proc), span => AstNode { span, ast: AstKind::KeyWord(kw) }, 408 - } 409 - } 410 - fn kw_const() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 411 - select! { 412 - Token::KeyWord(kw @ KeyWord::Const), span => AstNode { span, ast: AstKind::KeyWord(kw) }, 413 - } 414 - } 415 - fn kw_mem() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 416 - select! { 417 - Token::KeyWord(kw @ KeyWord::Mem), span => AstNode { span, ast: AstKind::KeyWord(kw) }, 418 - } 419 - } 420 - fn kw_var() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 421 - select! { 422 - Token::KeyWord(kw @ KeyWord::Var), span => AstNode { span, ast: AstKind::KeyWord(kw) }, 423 - } 424 - } 425 - fn kw_struct() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 426 - select! { 427 - Token::KeyWord(kw @ KeyWord::Struct), span => AstNode { span, ast: AstKind::KeyWord(kw) }, 428 - } 429 - } 430 - 431 - fn word() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 432 - select! { 433 - Token::Word(w), span => AstNode { span, ast: AstKind::Word(w) }, 434 - } 435 - } 436 - fn separator() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 437 - select! { 438 - Token::SigSep, span => AstNode { span, ast: AstKind::Separator }, 439 - } 440 - } 441 - fn ignore() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 442 - select! { 443 - Token::Ignore, span => AstNode { span, ast: AstKind::Binding(Binding::Ignore) }, 444 - } 445 - } 446 - fn binding() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 447 - let name_type = word() 448 - .then(separator()) 449 - .then(ty()) 450 - .map_with_span(|((name, sep), ty), span| AstNode { 451 - span, 452 - ast: AstKind::Binding(Binding::Bind { 453 - name: name.boxed(), 454 - sep: sep.boxed(), 455 - ty: ty.boxed(), 456 - }), 457 - }); 458 - 459 - choice((name_type, ignore())) 460 - } 461 - 462 - fn var() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 463 - kw_var() 464 - .then(kw_ret().or_not()) 465 - .then(word()) 466 - .then(separator()) 467 - .then(ty()) 468 - .map_with_span(|((((var, ret), name), sep), ty), span| AstNode { 469 - span, 470 - ast: AstKind::Var(box Var { 471 - var, 472 - ret, 473 - name, 474 - sep, 475 - ty, 476 - }), 477 - }) 478 - } 479 - fn accessor() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 480 - just(Token::FieldAccess).map_with_span(|_, span| AstNode { 481 - span, 482 - ast: AstKind::Accessor, 483 - }) 484 - } 485 - 486 - fn field_access() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 487 - accessor() 488 - .then(word()) 489 - .map_with_span(|(access, field), span| AstNode { 490 - span, 491 - ast: AstKind::FieldAccess(box FieldAccess { access, field }), 492 - }) 493 - } 494 - 495 - fn body() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> + Clone { 496 - recursive(|body: Recursive<'_, Token, AstNode, _>| { 497 - let bind = kw_bind() 498 - .then(binding().repeated().at_least(1)) 499 - .then(kw_do()) 500 - .then(body.clone()) 501 - .then(kw_end()) 502 - .map_with_span(|((((bind, bindings), do_), body), end), span| AstNode { 503 - ast: AstKind::Bind(Bind { 504 - bind: bind.boxed(), 505 - bindings, 506 - do_: do_.boxed(), 507 - body: body.boxed(), 508 - end: end.boxed(), 509 - }), 510 - span, 511 - }); 512 - 513 - let while_ = kw_while() 514 - .then(body.clone()) 515 - .then(kw_do()) 516 - .then(body.clone()) 517 - .then(kw_end()) 518 - .map_with_span(|((((while_, cond), do_), body), end), span| AstNode { 519 - ast: AstKind::While(While { 520 - while_: box while_, 521 - cond: box cond, 522 - do_: box do_, 523 - body: box body, 524 - end: box end, 525 - }), 526 - span, 527 - }); 528 - 529 - let lie = kw_else().then(body.clone()).map(|(else_, body)| Else { 530 - else_: box else_, 531 - body: box body, 532 - }); 533 - let if_ = kw_if() 534 - .then(body.clone()) 535 - .then(lie.or_not()) 536 - .then(kw_end()) 537 - .map_with_span(|(((if_, truth), lie), end), span| AstNode { 538 - span, 539 - ast: AstKind::If(If { 540 - if_: box if_, 541 - truth: box truth, 542 - lie, 543 - end: box end, 544 - }), 545 - }); 546 - 547 - let cast = kw_cast() 548 - .then(ty()) 549 - .map_with_span(|(cast, ty), span| AstNode { 550 - span, 551 - ast: AstKind::Cast(Cast { 552 - cast: box cast, 553 - ty: box ty, 554 - }), 555 - }); 556 - 557 - let pat = choice((literal(), ignore(), word())); 558 - let cond_branch = kw_else().then(pat).then(kw_do()).then(body.clone()).map( 559 - |(((else_, pat), do_), body)| CondBranch { 560 - else_: box else_, 561 - pat: box pat, 562 - do_: box do_, 563 - body: box body, 564 - }, 565 - ); 566 - let pat = choice((literal(), ignore(), word())); 567 - let cond = kw_cond() 568 - .then(pat) 569 - .then(kw_do()) 570 - .then(body.clone()) 571 - .then(cond_branch.repeated()) 572 - .then(kw_end()) 573 - .map_with_span( 574 - |(((((cond, pat), do_), body), branches), end), span| AstNode { 575 - span, 576 - ast: AstKind::Cond(Cond { 577 - cond: box cond, 578 - pat: box pat, 579 - do_: box do_, 580 - body: box body, 581 - branches, 582 - end: box end, 583 - }), 584 - }, 585 - ); 586 - 587 - choice(( 588 - field_access(), 589 - literal(), 590 - var(), 591 - word(), 592 - bind, 593 - while_, 594 - if_, 595 - cond, 596 - cast, 597 - kw_ret(), 598 - )) 599 - .repeated() 600 - .map_with_span(|body, span| AstNode { 601 - span, 602 - ast: AstKind::Body(body), 603 - }) 604 - }) 605 - } 606 - 607 - fn proc_signature() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 608 - ty().repeated() 609 - .then(separator().then(ty().repeated().at_least(1)).or_not()) 610 - .map_with_span(|(ins, maybe_outs), span| { 611 - let (sep, outs) = if let Some((sep, outs)) = maybe_outs { 612 - (Some(box sep), Some(outs)) 613 - } else { 614 - (None, None) 615 - }; 616 - AstNode { 617 - span, 618 - ast: AstKind::ProcSignature(ProcSignature { ins, sep, outs }), 619 - } 620 - }) 621 - } 622 - 623 - fn lbracket() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 624 - just(Token::LBracket).map_with_span(|_, span| AstNode { 625 - span, 626 - ast: AstKind::LBracket, 627 - }) 628 - } 629 - fn rbracket() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 630 - just(Token::RBracket).map_with_span(|_, span| AstNode { 631 - span, 632 - ast: AstKind::RBracket, 633 - }) 634 - } 635 - 636 - fn generics() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 637 - lbracket() 638 - .then(word().repeated().at_least(1)) 639 - .then(rbracket()) 640 - .map_with_span(|((left_bracket, tys), right_bracket), span| AstNode { 641 - span, 642 - ast: AstKind::Generics(Generics { 643 - left_bracket: box left_bracket, 644 - tys, 645 - right_bracket: box right_bracket, 646 - }), 647 - }) 648 - } 649 - 650 - fn proc() -> impl Parser<Token, TopLevel, Error = Simple<Token, Span>> { 651 - kw_proc() 652 - .then(generics().or_not()) 653 - .then(word()) 654 - .then(proc_signature()) 655 - .then(kw_do()) 656 - .then(body()) 657 - .then(kw_end()) 658 - .map( 659 - |((((((proc, generics), name), signature), do_), body), end)| { 660 - TopLevel::Proc(Proc { 661 - proc, 662 - generics, 663 - name, 664 - signature, 665 - do_, 666 - body, 667 - end, 668 - }) 669 - }, 670 - ) 671 - } 672 - 673 - fn const_signature() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 674 - separator() 675 - .then(ty().repeated().at_least(1)) 676 - .map_with_span(|(sep, tys), span| AstNode { 677 - span, 678 - ast: AstKind::ConstSignature(ConstSignature { sep: box sep, tys }), 679 - }) 680 - } 681 - 682 - fn const_() -> impl Parser<Token, TopLevel, Error = Simple<Token, Span>> { 683 - kw_const() 684 - .then(word()) 685 - .then(const_signature()) 686 - .then(kw_do()) 687 - .then(body()) 688 - .then(kw_end()) 689 - .map(|(((((const_, name), signature), do_), body), end)| { 690 - TopLevel::Const(Const { 691 - const_, 692 - name, 693 - signature, 694 - do_, 695 - body, 696 - end, 697 - }) 698 - }) 699 - } 700 - 701 - fn mem() -> impl Parser<Token, TopLevel, Error = Simple<Token, Span>> { 702 - kw_mem() 703 - .then(word()) 704 - .then(kw_do()) 705 - .then(body()) 706 - .then(kw_end()) 707 - .map(|((((mem, name), do_), body), end)| { 708 - TopLevel::Mem(Mem { 709 - mem, 710 - name, 711 - do_, 712 - body, 713 - end, 714 - }) 715 - }) 716 - } 717 - 718 - fn toplevel_var() -> impl Parser<Token, TopLevel, Error = Simple<Token, Span>> { 719 - kw_var() 720 - .then(word()) 721 - .then(separator()) 722 - .then(ty()) 723 - .map(|(((var, name), sep), ty)| TopLevel::Var(ToplevelVar { var, name, sep, ty })) 724 - } 725 - 726 - fn struct_field() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 727 - word() 728 - .then(separator()) 729 - .then(ty()) 730 - .map_with_span(|((name, sep), ty), span| AstNode { 731 - span, 732 - ast: AstKind::StructField(StructField { 733 - name: box name, 734 - sep: box sep, 735 - ty: box ty, 736 - }), 737 - }) 738 - } 739 - fn struct_() -> impl Parser<Token, TopLevel, Error = Simple<Token, Span>> { 740 - kw_struct() 741 - .then(word()) 742 - .then(kw_do()) 743 - .then(struct_field().repeated()) 744 - .then(kw_end()) 745 - .map(|((((struct_, name), do_), body), end)| { 746 - TopLevel::Struct(Struct { 747 - struct_, 748 - name, 749 - do_, 750 - body, 751 - end, 752 - }) 753 - }) 754 - } 755 - 756 - fn include() -> impl Parser<Token, TopLevel, Error = Simple<Token, Span>> { 757 - kw_include() 758 - .then(include_path()) 759 - .map(|(include, path)| TopLevel::Include(Include { include, path })) 760 - } 761 - 762 - fn toplevel() -> impl Parser<Token, Vec<TopLevel>, Error = Simple<Token, Span>> { 763 - choice(( 764 - include(), 765 - proc(), 766 - const_(), 767 - mem(), 768 - toplevel_var(), 769 - struct_(), 770 - )) 771 - .repeated() 772 - .then_ignore(end()) 773 - .or(end().to(vec![])) 774 - } 775 - 776 - pub fn parse_no_include(tokens: Vec<(Token, Span)>) -> Result<Vec<TopLevel>, Error> { 777 - toplevel() 778 - .parse(Stream::from_iter( 779 - tokens 780 - .last() 781 - .map(|(_, s)| s.clone()) 782 - .unwrap_or_else(|| Span::point("", 0)), 783 - tokens.into_iter(), 784 - )) 785 - .map_err(Error::Parser) 786 - } 787 - 788 - pub fn parse(tokens: Vec<(Token, Span)>) -> Result<FnvHashMap<String, TopLevel>, Error> { 789 - let items = match toplevel().parse(Stream::from_iter( 790 - tokens.last().unwrap().1.clone(), 791 - tokens.into_iter(), 792 - )) { 793 - Ok(items) => items, 794 - Err(es) => return Error::Parser(es).error(), 795 - }; 796 - 797 - let (includes, mut items) = items 798 - .into_iter() 799 - .partition::<Vec<_>, _>(|item| matches!(item, TopLevel::Include(_))); 800 - 801 - for include in includes { 802 - if let TopLevel::Include(include) = include { 803 - resolve_include(&include.path.span.file, include.path(), &mut items)?; 804 - } else { 805 - unreachable!(); 806 - } 807 - } 808 - 809 - let mut res = FnvHashMap::default(); 810 - let mut errors = Vec::new(); 811 - 812 - for item in items { 813 - match res.entry(item.name().unwrap()) { 814 - Entry::Occupied(it) => { 815 - let redefined: &TopLevel = it.get(); 816 - errors.push(RedefinitionError { 817 - redefining_item: item.span(), 818 - redefined_item: redefined.span(), 819 - }); 820 - } 821 - Entry::Vacant(v) => { 822 - v.insert(item); 823 - } 824 - } 825 - } 826 - 827 - if errors.is_empty() { 828 - res.okay() 829 - } else { 830 - Error::Redefinition(errors).error() 831 - } 832 - }
-190
rotth/src/ast/test.rs
··· 1 - use super::*; 2 - use crate::lexer::lex_string; 3 - use chumsky::{Parser, Stream}; 4 - use std::assert_matches::assert_matches; 5 - 6 - #[test] 7 - fn test_body() { 8 - let tokens = lex_string( 9 - indoc::indoc! {r#" 10 - 0 while dup 15 <= do 11 - bind i: u64 do 12 - i 3 mod 13 - 0 = dup if "Foo" puts end 14 - i 5 mod 15 - 0 = dup if "Bar" puts end 16 - or not if i putu end 17 - "\n" puts 18 - i 1 + 19 - end 20 - end drop 21 - 0 22 - "#} 23 - .into(), 24 - "./".try_into().unwrap(), 25 - ) 26 - .unwrap(); 27 - let ast = body().then_ignore(end()).parse(Stream::from_iter( 28 - tokens.last().unwrap().1.clone(), 29 - tokens.into_iter(), 30 - )); 31 - assert_matches!( 32 - ast, 33 - Ok(AstNode { 34 - span: _, 35 - ast: AstKind::Body(_) 36 - }) 37 - ) 38 - } 39 - #[test] 40 - fn test_const() { 41 - let tokens = lex_string( 42 - indoc::indoc! {r#" 43 - const FOO: u64 do 1 end 44 - "#} 45 - .into(), 46 - "./".try_into().unwrap(), 47 - ) 48 - .unwrap(); 49 - let ast = const_().then_ignore(end()).parse(Stream::from_iter( 50 - tokens.last().unwrap().1.clone(), 51 - tokens.into_iter(), 52 - )); 53 - assert_matches!( 54 - ast, 55 - Ok(TopLevel::Const(Const { 56 - const_: _, 57 - name: _, 58 - signature: _, 59 - do_: _, 60 - body: _, 61 - end: _, 62 - })) 63 - ) 64 - } 65 - #[test] 66 - fn test_mem() { 67 - let tokens = lex_string( 68 - indoc::indoc! {r#" 69 - mem FOO do 1 end 70 - "#} 71 - .into(), 72 - "./".try_into().unwrap(), 73 - ) 74 - .unwrap(); 75 - let ast = mem().then_ignore(end()).parse(Stream::from_iter( 76 - tokens.last().unwrap().1.clone(), 77 - tokens.into_iter(), 78 - )); 79 - assert_matches!( 80 - ast, 81 - Ok(TopLevel::Mem(Mem { 82 - mem: _, 83 - name: _, 84 - do_: _, 85 - body: _, 86 - end: _, 87 - })) 88 - ) 89 - } 90 - #[test] 91 - fn test_include() { 92 - let tokens = lex_string( 93 - indoc::indoc! {r#" 94 - include "./foo.rh" 95 - "#} 96 - .into(), 97 - "./".try_into().unwrap(), 98 - ) 99 - .unwrap(); 100 - let ast = include().then_ignore(end()).parse(Stream::from_iter( 101 - tokens.last().unwrap().1.clone(), 102 - tokens.into_iter(), 103 - )); 104 - assert_matches!( 105 - ast, 106 - Ok(TopLevel::Include(Include { 107 - include: _, 108 - path: _ 109 - })) 110 - ) 111 - } 112 - #[test] 113 - fn test_proc() { 114 - let tokens = lex_string( 115 - indoc::indoc! {r#" 116 - proc {T} foo u64 : u64 do 117 - 1 + 118 - end 119 - "#} 120 - .into(), 121 - "./".try_into().unwrap(), 122 - ) 123 - .unwrap(); 124 - let ast = proc().then_ignore(end()).parse(Stream::from_iter( 125 - tokens.last().unwrap().1.clone(), 126 - tokens.into_iter(), 127 - )); 128 - assert_matches!( 129 - ast, 130 - Ok(TopLevel::Proc(Proc { 131 - proc: _, 132 - generics: _, 133 - name: _, 134 - signature: _, 135 - do_: _, 136 - body: _, 137 - end: _ 138 - })) 139 - ) 140 - } 141 - #[test] 142 - fn test_struct() { 143 - let tokens = lex_string( 144 - indoc::indoc! {r#" 145 - struct foo do 146 - field: u64 147 - field2: u64 148 - end 149 - "#} 150 - .into(), 151 - "./".try_into().unwrap(), 152 - ) 153 - .unwrap(); 154 - let ast = struct_().then_ignore(end()).parse(Stream::from_iter( 155 - tokens.last().unwrap().1.clone(), 156 - tokens.into_iter(), 157 - )); 158 - assert_matches!( 159 - ast, 160 - Ok(TopLevel::Struct(Struct { 161 - struct_: _, 162 - name: _, 163 - do_: _, 164 - body: _, 165 - end: _ 166 - })) 167 - ) 168 - } 169 - #[test] 170 - fn test_ty() { 171 - let tokens = lex_string( 172 - indoc::indoc! {r#" 173 - &>char 174 - "#} 175 - .into(), 176 - "./".try_into().unwrap(), 177 - ) 178 - .unwrap(); 179 - let ast = ty().then_ignore(end()).parse(Stream::from_iter( 180 - tokens.last().unwrap().1.clone(), 181 - tokens.into_iter(), 182 - )); 183 - assert_matches!( 184 - ast, 185 - Ok(AstNode { 186 - span: _, 187 - ast: AstKind::Type(_) 188 - }) 189 - ) 190 - }
+5
rotth/src/ctir.rs
··· 1 + pub struct Walker {} 2 + 3 + impl Walker { 4 + pub fn walk() {} 5 + }
-540
rotth/src/hir.rs
··· 1 - use crate::{ 2 - ast::{self, AstKind, AstNode, Cast}, 3 - iconst::IConst, 4 - lexer::KeyWord, 5 - span::Span, 6 - types::{StructId, StructIndex}, 7 - }; 8 - use fnv::FnvHashMap; 9 - use somok::Somok; 10 - 11 - #[derive(Debug, Clone)] 12 - pub enum TopLevel { 13 - Proc(Proc), 14 - Const(Const), 15 - Mem(Mem), 16 - Var(TopLevelVar), 17 - } 18 - impl TopLevel { 19 - pub fn as_proc(&self) -> Option<&Proc> { 20 - if let Self::Proc(v) = self { 21 - Some(v) 22 - } else { 23 - None 24 - } 25 - } 26 - 27 - pub fn as_const(&self) -> Option<&Const> { 28 - if let Self::Const(v) = self { 29 - Some(v) 30 - } else { 31 - None 32 - } 33 - } 34 - 35 - pub fn as_var(&self) -> Option<&TopLevelVar> { 36 - if let Self::Var(v) = self { 37 - Some(v) 38 - } else { 39 - None 40 - } 41 - } 42 - pub fn span(&self) -> Span { 43 - match self { 44 - TopLevel::Proc(p) => p.span.clone(), 45 - TopLevel::Const(c) => c.span.clone(), 46 - TopLevel::Mem(m) => m.span.clone(), 47 - TopLevel::Var(v) => v.span.clone(), 48 - } 49 - } 50 - } 51 - 52 - #[derive(Debug, Clone)] 53 - pub struct TopLevelVar { 54 - pub ty: ast::Type, 55 - pub span: Span, 56 - } 57 - 58 - #[derive(Debug, Clone)] 59 - pub struct Proc { 60 - pub generics: Vec<String>, 61 - pub ins: Vec<HirNode>, 62 - pub outs: Vec<HirNode>, 63 - pub body: Vec<HirNode>, 64 - pub span: Span, 65 - pub vars: FnvHashMap<String, Var>, 66 - } 67 - 68 - #[derive(Debug, Clone)] 69 - pub struct Const { 70 - pub outs: Vec<HirNode>, 71 - pub body: Vec<HirNode>, 72 - pub span: Span, 73 - } 74 - 75 - #[derive(Debug, Clone)] 76 - pub struct Mem { 77 - pub body: Vec<HirNode>, 78 - pub span: Span, 79 - } 80 - 81 - #[derive(Debug, Clone)] 82 - pub struct HirNode { 83 - pub span: Span, 84 - pub hir: HirKind, 85 - } 86 - 87 - #[derive(Debug, Clone)] 88 - pub enum HirKind { 89 - Word(String), 90 - Intrinsic(Intrinsic), 91 - Bind(Bind), 92 - While(While), 93 - If(If), 94 - Cond(Cond), 95 - Literal(IConst), 96 - IgnorePattern, 97 - Return, 98 - FieldAccess(FieldAccess), 99 - Type(ast::Type), 100 - } 101 - #[derive(Debug, Clone)] 102 - pub struct FieldAccess { 103 - pub ty: Option<StructId>, 104 - pub field: String, 105 - } 106 - #[derive(Debug, Clone)] 107 - pub struct If { 108 - pub truth: Vec<HirNode>, 109 - pub lie: Option<Vec<HirNode>>, 110 - } 111 - 112 - #[derive(Debug, Clone)] 113 - pub struct Cond { 114 - pub branches: Vec<CondBranch>, 115 - } 116 - 117 - #[derive(Debug, Clone)] 118 - pub struct CondBranch { 119 - pub pattern: HirNode, 120 - pub body: Vec<HirNode>, 121 - } 122 - 123 - #[derive(Debug, Clone)] 124 - pub struct Bind { 125 - pub bindings: Vec<Binding>, 126 - pub body: Vec<HirNode>, 127 - } 128 - #[derive(Debug, Clone)] 129 - pub struct While { 130 - pub cond: Vec<HirNode>, 131 - pub body: Vec<HirNode>, 132 - } 133 - 134 - #[derive(Debug, Clone)] 135 - pub enum Binding { 136 - Ignore, 137 - Bind { name: String, ty: Box<HirNode> }, 138 - } 139 - 140 - #[derive(Debug, Clone)] 141 - pub enum Intrinsic { 142 - Drop, 143 - Dup, 144 - Swap, 145 - Over, 146 - 147 - Cast(Box<HirNode>), 148 - 149 - ReadU64, 150 - ReadU8, 151 - WriteU64, 152 - WriteU8, 153 - 154 - CompStop, 155 - Dump, 156 - Print, 157 - 158 - Syscall0, 159 - Syscall1, 160 - Syscall2, 161 - Syscall3, 162 - Syscall4, 163 - Syscall5, 164 - Syscall6, 165 - 166 - Argc, 167 - Argv, 168 - 169 - Add, 170 - Sub, 171 - Divmod, 172 - Mul, 173 - 174 - Eq, 175 - Ne, 176 - Lt, 177 - Le, 178 - Gt, 179 - Ge, 180 - } 181 - 182 - #[derive(Debug, Clone)] 183 - pub struct Var { 184 - pub ty: HirNode, 185 - pub escaping: bool, 186 - } 187 - 188 - pub struct Walker<'s> { 189 - structs: &'s StructIndex, 190 - proc_vars: FnvHashMap<String, Var>, 191 - } 192 - 193 - impl<'s> Walker<'s> { 194 - pub fn new(structs: &'s StructIndex) -> Self { 195 - Self { 196 - structs, 197 - proc_vars: Default::default(), 198 - } 199 - } 200 - 201 - fn intrinsic(&mut self, ast: &AstNode) -> Option<HirNode> { 202 - let intrinsic = match &ast.ast { 203 - AstKind::Cast(Cast { 204 - cast: _, 205 - ty: 206 - box AstNode { 207 - span, 208 - ast: AstKind::Type(ty), 209 - }, 210 - }) => Intrinsic::Cast(box HirNode { 211 - span: span.clone(), 212 - hir: HirKind::Type(ty.clone()), 213 - }), 214 - AstKind::Word(ref w) => match w.as_str() { 215 - "drop" => Intrinsic::Drop, 216 - "dup" => Intrinsic::Dup, 217 - "swap" => Intrinsic::Swap, 218 - "over" => Intrinsic::Over, 219 - 220 - "@u64" => Intrinsic::ReadU64, 221 - "@u8" => Intrinsic::ReadU8, 222 - "!u64" => Intrinsic::WriteU64, 223 - "!u8" => Intrinsic::WriteU8, 224 - 225 - "&?&" => Intrinsic::CompStop, 226 - "&?" => Intrinsic::Dump, 227 - "print" => Intrinsic::Print, 228 - 229 - "syscall0" => Intrinsic::Syscall0, 230 - "syscall1" => Intrinsic::Syscall1, 231 - "syscall2" => Intrinsic::Syscall2, 232 - "syscall3" => Intrinsic::Syscall3, 233 - "syscall4" => Intrinsic::Syscall4, 234 - "syscall5" => Intrinsic::Syscall5, 235 - "syscall6" => Intrinsic::Syscall6, 236 - 237 - "argc" => Intrinsic::Argc, 238 - "argv" => Intrinsic::Argv, 239 - 240 - "+" => Intrinsic::Add, 241 - "-" => Intrinsic::Sub, 242 - "*" => Intrinsic::Mul, 243 - "divmod" => Intrinsic::Divmod, 244 - 245 - "=" => Intrinsic::Eq, 246 - "!=" => Intrinsic::Ne, 247 - "<" => Intrinsic::Lt, 248 - "<=" => Intrinsic::Le, 249 - ">" => Intrinsic::Gt, 250 - ">=" => Intrinsic::Ge, 251 - _ => return None, 252 - }, 253 - _ => return None, 254 - }; 255 - HirNode { 256 - span: ast.span.clone(), 257 - hir: HirKind::Intrinsic(intrinsic), 258 - } 259 - .some() 260 - } 261 - 262 - fn hir_bindings(&mut self, bindings: Vec<AstNode>) -> Vec<Binding> { 263 - let mut res = Vec::with_capacity(bindings.len()); 264 - for binding in bindings { 265 - if let AstKind::Binding(binding) = binding.ast { 266 - match binding { 267 - ast::Binding::Ignore => res.push(Binding::Ignore), 268 - ast::Binding::Bind { 269 - name: 270 - box AstNode { 271 - span: _, 272 - ast: AstKind::Word(name), 273 - }, 274 - sep: _, 275 - ty: 276 - box AstNode { 277 - span, 278 - ast: AstKind::Type(ty), 279 - }, 280 - } => res.push(Binding::Bind { 281 - name, 282 - ty: box HirNode { 283 - span, 284 - hir: HirKind::Type(ty), 285 - }, 286 - }), 287 - _ => unreachable!(), 288 - } 289 - } else { 290 - unreachable!() 291 - } 292 - } 293 - res 294 - } 295 - 296 - pub fn walk_ast( 297 - &mut self, 298 - ast: FnvHashMap<String, ast::TopLevel>, 299 - ) -> FnvHashMap<String, TopLevel> { 300 - ast.into_iter() 301 - .map(|(name, item)| (name, self.walk_toplevel(item))) 302 - .collect() 303 - } 304 - 305 - fn walk_toplevel(&mut self, item: ast::TopLevel) -> TopLevel { 306 - match item { 307 - ast::TopLevel::Proc(p) => TopLevel::Proc(self.walk_proc(p)), 308 - ast::TopLevel::Const(c) => TopLevel::Const(self.walk_const(c)), 309 - ast::TopLevel::Mem(m) => TopLevel::Mem(self.walk_mem(m)), 310 - ast::TopLevel::Var(v) => { 311 - let ty = coerce_ast!(v.ty => Type || unreachable!()); 312 - TopLevel::Var(TopLevelVar { 313 - ty, 314 - span: v.name.span, 315 - }) 316 - } 317 - _ => unreachable!(), 318 - } 319 - } 320 - 321 - fn walk_mem(&mut self, mem: ast::Mem) -> Mem { 322 - let body = coerce_ast!(mem.body => Body || unreachable!()) 323 - .into_iter() 324 - .map(|ast| self.walk_node(ast).unwrap()) 325 - .collect::<Vec<_>>(); 326 - Mem { 327 - body, 328 - span: mem.mem.span.merge(mem.end.span), 329 - } 330 - } 331 - 332 - fn walk_const(&mut self, const_: ast::Const) -> Const { 333 - let outs = coerce_ast!(const_.signature => ConstSignature || unreachable!()) 334 - .tys 335 - .into_iter() 336 - .map(|ty| { 337 - let span = ty.span; 338 - let ty = coerce_ast!(ty => Type || unreachable!()); 339 - HirNode { 340 - span, 341 - hir: HirKind::Type(ty), 342 - } 343 - }) 344 - .collect(); 345 - let body = coerce_ast!(const_.body => Body || unreachable!()) 346 - .into_iter() 347 - .map(|ast| self.walk_node(ast).unwrap()) 348 - .collect::<Vec<_>>(); 349 - Const { 350 - outs, 351 - body, 352 - span: const_.const_.span.merge(const_.end.span), 353 - } 354 - } 355 - 356 - fn walk_proc(&mut self, proc: ast::Proc) -> Proc { 357 - let generics = proc 358 - .generics 359 - .map(|g| { 360 - coerce_ast!(g => Generics || unreachable!()) 361 - .tys 362 - .into_iter() 363 - .map(|ty| coerce_ast!(ty => Word || unreachable!())) 364 - }) 365 - .into_iter() 366 - .flatten() 367 - .collect::<Vec<_>>(); 368 - 369 - let (ins, outs) = match proc.signature.ast { 370 - AstKind::ProcSignature(signature) => self.walk_proc_signature(signature), 371 - _ => unreachable!(), 372 - }; 373 - 374 - let body = self.try_walk_body(proc.body); 375 - let mut vars = Default::default(); 376 - std::mem::swap(&mut vars, &mut self.proc_vars); 377 - 378 - Proc { 379 - ins, 380 - outs, 381 - generics, 382 - body: body.unwrap(), 383 - vars, 384 - span: proc.proc.span.merge(proc.end.span), 385 - } 386 - } 387 - 388 - fn try_walk_body(&mut self, node: AstNode) -> Option<Vec<HirNode>> { 389 - let body = coerce_ast!(node => Body || None)?; 390 - body.into_iter() 391 - .filter_map(|ast| self.walk_node(ast)) 392 - .collect::<Vec<_>>() 393 - .some() 394 - } 395 - 396 - fn walk_node(&mut self, node: AstNode) -> Option<HirNode> { 397 - if let Some(node) = self.intrinsic(&node) { 398 - return node.some(); 399 - } 400 - let hir = match node.ast { 401 - AstKind::Bind(bind) => HirKind::Bind(self.walk_bind(bind)), 402 - AstKind::While(while_) => HirKind::While(self.walk_while(while_)), 403 - AstKind::If(if_) => HirKind::If(self.walk_if(if_)), 404 - AstKind::Cond(cond) => HirKind::Cond(self.walk_cond(cond)), 405 - AstKind::Cast(_) => unreachable!(), 406 - AstKind::Word(w) => HirKind::Word(w), 407 - AstKind::Literal(l) => HirKind::Literal(l), 408 - AstKind::KeyWord(KeyWord::Return) => HirKind::Return, 409 - AstKind::Var(box var) => { 410 - self.walk_var(var); 411 - return None; 412 - } 413 - AstKind::FieldAccess(box access) => { 414 - let access = FieldAccess { 415 - ty: None, 416 - field: coerce_ast!(access.field => Word || unreachable!()), 417 - }; 418 - HirKind::FieldAccess(access) 419 - } 420 - shouldnt_happen => todo!("{:?}", shouldnt_happen), 421 - }; 422 - HirNode { 423 - span: node.span, 424 - hir, 425 - } 426 - .some() 427 - } 428 - 429 - fn walk_var(&mut self, var: ast::Var) { 430 - let name = coerce_ast!(var.name => Word || unreachable!()); 431 - let escaping = var.ret.is_some(); 432 - let span = var.ty.span; 433 - let ty = coerce_ast!(var.ty => Type || unreachable!()); 434 - let var = Var { 435 - ty: HirNode { 436 - span, 437 - hir: HirKind::Type(ty), 438 - }, 439 - escaping, 440 - }; 441 - self.proc_vars.insert(name, var); 442 - } 443 - 444 - fn walk_bind(&mut self, bind: ast::Bind) -> Bind { 445 - let bindings = self.hir_bindings(bind.bindings); 446 - let body = coerce_ast!(bind.body => Body || unreachable!()) 447 - .into_iter() 448 - .filter_map(|node| self.walk_node(node)) 449 - .collect(); 450 - Bind { bindings, body } 451 - } 452 - 453 - fn walk_cond(&mut self, cond: ast::Cond) -> Cond { 454 - let branches = cond 455 - .branches 456 - .into_iter() 457 - .map(|b| self.walk_cond_branch(b)) 458 - .collect(); 459 - Cond { branches } 460 - } 461 - 462 - fn walk_cond_branch(&mut self, branch: ast::CondBranch) -> CondBranch { 463 - let pattern = match branch.pat.ast { 464 - AstKind::Binding(ast::Binding::Ignore) => HirNode { 465 - span: branch.pat.span, 466 - hir: HirKind::IgnorePattern, 467 - }, 468 - AstKind::Literal(l) => HirNode { 469 - span: branch.pat.span, 470 - hir: HirKind::Literal(l), 471 - }, 472 - _ => unreachable!(), 473 - }; 474 - let body = coerce_ast!(branch.body => Body || unreachable!()) 475 - .into_iter() 476 - .filter_map(|node| self.walk_node(node)) 477 - .collect(); 478 - CondBranch { pattern, body } 479 - } 480 - 481 - fn walk_while(&mut self, while_: ast::While) -> While { 482 - let cond = coerce_ast!(while_.cond => Body || unreachable!()) 483 - .into_iter() 484 - .filter_map(|node| self.walk_node(node)) 485 - .collect(); 486 - let body = coerce_ast!(while_.body => Body || unreachable!()) 487 - .into_iter() 488 - .filter_map(|node| self.walk_node(node)) 489 - .collect(); 490 - While { cond, body } 491 - } 492 - 493 - fn walk_if(&mut self, if_: ast::If) -> If { 494 - let truth = coerce_ast!(if_.truth => Body || unreachable!()) 495 - .into_iter() 496 - .filter_map(|node| self.walk_node(node)) 497 - .collect(); 498 - let lie = if_.lie.map(|lie| { 499 - coerce_ast!(lie.body => Body || unreachable!()) 500 - .into_iter() 501 - .filter_map(|node| self.walk_node(node)) 502 - .collect() 503 - }); 504 - 505 - If { truth, lie } 506 - } 507 - 508 - fn walk_proc_signature( 509 - &mut self, 510 - signature: ast::ProcSignature, 511 - ) -> (Vec<HirNode>, Vec<HirNode>) { 512 - let mut ins = Vec::with_capacity(signature.ins.len()); 513 - for ty in signature.ins { 514 - let span = ty.span; 515 - let ty = coerce_ast!(ty => Type || unreachable!()); 516 - let ty = HirNode { 517 - span, 518 - hir: HirKind::Type(ty), 519 - }; 520 - ins.push(ty); 521 - } 522 - let outs = if let Some(outs) = signature.outs { 523 - let mut proc_outs = Vec::with_capacity(outs.len()); 524 - for ty in outs { 525 - let span = ty.span; 526 - let ty = coerce_ast!(ty => Type || unreachable!()); 527 - let ty = HirNode { 528 - span, 529 - hir: HirKind::Type(ty), 530 - }; 531 - proc_outs.push(ty); 532 - } 533 - proc_outs 534 - } else { 535 - Vec::new() 536 - }; 537 - 538 - (ins, outs) 539 - } 540 - }
+93 -60
rotth/src/inference.rs
··· 1 + use rotth_parser::types::Primitive; 2 + 3 + use crate::{ 4 + tir::{ConcreteType, GenId, Type, TypeId}, 5 + typecheck::{THeap, TypeStack}, 6 + }; 1 7 ///! # Type inference in less than 100 lines of Rust 2 8 ///! 3 9 ///! - Do with it what you will ··· 6 12 ///! ~ zesterer 7 13 use std::collections::HashMap; 8 14 9 - use crate::types::{StructId, StructIndex, Type, ValueType}; 10 - 11 15 /// A identifier to uniquely refer to our type terms 12 - pub type TypeId = usize; 16 + #[derive(Clone, Copy, Eq, PartialEq, Hash)] 17 + pub struct TermId(usize); 18 + 19 + impl std::fmt::Debug for TermId { 20 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 21 + write!(f, "TermId({})", self.0) 22 + } 23 + } 13 24 14 25 /// Information about a type term 15 - #[derive(Clone, Copy, Debug)] 26 + #[derive(Clone, Copy, Debug, PartialEq)] 16 27 pub enum TypeInfo { 17 28 // No information about the type of this type term 18 29 Unknown, 19 30 // This type term is the same as another type term 20 - Ref(TypeId), 31 + Ref(TermId), 21 32 22 - Ptr(TypeId), 33 + Ptr(TermId), 23 34 35 + Generic(GenId), 36 + 37 + Void, 24 38 Bool, 25 39 Char, 26 40 ··· 34 48 I16, 35 49 I8, 36 50 37 - Struct(StructId), 51 + Struct(TypeId), 52 + } 53 + 54 + pub fn type_to_info(engine: &mut Engine, term: &Type, generics_are_unknown: bool) -> TypeInfo { 55 + let mut type_to_id = |term| { 56 + let info = type_to_info(engine, term, generics_are_unknown); 57 + engine.insert(info) 58 + }; 59 + match term { 60 + Type::Generic(_) if generics_are_unknown => TypeInfo::Unknown, 61 + Type::Generic(g) => TypeInfo::Generic(*g), 62 + Type::Concrete(c) => match c { 63 + ConcreteType::Ptr(box t) => TypeInfo::Ptr(type_to_id(t)), 64 + ConcreteType::Primitive(p) => match p { 65 + Primitive::Void => TypeInfo::Void, 66 + Primitive::Bool => TypeInfo::Bool, 67 + Primitive::Char => TypeInfo::Char, 68 + Primitive::U64 => TypeInfo::U64, 69 + Primitive::U32 => TypeInfo::U32, 70 + Primitive::U16 => TypeInfo::U16, 71 + Primitive::U8 => TypeInfo::U8, 72 + Primitive::I64 => TypeInfo::I64, 73 + Primitive::I32 => TypeInfo::I32, 74 + Primitive::I16 => TypeInfo::I16, 75 + Primitive::I8 => TypeInfo::I8, 76 + }, 77 + ConcreteType::Custom(t) => TypeInfo::Struct(*t), 78 + }, 79 + } 38 80 } 39 81 40 - #[derive(Default)] 82 + #[derive(Default, Debug)] 41 83 pub struct Engine { 42 84 id_counter: usize, // Used to generate unique IDs 43 - vars: HashMap<TypeId, TypeInfo>, 85 + vars: HashMap<TermId, TypeInfo>, 44 86 } 45 87 46 88 impl Engine { 47 89 /// Create a new type term with whatever we have about its type 48 - pub fn insert(&mut self, info: TypeInfo) -> TypeId { 90 + pub fn insert(&mut self, info: TypeInfo) -> TermId { 49 91 // Generate a new ID for our type term 92 + let id = TermId(self.id_counter); 50 93 self.id_counter += 1; 51 - let id = self.id_counter; 52 94 self.vars.insert(id, info); 53 95 id 54 96 } 55 97 98 + pub fn unify_stacks( 99 + &mut self, 100 + heap: &THeap, 101 + mut a: TypeStack, 102 + mut b: TypeStack, 103 + ) -> Result<(), String> { 104 + let a_ty = a.pop(heap); 105 + let b_ty = b.pop(heap); 106 + match (a_ty, b_ty) { 107 + (None, None) => Ok(()), 108 + (None, Some(_)) | (Some(_), None) => Err(String::from("Stacks differ in depth")), 109 + (Some(a_ty), Some(b_ty)) => { 110 + self.unify(a_ty, b_ty)?; 111 + self.unify_stacks(heap, a, b) 112 + } 113 + } 114 + } 115 + 56 116 /// Make the types of two type terms equivalent (or produce an error if 57 117 /// there is a conflict between them) 58 - pub fn unify(&mut self, a: TypeId, b: TypeId, structs: &StructIndex) -> Result<(), String> { 118 + pub fn unify(&mut self, a: TermId, b: TermId) -> Result<(), String> { 59 119 use TypeInfo::*; 120 + // dbg! {(a,b)}; 121 + // dbg! {&self.vars}; 122 + if a == b { 123 + return Ok(()); 124 + } 125 + // match dbg! {(self.vars[&a], self.vars[&b])} { 60 126 match (self.vars[&a], self.vars[&b]) { 61 127 // Follow any references 62 - (Ref(a), _) => self.unify(a, b, structs), 63 - (_, Ref(b)) => self.unify(a, b, structs), 128 + (Ref(a), Ref(b)) if a == b => Ok(()), 129 + (Ref(a), _) => self.unify(a, b), 130 + (_, Ref(b)) => self.unify(a, b), 64 131 65 132 // When we don't know anything about either term, assume that 66 133 // they match and make the one we know nothing about reference the ··· 75 142 } 76 143 77 144 // Primitives are trivial to unify 145 + (Void, Void) => Ok(()), 78 146 (Bool, Bool) => Ok(()), 79 147 (Char, Char) => Ok(()), 80 148 (U64, U64) => Ok(()), ··· 88 156 89 157 // When unifying complex types, we must check their sub-types. This 90 158 // can be trivially implemented for tuples, sum types, etc. 159 + (Generic(a_id), Generic(b_id)) if a_id == b_id => Ok(()), 91 160 (Struct(a_id), Struct(b_id)) if a_id == b_id => Ok(()), 92 - (Ptr(a), Ptr(b)) => self.unify(a, b, structs), 161 + (Ptr(a), Ptr(b)) => self.unify(a, b), 93 162 94 163 // If no previous attempts to unify were successful, raise an error 95 164 (a, b) => Err(format!("Conflict between {:?} and {:?}", a, b)), ··· 99 168 /// Attempt to reconstruct a concrete type from the given type term ID. This 100 169 /// may fail if we don't yet have enough information to figure out what the 101 170 /// type is. 102 - pub fn reconstruct(&self, id: TypeId) -> Result<Type, String> { 171 + pub fn reconstruct(&self, id: TermId) -> Result<Type, String> { 103 172 use TypeInfo::*; 104 173 match self.vars[&id] { 105 174 Unknown => Err("Cannot infer".to_string()), 106 175 Ref(id) => self.reconstruct(id), 176 + Ptr(v) => Ok(Type::Concrete(ConcreteType::Ptr(box self.reconstruct(v)?))), 177 + Generic(id) => Ok(Type::Generic(id)), 178 + Void => Ok(Type::VOID), 107 179 Bool => Ok(Type::BOOL), 108 180 Char => Ok(Type::CHAR), 109 181 U64 => Ok(Type::U64), ··· 114 186 I32 => Ok(Type::I32), 115 187 I16 => Ok(Type::I16), 116 188 I8 => Ok(Type::I8), 117 - Struct(id) => Ok(Type { 118 - ptr_depth: 0, 119 - value_type: ValueType::Struct(id), 120 - }), 121 - Ptr(v) => { 122 - let mut depth = 1; 123 - let mut next = v; 124 - let ty = loop { 125 - match self.vars[&next] { 126 - Ptr(v) => { 127 - next = v; 128 - depth += 1; 129 - } 130 - ty => break ty, 131 - } 132 - }; 133 - let ty = match ty { 134 - Unknown => return Err("Cannot infer".to_string()), 135 - Ref(id) => self.reconstruct(id)?, 136 - Bool => Type::BOOL, 137 - Char => Type::CHAR, 138 - U64 => Type::U64, 139 - U32 => Type::U32, 140 - U16 => Type::U16, 141 - U8 => Type::U8, 142 - I64 => Type::I64, 143 - I32 => Type::I32, 144 - I16 => Type::I16, 145 - I8 => Type::I8, 146 - Struct(id) => Type { 147 - ptr_depth: 0, 148 - value_type: ValueType::Struct(id), 149 - }, 150 - Ptr(_) => unreachable!(), 151 - }; 152 - Ok(Type { 153 - ptr_depth: depth, 154 - value_type: ty.value_type, 155 - }) 156 - } 189 + Struct(id) => Ok(Type::Concrete(ConcreteType::Custom(id))), 157 190 } 158 191 } 159 192 } ··· 165 198 // same type, such as in the statement `x = y;`. 166 199 #[test] 167 200 fn test() { 168 - let structs = StructIndex::default(); 169 201 let mut engine = Engine::default(); 170 202 171 - // proc {T} incptr &>T : &>T 203 + // proc [T] incptr &>T : &>T 172 204 let var = engine.insert(TypeInfo::Unknown); 173 205 174 206 let i = engine.insert(TypeInfo::Ptr(var)); 175 207 let o = engine.insert(TypeInfo::Ptr(var)); 176 208 177 209 // 0 cast &>u64 incptr 178 - let u = engine.insert(TypeInfo::U64); 210 + // let u = engine.insert(TypeInfo::U64); 211 + let u = engine.insert(TypeInfo::Struct(TypeId(0))); 179 212 let a = engine.insert(TypeInfo::Ptr(u)); 180 - engine.unify(a, i, &structs).unwrap(); 213 + engine.unify(a, i).unwrap(); 181 214 182 215 // ...and compute the resulting type 183 216 panic!("Final type = {:?}", engine.reconstruct(o));
-231
rotth/src/lexer.rs
··· 1 - use std::{io::Read, path::PathBuf}; 2 - 3 - use crate::{span::Span, Error, Result}; 4 - use chumsky::{prelude::*, text::Character, Error as CError, Stream}; 5 - use somok::Somok; 6 - 7 - #[derive(Clone, Hash, PartialEq, Eq)] 8 - pub enum Token { 9 - Bool(bool), 10 - Word(String), 11 - Str(String), 12 - Char(char), 13 - KeyWord(KeyWord), 14 - Num(String), 15 - Ignore, 16 - SigSep, 17 - Ptr, 18 - FieldAccess, 19 - LBracket, 20 - RBracket, 21 - } 22 - 23 - impl std::fmt::Debug for Token { 24 - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 25 - match self { 26 - Self::Bool(b) => write!(f, "{}", b), 27 - Self::Word(word) => write!(f, "{}", word), 28 - Self::Str(str) => write!(f, "{:?}", str), 29 - Self::Char(c) => write!(f, "{:?}", c), 30 - Self::KeyWord(keyword) => keyword.fmt(f), 31 - Self::Num(num) => write!(f, "{}", num), 32 - Self::Ignore => write!(f, "_"), 33 - Self::SigSep => write!(f, ":"), 34 - Self::Ptr => write!(f, "&>"), 35 - Self::FieldAccess => write!(f, "->"), 36 - Self::LBracket => write!(f, "{{"), 37 - Self::RBracket => write!(f, "}}"), 38 - } 39 - } 40 - } 41 - 42 - impl std::fmt::Display for Token { 43 - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 44 - <Self as std::fmt::Debug>::fmt(self, f) 45 - } 46 - } 47 - 48 - #[derive(Debug, Clone, Hash, PartialEq, Eq)] 49 - pub enum KeyWord { 50 - Include, 51 - Return, 52 - Cond, 53 - If, 54 - Else, 55 - Proc, 56 - While, 57 - Do, 58 - Bind, 59 - Const, 60 - Mem, 61 - Var, 62 - Struct, 63 - Cast, 64 - End, 65 - } 66 - 67 - impl std::fmt::Display for KeyWord { 68 - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 69 - std::fmt::Debug::fmt(self, f) 70 - } 71 - } 72 - 73 - pub fn word_parser<C: Character, E: CError<C>>( 74 - ) -> impl Parser<C, C::Collection, Error = E> + Copy + Clone { 75 - const ALLOWED_NON_ALPHA: &[u8; 24] = b"()[]<>|\\/!@#$%^&*-=+_?.,"; 76 - filter(|c: &C| { 77 - c.to_char().is_ascii_alphabetic() || ALLOWED_NON_ALPHA.contains(&(c.to_char() as u8)) 78 - }) 79 - .map(Some) 80 - .chain::<C, Vec<_>, _>( 81 - filter(|c: &C| { 82 - c.to_char().is_ascii_alphanumeric() || ALLOWED_NON_ALPHA.contains(&(c.to_char() as u8)) 83 - }) 84 - .repeated(), 85 - ) 86 - .collect() 87 - } 88 - 89 - fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = Simple<char, Span>> 90 - where 91 - { 92 - let escaped = just('\\').ignore_then(any()).map(|c| match c { 93 - 'n' => '\n', 94 - 'r' => '\r', 95 - 't' => '\t', 96 - '\\' => '\\', 97 - _ => panic!("Invalid escape sequence"), 98 - }); 99 - 100 - let char = just('\'') 101 - .ignore_then(choice((escaped, any()))) 102 - .then_ignore(just('\'')) 103 - .map(Token::Char); 104 - 105 - let string = just('"') 106 - .ignore_then(none_of(['"']).repeated().collect()) 107 - .then_ignore(just('"')) 108 - .map(|s: String| { 109 - let mut res = Vec::new(); 110 - let mut escape = false; 111 - for b in s.into_bytes() { 112 - if escape { 113 - match b { 114 - b'n' => res.push(b'\n'), 115 - b'r' => res.push(b'\r'), 116 - b't' => res.push(b'\t'), 117 - b'\\' => res.push(b'\\'), 118 - _ => panic!("Invalid escape sequence \\{}!", b as char), 119 - } 120 - escape = false; 121 - } else if b == b'\\' { 122 - escape = true; 123 - continue; 124 - } else { 125 - res.push(b) 126 - } 127 - } 128 - String::from_utf8(res).unwrap() 129 - }) 130 - .map(Token::Str); 131 - 132 - let lbracket = just('{').to(Token::LBracket); 133 - let rbracket = just('}').to(Token::RBracket); 134 - 135 - let num = text::int(10).map(Token::Num); 136 - 137 - let word = word_parser().map(Token::Word); 138 - 139 - let bool = word_parser().try_map(|i: String, s| { 140 - Token::Bool(match i.as_str() { 141 - "true" => true, 142 - "false" => false, 143 - _ => return Simple::custom(s, "Invalid keyword".to_string()).error(), 144 - }) 145 - .okay() 146 - }); 147 - 148 - let keyword = word_parser().try_map(|i: String, s| { 149 - Token::KeyWord(match i.as_str() { 150 - "include" => KeyWord::Include, 151 - "return" => KeyWord::Return, 152 - "cond" => KeyWord::Cond, 153 - "if" => KeyWord::If, 154 - "else" => KeyWord::Else, 155 - "proc" => KeyWord::Proc, 156 - "while" => KeyWord::While, 157 - "do" => KeyWord::Do, 158 - "bind" => KeyWord::Bind, 159 - "const" => KeyWord::Const, 160 - "mem" => KeyWord::Mem, 161 - "var" => KeyWord::Var, 162 - "struct" => KeyWord::Struct, 163 - "cast" => KeyWord::Cast, 164 - "end" => KeyWord::End, 165 - _ => return Simple::custom(s, "Invalid keyword").error(), 166 - }) 167 - .okay() 168 - }); 169 - 170 - let ignore = word_parser().try_map(|i: String, s| match i.as_str() { 171 - "_" => Token::Ignore.okay(), 172 - _ => Simple::custom(s, "Invalid keyword").error(), 173 - }); 174 - 175 - let ptr = just('&').ignore_then(just('>').ignored()).to(Token::Ptr); 176 - 177 - let sig_sep = just(':').to(Token::SigSep); 178 - let field_access = just('-').then(just('>')).to(Token::FieldAccess); 179 - 180 - let token = choice(( 181 - num, 182 - char, 183 - string, 184 - lbracket, 185 - rbracket, 186 - field_access, 187 - ptr, 188 - sig_sep, 189 - ignore, 190 - bool, 191 - keyword, 192 - word, 193 - )) 194 - .recover_with(skip_then_retry_until([])); 195 - 196 - let comment = just(";").then(take_until(just('\n'))).padded(); 197 - 198 - token 199 - .map_with_span(|a, b| (a, b)) 200 - .padded_by(comment.repeated()) 201 - .padded() 202 - .repeated() 203 - } 204 - 205 - pub fn lex(source: PathBuf) -> Result<Vec<(Token, Span)>> { 206 - let mut src = String::new(); 207 - std::fs::File::open(&source)?.read_to_string(&mut src)?; 208 - 209 - match lexer().parse(Stream::from_iter( 210 - Span::new(source.to_string_lossy().into_owned(), src.len(), src.len()), 211 - src.chars() 212 - .enumerate() 213 - .map(|(i, c)| (c, Span::point(source.to_string_lossy().into_owned(), i))), 214 - )) { 215 - Ok(tokens) => tokens.okay(), 216 - Err(es) => Error::Lexer(es).error(), 217 - } 218 - } 219 - 220 - pub fn lex_string(source: String, file: PathBuf) -> Result<Vec<(Token, Span)>> { 221 - match lexer().parse(Stream::from_iter( 222 - Span::new(file.clone(), source.len(), source.len()), 223 - source 224 - .chars() 225 - .enumerate() 226 - .map(|(i, c)| (c, Span::point(file.clone(), i))), 227 - )) { 228 - Ok(tokens) => tokens.okay(), 229 - Err(es) => Error::Lexer(es).error(), 230 - } 231 - }
+12 -62
rotth/src/lib.rs
··· 1 1 #![feature(assert_matches)] 2 2 #![feature(iter_intersperse)] 3 - #![feature(box_syntax)] 4 - #![feature(box_patterns)] 5 - 6 - #[macro_export] 7 - macro_rules! coerce_ast { 8 - ($node:expr => $kind:tt || None) => { 9 - if let $crate::ast::AstKind::$kind(ast) = $node.ast { 10 - Some(ast) 11 - } else { 12 - None 13 - } 14 - }; 15 - ($node:expr => $kind:tt || $or:expr) => { 16 - if let $crate::ast::AstKind::$kind(ast) = $node.ast { 17 - ast 18 - } else { 19 - $or 20 - } 21 - }; 22 - ($node:expr => REF $kind:tt || None) => { 23 - if let $crate::ast::AstKind::$kind(ast) = &$node.ast { 24 - Some(ast) 25 - } else { 26 - None 27 - } 28 - }; 29 - ($node:expr => REF $kind:tt || $or:expr) => { 30 - if let $crate::ast::AstKind::$kind(ast) = &$node.ast { 31 - ast 32 - } else { 33 - $or 34 - } 35 - }; 36 - } 3 + #![feature(box_syntax, box_patterns)] 4 + #![feature(string_remove_matches)] 5 + #![feature(type_alias_impl_trait)] 6 + #![feature(array_windows)] 37 7 38 - pub mod ast; 39 - // pub mod emit; 40 - // pub mod eval; 41 - pub mod hir; 42 - pub mod iconst; 43 8 pub mod inference; 44 - pub mod lexer; 45 9 // pub mod lir; 46 - pub mod resolver; 47 - pub mod span; 10 + pub mod ctir; 48 11 pub mod tir; 49 12 pub mod typecheck; 50 - pub mod types; 51 13 52 - use chumsky::prelude::Simple; 53 - use lexer::Token; 54 - use span::Span; 14 + use rotth_parser::ParserError; 55 15 use thiserror::Error; 56 16 use typecheck::TypecheckError; 57 17 ··· 59 19 pub enum Error { 60 20 #[error("IO error {0}")] 61 21 IO(#[from] std::io::Error), 62 - #[error("Lexer error {0:?}")] 63 - Lexer(Vec<Simple<char, Span>>), 22 + #[error("Lexer error")] 23 + Lexer, 64 24 #[error("Parser error {0:?}")] 65 - Parser(Vec<Simple<Token, Span>>), 66 - #[error("Redefinition error {0:?}")] 67 - Redefinition(Vec<RedefinitionError>), 25 + Parser(ParserError), 68 26 #[error("Typecheck error {0:?}")] 69 27 Typecheck(TypecheckError), 70 28 } 71 29 72 - impl From<TypecheckError> for Error { 73 - fn from(e: TypecheckError) -> Self { 74 - Self::Typecheck(e) 30 + impl From<ParserError> for Error { 31 + fn from(e: ParserError) -> Self { 32 + Self::Parser(e) 75 33 } 76 34 } 77 - 78 - #[derive(Debug)] 79 - pub struct RedefinitionError { 80 - pub redefining_item: Span, 81 - pub redefined_item: Span, 82 - } 83 - 84 - pub type Result<T> = std::result::Result<T, Error>;
+41 -59
rotth/src/lir.rs
··· 1 - use crate::{ 2 - eval::eval, 3 - hir::{ 4 - self, Bind, Binding, Cond, CondBranch, Const, HirKind, HirNode, If, Intrinsic, Mem, Proc, 5 - TopLevel, While, 6 - }, 7 - iconst::IConst, 8 - types::{self, StructIndex, Type}, 1 + use fnv::FnvHashMap; 2 + use rotth_parser::{ 3 + ast::ItemPathBuf, 4 + hir::{self, Binding, Hir, Intrinsic, While}, 9 5 }; 6 + use somok::{Either, Somok, Ternary}; 7 + use Op::*; 8 + 9 + use crate::tir::{TirNode, TopLevel, TypecheckedProgram}; 10 + 11 + #[derive(Debug, Clone)] 12 + pub enum IConst {} 10 13 11 14 #[derive(Debug)] 12 15 pub enum Op { ··· 69 72 Return, 70 73 Exit, 71 74 } 72 - use fnv::FnvHashMap; 73 - use somok::{Either, PartitionThree, Somok, Ternary}; 74 - use Op::*; 75 75 76 76 #[derive(Clone)] 77 77 enum ComConst { 78 78 Compiled(Vec<IConst>), 79 - NotCompiled(Const), 79 + NotCompiled(Vec<TirNode>), 80 80 } 81 81 82 82 #[derive(Clone)] 83 83 enum ComMem { 84 84 Compiled(usize), 85 - NotCompiled(Mem), 85 + NotCompiled(Vec<TirNode>), 86 86 } 87 87 88 88 pub struct Compiler { ··· 95 95 strings: Vec<String>, 96 96 bindings: Vec<Vec<String>>, 97 97 mems: FnvHashMap<String, ComMem>, 98 - vars: FnvHashMap<String, types::Type>, 99 - local_vars: FnvHashMap<String, (usize, hir::Var)>, 98 + // vars: FnvHashMap<String, types::Type>, 99 + // local_vars: FnvHashMap<String, (usize, hir::Var<'p>)>, 100 100 local_vars_size: usize, 101 101 escaping_size: usize, 102 - structs: StructIndex, 102 + // structs: StructIndex, 103 103 } 104 104 105 105 impl Compiler { 106 106 pub fn compile( 107 107 mut self, 108 - items: FnvHashMap<String, TopLevel>, 108 + program: TypecheckedProgram, 109 109 ) -> (Vec<Op>, Vec<String>, FnvHashMap<String, usize>) { 110 - let (procs, consts_mems_gvars) = items 110 + let (procs, consts_mems_gvars) = program 111 + .items 111 112 .into_iter() 112 113 .partition::<Vec<_>, _>(|(_, it)| matches!(it, TopLevel::Proc(_))); 113 114 let procs = procs ··· 322 323 self.mems.insert(name.clone(), ComMem::Compiled(size)); 323 324 } 324 325 325 - fn compile_body(&mut self, body: Vec<HirNode>) { 326 + fn compile_body(&mut self, body: Vec<TirNode>) { 326 327 for node in body { 327 328 match node.hir { 328 - HirKind::Cond(cond) => self.compile_cond(cond), 329 - HirKind::Return => { 329 + Hir::Cond(cond) => self.compile_cond(cond), 330 + Hir::Return => { 330 331 let num_bindings = self.bindings.iter().flatten().count(); 331 332 for _ in 0..num_bindings { 332 333 self.emit(Unbind) ··· 335 336 self.emit(FreeLocals(i)); 336 337 self.emit(Return) 337 338 } 338 - HirKind::Literal(c) => match c { 339 + Hir::Literal(c) => match c { 339 340 IConst::Str(s) => { 340 341 let i = self.strings.len(); 341 342 self.strings.push(s); ··· 343 344 } 344 345 _ => self.emit(Push(c)), 345 346 }, 346 - HirKind::Word(w) if self.is_const(&w) => { 347 + Hir::Path(w) if self.is_const(&w) => { 347 348 let c = self.compile_const(w); 348 349 for c in c { 349 350 self.emit(Push(c)) 350 351 } 351 352 } 352 - HirKind::Word(w) if self.is_mem(&w) => { 353 + Hir::Path(w) if self.is_mem(&w) => { 353 354 self.compile_mem(&w); 354 355 self.emit(PushMem(w)) 355 356 } 356 - HirKind::Word(w) if self.is_binding(&w) => { 357 + Hir::Path(w) if self.is_binding(&w) => { 357 358 let offset = self 358 359 .bindings 359 360 .iter() ··· 363 364 .unwrap(); 364 365 self.emit(UseBinding(offset)) 365 366 } 366 - HirKind::Word(w) if self.is_lvar(&w) => { 367 + Hir::Path(w) if self.is_lvar(&w) => { 367 368 let &(offset, ref var) = &self.local_vars[&w]; 368 - if var.escaping { 369 - self.emit(PushEscaping(offset)) 370 - } else { 371 - self.emit(PushLvar(offset)) 372 - } 369 + self.emit(PushLvar(offset)) 373 370 } 374 - HirKind::Word(w) if self.is_gvar(&w) => self.emit(PushMem(w)), 375 - HirKind::Word(w) => { 371 + Hir::Path(w) if self.is_gvar(&w) => self.emit(PushMem(w)), 372 + Hir::Path(w) => { 376 373 let mangled = self.mangle_table.get(&w).unwrap().clone(); 377 374 self.emit(Call(mangled)) 378 375 } 379 - HirKind::Intrinsic(i) => match i { 376 + Hir::Intrinsic(i) => match i { 380 377 Intrinsic::Drop => self.emit(Drop), 381 378 Intrinsic::Dup => self.emit(Dup), 382 379 Intrinsic::Swap => self.emit(Swap), ··· 417 414 418 415 Intrinsic::CompStop => return, 419 416 }, 420 - HirKind::If(cond) => self.compile_if(cond), 421 - HirKind::While(while_) => self.compile_while(while_), 422 - HirKind::Bind(bind) => self.compile_bind(bind), 423 - HirKind::IgnorePattern => unreachable!(), // this is a noop 424 - HirKind::FieldAccess(f) => { 417 + Hir::If(cond) => self.compile_if(cond), 418 + Hir::While(while_) => self.compile_while(while_), 419 + Hir::Bind(bind) => self.compile_bind(bind), 420 + Hir::IgnorePattern => unreachable!(), // this is a noop 421 + Hir::FieldAccess(f) => { 425 422 let struct_ = &self.structs[f.ty.unwrap()]; 426 423 let offset = struct_.fields[&f.field].offset; 427 424 self.emit(Push(IConst::U64(offset as _))); ··· 431 428 } 432 429 } 433 430 434 - fn compile_bind(&mut self, bind: Bind) { 431 + fn compile_bind(&mut self, bind: hir::Bind) { 435 432 let mut new_bindings = Vec::new(); 436 433 for binding in bind.bindings.iter().rev() { 437 434 match binding { ··· 495 492 496 493 self.emit(Dup); 497 494 match pattern.hir { 498 - HirKind::Literal(c) => self.emit(Push(c)), 499 - HirKind::Word(w) if self.is_const(&w) => { 495 + Hir::Literal(c) => self.emit(Push(c)), 496 + Hir::Word(w) if self.is_const(&w) => { 500 497 let c = self.compile_const(w)[0].clone(); 501 498 self.emit(Push(c)) 502 499 } 503 - HirKind::Word(w) => unreachable!("Impossible non-constant: {}", w), 504 - HirKind::IgnorePattern => self.emit(Dup), // todo: this is hacky 500 + Hir::Word(w) => unreachable!("Impossible non-constant: {}", w), 501 + Hir::IgnorePattern => self.emit(Dup), // todo: this is hacky 505 502 _ => unreachable!(), 506 503 } 507 504 self.emit(Eq); ··· 562 559 escaping_size: Default::default(), 563 560 structs: Default::default(), 564 561 } 565 - } 566 - 567 - fn mangle_name(&mut self, name: String) -> String { 568 - let name_mangled = if name != "main" { 569 - format!( 570 - "proc{}_{}", 571 - self.proc_id, 572 - name.replace(|p: char| !p.is_ascii_alphabetic(), "") 573 - ) 574 - } else { 575 - name.clone() 576 - }; 577 - self.mangle_table.insert(name, name_mangled.clone()); 578 - self.proc_id += 1; 579 - name_mangled 580 562 } 581 563 582 564 fn is_const(&self, w: &str) -> bool {
+176 -214
rotth/src/main.rs
··· 1 1 use ariadne::{Color, FileCache, Fmt, Label, Report, ReportKind, Span}; 2 2 use chumsky::error::SimpleReason; 3 - use clap::Parser as ClapParser; 4 - use fnv::FnvHashMap; 5 - use rotth::{ 6 - ast, 7 - // emit, 8 - // eval::eval, 9 - hir, 10 - lexer::lex, 11 - // lir, 12 - typecheck::ErrorKind, 13 - Error, 14 - Result, 15 - }; 3 + use clap::Parser; 4 + use rotth::{tir, typecheck, Error}; 5 + use rotth_parser::hir::Walker; 16 6 use somok::Somok; 17 - use std::{fs::OpenOptions, io::BufWriter, path::PathBuf, time::Instant}; 7 + use std::{path::PathBuf, time::Instant}; 18 8 19 - #[derive(ClapParser)] 9 + #[derive(Parser)] 20 10 struct Args { 21 11 #[clap(short = 'k', long)] 22 12 dump_tokens: bool, ··· 24 14 dump_ast: bool, 25 15 #[clap(short = 'i', long)] 26 16 dump_hir: bool, 17 + #[clap(short = 'c', long)] 18 + dump_tir: bool, 27 19 #[clap(short = 'l', long)] 28 20 dump_lir: bool, 29 21 #[clap(short = 't', long)] ··· 47 39 let mut sources = FileCache::default(); 48 40 match e { 49 41 Error::IO(e) => eprintln!("{}", e), 50 - Error::Lexer(es) => { 42 + Error::Lexer => {} 43 + Error::Parser(rotth_parser::ParserError(es)) => { 51 44 for e in es { 52 - let report = Report::build(ReportKind::Error, e.span().source(), e.span().start); 45 + match e { 46 + rotth_parser::Error::Parser(e) => { 47 + let report = 48 + Report::build(ReportKind::Error, e.span().source(), e.span().start); 53 49 54 - let report = match e.reason() { 55 - SimpleReason::Unexpected => report 56 - .with_message(format!( 57 - "{}, expected {}", 58 - if e.found().is_some() { 59 - "Unexpected character in input" 60 - } else { 61 - "Unexpected end of input" 62 - }, 63 - if e.expected().len() == 0 { 64 - "something else".to_string() 65 - } else { 66 - e.expected() 67 - .map(|expected| match expected { 68 - Some(expected) => expected.to_string(), 69 - None => "end of input".to_string(), 70 - }) 71 - .collect::<Vec<_>>() 72 - .join(", ") 73 - } 74 - )) 75 - .with_label( 76 - Label::new(e.span()) 50 + let report = match e.reason() { 51 + SimpleReason::Unexpected => report 77 52 .with_message(format!( 78 - "Unexpected character {}", 79 - e.found() 80 - .map(ToString::to_string) 81 - .unwrap_or_else(|| "end of file".to_string()) 82 - .fg(Color::Red) 53 + "{}, expected {}", 54 + if e.found().is_some() { 55 + "Unexpected token in input" 56 + } else { 57 + "Unexpected end of input" 58 + }, 59 + if e.expected().len() == 0 { 60 + "something else".to_string() 61 + } else { 62 + e.expected() 63 + .map(|expected| match expected { 64 + Some(expected) => expected.to_string(), 65 + None => "end of input".to_string(), 66 + }) 67 + .collect::<Vec<_>>() 68 + .join(", ") 69 + } 83 70 )) 84 - .with_color(Color::Red), 85 - ), 86 - SimpleReason::Custom(msg) => report.with_message(msg).with_label( 87 - Label::new(e.span()) 88 - .with_message(format!("{}", msg.fg(Color::Red))) 89 - .with_color(Color::Red), 90 - ), 91 - SimpleReason::Unclosed { 92 - span: _, 93 - delimiter: _, 94 - } => todo!(), 95 - }; 96 - report.finish().print(&mut sources).unwrap(); 97 - } 98 - } 99 - Error::Parser(es) => { 100 - for e in es { 101 - let report = Report::build(ReportKind::Error, e.span().source(), e.span().start); 102 - 103 - let report = match e.reason() { 104 - SimpleReason::Unexpected => report 105 - .with_message(format!( 106 - "{}, expected {}", 107 - if e.found().is_some() { 108 - "Unexpected token in input" 109 - } else { 110 - "Unexpected end of input" 111 - }, 112 - if e.expected().len() == 0 { 113 - "something else".to_string() 114 - } else { 115 - e.expected() 116 - .map(|expected| match expected { 117 - Some(expected) => expected.to_string(), 118 - None => "end of input".to_string(), 119 - }) 120 - .collect::<Vec<_>>() 121 - .join(", ") 122 - } 123 - )) 71 + .with_label( 72 + Label::new(e.span()) 73 + .with_message(format!( 74 + "Unexpected token {}", 75 + e.found() 76 + .map(ToString::to_string) 77 + .unwrap_or_else(|| "end of file".to_string()) 78 + .fg(Color::Red) 79 + )) 80 + .with_color(Color::Red), 81 + ), 82 + SimpleReason::Custom(msg) => report.with_message(msg).with_label( 83 + Label::new(e.span()) 84 + .with_message(format!("{}", msg.fg(Color::Red))) 85 + .with_color(Color::Red), 86 + ), 87 + SimpleReason::Unclosed { 88 + span: _, 89 + delimiter: _, 90 + } => todo!(), 91 + }; 92 + report.finish().print(&mut sources).unwrap(); 93 + } 94 + rotth_parser::Error::Redefinition(e) => { 95 + let report = Report::build( 96 + ReportKind::Error, 97 + e.redefined_item.source(), 98 + e.redefined_item.start, 99 + ) 100 + .with_message("Duplicate word definitions") 101 + .with_label( 102 + Label::new(e.redefined_item) 103 + .with_message("Word originally defined here...") 104 + .with_color(Color::Green), 105 + ) 124 106 .with_label( 125 - Label::new(e.span()) 126 - .with_message(format!( 127 - "Unexpected token {}", 128 - e.found() 129 - .map(ToString::to_string) 130 - .unwrap_or_else(|| "end of file".to_string()) 131 - .fg(Color::Red) 132 - )) 133 - .with_color(Color::Red), 134 - ), 135 - SimpleReason::Custom(msg) => report.with_message(msg).with_label( 136 - Label::new(e.span()) 137 - .with_message(format!("{}", msg.fg(Color::Red))) 138 - .with_color(Color::Red), 139 - ), 140 - SimpleReason::Unclosed { 141 - span: _, 142 - delimiter: _, 143 - } => todo!(), 144 - }; 145 - report.finish().print(&mut sources).unwrap(); 146 - } 147 - } 148 - Error::Redefinition(es) => { 149 - for e in es { 150 - let report = Report::build( 151 - ReportKind::Error, 152 - e.redefined_item.source(), 153 - e.redefined_item.start, 154 - ) 155 - .with_message("Duplicate word definitions") 156 - .with_label( 157 - Label::new(e.redefined_item) 158 - .with_message("Word originally defined here...") 159 - .with_color(Color::Green), 160 - ) 161 - .with_label( 162 - Label::new(e.redefining_item) 163 - .with_message("redefined here") 164 - .with_color(Color::Yellow), 165 - ); 166 - report.finish().print(&mut sources).unwrap(); 107 + Label::new(e.redefining_item) 108 + .with_message("redefined here") 109 + .with_color(Color::Yellow), 110 + ); 111 + report.finish().print(&mut sources).unwrap(); 112 + } 113 + rotth_parser::Error::UnresolvedInclude(_) => todo!(), 114 + } 167 115 } 168 116 } 169 117 Error::Typecheck(e) => { 170 118 let report = Report::build(ReportKind::Error, e.span.source(), e.span.start) 171 119 .with_message(e.message); 172 120 173 - let report = 174 - match e.kind { 175 - ErrorKind::TypeMismatch { expected, actual } => report.with_label( 176 - Label::new(e.span).with_message( 177 - format!( 178 - "Unexpected types: {} where {} expected", 179 - format!("{:?}", actual).fg(Color::Green), 180 - format!("{:?}", expected).fg(Color::Yellow) 181 - ) 182 - .fg(Color::Red), 183 - ), 121 + let report = match e.kind { 122 + typecheck::ErrorKind::TypeMismatch { expected, actual } => report.with_label( 123 + Label::new(e.span).with_message( 124 + format!( 125 + "Unexpected types: {} where {} expected", 126 + format!("{:?}", actual).fg(Color::Green), 127 + format!("{:?}", expected).fg(Color::Yellow) 128 + ) 129 + .fg(Color::Red), 184 130 ), 185 - ErrorKind::NotEnoughData => report.with_label( 186 - Label::new(e.span) 187 - .with_message("Not enough data on the stack".fg(Color::Red)), 188 - ), 189 - 190 - ErrorKind::Undefined => report 191 - .with_label(Label::new(e.span).with_message("Unknown word".fg(Color::Red))), 192 - ErrorKind::InvalidMain => report.with_label( 193 - Label::new(e.span).with_message( 194 - format!("Invalid type signature for `{}`", "main".fg(Color::Yellow)) 195 - .fg(Color::Red), 196 - ), 131 + ), 132 + typecheck::ErrorKind::NotEnoughData => report.with_label( 133 + Label::new(e.span).with_message("Not enough data on the stack".fg(Color::Red)), 134 + ), 135 + typecheck::ErrorKind::UnsupportedOperation => report.with_label( 136 + Label::new(e.span).with_message("Not enough data on the stack".fg(Color::Red)), 137 + ), 138 + typecheck::ErrorKind::Undefined => report 139 + .with_label(Label::new(e.span).with_message("Unknown word".fg(Color::Red))), 140 + typecheck::ErrorKind::InvalidMain => report.with_label( 141 + Label::new(e.span).with_message( 142 + format!("Invalid type signature for `{}`", "main".fg(Color::Yellow)) 143 + .fg(Color::Red), 197 144 ), 198 - ErrorKind::InvalidWhile => report.with_label(Label::new(e.span).with_message( 145 + ), 146 + typecheck::ErrorKind::InvalidWhile => { 147 + report.with_label(Label::new(e.span).with_message( 199 148 "While body must not alter types on the stack".fg(Color::Red), 200 - )), 201 - ErrorKind::CompStop => report 202 - .with_label(Label::new(e.span).with_message("Compilation stopped here")), 203 - ErrorKind::Unexpected => { 204 - report.with_label(Label::new(e.span).with_message("Unexpected word")) 205 - } 206 - ErrorKind::CallInConst => { 207 - report.with_label(Label::new(e.span).with_message("Procedure call here")) 208 - } 209 - }; 149 + )) 150 + } 151 + typecheck::ErrorKind::CompStop => { 152 + report.with_label(Label::new(e.span).with_message("Compilation stopped here")) 153 + } 154 + typecheck::ErrorKind::Unexpected => { 155 + report.with_label(Label::new(e.span).with_message("Unexpected word")) 156 + } 157 + typecheck::ErrorKind::CallInConst => { 158 + report.with_label(Label::new(e.span).with_message("Procedure call here")) 159 + } 160 + typecheck::ErrorKind::UnificationError => report.with_label( 161 + Label::new(e.span).with_message("Unification error".fg(Color::Red)), 162 + ), 163 + }; 210 164 211 165 report.finish().print(&mut sources).unwrap(); 212 166 } 213 167 } 214 168 } 215 169 216 - fn compiler() -> Result<()> { 170 + fn compiler() -> Result<(), Error> { 217 171 let args = Args::parse(); 218 172 219 173 let start = Instant::now(); 220 174 221 - let source = args.source.canonicalize()?; 175 + let source = Box::leak(args.source.canonicalize()?.into_boxed_path()); 222 176 223 - let tokens = lex(source.clone())?; 177 + let src_text = Box::leak(std::fs::read_to_string(&source)?.into_boxed_str()); 178 + 179 + let tokens = rotth_lexer::lex(src_text, source); 224 180 225 181 let tokenized = Instant::now(); 226 182 if args.time { ··· 228 184 } 229 185 230 186 if args.dump_tokens { 231 - println!("Tokens:\n"); 187 + println!("Tokens:"); 232 188 println!("{tokens:?}"); 233 189 } 234 190 235 - let ast = ast::parse(tokens)?; 236 - let (structs, ast) = ast 237 - .into_iter() 238 - .partition::<FnvHashMap<_, _>, _>(|(_, i)| matches!(i, ast::TopLevel::Struct(_))); 191 + let ast = rotth_parser::ast::parse(tokens)?; 192 + let ast = rotth_parser::ast::resolve_includes(ast)?; 193 + // let (structs, ast) = ast 194 + // .into_iter() 195 + // .partition::<FnvHashMap<_, _>, _>(|(_, i)| matches!(i, ast::TopLevel::Struct(_))); 239 196 240 197 let parsed = Instant::now(); 241 198 if args.time { ··· 243 200 } 244 201 245 202 if args.dump_ast { 246 - println!("AST:\n"); 203 + println!("AST:"); 247 204 println!("{ast:#?}"); 248 205 } 249 206 250 - let struct_index = rotth::types::define_structs(structs); 207 + // let struct_index = rotth::types::define_structs(structs); 251 208 252 - let mut walker = hir::Walker::new(&struct_index); 253 - let hir = walker.walk_ast(ast); 209 + let walker = Walker::new(); 210 + let (hir, structs) = walker.walk_ast(ast); 254 211 255 212 let lowered = Instant::now(); 256 213 if args.time { 257 214 println!("Lowered in:\t{:?}", lowered - parsed) 258 215 } 259 216 260 - if args.dump_ast { 261 - println!("HIR:\n"); 217 + if args.dump_hir { 218 + println!("HIR:"); 262 219 println!("{hir:#?}"); 263 220 } 264 221 265 - // let procs = Typechecker::typecheck_program(hir, &struct_index)?; 222 + let tir = tir::Walker::walk(hir, structs)?; 266 223 267 224 let typechecked = Instant::now(); 268 225 if args.time { 269 226 println!("Typechecked in:\t{:?}", typechecked - lowered) 270 227 } 271 228 272 - // let comp = lir::Compiler::new(struct_index); 273 - // let (lir, strs, mems) = comp.compile(procs); 229 + if args.dump_tir { 230 + println!("TIR:"); 231 + println!("{tir:#?}"); 232 + } 233 + 234 + // // let comp = lir::Compiler::new(struct_index); 235 + // // let (lir, strs, mems) = comp.compile(procs); 274 236 275 - let transpiled = Instant::now(); 276 - if args.time { 277 - println!("Transpiled in:\t{:?}", transpiled - typechecked); 278 - } 237 + // let transpiled = Instant::now(); 238 + // if args.time { 239 + // println!("Transpiled in:\t{:?}", transpiled - typechecked); 240 + // } 279 241 280 - if args.dump_lir { 281 - println!("LIR:\n"); 282 - // for (i, op) in lir.iter().enumerate() { 283 - // println!("{i}:\t{op:?}"); 284 - // } 285 - } 286 - if args.compile { 287 - // emit::compile( 288 - // lir, 289 - // &strs, 290 - // &mems, 291 - // BufWriter::new( 292 - // OpenOptions::new() 293 - // .create(true) 294 - // .write(true) 295 - // .truncate(true) 296 - // .open(source.with_extension("asm"))?, 297 - // ), 298 - // )?; 242 + // if args.dump_lir { 243 + // println!("LIR:\n"); 244 + // // for (i, op) in lir.iter().enumerate() { 245 + // // println!("{i}:\t{op:?}"); 246 + // // } 247 + // } 248 + // if args.compile { 249 + // // emit::compile( 250 + // // lir, 251 + // // &strs, 252 + // // &mems, 253 + // // BufWriter::new( 254 + // // OpenOptions::new() 255 + // // .create(true) 256 + // // .write(true) 257 + // // .truncate(true) 258 + // // .open(source.with_extension("asm"))?, 259 + // // ), 260 + // // )?; 299 261 300 - let compiled = Instant::now(); 301 - if args.time { 302 - println!("Compiled in:\t{:?}", compiled - transpiled); 303 - println!("Total:\t{:?}", compiled - start); 304 - } 305 - } else { 306 - // println!("exitcode: {:?}", eval(lir, &strs).unwrap()); 307 - let evaluated = Instant::now(); 308 - if args.time { 309 - println!("Evaluated in:\t{:?}", evaluated - transpiled); 310 - println!("Total:\t{:?}", evaluated - start); 311 - } 312 - } 262 + // let compiled = Instant::now(); 263 + // if args.time { 264 + // println!("Compiled in:\t{:?}", compiled - transpiled); 265 + // println!("Total:\t{:?}", compiled - start); 266 + // } 267 + // } else { 268 + // // println!("exitcode: {:?}", eval(lir, &strs).unwrap()); 269 + // let evaluated = Instant::now(); 270 + // if args.time { 271 + // println!("Evaluated in:\t{:?}", evaluated - transpiled); 272 + // println!("Total:\t{:?}", evaluated - start); 273 + // } 274 + // } 313 275 314 276 ().okay() 315 277 }
-25
rotth/src/resolver.rs
··· 1 - use crate::{ 2 - ast::{parse, TopLevel}, 3 - lexer::lex, 4 - Result, 5 - }; 6 - use somok::Somok; 7 - use std::path::Path; 8 - 9 - pub fn resolve_include( 10 - included_from: &Path, 11 - path: &Path, 12 - existing: &mut Vec<TopLevel>, 13 - ) -> Result<()> { 14 - let source = if path.is_relative() { 15 - included_from.parent().unwrap().join(path) 16 - } else { 17 - path.into() 18 - }; 19 - let tokens = lex(source)?; 20 - 21 - let ast = parse(tokens)?; 22 - 23 - existing.extend(ast.into_iter().map(|(_, i)| i)); 24 - ().okay() 25 - }
-89
rotth/src/span.rs
··· 1 - use std::{ 2 - ops::Range, 3 - path::{Path, PathBuf}, 4 - }; 5 - 6 - #[derive(Clone, Hash, PartialEq, Eq)] 7 - pub struct Span { 8 - pub file: PathBuf, 9 - pub start: usize, 10 - pub end: usize, 11 - } 12 - 13 - impl Span { 14 - pub fn new(file: impl Into<PathBuf>, start: usize, end: usize) -> Self { 15 - Self { 16 - file: file.into(), 17 - start, 18 - end, 19 - } 20 - } 21 - pub fn point(file: impl Into<PathBuf>, point: usize) -> Self { 22 - Self { 23 - file: file.into(), 24 - start: point, 25 - end: point + 1, 26 - } 27 - } 28 - pub fn length(&self) -> usize { 29 - self.end - self.start 30 - } 31 - 32 - pub fn merge(self, other: Self) -> Self { 33 - assert!(self.file == other.file); 34 - assert!(self.start < other.start); 35 - Self { 36 - file: self.file, 37 - start: self.start, 38 - end: other.end, 39 - } 40 - } 41 - } 42 - 43 - impl std::fmt::Debug for Span { 44 - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 45 - if f.alternate() { 46 - write!(f, "{:?}[{}..{}]", &self.file, &self.start, &self.end) 47 - } else { 48 - write!(f, "[{}..{}]", &self.start, &self.end) 49 - } 50 - } 51 - } 52 - 53 - impl ariadne::Span for Span { 54 - type SourceId = Path; 55 - 56 - fn source(&self) -> &Self::SourceId { 57 - &self.file 58 - } 59 - 60 - fn start(&self) -> usize { 61 - self.start 62 - } 63 - 64 - fn end(&self) -> usize { 65 - self.end 66 - } 67 - } 68 - 69 - impl chumsky::Span for Span { 70 - type Context = PathBuf; 71 - 72 - type Offset = usize; 73 - 74 - fn new(file: Self::Context, range: Range<Self::Offset>) -> Self { 75 - Self::new(file, range.start, range.end) 76 - } 77 - 78 - fn context(&self) -> Self::Context { 79 - self.file.clone() 80 - } 81 - 82 - fn start(&self) -> Self::Offset { 83 - self.start 84 - } 85 - 86 - fn end(&self) -> Self::Offset { 87 - self.end 88 - } 89 - }
+1083 -222
rotth/src/tir.rs
··· 1 + use fnv::FnvHashMap; 2 + use rotth_parser::{ 3 + ast::{ItemPath, ItemPathBuf, Literal}, 4 + hir::{self, FieldAccess, Hir, Intrinsic}, 5 + types::{self, Primitive, StructIndex}, 6 + }; 7 + use smol_str::SmolStr; 8 + use somok::Somok; 9 + use spanner::{Span, Spanned}; 10 + 1 11 use crate::{ 2 - ast, 3 - hir::{self, HirKind, HirNode}, 4 - iconst::IConst, 5 - span::Span, 6 - typecheck::{error, ErrorKind::*, Result, THeap, TypeStack}, 7 - types::{StructId, StructIndex}, 12 + inference::{type_to_info, Engine, TermId, TypeInfo}, 13 + typecheck::{self, error, ErrorKind, THeap, TypeStack}, 14 + Error, 8 15 }; 9 - use fnv::FnvHashMap; 10 - use somok::Somok; 11 16 12 17 #[derive(Debug, Clone)] 13 18 pub enum TopLevel { 14 - Proc(), 15 - Const(), 19 + Proc(Vec<TirNode>), 20 + Const(Vec<TirNode>), 16 21 Mem(), 17 22 Var(), 18 23 } 24 + #[derive(Clone)] 19 25 pub struct TirNode { 20 - ins: Vec<Type>, 21 - outs: Vec<Type>, 22 - hir: HirKind, 26 + pub span: Span, 27 + pub node: Tir, 28 + pub ins: Vec<TermId>, 29 + pub outs: Vec<TermId>, 23 30 } 24 - #[derive(Debug, Clone, PartialEq, Eq)] 25 - pub struct Type { 26 - pub ptr_depth: usize, 27 - pub kind: TypeKind, 31 + 32 + impl std::fmt::Debug for TirNode { 33 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 34 + if f.alternate() { 35 + write!( 36 + f, 37 + "{:#?}@{:#?} {:?}:{:?}", 38 + &self.node, &self.span, &self.ins, &self.outs 39 + ) 40 + } else { 41 + write!( 42 + f, 43 + "{:?}@{:?} {:?}:{:?}", 44 + &self.node, &self.span, &self.ins, &self.outs 45 + ) 46 + } 47 + } 28 48 } 29 49 30 - impl Type { 31 - const BOOL: Self = Self { 32 - ptr_depth: 0, 33 - kind: TypeKind::Concrete(ConcreteType::Bool), 34 - }; 35 - const CHAR: Self = Self { 36 - ptr_depth: 0, 37 - kind: TypeKind::Concrete(ConcreteType::Char), 38 - }; 39 - const U64: Self = Self { 40 - ptr_depth: 0, 41 - kind: TypeKind::Concrete(ConcreteType::U64), 42 - }; 50 + #[derive(Debug, Clone)] 51 + pub struct Bind { 52 + pub bindings: Vec<Spanned<hir::Binding>>, 53 + pub body: Vec<TirNode>, 54 + } 55 + #[derive(Debug, Clone)] 56 + pub struct While { 57 + pub cond: Vec<TirNode>, 58 + pub body: Vec<TirNode>, 59 + } 60 + #[derive(Debug, Clone)] 61 + pub struct If { 62 + pub truth: Vec<TirNode>, 63 + pub lie: Option<Vec<TirNode>>, 64 + } 65 + #[derive(Debug, Clone)] 66 + pub struct Cond { 67 + pub branches: Vec<CondBranch>, 68 + } 69 + #[derive(Debug, Clone)] 70 + pub struct CondBranch { 71 + pub pattern: TirNode, 72 + pub body: Vec<TirNode>, 73 + } 43 74 44 - pub fn ptr_to(ty: Self) -> Self { 45 - let ptr_depth = ty.ptr_depth + 1; 46 - Self { 47 - ptr_depth, 48 - kind: ty.kind, 75 + #[derive(Clone)] 76 + pub enum Tir { 77 + BindingUse(ItemPathBuf), 78 + ConstUse(ItemPathBuf), 79 + Call(ItemPathBuf), 80 + Intrinsic(hir::Intrinsic), 81 + Bind(Bind), 82 + While(While), 83 + If(If), 84 + Cond(Cond), 85 + Literal(Literal), 86 + IgnorePattern, 87 + Return, 88 + FieldAccess(FieldAccess), 89 + } 90 + 91 + impl std::fmt::Debug for Tir { 92 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 93 + match self { 94 + Self::BindingUse(arg0) => f.debug_tuple("BindingUse").field(arg0).finish(), 95 + Self::ConstUse(arg0) => f.debug_tuple("ConstUse").field(arg0).finish(), 96 + Self::Call(arg0) => f.debug_tuple("Call").field(arg0).finish(), 97 + Self::Intrinsic(arg0) => arg0.fmt(f), 98 + Self::Bind(arg0) => arg0.fmt(f), 99 + Self::While(arg0) => arg0.fmt(f), 100 + Self::If(arg0) => arg0.fmt(f), 101 + Self::Cond(arg0) => arg0.fmt(f), 102 + Self::Literal(arg0) => arg0.fmt(f), 103 + Self::IgnorePattern => write!(f, "_"), 104 + Self::Return => write!(f, "return"), 105 + Self::FieldAccess(arg0) => arg0.fmt(f), 49 106 } 50 107 } 51 108 } 52 109 53 - #[derive(Debug, Clone, PartialEq, Eq)] 54 - pub enum TypeKind { 55 - Generic(String), 110 + #[derive(Clone, PartialEq, Eq, Hash)] 111 + pub enum Type { 112 + Generic(GenId), 56 113 Concrete(ConcreteType), 57 114 } 58 - #[derive(Debug, Clone, PartialEq, Eq)] 59 - pub enum ConcreteType { 60 - Bool, 61 - Char, 115 + 116 + impl Type { 117 + pub const BOOL: Self = Self::Concrete(ConcreteType::Primitive(Primitive::Bool)); 118 + pub const CHAR: Self = Self::Concrete(ConcreteType::Primitive(Primitive::Char)); 119 + pub const U64: Self = Self::Concrete(ConcreteType::Primitive(Primitive::U64)); 120 + pub const U32: Self = Self::Concrete(ConcreteType::Primitive(Primitive::U32)); 121 + pub const U16: Self = Self::Concrete(ConcreteType::Primitive(Primitive::U16)); 122 + pub const U8: Self = Self::Concrete(ConcreteType::Primitive(Primitive::U8)); 123 + 124 + pub const I64: Self = Self::Concrete(ConcreteType::Primitive(Primitive::I64)); 125 + pub const I32: Self = Self::Concrete(ConcreteType::Primitive(Primitive::I32)); 126 + pub const I16: Self = Self::Concrete(ConcreteType::Primitive(Primitive::I16)); 127 + pub const I8: Self = Self::Concrete(ConcreteType::Primitive(Primitive::I8)); 128 + 129 + pub const VOID: Self = Self::Concrete(ConcreteType::Primitive(Primitive::Void)); 130 + 131 + pub fn ptr_to(t: Self) -> Self { 132 + Self::Concrete(ConcreteType::Ptr(box t)) 133 + } 134 + } 135 + 136 + impl std::fmt::Debug for Type { 137 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 138 + match self { 139 + Type::Generic(i) => write!(f, "Generic({:?})", i), 140 + Type::Concrete(t) => t.fmt(f), 141 + } 142 + } 143 + } 144 + 145 + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 146 + pub struct TypeId(pub usize); 62 147 63 - U64, 64 - U32, 65 - U16, 66 - U8, 148 + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 149 + pub struct GenId(pub usize); 67 150 68 - I64, 69 - I32, 70 - I16, 71 - I8, 151 + #[derive(Clone, PartialEq, Eq, Hash)] 152 + pub enum ConcreteType { 153 + Ptr(Box<Type>), 154 + Primitive(Primitive), 155 + Custom(TypeId), 156 + } 72 157 73 - Struct(StructId), 158 + impl std::fmt::Debug for ConcreteType { 159 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 160 + match self { 161 + ConcreteType::Ptr(box ty) => { 162 + write!(f, "&>")?; 163 + ty.fmt(f) 164 + } 165 + ConcreteType::Primitive(p) => p.fmt(f), 166 + ConcreteType::Custom(s) => s.fmt(f), 167 + } 168 + } 74 169 } 170 + 75 171 #[derive(Debug, Clone)] 76 - struct KProc { 77 - generics: Vec<String>, 78 - ins: Vec<Type>, 79 - outs: Vec<Type>, 80 - body: Vec<HirNode>, 172 + pub struct KProc<T> { 173 + pub generics: FnvHashMap<SmolStr, GenId>, 174 + pub span: Span, 175 + pub ins: Vec<Type>, 176 + pub outs: Vec<Type>, 177 + pub body: Vec<T>, 81 178 } 82 - struct KConst { 83 - outs: Vec<Type>, 84 - body: Vec<HirNode>, 179 + #[derive(Debug)] 180 + pub struct KConst { 181 + pub outs: Vec<Type>, 182 + pub body: Vec<TirNode>, 85 183 } 86 184 struct KMem {} 87 185 struct KGVar {} 88 186 187 + #[derive(Debug)] 188 + pub struct KStruct { 189 + pub id: TypeId, 190 + pub fields: FnvHashMap<SmolStr, Type>, 191 + } 192 + 89 193 pub struct Walker { 90 - typechecked_items: FnvHashMap<String, TopLevel>, 91 - known_consts: FnvHashMap<String, KConst>, 92 - known_procs: FnvHashMap<String, KProc>, 93 - known_gvars: FnvHashMap<String, KGVar>, 94 - known_mems: FnvHashMap<String, KMem>, 194 + known_procs: FnvHashMap<ItemPathBuf, KProc<Spanned<Hir>>>, 195 + known_gvars: FnvHashMap<ItemPathBuf, KGVar>, 196 + known_mems: FnvHashMap<ItemPathBuf, KMem>, 197 + known_structs: FnvHashMap<ItemPathBuf, KStruct>, 198 + checked_consts: FnvHashMap<ItemPathBuf, KConst>, 199 + checked_procs: FnvHashMap<ItemPathBuf, KProc<TirNode>>, 200 + ty_ctx: TyCtx, 95 201 structs: StructIndex, 96 - outputs: FnvHashMap<String, hir::TopLevel>, 97 - items: FnvHashMap<String, hir::TopLevel>, 98 - heap: THeap, 202 + next_type_id: usize, 203 + next_gen_id: usize, 204 + } 205 + 206 + #[derive(Debug)] 207 + pub struct TypecheckedProgram { 208 + pub procs: FnvHashMap<ItemPathBuf, KProc<TirNode>>, 209 + pub consts: FnvHashMap<ItemPathBuf, KConst>, 210 + pub types: FnvHashMap<ItemPathBuf, KStruct>, 211 + } 212 + 213 + #[derive(Default)] 214 + pub struct TyCtx { 215 + pub engine: Engine, 99 216 } 217 + 100 218 impl Walker { 101 219 pub fn walk( 102 - items: FnvHashMap<String, hir::TopLevel>, 103 - ) -> Result<FnvHashMap<String, hir::TopLevel>> { 220 + ast: FnvHashMap<ItemPathBuf, hir::TopLevel>, 221 + structs: StructIndex, 222 + ) -> Result<TypecheckedProgram, Error> { 104 223 let mut this = Walker { 105 - typechecked_items: Default::default(), 106 - known_consts: Default::default(), 224 + checked_consts: Default::default(), 107 225 known_procs: Default::default(), 108 226 known_gvars: Default::default(), 109 227 known_mems: Default::default(), 110 - structs: Default::default(), 111 - outputs: Default::default(), 112 - items: Default::default(), 113 - heap: Default::default(), 228 + known_structs: Default::default(), 229 + structs, 230 + checked_procs: Default::default(), 231 + ty_ctx: Default::default(), 232 + next_type_id: Default::default(), 233 + next_gen_id: Default::default(), 114 234 }; 115 235 116 - for (name, item) in &items { 117 - match item { 118 - hir::TopLevel::Proc(proc) => this.register_proc(name, proc.clone())?, 119 - hir::TopLevel::Const(const_) => this.register_const(name, const_.clone())?, 236 + for ty in this.structs.clone() { 237 + let mut fields = FnvHashMap::default(); 238 + for (n, ty) in &ty.fields { 239 + let ty = this.abstract_to_concrete_type(ty, None)?; 240 + fields.insert(n.clone(), ty); 241 + } 242 + let id = this.type_id(); 243 + this.known_structs.insert(ty.name, KStruct { id, fields }); 244 + } 245 + 246 + for (path, def) in ast { 247 + match def { 248 + hir::TopLevel::Proc(proc) => this.register_proc(path, proc)?, 249 + hir::TopLevel::Const(const_) => this.register_const(path, const_)?, 120 250 hir::TopLevel::Mem(_) => todo!(), 121 251 hir::TopLevel::Var(_) => todo!(), 122 - }; 252 + } 123 253 } 124 - this.items = items; 125 - this.typecheck_proc("main", Default::default())?; 126 - this.outputs.okay() 127 - } 128 254 129 - fn register_const(&mut self, proc_name: &str, const_: hir::Const) -> Result<()> { 130 - let outs = const_ 131 - .outs 132 - .into_iter() 133 - .map(|ty| self.abstract_to_concrete_type(ty, &[])) 134 - .collect::<Result<Vec<_>>>()?; 135 - 136 - let known_const = KConst { 137 - outs, 138 - body: const_.body, 139 - }; 255 + this.typecheck()?; 140 256 141 - self.known_consts.insert(proc_name.to_string(), known_const); 142 - ().okay() 257 + TypecheckedProgram { 258 + procs: this.checked_procs, 259 + consts: this.checked_consts, 260 + types: this.known_structs, 261 + } 262 + .okay() 143 263 } 144 264 145 - fn register_proc(&mut self, proc_name: &str, proc: hir::Proc) -> Result<()> { 146 - let generics = proc.generics; 265 + fn register_proc(&mut self, path: ItemPathBuf, proc: hir::Proc) -> Result<(), Error> { 266 + let generics = proc 267 + .generics 268 + .into_iter() 269 + .map(|g| (g, self.gen_id())) 270 + .collect(); 271 + self.gen_id_reset(); 147 272 let ins = proc 148 273 .ins 149 274 .into_iter() 150 - .map(|ty| self.abstract_to_concrete_type(ty, &generics)) 151 - .collect::<Result<Vec<_>>>()?; 275 + .map(|ty| self.abstract_to_concrete_type(&ty, Some(&generics))) 276 + .collect::<Result<Vec<_>, _>>()?; 152 277 let outs = proc 153 278 .outs 154 279 .into_iter() 155 - .map(|ty| self.abstract_to_concrete_type(ty, &generics)) 156 - .collect::<Result<Vec<_>>>()?; 157 - 158 - if proc_name == "main" && !(ins.is_empty() || matches!(&outs[..], [Type::U64])) { 159 - return error( 160 - proc.span, 161 - InvalidMain, 162 - "Main must have no inputs and a single `u64` output", 163 - ); 164 - } 280 + .map(|ty| self.abstract_to_concrete_type(&ty, Some(&generics))) 281 + .collect::<Result<Vec<_>, _>>()?; 165 282 166 283 let known_proc = KProc { 167 284 generics, 168 285 ins, 169 286 outs, 287 + span: proc.span, 170 288 body: proc.body, 171 289 }; 172 290 173 - self.known_procs.insert(proc_name.to_string(), known_proc); 291 + self.known_procs.insert(path, known_proc); 292 + ().okay() 293 + } 294 + 295 + fn register_const(&mut self, path: ItemPathBuf, const_: hir::Const) -> Result<(), Error> { 296 + let outs = const_ 297 + .outs 298 + .iter() 299 + .map(|ty| self.abstract_to_concrete_type(ty, None)) 300 + .collect::<Result<Vec<_>, _>>()?; 301 + 302 + let mut heap = THeap::default(); 303 + let mut ts = TypeStack::default(); 304 + let body = self.typecheck_body(&mut ts, &mut heap, &const_.body, None, None, None, true)?; 305 + 306 + let known_const = KConst { outs, body }; 307 + self.checked_consts.insert(path, known_const); 174 308 ().okay() 175 309 } 176 310 177 - fn typecheck_proc( 311 + fn typecheck(&mut self) -> Result<(), Error> { 312 + let mut heap = THeap::default(); 313 + let known_procs = self.known_procs.keys().cloned().collect::<Vec<_>>(); 314 + 315 + for path in known_procs { 316 + self.typecheck_proc(&mut heap, &path)?; 317 + } 318 + 319 + Ok(()) 320 + } 321 + 322 + fn typecheck_proc(&mut self, heap: &mut THeap, path: &ItemPath) -> Result<(), Error> { 323 + let proc = self.known_procs.get(path).cloned().unwrap(); 324 + 325 + let mut ins = TypeStack::from_iter( 326 + proc.ins.iter().map(|term| { 327 + let info = type_to_info(&mut self.ty_ctx.engine, term, false); 328 + self.ty_ctx.engine.insert(info) 329 + }), 330 + heap, 331 + ); 332 + 333 + let outs = proc.outs.iter().map(|term| { 334 + let info = type_to_info(&mut self.ty_ctx.engine, term, false); 335 + self.ty_ctx.engine.insert(info) 336 + }); 337 + let outs = TypeStack::from_iter(outs, heap); 338 + 339 + let body = self.typecheck_body( 340 + &mut ins, 341 + heap, 342 + &proc.body, 343 + None, 344 + Some(&proc.generics), 345 + Some(&outs), 346 + false, 347 + )?; 348 + 349 + if let Err(msg) = self.ty_ctx.engine.unify_stacks(heap, ins, outs) { 350 + return error(proc.span, ErrorKind::UnificationError, msg); 351 + } 352 + 353 + self.checked_procs.insert( 354 + path.to_owned(), 355 + KProc { 356 + generics: proc.generics, 357 + span: proc.span, 358 + ins: proc.ins, 359 + outs: proc.outs, 360 + body, 361 + }, 362 + ); 363 + Ok(()) 364 + } 365 + 366 + #[allow(clippy::too_many_arguments)] 367 + fn typecheck_body( 178 368 &mut self, 179 - proc_name: &str, 180 - type_substitutions: FnvHashMap<String, Type>, 181 - ) -> Result<()> { 182 - let proc = if let Some(proc) = self.known_procs.get(proc_name) { 183 - proc 184 - } else { 185 - return error( 186 - Span::point("", 0), 187 - Undefined, 188 - format!("Procedure `{}` is not defined", proc_name), 189 - ); 190 - }; 191 - let mut stack = TypeStack::default(); 192 - for ty in &proc.ins { 193 - match &ty.kind { 194 - TypeKind::Generic(g) => { 195 - if let Some(ty) = type_substitutions.get(g) { 196 - stack.push(&mut self.heap, ty.clone()) 369 + ins: &mut TypeStack, 370 + heap: &mut THeap, 371 + body: &[Spanned<Hir>], 372 + bindings: Option<&FnvHashMap<SmolStr, TermId>>, 373 + generics: Option<&FnvHashMap<SmolStr, GenId>>, 374 + expected_outs: Option<&TypeStack>, 375 + in_const: bool, 376 + ) -> Result<Vec<TirNode>, Error> { 377 + let mut checked_body = Vec::new(); 378 + for node in body { 379 + let node = match &node.inner { 380 + Hir::Path(path) 381 + if path 382 + .only() 383 + .and_then(|p| bindings.and_then(|bs| bs.get(p))) 384 + .is_some() => 385 + { 386 + let ty = path 387 + .only() 388 + .and_then(|p| bindings.and_then(|bs| bs.get(p))) 389 + .copied() 390 + .unwrap(); 391 + ins.push(heap, ty); 392 + TirNode { 393 + span: node.span, 394 + node: Tir::BindingUse(path.clone()), 395 + ins: vec![], 396 + outs: vec![ty], 397 + } 398 + } 399 + Hir::Path(proc_name) if self.is_proc(proc_name) => { 400 + if in_const { 401 + return error( 402 + node.span, 403 + ErrorKind::CallInConst, 404 + "Calls in constant bodies are not supported", 405 + ); 406 + } 407 + let (ins, outs) = if let Some(p) = self.known_procs.get(proc_name) { 408 + let expected_ins = p 409 + .ins 410 + .iter() 411 + .map(|ty| { 412 + let info = type_to_info(&mut self.ty_ctx.engine, ty, true); 413 + self.ty_ctx.engine.insert(info) 414 + }) 415 + .collect::<Vec<_>>(); 416 + for expected_ty in &expected_ins { 417 + if let Some(actual_t) = ins.pop(heap) { 418 + if let Err(message) = 419 + self.ty_ctx.engine.unify(*expected_ty, actual_t) 420 + { 421 + return error(node.span, ErrorKind::UnificationError, message); 422 + } 423 + } else { 424 + return error( 425 + node.span, 426 + ErrorKind::NotEnoughData, 427 + format!( 428 + "Not enough data in the stack for `{:?}` proc", 429 + proc_name 430 + ), 431 + ); 432 + } 433 + } 434 + let outs = p 435 + .outs 436 + .iter() 437 + .map(|ty| { 438 + let info = type_to_info(&mut self.ty_ctx.engine, ty, true); 439 + self.ty_ctx.engine.insert(info) 440 + }) 441 + .collect::<Vec<_>>(); 442 + for out_t in &outs { 443 + ins.push(heap, *out_t); 444 + } 445 + (expected_ins, outs) 446 + } else { 447 + return error(node.span, ErrorKind::Undefined, "Undefined proc"); 448 + }; 449 + 450 + TirNode { 451 + span: node.span, 452 + node: Tir::Call(proc_name.clone()), 453 + ins, 454 + outs, 455 + } 456 + } 457 + Hir::Path(const_name) if self.is_const(const_name) => { 458 + let outs: Vec<TermId> = self 459 + .checked_consts 460 + .get(const_name) 461 + .unwrap() 462 + .outs 463 + .iter() 464 + .map(|term| { 465 + let info = type_to_info(&mut self.ty_ctx.engine, term, false); 466 + self.ty_ctx.engine.insert(info) 467 + }) 468 + .collect(); 469 + 470 + for ty in &outs { 471 + ins.push(heap, *ty); 472 + } 473 + 474 + TirNode { 475 + span: node.span, 476 + node: Tir::ConstUse(const_name.clone()), 477 + ins: vec![], 478 + outs, 479 + } 480 + } 481 + Hir::Path(path) => { 482 + return error( 483 + node.span, 484 + ErrorKind::Undefined, 485 + format!("Undefined word `{:?}`", path), 486 + ) 487 + } 488 + Hir::Intrinsic(i) => { 489 + let (mut w_ins, mut w_outs) = (Vec::new(), Vec::new()); 490 + match i { 491 + Intrinsic::Drop => { 492 + if let Some(ty) = ins.pop(heap) { 493 + w_ins.push(ty); 494 + } else { 495 + return error( 496 + node.span, 497 + ErrorKind::NotEnoughData, 498 + "Not enough data in the stack for `pop` intrinsic", 499 + ); 500 + } 501 + } 502 + Intrinsic::Dup => { 503 + if let Some(ty) = ins.pop(heap) { 504 + ins.push(heap, ty); 505 + ins.push(heap, ty); 506 + w_ins.push(ty); 507 + w_outs.push(ty); 508 + w_outs.push(ty); 509 + } else { 510 + return error( 511 + node.span, 512 + ErrorKind::NotEnoughData, 513 + "Not enough data in the stack for `dup` intrinsic", 514 + ); 515 + } 516 + } 517 + Intrinsic::Swap => { 518 + if let Some(ty1) = ins.pop(heap) { 519 + if let Some(ty2) = ins.pop(heap) { 520 + ins.push(heap, ty1); 521 + ins.push(heap, ty2); 522 + w_ins.push(ty1); 523 + w_ins.push(ty2); 524 + w_outs.push(ty1); 525 + w_outs.push(ty2); 526 + } else { 527 + return error( 528 + node.span, 529 + ErrorKind::NotEnoughData, 530 + "Not enough data in the stack for `swap` intrinsic", 531 + ); 532 + } 533 + } else { 534 + return error( 535 + node.span, 536 + ErrorKind::NotEnoughData, 537 + "Not enough data in the stack for `swap` intrinsic", 538 + ); 539 + } 540 + } 541 + Intrinsic::Over => { 542 + if let Some(ty1) = ins.pop(heap) { 543 + if let Some(ty2) = ins.pop(heap) { 544 + ins.push(heap, ty2); 545 + ins.push(heap, ty1); 546 + ins.push(heap, ty2); 547 + w_ins.push(ty1); 548 + w_ins.push(ty2); 549 + w_outs.push(ty2); 550 + w_outs.push(ty1); 551 + w_outs.push(ty2); 552 + } else { 553 + return error( 554 + node.span, 555 + ErrorKind::NotEnoughData, 556 + "Not enough data in the stack for `over` intrinsic", 557 + ); 558 + } 559 + } else { 560 + return error( 561 + node.span, 562 + ErrorKind::NotEnoughData, 563 + "Not enough data in the stack for `over` intrinsic", 564 + ); 565 + } 566 + } 567 + Intrinsic::Cast(o_ty) => { 568 + let o_type = self.abstract_to_concrete_type(o_ty, generics)?; 569 + let o_type = type_to_info(&mut self.ty_ctx.engine, &o_type, false); 570 + let o_type = self.ty_ctx.engine.insert(o_type); 571 + if let Some(in_t) = ins.pop(heap) { 572 + ins.push(heap, o_type); 573 + w_ins.push(in_t); 574 + w_outs.push(o_type); 575 + } else { 576 + return error( 577 + node.span, 578 + ErrorKind::NotEnoughData, 579 + "Not enough data in the stack for `cast` intrinsic", 580 + ); 581 + } 582 + } 583 + Intrinsic::ReadU64 => { 584 + if let Some(actual) = ins.pop(heap) { 585 + // let vptr = type_to_info( 586 + // &mut self.ty_ctx.engine, 587 + // &Type::ptr_to(Type::VOID), 588 + // false, 589 + // ); 590 + let unknown = self.ty_ctx.engine.insert(TypeInfo::Unknown); 591 + let vptr = TypeInfo::Ptr(unknown); 592 + let expect = self.ty_ctx.engine.insert(vptr); 593 + if let Err(message) = self.ty_ctx.engine.unify(expect, actual) { 594 + return error(node.span, ErrorKind::UnificationError, message); 595 + } else { 596 + let out_ty = self.ty_ctx.engine.insert(TypeInfo::U64); 597 + ins.push(heap, out_ty); 598 + w_ins.push(expect); 599 + w_outs.push(out_ty); 600 + } 601 + } else { 602 + return error( 603 + node.span, 604 + ErrorKind::NotEnoughData, 605 + "Not enough data in the stack for `!u64` intrinsic", 606 + ); 607 + } 608 + } 609 + Intrinsic::ReadU8 => todo!(), 610 + Intrinsic::WriteU64 => { 611 + if let Some(ty1) = ins.pop(heap) { 612 + let vptr = type_to_info( 613 + &mut self.ty_ctx.engine, 614 + &Type::ptr_to(Type::VOID), 615 + false, 616 + ); 617 + let expect = self.ty_ctx.engine.insert(vptr); 618 + if let Err(message) = self.ty_ctx.engine.unify(expect, ty1) { 619 + return error(node.span, ErrorKind::UnificationError, message); 620 + } 621 + if let Some(ty2) = ins.pop(heap) { 622 + let u64 = type_to_info( 623 + &mut self.ty_ctx.engine, 624 + &Type::ptr_to(Type::VOID), 625 + false, 626 + ); 627 + let expect = self.ty_ctx.engine.insert(u64); 628 + if let Err(message) = self.ty_ctx.engine.unify(expect, ty2) { 629 + return error( 630 + node.span, 631 + ErrorKind::UnificationError, 632 + message, 633 + ); 634 + } 635 + w_ins.push(ty1); 636 + w_ins.push(ty2); 637 + } else { 638 + return error( 639 + node.span, 640 + ErrorKind::NotEnoughData, 641 + "Not enough data in the stack for `!u64` intrinsic", 642 + ); 643 + } 644 + } else { 645 + return error( 646 + node.span, 647 + ErrorKind::NotEnoughData, 648 + "Not enough data in the stack for `!u64` intrinsic", 649 + ); 650 + } 651 + } 652 + Intrinsic::WriteU8 => todo!(), 653 + Intrinsic::CompStop => todo!(), 654 + Intrinsic::Dump => todo!(), 655 + Intrinsic::Print => todo!(), 656 + Intrinsic::Syscall0 => todo!(), 657 + Intrinsic::Syscall1 => todo!(), 658 + Intrinsic::Syscall2 => todo!(), 659 + Intrinsic::Syscall3 => todo!(), 660 + Intrinsic::Syscall4 => todo!(), 661 + Intrinsic::Syscall5 => todo!(), 662 + Intrinsic::Syscall6 => todo!(), 663 + Intrinsic::Argc => todo!(), 664 + Intrinsic::Argv => todo!(), 665 + Intrinsic::Add => { 666 + if let Some(a) = ins.pop(heap) { 667 + if let Some(b) = ins.pop(heap) { 668 + if let Err(message) = self.ty_ctx.engine.unify(a, b) { 669 + return error( 670 + node.span, 671 + ErrorKind::UnificationError, 672 + message, 673 + ); 674 + } 675 + ins.push(heap, a); 676 + } else { 677 + return error( 678 + node.span, 679 + ErrorKind::NotEnoughData, 680 + "Not enough data in the stack for `add` intrinsic", 681 + ); 682 + } 683 + } else { 684 + return error( 685 + node.span, 686 + ErrorKind::NotEnoughData, 687 + "Not enough data in the stack for `add` intrinsic", 688 + ); 689 + } 690 + } 691 + Intrinsic::Sub => todo!(), 692 + Intrinsic::Divmod => todo!(), 693 + Intrinsic::Mul => todo!(), 694 + Intrinsic::Eq => todo!(), 695 + Intrinsic::Ne => todo!(), 696 + Intrinsic::Lt => todo!(), 697 + Intrinsic::Le => todo!(), 698 + Intrinsic::Gt => todo!(), 699 + Intrinsic::Ge => todo!(), 700 + }; 701 + TirNode { 702 + span: node.span, 703 + node: Tir::Intrinsic(i.clone()), 704 + ins: w_ins, 705 + outs: w_outs, 706 + } 707 + } 708 + Hir::Bind(hir::Bind { bindings, body }) => { 709 + let mut w_ins = Vec::new(); 710 + let bindings_hash = bindings 711 + .iter() 712 + .filter_map(|Spanned { span, inner: b }| match b { 713 + hir::Binding::Ignore => { 714 + if let Some(ty) = ins.pop(heap) { 715 + w_ins.push(ty); 716 + None 717 + } else { 718 + Some(error( 719 + *span, 720 + ErrorKind::NotEnoughData, 721 + "Not enough data to bind", 722 + )) 723 + } 724 + } 725 + hir::Binding::Bind { name, ty: expected } => { 726 + let ty = if let Some(ty) = ins.pop(heap) { 727 + if let Some(ty2) = expected { 728 + let ty2 = self 729 + .abstract_to_concrete_type( 730 + &Spanned { 731 + span: node.span, 732 + inner: ty2.clone(), 733 + }, 734 + generics, 735 + ) 736 + .map(|ty| { 737 + let info = type_to_info( 738 + &mut self.ty_ctx.engine, 739 + &ty, 740 + false, 741 + ); 742 + self.ty_ctx.engine.insert(info) 743 + }); 744 + 745 + if let Ok(ty2) = ty2 { 746 + if let Err(message) = self.ty_ctx.engine.unify(ty, ty2) 747 + { 748 + return Some(error( 749 + *span, 750 + ErrorKind::UnificationError, 751 + message, 752 + )); 753 + } 754 + } 755 + } 756 + ty 757 + } else { 758 + return Some(error( 759 + *span, 760 + ErrorKind::NotEnoughData, 761 + "Not enough data to bind", 762 + )); 763 + }; 764 + w_ins.push(ty); 765 + Some(Ok((name.clone(), ty))) 766 + } 767 + }) 768 + .collect::<Result<FnvHashMap<_, _>, _>>()?; 769 + let b_ins = ins.clone().into_vec(heap); 770 + let body = self.typecheck_body( 771 + ins, 772 + heap, 773 + body, 774 + Some(&bindings_hash), 775 + generics, 776 + expected_outs, 777 + in_const, 778 + )?; 779 + let mut a_ins = ins.clone().into_vec(heap).into_iter(); 780 + for _ in b_ins { 781 + a_ins.next(); 782 + } 783 + let w_outs = a_ins.collect(); 784 + TirNode { 785 + span: node.span, 786 + node: Tir::Bind(Bind { 787 + bindings: bindings.clone(), 788 + body, 789 + }), 790 + ins: w_ins, 791 + outs: w_outs, 792 + } 793 + } 794 + Hir::While(hir::While { cond, body }) => { 795 + let mut ins_c = ins.clone(); 796 + let cond = self.typecheck_body( 797 + &mut ins_c, 798 + heap, 799 + cond, 800 + bindings, 801 + generics, 802 + expected_outs, 803 + in_const, 804 + )?; 805 + if let Some(ty) = ins_c.pop(heap) { 806 + let bool = self.ty_ctx.engine.insert(TypeInfo::Bool); 807 + if let Err(message) = self.ty_ctx.engine.unify(ty, bool) { 808 + return error(node.span, ErrorKind::UnificationError, message); 809 + } 810 + if let Err(message) = 811 + self.ty_ctx.engine.unify_stacks(heap, ins.clone(), ins_c) 812 + { 813 + return error(node.span, ErrorKind::UnificationError, message); 814 + }; 197 815 } else { 198 - let span = self.items[proc_name].span(); 199 816 return error( 200 - span, 201 - Undefined, 202 - format!("Undefined type `{}` in this scope", g), 817 + node.span, 818 + ErrorKind::NotEnoughData, 819 + "Not enough data on the stack for `while` condition", 203 820 ); 821 + }; 822 + let mut ins_b = ins.clone(); 823 + let body = self.typecheck_body( 824 + &mut ins_b, 825 + heap, 826 + body, 827 + bindings, 828 + generics, 829 + expected_outs, 830 + in_const, 831 + )?; 832 + if let Err(message) = self.ty_ctx.engine.unify_stacks(heap, ins.clone(), ins_b) 833 + { 834 + return error(node.span, ErrorKind::UnificationError, message); 835 + }; 836 + 837 + TirNode { 838 + span: node.span, 839 + node: Tir::While(While { cond, body }), 840 + ins: vec![], 841 + outs: vec![], 204 842 } 205 843 } 206 - TypeKind::Concrete(_) => stack.push(&mut self.heap, ty.clone()), 207 - } 208 - } 844 + Hir::If(hir::If { truth, lie }) => { 845 + let bool = self.ty_ctx.engine.insert(TypeInfo::Bool); 846 + let b = ins.pop(heap).map(|b| self.ty_ctx.engine.unify(b, bool)); 847 + if let Some(Err(message)) = b { 848 + return error(node.span, ErrorKind::UnificationError, message); 849 + } else if b.is_none() { 850 + return error( 851 + node.span, 852 + ErrorKind::NotEnoughData, 853 + "Not enough data on the stack for `if`", 854 + ); 855 + }; 209 856 210 - self.typecheck_body(proc_name, proc.body.clone(), &mut stack)?; 857 + let mut ins_t = ins.clone(); 858 + let truth = self.typecheck_body( 859 + &mut ins_t, 860 + heap, 861 + truth, 862 + bindings, 863 + generics, 864 + expected_outs, 865 + in_const, 866 + )?; 867 + let lie = if let Some(lie) = lie { 868 + let mut ins_l = ins.clone(); 869 + let lie = self.typecheck_body( 870 + &mut ins_l, 871 + heap, 872 + lie, 873 + bindings, 874 + generics, 875 + expected_outs, 876 + in_const, 877 + )?; 211 878 212 - todo!() 213 - } 879 + if let Err(message) = self.ty_ctx.engine.unify_stacks(heap, ins_t, ins_l) { 880 + return error(node.span, ErrorKind::UnificationError, message); 881 + } 882 + Some(lie) 883 + } else { 884 + None 885 + }; 214 886 215 - fn typecheck_body( 216 - &mut self, 217 - item_name: &str, 218 - body: Vec<HirNode>, 219 - stack: &mut TypeStack, 220 - ) -> Result<()> { 221 - for node in body { 222 - match &node.hir { 223 - HirKind::Word(w) => match w.as_str() { 224 - rec if rec == item_name && !self.is_proc(rec) => { 225 - return error(node.span.clone(), Unexpected, "Recursive const refinition") 887 + TirNode { 888 + span: node.span, 889 + node: Tir::If(If { truth, lie }), 890 + ins: vec![bool], 891 + outs: vec![], 226 892 } 227 - rec if rec == item_name => {} 228 - proc_name if self.is_proc(proc_name) => { 229 - let proc = &self.known_procs[proc_name]; 893 + } 894 + Hir::Cond(hir::Cond { branches }) => { 895 + let ty = if let Some(ty) = ins.pop(heap) { 896 + ty 897 + } else { 898 + return error( 899 + node.span, 900 + ErrorKind::NotEnoughData, 901 + "Not enough data for `cond`", 902 + ); 903 + }; 904 + let mut bodies = Vec::new(); 905 + let mut tir_branches = Vec::new(); 906 + for hir::CondBranch { pattern, body } in branches { 907 + let (pat_ty, tir_pat) = match &pattern.inner { 908 + Hir::Literal(l) => match l { 909 + Literal::Bool(_) => ( 910 + self.ty_ctx.engine.insert(TypeInfo::Bool), 911 + Tir::Literal(l.clone()), 912 + ), 913 + Literal::Num(_) => ( 914 + self.ty_ctx.engine.insert(TypeInfo::U64), 915 + Tir::Literal(l.clone()), 916 + ), 917 + Literal::String(_) => todo!(), 918 + Literal::Char(_) => ( 919 + self.ty_ctx.engine.insert(TypeInfo::Char), 920 + Tir::Literal(l.clone()), 921 + ), 922 + }, 923 + Hir::IgnorePattern => ( 924 + self.ty_ctx.engine.insert(TypeInfo::Unknown), 925 + Tir::IgnorePattern, 926 + ), 927 + _ => todo!(), 928 + }; 929 + let tir_pattern = TirNode { 930 + span: pattern.span, 931 + node: tir_pat, 932 + ins: vec![], 933 + outs: vec![], 934 + }; 935 + if let Err(message) = self.ty_ctx.engine.unify(ty, pat_ty) { 936 + return error(pattern.span, ErrorKind::UnificationError, message); 937 + } 938 + let mut ins_b = ins.clone(); 939 + let body = self.typecheck_body( 940 + &mut ins_b, 941 + heap, 942 + body, 943 + bindings, 944 + generics, 945 + expected_outs, 946 + in_const, 947 + )?; 948 + let tir_branch = CondBranch { 949 + pattern: tir_pattern, 950 + body, 951 + }; 952 + tir_branches.push(tir_branch); 953 + bodies.push(ins_b); 230 954 } 231 - const_name if self.is_const(const_name) => {} 232 - _ => todo!(), 233 - }, 234 - HirKind::Intrinsic(_) => todo!(), 235 - HirKind::Bind(_) => todo!(), 236 - HirKind::While(_) => todo!(), 237 - HirKind::If(_) => todo!(), 238 - HirKind::Cond(_) => todo!(), 239 - HirKind::Literal(ref c) => match c { 240 - IConst::Bool(_) => { 241 - stack.push(&mut self.heap, Type::BOOL); 955 + if bodies.array_windows::<2>().any(|[a, b]| { 956 + self.ty_ctx 957 + .engine 958 + .unify_stacks(heap, a.clone(), b.clone()) 959 + .is_err() 960 + }) { 961 + return error(node.span, ErrorKind::UnificationError, "Uhh"); 962 + } 963 + *ins = bodies.pop().unwrap(); 964 + 965 + TirNode { 966 + span: node.span, 967 + node: Tir::Cond(Cond { 968 + branches: tir_branches, 969 + }), 970 + ins: vec![], 971 + outs: vec![], 242 972 } 243 - IConst::U64(_) => { 244 - stack.push(&mut self.heap, Type::U64); 973 + } 974 + Hir::Literal(l) => { 975 + let mut w_outs = Vec::new(); 976 + match l { 977 + Literal::Bool(_) => { 978 + let bool = self.ty_ctx.engine.insert(TypeInfo::Bool); 979 + ins.push(heap, bool); 980 + w_outs.push(bool) 981 + } 982 + Literal::Num(_) => { 983 + let u64 = self.ty_ctx.engine.insert(TypeInfo::U64); 984 + ins.push(heap, u64); 985 + w_outs.push(u64) 986 + } 987 + Literal::String(_) => { 988 + let cptr = type_to_info( 989 + &mut self.ty_ctx.engine, 990 + &Type::ptr_to(Type::CHAR), 991 + false, 992 + ); 993 + let cptr = self.ty_ctx.engine.insert(cptr); 994 + let u64 = self.ty_ctx.engine.insert(TypeInfo::U64); 995 + ins.push(heap, u64); 996 + ins.push(heap, cptr); 997 + w_outs.push(u64); 998 + w_outs.push(cptr) 999 + } 1000 + Literal::Char(_) => { 1001 + let char = self.ty_ctx.engine.insert(TypeInfo::Char); 1002 + ins.push(heap, char); 1003 + w_outs.push(char) 1004 + } 1005 + }; 1006 + TirNode { 1007 + span: node.span, 1008 + node: Tir::Literal(l.clone()), 1009 + ins: vec![], 1010 + outs: w_outs, 245 1011 } 246 - IConst::I64(_) => todo!(), 247 - IConst::Char(_) => { 248 - stack.push(&mut self.heap, Type::CHAR); 1012 + } 1013 + Hir::IgnorePattern => todo!(), 1014 + Hir::Return => { 1015 + if let Some(expected) = expected_outs { 1016 + if let Err(message) = 1017 + self.ty_ctx 1018 + .engine 1019 + .unify_stacks(heap, ins.clone(), expected.clone()) 1020 + { 1021 + return error(node.span, ErrorKind::UnificationError, message); 1022 + } 249 1023 } 250 - IConst::Str(_) => { 251 - stack.push(&mut self.heap, Type::U64); 252 - stack.push(&mut self.heap, Type::ptr_to(Type::CHAR)); 1024 + TirNode { 1025 + span: node.span, 1026 + node: Tir::Return, 1027 + ins: ins.clone().into_vec(heap), 1028 + outs: vec![], 253 1029 } 254 - IConst::Ptr(_) => todo!(), 255 - }, 256 - HirKind::IgnorePattern => todo!(), 257 - HirKind::Return => todo!(), 258 - HirKind::FieldAccess(_) => todo!(), 259 - HirKind::Type(_) => todo!(), 260 - } 1030 + } 1031 + Hir::FieldAccess(hir::FieldAccess { field }) => { 1032 + let (in_ty, out_ty) = if let Some(ty) = ins.pop(heap) { 1033 + let out_ty = match self.ty_ctx.engine.reconstruct(ty) { 1034 + Ok(ty) => match ty { 1035 + Type::Generic(_) => todo!(), 1036 + Type::Concrete(ty) => match ty { 1037 + ConcreteType::Ptr(box ty) => match ty { 1038 + Type::Generic(_) => todo!(), 1039 + Type::Concrete(ty) => match ty { 1040 + ConcreteType::Ptr(_) => todo!(), 1041 + ConcreteType::Primitive(_) => todo!(), 1042 + ConcreteType::Custom(id) => { 1043 + if let Some((_, KStruct { id: _, fields })) = self 1044 + .known_structs 1045 + .iter() 1046 + .find(|(_, v)| v.id == id) 1047 + { 1048 + if let Some(ty) = fields.get(field) { 1049 + let info = type_to_info( 1050 + &mut self.ty_ctx.engine, 1051 + ty, 1052 + true, 1053 + ); 1054 + let ty = self.ty_ctx.engine.insert(info); 1055 + self.ty_ctx.engine.insert(TypeInfo::Ptr(ty)) 1056 + } else { 1057 + return error( 1058 + node.span, 1059 + ErrorKind::Undefined, 1060 + "No suchfield on this type", 1061 + ); 1062 + } 1063 + } else { 1064 + return error( 1065 + node.span, 1066 + ErrorKind::Undefined, 1067 + "Undefined type", 1068 + ); 1069 + } 1070 + } 1071 + }, 1072 + }, 1073 + ConcreteType::Primitive(_) => todo!(), 1074 + ConcreteType::Custom(_) => todo!(), 1075 + }, 1076 + }, 1077 + Err(_) => todo!(), 1078 + }; 1079 + ins.push(heap, out_ty); 1080 + (ty, out_ty) 1081 + } else { 1082 + return error( 1083 + node.span, 1084 + ErrorKind::NotEnoughData, 1085 + "There is no struct pointer on the stack", 1086 + ); 1087 + }; 1088 + 1089 + TirNode { 1090 + span: node.span, 1091 + node: Tir::FieldAccess(FieldAccess { 1092 + field: field.clone(), 1093 + }), 1094 + ins: vec![in_ty], 1095 + outs: vec![out_ty], 1096 + } 1097 + } 1098 + }; 1099 + checked_body.push(node); 261 1100 } 262 - ().okay() 1101 + 1102 + Ok(checked_body) 263 1103 } 264 1104 265 - fn abstract_to_concrete_type(&mut self, ty: HirNode, generics: &[String]) -> Result<Type> { 266 - let span = ty.span; 267 - let ty = if let HirKind::Type(ty) = ty.hir { 268 - ty 269 - } else { 270 - unreachable!() 271 - }; 272 - let kind = match ty.type_name.as_str() { 273 - "bool" => TypeKind::Concrete(ConcreteType::Bool), 274 - "char" => TypeKind::Concrete(ConcreteType::Char), 1105 + fn type_id(&mut self) -> TypeId { 1106 + let id = TypeId(self.next_type_id); 1107 + self.next_type_id += 1; 1108 + id 1109 + } 275 1110 276 - "u64" => TypeKind::Concrete(ConcreteType::U64), 277 - "u32" => TypeKind::Concrete(ConcreteType::U32), 278 - "u16" => TypeKind::Concrete(ConcreteType::U16), 279 - "u8" => TypeKind::Concrete(ConcreteType::U8), 1111 + fn gen_id(&mut self) -> GenId { 1112 + let id = GenId(self.next_type_id); 1113 + self.next_gen_id += 1; 1114 + id 1115 + } 280 1116 281 - "i64" => TypeKind::Concrete(ConcreteType::I64), 282 - "i32" => TypeKind::Concrete(ConcreteType::I32), 283 - "i16" => TypeKind::Concrete(ConcreteType::I16), 284 - "i8" => TypeKind::Concrete(ConcreteType::I8), 1117 + fn gen_id_reset(&mut self) { 1118 + self.next_gen_id = 0; 1119 + } 285 1120 286 - name if generics.contains(&ty.type_name) => TypeKind::Generic(ty.type_name), 287 - name if self.is_struct(name) => { 288 - TypeKind::Concrete(ConcreteType::Struct(self.structs.name_to_id(name).unwrap())) 289 - } 290 - name => { 291 - return error( 1121 + fn abstract_to_concrete_type( 1122 + &mut self, 1123 + ty: &Spanned<types::Type>, 1124 + generics: Option<&FnvHashMap<SmolStr, GenId>>, 1125 + ) -> Result<Type, Error> { 1126 + let span = ty.span; 1127 + let kind = match &ty.inner { 1128 + types::Type::Ptr(box t) => Type::ptr_to(self.abstract_to_concrete_type( 1129 + &Spanned { 292 1130 span, 293 - Undefined, 294 - format!("Cannot find type `{}` in this scope", name), 295 - ) 1131 + inner: t.clone(), 1132 + }, 1133 + generics, 1134 + )?), 1135 + types::Type::Primitive(ty) => Type::Concrete(ConcreteType::Primitive(*ty)), 1136 + types::Type::Custom(ty) => { 1137 + if let Some(ty) = self.known_structs.get(ty) { 1138 + Type::Concrete(ConcreteType::Custom(ty.id)) 1139 + } else if let Some(ty) = self.structs.get(ty).cloned() { 1140 + let mut fields = FnvHashMap::default(); 1141 + for (n, ty) in ty.fields { 1142 + let ty = self.abstract_to_concrete_type(&ty, None)?; 1143 + fields.insert(n, ty); 1144 + } 1145 + let id = self.type_id(); 1146 + self.known_structs.insert(ty.name, KStruct { id, fields }); 1147 + Type::Concrete(ConcreteType::Custom(id)) 1148 + } else if let Some(g) = ty.only() { 1149 + if let Some(id) = generics.and_then(|gs| gs.get(g)) { 1150 + Type::Generic(*id) 1151 + } else { 1152 + return typecheck::error( 1153 + span, 1154 + typecheck::ErrorKind::Undefined, 1155 + "This type name is not found in the current scope", 1156 + ); 1157 + } 1158 + } else { 1159 + return typecheck::error( 1160 + span, 1161 + typecheck::ErrorKind::Undefined, 1162 + "This type name is not found in the current scope", 1163 + ); 1164 + } 296 1165 } 297 1166 }; 298 1167 299 - Type { 300 - ptr_depth: ty.ptr_count, 301 - kind, 302 - } 303 - .okay() 304 - } 305 - 306 - fn is_struct(&self, name: &str) -> bool { 307 - self.structs.known(name) 1168 + kind.okay() 308 1169 } 309 1170 310 - fn is_proc(&self, proc_name: &str) -> bool { 311 - todo!() 1171 + fn is_proc(&self, name: &ItemPath) -> bool { 1172 + self.known_procs.contains_key(name) 312 1173 } 313 1174 314 - fn is_const(&self, const_name: &str) -> bool { 315 - todo!() 1175 + fn is_const(&self, name: &ItemPath) -> bool { 1176 + self.checked_consts.contains_key(name) 316 1177 } 317 1178 }
+30 -39
rotth/src/typecheck.rs
··· 1 1 use simplearena::{Heap, Ref}; 2 2 use somok::Somok; 3 + use spanner::Span; 3 4 use std::collections::VecDeque; 4 5 5 - use crate::{span::Span, tir, types::Type, Error}; 6 + use crate::{ 7 + inference::{TermId, TypeInfo}, 8 + Error, 9 + }; 10 + 11 + pub fn error<T>(span: Span, kind: ErrorKind, message: impl ToString) -> Result<T, Error> { 12 + Error::Typecheck(TypecheckError::new(span, kind, message)).error() 13 + } 14 + 15 + impl From<TypecheckError> for Error { 16 + fn from(e: TypecheckError) -> Self { 17 + Self::Typecheck(e) 18 + } 19 + } 6 20 7 21 #[derive(Debug)] 8 22 pub struct TypecheckError { ··· 23 37 #[derive(Debug)] 24 38 pub enum ErrorKind { 25 39 TypeMismatch { 26 - expected: Vec<tir::Type>, 27 - actual: Vec<tir::Type>, 40 + expected: Vec<TypeInfo>, 41 + actual: Vec<TypeInfo>, 28 42 }, 43 + UnificationError, 44 + UnsupportedOperation, 29 45 NotEnoughData, 30 46 Undefined, 31 47 InvalidMain, ··· 34 50 Unexpected, 35 51 CallInConst, 36 52 } 37 - pub fn error<T>(span: Span, kind: ErrorKind, message: impl ToString) -> Result<T> { 38 - Error::Typecheck(TypecheckError::new(span, kind, message)).error() 39 - } 40 - 41 - pub type Result<T> = std::result::Result<T, Error>; 42 53 43 54 #[derive(Clone, Default)] 44 55 pub struct TypeStack { ··· 46 57 } 47 58 48 59 impl TypeStack { 49 - pub fn push(&mut self, heap: &mut THeap, ty: tir::Type) { 60 + pub fn push(&mut self, heap: &mut THeap, ty: TermId) { 50 61 let frame = TypeFrame { 51 62 ty, 52 63 prev: self.top.clone(), ··· 54 65 self.top = heap.alloc(frame).some(); 55 66 } 56 67 57 - pub fn pop(&mut self, heap: &THeap) -> Option<tir::Type> { 68 + pub fn pop(&mut self, heap: &THeap) -> Option<TermId> { 58 69 if let Some(top) = self.top.clone() { 59 70 let top = top.deref(heap).unwrap(); 60 71 let prev = top.prev.clone(); 61 72 self.top = prev; 62 - top.ty.clone().some() 73 + top.ty.some() 63 74 } else { 64 75 None 65 76 } 66 77 } 67 78 68 - pub fn eq(&self, other: &Self, heap: &THeap) -> bool { 69 - let (mut next_left, mut next_right) = (&self.top, &other.top); 70 - loop { 71 - match (next_left, next_right) { 72 - (Some(lhs), Some(rhs)) => { 73 - let lhs = if let Some(lhs) = lhs.deref(heap) { 74 - lhs 75 - } else { 76 - return false; 77 - }; 78 - let rhs = if let Some(rhs) = rhs.deref(heap) { 79 - rhs 80 - } else { 81 - return false; 82 - }; 83 - if lhs.ty != rhs.ty { 84 - break false; 85 - } 86 - next_left = &lhs.prev; 87 - next_right = &rhs.prev; 88 - continue; 89 - } 90 - (None, None) => break true, 91 - _ => break false, 92 - } 79 + pub fn from_iter(tys: impl Iterator<Item = TermId>, heap: &mut THeap) -> Self { 80 + let mut stack = Self::default(); 81 + for ty in tys { 82 + stack.push(heap, ty) 93 83 } 84 + stack 94 85 } 95 86 96 - pub fn into_vec(self, heap: &THeap) -> Vec<tir::Type> { 87 + pub fn into_vec(self, heap: &THeap) -> Vec<TermId> { 97 88 let mut res = VecDeque::new(); 98 89 let mut next = self.top; 99 90 while let Some(top) = next { 100 91 let top = top.deref(heap).unwrap(); 101 - res.push_front(top.ty.clone()); 92 + res.push_front(top.ty); 102 93 next = top.prev.clone() 103 94 } 104 95 res.into() ··· 107 98 108 99 #[derive(Debug, Clone)] 109 100 pub struct TypeFrame { 110 - ty: tir::Type, 101 + ty: TermId, 111 102 prev: Option<TRef>, 112 103 } 113 104
-257
rotth/src/types.rs
··· 1 - use crate::ast::TopLevel; 2 - use fnv::FnvHashMap; 3 - 4 - #[derive(Copy, Clone, Eq, PartialEq)] 5 - pub struct Type { 6 - pub ptr_depth: usize, 7 - pub value_type: ValueType, 8 - } 9 - 10 - impl std::fmt::Debug for Type { 11 - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 12 - write!( 13 - f, 14 - "{}{:?}", 15 - "&>".repeat(self.ptr_depth as usize), 16 - self.value_type 17 - ) 18 - } 19 - } 20 - impl Type { 21 - pub const BOOL: Self = Type { 22 - ptr_depth: 0, 23 - value_type: ValueType::Primitive(Primitive::Bool), 24 - }; 25 - 26 - pub const CHAR: Self = Type { 27 - ptr_depth: 0, 28 - value_type: ValueType::Primitive(Primitive::Char), 29 - }; 30 - 31 - pub const U64: Self = Type { 32 - ptr_depth: 0, 33 - value_type: ValueType::Primitive(Primitive::U64), 34 - }; 35 - pub const U32: Self = Type { 36 - ptr_depth: 0, 37 - value_type: ValueType::Primitive(Primitive::U32), 38 - }; 39 - pub const U16: Self = Type { 40 - ptr_depth: 0, 41 - value_type: ValueType::Primitive(Primitive::U16), 42 - }; 43 - pub const U8: Self = Type { 44 - ptr_depth: 0, 45 - value_type: ValueType::Primitive(Primitive::U8), 46 - }; 47 - 48 - pub const I64: Self = Type { 49 - ptr_depth: 0, 50 - value_type: ValueType::Primitive(Primitive::I64), 51 - }; 52 - pub const I32: Self = Type { 53 - ptr_depth: 0, 54 - value_type: ValueType::Primitive(Primitive::I32), 55 - }; 56 - pub const I16: Self = Type { 57 - ptr_depth: 0, 58 - value_type: ValueType::Primitive(Primitive::I16), 59 - }; 60 - pub const I8: Self = Type { 61 - ptr_depth: 0, 62 - value_type: ValueType::Primitive(Primitive::I8), 63 - }; 64 - 65 - pub const ANY: Self = Type { 66 - ptr_depth: 0, 67 - value_type: ValueType::Any, 68 - }; 69 - 70 - pub fn ptr_to(ty: Self) -> Self { 71 - let ptr_depth = ty.ptr_depth + 1; 72 - Self { 73 - ptr_depth, 74 - value_type: ty.value_type, 75 - } 76 - } 77 - 78 - pub fn pointee(&self) -> Self { 79 - assert!(self.is_ptr()); 80 - let ptr_depth = self.ptr_depth - 1; 81 - Self { 82 - ptr_depth, 83 - value_type: self.value_type, 84 - } 85 - } 86 - 87 - pub fn is_ptr(&self) -> bool { 88 - self.ptr_depth > 0 89 - } 90 - 91 - pub fn is_ptr_to(&self, ty: Self) -> bool { 92 - self.is_ptr() 93 - && self.ptr_depth.saturating_sub(1) == ty.ptr_depth 94 - && self.value_type == ty.value_type 95 - } 96 - 97 - pub fn size(&self, struct_index: &StructIndex) -> usize { 98 - if self.ptr_depth > 0 { 99 - 8 100 - } else { 101 - match self.value_type { 102 - ValueType::Primitive(p) => p.size(), 103 - ValueType::Any => unreachable!("Naked any type"), 104 - ValueType::Struct(s) => struct_index[s].size, 105 - } 106 - } 107 - } 108 - } 109 - 110 - #[derive(Debug, Copy, Clone, PartialEq, Eq)] 111 - pub enum ValueType { 112 - Primitive(Primitive), 113 - Struct(StructId), 114 - Any, 115 - } 116 - 117 - #[derive(Debug, Copy, Clone, PartialEq, Eq)] 118 - pub enum Primitive { 119 - Bool, 120 - Char, 121 - 122 - U64, 123 - U32, 124 - U16, 125 - U8, 126 - 127 - I64, 128 - I32, 129 - I16, 130 - I8, 131 - } 132 - impl Primitive { 133 - fn size(&self) -> usize { 134 - match self { 135 - Primitive::Bool => 1, 136 - Primitive::Char => 1, 137 - 138 - Primitive::U64 => 8, 139 - Primitive::U32 => 4, 140 - Primitive::U16 => 2, 141 - Primitive::U8 => 1, 142 - 143 - Primitive::I64 => 8, 144 - Primitive::I32 => 4, 145 - Primitive::I16 => 2, 146 - Primitive::I8 => 1, 147 - } 148 - } 149 - } 150 - 151 - pub struct StructBuilder<'i> { 152 - index: &'i mut StructIndex, 153 - fields: FnvHashMap<String, Type>, 154 - name: String, 155 - } 156 - 157 - impl<'i> StructBuilder<'i> { 158 - pub fn field(&mut self, name: String, ty: Type) -> &mut Self { 159 - self.fields.insert(name, ty); 160 - self 161 - } 162 - pub fn finish(self) -> StructId { 163 - let mut fields = FnvHashMap::default(); 164 - let mut curr_offset = 0; 165 - for (name, ty) in self.fields { 166 - let field = Field { 167 - ty, 168 - offset: curr_offset, 169 - }; 170 - curr_offset += ty.size(self.index); 171 - fields.insert(name, field); 172 - } 173 - 174 - let struct_ = Struct { 175 - name: self.name, 176 - fields, 177 - size: curr_offset, 178 - }; 179 - let id = self.index.structs.len(); 180 - self.index.structs.push(struct_); 181 - StructId(id) 182 - } 183 - } 184 - 185 - #[derive(Default)] 186 - pub struct StructIndex { 187 - structs: Vec<Struct>, 188 - } 189 - 190 - impl StructIndex { 191 - pub fn new_struct(&'_ mut self, name: String) -> StructBuilder<'_> { 192 - StructBuilder { 193 - index: self, 194 - fields: Default::default(), 195 - name, 196 - } 197 - } 198 - pub fn known(&self, name: &str) -> bool { 199 - self.structs.iter().any(|s| s.name == name) 200 - } 201 - pub fn id_names(&'_ self) -> impl Iterator<Item = (StructId, &'_ str)> { 202 - self.structs 203 - .iter() 204 - .enumerate() 205 - .map(|(i, s)| (StructId(i), &*s.name)) 206 - } 207 - pub fn name_to_id(&self, name: &str) -> Option<StructId> { 208 - self.id_names() 209 - .find_map(|(i, n)| if n == name { Some(i) } else { None }) 210 - } 211 - } 212 - 213 - impl std::ops::Index<StructId> for StructIndex { 214 - type Output = Struct; 215 - 216 - fn index(&self, index: StructId) -> &Self::Output { 217 - &self.structs[index.0] 218 - } 219 - } 220 - 221 - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 222 - pub struct StructId(usize); 223 - 224 - #[derive(Debug, PartialEq, Eq)] 225 - pub struct Struct { 226 - pub name: String, 227 - pub fields: FnvHashMap<String, Field>, 228 - pub size: usize, 229 - } 230 - 231 - #[derive(Debug, PartialEq, Eq)] 232 - pub struct Field { 233 - pub ty: Type, 234 - pub offset: usize, 235 - } 236 - 237 - pub fn define_structs(structs: FnvHashMap<String, TopLevel>) -> StructIndex { 238 - let mut index = StructIndex::default(); 239 - for (name, struct_) in structs { 240 - if let TopLevel::Struct(s) = &struct_ { 241 - let mut builder = index.new_struct(name); 242 - for field in &s.body { 243 - let field = coerce_ast!(field => REF StructField || unreachable!()); 244 - let name = coerce_ast!(field.name => REF Word || unreachable!()); 245 - let ty = coerce_ast!(field.ty => REF Type || unreachable!()) 246 - .clone() 247 - .to_primitive_type(); 248 - 249 - builder.field(name.clone(), ty); 250 - } 251 - builder.finish(); 252 - } else { 253 - unreachable!(); 254 - } 255 - } 256 - index 257 - }
+10
spanner/Cargo.toml
··· 1 + [package] 2 + name = "spanner" 3 + version = "0.1.0" 4 + edition = "2021" 5 + 6 + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 + 8 + [dependencies] 9 + ariadne = "0.1" 10 + chumsky = { git = "https://github.com/zesterer/chumsky.git" }
+134
spanner/src/lib.rs
··· 1 + use std::{ 2 + fmt::Debug, 3 + ops::{Deref, DerefMut, Range}, 4 + path::Path, 5 + }; 6 + 7 + #[derive(Copy, Clone, Hash, PartialEq, Eq)] 8 + pub struct Spanned<T> { 9 + pub span: Span, 10 + pub inner: T, 11 + } 12 + 13 + impl<T: Debug> Debug for Spanned<T> { 14 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 15 + if f.alternate() { 16 + write!(f, "{:#?}@{:#?}", self.inner, self.span) 17 + } else { 18 + write!(f, "{:?}@{:?}", self.inner, self.span) 19 + } 20 + } 21 + } 22 + 23 + impl<T> Spanned<T> { 24 + pub fn map<F, B>(self, f: F) -> Spanned<B> 25 + where 26 + F: FnOnce(T) -> B, 27 + { 28 + Spanned { 29 + span: self.span, 30 + inner: f(self.inner), 31 + } 32 + } 33 + } 34 + 35 + impl<T> Deref for Spanned<T> { 36 + type Target = T; 37 + 38 + fn deref(&self) -> &Self::Target { 39 + &self.inner 40 + } 41 + } 42 + 43 + impl<T> DerefMut for Spanned<T> { 44 + fn deref_mut(&mut self) -> &mut Self::Target { 45 + &mut self.inner 46 + } 47 + } 48 + 49 + #[derive(Copy, Clone, Hash, PartialEq, Eq)] 50 + pub struct Span { 51 + pub file: &'static Path, 52 + pub start: usize, 53 + pub end: usize, 54 + } 55 + 56 + impl Span { 57 + pub fn new(file: &'static Path, start: usize, end: usize) -> Self { 58 + Self { file, start, end } 59 + } 60 + pub fn point(file: &'static Path, point: usize) -> Self { 61 + Self { 62 + file, 63 + start: point, 64 + end: point + 1, 65 + } 66 + } 67 + pub fn length(&self) -> usize { 68 + self.end - self.start 69 + } 70 + 71 + pub fn merge(self, other: Self) -> Self { 72 + assert!(self.file == other.file); 73 + assert!(self.start < other.start); 74 + Self { 75 + file: self.file, 76 + start: self.start, 77 + end: other.end, 78 + } 79 + } 80 + } 81 + 82 + impl Debug for Span { 83 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 84 + if f.alternate() { 85 + write!(f, "{:?}[{}..{}]", &self.file, &self.start, &self.end) 86 + } else { 87 + write!( 88 + f, 89 + "{:?}[{}..{}]", 90 + self.file.file_name().unwrap(), 91 + &self.start, 92 + &self.end 93 + ) 94 + } 95 + } 96 + } 97 + 98 + impl ariadne::Span for Span { 99 + type SourceId = Path; 100 + 101 + fn source(&self) -> &Self::SourceId { 102 + self.file 103 + } 104 + 105 + fn start(&self) -> usize { 106 + self.start 107 + } 108 + 109 + fn end(&self) -> usize { 110 + self.end 111 + } 112 + } 113 + 114 + impl chumsky::Span for Span { 115 + type Context = &'static Path; 116 + 117 + type Offset = usize; 118 + 119 + fn new(file: Self::Context, range: Range<Self::Offset>) -> Self { 120 + Self::new(file, range.start, range.end) 121 + } 122 + 123 + fn context(&self) -> Self::Context { 124 + self.file 125 + } 126 + 127 + fn start(&self) -> Self::Offset { 128 + self.start 129 + } 130 + 131 + fn end(&self) -> Self::Offset { 132 + self.end 133 + } 134 + }