Skip to content

Commit

Permalink
WIP Fixing generator for test.capnp
Browse files Browse the repository at this point in the history
  • Loading branch information
ObsidianMinor committed Sep 17, 2024
1 parent 9ce70b6 commit 2dd2b94
Show file tree
Hide file tree
Showing 11 changed files with 26,088 additions and 155 deletions.
58 changes: 36 additions & 22 deletions recapnc/src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -727,18 +727,24 @@ impl GeneratorContext {
ctx: &mut FileContext,
) -> Result<Box<syn::Type>> {
let base = self.resolve_type_kind(scope, &info.kind, ctx)?;
let mut wrapped = base;
for _ in 0..info.list_depth {
wrapped = syn::parse_quote!(_p::List<#wrapped>);
}
Ok(wrapped)
Ok(wrap_in_list(base, info.list_depth as usize))
}

fn resolve_type_kind(
&self,
scope: &TypeScope,
info: &TypeKind,
ctx: &mut FileContext,
) -> Result<Box<syn::Type>> {
}

/// Resolve the Rust type for a type kind but without specialization wrappers like `Enum<T>` or
/// `Struct<T>`.
fn resolve_base_type_kind(
&self,
scope: &TypeScope,
info: &TypeKind,
ctx: &mut FileContext,
) -> Result<Box<syn::Type>> {
Ok(match info {
TypeKind::Void => syn::parse_quote!(()),
Expand All @@ -759,8 +765,8 @@ impl GeneratorContext {
ctx.required_imports.insert(type_info.scope.file.id);
}

let resolved = type_info.resolve_path(scope);
syn::parse_quote!(_p::Enum<#resolved>)
let path = type_info.resolve_path(scope);
syn::parse_quote!(#path)
},
TypeKind::Data => syn::parse_quote!(_p::Data),
TypeKind::Text => syn::parse_quote!(_p::Text),
Expand All @@ -770,8 +776,8 @@ impl GeneratorContext {
ctx.required_imports.insert(type_info.scope.file.id);
}

let resolved = type_info.resolve_path(scope);
syn::parse_quote!(_p::Struct<#resolved>)
let path = type_info.resolve_path(scope);
syn::parse_quote!(#path)
},
TypeKind::Interface { .. } => syn::parse_quote!(_p::AnyPtr), // TODO
TypeKind::AnyPointer => syn::parse_quote!(_p::AnyPtr),
Expand Down Expand Up @@ -842,12 +848,12 @@ impl GeneratorContext {
} else {
use TypeKind::*;
match &type_info.kind {
Void => todo!(),
Bool => todo!(),
Int8 | Uint8 => todo!(),
Int16 | Uint16 | Enum { .. } => todo!(),
Int32 | Uint32 | Float32 => todo!(),
Int64 | Uint64 | Float64 => todo!(),
Void => ElementSize::Void,
Bool => ElementSize::Bit,
Int8 | Uint8 => ElementSize::Byte,
Int16 | Uint16 | Enum { .. } => ElementSize::TwoBytes,
Int32 | Uint32 | Float32 => ElementSize::FourBytes,
Int64 | Uint64 | Float64 => ElementSize::EightBytes,
Struct { schema, .. } =>
ElementSize::InlineComposite(schema.struct_size()),
AnyStruct => {
Expand All @@ -863,7 +869,8 @@ impl GeneratorContext {

assert_eq!(value_element_size, expected_element_size);

generate_untyped_list_value(&value)
let expr = generate_untyped_list_value(&value);
syn::parse_quote!(::core::option::Option::Some(#expr))
} else {
quote_none!()
});
Expand Down Expand Up @@ -1076,21 +1083,28 @@ impl GeneratorContext {
};

let expr = if ptr.is_null() {
syn::parse_quote!(_p::ConstPtr::null())
syn::parse_quote!(_p::ty::ConstPtr::null())
} else {
let slice = ptr_to_slice(&ptr);
let words = words_lit(&slice);

syn::parse_quote!(unsafe { _p::ConstPtr::new(#words) })
syn::parse_quote!(unsafe { _p::ty::ConstPtr::new(#words) })
};

Ok(expr)
}
}

fn wrap_in_list(mut t: Box<syn::Type>, depth: usize) -> Box<syn::Type> {
for _ in 0..depth {
t = syn::parse_quote!(_p::List<#t>);
}
t
}

fn words_lit(words: &[Word]) -> TokenStream {
let words = words.iter().map(|Word([b0, b1, b2, b3, b4, b5, b6, b7])| {
quote!(Word([#b0, #b1, #b2, #b3, #b4, #b5, #b6, #b7]))
quote!(_p::Word([#b0, #b1, #b2, #b3, #b4, #b5, #b6, #b7]))
});

quote!(&[#(#words),*])
Expand Down Expand Up @@ -1118,7 +1132,7 @@ fn generate_untyped_ptr_value(s: &any::PtrReader) -> Box<syn::Expr> {
let slice = ptr_to_slice(s);
let words = words_lit(&slice);

syn::parse_quote!(_p::PtrReader::slice_unchecked(#words))
syn::parse_quote!(unsafe { _p::PtrReader::slice_unchecked(#words) })
}

fn ptr_to_slice(p: &any::PtrReader) -> Box<[Word]> {
Expand Down Expand Up @@ -1163,7 +1177,7 @@ fn generate_untyped_struct_value(s: &any::StructReader) -> Box<syn::Expr> {
let StructSize { data, ptrs } = s.as_ref().size();
let size = quote!(_p::StructSize { data: #data, ptrs: #ptrs });

syn::parse_quote!(_p::StructReader::slice_unchecked(#words, #size))
syn::parse_quote!(unsafe { _p::StructReader::slice_unchecked(#words, #size) })
}

/// Deep-clone a struct into an array of words without the root pointer.
Expand Down Expand Up @@ -1211,7 +1225,7 @@ fn generate_untyped_list_value(list: &any::ListReader) -> Box<syn::Expr> {

let element_size_quote = element_size_to_tokens(value_element_size);

syn::parse_quote!(_p::ListReader::slice_unchecked(#words, #len, #element_size_quote))
syn::parse_quote!(unsafe { _p::ListReader::slice_unchecked(#words, #len, #element_size_quote) })
}

/// Deep-clone a list into an array of words without the root pointer.
Expand Down
153 changes: 22 additions & 131 deletions recapnc/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,12 @@ impl SchemaLoader {
let binding = match binding.which().map_err(SchemaError::UnknownScopeBinding)? {
Which::Type(ty) => {
let ty = ty.get();
self.resolve_brand_type(&ty)?
self.resolve_type(&ty)?
},
Which::Unbound(()) => ParameterBinding::scope_bound(scope_id, index as u16),
Which::Unbound(()) => TypeKind::ScopeBound {
scope: scope_id,
index: index as u16,
}.into(),
};
bindings.push(binding);
}
Expand All @@ -176,82 +179,6 @@ impl SchemaLoader {
Ok(Branding { scopes })
}

fn resolve_brand_type<'a>(
&'a self,
ty: &ReaderOf<'a, schema_capnp::Type>,
) -> Result<ParameterBinding<'a>> {
self.resolve_brand_type_inner(ty, 0)
}

fn resolve_brand_type_inner<'a>(
&'a self,
ty: &ReaderOf<'a, schema_capnp::Type>,
list_depth: u32,
) -> Result<ParameterBinding<'a>> {
use schema_capnp::r#type::Which;
let kind = match ty.which().map_err(SchemaError::UnknownType)? {
Which::Void(()) |
Which::Bool(()) |
Which::Int8(()) |
Which::Int16(()) |
Which::Int32(()) |
Which::Int64(()) |
Which::Uint8(()) |
Which::Uint16(()) |
Which::Uint32(()) |
Which::Uint64(()) |
Which::Float32(()) |
Which::Float64(()) |
Which::Enum(_) => Err(SchemaError::InvalidBrandType)?,
Which::Text(()) => GenericBinding::Text,
Which::Data(()) => GenericBinding::Data,
Which::List(list) => {
let ty = list.element_type().get();
return self.resolve_brand_type_inner(&ty, list_depth + 1)
},
Which::Struct(struct_type) => {
let brand = struct_type.brand().get();
GenericBinding::Struct {
schema: self.try_schema(struct_type.type_id())?,
parameters: self.resolve_brand(&brand)?
}
},
Which::Interface(interface) => {
let brand = interface.brand().get();
GenericBinding::Struct {
schema: self.try_schema(interface.type_id())?,
parameters: self.resolve_brand(&brand)?
}
},
Which::AnyPointer(ptr) => {
use schema_capnp::r#type::any_pointer::Which;
match ptr.which().map_err(SchemaError::UnknownType)? {
Which::Unconstrained(unconstrained) => {
use schema_capnp::r#type::any_pointer::unconstrained::Which;
match unconstrained.which().map_err(SchemaError::UnknownType)? {
Which::AnyKind(()) => GenericBinding::AnyPointer,
Which::Struct(()) => GenericBinding::AnyStruct,
Which::List(()) => GenericBinding::AnyList,
Which::Capability(()) => GenericBinding::AnyCapability,
}
},
Which::Parameter(param) => {
GenericBinding::ScopeBound {
scope: param.scope_id(),
index: param.parameter_index(),
}
},
Which::ImplicitMethodParameter(method_param) => {
GenericBinding::ImplicitMethodParameter {
index: method_param.parameter_index(),
}
},
}
},
};
Ok(ParameterBinding { list_depth, kind })
}

pub fn gather_node_parameters<'a>(&'a self, node: &ReaderOf<'a, Node>) -> Result<VecDeque<Parameter<'a>>> {
let mut vec = VecDeque::new();
let mut node = node.clone();
Expand All @@ -272,7 +199,7 @@ impl SchemaLoader {
&'a self,
node: &ReaderOf<'a, Node>,
brand: &Branding<'a>,
) -> Result<VecDeque<ParameterBinding<'a>>> {
) -> Result<VecDeque<Type<'a>>> {
let mut vec = VecDeque::new();
let mut node = node.clone();
while node.is_generic() {
Expand All @@ -281,7 +208,7 @@ impl SchemaLoader {
match brand.find(scope) {
Some(ScopeBranding::Inherit) => {
for (idx, _) in params.into_iter().enumerate().rev() {
vec.push_front(ParameterBinding::scope_bound(scope, idx as u16));
vec.push_front(TypeKind::ScopeBound { scope, index: idx as u16 }.into());
}
}
Some(ScopeBranding::Bind(bindings)) => {
Expand All @@ -290,7 +217,7 @@ impl SchemaLoader {
}
None => for _ in 0..params.len() {
// no binding was found, so we just push any pointer for each generic
vec.push_front(ParameterBinding::ANY_POINTER)
vec.push_front(TypeKind::AnyPointer.into())
}
}

Expand All @@ -303,15 +230,13 @@ impl SchemaLoader {

pub fn resolve_type<'a>(
&'a self,
node: &ReaderOf<'a, Node>,
ty: &ReaderOf<'a, schema_capnp::Type>,
) -> Result<Type<'a>> {
self.resolve_type_inner(node, ty, 0)
self.resolve_type_inner(ty, 0)
}

fn resolve_type_inner<'a>(
&'a self,
node: &ReaderOf<'a, Node>,
ty: &ReaderOf<'a, schema_capnp::Type>,
list_depth: u32,
) -> Result<Type<'a>> {
Expand All @@ -333,7 +258,7 @@ impl SchemaLoader {
Which::Data(()) => TypeKind::Data,
Which::List(list) => {
let element_type = list.element_type().get();
return self.resolve_type_inner(node, &element_type, list_depth + 1)
return self.resolve_type_inner(&element_type, list_depth + 1)
},
Which::Enum(e) => {
let ty = self.try_schema(e.type_id())?;
Expand Down Expand Up @@ -381,52 +306,10 @@ pub struct Parameter<'a> {
pub name: text::Reader<'a>,
}

#[derive(Clone)]
pub enum GenericBinding<'a> {
Data,
Text,
Struct {
schema: StructSchema<'a>,
parameters: Branding<'a>,
},
Interface {
schema: InterfaceSchema<'a>,
parameters: Branding<'a>,
},
AnyPointer,
AnyStruct,
AnyList,
AnyCapability,
ScopeBound {
scope: Id,
index: u16,
},
ImplicitMethodParameter {
index: u16,
},
}

#[derive(Clone)]
pub struct ParameterBinding<'a> {
pub list_depth: u32,
pub kind: GenericBinding<'a>,
}

impl ParameterBinding<'_> {
pub const ANY_POINTER: Self = Self { list_depth: 0, kind: GenericBinding::AnyPointer };

pub fn scope_bound(scope: Id, index: u16) -> Self {
Self {
list_depth: 0,
kind: GenericBinding::ScopeBound { scope, index }
}
}
}

#[derive(Clone)]
pub enum ScopeBranding<'a> {
Inherit,
Bind(Vec<ParameterBinding<'a>>),
Bind(Vec<Type<'a>>),
}

#[derive(Clone)]
Expand Down Expand Up @@ -497,16 +380,24 @@ pub trait Schema<'a>: Sized {
}

/// Gather a list of all generic bindings with the given brand.
fn gather_bindings(&self, brand: &Branding<'a>) -> Result<VecDeque<ParameterBinding<'a>>> {
fn gather_bindings(&self, brand: &Branding<'a>) -> Result<VecDeque<Type<'a>>> {
self.loader().gather_node_bindings(self.node(), brand)
}
}

#[derive(Clone)]
pub struct Type<'a> {
pub list_depth: u32,
pub kind: TypeKind<'a>,
}

impl<'a> From<TypeKind<'a>> for Type<'a> {
fn from(value: TypeKind<'a>) -> Self {
Type { list_depth: 0, kind: value }
}
}

#[derive(Clone)]
pub enum TypeKind<'a> {
Void,
Bool,
Expand Down Expand Up @@ -665,7 +556,7 @@ impl<'a> FieldSchema<'a, '_> {
let ty = slot.r#type().get();
FieldType::Slot {
offset: slot.offset(),
field_type: self.parent.loader.resolve_type(&self.parent.node, &ty)?,
field_type: self.parent.loader.resolve_type(&ty)?,
default_value: slot.had_explicit_default()
.then(|| slot.default_value().get_option())
.flatten(),
Expand Down Expand Up @@ -716,7 +607,7 @@ schema_type!(ConstSchema, Const, r#const);
impl<'a> ConstSchema<'a> {
pub fn value_type(&self) -> Result<Type<'a>> {
let ty = self.info.r#type().get();
self.loader.resolve_type(&self.node, &ty)
self.loader.resolve_type(&ty)
}

pub fn value(&self) -> ReaderOf<'a, Value> {
Expand Down
Loading

0 comments on commit 2dd2b94

Please sign in to comment.