added header wrappers and stdlib
This commit is contained in:
@@ -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::<u8>()).unwrap();
|
||||||
|
|
||||||
|
// Allocate the memory
|
||||||
|
unsafe {
|
||||||
|
let ptr = alloc(layout);
|
||||||
|
if ptr.is_null() {
|
||||||
|
// Allocation failed
|
||||||
|
null_mut()
|
||||||
|
} else {
|
||||||
|
ptr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
-2
@@ -13,7 +13,7 @@ fn main() {
|
|||||||
.about("The wyst compiler")
|
.about("The wyst compiler")
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("file")
|
Arg::with_name("file")
|
||||||
.required(true)
|
.required_unless_one(&["stdio", "hex"])
|
||||||
.help("Sets the input file to use"),
|
.help("Sets the input file to use"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
@@ -35,10 +35,19 @@ fn main() {
|
|||||||
.long("stdio")
|
.long("stdio")
|
||||||
.help("LSP Mode"),
|
.help("LSP Mode"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("hex")
|
||||||
|
.short('h')
|
||||||
|
.long("hex")
|
||||||
|
.takes_value(true)
|
||||||
|
.help("Turn an identifier into hex"),
|
||||||
|
)
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
if matches.is_present("stdio") {
|
if matches.is_present("stdio") {
|
||||||
println!("stdio mode!");
|
println!("stdio mode!");
|
||||||
|
} else if matches.is_present("hex") {
|
||||||
|
let ident = matches.value_of("hex").unwrap().to_string();
|
||||||
|
println!("_0x{}", hex::encode(ident));
|
||||||
} else {
|
} else {
|
||||||
let file = matches.value_of("file").unwrap().to_string();
|
let file = matches.value_of("file").unwrap().to_string();
|
||||||
let output = matches.value_of("output").unwrap_or("out").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 {
|
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 {
|
pub fn transpile_pairs(&mut self, pairs: Pairs<Rule>) -> String {
|
||||||
let mut res = String::new();
|
let mut res = String::new();
|
||||||
for pair in pairs {
|
for pair in pairs {
|
||||||
@@ -119,7 +163,7 @@ impl Transpiler {
|
|||||||
res += "#[allow(unused_imports)]\nuse ";
|
res += "#[allow(unused_imports)]\nuse ";
|
||||||
res += self
|
res += self
|
||||||
.mod_manager
|
.mod_manager
|
||||||
.add(tokens[0].as_str().to_string(), true)
|
.add(&mut self.clone(), tokens[0].as_str().to_string(), true)
|
||||||
.as_str();
|
.as_str();
|
||||||
res += "::*;\n";
|
res += "::*;\n";
|
||||||
}
|
}
|
||||||
@@ -127,24 +171,13 @@ impl Transpiler {
|
|||||||
res += "#[allow(unused_imports)]\nuse ";
|
res += "#[allow(unused_imports)]\nuse ";
|
||||||
res += self
|
res += self
|
||||||
.mod_manager
|
.mod_manager
|
||||||
.add(tokens[0].as_str().to_string(), false)
|
.add(&mut self.clone(), tokens[0].as_str().to_string(), false)
|
||||||
.as_str();
|
.as_str();
|
||||||
res += "::*;\n";
|
res += "::*;\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
Rule::identifier | Rule::def_identifier => {
|
Rule::identifier | Rule::def_identifier => {
|
||||||
let ident = pair.as_str().trim();
|
res += self.encode_ident(pair.as_str().trim()).as_str();
|
||||||
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(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Rule::call => {
|
Rule::call => {
|
||||||
@@ -183,6 +216,13 @@ impl Transpiler {
|
|||||||
res += pair.as_str();
|
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 += " ";
|
||||||
res += pair.as_str();
|
res += pair.as_str();
|
||||||
|
|||||||
+84
-26
@@ -1,9 +1,10 @@
|
|||||||
use std::fs;
|
|
||||||
use std::path::Path;
|
|
||||||
use crate::transpiler::{Rule, State, Transpiler, WystParser};
|
use crate::transpiler::{Rule, State, Transpiler, WystParser};
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use dirs::home_dir;
|
use dirs::home_dir;
|
||||||
use pest::Parser;
|
use pest::Parser;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fs;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub enum ProblemType {
|
pub enum ProblemType {
|
||||||
@@ -29,18 +30,23 @@ pub struct Problem {
|
|||||||
pub struct Module {
|
pub struct Module {
|
||||||
pub rs_mod: String,
|
pub rs_mod: String,
|
||||||
pub file_path: String,
|
pub file_path: String,
|
||||||
pub code: String
|
pub code: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ModManager {
|
pub struct ModManager {
|
||||||
pub modules: Vec<Module>,
|
pub modules: Vec<Module>,
|
||||||
pub macros: Vec<String>
|
pub macros: Vec<String>,
|
||||||
|
pub map: HashMap<String, String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModManager {
|
impl ModManager {
|
||||||
pub fn new() -> 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> {
|
pub fn check(&mut self, path: String) -> Option<Module> {
|
||||||
for module in self.modules.clone() {
|
for module in self.modules.clone() {
|
||||||
@@ -50,37 +56,83 @@ impl ModManager {
|
|||||||
}
|
}
|
||||||
None
|
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 mut problems: Vec<ProblemCap> = Vec::new();
|
||||||
let mod_name = format!("mod_{}", self.modules.len());
|
let mod_name = format!("mod_{}", self.modules.len());
|
||||||
let home_dirpb = home_dir().unwrap();
|
let home_dirpb = home_dir().unwrap();
|
||||||
let home_dir = home_dirpb.to_str().unwrap();
|
let home_dir = home_dirpb.to_str().unwrap();
|
||||||
let mut file_path = file_path;
|
let mut file_path = file_path;
|
||||||
if global {
|
if global {
|
||||||
let mut tmp = Path::new(home_dir).join("wyst").join("lib").join(file_path.clone()).to_str().unwrap().to_string();
|
let mut tmp = Path::new(home_dir)
|
||||||
if !Path::new(&tmp).exists() {
|
.join("wyst")
|
||||||
tmp = Path::new("lib").join(file_path).to_str().unwrap().to_string();
|
.join("lib")
|
||||||
}
|
.join(file_path.clone())
|
||||||
file_path = tmp;
|
.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()) {
|
if let Some(modl) = self.check(file_path.clone()) {
|
||||||
return modl.rs_mod;
|
return modl.rs_mod;
|
||||||
}
|
}
|
||||||
if let Ok(code) = fs::read_to_string(file_path.clone()) {
|
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 {
|
match file_path.rsplit_once('.').unwrap_or(("", "")).1 {
|
||||||
"rs" => {
|
"rs" => match WystParser::parse(Rule::rust_code, &code) {
|
||||||
match WystParser::parse(Rule::rust_code, &code) {
|
Ok(parsed) => {
|
||||||
Ok(parsed) => {
|
self.modules.push(Module {
|
||||||
for pair in parsed {
|
rs_mod: mod_name.clone(),
|
||||||
for p in pair.into_inner() {
|
file_path: file_path.clone(),
|
||||||
if p.as_rule() == Rule::rust_macro_lint {
|
code: code.clone(),
|
||||||
self.macros.push(p.into_inner().as_str().to_string());
|
});
|
||||||
}
|
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,14 +161,20 @@ impl ModManager {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let rust_code = trsp.transpile_code(module.code, 0).expect("");
|
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);
|
problems.append(&mut trsp.problems);
|
||||||
self.modules = trsp.mod_manager.modules;
|
self.modules = trsp.mod_manager.modules;
|
||||||
}
|
}
|
||||||
|
|
||||||
"rs" => {
|
"rs" => fs::write(
|
||||||
fs::write(Path::new("build").join((module.rs_mod+".rs").as_str()), &module.code).unwrap()
|
Path::new("build").join((module.rs_mod + ".rs").as_str()),
|
||||||
}
|
&module.code,
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-2
@@ -1,4 +1,4 @@
|
|||||||
WHITESPACE = _{ " " | "\t" | "\n" }
|
WHITESPACE = _{ ("//" ~ (!"\n" ~ ANY)*) | ("/*" ~ (!"*/" ~ ANY)*) | " " | "\t" | "\n" }
|
||||||
wspc = { " " | "\t" | "\n" }
|
wspc = { " " | "\t" | "\n" }
|
||||||
|
|
||||||
// [chars]
|
// [chars]
|
||||||
@@ -17,6 +17,7 @@ string = { "\"" ~ (raw_string | escape )* ~ "\"" }
|
|||||||
char = { "'" ~ (escape | ANY) ~ "'" }
|
char = { "'" ~ (escape | ANY) ~ "'" }
|
||||||
bool = @{"true" | "false"}
|
bool = @{"true" | "false"}
|
||||||
keyword = @{"struct"}
|
keyword = @{"struct"}
|
||||||
|
map = { "#" ~ "map" ~ identifier ~ comma ~ identifier }
|
||||||
|
|
||||||
// [numbers]
|
// [numbers]
|
||||||
hex = @{ "0" ~ ("x"|"X") ~ ('0'..'9' | 'a'..'f' | 'A'..'F')*}
|
hex = @{ "0" ~ ("x"|"X") ~ ('0'..'9' | 'a'..'f' | 'A'..'F')*}
|
||||||
@@ -75,6 +76,11 @@ top_expr = {
|
|||||||
include |
|
include |
|
||||||
include_global |
|
include_global |
|
||||||
func_def |
|
func_def |
|
||||||
struct_def
|
struct_def |
|
||||||
|
map
|
||||||
)* ~ !ANY
|
)* ~ !ANY
|
||||||
}
|
}
|
||||||
|
|
||||||
|
header_expr = {
|
||||||
|
map*
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user