SeaLang/src/bin/main.rs
2024-09-13 19:07:42 +02:00

116 lines
3.6 KiB
Rust

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::<PathBuf>("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}");
}
}
_ => {}
}
}
}