use std::{io::Read, path::PathBuf}; use clap::Command; use compiler::{ lexer::Tokenizer, parser::Tree, triples::{MirBuilder, IR}, }; fn main() { let cmd = clap::Command::new("sea") .bin_name("sea") .arg( clap::Arg::new("input") .short('i') .help("sea source file.") .value_parser(clap::builder::PathBufValueParser::new()), ) .subcommands([ Command::new("ast").about("output AST."), Command::new("ast2").about("output AST."), Command::new("mir").about("output machine-level intermediate representation."), Command::new("ir").about("output intermediate representation."), Command::new("asm").about("output x86-64 assembly (intel syntax)."), ]); let matches = cmd.get_matches(); let path = matches.get_one::("input"); let source = path .and_then(|p| std::fs::read(p).ok()) .or_else(|| { let mut buf = Vec::new(); std::io::stdin().read(&mut buf).ok()?; Some(buf) }) .expect("no source bytes."); let tokens = Tokenizer::new(&source).unwrap(); let mut tree = Tree::new(); tree.parse(tokens.iter()).unwrap(); tree.fold_comptime(); if let Some((cmd, _matches)) = matches.subcommand() { match cmd { "ast" => { let mut buf = String::new(); tree.render(&mut buf).unwrap(); println!("AST:\n{buf}"); } "ast2" => { let mut tree2 = compiler::ast2::ast_gen::Parser::new(); tree2.parse(tokens.iter()); eprintln!("{tree2:#?}"); println!("AST (new):\n{tree2}"); } "ir" => { let mut ir = IR::new(); let builder = ir.build(&mut tree); let mut buf = String::new(); builder.render(&mut buf).unwrap(); println!("IR:\n{buf}"); } "mir" => { let mut ir = IR::new(); ir.build(&mut tree); let mut mir = MirBuilder::new(&ir, tree.strings); mir.build(); let MirBuilder { strings, functions, .. } = mir; for (name, mir) in functions { println!("{}:\n{}", strings.get_str(name), mir.display(&strings)); } } "asm" => { let mut ir = IR::new(); ir.build(&mut tree); let mut mir = MirBuilder::new(&ir, tree.strings); mir.build(); let MirBuilder { globals, strings, functions, .. } = mir; println!(".intel_syntax"); println!(".text"); for (_name, mir) in globals { let assembly = mir .assemble(&strings) .unwrap() .finish_constants(&strings) .unwrap(); println!("{assembly}"); } for (_name, mir) in functions { let assembly = mir .assemble(&strings) .unwrap() .finish_as_function(&strings) .unwrap(); println!("{assembly}"); } } _ => {} } } }