From 167cf967dc5ba42a1df02a1e41175b2a7f7a800c Mon Sep 17 00:00:00 2001 From: polyprogrammist Date: Fri, 8 Nov 2024 19:49:08 +0800 Subject: [PATCH] storedirect, loaddirect --- jest.config.js | 2 +- src/astbuilder/handle_type.ts | 2 +- test/generated_files/generated_block.ts | 28 ++++++------------------- test/generated_files/generated_test.ts | 28 ++++++------------------- test/tlbgen.spec.ts | 28 ------------------------- 5 files changed, 14 insertions(+), 74 deletions(-) diff --git a/jest.config.js b/jest.config.js index 6218cc8..8af0e05 100644 --- a/jest.config.js +++ b/jest.config.js @@ -3,6 +3,6 @@ module.exports = { preset: 'ts-jest', testEnvironment: 'node', testMatch: [ - "**/?(*.)+(spec|test).[j|t]s?(x)" + "**/?(*.)+(spec|test).[j]s?(x)" ] }; \ No newline at end of file diff --git a/src/astbuilder/handle_type.ts b/src/astbuilder/handle_type.ts index f141e90..2cd7d98 100644 --- a/src/astbuilder/handle_type.ts +++ b/src/astbuilder/handle_type.ts @@ -182,7 +182,7 @@ export function getType( throw new Error('Hashmap key should be number') } return { kind: "TLBHashmapType", key: key, value: value, extra: extra, directStore: false }; - } else if (expr.name == "Hashmap") { + } else if (expr.name == "Hashmap" && constructor.tlbType != "HashmapNode") { let key = getType(expr.args[0], constructor, fieldTypeName) let value = getType(expr.args[1], constructor, fieldTypeName) if (key.kind != 'TLBExprMathType') { diff --git a/test/generated_files/generated_block.ts b/test/generated_files/generated_block.ts index 3a19ff2..0513075 100644 --- a/test/generated_files/generated_block.ts +++ b/test/generated_files/generated_block.ts @@ -138,8 +138,8 @@ export interface HashmapNode_hmn_leaf { export interface HashmapNode_hmn_fork { readonly kind: 'HashmapNode_hmn_fork'; readonly n: number; - readonly left: Dictionary; - readonly right: Dictionary; + readonly left: Hashmap; + readonly right: Hashmap; } // hml_short$0 {m:#} {n:#} len:(Unary ~n) {n <= m} s:(n * Bit) = HmLabel ~n m; @@ -4021,15 +4021,9 @@ export function loadHashmapNode(slice: Slice, arg0: number, loadX: (slice: Sl } if (true) { let slice1 = slice.loadRef().beginParse(true); - let left: Dictionary = Dictionary.loadDirect(Dictionary.Keys.BigUint((arg0 - 1)), { - serialize: () => { throw new Error('Not implemented') }, - parse: loadX, - }, slice1); + let left: Hashmap = loadHashmap(slice1, (arg0 - 1), loadX); let slice2 = slice.loadRef().beginParse(true); - let right: Dictionary = Dictionary.loadDirect(Dictionary.Keys.BigUint((arg0 - 1)), { - serialize: () => { throw new Error('Not implemented') }, - parse: loadX, - }, slice2); + let right: Hashmap = loadHashmap(slice2, (arg0 - 1), loadX); return { kind: 'HashmapNode_hmn_fork', n: (arg0 - 1), @@ -4051,20 +4045,10 @@ export function storeHashmapNode(hashmapNode: HashmapNode, storeX: (x: X) if ((hashmapNode.kind == 'HashmapNode_hmn_fork')) { return ((builder: Builder) => { let cell1 = beginCell(); - cell1.storeDictDirect(hashmapNode.left, Dictionary.Keys.BigUint((hashmapNode.arg0 - 1)), { - serialize: ((arg: X, builder: Builder) => { - storeX(arg)(builder); - }), - parse: () => { throw new Error('Not implemented') }, - }); + storeHashmap(hashmapNode.left, storeX)(cell1); builder.storeRef(cell1); let cell2 = beginCell(); - cell2.storeDictDirect(hashmapNode.right, Dictionary.Keys.BigUint((hashmapNode.arg0 - 1)), { - serialize: ((arg: X, builder: Builder) => { - storeX(arg)(builder); - }), - parse: () => { throw new Error('Not implemented') }, - }); + storeHashmap(hashmapNode.right, storeX)(cell2); builder.storeRef(cell2); }) diff --git a/test/generated_files/generated_test.ts b/test/generated_files/generated_test.ts index 9bec734..1dd3d50 100644 --- a/test/generated_files/generated_test.ts +++ b/test/generated_files/generated_test.ts @@ -507,8 +507,8 @@ export interface HashmapNode_hmn_leaf { export interface HashmapNode_hmn_fork { readonly kind: 'HashmapNode_hmn_fork'; readonly n: number; - readonly left: Dictionary; - readonly right: Dictionary; + readonly left: Hashmap; + readonly right: Hashmap; } // hml_short$0 {m:#} {n:#} len:(Unary ~n) {n <= m} s:(n * Bit) = HmLabel ~n m; @@ -2604,15 +2604,9 @@ export function loadHashmapNode(slice: Slice, arg0: number, loadX: (slice: Sl } if (true) { let slice1 = slice.loadRef().beginParse(true); - let left: Dictionary = Dictionary.loadDirect(Dictionary.Keys.BigUint((arg0 - 1)), { - serialize: () => { throw new Error('Not implemented') }, - parse: loadX, - }, slice1); + let left: Hashmap = loadHashmap(slice1, (arg0 - 1), loadX); let slice2 = slice.loadRef().beginParse(true); - let right: Dictionary = Dictionary.loadDirect(Dictionary.Keys.BigUint((arg0 - 1)), { - serialize: () => { throw new Error('Not implemented') }, - parse: loadX, - }, slice2); + let right: Hashmap = loadHashmap(slice2, (arg0 - 1), loadX); return { kind: 'HashmapNode_hmn_fork', n: (arg0 - 1), @@ -2634,20 +2628,10 @@ export function storeHashmapNode(hashmapNode: HashmapNode, storeX: (x: X) if ((hashmapNode.kind == 'HashmapNode_hmn_fork')) { return ((builder: Builder) => { let cell1 = beginCell(); - cell1.storeDictDirect(hashmapNode.left, Dictionary.Keys.BigUint((hashmapNode.arg0 - 1)), { - serialize: ((arg: X, builder: Builder) => { - storeX(arg)(builder); - }), - parse: () => { throw new Error('Not implemented') }, - }); + storeHashmap(hashmapNode.left, storeX)(cell1); builder.storeRef(cell1); let cell2 = beginCell(); - cell2.storeDictDirect(hashmapNode.right, Dictionary.Keys.BigUint((hashmapNode.arg0 - 1)), { - serialize: ((arg: X, builder: Builder) => { - storeX(arg)(builder); - }), - parse: () => { throw new Error('Not implemented') }, - }); + storeHashmap(hashmapNode.right, storeX)(cell2); builder.storeRef(cell2); }) diff --git a/test/tlbgen.spec.ts b/test/tlbgen.spec.ts index 73778fd..cc04d09 100644 --- a/test/tlbgen.spec.ts +++ b/test/tlbgen.spec.ts @@ -509,34 +509,6 @@ describe('Generating tlb code', () => { checkDifferOnStoreLoad(intBitsParametrizedOutsideIncorrect, loadIntBitsParametrizedOutside, storeIntBitsParametrizedOutside); }) - test('storedirect', () => { - let simpleDict: Dictionary = Dictionary.empty() - simpleDict.set(1, 6); - simpleDict.set(2, 7); - simpleDict.set(0, 5); - - let builder = beginCell(); - builder.storeDictDirect(simpleDict, Dictionary.Keys.Int(32), Dictionary.Values.Int(32)); - let slice = builder.endCell().beginParse(); - - let hashmap = loadHashmap(slice, 32, (arg: Slice) => { - return arg.loadInt(32) + 1; - }) - - let new_builder = beginCell(); - storeHashmap(hashmap, (x: number) => { - return ((builder: Builder) => { - builder.storeInt(x, 32); - }) - })(new_builder) - - let newSlice = new_builder.endCell().beginParse(); - - - let newDict = newSlice.loadDictDirect(Dictionary.Keys.Int(32), Dictionary.Values.Int(32)); - console.log(newDict); - }) - test('block tlb tests', () => { const state = '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';