Skip to content

Commit e1a7e70

Browse files
Jantherfvictorio
andauthored
Cleaning up variant logic (#1209)
* exiting early when the variant is a string or an Identifier to avoid an extra check at the end * adding a printVariant helper * storing `variant` before switch statement * helper function for variant creation * Avoid unnecessary type casts * updating all `createNonterminalVariant` based on Franco's feedback --------- Co-authored-by: Franco Victorio <[email protected]>
1 parent 44521d7 commit e1a7e70

37 files changed

Lines changed: 775 additions & 942 deletions

src/slang-nodes/ArgumentsDeclaration.ts

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,27 @@
1+
import * as ast from '@nomicfoundation/slang/ast';
12
import { NonterminalKind } from '@nomicfoundation/slang/cst';
23
import { SlangNode } from './SlangNode.js';
34
import { PositionalArgumentsDeclaration } from './PositionalArgumentsDeclaration.js';
45
import { NamedArgumentsDeclaration } from './NamedArgumentsDeclaration.js';
56

6-
import type * as ast from '@nomicfoundation/slang/ast';
77
import type { AstPath, Doc, ParserOptions } from 'prettier';
88
import type { AstNode } from './types.d.ts';
99
import type { PrintFunction } from '../types.d.ts';
1010

11+
function createNonterminalVariant(
12+
variant: ast.ArgumentsDeclaration['variant'],
13+
options: ParserOptions<AstNode>
14+
): ArgumentsDeclaration['variant'] {
15+
if (variant instanceof ast.PositionalArgumentsDeclaration) {
16+
return new PositionalArgumentsDeclaration(variant, options);
17+
}
18+
if (variant instanceof ast.NamedArgumentsDeclaration) {
19+
return new NamedArgumentsDeclaration(variant, options);
20+
}
21+
const exhaustiveCheck: never = variant;
22+
return exhaustiveCheck;
23+
}
24+
1125
export class ArgumentsDeclaration extends SlangNode {
1226
readonly kind = NonterminalKind.ArgumentsDeclaration;
1327

@@ -16,22 +30,7 @@ export class ArgumentsDeclaration extends SlangNode {
1630
constructor(ast: ast.ArgumentsDeclaration, options: ParserOptions<AstNode>) {
1731
super(ast);
1832

19-
switch (ast.variant.cst.kind) {
20-
case NonterminalKind.PositionalArgumentsDeclaration:
21-
this.variant = new PositionalArgumentsDeclaration(
22-
ast.variant as ast.PositionalArgumentsDeclaration,
23-
options
24-
);
25-
break;
26-
case NonterminalKind.NamedArgumentsDeclaration:
27-
this.variant = new NamedArgumentsDeclaration(
28-
ast.variant as ast.NamedArgumentsDeclaration,
29-
options
30-
);
31-
break;
32-
default:
33-
throw new Error(`Unexpected variant: ${ast.variant.cst.kind}`);
34-
}
33+
this.variant = createNonterminalVariant(ast.variant, options);
3534

3635
this.updateMetadata(this.variant);
3736
}

src/slang-nodes/ConstructorAttribute.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { NonterminalKind, TerminalNode } from '@nomicfoundation/slang/cst';
2+
import { printVariant } from '../slang-printers/print-variant.js';
23
import { SlangNode } from './SlangNode.js';
34
import { ModifierInvocation } from './ModifierInvocation.js';
45

@@ -15,17 +16,17 @@ export class ConstructorAttribute extends SlangNode {
1516
constructor(ast: ast.ConstructorAttribute, options: ParserOptions<AstNode>) {
1617
super(ast);
1718

18-
this.variant =
19-
ast.variant instanceof TerminalNode
20-
? ast.variant.unparse()
21-
: new ModifierInvocation(ast.variant, options);
19+
const variant = ast.variant;
20+
if (variant instanceof TerminalNode) {
21+
this.variant = variant.unparse();
22+
return;
23+
}
24+
this.variant = new ModifierInvocation(variant, options);
2225

23-
if (typeof this.variant !== 'string') this.updateMetadata(this.variant);
26+
this.updateMetadata(this.variant);
2427
}
2528

2629
print(path: AstPath<ConstructorAttribute>, print: PrintFunction): Doc {
27-
return typeof this.variant === 'string'
28-
? this.variant
29-
: path.call(print, 'variant');
30+
return printVariant(this, path, print);
3031
}
3132
}

src/slang-nodes/ContractMember.ts

Lines changed: 49 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import * as ast from '@nomicfoundation/slang/ast';
12
import { NonterminalKind } from '@nomicfoundation/slang/cst';
23
import { SlangNode } from './SlangNode.js';
34
import { UsingDirective } from './UsingDirective.js';
@@ -14,11 +15,57 @@ import { StateVariableDefinition } from './StateVariableDefinition.js';
1415
import { ErrorDefinition } from './ErrorDefinition.js';
1516
import { UserDefinedValueTypeDefinition } from './UserDefinedValueTypeDefinition.js';
1617

17-
import type * as ast from '@nomicfoundation/slang/ast';
1818
import type { AstPath, Doc, ParserOptions } from 'prettier';
1919
import type { AstNode } from './types.d.ts';
2020
import type { PrintFunction } from '../types.d.ts';
2121

22+
function createNonterminalVariant(
23+
variant: ast.ContractMember['variant'],
24+
options: ParserOptions<AstNode>
25+
): ContractMember['variant'] {
26+
if (variant instanceof ast.UsingDirective) {
27+
return new UsingDirective(variant, options);
28+
}
29+
if (variant instanceof ast.FunctionDefinition) {
30+
return new FunctionDefinition(variant, options);
31+
}
32+
if (variant instanceof ast.ConstructorDefinition) {
33+
return new ConstructorDefinition(variant, options);
34+
}
35+
if (variant instanceof ast.ReceiveFunctionDefinition) {
36+
return new ReceiveFunctionDefinition(variant, options);
37+
}
38+
if (variant instanceof ast.FallbackFunctionDefinition) {
39+
return new FallbackFunctionDefinition(variant, options);
40+
}
41+
if (variant instanceof ast.UnnamedFunctionDefinition) {
42+
return new UnnamedFunctionDefinition(variant, options);
43+
}
44+
if (variant instanceof ast.ModifierDefinition) {
45+
return new ModifierDefinition(variant, options);
46+
}
47+
if (variant instanceof ast.StructDefinition) {
48+
return new StructDefinition(variant, options);
49+
}
50+
if (variant instanceof ast.EnumDefinition) {
51+
return new EnumDefinition(variant);
52+
}
53+
if (variant instanceof ast.EventDefinition) {
54+
return new EventDefinition(variant, options);
55+
}
56+
if (variant instanceof ast.StateVariableDefinition) {
57+
return new StateVariableDefinition(variant, options);
58+
}
59+
if (variant instanceof ast.ErrorDefinition) {
60+
return new ErrorDefinition(variant, options);
61+
}
62+
if (variant instanceof ast.UserDefinedValueTypeDefinition) {
63+
return new UserDefinedValueTypeDefinition(variant);
64+
}
65+
const exhaustiveCheck: never = variant;
66+
return exhaustiveCheck;
67+
}
68+
2269
export class ContractMember extends SlangNode {
2370
readonly kind = NonterminalKind.ContractMember;
2471

@@ -40,84 +87,7 @@ export class ContractMember extends SlangNode {
4087
constructor(ast: ast.ContractMember, options: ParserOptions<AstNode>) {
4188
super(ast);
4289

43-
switch (ast.variant.cst.kind) {
44-
case NonterminalKind.UsingDirective:
45-
this.variant = new UsingDirective(
46-
ast.variant as ast.UsingDirective,
47-
options
48-
);
49-
break;
50-
case NonterminalKind.FunctionDefinition:
51-
this.variant = new FunctionDefinition(
52-
ast.variant as ast.FunctionDefinition,
53-
options
54-
);
55-
break;
56-
case NonterminalKind.ConstructorDefinition:
57-
this.variant = new ConstructorDefinition(
58-
ast.variant as ast.ConstructorDefinition,
59-
options
60-
);
61-
break;
62-
case NonterminalKind.ReceiveFunctionDefinition:
63-
this.variant = new ReceiveFunctionDefinition(
64-
ast.variant as ast.ReceiveFunctionDefinition,
65-
options
66-
);
67-
break;
68-
case NonterminalKind.FallbackFunctionDefinition:
69-
this.variant = new FallbackFunctionDefinition(
70-
ast.variant as ast.FallbackFunctionDefinition,
71-
options
72-
);
73-
break;
74-
case NonterminalKind.UnnamedFunctionDefinition:
75-
this.variant = new UnnamedFunctionDefinition(
76-
ast.variant as ast.UnnamedFunctionDefinition,
77-
options
78-
);
79-
break;
80-
case NonterminalKind.ModifierDefinition:
81-
this.variant = new ModifierDefinition(
82-
ast.variant as ast.ModifierDefinition,
83-
options
84-
);
85-
break;
86-
case NonterminalKind.StructDefinition:
87-
this.variant = new StructDefinition(
88-
ast.variant as ast.StructDefinition,
89-
options
90-
);
91-
break;
92-
case NonterminalKind.EnumDefinition:
93-
this.variant = new EnumDefinition(ast.variant as ast.EnumDefinition);
94-
break;
95-
case NonterminalKind.EventDefinition:
96-
this.variant = new EventDefinition(
97-
ast.variant as ast.EventDefinition,
98-
options
99-
);
100-
break;
101-
case NonterminalKind.StateVariableDefinition:
102-
this.variant = new StateVariableDefinition(
103-
ast.variant as ast.StateVariableDefinition,
104-
options
105-
);
106-
break;
107-
case NonterminalKind.ErrorDefinition:
108-
this.variant = new ErrorDefinition(
109-
ast.variant as ast.ErrorDefinition,
110-
options
111-
);
112-
break;
113-
case NonterminalKind.UserDefinedValueTypeDefinition:
114-
this.variant = new UserDefinedValueTypeDefinition(
115-
ast.variant as ast.UserDefinedValueTypeDefinition
116-
);
117-
break;
118-
default:
119-
throw new Error(`Unexpected variant: ${ast.variant.cst.kind}`);
120-
}
90+
this.variant = createNonterminalVariant(ast.variant, options);
12191

12292
this.updateMetadata(this.variant);
12393
}

src/slang-nodes/ContractSpecifier.ts

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,27 @@
1+
import * as ast from '@nomicfoundation/slang/ast';
12
import { NonterminalKind } from '@nomicfoundation/slang/cst';
23
import { SlangNode } from './SlangNode.js';
34
import { InheritanceSpecifier } from './InheritanceSpecifier.js';
45
import { StorageLayoutSpecifier } from './StorageLayoutSpecifier.js';
56

6-
import type * as ast from '@nomicfoundation/slang/ast';
77
import type { AstPath, Doc, ParserOptions } from 'prettier';
88
import type { AstNode } from './types.d.ts';
99
import type { PrintFunction } from '../types.d.ts';
1010

11+
function createNonterminalVariant(
12+
variant: ast.ContractSpecifier['variant'],
13+
options: ParserOptions<AstNode>
14+
): ContractSpecifier['variant'] {
15+
if (variant instanceof ast.InheritanceSpecifier) {
16+
return new InheritanceSpecifier(variant, options);
17+
}
18+
if (variant instanceof ast.StorageLayoutSpecifier) {
19+
return new StorageLayoutSpecifier(variant, options);
20+
}
21+
const exhaustiveCheck: never = variant;
22+
return exhaustiveCheck;
23+
}
24+
1125
export class ContractSpecifier extends SlangNode {
1226
readonly kind = NonterminalKind.ContractSpecifier;
1327

@@ -16,22 +30,8 @@ export class ContractSpecifier extends SlangNode {
1630
constructor(ast: ast.ContractSpecifier, options: ParserOptions<AstNode>) {
1731
super(ast);
1832

19-
switch (ast.variant.cst.kind) {
20-
case NonterminalKind.InheritanceSpecifier:
21-
this.variant = new InheritanceSpecifier(
22-
ast.variant as ast.InheritanceSpecifier,
23-
options
24-
);
25-
break;
26-
case NonterminalKind.StorageLayoutSpecifier:
27-
this.variant = new StorageLayoutSpecifier(
28-
ast.variant as ast.StorageLayoutSpecifier,
29-
options
30-
);
31-
break;
32-
default:
33-
throw new Error(`Unexpected variant: ${ast.variant.cst.kind}`);
34-
}
33+
this.variant = createNonterminalVariant(ast.variant, options);
34+
3535
this.updateMetadata(this.variant);
3636
}
3737

src/slang-nodes/ElementaryType.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { NonterminalKind, TerminalNode } from '@nomicfoundation/slang/cst';
2+
import { printVariant } from '../slang-printers/print-variant.js';
23
import { SlangNode } from './SlangNode.js';
34
import { AddressType } from './AddressType.js';
45

@@ -14,17 +15,17 @@ export class ElementaryType extends SlangNode {
1415
constructor(ast: ast.ElementaryType) {
1516
super(ast);
1617

17-
this.variant =
18-
ast.variant instanceof TerminalNode
19-
? ast.variant.unparse()
20-
: new AddressType(ast.variant);
18+
const variant = ast.variant;
19+
if (variant instanceof TerminalNode) {
20+
this.variant = variant.unparse();
21+
return;
22+
}
23+
this.variant = new AddressType(variant);
2124

22-
if (typeof this.variant !== 'string') this.updateMetadata(this.variant);
25+
this.updateMetadata(this.variant);
2326
}
2427

2528
print(path: AstPath<ElementaryType>, print: PrintFunction): Doc {
26-
return typeof this.variant === 'string'
27-
? this.variant
28-
: path.call(print, 'variant');
29+
return printVariant(this, path, print);
2930
}
3031
}

src/slang-nodes/ExperimentalFeature.ts

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
import {
2-
NonterminalKind,
3-
TerminalKind,
4-
TerminalNode
5-
} from '@nomicfoundation/slang/cst';
1+
import { NonterminalKind, TerminalNode } from '@nomicfoundation/slang/cst';
62
import { SlangNode } from './SlangNode.js';
73
import { StringLiteral } from './StringLiteral.js';
84
import { Identifier } from './Identifier.js';
@@ -20,13 +16,14 @@ export class ExperimentalFeature extends SlangNode {
2016
constructor(ast: ast.ExperimentalFeature, options: ParserOptions<AstNode>) {
2117
super(ast);
2218

23-
this.variant =
24-
ast.variant instanceof TerminalNode
25-
? new Identifier(ast.variant)
26-
: new StringLiteral(ast.variant, options);
19+
const variant = ast.variant;
20+
if (variant instanceof TerminalNode) {
21+
this.variant = new Identifier(variant);
22+
return;
23+
}
24+
this.variant = new StringLiteral(variant, options);
2725

28-
if (this.variant.kind !== TerminalKind.Identifier)
29-
this.updateMetadata(this.variant);
26+
this.updateMetadata(this.variant);
3027
}
3128

3229
print(path: AstPath<ExperimentalFeature>, print: PrintFunction): Doc {

0 commit comments

Comments
 (0)