Support for factorial computed with a for cycle
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Mon, 27 Aug 2012 14:27:06 +0200
changeset 5d3193a7086e7
parent 4 f352a33fb71b
child 6 6e4682985907
Support for factorial computed with a for cycle
.hgignore
src/main/java/org/apidesign/java4browser/ByteCodeToJavaScript.java
src/test/java/org/apidesign/java4browser/StaticMethod.java
src/test/java/org/apidesign/java4browser/StaticMethodTest.java
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/.hgignore	Mon Aug 27 14:27:06 2012 +0200
     1.3 @@ -0,0 +1,1 @@
     1.4 +^target/.*
     2.1 --- a/src/main/java/org/apidesign/java4browser/ByteCodeToJavaScript.java	Mon Aug 27 13:16:29 2012 +0200
     2.2 +++ b/src/main/java/org/apidesign/java4browser/ByteCodeToJavaScript.java	Mon Aug 27 14:27:06 2012 +0200
     2.3 @@ -79,14 +79,12 @@
     2.4                  index++;
     2.5              }
     2.6          }
     2.7 -        out.append(") {").append("\n  var ");
     2.8 +        out.append(") {").append("\n");
     2.9          final Code code = m.getCode();
    2.10          int len = code.getMaxLocals();
    2.11 -        space = "";
    2.12 -        for (int i = 0; i < len; i++) {
    2.13 -            out.append(space);
    2.14 -            out.append("var").append(String.valueOf(i));
    2.15 -            space = ",";
    2.16 +        for (int index = args.size(), i = args.size(); i < len; i++) {
    2.17 +            out.append("  var ");
    2.18 +            out.append("arg").append(String.valueOf(i)).append(";\n");
    2.19          }
    2.20          out.append(";\n  var stack = new Array(");
    2.21          out.append(Integer.toString(code.getMaxStack()));
    2.22 @@ -139,6 +137,30 @@
    2.23                      out.append("stack.push(arg").append(indx + ");");
    2.24                      break;
    2.25                  }
    2.26 +                case bc_istore_0:
    2.27 +                case bc_lstore_0:
    2.28 +                case bc_fstore_0:
    2.29 +                case bc_dstore_0:
    2.30 +                    out.append("arg0 = stack.pop();");
    2.31 +                    break;
    2.32 +                case bc_istore_1:
    2.33 +                case bc_lstore_1:
    2.34 +                case bc_fstore_1:
    2.35 +                case bc_dstore_1:
    2.36 +                    out.append("arg1 = stack.pop();");
    2.37 +                    break;
    2.38 +                case bc_istore_2:
    2.39 +                case bc_lstore_2:
    2.40 +                case bc_fstore_2:
    2.41 +                case bc_dstore_2:
    2.42 +                    out.append("arg2 = stack.pop();");
    2.43 +                    break;
    2.44 +                case bc_istore_3:
    2.45 +                case bc_lstore_3:
    2.46 +                case bc_fstore_3:
    2.47 +                case bc_dstore_3:
    2.48 +                    out.append("arg3 = stack.pop();");
    2.49 +                    break;
    2.50                  case bc_iadd:
    2.51                  case bc_ladd:
    2.52                  case bc_fadd:
    2.53 @@ -165,6 +187,16 @@
    2.54                  case bc_ddiv:
    2.55                      out.append("{ var tmp = stack.pop(); stack.push(stack.pop() / tmp); }");
    2.56                      break;
    2.57 +                case bc_iinc: {
    2.58 +                    final int varIndx = (byteCodes[++i] + 256) % 256;
    2.59 +                    final int incrBy = (byteCodes[++i] + 256) % 256;
    2.60 +                    if (incrBy == 1) {
    2.61 +                        out.append("arg" + varIndx).append("++;");
    2.62 +                    } else {
    2.63 +                        out.append("arg" + varIndx).append(" += " + incrBy).append(";");
    2.64 +                    }
    2.65 +                    break;
    2.66 +                }
    2.67                  case bc_ireturn:
    2.68                  case bc_lreturn:
    2.69                  case bc_freturn:
    2.70 @@ -237,6 +269,12 @@
    2.71                  case bc_if_icmpge:
    2.72                      i = generateIf(byteCodes, i, "<=");
    2.73                      break;
    2.74 +                case bc_goto: {
    2.75 +                    int indx = i + readIntArg(byteCodes, i);
    2.76 +                    out.append("gt = " + indx).append("; continue;");
    2.77 +                    i += 2;
    2.78 +                    break;
    2.79 +                }
    2.80                  case bc_invokestatic: {
    2.81                      int methodIndex = readIntArg(byteCodes, i);
    2.82                      CPMethodInfo mi = (CPMethodInfo) jc.getConstantPool().get(methodIndex);
    2.83 @@ -286,9 +324,9 @@
    2.84      }
    2.85  
    2.86      private int readIntArg(byte[] byteCodes, int offsetInstruction) {
    2.87 -        final int indxHi = (byteCodes[offsetInstruction + 1] + 256) % 256;
    2.88 -        final int indxLo = (byteCodes[offsetInstruction + 2] + 256) % 256;
    2.89 -        return (indxHi << 16) + indxLo;
    2.90 +        final int indxHi = byteCodes[offsetInstruction + 1] << 8;
    2.91 +        final int indxLo = byteCodes[offsetInstruction + 2];
    2.92 +        return (indxHi & 0xffffff00) | (indxLo & 0xff);
    2.93      }
    2.94      
    2.95      private static int countArgs(String descriptor, boolean[] hasReturnType, StringBuilder sig) {
     3.1 --- a/src/test/java/org/apidesign/java4browser/StaticMethod.java	Mon Aug 27 13:16:29 2012 +0200
     3.2 +++ b/src/test/java/org/apidesign/java4browser/StaticMethod.java	Mon Aug 27 14:27:06 2012 +0200
     3.3 @@ -44,4 +44,11 @@
     3.4              return n * factRec(n - 1);
     3.5          }
     3.6      }
     3.7 +    public static long factIter(int n) {
     3.8 +        long res = 1;
     3.9 +        for (int i = 2; i <= n; i++) {
    3.10 +            res *= i;
    3.11 +        }
    3.12 +        return res;
    3.13 +    }
    3.14  }
     4.1 --- a/src/test/java/org/apidesign/java4browser/StaticMethodTest.java	Mon Aug 27 13:16:29 2012 +0200
     4.2 +++ b/src/test/java/org/apidesign/java4browser/StaticMethodTest.java	Mon Aug 27 14:27:06 2012 +0200
     4.3 @@ -82,6 +82,14 @@
     4.4              5
     4.5          );
     4.6      }
     4.7 +    @Test public void factIter() throws Exception {
     4.8 +        assertExec(
     4.9 +            "Factorial of 5 is 120",
    4.10 +            "org_apidesign_java4browser_StaticMethod_factIterJI", 
    4.11 +            Double.valueOf(120),
    4.12 +            5
    4.13 +        );
    4.14 +    }
    4.15      
    4.16      private static void assertExec(String msg, String methodName, Object expRes, Object... args) throws Exception {
    4.17          StringBuilder sb = new StringBuilder();
    4.18 @@ -90,6 +98,8 @@
    4.19          Object ret = null;
    4.20          try {
    4.21              ret = i.invokeFunction(methodName, args);
    4.22 +        } catch (ScriptException ex) {
    4.23 +            fail("Execution failed in " + sb, ex);
    4.24          } catch (NoSuchMethodException ex) {
    4.25              fail("Cannot find method in " + sb, ex);
    4.26          }