Skip to content

Commit

Permalink
Merge pull request #75 from NLnetLabs/rotodoc
Browse files Browse the repository at this point in the history
Rotodoc
  • Loading branch information
tertsdiepraam authored Nov 14, 2024
2 parents 89fcc50 + 05604d9 commit 730f285
Show file tree
Hide file tree
Showing 9 changed files with 361 additions and 58 deletions.
4 changes: 2 additions & 2 deletions examples/presentation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,9 @@ fn main() -> Result<(), Box<dyn Error>> {

// Registering types and their methods

rt.register_clone_type_with_name::<RotondaRoute>("Route")?;
rt.register_clone_type_with_name::<RotondaRoute>("Route", "A route")?;

rt.register_clone_type_with_name::<Log>("Log")?;
rt.register_clone_type_with_name::<Log>("Log", "A thing to log to")?;

#[roto_method(rt, RotondaRoute)]
fn prefix_matches(
Expand Down
4 changes: 3 additions & 1 deletion examples/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ fn main() -> Result<(), roto::RotoReport> {

let mut runtime = Runtime::basic().unwrap();

runtime.register_copy_type::<Bla>().unwrap();
runtime
.register_copy_type::<Bla>("Some random type")
.unwrap();

#[roto_method(runtime, Bla, x)]
fn get_x(bla: *const Bla) -> u32 {
Expand Down
11 changes: 10 additions & 1 deletion examples/simple.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::net::IpAddr;
use std::{env::args, net::IpAddr};

use roto::{read_files, Runtime, Verdict};

Expand All @@ -7,6 +7,15 @@ fn main() -> Result<(), roto::RotoReport> {

let runtime = Runtime::basic().unwrap();

let mut arguments = args();
let _program_name = arguments.next().unwrap();

let subcommand = arguments.next();
if Some("doc") == subcommand.as_deref() {
runtime.print_documentation();
return Ok(())
}

let mut compiled = read_files(["examples/simple.roto"])?
.compile(runtime, usize::BITS / 8)
.inspect_err(|e| eprintln!("{e}"))?;
Expand Down
47 changes: 40 additions & 7 deletions macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,16 +147,45 @@ fn generate_function(item: syn::ItemFn) -> Intermediate {
block: _,
} = item.clone();

let mut docstring = String::new();

for attr in &attrs {
if attr.path().is_ident("doc") {
let value = match &attr.meta {
syn::Meta::NameValue(name_value) => &name_value.value,
_ => panic!("doc attribute must be a name and a value"),
};
let lit = match value {
syn::Expr::Lit(expr_lit) => &expr_lit.lit,
_ => panic!(
"argument to doc attribute must be a string literal"
),
};
let litstr = match lit {
syn::Lit::Str(litstr) => litstr,
_ => panic!(
"argument to doc attribute must be a string literal"
),
};
docstring.push_str(litstr.value().trim());
docstring.push('\n');
}
}

assert!(sig.unsafety.is_none());
assert!(sig.variadic.is_none());

let ident = sig.ident;
let args = sig.inputs.iter().map(|i| {
let syn::FnArg::Typed(syn::PatType { pat, .. }) = i else {
panic!()
};
pat
});
let args: Vec<_> = sig
.inputs
.iter()
.map(|i| {
let syn::FnArg::Typed(syn::PatType { pat, .. }) = i else {
panic!()
};
pat
})
.collect();

let generics = sig.generics;
let inputs = sig.inputs.clone().into_iter();
Expand Down Expand Up @@ -190,7 +219,11 @@ fn generate_function(item: syn::ItemFn) -> Intermediate {
};

let identifier = quote! {
#ident as extern "C" fn(#arg_types)
roto::DocumentedFunc {
func: #ident as extern "C" fn(#arg_types),
docstring: #docstring,
argument_names: &[#(stringify!(#args)),*]
}
};

Intermediate {
Expand Down
5 changes: 3 additions & 2 deletions src/codegen/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,7 @@ fn issue_52() {
}

let mut rt = Runtime::basic().unwrap();
rt.register_clone_type::<Foo>().unwrap();
rt.register_clone_type::<Foo>("A Foo!").unwrap();

#[roto_static_method(rt, Foo)]
fn bar(_x: u32) -> u32 {
Expand Down Expand Up @@ -866,7 +866,8 @@ fn arc_type() {

let mut rt = Runtime::basic().unwrap();

rt.register_clone_type::<CloneDrop>().unwrap();
rt.register_clone_type::<CloneDrop>("A CloneDrop type")
.unwrap();

let s = src!(
"
Expand Down
7 changes: 6 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Needed for the roto macros
extern crate self as roto;

pub(crate) mod ast;

pub(crate) mod codegen;
Expand All @@ -13,4 +16,6 @@ pub use lower::eval::Memory;
pub use lower::value::IrValue;
pub use pipeline::*;
pub use roto_macros::{roto_function, roto_method, roto_static_method};
pub use runtime::{val::Val, verdict::Verdict, Runtime, RuntimeType};
pub use runtime::{
val::Val, verdict::Verdict, DocumentedFunc, Runtime, RuntimeType,
};
46 changes: 45 additions & 1 deletion src/runtime/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ use std::{any::TypeId, sync::Arc};

use crate::{lower::value::ReturnValue, IrValue, Runtime};

use super::ty::{Reflect, TypeRegistry};
use super::{
ty::{Reflect, TypeRegistry},
DocumentedFunc,
};

#[derive(Clone)]
pub struct FunctionDescription {
Expand Down Expand Up @@ -59,10 +62,18 @@ impl std::fmt::Debug for FunctionDescription {
}

pub trait Func<A, R>: Sized {
type FunctionType;

fn parameter_types(reg: &mut TypeRegistry) -> Vec<TypeId>;
fn return_type(reg: &mut TypeRegistry) -> TypeId;
fn ptr(&self) -> *const u8;
fn wrapped(self) -> Arc<dyn Fn(Vec<IrValue>) -> Option<IrValue>>;
fn docstring(&self) -> &'static str {
""
}
fn argument_names(&self) -> &'static [&'static str] {
&[]
}

fn to_function_description(
self,
Expand All @@ -82,6 +93,37 @@ pub trait Func<A, R>: Sized {
}
}

impl<F, A, R> Func<A, R> for DocumentedFunc<F>
where
F: Func<A, R>,
{
type FunctionType = F;

fn parameter_types(reg: &mut TypeRegistry) -> Vec<TypeId> {
F::parameter_types(reg)
}

fn return_type(reg: &mut TypeRegistry) -> TypeId {
F::return_type(reg)
}

fn ptr(&self) -> *const u8 {
self.func.ptr()
}

fn wrapped(self) -> Arc<dyn Fn(Vec<IrValue>) -> Option<IrValue>> {
self.func.wrapped()
}

fn docstring(&self) -> &'static str {
self.docstring
}

fn argument_names(&self) -> &'static [&'static str] {
self.argument_names
}
}

macro_rules! func_impl {
($($arg:ident),*) => {
impl<$($arg,)* Ret> Func<($($arg,)*), Ret> for for<'a> extern "C" fn($($arg),*) -> Ret
Expand All @@ -91,6 +133,8 @@ macro_rules! func_impl {
)*
Ret: Reflect + Into<ReturnValue> + 'static,
{
type FunctionType = Self;

#[allow(unused_variables)]
fn parameter_types(reg: &mut TypeRegistry) -> Vec<TypeId> {
vec![$(reg.resolve::<$arg>().type_id),*]
Expand Down
Loading

0 comments on commit 730f285

Please sign in to comment.