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