kb/
m.rs

1use super::translate_files;
2use super::BasicError;
3use super::DefaultHandler;
4use super::Handler;
5use super::Loader;
6use super::RcStr;
7use super::Source;
8use super::Val;
9use super::Vm;
10
11pub fn main() {
12    let mut loader = Loader::new();
13    let mut module_name: Option<RcStr> = None;
14    let mut state = State::Normal;
15    let mut test_flag = false;
16
17    for arg in std::env::args() {
18        let arg: &str = &arg;
19
20        match &state {
21            State::Normal => match arg {
22                "-m" => state = State::Module,
23                "-t" => test_flag = true,
24                _ => loader.add_source_root(arg),
25            },
26            State::Module => {
27                module_name = Some(arg.to_owned().into());
28                state = State::Normal;
29            }
30        }
31    }
32
33    let module_name = if let Some(module_name) = module_name {
34        module_name
35    } else {
36        eprintln!("Start module name not specified");
37        std::process::exit(1);
38    };
39
40    let result = if test_flag {
41        run_tests(&mut loader, &module_name)
42    } else {
43        run(&mut loader, &module_name)
44    };
45
46    match result {
47        Ok(()) => {}
48        Err(error) => {
49            eprintln!("{}", error.format());
50            std::process::exit(1);
51        }
52    }
53}
54
55fn run(loader: &mut Loader, module_name: &RcStr) -> Result<(), BasicError> {
56    let files = loader.load(&module_name)?;
57    let code = translate_files(files)?;
58    let mut vm = Vm::new(DefaultHandler);
59    match vm.exec(&code) {
60        Ok(_) => Ok(()),
61        Err(error) => Err(BasicError {
62            marks: vm.trace().clone(),
63            message: format!("{}", error),
64            help: None,
65        }),
66    }
67}
68
69fn run_tests(loader: &mut Loader, module_name: &RcStr) -> Result<(), BasicError> {
70    use std::fmt::Write;
71    let child_modules = loader.list_child_modules(module_name)?;
72    let mut test_src = String::new();
73    let test_out = &mut test_src;
74    let mut test_prefixes = Vec::new();
75
76    for child_module in child_modules {
77        writeln!(test_out, "import {}", child_module).unwrap();
78        test_prefixes.push(format!("{}#", child_module).into());
79    }
80
81    loader.add_source(
82        Source {
83            name: "[test]".into(),
84            data: test_src.into(),
85        }
86        .into(),
87    );
88
89    let files = loader.load(&"[test]".into())?;
90    let code = translate_files(files)?;
91    let mut vm = Vm::new(DefaultHandler);
92
93    println!("testing {}", module_name);
94    let r = vm.exec_and_run_tests(&code, &test_prefixes);
95    err_trace(&mut vm, r)
96}
97
98fn err_trace<H: Handler, T>(vm: &mut Vm<H>, r: Result<T, Val>) -> Result<T, BasicError> {
99    match r {
100        Ok(t) => Ok(t),
101        Err(error) => Err(BasicError {
102            marks: vm.trace().clone(),
103            message: format!("{}", error),
104            help: None,
105        }),
106    }
107}
108
109enum State {
110    Normal,
111    Module,
112}