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.

Fixed path for asm output

Ivan Chinenov (Mar 13, 2022, 12:37 PM +0300) 330c2b2c 4e86e5c6

+17 -583
-578
src/hir.bak.rs
··· 1 - use crate::{ 2 - iconst::IConst, 3 - lexer::{KeyWord, Token}, 4 - resolver::resolve_include, 5 - span::Span, 6 - types::Type, 7 - Error, RedefinitionError, 8 - }; 9 - use chumsky::{prelude::*, Stream}; 10 - use somok::Somok; 11 - use std::{ 12 - collections::{hash_map::Entry, HashMap}, 13 - path::PathBuf, 14 - }; 15 - 16 - #[derive(Debug, Clone)] 17 - pub struct Signature { 18 - pub ins: Vec<Type>, 19 - pub outs: Vec<Type>, 20 - } 21 - 22 - #[derive(Debug, Clone)] 23 - pub struct Proc { 24 - pub signature: Signature, 25 - pub body: Vec<AstNode>, 26 - } 27 - fn ty() -> impl Parser<Token, Type, Error = Simple<Token, Span>> { 28 - let value_type = filter_map(|s, t| match &t { 29 - Token::Word(ty) => match &**ty { 30 - "u64" => Type::U64.okay(), 31 - "u32" => Type::U32.okay(), 32 - "u16" => Type::U16.okay(), 33 - "u8" => Type::U8.okay(), 34 - 35 - "i64" => Type::I64.okay(), 36 - "i32" => Type::I32.okay(), 37 - "i16" => Type::I16.okay(), 38 - "i8" => Type::I8.okay(), 39 - 40 - "bool" => Type::BOOL.okay(), 41 - "char" => Type::CHAR.okay(), 42 - _ => Simple::expected_input_found( 43 - s, 44 - vec![Some(Token::Word("type".to_string()))], 45 - Some(t), 46 - ) 47 - .error(), 48 - }, 49 - _ => Simple::expected_input_found( 50 - s, 51 - vec![Some(Token::Word("some-type".to_string()))], 52 - Some(t), 53 - ) 54 - .error(), 55 - }); 56 - let any = just(Token::Word("()".to_string())).to(Type::ANY); 57 - let ptr_type = recursive(|p_ty| { 58 - just(Token::Ptr) 59 - .ignore_then(choice((p_ty, choice((value_type, any))))) 60 - .map(Type::ptr_to) 61 - }); 62 - choice((value_type, ptr_type)) 63 - } 64 - 65 - fn proc() -> impl Parser<Token, (String, (TopLevel, Span)), Error = Simple<Token, Span>> { 66 - let sig_sep = just(Token::SigSep); 67 - let signature = ty() 68 - .repeated() 69 - .then(sig_sep.then(ty().repeated().at_least(1)).or_not()) 70 - .map(|(ins, outs)| { 71 - let outs = if let Some((_, types)) = outs { 72 - types 73 - } else { 74 - vec![] 75 - }; 76 - Signature { ins, outs } 77 - }); 78 - 79 - just(Token::KeyWord(KeyWord::Proc)) 80 - .ignored() 81 - .then(identifier()) 82 - .then(signature) 83 - .then_ignore(just(Token::KeyWord(KeyWord::Do))) 84 - .then(body()) 85 - .then_ignore(just(Token::KeyWord(KeyWord::End))) 86 - .map_with_span(|((((), name), signature), body), s| { 87 - (name, (TopLevel::Proc(Proc { signature, body }), s)) 88 - }) 89 - } 90 - 91 - #[derive(Debug, Clone)] 92 - pub struct AstNode { 93 - pub span: Span, 94 - pub ast: AstKind, 95 - } 96 - 97 - #[derive(Debug, Clone)] 98 - pub enum AstKind { 99 - Literal(IConst), 100 - Word(String), 101 - Intrinsic(Intrinsic), 102 - If(If), 103 - Cond(Cond), 104 - Return, 105 - While(While), 106 - Bind(Bind), 107 - } 108 - 109 - #[derive(Debug, Clone)] 110 - pub struct Cond { 111 - pub branches: Vec<CondBranch>, 112 - pub other: Vec<AstNode>, 113 - } 114 - 115 - #[derive(Debug, Clone)] 116 - pub struct CondBranch { 117 - pub pattern: AstNode, 118 - pub body: Vec<AstNode>, 119 - } 120 - 121 - #[derive(Debug, Clone)] 122 - pub enum Intrinsic { 123 - Drop, 124 - Dup, 125 - Swap, 126 - Over, 127 - 128 - Cast(Type), 129 - 130 - ReadU64, 131 - ReadU8, 132 - WriteU64, 133 - WriteU8, 134 - 135 - CompStop, 136 - Dump, 137 - Print, 138 - 139 - Syscall0, 140 - Syscall1, 141 - Syscall2, 142 - Syscall3, 143 - Syscall4, 144 - Syscall5, 145 - Syscall6, 146 - 147 - Argc, 148 - Argv, 149 - 150 - Add, 151 - Sub, 152 - Divmod, 153 - Mul, 154 - 155 - Eq, 156 - Ne, 157 - Lt, 158 - Le, 159 - Gt, 160 - Ge, 161 - } 162 - 163 - #[derive(Debug, Clone)] 164 - pub struct Const { 165 - pub body: Vec<AstNode>, 166 - pub types: Vec<Type>, 167 - } 168 - 169 - #[derive(Debug, Clone)] 170 - pub struct Bind { 171 - pub bindings: Vec<Binding>, 172 - pub body: Vec<AstNode>, 173 - } 174 - 175 - #[derive(Debug, Clone)] 176 - pub enum Binding { 177 - Ignore, 178 - Bind { name: String, ty: Type }, 179 - } 180 - 181 - #[derive(Debug, Clone)] 182 - pub struct If { 183 - pub truth: Vec<AstNode>, 184 - pub lie: Option<Vec<AstNode>>, 185 - } 186 - 187 - #[derive(Debug, Clone)] 188 - pub struct While { 189 - pub cond: Vec<AstNode>, 190 - pub body: Vec<AstNode>, 191 - } 192 - 193 - fn word() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 194 - filter_map(|span, token| { 195 - match token { 196 - Token::Word(ref w) 197 - if matches!( 198 - w.as_str(), 199 - "drop" 200 - | "dup" 201 - | "swap" 202 - | "over" 203 - | "&?&" 204 - | "&?" 205 - | "print" 206 - | "=" 207 - | "!=" 208 - | "<" 209 - | "<=" 210 - | ">" 211 - | ">=" 212 - ) => 213 - { 214 - return Simple::expected_input_found( 215 - span, 216 - vec![Some(Token::Word("not-intrinsic".to_string()))], 217 - Some(token), 218 - ) 219 - .error(); 220 - } 221 - Token::Word(w) => AstNode { 222 - ast: AstKind::Word(w), 223 - span, 224 - }, 225 - _ => { 226 - return Simple::expected_input_found( 227 - span, 228 - vec![Some(Token::Word("not-intrinsic".to_string()))], 229 - Some(token), 230 - ) 231 - .error(); 232 - } 233 - } 234 - .okay() 235 - }) 236 - } 237 - 238 - fn intrinsic() -> impl Parser<Token, AstNode, Error = Simple<Token, Span>> { 239 - filter_map(|span, token| match &token { 240 - Token::Word(w) => AstNode { 241 - ast: match w.as_str() { 242 - "drop" => AstKind::Intrinsic(Intrinsic::Drop), 243 - "dup" => AstKind::Intrinsic(Intrinsic::Dup), 244 - "swap" => AstKind::Intrinsic(Intrinsic::Swap), 245 - "over" => AstKind::Intrinsic(Intrinsic::Over), 246 - 247 - "@u64" => AstKind::Intrinsic(Intrinsic::ReadU64), 248 - "@u8" => AstKind::Intrinsic(Intrinsic::ReadU8), 249 - "!u64" => AstKind::Intrinsic(Intrinsic::WriteU64), 250 - "!u8" => AstKind::Intrinsic(Intrinsic::WriteU8), 251 - 252 - "&?&" => AstKind::Intrinsic(Intrinsic::CompStop), 253 - "&?" => AstKind::Intrinsic(Intrinsic::Dump), 254 - "print" => AstKind::Intrinsic(Intrinsic::Print), 255 - 256 - "syscall0" => AstKind::Intrinsic(Intrinsic::Syscall0), 257 - "syscall1" => AstKind::Intrinsic(Intrinsic::Syscall1), 258 - "syscall2" => AstKind::Intrinsic(Intrinsic::Syscall2), 259 - "syscall3" => AstKind::Intrinsic(Intrinsic::Syscall3), 260 - "syscall4" => AstKind::Intrinsic(Intrinsic::Syscall4), 261 - "syscall5" => AstKind::Intrinsic(Intrinsic::Syscall5), 262 - "syscall6" => AstKind::Intrinsic(Intrinsic::Syscall6), 263 - 264 - "argc" => AstKind::Intrinsic(Intrinsic::Argc), 265 - "argv" => AstKind::Intrinsic(Intrinsic::Argv), 266 - 267 - "+" => AstKind::Intrinsic(Intrinsic::Add), 268 - "-" => AstKind::Intrinsic(Intrinsic::Sub), 269 - "*" => AstKind::Intrinsic(Intrinsic::Mul), 270 - "divmod" => AstKind::Intrinsic(Intrinsic::Divmod), 271 - 272 - "=" => AstKind::Intrinsic(Intrinsic::Eq), 273 - "!=" => AstKind::Intrinsic(Intrinsic::Ne), 274 - "<" => AstKind::Intrinsic(Intrinsic::Lt), 275 - "<=" => AstKind::Intrinsic(Intrinsic::Le), 276 - ">" => AstKind::Intrinsic(Intrinsic::Gt), 277 - ">=" => AstKind::Intrinsic(Intrinsic::Ge), 278 - _ => { 279 - return Simple::expected_input_found( 280 - span, 281 - vec![Some(Token::Word("some-intrinsic".to_string()))], 282 - Some(token), 283 - ) 284 - .error() 285 - } 286 - }, 287 - span, 288 - } 289 - .okay(), 290 - _ => Simple::expected_input_found( 291 - span, 292 - vec![Some(Token::Word("some-intrinsic".to_string()))], 293 - Some(token), 294 - ) 295 - .error(), 296 - }) 297 - } 298 - 299 - fn identifier() -> impl Parser<Token, String, Error = Simple<Token, Span>> { 300 - filter(|t| matches!(t, Token::Word(_))).map(|token| match token { 301 - Token::Word(w) => w, 302 - _ => unreachable!(), 303 - }) 304 - } 305 - 306 - fn body() -> impl Parser<Token, Vec<AstNode>, Error = Simple<Token, Span>> + Clone { 307 - recursive(|body| { 308 - let name_type = identifier() 309 - .then_ignore(just(Token::SigSep)) 310 - .then(ty()) 311 - .map(|(name, ty)| Binding::Bind { name, ty }); 312 - 313 - let ignore = just(Token::Ignore).to(Binding::Ignore); 314 - 315 - let bind = just(Token::KeyWord(KeyWord::Bind)) 316 - .ignore_then(choice((ignore, name_type)).repeated().at_least(1)) 317 - .then_ignore(just(Token::KeyWord(KeyWord::Do))) 318 - .then(body.clone()) 319 - .then_ignore(just(Token::KeyWord(KeyWord::End))) 320 - .map_with_span(|(bindings, body), span| AstNode { 321 - ast: AstKind::Bind(Bind { bindings, body }), 322 - span, 323 - }); 324 - 325 - let num = filter(|t| matches!(t, Token::Num(_))).map_with_span(|token, span| AstNode { 326 - ast: AstKind::Literal(if let Token::Num(n) = token { 327 - IConst::U64(n.parse().unwrap()) 328 - } else { 329 - unreachable!() 330 - }), 331 - span, 332 - }); 333 - 334 - let char = 335 - filter(|token| matches!(token, Token::Char(_))).map_with_span( 336 - |token, span| match token { 337 - Token::Char(c) => AstNode { 338 - span, 339 - ast: AstKind::Literal(IConst::Char(c)), 340 - }, 341 - _ => unreachable!(), 342 - }, 343 - ); 344 - 345 - let string = 346 - filter(|token| matches!(token, Token::Str(_))).map_with_span( 347 - |token, span| match token { 348 - Token::Str(s) => AstNode { 349 - span, 350 - ast: AstKind::Literal(IConst::Str(s)), 351 - }, 352 - _ => unreachable!(), 353 - }, 354 - ); 355 - 356 - let bool = filter(|t| matches!(t, Token::Word(_))).try_map(|token, span| match &token { 357 - Token::Word(w) => match w.as_str() { 358 - "true" => AstNode { 359 - ast: AstKind::Literal(IConst::Bool(true)), 360 - span, 361 - } 362 - .okay(), 363 - "false" => AstNode { 364 - ast: AstKind::Literal(IConst::Bool(false)), 365 - span, 366 - } 367 - .okay(), 368 - _ => Simple::expected_input_found( 369 - span, 370 - vec![ 371 - Some(Token::Word("true".to_string())), 372 - Some(Token::Word("false".to_string())), 373 - ], 374 - Some(token), 375 - ) 376 - .error(), 377 - }, 378 - _ => unreachable!(), 379 - }); 380 - 381 - let while_ = { 382 - just(Token::KeyWord(KeyWord::While)) 383 - .ignore_then(body.clone()) 384 - .then_ignore(just(Token::KeyWord(KeyWord::Do))) 385 - .then(body.clone()) 386 - .then_ignore(just(Token::KeyWord(KeyWord::End))) 387 - .map_with_span(|(cond, body), span| AstNode { 388 - ast: AstKind::While(While { cond, body }), 389 - span, 390 - }) 391 - }; 392 - 393 - let if_ = { 394 - let truth = body 395 - .clone() 396 - .then( 397 - just(Token::KeyWord(KeyWord::Else)) 398 - .ignore_then(body.clone()) 399 - .or_not(), 400 - ) 401 - .then_ignore(just(Token::KeyWord(KeyWord::End))); 402 - 403 - just(Token::KeyWord(KeyWord::If)) 404 - .ignored() 405 - .then(truth) 406 - .map_with_span(|((), (truth, lie)), span| AstNode { 407 - ast: AstKind::If(If { truth, lie }), 408 - span, 409 - }) 410 - }; 411 - 412 - let ret = just(Token::KeyWord(KeyWord::Return)).map_with_span(|_, span| AstNode { 413 - span, 414 - ast: AstKind::Return, 415 - }); 416 - 417 - let cast = just(Token::KeyWord(KeyWord::Cast)) 418 - .ignore_then(ty()) 419 - .map_with_span(|ty, span| AstNode { 420 - span, 421 - ast: AstKind::Intrinsic(Intrinsic::Cast(ty)), 422 - }); 423 - 424 - let pattern = choice((num, char, bool, word())); 425 - let cond_branch = pattern 426 - .then_ignore(just(Token::KeyWord(KeyWord::Do))) 427 - .then(body.clone()) 428 - .map(|(pattern, body)| CondBranch { pattern, body }); 429 - let cond = just(Token::KeyWord(KeyWord::Cond)) 430 - .ignore_then( 431 - cond_branch 432 - .separated_by(just(Token::KeyWord(KeyWord::Else))) 433 - .at_least(1), 434 - ) 435 - .then( 436 - just(Token::KeyWord(KeyWord::Otherwise)) 437 - .ignore_then(body) 438 - .then_ignore(just(Token::KeyWord(KeyWord::End))), 439 - ) 440 - .map_with_span(|(branches, other), span| AstNode { 441 - span, 442 - ast: AstKind::Cond(Cond { branches, other }), 443 - }); 444 - 445 - choice(( 446 - bool, 447 - intrinsic(), 448 - word(), 449 - char, 450 - string, 451 - num, 452 - ret, 453 - if_, 454 - cond, 455 - while_, 456 - bind, 457 - cast, 458 - )) 459 - .repeated() 460 - }) 461 - } 462 - 463 - fn constant() -> impl Parser<Token, (String, (TopLevel, Span)), Error = Simple<Token, Span>> { 464 - just(Token::KeyWord(KeyWord::Const)) 465 - .ignore_then(identifier()) 466 - .then_ignore(just(Token::SigSep)) 467 - .then(ty().repeated().at_least(1)) 468 - .then_ignore(just(Token::KeyWord(KeyWord::Do))) 469 - .then(body()) 470 - .then_ignore(just(Token::KeyWord(KeyWord::End))) 471 - .map_with_span(|((name, types), body), span| { 472 - (name, (TopLevel::Const(Const { body, types }), span)) 473 - }) 474 - } 475 - 476 - fn include() -> impl Parser<Token, (String, (TopLevel, Span)), Error = Simple<Token, Span>> { 477 - just(Token::KeyWord(KeyWord::Include)) 478 - .ignore_then( 479 - filter(|token| matches!(token, Token::Str(_))).map(|token| match token { 480 - Token::Str(s) => s.into(), 481 - _ => unreachable!(), 482 - }), 483 - ) 484 - .map_with_span(|path, span| (String::new(), (TopLevel::Include(path), span))) 485 - } 486 - 487 - #[derive(Debug, Clone)] 488 - pub struct Mem { 489 - pub body: Vec<AstNode>, 490 - } 491 - 492 - #[derive(Debug, Clone)] 493 - pub enum TopLevel { 494 - Proc(Proc), 495 - Const(Const), 496 - Include(PathBuf), 497 - Mem(Mem), 498 - } 499 - impl TopLevel { 500 - pub fn as_proc(&self) -> Option<&Proc> { 501 - if let Self::Proc(v) = self { 502 - Some(v) 503 - } else { 504 - None 505 - } 506 - } 507 - 508 - pub fn as_const(&self) -> Option<&Const> { 509 - if let Self::Const(v) = self { 510 - Some(v) 511 - } else { 512 - None 513 - } 514 - } 515 - } 516 - 517 - fn mem() -> impl Parser<Token, (String, (TopLevel, Span)), Error = Simple<Token, Span>> { 518 - just(Token::KeyWord(KeyWord::Mem)) 519 - .ignore_then(identifier()) 520 - .then_ignore(just(Token::KeyWord(KeyWord::Do))) 521 - .then(body()) 522 - .then_ignore(just(Token::KeyWord(KeyWord::End))) 523 - .map_with_span(|(name, body), span| (name, (TopLevel::Mem(Mem { body }), span))) 524 - } 525 - 526 - fn toplevel_items( 527 - ) -> impl Parser<Token, Vec<(String, (TopLevel, Span))>, Error = Simple<Token, Span>> { 528 - choice((proc(), constant(), include(), mem())) 529 - .repeated() 530 - .then_ignore(end()) 531 - .collect() 532 - } 533 - 534 - pub fn parse(tokens: Vec<(Token, Span)>) -> Result<HashMap<String, (TopLevel, Span)>, Error> { 535 - let items = match toplevel_items().parse(Stream::from_iter( 536 - tokens.last().unwrap().1.clone(), 537 - tokens.into_iter(), 538 - )) { 539 - Ok(items) => items, 540 - Err(es) => return Error::Parser(es).error(), 541 - }; 542 - 543 - let (includes, mut items) = items 544 - .into_iter() 545 - .partition::<Vec<_>, _>(|(_, (item, _))| matches!(item, TopLevel::Include(_))); 546 - 547 - for (_, (include, _)) in includes { 548 - if let TopLevel::Include(path) = include { 549 - resolve_include(path, &mut items)?; 550 - } else { 551 - unreachable!(); 552 - } 553 - } 554 - 555 - let mut res = HashMap::new(); 556 - let mut errors = Vec::new(); 557 - 558 - for (name, (item, span)) in items { 559 - match res.entry(name) { 560 - Entry::Occupied(it) => { 561 - let redefined: &(TopLevel, Span) = it.get(); 562 - errors.push(RedefinitionError { 563 - redefining_item: span, 564 - redefined_item: redefined.1.clone(), 565 - }); 566 - } 567 - Entry::Vacant(v) => { 568 - v.insert((item, span)); 569 - } 570 - } 571 - } 572 - 573 - if errors.is_empty() { 574 - res.okay() 575 - } else { 576 - Error::Redefinition(errors).error() 577 - } 578 - }
+17 -5
src/main.rs
··· 18 18 struct Args { 19 19 #[clap(short = 'k', long)] 20 20 dump_tokens: bool, 21 + #[clap(short = 'a', long)] 22 + dump_ast: bool, 21 23 #[clap(short = 'i', long)] 22 24 dump_hir: bool, 23 25 #[clap(short = 'l', long)] ··· 218 220 let source = args.source.canonicalize()?; 219 221 std::env::set_current_dir(&source.parent().unwrap())?; 220 222 221 - let tokens = lex(source)?; 223 + let tokens = lex(source.clone())?; 222 224 223 225 let tokenized = Instant::now(); 224 226 if args.time { ··· 237 239 println!("Parsed in:\t{:?}", parsed - tokenized) 238 240 } 239 241 240 - if args.dump_hir { 241 - println!("HIR:\n"); 242 + if args.dump_ast { 243 + println!("AST:\n"); 242 244 println!("{ast:#?}"); 243 245 } 244 246 245 247 let hir = hir_for_ast(ast); 246 248 249 + let lowered = Instant::now(); 250 + if args.time { 251 + println!("Lowered in:\t{:?}", lowered - parsed) 252 + } 253 + 254 + if args.dump_ast { 255 + println!("HIR:\n"); 256 + println!("{hir:#?}"); 257 + } 258 + 247 259 let procs = typecheck_program(hir)?; 248 260 249 261 let typechecked = Instant::now(); 250 262 if args.time { 251 - println!("Typechecked in:\t{:?}", typechecked - parsed) 263 + println!("Typechecked in:\t{:?}", typechecked - lowered) 252 264 } 253 265 254 266 let comp = lir::Compiler::default(); ··· 276 288 .create(true) 277 289 .write(true) 278 290 .truncate(true) 279 - .open(args.source.with_extension("asm"))?, 291 + .open(source.with_extension("asm"))?, 280 292 ), 281 293 )?; 282 294