From: rtrimana Date: Wed, 23 Nov 2016 17:27:55 +0000 (-0800) Subject: Adding struct support for Java in compiler X-Git-Url: http://plrg.eecs.uci.edu/git/?p=iot2.git;a=commitdiff_plain;h=8946012fd7b634404bffa2d3977c309f4e31bcb7;hp=63e2f6812efecef878f971b5d8ad83eb1ff9824a Adding struct support for Java in compiler --- diff --git a/config/iotpolicy/camerapolicy.pol b/config/iotpolicy/camerapolicy.pol index 2a69e55..ca807b6 100644 --- a/config/iotpolicy/camerapolicy.pol +++ b/config/iotpolicy/camerapolicy.pol @@ -8,6 +8,7 @@ public interface Camera { public boolean MethodE(String I, boolean J); public void MethodF(LightBulb K); public Enum MethodG(Enum L); + public Struct MethodH(Struct M, int N); capability ImageCapture { description = "The quick brown fox jumps over the smart dog"; @@ -17,6 +18,7 @@ public interface Camera { method = "MethodC(String E, List F)"; method = "MethodF(LightBulb K)"; method = "MethodG(Enum L)"; + method = "MethodH(Struct M, int N)"; } capability VideoRecording { diff --git a/iotjava/iotpolicy/IoTCompiler.java b/iotjava/iotpolicy/IoTCompiler.java index db60fcc..e8abdfa 100644 --- a/iotjava/iotpolicy/IoTCompiler.java +++ b/iotjava/iotpolicy/IoTCompiler.java @@ -598,54 +598,294 @@ public class IoTCompiler { } + /** + * HELPER: checkAndWriteStructSetupJavaStub() writes the struct type setup + */ + private void checkAndWriteStructSetupJavaStub(List methParams, List methPrmTypes, + InterfaceDecl intDecl, String method) { + + // Iterate and find struct declarations + for (int i = 0; i < methParams.size(); i++) { + String paramType = methPrmTypes.get(i); + String param = methParams.get(i); + String simpleType = getSimpleType(paramType); + if (isStructClass(simpleType)) { + // Check if this is enum type + int methodNumId = intDecl.getMethodNumId(method); + String helperMethod = methodNumId + "struct" + i; + println("int methodIdStruct" + i + " = " + intDecl.getHelperMethodNumId(helperMethod) + ";"); + println("Class retTypeStruct" + i + " = void.class;"); + println("Class[] paramClsStruct" + i + " = new Class[] { int.class };"); + if (isArray(param)) { // An array + println("Object[] paramObjStruct" + i + " = new Object[] { " + getSimpleArrayType(param) + ".length };"); + } else if (isList(paramType)) { // A list + println("Object[] paramObjStruct" + i + " = new Object[] { " + getSimpleArrayType(param) + ".size() };"); + } else { // Just one element + println("Object[] paramObjStruct" + i + " = new Object[] { new Integer(1) };"); + } + println("rmiCall.remoteCall(objectId, methodIdStruct" + i + + ", retTypeStruct" + i + ", null, paramClsStruct" + i + + ", paramObjStruct" + i + ");\n"); + } + } + } + + + /** + * HELPER: isStructPresent() checks presence of struct + */ + private boolean isStructPresent(List methParams, List methPrmTypes) { + + // Iterate and find enum declarations + for (int i = 0; i < methParams.size(); i++) { + String paramType = methPrmTypes.get(i); + String param = methParams.get(i); + String simpleType = getSimpleType(paramType); + if (isStructClass(simpleType)) + return true; + } + return false; + } + + + /** + * HELPER: writeLengthStructParamClassJavaStub() writes lengths of params + */ + private void writeLengthStructParamClassJavaStub(List methParams, List methPrmTypes) { + + // Iterate and find struct declarations - count number of params + for (int i = 0; i < methParams.size(); i++) { + String paramType = methPrmTypes.get(i); + String param = methParams.get(i); + String simpleType = getGenericType(paramType); + if (isStructClass(simpleType)) { + int members = getNumOfMembers(simpleType); + if (isArray(param)) { // An array + String structLen = param + ".length"; + print(members + "*" + structLen); + } else if (isList(paramType)) { // A list + String structLen = param + ".size()"; + print(members + "*" + structLen); + } else + print(Integer.toString(members)); + } else + print("1"); + if (i != methParams.size() - 1) { + print("+"); + } + } + } + + + /** + * HELPER: writeStructMembersJavaStub() writes parameters of struct + */ + private void writeStructMembersJavaStub(String simpleType, String paramType, String param) { + + // Get the struct declaration for this struct and generate initialization code + StructDecl structDecl = getStructDecl(simpleType); + List memTypes = structDecl.getMemberTypes(simpleType); + List members = structDecl.getMembers(simpleType); + if (isArray(param)) { // An array + println("for(int i = 0; i < " + param + ".length; i++) {"); + } else if (isList(paramType)) { // A list + println("for(int i = 0; i < " + param + ".size(); i++) {"); + } + if (isArrayOrList(param, paramType)) { // An array or list + for (int i = 0; i < members.size(); i++) { + String prmType = checkAndGetArray(memTypes.get(i), members.get(i)); + println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;"); + print("paramObj[pos++] = " + param + "[i]."); + print(getSimpleIdentifier(members.get(i))); + println(";"); + } + println("}"); + } else { // Just one struct element + for (int i = 0; i < members.size(); i++) { + String prmType = checkAndGetArray(memTypes.get(i), members.get(i)); + println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;"); + print("paramObj[pos++] = " + param + "."); + print(getSimpleIdentifier(members.get(i))); + println(";"); + } + } + } + + + /** + * HELPER: writeStructParamClassJavaStub() writes parameters if struct is present + */ + private void writeStructParamClassJavaStub(List methParams, List methPrmTypes) { + + print("int paramLen = "); + writeLengthStructParamClassJavaStub(methParams, methPrmTypes); + println(";"); + println("Object[] paramObj = new Object[paramLen];"); + println("Class[] paramCls = new Class[paramLen];"); + println("int pos = 0;"); + // Iterate again over the parameters + for (int i = 0; i < methParams.size(); i++) { + String paramType = methPrmTypes.get(i); + String param = methParams.get(i); + String simpleType = getGenericType(paramType); + if (isStructClass(simpleType)) { + writeStructMembersJavaStub(simpleType, paramType, param); + } else { + String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i)); + println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;"); + print("paramObj[pos++] = "); + print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i)); + println(";"); + } + } + + } + + + /** + * HELPER: writeStructRetMembersJavaStub() writes parameters of struct + */ + private void writeStructRetMembersJavaStub(String simpleType, String retType) { + + // Get the struct declaration for this struct and generate initialization code + StructDecl structDecl = getStructDecl(simpleType); + List memTypes = structDecl.getMemberTypes(simpleType); + List members = structDecl.getMembers(simpleType); + if (isArrayOrList(retType, retType)) { // An array or list + println("for(int i = 0; i < retLen.length; i++) {"); + } + if (isArray(retType)) { // An array + for (int i = 0; i < members.size(); i++) { + String prmType = checkAndGetArray(memTypes.get(i), members.get(i)); + print("structRet[i]." + getSimpleIdentifier(members.get(i))); + println(" = (" + getSimpleType(getEnumType(prmType)) + ") retObj[retObjPos++];"); + } + println("}"); + } else if (isList(retType)) { // A list + println(simpleType + " structRetMem = new " + simpleType + "();"); + for (int i = 0; i < members.size(); i++) { + String prmType = checkAndGetArray(memTypes.get(i), members.get(i)); + print("structRetMem." + getSimpleIdentifier(members.get(i))); + println(" = (" + getSimpleType(getEnumType(prmType)) + ") retObj[retObjPos++];"); + } + println("structRet.add(structRetMem);"); + println("}"); + } else { // Just one struct element + for (int i = 0; i < members.size(); i++) { + String prmType = checkAndGetArray(memTypes.get(i), members.get(i)); + print("structRet." + getSimpleIdentifier(members.get(i))); + println(" = (" + getSimpleType(getEnumType(prmType)) + ") retObj[retObjPos++];"); + } + } + println("return structRet;"); + } + + + /** + * HELPER: writeStructReturnJavaStub() writes parameters if struct is present + */ + private void writeStructReturnJavaStub(String simpleType, String retType) { + + // Handle the returned struct!!! + println("Object retLenObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);"); + // Minimum retLen is 1 if this is a single struct object + println("int retLen = (int) retLenObj;"); + int numMem = getNumOfMembers(simpleType); + println("Class[] retCls = new Class[" + numMem + "*retLen];"); + println("Class[] retClsVal = new Class[" + numMem + "*retLen];"); + println("int retPos = 0;"); + // Get the struct declaration for this struct and generate initialization code + StructDecl structDecl = getStructDecl(simpleType); + List memTypes = structDecl.getMemberTypes(simpleType); + List members = structDecl.getMembers(simpleType); + if (isArrayOrList(retType, retType)) { // An array or list + println("for(int i = 0; i < retLen; i++) {"); + for (int i = 0; i < members.size(); i++) { + String prmType = checkAndGetArray(memTypes.get(i), members.get(i)); + println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;"); + println("retClsVal[retPos++] = null;"); + } + println("}"); + } else { // Just one struct element + for (int i = 0; i < members.size(); i++) { + String prmType = checkAndGetArray(memTypes.get(i), members.get(i)); + println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;"); + println("retClsVal[retPos++] = null;"); + } + } + println("Object[] retObj = rmiCall.getStructObjects(retCls, retClsVal);"); + if (isArray(retType)) { // An array + println(simpleType + "[] structRet = new " + simpleType + "[retLen];"); + println("for(int i = 0; i < retLen; i++) {"); + println("structRet[i] = new " + simpleType + "();"); + println("}"); + } else if (isList(retType)) { // A list + println("List<" + simpleType + "> structRet = new ArrayList<" + simpleType + ">();"); + } else + println(simpleType + " structRet = new " + simpleType + "();"); + println("int retObjPos = 0;"); + writeStructRetMembersJavaStub(simpleType, retType); + } + + /** * HELPER: writeStdMethodBodyJavaStub() writes the standard method body in the stub class */ private void writeStdMethodBodyJavaStub(InterfaceDecl intDecl, List methParams, List methPrmTypes, String method) { + checkAndWriteStructSetupJavaStub(methParams, methPrmTypes, intDecl, method); println("int methodId = " + intDecl.getMethodNumId(method) + ";"); String retType = intDecl.getMethodType(method); - println("Class retType = " + getSimpleType(getEnumType(retType)) + ".class;"); + println("Class retType = " + getSimpleType(getStructType(getEnumType(retType))) + ".class;"); checkAndWriteEnumTypeJavaStub(methParams, methPrmTypes); // Generate array of parameter types - print("Class[] paramCls = new Class[] { "); - for (int i = 0; i < methParams.size(); i++) { - String paramType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i)); - print(getSimpleType(getEnumType(paramType)) + ".class"); - // Check if this is the last element (don't print a comma) - if (i != methParams.size() - 1) { - print(", "); + if (isStructPresent(methParams, methPrmTypes)) { + writeStructParamClassJavaStub(methParams, methPrmTypes); + } else { + print("Class[] paramCls = new Class[] { "); + for (int i = 0; i < methParams.size(); i++) { + String paramType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i)); + print(getSimpleType(getEnumType(paramType)) + ".class"); + // Check if this is the last element (don't print a comma) + if (i != methParams.size() - 1) { + print(", "); + } } - } - println(" };"); - // Generate array of parameter objects - print("Object[] paramObj = new Object[] { "); - for (int i = 0; i < methParams.size(); i++) { - print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i)); - // Check if this is the last element (don't print a comma) - if (i != methParams.size() - 1) { - print(", "); + println(" };"); + // Generate array of parameter objects + print("Object[] paramObj = new Object[] { "); + for (int i = 0; i < methParams.size(); i++) { + print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i)); + // Check if this is the last element (don't print a comma) + if (i != methParams.size() - 1) { + print(", "); + } } + println(" };"); } - println(" };"); // Check if this is "void" if (retType.equals("void")) { println("rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);"); } else { // We do have a return value - // Check if the return value NONPRIMITIVES - if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES) { - String[] retGenValType = getTypeOfGeneric(retType); - println("Class retGenValType = " + retGenValType[0] + ".class;"); - println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, retGenValType, paramCls, paramObj);"); - println("return (" + retType + ")retObj;"); - } else if (getParamCategory(retType) == ParamCategory.ENUM) { - // This is an enum type - println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);"); - checkAndWriteEnumRetTypeJavaStub(retType); + // Generate array of parameter types + if (isStructClass(getGenericType(getSimpleArrayType(retType)))) { + writeStructReturnJavaStub(getGenericType(getSimpleArrayType(retType)), retType); } else { - println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);"); - println("return (" + retType + ")retObj;"); + // Check if the return value NONPRIMITIVES + if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES) { + String[] retGenValType = getTypeOfGeneric(retType); + println("Class retGenValType = " + retGenValType[0] + ".class;"); + println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, retGenValType, paramCls, paramObj);"); + println("return (" + retType + ")retObj;"); + } else if (getParamCategory(retType) == ParamCategory.ENUM) { + // This is an enum type + println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);"); + checkAndWriteEnumRetTypeJavaStub(retType); + } else { + println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);"); + println("return (" + retType + ")retObj;"); + } } } } @@ -1182,6 +1422,264 @@ public class IoTCompiler { println("Object retObj = retEnumVal;"); } } + + + /** + * HELPER: writeLengthStructParamClassJavaSkeleton() writes lengths of params + */ + private void writeLengthStructParamClassJavaSkeleton(List methParams, List methPrmTypes, + String method, InterfaceDecl intDecl) { + + // Iterate and find struct declarations - count number of params + for (int i = 0; i < methParams.size(); i++) { + String paramType = methPrmTypes.get(i); + String param = methParams.get(i); + String simpleType = getGenericType(paramType); + if (isStructClass(simpleType)) { + int members = getNumOfMembers(simpleType); + print(Integer.toString(members) + "*"); + int methodNumId = intDecl.getMethodNumId(method); + print("struct" + methodNumId + "Size" + i); + } else + print("1"); + if (i != methParams.size() - 1) { + print("+"); + } + } + } + + + /** + * HELPER: writeStructMembersJavaSkeleton() writes parameters of struct + */ + private void writeStructMembersJavaSkeleton(String simpleType, String paramType, + String param, String method, InterfaceDecl intDecl, int iVar) { + + // Get the struct declaration for this struct and generate initialization code + StructDecl structDecl = getStructDecl(simpleType); + List memTypes = structDecl.getMemberTypes(simpleType); + List members = structDecl.getMembers(simpleType); + if (isArrayOrList(param, paramType)) { // An array or list + int methodNumId = intDecl.getMethodNumId(method); + String counter = "struct" + methodNumId + "Size" + iVar; + println("for(int i = 0; i < " + counter + "; i++) {"); + } + println("int pos = 0;"); + if (isArrayOrList(param, paramType)) { // An array or list + println("for(int i = 0; i < retLen; i++) {"); + for (int i = 0; i < members.size(); i++) { + String prmType = checkAndGetArray(memTypes.get(i), members.get(i)); + println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;"); + println("paramClsGen[pos++] = null;"); + } + println("}"); + } else { // Just one struct element + for (int i = 0; i < members.size(); i++) { + String prmType = checkAndGetArray(memTypes.get(i), members.get(i)); + println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;"); + println("paramClsGen[pos++] = null;"); + } + } + } + + + + /** + * HELPER: writeStructMembersInitJavaSkeleton() writes parameters of struct + */ + private void writeStructMembersInitJavaSkeleton(InterfaceDecl intDecl, List methParams, + List methPrmTypes, String method) { + + for (int i = 0; i < methParams.size(); i++) { + String paramType = methPrmTypes.get(i); + String param = methParams.get(i); + String simpleType = getGenericType(paramType); + if (isStructClass(simpleType)) { + int methodNumId = intDecl.getMethodNumId(method); + String counter = "struct" + methodNumId + "Size" + i; + // Declaration + if (isArray(param)) { // An array + println(simpleType + "[] paramStruct" + i + " = new " + simpleType + "[" + counter + "];"); + println("for(int i = 0; i < " + counter + "; i++) {"); + println("paramStruct" + i + "[i] = new " + simpleType + "();"); + println("}"); + } else if (isList(paramType)) { // A list + println("List<" + simpleType + "> structRet = new ArrayList<" + simpleType + ">();"); + } else + println(simpleType + " paramStruct" + i + " = new " + simpleType + "();"); + println("int objPos = 0;"); + // Initialize members + StructDecl structDecl = getStructDecl(simpleType); + List members = structDecl.getMembers(simpleType); + List memTypes = structDecl.getMemberTypes(simpleType); + if (isArrayOrList(param, paramType)) { // An array or list + println("for(int i = 0; i < " + counter + "; i++) {"); + } + if (isArray(param)) { // An array + for (int j = 0; j < members.size(); j++) { + String prmType = checkAndGetArray(memTypes.get(j), members.get(j)); + print("paramStruct" + i + "[i]." + getSimpleIdentifier(members.get(j))); + println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];"); + } + println("}"); + } else if (isList(paramType)) { // A list + println(simpleType + " paramStructMem = new " + simpleType + "();"); + for (int j = 0; j < members.size(); j++) { + String prmType = checkAndGetArray(memTypes.get(j), members.get(j)); + print("paramStructMem." + getSimpleIdentifier(members.get(j))); + println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];"); + } + println("paramStruct" + i + ".add(paramStructMem);"); + println("}"); + } else { // Just one struct element + for (int j = 0; j < members.size(); j++) { + String prmType = checkAndGetArray(memTypes.get(j), members.get(j)); + print("paramStruct" + i + "." + getSimpleIdentifier(members.get(j))); + println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];"); + } + } + } else { + // Take offsets of parameters + println("int offset" + i +" = objPos;"); + } + } + } + + + /** + * HELPER: writeStructReturnJavaSkeleton() writes parameters if struct is present + */ + private void writeStructReturnJavaSkeleton(String simpleType, String retType) { + + // Minimum retLen is 1 if this is a single struct object + if (isArray(retType)) + println("int retLen = retStruct.length;"); + else if (isList(retType)) + println("int retLen = retStruct.size();"); + else // Just single struct object + println("int retLen = 1;"); + println("Object retLenObj = retLen;"); + println("rmiObj.sendReturnObj(retLenObj);"); + int numMem = getNumOfMembers(simpleType); + println("Class[] retCls = new Class[" + numMem + "*retLen];"); + println("Object[] retObj = new Object[" + numMem + "*retLen];"); + println("int retPos = 0;"); + // Get the struct declaration for this struct and generate initialization code + StructDecl structDecl = getStructDecl(simpleType); + List memTypes = structDecl.getMemberTypes(simpleType); + List members = structDecl.getMembers(simpleType); + if (isArrayOrList(retType, retType)) { // An array or list + println("for(int i = 0; i < retLen; i++) {"); + for (int i = 0; i < members.size(); i++) { + String prmType = checkAndGetArray(memTypes.get(i), members.get(i)); + println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;"); + print("retObj[retPos++] = retStruct[i]."); + print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i)); + println(";"); + } + println("}"); + } else { // Just one struct element + for (int i = 0; i < members.size(); i++) { + String prmType = checkAndGetArray(memTypes.get(i), members.get(i)); + println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;"); + print("retObj[retPos++] = retStruct."); + print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i)); + println(";"); + } + } + + } + + + /** + * HELPER: writeMethodHelperStructJavaSkeleton() writes the struct in skeleton + */ + private void writeMethodHelperStructJavaSkeleton(InterfaceDecl intDecl, List methParams, + List methPrmTypes, String method, Set callbackClasses) { + + // Generate array of parameter objects + boolean isCallbackMethod = false; + String callbackType = null; + print("int paramLen = "); + writeLengthStructParamClassJavaSkeleton(methParams, methPrmTypes, method, intDecl); + println(";"); + println("Class[] paramCls = new Class[paramLen];"); + println("Class[] paramClsGen = new Class[paramLen];"); + // Iterate again over the parameters + for (int i = 0; i < methParams.size(); i++) { + String paramType = methPrmTypes.get(i); + String param = methParams.get(i); + String simpleType = getGenericType(paramType); + if (isStructClass(simpleType)) { + writeStructMembersJavaSkeleton(simpleType, paramType, param, method, intDecl, i); + } else { + String prmType = returnGenericCallbackType(methPrmTypes.get(i)); + if (callbackClasses.contains(prmType)) { + isCallbackMethod = true; + callbackType = prmType; + print("int.class"); + } else { // Generate normal classes if it's not a callback object + String paramTypeOth = checkAndGetArray(methPrmTypes.get(i), methParams.get(i)); + println("paramCls[pos] = " + getSimpleType(getEnumType(paramTypeOth)) + ".class;"); + print("paramClsGen[pos++] = "); + String prmTypeOth = methPrmTypes.get(i); + if (getParamCategory(prmTypeOth) == ParamCategory.NONPRIMITIVES) + println(getTypeOfGeneric(prmType)[0] + ".class;"); + else + println("null;"); + } + } + } + println("Object[] paramObj = rmiObj.getMethodParams(paramCls, paramClsGen);"); + writeStructMembersInitJavaSkeleton(intDecl, methParams, methPrmTypes, method); + checkAndWriteEnumTypeJavaSkeleton(methParams, methPrmTypes); + Map mapStubParam = null; + if (isCallbackMethod) + mapStubParam = writeCallbackJavaStubGeneration(methParams, methPrmTypes, callbackType); + // Check if this is "void" + String retType = intDecl.getMethodType(method); + if (retType.equals("void")) { + print(intDecl.getMethodId(method) + "("); + } else if (isEnumClass(getSimpleArrayType(getSimpleType(retType)))) { // Enum type + checkAndWriteEnumRetTypeJavaSkeleton(retType, intDecl.getMethodId(method)); + } else if (isStructClass(getSimpleArrayType(getSimpleType(retType)))) { // Struct type + print(retType + " retStruct = " + intDecl.getMethodId(method) + "("); + } else { // We do have a return value + print("Object retObj = " + intDecl.getMethodId(method) + "("); + } + for (int i = 0; i < methParams.size(); i++) { + + if (isCallbackMethod) { + print(mapStubParam.get(i)); // Get the callback parameter + } else if (isEnumClass(getSimpleType(methPrmTypes.get(i)))) { // Enum class + print(getEnumParam(methPrmTypes.get(i), methParams.get(i), i)); + } else if (isStructClass(getSimpleType(methPrmTypes.get(i)))) { + print("paramStruct" + i); + } else { + String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i)); + print("(" + prmType + ") paramObj[offset" + i + "]"); + } + if (i != methParams.size() - 1) + print(", "); + } + println(");"); + if (!retType.equals("void")) { + if (isEnumClass(getSimpleArrayType(getSimpleType(retType)))) { // Enum type + checkAndWriteEnumRetConvJavaSkeleton(retType); + println("rmiObj.sendReturnObj(retObj);"); + } else if (isStructClass(getSimpleArrayType(getSimpleType(retType)))) { // Struct type + writeStructReturnJavaSkeleton(getSimpleArrayType(getSimpleType(retType)), retType); + println("rmiObj.sendReturnObj(retCls, retObj);"); + } else + println("rmiObj.sendReturnObj(retObj);"); + } + if (isCallbackMethod) { // Catch exception if this is callback + println("} catch(Exception ex) {"); + println("ex.printStackTrace();"); + println("throw new Error(\"Exception from callback object instantiation!\");"); + println("}"); + } + } /** @@ -1189,6 +1687,7 @@ public class IoTCompiler { */ private void writeStdMethodHelperBodyJavaSkeleton(InterfaceDecl intDecl, List methParams, List methPrmTypes, String method, Set callbackClasses) { + // Generate array of parameter objects boolean isCallbackMethod = false; String callbackType = null; @@ -1230,6 +1729,8 @@ public class IoTCompiler { print(intDecl.getMethodId(method) + "("); } else if (isEnumClass(getSimpleArrayType(getSimpleType(retType)))) { // Enum type checkAndWriteEnumRetTypeJavaSkeleton(retType, intDecl.getMethodId(method)); + } else if (isStructClass(getSimpleArrayType(getSimpleType(retType)))) { // Struct type + print(retType + " retStruct = " + intDecl.getMethodId(method) + "("); } else { // We do have a return value print("Object retObj = " + intDecl.getMethodId(method) + "("); } @@ -1248,9 +1749,14 @@ public class IoTCompiler { } println(");"); if (!retType.equals("void")) { - if (isEnumClass(getSimpleArrayType(getSimpleType(retType)))) // Enum type + if (isEnumClass(getSimpleArrayType(getSimpleType(retType)))) { // Enum type checkAndWriteEnumRetConvJavaSkeleton(retType); - println("rmiObj.sendReturnObj(retObj);"); + println("rmiObj.sendReturnObj(retObj);"); + } else if (isStructClass(getSimpleArrayType(getSimpleType(retType)))) { // Struct type + writeStructReturnJavaSkeleton(getSimpleArrayType(getSimpleType(retType)), retType); + println("rmiObj.sendReturnObj(retCls, retObj);"); + } else + println("rmiObj.sendReturnObj(retObj);"); } if (isCallbackMethod) { // Catch exception if this is callback println("} catch(Exception ex) {"); @@ -1272,22 +1778,165 @@ public class IoTCompiler { List methParams = intDecl.getMethodParams(method); List methPrmTypes = intDecl.getMethodParamTypes(method); - String methodId = intDecl.getMethodId(method); - print("public void ___"); - String helperMethod = methodId; - if (uniqueMethodIds.contains(methodId)) - helperMethod = helperMethod + intDecl.getMethodNumId(method); - else - uniqueMethodIds.add(methodId); - // Check if this is "void" - String retType = intDecl.getMethodType(method); - if (retType.equals("void")) - println(helperMethod + "() {"); - else - println(helperMethod + "() throws IOException {"); - // Now, write the helper body of skeleton! - writeStdMethodHelperBodyJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses); - println("}\n"); + if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently + String methodId = intDecl.getMethodId(method); + print("public void ___"); + String helperMethod = methodId; + if (uniqueMethodIds.contains(methodId)) + helperMethod = helperMethod + intDecl.getMethodNumId(method); + else + uniqueMethodIds.add(methodId); + String retType = intDecl.getMethodType(method); + print(helperMethod + "("); + boolean begin = true; + for (int i = 0; i < methParams.size(); i++) { // Print size variables + String paramType = methPrmTypes.get(i); + String param = methParams.get(i); + String simpleType = getSimpleType(paramType); + if (isStructClass(simpleType)) { + if (!begin) { // Generate comma for not the beginning variable + print(", "); begin = false; + } + int methodNumId = intDecl.getMethodNumId(method); + print("int struct" + methodNumId + "Size" + i); + } + // TODO: Need to create comma separation + } + // Check if this is "void" + if (retType.equals("void")) + println(") {"); + else + println(") throws IOException {"); + writeMethodHelperStructJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses); + println("}\n"); + } else { + String methodId = intDecl.getMethodId(method); + print("public void ___"); + String helperMethod = methodId; + if (uniqueMethodIds.contains(methodId)) + helperMethod = helperMethod + intDecl.getMethodNumId(method); + else + uniqueMethodIds.add(methodId); + // Check if this is "void" + String retType = intDecl.getMethodType(method); + if (retType.equals("void")) + println(helperMethod + "() {"); + else + println(helperMethod + "() throws IOException {"); + // Now, write the helper body of skeleton! + writeStdMethodHelperBodyJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses); + println("}\n"); + } + } + // Write method helper for structs + writeMethodHelperStructSetupJavaSkeleton(methods, intDecl); + } + + + /** + * HELPER: writeMethodHelperStructSetupJavaSkeleton() writes the method helper of the struct in skeleton class + */ + private void writeMethodHelperStructSetupJavaSkeleton(Collection methods, + InterfaceDecl intDecl) { + + // Use this set to handle two same methodIds + for (String method : methods) { + + List methParams = intDecl.getMethodParams(method); + List methPrmTypes = intDecl.getMethodParamTypes(method); + // Check for params with structs + for (int i = 0; i < methParams.size(); i++) { + String paramType = methPrmTypes.get(i); + String param = methParams.get(i); + String simpleType = getSimpleType(paramType); + if (isStructClass(simpleType)) { + int methodNumId = intDecl.getMethodNumId(method); + print("public int ___"); + String helperMethod = methodNumId + "struct" + i; + println(helperMethod + "() {"); + // Now, write the helper body of skeleton! + println("Object[] paramObj = rmiObj.getMethodParams(new Class[] { int.class }, new Class[] { null });"); + println("return (int) paramObj[0];"); + println("}\n"); + } + } + } + } + + + /** + * HELPER: writeCountVarStructJavaSkeleton() writes counter variable of struct for skeleton + */ + private void writeCountVarStructJavaSkeleton(Collection methods, InterfaceDecl intDecl) { + + // Use this set to handle two same methodIds + for (String method : methods) { + + List methParams = intDecl.getMethodParams(method); + List methPrmTypes = intDecl.getMethodParamTypes(method); + // Check for params with structs + for (int i = 0; i < methParams.size(); i++) { + String paramType = methPrmTypes.get(i); + String param = methParams.get(i); + String simpleType = getSimpleType(paramType); + if (isStructClass(simpleType)) { + int methodNumId = intDecl.getMethodNumId(method); + println("int struct" + methodNumId + "Size" + i + " = 0;"); + } + } + } + } + + + /** + * HELPER: writeInputCountVarStructJavaSkeleton() writes counter variable of struct for skeleton + */ + private void writeInputCountVarStructJavaSkeleton(String method, InterfaceDecl intDecl) { + + List methParams = intDecl.getMethodParams(method); + List methPrmTypes = intDecl.getMethodParamTypes(method); + // Check for params with structs + for (int i = 0; i < methParams.size(); i++) { + String paramType = methPrmTypes.get(i); + String param = methParams.get(i); + String simpleType = getSimpleType(paramType); + boolean begin = true; + if (isStructClass(simpleType)) { + if (!begin) { + print(", "); begin = false; + } + int methodNumId = intDecl.getMethodNumId(method); + print("struct" + methodNumId + "Size" + i); + } + } + } + + + /** + * HELPER: writeMethodCallStructJavaSkeleton() writes method call for wait invoke in skeleton + */ + private void writeMethodCallStructJavaSkeleton(Collection methods, InterfaceDecl intDecl) { + + // Use this set to handle two same methodIds + for (String method : methods) { + + List methParams = intDecl.getMethodParams(method); + List methPrmTypes = intDecl.getMethodParamTypes(method); + // Check for params with structs + for (int i = 0; i < methParams.size(); i++) { + String paramType = methPrmTypes.get(i); + String param = methParams.get(i); + String simpleType = getSimpleType(paramType); + if (isStructClass(simpleType)) { + int methodNumId = intDecl.getMethodNumId(method); + print("case "); + String helperMethod = methodNumId + "struct" + i; + String tempVar = "struct" + methodNumId + "Size" + i; + print(intDecl.getHelperMethodNumId(helperMethod) + ": "); + print(tempVar + " = ___"); + println(helperMethod + "(); break;"); + } + } } } @@ -1323,6 +1972,7 @@ public class IoTCompiler { Set uniqueMethodIds = new HashSet(); println("private void ___waitRequestInvokeMethod() throws IOException {"); // Write variables here if we have callbacks or enums or structs + writeCountVarStructJavaSkeleton(methods, intDecl); println("while (true) {"); println("rmiObj.getMethodBytes();"); println("int _objectId = rmiObj.getObjectId();"); @@ -1340,7 +1990,9 @@ public class IoTCompiler { helperMethod = helperMethod + methodNumId; else uniqueMethodIds.add(methodId); - println(helperMethod + "(); break;"); + print(helperMethod + "("); + writeInputCountVarStructJavaSkeleton(method, intDecl); + println("); break;"); } String method = "___initCallBack()"; // Print case -9999 (callback handler) if callback exists @@ -1348,6 +2000,7 @@ public class IoTCompiler { int methodId = intDecl.getHelperMethodNumId(method); println("case " + methodId + ": ___regCB(); break;"); } + writeMethodCallStructJavaSkeleton(methods, intDecl); println("default: "); println("throw new Error(\"Method Id \" + methodId + \" not recognized!\");"); println("}"); @@ -3405,9 +4058,14 @@ public class IoTCompiler { // Handle and return the correct struct declaration private String getStructType(String type) { - if (isStructClass(type)) { - // TODO: complete this method - return type; + // Strips off array "[]" for return type + String pureType = getSimpleArrayType(type); + // Take the inner type of generic + if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) + pureType = getTypeOfGeneric(type)[0]; + if (isStructClass(pureType)) { + String structType = "int"; + return structType; } else return type; } @@ -3443,6 +4101,36 @@ public class IoTCompiler { } + // Return a struct declaration + private StructDecl getStructDecl(String type) { + + // Just iterate over the set of interfaces + for (String intface : mapIntfacePTH.keySet()) { + DeclarationHandler decHandler = mapIntDeclHand.get(intface); + StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface); + List listStructDecl = structDecl.getStructTypes(); + if (listStructDecl.contains(type)) + return structDecl; + } + return null; + } + + + // Return number of members (-1 if not found) + private int getNumOfMembers(String type) { + + // Just iterate over the set of interfaces + for (String intface : mapIntfacePTH.keySet()) { + DeclarationHandler decHandler = mapIntDeclHand.get(intface); + StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface); + List listStructDecl = structDecl.getStructTypes(); + if (listStructDecl.contains(type)) + return structDecl.getNumOfMembers(type); + } + return -1; + } + + // Generate a set of classes for include statements private Set getIncludeClasses(Collection methods, InterfaceDecl intDecl, String intface, boolean needExchange) { @@ -3531,6 +4219,18 @@ public class IoTCompiler { } + // Gets generic type inside "<" and ">" + private String getGenericType(String type) { + + // Handle <, >, and , for 2-type generic/template + if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) { + String[] substr = type.split("<")[1].split(">")[0].split(","); + return substr[0]; + } else + return type; + } + + // This helper function strips off array declaration, e.g. int[] becomes int private String getSimpleArrayType(String type) { @@ -3576,6 +4276,9 @@ public class IoTCompiler { return cplusTemplate; } else return getNonPrimitiveCplusClass(paramType); + } else if(paramType.contains("[]")) { // Array type (used for return type only) + String cArray = "vector<" + getSimpleArrayType(paramType) + ">"; + return cArray; } else if(getParamCategory(paramType) == ParamCategory.USERDEFINED) { return paramType + "*"; } else diff --git a/iotjava/iotpolicy/tree/StructDecl.java b/iotjava/iotpolicy/tree/StructDecl.java index ef58b55..75ef1d1 100644 --- a/iotjava/iotpolicy/tree/StructDecl.java +++ b/iotjava/iotpolicy/tree/StructDecl.java @@ -105,4 +105,14 @@ public class StructDecl extends Declaration { int index = listStructs.indexOf(structType); return listMembers.get(index); } + + + /** + * getNumOfMembers() gets number of members + */ + public int getNumOfMembers(String structType) { + + int index = listStructs.indexOf(structType); + return listMembers.get(index).size(); + } } diff --git a/iotjava/iotrmi/Java/sample/TestClass_Stub.java b/iotjava/iotrmi/Java/sample/TestClass_Stub.java index bb6df9b..2a45396 100644 --- a/iotjava/iotrmi/Java/sample/TestClass_Stub.java +++ b/iotjava/iotrmi/Java/sample/TestClass_Stub.java @@ -250,7 +250,7 @@ public class TestClass_Stub implements TestClassInterface { paramCls2[pos] = int.class; paramObj2[pos++] = data[i].year; } - System.out.println(Arrays.toString(paramObj2)); + //System.out.println(Arrays.toString(paramObj2)); Object retObj = rmiCall.remoteCall(objectId, methodId2, retType2, null, paramCls2, paramObj2); // RETURN STRUCT // Get the length of the struct first