Tuesday, March 11, 2014

PythonJS 0.8.6 Released



Above, PythonJS is used to create a dynamic water physics demo that integrates: Three.js, Skunami.js, p2.js, and Pixi.js. The yellow 'blob' is created by an array of p2.js springs and particles that are rendered as metaballs using MarchingCubes in Three.js.

You can get the new PythonJS 0.8.6 release here. The new release includes many bug fixes and better inter-operation with external JavaScript libraries. Bindings and wrappers are no longer required to work with external JavaScript libraries, types passed to JavaScript functions will be recursively transformed into JavaScript types. Calling Python functions from JavaScript has also been improved. New experimental backends are also included that translate Python into: CoffeeScript, Dart, and Lua.

Sunday, February 23, 2014

pypubjs exports to Android


The Pypubjs IDE can now export to Android using Phonegap. This requires installing PhoneGap and the Android SDK. Phonegap is easily installed with one command sudo npm install -g phonegap. The Android SDK is more work to setup, download it and set your PATH environment variable to include: /tools and /platform-tools. You also need Oracle's Java, here is the steps I did to get it running in Ubuntu:

 sudo add-apt-repository ppa:webupd8team/java
 sudo apt-get update
 sudo apt-get install oracle-java7-installer
 sudo apt-get install ant

 export JAVA_HOME=/usr/lib/jvm/java-7-oracle

Code Visualization


I have integrated a new backend into PythonJS that translates Python code into a visual graph using vis.js. You can load code into the Pypubjs editor, and by clicking "graph" it will run the translation in the background and display the graph in a new window. This can be helpful if you are working with code written by someone else, and need a way to quickly understand it at a higher level.

source code

Friday, February 21, 2014

Fishing in a River of Trash - part2


pypubjs


I am working on an integrated development environment for PythonJS, called Pypubjs. Using Pypubjs you will be able to easily put together HTML5 projects written in CSS, JavaScript and Python, and quickly package binaries for all platforms: Linux, Windows, OSX and mobile using PhoneGap. The IDE itself is written in PythonJS and HTML5 using Node-Webkit and the Ace.js code editor with Darkstrap CSS by Dan Neu (a hack of Twitter's Bootstrap.

see source code

Thursday, February 20, 2014

Fishing in a River of Trash - part1


I had posted earlier this month about the garbage polluting the river that flows into Tarlac City here. 30Km downstream in the center of Tarlac City, things get much worse.

Passing through the city I often see people of all ages fishing in the river, despite its extreme level of pollution. Today I saw four young boys with a battery and two long prods shocking fish to catch them. They were also collecting coconuts from the river.

Tuesday, February 11, 2014

PythonJS to Lua


I recently refactored PythonJS into a better meta-translator and added new backends for: CoffeeScript and Lua. The regression tests now include benchmarks that generate the bar graphs below. I also merged the Lua.js translator to see what happens when you translate Python to Lua and then to JavaScript, the result is slower than PythonJS direct to JavaScript. The Dart backend has the highest performance. LuaJIT also performs well with about half the Pystones of CPython.

Recursive Fibonacci


(time in seconds, less is better)

Pystones


(time in seconds, less is better)

Monday, February 3, 2014

San Jose - Tarlac Province


San Jose, Tarlac Province, has a network of cool streams flowing from the western mountains, it one of the few places in the Philippines that it is still safe to drink water directly from the river. Many small villages can be found near and along the water ways.

Until recently the people in San Jose had lived in near perfect harmony with their environment; sadly things have recently changed. Along my short 3km hike to the river, I estimate I encountered about twenty small dumping sites composed mainly of baby diapers. All of these sites were relatively new. Each site had about 20-100 diapers.

above: baby diapers torn apart and scattered by wild dogs.

Garbage Dynamics

Garbage accumulates at different rates depending on what type it is and where it was dumped. Often it starts out as a few pieces of discarded plastic, once a place no longer is pristine, people are more likely to litter more. Once some threshold has been reached, someone will dump the first big bag of trash, this quickly leads others to dump more in the same area. There is a powerful feedback effect.

It is routine in the Philippines to burn trash in remote areas, this helps restore the areas to a relatively clean state, and control the feedback effect. Diapers are hard to burn compared to most other trash, so they tend to build up and encourage the growth of dumping sites. The Pinoy style for trash burning is simply to throw some grass on top and set it ablaze. This technique fails with diapers.

How To Safely Burn Plastics

Grass and wood should be placed under the plastic. A ratio of at least 50/50 wood/plastic is the minimum. Less harmful dioxins are released when the fire is hot, so the more dry wood the better.

Anything thing with chlorine (like paper products) when burned with plastics creates more dioxins, so burn them separately. Avoid burning black and dark colored plastics. Obviously, try to recycle as much of the plastic as possible, instead of burning it.

Thursday, January 23, 2014

Spaceship Earth


A new computer model by Eric Wolf, estimates the earth will be destroyed by our sun in 1.5 billion years. [1]

It is a popular idea in science and science fiction that we will one day escape destruction on earth by colonizing other planets. In these scenarios the polluted and spent earth is left behind. But, will there be enough space ships to save us all? What about all the plants and animals we would leave behind? This is a bad way of thinking about the future that can have a negative impact on how we think about the present. We more readily accept pollution and things that harm the planet, when we think that in the distant future, we are going to ditch the earth anyways.

Instead we should plan to save the earth by turning it into a giant space ship, so we can safely move the earth to a higher orbit as the sun becomes a red giant star. Is it too soon to worry about these things? It might take millions of years to safely move the earth to this higher orbit, and transforming the earth into a spaceship may itself take millions of years as well, so we better start now to be sure we have enough time.

Much of the earth as we know it will be lost in this radical transformation into spaceship. In order to preserve natural habitats and places for cities of the future, we will need to greatly increase the total surface area, control the weather, and globally route the flow of fresh water. I have created this animation in Blender to try to capture some of these ideas. I imagine the disk structure as a place for the new cities, where people can enjoy flying around in the lower gravity. The original earth surface enclosed in a protective biosphere, can be maintained for wild animals and returned to its natural state. I placed the rocket booster at the south pole, I imagine we would have to drill to the earths core and reinforce the entire earth through its center from both poles.

Thursday, January 16, 2014

Tarlac City vs Ace Manalang


No one here can escape the foul smell of burning plastic. Last month I ran into the Mayor of Tarlac City ("Ace" Manalang) and confronted him about the widespread dumping of plastic and other waste burning all around the city. He tried to dodge my questions, and kept repeating that: "nothing can be done to change the people".

Is it time to give up on clean air and water? I took to the streets to see what people think, and the results surprised me. I spoke with many different people of all ages, and there was a clear pattern in every instance. Women are aware and concerned about the situation, and actively clean and recycle plastics. Children under the age of ten enjoyed picking up plastics, it is seen as a game that can make a little money.

Most of the men I spoke with were either drinking beer or gin. They were unaware and not concerned by problems created by burning plastics. When asked to help clean up the community along side the women and children, all quickly refused. This is what surprised me, they clearly had nothing better to do, yet refused to help. What was holding them back? These drunken men were ironically concerned about their public image and status within the community. If they were seen cleaning trash they could be labeled a "scavenger".

Tuesday, December 10, 2013

PythonJS and Dart - Operator Overloading


PythonJS now translates operator overloading from Python to the Dart backend, see my commit here. Dart supports all the same operators as Python, except for in-place operators. In-place operators are very useful, I am curious why the Dart developers have left this feature out?

Even if this feature is missing in Dart, it can still be forced to work when PythonJS translates to Dart code, by inlining a special if/else for each in-place assignment. Example x += y
if x is a Number or String: then use +=: else use x.__iadd__(y)

The Dart2js compiler is smart enough to determine the type of x at compile time, and optimize the if/else away. This opens the door for doing more dumb tricks from PythonJS that get optimized away by Dart2js.

Python Input

class Vector3:
 def __init__(self, x=0, y=0, z=0 ):
  self._x = x
  self._y = y
  self._z = z

 def set(self, x,y,z):
  self._x = x
  self._y = y
  self._z = z

 @property
 def x(self):
  return self._x
 @x.setter
 def x(self, value):
  print 'x setter', value
  self._x = value

 @property
 def y(self):
  return self._y
 @y.setter
 def y(self, value):
  print 'y setter', value
  self._y = value

 @property
 def z(self):
  return self._z
 @z.setter
 def z(self, value):
  print 'z setter', value
  self._z = value


 def add(self, other):
  self.set( self.x+other.x, self.y+other.y, self.z+other.z )
  return self

 def __add__(self, other):
  if instanceof(other, Number):
   return Vector3( self.x+other, self.y+other, self.z+other )
  else:
   return Vector3( self.x+other.x, self.y+other.y, self.z+other.z )

 def __iadd__(self, other):
  if instanceof(other, Number):
   self.addScalar( other )
  else:
   self.add( other )

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


 def sub(self, other):
  self.set( self.x-other.x, self.y-other.y, self.z-other.z )
  return self

 def __sub__(self, other):
  if instanceof(other, Number):
   return Vector3( self.x-other, self.y-other, self.z-other )
  else:
   return Vector3( self.x-other.x, self.y-other.y, self.z-other.z )

 def __isub__(self, other):
  if instanceof(other, Number):
   self.set( self.x-other, self.y-other, self.z-other )
  else:
   self.sub( other )


 def multiply(self, other):
  self.set( self.x*other.x, self.y*other.y, self.z*other.z )
  return self

 def __mul__(self, other):
  if instanceof(other, Number):
   return Vector3( self.x*other, self.y*other, self.z*other )
  else:
   return Vector3( self.x*other.x, self.y*other.y, self.z*other.z )

 def __imul__(self, other):
  if instanceof(other, Number):
   self.multiplyScalar( other )
  else:
   self.multiply( other )

 def multiplyScalar(self, s):
  self.set( self.x*s, self.y*s, self.z*s )
  return self

 def divide(self, other):
  self.set( self.x/other.x, self.y/other.y, self.z/other.z )
  return self

 def divideScalar(self, s):
  self.set( self.x/s, self.y/s, self.z/s )
  return self

 def __div__(self, other):
  if instanceof(other, Number):
   return Vector3( self.x/other, self.y/other, self.z/other )
  else:
   return Vector3( self.x/other.x, self.y/other.y, self.z/other.z )

 def __idiv__(self, other):
  if instanceof(other, Number):
   self.divideScalar( other )
  else:
   self.divide( other )


def show_vec(v):
 print '-------------'
 print v.x
 print v.y
 print v.z

def main():
 n = 1
 n += 2
 print n

 v1 = Vector3(1, 2, 3)
 v2 = Vector3(10, 0, 10)
 print v1, v2
 print 'testing +'
 a = v1 + v2
 show_vec(a)

 print 'testing +='
 a += 2.5
 show_vec(a)
 a += v1
 show_vec(a)

 print 'testing -='
 a -= v1
 show_vec(a)
 a -= 100
 show_vec(a)

 print 'testing *'
 b = v1 * v2
 show_vec(b)

 print 'testing *='
 b *= 10.0
 show_vec(b)
 b *= v2
 show_vec(b)

 print 'testing setters'
 b.x = 1
 b.y = 2
 b.z = 3

Dart Output


class Vector3 {
  var _z;
  var _y;
  var _x;
  static void __init__(self, [x=0,y=0,z=0]) {
    self._x = x;
    self._y = y;
    self._z = z;
  }

  Vector3(x,y,z) {Vector3.__init__(this,x,y,z);}
  set(x,y,z) { return Vector3.__set(this,x,y,z); }
  static __set(self, x, y, z) {
    self._x = x;
    self._y = y;
    self._z = z;
  }

  get x {
    return this._x;
  }

  set x(value) {
    print(["x setter", value]);
    this._x = value;
  }

  get y {
    return this._y;
  }

  set y(value) {
    print(["y setter", value]);
    this._y = value;
  }

  get z {
    return this._z;
  }

  set z(value) {
    print(["z setter", value]);
    this._z = value;
  }

  add(other) { return Vector3.__add(this,other); }
  static __add(self, other) {
    self.set((self.x + other.x), (self.y + other.y), (self.z + other.z));
    return self;
  }

  operator +(other) { return Vector3.____add__(this,other); }
  static ____add__(self, other) {
    if (other is num) {
      return  new Vector3((self.x + other), (self.y + other), (self.z + other));
    } else {
      return  new Vector3((self.x + other.x), (self.y + other.y), (self.z + other.z));
    }
  }

  __iadd__(other) { return Vector3.____iadd__(this,other); }
  static ____iadd__(self, other) {
    if (other is num) {
      self.addScalar(other);
    } else {
      self.add(other);
    }
  }

  addScalar(s) { return Vector3.__addScalar(this,s); }
  static __addScalar(self, s) {
    self.set((self.x + s), (self.y + s), (self.z + s));
    return self;
  }

  sub(other) { return Vector3.__sub(this,other); }
  static __sub(self, other) {
    self.set((self.x - other.x), (self.y - other.y), (self.z - other.z));
    return self;
  }

  operator -(other) { return Vector3.____sub__(this,other); }
  static ____sub__(self, other) {
    if (other is num) {
      return  new Vector3((self.x - other), (self.y - other), (self.z - other));
    } else {
      return  new Vector3((self.x - other.x), (self.y - other.y), (self.z - other.z));
    }
  }

  __isub__(other) { return Vector3.____isub__(this,other); }
  static ____isub__(self, other) {
    if (other is num) {
      self.set((self.x - other), (self.y - other), (self.z - other));
    } else {
      self.sub(other);
    }
  }

  multiply(other) { return Vector3.__multiply(this,other); }
  static __multiply(self, other) {
    self.set((self.x * other.x), (self.y * other.y), (self.z * other.z));
    return self;
  }

  operator *(other) { return Vector3.____mul__(this,other); }
  static ____mul__(self, other) {
    if (other is num) {
      return  new Vector3((self.x * other), (self.y * other), (self.z * other));
    } else {
      return  new Vector3((self.x * other.x), (self.y * other.y), (self.z * other.z));
    }
  }

  __imul__(other) { return Vector3.____imul__(this,other); }
  static ____imul__(self, other) {
    if (other is num) {
      self.multiplyScalar(other);
    } else {
      self.multiply(other);
    }
  }

  multiplyScalar(s) { return Vector3.__multiplyScalar(this,s); }
  static __multiplyScalar(self, s) {
    self.set((self.x * s), (self.y * s), (self.z * s));
    return self;
  }

  divide(other) { return Vector3.__divide(this,other); }
  static __divide(self, other) {
    self.set((self.x / other.x), (self.y / other.y), (self.z / other.z));
    return self;
  }

  divideScalar(s) { return Vector3.__divideScalar(this,s); }
  static __divideScalar(self, s) {
    self.set((self.x / s), (self.y / s), (self.z / s));
    return self;
  }

  operator /(other) { return Vector3.____div__(this,other); }
  static ____div__(self, other) {
    if (other is num) {
      return  new Vector3((self.x / other), (self.y / other), (self.z / other));
    } else {
      return  new Vector3((self.x / other.x), (self.y / other.y), (self.z / other.z));
    }
  }

  __idiv__(other) { return Vector3.____idiv__(this,other); }
  static ____idiv__(self, other) {
    if (other is num) {
      self.divideScalar(other);
    } else {
      self.divide(other);
    }
  }

}

show_vec(v) {
  print("-------------");
  print(v.x);
  print(v.y);
  print(v.z);
}

main() {
  var a, v1, v2, b, n;
  n = 1;
  if (n is num || n is String) {
    n += 2;
  } else {
    n.__iadd__(2);
  }
  print(n);
  v1 =  new Vector3(1, 2, 3);
  v2 =  new Vector3(10, 0, 10);
  print([v1, v2]);
  print("testing +");
  a = (v1 + v2);
  show_vec(a);
  print("testing +=");
  if (a is num || a is String) {
    a += 2.5;
  } else {
    a.__iadd__(2.5);
  }
  show_vec(a);
  if (a is num || a is String) {
    a += v1;
  } else {
    a.__iadd__(v1);
  }
  show_vec(a);
  print("testing -=");
  if (a is num || a is String) {
    a -= v1;
  } else {
    a.__isub__(v1);
  }
  show_vec(a);
  if (a is num || a is String) {
    a -= 100;
  } else {
    a.__isub__(100);
  }
  show_vec(a);
  print("testing *");
  b = (v1 * v2);
  show_vec(b);
  print("testing *=");
  if (b is num || b is String) {
    b *= 10.0;
  } else {
    b.__imul__(10.0);
  }
  show_vec(b);
  if (b is num || b is String) {
    b *= v2;
  } else {
    b.__imul__(v2);
  }
  show_vec(b);
  print("testing setters");
  b.x = 1;
  b.y = 2;
  b.z = 3;
}

Friday, December 6, 2013

PythonJS Dart Backend


I have started working on a second backend for PythonJS that outputs Dart code. Dart is a new language by Google that is very similar to JavaScript, it includes all the things missing from JavaScript like: classes, static types, operator overloading, and a compiler that checks all your code. Using dart2js you can translate Dart code into JavaScript code so that it works in all web browsers.

One of the limitations of Dart is that it lacks multiple inheritance, [1], [2]. It features Mix-ins and Interfaces, but these can not fully capture all the power that proper multiple inheritance provides. Using PythonJS you can bypass this limitation of Dart and use multiple inheritance.

Multiple Inheritance

PythonJS implements multiple inheritance in Dart using: static class methods, stub-methods, and interfaces. The method body is placed inside static class methods. The stub-methods are real methods on the instance, and simply forward calls to the static class methods and pass this as the first argument. Sub-classes can extend a method of the parent, and still call the parent's method using the normal Python syntax: parent.some_method(self).

Python Input

class A:
 def foo(self):
  print 'foo'

class B:
 def bar(self):
  print 'bar'

class C( A, B ):
 def call_foo_bar(self):
  print 'call_foo_bar in subclass C'
  self.foo()
  self.bar()

 ## extend foo ##
 def foo(self):
  A.foo(self)
  print 'foo extended'

Dart Output

class A {
  foo() { return A.__foo(this); }
  static __foo(self) {
    print("foo");
  }
}

class B {
  bar() { return B.__bar(this); }
  static __bar(self) {
    print("bar");
  }
}

class C implements A, B {
  call_foo_bar() { return C.__call_foo_bar(this); }
  static __call_foo_bar(self) {
    print("call_foo_bar in subclass C");
    self.foo();
    self.bar();
  }

  foo() { return C.__foo(this); }
  static __foo(self) {
    A.__foo(self);
    print("foo extended");
  }

  bar() { return B.__bar(this); }
}

Monday, December 2, 2013

JavaScript Yield


Firefox has had support for the yield keyword for a long time already, but Google Chrome is only just recently supporting this features as an experimental option. Basically, this means if you want your website to work in most web browsers, you can forget about using yield and the beauty of generator functions for the next couple years, it is going to take awhile before the majority of users upgrade. It is time to give up on yield? There is one option...

PythonJS now supports generator functions that will work in all browsers by translating the generator into a class with state-machine at compile time. Using PythonJS to write generator functions also produces JavaScript that runs faster than hand-written JavaScript that uses the native yield keyword. This is likely because the native yield is still a rarely used feature, and JIT's have not tuned their performance for it. PythonJS translates generator functions into simple classes with a next method, which is very JIT friendly. The results below show native yield is more than 10 times slower than yield in PythonJS. I was unable to test native yield in Chrome, for some reason I could not get it to work even after switching on harmony.

The Fibonacci series computed 1,000 times to 1,000 places in Firefox28, Python2.7, PyPy2.2, and GoogleChrome. Lower times are better. The code used in this benchmark is below: