]> Witch of Git - ivy/blob - src/main.rs
Avoid redundant loads in capture generation
[ivy] / src / main.rs
1 use ivy::{
2 ast::Ast,
3 parse,
4 trans::{self, translate},
5 BUILTINS,
6 };
7 use std::{
8 fs,
9 io::{self, Read, Write},
10 path::{Path, PathBuf},
11 process::Command,
12 };
13 use structopt::{clap, StructOpt};
14 use tempfile;
15
16 /// The Ivy compiler.
17 ///
18 /// If no mode is specified, this will fully compile the program.
19 #[derive(Debug, StructOpt)]
20 #[structopt(setting = clap::AppSettings::ArgRequiredElseHelp)]
21 struct Opt {
22 /// Output assembly.
23 #[structopt(short = "S", long = "assembly", conflicts_with = "pretty")]
24 assembly: bool,
25
26 /// Pretty-print the source code.
27 #[structopt(short = "p", long = "pretty")]
28 pretty: bool,
29
30 /// Input path. Use "-" for stdin.
31 input: PathBuf,
32
33 /// Output path. Defaults to stdout or a.out, depending on the mode.
34 #[structopt(short = "o", long = "output")]
35 output: Option<PathBuf>,
36 }
37
38 fn main() -> io::Result<()> {
39 let opt = Opt::from_args();
40 let text = match &opt.input {
41 path if path == Path::new("-") => {
42 let mut text = String::new();
43 std::io::stdin().read_to_string(&mut text)?;
44 text
45 }
46 path => fs::read_to_string(path)?,
47 };
48 let sexp = match parse(&text) {
49 Ok(item) => item,
50 Err(err) => {
51 println!("{:?}", err);
52 std::process::exit(1);
53 }
54 };
55 let (ast, mut builtins) = match Ast::parse(BUILTINS, &sexp) {
56 Ok(ast) => ast,
57 Err(err) => {
58 println!("{}", err);
59 std::process::exit(1);
60 }
61 };
62 if opt.pretty {
63 match opt.output {
64 Some(path) => {
65 let mut file = fs::File::create(path)?;
66 writeln!(file, "{}", ast.to_doc().pretty(80))?;
67 }
68 None => println!("{}", ast.to_doc().pretty(80)),
69 }
70 return Ok(());
71 }
72 let code = match translate(&ast) {
73 Ok(code) => code,
74 Err(err) => {
75 println!("{}", err);
76 std::process::exit(1);
77 }
78 };
79 builtins.retain(|_, v| code.globals.contains(&v.global_number().unwrap()));
80 if opt.assembly {
81 match opt.output {
82 Some(path) => {
83 let mut file = fs::File::create(path)?;
84 trans::x64::write_compile(&builtins, &mut file, &code)?;
85 }
86 None => {
87 let stdout = std::io::stdout();
88 trans::x64::write_compile(&builtins, &mut stdout.lock(), &code)?;
89 }
90 }
91 return Ok(());
92 }
93 let mut file = tempfile::Builder::new().suffix(".s").tempfile()?;
94 trans::x64::write_compile(&builtins, &mut file, &code)?;
95 Command::new("clang")
96 .args(&[
97 "-masm=intel",
98 "-nostartfiles",
99 "-Lrt/target/release",
100 "-lrt",
101 "-Wl,-e,_start",
102 ])
103 .arg(file.path())
104 .arg("-o")
105 .arg(opt.output.unwrap_or_else(|| "a.out".into()))
106 .spawn()?
107 .wait()?;
108 Ok(())
109 }