Skip to content

Commit

Permalink
Implement iterator-based Sequence.cached
Browse files Browse the repository at this point in the history
  • Loading branch information
GrieferAtWork committed Dec 20, 2024
1 parent 51b3475 commit c5fb4cf
Show file tree
Hide file tree
Showing 30 changed files with 1,201 additions and 54 deletions.
1 change: 1 addition & 0 deletions .vs/deemon-v141.sln
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{2360741E-F
..\util\test\deemon-sequence-each-contains.dee = ..\util\test\deemon-sequence-each-contains.dee
..\util\test\deemon-sequence-each.dee = ..\util\test\deemon-sequence-each.dee
..\util\test\deemon-sequence-enumerate.dee = ..\util\test\deemon-sequence-enumerate.dee
..\util\test\deemon-sequence-flatten.dee = ..\util\test\deemon-sequence-flatten.dee
..\util\test\deemon-sequence-locate.dee = ..\util\test\deemon-sequence-locate.dee
..\util\test\deemon-sequence-math.dee = ..\util\test\deemon-sequence-math.dee
..\util\test\deemon-sequence-reversed.dee = ..\util\test\deemon-sequence-reversed.dee
Expand Down
2 changes: 2 additions & 0 deletions .vs/deemon-v141.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@
<ClInclude Include="..\src\deemon\objects\int-8bit.h" />
<ClInclude Include="..\src\deemon\objects\int_logic.h" />
<ClInclude Include="..\src\deemon\objects\seq\byattr.h" />
<ClInclude Include="..\src\deemon\objects\seq\cached-seq.h" />
<ClInclude Include="..\src\deemon\objects\seq\combinations.h" />
<ClInclude Include="..\src\deemon\objects\seq\concat.h" />
<ClInclude Include="..\src\deemon\objects\seq\default-api-methods-attrproxy-impl.c.inl" />
Expand Down Expand Up @@ -443,6 +444,7 @@
<ClCompile Include="..\src\deemon\objects\roset.c" />
<ClCompile Include="..\src\deemon\objects\seq.c" />
<ClCompile Include="..\src\deemon\objects\seq\byattr.c" />
<ClCompile Include="..\src\deemon\objects\seq\cached-seq.c" />
<ClCompile Include="..\src\deemon\objects\seq\combinations.c" />
<ClCompile Include="..\src\deemon\objects\seq\concat.c" />
<ClCompile Include="..\src\deemon\objects\seq\default-api-methods.c" />
Expand Down
6 changes: 6 additions & 0 deletions .vs/deemon-v141.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,9 @@
<ClInclude Include="..\src\deemon\objects\seq\byattr.h">
<Filter>src\objects\seq</Filter>
</ClInclude>
<ClInclude Include="..\src\deemon\objects\seq\cached-seq.h">
<Filter>src\objects\seq</Filter>
</ClInclude>
<ClInclude Include="..\src\deemon\objects\seq\combinations.h">
<Filter>src\objects\seq</Filter>
</ClInclude>
Expand Down Expand Up @@ -1298,6 +1301,9 @@
<ClCompile Include="..\src\deemon\objects\seq\byattr.c">
<Filter>src\objects\seq</Filter>
</ClCompile>
<ClCompile Include="..\src\deemon\objects\seq\cached-seq.c">
<Filter>src\objects\seq</Filter>
</ClCompile>
<ClCompile Include="..\src\deemon\objects\seq\combinations.c">
<Filter>src\objects\seq</Filter>
</ClCompile>
Expand Down
1 change: 1 addition & 0 deletions .vs/deemon-v142.sln
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{2360741E-F
..\util\test\deemon-sequence-each-contains.dee = ..\util\test\deemon-sequence-each-contains.dee
..\util\test\deemon-sequence-each.dee = ..\util\test\deemon-sequence-each.dee
..\util\test\deemon-sequence-enumerate.dee = ..\util\test\deemon-sequence-enumerate.dee
..\util\test\deemon-sequence-flatten.dee = ..\util\test\deemon-sequence-flatten.dee
..\util\test\deemon-sequence-locate.dee = ..\util\test\deemon-sequence-locate.dee
..\util\test\deemon-sequence-math.dee = ..\util\test\deemon-sequence-math.dee
..\util\test\deemon-sequence-reversed.dee = ..\util\test\deemon-sequence-reversed.dee
Expand Down
2 changes: 2 additions & 0 deletions .vs/deemon-v142.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@
<ClInclude Include="..\src\deemon\objects\int-8bit.h" />
<ClInclude Include="..\src\deemon\objects\int_logic.h" />
<ClInclude Include="..\src\deemon\objects\seq\byattr.h" />
<ClInclude Include="..\src\deemon\objects\seq\cached-seq.h" />
<ClInclude Include="..\src\deemon\objects\seq\combinations.h" />
<ClInclude Include="..\src\deemon\objects\seq\concat.h" />
<ClInclude Include="..\src\deemon\objects\seq\default-api-methods-attrproxy-impl.c.inl" />
Expand Down Expand Up @@ -443,6 +444,7 @@
<ClCompile Include="..\src\deemon\objects\roset.c" />
<ClCompile Include="..\src\deemon\objects\seq.c" />
<ClCompile Include="..\src\deemon\objects\seq\byattr.c" />
<ClCompile Include="..\src\deemon\objects\seq\cached-seq.c" />
<ClCompile Include="..\src\deemon\objects\seq\combinations.c" />
<ClCompile Include="..\src\deemon\objects\seq\concat.c" />
<ClCompile Include="..\src\deemon\objects\seq\default-api-methods.c" />
Expand Down
6 changes: 6 additions & 0 deletions .vs/deemon-v142.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,9 @@
<ClInclude Include="..\src\deemon\objects\seq\byattr.h">
<Filter>src\objects\seq</Filter>
</ClInclude>
<ClInclude Include="..\src\deemon\objects\seq\cached-seq.h">
<Filter>src\objects\seq</Filter>
</ClInclude>
<ClInclude Include="..\src\deemon\objects\seq\combinations.h">
<Filter>src\objects\seq</Filter>
</ClInclude>
Expand Down Expand Up @@ -1298,6 +1301,9 @@
<ClCompile Include="..\src\deemon\objects\seq\byattr.c">
<Filter>src\objects\seq</Filter>
</ClCompile>
<ClCompile Include="..\src\deemon\objects\seq\cached-seq.c">
<Filter>src\objects\seq</Filter>
</ClCompile>
<ClCompile Include="..\src\deemon\objects\seq\combinations.c">
<Filter>src\objects\seq</Filter>
</ClCompile>
Expand Down
1 change: 1 addition & 0 deletions src/deemon/objects/dict.c
Original file line number Diff line number Diff line change
Expand Up @@ -2906,6 +2906,7 @@ INTERN_TPCONST struct type_getset tpconst dict_getsets[] = {
TYPE_GETTER_F(STR_frozen, &DeeRoDict_FromSequence, METHOD_FNOREFESCAPE,
"->?Ert:RoDict\n"
"Returns a read-only (frozen) copy of @this ?."),
TYPE_GETTER(STR_cached, &DeeObject_NewRef, "->?."),
#ifndef CONFIG_NO_DEEMON_100_COMPAT
TYPE_GETSET_F("max_load_factor",
&deprecated_d100_get_maxloadfactor,
Expand Down
1 change: 1 addition & 0 deletions src/deemon/objects/hashset.c
Original file line number Diff line number Diff line change
Expand Up @@ -2048,6 +2048,7 @@ INTERN_TPCONST struct type_getset tpconst hashset_getsets[] = {
TYPE_GETTER_F(STR_frozen, &DeeRoSet_FromSequence, METHOD_FNOREFESCAPE,
"->?Ert:RoSet\n"
"Returns a read-only (frozen) copy of @this HashSet"),
TYPE_GETTER(STR_cached, &DeeObject_NewRef, "->?."),
#ifndef CONFIG_NO_DEEMON_100_COMPAT
TYPE_GETSET_F("max_load_factor",
&deprecated_d100_get_maxloadfactor,
Expand Down
1 change: 1 addition & 0 deletions src/deemon/objects/list.c
Original file line number Diff line number Diff line change
Expand Up @@ -3608,6 +3608,7 @@ PRIVATE struct type_getset tpconst list_getsets[] = {
TYPE_GETTER_F(STR_frozen, &list_get_frozen, METHOD_FNOREFESCAPE,
"->?DTuple\n"
"Return a copy of the contents of @this List as an immutable sequence"),
TYPE_GETTER(STR_cached, &DeeObject_NewRef, "->?."),
TYPE_GETTER_F("__sizeof__", &list_sizeof, METHOD_FNOREFESCAPE, "->?Dint"),
TYPE_GETSET_END
};
Expand Down
1 change: 1 addition & 0 deletions src/deemon/objects/rodict.c
Original file line number Diff line number Diff line change
Expand Up @@ -1082,6 +1082,7 @@ PRIVATE struct type_method tpconst rodict_methods[] = {

PRIVATE struct type_getset tpconst rodict_getsets[] = {
TYPE_GETTER(STR_frozen, &DeeObject_NewRef, "->?."),
TYPE_GETTER(STR_cached, &DeeObject_NewRef, "->?."),
TYPE_GETTER_F("__sizeof__", &rodict_sizeof, METHOD_FNOREFESCAPE, "->?Dint"),
TYPE_GETSET_END
};
Expand Down
1 change: 1 addition & 0 deletions src/deemon/objects/roset.c
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,7 @@ PRIVATE struct type_method tpconst roset_methods[] = {

PRIVATE struct type_getset tpconst roset_getsets[] = {
TYPE_GETTER(STR_frozen, &DeeObject_NewRef, "->?."),
TYPE_GETTER(STR_cached, &DeeObject_NewRef, "->?."),
TYPE_GETTER_F("__sizeof__", &roset_sizeof, METHOD_FNOREFESCAPE, "->?Dint"),
TYPE_GETSET_END
};
Expand Down
86 changes: 55 additions & 31 deletions src/deemon/objects/seq.c
Original file line number Diff line number Diff line change
Expand Up @@ -2179,35 +2179,59 @@ PRIVATE struct type_getset tpconst seq_getsets[] = {
/**/ "print repr x.flatten; /* { 0, 1, 2, 5, 7, 9, 1, 10, 1 } */"
"}"),

/* TODO: Implement this one similar to how "first" and "last" are implement (iow: using `struct Dee_type_seq_cache') */
/* TODO: Variants of this need to be added for `Set' and `Mapping' */
//TODO: TYPE_GETTER("cached", &DeeSeq_InvokeCached,
//TODO: "->?.\n"
//TODO: "Returns a sequence that is a lazily-populated, read-only proxy of @this ?{.}.\n"
//TODO: "As such, ?#cached behaves similar to ?#frozen, except that the rather than"
//TODO: /**/ "evaluating the elements of the sequence immediately, said evaluation will"
//TODO: /**/ "happen the first time elements are accessed. Additionally, there is no"
//TODO: /**/ "requirement that changes to the original sequence won't propagate into the"
//TODO: /**/ "\"cached\" sequence (even after the cache may have been populated).\n"
//TODO: "The only difference between some $seq and ${seq.cached} is that the later"
//TODO: /**/ "will allow for #B{O(1)} access to elements after an initial access, and"
//TODO: /**/ "that any side-effects of accessing some element will happen exactly once.\n"
//TODO: "In practice, this means that ?Acached?DTuple and ?Acached?DList will just"
//TODO: /**/ "re-return the tuple/list, but for most other sequences, a proxy is returned"
//TODO: /**/ "that will do one of the following:"
//TODO: "#L-{"
//TODO: /**/ "If @this's ?A__seqclass__?DType is ?. and implement ${operator []} and ${operator size},"
//TODO: /**/ /**/ "the cache lazily computes its size the first time it is accessed, and elements"
//TODO: /**/ /**/ "are saved into an internal buffer which is re-used during repeated calls|"
//TODO: /**/ "If @this's ?A__seqclass__?DType is ?. and only implement ${operator []}, the same thing"
//TODO: /**/ /**/ "happens, except that the size is determined by accessing+caching elements"
//TODO: /**/ /**/ "until the underlying sequence's ${operator []} returns :IndexError|"
//TODO: /**/ "If @this implements ${operator iter}, that operator is invoked the first time"
//TODO: /**/ /**/ "the size- or an element of the cache is accessed, then proceeds to yield from"
//TODO: /**/ /**/ "that iterator and cache its results until the requested index is reached. (In"
//TODO: /**/ /**/ "the case of the returned cache's size being accessed, the cache is populated"
//TODO: /**/ /**/ "fully)"
//TODO: "}"),
TYPE_GETTER(STR_cached, &default_seq_cached,
"->?.\n"
"Returns a sequence that is a lazily-populated, read-only proxy of @this ?..\n"
"The returned proxy will ensure that any indirect side-effects¹ of accessing elements, "
/**/ "or iterating the sequence will only happen once upon initial access/iteration. "
/**/ "E.g. a yield-function is only executed one time, and only up the point that "
/**/ "elements have been requested for.\n"
"Sequence types where element access/iteration has no indirect side-effects¹, meaning "
/**/ "essentially every materialized ?. type (e.g. ?DList, ?DTuple, ?DDict, ...), can "
/**/ "implement this property as a no-op: ${property cached = { . -\\> this; }}\n"
"As such, ?#cached behaves similar to ?#frozen, except that the rather than "
/**/ "evaluating the elements of the sequence immediately, said evaluation will "
/**/ "happen the first time elements are accessed. Additionally, there is no "
/**/ "requirement that changes to the original sequence won't propagate into the "
/**/ "\"cached\" sequence (even after the cache may have been populated).\n"
"The difference between some $seq and ${seq.cached} is that the later "
/**/ "will allow for #B{O(1)} access to elements after an initial access, and "
/**/ "that any indirect side-effects¹ of accessing some element will happen "
/**/ "exactly once.\n"
"${"
/**/ "/* \"lines\" will lazily populate itself from the contents of \"data.txt\" */\n"
/**/ "local lines = Sequence.cached(File.open(\"data.txt\", \"rb\"));\n"
/**/ "print lines.locate(line -\\> !line.startswith(\"##\"));\n"
/**/ "\\\n"
/**/ "/* This will print the first couple of lines from the cache, up until (and\n"
/**/ " * including) the already-accessed line, then continue reading from \"data.txt\" */\n"
/**/ "for (local line: lines)\n"
/**/ " print line;"
"}\n"
"${"
/**/ "function getItems() {\n"
/**/ " print \"Enter\";\n"
/**/ " yield 10;\n"
/**/ " print \"Middle\";\n"
/**/ " yield 20;\n"
/**/ " print \"Leave\";\n"
/**/ "}\n"
/**/ "\\\n"
/**/ "local items = getItems().cached;\n"
/**/ "print items[0]; /* Enter 10 */\n"
/**/ "print items[0]; /* 10 */\n"
/**/ "print items[1]; /* Middle 20 */\n"
/**/ "print items[0]; /* 10 */\n"
/**/ "print items[1]; /* 20 */\n"
/**/ "print ##items; /* Leave 3 */\n"
/**/ "print repr items; /* { 10, 20, 30 } */"
"}\n"
"#L{"
/**/ "{¹}An indirect side-effect is a change to the program's global state, usually caused "
/**/ /**/ "by the invocation of user-code. Examples include: changes to global variables, "
/**/ /**/ "output being written to a file, or text being printed to stdout."
"}"),

/* TODO: itemtype->?DType
* Check if the type of @this overrides the ?#ItemType class attribute.
Expand All @@ -2233,9 +2257,9 @@ PRIVATE struct type_getset tpconst seq_getsets[] = {
"Returns a copy of @this Sequence, with all of its current elements, as well as "
/**/ "their current order frozen in place, constructing a snapshot of the Sequence's "
/**/ "current elements. - The actual type of Sequence returned is implementation- "
/**/ "and type- specific, but a guaranty is made that nothing no non-implementation-"
/**/ "specific functions/attributes (i.e. anything that doesn't match #C{__*__}) will "
/**/ "be able to change the elements of the returned sequence.\n"
/**/ "and type- specific, but a guaranty is made that no non-implementation-specific "
/**/ "functions/attributes (i.e. anything that doesn't match #C{__*__}) will be able "
/**/ "to change the elements of the returned sequence.\n"
"By default, this attribute simply casts @this Sequence into a ?DTuple, but sequence "
/**/ "types that are known to already be immutable can override this attribute such "
/**/ "that they simple re-return themselves.\n"
Expand Down
Loading

0 comments on commit c5fb4cf

Please sign in to comment.