Compiler is very bad (not strictly) checking the code


#1

The compiler is very bad (not strictly) checking the code. I sometimes make typos or write the wrong code. But the source is compiled and does not produce any errors. Here is an example. Obviously wrong code that does not give any error messages:

t = bytearray[11]
t[0] = chr(‘t’)
t[1] = chr(‘e’)
t[2] = chr(‘s’)
t[3] = chr(‘t’)
t[4] = chr(’=’)
t[5] = chr(’"’)
t[6] = chr(‘1’)
t[7] = chr(’"’)
t[8] = 255
t[9] = 255
t[10] = 255

However, if I check it in any Python sandbox, I get an error:

Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux

Traceback (most recent call last):
File “python”, line 1, in
TypeError: ‘type’ object is not subscriptable

This makes development very difficult. For example, I am writing a program, everything works. I add a new functionality and the program stops working. But I wrote a lot of new code, but Zerynth does not give an error and I begin to guess that there is an error in the code, but I cannot know where. You have to unwind the code step by the time it worked.


#2

Hello @trawen,

and thanks for your feedback!

What you are describing is not a bug in the Zerynth compiler, but a feature (yes, a feature) of Python that is hidden by the common use of the REPL ( a.k.a. the prompt you get when you type start python in interactive mode).
Python is a dynamic language and there is no way for the compiler to understand that the “bytearray[]” part is actually a bytearray until execution time. For the compiler (i.e. the program that converts Python into an executable string of bytecode) the “bytearray[]” is just “apply the [] operator to the name bytearray”.

When you type this code into the Python REPL (which stand for Read-Eval-Print-Loop, please note the Eval part of it) the code is actualy compiled with no error and the executed raising an exception. Zerynth gives you an exception that is not catched when you run the code on the microcontroller (try catching and printing the execption in the serial console).

To better show the point, let me introduce the “dis” module of Python. It compiles any piece of Python code to bytecode.

import dis

def test_compile():
    a = bytearray[11]

dis.dis(test_compile)

The output of the above code in REPL should give no error and be something like:

 2           0 LOAD_GLOBAL              0 (bytearray)
              2 LOAD_CONST               1 (11)
              4 BINARY_SUBSCR
              6 STORE_FAST               0 (a)
              8 LOAD_CONST               0 (None)
             10 RETURN_VALUE

As you can see, the “bytearray[]” part is just loading a global name (“bytearray”), then loading a constant (11) and then applying the BINARY_SUBSCR operator which, in the case of bytearray, raises an exception.
Indeed, if you then try to run test_compile() you will get the same error.

The only way both in Python and Zerynth to catch a TypeError is to execute the code, it is not possible for the compiler to decide that the code is wrong without executing it. A good approach is to at least always enclose your main function into a try/except block so you can print a traceback in the Zerynth console and find the line where the error was raised.