Concatenation of string and integer works emul
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Tue, 09 Oct 2012 11:11:58 -0700
branchemul
changeset 9419497b4312bb
parent 93 a236a9f137ac
child 95 66415b4fad21
Concatenation of string and integer works
core/src/main/java/org/apidesign/bck2brwsr/core/JavaScriptBody.java
emul/src/main/java/java/lang/AbstractStringBuilder.java
vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java
vm/src/test/java/org/apidesign/vm4brwsr/StaticMethod.java
vm/src/test/java/org/apidesign/vm4brwsr/StaticMethodTest.java
vm/src/test/java/org/apidesign/vm4brwsr/StringTest.java
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/core/src/main/java/org/apidesign/bck2brwsr/core/JavaScriptBody.java	Tue Oct 09 11:11:58 2012 -0700
     1.3 @@ -0,0 +1,38 @@
     1.4 +/*
     1.5 + * To change this template, choose Tools | Templates
     1.6 + * and open the template in the editor.
     1.7 + */
     1.8 +package org.apidesign.bck2brwsr.core;
     1.9 +
    1.10 +import java.lang.annotation.ElementType;
    1.11 +import java.lang.annotation.Retention;
    1.12 +import java.lang.annotation.RetentionPolicy;
    1.13 +import java.lang.annotation.Target;
    1.14 +
    1.15 +/** Put this method on a method in case it should have a special
    1.16 + * body in the <em>JavaScript</em>.
    1.17 + *
    1.18 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    1.19 + */
    1.20 +@Retention(RetentionPolicy.CLASS)
    1.21 +@Target({ ElementType.METHOD, ElementType.CONSTRUCTOR })
    1.22 +public @interface JavaScriptBody {
    1.23 +    /** Names of parameters for the method. 
    1.24 +     * 
    1.25 +     * <!--
    1.26 +     * If not specified
    1.27 +     * it will be <code>arg0, arg1, arg2</code>. In case of
    1.28 +     * instance methods, the <code>arg0</code> is reference
    1.29 +     * to <code>this</code>.
    1.30 +     * -->
    1.31 +     * 
    1.32 +     * @return array of the names of parameters for the method
    1.33 +     *    in JavaScript
    1.34 +     */
    1.35 +    public String[] args();
    1.36 +    
    1.37 +    /** The actual body of the method in JavaScript. This string will be
    1.38 +     * put into generated header (ends with '{') and footer (ends with '}').
    1.39 +     */
    1.40 +    public String body();
    1.41 +}
     2.1 --- a/emul/src/main/java/java/lang/AbstractStringBuilder.java	Mon Oct 08 17:10:27 2012 -0700
     2.2 +++ b/emul/src/main/java/java/lang/AbstractStringBuilder.java	Tue Oct 09 11:11:58 2012 -0700
     2.3 @@ -25,6 +25,8 @@
     2.4  
     2.5  package java.lang;
     2.6  
     2.7 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
     2.8 +
     2.9  /**
    2.10   * A mutable sequence of characters.
    2.11   * <p>
    2.12 @@ -598,6 +600,10 @@
    2.13       * @param   i   an {@code int}.
    2.14       * @return  a reference to this object.
    2.15       */
    2.16 +    @JavaScriptBody(
    2.17 +        args={ "self", "i" },
    2.18 +        body="return java_lang_AbstractStringBuilder_appendLjava_lang_AbstractStringBuilderLjava_lang_String(self,i.toString());"
    2.19 +    )
    2.20      public AbstractStringBuilder append(int i) {
    2.21          if (i == Integer.MIN_VALUE) {
    2.22              append("-2147483648");
     3.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Mon Oct 08 17:10:27 2012 -0700
     3.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Tue Oct 09 11:11:58 2012 -0700
     3.3 @@ -23,8 +23,10 @@
     3.4  import java.util.Collection;
     3.5  import java.util.List;
     3.6  import org.apidesign.bck2brwsr.core.ExtraJavaScript;
     3.7 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
     3.8  import org.netbeans.modules.classfile.Annotation;
     3.9  import org.netbeans.modules.classfile.AnnotationComponent;
    3.10 +import org.netbeans.modules.classfile.ArrayElementValue;
    3.11  import static org.netbeans.modules.classfile.ByteCodes.*;
    3.12  import org.netbeans.modules.classfile.CPClassInfo;
    3.13  import org.netbeans.modules.classfile.CPEntry;
    3.14 @@ -135,6 +137,9 @@
    3.15          }
    3.16      }
    3.17      private void generateStaticMethod(Method m, List<String> toInitilize) throws IOException {
    3.18 +        if (javaScriptBody(m, true)) {
    3.19 +            return;
    3.20 +        }
    3.21          final String mn = findMethodName(m);
    3.22          out.append("\nfunction ").append(
    3.23              jc.getName().getInternalName().replace('/', '_')
    3.24 @@ -180,6 +185,9 @@
    3.25      }
    3.26      
    3.27      private void generateInstanceMethod(Method m) throws IOException {
    3.28 +        if (javaScriptBody(m, false)) {
    3.29 +            return;
    3.30 +        }
    3.31          out.append("\nfunction ").append(
    3.32              jc.getName().getInternalName().replace('/', '_')
    3.33          ).append('_').append(findMethodName(m));
    3.34 @@ -900,4 +908,45 @@
    3.35      private String findDescriptor(String d) {
    3.36          return d.replace('[', 'A');
    3.37      }
    3.38 +
    3.39 +    private boolean javaScriptBody(Method m, boolean isStatic) throws IOException {
    3.40 +        final ClassName extraAnn = ClassName.getClassName(JavaScriptBody.class.getName().replace('.', '/'));
    3.41 +        Annotation a = m.getAnnotation(extraAnn);
    3.42 +        if (a != null) {
    3.43 +            final ElementValue annVal = a.getComponent("body").getValue();
    3.44 +            String body = ((PrimitiveElementValue) annVal).getValue().getValue().toString();
    3.45 +            
    3.46 +            final ArrayElementValue arrVal = (ArrayElementValue) a.getComponent("args").getValue();
    3.47 +            final int len = arrVal.getValues().length;
    3.48 +            String[] names = new String[len];
    3.49 +            for (int i = 0; i < len; i++) {
    3.50 +                names[i] = ((PrimitiveElementValue) arrVal.getValues()[i]).getValue().getValue().toString();
    3.51 +            }
    3.52 +            out.append("\nfunction ").append(
    3.53 +                jc.getName().getInternalName().replace('/', '_')).append('_').append(findMethodName(m));
    3.54 +            out.append("(");
    3.55 +            String space;
    3.56 +            int index;
    3.57 +            if (!isStatic) {                
    3.58 +                out.append(names[0]);
    3.59 +                space = ",";
    3.60 +                index = 1;
    3.61 +            } else {
    3.62 +                space = "";
    3.63 +                index = 0;
    3.64 +            }
    3.65 +            List<Parameter> args = m.getParameters();
    3.66 +            for (int i = 0; i < args.size(); i++) {
    3.67 +                out.append(space);
    3.68 +                out.append(names[index]);
    3.69 +                final String desc = findDescriptor(args.get(i).getDescriptor());
    3.70 +                index++;
    3.71 +            }
    3.72 +            out.append(") {").append("\n");
    3.73 +            out.append(body);
    3.74 +            out.append("\n}\n");
    3.75 +            return true;
    3.76 +        }
    3.77 +        return false;
    3.78 +    }
    3.79  }
     4.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethod.java	Mon Oct 08 17:10:27 2012 -0700
     4.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethod.java	Tue Oct 09 11:11:58 2012 -0700
     4.3 @@ -17,6 +17,8 @@
     4.4  */
     4.5  package org.apidesign.vm4brwsr;
     4.6  
     4.7 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
     4.8 +
     4.9  /**
    4.10   *
    4.11   * @author Jaroslav Tulach <jtulach@netbeans.org>
    4.12 @@ -91,4 +93,11 @@
    4.13          cnt++;
    4.14          return cnt;
    4.15      }
    4.16 +    
    4.17 +    @JavaScriptBody(
    4.18 +        args="i", body="return i.toString();"
    4.19 +    )
    4.20 +    public static String i2s(int i) {
    4.21 +        throw new IllegalStateException();
    4.22 +    }
    4.23  }
     5.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethodTest.java	Mon Oct 08 17:10:27 2012 -0700
     5.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethodTest.java	Tue Oct 09 11:11:58 2012 -0700
     5.3 @@ -184,6 +184,15 @@
     5.4          );
     5.5      }
     5.6      
     5.7 +    @Test public void javaScriptBody() throws Exception {
     5.8 +        assertExec(
     5.9 +            "JavaScript string",
    5.10 +            "org_apidesign_vm4brwsr_StaticMethod_i2sLjava_lang_StringI",
    5.11 +            "333",
    5.12 +            333
    5.13 +        );
    5.14 +    }
    5.15 +    
    5.16      private static void assertExec(String msg, String methodName, Object expRes, Object... args) throws Exception {
    5.17          StringBuilder sb = new StringBuilder();
    5.18          Invocable i = compileClass(sb, "org/apidesign/vm4brwsr/StaticMethod");
     6.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/StringTest.java	Mon Oct 08 17:10:27 2012 -0700
     6.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/StringTest.java	Tue Oct 09 11:11:58 2012 -0700
     6.3 @@ -30,9 +30,12 @@
     6.4          assertExec(
     6.5              "Five executions should generate 5Hello World!",
     6.6              "org_apidesign_vm4brwsr_StringSample_toStringTestLjava_lang_StringI",
     6.7 -            "5Hello World!", 5
     6.8 +            "Hello World!5", 5
     6.9          );
    6.10      }
    6.11 +    @Test public void toStringConcatenationJava() throws Exception {
    6.12 +        assertEquals("Hello World!5", StringSample.toStringTest(5));
    6.13 +    }
    6.14      
    6.15      private static void assertExec(String msg, String methodName, Object expRes, Object... args) throws Exception {
    6.16          StringBuilder sb = new StringBuilder();