Skip to content

Commit

Permalink
impl part 2
Browse files Browse the repository at this point in the history
  • Loading branch information
littledivy committed Nov 8, 2023
1 parent 32cbe7e commit 610d035
Show file tree
Hide file tree
Showing 7 changed files with 224 additions and 24 deletions.
101 changes: 92 additions & 9 deletions deno_bindgen_ir/codegen/deno.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ use std::{
io::{Result, Write},
};

use syn::token::In;

use super::Generator;
use crate::{inventory::Inventory, Symbol, Type};
use crate::{
inventory::{Inventory, Struct},
Symbol, Type,
};

struct TypeScriptType<'a>(&'a str);

Expand Down Expand Up @@ -163,16 +164,19 @@ impl<'a> Codegen<'a> {
fn format_paren<W: Write, T>(
writer: &mut W,
items: &[T],
allow_empty: bool,
callback: impl Fn(&mut W, &[T]) -> Result<()>,
nesting_spaces: usize,
delim: (char, char),
) -> Result<()> {
write!(writer, "(")?;
if items.len() > 0 {
let (start, end) = delim;
write!(writer, "{start}")?;
if items.len() > 0 || allow_empty {
write!(writer, "\n")?;
callback(writer, items)?;
write!(writer, "{:indent$})", "", indent = nesting_spaces)?;
write!(writer, "{:indent$}{end}", "", indent = nesting_spaces)?;
} else {
write!(writer, ")")?;
write!(writer, "{end}")?;
}

Ok(())
Expand All @@ -181,10 +185,14 @@ impl<'a> Codegen<'a> {
for symbol in self.symbols {
match symbol {
Inventory::Symbol(symbol) => {
write!(writer, "export function {}", symbol.name)?;
if !symbol.internal {
write!(writer, "export ")?;
}
write!(writer, "function {}", symbol.name)?;
format_paren(
writer,
symbol.parameters,
false,
|writer, parameters| {
for (i, parameter) in parameters.iter().enumerate() {
writeln!(
Expand All @@ -197,6 +205,7 @@ impl<'a> Codegen<'a> {
Ok(())
},
0,
('(', ')'),
)?;
writeln!(
writer,
Expand All @@ -208,6 +217,7 @@ impl<'a> Codegen<'a> {
format_paren(
writer,
symbol.parameters,
false,
|writer, parameters| {
for (i, parameter) in parameters.iter().enumerate() {
let ident = format!("arg{}", i);
Expand All @@ -220,11 +230,84 @@ impl<'a> Codegen<'a> {
Ok(())
},
2,
('(', ')'),
)?;

writeln!(writer, "\n}}\n")?;
}
_ => {}
Inventory::Struct(Struct {
name,
methods,
constructor,
}) => {
write!(writer, "export class {name} ")?;

format_paren(
writer,
&methods,
false,
|writer, methods| {
writeln!(writer, " ptr: Deno.PointerObject | null = null;\n")?;

writeln!(
writer,
" static __constructor(ptr: Deno.PointerObject) {{"
)?;
writeln!(
writer,
" const self = Object.create({name}.prototype);"
)?;
writeln!(writer, " self.ptr = ptr;")?;
writeln!(writer, " return self;")?;
writeln!(writer, " }}")?;

for method in methods {
// Skip the first argument, which is always the pointer to the struct.
let parameters = &method.parameters[1..];
writeln!(
writer,
"\n {name}({parameters}): {return_type} {{",
name = method.name,
parameters = parameters
.iter()
.enumerate()
.map(|(i, parameter)| {
format!("arg{}: {}", i, TypeScriptType::from(*parameter))
})
.collect::<Vec<_>>()
.join(", "),
return_type = TypeScriptType::from(method.return_type)
)?;

write!(writer, " return {}", method.name)?;
format_paren(
writer,
parameters,
true,
|writer, parameters| {
writeln!(writer, " this.ptr,",)?;
for (i, parameter) in parameters.iter().enumerate() {
let ident = format!("arg{}", i);
writeln!(
writer,
" {},",
TypeScriptType::from(*parameter).into_raw(&ident)
)?;
}
Ok(())
},
4,
('(', ')'),
)?;

writeln!(writer, "\n }}")?;
}
Ok(())
},
0,
('{', '}'),
)?;
}
}
}

Expand Down
9 changes: 9 additions & 0 deletions deno_bindgen_ir/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,15 @@ pub struct Symbol {
pub parameters: &'static [Type],
pub return_type: Type,
pub non_blocking: bool,
pub internal: bool,
}

pub struct SymbolBuilder {
name: Ident,
parameters: Vec<Type>,
return_type: Type,
non_blocking: bool,
internal: bool,
}

impl SymbolBuilder {
Expand All @@ -128,6 +130,7 @@ impl SymbolBuilder {
parameters: Vec::new(),
return_type: Default::default(),
non_blocking: false,
internal: false,
}
}

Expand All @@ -142,6 +145,10 @@ impl SymbolBuilder {
pub fn non_blocking(&mut self, non_blocking: bool) {
self.non_blocking = non_blocking;
}

pub fn internal(&mut self, internal: bool) {
self.internal = internal;
}
}

impl ToTokens for SymbolBuilder {
Expand All @@ -154,13 +161,15 @@ impl ToTokens for SymbolBuilder {
let return_type = &self.return_type.to_ident();
let non_blocking = &self.non_blocking;
let name = &self.name;
let internal = &self.internal;

tokens.extend(quote! {
deno_bindgen::Symbol {
name: stringify!(#name),
parameters: &[#(#parameters),*],
return_type: #return_type,
non_blocking: #non_blocking,
internal: #internal,
}
});
}
Expand Down
30 changes: 21 additions & 9 deletions deno_bindgen_macro/src/fn_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ fn parse_type(ty: &Box<syn::Type>) -> Result<Type> {
}
}

pub fn handle(fn_: ItemFn, attrs: FnAttributes) -> Result<TokenStream2> {
pub fn handle_inner(
fn_: ItemFn,
attrs: FnAttributes,
) -> Result<(TokenStream2, SymbolBuilder)> {
if fn_.sig.asyncness.is_some() {
return Err(Error::Asyncness);
}
Expand All @@ -74,6 +77,7 @@ pub fn handle(fn_: ItemFn, attrs: FnAttributes) -> Result<TokenStream2> {

let mut symbol = SymbolBuilder::new(fn_.sig.ident.clone());
symbol.non_blocking(attrs.non_blocking);
symbol.internal(attrs.internal);

// Cannot use enumerate here, there can be multiple raw args per type.
let mut i = 0;
Expand Down Expand Up @@ -168,13 +172,21 @@ pub fn handle(fn_: ItemFn, attrs: FnAttributes) -> Result<TokenStream2> {
#ret_ident
});

Ok(quote::quote! {
const _: () = {
#[deno_bindgen::linkme::distributed_slice(deno_bindgen::INVENTORY)]
pub static _A: deno_bindgen::Inventory = deno_bindgen::Inventory::Symbol(#symbol);
};
Ok((
quote::quote! {
const _: () = {
#[deno_bindgen::linkme::distributed_slice(deno_bindgen::INVENTORY)]
pub static _A: deno_bindgen::Inventory = deno_bindgen::Inventory::Symbol(#symbol);
};

#[no_mangle]
#ffi_fn
},
symbol,
))
}

#[no_mangle]
#ffi_fn
})
pub fn handle(fn_: ItemFn, attrs: FnAttributes) -> Result<TokenStream2> {
let (ffi_fn, _) = handle_inner(fn_, attrs)?;
Ok(ffi_fn)
}
44 changes: 41 additions & 3 deletions deno_bindgen_macro/src/impl_.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use proc_macro2::TokenStream as TokenStream2;
use syn::ItemImpl;
use syn::{parse_quote, ImplItemFn, ItemImpl, parse, punctuated::Punctuated};

use crate::util::{self, Result};

Expand All @@ -19,6 +19,44 @@ pub fn handle(impl_: ItemImpl) -> Result<TokenStream2> {

let ref ty_str @ _ = self_ty.get_ident().unwrap();

let mut methods = Vec::new();
let mut syms = Punctuated::<TokenStream2, syn::Token![,]>::new();
for item in impl_.items.iter() {
match item {
syn::ImplItem::Fn(ImplItemFn { sig, .. }) => {
if sig.receiver().is_some() {
let ref method_name = sig.ident;
let ref out = sig.output;
let inputs = sig.inputs.iter().skip(1).collect::<Vec<_>>();
let idents = inputs
.iter()
.map(|arg| match arg {
syn::FnArg::Receiver(_) => unreachable!(),
syn::FnArg::Typed(pat_type) => match &*pat_type.pat {
syn::Pat::Ident(ident) => ident.ident.clone(),
_ => unreachable!(),
},
})
.collect::<Vec<_>>();
let method = parse_quote! {
fn #method_name (self_: *mut #ty_str, #(#inputs),*) #out {
let self_ = unsafe { &mut *self_ };
self_. #method_name (#(#idents),*)
}
};

let (generated, sym) = crate::fn_::handle_inner(method, crate::FnAttributes {
internal: true,
..Default::default()
})?;
methods.push(generated);
syms.push(quote::quote! { #sym });
}
}
_ => {}
}
}

// TODO:
// - create a new quoted function for each method and codegen using fn_::handle
// where first arg is self ptr and rest are method args
Expand All @@ -27,7 +65,7 @@ pub fn handle(impl_: ItemImpl) -> Result<TokenStream2> {

Ok(quote::quote! {
#impl_

#(#methods)*
const _: () = {
// Assert that the type implements `BindgenType`.
const fn _assert_impl<T: ::deno_bindgen::BindgenType>() {}
Expand All @@ -38,7 +76,7 @@ pub fn handle(impl_: ItemImpl) -> Result<TokenStream2> {
deno_bindgen::inventory::Struct {
name: stringify!(#ty_str),
constructor: None,
methods: &[],
methods: &[#syms],
}
);
};
Expand Down
1 change: 1 addition & 0 deletions deno_bindgen_macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ mod util;
#[derive(Default)]
pub(crate) struct FnAttributes {
pub(crate) non_blocking: bool,
pub(crate) internal: bool,
}

impl FnAttributes {
Expand Down
Loading

0 comments on commit 610d035

Please sign in to comment.