/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-FileCopyrightText: Copyright © 2016-2021 Tony Garnock-Jones export type NonEmptyStack = { item: T, rest: Stack }; export type Stack = null | NonEmptyStack; export function empty(): Stack { return null; } export function push(item: T, rest: Stack): NonEmptyStack { return { item, rest }; } export function isEmpty(s: Stack): s is null { return s === null; } export function nonEmpty(s: Stack): s is NonEmptyStack { return s !== null; } export function rest(s: Stack): Stack { if (nonEmpty(s)) { return s.rest; } else { throw new Error("pop from empty Stack"); } } export function drop(s: Stack, n: number): Stack { while (n--) s = rest(s); return s; } export function dropNonEmpty(s: NonEmptyStack, n: number): NonEmptyStack { while (n--) { const next = s.rest; if (!nonEmpty(next)) throw new Error("dropNonEmpty popped too far"); s = next; } return s; }