• R/O
  • SSH

提交

标签
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#objective-cqtwindows誰得cocoapythonphprubygameguibathyscaphec翻訳omegat計画中(planning stage)frameworktwittertestdomvb.netdirectxbtronarduinopreviewerゲームエンジン

C preprocessor written in Python


Commit MetaInfo

修订版6be5692fce173b086f0807505d474e96e9d6b85d (tree)
时间2022-02-01 12:25:30
作者Eric Hopper <hopper@omni...>
CommiterEric Hopper

Log Message

Initial, non-working version of lazy_sequence.py

更改概述

差异

diff -r 0cbc50dd70f7 -r 6be5692fce17 src/pycpre/lazy_sequence.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pycpre/lazy_sequence.py Mon Jan 31 19:25:30 2022 -0800
@@ -0,0 +1,137 @@
1+# This file is part of the pycpre distribution.
2+# Copyright 2022 Eric Hopper
3+#
4+# You may modify and/or redistribute this software under the terms of the GNU
5+# General Public License version as published by the Free Software Foundation,
6+# version 3 or greater.
7+#
8+# You should have received a copy of the GNU General Public License along with
9+# this program. If not, see <https://www.gnu.org/licenses/gpl-3.0.html>
10+
11+from collections.abc import Sequence
12+from heapq import heappush
13+from typing import Generic, Iterable, Iterator, List, Optional, TypeVar, Union
14+from weakref import ref, ReferenceType
15+
16+
17+T = TypeVar("T")
18+
19+
20+# class _SequenceRef(ReferenceType["LazySequence"[T]]):
21+# def __init__(
22+# self,
23+# sequence: "LazySequence"[T],
24+# state: "_LazySequenceState"[T],
25+# **kwargs
26+# ):
27+# super().__init__(self, sequence, state._refdestroyed)
28+#
29+# def __cmp__(self, other_ref: "_SequenceRef"[T]) -> int:
30+# me = self()
31+# other = other_ref()
32+# if (me, other) is (None, None):
33+# return id(self) - id(other_ref)
34+# elif me is None:
35+# return -1
36+# elif other is None:
37+# return 1
38+# else: # me and other are both not None
39+# cmpval: int = me.index - other.index
40+# if cmpval == 0:
41+# cmpval = id(self) - id(other_ref)
42+# return cmpval
43+
44+class _LazySequenceState(Generic[T]):
45+ def __init__(self, item_iterator: Iterator[T], **kwargs):
46+ super().__init__(**kwargs)
47+ self.buffer: List[T] = []
48+ self.iterator: Iterator[T] = item_iterator
49+ self.heads: List[ReferenceType[T]]= []
50+ self.index_of_0: int = 0
51+
52+ def new_sequence(self, sequence: "LazySequence"[T]) -> None:
53+ assert sequence.state is self
54+ if sequence.index < self.index_of_0:
55+ raise RuntimeError("LazySequence created that's attempting to time "
56+ "travel to the past.")
57+ self.heads.append(ref(sequence, self._refdestroyed))
58+
59+ def _refdestroyed(self, ref: ReferenceType[T]):
60+ try:
61+ refidx = self.heads.index(ref)
62+ except ValueError:
63+ return
64+ del self.heads[refidx]
65+ self.update_min()
66+
67+ def update_min(self):
68+ newheads: List[ReferenceType[T]] = []
69+ min_idx: Optional[int] = None
70+ for seqref in self.heads:
71+ seq = seqref()
72+ if seq is not None:
73+ newheads.append(seqref)
74+ if min_idx is None or seq.index < min_idx:
75+ min_idx = seq.index
76+ assert min_idx >= self.index_of_0
77+ if min_idx > self.index_of_0:
78+ del self.buffer[0:min_idx]
79+ self.index_of_0 = min_idx
80+
81+ def ensure_index(self, buffer_idx: int) -> T:
82+ if buffer_idx < self.index_of_0:
83+ return
84+ if (buffer_idx - self.index_of_0) >= len(self.buffer):
85+ for _ in range(len(self.buffer), buffer_idx + 1):
86+ self.buffer.append(next(self.iterator))
87+ assert (buffer_idx - self.index_of_0) < len(self.buffer)
88+ return self.buffer[buffer_idx - self.index_of_0]
89+
90+
91+class LazySequence(Sequence[T]):
92+ def __init__(self, item_iterator: Union["LazySequence", Iterable[T]], **kwargs):
93+ if isinstance(item_iterator, LazySequence):
94+ self.state = item_iterator.state
95+ self.index = item_iterator.index
96+ else:
97+ self.state = _LazySequenceState(iter(item_iterator))
98+ self.index = 0
99+ self.state.new_sequence(self)
100+
101+ def __reversed__(self):
102+ raise NotImplemented("Lazy sequences can't be reversed.")
103+
104+ def __len__(self) -> int:
105+ raise NotImplemented("Lazy sequences may be infinitely long.")
106+
107+ def __getitem__(self, index: Union[int, slice]) \
108+ -> Union[T, "LazySequence"[T], List[T]]:
109+ if index < 0:
110+ raise ValueError("Lazy sequences may not have an end and don't "
111+ "support indexing from the end.")
112+ if isinstance(index, int):
113+ return self.state.ensure_index(self.index + index)
114+ else:
115+ if index.start < 0 or index.stop < 0:
116+ raise ValueError("Lazy sequences may not have an end and don't "
117+ "support indexing from the end.")
118+ if index.step is not None and index.stop is None:
119+ raise ValueError("Lazy sequences do not support step slicing "
120+ "without an end.")
121+ start = index.start if index.start is not None else 0
122+ if index.stop is None:
123+ newseq = LazySequence(self)
124+ newseq.index += start
125+ return newseq
126+ else:
127+ stop = max(index.stop, start)
128+ start += self.index
129+ stop += self.index
130+ assert self.state.index_of_0 <= start
131+ self.state.ensure_index(self.index + stop)
132+ start -= self.state.index_of_0
133+ stop -= self.state.index_of_0
134+ if index.step is None:
135+ return self.state.buffer[start:stop]
136+ else:
137+ return self.state.buffer[start:stop:index.step]