Files @ dda9cb591b33
Branch filter:

Location: CSY/reowolf/bin-compiler/src/main.rs

dda9cb591b33 4.8 KiB application/rls-services+xml Show Annotation Show as Raw Download as Raw
MH
Add support for log level to bin-compiler
use std::fs::File;
use std::io::Read;

use clap::{App, Arg};
use reowolf_rs as rw;

fn main() {
    let app = App::new("rwc")
        .author("Henger, M.")
        .version(env!("CARGO_PKG_VERSION"))
        .about("Reowolf compiler")
        .arg(
            Arg::new("input")
                .long("input")
                .short('i')
                .help("input files")
                .required(true)
                .takes_value(true)
                .multiple_occurrences(true)
        )
        .arg(
            Arg::new("threads")
                .long("threads")
                .short('t')
                .help("number of runtime threads")
                .default_value("1")
                .takes_value(true)
        )
        .arg(
            Arg::new("loglevel")
                .long("log_level")
                .short('l')
                .help("set log level ('none', 'info', 'debug' or 'all')")
                .default_value("all")
                .takes_value(true)
        )
        .arg(
            Arg::new("stdlib")
                .long("stdlib")
                .short('s')
                .help("standard library directory (overrides default)")
                .takes_value(true)
        );

    // Retrieve arguments and convert
    let app = app.get_matches();
    let input_files = app.values_of("input");
    if input_files.is_none() {
        println!("ERROR: Expected at least one input file");
        return;
    }

    let num_threads = app.value_of("threads").unwrap();
    let num_threads = match num_threads.parse::<i32>() {
        Ok(num_threads) => {
            if num_threads < 0 || num_threads > 255 {
                println!("ERROR: Number of threads must be a number between 0 and 256");
                return;
            }

            num_threads as u32
        },
        Err(err) => {
            println!("ERROR: Failed to parse number of threads\nbecause: {}", err);
            return;
        }
    };

    let log_level = app.value_of("loglevel").unwrap();
    let log_level = match log_level {
        "none" | "None" => rw::runtime2::LogLevel::None,
        "debug" | "Debug" => rw::runtime2::LogLevel::Debug,
        "info" | "Info" | "all" | "All" => rw::runtime2::LogLevel::Info,
        _ => {
            println!("ERROR: Unexpected log level");
            return;
        }
    };

    let standard_library_dir = app.value_of("stdlib")
        .map(|v| v.to_string());

    // Add input files to file buffer
    let input_files = input_files.unwrap();
    assert!(input_files.len() > 0); // because arg is required

    let mut builder = rw::ProtocolDescriptionBuilder::new(standard_library_dir)
        .expect("create protocol description builder");
    let mut file_buffer = Vec::with_capacity(4096);

    for input_file in input_files {
        print!("Adding file: {} ... ", input_file);
        let mut file = match File::open(input_file) {
            Ok(file) => file,
            Err(err) => {
                println!("FAILED (to open file)\nbecause:\n{}", err);
                return;
            }
        };

        file_buffer.clear();
        if let Err(err) = file.read_to_end(&mut file_buffer) {
            println!("FAILED (to read file)\nbecause:\n{}", err);
            return;
        }

        if let Err(err) = builder.add(input_file.to_string(), file_buffer.clone()) {
            println!("FAILED (to tokenize file)\nbecause:\n{}", err);
        }

        println!("Success");
    }

    // Compile the program
    print!("Compiling program ... ");
    let protocol_description = match builder.compile() {
        Ok(pd) => pd,
        Err(err) => {
            println!("FAILED\nbecause:\n{}", err);
            return;
        }
    };

    println!("Success");

    // Start runtime
    print!("Startup of runtime ... ");
    let runtime = rw::runtime2::Runtime::new(num_threads, log_level, protocol_description);
    if let Err(err) = &runtime {
        println!("FAILED\nbecause:\n{}", err);
    }
    println!("Success");

    // Make sure there is a nameless module with a main component
    print!("Creating main component ... ");
    let runtime = runtime.unwrap();
    if let Err(err) = runtime.create_component(b"", b"main") {
        use rw::ComponentCreationError as CCE;
        let reason = match err {
            CCE::ModuleDoesntExist => "Input files did not contain a nameless module (that should contain the 'main' component)",
            CCE::DefinitionDoesntExist => "Input files did not contain a component called 'main'",
            CCE::DefinitionNotComponent => "Input file contained a 'main' function, but not a 'main' component",
            _ => "Unexpected error"
        };
        println!("FAILED\nbecause:\n{} (raw error: {:?})", reason, err);
        return;
    }

    println!("Success");
    println!("Now running until all components have exited");
    println!("--------------------------------------------\n\n");
}