Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Variable-arity returns and function contracts. #6568

Merged
merged 20 commits into from
May 9, 2024

Conversation

Moderocky
Copy link
Member

Description

This provides better support for things that aren't able to determine their return arity during parse time.

Typically, things will error during parse time if you, for example, try to set a single variable {var} to several values {list::*}.
This is fine and intended behaviour, and helps to prevent a lot of silly mistakes (or people not realising that something returns multiple things), however it also causes annoying issues with things that conceivably could be simple (and there are real cases where it should be permissible to set {x} to ...) but aren't able to determine whether they will be single.

Two features are added to assist with this.

Function/Callable Contracts

This addresses the problem in the linked issue.
Some functions (currently only clamp that I could find, there might be others where this could be applied) are marked non-single but are guaranteed to return only a single value when a single input is used.
This means that it can never use a single variable (e.g. set {x} to clamp(0, 1, 2)) even if it's a guarantee that the function will return only one value.

This feature adds optional function contracts. A contract is like an agreement for the return type hints/singularity/etc. based on the actual argument expressions used.
For example, a function could be single if expression[0].isSingle() or it might always return the return type of expression[n], or return the same number of values as argument (e.g. some kind of packIntoList(A, B, C) function).
Contracts allow us to specify this in order to have a more reliable signature and type hints at parsing time.

This information is typically unavailable to a Function until it becomes a FunctionReference, and so wasn't really possible before.
Functions defer to their contract for return types and singularity, but a function reference can be its own contract so nothing has changed for most functions.

The clamp function has been changed to use a contract (single = arg 0 is single), fixing the linked issue. It will now be single with single inputs and properly error if used in the wrong way.

Potential Singles

This is a user-knows-best model, and so should be applied with caution.
This is a special toggle for expressions that may return multiple values, but still ought to permit single changers in the SET mode.
If an expression returns true from permitSingle(), then it can be used as the change value for a single expression/variable in the SET mode.
E.g. set {x} to blah and set {x::*} to blah would both be permissible.
When used in single mode, the first value of the array is returned and everything else (if it exists) is discarded, which is actually what happens in a normal single expression.

This is designed for cases where singularity might be known only at runtime (or based on some factor Skript can't safely acquire) but the user probably has a good idea based on the use case. We trust the user to make the right decision.

Currently, no existing syntax uses this -- I felt it was out of scope for this PR.


Target Minecraft Versions: any
Requirements: none
Related Issues: #6488, alternative to #6567

@Moderocky Moderocky added enhancement Feature request, an issue about something that could be improved, or a PR improving something. feature Pull request adding a new feature. functions Related to functions labels Apr 15, 2024
Copy link
Member

@sovdeeth sovdeeth left a comment

Choose a reason for hiding this comment

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

this looks very nice, exactly what i had wanted when I originally made clamp()!

@Moderocky
Copy link
Member Author

this looks very nice, exactly what i had wanted when I originally made clamp()!

Do let me know if any other functions should make use of this.

@sovdeeth
Copy link
Member

this looks very nice, exactly what i had wanted when I originally made clamp()!

Do let me know if any other functions should make use of this.

I'm sure we could do the same for things like round, or really any of the math operations, allow them to be vectorized essentially.

@sovdeeth sovdeeth added the feature-ready A PR/issue that has been approved, tested and can be merged/closed in the next feature version. label May 9, 2024
@sovdeeth sovdeeth merged commit 389dbf9 into SkriptLang:dev/feature May 9, 2024
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Feature request, an issue about something that could be improved, or a PR improving something. feature Pull request adding a new feature. feature-ready A PR/issue that has been approved, tested and can be merged/closed in the next feature version. functions Related to functions
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants