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

Allow for a failing test to automatically raise an error #368

Open
jimbxb opened this issue Nov 25, 2022 · 3 comments
Open

Allow for a failing test to automatically raise an error #368

jimbxb opened this issue Nov 25, 2022 · 3 comments
Labels
enhancement New feature or request error message detection and reporting of errors in Wybe code good first issue Good for newcomers

Comments

@jimbxb
Copy link
Collaborator

jimbxb commented Nov 25, 2022

If a test is called in a det context, the compilation will error. This is good, I hope we can agree.

Sometimes, though, you don't really care about what happens in the failure case, and instead would want to abort the program. Automatically generating such code would reduce boilerplate code written.

Consider the following:

?lst = [1,2,3]
if { lst^head = ?h :: 
    pass
   | else :: 
    !error("no head")
}
!print(h)

In such a case, we could via some static analysis know that the head call cannot fail. Alternatively, as the programmer, we may wish to handle this, but of course make it explicit. Consider this:

?lst = [1,2,3]
?head(lst) = ?h
!print(h)

The preceding ? says "I know this is a test, and if this fails call !error". The compiler could automatically generate the if here, which would allow for the !error call to have the call position resource set appropriately.

While this probably isn't ideal, I think it could be handy if you want to do something in an admittedly hacky way.

@jimbxb jimbxb added enhancement New feature or request error message detection and reporting of errors in Wybe code good first issue Good for newcomers labels Nov 25, 2022
@pschachte
Copy link
Owner

For this case, I would expect to write this:

?lst = [1,2,3]
head(lst) = ?h
| error "head of empty list"

I'm not sure if this works, but it should. And it does have the benefit of incorporating an error message.

I'm not crazy about overloading the question mark this way, but for cases where you don't want to bother with the error message, how about this instead:

?lst = [1,2,3]
trust {head(lst) = ?h}

I would hope that trust could be written as a HO proc, so this feature could be in the library rather than the language.

@jimbxb
Copy link
Collaborator Author

jimbxb commented Nov 25, 2022

I believe one alternative that works currently is

head(lst, ?h, _)

Which reifies the test, ignoring the succeed/fail bool. I think the program should segfault in many cases where lst has no head, but I'm sure there's silent failures that can arise and cause havock with other tests. :)


The ... | error syntax looks nice enough. I think the call to error needs a !, which is fine, we just need to double check that special resources are handled appropriately here.


trust looks fishy to me. While I like the idea that lambdas can bind variables, I feel it's very "action-at-a-distance"-y. The lambda also need to have the {test} modifier, I believe. Inferring such would be difficult too -- you'd need to mode check the body of the lambda, but that requires type checking of the body, which is done at the same time as mode checking of the calling context, and relies on the detism of the lambda... Sigh.

Actually, as it's a test, why can't it be reified like

def trust(test:bool) {
    if { ~test :: !error("uh oh!") }
}

trust(head(lst, ?h))

# which is just
head(lst, ?h, ?tmp)
trust(tmp)

That might not work right now, but I don't see why we can't allow it.

@pschachte
Copy link
Owner

head(lst, ?h, _) had better not be allowed, since ?h won't be bound if the call to head fails. If the Wybe compiler doesn't reject it, that's a bug. Anyway, I'm pretty sure LLVM will wind up rejecting it, because h will be assigned undef in that branch. Reifying tests with outputs can't be allowed, at least not unless the reified Boolean variable is checked and confirmed to be true before any outputs are accessed.

You're right about the ! in front of the error call. I forgot that.

I don't see trust {head(lst) = ?h} as action at a distance. What's necessary for this to type/mode check properly is to have the ability to declare of a lambda that it will be executed at least once (better still for this case, exactly once), and trust would have to declare that for its argument. Of course, this would have to be checked by the compiler. Then trust {head(lst) = ?h} is no more action at a distance than head(lst) = ?h.

Because head(lst, ?h, _) can't be allowed, neither can trust(head(lst, ?h)).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request error message detection and reporting of errors in Wybe code good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

2 participants