Wednesday, October 30, 2013

NodeBlockly


This week I have added two new features to GoogleBlockly, first is zooming the block workspace in and out with the mouse wheel, and second is nodes. I have not forked Blockly's source code to do this; instead these changes are dynamically applied at runtime from PythonJS by changing some of Blockly's internal functions and prototypes. "NodeBlockly" is still a work in progress, and likely will be a large effort to finish off, I am accepting donations to continue this work, so please GitTip me.

"Data-flow is often a simpler way to represent certain common tasks. However we chose not to use it for two reasons. The first is that data-flow languages usually fail badly when attempting to solve tasks outside their domain. The second is that the generated code looks nothing like the visual data-flow representation, which serves as a barrier for the user graduating from the visual programming language to a text-based code editor. We feel strongly that users should not be locked in." from http://code.google.com/p/blockly/wiki/FAQHighLevel

The developers of GoogleBlockly have dismissed node and flow-graph based editing because it produces code that may not closely match its visual form, and this would make Blockly less useful for children to learn programming when reading the generated output code. This is something to consider, but I do not think Blockly should be without nodes just for that reason alone. Having the option to connect blocks via nodes can be very helpful to visually organize a program. If everything is restricted to only using click-blocks, without any node connections, quickly a program can become hard to understand because the blocks have become so nested and convoluted.

Node based programming is also important for professional use. Blockly has great potential to be integrated with game engines and other kinds of applications that need to bridge the gap between low-level scripting (JavaScript) and high level application logic managed by artists and designers. Blockly's internal API is lacking a good event system to interact with external toolkits, this is also something I am working on fixing, so that Blockly can be integrated with complex applications.

Try Node Blockly

Once you have checked out the latest PythonJS source code and installed Tornado, you also need to pull the latest: Three.js, Tween.js, and GoogleBlockly. These should be saved in your home directory. From the terminal run server.py (in PythonJS/tests) and point your web browser to: http://localhost:8080/threejs_node_blockly.html

Blocks are connected together in the normal way using the left mouse button and dragging them to the female slot. To create a node connection you do the same thing with the middle mouse button, a new node input will be created, and the original block will be connected to it and snap back to its original position. (this is just a temporary hack, later you will be able to left click to create a new node and drag it into a slot.)

Sunday, October 27, 2013

GoogleBlockly and Physijs


GoogleBlockly integrated with Physijs using PythonJS. Physijs is a physics plugin for Three.js that makes integration with ammo.js very simple. It exposes several constraint and geometry types, including a vehicle object. You can take a look at my wrapper for Physijs, here.

Friday, October 25, 2013

Google Blockly Underestimated


Above is my test showing the PythonJS custom block generator integrated with Google Blockly and THREE.js. Get the source code here.

Truffle Blocks, by David Griffiths integrates Google Blockly and the GerminationX html5 game engine. In Truffle Blocks, Google Blockly has a hard time when scaling up to deal with complex logic, because it requires too much screen space. The solution is to write custom Blocks that are higher level and domain specific to your application. But writing these custom Blocks in JavaScript is not so simple, there is a large gap between the ease of using Blockly's block-programming, and the complexity of its internal API and JavaScript itself. The PythonJS wrapper for Blockly helps bridge this gap, by providing a way to almost automatically generate custom Blocks from PythonJS functions using decorators and a simple API. You can take a look at my wrapper here.

Blockly Three.js and Tween.js


Tween.js by Soledad Penades is a fast and simple animation library that can interpolate "tween" values. I have created a binding for Tween.js for PythonJS, here, and integrated it with the GoogleBlockly THREE.js editor, the new animation blocks are efficiently driven by Tween.js and can animate translation and color. see my commit here.

Last night I was chatting with Erik de Bruijn (creator of The UltiMaker 3D printer) and he completely blew me away with his work he has been pioneering with GoogleBlockly and THREE.js to make a constructive solid geometry editor called "UltiShaper". Do not miss these youtubes he has posted!

Wednesday, October 23, 2013

GoogleBlockly THREE.js Editor


This is my prototype showing how GoogleBlockly and THREE.js can be integrated using PythonJS. Check out the source code here.

When the initial tree of blocks is compiled, any block that accepts dynamic inputs is gets wrapped by __blockinstance( call, id ), this attaches the return value instance to the Blockly Block that created it, id is the unique block identifier. Then when the blocks dynamic inputs are later changed, it can call the callbacks that update the attached instance directly using the JavaScript output from Blockly.

learn more about PythonJS at the new site that Amirouche recently setup.

http://www.pythonjs.net

Sunday, October 20, 2013

THREE.js PythonJS Editor Prototype


Power is still slowly being restored to Tarlac, I am still without power or internet. Currently I am using internet cafe's and friends houses to charge up, code, and go online.

This week I made many fixes to PythonJS and added new features like: list comprehensions, lambda functions, websockets, integration with Ace Editor, and updated the THREE.js bindings. This youtube shows off a prototype editor that allows you to edit the Python source in Ace, and dynamically recompile it.

Thursday, October 17, 2013

Custom Unicode Operators in Python


Ferdinand Jamitzky has an interesting hack that adds custom operators to Python using the | bitwise-or operator on both sides of the custom operator. This technique can also be leveraged by the PythonJS compiler to support custom operators, by pre-processing the source before it is turned into an AST, custom operators defined by the special decorator @custom_operator("operator-name") can be automatically replaced in the source with |'operator-name'|. See this commit.

Example

@custom_operator( 'XXX' )
def operatorX(x,y):
 return x | y

@custom_operator( 'YYY' )
def operatorY(x,y):
 return x | y

def test():
 a = 1 |'operatorX'| 2 |'operatorY'| 3
 print a
 b = 1 XXX 2 YYY 3
 print b
The above gets translated by PythonJS into this intermediate form:
    a = operatorY( operatorX( 1, 2 ), 3 )
    print a
    b = operatorY( operatorX( 1, 2 ), 3 )
    print b

Unicode Example ⊖

We can also use unquoted unicode strings as operator names, this example uses the circled minus operator ⊖ directly in our Python code. The @custom_operator decorator marks this operator to call the symmetric_difference function. See this commit.

@custom_operator( '⊖' )
def symmetric_difference(a,b):
 d = []
 for v in a:
  if b.count(v): pass
  elif d.count(v): pass
  else: d.append( v )
 for v in b:
  if a.count(v): pass
  elif d.count(v): pass
  else: d.append( v )
 return d

def test():
 sdiff = [1,2,3] ⊖ [2,3,4]
 print sdiff
 for v in sdiff:
  print v

Wednesday, October 16, 2013

PythonJS


Amirouche and I have decided to rename the PythonScript project to PythonJS. I have switched to working in the main develop branch on github, so use that instead of pulling from my old fork.

PythonJS has many advantages over current Python-to-JavaScript translators. 1. Speed: using static type analysis the compiler can optimize the code so that it runs faster, this early test shows our compiler can output JavaScript that runs many times faster than CPython, and twice as fast as PyPy. 2. Simplicity: PythonJS is one of the only Python-to-JavaScript translators written entirely in Python, the code base is much smaller than the others, and is easy to understand and extend. 3. Support for directly calling external JavaScript functions, by generating wrapper code at runtime. 4. Easily write wrappers to external JavaScript libraries for performance critical applications.

Monday, October 14, 2013

Writing JavaScript Prototypes in Python

Four days after Typhoon Nari, and still the power has not been restored to most areas of Tarlac, including where I live. Despite this I have managed to continue working on PythonScript at internet cafe's and other places with power and internet.

The with keyword is not often used in Python programs, probably you have only seen it used as a short cut for opening files. The with syntax also had support in early Javascript, but it is now deprecated. This makes with not useful for direct translation to JavaScript. This leaves with available for us to hijack in PythonScript as a custom syntax for other things. The new statement with javascript: now tells the compiler to treat the following block of code as inlined JavaScript. Previously you had to use the special JS(str) function to inline JavaScript as a string literal, this can still be useful, but in general leads to messy code. The new with javascript: statement can replace JS(str) in all cases where the code to be inlined is also valid Python syntax.

JavaScript Prototypes

Instead of proper classes, JavaScript has Object prototypes that can be extended with new functions that act like bound methods. In these functions the binding to this is based on the current calling context, so they break when assigned to a variable or passed to a callback function. Example:

func = document.createElement
e = func( 'a' )
e.setAttribute('id', 'myid')

The above will fail because createElement depends on its calling context of document in order to work. The ugly JavaScript way of doing this is using the bind function to create a wrapper function that binds document as the calling context:

func = document.createElement.bind( document )

Extending JavaScript Prototypes from PythonScript

Using the new with javascript: statement, we can now easily write inline JavaScript functions and assign them to prototypes using a special decorator syntax: @[class-name].prototype.[method-name]. The decorator ensures that when the method is called from PythonScript the proper calling context is bound to this.

The code below is from runtime/builtins.py it shows how the String prototype is changed to behave like Python's string class. Note that other decorators are not allowed within with javascript: blocked code.

with javascript:
    def _create_empty_object(arr):
            o = Object.create(null)
            for i in arr:
                o[ i ] = True
            return o


def _setup_str_prototype():

    with javascript:

        @String.prototype.startswith
        def func(a):
            if this.substring(0, a.length) == a:
                return True
            else:
                return False

        @String.prototype.endswith
        def func(a):
            if this.substring(this.length-a.length, this.length) == a:
                return True
            else:
                return False

        @String.prototype.join
        def func(a):
            out = ''
            if instanceof(a, Array):
                arr = a
            else:
                arr = a.__dict__.js_object
            i = 0
            for value in arr:
                out += value
                i += 1
                if i < arr.length:
                    out += this
            return out

        @String.prototype.upper
        def func():
            return this.toUpperCase()

        @String.prototype.lower
        def func():
            return this.toLowerCase()

        @String.prototype.index
        def func(a):
            return this.indexOf(a)

        @String.prototype.isdigit
        def func():
            digits = _create_empty_object( ['0','1','2','3','4','5','6','7','8','9'] )
            for char in this:
                if char in digits: pass
                else: return False
            return True


Saturday, October 12, 2013

Typhoon Nari


I have been back in the Philippines for about a month now, the weather this year has been more wet than it normally is. Two nights ago Typhoon Nari hit us hard in Tarlac, these are the most powerful winds I have ever seen. Now two days after, the city is still without power. I have been charging my laptop at the generator-powered bus station and using their free wifi, at least until the security guard caught me today using the power plug that is supposed to power the pump for the goldfish pond. I tried to explain to him that gold fish do not need much oxygen, but he was not hearing me out.

Until power is restored at home, I won't be able to do much work on PythonScript. However, I am still working on what I can. Today I improved the way JavaScript can be inlined into PythonScript. Previously to inline JavaScript you had to wrap it in JS("some javascript code"), this becomes tedious after awhile. The new style to inline JavaScript is using the with statement like this: with javascript: When you enter a with javascript: block the compiler will switch into a different mode where you can create JavaScript Arrays and Objects using Python's literal list and dict syntax; this is a shortcut for calling JSArray() and JSObject().

with javascript:


<html>
<head>
<script src="pythonscript.js"></script>

<script type="text/python">

a = 'hello'
b = 'world'

def test():

 with javascript:
  arr = []
  arr.push('hello')
  arr[1] = 'world'
  ob = { x:'foo', y:'bar'}
  console.log( arr )
  console.log( ob )

</script>
</head>

<body>
<button onclick="test()">click me</button>
</body>
</html>

Thursday, October 10, 2013

PythonScript - Updates


One of the first changes I made this week to PythonScript was to change the default variable scope from global to local. PythonScript now follows the Python standard, where each function defines a new scope of local variables. The global keyword is now used to declare global variables when you need to assign a value to a global. The commit to do this is tiny, it simply injects var for you by looking at all variable assignments in a function.

I also added and improved some builtins: min, max, abs, chr, ord, tuple and dict. The new dict goes beyond what is possible in normal Python by allowing any type to be used as a key, so in case you ever had wanted to use a list or another dict as a dict key, now you can in PythonScript. See my commits here: [1], [2], [3]

Direct DOM

Another major missing feature of PythonScript was HTML DOM bindings, I first tried writting wrapper, but dropped that approach quickly when I found it was easy to modify the special get_attribute method to directly support DOM by generating wrapper functions at runtime. I was able to generalize this so that PythonScript can directly call other JavaScript functions, see this commit. The example below changes the text of button when clicked to 'CLICKED!' and inserts 'hello world' below it.
<html>
<head>
<script src="pythonscript.js"></script>
</head>
<body>
<button id="mybutton" onclick="test()">click me</button>

<script type="text/python">

a = 'hello'
b = 'world'

def test():
 con = document.createElement( 'div' )
 con.setAttribute('id', 'mydiv')
 document.body.appendChild(con)
 print( con )
 txt = document.createTextNode( a+b )
 con.appendChild(txt)

 print( con.getAttribute('id') )
 btn = document.getElementById('mybutton')
 print(btn)
 btn.firstChild.nodeValue = 'CLICKED!'

</script>
</body>
</html>

array

PythonScript now supports an array builtin that acts like array.array from Python's standard library. It is implemented using Javascripts ArrayBuffer and DataView API. If you are dealing with large sets of numbers, then using the new array builtin can save you memory, because in normal JavaScript each number is 64bits and costs you 8 bytes. When using array you can have a list-like-object that only uses 4 bytes (32bits) for each number it contains. See my commits here: [1], [2]

create a 32bit floating point array

arr = array('f', [0.1, 0.2] )
arr.append( 1.1 )
arr.append( 2.2 )
for value in arr:
 print( value )

As you can see above, the array class dynamically grows its internal ArrayBuffer for you when you append new items to it. This array will use half the memory of a normal JavaScript array, but can we do better?

create a 16bit floating point array

arr = array('float16', [-10.0, 3.141592653589793, 10.0])
print 'error:', arr[1] - 3.141592653589793

Above creates a special quantized array type. The DataView API has no notion of '16bit floats', but we can roll our own using Int16. Internally the array class finds the min and max the array will hold by looking at the array used to initialize it, then when packing and adding new values they are scaled and quantized. Later when accessing the elements of the array they get 'unscaled and unquantized' back into floats. The error between input and output is minimal for an array with minimal dynamic range. The example above has a dynamic range of -10 to 10, the error for PI is only 0.0000172, not bad. [1]

create an 8bit floating point array

arr = array('float8', [-10.0, 3.141592653589793, 10.0])
print 'error:', arr[1] - 3.141592653589793

For the ultimate memory savings you can use the special 8bit float type that only uses one byte per-number. This can be used for cases where a larger amount of error is acceptable, and the input data has values that are not far apart (low dynamic range). The above example, with the same dynamic range as the previous example produces a greater error of about 0.07. If the dynamic range is increased to -50 to 50, then the error increases to 0.38568 and PI becomes 2.7559.

Saturday, October 5, 2013

JavaScript Operator Overloading


Javascript has no support for operator overloading. Axel Rauschmayer created a clever hack to provide "fake" operator overloading, but this has several drawbacks. Juho Vepsäläinen created an example solution using JSShaper, that parses and modifies the JavaScript AST, see his blog post and commit. Too bad Juho stopped working on his project two years ago, and only providing support for: +, -, /, *

I also had a look at CoffeeScript and TypeScript, and was very surprised to see that neither one of these has support for operator overloading. CoffeeScript could have added this feature, but would have needed static type checking in order to do it selectively, see this issue. TypeScript can easily support operator overloading, last year Ursuletzu created a fork that adds this feature, but his work was rejected by Jonathan Turner, see this heated thread.

Is it time to give up on operator overloading and JavaScript? Not yet, about a week ago I blogged about adding support for __getattr__ to PythonScript. My approach was similar to Juho Vepsäläinen's, but instead of changing the JavaScript AST, I modified the Python AST in the first stage of the PythonScript compiler. Python provides a well developed system for operator overloading that can be fully leveraged using this technique. It may sound ironic, the best solution for operator overloading in JavaScript is to write your code in Python. In my recent commits [1] [2], to the PythonScript development branch, I have added support for overloading the following operators:

  • +
  • -
  • *
  • /
  • %
  • <<
  • >>
  • &
  • ^
  • |
  • +=
  • -=
  • *=
  • /=
  • %=
  • <<=
  • >>=
  • &=
  • ^=
  • |=

THREE.Vector3

I have fully wrapped the THREE.Vector3 class with smart methods that are able to detect if the right operand is a scalar or Vector3 type. The technique for checking the type of a JavaScript object at runtime is to inline a JavaScript expression into the the Python if statement. At first this seems strange, but is actually a very powerful feature of the PythonScript compiler. See below: JS("{}.toString.call(o) === '[object Object]'")

class Vector3:
 ... 

 def add(self, o):
  assert isinstance(o, Vector3)
  self.set( self.x+o.x, self.y+o.y, self.z+o.z )
  return self

 def addScalar(self, s):
  self.set( self.x+s, self.y+s, self.z+s )
  return self

 def __add__(self, o):
  if JS("{}.toString.call(o) === '[object Object]'"):
   assert isinstance(o, Vector3)
   return Vector3( self.x+o.x, self.y+o.y, self.z+o.z )
  else:
   return Vector3( self.x+o, self.y+o, self.z+o )

 def __iadd__(self, o):
  if JS("{}.toString.call(o) === '[object Object]'"):
   self.add( o )
  else:
   self.addScalar( o )

Thursday, October 3, 2013

PythonScript - Wrapping Javascript Libraries


Wrapping THREE.js

Wrapping Javascript libraries in PythonScript is a simple and direct procedure, using the JS(string) function you can directly inline javascript. The example below wraps the THREE.Vector3 class, in the __init__ constructor it directly calls new THREE.Vector3(x,y,z) and assigned it to self._vec.
class Vector3:
 def __init__(self, x=0, y=0, z=0 ):
  self._vec = JS('new THREE.Vector3(x,y,z)')

 @property
 def x(self):
  vec = self._vec
  return JS('vec.x')
 @x.setter
 def x(self, value):
  vec = self._vec
  JS('vec.x=value')

 @property
 def y(self):
  vec = self._vec
  return JS('vec.y')
 @y.setter
 def y(self, value):
  vec = self._vec
  JS('vec.y=value')

 @property
 def z(self):
  vec = self._vec
  return JS('vec.z')
 @x.setter
 def z(self, value):
  vec = self._vec
  JS('vec.z=value')

@property

The example wrapper above is using the @property decorator to expose the vector x,y,z attributes from Javascript to PythonScript. This was previously not supported by PythonScript, you can see my commit here that adds basic support for getter/setter property decorators.

The python_to_pythonjs compiler was modified to support the @property decorator by inserting the right calls for each instance of a class where those properties get used. This requires that the compiler knows what class type each instance is - this becomes a problem for scripts that are later compiled in another pass, because the compiler needs all the information that was introspected during AST traversal. To workaround this problem the introspected data is dumped to a file for each wrapper module and is loaded later when a script calls: from some_module import *

tests/server.py

I also added a test server, see this commit, using the Tornado web framework that dynamically converts html files that contain embedded PythonScript. It will process any PythonScript wrappers in the head and cache the AST introspection data so that the embedded PythonScript can properly import and use the wrapper classes in them.

Example


<html><head>
<script src="pythonscript.js"></script>
<script src="libs/three/three.min.js"></script>
<script src="bindings/three.py"></script>

<script type="text/python" closure="true">
from three import *

def test():
 v = Vector3(1, 2, 3)
 print( v.x )
 print( v.y )
 print( v.z )

</script>
</head>

<body>
<button onclick="test()">click me</button>
</body>
</html>