Skip to content

Commit

Permalink
Initial Dlang support
Browse files Browse the repository at this point in the history
closes: mozilla#866
  • Loading branch information
kassane committed Sep 29, 2024
1 parent 3ed9434 commit 47f7b6f
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 6 deletions.
2 changes: 1 addition & 1 deletion src/bindgen/bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ impl Bindings {

pub fn write<F: Write>(&self, file: F) {
match self.config.language {
Language::Cxx | Language::C => {
Language::Cxx | Language::C | Language::D => {
self.write_with_backend(file, &mut CLikeLanguageBackend::new(&self.config))
}
Language::Cython => {
Expand Down
6 changes: 5 additions & 1 deletion src/bindgen/cdecl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,11 @@ impl CDecl {
"error generating cdecl for {:?}",
t
);
self.type_name = p.to_repr_c(config).to_string();
if config.language == Language::D {
self.type_name = p.to_repr_d(config).to_string();
} else {
self.type_name = p.to_repr_c(config).to_string();
}
}
Type::Ptr {
ref ty,
Expand Down
7 changes: 7 additions & 0 deletions src/bindgen/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub enum Language {
Cxx,
C,
Cython,
D,
}

impl FromStr for Language {
Expand All @@ -42,6 +43,9 @@ impl FromStr for Language {
"C" => Ok(Language::C),
"cython" => Ok(Language::Cython),
"Cython" => Ok(Language::Cython),
"d" => Ok(Language::D),
"dlang" => Ok(Language::D),
"D" => Ok(Language::D),
_ => Err(format!("Unrecognized Language: '{}'.", s)),
}
}
Expand All @@ -54,6 +58,7 @@ impl Language {
match self {
Language::Cxx | Language::C => "typedef",
Language::Cython => "ctypedef",
Language::D => "alias",
}
}
}
Expand Down Expand Up @@ -166,6 +171,7 @@ pub enum DocumentationStyle {
C99,
Doxy,
Cxx,
D,
Auto,
}

Expand All @@ -179,6 +185,7 @@ impl FromStr for DocumentationStyle {
"cxx" => Ok(DocumentationStyle::Cxx),
"c++" => Ok(DocumentationStyle::Cxx),
"doxy" => Ok(DocumentationStyle::Doxy),
"dlang" => Ok(DocumentationStyle::D),
"auto" => Ok(DocumentationStyle::Auto),
_ => Err(format!("Unrecognized documentation style: '{}'.", s)),
}
Expand Down
5 changes: 5 additions & 0 deletions src/bindgen/ir/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,11 @@ impl Constant {
write!(out, " {} # = ", name);
language_backend.write_literal(out, value);
}
Language::D => {
write!(out, "enum {} = ", name);
language_backend.write_literal(out, value);
out.write(";");
}
}

condition.write_after(config, out);
Expand Down
23 changes: 22 additions & 1 deletion src/bindgen/ir/enumeration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -729,6 +729,27 @@ impl Enum {
write!(out, "{}enum {}", config.style.cython_def(), tag_name);
}
}
Language::D => {
out.write("enum");

if self.annotations.must_use(config) {
if let Some(ref anno) = config.enumeration.must_use {
write!(out, " {}", anno)
}
}

if let Some(note) = self
.annotations
.deprecated_note(config, DeprecatedNoteKind::Enum)
{
write!(out, " {}", note);
}

write!(out, " {}", tag_name);
if let Some(prim) = size {
write!(out, " : {}", prim);
}
}
}
out.open_brace();

Expand Down Expand Up @@ -781,7 +802,7 @@ impl Enum {
) {
match config.language {
Language::C if config.style.generate_typedef() => out.write("typedef "),
Language::C | Language::Cxx => {}
Language::C | Language::Cxx | Language::D => {}
Language::Cython => out.write(config.style.cython_def()),
}

Expand Down
51 changes: 51 additions & 0 deletions src/bindgen/ir/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,57 @@ impl PrimitiveType {
}
}

pub fn to_repr_d(&self, config: &Config) -> &'static str {
match *self {
PrimitiveType::Void => "void",
PrimitiveType::Bool => "bool",
PrimitiveType::Char => "char",
PrimitiveType::SChar => "byte",
PrimitiveType::UChar => "ubyte",
// NOTE: It'd be nice to use a char32_t, but:
//
// * uchar.h is not present on mac (see #423).
//
// * char32_t isn't required to be compatible with Rust's char, as
// the C++ spec only requires it to be the same size as
// uint_least32_t, which is _not_ guaranteed to be 4-bytes.
//
PrimitiveType::Char32 => "uint",
PrimitiveType::Integer {
kind,
signed,
zeroable: _,
} => match (kind, signed) {
(IntKind::Short, true) => "short",
(IntKind::Short, false) => "ushort",
(IntKind::Int, true) => "int",
(IntKind::Int, false) => "uint",
(IntKind::Long, true) => "long",
(IntKind::Long, false) => "ulong",
(IntKind::LongLong, true) => "long long",
(IntKind::LongLong, false) => "ulong long",
(IntKind::SizeT, true) => "long",
(IntKind::SizeT, false) => "ulong",
(IntKind::Size, true) if config.usize_is_size_t => "long",
(IntKind::Size, false) if config.usize_is_size_t => "ulong",
(IntKind::Size, true) => "long",
(IntKind::Size, false) => "ulong",
(IntKind::B8, true) => "byte",
(IntKind::B8, false) => "ubyte",
(IntKind::B16, true) => "short",
(IntKind::B16, false) => "ushort",
(IntKind::B32, true) => "int",
(IntKind::B32, false) => "uint",
(IntKind::B64, true) => "long",
(IntKind::B64, false) => "ulong",
},
PrimitiveType::Float => "float",
PrimitiveType::Double => "double",
PrimitiveType::PtrDiffT => "long",
PrimitiveType::VaList => "...",
}
}

fn can_cmp_order(&self) -> bool {
!matches!(*self, PrimitiveType::Bool)
}
Expand Down
1 change: 1 addition & 0 deletions src/bindgen/language_backend/clike.rs
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,7 @@ impl LanguageBackend for CLikeLanguageBackend<'_> {
DocumentationStyle::Doxy => out.write(" *"),
DocumentationStyle::C99 => out.write("//"),
DocumentationStyle::Cxx => out.write("///"),
DocumentationStyle::D => out.write("///"),
DocumentationStyle::Auto => unreachable!(), // Auto case should always be covered
}

Expand Down
4 changes: 2 additions & 2 deletions src/bindgen/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ impl<'a, F: Write> SourceWriter<'a, F> {

pub fn open_brace(&mut self) {
match self.bindings.config.language {
Language::Cxx | Language::C => match self.bindings.config.braces {
Language::Cxx | Language::C | Language::D => match self.bindings.config.braces {
Braces::SameLine => {
self.write(" {");
self.push_tab();
Expand All @@ -183,7 +183,7 @@ impl<'a, F: Write> SourceWriter<'a, F> {
pub fn close_brace(&mut self, semicolon: bool) {
self.pop_tab();
match self.bindings.config.language {
Language::Cxx | Language::C => {
Language::Cxx | Language::C | Language::D => {
self.new_line();
if semicolon {
self.write("};");
Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ fn main() {
.long("lang")
.value_name("LANGUAGE")
.help("Specify the language to output bindings in")
.value_parser(["c++", "C++", "c", "C", "cython", "Cython"]),
.value_parser(["c++", "C++", "c", "C", "cython", "Cython", "d", "dlang", "D"]),
)
.arg(
Arg::new("package-version")
Expand Down

0 comments on commit 47f7b6f

Please sign in to comment.