-
Notifications
You must be signed in to change notification settings - Fork 222
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Jonathan Feinberg
committed
Jul 28, 2010
1 parent
3e7ad24
commit 6cf1f6a
Showing
9 changed files
with
355 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package jycessing.build; | ||
|
||
|
||
public class GenerateDriver { | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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("; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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__(); | ||
} | ||
} | ||
|
||
} |