Skip to content

Commit

Permalink
impl classes initial sketch
Browse files Browse the repository at this point in the history
  • Loading branch information
littledivy committed Nov 7, 2023
1 parent be92ba0 commit 32cbe7e
Show file tree
Hide file tree
Showing 13 changed files with 232 additions and 55 deletions.
6 changes: 5 additions & 1 deletion deno_bindgen/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ pub use linkme;
use linkme::distributed_slice;

#[distributed_slice]
pub static INVENTORY: [Symbol];
pub static INVENTORY: [Inventory];

pub trait BindgenType {
fn type_name() -> &'static str;
}

#[no_mangle]
fn init_deno_bindgen(opt: Options) {
Expand Down
109 changes: 68 additions & 41 deletions deno_bindgen_ir/codegen/deno.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ use std::{
io::{Result, Write},
};

use syn::token::In;

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

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

Expand Down Expand Up @@ -93,11 +95,11 @@ impl From<Type> for DenoFfiType {
}

pub struct Codegen<'a> {
symbols: &'a [Symbol],
symbols: &'a [Inventory],
}

impl<'a> Codegen<'a> {
pub fn new(symbols: &'a [Symbol]) -> Self {
pub fn new(symbols: &'a [Inventory]) -> Self {
Self { symbols }
}

Expand Down Expand Up @@ -132,21 +134,26 @@ impl<'a> Codegen<'a> {
}

for symbol in self.symbols {
writeln!(writer, " {}: {{", symbol.name)?;
write!(writer, " parameters: ")?;
format_bracket(writer, symbol.parameters, |writer, parameters| {
for parameter in parameters {
writeln!(writer, " {},", DenoFfiType::from(*parameter))?;
match symbol {
Inventory::Symbol(symbol) => {
writeln!(writer, " {}: {{", symbol.name)?;
write!(writer, " parameters: ")?;
format_bracket(writer, symbol.parameters, |writer, parameters| {
for parameter in parameters {
writeln!(writer, " {},", DenoFfiType::from(*parameter))?;
}
Ok(())
})?;
writeln!(
writer,
" result: {},",
DenoFfiType::from(symbol.return_type)
)?;
writeln!(writer, " nonblocking: {}", symbol.non_blocking)?;
writeln!(writer, " }},")?;
}
Ok(())
})?;
writeln!(
writer,
" result: {},",
DenoFfiType::from(symbol.return_type)
)?;
writeln!(writer, " nonblocking: {}", symbol.non_blocking)?;
writeln!(writer, " }},")?;
_ => {}
}
}

Ok(())
Expand All @@ -166,39 +173,59 @@ impl<'a> Codegen<'a> {
write!(writer, "{:indent$})", "", indent = nesting_spaces)?;
} else {
write!(writer, ")")?;
}
}

Ok(())
}

for symbol in self.symbols {
write!(writer, "export function {}", symbol.name)?;
format_paren(writer, symbol.parameters, |writer, parameters| {
for (i, parameter) in parameters.iter().enumerate() {
match symbol {
Inventory::Symbol(symbol) => {
write!(writer, "export function {}", symbol.name)?;
format_paren(
writer,
symbol.parameters,
|writer, parameters| {
for (i, parameter) in parameters.iter().enumerate() {
writeln!(
writer,
" arg{}: {},",
i,
TypeScriptType::from(*parameter)
)?;
}
Ok(())
},
0,
)?;
writeln!(
writer,
" arg{}: {},",
i,
TypeScriptType::from(*parameter)
": {} {{",
TypeScriptType::from(symbol.return_type)
.apply_promise(symbol.non_blocking)
)?;
write!(writer, " return symbols.{}", symbol.name)?;
format_paren(
writer,
symbol.parameters,
|writer, parameters| {
for (i, parameter) in parameters.iter().enumerate() {
let ident = format!("arg{}", i);
writeln!(
writer,
" {},",
TypeScriptType::from(*parameter).into_raw(&ident)
)?;
}
Ok(())
},
2,
)?;
}
Ok(())
}, 0)?;
writeln!(writer, ": {} {{", TypeScriptType::from(symbol.return_type).apply_promise(symbol.non_blocking))?;
write!(writer, " return symbols.{}", symbol.name)?;
format_paren(writer, symbol.parameters, |writer, parameters| {
for (i, parameter) in parameters.iter().enumerate() {
let ident = format!("arg{}", i);
writeln!(
writer,
" {},",
TypeScriptType::from(*parameter).into_raw(&ident)
)?;
}
Ok(())
}, 2)?;

writeln!(writer, "\n}}\n")?;
writeln!(writer, "\n}}\n")?;
}
_ => {}
}
}

Ok(())
Expand Down
4 changes: 2 additions & 2 deletions deno_bindgen_ir/codegen/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::path::PathBuf;

use crate::Symbol;
use crate::{inventory::Inventory, Symbol};

mod deno;

Expand All @@ -18,7 +18,7 @@ pub trait Generator {
}

pub fn generate(
symbols: &'static [Symbol],
symbols: &'static [Inventory],
opt: Options,
) -> std::io::Result<()> {
let mut codegen = match opt.target {
Expand Down
13 changes: 13 additions & 0 deletions deno_bindgen_ir/inventory.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use crate::Symbol;

#[derive(Debug)]
pub struct Struct {
pub name: &'static str,
pub constructor: Option<Symbol>,
pub methods: &'static [Symbol],
}

pub enum Inventory {
Symbol(Symbol),
Struct(Struct),
}
5 changes: 4 additions & 1 deletion deno_bindgen_ir/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use proc_macro2::Ident;
use quote::{format_ident, quote, ToTokens};
use quote::{quote, ToTokens};
use syn::{parse_quote, Pat};

pub mod codegen;
pub mod inventory;

pub use inventory::Inventory;

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Default)]
pub enum Type {
Expand Down
7 changes: 5 additions & 2 deletions deno_bindgen_macro/src/fn_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ use syn::{
ItemFn, PatType, ReturnType, TypePath, TypePtr, TypeReference, TypeSlice,
};

use crate::{util::{Error, Result}, FnAttributes};
use crate::{
util::{Error, Result},
FnAttributes,
};

fn parse_type(ty: &Box<syn::Type>) -> Result<Type> {
match **ty {
Expand Down Expand Up @@ -168,7 +171,7 @@ pub fn handle(fn_: ItemFn, attrs: FnAttributes) -> Result<TokenStream2> {
Ok(quote::quote! {
const _: () = {
#[deno_bindgen::linkme::distributed_slice(deno_bindgen::INVENTORY)]
pub static _A: deno_bindgen::Symbol = #symbol;
pub static _A: deno_bindgen::Inventory = deno_bindgen::Inventory::Symbol(#symbol);
};

#[no_mangle]
Expand Down
46 changes: 46 additions & 0 deletions deno_bindgen_macro/src/impl_.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use proc_macro2::TokenStream as TokenStream2;
use syn::ItemImpl;

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

pub fn handle(impl_: ItemImpl) -> Result<TokenStream2> {
if impl_.generics.params.first().is_some() {
return Err(util::Error::Generics);
}

if impl_.generics.where_clause.is_some() {
return Err(util::Error::WhereClause);
}

let self_ty = match *impl_.self_ty {
syn::Type::Path(ref type_path) => type_path.path.clone(),
_ => return Err(util::Error::UnsupportedType),
};

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

// 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
// - constructor is a simply special case with no self ptr.
// - we also need to be aware of &mut self and Self types.

Ok(quote::quote! {
#impl_

const _: () = {
// Assert that the type implements `BindgenType`.
const fn _assert_impl<T: ::deno_bindgen::BindgenType>() {}
_assert_impl::<#ty_str>();

#[deno_bindgen::linkme::distributed_slice(deno_bindgen::INVENTORY)]
pub static _B: deno_bindgen::Inventory = deno_bindgen::Inventory::Struct(
deno_bindgen::inventory::Struct {
name: stringify!(#ty_str),
constructor: None,
methods: &[],
}
);
};
})
}
22 changes: 16 additions & 6 deletions deno_bindgen_macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@
use deno_bindgen_ir::Symbol;
use proc_macro::TokenStream;
use quote::{format_ident, quote};
use syn::{parse_macro_input, parse_quote, ItemFn, meta::ParseNestedMeta};
use syn::{
meta::ParseNestedMeta, parse2, parse_macro_input, parse_quote, Item, ItemFn,
};

mod fn_;
mod impl_;
mod struct_;
mod util;

#[derive(Default)]
Expand All @@ -26,10 +30,16 @@ impl FnAttributes {

#[proc_macro_attribute]
pub fn deno_bindgen(args: TokenStream, input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as ItemFn);
let mut attrs = FnAttributes::default();
let attrs_parser = syn::meta::parser(|meta| attrs.parse(meta));
parse_macro_input!(args with attrs_parser);
match parse2::<Item>(input.into()).unwrap() {
Item::Fn(input) => {
let mut attrs = FnAttributes::default();
let attrs_parser = syn::meta::parser(|meta| attrs.parse(meta));
parse_macro_input!(args with attrs_parser);

fn_::handle(input, attrs).unwrap().into()
fn_::handle(input, attrs).unwrap().into()
}
Item::Struct(input) => struct_::handle(input).unwrap().into(),
Item::Impl(input) => impl_::handle(input).unwrap().into(),
_ => panic!("only functions are supported"),
}
}
25 changes: 25 additions & 0 deletions deno_bindgen_macro/src/struct_.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use proc_macro2::TokenStream as TokenStream2;
use syn::ItemStruct;

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

pub fn handle(struct_: ItemStruct) -> Result<TokenStream2> {
if struct_.generics.params.first().is_some() {
return Err(util::Error::Generics);
}

if struct_.generics.where_clause.is_some() {
return Err(util::Error::WhereClause);
}

let ref ty_str @ _ = struct_.ident;
Ok(quote::quote! {
#struct_

impl ::deno_bindgen::BindgenType for #ty_str {
fn type_name() -> &'static str {
stringify!(#ty_str)
}
}
})
}
4 changes: 4 additions & 0 deletions deno_bindgen_macro/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ pub enum Error {
Asyncness,
Reciever,
UnsupportedType,
Generics,
WhereClause,
}

impl std::fmt::Display for Error {
Expand All @@ -11,6 +13,8 @@ impl std::fmt::Display for Error {
Error::Asyncness => write!(f, "async functions are not supported"),
Error::Reciever => write!(f, "methods are not supported"),
Error::UnsupportedType => write!(f, "unsupported type"),
Error::Generics => write!(f, "generics are not supported"),
Error::WhereClause => write!(f, "where clauses are not supported"),
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions example/bindings_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,13 @@ Deno.test({
},
});


Deno.test({
name: "non_blocking#test",
fn: async () => {
const result = await non_blocking();
assertEquals(result, 42);
},
});
});

// struct (glorified pointers)
// impl on struct
Loading

0 comments on commit 32cbe7e

Please sign in to comment.