//--------------------------------------------------------------------------- // @syndicate-lang/core, an implementation of Syndicate dataspaces for JS. // Copyright (C) 2016-2021 Tony Garnock-Jones // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . //--------------------------------------------------------------------------- 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; }