Skip to content

Implementing slice() and slices#345

Merged
JeffersGlass merged 32 commits into
spylang:mainfrom
JeffersGlass:slice_impl
Feb 8, 2026
Merged

Implementing slice() and slices#345
JeffersGlass merged 32 commits into
spylang:mainfrom
JeffersGlass:slice_impl

Conversation

@JeffersGlass
Copy link
Copy Markdown
Contributor

@JeffersGlass JeffersGlass commented Dec 30, 2025

Implements slice objects by (1) writing a Slice class in spy and (2) turning Slice ast nodes into calls to the Slice constructor at frame eval time.

@antocuni
Copy link
Copy Markdown
Member

Teach cwriter about outputting structs (as PBC's if blue?)

why do you need it?
That's something which is on the general plan for SPy but probably not super easy to do, I didn't expect it to be required for this PR

@JeffersGlass
Copy link
Copy Markdown
Contributor Author

Teach cwriter about outputting structs (as PBC's if blue?)

why do you need it?

That might be a holdover from an earlier implementation detail; I'm not sure it's still relevant.

Add parsing of slice nodes

Make slices into calls to slice() in astframe; implement list.__getitem__(slice)

Add slice (with hack) to make_fqn_const

Fix mypy issue in fmt_expr_Slice

Dump constant structs to c

Implement slice indices and tests

Implement slicing of lists, so long as step == 1
Merge from main

More improvements to list and slices; some additional tests (some failing)

Working slicing except for imports in _list in tests?

Avoid circular imports in stdlib

Suppress NoneType params and args in c backend

Experiments with doppler
Merge branch 'main' into slice_impl

Doppler working with a janky fqn hack that breaks c =O

Much less janky implementation of eval_Slice in astframe

Got opspec with fast_metacall... not right but closer

Remove typo in shift_sice_expr

Cleanup and clarify shift_expr_Slice
Simplify ASTFrame and Doppler for slice

Remove unnecessary backend changes
Merge branch 'main' into slice_impl

Cleanup types and tests

Cleanup tests and old dead code
@JeffersGlass JeffersGlass marked this pull request as ready for review January 29, 2026 16:09
@JeffersGlass
Copy link
Copy Markdown
Contributor Author

This I think is ready for review! One discussed feature was using a bitmask instead of individual ints to account for the possible None-ness of the slice's attributes; I have not implemented that here.

Copy link
Copy Markdown
Member

@antocuni antocuni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very good job @JeffersGlass 👏
I left some comments here and there; they might look a lot but it's just because this PR is pretty big, but overall it looks good.

Another note: this PR implements slice support only for __getitem__, correcT? It might be worth raising a WIP in the __setitem__ case (and leave the actual implementation for another PR)

Comment thread docs/src/contributing.md
Comment thread spy/analyze/symtable.py
Comment thread spy/backend/c/context.py
paramlist = [f"{p.c_type} {p.name}" for p in self.params]
paramlist = [
f"{p.c_type} {p.name}" for p in self.params if p.c_type.name != "void"
]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interesting. I suppose this is needed because "somewhere" you get a function with a void parameter?
Which function is that?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code suppresses any None parameters of functions - in particular opimpls returned by slice.__new__.

Consider the following spy code:

def main() -> None:
    l = [1,2,3][:1]

The metafunc that is slice.__new__ ends up selecting impl6 to us. For typechecking reasons, impl6 takes parameters of the form (None, int, None). But in the C code, we don't need (or want) to pass a void parameteter - we know we only need a single int to specify, in this case, the end of the slice. Otherwise, we end up with code like:

spy__slice$Slice spy__slice$Slice$__new__$impl6(void _start, int32_t _stop, void _step) {  //<<< errror
    return (spy__slice$Slice){ 0, 1, _stop, 0, 1, 1 };
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah I see, basically you want to support this scenario:

def foo(x: None) -> None:
    pass

I never thought about it but I suppose it makes sense to allow it. It should have a test in test_basic.py though (like test_None_arguments)

Comment thread spy/backend/spy.py
Comment thread spy/tests/stdlib/test__list.py Outdated
Comment thread stdlib/_list.spy Outdated
Comment thread stdlib/_list.spy Outdated
Comment thread stdlib/_slice.spy Outdated
Comment thread stdlib/_slice.spy Outdated
Comment thread stdlib/_slice.spy Outdated
Comment thread .python-version Outdated
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This appears to have been committed in error in an earlier PR

@JeffersGlass
Copy link
Copy Markdown
Contributor Author

Another note: this PR implements slice support only for getitem, correcT? It might be worth raising a WIP in the setitem case (and leave the actual implementation for another PR)

Added a WIP error for _list.__setitem__(slice); will leave the implementation to a future PR.

@JeffersGlass JeffersGlass requested a review from antocuni February 6, 2026 18:45
Copy link
Copy Markdown
Member

@antocuni antocuni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you @JeffersGlass!
There is a conflict in doppler.py, but feel free to merge it once the conflict is resolved and you add test_None_arguments in test_basic.py

@JeffersGlass JeffersGlass merged commit db69c10 into spylang:main Feb 8, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants