tr-lang 0.4.0

A programming language made to bring syntax closer to Turkish
Documentation
#![feature(io_error_more)]

use std::fs;
use std::fs::canonicalize;
use std::io::Write;

use std::path::PathBuf;
use std::process::exit;

pub mod lexer;
use lexer::Lexer;

pub mod parser;
use parser::Parser;

pub mod bytecode;
pub mod mem;
pub mod store;
pub mod token;
mod util;
use util::{get_lang, SupportedLanguage};
mod utilbin;

pub mod errwarn;
use errwarn::ErrorGenerator;
pub mod runtime;

mod argsparser;
#[cfg(feature = "interactive")]
mod interactive;

fn main() {
    let args = argsparser::parse_args();
    if args.help == true {
        utilbin::print_help(args.help_exitc, args.name);
    }
    if args.version {
        utilbin::print_version(args.name);
    }
    if args.license {
        utilbin::print_license();
    }

    match args.sub_cmd {
        argsparser::Subcommands::Byt => {
            let mut path = PathBuf::from(&args.file);
            let mut lexer = Lexer::new(match util::read_file(&path) {
                Ok(f) => f,
                Err(util::FSErr::IsADir) => {
                    path.push("giriş.trl");
                    match util::read_file(&path) {
                        Ok(f) => f,
                        Err(e) => match get_lang() {    
                            SupportedLanguage::Turkish => ErrorGenerator::error(
                                "DosyaHatası",
                                &format!("{:?}", e),
                                0, 0, path.display().to_string(),
                                None
                            ),
                            SupportedLanguage::English => ErrorGenerator::error(
                                "FSError",
                                &format!("{:?}", e),
                                0, 0, path.display().to_string(),
                                None,
                            ),
                        }.error(),
                    }
                }
                Err(e) => match get_lang() {    
                    SupportedLanguage::Turkish => ErrorGenerator::error(
                        "DosyaHatası",
                        &format!("{:?}", e),
                        0, 0, path.display().to_string(),
                        None
                    ),
                    SupportedLanguage::English => ErrorGenerator::error(
                        "FSError",
                        &format!("{:?}", e),
                        0, 0, path.display().to_string(),
                        None,
                    ),
                }.error(),
            });
            if args.lex_out {
                let canon_path = match canonicalize(path) {
                    Ok(a) => a.display().to_string(),
                    Err(e) => panic!("`{}` adlı dosya yüklenemedi: {}", args.file.clone(), e),
                };
                let lexed = lexer
                    .clone()
                    .tokenize(&mut vec![canon_path.clone()], canon_path)
                    .unwrap_or_else(|e| e.error());
                println!("{:#?}", &lexed);
            }

            let mut parser = match Parser::from_lexer(&mut lexer, args.file.clone()) {
                Ok(p) => p,
                Err(e) => e.error(),
            };
            let parsed = parser.parse().unwrap_or_else(|e| e.error());
            if args.prs_out {
                println!("{:#?}", parsed.clone());
            }

            let encoded = bytecode::to_bytecode(parsed.clone());
            {
                let mut bytecode_src = fs::File::create(&match &args.outfile {
                    Some(f) => f.clone(),
                    None => {
                        let mut pb = PathBuf::from(args.file);
                        pb.set_extension("trbyt");
                        pb.display().to_string()
                    }
                })
                .unwrap();

                bytecode_src.write_all(&encoded[..]).unwrap();
            }
        }
        argsparser::Subcommands::Run => {
            // TODO: if specified accept args.outfile
            let mut path = PathBuf::from(args.file.clone());
            let mut lexer = Lexer::new(match util::read_file(&path) {
                Ok(f) => f,
                Err(util::FSErr::IsADir) => {
                    path.push("giriş.trl");
                    match util::read_file(&path) {
                        Ok(f) => f,
                        Err(e) => match get_lang() {    
                            SupportedLanguage::Turkish => ErrorGenerator::error(
                                "DosyaHatası",
                                &format!("{:?}", e),
                                0, 0, path.display().to_string(),
                                None
                            ),
                            SupportedLanguage::English => ErrorGenerator::error(
                                "FSError",
                                &format!("{:?}", e),
                                0, 0, path.display().to_string(),
                                None,
                            ),
                        }.error(),
                    }
                }
                Err(e) => match get_lang() {    
                    SupportedLanguage::Turkish => ErrorGenerator::error(
                        "DosyaHatası",
                        &format!("{:?}", e),
                        0, 0, path.display().to_string(),
                        None
                    ),
                    SupportedLanguage::English => ErrorGenerator::error(
                        "FSError",
                        &format!("{:?}", e),
                        0, 0, path.display().to_string(),
                        None,
                    ),
                }.error(),
            });
            if args.lex_out {
                let canon_path = match canonicalize(path) {
                    Ok(a) => a.as_path().display().to_string(),
                    Err(e) => panic!("`{}` adlı dosya yüklenemedi: {}", args.file.clone(), e),
                };
                let lexed = lexer
                    .clone()
                    .tokenize(&mut vec![canon_path.clone()], canon_path)
                    .unwrap_or_else(|e| e.error());
                println!("{:#?}", lexed);
            }

            let mut parser = match Parser::from_lexer(&mut lexer, args.file.clone()) {
                Ok(p) => p,
                Err(e) => e.error(),
            };
            if args.prs_out {
                let parsed = parser.clone().parse().unwrap_or_else(|e| e.error());
                println!("{:#?}", parsed);
            }

            let mut run = runtime::Run::new(parser.parse().unwrap_or_else(|e| e.error()));
            run.run(args.file, None, false)
                .unwrap_or_else(|(_, _, a)| a.error());
        }
        argsparser::Subcommands::RunBytes => {
            let path = PathBuf::from(args.file.clone());
            let con = utilbin::read_file_to_vec_u8(&path);
            let parsed = bytecode::from_bytecode(&con[..]);

            let mut run = runtime::Run::new(parsed);
            run.run(args.file, None, false)
                .unwrap_or_else(|(_, _, a)| a.error());
        }
        argsparser::Subcommands::Command => {
            runtime::Run::new(
                match Parser::from_lexer(&mut Lexer::new(args.file), ".".to_string()) {
                    Ok(p) => p,
                    Err(e) => e.error(),
                }.parse().unwrap_or_else(|e| e.error()),
            )
            .run(".".to_string(), None, false)
            .unwrap_or_else(|(_, _, a)| a.error());
        }
        #[cfg(feature = "interactive")]
        argsparser::Subcommands::Interact => interactive::Interactive::new(args.quiet).start(),
    }
}