Skip to content

Commit

Permalink
finalized way i'm going to write files
Browse files Browse the repository at this point in the history
created lazy static maps, simple types written to file. RIght now files clobber each other.
  • Loading branch information
LivingInSyn committed Feb 25, 2018
1 parent 5fc11cd commit bbdcb17
Show file tree
Hide file tree
Showing 3 changed files with 202 additions and 12 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ authors = ["Jeremy Mill <jeremymill@gmail.com>"]
syn = "0.12.12"
quote = "0.3.15"
proc-macro2 = "0.2.2"
lazy_static = "1.0"

[lib]
proc-macro = true
157 changes: 157 additions & 0 deletions src/filewriter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
use std::fs::File;
use syn::{Ident};
use std::io;
use std::io::Write;
use std::collections::HashMap;

lazy_static! {
static ref CSHARPMAP: HashMap<&'static str, &'static str> = {
let mut m = HashMap::new();
m.insert("bool", "byte");
m.insert("c_char", "sbyte");
m.insert("i8", "sbyte");
m.insert("c_schar", "sbyte");
m.insert("c_char_pntr", "string");
m.insert("u8", "byte");
m.insert("c_uchar", "byte");
m.insert("u16", "ushort");
m.insert("c_ushort", "ushort");
m.insert("i16", "short");
m.insert("c_short", "short");
m.insert("c_void", "IntPtr");
m.insert("u32", "uint");
m.insert("c_uint", "uint");
m.insert("i32", "int");
m.insert("c_int", "int");
m.insert("f32", "float");
m.insert("c_float", "float");
m.insert("i64", "long");
m.insert("c_long", "long");
m.insert("c_longlong", "long");
m.insert("c_double", "double");
m.insert("f64", "double");
m
};
static ref CPPMAP: HashMap<&'static str, &'static str> = {
let mut m = HashMap::new();
m.insert("bool", "bool");
m.insert("c_char", "signed char");
m.insert("i8", "signed char");
m.insert("c_schar", "signed char");
m.insert("c_char_pntr", "char*");
m.insert("u8", "unsigned char");
m.insert("c_uchar", "unsigned char");
m.insert("u16", "unsigned short");
m.insert("c_ushort", "unsigned short");
m.insert("i16", "short");
m.insert("c_short", "short");
m.insert("c_void", "void*");
m.insert("u32", "unsigned int");
m.insert("c_uint", "unsigned int");
m.insert("i32", "int");
m.insert("c_int", "int");
m.insert("f32", "float");
m.insert("c_float", "float");
m.insert("i64", "long long int");
m.insert("c_long", "long long int");
m.insert("c_longlong", "long long int");
m.insert("c_ulong", "unsigned long long int");
m.insert("c_ulonglong", "unsigned long long int");
m.insert("c_double", "double");
m.insert("f64", "double");
m
};
static ref PYMAP: HashMap<&'static str, &'static str> = {
let mut m = HashMap::new();
m.insert("bool", "c_bool");
m.insert("c_char", "c_byte");
m.insert("i8", "c_byte");
m.insert("c_schar", "c_byte");
m.insert("c_char_pntr", "c_char_p");
m.insert("u8", "c_ubyte");
m.insert("c_uchar", "c_ubyte");
m.insert("u16", "c_ushort");
m.insert("c_ushort", "c_ushort");
m.insert("i16", "c_short");
m.insert("c_short", "c_short");
m.insert("c_void", "c_void_p");
m.insert("u32", "c_uint");
m.insert("c_uint", "c_uint");
m.insert("i32", "c_int");
m.insert("c_int", "c_int");
m.insert("f32", "c_float");
m.insert("c_float", "c_float");
m.insert("i64", "c_longlong");
m.insert("c_long", "c_longlong");
m.insert("c_longlong", "c_longlong");
m.insert("c_ulong", "c_ulonglong");
m.insert("c_ulonglong", "c_ulonglong");
m.insert("c_double", "c_double");
m.insert("f64", "c_double");
m
};
}

pub enum LanguageType {
CPP,
Python,
CSharp,
}

///Creates a file, writes the struct opening
pub fn create_file(filename: &'static str, ltype: LanguageType, structname: Ident) -> io::Result<File> {
let mut file = File::create(filename)?;
//write the struct opening
match ltype {
LanguageType::CPP => {
write!(file, "typedef struct {}Tag {{\n", structname)?;
},
LanguageType::Python => {
write!(file, "class {}(Structure):\n", structname)?;
}
LanguageType::CSharp => {
write!(file, "\t[StructLayout(LayoutKind.Sequential)]\n\tpublic struct {}\n\t{{\n", structname)?;
}
}
//return the file ref
return Ok(file);
}

///adds a simple type like i32 or other struct to the file
pub fn add_simple_type(file: &mut File, ltype: LanguageType, name: Ident, dtype: Ident) {
match ltype {
LanguageType::CPP => {
match CPPMAP.get(&dtype.as_ref()) {
Some(t) => write!(file, "\t\tpublic {} {};\n", t, name).unwrap(),
None => write!(file, "\t\tpublic {} {};\n", dtype, name).unwrap()
}
},
LanguageType::Python => {
match PYMAP.get(&dtype.as_ref()) {
Some(t) => write!(file, "\t\tpublic {} {};\n", t, name).unwrap(),
None => write!(file, "\t\tpublic {} {};\n", dtype, name).unwrap()
}
}
LanguageType::CSharp => {
match CSHARPMAP.get(&dtype.as_ref()) {
Some(t) => write!(file, "\t\tpublic {} {};\n", t, name).unwrap(),
None => write!(file, "\t\tpublic {} {};\n", dtype, name).unwrap()
}
}
}
}

// ///adds an array type to the file
// pub fn add_array(file: File, ltype: LanguageType, name: Ident, length: i64, dtype: Ident) {

// }

// ///adds a pointer type to the file
// pub fn add_pointer(file: File, ltype: LanguageType, name: Ident) {
// //todo: add more args here
// }

// ///nicely closes the struct
// pub fn close_struct(file: File, ltype: LanguageType) {
// //todo: add more args here
// }
56 changes: 44 additions & 12 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,16 @@ extern crate proc_macro2;
extern crate syn;
#[macro_use]
extern crate quote;
#[macro_use]
extern crate lazy_static;

use proc_macro::TokenStream;
use proc_macro2::TokenNode;
use syn::{Data, Type, Fields};
use syn::{Data, Type, Fields};//, Ident};

mod filewriter;
use filewriter::*;


#[proc_macro_derive(Translate)]
pub fn translate(input: TokenStream) -> TokenStream {
Expand All @@ -18,13 +24,15 @@ pub fn translate(input: TokenStream) -> TokenStream {
let ast = syn::parse(input).unwrap();

// Build the impl
let gen = impl_translate(ast);
impl_translate(ast);

// Return the generated impl
gen.parse().unwrap()
//return empty tokenstream
let empty_tokens = quote!{
};
empty_tokens.parse().unwrap()
}

fn impl_translate(ast: syn::DeriveInput) -> quote::Tokens {
fn impl_translate(ast: syn::DeriveInput) {
// let name = ast.ident;

println!("name is: {}", ast.ident);
Expand All @@ -47,11 +55,14 @@ fn impl_translate(ast: syn::DeriveInput) -> quote::Tokens {
};
}
}
//if it is repc, lets try and translate it
if is_reprc {
//make sure we're matching a struct
match ast.data {
Data::Struct(ds) => {
//TODO: create the file
let mut cppfile = create_file("TestOut.h", LanguageType::CPP, ast.ident).unwrap();
let mut pyfile = create_file("TestOut.py", LanguageType::Python, ast.ident).unwrap();
let mut csfile = create_file("TestOut.cs", LanguageType::CSharp, ast.ident).unwrap();
//make sure we're matching named fields
match ds.fields {
Fields::Named(fieldsnamed) => {
Expand All @@ -64,15 +75,38 @@ fn impl_translate(ast: syn::DeriveInput) -> quote::Tokens {
//now we can find the type of the field
//field.ty is Enum syn::Type (https://dtolnay.github.io/syn/syn/enum.Type.html)
match field.ty {
Type::Array(_array) => {println!("{} is an array", field.ident.unwrap())},
Type::Ptr(_ptr) => {println!("{} is a ptr", field.ident.unwrap())},
//array
Type::Array(_array) => {
println!("{} is an array", field.ident.unwrap())
},
//pointer
Type::Ptr(ptr) => {
println!("{} is a ptr", field.ident.unwrap());
//get the type of the pointer
let fp_path = match *ptr.elem {
Type::Array(array) => {
// //TODO: fix this
//write an array pointer to the file
},
Type::Ptr(ptr) => {
//TODO: add a pointer to a file
},
Type::Path(path) => {
//recursive?
},
_ => {println!("not supported")}
};
},
//aparently fields like u16, i32, etc. are paths to their type
Type::Path(typepath)=> {
println!("{} is a path type", field.ident.unwrap());
//get the last Punctuated<PathSegment, Colon2> from
//typepath.path.segments
let segment = typepath.path.segments.iter().last().unwrap();
println!("type is: {}", segment.ident);
println!("name is: {}", field.ident.unwrap());
add_simple_type(&mut cppfile, LanguageType::CPP, field.ident.unwrap(), segment.ident);
add_simple_type(&mut csfile, LanguageType::Python, field.ident.unwrap(), segment.ident);
add_simple_type(&mut pyfile, LanguageType::CSharp, field.ident.unwrap(), segment.ident);
},

/* I'm not going to support these types yet */
Expand Down Expand Up @@ -103,9 +137,7 @@ fn impl_translate(ast: syn::DeriveInput) -> quote::Tokens {
_ => {}
}
}
//empty quote! macro generates an empty quote::Tokens to return
quote! {
}

}

#[cfg(test)]
Expand Down

0 comments on commit bbdcb17

Please sign in to comment.