Skip to content

Commit

Permalink
Add ProcMacroHost definition
Browse files Browse the repository at this point in the history
commit-id:18967d01
  • Loading branch information
maciektr committed Feb 6, 2024
1 parent 3a6bcfc commit 4c1e194
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 9 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions scarb/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ cairo-lang-sierra-to-casm.workspace = true
cairo-lang-sierra.workspace = true
cairo-lang-starknet-classes.workspace = true
cairo-lang-starknet.workspace = true
cairo-lang-syntax.workspace = true
cairo-lang-test-plugin.workspace = true
cairo-lang-utils.workspace = true
camino.workspace = true
Expand Down
33 changes: 24 additions & 9 deletions scarb/src/compiler/db.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use anyhow::{anyhow, Result};
use cairo_lang_compiler::db::RootDatabase;
use cairo_lang_compiler::db::{RootDatabase, RootDatabaseBuilder};
use cairo_lang_compiler::project::{AllCratesConfig, ProjectConfig, ProjectConfigContent};
use cairo_lang_defs::db::DefsGroup;
use cairo_lang_defs::ids::ModuleId;
Expand All @@ -11,6 +11,8 @@ use smol_str::SmolStr;
use std::sync::Arc;
use tracing::trace;

use crate::compiler::plugin::proc_macro::ProcMacroHostPlugin;
use crate::compiler::plugin::CairoPlugin;
use crate::compiler::{CompilationUnit, CompilationUnitComponent};
use crate::core::Workspace;
use crate::DEFAULT_MODULE_MAIN_FILE;
Expand All @@ -23,19 +25,32 @@ pub(crate) fn build_scarb_root_database(
let mut b = RootDatabase::builder();
b.with_project_config(build_project_config(unit)?);
b.with_cfg(unit.cfg_set.clone());

for plugin_info in &unit.cairo_plugins {
let package_id = plugin_info.package.id;
let plugin = ws.config().cairo_plugins().fetch(package_id)?;
let instance = plugin.instantiate()?;
b.with_plugin_suite(instance.plugin_suite());
}

load_plugins(unit, ws, &mut b)?;
let mut db = b.build()?;
inject_virtual_wrapper_lib(&mut db, unit)?;
Ok(db)
}

fn load_plugins(
unit: &CompilationUnit,
ws: &Workspace<'_>,
builder: &mut RootDatabaseBuilder,
) -> Result<()> {
let mut proc_macros = ProcMacroHostPlugin::default();
for plugin_info in &unit.cairo_plugins {
if plugin_info.builtin {
let package_id = plugin_info.package.id;
let plugin = ws.config().cairo_plugins().fetch(package_id)?;
let instance = plugin.instantiate()?;
builder.with_plugin_suite(instance.plugin_suite());
} else {
proc_macros.register(plugin_info.package.clone());
}
}
builder.with_plugin_suite(proc_macros.instantiate()?.plugin_suite());
Ok(())
}

/// Generates a wrapper lib file for appropriate compilation units.
///
/// This approach allows compiling crates that do not define `lib.cairo` file.
Expand Down
1 change: 1 addition & 0 deletions scarb/src/compiler/plugin/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::core::PackageId;
use self::builtin::{BuiltinStarkNetPlugin, BuiltinTestPlugin};

pub mod builtin;
pub mod proc_macro;

pub trait CairoPlugin: Sync {
fn id(&self) -> PackageId;
Expand Down
101 changes: 101 additions & 0 deletions scarb/src/compiler/plugin/proc_macro/host.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
use crate::compiler::plugin::{CairoPlugin, CairoPluginInstance};
use crate::core::{Package, PackageId, PackageName, SourceId};
use crate::internal::to_version::ToVersion;
use anyhow::Result;
use cairo_lang_defs::plugin::{MacroPlugin, MacroPluginMetadata, PluginResult};
use cairo_lang_semantic::plugin::PluginSuite;
use cairo_lang_syntax::node::ast::ModuleItem;
use cairo_lang_syntax::node::db::SyntaxGroup;
use smol_str::SmolStr;
use std::collections::HashMap;
use std::sync::Arc;
use typed_builder::TypedBuilder;

#[derive(Debug, Clone)]
pub struct ProcMacroInstance {}

impl ProcMacroInstance {
pub fn new(_package: Package) -> Self {
// Load shared library
// TODO(maciektr): Implement
Self {}
}
}

#[derive(Debug, TypedBuilder)]
pub struct ProcMacroHost {
macros: HashMap<SmolStr, Box<ProcMacroInstance>>,
}

impl MacroPlugin for ProcMacroHost {
fn generate_code(
&self,
_db: &dyn SyntaxGroup,
_item_ast: ModuleItem,
_metadata: &MacroPluginMetadata<'_>,
) -> PluginResult {
// Apply expansion to `item_ast` where needed.
// TODO(maciektr): Implement
PluginResult::default()
}

fn declared_attributes(&self) -> Vec<String> {
self.macros.keys().map(|name| name.to_string()).collect()
}
}

#[derive(Default)]
pub struct ProcMacroHostPlugin {
macros: HashMap<SmolStr, Box<ProcMacroInstance>>,
}

impl ProcMacroHostPlugin {
pub fn plugin_id() -> PackageId {
PackageId::new(
PackageName::PROC_MACRO_HOST,
crate::version::get().cairo.version.to_version().unwrap(),
SourceId::for_std(),
)
}

pub fn register(&mut self, package: Package) {
// Create instance
// Register instance in hash map
let name = package.id.name.to_smol_str();
let instance = ProcMacroInstance::new(package);
self.macros.insert(name, Box::new(instance));
}
}

impl CairoPlugin for ProcMacroHostPlugin {
fn id(&self) -> PackageId {
Self::plugin_id()
}

fn instantiate(&self) -> Result<Box<dyn CairoPluginInstance>> {
let instance = ProcMacroHostPluginInstance::builder()
.macros(self.macros.clone())
.build();
Ok(Box::new(instance))
}
}

#[derive(TypedBuilder)]
pub struct ProcMacroHostPluginInstance {
macros: HashMap<SmolStr, Box<ProcMacroInstance>>,
}

impl ProcMacroHostPluginInstance {
/// Build compiler `MacroPlugin` from Scarb representation `ProcMacroHostPluginInstance`.
pub fn build(&self) -> ProcMacroHost {
ProcMacroHost::builder().macros(self.macros.clone()).build()
}
}

impl CairoPluginInstance for ProcMacroHostPluginInstance {
fn plugin_suite(&self) -> PluginSuite {
let mut suite = PluginSuite::default();
suite.add_plugin_ex(Arc::new(self.build()));
suite
}
}
3 changes: 3 additions & 0 deletions scarb/src/compiler/plugin/proc_macro/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mod host;

pub use host::*;
1 change: 1 addition & 0 deletions scarb/src/core/package/name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ impl PackageName {
pub const CORE: Self = PackageName(SmolStr::new_inline(CORELIB_CRATE_NAME));
pub const STARKNET: Self = PackageName(SmolStr::new_inline("starknet"));
pub const TEST_PLUGIN: Self = PackageName(SmolStr::new_inline("test_plugin"));
pub const PROC_MACRO_HOST: Self = PackageName(SmolStr::new_inline("proc_macro_host"));

/// Constructs and validates new [`PackageName`].
///
Expand Down

0 comments on commit 4c1e194

Please sign in to comment.