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

Dev #1750

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from
Draft

Dev #1750

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
21 changes: 16 additions & 5 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ members = [
"plugins/cairo-lang-macro",
"plugins/cairo-lang-macro-attributes",
"plugins/cairo-lang-macro-stable",
"plugins/cairo-lang-quote",
"utils/create-output-dir",
"utils/scarb-proc-macro-server-types",
"utils/scarb-build-metadata",
Expand All @@ -35,6 +36,7 @@ anyhow = "1"
assert_fs = "1"
async-trait = "0.1"
axum = { version = "0.6", features = ["http2"] }
bumpalo = "3"
cairo-lang-compiler = "2.9.1"
cairo-lang-defs = "2.9.1"
cairo-lang-diagnostics = "2.9.1"
Expand Down
37 changes: 24 additions & 13 deletions plugins/cairo-lang-macro-stable/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,31 @@
use crate::ffi::{StableOption, StableSlice};
use std::ffi::CStr;
use std::num::NonZeroU8;
use std::os::raw::c_char;
use std::ptr::NonNull;

pub mod ffi;

#[repr(C)]
#[derive(Debug)]
pub struct StableToken {
pub span: StableTextSpan,
pub ptr: *const u8,
pub len: usize,
}

#[repr(C)]
#[derive(Debug)]
pub struct StableTextSpan {
pub start: u32,
pub end: u32,
}

#[repr(C)]
#[derive(Debug)]
pub enum StableTokenTree {
Ident(StableToken),
}

#[repr(C)]
#[derive(Debug)]
pub struct StableExpansion {
Expand All @@ -23,8 +43,9 @@ pub type StableExpansionsList = StableSlice<StableExpansion>;
#[repr(C)]
#[derive(Debug)]
pub struct StableTokenStream {
pub value: *mut c_char,
pub tokens: StableSlice<StableTokenTree>,
pub metadata: StableTokenStreamMetadata,
pub size_hint: usize,
}

/// Token stream metadata.
Expand All @@ -35,6 +56,7 @@ pub struct StableTokenStream {
pub struct StableTokenStreamMetadata {
pub original_file_path: Option<NonNull<c_char>>,
pub file_id: Option<NonNull<c_char>>,
pub edition: Option<NonNull<c_char>>,
}

/// Auxiliary data returned by the procedural macro.
Expand Down Expand Up @@ -76,17 +98,6 @@ pub struct StableResultWrapper {
pub output: StableProcMacroResult,
}

impl StableTokenStream {
/// Convert to String.
///
/// # Safety
pub unsafe fn to_string(&self) -> String {
// Note that this does not deallocate the c-string.
// The memory must still be freed with `CString::from_raw`.
CStr::from_ptr(self.value).to_string_lossy().to_string()
}
}

#[repr(C)]
pub struct StablePostProcessContext {
pub aux_data: StableSlice<StableAuxData>,
Expand Down
9 changes: 6 additions & 3 deletions plugins/cairo-lang-macro/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "cairo-lang-macro"
version = "0.1.1"
edition.workspace = true
rust-version = "1.64"
rust-version = "1.73"

authors.workspace = true
categories = ["development-tools"]
Expand All @@ -14,8 +14,11 @@ readme = "README.md"
repository.workspace = true

[dependencies]
cairo-lang-macro-attributes = "0.1"
cairo-lang-macro-stable = "1"
bumpalo.workspace = true
cairo-lang-macro-attributes = { path = "../cairo-lang-macro-attributes" }
cairo-lang-macro-stable = { path = "../cairo-lang-macro-stable" }
cairo-lang-primitive-token = "1.0.0"
cairo-lang-quote = { path = "../cairo-lang-quote", version = "0.1.0" }
linkme.workspace = true
serde = { workspace = true, optional = true }

Expand Down
77 changes: 51 additions & 26 deletions plugins/cairo-lang-macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,28 @@
//!

pub use cairo_lang_macro_attributes::*;
pub use cairo_lang_quote::*;

#[doc(hidden)]
pub use linkme;

use std::cell::RefCell;

use cairo_lang_macro_stable::ffi::StableSlice;
use cairo_lang_macro_stable::{
StableExpansionsList, StablePostProcessContext, StableProcMacroResult,
StableExpansionsList, StablePostProcessContext, StableProcMacroResult, StableTextSpan,
};
use std::ffi::{c_char, CStr, CString};
use std::ops::Deref;

mod types;

pub use types::*;

// A thread-local allocation context for allocating tokens on proc macro side.
thread_local!(static CONTEXT: RefCell<AllocationContext> = RefCell::default() );

thread_local!(static CALL_SITE: RefCell<(u32, u32)> = RefCell::default());

#[doc(hidden)]
#[derive(Clone)]
pub struct ExpansionDefinition {
Expand Down Expand Up @@ -94,32 +103,48 @@ pub unsafe extern "C" fn free_expansions_list(list: StableExpansionsList) {
#[no_mangle]
pub unsafe extern "C" fn expand(
item_name: *const c_char,
call_site: StableTextSpan,
stable_attr: cairo_lang_macro_stable::StableTokenStream,
stable_token_stream: cairo_lang_macro_stable::StableTokenStream,
) -> cairo_lang_macro_stable::StableResultWrapper {
let token_stream = TokenStream::from_stable(&stable_token_stream);
let attr_token_stream = TokenStream::from_stable(&stable_attr);
let item_name = CStr::from_ptr(item_name).to_string_lossy().to_string();
let fun = MACRO_DEFINITIONS_SLICE
.iter()
.find_map(|m| {
if m.name == item_name.as_str() {
Some(m.fun.clone())
} else {
None
}
})
.expect("procedural macro not found");
let result = match fun {
ExpansionFunc::Attr(fun) => fun(attr_token_stream, token_stream),
ExpansionFunc::Other(fun) => fun(token_stream),
};
let result: StableProcMacroResult = result.into_stable();
cairo_lang_macro_stable::StableResultWrapper {
input: stable_token_stream,
input_attr: stable_attr,
output: result,
}
CONTEXT.with(|ctx_cell| {
// Read size hint from stable token stream. This will be used to create a sufficiently
// large bump allocation buffer.
let size_hint: usize = stable_token_stream.size_hint + stable_attr.size_hint;
// Replace the allocation context with a new one.
// If there is no interned string guards, the old context will be de-allocated.
ctx_cell.replace(AllocationContext::with_capacity(size_hint));
let ctx_borrow = ctx_cell.borrow();
let ctx: &AllocationContext = ctx_borrow.deref();
// Set the call site for the current expand call.
CALL_SITE.replace((call_site.start, call_site.end));
// Copy the stable token stream into current context.
let token_stream = TokenStream::from_stable_in(&stable_token_stream, ctx);
let attr_token_stream = TokenStream::from_stable_in(&stable_attr, ctx);
let item_name = CStr::from_ptr(item_name)
.to_str()
.expect("item name must be a valid string");
let fun = MACRO_DEFINITIONS_SLICE
.iter()
.find_map(|m| {
if m.name == item_name {
Some(m.fun.clone())
} else {
None
}
})
.expect("procedural macro not found");
let result = match fun {
ExpansionFunc::Attr(fun) => fun(attr_token_stream, token_stream),
ExpansionFunc::Other(fun) => fun(token_stream),
};
let result: StableProcMacroResult = result.into_stable();
cairo_lang_macro_stable::StableResultWrapper {
input: stable_token_stream,
input_attr: stable_attr,
output: result,
}
})
}

/// Free the memory allocated for the [`StableProcMacroResult`].
Expand All @@ -134,7 +159,7 @@ pub unsafe extern "C" fn expand(
#[doc(hidden)]
#[no_mangle]
pub unsafe extern "C" fn free_result(result: StableProcMacroResult) {
ProcMacroResult::from_owned_stable(result);
ProcMacroResult::free_owned_stable(result);
}

/// Distributed slice for storing auxiliary data collection callback pointers.
Expand Down
Loading
Loading