From ddc1e6f1d01c79460613b21592ae20e8bb238ac7 Mon Sep 17 00:00:00 2001 From: ivanjermakov Date: Sat, 20 Apr 2024 11:06:41 +0200 Subject: [PATCH] Ast: narrow `PatternExpr` --- src/ast/match.ts | 50 +++++++++++++++++++++++++++++++---------- src/ast/operand.ts | 16 ++++--------- src/codegen/js/expr.ts | 14 +----------- src/semantic/exhaust.ts | 7 +----- src/semantic/index.ts | 12 +--------- 5 files changed, 45 insertions(+), 54 deletions(-) diff --git a/src/ast/match.ts b/src/ast/match.ts index ee04643..027c7dd 100644 --- a/src/ast/match.ts +++ b/src/ast/match.ts @@ -2,17 +2,23 @@ import { LexerToken } from '../lexer/lexer' import { ParseNode, filterNonAstNodes } from '../parser' import { nameLikeTokens } from '../parser/fns' import { Typed } from '../semantic' +import { unreachable } from '../util/todo' import { Expr, buildExpr } from './expr' import { AstNode } from './index' import { + BoolLiteral, + CharLiteral, FloatLiteral, Identifier, IntLiteral, Name, - Operand, + StringInterpolated, + StringLiteral, + buildBool, + buildChar, buildIdentifier, buildName, - buildOperand + buildString } from './operand' import { Block, buildBlock } from './statement' @@ -59,23 +65,43 @@ export const buildPattern = (node: ParseNode): Pattern => { return { kind: 'pattern', parseNode: node, name, expr } } -export type PatternExpr = Name | ConPattern | ListPattern | Operand | Hole +export type PatternExpr = + | Name + | ConPattern + | ListPattern + | Hole + | StringLiteral + | StringInterpolated + | CharLiteral + | IntLiteral + | FloatLiteral + | BoolLiteral export const buildPatternExpr = (node: ParseNode): PatternExpr => { const n = filterNonAstNodes(node)[0] if (nameLikeTokens.includes((n).kind)) { return buildName(n) } - if (n.kind === 'con-pattern') { - return buildConPattern(n) + switch (n.kind) { + case 'name': + return buildName(n) + case 'con-pattern': + return buildConPattern(n) + case 'list-pattern': + return buildListPattern(n) + case 'hole': + return buildHole(n) + case 'number': + return buildNumber(n) + case 'string': + return buildString(n) + case 'char': + return buildChar(n) + case 'bool': + return buildBool(n) + default: + return unreachable(n.kind) } - if (n.kind === 'hole') { - return buildHole(n) - } - if (n.kind === 'number') { - return buildNumber(n) - } - return buildOperand(node) } export interface ConPattern extends AstNode<'con-pattern'>, Partial { diff --git a/src/ast/operand.ts b/src/ast/operand.ts index f22262b..f7e5a79 100644 --- a/src/ast/operand.ts +++ b/src/ast/operand.ts @@ -51,11 +51,11 @@ export const buildOperand = (node: ParseNode): Operand => { case 'string': return buildString(n) case 'char': - return buildCharLiteral(n) + return buildChar(n) case 'number': return buildNumber(n) case 'bool': - return buildBoolLiteral(n) + return buildBool(n) case 'identifier': return buildIdentifier(n) } @@ -209,7 +209,7 @@ export interface CharLiteral extends AstNode<'char-literal'>, Partial { value: string } -export const buildCharLiteral = (node: ParseNode): CharLiteral => { +export const buildChar = (node: ParseNode): CharLiteral => { return { kind: 'char-literal', parseNode: node, value: (node).value } } @@ -217,23 +217,15 @@ export interface IntLiteral extends AstNode<'int-literal'>, Partial { value: string } -export const buildIntLiteral = (node: ParseNode): IntLiteral => { - return { kind: 'int-literal', parseNode: node, value: (node).value } -} - export interface FloatLiteral extends AstNode<'float-literal'>, Partial { value: string } -export const buildFloatLiteral = (node: ParseNode): FloatLiteral => { - return { kind: 'float-literal', parseNode: node, value: (node).value } -} - export interface BoolLiteral extends AstNode<'bool-literal'>, Partial { value: string } -export const buildBoolLiteral = (node: ParseNode): BoolLiteral => { +export const buildBool = (node: ParseNode): BoolLiteral => { return { kind: 'bool-literal', parseNode: node, value: (node).value } } diff --git a/src/codegen/js/expr.ts b/src/codegen/js/expr.ts index 09762a4..98da913 100644 --- a/src/codegen/js/expr.ts +++ b/src/codegen/js/expr.ts @@ -417,18 +417,7 @@ export const emitPatternExprCondition = (patternExpr: PatternExpr, ctx: Context, } case 'string-interpolated': return { emit: jsVariable(resultVar, jsError('string-interpolated')), resultVar } - case 'list-expr': - case 'operand-expr': - case 'unary-expr': - case 'binary-expr': - case 'identifier': case 'name': - case 'if-expr': - case 'if-let-expr': - case 'while-expr': - case 'for-expr': - case 'match-expr': - case 'closure-expr': return unreachable() } } @@ -476,14 +465,13 @@ export const emitPattern = (pattern: Pattern, ctx: Context, assignVar: string, p }) return emitTree([...patterns]) case 'string-interpolated': - case 'list-expr': + case 'list-pattern': return emitToken(`${jsError(pattern.expr.kind).value};`) case 'string-literal': case 'char-literal': case 'int-literal': case 'float-literal': case 'bool-literal': - case 'identifier': case 'hole': return emitToken('') default: diff --git a/src/semantic/exhaust.ts b/src/semantic/exhaust.ts index d6a6fea..0d88e07 100644 --- a/src/semantic/exhaust.ts +++ b/src/semantic/exhaust.ts @@ -29,7 +29,7 @@ import { MatchExpr, PatternExpr } from '../ast/match' import { Context, addError, addWarning } from '../scope' import { concatVid, idToVid, vidFromScope, vidFromString, vidToString } from '../scope/util' import { VariantDef, VirtualIdentifierMatch, resolveVid } from '../scope/vid' -import { assert, unreachable } from '../util/todo' +import { assert } from '../util/todo' import { nonExhaustiveMatchError, unreachableMatchClauseError } from './error' export interface MatchTree { @@ -92,14 +92,11 @@ const matchPattern = (pattern: PatternExpr, tree: MatchTree, ctx: Context): bool return true case 'string-literal': case 'char-literal': - case 'unary-expr': case 'string-interpolated': case 'int-literal': case 'float-literal': case 'bool-literal': - case 'identifier': case 'list-pattern': - case 'operand-expr': // match the node return true case 'con-pattern': @@ -161,8 +158,6 @@ const matchPattern = (pattern: PatternExpr, tree: MatchTree, ctx: Context): bool } } return matched - default: - return unreachable(pattern.kind) } } diff --git a/src/semantic/index.ts b/src/semantic/index.ts index 3f4810b..d216ab9 100644 --- a/src/semantic/index.ts +++ b/src/semantic/index.ts @@ -46,7 +46,6 @@ import { typeArgCountMismatchError, typeError, unexpectedInInstanceScopeError, - unexpectedPatternKindError, unexpectedTopLevelStatementError, unknownTypeError, unnecessaryPubMethodError, @@ -412,16 +411,7 @@ export const checkParam = (param: Param, index: number, ctx: Context): void => { } } - switch (param.pattern.expr.kind) { - case 'operand-expr': - case 'unary-expr': - case 'binary-expr': - addError(ctx, unexpectedPatternKindError(ctx, param)) - break - default: - checkPattern(param.pattern, param.type, ctx, false) - break - } + checkPattern(param.pattern, param.type, ctx, false) } const checkTraitDef = (traitDef: TraitDef, ctx: Context) => {