added header wrappers and stdlib

This commit is contained in:
2024-07-24 14:12:37 +02:00
parent 1aab723c3f
commit c48cad6817
6 changed files with 181 additions and 45 deletions
+11 -2
View File
@@ -13,7 +13,7 @@ fn main() {
.about("The wyst compiler")
.arg(
Arg::with_name("file")
.required(true)
.required_unless_one(&["stdio", "hex"])
.help("Sets the input file to use"),
)
.arg(
@@ -35,10 +35,19 @@ fn main() {
.long("stdio")
.help("LSP Mode"),
)
.arg(
Arg::with_name("hex")
.short('h')
.long("hex")
.takes_value(true)
.help("Turn an identifier into hex"),
)
.get_matches();
if matches.is_present("stdio") {
println!("stdio mode!");
} else if matches.is_present("hex") {
let ident = matches.value_of("hex").unwrap().to_string();
println!("_0x{}", hex::encode(ident));
} else {
let file = matches.value_of("file").unwrap().to_string();
let output = matches.value_of("output").unwrap_or("out").to_string();
+54 -14
View File
@@ -68,6 +68,50 @@ pub fn to_indexable(pairs: Pairs<Rule>) -> Vec<Pair<Rule>> {
}
impl Transpiler {
pub fn encode_ident(&mut self, ident: &str) -> String {
match WystParser::parse(Rule::def_identifier, ident) {
Ok(parsed) => {
let mut output = String::new();
for pair in parsed {
let tokens = to_indexable(pair.clone().into_inner());
for t in tokens {
match t.as_rule() {
Rule::identifier => {
let ident = t.as_str().trim();
let ident_rs = format!("_0x{}", hex::encode(ident.as_bytes()));
if self.mod_manager.macros.contains(&ident_rs) {
output += ident_rs.as_str();
output += "!";
} else {
output += match ident {
"void" => "()",
"int" => "i32",
"float" => "f64",
"Vec" => "Vec",
_ => {
if self.mod_manager.map.contains_key(ident) {
self.mod_manager.map.get(ident).unwrap()
} else {
ident_rs.as_str()
}
}
};
}
}
Rule::def_identifier => {
output += "<";
output += self.encode_ident(t.as_str()).as_str();
output += ">";
}
_ => {}
}
}
}
output
}
Err(_) => String::new(),
}
}
pub fn transpile_pairs(&mut self, pairs: Pairs<Rule>) -> String {
let mut res = String::new();
for pair in pairs {
@@ -119,7 +163,7 @@ impl Transpiler {
res += "#[allow(unused_imports)]\nuse ";
res += self
.mod_manager
.add(tokens[0].as_str().to_string(), true)
.add(&mut self.clone(), tokens[0].as_str().to_string(), true)
.as_str();
res += "::*;\n";
}
@@ -127,24 +171,13 @@ impl Transpiler {
res += "#[allow(unused_imports)]\nuse ";
res += self
.mod_manager
.add(tokens[0].as_str().to_string(), false)
.add(&mut self.clone(), tokens[0].as_str().to_string(), false)
.as_str();
res += "::*;\n";
}
Rule::identifier | Rule::def_identifier => {
let ident = pair.as_str().trim();
let ident_rs = format!("_0x{}", hex::encode(ident.as_bytes()));
if self.mod_manager.macros.contains(&ident_rs) {
res += ident_rs.as_str();
res += "!";
} else {
res += match ident {
"void" => "()",
"int" => "i32",
_ => ident_rs.as_str(),
};
}
res += self.encode_ident(pair.as_str().trim()).as_str();
}
Rule::call => {
@@ -183,6 +216,13 @@ impl Transpiler {
res += pair.as_str();
}
Rule::map => {
self.mod_manager.map.insert(
tokens[0].as_str().to_string(),
tokens[2].as_str().to_string(),
);
}
_ => {
res += " ";
res += pair.as_str();
+85 -27
View File
@@ -1,9 +1,10 @@
use std::fs;
use std::path::Path;
use crate::transpiler::{Rule, State, Transpiler, WystParser};
use serde::{Deserialize, Serialize};
use dirs::home_dir;
use pest::Parser;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fs;
use std::path::Path;
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ProblemType {
@@ -29,18 +30,23 @@ pub struct Problem {
pub struct Module {
pub rs_mod: String,
pub file_path: String,
pub code: String
pub code: String,
}
#[derive(Debug, Clone)]
pub struct ModManager {
pub modules: Vec<Module>,
pub macros: Vec<String>
pub macros: Vec<String>,
pub map: HashMap<String, String>,
}
impl ModManager {
pub fn new() -> ModManager {
ModManager {modules: Vec::new(), macros: Vec::new()}
ModManager {
modules: Vec::new(),
macros: Vec::new(),
map: HashMap::new(),
}
}
pub fn check(&mut self, path: String) -> Option<Module> {
for module in self.modules.clone() {
@@ -50,37 +56,83 @@ impl ModManager {
}
None
}
pub fn add(&mut self, file_path: String, global: bool) -> String {
pub fn add(&mut self, root: &mut Transpiler, file_path: String, global: bool) -> String {
let mut problems: Vec<ProblemCap> = Vec::new();
let mod_name = format!("mod_{}", self.modules.len());
let home_dirpb = home_dir().unwrap();
let home_dir = home_dirpb.to_str().unwrap();
let mut file_path = file_path;
if global {
let mut tmp = Path::new(home_dir).join("wyst").join("lib").join(file_path.clone()).to_str().unwrap().to_string();
if !Path::new(&tmp).exists() {
tmp = Path::new("lib").join(file_path).to_str().unwrap().to_string();
}
file_path = tmp;
let mut tmp = Path::new(home_dir)
.join("wyst")
.join("lib")
.join(file_path.clone())
.to_str()
.unwrap()
.to_string();
if !Path::new(&tmp).exists() {
tmp = Path::new("lib")
.join(file_path)
.to_str()
.unwrap()
.to_string();
}
file_path = tmp;
}
if let Some(modl) = self.check(file_path.clone()) {
return modl.rs_mod;
}
if let Ok(code) = fs::read_to_string(file_path.clone()) {
self.modules.push(Module { rs_mod: mod_name.clone(), file_path: file_path.clone(), code: code.clone() });
match file_path.rsplit_once('.').unwrap_or(("", "")).1 {
"rs" => {
match WystParser::parse(Rule::rust_code, &code) {
Ok(parsed) => {
for pair in parsed {
for p in pair.into_inner() {
if p.as_rule() == Rule::rust_macro_lint {
self.macros.push(p.into_inner().as_str().to_string());
}
"rs" => match WystParser::parse(Rule::rust_code, &code) {
Ok(parsed) => {
self.modules.push(Module {
rs_mod: mod_name.clone(),
file_path: file_path.clone(),
code: code.clone(),
});
for pair in parsed {
for p in pair.into_inner() {
if p.as_rule() == Rule::rust_macro_lint {
self.macros.push(p.into_inner().as_str().to_string());
}
}
}
Err(_) => {}
}
Err(_) => {}
},
"h" => {
file_path = file_path.rsplit_once('.').unwrap_or(("", "")).0.to_string();
file_path += ".rs";
let parsed = WystParser::parse(Rule::header_expr, &code).unwrap();
for pair in parsed {
root.transpile_pairs(pair.into_inner());
}
self.map.extend(root.mod_manager.map.clone().into_iter());
if let Ok(code1) = fs::read_to_string(file_path.clone()) {
let parsed = WystParser::parse(Rule::rust_code, &code1).unwrap();
self.modules.push(Module {
rs_mod: mod_name.clone(),
file_path: file_path.clone(),
code: code1.clone(),
});
for pair in parsed {
for p in pair.into_inner() {
if p.as_rule() == Rule::rust_macro_lint {
self.macros.push(p.into_inner().as_str().to_string());
}
}
}
} else {
problems.push(ProblemCap::Error(Problem {
problem_msg: format!("Sub Header not found '{}'", file_path),
problem_type: ProblemType::FileNotFound,
state: State {
line: 0,
column: 0,
file: None,
},
}))
}
}
_ => {}
@@ -109,18 +161,24 @@ impl ModManager {
..Default::default()
};
let rust_code = trsp.transpile_code(module.code, 0).expect("");
fs::write(Path::new("build").join((module.rs_mod+".rs").as_str()), rust_code).expect("Error writing rust file: ");
fs::write(
Path::new("build").join((module.rs_mod + ".rs").as_str()),
rust_code,
)
.expect("Error writing rust file: ");
problems.append(&mut trsp.problems);
self.modules = trsp.mod_manager.modules;
}
"rs" => {
fs::write(Path::new("build").join((module.rs_mod+".rs").as_str()), &module.code).unwrap()
}
"rs" => fs::write(
Path::new("build").join((module.rs_mod + ".rs").as_str()),
&module.code,
)
.unwrap(),
_ => {}
}
}
problems
}
}
}
+8 -2
View File
@@ -1,4 +1,4 @@
WHITESPACE = _{ " " | "\t" | "\n" }
WHITESPACE = _{ ("//" ~ (!"\n" ~ ANY)*) | ("/*" ~ (!"*/" ~ ANY)*) | " " | "\t" | "\n" }
wspc = { " " | "\t" | "\n" }
// [chars]
@@ -17,6 +17,7 @@ string = { "\"" ~ (raw_string | escape )* ~ "\"" }
char = { "'" ~ (escape | ANY) ~ "'" }
bool = @{"true" | "false"}
keyword = @{"struct"}
map = { "#" ~ "map" ~ identifier ~ comma ~ identifier }
// [numbers]
hex = @{ "0" ~ ("x"|"X") ~ ('0'..'9' | 'a'..'f' | 'A'..'F')*}
@@ -75,6 +76,11 @@ top_expr = {
include |
include_global |
func_def |
struct_def
struct_def |
map
)* ~ !ANY
}
header_expr = {
map*
}