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

Only allow to raise and catch exceptions deriving from BaseException #5

Merged
merged 4 commits into from
Aug 20, 2016
Merged

Only allow to raise and catch exceptions deriving from BaseException #5

merged 4 commits into from
Aug 20, 2016

Conversation

mheinzel
Copy link
Contributor

@mheinzel mheinzel commented Aug 7, 2016

Hi Matt,

I made some changes regarding exception handling. Previously you could raise anything at all and catch "real objects" (Object ObjectInfo) of any class. You can see that in the tests I added.
The behavior now matches the Python interpreter more closely and only allows raising and catching exceptions deriving from BaseException.

 

When digging around in the code I found some more things that seem to be not handled completely right. I think we agree that achieving perfectly identical behavior would make the code more complex and is not the goal of this project, but I will mention them briefly (for reference):

  • Evaluation (and check of correctness) of except clauses should happen only when an exception
    was raised and could be caught by them.
    E.g. this works fine in Python 3.5 (but not when changing the order of the two except clauses):

    try:
          raise Exception()
    except Exception:
          print("caught")
    except 3:
         pass

    This means ExceptionHandler should contain an Expression instead of a ClassInfo.
    Also, it is legal for this expression to be a tuple of multiple valid exception classes
    (e.g. except (SystemError, TypeError):).

  • Parsing: xor_expr: and_expr ('^' and_expr) should be xor_expr: (xor_expr '^') and_expr (the same for and, or etc.). Currently 1 ^ 2 ^ 3 is a parsing error.

  • Parsing: In the language reference, there exists a separate target type, mainly for assignment.
    you can not assign to an expression_list, only to a target_list, which makes code like
    1 + 2 = "test" a parsing error instead of having to handle it later.

  • Optional function parameters should come in the end. Code like def f(a = 1, b): print(a, b) should not be allowed. Calling f(3) causes Prelude.!!: index too large.

I also found a nice way to create an endless loop in the interpeter: Redefining exception types and causing an internal exception e.g.:

TypeError = 3
"".a

This is because internal exceptions are raised by the name of the exception. raiseInternal then looks up the corresponding class to create an exception object. If that fails, it raises an exception (and now the same thing happens again and again). :D
Redefining existing classes is nothing you would normally do, though, so I see no need to fix it.

Matthias

@mattgreen mattgreen merged commit f3e7cd6 into mattgreen:master Aug 20, 2016
@mheinzel mheinzel deleted the must-derive-from-baseexception branch August 31, 2016 07:19
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