From 672f7711df473bd90e96b83d291b84e62f1417ee Mon Sep 17 00:00:00 2001 From: Klaus Date: Thu, 3 Jul 2025 20:19:56 +0100 Subject: [PATCH 1/4] cleaning up how we check for `TupleExpression`s with a single item, so we minimise the amount of chained accesses and as a bonus removing the non-null assertions --- src/slang-nodes/ConditionalExpression.ts | 21 +++++++++++++++------ src/slang-nodes/MemberAccessExpression.ts | 6 +++--- src/slang-nodes/TupleValues.ts | 13 +++++++++---- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/slang-nodes/ConditionalExpression.ts b/src/slang-nodes/ConditionalExpression.ts index 3eb098044..9ef53d653 100644 --- a/src/slang-nodes/ConditionalExpression.ts +++ b/src/slang-nodes/ConditionalExpression.ts @@ -133,13 +133,22 @@ export class ConditionalExpression implements SlangNode { // We can remove parentheses only because we are sure that the // `condition` must be a single `bool` value. const operandLoc = this.operand.loc; - while ( - this.operand.variant.kind === NonterminalKind.TupleExpression && - this.operand.variant.items.items.length === 1 && - this.operand.variant.items.items[0].expression!.variant.kind !== - NonterminalKind.ConditionalExpression + + const getOperandSingleExpression = (): Expression | undefined => { + const operandVariant = this.operand.variant; + return operandVariant.kind === NonterminalKind.TupleExpression + ? operandVariant.items.getSingleExpression() + : undefined; + }; + + for ( + let operandSingleExpression = getOperandSingleExpression(); + operandSingleExpression && + operandSingleExpression.variant.kind !== + NonterminalKind.ConditionalExpression; + operandSingleExpression = getOperandSingleExpression() ) { - this.operand = this.operand.variant.items.items[0].expression!; + this.operand = operandSingleExpression; } this.operand.loc = operandLoc; } diff --git a/src/slang-nodes/MemberAccessExpression.ts b/src/slang-nodes/MemberAccessExpression.ts index 734c8a0fa..b55919b6c 100644 --- a/src/slang-nodes/MemberAccessExpression.ts +++ b/src/slang-nodes/MemberAccessExpression.ts @@ -24,9 +24,9 @@ function isEndOfChain( path: AstPath ): boolean { for ( - let i = 2, current: StrictAstNode = node, grandparent = path.getNode(i)!; - isChainableExpression(grandparent); - i += 2, current = grandparent, grandparent = path.getNode(i)! + let i = 2, current: StrictAstNode = node, grandparent = path.getNode(i); + grandparent && isChainableExpression(grandparent); + i += 2, current = grandparent, grandparent = path.getNode(i) ) { switch (grandparent.kind) { case NonterminalKind.MemberAccessExpression: diff --git a/src/slang-nodes/TupleValues.ts b/src/slang-nodes/TupleValues.ts index e2e37cdcf..6ad6a0ea4 100644 --- a/src/slang-nodes/TupleValues.ts +++ b/src/slang-nodes/TupleValues.ts @@ -8,6 +8,7 @@ import type * as ast from '@nomicfoundation/slang/ast'; import type { AstPath, Doc, ParserOptions } from 'prettier'; import type { AstNode } from './types.d.ts'; import type { PrintFunction, SlangNode } from '../types.d.ts'; +import type { Expression } from './Expression.js'; export class TupleValues implements SlangNode { readonly kind = NonterminalKind.TupleValues; @@ -32,11 +33,15 @@ export class TupleValues implements SlangNode { this.loc = metadata.loc; } + getSingleExpression(): Expression | undefined { + return this.items.length === 1 ? this.items[0].expression : undefined; + } + print(path: AstPath, print: PrintFunction): Doc { - return this.items.length === 1 && - this.items[0].expression && - this.items[0].expression.variant.kind !== TerminalKind.Identifier && - isBinaryOperation(this.items[0].expression.variant) + const singleExpression = this.getSingleExpression(); + return singleExpression && + singleExpression.variant.kind !== TerminalKind.Identifier && + isBinaryOperation(singleExpression.variant) ? path.map(print, 'items') : printSeparatedList(path.map(print, 'items')); } From d51cf4904837a34ba44cc435b2b7c48a066b92b6 Mon Sep 17 00:00:00 2001 From: Klaus Date: Wed, 9 Jul 2025 20:23:26 +0100 Subject: [PATCH 2/4] cleanup --- src/slang-nodes/ConditionalExpression.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/slang-nodes/ConditionalExpression.ts b/src/slang-nodes/ConditionalExpression.ts index 9ef53d653..d8098c3fe 100644 --- a/src/slang-nodes/ConditionalExpression.ts +++ b/src/slang-nodes/ConditionalExpression.ts @@ -100,6 +100,14 @@ function traditionalTernaries( ]); } +function getOperandSingleExpression({ + variant +}: Expression): Expression | undefined { + return variant.kind === NonterminalKind.TupleExpression + ? variant.items.getSingleExpression() + : undefined; +} + export class ConditionalExpression implements SlangNode { readonly kind = NonterminalKind.ConditionalExpression; @@ -133,20 +141,12 @@ export class ConditionalExpression implements SlangNode { // We can remove parentheses only because we are sure that the // `condition` must be a single `bool` value. const operandLoc = this.operand.loc; - - const getOperandSingleExpression = (): Expression | undefined => { - const operandVariant = this.operand.variant; - return operandVariant.kind === NonterminalKind.TupleExpression - ? operandVariant.items.getSingleExpression() - : undefined; - }; - for ( - let operandSingleExpression = getOperandSingleExpression(); + let operandSingleExpression = getOperandSingleExpression(this.operand); operandSingleExpression && operandSingleExpression.variant.kind !== NonterminalKind.ConditionalExpression; - operandSingleExpression = getOperandSingleExpression() + operandSingleExpression = getOperandSingleExpression(this.operand) ) { this.operand = operandSingleExpression; } From d49ddafb0599c384b629471d64286e7129a2a936 Mon Sep 17 00:00:00 2001 From: Klaus Date: Fri, 11 Jul 2025 00:25:20 +0100 Subject: [PATCH 3/4] small size improvement --- src/slang-nodes/TupleValues.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/slang-nodes/TupleValues.ts b/src/slang-nodes/TupleValues.ts index 6ad6a0ea4..221c7af98 100644 --- a/src/slang-nodes/TupleValues.ts +++ b/src/slang-nodes/TupleValues.ts @@ -34,7 +34,8 @@ export class TupleValues implements SlangNode { } getSingleExpression(): Expression | undefined { - return this.items.length === 1 ? this.items[0].expression : undefined; + const items = this.items; + return items.length === 1 ? items[0].expression : undefined; } print(path: AstPath, print: PrintFunction): Doc { From 012652787fd4f9a1fdca1c38ea731c95d42135ef Mon Sep 17 00:00:00 2001 From: Klaus Date: Sun, 13 Jul 2025 14:28:16 +0100 Subject: [PATCH 4/4] storing expression.variant instead of expression --- src/slang-nodes/TupleValues.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/slang-nodes/TupleValues.ts b/src/slang-nodes/TupleValues.ts index 221c7af98..37eafc62b 100644 --- a/src/slang-nodes/TupleValues.ts +++ b/src/slang-nodes/TupleValues.ts @@ -39,10 +39,10 @@ export class TupleValues implements SlangNode { } print(path: AstPath, print: PrintFunction): Doc { - const singleExpression = this.getSingleExpression(); - return singleExpression && - singleExpression.variant.kind !== TerminalKind.Identifier && - isBinaryOperation(singleExpression.variant) + const singleExpressionVariant = this.getSingleExpression()?.variant; + return singleExpressionVariant && + singleExpressionVariant.kind !== TerminalKind.Identifier && + isBinaryOperation(singleExpressionVariant) ? path.map(print, 'items') : printSeparatedList(path.map(print, 'items')); }