diff --git a/examples/convert.rs b/examples/convert.rs index ccf0853931..32a1f46c93 100644 --- a/examples/convert.rs +++ b/examples/convert.rs @@ -13,7 +13,7 @@ fn main() { //println!("{:?}", module); let options = javelin::back::msl::Options {}; - let msl = module.to_msl(&options).unwrap(); + let msl = javelin::back::msl::write_string(&module, &options).unwrap(); println!("{}", msl); } diff --git a/src/back/msl.rs b/src/back/msl.rs index 959f1558ad..74fa85376f 100644 --- a/src/back/msl.rs +++ b/src/back/msl.rs @@ -1,5 +1,6 @@ use std::fmt::{Error as FmtError, Write}; + pub struct Options { } @@ -14,14 +15,107 @@ impl From for Error { } } -impl crate::Module { - pub fn to_msl(&self, _options: &Options) -> Result { - let mut out = String::new(); +pub struct Writer { + out: W, +} - writeln!(out, "#include ")?; - writeln!(out, "#include ")?; - writeln!(out, "using namespace metal;")?; - - Ok(out) +fn scalar_kind_string(kind: crate::ScalarKind) -> &'static str { + match kind { + crate::ScalarKind::Float => "float", + crate::ScalarKind::Sint => "signed int", + crate::ScalarKind::Uint => "unsigned int", } } + +fn vector_size_string(size: crate::VectorSize) -> &'static str { + match size { + crate::VectorSize::Bi => "2", + crate::VectorSize::Tri => "3", + crate::VectorSize::Quad => "4", + } +} + +impl Writer { + fn put_type_pre(&mut self, ty: &crate::Type) -> Result<(), FmtError> { + match *ty { + crate::Type::Void => { + write!(self.out, "void") + }, + crate::Type::Scalar { kind, .. } => { + write!(self.out, "{}", scalar_kind_string(kind)) + }, + crate::Type::Vector { size, kind, .. } => { + write!(self.out, "{}{}", scalar_kind_string(kind), vector_size_string(size)) + }, + crate::Type::Matrix { columns, rows, kind, .. } => { + write!(self.out, "{}{}x{}", scalar_kind_string(kind), vector_size_string(columns), vector_size_string(rows)) + } + crate::Type::Array { ref base, .. } => { + self.put_type_pre(base) + } + _ => panic!("Unknown type {:?}", ty), + } + } + + fn put_type_post(&mut self, ty: &crate::Type) -> Result<(), FmtError> { + match *ty { + crate::Type::Array { length, .. } => { + write!(self.out, "[{}]", length) + } + _ => Ok(()) + } + } + + fn put_struct_name( + &mut self, + token: crate::Token, + module: &crate::Module, + ) -> Result<(), FmtError> { + match module.struct_declarations[token].name { + Some(ref name) => write!(self.out, "{}", name), + None => write!(self.out, "_Struct{}", token.index()), + } + } + + fn put_struct_member_name( + &mut self, + token: crate::Token, + index: usize, + module: &crate::Module, + ) -> Result<(), FmtError> { + match module.struct_declarations[token].members[index].name { + Some(ref name) => write!(self.out, "{}", name), + None => write!(self.out, "_field{}", index), + } + } + + pub fn write(&mut self, module: &crate::Module) -> Result<(), Error> { + writeln!(self.out, "#include ")?; + writeln!(self.out, "#include ")?; + writeln!(self.out, "using namespace metal;")?; + + writeln!(self.out, "")?; + for (token, decl) in module.struct_declarations.iter() { + write!(self.out, "struct ")?; + self.put_struct_name(token, module)?; + writeln!(self.out, " {{")?; + for (index, member) in decl.members.iter().enumerate() { + write!(self.out, "\t")?; + self.put_type_pre(&member.ty)?; + write!(self.out, " ")?; + self.put_struct_member_name(token, index, module)?; + self.put_type_post(&member.ty)?; + writeln!(self.out, ";")?; + } + writeln!(self.out, "}};")?; + } + + Ok(()) + } +} + +pub fn write_string(module: &crate::Module, _options: &Options) -> Result { + let mut w = Writer { out: String::new() }; + w.write(module)?; + Ok(w.out) +} diff --git a/src/storage.rs b/src/storage.rs index 8142b75cf5..b56c426ca2 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -1,5 +1,6 @@ use std::{ fmt, + hash, marker::PhantomData, }; @@ -37,6 +38,11 @@ impl fmt::Debug for Token { write!(formatter, "Token({})", self.index) } } +impl hash::Hash for Token { + fn hash(&self, hasher: &mut H) { + self.index.hash(hasher) + } +} impl Token { #[cfg(test)]