Added rust imports with header
This commit is contained in:
@@ -2,6 +2,9 @@
|
||||
# will have compiled files and executables
|
||||
debug/
|
||||
target/
|
||||
test/
|
||||
.vscode/
|
||||
.idea/
|
||||
|
||||
# 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
|
||||
|
||||
@@ -15,3 +15,4 @@ serde = "1.0.203"
|
||||
serde_derive = "1.0.203"
|
||||
lsp-types = "0.97.0"
|
||||
zip = "2.1.3"
|
||||
dirs = "5.0.1"
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
}
|
||||
+147
-25
@@ -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)]
|
||||
pub struct Module {
|
||||
@@ -45,31 +73,125 @@ impl FileWriter {
|
||||
self.files.push(module);
|
||||
}
|
||||
}
|
||||
pub fn add(&mut self, filepath: String, variables: &mut Variables) -> String {
|
||||
if filepath.ends_with(".dll") {
|
||||
read_dll(filepath.clone());
|
||||
return "xyz".to_string();
|
||||
pub fn add(
|
||||
&mut self,
|
||||
filepath: 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()) {
|
||||
return module.mod_rs.clone();
|
||||
return Ok(module.mod_rs.clone());
|
||||
}
|
||||
match filepath.rsplit_once('.').expect("Err_SPLIT").1 {
|
||||
"wt" => {
|
||||
let mut trsp = Transpiler {
|
||||
writer: self.clone(),
|
||||
..Default::default()
|
||||
};
|
||||
let mut vars = Variables::new();
|
||||
let code = fs::read_to_string(filepath.clone()).expect("failed to read");
|
||||
let code_rs = trsp.transpile(code.clone(), 0, &mut vars);
|
||||
let module = Module {
|
||||
file_ws: filepath,
|
||||
mod_rs: format!("mod_{}", self.mod_num),
|
||||
file_rs: format!("build/mod_{}.rs", self.mod_num),
|
||||
_code: code,
|
||||
code_rs,
|
||||
};
|
||||
self.files.push(module.clone());
|
||||
self.expand(trsp.writer);
|
||||
variables.expand(vars);
|
||||
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),
|
||||
}),
|
||||
}
|
||||
let mut trsp = Transpiler {
|
||||
writer: self.clone(),
|
||||
..Default::default()
|
||||
};
|
||||
let mut vars = Variables::new();
|
||||
let code = fs::read_to_string(filepath.clone()).expect("failed to read");
|
||||
let code_rs = trsp.transpile(code.clone(), 0, &mut vars);
|
||||
let module = Module {
|
||||
file_ws: filepath,
|
||||
mod_rs: format!("mod_{}", self.mod_num),
|
||||
file_rs: format!("build/mod_{}.rs", self.mod_num),
|
||||
_code: code,
|
||||
code_rs,
|
||||
};
|
||||
self.files.push(module.clone());
|
||||
self.expand(trsp.writer);
|
||||
variables.expand(vars);
|
||||
return module.mod_rs;
|
||||
}
|
||||
}
|
||||
|
||||
+8
-3
@@ -1,8 +1,8 @@
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
#[derive(Debug, PartialEq, Clone, Copy, Serialize)]
|
||||
#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize)]
|
||||
pub struct LexerState {
|
||||
pub line: usize,
|
||||
pub column: usize,
|
||||
@@ -29,6 +29,7 @@ pub enum TokenType {
|
||||
Include,
|
||||
String,
|
||||
Comment,
|
||||
StaticExecution,
|
||||
// EOF,
|
||||
}
|
||||
|
||||
@@ -64,7 +65,7 @@ pub struct Node {
|
||||
token_regex: Lazy<Regex>,
|
||||
}
|
||||
|
||||
const SYNTAX: [Node; 16] = [
|
||||
const SYNTAX: [Node; 17] = [
|
||||
Node {
|
||||
token_type: TokenType::Semicolon,
|
||||
token_regex: Lazy::new(|| Regex::new(r"^\;").unwrap()),
|
||||
@@ -133,6 +134,10 @@ const SYNTAX: [Node; 16] = [
|
||||
token_type: TokenType::Include,
|
||||
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 {
|
||||
|
||||
+3
-1
@@ -103,11 +103,13 @@ pub fn get_items(mut items: Variables, lname: String) -> Vec<CompletionItem> {
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ProblemType {
|
||||
VariableNotFound,
|
||||
FileNotFound,
|
||||
HeaderSyntaxError,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Problem {
|
||||
pub code: u32,
|
||||
//pub code: u32,
|
||||
pub problem_type: ProblemType,
|
||||
pub problem_msg: String,
|
||||
}
|
||||
|
||||
+15
-5
@@ -10,7 +10,7 @@ mod variable;
|
||||
use clap::Parser;
|
||||
use std::{fs, path::Path};
|
||||
use transpiler::Transpiler;
|
||||
use variable::{Variable, Variables};
|
||||
use variable::{Variable, VariableType, Variables};
|
||||
|
||||
use crate::lsp::run_lsp_server;
|
||||
|
||||
@@ -50,8 +50,11 @@ fn main() {
|
||||
transpiled_code += "std::process::exit(";
|
||||
transpiled_code += vars.get_var("main".to_string(), &mut trsp).as_str();
|
||||
transpiled_code += "())}";
|
||||
for problem in trsp.problems {
|
||||
println!("{}", problem.problem_msg)
|
||||
for problem in &trsp.problems {
|
||||
println!("{:?}: {}", problem.problem_type, problem.problem_msg)
|
||||
}
|
||||
if trsp.problems.len() > 0 {
|
||||
return;
|
||||
}
|
||||
trsp.writer.write();
|
||||
|
||||
@@ -81,9 +84,15 @@ fn main() {
|
||||
println!("{}", problem.problem_msg)
|
||||
}
|
||||
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() {
|
||||
if var.vtype != VariableType::Func {
|
||||
continue;
|
||||
}
|
||||
let mut dparams = String::new();
|
||||
println!("{:?}", var.params.vars);
|
||||
for i in 0..var.params.vars.len() {
|
||||
dparams += format!("params.get({}).expect(\"Err_prms\"),", i).as_str();
|
||||
}
|
||||
@@ -93,7 +102,8 @@ fn main() {
|
||||
)
|
||||
.as_str();
|
||||
}
|
||||
dll_main += "}";
|
||||
dll_main += "}}\nfn main(){}";
|
||||
//dll_main = "fn main(){}".to_string();
|
||||
compile::write_to_rust_file(&transpiled_code, "build/wslib.rs")
|
||||
.expect("Error writing to temporary Rust file");
|
||||
compile::write_to_rust_file(&dll_main, "build/main.rs")
|
||||
|
||||
@@ -25,6 +25,7 @@ pub enum AstType {
|
||||
CodeBlock,
|
||||
Json,
|
||||
Impl,
|
||||
StaticExecution,
|
||||
Other,
|
||||
}
|
||||
|
||||
@@ -345,6 +346,12 @@ impl Parser {
|
||||
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());
|
||||
}
|
||||
|
||||
+41
-24
@@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
file_writer::FileWriter,
|
||||
lexer::{lex, LexerState, TokenType},
|
||||
lspcom::Problem,
|
||||
lspcom::{Problem, ProblemType},
|
||||
parser::{is_decl, Ast, AstType, Parser},
|
||||
variable::{VariableType, Variables},
|
||||
};
|
||||
@@ -260,30 +260,39 @@ impl Transpiler {
|
||||
)
|
||||
.as_str();
|
||||
} else if ast.ast_type == AstType::Include {
|
||||
let modname = self.writer.add(
|
||||
Path::new("lib")
|
||||
.join(&ast.tokens[0].value.clone())
|
||||
.to_str()
|
||||
.expect("ErrConvStr0")
|
||||
.to_string(),
|
||||
variables,
|
||||
);
|
||||
result += "mod ";
|
||||
result += modname.as_str();
|
||||
result += ";\n";
|
||||
result += "use ";
|
||||
result += modname.as_str();
|
||||
result += "::*;\n";
|
||||
self.modnum += 1;
|
||||
match self
|
||||
.writer
|
||||
.add(ast.tokens[0].value.clone(), variables, true)
|
||||
{
|
||||
Ok(modname) => {
|
||||
result += "mod ";
|
||||
result += modname.as_str();
|
||||
result += ";\n";
|
||||
result += "use ";
|
||||
result += modname.as_str();
|
||||
result += "::*;\n";
|
||||
}
|
||||
Err(ptype) => {
|
||||
self.problems.push(ptype);
|
||||
}
|
||||
}
|
||||
} else if ast.ast_type == AstType::IncludeLocal {
|
||||
let modname = self.writer.add(ast.tokens[0].value.clone(), variables);
|
||||
result += "mod ";
|
||||
result += modname.as_str();
|
||||
result += ";\n";
|
||||
result += "use ";
|
||||
result += modname.as_str();
|
||||
result += "::*;\n";
|
||||
self.modnum += 1;
|
||||
match self
|
||||
.writer
|
||||
.add(ast.tokens[0].value.clone(), variables, false)
|
||||
{
|
||||
Ok(modname) => {
|
||||
result += "mod ";
|
||||
result += modname.as_str();
|
||||
result += ";\n";
|
||||
result += "use ";
|
||||
result += modname.as_str();
|
||||
result += "::*;\n";
|
||||
}
|
||||
Err(ptype) => {
|
||||
self.problems.push(ptype);
|
||||
}
|
||||
}
|
||||
} else if ast.ast_type == AstType::State3 {
|
||||
result += format!(
|
||||
"{} {} {}",
|
||||
@@ -342,6 +351,14 @@ impl Transpiler {
|
||||
)
|
||||
.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 {
|
||||
result += "&mut ";
|
||||
result += ast.tokens[0].value.as_str();
|
||||
|
||||
+4
-5
@@ -1,7 +1,7 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use rand::Rng;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
lexer::LexerState,
|
||||
@@ -9,7 +9,7 @@ use crate::{
|
||||
transpiler::Transpiler,
|
||||
};
|
||||
|
||||
#[derive(Clone, PartialEq, Debug, Serialize)]
|
||||
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
|
||||
pub enum VariableType {
|
||||
Var,
|
||||
Func,
|
||||
@@ -18,7 +18,7 @@ pub enum VariableType {
|
||||
Namespace,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct Variable {
|
||||
pub vtype: VariableType,
|
||||
pub desc: String,
|
||||
@@ -27,7 +27,7 @@ pub struct Variable {
|
||||
pub rname: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct Variables {
|
||||
pub vars: HashMap<String, Variable>,
|
||||
}
|
||||
@@ -142,7 +142,6 @@ impl Variables {
|
||||
return x.rname.clone();
|
||||
} else {
|
||||
root.problems.push(Problem {
|
||||
code: 1,
|
||||
problem_type: ProblemType::VariableNotFound,
|
||||
problem_msg: format!("Variable '{}' doesn't exist", &name),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user