syndicate-js/packages/compiler/src/syntax/list.ts

57 lines
1.5 KiB
TypeScript

/// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
export interface List<T, C> extends Iterable<T> {
item: T | null;
next: List<T, C> | null;
context: C;
toArray(): Array<T>;
}
export function atEnd<T, C>(xs: List<T, C>): xs is (List<T, C> & { item: null, next: null }) {
return xs.item === null;
}
export function notAtEnd<T, C>(xs: List<T, C>): xs is (List<T, C> & { item: T, next: List<T, C> }) {
return xs.item !== null;
}
export class ArrayList<T, C> implements List<T, C> {
readonly items: Array<T>;
readonly index: number = 0;
constructor(items: Array<T>, public context: C, index = 0) {
this.items = items;
this.index = index;
}
get item(): T | null {
return this.items[this.index] ?? null;
}
get next(): List<T, C> | null {
if (this.index >= this.items.length) return null;
return new ArrayList(this.items, this.context, this.index + 1);
}
toArray(): Array<T> {
return this.items.slice(this.index);
}
[Symbol.iterator](): Iterator<T> {
let i: List<T, C> = this;
return {
next(): IteratorResult<T> {
if (notAtEnd(i)) {
const value = i.item;
i = i.next;
return { done: false, value };
} else {
return { done: true, value: null };
}
}
};
}
}