Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
robertbastian committed Nov 23, 2023
1 parent 4e1046a commit c1c5740
Show file tree
Hide file tree
Showing 50 changed files with 636 additions and 223 deletions.
2 changes: 1 addition & 1 deletion Makefile.toml
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,8 @@ dependencies = [
"gen-feature-c",
"gen-feature-c2",
"gen-feature-js",
"gen-feature-dotnet",
"gen-feature-dart",
"gen-feature-dotnet",
]

[tasks.gen-examples]
Expand Down
38 changes: 29 additions & 9 deletions core/src/ast/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,8 +383,9 @@ pub enum TypeName {
Writeable,
/// A `&DiplomatStr` type.
StrReference(Lifetime, StringEncoding),
/// A `&[T]` type, where `T` is a primitive.
PrimitiveSlice(Lifetime, Mutability, PrimitiveType),
/// A `&[T]` or `Box<[T]>` type, where `T` is a primitive.
/// Owned slices don't have a lifetime or mutability.
PrimitiveSlice(Option<(Lifetime, Mutability)>, PrimitiveType),
/// The `()` type.
Unit,
/// The `Self` type.
Expand Down Expand Up @@ -514,7 +515,7 @@ impl TypeName {
))
.unwrap()
}
TypeName::PrimitiveSlice(lifetime, mutability, name) => {
TypeName::PrimitiveSlice(Some((lifetime, mutability)), name) => {
let primitive_name = PRIMITIVE_TO_STRING.get(name).unwrap();
let formatted_str = format!(
"{}[{}]",
Expand All @@ -523,6 +524,11 @@ impl TypeName {
);
syn::parse_str(&formatted_str).unwrap()
}
TypeName::PrimitiveSlice(None, name) => syn::parse_str(&format!(
"Box<[{}]>",
PRIMITIVE_TO_STRING.get(name).unwrap()
))
.unwrap(),
TypeName::Unit => syn::parse_quote! {
()
},
Expand All @@ -539,7 +545,7 @@ impl TypeName {
/// - If the type is a path equal to [`diplomat_runtime::DiplomatResult`], returns a [`TypeName::DiplomatResult`] with the type parameters recursively converted
/// - If the type is a path equal to [`diplomat_runtime::DiplomatWriteable`], returns a [`TypeName::Writeable`]
/// - If the type is a reference to `DiplomatStr`, returns a [`TypeName::StrReference`]
/// - If the type is a reference to a slice of a Rust primitive, returns a [`TypeName::PrimitiveSlice`]
/// - If the type is a reference (owned or borrowed) to a slice of a Rust primitive, returns a [`TypeName::PrimitiveSlice`]
/// - If the type is a reference (`&` or `&mut`), returns a [`TypeName::Reference`] with the referenced type recursively converted
/// - Otherwise, assume that the reference is to a [`CustomType`] in either the current module or another one, returns a [`TypeName::Named`]
pub fn from_syn(ty: &syn::Type, self_path_type: Option<PathType>) -> TypeName {
Expand All @@ -566,7 +572,10 @@ impl TypeName {
.get_ident()
.and_then(|i| STRING_TO_PRIMITIVE.get(i.to_string().as_str()))
{
return TypeName::PrimitiveSlice(lifetime, mutability, *primitive);
return TypeName::PrimitiveSlice(
Some((lifetime, mutability)),
*primitive,
);
}
}
}
Expand All @@ -586,7 +595,15 @@ impl TypeName {
} else if p.path.segments.len() == 1 && p.path.segments[0].ident == "Box" {
if let PathArguments::AngleBracketed(type_args) = &p.path.segments[0].arguments
{
if let GenericArgument::Type(tpe) = &type_args.args[0] {
if let GenericArgument::Type(syn::Type::Slice(slice)) = &type_args.args[0] {
if let TypeName::Primitive(p) =
TypeName::from_syn(&*slice.elem, self_path_type)
{
TypeName::PrimitiveSlice(None, p)
} else {
panic!("Owned slices only support primitives.")
}
} else if let GenericArgument::Type(tpe) = &type_args.args[0] {
TypeName::Box(Box::new(TypeName::from_syn(tpe, self_path_type)))
} else {
panic!("Expected first type argument for Box to be a type")
Expand Down Expand Up @@ -679,7 +696,9 @@ impl TypeName {
err.visit_lifetimes(visit)
}
TypeName::StrReference(lt, ..) => visit(lt, LifetimeOrigin::StrReference),
TypeName::PrimitiveSlice(lt, ..) => visit(lt, LifetimeOrigin::PrimitiveSlice),
TypeName::PrimitiveSlice(Some((lt, _)), ..) => {
visit(lt, LifetimeOrigin::PrimitiveSlice)
}
_ => ControlFlow::Continue(()),
}
}
Expand Down Expand Up @@ -888,7 +907,7 @@ impl TypeName {
err.check_lifetime_elision(full_type, in_path, env, errors);
}
TypeName::StrReference(Lifetime::Anonymous, ..)
| TypeName::PrimitiveSlice(Lifetime::Anonymous, ..) => {
| TypeName::PrimitiveSlice(Some((Lifetime::Anonymous, _)), ..) => {
errors.push(ValidityError::LifetimeElisionInReturn {
full_type: full_type.clone(),
sub_type: self.clone(),
Expand Down Expand Up @@ -951,10 +970,11 @@ impl fmt::Display for TypeName {
ReferenceDisplay(lifetime, &Mutability::Immutable)
)
}
TypeName::PrimitiveSlice(lifetime, mutability, typ) => {
TypeName::PrimitiveSlice(Some((lifetime, mutability)), typ) => {
write!(f, "{}[{typ}]", ReferenceDisplay(lifetime, mutability))
}
TypeName::Unit => "()".fmt(f),
TypeName::PrimitiveSlice(None, typ) => write!(f, "Box<[{typ}]>"),
}
}
}
Expand Down
16 changes: 12 additions & 4 deletions core/src/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -470,8 +470,12 @@ impl<'ast, 'errors> LoweringContext<'ast, 'errors> {
ltl?.lower_lifetime(lifetime),
*encoding,
))),
ast::TypeName::PrimitiveSlice(lifetime, mutability, prim) => {
let borrow = Borrow::new(ltl?.lower_lifetime(lifetime), *mutability);
ast::TypeName::PrimitiveSlice(lm, prim) => {
let borrow = if let Some((lifetime, mutability)) = lm {
Some(Borrow::new(ltl?.lower_lifetime(lifetime), *mutability))
} else {
None
};
let prim = PrimitiveType::from_ast(*prim);

Some(Type::Slice(Slice::Primitive(borrow, prim)))
Expand Down Expand Up @@ -663,8 +667,12 @@ impl<'ast, 'errors> LoweringContext<'ast, 'errors> {
ltl?.lower_lifetime(lifetime),
*encoding,
))),
ast::TypeName::PrimitiveSlice(lifetime, mutability, prim) => {
let borrow = Borrow::new(ltl?.lower_lifetime(lifetime), *mutability);
ast::TypeName::PrimitiveSlice(lm, prim) => {
let borrow = if let Some((lifetime, mutability)) = lm {
Some(Borrow::new(ltl?.lower_lifetime(lifetime), *mutability))
} else {
None
};
let prim = PrimitiveType::from_ast(*prim);

Some(OutType::Slice(Slice::Primitive(borrow, prim)))
Expand Down
9 changes: 5 additions & 4 deletions core/src/hir/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,10 +374,11 @@ impl<'m> BorrowingFieldVisitor<'m> {
method_lifetimes: &MethodLifetimes,
leaves: &mut SmallVec<[BorrowingFieldVisitorLeaf; 8]>,
) {
let method_lifetime = slice
.lifetime()
.flat_map_nonstatic(|lt| lt.as_method_lifetime(method_lifetimes));
leaves.push(BorrowingFieldVisitorLeaf::Slice(parent, method_lifetime));
if let Some(lifetime) = slice.lifetime() {
let method_lifetime =
lifetime.flat_map_nonstatic(|lt| lt.as_method_lifetime(method_lifetimes));
leaves.push(BorrowingFieldVisitorLeaf::Slice(parent, method_lifetime));
}
}

/// Add a struct as a parent and recurse down leaves during construction of a
Expand Down
11 changes: 6 additions & 5 deletions core/src/hir/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ pub enum Slice {
/// A string slice, e.g. `&DiplomatStr`.
Str(MaybeStatic<TypeLifetime>, StringEncoding),

/// A primitive slice, e.g. `&mut [u8]`.
Primitive(Borrow, PrimitiveType),
/// A primitive slice, e.g. `&mut [u8]` or `Box<[usize]>
Primitive(Option<Borrow>, PrimitiveType),
}

// For now, the lifetime in not optional. This is because when you have references
Expand Down Expand Up @@ -88,10 +88,11 @@ impl SelfType {
impl Slice {
/// Returns the [`TypeLifetime`] contained in either the `Str` or `Primitive`
/// variant.
pub fn lifetime(&self) -> &MaybeStatic<TypeLifetime> {
pub fn lifetime(&self) -> Option<&MaybeStatic<TypeLifetime>> {
match self {
Slice::Str(lifetime, ..) => lifetime,
Slice::Primitive(reference, ..) => &reference.lifetime,
Slice::Str(lifetime, ..) => Some(lifetime),
Slice::Primitive(Some(reference), ..) => Some(&reference.lifetime),
Slice::Primitive(..) => None,
}
}
}
Expand Down
36 changes: 20 additions & 16 deletions example/c/include/diplomat_runtime.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 20 additions & 16 deletions example/c2/include/diplomat_runtime.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 20 additions & 16 deletions example/cpp/include/diplomat_runtime.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 20 additions & 16 deletions example/cpp2/include/diplomat_runtime.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions example/dart/lib/lib.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit c1c5740

Please sign in to comment.