From d62fa488b509e19073475a7b3a9dace77567d227 Mon Sep 17 00:00:00 2001 From: Ori Ziv Date: Wed, 16 Aug 2023 08:42:55 +0300 Subject: [PATCH] Added selector inline macro for starknet. commit-id:5bae488f --- crates/cairo-lang-compiler/src/db.rs | 4 +- crates/cairo-lang-language-server/src/lib.rs | 2 + .../src/inline_macros/mod.rs | 2 +- crates/cairo-lang-semantic/src/patcher.rs | 271 ++++++++++++++++++ crates/cairo-lang-starknet/src/abi_test.rs | 2 + .../cairo-lang-starknet/src/contract_class.rs | 2 + .../src/inline_macros/mod.rs | 1 + .../src/inline_macros/selector.rs | 46 +++ crates/cairo-lang-starknet/src/lib.rs | 1 + .../src/plugin/dispatcher.rs | 7 +- .../cairo-lang-starknet/src/plugin/events.rs | 8 +- .../plugin_test_data/components/component | 4 +- .../plugin_test_data/contracts/contract | 8 +- .../plugin_test_data/contracts/dispatcher | 16 +- .../plugin/plugin_test_data/contracts/events | 8 +- .../plugin_test_data/contracts/external_event | 8 +- crates/cairo-lang-starknet/src/test_utils.rs | 2 + crates/cairo-lang-test-runner/src/lib.rs | 4 +- 18 files changed, 359 insertions(+), 37 deletions(-) create mode 100644 crates/cairo-lang-semantic/src/patcher.rs create mode 100644 crates/cairo-lang-starknet/src/inline_macros/mod.rs create mode 100644 crates/cairo-lang-starknet/src/inline_macros/selector.rs diff --git a/crates/cairo-lang-compiler/src/db.rs b/crates/cairo-lang-compiler/src/db.rs index 33118e29693..e55ab6bec8f 100644 --- a/crates/cairo-lang-compiler/src/db.rs +++ b/crates/cairo-lang-compiler/src/db.rs @@ -100,10 +100,10 @@ impl RootDatabaseBuilder { pub fn with_inline_macro_plugin( &mut self, - name: String, + name: &str, plugin: Arc, ) -> &mut Self { - self.inline_macro_plugins.insert(name, plugin); + self.inline_macro_plugins.insert(name.into(), plugin); self } diff --git a/crates/cairo-lang-language-server/src/lib.rs b/crates/cairo-lang-language-server/src/lib.rs index a6f81855d6c..3671924f527 100644 --- a/crates/cairo-lang-language-server/src/lib.rs +++ b/crates/cairo-lang-language-server/src/lib.rs @@ -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; @@ -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."); diff --git a/crates/cairo-lang-semantic/src/inline_macros/mod.rs b/crates/cairo-lang-semantic/src/inline_macros/mod.rs index b78071fe8a9..3cfb82bcbd6 100644 --- a/crates/cairo-lang-semantic/src/inline_macros/mod.rs +++ b/crates/cairo-lang-semantic/src/inline_macros/mod.rs @@ -21,7 +21,7 @@ pub fn get_default_inline_macro_plugins() -> OrderedHashMap InlinePluginResult { diff --git a/crates/cairo-lang-semantic/src/patcher.rs b/crates/cairo-lang-semantic/src/patcher.rs new file mode 100644 index 00000000000..79e1bb5e75e --- /dev/null +++ b/crates/cairo-lang-semantic/src/patcher.rs @@ -0,0 +1,271 @@ +use cairo_lang_defs::db::DefsGroup; +use cairo_lang_filesystem::span::{TextOffset, TextSpan, TextWidth}; +use cairo_lang_syntax::node::db::SyntaxGroup; +use cairo_lang_syntax::node::{SyntaxNode, TypedSyntaxNode}; +use cairo_lang_utils::extract_matches; +use cairo_lang_utils::unordered_hash_map::UnorderedHashMap; + +/// Interface for modifying syntax nodes. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum RewriteNode { + /// A rewrite node that represents a trimmed copy of a syntax node: + /// one with the leading and trailing trivia excluded. + Trimmed { + node: SyntaxNode, + trim_left: bool, + trim_right: bool, + }, + Copied(SyntaxNode), + Modified(ModifiedNode), + Text(String), +} +impl RewriteNode { + pub fn new_trimmed(syntax_node: SyntaxNode) -> Self { + Self::Trimmed { node: syntax_node, trim_left: true, trim_right: true } + } + + pub fn new_modified(children: Vec) -> Self { + Self::Modified(ModifiedNode { children: Some(children) }) + } + + /// Creates a rewrite node from an AST object. + pub fn from_ast(node: &T) -> Self { + RewriteNode::Copied(node.as_syntax_node()) + } + + /// Prepares a node for modification. + pub fn modify(&mut self, db: &dyn SyntaxGroup) -> &mut ModifiedNode { + match self { + RewriteNode::Copied(syntax_node) => { + *self = RewriteNode::new_modified( + syntax_node.children(db).map(RewriteNode::Copied).collect(), + ); + extract_matches!(self, RewriteNode::Modified) + } + + RewriteNode::Trimmed { node, trim_left, trim_right } => { + let num_children = node.children(db).len(); + let mut new_children = Vec::new(); + + // Get the index of the leftmost nonempty child. + let Some(left_idx) = + node.children(db).position(|child| child.width(db) != TextWidth::default()) + else { + *self = RewriteNode::Modified(ModifiedNode { children: None }); + return extract_matches!(self, RewriteNode::Modified); + }; + // Get the index of the rightmost nonempty child. + let right_idx = node + .children(db) + .rposition(|child| child.width(db) != TextWidth::default()) + .unwrap(); + new_children.extend(itertools::repeat_n( + RewriteNode::Modified(ModifiedNode { children: None }), + left_idx, + )); + + // The number of children between the first and last nonempty nodes. + let num_middle = right_idx - left_idx + 1; + let mut children_iter = node.children(db).skip(left_idx); + match num_middle { + 1 => { + new_children.push(RewriteNode::Trimmed { + node: children_iter.next().unwrap(), + trim_left: *trim_left, + trim_right: *trim_right, + }); + } + _ => { + new_children.push(RewriteNode::Trimmed { + node: children_iter.next().unwrap(), + trim_left: *trim_left, + trim_right: false, + }); + for _ in 0..(num_middle - 2) { + let child = children_iter.next().unwrap(); + new_children.push(RewriteNode::Copied(child)); + } + new_children.push(RewriteNode::Trimmed { + node: children_iter.next().unwrap(), + trim_left: false, + trim_right: *trim_right, + }); + } + }; + new_children.extend(itertools::repeat_n( + RewriteNode::Modified(ModifiedNode { children: None }), + num_children - right_idx - 1, + )); + + *self = RewriteNode::Modified(ModifiedNode { children: Some(new_children) }); + extract_matches!(self, RewriteNode::Modified) + } + RewriteNode::Modified(modified) => modified, + RewriteNode::Text(_) => panic!("A text node can't be modified"), + } + } + + /// Prepares a node for modification and returns a specific child. + pub fn modify_child(&mut self, db: &dyn SyntaxGroup, index: usize) -> &mut RewriteNode { + if matches!(self, RewriteNode::Modified(ModifiedNode { children: None })) { + // Modification of an empty node is idempotent. + return self; + } + &mut self.modify(db).children.as_mut().unwrap()[index] + } + + /// Replaces this node with text. + pub fn set_str(&mut self, s: String) { + *self = RewriteNode::Text(s) + } + /// Creates a new Rewrite node by interpolating a string with patches. + /// Each substring of the form `$$` is replaced with syntax nodes from `patches`. + /// A `$$` substring is replaced with `$`. + pub fn interpolate_patched( + code: &str, + patches: UnorderedHashMap, + ) -> RewriteNode { + let mut chars = code.chars().peekable(); + let mut pending_text = String::new(); + let mut children = Vec::new(); + while let Some(c) = chars.next() { + if c != '$' { + pending_text.push(c); + continue; + } + + // An opening $ was detected. + + // Read the name + let mut name = String::new(); + for c in chars.by_ref() { + if c == '$' { + break; + } + name.push(c); + } + + // A closing $ was found. + // If the string between the `$`s is empty - push a single `$` to the output. + if name.is_empty() { + pending_text.push('$'); + continue; + } + // If the string wasn't empty and there is some pending text, first flush it as a text + // child. + if !pending_text.is_empty() { + children.push(RewriteNode::Text(pending_text.clone())); + pending_text.clear(); + } + // Replace the substring with the relevant rewrite node. + // TODO(yuval): this currently panics. Fix it. + children.push(patches[&name].clone()); + } + // Flush the remaining text as a text child. + if !pending_text.is_empty() { + children.push(RewriteNode::Text(pending_text.clone())); + } + + RewriteNode::new_modified(children) + } +} +impl From for RewriteNode { + fn from(node: SyntaxNode) -> Self { + RewriteNode::Copied(node) + } +} + +/// A modified rewrite node. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct ModifiedNode { + /// Children of the node. + /// Can be None, in which case this is an empty node (of width 0). It's not the same as + /// Some(vec![]) - None can be (idempotently) modified, whereas modifying Some(vec![]) would + /// panic. + pub children: Option>, +} + +#[derive(Debug, PartialEq, Eq)] +pub struct Patch { + span: TextSpan, + origin_span: TextSpan, +} + +#[derive(Debug, Default, PartialEq, Eq)] +pub struct Patches { + patches: Vec, +} +impl Patches { + pub fn translate(&self, _db: &dyn DefsGroup, span: TextSpan) -> Option { + for Patch { span: patch_span, origin_span } in &self.patches { + if patch_span.contains(span) { + let start = origin_span.start.add_width(span.start - patch_span.start); + return Some(TextSpan { start, end: start.add_width(span.end - span.start) }); + } + } + None + } +} + +pub struct PatchBuilder<'a> { + pub db: &'a dyn SyntaxGroup, + pub code: String, + pub patches: Patches, +} +impl<'a> PatchBuilder<'a> { + pub fn new(db: &'a dyn SyntaxGroup) -> Self { + Self { db, code: String::default(), patches: Patches::default() } + } + + pub fn add_char(&mut self, c: char) { + self.code.push(c); + } + + pub fn add_str(&mut self, s: &str) { + self.code += s; + } + + pub fn add_modified(&mut self, node: RewriteNode) { + match node { + RewriteNode::Copied(node) => self.add_node(node), + RewriteNode::Trimmed { node, trim_left, trim_right } => { + self.add_trimmed_node(node, trim_left, trim_right) + } + RewriteNode::Modified(modified) => { + if let Some(children) = modified.children { + for child in children { + self.add_modified(child) + } + } + } + RewriteNode::Text(s) => self.add_str(s.as_str()), + } + } + + pub fn add_node(&mut self, node: SyntaxNode) { + let orig_span = node.span(self.db); + let start = TextOffset::default().add_width(TextWidth::from_str(&self.code)); + self.patches.patches.push(Patch { + span: TextSpan { start, end: start.add_width(orig_span.end - orig_span.start) }, + origin_span: node.span(self.db), + }); + self.code += node.get_text(self.db).as_str(); + } + + fn add_trimmed_node(&mut self, node: SyntaxNode, trim_left: bool, trim_right: bool) { + let TextSpan { start: trimmed_start, end: trimmed_end } = node.span_without_trivia(self.db); + let orig_start = if trim_left { trimmed_start } else { node.span(self.db).start }; + let orig_end = if trim_right { trimmed_end } else { node.span(self.db).end }; + let origin_span = TextSpan { start: orig_start, end: orig_end }; + + let text = node.get_text_of_span(self.db, origin_span); + let start = TextOffset::default().add_width(TextWidth::from_str(&self.code)); + + self.code += &text; + + self.patches.patches.push(Patch { + span: TextSpan { start, end: start.add_width(TextWidth::from_str(&text)) }, + origin_span, + }); + } +} diff --git a/crates/cairo-lang-starknet/src/abi_test.rs b/crates/cairo-lang-starknet/src/abi_test.rs index aa6ff560199..5be2cd8331a 100644 --- a/crates/cairo-lang-starknet/src/abi_test.rs +++ b/crates/cairo-lang-starknet/src/abi_test.rs @@ -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] @@ -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( diff --git a/crates/cairo-lang-starknet/src/contract_class.rs b/crates/cairo-lang-starknet/src/contract_class.rs index 2105a190746..61d8ce66ad2 100644 --- a/crates/cairo-lang-starknet/src/contract_class.rs +++ b/crates/cairo-lang-starknet/src/contract_class.rs @@ -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; @@ -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))?; diff --git a/crates/cairo-lang-starknet/src/inline_macros/mod.rs b/crates/cairo-lang-starknet/src/inline_macros/mod.rs new file mode 100644 index 00000000000..199a414becc --- /dev/null +++ b/crates/cairo-lang-starknet/src/inline_macros/mod.rs @@ -0,0 +1 @@ +pub mod selector; diff --git a/crates/cairo-lang-starknet/src/inline_macros/selector.rs b/crates/cairo-lang-starknet/src/inline_macros/selector.rs new file mode 100644 index 00000000000..3b198346a3b --- /dev/null +++ b/crates/cairo-lang-starknet/src/inline_macros/selector.rs @@ -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)] +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![] } + } +} diff --git a/crates/cairo-lang-starknet/src/lib.rs b/crates/cairo-lang-starknet/src/lib.rs index 33b2254e012..ac23a7afc32 100644 --- a/crates/cairo-lang-starknet/src/lib.rs +++ b/crates/cairo-lang-starknet/src/lib.rs @@ -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)] diff --git a/crates/cairo-lang-starknet/src/plugin/dispatcher.rs b/crates/cairo-lang-starknet/src/plugin/dispatcher.rs index 7f0c15a93b9..288c24afad9 100644 --- a/crates/cairo-lang-starknet/src/plugin/dispatcher.rs +++ b/crates/cairo-lang-starknet/src/plugin/dispatcher.rs @@ -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 { @@ -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(), diff --git a/crates/cairo-lang-starknet/src/plugin/events.rs b/crates/cairo-lang-starknet/src/plugin/events.rs index efa195dd8c0..4002f864b49 100644 --- a/crates/cairo-lang-starknet/src/plugin/events.rs +++ b/crates/cairo-lang-starknet/src/plugin/events.rs @@ -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)] @@ -218,7 +217,6 @@ 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)); @@ -226,12 +224,11 @@ pub fn handle_enum(db: &dyn SyntaxGroup, enum_ast: ast::ItemEnum) -> PluginResul 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(), @@ -239,13 +236,12 @@ pub fn handle_enum(db: &dyn SyntaxGroup, enum_ast: ast::ItemEnum) -> PluginResul 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(), diff --git a/crates/cairo-lang-starknet/src/plugin/plugin_test_data/components/component b/crates/cairo-lang-starknet/src/plugin/plugin_test_data/components/component index 9c90fc4e455..7d6aa33b4f7 100644 --- a/crates/cairo-lang-starknet/src/plugin/plugin_test_data/components/component +++ b/crates/cairo-lang-starknet/src/plugin/plugin_test_data/components/component @@ -177,7 +177,7 @@ impl EventIsEvent of starknet::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 ); @@ -189,7 +189,7 @@ impl EventIsEvent of starknet::Event { ) -> Option { let selector = *array::SpanTrait::pop_front(ref keys)?; - if selector == 0x100572688f36e5f96cee69badc6dcd8712fa19d323be018601b92e967c60678 { + if selector == selector!("Log") { let val = starknet::Event::deserialize( ref keys, ref data )?; diff --git a/crates/cairo-lang-starknet/src/plugin/plugin_test_data/contracts/contract b/crates/cairo-lang-starknet/src/plugin/plugin_test_data/contracts/contract index abd1b2ba8fa..8c5f1e6f07c 100644 --- a/crates/cairo-lang-starknet/src/plugin/plugin_test_data/contracts/contract +++ b/crates/cairo-lang-starknet/src/plugin/plugin_test_data/contracts/contract @@ -280,13 +280,13 @@ impl EventIsEvent of starknet::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 ); @@ -298,13 +298,13 @@ impl EventIsEvent of starknet::Event { ) -> Option { 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 )?; diff --git a/crates/cairo-lang-starknet/src/plugin/plugin_test_data/contracts/dispatcher b/crates/cairo-lang-starknet/src/plugin/plugin_test_data/contracts/dispatcher index bd2fc956828..36db1f75657 100644 --- a/crates/cairo-lang-starknet/src/plugin/plugin_test_data/contracts/dispatcher +++ b/crates/cairo-lang-starknet/src/plugin/plugin_test_data/contracts/dispatcher @@ -49,7 +49,7 @@ impl IContractDispatcherImpl of IContractDispatcherTrait { 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); @@ -64,7 +64,7 @@ impl IContractDispatcherImpl of IContractDispatcherTrait { 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); @@ -86,7 +86,7 @@ impl IContractLibraryDispatcherImpl of IContractDispatcherTrait { ) { 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 ); @@ -182,13 +182,13 @@ impl MyEventEnumIsEvent of starknet::Event { ) -> Option { 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 )?; diff --git a/crates/cairo-lang-starknet/src/plugin/plugin_test_data/contracts/external_event b/crates/cairo-lang-starknet/src/plugin/plugin_test_data/contracts/external_event index 142e453edf5..91fb5a830f4 100644 --- a/crates/cairo-lang-starknet/src/plugin/plugin_test_data/contracts/external_event +++ b/crates/cairo-lang-starknet/src/plugin/plugin_test_data/contracts/external_event @@ -66,13 +66,13 @@ impl EventIsEvent of starknet::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 ); @@ -84,13 +84,13 @@ impl EventIsEvent of starknet::Event { ) -> Option { 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 )?; diff --git a/crates/cairo-lang-starknet/src/test_utils.rs b/crates/cairo-lang-starknet/src/test_utils.rs index 94f475ac6c9..0777afcdb1a 100644 --- a/crates/cairo-lang-starknet/src/test_utils.rs +++ b/crates/cairo-lang-starknet/src/test_utils.rs @@ -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`. @@ -27,6 +28,7 @@ pub static SHARED_DB: Lazy> = Lazy::new(|| { RootDatabase::builder() .detect_corelib() .with_macro_plugin(Arc::new(StarkNetPlugin::default())) + .with_inline_macro_plugin(SelectorMacro::NAME, Arc::new(SelectorMacro)) .build() .unwrap(), ) diff --git a/crates/cairo-lang-test-runner/src/lib.rs b/crates/cairo-lang-test-runner/src/lib.rs index 0963735d46f..52625b2b9d6 100644 --- a/crates/cairo-lang-test-runner/src/lib.rs +++ b/crates/cairo-lang-test-runner/src/lib.rs @@ -26,6 +26,7 @@ use cairo_lang_starknet::casm_contract_class::ENTRY_POINT_COST; use cairo_lang_starknet::contract::{ find_contracts, get_contracts_info, get_module_abi_functions, ContractInfo, }; +use cairo_lang_starknet::inline_macros::selector::SelectorMacro; use cairo_lang_starknet::plugin::consts::{CONSTRUCTOR_MODULE, EXTERNAL_MODULE, L1_HANDLER_MODULE}; use cairo_lang_starknet::plugin::StarkNetPlugin; use cairo_lang_utils::casts::IntoOrPanic; @@ -75,7 +76,8 @@ impl TestRunner { b.with_macro_plugin(Arc::new(TestPlugin::default())); if starknet { - b.with_macro_plugin(Arc::new(StarkNetPlugin::default())); + b.with_macro_plugin(Arc::new(StarkNetPlugin::default())) + .with_inline_macro_plugin(SelectorMacro::NAME, Arc::new(SelectorMacro)); } b.build()?