Skip to content

Commit

Permalink
[core] Inline macro - delete! (#1271)
Browse files Browse the repository at this point in the history
* adding delete_macro (wip)

* fix test delete!()

* fix delete.rs
  • Loading branch information
dubzn authored Dec 13, 2023
1 parent ec8fe13 commit 772e4b6
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 1 deletion.
8 changes: 7 additions & 1 deletion crates/dojo-core/src/world_test.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ struct Fizz {
trait Ibar<TContractState> {
fn set_foo(self: @TContractState, a: felt252, b: u128);
fn delete_foo(self: @TContractState);
fn delete_foo_macro(self: @TContractState, foo: Foo);
fn set_char(self: @TContractState, a: felt252, b: u32);
}

Expand Down Expand Up @@ -67,6 +68,10 @@ mod bar {
.delete_entity('Foo', array![get_caller_address().into()].span(), layout.span());
}

fn delete_foo_macro(self: @ContractState, foo: Foo) {
delete!(self.world.read(), Foo { caller: foo.caller, a: foo.a, b: foo.b });
}

fn set_char(self: @ContractState, a: felt252, b: u32) {
set!(
self.world.read(),
Expand Down Expand Up @@ -151,7 +156,8 @@ fn test_delete() {
assert(stored.b == 1337, 'data not stored');

// delete model
bar_contract.delete_foo();
bar_contract.delete_foo_macro(stored);

let deleted: Foo = get!(world, get_caller_address(), Foo);
assert(deleted.a == 0, 'data not deleted');
assert(deleted.b == 0, 'data not deleted');
Expand Down
164 changes: 164 additions & 0 deletions crates/dojo-lang/src/inline_macros/delete.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
use std::collections::HashMap;

use cairo_lang_defs::patcher::PatchBuilder;
use cairo_lang_defs::plugin::{
InlineMacroExprPlugin, InlinePluginResult, NamedPlugin, PluginDiagnostic, PluginGeneratedFile,
};
use cairo_lang_semantic::inline_macros::unsupported_bracket_diagnostic;
use cairo_lang_syntax::node::ast::{ExprPath, ExprStructCtorCall, FunctionWithBody, ItemModule};
use cairo_lang_syntax::node::kind::SyntaxKind;
use cairo_lang_syntax::node::{ast, TypedSyntaxNode};

use super::unsupported_arg_diagnostic;
use super::utils::{parent_of_kind, SystemRWOpRecord, SYSTEM_WRITES};

#[derive(Debug, Default)]
pub struct DeleteMacro;

impl NamedPlugin for DeleteMacro {
const NAME: &'static str = "delete";
}

impl InlineMacroExprPlugin for DeleteMacro {
fn generate_code(
&self,
db: &dyn cairo_lang_syntax::node::db::SyntaxGroup,
syntax: &ast::ExprInlineMacro,
) -> InlinePluginResult {
let ast::WrappedArgList::ParenthesizedArgList(arg_list) = syntax.arguments(db) else {
return unsupported_bracket_diagnostic(db, syntax);
};
let mut builder = PatchBuilder::new(db);
builder.add_str("{");

let args = arg_list.arguments(db).elements(db);

if args.len() != 2 {
return InlinePluginResult {
code: None,
diagnostics: vec![PluginDiagnostic {
stable_ptr: arg_list.arguments(db).stable_ptr().untyped(),
message: "Invalid arguments. Expected \"(world, (models,))\"".to_string(),
}],
};
}

let world = &args[0];

let ast::ArgClause::Unnamed(models) = args[1].arg_clause(db) else {
return unsupported_arg_diagnostic(db, syntax);
};

let mut bundle = vec![];

match models.value(db) {
ast::Expr::Parenthesized(parens) => {
let syntax_node = parens.expr(db).as_syntax_node();
bundle.push((syntax_node.get_text(db), syntax_node));
}
ast::Expr::Tuple(list) => {
list.expressions(db).elements(db).into_iter().for_each(|expr| {
let syntax_node = expr.as_syntax_node();
bundle.push((syntax_node.get_text(db), syntax_node));
})
}
ast::Expr::StructCtorCall(ctor) => {
let syntax_node = ctor.as_syntax_node();
bundle.push((syntax_node.get_text(db), syntax_node));
}
_ => {
return InlinePluginResult {
code: None,
diagnostics: vec![PluginDiagnostic {
message: "Invalid arguments. Expected \"(world, (models,))\"".to_string(),
stable_ptr: arg_list.arguments(db).stable_ptr().untyped(),
}],
};
}
}

if bundle.is_empty() {
return InlinePluginResult {
code: None,
diagnostics: vec![PluginDiagnostic {
message: "Invalid arguments: No models provided.".to_string(),
stable_ptr: arg_list.arguments(db).stable_ptr().untyped(),
}],
};
}

let module_syntax_node =
parent_of_kind(db, &syntax.as_syntax_node(), SyntaxKind::ItemModule);
let module_name = if let Some(module_syntax_node) = &module_syntax_node {
let mod_ast = ItemModule::from_syntax_node(db, module_syntax_node.clone());
mod_ast.name(db).as_syntax_node().get_text_without_trivia(db)
} else {
"".into()
};

let fn_syntax_node =
parent_of_kind(db, &syntax.as_syntax_node(), SyntaxKind::FunctionWithBody);
let fn_name = if let Some(fn_syntax_node) = &fn_syntax_node {
let fn_ast = FunctionWithBody::from_syntax_node(db, fn_syntax_node.clone());
fn_ast.declaration(db).name(db).as_syntax_node().get_text_without_trivia(db)
} else {
"".into()
};

for (entity, syntax_node) in bundle {
// db.lookup_intern_file(key0);
if !module_name.is_empty() && !fn_name.is_empty() {
let mut system_writes = SYSTEM_WRITES.lock().unwrap();
// fn_syntax_node
if system_writes.get(&module_name).is_none() {
system_writes.insert(module_name.clone(), HashMap::new());
}
let fns = system_writes.get_mut(&module_name).unwrap();
if fns.get(&fn_name).is_none() {
fns.insert(fn_name.clone(), vec![]);
}

match syntax_node.kind(db) {
SyntaxKind::ExprPath => {
fns.get_mut(&fn_name).unwrap().push(SystemRWOpRecord::Path(
ExprPath::from_syntax_node(db, syntax_node),
));
}
// SyntaxKind::StatementExpr => {
// todo!()
// }
SyntaxKind::ExprStructCtorCall => {
fns.get_mut(&fn_name).unwrap().push(SystemRWOpRecord::StructCtor(
ExprStructCtorCall::from_syntax_node(db, syntax_node.clone()),
));
}
_ => eprintln!(
"Unsupport component value type {} for semantic writer analysis",
syntax_node.kind(db)
),
}
}

builder.add_str(&format!(
"
let __delete_macro_value__ = {};
{}.delete_entity(dojo::model::Model::name(@__delete_macro_value__),
dojo::model::Model::keys(@__delete_macro_value__),
dojo::model::Model::layout(@__delete_macro_value__));",
entity,
world.as_syntax_node().get_text(db),
));
}
builder.add_str("}");

InlinePluginResult {
code: Some(PluginGeneratedFile {
name: "delete_inline_macro".into(),
content: builder.code,
diagnostics_mappings: builder.diagnostics_mappings,
aux_data: None,
}),
diagnostics: vec![],
}
}
}
1 change: 1 addition & 0 deletions crates/dojo-lang/src/inline_macros/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use cairo_lang_syntax::node::db::SyntaxGroup;
use cairo_lang_syntax::node::{ast, Terminal, TypedSyntaxNode};
use smol_str::SmolStr;

pub mod delete;
pub mod emit;
pub mod get;
pub mod set;
Expand Down
2 changes: 2 additions & 0 deletions crates/dojo-lang/src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use smol_str::SmolStr;
use url::Url;

use crate::contract::DojoContract;
use crate::inline_macros::delete::DeleteMacro;
use crate::inline_macros::emit::EmitMacro;
use crate::inline_macros::get::GetMacro;
use crate::inline_macros::set::SetMacro;
Expand Down Expand Up @@ -216,6 +217,7 @@ pub fn dojo_plugin_suite() -> PluginSuite {

suite
.add_plugin::<BuiltinDojoPlugin>()
.add_inline_macro_plugin::<DeleteMacro>()
.add_inline_macro_plugin::<GetMacro>()
.add_inline_macro_plugin::<SetMacro>()
.add_inline_macro_plugin::<EmitMacro>();
Expand Down

0 comments on commit 772e4b6

Please sign in to comment.