1.1 --- a/src/main/java/org/apidesign/java4browser/ByteCodeToJavaScript.java Fri Sep 21 10:14:25 2012 +0200
1.2 +++ b/src/main/java/org/apidesign/java4browser/ByteCodeToJavaScript.java Mon Sep 24 09:35:00 2012 +0200
1.3 @@ -19,6 +19,7 @@
1.4
1.5 import java.io.IOException;
1.6 import java.io.InputStream;
1.7 +import java.util.ArrayList;
1.8 import java.util.Collection;
1.9 import java.util.List;
1.10 import static org.netbeans.modules.classfile.ByteCodes.*;
1.11 @@ -26,6 +27,7 @@
1.12 import org.netbeans.modules.classfile.CPEntry;
1.13 import org.netbeans.modules.classfile.CPFieldInfo;
1.14 import org.netbeans.modules.classfile.CPMethodInfo;
1.15 +import org.netbeans.modules.classfile.CPStringInfo;
1.16 import org.netbeans.modules.classfile.ClassFile;
1.17 import org.netbeans.modules.classfile.ClassName;
1.18 import org.netbeans.modules.classfile.Code;
1.19 @@ -71,9 +73,10 @@
1.20 ByteCodeToJavaScript compiler = new ByteCodeToJavaScript(
1.21 jc, out, references
1.22 );
1.23 + List<String> toInitilize = new ArrayList<String>();
1.24 for (Method m : jc.getMethods()) {
1.25 if (m.isStatic()) {
1.26 - compiler.generateStaticMethod(m);
1.27 + compiler.generateStaticMethod(m, toInitilize);
1.28 } else {
1.29 compiler.generateInstanceMethod(m);
1.30 }
1.31 @@ -101,14 +104,21 @@
1.32 out.append("\n}");
1.33 ClassName sc = jc.getSuperClass();
1.34 if (sc != null) {
1.35 - out.append("\n ").append(className)
1.36 + out.append("\n").append(className)
1.37 .append(".prototype = new ").append(sc.getInternalName().replace('/', '_'));
1.38 }
1.39 + for (String init : toInitilize) {
1.40 + out.append("\n").append(init).append("();");
1.41 + }
1.42 }
1.43 - private void generateStaticMethod(Method m) throws IOException {
1.44 + private void generateStaticMethod(Method m, List<String> toInitilize) throws IOException {
1.45 + final String mn = findMethodName(m);
1.46 out.append("\nfunction ").append(
1.47 jc.getName().getInternalName().replace('/', '_')
1.48 - ).append('_').append(findMethodName(m));
1.49 + ).append('_').append(mn);
1.50 + if (mn.equals("classV")) {
1.51 + toInitilize.add(jc.getName().getInternalName().replace('/', '_') + '_' + mn);
1.52 + }
1.53 out.append('(');
1.54 String space = "";
1.55 List<Parameter> args = m.getParameters();
1.56 @@ -131,9 +141,7 @@
1.57 out.append(" var ");
1.58 out.append("arg").append(String.valueOf(i)).append(";\n");
1.59 }
1.60 - out.append(" var stack = new Array(");
1.61 - out.append(Integer.toString(code.getMaxStack()));
1.62 - out.append(");\n");
1.63 + out.append(" var stack = new Array();\n");
1.64 produceCode(code.getByteCodes());
1.65 } else {
1.66 out.append(" /* no code found for ").append(m.getTypeSignature()).append(" */\n");
1.67 @@ -361,9 +369,10 @@
1.68 out.append("stack.push(5);");
1.69 break;
1.70 case bc_ldc: {
1.71 - int indx = byteCodes[i++];
1.72 + int indx = byteCodes[++i];
1.73 CPEntry entry = jc.getConstantPool().get(indx);
1.74 - out.append("stack.push(" + entry.getValue() + ");");
1.75 + String v = encodeConstant(entry);
1.76 + out.append("stack.push(").append(v).append(");");
1.77 break;
1.78 }
1.79 case bc_ldc_w:
1.80 @@ -371,7 +380,8 @@
1.81 int indx = readIntArg(byteCodes, i);
1.82 CPEntry entry = jc.getConstantPool().get(indx);
1.83 i += 2;
1.84 - out.append("stack.push(" + entry.getValue() + ");");
1.85 + String v = encodeConstant(entry);
1.86 + out.append("stack.push(").append(v).append(");");
1.87 break;
1.88 }
1.89 case bc_lcmp:
1.90 @@ -483,6 +493,41 @@
1.91 i += 2;
1.92 break;
1.93 }
1.94 + case bc_newarray: {
1.95 + int type = byteCodes[i++];
1.96 + out.append("stack.push(new Array(stack.pop()));");
1.97 + break;
1.98 + }
1.99 + case bc_anewarray: {
1.100 + i += 2; // skip type of array
1.101 + out.append("stack.push(new Array(stack.pop()));");
1.102 + break;
1.103 + }
1.104 + case bc_arraylength:
1.105 + out.append("stack.push(stack.pop().length);");
1.106 + break;
1.107 + case bc_iastore:
1.108 + case bc_lastore:
1.109 + case bc_fastore:
1.110 + case bc_dastore:
1.111 + case bc_aastore:
1.112 + case bc_bastore:
1.113 + case bc_castore:
1.114 + case bc_sastore: {
1.115 + out.append("{ var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; }");
1.116 + break;
1.117 + }
1.118 + case bc_iaload:
1.119 + case bc_laload:
1.120 + case bc_faload:
1.121 + case bc_daload:
1.122 + case bc_aaload:
1.123 + case bc_baload:
1.124 + case bc_caload:
1.125 + case bc_saload: {
1.126 + out.append("{ var indx = stack.pop(); stack.push(stack.pop()[indx]); }");
1.127 + break;
1.128 + }
1.129 case bc_dup:
1.130 out.append("stack.push(stack[stack.length - 1]);");
1.131 break;
1.132 @@ -492,7 +537,7 @@
1.133 case bc_getfield: {
1.134 int indx = readIntArg(byteCodes, i);
1.135 CPFieldInfo fi = (CPFieldInfo) jc.getConstantPool().get(indx);
1.136 - out.append(" stack.push(stack.pop().").append(fi.getFieldName()).append(");");
1.137 + out.append("stack.push(stack.pop().").append(fi.getFieldName()).append(");");
1.138 i += 2;
1.139 break;
1.140 }
1.141 @@ -735,4 +780,14 @@
1.142 out.append(d);
1.143 }
1.144 }
1.145 +
1.146 + private String encodeConstant(CPEntry entry) {
1.147 + final String v;
1.148 + if (entry instanceof CPStringInfo) {
1.149 + v = "\"" + entry.getValue().toString().replace("\"", "\\\"") + "\"";
1.150 + } else {
1.151 + v = entry.getValue().toString();
1.152 + }
1.153 + return v;
1.154 + }
1.155 }
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/src/test/java/org/apidesign/java4browser/Array.java Mon Sep 24 09:35:00 2012 +0200
2.3 @@ -0,0 +1,76 @@
2.4 +/*
2.5 +Java 4 Browser Bytecode Translator
2.6 +Copyright (C) 2012-2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
2.7 +
2.8 +This program is free software: you can redistribute it and/or modify
2.9 +it under the terms of the GNU General Public License as published by
2.10 +the Free Software Foundation, version 2 of the License.
2.11 +
2.12 +This program is distributed in the hope that it will be useful,
2.13 +but WITHOUT ANY WARRANTY; without even the implied warranty of
2.14 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2.15 +GNU General Public License for more details.
2.16 +
2.17 +You should have received a copy of the GNU General Public License
2.18 +along with this program. Look for COPYING file in the top folder.
2.19 +If not, see http://opensource.org/licenses/GPL-2.0.
2.20 +*/
2.21 +package org.apidesign.java4browser;
2.22 +
2.23 +/**
2.24 + *
2.25 + * @author Jaroslav Tulach <jtulach@netbeans.org>
2.26 + */
2.27 +public class Array {
2.28 + byte[] bytes = { 1 };
2.29 + short[] shorts = { 2, 3 };
2.30 + int[] ints = { 4, 5, 6 };
2.31 + float[] floats = { 7, 8, 9, 10 };
2.32 + double[][] doubles = { {11}, {12}, {13}, {14}, {15} };
2.33 + char[] chars = { 'a', 'b' };
2.34 +
2.35 + private Array() {
2.36 + }
2.37 +
2.38 + byte bytes() {
2.39 + return bytes[0];
2.40 + }
2.41 + short shorts() {
2.42 + return shorts[1];
2.43 + }
2.44 +
2.45 + int ints() {
2.46 + return ints[2];
2.47 + }
2.48 +
2.49 + float floats() {
2.50 + return floats[3];
2.51 + }
2.52 +
2.53 + double doubles() {
2.54 + return doubles[4][0];
2.55 + }
2.56 +
2.57 + private static final Array[] ARR = { new Array(), new Array(), new Array() };
2.58 +
2.59 + public static double sum() {
2.60 + double sum = 0.0;
2.61 + for (int i = 0; i < ARR.length; i++) {
2.62 + sum += ARR[i].bytes();
2.63 + sum += ARR[i].shorts();
2.64 + sum += ARR[i].ints();
2.65 + sum += ARR[i].floats();
2.66 + sum += ARR[i].doubles();
2.67 + }
2.68 + return sum;
2.69 + }
2.70 + public static int simple() {
2.71 + int[] arr = { 0, 1, 2, 3, 4, 5 };
2.72 +
2.73 + int sum = 0;
2.74 + for (int i = 0; i < arr.length; i++) {
2.75 + sum += arr[i];
2.76 + }
2.77 + return sum;
2.78 + }
2.79 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/src/test/java/org/apidesign/java4browser/ArrayTest.java Mon Sep 24 09:35:00 2012 +0200
3.3 @@ -0,0 +1,63 @@
3.4 +/*
3.5 +Java 4 Browser Bytecode Translator
3.6 +Copyright (C) 2012-2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
3.7 +
3.8 +This program is free software: you can redistribute it and/or modify
3.9 +it under the terms of the GNU General Public License as published by
3.10 +the Free Software Foundation, version 2 of the License.
3.11 +
3.12 +This program is distributed in the hope that it will be useful,
3.13 +but WITHOUT ANY WARRANTY; without even the implied warranty of
3.14 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3.15 +GNU General Public License for more details.
3.16 +
3.17 +You should have received a copy of the GNU General Public License
3.18 +along with this program. Look for COPYING file in the top folder.
3.19 +If not, see http://opensource.org/licenses/GPL-2.0.
3.20 +*/
3.21 +package org.apidesign.java4browser;
3.22 +
3.23 +import javax.script.Invocable;
3.24 +import javax.script.ScriptException;
3.25 +import org.testng.annotations.Test;
3.26 +import static org.testng.Assert.*;
3.27 +
3.28 +/**
3.29 + *
3.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
3.31 + */
3.32 +public class ArrayTest {
3.33 + @Test public void verifySimpleIntOperation() throws Exception {
3.34 + assertExec("CheckTheSum", "org_apidesign_java4browser_Array_simpleI",
3.35 + Double.valueOf(15)
3.36 + );
3.37 + }
3.38 + @Test public void verifyOperationsOnArrays() throws Exception {
3.39 + assertExec("The sum is 105", "org_apidesign_java4browser_Array_sumD",
3.40 + Double.valueOf(105)
3.41 + );
3.42 + }
3.43 +
3.44 + private static void assertExec(String msg, String methodName, Object expRes, Object... args) throws Exception {
3.45 + StringBuilder sb = new StringBuilder();
3.46 + Invocable i = StaticMethodTest.compileClass(sb,
3.47 + "org/apidesign/java4browser/Array"
3.48 + );
3.49 +
3.50 + Object ret = null;
3.51 + try {
3.52 + ret = i.invokeFunction(methodName, args);
3.53 + } catch (ScriptException ex) {
3.54 + fail("Execution failed in " + sb, ex);
3.55 + } catch (NoSuchMethodException ex) {
3.56 + fail("Cannot find method in " + sb, ex);
3.57 + }
3.58 + if (ret == null && expRes == null) {
3.59 + return;
3.60 + }
3.61 + if (expRes.equals(ret)) {
3.62 + return;
3.63 + }
3.64 + assertEquals(ret, expRes, msg + "was: " + ret + "\n" + sb);
3.65 + }
3.66 +}
4.1 --- a/src/test/java/org/apidesign/java4browser/StaticMethodTest.java Fri Sep 21 10:14:25 2012 +0200
4.2 +++ b/src/test/java/org/apidesign/java4browser/StaticMethodTest.java Mon Sep 24 09:35:00 2012 +0200
4.3 @@ -182,7 +182,7 @@
4.4 int lastBlock = sb.lastIndexOf("{");
4.5 throw new IllegalStateException(
4.6 "Error while compiling " + name + "\n" +
4.7 - sb.substring(lastBlock + 1, sb.length()),
4.8 + sb.substring(0, sb.length()),
4.9 ex
4.10 );
4.11 }