better variable manager

This commit is contained in:
2024-07-03 17:17:25 +02:00
parent 9b755b1821
commit e3ebe9d8d3
5 changed files with 273 additions and 217 deletions
+6 -5
View File
@@ -1,15 +1,16 @@
use utils::ProblemCap; use utils::{ProblemCap, Variables};
use variable::Variables;
mod parser; mod parser;
mod transpiler; mod transpiler;
mod utils; mod utils;
mod variable;
fn main() { fn main() {
let mut vars = Variables::new(); let mut vars = Variables::new();
let mut trsp = transpiler::Transpiler::default(); let mut trsp = transpiler::Transpiler::default();
let out = trsp.transpile("struct Test {}".to_string(), 0, &mut vars); trsp.inject.inject = true;
trsp.inject.state.line = 2;
trsp.inject.state.column = 2;
let out = trsp.transpile("int x\nx".to_string(), 0, &mut vars);
for p in trsp.problems { for p in trsp.problems {
match p { match p {
ProblemCap::Error(problem) => { ProblemCap::Error(problem) => {
@@ -23,5 +24,5 @@ fn main() {
} }
} }
} }
println!("{out}\n\n\n{:?}", vars); println!("{out}\n\n\n");
} }
+48 -12
View File
@@ -2,8 +2,7 @@ use std::usize;
use crate::{ use crate::{
transpiler::{State, Transpiler}, transpiler::{State, Transpiler},
utils::{Problem, ProblemCap, ProblemType}, utils::{Problem, ProblemCap, ProblemType, Variables},
variable::Variables,
}; };
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@@ -27,10 +26,34 @@ pub fn extract_values(token: Token) -> (String, State) {
} }
} }
pub fn extract_ast(ast: Ast) -> Vec<String> {
let mut vstr: Vec<String> = Vec::new();
match ast {
Ast::Struct(a, _) => {
vstr.push(a);
}
Ast::Single(a) => match a {
Token::Identifier(b, _) => vstr.push(b),
_ => {}
},
Ast::Variable(a, b) => {
vstr.push(a);
vstr.push(b);
}
Ast::Function(a, b, _, _) => {
vstr.push(a);
vstr.push(b);
}
}
vstr
}
#[derive(Clone, Debug)]
pub enum Ast { pub enum Ast {
Variable(String, String), Variable(String, String),
Function(String, String, String, String), Function(String, String, String, String),
Struct(String, String), Struct(String, String),
Single(Token),
} }
pub fn get_token(v: String, t: u32, state: State) -> Token { pub fn get_token(v: String, t: u32, state: State) -> Token {
@@ -48,6 +71,7 @@ pub fn get_token(v: String, t: u32, state: State) -> Token {
pub fn tokenize(code: String, state: &mut State, root: &mut Transpiler) -> Vec<Token> { pub fn tokenize(code: String, state: &mut State, root: &mut Transpiler) -> Vec<Token> {
let mut code = code; let mut code = code;
code += " ";
let mut tokens: Vec<Token> = Vec::new(); let mut tokens: Vec<Token> = Vec::new();
let mut token_value: String = String::new(); let mut token_value: String = String::new();
let mut token_type: u32 = 0; let mut token_type: u32 = 0;
@@ -60,6 +84,12 @@ pub fn tokenize(code: String, state: &mut State, root: &mut Transpiler) -> Vec<T
let mut t: u32 = 0; let mut t: u32 = 0;
let mut ignore = false; let mut ignore = false;
state.column += 1; state.column += 1;
if root.inject.inject
&& root.inject.state.line == state.line
&& root.inject.state.column == state.column
{
token_value += "list_vx";
}
if stoken.1 > 0 { if stoken.1 > 0 {
match c { match c {
'(' => { '(' => {
@@ -184,9 +214,14 @@ pub fn parse(
) -> Vec<Ast> { ) -> Vec<Ast> {
let mut ast: Vec<Ast> = Vec::new(); let mut ast: Vec<Ast> = Vec::new();
let mut tokens = tokenize(code, state, root); let mut tokens = tokenize(code, state, root);
let mut pcon: Vec<(u32, u32)> = Vec::new();
while tokens.len() > 0 { while tokens.len() > 0 {
let mut drain: usize = 1; 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)));
tokens.drain(0..1);
continue;
}
match tokens.as_slice() { match tokens.as_slice() {
[Token::Identifier(var_type, state0), Token::Identifier(var_name, _state1), Token::Round(round, _state2), Token::Curly(curly, _state3), ..] => [Token::Identifier(var_type, state0), Token::Identifier(var_name, _state1), Token::Round(round, _state2), Token::Curly(curly, _state3), ..] =>
{ {
@@ -221,15 +256,16 @@ pub fn parse(
drain += 2; drain += 2;
} }
x => { x => {
let estate = extract_values(x[0].clone()).1; ast.push(Ast::Single(x[0].clone()));
if !pcon.contains(&(estate.line, estate.column)) { //let estate = extract_values(x[0].clone()).1;
root.problems.push(ProblemCap::Error(Problem { //if !pcon.contains(&(estate.line, estate.column)) {
problem_msg: format!("Invalid placement"), // root.problems.push(ProblemCap::Error(Problem {
problem_type: ProblemType::SyntaxError, // problem_msg: format!("Invalid placement"),
state: estate, // problem_type: ProblemType::SyntaxError,
})); // state: estate,
pcon.push((root.state.line, root.state.column)); // }));
} // pcon.push((root.state.line, root.state.column));
//}
} }
} }
tokens.drain(0..drain); tokens.drain(0..drain);
+33 -7
View File
@@ -1,7 +1,6 @@
use crate::{ use crate::{
parser::{self, Ast}, parser::{self, extract_ast, Ast},
utils::ProblemCap, utils::{ProblemCap, VariableType, Variables},
variable::Variables,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -14,18 +13,30 @@ pub struct State {
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Transpiler { pub struct Transpiler {
pub matched_vars: Variables, pub matched_vars: Variables,
pub peek: String,
// pub libmgr: LibManager,
pub problems: Vec<ProblemCap>, pub problems: Vec<ProblemCap>,
pub state: State, pub state: State,
pub inject: Inject,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Inject {
pub state: State,
pub inject: bool,
}
impl Default for Inject {
fn default() -> Self {
Inject {
inject: false,
state: State { line: 0, column: 0 },
}
}
} }
impl Default for Transpiler { impl Default for Transpiler {
fn default() -> Self { fn default() -> Self {
Transpiler { Transpiler {
matched_vars: Variables::new(), matched_vars: Variables::new(),
peek: String::new(), inject: Inject::default(),
// libmgr: LibManager::new(".".to_string()),
problems: Vec::new(), problems: Vec::new(),
state: State { line: 1, column: 0 }, state: State { line: 1, column: 0 },
} }
@@ -40,6 +51,20 @@ impl Transpiler {
res += " ".repeat(indent * 2).as_str(); res += " ".repeat(indent * 2).as_str();
} }
for a in ast { for a in ast {
let astval = extract_ast(a.clone());
if self.inject.inject {
for val in astval {
if val.contains("list_vx") {
for (name, var) in vars.clone().iter_mut() {
if self.inject.state.line > var.state.line
|| var.vtype != VariableType::Var
{
self.matched_vars.vars.insert(name.clone(), var.clone());
}
}
}
}
}
match a { match a {
Ast::Variable(var_type, var_name) => { Ast::Variable(var_type, var_name) => {
res += format!("let mut {}: {}", var_name, var_type).as_str(); res += format!("let mut {}: {}", var_name, var_type).as_str();
@@ -66,6 +91,7 @@ impl Transpiler {
) )
.as_str() .as_str()
} }
Ast::Single(_) => {}
} }
} }
if indent > 0 { if indent > 0 {
+186 -2
View File
@@ -1,6 +1,8 @@
use serde::{Deserialize, Serialize};
use crate::transpiler::State; use crate::transpiler::State;
use crate::transpiler::Transpiler;
use rand::Rng;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ProblemType { pub enum ProblemType {
@@ -22,3 +24,185 @@ pub struct Problem {
pub problem_msg: String, pub problem_msg: String,
pub state: State, pub state: State,
} }
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
pub enum VariableType {
Var,
Func,
Keyword,
Struct,
Namespace,
Enum,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Variable {
pub vtype: VariableType,
pub desc: String,
pub state: State,
pub params: Variables,
pub rname: String,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Variables {
pub vars: HashMap<String, Variable>,
}
impl Variables {
pub fn new() -> Variables {
Variables {
vars: HashMap::from([(
"void".to_string(),
Variable {
vtype: VariableType::Keyword,
desc: "".to_string(),
state: State { line: 0, column: 0 },
params: Variables {
vars: HashMap::new(),
},
rname: "".to_string(),
},
)]),
}
}
pub fn new_var(&mut self, name: String, state: State, desc: String) -> String {
let rname = generate_varname();
self.vars.insert(
name,
Variable {
vtype: VariableType::Var,
desc,
state,
params: Variables {
vars: HashMap::new(),
},
rname: rname.clone(),
},
);
rname
}
pub fn new_namespace(&mut self, name: String, state: State, desc: String) -> String {
let rname = generate_varname();
self.vars.insert(
name,
Variable {
vtype: VariableType::Namespace,
desc,
state,
params: Variables {
vars: HashMap::new(),
},
rname: rname.clone(),
},
);
rname
}
pub fn new_struct(&mut self, name: String, state: State, desc: String) -> String {
let rname = generate_varname();
self.vars.insert(
name,
Variable {
vtype: VariableType::Struct,
desc,
state,
params: Variables {
vars: HashMap::new(),
},
rname: rname.clone(),
},
);
rname
}
pub fn new_enum(&mut self, name: String, state: State, desc: String) -> String {
let rname = generate_varname();
self.vars.insert(
name,
Variable {
vtype: VariableType::Enum,
desc,
state,
params: Variables {
vars: HashMap::new(),
},
rname: rname.clone(),
},
);
rname
}
// pub fn new_keyword(&mut self, name: String, state: State, 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: State, desc: String) -> String {
let rname = generate_varname();
self.vars.insert(
name,
Variable {
vtype: VariableType::Func,
desc,
state,
params: Variables {
vars: HashMap::new(),
},
rname: rname.clone(),
},
);
rname
}
pub fn get_var(&mut self, name: String, root: &mut Transpiler, state: State) -> String {
if let Some(x) = self.get_mut(name.clone()) {
return x.rname.clone();
} else {
root.problems.push(ProblemCap::Error(Problem {
problem_type: ProblemType::VariableNotFound,
problem_msg: format!("Variable '{}' doesn't exist", &name),
state: state,
}));
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 expand(&mut self, vars: Variables) {
for (x, y) in vars.vars {
self.vars.insert(x, y);
}
}
}
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
}
-191
View File
@@ -1,191 +0,0 @@
use std::collections::HashMap;
use rand::Rng;
use serde::{Deserialize, Serialize};
use crate::{
transpiler::{State, Transpiler},
utils::{Problem, ProblemCap, ProblemType},
};
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
pub enum VariableType {
Var,
Func,
Keyword,
Struct,
Namespace,
Enum,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Variable {
pub vtype: VariableType,
pub desc: String,
pub state: State,
pub params: Variables,
pub rname: String,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Variables {
pub vars: HashMap<String, Variable>,
}
impl Variables {
pub fn new() -> Variables {
Variables {
vars: HashMap::from([(
"void".to_string(),
Variable {
vtype: VariableType::Keyword,
desc: "".to_string(),
state: State { line: 0, column: 0 },
params: Variables {
vars: HashMap::new(),
},
rname: "".to_string(),
},
)]),
}
}
pub fn new_var(&mut self, name: String, state: State, desc: String) -> String {
let rname = generate_varname();
self.vars.insert(
name,
Variable {
vtype: VariableType::Var,
desc,
state,
params: Variables {
vars: HashMap::new(),
},
rname: rname.clone(),
},
);
rname
}
pub fn new_namespace(&mut self, name: String, state: State, desc: String) -> String {
let rname = generate_varname();
self.vars.insert(
name,
Variable {
vtype: VariableType::Namespace,
desc,
state,
params: Variables {
vars: HashMap::new(),
},
rname: rname.clone(),
},
);
rname
}
pub fn new_struct(&mut self, name: String, state: State, desc: String) -> String {
let rname = generate_varname();
self.vars.insert(
name,
Variable {
vtype: VariableType::Struct,
desc,
state,
params: Variables {
vars: HashMap::new(),
},
rname: rname.clone(),
},
);
rname
}
pub fn new_enum(&mut self, name: String, state: State, desc: String) -> String {
let rname = generate_varname();
self.vars.insert(
name,
Variable {
vtype: VariableType::Enum,
desc,
state,
params: Variables {
vars: HashMap::new(),
},
rname: rname.clone(),
},
);
rname
}
// pub fn new_keyword(&mut self, name: String, state: State, 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: State, desc: String) -> String {
let rname = generate_varname();
self.vars.insert(
name,
Variable {
vtype: VariableType::Func,
desc,
state,
params: Variables {
vars: HashMap::new(),
},
rname: rname.clone(),
},
);
rname
}
pub fn get_var(&mut self, name: String, root: &mut Transpiler, state: State) -> String {
if let Some(x) = self.get_mut(name.clone()) {
return x.rname.clone();
} else {
root.problems.push(ProblemCap::Error(Problem {
problem_type: ProblemType::VariableNotFound,
problem_msg: format!("Variable '{}' doesn't exist", &name),
state: state,
}));
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 expand(&mut self, vars: Variables) {
for (x, y) in vars.vars {
self.vars.insert(x, y);
}
}
}
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
}