From 101b759acb23d5824c30161cd6a67813aede4577 Mon Sep 17 00:00:00 2001
From: Volker Berlin <volker.berlin@googlemail.com>
Date: Sat, 10 Nov 2018 10:46:36 +0100
Subject: [PATCH] Add the Member interface to generalize the API usage

---
 .../inetsoftware/classparser/ConstantRef.java | 117 +++++++++++-------
 src/de/inetsoftware/classparser/Member.java   |  47 +++++++
 .../inetsoftware/classparser/MethodInfo.java  |  14 ++-
 .../binary/BinaryModuleWriter.java            |   4 +-
 .../jwebassembly/module/FunctionName.java     |  28 ++---
 .../jwebassembly/module/ModuleGenerator.java  |   6 +-
 .../jwebassembly/module/ModuleWriter.java     |   4 +-
 .../module/WasmCallInstruction.java           |  13 +-
 .../jwebassembly/module/WasmCodeBuilder.java  |  25 +++-
 .../module/WasmGlobalInstruction.java         |   8 +-
 .../jwebassembly/text/TextModuleWriter.java   |   4 +-
 11 files changed, 175 insertions(+), 95 deletions(-)
 create mode 100644 src/de/inetsoftware/classparser/Member.java

diff --git a/src/de/inetsoftware/classparser/ConstantRef.java b/src/de/inetsoftware/classparser/ConstantRef.java
index bbd707c..f6ee58f 100644
--- a/src/de/inetsoftware/classparser/ConstantRef.java
+++ b/src/de/inetsoftware/classparser/ConstantRef.java
@@ -1,47 +1,70 @@
-/*
-   Copyright 2017 Volker Berlin (i-net software)
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-
-*/
-package de.inetsoftware.classparser;
-
-/**
- * @author Volker Berlin
- */
-public abstract class ConstantRef {
-
-    private final ConstantClass       constClass;
-
-    private final ConstantNameAndType nameAndType;
-
-    ConstantRef( ConstantClass constClass, ConstantNameAndType nameAndType ) {
-        this.constClass = constClass;
-        this.nameAndType = nameAndType;
-    }
-
-    public String getName() {
-        return nameAndType.getName();
-    }
-
-    /**
-     * Get the type of the method. For example "(Ljava.lang.String;)I"
-     */
-    public String getType() {
-        return nameAndType.getType();
-    }
-
-    public ConstantClass getConstantClass() {
-        return constClass;
-    }
-}
+/*
+   Copyright 2017 - 2018 Volker Berlin (i-net software)
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+package de.inetsoftware.classparser;
+
+/**
+ * A reference to an member that is described in the constant pool of a Java class.
+ * 
+ * @author Volker Berlin
+ */
+public abstract class ConstantRef implements Member {
+
+    private final ConstantClass       constClass;
+
+    private final ConstantNameAndType nameAndType;
+
+    /**
+     * Create a new instance.
+     * 
+     * @param constClass
+     *            the class description
+     * @param nameAndType
+     *            the name and type description
+     */
+    ConstantRef( ConstantClass constClass, ConstantNameAndType nameAndType ) {
+        this.constClass = constClass;
+        this.nameAndType = nameAndType;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String getName() {
+        return nameAndType.getName();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String getClassName() {
+        return getConstantClass().getName();
+    }
+
+    /**
+     * Get the type of the method. For example "(Ljava.lang.String;)I"
+     */
+    @Override
+    public String getType() {
+        return nameAndType.getType();
+    }
+
+    public ConstantClass getConstantClass() {
+        return constClass;
+    }
+}
diff --git a/src/de/inetsoftware/classparser/Member.java b/src/de/inetsoftware/classparser/Member.java
new file mode 100644
index 0000000..37f8838
--- /dev/null
+++ b/src/de/inetsoftware/classparser/Member.java
@@ -0,0 +1,47 @@
+/*
+   Copyright 2018 Volker Berlin (i-net software)
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+package de.inetsoftware.classparser;
+
+/**
+ * Described a field, method, function, etc.
+ * 
+ * @author Volker Berlin
+ *
+ */
+public interface Member {
+
+    /**
+     * The simple name without package
+     * 
+     * @return the name
+     */
+    String getName();
+
+    /**
+     * The class name of the declaring class.
+     * 
+     * @return the class name
+     */
+    String getClassName();
+
+    /**
+     * Get the type of the method or field. For example "(Ljava.lang.String;)I"
+     * 
+     * @return the type
+     */
+    String getType();
+}
diff --git a/src/de/inetsoftware/classparser/MethodInfo.java b/src/de/inetsoftware/classparser/MethodInfo.java
index a745f87..c2dafa9 100644
--- a/src/de/inetsoftware/classparser/MethodInfo.java
+++ b/src/de/inetsoftware/classparser/MethodInfo.java
@@ -27,7 +27,7 @@ import de.inetsoftware.classparser.Attributes.AttributeInfo;
 /**
  * @author Volker Berlin
  */
-public class MethodInfo {
+public class MethodInfo implements Member {
 
     private final int          accessFlags;
 
@@ -99,10 +99,19 @@ public class MethodInfo {
     /**
      * @return the name
      */
+    @Override
     public String getName() {
         return name;
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String getClassName() {
+        return getDeclaringClassFile().getThisClass().getName();
+    }
+
     /**
      * @return the attributes
      */
@@ -125,7 +134,8 @@ public class MethodInfo {
     /**
      * Get the signature of the method without generic types.
      */
-    public String getDescription() {
+    @Override
+    public String getType() {
         return description;
     }
 
diff --git a/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java b/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java
index 886de1a..890400c 100644
--- a/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java
+++ b/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java
@@ -29,7 +29,7 @@ import java.util.Map.Entry;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
-import de.inetsoftware.classparser.ConstantRef;
+import de.inetsoftware.classparser.Member;
 import de.inetsoftware.jwebassembly.JWebAssembly;
 import de.inetsoftware.jwebassembly.WasmException;
 import de.inetsoftware.jwebassembly.module.FunctionName;
@@ -356,7 +356,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
      * {@inheritDoc}
      */
     @Override
-    protected void writeGlobalAccess( boolean load, FunctionName name, ConstantRef ref ) throws IOException {
+    protected void writeGlobalAccess( boolean load, FunctionName name, Member ref ) throws IOException {
         Global var = globals.get( name.fullName );
         if( var == null ) { // if not declared then create a definition in the global section
             var = new Global();
diff --git a/src/de/inetsoftware/jwebassembly/module/FunctionName.java b/src/de/inetsoftware/jwebassembly/module/FunctionName.java
index 63a13d2..ffed857 100644
--- a/src/de/inetsoftware/jwebassembly/module/FunctionName.java
+++ b/src/de/inetsoftware/jwebassembly/module/FunctionName.java
@@ -18,8 +18,7 @@ package de.inetsoftware.jwebassembly.module;
 
 import javax.annotation.Nonnull;
 
-import de.inetsoftware.classparser.ConstantRef;
-import de.inetsoftware.classparser.MethodInfo;
+import de.inetsoftware.classparser.Member;
 
 /**
  * Described the name of WebAssembly function.
@@ -40,28 +39,15 @@ public class FunctionName {
     public final String signatureName;
 
     /**
-     * Create a new instance from the given parsed Java method.
+     * Create a new instance from the given reference in the ConstantPool or parsed method.
      * 
-     * @param method
+     * @param methodOrField
      *            the Java method
      */
-    FunctionName( @Nonnull MethodInfo method ) {
-        String methodName = method.getName();
-        String className = method.getDeclaringClassFile().getThisClass().getName();
+    FunctionName( @Nonnull Member methodOrField ) {
+        String methodName = methodOrField.getName();
+        String className = methodOrField.getClassName();
         fullName = className + '.' + methodName;
-        signatureName = fullName + method.getDescription();
-    }
-
-    /**
-     * Create a new instance from the given reference in the ConstantPool.
-     * 
-     * @param method
-     *            the Java method
-     */
-    FunctionName( @Nonnull ConstantRef method ) {
-        String methodName = method.getName();
-        String className = method.getConstantClass().getName();
-        fullName = className + '.' + methodName;
-        signatureName = fullName + method.getType();
+        signatureName = fullName + methodOrField.getType();
     }
 }
diff --git a/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java b/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java
index 24cf5a2..8f3e568 100644
--- a/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java
+++ b/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java
@@ -96,7 +96,7 @@ public class ModuleGenerator {
             MethodInfo[] methods = classFile.getMethods();
             for( MethodInfo method : methods ) {
                 Code code = method.getCode();
-                if( method.getName().equals( "<init>" ) && method.getDescription().equals( "()V" )
+                if( method.getName().equals( "<init>" ) && method.getType().equals( "()V" )
                                 && code.isSuperInitReturn( classFile.getSuperClass() ) ) {
                     continue; //default constructor
                 }
@@ -149,7 +149,7 @@ public class ModuleGenerator {
                 writeExport( name, method );
                 writer.writeMethodStart( name );
 
-                codeBuilder.buildCode( code, !method.getDescription().endsWith( ")V" ) );
+                codeBuilder.buildCode( code, !method.getType().endsWith( ")V" ) );
                 writeMethodSignature( method, code.getLocalVariableTable(), codeBuilder );
 
                 for( WasmInstruction instruction : codeBuilder.getInstructions() ) {
@@ -200,7 +200,7 @@ public class ModuleGenerator {
      *             if some Java code can't converted
      */
     private void writeMethodSignature( MethodInfo method, @Nullable LocalVariableTable variables, WasmCodeBuilder codeBuilder ) throws IOException, WasmException {
-        String signature = method.getDescription();
+        String signature = method.getType();
         String kind = "param";
         int paramCount = 0;
         ValueType type = null;
diff --git a/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java b/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java
index cd0c5dc..a0aba08 100644
--- a/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java
+++ b/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java
@@ -21,7 +21,7 @@ import java.io.IOException;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
-import de.inetsoftware.classparser.ConstantRef;
+import de.inetsoftware.classparser.Member;
 
 /**
  * Module Writer base class.
@@ -156,7 +156,7 @@ public abstract class ModuleWriter implements Closeable {
      * @throws IOException
      *             if any I/O error occur
      */
-    protected abstract void writeGlobalAccess( boolean load, FunctionName name, ConstantRef ref ) throws IOException;
+    protected abstract void writeGlobalAccess( boolean load, FunctionName name, Member ref ) throws IOException;
 
 
     /**
diff --git a/src/de/inetsoftware/jwebassembly/module/WasmCallInstruction.java b/src/de/inetsoftware/jwebassembly/module/WasmCallInstruction.java
index 4d812ee..1cc0884 100644
--- a/src/de/inetsoftware/jwebassembly/module/WasmCallInstruction.java
+++ b/src/de/inetsoftware/jwebassembly/module/WasmCallInstruction.java
@@ -20,7 +20,7 @@ import java.io.IOException;
 
 import javax.annotation.Nonnull;
 
-import de.inetsoftware.classparser.ConstantRef;
+import de.inetsoftware.classparser.Member;
 
 /**
  * WasmInstruction for a function call.
@@ -30,7 +30,7 @@ import de.inetsoftware.classparser.ConstantRef;
  */
 class WasmCallInstruction extends WasmInstruction {
 
-    private final ConstantRef method;
+    private final Member    method;
 
     private final ValueType valueType;
 
@@ -42,11 +42,11 @@ class WasmCallInstruction extends WasmInstruction {
      * @param javaCodePos
      *            the code position/offset in the Java method
      */
-    WasmCallInstruction( ConstantRef method, int javaCodePos ) {
+    WasmCallInstruction( Member method, int javaCodePos ) {
         super( javaCodePos );
         this.method = method;
         String signature = method.getType();
-        this.valueType = ValueType.getValueType(  signature, signature.indexOf( ')' ) + 1 );
+        this.valueType = ValueType.getValueType( signature, signature.indexOf( ')' ) + 1 );
     }
 
     /**
@@ -56,7 +56,6 @@ class WasmCallInstruction extends WasmInstruction {
         writer.writeFunctionCall( new FunctionName( method ).signatureName );
     }
 
-
     /**
      * {@inheritDoc}
      */
@@ -77,8 +76,8 @@ class WasmCallInstruction extends WasmInstruction {
                 return paramCount;
             }
             paramCount++;
-            ValueType.getValueType(  signature, i );
+            ValueType.getValueType( signature, i );
         }
-        throw new Error(); 
+        throw new Error();
     }
 }
diff --git a/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java b/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java
index c2607bd..065f2d2 100644
--- a/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java
+++ b/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java
@@ -77,15 +77,30 @@ public abstract class WasmCodeBuilder {
      *            the value type
      * @param load
      *            true: if load
-     * @param idx
-     *            the memory/slot idx of the variable
+     * @param javaIdx
+     *            the memory/slot index of the variable in Java byte code
      * @param javaCodePos
      *            the code position/offset in the Java method
      */
     @Nonnull
-    protected void addLoadStoreInstruction( ValueType valueType, boolean load, @Nonnegative int idx, int javaCodePos ) {
-        localVariables.use( valueType, idx );
-        instructions.add( new WasmLoadStoreInstruction( load, idx, localVariables, javaCodePos ) );
+    protected void addLoadStoreInstruction( ValueType valueType, boolean load, @Nonnegative int javaIdx, int javaCodePos ) {
+        localVariables.use( valueType, javaIdx );
+        instructions.add( new WasmLoadStoreInstruction( load, javaIdx, localVariables, javaCodePos ) );
+    }
+
+    /**
+     * Create a WasmLoadStoreInstruction get_local/set_local.
+     * 
+     * @param load
+     *            true: if load
+     * @param wasmIdx
+     *            the index of the variable
+     * @param javaCodePos
+     *            the code position/offset in the Java method
+     */
+    @Nonnull
+    protected void addLoadStoreInstruction( boolean load, @Nonnegative int wasmIdx, int javaCodePos ) {
+        instructions.add( new WasmLoadStoreInstruction( load, wasmIdx, null, javaCodePos ) );
     }
 
     /**
diff --git a/src/de/inetsoftware/jwebassembly/module/WasmGlobalInstruction.java b/src/de/inetsoftware/jwebassembly/module/WasmGlobalInstruction.java
index 35b03fc..cdc85c7 100644
--- a/src/de/inetsoftware/jwebassembly/module/WasmGlobalInstruction.java
+++ b/src/de/inetsoftware/jwebassembly/module/WasmGlobalInstruction.java
@@ -20,7 +20,7 @@ import java.io.IOException;
 
 import javax.annotation.Nonnull;
 
-import de.inetsoftware.classparser.ConstantRef;
+import de.inetsoftware.classparser.Member;
 
 /**
  * WasmInstruction for set and get global variables.
@@ -30,9 +30,9 @@ import de.inetsoftware.classparser.ConstantRef;
  */
 class WasmGlobalInstruction extends WasmInstruction {
 
-    private boolean     load;
+    private boolean load;
 
-    private ConstantRef ref;
+    private Member  ref;
 
     /**
      * Create an instance of a load/store instruction
@@ -44,7 +44,7 @@ class WasmGlobalInstruction extends WasmInstruction {
      * @param javaCodePos
      *            the code position/offset in the Java method
      */
-    WasmGlobalInstruction( boolean load, ConstantRef ref, int javaCodePos ) {
+    WasmGlobalInstruction( boolean load, Member ref, int javaCodePos ) {
         super( javaCodePos );
         this.load = load;
         this.ref = ref;
diff --git a/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java b/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java
index c020e65..23c46b4 100644
--- a/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java
+++ b/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java
@@ -22,7 +22,7 @@ import java.util.HashSet;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
-import de.inetsoftware.classparser.ConstantRef;
+import de.inetsoftware.classparser.Member;
 import de.inetsoftware.jwebassembly.JWebAssembly;
 import de.inetsoftware.jwebassembly.module.FunctionName;
 import de.inetsoftware.jwebassembly.module.ModuleWriter;
@@ -176,7 +176,7 @@ public class TextModuleWriter extends ModuleWriter {
      * {@inheritDoc}
      */
     @Override
-    protected void writeGlobalAccess( boolean load, FunctionName name, ConstantRef ref ) throws IOException {
+    protected void writeGlobalAccess( boolean load, FunctionName name, Member ref ) throws IOException {
         if( !globals.contains( name.fullName ) ) {
             // declare global variable if not already declared.
             output.append( "\n  " );