yggdrasil/src/syntax/syscall.rs

83 lines
2.1 KiB
Rust

use quote::{quote, ToTokens};
use syn::{parenthesized, parse::ParseStream, punctuated::Punctuated, Ident, Token};
use super::{common::Attributes, document::DocumentItemAttributes};
pub struct SyscallDefinition {
pub attributes: Attributes,
pub name: Ident,
pub arguments: Punctuated<SyscallArgument, Token![,]>,
pub return_type: Option<syn::Type>,
}
pub struct SyscallArgument {
pub name: syn::Ident,
pub ty: syn::Type,
}
impl DocumentItemAttributes for SyscallDefinition {
fn extend_attributes<I: IntoIterator<Item = syn::Attribute>>(&mut self, attrs: I) {
self.attributes.extend(attrs);
}
}
impl syn::parse::Parse for SyscallDefinition {
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
let arguments;
let name = input.parse()?;
parenthesized!(arguments in input);
let arguments = arguments.parse_terminated(SyscallArgument::parse, Token![,])?;
let return_type = if input.peek(Token![->]) {
input.parse::<Token![->]>()?;
let ty = input.parse()?;
Some(ty)
} else {
None
};
input.parse::<Token![;]>()?;
Ok(Self {
attributes: Attributes::new(),
name,
arguments,
return_type,
})
}
}
impl syn::parse::Parse for SyscallArgument {
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
let name = input.parse()?;
input.parse::<Token![:]>()?;
let ty = input.parse()?;
Ok(Self { name, ty })
}
}
impl ToTokens for SyscallArgument {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
let Self { name, ty } = self;
tokens.extend(quote!(#name: #ty))
}
}
impl ToTokens for SyscallDefinition {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
let Self {
attributes,
name,
arguments,
return_type,
} = self;
let return_type = return_type.as_ref().map(|ty| quote!(-> #ty));
tokens.extend(quote! {
#attributes
syscall #name (#arguments) #return_type;
});
}
}