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

impl Mapping::contains, Mapping::remove #2436

Merged
merged 3 commits into from
Jun 30, 2023
Merged
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
10 changes: 9 additions & 1 deletion compiler/ast/src/functions/core_function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ pub enum CoreFunction {
MappingGet,
MappingGetOrUse,
MappingSet,
MappingRemove,
MappingContains,

GroupToXCoordinate,
GroupToYCoordinate,
Expand Down Expand Up @@ -373,6 +375,8 @@ impl CoreFunction {
(sym::Mapping, sym::get) => Self::MappingGet,
(sym::Mapping, sym::get_or_use) => Self::MappingGetOrUse,
(sym::Mapping, sym::set) => Self::MappingSet,
(sym::Mapping, sym::remove) => Self::MappingRemove,
(sym::Mapping, sym::contains) => Self::MappingContains,

(sym::group, sym::to_x_coordinate) => Self::GroupToXCoordinate,
(sym::group, sym::to_y_coordinate) => Self::GroupToYCoordinate,
Expand Down Expand Up @@ -556,6 +560,8 @@ impl CoreFunction {
Self::MappingGet => 2,
Self::MappingGetOrUse => 3,
Self::MappingSet => 3,
Self::MappingRemove => 2,
Self::MappingContains => 2,

Self::GroupToXCoordinate => 1,
Self::GroupToYCoordinate => 1,
Expand All @@ -582,7 +588,9 @@ impl CoreFunction {
| CoreFunction::MappingGet
| CoreFunction::MappingGetOrUse
| CoreFunction::ChaChaRandScalar
| CoreFunction::MappingSet => true,
| CoreFunction::MappingSet
| CoreFunction::MappingRemove
| CoreFunction::MappingContains => true,
CoreFunction::BHP256CommitToAddress
| CoreFunction::BHP256CommitToField
| CoreFunction::BHP256CommitToGroup
Expand Down
6 changes: 4 additions & 2 deletions compiler/parser/src/parser/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,10 @@ impl ParserContext<'_> {
match (args.len(), CoreFunction::from_symbols(sym::Mapping, method.name)) {
(1, Some(CoreFunction::MappingGet))
| (2, Some(CoreFunction::MappingGetOrUse))
| (2, Some(CoreFunction::MappingSet)) => {
// Found an instance of `<mapping>.get`, `<mapping>.get_or_use`, or `<mapping>.set`
| (2, Some(CoreFunction::MappingSet))
| (1, Some(CoreFunction::MappingRemove))
| (1, Some(CoreFunction::MappingContains)) => {
// Found an instance of `<mapping>.get`, `<mapping>.get_or_use`, `<mapping>.set`, `<mapping>.remove`, or `<mapping>.contains`.
Ok(Expression::Access(AccessExpression::AssociatedFunction(AssociatedFunction {
ty: Type::Identifier(Identifier::new(sym::Mapping)),
name: method,
Expand Down
4 changes: 2 additions & 2 deletions compiler/parser/src/parser/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,14 +135,14 @@ impl ParserContext<'_> {
Expression::Identifier(Identifier { name: sym::decrement, .. }) => {
self.emit_warning(ParserWarning::deprecated(
"decrement",
"Use `Mapping::{get, get_or_use, set}` for manipulating on-chain mappings.",
"Use `Mapping::{get, get_or_use, set, remove, contains}` for manipulating on-chain mappings.",
place.span(),
));
}
Expression::Identifier(Identifier { name: sym::increment, .. }) => {
self.emit_warning(ParserWarning::deprecated(
"increment",
"Use `Mapping::{get, get_or_use, set}` for manipulating on-chain mappings.",
"Use `Mapping::{get, get_or_use, set, remove, contains}` for manipulating on-chain mappings.",
place.span(),
));
}
Expand Down
14 changes: 14 additions & 0 deletions compiler/passes/src/code_generation/visit_expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,20 @@ impl<'a> CodeGenerator<'a> {
.expect("failed to write to string");
(String::new(), instruction)
}
sym::remove => {
let mut instruction = " remove".to_string();
// Write the mapping name and the key.
writeln!(instruction, " {}[{}];", arguments[0], arguments[1]).expect("failed to write to string");
(String::new(), instruction)
}
sym::contains => {
let mut instruction = " contains".to_string();
let destination_register = get_destination_register();
// Write the mapping name and the key.
writeln!(instruction, " {}[{}] into {destination_register};", arguments[0], arguments[1])
.expect("failed to write to string");
(destination_register, instruction)
}
_ => unreachable!("The only variants of Mapping are get, get_or, and set"),
},
Type::Identifier(Identifier { name: sym::group, .. }) => {
Expand Down
36 changes: 36 additions & 0 deletions compiler/passes/src/type_checking/checker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,42 @@ impl<'a> TypeChecker<'a> {
None
}
}
CoreFunction::MappingRemove => {
// Check that the operation is invoked in a `finalize` block.
if !self.is_finalize {
self.handler.emit_err(TypeCheckerError::invalid_operation_outside_finalize(
"Mapping::remove",
function_span,
))
}
// Check that the first argument is a mapping.
if let Some(mapping_type) = self.assert_mapping_type(&arguments[0].0, arguments[0].1) {
// Check that the second argument matches the key type of the mapping.
self.assert_type(&arguments[1].0, &mapping_type.key, arguments[1].1);
// Return nothing.
Some(Type::Unit)
} else {
None
}
}
CoreFunction::MappingContains => {
// Check that the operation is invoked in a `finalize` block.
if !self.is_finalize {
self.handler.emit_err(TypeCheckerError::invalid_operation_outside_finalize(
"Mapping::contains",
function_span,
))
}
// Check that the first argument is a mapping.
if let Some(mapping_type) = self.assert_mapping_type(&arguments[0].0, arguments[0].1) {
// Check that the second argument matches the key type of the mapping.
self.assert_type(&arguments[1].0, &mapping_type.key, arguments[1].1);
// Return a boolean.
Some(Type::Boolean)
} else {
None
}
}
CoreFunction::GroupToXCoordinate | CoreFunction::GroupToYCoordinate => {
// Check that the first argument is a group.
self.assert_group_type(&arguments[0].0, arguments[0].1);
Expand Down
2 changes: 2 additions & 0 deletions compiler/span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ symbols! {
commit_to_address,
commit_to_field,
commit_to_group,
contains,
get,
get_or_use,
hash_to_address,
Expand Down Expand Up @@ -190,6 +191,7 @@ symbols! {
rand_u32,
rand_u64,
rand_u128,
remove,
set,
to_x_coordinate,
to_y_coordinate,
Expand Down
12 changes: 12 additions & 0 deletions tests/expectations/compiler/finalize/contains.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
namespace: Compile
expectation: Pass
outputs:
- - initial_ast: dd6cce951b7bb1d85a9d077163ed2250323679284134c5f4686bedffff3e2195
unrolled_ast: dd6cce951b7bb1d85a9d077163ed2250323679284134c5f4686bedffff3e2195
ssa_ast: 935a4693920001b5de888f5e392e99fa4708c4fede196e03cc017bd01b1f871a
flattened_ast: 07926dfa14daa0d8b378d22bee1d93452ebfa555f7b4bea78a9b20b9c8bbcfdd
inlined_ast: 07926dfa14daa0d8b378d22bee1d93452ebfa555f7b4bea78a9b20b9c8bbcfdd
dce_ast: 07926dfa14daa0d8b378d22bee1d93452ebfa555f7b4bea78a9b20b9c8bbcfdd
bytecode: b8da9b000713a8ba980f8fa632c27a18563320758826f1f6cca908650ed8505a
warnings: ""
2 changes: 1 addition & 1 deletion tests/expectations/compiler/finalize/decrement_fail.out
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
namespace: Compile
expectation: Fail
outputs:
- "Error [ETYC0372005]: Unknown function `decrement`\n --> compiler-test:11:9\n |\n 11 | decrement(amounts, addr, amount);\n | ^^^^^^^^^\nWarning [WPAR0370001]: The keyword `decrement` is deprecated.\n --> compiler-test:11:9\n |\n 11 | decrement(amounts, addr, amount);\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n |\n = Use `Mapping::{get, get_or_use, set}` for manipulating on-chain mappings."
- "Error [ETYC0372005]: Unknown function `decrement`\n --> compiler-test:11:9\n |\n 11 | decrement(amounts, addr, amount);\n | ^^^^^^^^^\nWarning [WPAR0370001]: The keyword `decrement` is deprecated.\n --> compiler-test:11:9\n |\n 11 | decrement(amounts, addr, amount);\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n |\n = Use `Mapping::{get, get_or_use, set, remove, contains}` for manipulating on-chain mappings."
2 changes: 1 addition & 1 deletion tests/expectations/compiler/finalize/finalize_fail.out
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
namespace: Compile
expectation: Fail
outputs:
- "Error [ETYC0372005]: Unknown function `increment`\n --> compiler-test:12:9\n |\n 12 | increment(account, receiver, amount);\n | ^^^^^^^^^\nError [ETYC0372071]: A finalize block cannot return a value.\n --> compiler-test:19:5\n |\n 19 | finalize public_adder(a: u8, b: u8) -> public u8 {\n 20 | return a + b;\n 21 | }\n | ^\nError [ETYC0372005]: Unknown function `increment`\n --> compiler-test:28:9\n |\n 28 | increment(values, 0u8, 1u8);\n | ^^^^^^^^^\nError [ETYC0372005]: Unknown function `increment`\n --> compiler-test:29:9\n |\n 29 | increment(account, self.caller, 1u64);\n | ^^^^^^^^^\nWarning [WPAR0370001]: The keyword `increment` is deprecated.\n --> compiler-test:12:9\n |\n 12 | increment(account, receiver, amount);\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n |\n = Use `Mapping::{get, get_or_use, set}` for manipulating on-chain mappings.\nWarning [WPAR0370001]: The keyword `increment` is deprecated.\n --> compiler-test:28:9\n |\n 28 | increment(values, 0u8, 1u8);\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n |\n = Use `Mapping::{get, get_or_use, set}` for manipulating on-chain mappings.\nWarning [WPAR0370001]: The keyword `increment` is deprecated.\n --> compiler-test:29:9\n |\n 29 | increment(account, self.caller, 1u64);\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n |\n = Use `Mapping::{get, get_or_use, set}` for manipulating on-chain mappings."
- "Error [ETYC0372005]: Unknown function `increment`\n --> compiler-test:12:9\n |\n 12 | increment(account, receiver, amount);\n | ^^^^^^^^^\nError [ETYC0372071]: A finalize block cannot return a value.\n --> compiler-test:19:5\n |\n 19 | finalize public_adder(a: u8, b: u8) -> public u8 {\n 20 | return a + b;\n 21 | }\n | ^\nError [ETYC0372005]: Unknown function `increment`\n --> compiler-test:28:9\n |\n 28 | increment(values, 0u8, 1u8);\n | ^^^^^^^^^\nError [ETYC0372005]: Unknown function `increment`\n --> compiler-test:29:9\n |\n 29 | increment(account, self.caller, 1u64);\n | ^^^^^^^^^\nWarning [WPAR0370001]: The keyword `increment` is deprecated.\n --> compiler-test:12:9\n |\n 12 | increment(account, receiver, amount);\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n |\n = Use `Mapping::{get, get_or_use, set, remove, contains}` for manipulating on-chain mappings.\nWarning [WPAR0370001]: The keyword `increment` is deprecated.\n --> compiler-test:28:9\n |\n 28 | increment(values, 0u8, 1u8);\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n |\n = Use `Mapping::{get, get_or_use, set, remove, contains}` for manipulating on-chain mappings.\nWarning [WPAR0370001]: The keyword `increment` is deprecated.\n --> compiler-test:29:9\n |\n 29 | increment(account, self.caller, 1u64);\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n |\n = Use `Mapping::{get, get_or_use, set, remove, contains}` for manipulating on-chain mappings."
2 changes: 1 addition & 1 deletion tests/expectations/compiler/finalize/increment_fail.out
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
namespace: Compile
expectation: Fail
outputs:
- "Error [ETYC0372005]: Unknown function `increment`\n --> compiler-test:11:9\n |\n 11 | increment(amounts, addr, amount);\n | ^^^^^^^^^\nWarning [WPAR0370001]: The keyword `increment` is deprecated.\n --> compiler-test:11:9\n |\n 11 | increment(amounts, addr, amount);\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n |\n = Use `Mapping::{get, get_or_use, set}` for manipulating on-chain mappings."
- "Error [ETYC0372005]: Unknown function `increment`\n --> compiler-test:11:9\n |\n 11 | increment(amounts, addr, amount);\n | ^^^^^^^^^\nWarning [WPAR0370001]: The keyword `increment` is deprecated.\n --> compiler-test:11:9\n |\n 11 | increment(amounts, addr, amount);\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n |\n = Use `Mapping::{get, get_or_use, set, remove, contains}` for manipulating on-chain mappings."
12 changes: 12 additions & 0 deletions tests/expectations/compiler/finalize/remove.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
namespace: Compile
expectation: Pass
outputs:
- - initial_ast: f17405d1f77533951d0920b702487d1c24008ef33457df29f2e200879a83ffe5
unrolled_ast: f17405d1f77533951d0920b702487d1c24008ef33457df29f2e200879a83ffe5
ssa_ast: e5f96ad16a8d9be0e39013503d11a718e6c86449243a3647a4da9a677086fa03
flattened_ast: cf3f3389913274d14d788dd55d8b0e0df25330bcccb91e58a8f54ed92e7ca1f5
inlined_ast: cf3f3389913274d14d788dd55d8b0e0df25330bcccb91e58a8f54ed92e7ca1f5
dce_ast: cf3f3389913274d14d788dd55d8b0e0df25330bcccb91e58a8f54ed92e7ca1f5
bytecode: 5cae19c2ed8e380e13836028054b78e89448558fcf7af717be63d5737fe92edc
warnings: ""
2 changes: 1 addition & 1 deletion tests/expectations/parser/finalize/decrement_fail.out
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ namespace: ParseStatement
expectation: Fail
outputs:
- "Error [EPAR0370005]: expected ; -- found '['\n --> test:1:10\n |\n 1 | decrement[foo, bar, baz];\n | ^"
- "Error [EPAR0370005]: expected ; -- found '<eof>'\n --> test:1:15\n |\n 1 | decrement(floo)\n | ^Warning [WPAR0370001]: The keyword `decrement` is deprecated.\n --> test:1:1\n |\n 1 | decrement(floo)\n | ^^^^^^^^^^^^^^^\n |\n = Use `Mapping::{get, get_or_use, set}` for manipulating on-chain mappings."
- "Error [EPAR0370005]: expected ; -- found '<eof>'\n --> test:1:15\n |\n 1 | decrement(floo)\n | ^Warning [WPAR0370001]: The keyword `decrement` is deprecated.\n --> test:1:1\n |\n 1 | decrement(floo)\n | ^^^^^^^^^^^^^^^\n |\n = Use `Mapping::{get, get_or_use, set, remove, contains}` for manipulating on-chain mappings."
- "Error [EPAR0370005]: expected ; -- found 'foo'\n --> test:1:11\n |\n 1 | decrement foo[bar] by baz;\n | ^^^"
2 changes: 1 addition & 1 deletion tests/expectations/parser/finalize/increment_fail.out
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ namespace: ParseStatement
expectation: Fail
outputs:
- "Error [EPAR0370005]: expected ; -- found '['\n --> test:1:10\n |\n 1 | increment[foo, bar, baz];\n | ^"
- "Error [EPAR0370005]: expected ; -- found '<eof>'\n --> test:1:15\n |\n 1 | increment(floo)\n | ^Warning [WPAR0370001]: The keyword `increment` is deprecated.\n --> test:1:1\n |\n 1 | increment(floo)\n | ^^^^^^^^^^^^^^^\n |\n = Use `Mapping::{get, get_or_use, set}` for manipulating on-chain mappings."
- "Error [EPAR0370005]: expected ; -- found '<eof>'\n --> test:1:15\n |\n 1 | increment(floo)\n | ^Warning [WPAR0370001]: The keyword `increment` is deprecated.\n --> test:1:1\n |\n 1 | increment(floo)\n | ^^^^^^^^^^^^^^^\n |\n = Use `Mapping::{get, get_or_use, set, remove, contains}` for manipulating on-chain mappings."
- "Error [EPAR0370005]: expected ; -- found 'foo'\n --> test:1:11\n |\n 1 | increment foo[bar] by baz;\n | ^^^"
18 changes: 18 additions & 0 deletions tests/tests/compiler/finalize/contains.leo
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
namespace: Compile
expectation: Pass
*/

program test.aleo {

mapping balances: address => u32;

transition foo() -> () {
return then finalize(self.caller);
}

finalize foo(account: address) -> () {
let expect_false: bool = Mapping::contains(balances, account);
assert(!expect_false);
}
}
25 changes: 25 additions & 0 deletions tests/tests/compiler/finalize/remove.leo
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
namespace: Compile
expectation: Pass
*/

program test.aleo {

mapping balances: address => u32;

transition foo() -> () {
return then finalize(self.caller);
}

finalize foo(account: address) -> () {
Mapping::set(balances, account, 1u32);

let expect_true: bool = Mapping::contains(balances, account);
assert(expect_true);

Mapping::remove(balances, account); // Remove the mapping entry for account

let expect_false: bool = Mapping::contains(balances, account);
assert(!expect_false);
}
}
Loading