diff --git a/Cargo.toml b/Cargo.toml index feb4029..1b301ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ edition = "2021" [dependencies] regex = "1.10.4" once_cell = "1.19.0" -clap = { version = "4.0", features = ["derive"] } +clap = "3.0" rand = "0.8.5" serde_json = "1.0" serde = "1.0.203" diff --git a/src/compiler.rs b/src/compiler.rs new file mode 100644 index 0000000..27714b7 --- /dev/null +++ b/src/compiler.rs @@ -0,0 +1,74 @@ +use std::{fs, path::Path, process::Command}; + +use crate::{ + transpiler::{State, Transpiler}, + utils::{Problem, ProblemCap, ProblemType, Variables}, +}; + +pub fn transpile(input_file: String, output_file: String, is_main: bool) -> u8 { + let mut ecode: u8 = 0; + let mut trsp = Transpiler { + ..Default::default() + }; + let mut vars = Variables::new(); + if let Ok(file_contents) = fs::read_to_string(input_file) { + let mut output_code = trsp.transpile(file_contents, 0, &mut vars); + if is_main { + output_code += "fn main() {"; + output_code += vars + .get_var( + "main".to_string(), + &mut trsp, + State { + line: 0, + column: 0, + file: None, + }, + ) + .as_str(); + output_code += "();}"; + } + if let Ok(_) = fs::write(Path::new("build").join(output_file), output_code) {} + } else { + trsp.problems.push(ProblemCap::Error(Problem { + problem_msg: "File not found".to_string(), + problem_type: ProblemType::FileNotFound, + state: State { + line: 0, + column: 0, + file: None, + }, + })) + } + for p in trsp.problems { + match p { + ProblemCap::Error(problem) => { + ecode = 1; + if problem.state.file == None { + println!( + "\x1b[31;1m{:?}\x1b[0;1m: {}", + problem.problem_type, problem.problem_msg, + ) + } else { + println!( + "\x1b[31;1mError\x1b[0;1m: {}\x1b[0m\n{}:{}: {:?}", + problem.problem_msg, + problem.state.line, + problem.state.column, + problem.problem_type, + ) + } + } + } + } + ecode +} + +pub fn compile_rust(exe_file: String) { + Command::new("rustc") + .arg(Path::new("build").join("main.rs")) + .arg("-o") + .arg(exe_file) + .output() + .expect("Error compiling rust: "); +} diff --git a/src/main.rs b/src/main.rs index 43e92bf..3b30eda 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,25 +1,36 @@ -use utils::{ProblemCap, Variables}; +use std::{fs, process}; +mod compiler; mod parser; mod transpiler; mod utils; +use clap::{App, Arg}; +use compiler::{compile_rust, transpile}; fn main() { - let mut vars = Variables::new(); - let mut trsp = transpiler::Transpiler::default(); - let out = trsp.transpile("rust{let mut x;}".to_string(), 0, &mut vars); - for p in trsp.problems { - match p { - ProblemCap::Error(problem) => { - println!( - "\x1b[31;1mError\x1b[0;1m: {}\x1b[0m\n{}:{}: {:?}", - problem.problem_msg, - problem.state.line, - problem.state.column, - problem.problem_type, - ) - } - } - } - println!("{out}\n\n\n"); + let matches = App::new("Wyst") + .version("0.51") + .author("Leo dev") + .about("The wyst compiler") + .arg( + Arg::with_name("file") + .required(true) + .help("Sets the input file to use"), + ) + .arg( + Arg::with_name("output") + .short('o') + .long("output") + .takes_value(true) + .help("Specifies the output executable file name"), + ) + .get_matches(); + + let file = matches.value_of("file").unwrap().to_string(); + let output = matches.value_of("output").unwrap_or("out").to_string(); + if let Ok(_) = fs::create_dir("build") {} + let ecode = transpile(file, "main.rs".to_string(), true); + compile_rust(output); + fs::remove_dir_all("build").expect("Error removing build"); + process::exit(ecode as i32); } diff --git a/src/parser.rs b/src/parser.rs index af3b487..5bc2238 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -18,15 +18,15 @@ pub enum Token { // Square(String), } -pub fn extract_values(token: Token) -> (String, State) { +pub fn extract_values(token: Token) -> (u8, String, State) { match token { - Token::Number(x, state) => (x, state), - Token::Identifier(x, state) => (x, state), - Token::Curly(x, state) => (x, state), - Token::Round(x, state) => (x, state), - Token::DKeyword(x, state) => (x, state), - Token::SKeyword(x, state) => (x, state), - Token::Keyword(x, state) => (x, state), + Token::Number(x, state) => (0, x, state), + Token::Identifier(x, state) => (1, x, state), + Token::Curly(x, state) => (2, x, state), + Token::Round(x, state) => (3, x, state), + Token::DKeyword(x, state) => (4, x, state), + Token::SKeyword(x, state) => (5, x, state), + Token::Keyword(x, state) => (6, x, state), } } @@ -83,7 +83,11 @@ pub fn tokenize(code: String, state: &mut State, root: &mut Transpiler) -> Vec 0 { let mut drain: usize = 1; let vals = extract_values(tokens[0].clone()); - if vals.0.contains("list_vx") { - ast.push(Ast::Single(Token::Identifier(vals.0, vals.1))); + if vals.1.contains("list_vx") { + ast.push(Ast::Single(Token::Identifier(vals.1, vals.2))); tokens.drain(0..1); continue; } diff --git a/src/transpiler.rs b/src/transpiler.rs index 92ddbd4..c970ae8 100644 --- a/src/transpiler.rs +++ b/src/transpiler.rs @@ -1,5 +1,5 @@ use crate::{ - parser::{self, extract_ast, Ast}, + parser::{self, extract_ast, extract_values, Ast}, utils::{ProblemCap, VariableType, Variables}, }; use serde::{Deserialize, Serialize}; @@ -8,6 +8,7 @@ use serde::{Deserialize, Serialize}; pub struct State { pub line: u32, pub column: u32, + pub file: Option, } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -27,7 +28,11 @@ impl Default for Inject { fn default() -> Self { Inject { inject: false, - state: State { line: 0, column: 0 }, + state: State { + line: 0, + column: 0, + file: None, + }, } } } @@ -38,7 +43,11 @@ impl Default for Transpiler { matched_vars: Variables::new(), inject: Inject::default(), problems: Vec::new(), - state: State { line: 1, column: 0 }, + state: State { + line: 1, + column: 0, + file: None, + }, } } } @@ -96,7 +105,13 @@ impl Transpiler { res += rs.as_str(); res += "}"; } - Ast::Single(_) => {} + Ast::Single(x) => { + let vals = extract_values(x); + if vals.0 == 1 { + println!("{:?}", vals); + res += vars.get_var(vals.1, self, vals.2).as_str(); + } + } } } if indent > 0 { diff --git a/src/utils.rs b/src/utils.rs index 28526f6..626dfbe 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -19,7 +19,6 @@ pub enum ProblemCap { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Problem { - //pub code: u32, pub problem_type: ProblemType, pub problem_msg: String, pub state: State, @@ -57,7 +56,11 @@ impl Variables { Variable { vtype: VariableType::Keyword, desc: "".to_string(), - state: State { line: 0, column: 0 }, + state: State { + line: 0, + column: 0, + file: None, + }, params: Variables { vars: HashMap::new(), }, @@ -182,7 +185,26 @@ impl Variables { self.vars.iter_mut() } pub fn get_mut(&mut self, name: String) -> Option<&mut Variable> { - self.vars.get_mut(&name) + if !name.contains("::") { + return self.vars.get_mut(&name); + } + if let Some((x, _)) = name.split_once("::") { + println!("{x}"); + if let Some(v) = self.vars.get_mut(x) { + println!("{:?}", v); + let mut var = v; + for a in name.split("::") { + if let Some(b) = var.params.vars.get_mut(a) { + var = b; + } else { + return None; + } + } + return Some(var); + } + return None; + } + None } pub fn expand(&mut self, vars: Variables) { for (x, y) in vars.vars {