added header wrappers and stdlib
This commit is contained in:
+11
-2
@@ -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
@@ -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
@@ -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
@@ -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*
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user