Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement procedural macro diagnostics #1159

Merged
merged 1 commit into from
Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion plugins/cairo-lang-macro-attributes/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,5 @@ repository.workspace = true
proc-macro = true

[dependencies]
camino.workspace = true
quote.workspace = true
syn = { workspace = true, features = ["full", "extra-traits"] }
10 changes: 7 additions & 3 deletions plugins/cairo-lang-macro-attributes/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,14 @@ pub fn attribute_macro(_args: TokenStream, input: TokenStream) -> TokenStream {
#item

#[no_mangle]
pub unsafe extern "C" fn expand(token_stream: cairo_lang_macro_stable::StableTokenStream) -> cairo_lang_macro_stable::StableProcMacroResult {
let token_stream = cairo_lang_macro::TokenStream::from_stable(token_stream);
pub unsafe extern "C" fn expand(stable_token_stream: cairo_lang_macro_stable::StableTokenStream) -> cairo_lang_macro_stable::StableResultWrapper {
let token_stream = cairo_lang_macro::TokenStream::from_stable(&stable_token_stream);
let result = #item_name(token_stream);
result.into_stable()
let result: cairo_lang_macro_stable::StableProcMacroResult = result.into_stable();
cairo_lang_macro_stable::StableResultWrapper {
input: stable_token_stream,
output: result,
}
}
};
TokenStream::from(expanded)
Expand Down
37 changes: 37 additions & 0 deletions plugins/cairo-lang-macro-stable/src/ffi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/// This struct encapsulates a stable ABI representation of information required to construct a slice.
///
/// Please be aware that the memory management of values passing the FFI-barrier is tricky.
maciektr marked this conversation as resolved.
Show resolved Hide resolved
/// The memory must be freed on the same side of the barrier, where the allocation was made.
#[repr(C)]
#[derive(Debug)]
#[doc(hidden)]
pub struct StableSlice<T> {
maciektr marked this conversation as resolved.
Show resolved Hide resolved
ptr: *mut T,
len: usize,
}

impl<T> StableSlice<T> {
/// Create a new `StableSlice` from a Vector.
/// Note that the vector will not be deallocated automatically.
/// Please make sure to use `into_owned` afterward, to free the memory.
pub fn new(mut x: Vec<T>) -> Self {
x.shrink_to_fit();
assert_eq!(x.len(), x.capacity());
maciektr marked this conversation as resolved.
Show resolved Hide resolved
let ptr = x.as_mut_ptr();
let len = x.len();
std::mem::forget(x);
Self { ptr, len }
}

/// Convert to owned vector.
pub fn into_owned(self) -> Vec<T> {
unsafe { Vec::from_raw_parts(self.ptr, self.len, self.len) }
}

/// Returns raw pointer and length.
/// Can be used to construct a slice.
/// No ownership is transferred.
pub fn raw_parts(&self) -> (*mut T, usize) {
(self.ptr, self.len)
}
}
40 changes: 35 additions & 5 deletions plugins/cairo-lang-macro-stable/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,65 @@
use crate::ffi::StableSlice;
use std::ffi::{CStr, CString};
use std::num::NonZeroU8;
use std::os::raw::c_char;

pub mod ffi;

/// Token stream.
///
/// This struct implements FFI-safe stable ABI.
#[repr(C)]
#[derive(Debug, Clone)]
#[derive(Debug)]
pub struct StableTokenStream(*mut c_char);

#[repr(C)]
#[derive(Debug, Clone)]
#[derive(Debug)]
pub enum StableAuxData {
None,
Some(*mut c_char),
}

/// Diagnostic returned by the procedural macro.
///
/// This struct implements FFI-safe stable ABI.
#[repr(C)]
#[derive(Debug)]
pub struct StableDiagnostic {
pub message: *mut c_char,
mkaput marked this conversation as resolved.
Show resolved Hide resolved
pub severity: StableSeverity,
}

/// The severity of a diagnostic.
///
/// This struct implements FFI-safe stable ABI.
pub type StableSeverity = NonZeroU8;

/// Procedural macro result.
///
/// This struct implements FFI-safe stable ABI.
#[repr(C)]
#[derive(Debug, Clone)]
#[derive(Debug)]
pub enum StableProcMacroResult {
/// Plugin has not taken any action.
Leave,
Leave {
diagnostics: StableSlice<StableDiagnostic>,
},
/// Plugin generated [`StableTokenStream`] replacement.
Replace {
diagnostics: StableSlice<StableDiagnostic>,
token_stream: StableTokenStream,
aux_data: StableAuxData,
},
/// Plugin ordered item removal.
Remove,
Remove {
diagnostics: StableSlice<StableDiagnostic>,
},
}

#[repr(C)]
pub struct StableResultWrapper {
pub input: StableTokenStream,
pub output: StableProcMacroResult,
}

impl StableTokenStream {
Expand Down
Loading
Loading