We need to state and unify our goals

4 views
Skip to first unread message

Samuel Ytterbrink

unread,
Mar 2, 2011, 9:47:28 AM3/2/11
to py...@googlegroups.com
First of all sorry for making a new thread, but I didn't really know where to start complaining >.<. I haven't had the time to deal with all the mails that have arrived. I blame all the loss of time on OpenTTD which is an evil game who steals your time, eats your soul and leave you empty longing for more! I want to thank all of you for you contributions both in code and thought you are both/all wonderful! 

Good that the py-builtins.js has bean split, even if i just want to throw it away completely.

Now to the ranting. First of all I want to state why I think the way I do and then what I think. Cause I believe we have almost the same goals but we are ready to sacrifice different things to accomplish them. Also goals seems to get clouded when trying to find the correct way of doing things. (We should create a Goals page in the Wiki!)

Me, Me and Me:

My background as many others here is that I found pyjamas.  I tried to use it but it was buggy and didn't support things it said it would( property, Lists and decorators is just the top of the list). And when it did fail it did so with out a helping message. And after arguing a lot with the caretaker of the project, Luke, I found that there model seams to be broken, it can't support all of pythons features with out paying a to big price in performance. Second they put more effort in there libs( which is in Javastyle python) than the compiler. Also they don't translate to pure JavaScript but to JavaScript, CSS and HTML.

After I looked around the internets I found py2js and one of it's best features was it's 1 to 1 ness. Python and JavaScript are in a lot of ways the same language( at least they are of the same family). Py2Js uses this fact to its advantage and doesn't separate Python-space and JavaScript-space.

<code>
alert(10);
</code>

Is the same in Python and JavaScript for py2js.Therefor the JS function from pyjamas is not needed as much. 
Later when fixing bugs in py2js i saw the ugly py-builtins and wondered why? In an attempt to phrase the builtins in python i found the Catch-22, or as you said before the hen or the egg problem.( Why this is important is a lot bigger question, which I will return to later.) This however wasn't an easy task, I found that we need a JS function to be able to write the builtins in python. When looking I found a another project that actually a lot of our built-in code comes from( mostly all unused). And one that uses our test suite( thats how i found it!).


It uses a name-space, js.function(value,varibel,etc) , to know if it should un-box things cause there is no real good way to know if you are using python string or JavaScript strings. This however is a bad idea cause it is not very 1 to 1.

The more i have read in the mailing list it sounds as you( both) really want that project and not the py2js.

So now to the rant on what i want from py2js:

The Stdlib and Types:

As much special cases as possible of code should be able to execute without of the stdlib( or builtins), this makes the compiler more stand alone( and the project more modular). And if there are parts that can't be non stdlib-dependent we should make them modular from the rest of the compiler! 

As much of the lib should be written in python. This project is for people that don't want to write JavaScript, right? Therefor if our users can't help them selves contribute to the project, cause they don't know more then copy/past JavaScript. The project will suffer and will have a hard time maintaining bug fixes.

Also the best way to ensure that the compiler is optimal is if we use it a lot! and whit the whole standard lib written mostly in python will help with that. Its also beneficial in writing the lib cause we can use all the nifty features in the compiler to write the code, like classes and functions with star arguments!

The 1 to 1:ness of py2js almost in it self supports this features needed to do this and with the JavaScript eval function we don't even need the JS function we just need to be careful and don't use it in places where it get rerun a lot i.e. only use it for declarations(at top level?). The eval function can be optimised in the compiler( if it only has a string literal as argument) but it should only be used with flags.

The 1 to 1:ness as I think of it is like this:
To translate 1+1 to 1.__add__(1) is okay cause it would be correct in Python as well, it is not Py2Js black magic but Python black magic. Also to translate "Hello World" to str("Hello World") would be okay if it wasn't for the problem that  JavaScript strings would not be converted if they where in a variable that wasn't initialised but the compiler and then break badly cause lack of Pythonic error handling in the original string class.

There are other ways to handle the problems you have stated on enhancing the JavaScript types, look at jQuery. In jQuery you can do
<code>
jQuery(function($){
  if($===window.$){
    alert("jQuery is the real deal");
  }else{
    alert("Something else then jQuery are using the $ variable");
  }
})
</code>
So we could make our own decorator that switches between the standard implementation of the types and ours. So that you can do JavaScript safe zones and so on. also we could do fal-backs: if the Python implementation don't work use the standard one. jQuery uses a lot of native code to do its bidding that is one of the reasons its fast,  we should do the same!

	// Save a reference to some core methods
	toString = Object.prototype.toString,
	hasOwn = Object.prototype.hasOwnProperty,
	push = Array.prototype.push,
	slice = Array.prototype.slice,
	trim = String.prototype.trim,
	indexOf = Array.prototype.indexOf,
</code>

its also good if what you would write in a JavaScript prompt with the stdlib loaded and testing things is as close to python as possible:
<code>
>>> __name__
"__main__"
>>> __import__("sys").stdout.write("Hello World!")
Hello World!
undefined
>>>
</code>

Prefixes and Dummy Variables:

To use py2js prefixes is out of the question its just bad! it makes code not just ugly but it makes it less usable outside of our compiled environment. You should be able to build good JavaScript library with the help of Py2Js. It should be as easy to call functions from the JavaScript to Py2Js as the other way around!

If you want a good example of this look at my call-convention from the old Wiki!


caller needs to do:
```javascript
   fun.kwargs = {"varname":value};
   fun.defaults = fun.func_defaults.concat([]);
   func.apply(this, arguments);
   deleat fun.defaults;
   deleat fun.kwags;
```

and the  callee needs to fix the arguments like this:

```javascript
   var varname = arguments[arg_num] || arguments.callee.kwars["varname"] || arguments.callee.defaults.pop();
```
</code>

It doesn't support star or star star from JavaScript( if you don't follow the call-conventions) but you can use the function with its defaults from javascript as if it was a javascript function! And it only uses the func_defaults member of a function which is Python black magic( in my view of things acceptable black magic).

The compiler at the moment uses dummy variables which sometimes is needed but not to the extent it uses them( think of them as a stack in assembly) also you should never clutter the name-space we should use closures more! code from my test-compiler from old site!

def encapsulate(visible=[], *body):
  if visible:
    visible = ["var %s;\n" % ",\n  ".join(visible)]
  else:
    visible = []
  return "\n".join(visible + ["(function (){"] + list(body) + ["})()"])
</code>
and
  def visit_Compare(self, comp_expr):
    def  fix(i, op):
      if op == "in":
        return encapsulate("",
            "if(typeof $%d ==\"undefined\"){" % (i+1),
            "  return false;",
            "}else if(typeof $%d.__contains__ != \"undefined\"){" % (i+1),
            "  return $%d.__contains__($%d);" % (i+1, i),
            "}else if((typeof $%d.contains) != \"undefined\"){" % (i+1),
            "  return $%d.contains($%d);" % (i+1, i),
            "}else{",
            "  return $%d in $%d;" %  (i, i+1),
            "}",
            )
      return "$%d %s $%d" % (i, op, i+1)
    exprs = [self.visit(comp) for comp in [comp_expr.left] + comp_expr.comparators]
    ops = [self.visit(op) for op in comp_expr.ops]
    return encapsulate(
        "",
        "var %s;" % ", ".join("$%d = %s" % t for t in enumerate(exprs)),
        "return (" + " && ".join(
          fix(i, op) for i,op in enumerate(ops) ) + ");"
        )
</code>

as you see its not so beautifully code in any other case but you get the hint.

Hope you find this helping and informative and not so much ranting ^^. And just don't think TLDR.

//Samuel Ytterbrink

Ondrej Certik

unread,
Mar 2, 2011, 8:30:10 PM3/2/11
to py...@googlegroups.com
Hi Samuel,

On Wed, Mar 2, 2011 at 6:47 AM, Samuel Ytterbrink <nep...@gmail.com> wrote:
> First of all sorry for making a new thread, but I didn't really know where
> to start complaining >.<. I haven't had the time to deal with all the mails
> that have arrived. I blame all the loss of time on OpenTTD which is an evil
> game who steals your time, eats your soul and leave you empty longing for
> more! I want to thank all of you for you contributions both in code and
> thought you are both/all wonderful!
> Good that the py-builtins.js has bean split, even if i just want to throw it
> away completely.

[...]

Thanks for your long email. Did you write this before or after talking
with Christian over the phone?

I think it will be easier to simply discuss the issues over the phone.

For now, the py-builtins.js cannot be generated by the compiler, as it
is not mature enough. Eventually I think it will be generated,
especially with the two modes, that I mentioned. I think a general
conclusion is that instead of thinking big, let's concentrate on
fixing the immediate issues (modules, 2 modes, ...), but keep the door
open, so that the project can grow in the right direction and
eventually the py-builtins.js can be generated.

For example, once we write a pure Python AST parser, then the py2js
should be able to translate itself to JavaScript, thus an eval() for
Python code will be possible. But again, this further in the future.

Ondrej

Neppord

unread,
Mar 3, 2011, 6:15:41 AM3/3/11
to py...@googlegroups.com
I wrote it befor talking to him. I guess it was what triggered the need for the voice chat.

I see your point but... Some small changes can make the big ones harder. And rightnow we can write the stdlib python with the eval statement, and hopefully soon remove the merge script with our module implementation.

Reply all
Reply to author
Forward
0 new messages