From ea7222255aa1f7cc340c1942af0751597e935b6c Mon Sep 17 00:00:00 2001 From: Leo Dev Date: Wed, 12 Jun 2024 22:16:43 +0200 Subject: [PATCH] New variable system and stage 1 error checking --- src/lsp.rs | 7 +- src/lspcom.rs | 35 ++++-- src/main.rs | 7 +- src/parser.rs | 123 ++++++++++---------- src/transpiler.rs | 280 +++++++++++++++++++++++++++++----------------- src/variable.rs | 182 ++++++++++++++++++++++++------ 6 files changed, 410 insertions(+), 224 deletions(-) diff --git a/src/lsp.rs b/src/lsp.rs index 47fe3eb..af8dead 100644 --- a/src/lsp.rs +++ b/src/lsp.rs @@ -1,4 +1,7 @@ -use crate::lspcom::{get_completion, get_items, request_methods, LspServer, TextDocumentChangeParams}; +use crate::{ + lspcom::{get_completion, get_items, request_methods, LspServer, TextDocumentChangeParams}, + variable::Variables, +}; use lsp_types::*; use once_cell::sync::Lazy; use regex::Regex; @@ -33,7 +36,7 @@ impl LspServer for Server { .documents .get(params.text_document_position.text_document.uri.as_str()) .expect("err_textdoc"); - let items: HashMap = get_completion( + let items: Variables = get_completion( text.clone(), params.text_document_position.position.line as usize + 1, params.text_document_position.position.character as usize, diff --git a/src/lspcom.rs b/src/lspcom.rs index c6b6668..798515b 100644 --- a/src/lspcom.rs +++ b/src/lspcom.rs @@ -1,14 +1,12 @@ use crate::{ - parser::new_vars, transpiler::Transpiler, - variable::{Variable, VariableType}, + variable::{VariableType, Variables}, }; use lsp_types::{ CompletionItem, CompletionItemKind, CompletionParams, CompletionResponse, InitializeResult, }; use rand::{thread_rng, Rng}; use serde::{Deserialize, Serialize}; -use std::collections::HashMap; pub fn place_at(input: String, in2: String, line_goal: usize, column_goal: usize) -> String { let mut line: usize = 1; @@ -28,14 +26,14 @@ pub fn place_at(input: String, in2: String, line_goal: usize, column_goal: usize out } -pub fn get_completion(input: String, line: usize, column: usize) -> HashMap { +pub fn get_completion(input: String, line: usize, column: usize) -> Variables { let rand_id: u32 = thread_rng().gen(); let rand_id: String = rand_id.to_string(); let mut transpiler = Transpiler { peek: rand_id.clone(), ..Default::default() }; - transpiler.transpile(place_at(input, rand_id, line, column), 0, new_vars()); + transpiler.transpile(place_at(input, rand_id, line, column), 0, Variables::new()); transpiler.matched_vars } @@ -63,15 +61,16 @@ pub struct TextDocumentChangeParams { pub text: String, } -pub fn get_items( - items: HashMap, - lname: String, -) -> Vec { +pub fn get_items(mut items: Variables, lname: String) -> Vec { let mut completion_items: Vec = Vec::new(); - for (name, var) in items { - let mut item = CompletionItem::new_simple(lname.clone() + &name, var.desc); + for (name, var) in items.iter_mut() { + let mut item = CompletionItem::new_simple(lname.clone() + &name, var.desc.clone()); if var.vtype != VariableType::Func { - completion_items.extend(get_items(var.params, name + "::").iter().cloned()) + completion_items.extend( + get_items(var.params.clone(), name.to_owned() + "::") + .iter() + .cloned(), + ) } else { // item.documentation = Some(Documentation::MarkupContent(MarkupContent { // kind: MarkupKind::Markdown, @@ -99,3 +98,15 @@ pub fn get_items( } completion_items } + +#[derive(Clone, Debug)] +pub enum ProblemType { + VariableNotFound, +} + +#[derive(Clone, Debug)] +pub struct Problem { + pub code: u32, + pub problem_type: ProblemType, + pub problem_msg: String, +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 92679d4..bd5f66a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,9 +6,9 @@ mod parser; mod transpiler; mod variable; use clap::Parser; -use parser::new_vars; use std::{fs, path::Path}; use transpiler::Transpiler; +use variable::Variables; use crate::lsp::run_lsp_server; @@ -38,7 +38,10 @@ fn main() { } fs::create_dir("build").expect("error making build"); let mut trsp = Transpiler::default(); - let transpiled_code = trsp.transpile(file_content, 0, new_vars()); + let transpiled_code = trsp.transpile(file_content, 0, Variables::new()); + for problem in trsp.problems { + println!("{}", problem.problem_msg) + } match args.rust { Some(ref rust_file_name) => { diff --git a/src/parser.rs b/src/parser.rs index b0a5f81..05e86f3 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,10 +1,10 @@ use crate::{ lexer::{LexerState, Token, TokenType}, - variable::Variable, + variable::Variables, }; use once_cell::sync::Lazy; use regex::Regex; -use std::{collections::HashMap, fmt}; +use std::fmt; #[derive(Clone, Debug, PartialEq, Eq)] pub enum AstType { @@ -28,6 +28,16 @@ pub enum AstType { Other, } +pub fn is_decl(ast: &Ast) -> bool { + ast.ast_type == AstType::FunctionDeceleration + || ast.ast_type == AstType::VoidFunctionDeceleration + || ast.ast_type == AstType::Namespace + || ast.ast_type == AstType::VariableDeceleration + || ast.ast_type == AstType::PointerDeceleration + || ast.ast_type == AstType::MutVariableDeceleration + || ast.ast_type == AstType::StructDeceleration +} + pub struct Ast { pub tokens: Vec, pub ast_type: AstType, @@ -66,19 +76,12 @@ pub struct Parser { pub index: u32, pub include_regex: Lazy, pub include_regex_local: Lazy, - pub variables: HashMap, + pub variables: Variables, pub json: bool, } -pub fn new_vars() -> HashMap { - HashMap::from([( - "void".to_string(), - Variable::new_keyword(LexerState { line: 0, column: 0 }, String::from("")), - )]) -} - impl Parser { - pub fn new(tokens: Vec, variables: HashMap) -> Parser { + pub fn new(tokens: Vec, variables: Variables) -> Parser { Parser { tokens: tokens, index: 0, @@ -128,15 +131,13 @@ impl Parser { if index > 0 && self.tokens[index - 1].token_type == TokenType::Comment { desc = self.tokens[index - 1].value.clone() } - self.variables.insert( + self.variables.new_struct( self.tokens[index + 1].clone().value, - Variable::new_struct( - LexerState { - line: self.tokens[index + 1].clone().line, - column: self.tokens[index + 1].clone().column, - }, - desc, - ), + LexerState { + line: self.tokens[index + 1].clone().line, + column: self.tokens[index + 1].clone().column, + }, + desc, ); } else if self.tokens.len() - index > 2 && self.tokens[index].value == "namespace" @@ -151,15 +152,13 @@ impl Parser { if index > 0 && self.tokens[index - 1].token_type == TokenType::Comment { desc = self.tokens[index - 1].value.clone() } - self.variables.insert( + self.variables.new_namespace( self.tokens[index + 1].clone().value, - Variable::new_namespace( - LexerState { - line: self.tokens[index + 1].clone().line, - column: self.tokens[index + 1].clone().column, - }, - desc, - ), + LexerState { + line: self.tokens[index + 1].clone().line, + column: self.tokens[index + 1].clone().column, + }, + desc, ); } else if self.tokens.len() - index > 2 && self.tokens[index].value == "impl" @@ -211,15 +210,13 @@ impl Parser { { desc = self.tokens[index - 1].value.clone() } - self.variables.insert( + self.variables.new_func( self.tokens[index + 1].clone().value, - Variable::new_func( - LexerState { - line: self.tokens[index + 1].clone().line, - column: self.tokens[index + 1].clone().column, - }, - desc, - ), + LexerState { + line: self.tokens[index + 1].clone().line, + column: self.tokens[index + 1].clone().column, + }, + desc, ); } else if self.tokens.len() - index > 1 && self.tokens[index + 1].token_type == TokenType::Curly @@ -240,15 +237,13 @@ impl Parser { { desc = self.tokens[index - 1].value.clone() } - self.variables.insert( + self.variables.new_var( self.tokens[index + 1].clone().value, - Variable::new_var( - LexerState { - line: self.tokens[index + 1].clone().line, - column: self.tokens[index + 1].clone().column, - }, - desc, - ), + LexerState { + line: self.tokens[index + 1].clone().line, + column: self.tokens[index + 1].clone().column, + }, + desc, ); } else if self.tokens.len() - index > 1 { if self.tokens[index + 1].token_type == TokenType::Identifier { @@ -261,15 +256,13 @@ impl Parser { { desc = self.tokens[index - 1].value.clone() } - self.variables.insert( + self.variables.new_var( self.tokens[index + 1].clone().value, - Variable::new_var( - LexerState { - line: self.tokens[index + 1].clone().line, - column: self.tokens[index + 1].clone().column, - }, - desc, - ), + LexerState { + line: self.tokens[index + 1].clone().line, + column: self.tokens[index + 1].clone().column, + }, + desc, ); } else if self.tokens.len() - index > 2 && self.tokens[index + 2].token_type == TokenType::Identifier @@ -287,15 +280,13 @@ impl Parser { { desc = self.tokens[index - 1].value.clone() } - self.variables.insert( + self.variables.new_var( self.tokens[index + 1].clone().value, - Variable::new_var( - LexerState { - line: self.tokens[index + 1].clone().line, - column: self.tokens[index + 1].clone().column, - }, - desc, - ), + LexerState { + line: self.tokens[index + 1].clone().line, + column: self.tokens[index + 1].clone().column, + }, + desc, ); } else if self.tokens.len() - index > 2 && self.tokens[index + 1].value == "*" @@ -310,15 +301,13 @@ impl Parser { { desc = self.tokens[index - 1].value.clone() } - self.variables.insert( + self.variables.new_var( self.tokens[index + 1].clone().value, - Variable::new_var( - LexerState { - line: self.tokens[index + 1].clone().line, - column: self.tokens[index + 1].clone().column, - }, - desc, - ), + LexerState { + line: self.tokens[index + 1].clone().line, + column: self.tokens[index + 1].clone().column, + }, + desc, ); } } diff --git a/src/transpiler.rs b/src/transpiler.rs index ee6089b..a1f1925 100644 --- a/src/transpiler.rs +++ b/src/transpiler.rs @@ -1,9 +1,10 @@ use crate::{ lexer::{lex, LexerState, TokenType}, - parser::{new_vars, Ast, AstType, Parser}, - variable::{Variable, VariableType}, + lspcom::Problem, + parser::{is_decl, Ast, AstType, Parser}, + variable::{VariableType, Variables}, }; -use std::collections::HashMap; + use std::fs; #[derive(Debug, Clone)] @@ -15,7 +16,8 @@ pub struct Transpiler { pub macros: Vec, pub modnum: u32, pub peek: String, - pub matched_vars: HashMap, + pub matched_vars: Variables, + pub problems: Vec, } impl Default for Transpiler { @@ -28,18 +30,14 @@ impl Default for Transpiler { macros: vec![String::from("println")], modnum: 0, peek: String::new(), - matched_vars: HashMap::new(), + matched_vars: Variables::new(), + problems: Vec::new(), } } } impl Transpiler { - pub fn transpile( - &mut self, - input: String, - indent: u32, - variables: HashMap, - ) -> String { + pub fn transpile(&mut self, input: String, indent: u32, variables: Variables) -> String { let mut result = String::new(); if indent == 0 { // result += "type int = i32;\n"; @@ -58,6 +56,7 @@ impl Transpiler { let f_ast = full_ast.parse(); let mut variables = full_ast.variables.clone(); for ast in f_ast { + let mut ast = ast; if ast.ast_type == AstType::Other && ast.tokens[0].token_type == TokenType::Identifier && ast.tokens[0].value.contains(&self.peek) @@ -65,15 +64,28 @@ impl Transpiler { { let ctoken = &ast.tokens[0]; // let pname = ctoken.value.split(&self.peek).next().unwrap(); - for (name, var) in variables.clone() { + for (name, var) in variables.clone().iter_mut() { if (ctoken.line > var.state.line && var.vtype == VariableType::Var) || var.vtype != VariableType::Var { - self.matched_vars.insert(name, var); + self.matched_vars.add( + var.vtype.clone(), + name.to_string(), + var.state, + var.desc.clone(), + ); } } self.peek = String::new(); continue; + } else { + for i in (if is_decl(&ast) { 1 } else { 0 })..ast.tokens.len() { + if ast.tokens[i].token_type == TokenType::Identifier { + if ast.tokens[i].value.contains(&self.peek) && self.peek != "" {} + let x = variables.get_var(ast.tokens[i].value.clone(), self); + ast.tokens[i].value = x; + } + } } if last_ast.tokens.len() > 0 { let mut fl = 0; @@ -100,7 +112,7 @@ impl Transpiler { if self.auto_pub { result += "pub "; } - let mut vars: HashMap = variables.clone(); + let mut vars: Variables = variables.clone(); let round = self.transpile_round(ast.tokens[2].value.clone(), &mut vars); result += format!( "fn {}({}) -> {} {}", @@ -110,27 +122,12 @@ impl Transpiler { self.transpile(ast.tokens[3].value.clone(), indent + 1, vars.clone()) ) .as_str(); - let vvars = variables.clone(); - if let Some(v) = variables.get_mut(&ast.tokens[1].value) { - for (name, var) in vars { - if !(vvars.contains_key(&name)) { - v.params.insert( - name, - Variable::new_var( - LexerState { line: 0, column: 0 }, - var.desc, - ), - ); - } - } - } } else if ast.ast_type == AstType::VoidFunctionDeceleration { if self.auto_pub { result += "pub "; } - let mut vars: HashMap = variables.clone(); + let mut vars: Variables = variables.clone(); let round = self.transpile_round(ast.tokens[2].value.clone(), &mut vars); - // panic!("{:?}", vars); result += format!( "fn {}({}) {}", ast.tokens[1].value, @@ -138,25 +135,11 @@ impl Transpiler { self.transpile(ast.tokens[3].value.clone(), indent + 1, vars.clone()) ) .as_str(); - let vvars = variables.clone(); - if let Some(v) = variables.get_mut(&ast.tokens[1].value) { - for (name, var) in vars { - if !(vvars.contains_key(&name)) { - v.params.insert( - name, - Variable::new_var( - LexerState { line: 0, column: 0 }, - var.desc, - ), - ); - } - } - } } else if ast.ast_type == AstType::StructDeceleration { if self.auto_pub { result += "pub "; } - let mut vars: HashMap = variables.clone(); + let mut vars: Variables = variables.clone(); let round = self.transpile_round(ast.tokens[1].value.clone(), &mut vars); result += format!( "struct {} {} {}", @@ -172,15 +155,13 @@ impl Transpiler { .as_str(); result += "\n}\n"; let vvars = variables.clone(); - if let Some(v) = variables.get_mut(&ast.tokens[0].value) { - for (name, var) in vars { - if !(vvars.contains_key(&name)) { - v.params.insert( - name, - Variable::new_var( - LexerState { line: 0, column: 0 }, - var.desc, - ), + if let Some(v) = variables.get_mut(ast.tokens[0].value.clone()) { + for (name, var) in vars.iter_mut() { + if !(vvars.vars.contains_key(name)) { + v.params.new_var( + name.to_string(), + LexerState { line: 0, column: 0 }, + var.desc.clone(), ); } } @@ -210,6 +191,11 @@ impl Transpiler { ) ) .as_str(); + } else if ast.ast_type == AstType::Other + && ast.tokens[0].token_type == TokenType::Comment + { + result += ast.tokens[0].value.clone().as_str(); + result += " ".repeat((indent as usize) * 2).as_str(); } else if ast.tokens.len() == 1 && ast.tokens[0].token_type == TokenType::Square { result += format!( @@ -230,12 +216,6 @@ impl Transpiler { result += "}"; } else if ast.tokens.len() == 1 && ast.tokens[0].token_type == TokenType::Curly { - // if ast.tokens[0].token_type == TokenType::Newline { - // result += (ast.tokens[0].value.as_str().to_owned() - // + (" ".repeat((indent as usize) * 2).as_str())) - // .as_str(); - // } else { - // result += ast.tokens[0].value.as_str(); result += self .transpile_json( ast.tokens[0].value.as_str().to_string(), @@ -341,6 +321,9 @@ impl Transpiler { ) .as_str(); } + } else if ast.ast_type == AstType::Ref { + result += "&mut "; + result += ast.tokens[0].value.as_str(); } // flp else { @@ -352,17 +335,6 @@ impl Transpiler { result += ";\n"; result += " ".repeat((indent as usize) * 2).as_str(); } else { - // if last_ast.tokens.len() > 0 && ( - // last_ast.tokens[last_ast.tokens.len()-1].token_type == TokenType::Identifier || - // last_ast.tokens[last_ast.tokens.len()-1].token_type == TokenType::Keyword || - // last_ast.tokens[last_ast.tokens.len()-1].token_type == TokenType::Number - // ) { - // let ltkn = last_ast.tokens[last_ast.tokens.len()-1].token_type; - // if ltkn == TokenType::Identifier || - // ltkn == TokenType::Keyword || - // ltkn == TokenType::Number { - // } - // } result += ast.tokens[0].value.as_str(); if self.auto_macro && self @@ -396,7 +368,7 @@ impl Transpiler { self.clone().modnum ); let file_content = fs::read_to_string(s.to_string() + modfile).expect("Error reading file"); - let transpiled_code = self.transpile(file_content, 0, new_vars()); + let transpiled_code = self.transpile(file_content, 0, Variables::new()); fs::write( ("build/".to_string() + modname.as_str()) + ".rs", transpiled_code, @@ -404,11 +376,7 @@ impl Transpiler { .expect("Error writing file"); modname } - pub fn transpile_round( - &mut self, - input: String, - variables: &mut HashMap, - ) -> String { + pub fn transpile_round(&mut self, input: String, variables: &mut Variables) -> String { let mut result = String::new(); let lexer_out = lex(input.as_str(), false, self.state); match lexer_out { @@ -418,8 +386,10 @@ impl Transpiler { ast_type: AstType::Other, tokens: vec![], }; - for ast in full_ast.parse() { - *variables = full_ast.variables.clone(); + let fast = full_ast.parse(); + *variables = full_ast.variables.clone(); + for ast in fast { + let mut ast = ast; if ast.ast_type == AstType::Other && ast.tokens[0].token_type == TokenType::Identifier && ast.tokens[0].value.contains(&self.peek) @@ -427,9 +397,44 @@ impl Transpiler { { let ctoken = &ast.tokens[0]; // let pname = ctoken.value.split(&self.peek).next().unwrap(); - for (name, var) in variables.clone() { + for (name, var) in variables.clone().iter_mut() { + if (ctoken.line > var.state.line && var.vtype == VariableType::Var) + || var.vtype != VariableType::Var + { + self.matched_vars.add( + var.vtype.clone(), + name.to_string(), + var.state, + var.desc.clone(), + ); + } + } + self.peek = String::new(); + continue; + } else { + for i in (if is_decl(&ast) { 1 } else { 0 })..ast.tokens.len() { + if ast.tokens[i].token_type == TokenType::Identifier { + if ast.tokens[i].value.contains(&self.peek) && self.peek != "" {} + let x = variables.get_var(ast.tokens[i].value.clone(), self); + ast.tokens[i].value = x; + } + } + } + if ast.ast_type == AstType::Other + && ast.tokens[0].token_type == TokenType::Identifier + && ast.tokens[0].value.contains(&self.peek) + && self.peek != "" + { + let ctoken = &ast.tokens[0]; + // let pname = ctoken.value.split(&self.peek).next().unwrap(); + for (name, var) in variables.clone().iter_mut() { if ctoken.line > var.state.line || var.vtype != VariableType::Var { - self.matched_vars.insert(name, var); + self.matched_vars.add( + var.vtype.clone(), + name.to_string(), + var.state, + var.desc.clone(), + ); } } self.peek = String::new(); @@ -530,7 +535,7 @@ impl Transpiler { &mut self, input: String, state: LexerState, - variables: HashMap, + variables: Variables, ) -> String { let mut result = String::new(); let lexer_out = lex(input.as_str(), false, state); @@ -541,8 +546,10 @@ impl Transpiler { ast_type: AstType::Other, tokens: vec![], }; - for ast in full_ast.parse() { - let variables = full_ast.variables.clone(); + let fast = full_ast.parse(); + let mut variables = full_ast.variables.clone(); + for ast in fast { + let mut ast = ast; if ast.ast_type == AstType::Other && ast.tokens[0].token_type == TokenType::Identifier && ast.tokens[0].value.contains(&self.peek) @@ -550,9 +557,44 @@ impl Transpiler { { let ctoken = &ast.tokens[0]; // let pname = ctoken.value.split(&self.peek).next().unwrap(); - for (name, var) in variables.clone() { + for (name, var) in variables.clone().iter_mut() { + if (ctoken.line > var.state.line && var.vtype == VariableType::Var) + || var.vtype != VariableType::Var + { + self.matched_vars.add( + var.vtype.clone(), + name.to_string(), + var.state, + var.desc.clone(), + ); + } + } + self.peek = String::new(); + continue; + } else { + for i in (if is_decl(&ast) { 1 } else { 0 })..ast.tokens.len() { + if ast.tokens[i].token_type == TokenType::Identifier { + if ast.tokens[i].value.contains(&self.peek) && self.peek != "" {} + let x = variables.get_var(ast.tokens[i].value.clone(), self); + ast.tokens[i].value = x; + } + } + } + if ast.ast_type == AstType::Other + && ast.tokens[0].token_type == TokenType::Identifier + && ast.tokens[0].value.contains(&self.peek) + && self.peek != "" + { + let ctoken = &ast.tokens[0]; + // let pname = ctoken.value.split(&self.peek).next().unwrap(); + for (name, var) in variables.iter_mut() { if ctoken.line > var.state.line || var.vtype != VariableType::Var { - self.matched_vars.insert(name, var); + self.matched_vars.add( + var.vtype.clone(), + name.to_string(), + var.state, + var.desc.clone(), + ); } } self.peek = String::new(); @@ -628,6 +670,9 @@ impl Transpiler { result += " {"; result += ast.tokens[1].value.as_str(); result += "}"; + } else if ast.ast_type == AstType::Ref { + result += "&mut "; + result += ast.tokens[0].value.as_str(); } // flp else { @@ -648,7 +693,7 @@ impl Transpiler { &mut self, input: String, state: LexerState, - variables: HashMap, + variables: Variables, ) -> String { let mut result = String::new(); let lexer_out = lex(input.as_str(), false, state); @@ -661,8 +706,10 @@ impl Transpiler { ast_type: AstType::Other, tokens: vec![], }; - for ast in full_ast.parse() { - let variables = full_ast.variables.clone(); + let fast = full_ast.parse(); + let mut variables = full_ast.variables.clone(); + for ast in fast { + let mut ast = ast; if ast.ast_type == AstType::Other && ast.tokens[0].token_type == TokenType::Identifier && ast.tokens[0].value.contains(&self.peek) @@ -670,9 +717,44 @@ impl Transpiler { { let ctoken = &ast.tokens[0]; // let pname = ctoken.value.split(&self.peek).next().unwrap(); - for (name, var) in variables.clone() { + for (name, var) in variables.clone().iter_mut() { + if (ctoken.line > var.state.line && var.vtype == VariableType::Var) + || var.vtype != VariableType::Var + { + self.matched_vars.add( + var.vtype.clone(), + name.to_string(), + var.state, + var.desc.clone(), + ); + } + } + self.peek = String::new(); + continue; + } else { + for i in (if is_decl(&ast) { 1 } else { 0 })..ast.tokens.len() { + if ast.tokens[i].token_type == TokenType::Identifier { + if ast.tokens[i].value.contains(&self.peek) && self.peek != "" {} + let x = variables.get_var(ast.tokens[i].value.clone(), self); + ast.tokens[i].value = x; + } + } + } + if ast.ast_type == AstType::Other + && ast.tokens[0].token_type == TokenType::Identifier + && ast.tokens[0].value.contains(&self.peek) + && self.peek != "" + { + let ctoken = &ast.tokens[0]; + // let pname = ctoken.value.split(&self.peek).next().unwrap(); + for (name, var) in variables.iter_mut() { if ctoken.line > var.state.line || var.vtype != VariableType::Var { - self.matched_vars.insert(name, var); + self.matched_vars.add( + var.vtype.clone(), + name.to_string(), + var.state, + var.desc.clone(), + ); } } self.peek = String::new(); @@ -741,6 +823,9 @@ impl Transpiler { variables.clone(), ) .as_str(); + } else if ast.ast_type == AstType::Ref { + result += "&mut "; + result += ast.tokens[0].value.as_str(); } else { result += ast.tokens[0].value.as_str(); } @@ -755,16 +840,3 @@ impl Transpiler { } } } - -// fn clean_incl(input: &str) -> String { -// input -// .chars() -// .map(|c| { -// if c.is_alphanumeric() || c == '_' { -// c -// } else { -// '_' -// } -// }) -// .collect() -// } diff --git a/src/variable.rs b/src/variable.rs index 53cd6d1..0f45336 100644 --- a/src/variable.rs +++ b/src/variable.rs @@ -1,6 +1,12 @@ use std::collections::HashMap; -use crate::lexer::LexerState; +use rand::Rng; + +use crate::{ + lexer::LexerState, + lspcom::{Problem, ProblemType}, + transpiler::Transpiler, +}; #[derive(Clone, PartialEq, Debug)] pub enum VariableType { @@ -16,52 +22,154 @@ pub struct Variable { pub vtype: VariableType, pub desc: String, pub state: LexerState, - pub params: HashMap, + pub params: Variables, + pub rname: String, } -impl Variable { - pub fn new_var(state: LexerState, desc: String) -> Variable { - Variable { - vtype: VariableType::Var, - desc, - state, - params: HashMap::new(), +#[derive(Clone, Debug)] +pub struct Variables { + pub vars: HashMap, +} + +impl Variables { + pub fn new() -> Variables { + Variables { + vars: HashMap::from([( + "void".to_string(), + Variable { + vtype: VariableType::Keyword, + desc: "".to_string(), + state: LexerState { line: 0, column: 0 }, + params: Variables { + vars: HashMap::new(), + }, + rname: "".to_string(), + }, + )]), } } - - pub fn new_namespace(state: LexerState, desc: String) -> Variable { - Variable { - vtype: VariableType::Namespace, - desc, - state, - params: HashMap::new(), - } + pub fn new_var(&mut self, name: String, state: LexerState, desc: String) { + self.vars.insert( + name, + Variable { + vtype: VariableType::Var, + desc, + state, + params: Variables { + vars: HashMap::new(), + }, + rname: generate_varname(), + }, + ); } - pub fn new_struct(state: LexerState, desc: String) -> Variable { - Variable { - vtype: VariableType::Struct, - desc, - state, - params: HashMap::new(), - } + pub fn new_namespace(&mut self, name: String, state: LexerState, desc: String) { + self.vars.insert( + name, + Variable { + vtype: VariableType::Namespace, + desc, + state, + params: Variables { + vars: HashMap::new(), + }, + rname: generate_varname(), + }, + ); } - pub fn new_keyword(state: LexerState, desc: String) -> Variable { - Variable { - vtype: VariableType::Keyword, - desc, - state, - params: HashMap::new(), - } + pub fn new_struct(&mut self, name: String, state: LexerState, desc: String) { + self.vars.insert( + name, + Variable { + vtype: VariableType::Struct, + desc, + state, + params: Variables { + vars: HashMap::new(), + }, + rname: generate_varname(), + }, + ); } - pub fn new_func(state: LexerState, desc: String) -> Variable { - Variable { - vtype: VariableType::Func, - desc, - state, - params: HashMap::new(), + pub fn new_keyword(&mut self, name: String, state: LexerState, desc: String) { + self.vars.insert( + name, + Variable { + vtype: VariableType::Keyword, + desc, + state, + params: Variables { + vars: HashMap::new(), + }, + rname: generate_varname(), + }, + ); + } + + pub fn new_func(&mut self, name: String, state: LexerState, desc: String) { + self.vars.insert( + name, + Variable { + vtype: VariableType::Func, + desc, + state, + params: Variables { + vars: HashMap::new(), + }, + rname: generate_varname(), + }, + ); + } + pub fn add(&mut self, vtype: VariableType, name: String, state: LexerState, desc: String) { + self.vars.insert( + name, + Variable { + vtype, + desc, + state, + params: Variables { + vars: HashMap::new(), + }, + rname: generate_varname(), + }, + ); + } + pub fn get_var(&mut self, name: String, root: &mut Transpiler) -> String { + if let Some(x) = self.get_mut(name.clone()) { + return x.rname.clone(); + } else { + root.problems.push(Problem { + code: 1, + problem_type: ProblemType::VariableNotFound, + problem_msg: format!("Variable '{}' doesn't exist", &name), + }); + return name; } } + pub fn iter_mut( + &mut self, + ) -> std::collections::hash_map::IterMut<'_, std::string::String, Variable> { + self.vars.iter_mut() + } + pub fn get_mut(&mut self, name: String) -> Option<&mut Variable> { + self.vars.get_mut(&name) + } +} + +pub fn generate_varname() -> String { + let mut rng = rand::thread_rng(); + let charset: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ + abcdefghijklmnopqrstuvwxyz\ + 0123456789"; + let mut result = String::with_capacity(19); + result.push('_'); + result.push('0'); + result.push('x'); + for _ in 0..14 { + let random_char = charset[rng.gen_range(0..charset.len())] as char; + result.push(random_char); + } + result }