From cb72726e384ad0ac5db22d51d8a76d5ee121917d Mon Sep 17 00:00:00 2001 From: Joe Savona Date: Fri, 21 Apr 2023 08:03:37 -0700 Subject: [PATCH] Cleanup Stack impl Originally I defined `Stack` as an interface to ensure both Node and Empty variants would have an identical API. But exporting an interface allows a developer to define other implementations, when we really want to ensure that a Stack is precisely a Node or Empty instance. This PR changes to exporting a union of `Stack = Node | Empty`, and makes the interface private to the module. --- compiler/forget/src/Utils/Stack.ts | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/compiler/forget/src/Utils/Stack.ts b/compiler/forget/src/Utils/Stack.ts index 68b2df059d..a53b2207fe 100644 --- a/compiler/forget/src/Utils/Stack.ts +++ b/compiler/forget/src/Utils/Stack.ts @@ -5,10 +5,24 @@ * LICENSE file in the root directory of this source tree. */ -export interface Stack { - push(value: T): Stack; +/** + * An immutable stack data structure supporting O(1) push/pop operations. + */ +export type Stack = Node | Empty; - pop(): Stack; +// Static assertion that Stack is a StackInterface +function _assertStackInterface(stack: Stack): void { + let _: StackInterface = stack; +} + +// Internal interface to enforce consistent behavior btw Node/Empty variants +// Note that we export a union rather than the interface so that it is impossible +// to create additional variants: a Stack should always be exactly a Node or Empty +// instance. +interface StackInterface { + push(value: T): StackInterface; + + pop(): StackInterface; contains(value: T): boolean; @@ -25,7 +39,7 @@ export function empty(): Stack { return EMPTY as any; } -class Node implements Stack { +class Node implements StackInterface { #value: T; #next: Stack; @@ -58,9 +72,9 @@ class Node implements Stack { } } -class Empty implements Stack { +class Empty implements StackInterface { push(value: T): Stack { - return new Node(value, this); + return new Node(value as T, this as Stack); } pop(): Stack { return this;