Skip to content

Commit

Permalink
feat: .del map method (#95)
Browse files Browse the repository at this point in the history
`del: map<K, V> -> K -> Bool`

returns `true` if key deletion was successful and `false` if the key was missing from the map
  • Loading branch information
Gusarich authored Apr 25, 2024
1 parent f777da3 commit 1ef4691
Show file tree
Hide file tree
Showing 9 changed files with 925 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- The `isEmpty` extension function for the `Map` type: PR [#266](https://github.com/tact-lang/tact/pull/266)
- The `pow2` power function with base 2: PR [#267](https://github.com/tact-lang/tact/pull/267)
- The `try` and `try-catch` statements: PR [#212](https://github.com/tact-lang/tact/pull/212)
- The `del` method for the `Map` type: PR [#95](https://github.com/tact-lang/tact/pull/95)

### Changed

Expand Down
67 changes: 67 additions & 0 deletions src/abi/map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,73 @@ export const MapFunctions: Map<string, AbiFunction> = new Map([
},
},
],
[
"del",
{
name: "del",
resolve(ctx, args, ref) {
// Check arguments
if (args.length !== 2) {
throwError("del expects one argument", ref); // Ignore self argument
}
const self = args[0];
if (!self || self.kind !== "map") {
throwError("del expects a map as self argument", ref); // Should not happen
}

// Check key type
if (args[1].kind !== "ref" || args[1].optional) {
throwError(
"del expects a direct type as first argument",
ref,
);
}
if (args[1].name !== self.key) {
throwError(
`del expects a ${self.key} as first argument`,
ref,
);
}

// Returns boolean
return { kind: "ref", name: "Bool", optional: false };
},
generate: (ctx, args, exprs, ref) => {
if (args.length !== 2) {
throwError("del expects one argument", ref); // Ignore self argument
}
const self = args[0];
if (!self || self.kind !== "map") {
throwError("del expects a map as self argument", ref); // Should not happen
}

// Render expressions
const resolved = exprs.map((v) => writeExpression(v, ctx));

// Handle Int key
if (self.key === "Int") {
let bits = 257;
let kind = "int";
if (self.keyAs && self.keyAs.startsWith("int")) {
bits = parseInt(self.keyAs.slice(3), 10);
} else if (self.keyAs && self.keyAs.startsWith("uint")) {
bits = parseInt(self.keyAs.slice(4), 10);
kind = "uint";
}
ctx.used(`__tact_dict_delete_${kind}`);
return `${resolved[0]}~__tact_dict_delete_${kind}(${bits}, ${resolved[1]})`;
}

// Handle Address key
if (self.key === "Address") {
ctx.used(`__tact_dict_delete`);
return `${resolved[0]}~__tact_dict_delete(267, ${resolved[1]})`;
}

throwError(`del expects a map with Int keys`, ref);
},
},
],
[
"asCell",
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,30 @@ return __tact_create_address(chain, hash);",
"name": "__tact_dict_delete",
"signature": "(cell, int) __tact_dict_delete(cell dict, int key_len, slice index)",
},
{
"code": {
"code": "asm(index dict key_len) "DICTIDEL"",
"kind": "asm",
},
"comment": null,
"context": "stdlib",
"depends": Set {},
"flags": Set {},
"name": "__tact_dict_delete_int",
"signature": "(cell, int) __tact_dict_delete_int(cell dict, int key_len, int index)",
},
{
"code": {
"code": "asm(index dict key_len) "DICTUDEL"",
"kind": "asm",
},
"comment": null,
"context": "stdlib",
"depends": Set {},
"flags": Set {},
"name": "__tact_dict_delete_uint",
"signature": "(cell, int) __tact_dict_delete_uint(cell dict, int key_len, int index)",
},
{
"code": {
"code": "asm(value index dict key_len) "DICTSETREF"",
Expand Down Expand Up @@ -4275,6 +4299,30 @@ return __tact_create_address(chain, hash);",
"name": "__tact_dict_delete",
"signature": "(cell, int) __tact_dict_delete(cell dict, int key_len, slice index)",
},
{
"code": {
"code": "asm(index dict key_len) "DICTIDEL"",
"kind": "asm",
},
"comment": null,
"context": "stdlib",
"depends": Set {},
"flags": Set {},
"name": "__tact_dict_delete_int",
"signature": "(cell, int) __tact_dict_delete_int(cell dict, int key_len, int index)",
},
{
"code": {
"code": "asm(index dict key_len) "DICTUDEL"",
"kind": "asm",
},
"comment": null,
"context": "stdlib",
"depends": Set {},
"flags": Set {},
"name": "__tact_dict_delete_uint",
"signature": "(cell, int) __tact_dict_delete_uint(cell dict, int key_len, int index)",
},
{
"code": {
"code": "asm(value index dict key_len) "DICTSETREF"",
Expand Down Expand Up @@ -8315,6 +8363,30 @@ return __tact_create_address(chain, hash);",
"name": "__tact_dict_delete",
"signature": "(cell, int) __tact_dict_delete(cell dict, int key_len, slice index)",
},
{
"code": {
"code": "asm(index dict key_len) "DICTIDEL"",
"kind": "asm",
},
"comment": null,
"context": "stdlib",
"depends": Set {},
"flags": Set {},
"name": "__tact_dict_delete_int",
"signature": "(cell, int) __tact_dict_delete_int(cell dict, int key_len, int index)",
},
{
"code": {
"code": "asm(index dict key_len) "DICTUDEL"",
"kind": "asm",
},
"comment": null,
"context": "stdlib",
"depends": Set {},
"flags": Set {},
"name": "__tact_dict_delete_uint",
"signature": "(cell, int) __tact_dict_delete_uint(cell dict, int key_len, int index)",
},
{
"code": {
"code": "asm(value index dict key_len) "DICTSETREF"",
Expand Down
16 changes: 16 additions & 0 deletions src/generator/writers/writeStdlib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,22 @@ export function writeStdlib(ctx: WriterContext) {
ctx.asm(`asm(index dict key_len) "DICTDEL"`);
});

ctx.fun("__tact_dict_delete_int", () => {
ctx.signature(
`(cell, int) __tact_dict_delete_int(cell dict, int key_len, int index)`,
);
ctx.context("stdlib");
ctx.asm(`asm(index dict key_len) "DICTIDEL"`);
});

ctx.fun("__tact_dict_delete_uint", () => {
ctx.signature(
`(cell, int) __tact_dict_delete_uint(cell dict, int key_len, int index)`,
);
ctx.context("stdlib");
ctx.asm(`asm(index dict key_len) "DICTUDEL"`);
});

ctx.fun("__tact_dict_set_ref", () => {
ctx.signature(
`((cell), ()) __tact_dict_set_ref(cell dict, int key_len, slice index, cell value)`,
Expand Down
Loading

0 comments on commit 1ef4691

Please sign in to comment.