<commit_before>extern crate regex;
extern crate getopts;

mod matching;
mod support;
mod tokens;
mod lexer;
mod files;
mod symbols;
mod plp;
mod compiler;

use std::env;
use std::process;
use std::vec::Vec;
use tokens::*;
use symbols::*;
use symbols::symbol_table::*;
use compiler::symbol_analysis::*;
use lexer::*;
use support::*;
use files::dump;
use compiler::*;
use plp::PLPWriter;

fn main()
{
    let default_source = "sampleData/BasicArithmatic.java";
    let lex_output_file = "sampleData/output/stable/BasicArithmatic.java.lexed";
    let preprocessed_output_file = "sampleData/output/stable/BasicArithmatic.java.preprocessed";

    let args: Vec<String> = env::args().collect();

    let mut opts = getopts::Options::new();
    opts.optopt("s", "src", "Set input file name", "NAME");
    opts.optflag("a", "annotate", "Enables annotation of output source file");
    opts.optflag("m", "map", "Enables mapping of line numbers from Java source to output asm source");

    let matches = match opts.parse(&args[1..])
    {
        Ok(m) => m,
        Err(f) => {
                println!("{}", f);
                process::exit(1);
            }
    };

    let mut source_file = default_source.to_string();
    if matches.opt_present("s")
    {
        let brief = format!("Usage: grinder File [options]");
        println!("{}", opts.usage(&brief));
        source_file = match matches.opt_str("s")
        {
            Some(ref x) => x.clone(),
            None => default_source.to_string(),
        };
    }

    //TODO match options
    if !matches.free.is_empty() {
        println!("Free arguments: {:?}", matches.free);
    }

    let source_file = &*source_file.clone();
    let was_compile_successful = compile_oracle(&["javac", "-d", "output/temp/class", source_file]);

    if was_compile_successful
    {
        let mut base_writter = PLPWriter::new();
        base_writter.annotations_enabled = matches.opt_present("a");
        base_writter.mapping_enabled = matches.opt_present("m");

        // TODO: support multiple source files
        let mut tokens: Vec<Token> = lex_file(source_file, false);
        tokens.print_to(lex_output_file, false);

        remove_meta(&mut tokens);
        tokens.print_to(preprocessed_output_file, false);

        let mut symbols_table: SymbolTable = SymbolTable::new();
        let class_structure = parse_class(&tokens, 0, tokens[1].value.clone(), true, &mut symbols_table);
        let class_symbol = &class_structure.class_symbol;

        let main_symbol = symbols_table.lookup_by_name("main")[0];
        let main_label = match main_symbol.location {
                SymbolLocation::Memory(ref address) => address.label_name.clone(),
                _ => { panic!("Main found was not a function!"); },
            };

        let mut plp = base_writter.copy();
        let (static_memory_label, static_init_label) = get_class_labels(&class_symbol);

        // Compile static_init for class
        let mut static_init = base_writter.copy();
        static_init.label(&*static_init_label);
        static_init.indent_level += 1;
        let static_size = class_structure.static_variables.len();
        for static_variable in class_structure.static_variables
        {
            let start = static_variable.0;
            let name = static_variable.2;
            let namespace = static_variable.3;

            let registers = ("$t0", "$t1", "$t2", "$t3", "$t4");
            compile_statement(&tokens, start, &*namespace, registers, &symbols_table, &mut static_init);
        }

        let mut static_init_labels = Vec::new();
        static_init_labels.push(&*static_init_label);
        compile_program_header(&mut plp, &*main_label, &static_init_labels);

        // Static class memory
        plp.label(&*static_memory_label);
        plp.indent_level += 1;
        plp.space(static_size as u16);
        plp.indent_level -= 1;

        // TODO: write all static blocks
        plp.println();
        plp.code.push_str(&*static_init.code);

        // Compile static methods
        for static_method in class_structure.static_methods
        {
            let range = (static_method.0, static_method.1);
            let name = static_method.2;
            let namespace = static_method.3;
            let argument_types = static_method.4.unwrap();

            let method_symbol = symbols_table.lookup_function(&*namespace, &*name, &argument_types).unwrap();

            let registers = ("$t0", "$t1", "$t2", "$t3", "$t4");
            compile_method_body(&tokens, range, method_symbol, &*namespace, registers, &symbols_table, &mut plp);
        }
        plp.label("end");

        dump("output.asm", plp.code);
    }
}

///Start on open curly brace
fn parse_class(tokens: &Vec<Token>, start_index: usize, class_name: String, is_class_static: bool, symbols_table: &mut SymbolTable) -> ClassStructure
{
    let mut class_symbol: Symbol;
    let mut class_structure: ClassStructure = ClassStructure::new();
    let mut current_namespace: String = class_name.clone();
    let mut current_local_class_variables = 0;
    let mut current_static_class_variables = 0;

    println!("\n<------------ Parse Class --------------->");
    let mut min_value = 0;
    let mut skip_amount = 0;

    for (index, token) in tokens[start_index..].iter().enumerate()
    {
        if min_value != 0
        {
            min_value -= 1;
            continue;<commit_msg>Extract compile from main<commit_after>extern crate regex;
extern crate getopts;

mod matching;
mod support;
mod tokens;
mod lexer;
mod files;
mod symbols;
mod plp;
mod compiler;

use std::env;
use std::process;
use std::vec::Vec;
use tokens::*;
use symbols::*;
use symbols::symbol_table::*;
use compiler::symbol_analysis::*;
use lexer::*;
use support::*;
use files::dump;
use compiler::*;
use plp::PLPWriter;

fn main()
{
    let default_source = "sampleData/BasicArithmatic.java";
    let lex_output_file = "sampleData/output/stable/BasicArithmatic.java.lexed";
    let preprocessed_output_file = "sampleData/output/stable/BasicArithmatic.java.preprocessed";

    let args: Vec<String> = env::args().collect();

    let mut opts = getopts::Options::new();
    opts.optopt("s", "src", "Set input file name", "NAME");
    opts.optflag("a", "annotate", "Enables annotation of output source file");
    opts.optflag("m", "map", "Enables mapping of line numbers from Java source to output asm source");

    let matches = match opts.parse(&args[1..])
    {
        Ok(m) => m,
        Err(f) => {
                println!("{}", f);
                process::exit(1);
            }
    };

    let mut source_file = default_source.to_string();
    if matches.opt_present("s")
    {
        let brief = format!("Usage: grinder File [options]");
        println!("{}", opts.usage(&brief));
        source_file = match matches.opt_str("s")
        {
            Some(ref x) => x.clone(),
            None => default_source.to_string(),
        };
    }

    //TODO match options
    if !matches.free.is_empty() {
        println!("Free arguments: {:?}", matches.free);
    }

    let source_file = &*source_file.clone();
    let was_compile_successful = compile_oracle(&["javac", "-d", "output/temp/class", source_file]);

    if was_compile_successful
    {
        let mut base_writter = PLPWriter::new();
        base_writter.annotations_enabled = matches.opt_present("a");
        base_writter.mapping_enabled = matches.opt_present("m");

        compile(source_file, &base_writter);
    }
}

fn compile(source_file: &str, base_writter: &PLPWriter)
{
    // TODO: support multiple source files
    let mut tokens: Vec<Token> = lex_file(source_file, false);
    //tokens.print_to(lex_output_file, false);

    remove_meta(&mut tokens);
    //tokens.print_to(preprocessed_output_file, false);

    let mut symbols_table: SymbolTable = SymbolTable::new();
    let class_structure = parse_class(&tokens, 0, tokens[1].value.clone(), true, &mut symbols_table);
    let class_symbol = &class_structure.class_symbol;

    let main_symbol = symbols_table.lookup_by_name("main")[0];
    let main_label = match main_symbol.location {
            SymbolLocation::Memory(ref address) => address.label_name.clone(),
            _ => { panic!("Main found was not a function!"); },
        };

    let mut plp = base_writter.copy();
    let (static_memory_label, static_init_label) = get_class_labels(&class_symbol);

    // Compile static_init for class
    let mut static_init = base_writter.copy();
    static_init.label(&*static_init_label);
    static_init.indent_level += 1;
    let static_size = class_structure.static_variables.len();
    for static_variable in class_structure.static_variables
    {
        let start = static_variable.0;
        let name = static_variable.2;
        let namespace = static_variable.3;

        let registers = ("$t0", "$t1", "$t2", "$t3", "$t4");
        compile_statement(&tokens, start, &*namespace, registers, &symbols_table, &mut static_init);
    }

    let mut static_init_labels = Vec::new();
    static_init_labels.push(&*static_init_label);
    compile_program_header(&mut plp, &*main_label, &static_init_labels);

    // Static class memory
    plp.label(&*static_memory_label);
    plp.indent_level += 1;
    plp.space(static_size as u16);
    plp.indent_level -= 1;

    // TODO: write all static blocks
    plp.println();
    plp.code.push_str(&*static_init.code);

    // Compile static methods
    for static_method in class_structure.static_methods
    {
        let range = (static_method.0, static_method.1);
        let name = static_method.2;
        let namespace = static_method.3;
        let argument_types = static_method.4.unwrap();

        let method_symbol = symbols_table.lookup_function(&*namespace, &*name, &argument_types).unwrap();

        let registers = ("$t0", "$t1", "$t2", "$t3", "$t4");
        compile_method_body(&tokens, range, method_symbol, &*namespace, registers, &symbols_table, &mut plp);
    }
    plp.label("end");

    dump("output.asm", plp.code);
}

///Start on open curly brace
fn parse_class(tokens: &Vec<Token>, start_index: usize, class_name: String, is_class_static: bool, symbols_table: &mut SymbolTable) -> ClassStructure
{
    let mut class_symbol: Symbol;
    let mut class_structure: ClassStructure = ClassStructure::new();
    let mut current_namespace: String = class_name.clone();
    let mut current_local_class_variables = 0;
    let mut current_static_class_variables = 0;

    println!("\n<------------ Parse Class --------------->");
    let mut min_value = 0;
    let mut skip_amount = 0;

    for (index, token) in tokens[start_index..].iter().enumerate()
    {
        if min_value != 0
        {
            min_value -= 1;
            continue;
{'fraction_non_alphanumeric': 0.1382702301410542, 'fraction_numerical': 0.006310319227913883, 'mean_word_length': 3.0122859270290396, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1826339', 'n_tokens_mistral': 3344, 'n_tokens_neox': 3253, 'n_words': 775}