nohtyprm / MrPython

A simplified programming environment for Python (3.x) - based on IDLE
https://nohtyprm.github.io/MrPython/
Other
28 stars 36 forks source link

Precondition fail in interactive interpreter results in endless execution #202

Open Alexwestbrook opened 3 weeks ago

Alexwestbrook commented 3 weeks ago

For example take the following function:

def func(a:int) -> int:
    """
    Renvoie un nombre positif tel quel
    Precondition: a>=0
    """
    return a

assert func(1)==1
assert func(-1)==-1

Executing it will show the following error:

-----
Erreurs à l'exécution (Interprète Python) :
-----

Erreur: ligne 9
==> Erreur de précondition
     Fonction : func (Ligne 4)
     Précondition : a>=0
     Fausse avec 
        a = -1

===================================================

But running func(-1) in the interactive interpreter keeps on forever without any messages and I have to manually stop the execution.

EDIT: This issue also occurs whenever the precondition fails when calling the function inside another function WHICH HAS PRECONDITIONS. For example add this function to the script:

def func_1(a:int) -> int:
    """
    Renvoie un nombre positif tel quel
    Precondition: a>=-1
    """
    return func(a)

assert func_1(-1)==-1

It will run forever but if we changed it to remove preconditions:

def func_1(a:int) -> int:
    """
    Renvoie un nombre positif tel quel
    Precondition:
    """
    return func(a)

assert func_1(-1)==-1

It now shows the appropriate error:

-----
Erreurs à l'exécution (Interprète Python) :
-----

Erreur: ligne 16
==> Erreur de précondition
     Fonction : func (Ligne 4)
     Précondition : a>=0
     Fausse avec 
        a = a

===================================================

Note: The last error message could be more informative than a=a

fredokun commented 1 week ago

The precondition-checking is still a little bit experimental. There are multiple issues involved. For the "evaluation area", for the moment precondition-checking is not enabled because of non-trivial implementation details. For students the "best" thing to do is to say that only "correct" evaluations should be performed in this area. To put it differently, this is "normal python evaluation" unlike for embedded tests (asserts). One more reason to write assertion tests ! (this is not optimal, I know)

Alexwestbrook commented 1 week ago

I understand. However I've had a couple students think they had written an endless loop when it was just a precondition failure. Maybe there is a way to disable the precondition checking behavior to avoid confusing students.

I will just add here another example of unexpected behavior due to preconditions, although of a different nature, to avoid opening another issue. In this example, the error message of the division by 0 is placed on the wrong line depending on whether there was a precondition in the function:

def func(a: int) -> int:
    """fonction identité"""
    return a

assert func(1) == 1

def inverse(a: int) -> float:
    """
    Renvoie l'inverse de a
    Précondition: a>=0
    """
    return 1/a

assert inverse(0)==0

Executing this code results in the following error:

-----
Erreurs à l'exécution (Interprète Python) :
-----

Erreur: ligne 6
==> Division par zéro

========================================================

I have found through some other tests that the line number indicated appears to be the line number starting from the definition of the function. Removing the precondition results in the appropriate line number being reported.

-----
Erreurs à l'exécution (Interprète Python) :
-----

Erreur: ligne 12
==> Division par zéro

========================================================