1use crate::analyzer;
2use crate::builtins;
3use crate::emitter;
4use crate::parser;
5use crate::scanner;
6use crate::translator;
7use std::fs;
8use std::io;
9use std::path;
10use std::result;
11use thiserror::Error;
12use wasmtime;
13
14#[derive(Error, Debug)]
15pub enum Error {
16 #[error("can't create output path: {0}")]
17 OutputPathError(path::PathBuf),
18 #[error("io: {path}: {err}")]
19 IOError { path: path::PathBuf, err: io::Error },
20 #[error("scanner: {0}")]
21 ScannerError(#[from] scanner::Error),
22 #[error("parser: {0}")]
23 ParserError(#[from] parser::Error),
24 #[error("analyzer: {0}")]
25 AnalyzerError(#[from] analyzer::Error),
26 #[error("translator: {0}")]
27 TranslatorError(#[from] translator::Error),
28 #[error("emitter: {0}")]
29 EmitterError(#[from] emitter::Error),
30 #[error("wasmtime: {0}")]
31 Wasmtime(#[from] wasmtime::Error),
32}
33
34pub type Result<T> = result::Result<T, Error>;
35
36fn make_output_path(p: &path::Path) -> Result<path::PathBuf> {
37 let mut output_path = p.to_owned();
38 if output_path.set_extension("wasm") {
39 Ok(output_path)
40 } else {
41 Err(Error::OutputPathError(output_path))
42 }
43}
44
45pub fn compile<W: io::Write, R: io::Read>(mut w: W, r: R) -> Result<()> {
46 let toks = scanner::scan(io::BufReader::new(r));
47 let ast = parser::parse(toks)?;
48 let typed_ast = analyzer::analyze(ast)?;
49 let wasm = translator::translate(typed_ast)?;
50 Ok(emitter::emit(&mut w, wasm)?)
51}
52
53pub fn compile_file<P: Into<path::PathBuf>>(input_path: P) -> Result<()> {
54 let input_path = input_path.into();
55 let output_path = make_output_path(&input_path)?;
56 let f = fs::File::open(&input_path)
57 .map_err(|err| Error::IOError { path: input_path, err })?;
58 let r = io::BufReader::new(f);
59 let w = fs::File::create(&output_path)
60 .map_err(|err| Error::IOError { path: output_path, err })?;
61 compile(w, r)
62}
63
64pub fn execute<P: AsRef<path::Path>>(input_path: P) -> Result<()> {
65 let engine = wasmtime::Engine::default();
66 let module = wasmtime::Module::from_file(&engine, input_path)?;
67 let mut store = wasmtime::Store::new(&engine, ());
68 let imports = builtins::make_imports(&mut store);
69 wasmtime::Instance::new(&mut store, &module, &imports)?;
70 Ok(())
71}