Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
93a877d
standardising the instantiation of variants using an object as a dict…
Janther Feb 11, 2026
e3ab9ab
using Map instead
Janther Feb 11, 2026
ac1e5f7
adding a factory for the same functionality
Janther Feb 12, 2026
93216ae
key, value pair in the same array
Janther Feb 12, 2026
6050324
we don't need to store a string as a key anymore, we can directly use…
Janther Feb 12, 2026
5fb04f1
cleaner types
Janther Feb 12, 2026
6df8766
reversing the order of the parameter types to match the key, value or…
Janther Feb 12, 2026
112edc8
separating the complex factory into 2 specific ones
Janther Feb 12, 2026
8710204
cleaner name
Janther Feb 12, 2026
8269515
passing the types down to the second factory
Janther Feb 12, 2026
c7ad404
shorter name so it fits better and it's easier to read
Janther Feb 12, 2026
4d2fc90
standardising the factory type
Janther Feb 12, 2026
0f3af08
small typo
Janther Feb 12, 2026
461ebb8
some cleanup
Janther Feb 12, 2026
b7d873a
deleting intermediate function in `Statement` and `YulStatement`
Janther Feb 12, 2026
b9d322c
using `instanceof` instead of Map
Janther Feb 17, 2026
1043a9a
Clear names
Janther Feb 17, 2026
2305016
adding coverage for all cases only on `test` environment
Janther Feb 24, 2026
47b9a4a
adding an _exhaustiveCheck to make sure we check for every possible `…
Janther Feb 24, 2026
3219840
adding a c8 ignore comment to exhaustiveCkecks since we know they'll …
Janther Feb 24, 2026
0025a48
Moving all the exhaustive coverage check to the tests
Janther Feb 26, 2026
1044131
renaming `check-coverage` to `variant-coverage`
Janther Feb 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .c8rc
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"functions": 90,
"statements": 90,
"exclude": ["/node_modules/"],
"include": ["src/**/*.ts"],
"include": ["src/**/*.ts", "variant-coverage/**/*.ts"],
"reporter": ["lcov", "text"],
"temp-dir": "./coverage/"
}
1 change: 1 addition & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const compat = new FlatCompat({
export default [
{
ignores: [
'variant-coverage/**/*.ts',
'coverage/**/*.js',
'dist/**/*.cjs',
'dist/**/*.js',
Expand Down
22 changes: 8 additions & 14 deletions src/slang-nodes/ArgumentsDeclaration.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as ast from '@nomicfoundation/slang/ast';
import { NonterminalKind } from '@nomicfoundation/slang/cst';
import { createNonterminalVariantSimpleCreator } from '../slang-utils/create-nonterminal-variant-creator.js';
import { SlangNode } from './SlangNode.js';
import { PositionalArgumentsDeclaration } from './PositionalArgumentsDeclaration.js';
import { NamedArgumentsDeclaration } from './NamedArgumentsDeclaration.js';
Expand All @@ -8,20 +9,13 @@ import type { ParserOptions } from 'prettier';
import type { CollectedMetadata } from '../types.d.ts';
import type { AstNode } from './types.d.ts';

function createNonterminalVariant(
variant: ast.ArgumentsDeclaration['variant'],
collected: CollectedMetadata,
options: ParserOptions<AstNode>
): ArgumentsDeclaration['variant'] {
if (variant instanceof ast.PositionalArgumentsDeclaration) {
return new PositionalArgumentsDeclaration(variant, collected, options);
}
if (variant instanceof ast.NamedArgumentsDeclaration) {
return new NamedArgumentsDeclaration(variant, collected, options);
}
const exhaustiveCheck: never = variant;
throw new Error(`Unexpected variant: ${JSON.stringify(exhaustiveCheck)}`);
}
const createNonterminalVariant = createNonterminalVariantSimpleCreator<
ast.ArgumentsDeclaration,
ArgumentsDeclaration
>([
[ast.PositionalArgumentsDeclaration, PositionalArgumentsDeclaration],
[ast.NamedArgumentsDeclaration, NamedArgumentsDeclaration]
]);

export class ArgumentsDeclaration extends SlangNode {
readonly kind = NonterminalKind.ArgumentsDeclaration;
Expand Down
66 changes: 19 additions & 47 deletions src/slang-nodes/ContractMember.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as ast from '@nomicfoundation/slang/ast';
import { NonterminalKind } from '@nomicfoundation/slang/cst';
import { createNonterminalVariantSimpleCreator } from '../slang-utils/create-nonterminal-variant-creator.js';
import { SlangNode } from './SlangNode.js';
import { UsingDirective } from './UsingDirective.js';
import { FunctionDefinition } from './FunctionDefinition.js';
Expand All @@ -19,53 +20,24 @@ import type { ParserOptions } from 'prettier';
import type { CollectedMetadata } from '../types.d.ts';
import type { AstNode } from './types.d.ts';

function createNonterminalVariant(
variant: ast.ContractMember['variant'],
collected: CollectedMetadata,
options: ParserOptions<AstNode>
): ContractMember['variant'] {
if (variant instanceof ast.UsingDirective) {
return new UsingDirective(variant, collected, options);
}
if (variant instanceof ast.FunctionDefinition) {
return new FunctionDefinition(variant, collected, options);
}
if (variant instanceof ast.ConstructorDefinition) {
return new ConstructorDefinition(variant, collected, options);
}
if (variant instanceof ast.ReceiveFunctionDefinition) {
return new ReceiveFunctionDefinition(variant, collected, options);
}
if (variant instanceof ast.FallbackFunctionDefinition) {
return new FallbackFunctionDefinition(variant, collected, options);
}
if (variant instanceof ast.UnnamedFunctionDefinition) {
return new UnnamedFunctionDefinition(variant, collected, options);
}
if (variant instanceof ast.ModifierDefinition) {
return new ModifierDefinition(variant, collected, options);
}
if (variant instanceof ast.StructDefinition) {
return new StructDefinition(variant, collected, options);
}
if (variant instanceof ast.EnumDefinition) {
return new EnumDefinition(variant, collected);
}
if (variant instanceof ast.EventDefinition) {
return new EventDefinition(variant, collected, options);
}
if (variant instanceof ast.StateVariableDefinition) {
return new StateVariableDefinition(variant, collected, options);
}
if (variant instanceof ast.ErrorDefinition) {
return new ErrorDefinition(variant, collected, options);
}
if (variant instanceof ast.UserDefinedValueTypeDefinition) {
return new UserDefinedValueTypeDefinition(variant, collected);
}
const exhaustiveCheck: never = variant;
throw new Error(`Unexpected variant: ${JSON.stringify(exhaustiveCheck)}`);
}
const createNonterminalVariant = createNonterminalVariantSimpleCreator<
ast.ContractMember,
ContractMember
>([
[ast.UsingDirective, UsingDirective],
[ast.FunctionDefinition, FunctionDefinition],
[ast.ConstructorDefinition, ConstructorDefinition],
[ast.ReceiveFunctionDefinition, ReceiveFunctionDefinition],
[ast.FallbackFunctionDefinition, FallbackFunctionDefinition],
[ast.UnnamedFunctionDefinition, UnnamedFunctionDefinition],
[ast.ModifierDefinition, ModifierDefinition],
[ast.StructDefinition, StructDefinition],
[ast.EnumDefinition, EnumDefinition],
[ast.EventDefinition, EventDefinition],
[ast.StateVariableDefinition, StateVariableDefinition],
[ast.ErrorDefinition, ErrorDefinition],
[ast.UserDefinedValueTypeDefinition, UserDefinedValueTypeDefinition]
]);

export class ContractMember extends SlangNode {
readonly kind = NonterminalKind.ContractMember;
Expand Down
22 changes: 8 additions & 14 deletions src/slang-nodes/ContractSpecifier.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as ast from '@nomicfoundation/slang/ast';
import { NonterminalKind } from '@nomicfoundation/slang/cst';
import { createNonterminalVariantSimpleCreator } from '../slang-utils/create-nonterminal-variant-creator.js';
import { SlangNode } from './SlangNode.js';
import { InheritanceSpecifier } from './InheritanceSpecifier.js';
import { StorageLayoutSpecifier } from './StorageLayoutSpecifier.js';
Expand All @@ -8,20 +9,13 @@ import type { ParserOptions } from 'prettier';
import type { CollectedMetadata } from '../types.d.ts';
import type { AstNode } from './types.d.ts';

function createNonterminalVariant(
variant: ast.ContractSpecifier['variant'],
collected: CollectedMetadata,
options: ParserOptions<AstNode>
): ContractSpecifier['variant'] {
if (variant instanceof ast.InheritanceSpecifier) {
return new InheritanceSpecifier(variant, collected, options);
}
if (variant instanceof ast.StorageLayoutSpecifier) {
return new StorageLayoutSpecifier(variant, collected, options);
}
const exhaustiveCheck: never = variant;
throw new Error(`Unexpected variant: ${JSON.stringify(exhaustiveCheck)}`);
}
const createNonterminalVariant = createNonterminalVariantSimpleCreator<
ast.ContractSpecifier,
ContractSpecifier
>([
[ast.InheritanceSpecifier, InheritanceSpecifier],
[ast.StorageLayoutSpecifier, StorageLayoutSpecifier]
]);

export class ContractSpecifier extends SlangNode {
readonly kind = NonterminalKind.ContractSpecifier;
Expand Down
127 changes: 37 additions & 90 deletions src/slang-nodes/Expression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
NonterminalKind,
TerminalNode as SlangTerminalNode
} from '@nomicfoundation/slang/cst';
import { extractVariant } from '../slang-utils/extract-variant.js';
import { createNonterminalVariantCreator } from '../slang-utils/create-nonterminal-variant-creator.js';
import { SlangNode } from './SlangNode.js';
import { AssignmentExpression } from './AssignmentExpression.js';
import { ConditionalExpression } from './ConditionalExpression.js';
Expand Down Expand Up @@ -38,95 +38,42 @@ import type { ParserOptions } from 'prettier';
import type { CollectedMetadata } from '../types.d.ts';
import type { AstNode } from './types.d.ts';

function createNonterminalVariant(
variant: Exclude<ast.Expression['variant'], SlangTerminalNode>,
collected: CollectedMetadata,
options: ParserOptions<AstNode>
): Expression['variant'] {
if (variant instanceof ast.AssignmentExpression) {
return new AssignmentExpression(variant, collected, options);
}
if (variant instanceof ast.ConditionalExpression) {
return new ConditionalExpression(variant, collected, options);
}
if (variant instanceof ast.OrExpression) {
return new OrExpression(variant, collected, options);
}
if (variant instanceof ast.AndExpression) {
return new AndExpression(variant, collected, options);
}
if (variant instanceof ast.EqualityExpression) {
return new EqualityExpression(variant, collected, options);
}
if (variant instanceof ast.InequalityExpression) {
return new InequalityExpression(variant, collected, options);
}
if (variant instanceof ast.BitwiseOrExpression) {
return new BitwiseOrExpression(variant, collected, options);
}
if (variant instanceof ast.BitwiseXorExpression) {
return new BitwiseXorExpression(variant, collected, options);
}
if (variant instanceof ast.BitwiseAndExpression) {
return new BitwiseAndExpression(variant, collected, options);
}
if (variant instanceof ast.ShiftExpression) {
return new ShiftExpression(variant, collected, options);
}
if (variant instanceof ast.AdditiveExpression) {
return new AdditiveExpression(variant, collected, options);
}
if (variant instanceof ast.MultiplicativeExpression) {
return new MultiplicativeExpression(variant, collected, options);
}
if (variant instanceof ast.ExponentiationExpression) {
return new ExponentiationExpression(variant, collected, options);
}
if (variant instanceof ast.PostfixExpression) {
return new PostfixExpression(variant, collected, options);
}
if (variant instanceof ast.PrefixExpression) {
return new PrefixExpression(variant, collected, options);
}
if (variant instanceof ast.FunctionCallExpression) {
return new FunctionCallExpression(variant, collected, options);
}
if (variant instanceof ast.CallOptionsExpression) {
return new CallOptionsExpression(variant, collected, options);
}
if (variant instanceof ast.MemberAccessExpression) {
return new MemberAccessExpression(variant, collected, options);
}
if (variant instanceof ast.IndexAccessExpression) {
return new IndexAccessExpression(variant, collected, options);
}
if (variant instanceof ast.NewExpression) {
return new NewExpression(variant, collected, options);
}
if (variant instanceof ast.TupleExpression) {
return new TupleExpression(variant, collected, options);
}
if (variant instanceof ast.TypeExpression) {
return new TypeExpression(variant, collected, options);
}
if (variant instanceof ast.ArrayExpression) {
return new ArrayExpression(variant, collected, options);
}
if (variant instanceof ast.HexNumberExpression) {
return new HexNumberExpression(variant, collected);
}
if (variant instanceof ast.DecimalNumberExpression) {
return new DecimalNumberExpression(variant, collected);
}
if (variant instanceof ast.StringExpression) {
return extractVariant(new StringExpression(variant, collected, options));
}
if (variant instanceof ast.ElementaryType) {
return extractVariant(new ElementaryType(variant, collected));
}
const exhaustiveCheck: never = variant;
throw new Error(`Unexpected variant: ${JSON.stringify(exhaustiveCheck)}`);
}
const createNonterminalVariant = createNonterminalVariantCreator<
ast.Expression,
Expression
>(
[
[ast.AssignmentExpression, AssignmentExpression],
[ast.ConditionalExpression, ConditionalExpression],
[ast.OrExpression, OrExpression],
[ast.AndExpression, AndExpression],
[ast.EqualityExpression, EqualityExpression],
[ast.InequalityExpression, InequalityExpression],
[ast.BitwiseOrExpression, BitwiseOrExpression],
[ast.BitwiseXorExpression, BitwiseXorExpression],
[ast.BitwiseAndExpression, BitwiseAndExpression],
[ast.ShiftExpression, ShiftExpression],
[ast.AdditiveExpression, AdditiveExpression],
[ast.MultiplicativeExpression, MultiplicativeExpression],
[ast.ExponentiationExpression, ExponentiationExpression],
[ast.PostfixExpression, PostfixExpression],
[ast.PrefixExpression, PrefixExpression],
[ast.FunctionCallExpression, FunctionCallExpression],
[ast.CallOptionsExpression, CallOptionsExpression],
[ast.MemberAccessExpression, MemberAccessExpression],
[ast.IndexAccessExpression, IndexAccessExpression],
[ast.NewExpression, NewExpression],
[ast.TupleExpression, TupleExpression],
[ast.TypeExpression, TypeExpression],
[ast.ArrayExpression, ArrayExpression],
[ast.HexNumberExpression, HexNumberExpression],
[ast.DecimalNumberExpression, DecimalNumberExpression]
],
[
[ast.StringExpression, StringExpression],
[ast.ElementaryType, ElementaryType]
]
);

export class Expression extends SlangNode {
readonly kind = NonterminalKind.Expression;
Expand Down
22 changes: 8 additions & 14 deletions src/slang-nodes/FallbackFunctionAttribute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
NonterminalKind,
TerminalNode as SlangTerminalNode
} from '@nomicfoundation/slang/cst';
import { createNonterminalVariantSimpleCreator } from '../slang-utils/create-nonterminal-variant-creator.js';
import { SlangNode } from './SlangNode.js';
import { ModifierInvocation } from './ModifierInvocation.js';
import { OverrideSpecifier } from './OverrideSpecifier.js';
Expand All @@ -12,20 +13,13 @@ import type { ParserOptions } from 'prettier';
import type { CollectedMetadata } from '../types.d.ts';
import type { AstNode } from './types.d.ts';

function createNonterminalVariant(
variant: Exclude<ast.FallbackFunctionAttribute['variant'], SlangTerminalNode>,
collected: CollectedMetadata,
options: ParserOptions<AstNode>
): Exclude<FallbackFunctionAttribute['variant'], TerminalNode> {
if (variant instanceof ast.ModifierInvocation) {
return new ModifierInvocation(variant, collected, options);
}
if (variant instanceof ast.OverrideSpecifier) {
return new OverrideSpecifier(variant, collected);
}
const exhaustiveCheck: never = variant;
throw new Error(`Unexpected variant: ${JSON.stringify(exhaustiveCheck)}`);
}
const createNonterminalVariant = createNonterminalVariantSimpleCreator<
ast.FallbackFunctionAttribute,
FallbackFunctionAttribute
>([
[ast.ModifierInvocation, ModifierInvocation],
[ast.OverrideSpecifier, OverrideSpecifier]
]);

export class FallbackFunctionAttribute extends SlangNode {
readonly kind = NonterminalKind.FallbackFunctionAttribute;
Expand Down
29 changes: 9 additions & 20 deletions src/slang-nodes/ForStatementInitialization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
NonterminalKind,
TerminalNode as SlangTerminalNode
} from '@nomicfoundation/slang/cst';
import { createNonterminalVariantSimpleCreator } from '../slang-utils/create-nonterminal-variant-creator.js';
import { SlangNode } from './SlangNode.js';
import { ExpressionStatement } from './ExpressionStatement.js';
import { VariableDeclarationStatement } from './VariableDeclarationStatement.js';
Expand All @@ -13,26 +14,14 @@ import type { ParserOptions } from 'prettier';
import type { CollectedMetadata } from '../types.d.ts';
import type { AstNode } from './types.d.ts';

function createNonterminalVariant(
variant: Exclude<
ast.ForStatementInitialization['variant'],
SlangTerminalNode
>,
collected: CollectedMetadata,
options: ParserOptions<AstNode>
): Exclude<ForStatementInitialization['variant'], TerminalNode> {
if (variant instanceof ast.ExpressionStatement) {
return new ExpressionStatement(variant, collected, options);
}
if (variant instanceof ast.VariableDeclarationStatement) {
return new VariableDeclarationStatement(variant, collected, options);
}
if (variant instanceof ast.TupleDeconstructionStatement) {
return new TupleDeconstructionStatement(variant, collected, options);
}
const exhaustiveCheck: never = variant;
throw new Error(`Unexpected variant: ${JSON.stringify(exhaustiveCheck)}`);
}
const createNonterminalVariant = createNonterminalVariantSimpleCreator<
ast.ForStatementInitialization,
ForStatementInitialization
>([
[ast.ExpressionStatement, ExpressionStatement],
[ast.VariableDeclarationStatement, VariableDeclarationStatement],
[ast.TupleDeconstructionStatement, TupleDeconstructionStatement]
]);

export class ForStatementInitialization extends SlangNode {
readonly kind = NonterminalKind.ForStatementInitialization;
Expand Down
Loading