Skip to content

Commit

Permalink
Added selector inline macro for starknet.
Browse files Browse the repository at this point in the history
commit-id:5bae488f
  • Loading branch information
orizi committed Aug 17, 2023
1 parent 9b14a9b commit b98ade6
Show file tree
Hide file tree
Showing 17 changed files with 88 additions and 37 deletions.
4 changes: 2 additions & 2 deletions crates/cairo-lang-compiler/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,10 @@ impl RootDatabaseBuilder {

pub fn with_inline_macro_plugin(
&mut self,
name: String,
name: &str,
plugin: Arc<dyn InlineMacroExprPlugin>,
) -> &mut Self {
self.inline_macro_plugins.insert(name, plugin);
self.inline_macro_plugins.insert(name.into(), plugin);
self
}

Expand Down
2 changes: 2 additions & 0 deletions crates/cairo-lang-language-server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ use cairo_lang_semantic::items::imp::ImplId;
use cairo_lang_semantic::items::us::get_use_segments;
use cairo_lang_semantic::resolve::{AsSegments, ResolvedConcreteItem, ResolvedGenericItem};
use cairo_lang_semantic::{SemanticDiagnostic, TypeLongId};
use cairo_lang_starknet::inline_macros::selector::SelectorMacro;
use cairo_lang_starknet::plugin::StarkNetPlugin;
use cairo_lang_syntax::node::ast::PathSegment;
use cairo_lang_syntax::node::helpers::GetIdentifier;
Expand Down Expand Up @@ -81,6 +82,7 @@ pub async fn serve_language_service() {
let db = RootDatabase::builder()
.with_cfg(CfgSet::from_iter([Cfg::name("test")]))
.with_macro_plugin(Arc::new(StarkNetPlugin::default()))
.with_inline_macro_plugin(SelectorMacro::NAME, Arc::new(SelectorMacro))
.build()
.expect("Failed to initialize Cairo compiler database.");

Expand Down
2 changes: 1 addition & 1 deletion crates/cairo-lang-semantic/src/inline_macros/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub fn get_default_inline_macro_plugins() -> OrderedHashMap<String, Arc<dyn Inli
res
}

fn unsupported_bracket_diagnostic(
pub fn unsupported_bracket_diagnostic(
db: &dyn SyntaxGroup,
macro_ast: &ast::ExprInlineMacro,
) -> InlinePluginResult {
Expand Down
2 changes: 2 additions & 0 deletions crates/cairo-lang-starknet/src/abi_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use indoc::indoc;
use pretty_assertions::assert_eq;

use crate::abi::AbiBuilder;
use crate::inline_macros::selector::SelectorMacro;
use crate::plugin::StarkNetPlugin;

#[test]
Expand Down Expand Up @@ -201,6 +202,7 @@ fn test_abi_failure() {
let db = &mut RootDatabase::builder()
.detect_corelib()
.with_macro_plugin(Arc::new(StarkNetPlugin::default()))
.with_inline_macro_plugin(SelectorMacro::NAME, Arc::new(SelectorMacro))
.build()
.unwrap();
let module_id = setup_test_module(
Expand Down
2 changes: 2 additions & 0 deletions crates/cairo-lang-starknet/src/contract_class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use crate::contract::{
find_contracts, get_module_abi_functions, get_selector_and_sierra_function, ContractDeclaration,
};
use crate::felt252_serde::sierra_to_felt252s;
use crate::inline_macros::selector::SelectorMacro;
use crate::plugin::consts::{CONSTRUCTOR_MODULE, EXTERNAL_MODULE, L1_HANDLER_MODULE};
use crate::plugin::StarkNetPlugin;

Expand Down Expand Up @@ -85,6 +86,7 @@ pub fn compile_path(
let mut db = RootDatabase::builder()
.detect_corelib()
.with_macro_plugin(Arc::new(StarkNetPlugin::default()))
.with_inline_macro_plugin(SelectorMacro::NAME, Arc::new(SelectorMacro))
.build()?;

let main_crate_ids = setup_project(&mut db, Path::new(&path))?;
Expand Down
1 change: 1 addition & 0 deletions crates/cairo-lang-starknet/src/inline_macros/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod selector;
46 changes: 46 additions & 0 deletions crates/cairo-lang-starknet/src/inline_macros/selector.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use cairo_lang_defs::plugin::{InlineMacroExprPlugin, InlinePluginResult, PluginDiagnostic};
use cairo_lang_semantic::inline_macros::unsupported_bracket_diagnostic;
use cairo_lang_syntax::node::db::SyntaxGroup;
use cairo_lang_syntax::node::{ast, TypedSyntaxNode};

use crate::contract::starknet_keccak;

/// Macro for expanding a selector to a string literal.
#[derive(Debug, Default)]
pub struct SelectorMacro;
impl SelectorMacro {
pub const NAME: &'static str = "selector";
}
impl InlineMacroExprPlugin for SelectorMacro {
fn generate_code(
&self,
db: &dyn SyntaxGroup,
syntax: &ast::ExprInlineMacro,
) -> InlinePluginResult {
let ast::WrappedExprList::ParenthesizedExprList(args) = syntax.arguments(db) else {
return unsupported_bracket_diagnostic(db, syntax);
};

let arguments = &args.expressions(db).elements(db);
if arguments.len() != 1 {
let diagnostics = vec![PluginDiagnostic {
stable_ptr: syntax.stable_ptr().untyped(),
message: "selector macro must have a single argument".to_string(),
}];
return InlinePluginResult { code: None, diagnostics };
}

let ast::Expr::String(input_string) = &arguments[0] else {
let diagnostics = vec![PluginDiagnostic {
stable_ptr: syntax.stable_ptr().untyped(),
message: "selector macro argument must be a string".to_string(),
}];
return InlinePluginResult { code: None, diagnostics };
};
let selector_string = input_string.string_value(db).unwrap();

let selector = starknet_keccak(selector_string.as_bytes());
let code: String = format!("0x{}", selector.to_str_radix(16));
InlinePluginResult { code: Some(code), diagnostics: vec![] }
}
}
1 change: 1 addition & 0 deletions crates/cairo-lang-starknet/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub mod contract;
pub mod contract_class;
mod felt252_serde;
mod felt252_vec_compression;
pub mod inline_macros;
pub mod plugin;

#[cfg(test)]
Expand Down
7 changes: 2 additions & 5 deletions crates/cairo-lang-starknet/src/plugin/dispatcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use itertools::Itertools;
use super::consts::CALLDATA_PARAM_NAME;
use super::utils::is_ref_param;
use super::{DEPRECATED_ABI_ATTR, INTERFACE_ATTR};
use crate::contract::starknet_keccak;

/// If the trait is annotated with ABI_ATTR, generate the relevant dispatcher logic.
pub fn handle_trait(db: &dyn SyntaxGroup, trait_ast: ast::ItemTrait) -> PluginResult {
Expand Down Expand Up @@ -148,10 +147,8 @@ pub fn handle_trait(db: &dyn SyntaxGroup, trait_ast: ast::ItemTrait) -> PluginRe
[("func_decl".to_string(), dispatcher_signature(db, &declaration, "T", false))]
.into(),
));
let entry_point_selector = RewriteNode::Text(format!(
"0x{:x}",
starknet_keccak(declaration.name(db).text(db).as_bytes())
));
let entry_point_selector =
RewriteNode::Text(format!("selector!(\"{}\")", declaration.name(db).text(db)));
contract_caller_method_impls.push(declaration_method_impl(
dispatcher_signature(db, &declaration, &contract_caller_name, true),
entry_point_selector.clone(),
Expand Down
8 changes: 2 additions & 6 deletions crates/cairo-lang-starknet/src/plugin/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ use serde::{Deserialize, Serialize};
use smol_str::SmolStr;

use super::aux_data::StarkNetEventAuxData;
use crate::contract::starknet_keccak;

/// Generated auxiliary data for the `#[derive(starknet::Event)]` attribute.
#[derive(Clone, Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -218,34 +217,31 @@ pub fn handle_enum(db: &dyn SyntaxGroup, enum_ast: ast::ItemEnum) -> PluginResul
};
let variant_name = RewriteNode::new_trimmed(variant.name(db).as_syntax_node());
let name = variant.name(db).text(db);
let variant_selector = format!("0x{:x}", starknet_keccak(name.as_bytes()));
let member_kind =
get_field_kind_for_variant(db, &mut diagnostics, &variant, EventFieldKind::Nested);
variants.push((name, member_kind));
let append_member = append_field(member_kind, RewriteNode::Text("val".into()));
let append_variant = RewriteNode::interpolate_patched(
"
$enum_name$::$variant_name$(val) => {
array::ArrayTrait::append(ref keys, $variant_selector$);$append_member$
array::ArrayTrait::append(ref keys, selector!(\"$variant_name$\"));$append_member$
},",
[
(String::from("enum_name"), enum_name.clone()),
(String::from("variant_name"), variant_name.clone()),
(String::from("variant_selector"), RewriteNode::Text(variant_selector.clone())),
(String::from("append_member"), append_member),
]
.into(),
);
let deserialize_member = deserialize_field(member_kind, RewriteNode::Text("val".into()));
let deserialize_variant = RewriteNode::interpolate_patched(
"
if selector == $variant_selector$ {$deserialize_member$
if selector == selector!(\"$variant_name$\") {$deserialize_member$
return Option::Some($enum_name$::$variant_name$(val));
}",
[
(String::from("enum_name"), enum_name.clone()),
(String::from("variant_name"), variant_name.clone()),
(String::from("variant_selector"), RewriteNode::Text(variant_selector)),
(String::from("deserialize_member"), deserialize_member),
]
.into(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ impl EventIsEvent of starknet::Event<Event> {
) {
match self {
Event::Log(val) => {
array::ArrayTrait::append(ref keys, 0x100572688f36e5f96cee69badc6dcd8712fa19d323be018601b92e967c60678);
array::ArrayTrait::append(ref keys, selector!("Log"));
starknet::Event::append_keys_and_data(
val, ref keys, ref data
);
Expand All @@ -189,7 +189,7 @@ impl EventIsEvent of starknet::Event<Event> {
) -> Option<Event> {
let selector = *array::SpanTrait::pop_front(ref keys)?;

if selector == 0x100572688f36e5f96cee69badc6dcd8712fa19d323be018601b92e967c60678 {
if selector == selector!("Log") {
let val = starknet::Event::deserialize(
ref keys, ref data
)?;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -280,13 +280,13 @@ impl EventIsEvent of starknet::Event<Event> {
) {
match self {
Event::AwesomeEvent(val) => {
array::ArrayTrait::append(ref keys, 0x2fbea1ee750e49ff764a5c7183b4201cc4beb8ead010fbb75b671e6f31bb82);
array::ArrayTrait::append(ref keys, selector!("AwesomeEvent"));
starknet::Event::append_keys_and_data(
val, ref keys, ref data
);
},
Event::BestEventEver(val) => {
array::ArrayTrait::append(ref keys, 0x7b89143e59dd87ddfbccfa6075ca9296b9b5f26183bc738db54c2313fab4ed);
array::ArrayTrait::append(ref keys, selector!("BestEventEver"));
starknet::Event::append_keys_and_data(
val, ref keys, ref data
);
Expand All @@ -298,13 +298,13 @@ impl EventIsEvent of starknet::Event<Event> {
) -> Option<Event> {
let selector = *array::SpanTrait::pop_front(ref keys)?;

if selector == 0x2fbea1ee750e49ff764a5c7183b4201cc4beb8ead010fbb75b671e6f31bb82 {
if selector == selector!("AwesomeEvent") {
let val = starknet::Event::deserialize(
ref keys, ref data
)?;
return Option::Some(Event::AwesomeEvent(val));
}
if selector == 0x7b89143e59dd87ddfbccfa6075ca9296b9b5f26183bc738db54c2313fab4ed {
if selector == selector!("BestEventEver") {
let val = starknet::Event::deserialize(
ref keys, ref data
)?;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ impl IContractDispatcherImpl of IContractDispatcherTrait<IContractDispatcher> {

let mut ret_data = starknet::call_contract_syscall(
self.contract_address,
0x3c52d61651de3dcab6ceaa9f6505f7aed8f1ffc0f694ce2a9ed76e758d87a3,
selector!("get_something"),
array::ArrayTrait::span(@__calldata__),
);
let mut ret_data = starknet::SyscallResultTrait::unwrap_syscall(ret_data);
Expand All @@ -56,7 +56,7 @@ impl IContractDispatcherImpl of IContractDispatcherTrait<IContractDispatcher> {

let mut ret_data = starknet::call_contract_syscall(
self.contract_address,
0x1fc3f77ebc090777f567969ad9823cf6334ab888acb385ca72668ec5adbde80,
selector!("empty"),
array::ArrayTrait::span(@__calldata__),
);
let mut ret_data = starknet::SyscallResultTrait::unwrap_syscall(ret_data);
Expand All @@ -78,7 +78,7 @@ impl IContractLibraryDispatcherImpl of IContractDispatcherTrait<IContractLibrary

let mut ret_data = starknet::syscalls::library_call_syscall(
self.class_hash,
0x3c52d61651de3dcab6ceaa9f6505f7aed8f1ffc0f694ce2a9ed76e758d87a3,
selector!("get_something"),
array::ArrayTrait::span(@__calldata__),
);
let mut ret_data = starknet::SyscallResultTrait::unwrap_syscall(ret_data);
Expand All @@ -93,7 +93,7 @@ impl IContractLibraryDispatcherImpl of IContractDispatcherTrait<IContractLibrary

let mut ret_data = starknet::syscalls::library_call_syscall(
self.class_hash,
0x1fc3f77ebc090777f567969ad9823cf6334ab888acb385ca72668ec5adbde80,
selector!("empty"),
array::ArrayTrait::span(@__calldata__),
);
let mut ret_data = starknet::SyscallResultTrait::unwrap_syscall(ret_data);
Expand All @@ -120,7 +120,7 @@ impl IContractSafeLibraryDispatcherImpl of IContractSafeDispatcherTrait<IContrac

let mut ret_data = starknet::syscalls::library_call_syscall(
self.class_hash,
0x3c52d61651de3dcab6ceaa9f6505f7aed8f1ffc0f694ce2a9ed76e758d87a3,
selector!("get_something"),
array::ArrayTrait::span(@__calldata__),
);
let mut ret_data = ret_data?;
Expand All @@ -137,7 +137,7 @@ impl IContractSafeLibraryDispatcherImpl of IContractSafeDispatcherTrait<IContrac

let mut ret_data = starknet::syscalls::library_call_syscall(
self.class_hash,
0x1fc3f77ebc090777f567969ad9823cf6334ab888acb385ca72668ec5adbde80,
selector!("empty"),
array::ArrayTrait::span(@__calldata__),
);
let mut ret_data = ret_data?;
Expand All @@ -160,7 +160,7 @@ impl IContractSafeDispatcherImpl of IContractSafeDispatcherTrait<IContractSafeDi

let mut ret_data = starknet::call_contract_syscall(
self.contract_address,
0x3c52d61651de3dcab6ceaa9f6505f7aed8f1ffc0f694ce2a9ed76e758d87a3,
selector!("get_something"),
array::ArrayTrait::span(@__calldata__),
);
let mut ret_data = ret_data?;
Expand All @@ -177,7 +177,7 @@ impl IContractSafeDispatcherImpl of IContractSafeDispatcherTrait<IContractSafeDi

let mut ret_data = starknet::call_contract_syscall(
self.contract_address,
0x1fc3f77ebc090777f567969ad9823cf6334ab888acb385ca72668ec5adbde80,
selector!("empty"),
array::ArrayTrait::span(@__calldata__),
);
let mut ret_data = ret_data?;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,13 +164,13 @@ impl MyEventEnumIsEvent of starknet::Event<MyEventEnum> {
) {
match self {
MyEventEnum::A(val) => {
array::ArrayTrait::append(ref keys, 0x3783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760);
array::ArrayTrait::append(ref keys, selector!("A"));
starknet::Event::append_keys_and_data(
val, ref keys, ref data
);
},
MyEventEnum::B(val) => {
array::ArrayTrait::append(ref keys, 0x3675bff07515f5df96737194ea945c36c41e7b4fcef307b7cd4d0e602a69111);
array::ArrayTrait::append(ref keys, selector!("B"));
starknet::Event::append_keys_and_data(
val, ref keys, ref data
);
Expand All @@ -182,13 +182,13 @@ impl MyEventEnumIsEvent of starknet::Event<MyEventEnum> {
) -> Option<MyEventEnum> {
let selector = *array::SpanTrait::pop_front(ref keys)?;

if selector == 0x3783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760 {
if selector == selector!("A") {
let val = starknet::Event::deserialize(
ref keys, ref data
)?;
return Option::Some(MyEventEnum::A(val));
}
if selector == 0x3675bff07515f5df96737194ea945c36c41e7b4fcef307b7cd4d0e602a69111 {
if selector == selector!("B") {
let val = starknet::Event::deserialize(
ref keys, ref data
)?;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,13 @@ impl EventIsEvent of starknet::Event<Event> {
) {
match self {
Event::AwesomeEvent(val) => {
array::ArrayTrait::append(ref keys, 0x2fbea1ee750e49ff764a5c7183b4201cc4beb8ead010fbb75b671e6f31bb82);
array::ArrayTrait::append(ref keys, selector!("AwesomeEvent"));
starknet::Event::append_keys_and_data(
val, ref keys, ref data
);
},
Event::BestEventEver(val) => {
array::ArrayTrait::append(ref keys, 0x7b89143e59dd87ddfbccfa6075ca9296b9b5f26183bc738db54c2313fab4ed);
array::ArrayTrait::append(ref keys, selector!("BestEventEver"));
starknet::Event::append_keys_and_data(
val, ref keys, ref data
);
Expand All @@ -84,13 +84,13 @@ impl EventIsEvent of starknet::Event<Event> {
) -> Option<Event> {
let selector = *array::SpanTrait::pop_front(ref keys)?;

if selector == 0x2fbea1ee750e49ff764a5c7183b4201cc4beb8ead010fbb75b671e6f31bb82 {
if selector == selector!("AwesomeEvent") {
let val = starknet::Event::deserialize(
ref keys, ref data
)?;
return Option::Some(Event::AwesomeEvent(val));
}
if selector == 0x7b89143e59dd87ddfbccfa6075ca9296b9b5f26183bc738db54c2313fab4ed {
if selector == selector!("BestEventEver") {
let val = starknet::Event::deserialize(
ref keys, ref data
)?;
Expand Down
2 changes: 2 additions & 0 deletions crates/cairo-lang-starknet/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use once_cell::sync::Lazy;

use crate::allowed_libfuncs::BUILTIN_ALL_LIBFUNCS_LIST;
use crate::contract_class::compile_contract_in_prepared_db;
use crate::inline_macros::selector::SelectorMacro;
use crate::plugin::StarkNetPlugin;

/// Returns a path to example contract that matches `name`.
Expand All @@ -27,6 +28,7 @@ pub static SHARED_DB: Lazy<Mutex<RootDatabase>> = Lazy::new(|| {
RootDatabase::builder()
.detect_corelib()
.with_macro_plugin(Arc::new(StarkNetPlugin::default()))
.with_inline_macro_plugin(SelectorMacro::NAME, Arc::new(SelectorMacro))
.build()
.unwrap(),
)
Expand Down
Loading

0 comments on commit b98ade6

Please sign in to comment.