Le 5 janv. 2018 �� 12:34, Dimitris Chloupis <kilon.alios@gmail.com> a ��crit :


Well done, great to see my code be reused for new project. I am happy to see people take it one step further. 

What exactly your code offers additional to my code ? Is there is something special you do with it?

Python3Generator allows to generate a Python 3 AST programatically. So basically you have objects that represent Python 3 AST nodes and some messages in top of that to make the generation of the AST easier from Pharo.

E.g.

ast := 'print' asP3GIdentifier callWith: #('Hello world').

ast inspect


If you have a look at the readme on GitHub you will see more complexe examples.

 
There is a concept of �� Interpreter �� in this framework. Basically, an interpreter is an object to which you provide strings containing Python 3 code and that execute it.

There is a FFI interpreter which writes the python code in a file on the file system and uses the int system(char *) function to make python execute the file. It also redirect stderr to a file and read that file after execution in order to have eventual execution errors.

You don't really need this approach. The reason why I did not add this feature in Atlas is because the way that Python import its files is basically normal execution. 

So each time you 

import mymodule

what you do is you execute mymodule. Basically Python does the same thing with execution when it does a import. This is why we need the if main thing to detect whether the module execution happened because of import or because it was executed directly (via terminal, or double click).

So in case of Atlas all you have to do is put your code in a python module and import then module from atlas with sendMessage: 'import mymodule���.  

I wanted that to avoid the user having to set up a Python server listening on a socket when it is not needed to get data from Python.

 
There is a Atlas interpreter which uses the Atlas project from Kilon. Atlas makes Python and Pharo talk trough sockets. So this is what you want I guess. The thing is, if I want to send data from Python Pharo, I would use the Atlas interpreter and serialise data to send to Pharo through a socket as JSON for example. But for Matplotlib I do not need to read Python���s value so I did not implemented that. Nevertheless, it could be cool to have this ability to get Python���s data in Pharo because we could use Numpy or others Python modules for which getting Python's is important.


Atlas provide this ability via getValue: message. There is a catch , what you get is always strings. So that means if you use a complex Python object you will have to convert that to some form of string format that clearly represents the data . JSON could be a good candidate here because both Python and Pharo support this. I have created a very basic template Pharo object that parses strings to Pharo objects as an example that I have included but still its going to be tricky especially with Numpy because it all happens at C level and not Python level for performance reasons. Still its not that hard to do if you really need this feature which in your case you don't.

Yep, but if I want to get value from Python into Pharo, I want to have them as Pharo objects so as you said some conversion has to be made which means more work.

Another interesting thing when communicating through sockets between two different languages is: How do you manage callbacks? For example I would like to be able to make Python execute a Pharo Block at a certain point of the execution or to make Pharo execute a Python���s lambda. I do not have answer for that.


You can do that in Pharo side or Python side , its up to you. Only you need is a string that acts as a single. For example getValue: technically is kinda like a callback because it sends the string containing the python command but it waits for response from Python that will signal it if the return string contains the signature, if I remember correctly, getvalue: value. So essentially what I have done is create a mini transfer protocol.  

It was necessary for me to do this not because of callback  per se, but because I wanted to retain the live coding abilities of Pharo while coding using Python libraries. In order to do that I wanted to send Python errors back to Pharo and trigger the Pharo debugger with the python error as the name of the error. To do that I had to implement a protocol that diffirentiate between return values and value that concern only Atlas in this case python errors. 

This protocol can be extended of course to contain a myriad of things, callbacks, thread synchronization, C function calls , C memory etc. 

So technically speaking its already possible through Atlas. If you want to do something very special with callback that involves the Pharo IDE as I did with Python error you only need to extend this protocol adding your own kind of signal strings.

I think you could re-use the ideas behind the bridge but not the code. It is really specific to Python 3, I do not see how you could generate LISP using it as is.

Julien

As far as my Atlas  is concerned I had made also a Python 2 version but never bothered to continue developing it because I needed only Python 3. The good news is Python 2 and 3 have minor differences when it comes to sockets.

Indeed Atlas wont work magically with other language but porting it is not hard because I tried to keep the majority of the code as much as I could in Pharo side for this precise reason. So my initial intention was to provide Atlas to Pharo community as a means to use libraries of any programming language from inside Pharo. I hoped that people would use it as the foundation to bring other languages inside Pharo like I did for Python but alas it seems Pharoers for some weird reason prefer to use Pharo :D (joke for those that did not notice the laughing smiley face)

I was also planning adding the ability of memory mapped files that I used in my CPPBridge prohect. This form of communication accelerate things by thousands of times because its low level. But it sacrifices remote execution which means in this case you fall back to the existing socket bridge approach. This was necessary at the time because sockets are not a good idea if you plan on doing large loops, because obviously there is a delays , its low around 1 millisecond and less depending on the power of CPU but if you do 1 million iterations would turn that 1 millisecond to 1000 seconds which of course is no fun. 

On the other hand even without memory mapped files you can avoid this by making sure you keep the loop either on python side or pharo side with the condition it does not contain Atlas communication commands that open and close the socket.