# HG changeset patch # User Jaroslav Tulach # Date 1348472100 -7200 # Node ID d8807b6a636afeecd9504af21a636a7771a421ea # Parent 0e7dd9e2e31e57ccb284cc0ce93a6b92c6865920 Basic support for manipulating array diff -r 0e7dd9e2e31e -r d8807b6a636a src/main/java/org/apidesign/java4browser/ByteCodeToJavaScript.java --- a/src/main/java/org/apidesign/java4browser/ByteCodeToJavaScript.java Fri Sep 21 10:14:25 2012 +0200 +++ b/src/main/java/org/apidesign/java4browser/ByteCodeToJavaScript.java Mon Sep 24 09:35:00 2012 +0200 @@ -19,6 +19,7 @@ import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; import java.util.Collection; import java.util.List; import static org.netbeans.modules.classfile.ByteCodes.*; @@ -26,6 +27,7 @@ import org.netbeans.modules.classfile.CPEntry; import org.netbeans.modules.classfile.CPFieldInfo; import org.netbeans.modules.classfile.CPMethodInfo; +import org.netbeans.modules.classfile.CPStringInfo; import org.netbeans.modules.classfile.ClassFile; import org.netbeans.modules.classfile.ClassName; import org.netbeans.modules.classfile.Code; @@ -71,9 +73,10 @@ ByteCodeToJavaScript compiler = new ByteCodeToJavaScript( jc, out, references ); + List toInitilize = new ArrayList(); for (Method m : jc.getMethods()) { if (m.isStatic()) { - compiler.generateStaticMethod(m); + compiler.generateStaticMethod(m, toInitilize); } else { compiler.generateInstanceMethod(m); } @@ -101,14 +104,21 @@ out.append("\n}"); ClassName sc = jc.getSuperClass(); if (sc != null) { - out.append("\n ").append(className) + out.append("\n").append(className) .append(".prototype = new ").append(sc.getInternalName().replace('/', '_')); } + for (String init : toInitilize) { + out.append("\n").append(init).append("();"); + } } - private void generateStaticMethod(Method m) throws IOException { + private void generateStaticMethod(Method m, List toInitilize) throws IOException { + final String mn = findMethodName(m); out.append("\nfunction ").append( jc.getName().getInternalName().replace('/', '_') - ).append('_').append(findMethodName(m)); + ).append('_').append(mn); + if (mn.equals("classV")) { + toInitilize.add(jc.getName().getInternalName().replace('/', '_') + '_' + mn); + } out.append('('); String space = ""; List args = m.getParameters(); @@ -131,9 +141,7 @@ out.append(" var "); out.append("arg").append(String.valueOf(i)).append(";\n"); } - out.append(" var stack = new Array("); - out.append(Integer.toString(code.getMaxStack())); - out.append(");\n"); + out.append(" var stack = new Array();\n"); produceCode(code.getByteCodes()); } else { out.append(" /* no code found for ").append(m.getTypeSignature()).append(" */\n"); @@ -361,9 +369,10 @@ out.append("stack.push(5);"); break; case bc_ldc: { - int indx = byteCodes[i++]; + int indx = byteCodes[++i]; CPEntry entry = jc.getConstantPool().get(indx); - out.append("stack.push(" + entry.getValue() + ");"); + String v = encodeConstant(entry); + out.append("stack.push(").append(v).append(");"); break; } case bc_ldc_w: @@ -371,7 +380,8 @@ int indx = readIntArg(byteCodes, i); CPEntry entry = jc.getConstantPool().get(indx); i += 2; - out.append("stack.push(" + entry.getValue() + ");"); + String v = encodeConstant(entry); + out.append("stack.push(").append(v).append(");"); break; } case bc_lcmp: @@ -483,6 +493,41 @@ i += 2; break; } + case bc_newarray: { + int type = byteCodes[i++]; + out.append("stack.push(new Array(stack.pop()));"); + break; + } + case bc_anewarray: { + i += 2; // skip type of array + out.append("stack.push(new Array(stack.pop()));"); + break; + } + case bc_arraylength: + out.append("stack.push(stack.pop().length);"); + break; + case bc_iastore: + case bc_lastore: + case bc_fastore: + case bc_dastore: + case bc_aastore: + case bc_bastore: + case bc_castore: + case bc_sastore: { + out.append("{ var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; }"); + break; + } + case bc_iaload: + case bc_laload: + case bc_faload: + case bc_daload: + case bc_aaload: + case bc_baload: + case bc_caload: + case bc_saload: { + out.append("{ var indx = stack.pop(); stack.push(stack.pop()[indx]); }"); + break; + } case bc_dup: out.append("stack.push(stack[stack.length - 1]);"); break; @@ -492,7 +537,7 @@ case bc_getfield: { int indx = readIntArg(byteCodes, i); CPFieldInfo fi = (CPFieldInfo) jc.getConstantPool().get(indx); - out.append(" stack.push(stack.pop().").append(fi.getFieldName()).append(");"); + out.append("stack.push(stack.pop().").append(fi.getFieldName()).append(");"); i += 2; break; } @@ -735,4 +780,14 @@ out.append(d); } } + + private String encodeConstant(CPEntry entry) { + final String v; + if (entry instanceof CPStringInfo) { + v = "\"" + entry.getValue().toString().replace("\"", "\\\"") + "\""; + } else { + v = entry.getValue().toString(); + } + return v; + } } diff -r 0e7dd9e2e31e -r d8807b6a636a src/test/java/org/apidesign/java4browser/Array.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/test/java/org/apidesign/java4browser/Array.java Mon Sep 24 09:35:00 2012 +0200 @@ -0,0 +1,76 @@ +/* +Java 4 Browser Bytecode Translator +Copyright (C) 2012-2012 Jaroslav Tulach + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. Look for COPYING file in the top folder. +If not, see http://opensource.org/licenses/GPL-2.0. +*/ +package org.apidesign.java4browser; + +/** + * + * @author Jaroslav Tulach + */ +public class Array { + byte[] bytes = { 1 }; + short[] shorts = { 2, 3 }; + int[] ints = { 4, 5, 6 }; + float[] floats = { 7, 8, 9, 10 }; + double[][] doubles = { {11}, {12}, {13}, {14}, {15} }; + char[] chars = { 'a', 'b' }; + + private Array() { + } + + byte bytes() { + return bytes[0]; + } + short shorts() { + return shorts[1]; + } + + int ints() { + return ints[2]; + } + + float floats() { + return floats[3]; + } + + double doubles() { + return doubles[4][0]; + } + + private static final Array[] ARR = { new Array(), new Array(), new Array() }; + + public static double sum() { + double sum = 0.0; + for (int i = 0; i < ARR.length; i++) { + sum += ARR[i].bytes(); + sum += ARR[i].shorts(); + sum += ARR[i].ints(); + sum += ARR[i].floats(); + sum += ARR[i].doubles(); + } + return sum; + } + public static int simple() { + int[] arr = { 0, 1, 2, 3, 4, 5 }; + + int sum = 0; + for (int i = 0; i < arr.length; i++) { + sum += arr[i]; + } + return sum; + } +} diff -r 0e7dd9e2e31e -r d8807b6a636a src/test/java/org/apidesign/java4browser/ArrayTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/test/java/org/apidesign/java4browser/ArrayTest.java Mon Sep 24 09:35:00 2012 +0200 @@ -0,0 +1,63 @@ +/* +Java 4 Browser Bytecode Translator +Copyright (C) 2012-2012 Jaroslav Tulach + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. Look for COPYING file in the top folder. +If not, see http://opensource.org/licenses/GPL-2.0. +*/ +package org.apidesign.java4browser; + +import javax.script.Invocable; +import javax.script.ScriptException; +import org.testng.annotations.Test; +import static org.testng.Assert.*; + +/** + * + * @author Jaroslav Tulach + */ +public class ArrayTest { + @Test public void verifySimpleIntOperation() throws Exception { + assertExec("CheckTheSum", "org_apidesign_java4browser_Array_simpleI", + Double.valueOf(15) + ); + } + @Test public void verifyOperationsOnArrays() throws Exception { + assertExec("The sum is 105", "org_apidesign_java4browser_Array_sumD", + Double.valueOf(105) + ); + } + + private static void assertExec(String msg, String methodName, Object expRes, Object... args) throws Exception { + StringBuilder sb = new StringBuilder(); + Invocable i = StaticMethodTest.compileClass(sb, + "org/apidesign/java4browser/Array" + ); + + Object ret = null; + try { + ret = i.invokeFunction(methodName, args); + } catch (ScriptException ex) { + fail("Execution failed in " + sb, ex); + } catch (NoSuchMethodException ex) { + fail("Cannot find method in " + sb, ex); + } + if (ret == null && expRes == null) { + return; + } + if (expRes.equals(ret)) { + return; + } + assertEquals(ret, expRes, msg + "was: " + ret + "\n" + sb); + } +} diff -r 0e7dd9e2e31e -r d8807b6a636a src/test/java/org/apidesign/java4browser/StaticMethodTest.java --- a/src/test/java/org/apidesign/java4browser/StaticMethodTest.java Fri Sep 21 10:14:25 2012 +0200 +++ b/src/test/java/org/apidesign/java4browser/StaticMethodTest.java Mon Sep 24 09:35:00 2012 +0200 @@ -182,7 +182,7 @@ int lastBlock = sb.lastIndexOf("{"); throw new IllegalStateException( "Error while compiling " + name + "\n" + - sb.substring(lastBlock + 1, sb.length()), + sb.substring(0, sb.length()), ex ); }