kopia lustrzana https://github.com/Tldraw/Tldraw
69 wiersze
1.3 KiB
TypeScript
69 wiersze
1.3 KiB
TypeScript
import { EMPTY_ARRAY } from 'signia'
|
|
|
|
export type Stack<T> = StackItem<T> | EmptyStackItem<T>
|
|
|
|
export function stack<T>(items?: Array<T>): Stack<T> {
|
|
if (items) {
|
|
let result = EMPTY_STACK_ITEM as Stack<T>
|
|
while (items.length) {
|
|
result = result.push(items.pop()!)
|
|
}
|
|
return result
|
|
}
|
|
return EMPTY_STACK_ITEM as any
|
|
}
|
|
|
|
class EmptyStackItem<T> implements Iterable<T> {
|
|
readonly length = 0
|
|
readonly head = null
|
|
readonly tail: Stack<T> = this
|
|
|
|
push(head: T): Stack<T> {
|
|
return new StackItem<T>(head, this)
|
|
}
|
|
|
|
toArray() {
|
|
return EMPTY_ARRAY
|
|
}
|
|
|
|
[Symbol.iterator]() {
|
|
return {
|
|
next() {
|
|
return { value: undefined, done: true as const }
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
const EMPTY_STACK_ITEM = new EmptyStackItem()
|
|
|
|
class StackItem<T> implements Iterable<T> {
|
|
length: number
|
|
constructor(public readonly head: T, public readonly tail: Stack<T>) {
|
|
this.length = tail.length + 1
|
|
}
|
|
|
|
push(head: T): Stack<T> {
|
|
return new StackItem(head, this)
|
|
}
|
|
|
|
toArray() {
|
|
return Array.from(this)
|
|
}
|
|
|
|
[Symbol.iterator]() {
|
|
let stack = this as Stack<T>
|
|
return {
|
|
next() {
|
|
if (stack.length) {
|
|
const value = stack.head!
|
|
stack = stack.tail
|
|
return { value, done: false as const }
|
|
} else {
|
|
return { value: undefined, done: true as const }
|
|
}
|
|
},
|
|
}
|
|
}
|
|
}
|