1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#[macro_use]
extern crate quote;
#[macro_use]
pub mod result;
use std::{io::Write, path::PathBuf, process::{Command, Stdio}};
pub use result::*;
pub mod tokenizer;
pub use tokenizer::*;
pub mod ast;
pub use ast::*;
pub mod asg;
pub use asg::*;
pub mod parser;
pub use parser::*;
pub mod semantifier;
pub use semantifier::*;
pub mod import;
pub use import::*;
pub mod compiler;
pub use compiler::*;
pub mod coder;
pub mod prelude;
pub use prelude::*;
#[derive(Clone)]
pub struct Options {
pub format_output: bool,
pub derives: Vec<String>,
}
impl Default for Options {
fn default() -> Self {
Options {
format_output: true,
derives: vec![
"PartialEq".to_string(),
"Debug".to_string(),
"Clone".to_string(),
],
}
}
}
pub fn rustfmt(input: &str) -> String {
let mut proc = Command::new("rustfmt")
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::inherit())
.spawn()
.expect("rustfmt failed");
let stdin = proc.stdin.as_mut().unwrap();
stdin.write_all(input.as_bytes()).unwrap();
String::from_utf8_lossy(&proc.wait_with_output().unwrap().stdout).to_string()
}
pub fn compile_spec(name: &str, spec: &str, options: &Options) -> AsgResult<()> {
let resolver = PreludeImportResolver(NullImportResolver);
let program = asg::Program::from_ast(
&parse(spec).map_err(|x| -> Error { x.into() })?,
&resolver,
)?;
let compiler_options = CompileOptions {
derives: options.derives.clone(),
};
let compiled = compiler::compile_program(&program, &compiler_options);
let mut compiled = compiled.to_string();
if options.format_output {
compiled = rustfmt(&compiled);
}
let mut target: PathBuf = std::env::var("OUT_DIR").expect("OUT_DIR env var not set").into();
target.push(format!("{}.rs", name));
std::fs::write(target, compiled).expect("failed to write to target");
Ok(())
}
#[macro_export]
macro_rules! include_spec {
($package: tt) => {
include!(concat!(env!("OUT_DIR"), concat!("/", $package, ".rs")));
};
}