Tuesday, December 01, 2015

French Python ?

In two previous post, I showed how it was possible to transform some source code prior to having it executed.  My original motivation was to see how one could add a new keyword ("repeat") to use as "repeat n:" and it be equivalent to "for _ in range(n):".

As part of the additional motivation for my experiment, I mentioned the following:

In one of his posts to python-ideas, Terry Jan Reddy mentioned a discussion on the idle-dev list about making idle friendlier to beginners. In one of his post, he mentioned the idea of having non-English keywords. This idea is not new. There already exists an unmaintained version with Chinese Keywords as well as a Lithuanian and Russion version. Maintaining a version based on a different language for keywords is surely not something simple ... nor I think it would be desirable. However, it might be possible to essentially achieve the same goal by using an approach I describe in the next section.

Even just adding new keywords can be quite difficult. For example, in this post, Eli Bendersky explains how one can add a new keyword to Python. "All" you ned to do is

  1. Modify the grammar to add the new keyword
  2. Modify the AST generation code; this requires a knowledge of C
  3. Compile the AST into bytecode
  4. Recompile the modified Python interpreter
Not exactly for the faint of heart...

I thought I should revisit the idea I had to see how difficult it might be to create a French Python syntax. As it turned out, it was even simpler than implementing a new keyword. In addition to the code mentioned previously, the new function needed is simply:

def transform_source_code(text):
    dictionary = {...}
    toks = tokenize.generate_tokens(StringIO(text).readline)
    result = []
    for toktype, tokvalue, _, _, _ in toks:
        if toktype == tokenize.NAME and tokvalue in dictionary:
            result.append((toktype, dictionary[tokvalue]))
        else:
            result.append((toktype, tokvalue))
    return tokenize.untokenize(result)

where the dictionary contains the equivalent (e.g. "Vrai": "True", etc.)

The one change I made from the previous version was to replace __experimental__ by __nonstandard__.

For example, here's a test program:

from __nonstandard__ import french_syntax 
de math importe pi  

imprime(pi)  
imprime("The first 5 odd integers are:") 
pour i dans intervalle(1, 11, 2):  
imprime(i)  

imprime("This should be false:", Vrai et Faux)  

si pi == 3:  
imprime("We must be in Indiana") 
ousi pi > 4:  
print("Non standard Euclidean space") 
autrement:  
print("There should be nothing about Indiana nor Euclidean space.")

The code found in version 5 of this repository. Using this approach, it would be trivial to create localized Python versions suitable to introduce absolute beginners to programming concepts. I would not do this myself, here in Canada, but I could see the appeal in some other countries especially those where the English alphabet is not very well known by young learners.

Now, if only I could figure out how to use importlib instead of imp ...


No comments: