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.

Improvements to imports and structs

Ivan Chinenov (Jun 16, 2022, 3:31 PM +0300) 5b46493b 05b7d7e3

+637 -283
+6
bar.rh
··· 1 + include "foo.rh" 2 + 3 + struct Har do 4 + a: u64 5 + b: u8 6 + end
+3
baz.rh
··· 1 + proc a: u64 do 2 + 69 3 + end
+1
foo.rh
··· 1 + include "baz.rh"
+6 -1
justfile
··· 6 6 default: 7 7 @just --list 8 8 9 + assemble FILE: 10 + nasm -g -F dwarf -f elf64 {{root}}/print.asm -o {{root}}/print.o 11 + nasm -g -F dwarf -f elf64 {{FILE}}.asm -o {{FILE}}.o 12 + ld -o {{FILE}} {{FILE}}.o {{root}}/print.o 13 + 9 14 build FILE: 10 15 cargo run --bin rotth -- --compile -- {{rotthdir}}/{{FILE}}.rh 11 16 nasm -g -F dwarf -f elf64 {{root}}/print.asm -o {{root}}/print.o ··· 31 36 find {{rotthdir}} -type f ! -name "*.rh" -delete 32 37 33 38 build-extension: 34 - cd {{vscdir}} && yes | vsce package 39 + cd {{vscdir}} && yes | vsce package
new_tokenizer

This is a binary file and will not be displayed.

+23 -3
new_tokenizer.rh
··· 1 - ; proc [T] ptr+ &>T u64 : &>T do 2 - ; swap cast u64 + cast &>T 1 + include foo::baz::a Har from "bar.rh" 2 + 3 + ; struct Har do 4 + ; a: u64 5 + ; b: u8 3 6 ; end 4 7 8 + 9 + proc hartaker &>Har : u64 do 10 + drop 0 11 + end 12 + 5 13 proc main: u64 do 6 - 60 9 + 14 + a cast &>Har hartaker print 0 15 + end 16 + 17 + proc c1: u64 do 18 + a cast &>Har hartaker print 0 19 + end 20 + 21 + proc c2: u64 do 22 + a cast &>Har hartaker print 0 23 + end 24 + 25 + proc c3: u64 do 26 + a cast &>Har hartaker print 0 7 27 end
+3
rotth-lexer/src/lib.rs
··· 51 51 52 52 #[token("include")] 53 53 KwInclude, 54 + #[token("from")] 55 + KwFrom, 54 56 #[token("return")] 55 57 KwReturn, 56 58 #[token("cond")] ··· 106 108 Token::LBracket => write!(f, "{{"), 107 109 Token::RBracket => write!(f, "}}"), 108 110 Token::KwInclude => write!(f, "include"), 111 + Token::KwFrom => write!(f, "from"), 109 112 Token::KwReturn => write!(f, "return"), 110 113 Token::KwCond => write!(f, "cond"), 111 114 Token::KwIf => write!(f, "if"),
+6
rotth-lsp/src/semantic_token.rs
··· 30 30 match &**item { 31 31 TopLevel::Include(i) => { 32 32 push_token(&i.include, &mut semantic_tokens, SemanticTokenType::KEYWORD); 33 + if let Some(Qualifiers { items, from }) = &i.qualifiers { 34 + for item in items { 35 + push_token(item, &mut semantic_tokens, SemanticTokenType::FUNCTION); 36 + } 37 + push_token(from, &mut semantic_tokens, SemanticTokenType::KEYWORD); 38 + } 33 39 push_token(&i.path, &mut semantic_tokens, SemanticTokenType::STRING); 34 40 } 35 41 TopLevel::Proc(p) => {
+74 -48
rotth-parser/src/ast.rs
··· 11 11 fmt::Debug, 12 12 ops::{Deref, DerefMut}, 13 13 path::PathBuf, 14 + rc::Rc, 14 15 }; 15 16 16 17 use crate::{types::Type, Error, ParserError, Redefinition}; ··· 128 129 #[derive(Debug, Clone, Hash, PartialEq, Eq)] 129 130 pub enum Keyword { 130 131 Include, 132 + From, 131 133 Return, 132 134 Cond, 133 135 If, ··· 181 183 #[derive(Debug, Clone)] 182 184 pub struct Include { 183 185 pub include: Spanned<Keyword>, 184 - pub qualifiers: Vec<Spanned<Word>>, 186 + pub qualifiers: Option<Qualifiers>, 185 187 pub path: Spanned<PathBuf>, 186 188 } 187 189 190 + #[derive(Debug, Clone)] 191 + pub struct Qualifiers { 192 + pub items: Vec<Spanned<ItemPathBuf>>, 193 + pub from: Spanned<Keyword>, 194 + } 195 + 188 196 #[derive(Clone)] 189 197 pub enum Expr { 190 198 CompStop, ··· 384 392 self.segments.first().map(SmolStr::as_str) 385 393 } 386 394 395 + pub fn last(&self) -> Option<SmolStr> { 396 + self.segments.last().cloned() 397 + } 398 + 387 399 pub fn drop_first(&self) -> Option<&Self> { 388 400 self.segments 389 401 .split_first() ··· 416 428 417 429 #[macro_export] 418 430 macro_rules! path { 419 - ( $( $s:tt )::* ) => {{ 431 + ( $( $s:tt )::+ ) => {{ 420 432 let mut path = ItemPathBuf::new(); 421 433 $(path.push(stringify!($s));)* 422 434 path 423 435 }}; 436 + () => {{ 437 + ItemPathBuf::new() 438 + }}; 424 439 } 425 440 426 441 #[derive(PartialEq, Eq, Hash, Default, Clone)] ··· 504 519 505 520 #[derive(Clone)] 506 521 pub enum ResolvedItem { 507 - Ref(ItemPathBuf), 508 - Proc(Proc), 509 - Const(Const), 510 - Mem(Mem), 511 - Var(Var), 512 - Struct(ResolvedStruct), 513 - Module(Box<ResolvedFile>), 522 + Ref(Rc<ItemPathBuf>), 523 + Proc(Rc<Proc>), 524 + Const(Rc<Const>), 525 + Mem(Rc<Mem>), 526 + Var(Rc<Var>), 527 + Struct(Rc<ResolvedStruct>), 528 + Module(Rc<ResolvedFile>), 514 529 } 515 530 516 531 impl Debug for ResolvedItem { ··· 533 548 pub ast: FnvHashMap<SmolStr, Spanned<ResolvedItem>>, 534 549 } 535 550 536 - // impl ResolvedFile { 537 - // fn find(&self, path: &ItemPath) -> Option<&Spanned<ResolvedItem>> { 538 - // let mut segments = path.iter(); 539 - // let segment = segments.next(); 540 - // let item = segment.and_then(|s| self.ast.get(s)); 541 - // if let Some(path) = path.drop_first() { 542 - // match item { 543 - // Some(i) => match &**i { 544 - // ResolvedItem::Ref(_) => return None, 545 - // ResolvedItem::Proc(_) => return None, 546 - // ResolvedItem::Const(_) => return None, 547 - // ResolvedItem::Mem(_) => return None, 548 - // ResolvedItem::Var(_) => return None, 549 - // ResolvedItem::Struct(_) => return None, 550 - // ResolvedItem::Module(f) => return f.find(path), 551 - // }, 552 - // None => return None, 553 - // } 554 - // } 555 - // item 556 - // } 557 - // } 551 + impl ResolvedFile { 552 + pub fn find(&self, path: &ItemPath) -> Option<Spanned<ResolvedItem>> { 553 + let mut segments = path.iter(); 554 + let segment = segments.next(); 555 + let item = segment.and_then(|s| self.ast.get(s)); 556 + if let Some(path) = path.drop_first() { 557 + match item { 558 + Some(i) => match &**i { 559 + ResolvedItem::Ref(_) => return None, 560 + ResolvedItem::Proc(_) => return None, 561 + ResolvedItem::Const(_) => return None, 562 + ResolvedItem::Mem(_) => return None, 563 + ResolvedItem::Var(_) => return None, 564 + ResolvedItem::Struct(_) => return None, 565 + ResolvedItem::Module(f) => return f.find(path), 566 + }, 567 + None => return None, 568 + } 569 + } 570 + item.cloned() 571 + } 572 + } 558 573 559 574 #[derive(Debug, Clone)] 560 575 pub struct ResolvedStruct { ··· 579 594 } 580 595 }; 581 596 let resolved_item = match item.inner { 582 - TopLevel::Proc(p) => ResolvedItem::Proc(p), 583 - TopLevel::Const(c) => ResolvedItem::Const(c), 584 - TopLevel::Mem(m) => ResolvedItem::Mem(m), 585 - TopLevel::Var(v) => ResolvedItem::Var(v), 597 + TopLevel::Proc(p) => ResolvedItem::Proc(Rc::new(p)), 598 + TopLevel::Const(c) => ResolvedItem::Const(Rc::new(c)), 599 + TopLevel::Mem(m) => ResolvedItem::Mem(Rc::new(m)), 600 + TopLevel::Var(v) => ResolvedItem::Var(Rc::new(v)), 586 601 TopLevel::Struct(s) => match make_struct(s) { 587 - Ok(s) => ResolvedItem::Struct(s), 602 + Ok(s) => ResolvedItem::Struct(Rc::new(s)), 588 603 Err(mut es) => { 589 604 errors.append(&mut es); 590 605 continue; ··· 624 639 625 640 let module_ast = parse(tokens)?; 626 641 let resolved = resolve_includes_from(path.child(file_name), module_ast)?; 627 - for qualifier in qualifiers { 628 - let span = qualifier.span; 629 - let item = qualifier.map(|Word(w)| w).inner; 630 - let item_path = resolved.path.child(item.clone()); 631 - ast.insert( 632 - item, 633 - Spanned { 634 - span, 635 - inner: ResolvedItem::Ref(item_path), 636 - }, 637 - ); 642 + if let Some(Qualifiers { items, from: _ }) = qualifiers { 643 + for qualifier in items { 644 + let span = qualifier.span; 645 + let item = qualifier.inner; 646 + let item_path = resolved.path.join(&item); 647 + 648 + let i = resolved.find(&item); 649 + match i { 650 + Some(Spanned { span: _, inner: _ }) => { 651 + ast.insert( 652 + item.last().unwrap(), 653 + Spanned { 654 + span, 655 + inner: ResolvedItem::Ref(Rc::new(item_path)), 656 + }, 657 + ); 658 + } 659 + None => { 660 + todo!("Reject importing nonexistant items") 661 + } 662 + } 663 + } 638 664 } 639 - ResolvedItem::Module(box resolved) 665 + ResolvedItem::Module(Rc::new(resolved)) 640 666 } 641 667 }; 642 668
+14 -3
rotth-parser/src/ast/parsers.rs
··· 10 10 use super::{ 11 11 Bind, Cast, Cond, CondBranch, Const, ConstSignature, Else, Expr, FieldAccess, File, Generics, 12 12 If, Include, ItemPathBuf, Keyword, Literal, Mem, NameTypePair, Proc, ProcSignature, 13 - Punctuation, Struct, TopLevel, Var, While, Word, 13 + Punctuation, Qualifiers, Struct, TopLevel, Var, While, Word, 14 14 }; 15 15 16 16 pub(super) fn ty() -> impl Parser<Token, Spanned<Type>, Error = Simple<Token, Span>> + Clone { ··· 118 118 ) -> impl Parser<Token, Spanned<Keyword>, Error = Simple<Token, Span>> + Clone { 119 119 select! { 120 120 Token::KwInclude, span => Spanned { span, inner: Keyword::Include }, 121 + } 122 + } 123 + 124 + pub(super) fn kw_from() -> impl Parser<Token, Spanned<Keyword>, Error = Simple<Token, Span>> + Clone 125 + { 126 + select! { 127 + Token::KwFrom, span => Spanned { span, inner: Keyword::From }, 121 128 } 122 129 } 123 130 ··· 577 584 pub(super) fn include() -> impl Parser<Token, Spanned<TopLevel>, Error = Simple<Token, Span>> + Clone 578 585 { 579 586 kw_include() 580 - .then(word().repeated()) 587 + .then(path().repeated().then(kw_from()).or_not()) 581 588 .then(include_path()) 582 589 .map_with_span(|((include, qualifiers), path), span| Spanned { 583 590 span, 584 591 inner: TopLevel::Include(Include { 585 592 include, 586 - qualifiers, 593 + qualifiers: if let Some((items, from)) = qualifiers { 594 + Some(Qualifiers { items, from }) 595 + } else { 596 + None 597 + }, 587 598 path, 588 599 }), 589 600 })
+189 -138
rotth-parser/src/hir.rs
··· 1 + use std::rc::Rc; 2 + 1 3 use crate::{ 2 4 ast::Keyword, 3 5 ast::{ 4 - self, Cast, Expr, ItemPathBuf, Literal, ProcSignature, ResolvedFile, ResolvedItem, 5 - ResolvedStruct, Word, 6 + self, Cast, Expr, ItemPath, ItemPathBuf, Literal, ProcSignature, ResolvedFile, 7 + ResolvedItem, ResolvedStruct, Word, 6 8 }, 7 9 types::{StructIndex, Type}, 8 10 }; 9 11 use fnv::FnvHashMap; 10 12 use smol_str::SmolStr; 11 - use somok::{Either, PartitionThree, Somok, Ternary}; 13 + use somok::{Either, Somok}; 12 14 use spanner::{Span, Spanned}; 13 15 14 16 #[derive(Debug, Clone)] ··· 196 198 Ge, 197 199 } 198 200 199 - #[derive(Default)] 200 201 pub struct Walker { 201 202 proc_vars: FnvHashMap<ItemPathBuf, Var>, 202 203 current_path: ItemPathBuf, 204 + ast: Rc<ResolvedFile>, 203 205 items: FnvHashMap<ItemPathBuf, TopLevel>, 204 206 types: StructIndex, 205 207 } 206 208 207 209 impl Walker { 208 - pub fn new() -> Self { 210 + fn new(ast: Rc<ResolvedFile>) -> Self { 209 211 Self { 210 212 proc_vars: Default::default(), 211 213 current_path: Default::default(), 214 + ast, 212 215 items: Default::default(), 213 216 types: Default::default(), 214 217 } ··· 285 288 .some() 286 289 } 287 290 288 - pub fn walk_ast( 289 - mut self, 290 - ast: ResolvedFile, 291 - ) -> (FnvHashMap<ItemPathBuf, TopLevel>, StructIndex) { 292 - self.walk_module(ast); 293 - (self.items, self.types) 291 + pub fn walk_ast(ast: ResolvedFile) -> (FnvHashMap<ItemPathBuf, TopLevel>, StructIndex) { 292 + let ast = Rc::new(ast); 293 + let mut this = Self::new(ast.clone()); 294 + this.walk_module(ast); 295 + (this.items, this.types) 294 296 } 295 297 296 - fn walk_module(&mut self, module: ResolvedFile) { 297 - let (items, structs, modules) = module 298 - .ast 299 - .into_iter() 300 - .partition_three::<FnvHashMap<_, _>, _>(|(_, item)| match &**item { 301 - ResolvedItem::Ref(_) => Ternary::First, 302 - ResolvedItem::Proc(_) => Ternary::First, 303 - ResolvedItem::Const(_) => Ternary::First, 304 - ResolvedItem::Mem(_) => Ternary::First, 305 - ResolvedItem::Var(_) => Ternary::First, 306 - ResolvedItem::Struct(_) => Ternary::Second, 307 - ResolvedItem::Module(_) => Ternary::Third, 308 - }); 309 - let modules = modules 310 - .into_iter() 311 - .map(|(n, m)| { 312 - ( 313 - n, 314 - match m.inner { 315 - ResolvedItem::Module(box m) => m, 316 - _ => unreachable!(), 317 - }, 318 - ) 319 - }) 320 - .collect::<FnvHashMap<_, _>>(); 321 - let structs = structs 322 - .into_iter() 323 - .map(|(n, m)| { 324 - ( 325 - n, 326 - match m.inner { 327 - ResolvedItem::Struct(s) => s, 328 - _ => unreachable!(), 329 - }, 330 - ) 331 - }) 332 - .collect::<FnvHashMap<_, _>>(); 333 - for (_, module) in modules { 334 - self.walk_module(module); 335 - } 336 - self.current_path = module.path; 337 - for (_, struct_) in structs { 338 - self.walk_struct(struct_); 339 - } 340 - for (name, item) in items { 341 - let item = self.walk_toplevel(item.inner); 342 - let name = self.current_path.child(name); 343 - self.items.insert(name, item); 298 + fn walk_module(&mut self, module: Rc<ResolvedFile>) { 299 + let mp = self.current_path.clone(); 300 + self.current_path = module.path.clone(); 301 + for ( 302 + name, 303 + Spanned { 304 + span: _, 305 + inner: item, 306 + }, 307 + ) in &module.ast 308 + { 309 + self.walk_toplevel(name.clone(), item.clone()); 344 310 } 311 + self.current_path = mp; 345 312 } 346 313 347 - fn walk_struct(&mut self, struct_: ResolvedStruct) { 348 - let ResolvedStruct { name, fields } = struct_; 349 - let Word(name) = name.inner; 314 + fn walk_struct(&mut self, name: SmolStr) { 315 + let path = self.current_path.child(name); 316 + let struct_ = if let Some(Spanned { 317 + span: _, 318 + inner: ResolvedItem::Struct(s), 319 + }) = self.ast.find(&path) 320 + { 321 + s 322 + } else { 323 + unreachable!() 324 + }; 325 + let ResolvedStruct { name, fields } = &*struct_; 326 + let Word(name) = name.inner.clone(); 350 327 let name = self.current_path.child(name); 351 328 let mut builder = self.types.new_struct(name); 352 329 for (name, ty) in fields { 353 330 let span = ty.ty.span; 354 - let ty = ty.inner.ty.inner; 331 + let ty = ty.inner.ty.inner.clone(); 355 332 let ty = match ty { 356 333 ty @ Type::Primitive(_) | ty @ Type::Ptr(_) => ty, 357 334 Type::Custom(type_name) => { ··· 360 337 } 361 338 }; 362 339 let ty = Spanned { span, inner: ty }; 363 - builder.field(name, ty); 340 + builder.field(name.clone(), ty); 364 341 } 365 342 builder.finish(); 366 343 } 367 344 368 - fn walk_toplevel(&mut self, item: ResolvedItem) -> TopLevel { 345 + fn walk_ref(&mut self, name: SmolStr, referee: &ItemPath) { 346 + let path = self.current_path.child(name); 347 + match self.ast.find(referee) { 348 + Some(Spanned { 349 + span: _, 350 + inner: item, 351 + }) => match item { 352 + ResolvedItem::Ref(_) => todo!(), 353 + ResolvedItem::Module(m) => { 354 + for name in m.ast.keys() { 355 + let referee = referee.child(name.clone()); 356 + self.items 357 + .insert(path.child(name.clone()), TopLevel::Ref(referee)); 358 + } 359 + } 360 + _ => { 361 + self.items.insert(path, TopLevel::Ref(referee.to_owned())); 362 + } 363 + }, 364 + None => unreachable!(), 365 + } 366 + } 367 + 368 + fn walk_toplevel(&mut self, name: SmolStr, item: ResolvedItem) { 369 369 match item { 370 - ResolvedItem::Ref(p) => TopLevel::Ref(p), 371 - ResolvedItem::Proc(p) => TopLevel::Proc(self.walk_proc(p)), 372 - ResolvedItem::Const(c) => TopLevel::Const(self.walk_const(c)), 373 - ResolvedItem::Mem(m) => TopLevel::Mem(self.walk_mem(m)), 374 - ResolvedItem::Var(v) => TopLevel::Var(Var { 375 - ty: v.ty, 376 - span: v.name.span, 377 - }), 378 - ResolvedItem::Struct(_) => unreachable!(), 379 - ResolvedItem::Module(_) => unreachable!(), 370 + ResolvedItem::Ref(path) => self.walk_ref(name, &*path), 371 + ResolvedItem::Proc(_) => self.walk_proc(name), 372 + ResolvedItem::Const(_) => self.walk_const(name), 373 + ResolvedItem::Mem(_) => self.walk_mem(name), 374 + ResolvedItem::Var(v) => { 375 + self.items.insert( 376 + self.current_path.child(name), 377 + TopLevel::Var(Var { 378 + ty: v.ty.clone(), 379 + span: v.name.span, 380 + }), 381 + ); 382 + } 383 + ResolvedItem::Struct(_) => self.walk_struct(name), 384 + ResolvedItem::Module(module) => self.walk_module(module), 380 385 } 381 386 } 382 387 383 - fn walk_mem(&mut self, mem: ast::Mem) -> Mem { 388 + fn walk_mem(&mut self, name: SmolStr) { 389 + let path = self.current_path.child(name.clone()); 390 + let mem = if let Some(Spanned { 391 + span: _, 392 + inner: ResolvedItem::Mem(m), 393 + }) = self.ast.find(&path) 394 + { 395 + m 396 + } else { 397 + unreachable!() 398 + }; 384 399 let body = mem 385 400 .body 386 - .into_iter() 401 + .iter() 387 402 .map(|ast| self.walk_node(ast).unwrap()) 388 403 .collect::<Vec<_>>(); 389 - Mem { 390 - body, 391 - span: mem.mem.span.merge(mem.end.span), 392 - } 404 + self.items.insert( 405 + self.current_path.child(name), 406 + TopLevel::Mem(Mem { 407 + body, 408 + span: mem.mem.span.merge(mem.end.span), 409 + }), 410 + ); 393 411 } 394 412 395 - fn walk_const(&mut self, const_: ast::Const) -> Const { 396 - let outs = const_.signature.inner.tys; 413 + fn walk_const(&mut self, name: SmolStr) { 414 + let path = self.current_path.child(name.clone()); 415 + let const_ = if let Some(Spanned { 416 + span: _, 417 + inner: ResolvedItem::Const(c), 418 + }) = self.ast.find(&path) 419 + { 420 + c 421 + } else { 422 + unreachable!() 423 + }; 424 + let outs = const_.signature.inner.tys.clone(); 397 425 let body = const_ 398 426 .body 399 - .into_iter() 427 + .iter() 400 428 .map(|ast| self.walk_node(ast).unwrap()) 401 429 .collect::<Vec<_>>(); 402 - Const { 403 - outs, 404 - body, 405 - span: const_.const_.span.merge(const_.end.span), 406 - } 430 + self.items.insert( 431 + self.current_path.child(name), 432 + TopLevel::Const(Const { 433 + outs, 434 + body, 435 + span: const_.const_.span.merge(const_.end.span), 436 + }), 437 + ); 407 438 } 408 439 409 - fn walk_proc(&mut self, proc: ast::Proc) -> Proc { 440 + fn walk_proc(&mut self, name: SmolStr) { 441 + let path = self.current_path.child(name.clone()); 442 + let proc = if let Some(Spanned { 443 + span: _, 444 + inner: ResolvedItem::Proc(p), 445 + }) = self.ast.find(&path) 446 + { 447 + p 448 + } else { 449 + unreachable!() 450 + }; 451 + 410 452 let generics = proc 411 453 .generics 454 + .as_ref() 412 455 .map(|g| { 413 - g.inner.tys.into_iter().map(|ty| { 414 - let Word(ty) = ty.inner; 415 - ty 456 + g.inner.tys.iter().map(|ty| { 457 + let Word(ty) = &ty.inner; 458 + ty.clone() 416 459 }) 417 460 }) 418 461 .into_iter() 419 462 .flatten() 420 463 .collect::<Vec<_>>(); 421 464 422 - let ProcSignature { ins, sep: _, outs } = proc.signature.inner; 465 + let ProcSignature { ins, sep: _, outs } = proc.signature.inner.clone(); 423 466 let ins = ins.into_iter().collect(); 424 467 let outs = outs 425 468 .map(|i| i.into_iter().collect()) 426 469 .unwrap_or_else(Vec::new); 427 470 428 - let body = self.walk_body(proc.body); 471 + let body = self.walk_body(&proc.body); 429 472 let mut vars = Default::default(); 430 473 std::mem::swap(&mut vars, &mut self.proc_vars); 431 474 432 - Proc { 433 - ins, 434 - outs, 435 - generics, 436 - body, 437 - vars, 438 - span: proc.proc.span.merge(proc.end.span), 439 - } 475 + self.items.insert( 476 + self.current_path.child(name), 477 + TopLevel::Proc(Proc { 478 + ins, 479 + outs, 480 + generics, 481 + body, 482 + vars, 483 + span: proc.proc.span.merge(proc.end.span), 484 + }), 485 + ); 440 486 } 441 487 442 - fn walk_body(&mut self, body: Vec<Spanned<Expr>>) -> Vec<Spanned<Hir>> { 443 - body.into_iter() 488 + fn walk_body(&mut self, body: &[Spanned<Expr>]) -> Vec<Spanned<Hir>> { 489 + body.iter() 444 490 .filter_map(|ast| self.walk_node(ast)) 445 491 .collect::<Vec<_>>() 446 492 } 447 493 448 - fn walk_node(&mut self, node: Spanned<Expr>) -> Option<Spanned<Hir>> { 449 - if let Some(node) = self.intrinsic(&node) { 494 + fn walk_node(&mut self, node: &Spanned<Expr>) -> Option<Spanned<Hir>> { 495 + if let Some(node) = self.intrinsic(node) { 450 496 return node.some(); 451 497 } 452 - let hir = match node.inner { 498 + let hir = match &node.inner { 453 499 Expr::Bind(bind) => Hir::Bind(self.walk_bind(bind)), 454 500 Expr::While(while_) => Hir::While(self.walk_while(while_)), 455 501 Expr::If(if_) => Hir::If(self.walk_if(if_)), 456 502 Expr::Cond(box cond) => Hir::Cond(self.walk_cond(cond)), 457 503 Expr::Cast(_) => unreachable!(), 458 - Expr::Word(Word(w)) => Hir::Path(self.current_path.child(w)), 459 - Expr::Literal(l) => Hir::Literal(l), 504 + Expr::Word(Word(w)) => Hir::Path(self.current_path.child(w.clone())), 505 + Expr::Literal(l) => Hir::Literal(l.clone()), 460 506 Expr::Keyword(Keyword::Return) => Hir::Return, 461 507 Expr::Var(var) => { 462 508 self.walk_var(var); 463 509 return None; 464 510 } 465 511 Expr::FieldAccess(box access) => { 466 - let Word(field) = access.field.inner; 512 + let Word(field) = access.field.inner.clone(); 467 513 let access = FieldAccess { field }; 468 514 Hir::FieldAccess(access) 469 515 } 470 - Expr::Path(p) => Hir::Path(self.current_path.join(&p)), 516 + Expr::Path(p) => Hir::Path(self.current_path.join(p)), 471 517 expr => unreachable!("{:?}", expr), 472 518 }; 473 519 Spanned { ··· 477 523 .some() 478 524 } 479 525 480 - fn walk_var(&mut self, var: ast::Var) { 481 - let name = var.name.map(|Word(w)| self.current_path.child(w)); 482 - let ty = var.ty; 526 + fn walk_var(&mut self, var: &ast::Var) { 527 + let name = var 528 + .name 529 + .map_ref(|Word(w)| self.current_path.child(w.clone())); 530 + let ty = var.ty.clone(); 483 531 let var = Var { 484 532 ty, 485 533 span: name.span, ··· 487 535 self.proc_vars.insert(name.inner, var); 488 536 } 489 537 490 - fn walk_bind(&mut self, bind: ast::Bind) -> Bind { 538 + fn walk_bind(&mut self, bind: &ast::Bind) -> Bind { 491 539 let bindings = bind 492 540 .bindings 493 - .into_iter() 541 + .iter() 494 542 .map(|b| { 495 - b.map(|b| match b { 543 + b.map_ref(|b| match b { 496 544 Either::Left(Word(w)) if w == "_" => Binding::Ignore, 497 545 Either::Left(Word(w)) => Binding::Bind { 498 - name: self.current_path.child(w), 546 + name: self.current_path.child(w.clone()), 499 547 ty: None, 500 548 }, 501 549 Either::Right(r) => Binding::Bind { 502 - name: r.name.map(|Word(w)| self.current_path.child(w)).inner, 503 - ty: Some(r.ty.inner), 550 + name: r 551 + .name 552 + .map_ref(|Word(w)| self.current_path.child(w.clone())) 553 + .inner, 554 + ty: Some(r.ty.inner.clone()), 504 555 }, 505 556 }) 506 557 }) 507 558 .collect(); 508 559 let body = bind 509 560 .body 510 - .into_iter() 561 + .iter() 511 562 .filter_map(|node| self.walk_node(node)) 512 563 .collect(); 513 564 Bind { bindings, body } 514 565 } 515 566 516 - fn walk_cond(&mut self, cond: ast::Cond) -> Cond { 567 + fn walk_cond(&mut self, cond: &ast::Cond) -> Cond { 517 568 let branches = cond 518 569 .branches 519 - .into_iter() 520 - .map(|b| b.map(|b| self.walk_cond_branch(b)).inner) 570 + .iter() 571 + .map(|b| b.map_ref(|b| self.walk_cond_branch(b)).inner) 521 572 .collect(); 522 573 Cond { branches } 523 574 } 524 575 525 - fn walk_cond_branch(&mut self, branch: ast::CondBranch) -> CondBranch { 526 - let pattern = match branch.pat.inner { 576 + fn walk_cond_branch(&mut self, branch: &ast::CondBranch) -> CondBranch { 577 + let pattern = match &branch.pat.inner { 527 578 Expr::Word(Word(w)) if w == "_" => Spanned { 528 579 span: branch.pat.span, 529 580 inner: Hir::IgnorePattern, 530 581 }, 531 582 Expr::Path(p) => { 532 - let path = self.current_path.join(&p); 583 + let path = self.current_path.join(p); 533 584 Spanned { 534 585 span: branch.pat.span, 535 586 inner: Hir::Path(path), 536 587 } 537 588 } 538 589 Expr::Word(Word(w)) => { 539 - let path = self.current_path.child(w); 590 + let path = self.current_path.child(w.clone()); 540 591 Spanned { 541 592 span: branch.pat.span, 542 593 inner: Hir::Path(path), ··· 544 595 } 545 596 Expr::Literal(l) => Spanned { 546 597 span: branch.pat.span, 547 - inner: Hir::Literal(l), 598 + inner: Hir::Literal(l.clone()), 548 599 }, 549 600 e => unreachable!("{:?}", e), 550 601 }; 551 602 let body = branch 552 603 .body 553 - .into_iter() 604 + .iter() 554 605 .filter_map(|node| self.walk_node(node)) 555 606 .collect(); 556 607 CondBranch { pattern, body } 557 608 } 558 609 559 - fn walk_while(&mut self, while_: ast::While) -> While { 610 + fn walk_while(&mut self, while_: &ast::While) -> While { 560 611 let cond = while_ 561 612 .cond 562 - .into_iter() 613 + .iter() 563 614 .filter_map(|node| self.walk_node(node)) 564 615 .collect(); 565 616 let body = while_ 566 617 .body 567 - .into_iter() 618 + .iter() 568 619 .filter_map(|node| self.walk_node(node)) 569 620 .collect(); 570 621 While { cond, body } 571 622 } 572 623 573 - fn walk_if(&mut self, if_: ast::If) -> If { 624 + fn walk_if(&mut self, if_: &ast::If) -> If { 574 625 let truth = if_ 575 626 .truth 576 - .into_iter() 627 + .iter() 577 628 .filter_map(|node| self.walk_node(node)) 578 629 .collect(); 579 - let lie = if_.lie.map(|lie| { 630 + let lie = if_.lie.as_ref().map(|lie| { 580 631 lie.body 581 - .into_iter() 632 + .iter() 582 633 .filter_map(|node| self.walk_node(node)) 583 634 .collect() 584 635 });
+2 -2
rotth-parser/src/types.rs
··· 32 32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 33 33 match self { 34 34 Type::Ptr(box ty) => { 35 - let inner = ty.fmt(f)?; 36 - write!(f, "&>{:?}", inner) 35 + write!(f, "&>")?; 36 + ty.fmt(f) 37 37 } 38 38 Type::Primitive(p) => p.fmt(f), 39 39 Type::Custom(s) => s.fmt(f),
+1 -1
rotth-src/examples/args.rh
··· 1 - include cstrlen puts "../std.rh" 1 + include cstrlen puts from "../std.rh" 2 2 proc main: u64 do 3 3 argv cast &>u64 4 4 @u64 cast &>char
+1 -1
rotth-src/examples/bind.rh
··· 1 - include puts "../std.rh" 1 + include puts from "../std.rh" 2 2 3 3 proc main: u64 do 4 4 "hello"
+2 -2
rotth-src/examples/bind_nested.rh
··· 3 3 bind a b c do 4 4 b b 5 5 bind d e do 6 - d print 6 + a drop 7 7 end 8 8 c 9 - end 9 + end drop 0 10 10 end
+1 -1
rotth-src/examples/cond.rh
··· 1 - include getch "../std.rh" 1 + include getch puts from "../std.rh" 2 2 3 3 const QUIT: char do 'q' end 4 4
+3 -3
rotth-src/examples/echo.rh
··· 1 - include exit cstrlen puts "../std.rh" 1 + include exit cstrlen puts core::ptr+ from "../std.rh" 2 2 proc main: u64 do 3 3 argc 2 < if 1 exit 4 4 else 5 - argv 8 std::core::ptr+ 5 + argv 8 ptr+ 6 6 argc 1 - while dup 0 > do 7 7 over cast &>u64 @u64 cast &>char 8 8 dup cstrlen swap puts " " puts 9 - 1 - swap 8 std::core::ptr+ swap 9 + 1 - swap 8 ptr+ swap 10 10 end drop drop 11 11 "\n" puts 12 12 end
+1 -1
rotth-src/examples/foobar.rh
··· 1 - include mod puts putu or not "../std.rh" 1 + include mod puts putu or not from "../std.rh" 2 2 3 3 proc main: u64 do 4 4 0 while dup 15 <= do
+1 -1
rotth-src/examples/print_string.rh
··· 1 - include puts "../std.rh" 1 + include puts from "../std.rh" 2 2 3 3 proc main: u64 do 4 4 "Hello, World!\n" puts
+5 -4
rotth-src/examples/recurse.rh
··· 1 - proc foo do 2 - foo 1 + proc foo u64 do 2 + dup 10 = if drop return end 3 + dup print 1 + foo 3 4 end 4 5 5 6 proc main: u64 do 6 - ; foo 7 - 1 7 + 0 foo 8 + 0 8 9 end
+1 -1
rotth-src/examples/redefinition.rh
··· 1 - include puts "../std.rh" 1 + include puts from "../std.rh" 2 2 3 3 proc main: u64 do 4 4 end
+6 -1
rotth-src/examples/simplegeneric.rh
··· 1 + include puts putc putu from "../std.rh" 2 + 1 3 proc [T] inc T : T do 4 + cast u64 1 + cast T 2 5 end 3 6 4 7 proc main: u64 do 5 - 1 inc print 8 + 1 inc putu 9 + "\n" puts 10 + 'a' inc putc 6 11 0 7 12 end
+2 -2
rotth-src/examples/struct.rh
··· 1 - include puts "../std.rh" 1 + include puts putu from "../std.rh" 2 2 3 3 struct String do 4 4 len: u64 ··· 8 8 proc main: u64 do 9 9 returns-string 10 10 bind str: &>String do 11 - str -> len @u64 11 + str -> len @u64 dup putu "\n" puts 12 12 str -> buf cast &>u64 @u64 cast &>char 13 13 puts 14 14 end
+1 -1
rotth-src/examples/utoa.rh
··· 1 - include putu puts "../std.rh" 1 + include putu puts from "../std.rh" 2 2 3 3 proc main: u64 do 4 4 69 putu "\n" puts
+1 -1
rotth-src/examples/write_u8.rh
··· 1 - include puts "../std.rh" 1 + include puts from "../std.rh" 2 2 3 3 proc main: u64 do 4 4 "hello\n"
+7 -1
rotth-src/std.rh
··· 1 - include SYS_write SYS_read SYS_exit "./syscalls.rh" 1 + include SYS_write SYS_read SYS_exit from "./syscalls.rh" 2 2 include "./core.rh" 3 3 4 4 const STDIN: u64 do 0 end ··· 57 57 58 58 proc putb bool do 59 59 if "true" else "false" end puts 60 + end 61 + 62 + proc putc char do 63 + cast u8 PUTU_BUF !u8 64 + 1 PUTU_BUF cast &>char puts 65 + ZERO_PUTU_BUF 60 66 end 61 67 62 68 proc putu u64 do
+153 -23
rotth/src/ctir.rs
··· 1 1 use fnv::FnvHashMap; 2 - use rotth_parser::path; 2 + use rotth_parser::{path, types::Primitive}; 3 + use smol_str::SmolStr; 3 4 use somok::Somok; 4 5 use std::fmt::Write; 5 6 6 7 use crate::{ 7 8 inference::TermId, 8 9 tir::{ 9 - Bind, Cond, CondBranch, FieldAccess, GenId, If, KConst, KMem, KProc, Type, 10 - TypecheckedProgram, TypedIr, TypedNode, While, 10 + Bind, ConcreteType, Cond, CondBranch, FieldAccess, GenId, If, KConst, KMem, KProc, Type, 11 + TypeId, TypecheckedProgram, TypedIr, TypedNode, Var, While, 11 12 }, 12 13 typecheck, Error, 13 14 }; ··· 27 28 pub procs: FnvHashMap<ItemPathBuf, KProc<TypedNode<Type>>>, 28 29 pub consts: FnvHashMap<ItemPathBuf, KConst<Type>>, 29 30 pub mems: FnvHashMap<ItemPathBuf, KMem<Type>>, 31 + pub vars: FnvHashMap<ItemPathBuf, Var<Type>>, 32 + pub structs: FnvHashMap<TypeId, CStruct>, 30 33 } 31 34 32 35 fn substitutions(subs: &mut FnvHashMap<GenId, Type>, g: &Type, c: &Type) { ··· 35 38 subs.insert(*g, c.clone()); 36 39 } 37 40 (Type::Concrete(g), Type::Concrete(c)) => { 38 - if let (crate::tir::ConcreteType::Ptr(box g), crate::tir::ConcreteType::Ptr(box c)) = 39 - (g, c) 40 - { 41 + if let (ConcreteType::Ptr(box g), ConcreteType::Ptr(box c)) = (g, c) { 41 42 substitutions(subs, g, c) 42 43 } 43 44 } ··· 45 46 } 46 47 } 47 48 49 + #[derive(Debug)] 50 + pub struct CStruct { 51 + pub fields: FnvHashMap<SmolStr, Field>, 52 + } 53 + 54 + #[derive(Debug)] 55 + pub struct Field { 56 + pub size: usize, 57 + pub offset: usize, 58 + } 59 + 48 60 #[derive(Default)] 49 61 pub struct Walker { 50 62 procs: FnvHashMap<ItemPathBuf, Option<KProc<TypedNode<Type>>>>, 51 63 consts: FnvHashMap<ItemPathBuf, Option<KConst<Type>>>, 52 64 mems: FnvHashMap<ItemPathBuf, Option<KMem<Type>>>, 65 + vars: FnvHashMap<ItemPathBuf, Option<Var<Type>>>, 53 66 } 54 67 55 68 impl Walker { ··· 63 76 } 64 77 let mut this = Self::default(); 65 78 66 - let body = this.walk_body(&program, &main.body, &Default::default())?; 79 + let body = this.walk_body(&program, &main.body, &main.vars, &Default::default())?; 67 80 let main = KProc { 68 81 generics: Default::default(), 69 82 vars: main.vars.clone(), ··· 106 119 } 107 120 }) 108 121 .collect::<Result<_, _>>()?; 122 + 123 + let vars = this 124 + .vars 125 + .into_iter() 126 + .map(|(p, i)| { 127 + if let Some(i) = i { 128 + Ok((p, i)) 129 + } else { 130 + Err(ConcreteError::IncompleteConst(p)) 131 + } 132 + }) 133 + .collect::<Result<_, _>>()?; 134 + 135 + let structs = program 136 + .structs 137 + .into_iter() 138 + .map(|(_, i)| { 139 + (i.id, { 140 + let mut offset = 0; 141 + let mut fields = i 142 + .fields 143 + .into_iter() 144 + .map(|(n, t)| { 145 + let f = match t { 146 + Type::Generic(_) => todo!(), 147 + Type::Concrete(c) => match c { 148 + ConcreteType::Ptr(_) => 8, 149 + ConcreteType::Primitive(p) => match p { 150 + Primitive::Void => 0, 151 + Primitive::Bool => 1, 152 + Primitive::Char => 1, 153 + Primitive::U64 => 8, 154 + Primitive::U32 => 4, 155 + Primitive::U16 => 2, 156 + Primitive::U8 => 1, 157 + Primitive::I64 => 8, 158 + Primitive::I32 => 4, 159 + Primitive::I16 => 2, 160 + Primitive::I8 => 1, 161 + }, 162 + ConcreteType::Custom(_) => todo!(), 163 + }, 164 + }; 165 + (n, f) 166 + }) 167 + .collect::<Vec<_>>(); 168 + fields.sort_by_key(|(_, s)| *s); 169 + let fields = fields 170 + .into_iter() 171 + .map(|(n, s)| { 172 + let f = Field { size: s, offset }; 173 + offset += s; 174 + 175 + (n, f) 176 + }) 177 + .collect(); 178 + 179 + CStruct { fields } 180 + }) 181 + }) 182 + .collect(); 109 183 110 184 Ok(ConcreteProgram { 111 185 procs, 112 186 consts, 113 187 mems, 188 + vars, 189 + structs, 114 190 }) 115 191 } else { 116 192 Error::from(ConcreteError::NoEntry).error() ··· 121 197 &mut self, 122 198 program: &TypecheckedProgram, 123 199 body: &[TypedNode<TermId>], 200 + local_vars: &FnvHashMap<ItemPathBuf, Var<Type>>, 124 201 gensubs: &FnvHashMap<GenId, Type>, 125 202 ) -> Result<Vec<TypedNode<Type>>, Error> { 126 203 let mut concrete_body = Vec::new(); 127 204 for node in body { 128 - let node = self.walk_node(program, node, gensubs)?; 205 + let node = self.walk_node(program, node, local_vars, gensubs)?; 129 206 concrete_body.push(node) 130 207 } 131 208 Ok(concrete_body) ··· 135 212 &mut self, 136 213 program: &TypecheckedProgram, 137 214 node: &TypedNode<TermId>, 215 + local_vars: &FnvHashMap<ItemPathBuf, Var<Type>>, 138 216 gensubs: &FnvHashMap<GenId, Type>, 139 217 ) -> Result<TypedNode<Type>, Error> { 140 218 match &node.node { 141 - TypedIr::VarUse(_) => { 142 - todo!() 219 + TypedIr::GVarUse(var_name) => { 220 + if let Some(_var) = program.vars.get(var_name) { 221 + let ins = node 222 + .ins 223 + .iter() 224 + .map(|t| program.engine.reconstruct_substituting(gensubs, *t)) 225 + .collect::<Result<Vec<_>, _>>() 226 + .unwrap(); 227 + let outs = node 228 + .outs 229 + .iter() 230 + .map(|t| program.engine.reconstruct_substituting(gensubs, *t)) 231 + .collect::<Result<Vec<_>, _>>() 232 + .unwrap(); 233 + 234 + Ok(TypedNode { 235 + span: node.span, 236 + node: TypedIr::GVarUse(var_name.clone()), 237 + ins, 238 + outs, 239 + }) 240 + } else { 241 + unreachable!("") 242 + } 243 + } 244 + TypedIr::LVarUse(var_name) => { 245 + if let Some(_var) = local_vars.get(var_name) { 246 + let ins = node 247 + .ins 248 + .iter() 249 + .map(|t| program.engine.reconstruct_substituting(gensubs, *t)) 250 + .collect::<Result<Vec<_>, _>>() 251 + .unwrap(); 252 + let outs = node 253 + .outs 254 + .iter() 255 + .map(|t| program.engine.reconstruct_substituting(gensubs, *t)) 256 + .collect::<Result<Vec<_>, _>>() 257 + .unwrap(); 258 + 259 + Ok(TypedNode { 260 + span: node.span, 261 + node: TypedIr::LVarUse(var_name.clone()), 262 + ins, 263 + outs, 264 + }) 265 + } else { 266 + unreachable!("{:?}", var_name) 267 + } 143 268 } 144 269 TypedIr::MemUse(mem_name) => { 145 - let mem = program.mems.get(dbg! {mem_name}).unwrap(); 270 + let mem = program.mems.get(mem_name).unwrap(); 146 271 let ins = node 147 272 .ins 148 273 .iter() ··· 159 284 if !self.mems.contains_key(mem_name) { 160 285 self.mems.insert(mem_name.clone(), None); 161 286 let body: Vec<TypedNode<Type>> = 162 - self.walk_body(program, &mem.body, &Default::default())?; 287 + self.walk_body(program, &mem.body, local_vars, &Default::default())?; 163 288 let mem = KMem { 164 289 span: mem.span, 165 290 body, ··· 214 339 if !self.consts.contains_key(const_name) { 215 340 self.consts.insert(const_name.clone(), None); 216 341 let body: Vec<TypedNode<Type>> = 217 - self.walk_body(program, &const_.body, &Default::default())?; 342 + self.walk_body(program, &const_.body, local_vars, &Default::default())?; 218 343 let const_ = KConst { 219 - outs: outs.clone(), 344 + outs: const_.outs.clone(), 220 345 span: const_.span, 221 346 body, 222 347 }; ··· 284 409 if !self.procs.contains_key(&callee_name) { 285 410 self.procs.insert(callee_name.clone(), None); 286 411 let body: Vec<TypedNode<Type>> = 287 - self.walk_body(program, &callee.body, &gensubs)?; 412 + self.walk_body(program, &callee.body, &callee.vars, &gensubs)?; 288 413 let callee = KProc { 289 414 generics: Default::default(), 290 415 vars: callee.vars.clone(), ··· 337 462 .map(|t| program.engine.reconstruct_substituting(gensubs, *t)) 338 463 .collect::<Result<Vec<_>, _>>() 339 464 .unwrap(); 340 - let body = self.walk_body(program, body, gensubs)?; 465 + let body = self.walk_body(program, body, local_vars, gensubs)?; 341 466 342 467 Ok(TypedNode { 343 468 span: node.span, ··· 362 487 .map(|t| program.engine.reconstruct_substituting(gensubs, *t)) 363 488 .collect::<Result<Vec<_>, _>>() 364 489 .unwrap(); 365 - let cond = self.walk_body(program, cond, gensubs)?; 366 - let body = self.walk_body(program, body, gensubs)?; 490 + let cond = self.walk_body(program, cond, local_vars, gensubs)?; 491 + let body = self.walk_body(program, body, local_vars, gensubs)?; 367 492 368 493 Ok(TypedNode { 369 494 span: node.span, ··· 385 510 .map(|t| program.engine.reconstruct_substituting(gensubs, *t)) 386 511 .collect::<Result<Vec<_>, _>>() 387 512 .unwrap(); 388 - let truth = self.walk_body(program, truth, gensubs)?; 513 + let truth = self.walk_body(program, truth, local_vars, gensubs)?; 389 514 let lie = if let Some(lie) = lie { 390 - Some(self.walk_body(program, lie, gensubs)?) 515 + Some(self.walk_body(program, lie, local_vars, gensubs)?) 391 516 } else { 392 517 None 393 518 }; ··· 414 539 .unwrap(); 415 540 let mut concrete_branches = Vec::new(); 416 541 for CondBranch { pattern, body } in branches { 417 - let pattern = self.walk_node(program, pattern, gensubs)?; 418 - let body = self.walk_body(program, body, gensubs)?; 542 + let pattern = self.walk_node(program, pattern, local_vars, gensubs)?; 543 + let body = self.walk_body(program, body, local_vars, gensubs)?; 419 544 concrete_branches.push(CondBranch { pattern, body }) 420 545 } 421 546 Ok(TypedNode { ··· 500 625 .map(|t| program.engine.reconstruct_substituting(gensubs, *t)) 501 626 .collect::<Result<Vec<_>, _>>() 502 627 .unwrap(); 628 + 629 + let ty = match &ins[0] { 630 + Type::Concrete(ConcreteType::Ptr(box t)) => t.clone(), 631 + ty => todo!("{ty:?}"), 632 + }; 503 633 Ok(TypedNode { 504 634 span: node.span, 505 635 node: TypedIr::FieldAccess(FieldAccess { 506 - ty: ins[0].clone(), 636 + ty, 507 637 field: f.field.clone(), 508 638 }), 509 639 ins,
+1 -1
rotth/src/eval.rs
··· 33 33 todo!("Support memories in eval") 34 34 } 35 35 Op::PushStr(_i) => { 36 - todo!(); 36 + todo!("Support strings in eval"); 37 37 // let len = strings[*i].len() as u64; 38 38 // stack.push(len); 39 39 // stack.push(strings[*i].as_ptr() as u64);
-3
rotth/src/inference.rs
··· 208 208 /// there is a conflict between them) 209 209 pub fn unify(&mut self, a: TermId, b: TermId) -> Result<(), String> { 210 210 use TypeInfo::*; 211 - // dbg! {(a,b)}; 212 - // dbg! {&self.vars}; 213 211 if a == b { 214 212 return Ok(()); 215 213 } 216 - // match dbg! {(self.vars[&a], self.vars[&b])} { 217 214 match (self.vars[a.0], self.vars[b.0]) { 218 215 // Follow any references 219 216 (Ref(a), Ref(b)) if a == b => Ok(()),
+60 -19
rotth/src/lir.rs
··· 2 2 use rotth_parser::{ 3 3 ast::{ItemPath, ItemPathBuf, Literal}, 4 4 hir::{Binding, Intrinsic}, 5 - types::{Primitive, StructIndex}, 5 + types::Primitive, 6 6 }; 7 7 use somok::{Either, Somok}; 8 8 use Op::*; 9 9 10 10 use crate::{ 11 - ctir::ConcreteProgram, 11 + ctir::{CStruct, ConcreteProgram}, 12 12 eval::eval, 13 - tir::{self, Cond, CondBranch, If, KConst, KMem, KProc, Type, TypedIr, TypedNode, Var, While}, 13 + tir::{ 14 + self, Cond, CondBranch, FieldAccess, If, KConst, KMem, KProc, Type, TypeId, TypedIr, 15 + TypedNode, Var, While, 16 + }, 14 17 }; 15 18 16 19 #[derive(Default, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] ··· 96 99 NotCompiled(KMem<Type>), 97 100 } 98 101 99 - #[derive(Default)] 102 + #[derive(Clone)] 103 + pub enum ComVar { 104 + Compiled(usize), 105 + NotCompiled(Var<Type>), 106 + } 107 + 100 108 pub struct Compiler { 101 109 label: usize, 102 110 mangle_table: FnvHashMap<ItemPathBuf, Mangled>, ··· 108 116 strings: Vec<String>, 109 117 bindings: Vec<Vec<ItemPathBuf>>, 110 118 mems: FnvHashMap<ItemPathBuf, ComMem>, 111 - _vars: FnvHashMap<ItemPathBuf, Type>, 112 - local_vars: FnvHashMap<ItemPathBuf, (usize, Var)>, 119 + vars: FnvHashMap<ItemPathBuf, ComVar>, 120 + local_vars: FnvHashMap<ItemPathBuf, (usize, Var<Type>)>, 113 121 local_vars_size: usize, 114 122 _escaping_size: usize, 115 - _structs: StructIndex, 123 + structs: FnvHashMap<TypeId, CStruct>, 116 124 } 117 125 118 126 impl Compiler { 119 127 pub fn compile(program: ConcreteProgram) -> (Vec<Op>, Vec<String>, FnvHashMap<Mangled, usize>) { 120 - let mut this = Self::default(); 128 + let mut this = Self::new(program.structs); 121 129 122 130 this.emit(Call(Mangled("main".into()))); 123 131 this.emit(Exit); ··· 134 142 this.mangle_table.insert(name.clone(), mangled.clone()); 135 143 this.unmangle_table.insert(mangled.clone(), name.clone()); 136 144 this.mems.insert(name, ComMem::NotCompiled(mem)); 145 + } 146 + 147 + for (name, var) in program.vars { 148 + let mangled = this.mangle(&name); 149 + this.mangle_table.insert(name.clone(), mangled.clone()); 150 + this.unmangle_table.insert(mangled.clone(), name.clone()); 151 + this.vars.insert(name, ComVar::NotCompiled(var)); 137 152 } 138 153 139 154 let procs = program ··· 333 348 let mangled = self.mangle_table.get(&w).unwrap().clone(); 334 349 self.emit(PushMem(mangled)) 335 350 } 336 - TypedIr::VarUse(_w) => { 337 - todo!(); 338 - // let mangled = self.mangle_table.get(&_w).unwrap().clone(); 339 - // self.emit(PushMem(mangled)) 351 + TypedIr::GVarUse(var_name) => { 352 + let mangled = self.mangle_table.get(&var_name).unwrap().clone(); 353 + self.emit(PushMem(mangled)) 354 + } 355 + TypedIr::LVarUse(var_name) => { 356 + let lvar = self.local_vars.get(&var_name).unwrap().0; 357 + self.emit(Op::PushLvar(lvar)) 340 358 } 341 359 TypedIr::BindingUse(w) => { 342 360 let offset = self ··· 402 420 TypedIr::While(while_) => self.compile_while(while_), 403 421 TypedIr::Bind(bind) => self.compile_bind(bind), 404 422 TypedIr::IgnorePattern => unreachable!(), // this is a noop 405 - TypedIr::FieldAccess(_f) => { 406 - // let struct_ = &self.structs; 407 - // let offset = struct_.fields[&f.field].offset; 408 - let offset = 0; 423 + TypedIr::FieldAccess(FieldAccess { ty, field }) => { 424 + let ty = if let Type::Concrete(tir::ConcreteType::Custom(ty)) = ty { 425 + &self.structs[&ty] 426 + } else { 427 + todo!("{ty:?}") 428 + }; 429 + let offset = ty.fields[&field].offset; 409 430 self.emit(Push(Literal::Num(offset as _))); 410 431 self.emit(Add); 411 432 } ··· 527 548 strings, 528 549 bindings: Default::default(), 529 550 mems: Default::default(), 530 - _vars: Default::default(), 551 + vars: Default::default(), 531 552 local_vars: Default::default(), 532 553 local_vars_size: Default::default(), 533 554 _escaping_size: Default::default(), 534 - _structs: Default::default(), 555 + structs: Default::default(), 556 + } 557 + } 558 + 559 + fn new(structs: FnvHashMap<TypeId, CStruct>) -> Self { 560 + Self { 561 + label: 0, 562 + mangle_table: Default::default(), 563 + unmangle_table: Default::default(), 564 + proc_id: 0, 565 + current_name: Default::default(), 566 + result: Default::default(), 567 + consts: Default::default(), 568 + strings: Default::default(), 569 + bindings: Default::default(), 570 + mems: Default::default(), 571 + vars: Default::default(), 572 + local_vars: Default::default(), 573 + local_vars_size: Default::default(), 574 + _escaping_size: Default::default(), 575 + structs, 535 576 } 536 577 } 537 578 ··· 540 581 let name = name 541 582 .iter() 542 583 .intersperse(&joiner) 543 - .map(|s| s.replace(|c| r"-+{}[]&^%/\".contains(c), &format!("{}", self.proc_id))) 584 + .map(|s| s.replace(|c: char| !c.is_alphanumeric(), &format!("{}", self.proc_id))) 544 585 .collect::<String>(); 545 586 Mangled(name) 546 587 }
+8 -9
rotth/src/main.rs
··· 2 2 use chumsky::error::SimpleReason; 3 3 use clap::Parser; 4 4 use rotth::{ctir, emit, eval::eval, lir, tir, typecheck, Error}; 5 - use rotth_parser::hir::Walker; 5 + use rotth_parser::hir; 6 6 use somok::Somok; 7 7 use std::{fs::OpenOptions, io::BufWriter, path::PathBuf, time::Instant}; 8 8 ··· 14 14 dump_ast: bool, 15 15 #[clap(short = 'i', long)] 16 16 dump_hir: bool, 17 - #[clap(short = 'c', long)] 17 + #[clap(short = 'r', long)] 18 18 dump_tir: bool, 19 + #[clap(short = 'c', long)] 20 + dump_ctir: bool, 19 21 #[clap(short = 'l', long)] 20 22 dump_lir: bool, 21 23 #[clap(short = 't', long)] ··· 209 211 println!("{ast:#?}"); 210 212 } 211 213 212 - // let struct_index = rotth::types::define_structs(structs); 213 - 214 - let walker = Walker::new(); 215 - let (hir, structs) = walker.walk_ast(ast); 214 + let (hir, structs) = hir::Walker::walk_ast(ast); 216 215 217 216 let lowered = Instant::now(); 218 217 if args.time { ··· 238 237 239 238 let ctir = ctir::Walker::walk(tir)?; 240 239 241 - let instantiated = Instant::now(); 240 + let concretized = Instant::now(); 242 241 if args.time { 243 - println!("Concretized in:\t{:?}", instantiated - typechecked) 242 + println!("Concretized in:\t{:?}", concretized - typechecked) 244 243 } 245 244 246 - if args.dump_tir { 245 + if args.dump_ctir { 247 246 println!("CTIR:"); 248 247 println!("{ctir:#?}"); 249 248 }
+46 -12
rotth/src/tir.rs
··· 96 96 #[derive(Clone)] 97 97 pub enum TypedIr<T> { 98 98 MemUse(ItemPathBuf), 99 - VarUse(ItemPathBuf), 99 + GVarUse(ItemPathBuf), 100 + LVarUse(ItemPathBuf), 100 101 BindingUse(ItemPathBuf), 101 102 ConstUse(ItemPathBuf), 102 103 Call(ItemPathBuf), ··· 114 115 impl<T: std::fmt::Debug> std::fmt::Debug for TypedIr<T> { 115 116 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 116 117 match self { 117 - Self::VarUse(arg0) => f.debug_tuple("VarUse").field(arg0).finish(), 118 + Self::GVarUse(arg0) => f.debug_tuple("GVarUse").field(arg0).finish(), 119 + Self::LVarUse(arg0) => f.debug_tuple("LVarUse").field(arg0).finish(), 118 120 Self::MemUse(arg0) => f.debug_tuple("MemUse").field(arg0).finish(), 119 121 Self::BindingUse(arg0) => f.debug_tuple("BindingUse").field(arg0).finish(), 120 122 Self::ConstUse(arg0) => f.debug_tuple("ConstUse").field(arg0).finish(), ··· 196 198 #[derive(Debug, Clone)] 197 199 pub struct KProc<T> { 198 200 pub generics: FnvHashMap<SmolStr, GenId>, 199 - pub vars: FnvHashMap<ItemPathBuf, Var>, 201 + pub vars: FnvHashMap<ItemPathBuf, Var<Type>>, 200 202 pub span: Span, 201 203 pub ins: Vec<Type>, 202 204 pub outs: Vec<Type>, ··· 215 217 } 216 218 #[derive(Debug, Clone)] 217 219 218 - pub struct Var { 219 - pub ty: Type, 220 + pub struct Var<T> { 221 + pub ty: T, 220 222 } 221 223 222 224 #[derive(Debug)] ··· 237 239 #[derive(Debug)] 238 240 pub struct Walker { 239 241 known_procs: FnvHashMap<ItemPathBuf, Rc<KProc<Spanned<Hir>>>>, 240 - _known_gvars: FnvHashMap<ItemPathBuf, Var>, 242 + known_gvars: FnvHashMap<ItemPathBuf, Var<Type>>, 241 243 known_mems: FnvHashMap<ItemPathBuf, Rc<KMem<TermId>>>, 242 244 known_structs: FnvHashMap<ItemPathBuf, Rc<KStruct>>, 243 245 checked_consts: FnvHashMap<ItemPathBuf, Rc<KConst<TermId>>>, ··· 255 257 pub procs: FnvHashMap<ItemPathBuf, KProc<TypedNode<TermId>>>, 256 258 pub consts: FnvHashMap<ItemPathBuf, KConst<TermId>>, 257 259 pub mems: FnvHashMap<ItemPathBuf, KMem<TermId>>, 258 - pub types: FnvHashMap<ItemPathBuf, KStruct>, 260 + pub vars: FnvHashMap<ItemPathBuf, Var<Type>>, 261 + pub structs: FnvHashMap<ItemPathBuf, KStruct>, 259 262 pub engine: Engine, 260 263 } 261 264 ··· 267 270 let mut this = Walker { 268 271 checked_consts: Default::default(), 269 272 known_procs: Default::default(), 270 - _known_gvars: Default::default(), 273 + known_gvars: Default::default(), 271 274 known_mems: Default::default(), 272 275 known_structs: Default::default(), 273 276 structs, ··· 310 313 checked_procs, 311 314 engine, 312 315 known_mems, 316 + known_gvars, 313 317 .. 314 318 } = this; 315 319 ··· 323 327 .into_iter() 324 328 .map(|(a, b)| (a, Rc::try_unwrap(b).unwrap())) 325 329 .collect(), 326 - types: known_structs 330 + structs: known_structs 327 331 .into_iter() 328 332 .map(|(a, b)| (a, Rc::try_unwrap(b).unwrap())) 329 333 .collect(), 334 + vars: known_gvars, 330 335 engine, 331 336 } 332 337 .okay() ··· 469 474 if self.checked_consts.contains_key(&path) { 470 475 return Ok(()); 471 476 } 477 + 472 478 let outs = const_ 473 479 .outs 474 480 .iter() ··· 667 673 ins: &mut TypeStack, 668 674 heap: &mut THeap, 669 675 body: &[Spanned<Hir>], 670 - vars: &FnvHashMap<ItemPathBuf, Var>, 676 + vars: &FnvHashMap<ItemPathBuf, Var<Type>>, 671 677 bindings_in_scope: Option<&FnvHashMap<ItemPathBuf, TermId>>, 672 678 generics: Option<&FnvHashMap<SmolStr, GenId>>, 673 679 expected_outs: Option<&TypeStack>, ··· 697 703 ins.push(heap, ty); 698 704 TypedNode { 699 705 span: node.span, 700 - node: TypedIr::VarUse(path.clone()), 706 + node: TypedIr::LVarUse(path.clone()), 701 707 ins: vec![], 702 708 outs: vec![ty], 703 709 } ··· 1580 1586 self.engine.insert(TypeInfo::Unknown), 1581 1587 TypedIr::IgnorePattern, 1582 1588 ), 1583 - _ => todo!(), 1589 + Hir::Path(const_name) if self.is_const(const_name) => { 1590 + let const_ = self.checked_consts.get(const_name).cloned().unwrap(); 1591 + let mut ts = TypeStack::default(); 1592 + let r = self.typecheck_const_use( 1593 + &mut ts, 1594 + heap, 1595 + const_, 1596 + const_name, 1597 + pattern.span, 1598 + ); 1599 + (r.outs[0], TypedIr::ConstUse(const_name.clone())) 1600 + } 1601 + _ => todo!("Illegal?? pattern"), 1584 1602 }; 1585 1603 let tir_pattern = TypedNode { 1586 1604 span: pattern.span, ··· 1808 1826 types::Type::Custom(ty) => { 1809 1827 if let Some(ty) = self.known_structs.get(ty) { 1810 1828 Type::Concrete(ConcreteType::Custom(ty.id)) 1829 + } else if let Some(Ref::Struct(ty)) = self.item_refs.get(ty) { 1830 + let ty = Spanned { 1831 + span, 1832 + inner: types::Type::Custom(ty.clone()), 1833 + }; 1834 + self.abstract_to_concrete_type(&ty, generics)? 1835 + } else if let Some(r) = self.unresloved_item_refs.get(ty) { 1836 + if let Ref::Struct(ty) = self.resolve(r.clone()) { 1837 + let ty = Spanned { 1838 + span, 1839 + inner: types::Type::Custom(ty), 1840 + }; 1841 + self.abstract_to_concrete_type(&ty, generics)? 1842 + } else { 1843 + todo!("This is a error yo") 1844 + } 1811 1845 } else if let Some(ty) = self.structs.get(ty).cloned() { 1812 1846 let mut fields = FnvHashMap::default(); 1813 1847 for (n, ty) in ty.fields {
+9
spanner/src/lib.rs
··· 21 21 } 22 22 23 23 impl<T> Spanned<T> { 24 + pub fn map_ref<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 + } 24 33 pub fn map<F, B>(self, f: F) -> Spanned<B> 25 34 where 26 35 F: FnOnce(T) -> B,