Basic support for manipulating array
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Mon, 24 Sep 2012 09:35:00 +0200
changeset 21d8807b6a636a
parent 20 0e7dd9e2e31e
child 22 b9318fe303cd
Basic support for manipulating array
src/main/java/org/apidesign/java4browser/ByteCodeToJavaScript.java
src/test/java/org/apidesign/java4browser/Array.java
src/test/java/org/apidesign/java4browser/ArrayTest.java
src/test/java/org/apidesign/java4browser/StaticMethodTest.java
     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              }