Added rust imports with header

This commit is contained in:
2024-06-23 17:53:46 +02:00
parent 9a614ef367
commit 15e0ff362c
10 changed files with 306 additions and 64 deletions
+3
View File
@@ -2,6 +2,9 @@
# will have compiled files and executables # will have compiled files and executables
debug/ debug/
target/ target/
test/
.vscode/
.idea/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
+1
View File
@@ -15,3 +15,4 @@ serde = "1.0.203"
serde_derive = "1.0.203" serde_derive = "1.0.203"
lsp-types = "0.97.0" lsp-types = "0.97.0"
zip = "2.1.3" zip = "2.1.3"
dirs = "5.0.1"
+76
View File
@@ -0,0 +1,76 @@
use regex::Regex;
use std::fs;
use std::io::Write;
use std::{
fs::File,
io::{BufReader, Read},
};
use zip::{write::SimpleFileOptions, ZipArchive, ZipWriter};
use crate::variable::Variables;
pub fn read_dll(dll_path: String) -> Variables {
let mut vars = Variables::new();
let dll_file = File::open(dll_path).expect("err_dll_read");
let dll_reader = BufReader::new(dll_file);
let mut dll_zip = ZipArchive::new(dll_reader).expect("err_archive");
for i in 0..dll_zip.len() {
let mut buf = Vec::new();
let mut file = dll_zip.by_index(i).expect("err_dll_idx");
let filename = file.name();
if filename == "map.json" && file.is_file() {
file.read_to_end(&mut buf).expect("err_read_zip_file");
println!(
"Filename: {}\nFileContents: {}",
file.name(),
String::from_utf8_lossy(&buf)
);
}
}
vars
}
pub fn write_dll(vars: Variables, exe_path: String, dll_path: String) {
let dll_file = File::create(&dll_path).expect("Err_DllCREATE");
let mut dll = ZipWriter::new(dll_file);
dll.start_file("run", SimpleFileOptions::default())
.expect("ERR_STARTFILE_RUN");
let buf_vec = fs::read(exe_path).expect("ERR_READ_EXE");
let buf_u8: &[u8] = buf_vec.as_slice();
dll.write_all(buf_u8).expect("ERR_DLL_EXEWRITE");
dll.start_file("map.json", SimpleFileOptions::default())
.expect("ERR_STARTFILE_MAP");
let json_data = serde_json::to_string(&vars.vars).expect("ERR_MAP_JSON");
dll.write_all(json_data.as_bytes())
.expect("ERR_DLL_JSONWRITE");
println!("{:?}", serde_json::to_string(&vars.vars));
}
pub struct HeaderConfig {
pub file_path: String,
pub map_path: String,
}
impl HeaderConfig {
// Function to parse the input string
pub fn new(input: String) -> Option<Self> {
let re = Regex::new(r#"FILE_PATH\s*=\s*"([^"]*)""#).expect("ERR_REGEX_HDR");
let re1 = Regex::new(r#"MAP_PATH\s*=\s*"([^"]*)""#).expect("ERR_REGEX_HDR1");
let mut fp: String = String::new();
let mut mp: String = String::new();
if let Some(caps) = re.captures(input.as_str()) {
fp = caps.get(1)?.as_str().to_string();
} else {
return None;
}
if let Some(caps) = re1.captures(input.as_str()) {
mp = caps.get(1)?.as_str().to_string();
} else {
return None;
}
return Some(HeaderConfig {
file_path: fp,
map_path: mp,
});
}
}
+130 -8
View File
@@ -1,6 +1,34 @@
use std::fs; use std::{collections::HashMap, fs, path::Path};
use crate::{dllmgr::read_dll, transpiler::Transpiler, variable::Variables}; use dirs::home_dir;
use crate::{
dllmgr::{read_dll, HeaderConfig},
lspcom::{Problem, ProblemType},
transpiler::Transpiler,
variable::{Variable, Variables},
};
fn join_directories(dir1: &str, dir2: &str) -> String {
let mut main_seperator = '/';
if cfg!(windows) {
main_seperator = '\\';
}
let mut result = dir1.to_string();
if !result.ends_with(main_seperator) {
result.push(main_seperator);
}
let dir2_trimmed = if dir2.starts_with(main_seperator) {
&dir2[1..]
} else {
dir2
};
result.push_str(dir2_trimmed);
result
}
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Module { pub struct Module {
@@ -45,14 +73,41 @@ impl FileWriter {
self.files.push(module); self.files.push(module);
} }
} }
pub fn add(&mut self, filepath: String, variables: &mut Variables) -> String { pub fn add(
if filepath.ends_with(".dll") { &mut self,
read_dll(filepath.clone()); filepath: String,
return "xyz".to_string(); variables: &mut Variables,
global: bool,
) -> Result<String, Problem> {
let mut filepath = filepath;
if global {
let homedir_ = home_dir().expect("Err_HOMEDIR_NOTFOUND");
let homedir = homedir_.to_str().expect("ERR_HOMEDIR_STR");
let gdir = join_directories(&homedir, &join_directories("wyst", "lib"));
let lpath = join_directories("lib", &filepath);
let gpath = join_directories(&gdir, &filepath);
if Path::new(&lpath).exists() {
filepath = lpath;
} else if Path::new(&gpath).exists() {
filepath = gpath;
} else {
return Err(Problem {
problem_type: ProblemType::FileNotFound,
problem_msg: format!("failed to import {}: Not found", filepath),
});
}
}
if !Path::new(&filepath).exists() {
return Err(Problem {
problem_type: ProblemType::FileNotFound,
problem_msg: format!("failed to import {}: Not found", filepath),
});
} }
if let Some(module) = self.check(filepath.clone()) { if let Some(module) = self.check(filepath.clone()) {
return module.mod_rs.clone(); return Ok(module.mod_rs.clone());
} }
match filepath.rsplit_once('.').expect("Err_SPLIT").1 {
"wt" => {
let mut trsp = Transpiler { let mut trsp = Transpiler {
writer: self.clone(), writer: self.clone(),
..Default::default() ..Default::default()
@@ -70,6 +125,73 @@ impl FileWriter {
self.files.push(module.clone()); self.files.push(module.clone());
self.expand(trsp.writer); self.expand(trsp.writer);
variables.expand(vars); variables.expand(vars);
return module.mod_rs; self.mod_num += 1;
Ok(module.mod_rs)
}
"h" => {
let hdr_code = fs::read_to_string(filepath.clone()).expect("failed to read");
let mut parent = String::new();
match Path::new(&filepath).parent() {
Some(p) => parent = format!("{}", p.display()),
None => {}
};
match HeaderConfig::new(hdr_code) {
Some(hdrcnf) => {
let file_path = Path::new(&parent).join(hdrcnf.file_path.clone());
let map_path = Path::new(&parent).join(hdrcnf.map_path.clone());
match fs::read_to_string(file_path) {
Ok(code) => match fs::read_to_string(map_path) {
Ok(map_string) => {
let map: HashMap<String, Variable> =
serde_json::from_str(&map_string)
.expect(format!("err_hdr.map: {}", filepath).as_str());
let vars = Variables { vars: map };
let module = Module {
file_ws: filepath,
mod_rs: format!("mod_{}", self.mod_num),
file_rs: format!("build/mod_{}.rs", self.mod_num),
_code: code.clone(),
code_rs: code,
};
self.files.push(module.clone());
variables.expand(vars);
Ok(module.mod_rs)
}
Err(_) => Err(Problem {
problem_type: ProblemType::FileNotFound,
problem_msg: format!(
"failed to import {}: Not found",
hdrcnf.map_path
),
}),
},
Err(_) => Err(Problem {
problem_type: ProblemType::FileNotFound,
problem_msg: format!(
"failed to import {}: Not found",
hdrcnf.file_path
),
}),
}
}
None => Err(Problem {
problem_type: ProblemType::HeaderSyntaxError,
problem_msg: format!("failed to deserialize"),
}),
}
}
"dll" => {
read_dll(filepath.clone());
return Ok("xyz".to_string());
}
"rs" => Err(Problem {
problem_type: ProblemType::FileNotFound,
problem_msg: format!("failed to import {}: Not found", filepath),
}),
_ => Err(Problem {
problem_type: ProblemType::FileNotFound,
problem_msg: format!("failed to import {}: Not found", filepath),
}),
}
} }
} }
+8 -3
View File
@@ -1,8 +1,8 @@
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use regex::Regex; use regex::Regex;
use serde::Serialize; use serde::{Deserialize, Serialize};
use std::fmt; use std::fmt;
#[derive(Debug, PartialEq, Clone, Copy, Serialize)] #[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize)]
pub struct LexerState { pub struct LexerState {
pub line: usize, pub line: usize,
pub column: usize, pub column: usize,
@@ -29,6 +29,7 @@ pub enum TokenType {
Include, Include,
String, String,
Comment, Comment,
StaticExecution,
// EOF, // EOF,
} }
@@ -64,7 +65,7 @@ pub struct Node {
token_regex: Lazy<Regex>, token_regex: Lazy<Regex>,
} }
const SYNTAX: [Node; 16] = [ const SYNTAX: [Node; 17] = [
Node { Node {
token_type: TokenType::Semicolon, token_type: TokenType::Semicolon,
token_regex: Lazy::new(|| Regex::new(r"^\;").unwrap()), token_regex: Lazy::new(|| Regex::new(r"^\;").unwrap()),
@@ -133,6 +134,10 @@ const SYNTAX: [Node; 16] = [
token_type: TokenType::Include, token_type: TokenType::Include,
token_regex: Lazy::new(|| Regex::new(r#"^#include *"(.*?)""#).unwrap()), token_regex: Lazy::new(|| Regex::new(r#"^#include *"(.*?)""#).unwrap()),
}, },
Node {
token_type: TokenType::StaticExecution,
token_regex: Lazy::new(|| Regex::new(r"^#").unwrap()),
},
]; ];
fn get_first_char(value: &str) -> String { fn get_first_char(value: &str) -> String {
+3 -1
View File
@@ -103,11 +103,13 @@ pub fn get_items(mut items: Variables, lname: String) -> Vec<CompletionItem> {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum ProblemType { pub enum ProblemType {
VariableNotFound, VariableNotFound,
FileNotFound,
HeaderSyntaxError,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Problem { pub struct Problem {
pub code: u32, //pub code: u32,
pub problem_type: ProblemType, pub problem_type: ProblemType,
pub problem_msg: String, pub problem_msg: String,
} }
+15 -5
View File
@@ -10,7 +10,7 @@ mod variable;
use clap::Parser; use clap::Parser;
use std::{fs, path::Path}; use std::{fs, path::Path};
use transpiler::Transpiler; use transpiler::Transpiler;
use variable::{Variable, Variables}; use variable::{Variable, VariableType, Variables};
use crate::lsp::run_lsp_server; use crate::lsp::run_lsp_server;
@@ -50,8 +50,11 @@ fn main() {
transpiled_code += "std::process::exit("; transpiled_code += "std::process::exit(";
transpiled_code += vars.get_var("main".to_string(), &mut trsp).as_str(); transpiled_code += vars.get_var("main".to_string(), &mut trsp).as_str();
transpiled_code += "())}"; transpiled_code += "())}";
for problem in trsp.problems { for problem in &trsp.problems {
println!("{}", problem.problem_msg) println!("{:?}: {}", problem.problem_type, problem.problem_msg)
}
if trsp.problems.len() > 0 {
return;
} }
trsp.writer.write(); trsp.writer.write();
@@ -81,9 +84,15 @@ fn main() {
println!("{}", problem.problem_msg) println!("{}", problem.problem_msg)
} }
trsp.writer.write(); trsp.writer.write();
let mut dll_main = String::from("fn call_fn(params: Vec<Param>){"); let mut dll_main = String::from(
"mod wslib;use wslib::*;\nfn call_fn(fn_name: &str, params: Vec<Param>)->i32{match fn_name {",
);
for (name, var) in vars.vars.clone() { for (name, var) in vars.vars.clone() {
if var.vtype != VariableType::Func {
continue;
}
let mut dparams = String::new(); let mut dparams = String::new();
println!("{:?}", var.params.vars);
for i in 0..var.params.vars.len() { for i in 0..var.params.vars.len() {
dparams += format!("params.get({}).expect(\"Err_prms\"),", i).as_str(); dparams += format!("params.get({}).expect(\"Err_prms\"),", i).as_str();
} }
@@ -93,7 +102,8 @@ fn main() {
) )
.as_str(); .as_str();
} }
dll_main += "}"; dll_main += "}}\nfn main(){}";
//dll_main = "fn main(){}".to_string();
compile::write_to_rust_file(&transpiled_code, "build/wslib.rs") compile::write_to_rust_file(&transpiled_code, "build/wslib.rs")
.expect("Error writing to temporary Rust file"); .expect("Error writing to temporary Rust file");
compile::write_to_rust_file(&dll_main, "build/main.rs") compile::write_to_rust_file(&dll_main, "build/main.rs")
+7
View File
@@ -25,6 +25,7 @@ pub enum AstType {
CodeBlock, CodeBlock,
Json, Json,
Impl, Impl,
StaticExecution,
Other, Other,
} }
@@ -345,6 +346,12 @@ impl Parser {
ast_res.tokens.push(token.clone()); ast_res.tokens.push(token.clone());
} }
} }
TokenType::StaticExecution => {
if self.tokens[index + 1].token_type == TokenType::Square {
ast_res.tokens.push(self.tokens[index + 1].clone());
ast_res.ast_type = AstType::StaticExecution;
}
}
_ => { _ => {
ast_res.tokens.push(token.clone()); ast_res.tokens.push(token.clone());
} }
+29 -12
View File
@@ -1,7 +1,7 @@
use crate::{ use crate::{
file_writer::FileWriter, file_writer::FileWriter,
lexer::{lex, LexerState, TokenType}, lexer::{lex, LexerState, TokenType},
lspcom::Problem, lspcom::{Problem, ProblemType},
parser::{is_decl, Ast, AstType, Parser}, parser::{is_decl, Ast, AstType, Parser},
variable::{VariableType, Variables}, variable::{VariableType, Variables},
}; };
@@ -260,30 +260,39 @@ impl Transpiler {
) )
.as_str(); .as_str();
} else if ast.ast_type == AstType::Include { } else if ast.ast_type == AstType::Include {
let modname = self.writer.add( match self
Path::new("lib") .writer
.join(&ast.tokens[0].value.clone()) .add(ast.tokens[0].value.clone(), variables, true)
.to_str() {
.expect("ErrConvStr0") Ok(modname) => {
.to_string(),
variables,
);
result += "mod "; result += "mod ";
result += modname.as_str(); result += modname.as_str();
result += ";\n"; result += ";\n";
result += "use "; result += "use ";
result += modname.as_str(); result += modname.as_str();
result += "::*;\n"; result += "::*;\n";
self.modnum += 1; }
Err(ptype) => {
self.problems.push(ptype);
}
}
} else if ast.ast_type == AstType::IncludeLocal { } else if ast.ast_type == AstType::IncludeLocal {
let modname = self.writer.add(ast.tokens[0].value.clone(), variables); match self
.writer
.add(ast.tokens[0].value.clone(), variables, false)
{
Ok(modname) => {
result += "mod "; result += "mod ";
result += modname.as_str(); result += modname.as_str();
result += ";\n"; result += ";\n";
result += "use "; result += "use ";
result += modname.as_str(); result += modname.as_str();
result += "::*;\n"; result += "::*;\n";
self.modnum += 1; }
Err(ptype) => {
self.problems.push(ptype);
}
}
} else if ast.ast_type == AstType::State3 { } else if ast.ast_type == AstType::State3 {
result += format!( result += format!(
"{} {} {}", "{} {} {}",
@@ -342,6 +351,14 @@ impl Transpiler {
) )
.as_str(); .as_str();
} }
} else if ast.ast_type == AstType::StaticExecution {
result += r#"use serde::Deserialize;
use serde_json::Value;
#[derive(Deserialize, Debug)]
struct Request(i32, String, Vec<(bool, Value)>);
#[derive(Deserialize, Debug)]
struct Response(i32, Vec<(bool, Value)>);
"#;
} else if ast.ast_type == AstType::Ref { } else if ast.ast_type == AstType::Ref {
result += "&mut "; result += "&mut ";
result += ast.tokens[0].value.as_str(); result += ast.tokens[0].value.as_str();
+4 -5
View File
@@ -1,7 +1,7 @@
use std::collections::HashMap; use std::collections::HashMap;
use rand::Rng; use rand::Rng;
use serde::Serialize; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
lexer::LexerState, lexer::LexerState,
@@ -9,7 +9,7 @@ use crate::{
transpiler::Transpiler, transpiler::Transpiler,
}; };
#[derive(Clone, PartialEq, Debug, Serialize)] #[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
pub enum VariableType { pub enum VariableType {
Var, Var,
Func, Func,
@@ -18,7 +18,7 @@ pub enum VariableType {
Namespace, Namespace,
} }
#[derive(Clone, Debug, Serialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Variable { pub struct Variable {
pub vtype: VariableType, pub vtype: VariableType,
pub desc: String, pub desc: String,
@@ -27,7 +27,7 @@ pub struct Variable {
pub rname: String, pub rname: String,
} }
#[derive(Clone, Debug, Serialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Variables { pub struct Variables {
pub vars: HashMap<String, Variable>, pub vars: HashMap<String, Variable>,
} }
@@ -142,7 +142,6 @@ impl Variables {
return x.rname.clone(); return x.rname.clone();
} else { } else {
root.problems.push(Problem { root.problems.push(Problem {
code: 1,
problem_type: ProblemType::VariableNotFound, problem_type: ProblemType::VariableNotFound,
problem_msg: format!("Variable '{}' doesn't exist", &name), problem_msg: format!("Variable '{}' doesn't exist", &name),
}); });