Files @ 560ed3c4dc1d
Branch filter:

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

560ed3c4dc1d 3.8 KiB application/rls-services+xml Show Source Show as Raw Download as Raw
Max Henger
feat: compiler binary
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
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("debug")
                .long("debug")
                .short('d')
                .help("enable debug logging")
        );

    // 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 debug_enabled = app.is_present("debug");

    // 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();
    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");

    // Make sure there is a nameless module with a main component
    print!("Creating main component ... ");
    let runtime = rw::runtime2::Runtime::new(num_threads, debug_enabled, protocol_description);
    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");
}