Skip to content

Commit c4ca281

Browse files
committed
fix: generator code correct behavior for store method for Bit selection expression #56
1 parent 598c856 commit c4ca281

13 files changed

Lines changed: 1245 additions & 41 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
### Fixed
66

77
- Fix generate code for cell as ref [issues #59](https://github.com/ton-community/tlb-codegen/issues/59)
8+
- Fix generator code correct behavior for store method for Bit selection expression [issues #56](https://github.com/ton-community/tlb-codegen/issues/56)
89

910
### Chore
1011

src/generators/typescript/complex_expr.ts

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import {
3333
tTypeWithParameters,
3434
tTypedIdentifier,
3535
tUnaryOpExpression,
36+
tPostfixExpression,
3637
toCode,
3738
} from './tsgen';
3839
import { ExprForParam, convertToAST, getNegationDerivationFunctionBody, isBigIntExpr } from './utils';
@@ -138,12 +139,14 @@ export function storeExprForParam(
138139
theCell: string,
139140
exprForParam: ExprForParam,
140141
insideStoreParameters: Expression[],
142+
isOptional: boolean = false,
141143
): Statement {
144+
let params = insideStoreParameters;
145+
if (isOptional && params.length > 0) {
146+
params = [tPostfixExpression(params[0], '!'), ...params.slice(1)];
147+
}
142148
return tExpressionStatement(
143-
tFunctionCall(
144-
tMemberExpression(id(theCell), id('store' + exprForParam.fieldStoreSuffix)),
145-
insideStoreParameters,
146-
),
149+
tFunctionCall(tMemberExpression(id(theCell), id('store' + exprForParam.fieldStoreSuffix)), params),
147150
);
148151
}
149152
export function returnSliceFunc(): Expression {
@@ -210,17 +213,27 @@ export function loadTupleExpr(arrayLength: Expression, loadExpr: Expression): Ex
210213
[tArrowFunctionExpression([tTypedIdentifier(id('arg'), id('number'))], [tReturnStatement(loadExpr)])],
211214
);
212215
}
213-
export function storeExprCond(currentParam: Expression, storeExpr: Statement): Statement {
214-
return tIfStatement(tBinaryExpression(currentParam, '!=', id('undefined')), [storeExpr]);
216+
export function storeExprCond(currentParam: Expression, storeExpr: Statement, conditionExpr?: Expression): Statement {
217+
let condition: Expression;
218+
if (conditionExpr) {
219+
const undefinedCheck = tBinaryExpression(currentParam, '!=', id('undefined'));
220+
condition = tBinaryExpression(conditionExpr, '&&', undefinedCheck);
221+
} else {
222+
condition = tBinaryExpression(currentParam, '!=', id('undefined'));
223+
}
224+
return tIfStatement(condition, [storeExpr]);
215225
}
216226
export function storeExpressionNamedType(
217227
typeName: string,
218228
insideStoreParameters: Expression[],
219229
currentCell: string,
230+
isOptional: boolean = false,
220231
): Statement {
221-
return tExpressionStatement(
222-
tFunctionCall(tFunctionCall(id('store' + typeName), insideStoreParameters), [id(currentCell)]),
223-
);
232+
let params = insideStoreParameters;
233+
if (isOptional && params.length > 0) {
234+
params = [tPostfixExpression(params[0], '!'), ...params.slice(1)];
235+
}
236+
return tExpressionStatement(tFunctionCall(tFunctionCall(id('store' + typeName), params), [id(currentCell)]));
224237
}
225238
export function storeRefObjectStmt(currentCell: string, ctx: ConstructorContext, field: TLBField): Statement {
226239
return tExpressionStatement(

src/generators/typescript/generator.ts

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,7 @@ export function loadBoolTrue(slice: Slice): Bool {
558558
ctx.storeStatements.push(storeRefObjectStmt(currentCell, ctx, field));
559559
});
560560
} else if (field.subFields.length == 0) {
561-
let fieldInfo = this.handleType(field, field.fieldType, true, ctx, slicePrefix, 0);
561+
let fieldInfo = this.handleType(field, field.fieldType, true, ctx, slicePrefix, 0, false);
562562
if (fieldInfo.loadExpr) {
563563
addLoadProperty(field.name, fieldInfo.loadExpr, fieldInfo.typeParamExpr, ctx);
564564
}
@@ -581,6 +581,7 @@ export function loadBoolTrue(slice: Slice): Bool {
581581
ctx: ConstructorContext,
582582
slicePrefix: Array<number>,
583583
argIndex: number,
584+
isConditional: boolean = false,
584585
): FieldInfoType {
585586
let currentSlice = getCurrentSlice(slicePrefix, 'slice');
586587
let currentCell = getCurrentSlice(slicePrefix, 'cell');
@@ -748,16 +749,26 @@ export function loadBoolTrue(slice: Slice): Bool {
748749
result.typeParamExpr = id(typeName);
749750
if (isField) {
750751
result.loadExpr = tFunctionCall(id('load' + typeName), [id(theSlice)]);
751-
result.storeStmtOutside = storeExpressionNamedType(typeName, storeParametersOutside, currentCell);
752-
result.storeStmtInside = storeExpressionNamedType(typeName, storeParametersInside, currentCell);
752+
result.storeStmtOutside = storeExpressionNamedType(
753+
typeName,
754+
storeParametersOutside,
755+
currentCell,
756+
isConditional,
757+
);
758+
result.storeStmtInside = storeExpressionNamedType(
759+
typeName,
760+
storeParametersInside,
761+
currentCell,
762+
isConditional,
763+
);
753764
} else {
754765
result.loadExpr = id('load' + typeName);
755766
result.storeStmtOutside = tExpressionStatement(id('store' + typeName));
756767
}
757768
} else if (fieldType.kind == 'TLBCondType') {
758769
let subExprInfo: FieldInfoType;
759770
let conditionExpr: Expression;
760-
subExprInfo = this.handleType(field, fieldType.value, true, ctx, slicePrefix, argIndex);
771+
subExprInfo = this.handleType(field, fieldType.value, true, ctx, slicePrefix, argIndex, true);
761772
conditionExpr = convertToAST(fieldType.condition, ctx.constructor);
762773
if (subExprInfo.typeParamExpr) {
763774
result.typeParamExpr = tUnionTypeExpression([subExprInfo.typeParamExpr, id('undefined')]);
@@ -768,14 +779,32 @@ export function loadBoolTrue(slice: Slice): Bool {
768779
let currentParamOutside = storeParametersOutside[0];
769780
let currentParamInside = storeParametersInside[0];
770781
if (currentParamOutside && currentParamInside && subExprInfo.storeStmtOutside) {
771-
result.storeStmtOutside = storeExprCond(currentParamOutside, subExprInfo.storeStmtOutside);
772-
result.storeStmtInside = storeExprCond(currentParamInside, subExprInfo.storeStmtOutside);
782+
let storeConditionExpr: Expression | undefined;
783+
if (fieldType.condition) {
784+
let objectParam = id(ctx.typeName);
785+
storeConditionExpr = convertToAST(fieldType.condition, ctx.constructor, objectParam);
786+
}
787+
result.storeStmtOutside = storeExprCond(
788+
currentParamOutside,
789+
subExprInfo.storeStmtOutside,
790+
storeConditionExpr,
791+
);
792+
if (storeConditionExpr && fieldType.condition) {
793+
const storeConditionExprInside = convertToAST(fieldType.condition, ctx.constructor, id('arg'));
794+
result.storeStmtInside = storeExprCond(
795+
currentParamInside,
796+
subExprInfo.storeStmtOutside,
797+
storeConditionExprInside,
798+
);
799+
} else {
800+
result.storeStmtInside = storeExprCond(currentParamInside, subExprInfo.storeStmtOutside);
801+
}
773802
}
774803
} else if (fieldType.kind == 'TLBMultipleType') {
775804
let arrayLength: Expression;
776805
let subExprInfo: FieldInfoType;
777806
arrayLength = convertToAST(fieldType.times, ctx.constructor);
778-
subExprInfo = this.handleType(field, fieldType.value, false, ctx, slicePrefix, argIndex);
807+
subExprInfo = this.handleType(field, fieldType.value, false, ctx, slicePrefix, argIndex, false);
779808
let currentParamOutside = storeParametersOutside[0];
780809
let currentParamInside = storeParametersInside[0];
781810
if (subExprInfo.loadExpr) {
@@ -1002,8 +1031,8 @@ export function loadBoolTrue(slice: Slice): Bool {
10021031
result.loadFunctionExpr = returnSliceFunc();
10031032
}
10041033
result.typeParamExpr = id(exprForParam.paramType);
1005-
result.storeStmtOutside = storeExprForParam(theCell, exprForParam, storeParametersOutside);
1006-
result.storeStmtInside = storeExprForParam(theCell, exprForParam, storeParametersInside);
1034+
result.storeStmtOutside = storeExprForParam(theCell, exprForParam, storeParametersOutside, isConditional);
1035+
result.storeStmtInside = storeExprForParam(theCell, exprForParam, storeParametersInside, isConditional);
10071036
}
10081037

10091038
if (result.loadExpr && !result.loadFunctionExpr) {

src/generators/typescript/tsgen.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,12 @@ export interface UnaryOpExpression extends ASTNode {
154154
expr: Expression;
155155
}
156156

157+
export interface PostfixExpression extends ASTNode {
158+
type: 'PostfixExpression';
159+
expr: Expression;
160+
operator: string;
161+
}
162+
157163
export interface BinaryExpression extends ASTNode {
158164
type: 'BinaryExpression';
159165
binarySign: string;
@@ -205,7 +211,8 @@ export type Expression =
205211
| TypeParametersExpression
206212
| DeclareVariable
207213
| TernaryExpression
208-
| UnaryOpExpression;
214+
| UnaryOpExpression
215+
| PostfixExpression;
209216
export type GenDeclaration =
210217
| ImportDeclaration
211218
| StructDeclaration
@@ -367,6 +374,14 @@ export function tUnaryOpExpression(unaryOperator: string, expr: Expression): Una
367374
};
368375
}
369376

377+
export function tPostfixExpression(expr: Expression, operator: string): PostfixExpression {
378+
return {
379+
type: 'PostfixExpression',
380+
expr: expr,
381+
operator: operator,
382+
};
383+
}
384+
370385
export function tBinaryExpression(left: Expression, binarySign: string, right: Expression): BinaryExpression {
371386
return {
372387
type: 'BinaryExpression',
@@ -594,6 +609,10 @@ export function toCode(node: TheNode, code: CodeBuilder = new CodeBuilder()): Co
594609
code.add(`(${node.unaryOperator}${toCode(node.expr).render()})`, false);
595610
}
596611

612+
if (node.type == 'PostfixExpression') {
613+
code.add(`(${toCode(node.expr).render()}${node.operator})`, false);
614+
}
615+
597616
if (node.type == 'BinaryExpression') {
598617
code.add(`(${toCode(node.left).render()} ${node.binarySign} ${toCode(node.right).render()})`, false);
599618
}

src/generators/typescript/utils.ts

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,47 @@ export function addLoadProperty(
141141
ctx.loadProperties.push(tObjectProperty(nameId, nameId));
142142
}
143143

144-
export function convertToAST(mathExpr: TLBMathExpr, constructor: TLBConstructor, objectId?: Identifier): Expression {
144+
export function convertToAST(
145+
mathExpr: TLBMathExpr,
146+
constructor: TLBConstructor,
147+
objectId?: Identifier | Expression,
148+
): Expression {
145149
if (mathExpr instanceof TLBVarExpr) {
146150
let varName = mathExpr.x;
147151
if (objectId != undefined) {
148-
return tMemberExpression(objectId, id(varName));
152+
let fieldName = varName;
153+
let field = constructor.fields.find((f) => f.name === varName);
154+
if (field) {
155+
fieldName = field.name;
156+
} else {
157+
const parameter = constructor.parameters.find((p) => {
158+
let paramName = p.variable.name;
159+
if (p.argName) {
160+
paramName = p.argName;
161+
}
162+
return paramName === varName;
163+
});
164+
if (parameter) {
165+
const paramVarName = parameter.variable.name;
166+
if (paramVarName) {
167+
field = constructor.fields.find((f) => f.name === paramVarName);
168+
if (field) {
169+
fieldName = field.name;
170+
} else {
171+
fieldName = paramVarName;
172+
}
173+
}
174+
} else {
175+
const variable = constructor.variablesMap.get(varName);
176+
if (variable?.isField) {
177+
field = constructor.fields.find((f) => f.name === varName);
178+
if (field) {
179+
fieldName = field.name;
180+
}
181+
}
182+
}
183+
}
184+
return tMemberExpression(objectId, id(fieldName));
149185
}
150186
return id(varName);
151187
}

0 commit comments

Comments
 (0)