Skip to content

Commit

Permalink
progress
Browse files Browse the repository at this point in the history
  • Loading branch information
Jonathan Feinberg committed Jul 28, 2010
1 parent 3e7ad24 commit 6cf1f6a
Show file tree
Hide file tree
Showing 9 changed files with 355 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .classpath
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="generated"/>
<classpathentry kind="src" path="buildtime"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry combineaccessrules="false" kind="src" path="/processing-core"/>
<classpathentry kind="lib" path="C:/jython2.5.2b1core/jython.jar" sourcepath="C:/jython2.5.2b1src/src"/>
Expand Down
20 changes: 20 additions & 0 deletions buildtime/jycessing/build/Binding.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package jycessing.build;

public class Binding {
private final String localsName;
private final String name;

public Binding(final String localsName, final String name) {
this.name = name;
this.localsName = localsName;
}

public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append(localsName).append(".__setitem__(\"").append(name).append(
"\", new PyObject() {\n");

sb.append("});\n");
return sb.toString();
}
}
6 changes: 6 additions & 0 deletions buildtime/jycessing/build/GenerateDriver.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package jycessing.build;


public class GenerateDriver {

}
124 changes: 124 additions & 0 deletions buildtime/jycessing/build/PolymorphicMethod.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package jycessing.build;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import processing.core.PApplet;

public class PolymorphicMethod {
private final String name;
private final int arity;
private final List<Signature> signatures = new ArrayList<Signature>();

public PolymorphicMethod(final String name, final int arity) {
this.name = name;
this.arity = arity;
}

public void add(final Method method) {
if (method.getParameterTypes().length != arity) {
throw new IllegalArgumentException("I expect methods with " + arity
+ " args, but got " + method);
}
signatures.add(new Signature(method));
}

public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("public PyObject __call__(");
for (int i = 0; i < arity; i++) {
if (i > 0) {
sb.append(", ");
}
sb.append("final PyObject arg").append(i);
}
sb.append(") {\n");
if (signatures.size() == 1) {
sb.append("\t");
append(signatures.get(0), sb);
} else {
for (int i = 0; i < arity; i++) {
sb.append(String.format("\tfinal PyType t%d = arg%d.getType();\n", i, i));
}
for (int i = 0; i < signatures.size(); i++) {
final Signature sig = signatures.get(i);
if (i > 0) {
sb.append(" else ");
} else {
sb.append('\t');
}
sb.append("if (");
for (int j = 0; j < arity; j++) {
if (j > 0) {
sb.append(" && ");
}
sb.append(sig.getTypecheckExpression(j, "t" + j));
}
sb.append(") {\n\t\t");
append(sig, sb);
sb.append("\n\t}");
}
sb
.append(" else { throw new IllegalArgumentException(\"Couldn't figure out which \\\"");
sb.append(name);
sb.append("\\\" to call.\"); }");
}
sb.append("\n};\n");
return sb.toString();
}

private void append(final Signature signature, final StringBuilder sb) {
if (!signature.isVoid()) {
sb.append("return ").append(TypeUtil.pyConversionPrefix(signature.getReturnType()));
}
sb.append(name).append('(');
for (int i = 0; i < arity; i++) {
if (i > 0) {
sb.append(", ");
}
sb.append(TypeUtil.asJavaExpression("arg" + i, signature.getArgTypes().get(i)));
}
sb.append(')');
if (signature.isVoid()) {
sb.append(";\n");
sb.append("\t\treturn Py.None;");
} else {
sb.append(");");
}
}

public static void main(final String[] args) {
Map<String, ArrayList<PolymorphicMethod>> methods = new HashMap<String, ArrayList<PolymorphicMethod>>();

for (final Method m : PApplet.class.getDeclaredMethods()) {
final String name = m.getName();
if (!methods.containsKey(name)) {
methods.put(name, new ArrayList<PolymorphicMethod>());
}
final ArrayList<PolymorphicMethod> pms = methods.get(name);
final int arity = m.getParameterTypes().length;
if (pms.size() < arity + 1) {
for (int i = pms.size(); i < arity + 1; i++) {
pms.add(null);
}
}
if (pms.get(arity) == null) {
pms.set(arity, new PolymorphicMethod(name, arity));
}
final PolymorphicMethod pm = pms.get(arity);
pm.add(m);
}
for (final Entry<String, ArrayList<PolymorphicMethod>> e : methods.entrySet()) {
System.out.println("---------------" + e.getKey());
for (final PolymorphicMethod m : e.getValue()) {
if (m != null) {
System.out.println(m);
}
}
}
}
}
46 changes: 46 additions & 0 deletions buildtime/jycessing/build/Signature.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package jycessing.build;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;

public class Signature {
private final List<Class<?>> argTypes;
private final Class<?> returnType;

public Signature(final Method method) {
argTypes = Arrays.asList(method.getParameterTypes());
returnType = method.getReturnType();
}

public boolean isVoid() {
return returnType == Void.TYPE;
}

public String getTypecheckExpression(final int i, final String name) {
final Class<?> k = argTypes.get(i);
if (k == float.class) {
return String.format("%s == PyFloat.TYPE", name);
} else if (k == int.class) {
return String.format("%s == PyInteger.TYPE", name);
} else if (k == boolean.class) {
return String.format("%s == PyBoolean.TYPE", name);
} else if (k == String.class || k == char.class) {
return String.format("%s == PyString.TYPE", name);
} else if (k.isPrimitive()) {
throw new RuntimeException("You need a converter for " + k);
} else {
return String.format("%s.getProxyType() != null && %s.getProxyType() == %s.class",
name, name, k.getSimpleName());
}
}

public List<Class<?>> getArgTypes() {
return argTypes;
}

public Class<?> getReturnType() {
return returnType;
}

}
44 changes: 44 additions & 0 deletions buildtime/jycessing/build/TypeUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package jycessing.build;

public class TypeUtil {
public static String asJavaExpression(final String name, final Class<?> javaType) {
final StringBuilder sb = new StringBuilder();
if (javaType == float.class) {
sb.append("(float)").append(name).append(".asDouble()");
} else if (javaType == int.class) {
sb.append(name).append(".asInt()");
} else if (javaType == String.class) {
sb.append(name).append(".asString()");
} else if (javaType == char.class) {
sb.append(name).append(".asString().charAt(0)");
} else if (javaType == long.class) {
sb.append(name).append(".asLong()");
} else if (javaType == boolean.class) {
sb.append(name).append(".__nonzero__()");
} else if (javaType.isPrimitive()) {
throw new RuntimeException("You need a converter for " + javaType);
} else {
final String simpleName = javaType.isArray() ? javaType.getSimpleName() : javaType
.getName();
sb.append('(').append(simpleName).append(')').append(name).append(".__tojava__(")
.append(simpleName).append(".class)");
}
return sb.toString();
}

public static String pyConversionPrefix(final Class<?> javaType) {
if (javaType == float.class) {
return "new PyFloat(";
} else if (javaType == int.class) {
return "new PyInteger(";
} else if (javaType == String.class) {
return "new PyString(";
} else if (javaType == boolean.class) {
return "new PyBoolean(";
} else if (javaType.isPrimitive()) {
throw new RuntimeException("You need a converter for " + javaType);
} else {
return "Py.java2py(";
}
}
}
44 changes: 44 additions & 0 deletions src/jycessing/Bench.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package jycessing;

import java.lang.reflect.Method;

public class Bench {
long c;

public long meth(final long arg) {
return c += arg;
}

static long time(final Runnable b, final int iters) {
final long start = System.currentTimeMillis();
for (int i = 0; i < iters; i++) {
b.run();
}
return System.currentTimeMillis() - start;
}

public static void main(final String[] args) throws Exception {
final Method meth = Bench.class.getMethod("meth", long.class);
final Bench bench = new Bench();
final long directTime = time(new Runnable() {
@Override
public void run() {
bench.meth(System.currentTimeMillis());
}
}, 1000000);
System.out.println(bench.c);
System.out.println("direct: " + directTime + "ms");
final long dynamicTime = time(new Runnable() {
@Override
public void run() {
try {
meth.invoke(bench, System.currentTimeMillis());
} catch (Exception e) {
e.printStackTrace();
}
}
}, 1000000);
System.out.println(bench.c);
System.out.println("dynamic: " + dynamicTime + "ms");
}
}
14 changes: 14 additions & 0 deletions src/jycessing/PAppletJythonDriver.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import processing.core.PApplet;
import processing.core.PFont;
import processing.core.PImage;
import processing.core.PMatrix;

@SuppressWarnings("serial")
public class PAppletJythonDriver extends PApplet {
Expand All @@ -32,6 +33,7 @@ public PyObject __call__(final PyObject a, final PyObject b, final PyObject c) {
return Py.None;
}
});

locals.__setitem__("fill", new PyObject() {
public PyObject __call__(final PyObject arg) {
final PyType t = arg.getType();
Expand Down Expand Up @@ -215,9 +217,21 @@ public PyObject __call__(final PyObject which, final PyObject size) {
});
locals.__setitem__("loadFont", new PyObject() {
public PyObject __call__(final PyObject filename) {
System.err.println("loadFont type: " + filename.getType().getProxyType());
return Py.java2py(loadFont(filename.asString()));
}
});
locals.__setitem__("getMatrix", new PyObject() {
public PyObject __call__() {
return Py.java2py(getMatrix());
}
});
locals.__setitem__("applyMatrix", new PyObject() {
public PyObject __call__(final PyObject m) {
applyMatrix((PMatrix)m.__tojava__(PMatrix.class));
return Py.None;
}
});
}

public static void initializeStatics(final PyStringMap locals) {
Expand Down
55 changes: 55 additions & 0 deletions template/PAppletJythonDriver.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package jycessing;

import org.python.core.Py;
import org.python.core.PyException;
import org.python.core.PyFloat;
import org.python.core.PyInteger;
import org.python.core.PyJavaType;
import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.core.PyStringMap;
import org.python.core.PyType;

import processing.core.PApplet;
import processing.core.PFont;
import processing.core.PImage;

@SuppressWarnings("serial")
public class PAppletJythonDriver extends PApplet {

final PyObject setup;
final PyObject draw;

public PAppletJythonDriver(final PyStringMap locals) {
setup = locals.__finditem__("setup");
draw = locals.__finditem__("draw");

// BEGIN GENERATED CODE
// END GENERATED CODE
}

@Override
public void setup() {
if (setup != null) {
try {
setup.__call__();
} catch (PyException e) {
if (e.getCause() instanceof RendererChangeException) {
throw (RendererChangeException)e.getCause();
} else {
throw e;
}
}
}
}

@Override
public void draw() {
if (draw == null) {
super.draw();
} else {
draw.__call__();
}
}

}

0 comments on commit 6cf1f6a

Please sign in to comment.