diff --git a/lib/stdlib.h b/lib/stdlib.h new file mode 100644 index 0000000..e69de29 diff --git a/lib/stdlib.rs b/lib/stdlib.rs new file mode 100644 index 0000000..49d1a2c --- /dev/null +++ b/lib/stdlib.rs @@ -0,0 +1,23 @@ +use std::alloc::{alloc, Layout}; +use std::ptr::null_mut; + +// Malloc +pub fn _0x6d616c6c6f63(size: usize) -> *mut u8 { + if size == 0 { + return null_mut(); + } + + // Create a memory layout for the requested size + let layout = Layout::from_size_align(size, std::mem::align_of::()).unwrap(); + + // Allocate the memory + unsafe { + let ptr = alloc(layout); + if ptr.is_null() { + // Allocation failed + null_mut() + } else { + ptr + } + } +} diff --git a/src/main.rs b/src/main.rs index 84b27aa..c4e23ce 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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(); diff --git a/src/transpiler.rs b/src/transpiler.rs index 0e2959a..302eeff 100644 --- a/src/transpiler.rs +++ b/src/transpiler.rs @@ -68,6 +68,50 @@ pub fn to_indexable(pairs: Pairs) -> Vec> { } 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) -> 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(); diff --git a/src/utils.rs b/src/utils.rs index 740fb1b..412d22f 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -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, - pub macros: Vec + pub macros: Vec, + pub map: HashMap, } 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 { 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 = 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 } -} \ No newline at end of file +} diff --git a/src/wyst.pest b/src/wyst.pest index aaa9c58..30df927 100644 --- a/src/wyst.pest +++ b/src/wyst.pest @@ -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* +}