// -*- mode:C++; tab-width:2; c-basic-offset:2; indent-tabs-mode:nil -*-
//
// Copyright (C) 2000-2005 by Roger Rene Kommer / artefaktur, Kassel, Germany.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public License (LGPL).
//
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// License ACDK-FreeLicense document enclosed in the distribution
// for more for more details.
// This file is part of the Artefaktur Component Development Kit:
// ACDK
//
// Please refer to
// - http://www.acdk.de
// - http://www.artefaktur.com
// - http://acdk.sourceforge.net
// for more information.
//
#include "MethodInfo.h"
#include "ArgumentInfo.h"
#include "MetaCompiler.h"
#include "EnumArgAttribute.h"
#include "SetDispatchAttribute.h"
#include <acdk/lang/System.h>
namespace acdk {
namespace tools {
namespace mc {
using namespace acdk::lang::dmi;
MethodInfo::MethodInfo(IN(RTypeScope) parent, IN(RClassInfo) clsInfo, int accessflags)
: CodeInfo(accessflags, "", parent)
, _classInfo(clsInfo)
, args(new ArrayList())
, argcount(-1)
, _throws(new ArrayList())
, _altName(Nil)
{
flags |= MiMcKnownType;
}
//foreign
acdk::lang::Object
MethodInfo::clone(sys::Allocator* alc)
{
RMethodInfo ni = new (alc) MethodInfo(_parent, _classInfo, flags);
ni->_props = _props;
ni->name = name;
ni->flags = flags;
ni->returnType = returnType;
RIterator it = args->iterator();
ni->args = new ArrayList();
while (it->hasNext() == true)
{
acdk::lang::Object na = it->next()->clone(alc);
RArgumentInfo(na)->_parent = ∋
ni->args->add(na);
}
/*ni->args = (RArrayList)args->clone(alc);
RIterator it = ni->args->iterator();
while (it->hasNext() == true)
{
RArgumentInfo(it->next())->_parent = ni;
}
*/
ni->argcount = argcount;
ni->_javaSignature = _javaSignature;
ni->_throws = _throws;
return ∋
}
//virtual
RString
MethodInfo::getMetaInfoCIdentifier()
{
return _classInfo->name + "_method_" + getJavaSignature(true, argcount);
}
bool
MethodInfo::needMethodInfo()
{
return //(flags & ClazzIsKnownType) &&
_classInfo->needMethodInfo();
}
RString
getJavaSigOfTypename(IN(RString) tp)
{
if (tp->equals("void") == true)
return "V";
if (tp->equals("bool") == true)
return "Z";
if (tp->equals("byte") == true)
return "B";
if (tp->equals("char") == true)
return "C";
if (tp->equals("ucchar") == true || tp->equals("ucchar") == true)
return "UC";
if (tp->equals("short") == true)
return "S";
if (tp->equals("int") == true)
return "I";
/*if (tp->equals("long") == true)
return "L";*/
if (tp->equals("jlong") == true)
return "J";
if (tp->equals("float") == true)
return "F";
if (tp->equals("double") == true)
return "D";
return "L" + tp->replace("::", "/") + ";";
}
RString
getJavaSigOfAsCIdentifier(IN(RString) typ)
{
return typ->replace(":", "_")
->replace(".", "_")
->replace(".", "_")
->replace("/", "_")
->replace("(", "_")
->replace(")", "_")
->replace(";", "_")
->replace("<", "_") // templates
->replace(">", "_") // templates
->replace(" ", "_"); // templates
}
RString
MethodInfo::getJavaSignature(bool cidentifier, int argcount)
{
if (_javaSignature != Nil && argcount == -1) {
return cidentifier ? getJavaSigOfAsCIdentifier(_javaSignature) : _javaSignature;
}
StringBuffer sig(256);
sig.append(name);
sig.append("(");
int ac = argcount;
if (ac == -1)
ac = args->size();
RIterator it = args->iterator();
while (it->hasNext() == true && ac-- != 0)
{
RArgumentInfo ai = (RArgumentInfo)it->next();
if (ai->flags & MiAiByval)
sig.append("BYVAL");
if (ai->flags & MiAiIn)
sig.append("IN");
if (ai->flags & MiAiOut)
sig.append("OUT");
sig.append(getJavaSigOfTypename(ai->getMappedType()));
}
sig.append(")");
if (returnType != Nil) {
sig.append(getJavaSigOfTypename(returnType));
}
if (argcount == -1) {
_javaSignature = sig.toString();
return cidentifier ? getJavaSigOfAsCIdentifier(_javaSignature) : _javaSignature;
}
RString tstr = sig.toString();
return cidentifier ? getJavaSigOfAsCIdentifier(tstr) : tstr;
}
RMethodInfoArray
MethodInfo::getFixedParametersMethods()
{
int nodefargslength = getNoDefaultArgCount();
int allargslength = args->size();
if (allargslength == nodefargslength)
{
RMethodInfoArray mia = new MethodInfoArray(1);
argcount = nodefargslength;
mia[0] = this;
flags |= MiMiOrgPoly;
return mia;
}
int difmethodcount = allargslength - nodefargslength + 1;
RMethodInfoArray mia = new MethodInfoArray(difmethodcount);
argcount = allargslength;
mia[0] = this;
for (int i = 1; i < difmethodcount; ++i)
{
RMethodInfo ni = (RMethodInfo)clone();
ni->argcount = nodefargslength + i - 1;
mia[i] = ni;
}
flags |= MiMiOrgPoly;
return mia;
}
//virtual
RString
MethodInfo::toString()
{
if (_javaSignature == Nil)
_javaSignature = "";
if (name == Nil)
name = "<unknonwn name>";
return returnType + " " + _classInfo->name + "::" + name + "(" + _javaSignature + ")";
}
int
MethodInfo::getNoDefaultArgCount()
{
RIterator it = args->iterator();
int nodefargslength = 0;
while (it->hasNext() == true) {
RArgumentInfo ai = (RArgumentInfo)it->next();
if (ai->hasDefaultInitializer == true)
break;
++nodefargslength;
}
return nodefargslength;
}
bool
MethodInfo::isCreateInstance()
{
if ((MetaInfo::isStatic(flags) == true) && (name->equals("create_instance") == true))
{
return true;
}
return false;
}
bool
MethodInfo::checkModifier(IN(RStreamTokenizer) in)
{
if (in->sval->equals("oneway") == true)
{
flags |= MiMiOneway;
return true;
}
if (in->sval->equals("static") == true)
{
flags |= MiStatic;
return true;
}
if (in->sval->equals("virtual") == true)
{
flags |= MiMiVirtual;
return true;
}
if (in->sval->equals("overwrite") == true)
{
flags |= MiMiVirtual;
_localMcFlags |= McConfNoMetaInfo;
return true;
}
if (in->sval->equals("inline") == true || in->sval->equals("explicit") == true)
return true;
return false;
}
RString
parseOperator(IN(RStreamTokenizer) in)
{
int tk;
bool first = true;
StringBuffer sb;
while ((tk = in->nextToken()) != StreamTokenizer::TT_EOF)
{
if (tk == StreamTokenizer::TT_WORD) // operator new() operator delete
{
sb.append(in->sval);
first = false;
continue;
}
if (tk == '(')
{
if (first == false)
{
in->pushBack();
return sb.toString();
}
else
{
sb.append(char(tk));
}
}
else
{
sb.append(char(tk));
}
first = false;
}
return "";
}
int
getFlag(IN(RString) cargtype)
{
int argflag = 0;
if (cargtype->equals("IN") == true || cargtype->equals("INP") == true)
argflag |= MiAiIn;
else if (cargtype->equals("OUT") == true || cargtype->equals("OUTP") == true)
argflag |= MiAiOut;
else if (cargtype->equals("INOUT") == true || cargtype->equals("INOUTP") == true)
argflag |= MiAiOut | MiAiIn;
else if (cargtype->equals("READONLY") == true)
argflag |= MiReadOnly;
else if (cargtype->equals("BYVAL") == true || cargtype->equals("BYVALP") == true)
argflag |= MiAiByval;
else if (cargtype->equals("BYVALIN") == true || cargtype->equals("BYVALINP") == true)
argflag |= MiAiByval | MiAiIn;
else if (cargtype->equals("BYVALOUT") == true || cargtype->equals("BYVALOUTP") == true)
argflag |= MiAiByval | MiAiOut;
else if (cargtype->equals("BYVALINOUT") == true || cargtype->equals("BYVALINOUTP") == true)
argflag |= MiAiByval | MiAiIn | MiAiOut;
else if (cargtype->equals("BYREF") == true || cargtype->equals("BYREFIN") == true)
argflag |= MiAiByref | MiAiIn;
else if (cargtype->equals("BYREFOUT") == true)
argflag |= MiAiByref | MiAiOut;
else if (cargtype->equals("BYREFINOUT") == true)
argflag |= MiAiByref | MiAiOut | MiAiIn;
return argflag;
}
RString
readSkipExpression(IN(RStreamTokenizer) in)
{
StringBuffer sb;
int tk;
int openBrackets = 0;
do {
tk = in->nextToken();
if (tk == StreamTokenizer::TT_EOF)
return sb.toString();
if (tk == '(')
++openBrackets;
else if (tk == ')')
{
if (openBrackets == 0)
break;
--openBrackets;
}
else if (tk == ',' && openBrackets == 0)
break;
sb.append(in->toCode());
} while (true);
in->pushBack();
return sb.toString();
}
bool
MethodInfo::parse(IN(RStreamTokenizer) in)
{
int tk;
int openbrackets = 0;
enum Expect
{
Modifier,
//ReturnValue,
FuncName,
OperatorOps,
OpenArgBracket,
ArgType,
ArgName,
BeginBody,
StartExceptions,
ExceptionsDeclarator,
EndExceptionsDeclarator
};
RString cargtype;
Expect expect = Modifier;
RTokenStack tkstack = new TokenStack(in);
WantWhiteSpaceOnStack _wantWS(in, true);
bool hasDefaultInitializer = false;
RArgumentInfo lastargument = Nil;
int argflag = 0;
while ((tk = in->nextToken()) != StreamTokenizer::TT_EOF) {
tkstack->push();
if (tk == StreamTokenizer::TT_WS)
continue;
if (in->sval->startsWith("ACDK_") == true)
continue;
switch (expect) {
case Modifier :
if (tk == '~')
{
tk = in->nextToken();
flags |= MiMiDestructor;
returnType = "void";
expect = FuncName;
continue;
}
if (tk == ':')
continue;
if (tk != StreamTokenizer::TT_WORD) {
return false;
}
if (MetaCompiler::isAccessToken(in->sval))
continue;
if (checkModifier(in) == true)
continue;
if (isInvalidDeclStartIdentifier(in->sval) == true)
return false;
if (in->sval->equals(_classInfo->name) == true && (flags & MiMiDestructor) == 0)
{
flags |= MiMiConstructor;
returnType = "R" + _classInfo->name;
name = in->sval;
expect = OpenArgBracket;
}
else
{
int argflag = getFlag(in->sval);
if (argflag != 0)
{
flags |= argflag;
tk = in->nextToken();
if (tk != '(')
return false;
returnType = MetaCompiler::readComponentIndentifier(in);
tk = in->nextToken();
if (tk != ')')
return false;
}
else
{
in->pushBack();
returnType = MetaCompiler::readComponentIndentifier(in);
}
if (checkCompatibleType(returnType) == false)
{
if (needMethodInfo())
ACDK_LOG(Note, in->getStreamPos() + ": Ignore Method because incompatible return type: [" + returnType + "]: " + toString());
checkCompatibleType(returnType);
flags &= ~MiMcKnownType;
}
else
{
if (hasType(returnType) == TsEnum)
addCodeAttribute(new EnumArgAttribute(returnType));
}
expect = FuncName;
}
break;
/*
case ReturnValue :
if (in->sval->equals("oneway") == true) {
flags |= MiMiOneway;
expect = ReturnValue;
break;
}
in->pushBack();
returnType = MetaCompiler::readComponentIndentifier(in);
if (checkCompatibleType(returnType) == false) {
log(Note, in, "Ignore Method because incompatible return type: " + toString());
checkCompatibleType(returnType);
flags &= ~MiMcKnownType;
}
expect = FuncName;
break;
*/
case FuncName :
{
if (tk != StreamTokenizer::TT_WORD)
return false;
name = in->sval;
//System::out->println("Parse func name: " + name);
if (name->equals("operator") == true)
expect = OperatorOps;
else
expect = OpenArgBracket;
break;
}
case OperatorOps:
{
in->pushBack();
_operatorName = parseOperator(in);
name = acdk::lang::reflect::Method::encodeOperatorToFuncName(_operatorName);
expect = OpenArgBracket;
break;
}
case OpenArgBracket:
if (tk != '(')
return false;
expect = ArgType;
break;
case ArgType:
if (tk == '=')
{ // default initializer
StringBuffer defsb(" =");
if (lastargument != Nil)
lastargument->hasDefaultInitializer = true;
defsb.append(readSkipExpression(in));
tk = in->nextToken();
if (lastargument != Nil)
{
lastargument->defaultInitializer = defsb.toString();
lastargument->flags |= MiAiHasDefaultInit;
}
if (tk == ')')
{
expect = BeginBody;
break;
}
expect = ArgType;
break;
}
hasDefaultInitializer = false;
if (tk == ',')
break;
if (tk == ')') {
expect = BeginBody;
break;
}
in->pushBack();
cargtype = MetaCompiler::readComponentIndentifier(in);
argflag = getFlag(cargtype);
if (argflag != 0)
{
tk = in->nextToken();
if (tk != '(')
return false;
cargtype = MetaCompiler::readComponentIndentifier(in);
tk = in->nextToken();
if (tk != ')')
return false;
}
if (checkCompatibleType(cargtype) == false)
{
if (needMethodInfo())
ACDK_LOG(Note, in->getStreamPos() + ": Ignore Method because incompatible argument type: ["
+ cargtype + "] in method: " + toString());
flags &= ~MiMcKnownType;
}
expect = ArgName;
break;
case ArgName :
hasDefaultInitializer = false;
if (tk != StreamTokenizer::TT_WORD)
return false;
lastargument = new ArgumentInfo(this, cargtype, in->sval, argflag);
if (hasType(cargtype) == TsEnum)
{
lastargument->addCodeAttribute(new EnumArgAttribute(cargtype));
}
args->add((acdk::lang::Object)lastargument);
expect = ArgType;
break;
case BeginBody :
if (tk == StreamTokenizer::TT_WORD && in->sval->equals("const") == true)
{
flags |= MiReadOnly;
break;
}
if (isConstructor() && tk == ':')
{
MetaCompiler::skipUntilToken(in, '{');
tk = '{';
}
if (tk == '=')
{
flags |= MiMiAbstract;
do {
tk = in->nextToken();
} while (tk == StreamTokenizer::TT_WS);
if (tk != StreamTokenizer::TT_NUMBER || in->nval->intValue() != 0)
return false;
do {
tk = in->nextToken();
} while (tk == StreamTokenizer::TT_WS);
if (tk != ';')
return false;
flags |= MiMiAbstract;
tkstack->flush();
return true;
} else if (tk == '{') {
int bcount = 1;
while ((tk = in->nextToken()) != StreamTokenizer::TT_EOF) {
if (tk == '{')
++bcount;
else if (tk == '}') {
--bcount;
if (bcount == 0)
{
goto endOfParse;
}
}
}
return false;
} else if (tk == ';') {
tkstack->flush();
return name != Nil;
} else if (tk == StreamTokenizer::TT_WORD) {
if (in->sval->equals("throw") ||
in->sval->startsWith("THROWS"))
{
expect = StartExceptions;
if (in->sval->equals("throw") == true)
{
TokenStack tklocal(in);
tk = in->nextToken();
tklocal.push();
if (tk == '(')
{
tk = in->nextToken();
tklocal.push();
if (tk == ')')
{
tklocal.flush();
expect = BeginBody;
continue;
}
}
ACDK_LOG(Warn, in->getStreamPos() + ": Use the THROWS* macoros instead throw in function specifications");
}
break;
} else {
return false;
}
}
case StartExceptions :
if (tk != '(')
return false;
expect = ExceptionsDeclarator;
break;
case ExceptionsDeclarator:
if (tk != StreamTokenizer::TT_WORD)
return false;
_throws->add((acdk::lang::Object)in->sval);
expect = EndExceptionsDeclarator;
break;
case EndExceptionsDeclarator :
if (tk == ',')
expect = ExceptionsDeclarator;
else if (tk == ')')
expect = BeginBody;
break;
}
}
endOfParse:
tkstack->flush();
return name != Nil;
}
bool
MethodInfo::detectPureVirtualMethod(IN(RStreamTokenizer) in)
{
int tk;
TokenStack tkstack(in);
WantWhiteSpaceOnStack _wantWS(in, true);
bool attn = false;
while ((tk = in->nextToken()) != StreamTokenizer::TT_EOF) {
tkstack.push();
if (tk == ';' || tk == '{')
return false;
if (tk == ')')
attn = true;
if (attn == true && tk == '=') {
do {
tk = in->nextToken();
tkstack.push();
} while (tk == StreamTokenizer::TT_WS);
if (tk == StreamTokenizer::TT_NUMBER && in->nval->intValue() == 0) {
do {
tk = in->nextToken();
tkstack.push();
} while (tk == StreamTokenizer::TT_WS);
if (tk == ';')
return true;
}
}
}
return false;
}
void
MethodInfo::writeThrowDispatch(IN(RPrintWriter) out, IN(RClassInfo) clsinfo, int argcount)
{
if (_throws->size() == 0)
return;
out->print("void " + clsinfo->name + "_" + getJavaSignature(true, argcount) + "_throwDispatch(IN(::acdk::lang::RThrowable) ex)\n");
out->print("{\n");
RIterator it = _throws->iterator();
while (it->hasNext() == true)
{
RString t = (RString)it->next();
int idx = t->lastIndexOf("::");
if (idx == -1)
{
out->print(" if (instanceof(ex, " + t->substr(1) + ") == true)\n THROW_INSTANCE( " + t + "(ex));\n");
}
else
{
RString ns = t->substr(0, idx + 2);
RString cls = t->substr(idx + 2);
out->print(" if (instanceof(ex, " + ns + cls->substr(1) + ") == true)\n THROW_INSTANCE( " + t + "(ex));\n");
}
}
out->print("}\n\n");
}
void
MethodInfo::writeInfo(IN(RPrintWriter) out, IN(RClassInfo) clsinfo, int argcount)
{
if (ClassInfo::isCompatibleType(flags) == false || isDestructor() == true)
return;
if (generateMetaInfo(true) == false)
return;
int ac = argcount;
if (ac == -1)
ac = args->size();
RIterator it = args->iterator();
RString clsname = clsinfo->name;
while (it->hasNext() == true && ac-- > 0)
{
RArgumentInfo ai = (RArgumentInfo)it->next();
if (ai->_parent != this)
System::out->println("Ooops");
out->print("::acdk::lang::dmi::ClazzMethodArgInfo " + clsname + "_methods_" + getJavaSignature(true, argcount) + "_arg_" + ai->name + " = \n{\n");
//out->print("::acdk::lang::dmi::ClazzMethodArgInfo " + ai->getMetaInfoCIdentifier() + " = \n{\n");
out->print(RString(" ") + MetaInfo::flagsToString((ai->flags | MiMethodArgInfo) & ~MiMcKnownType, MethodArgInfoExtFlags(0), TpFtFqName | TpFtAcdkType) + ", \n");
out->print(" 0, //AttributesRes\n");
out->print(RString(" \"") + ai->getDmiName() + "\", // name of arg\n");
out->print(" -1, // hashCode\n");
out->print(" \"\", // ns\n");
out->print(" 0, // _scopeParent\n");
out->print(" 0, // _nextSibling\n");
out->print(RString(" ") + clazzInfoExpr(ai->getMappedType()) + " // type or arg\n");
out->print("};\n\n");
}
out->print("::acdk::lang::dmi::ClazzMethodArgInfo* " + clsname + "_methods_" + getJavaSignature(true, argcount) + "_args[] = \n{\n");
it = args->iterator();
ac = argcount;
if (ac == -1)
ac = args->size();
while (it->hasNext() == true && ac-- > 0)
{
RArgumentInfo ai = (RArgumentInfo)it->next();
out->print(" &" + clsname + "_methods_" + getJavaSignature(true, argcount) + "_arg_" + ai->name + ",\n");
//out->print(" &" + ai->getMetaInfoCIdentifier() + ",\n");
}
out->print(" 0\n};\n\n");
out->print("::acdk::lang::dmi::ClazzInfo* " + clsname + "_methods_" + getJavaSignature(true, argcount) + "_exceptions[] =\n{\n");
it = _throws->iterator();
while (it->hasNext() == true)
{
RString t = (RString)it->next();
out->print(" " + t + "::clazzInfo(), \n");
}
out->print(" 0\n};\n\n");
writeThrowDispatch(out, clsinfo, argcount);
out->print("::acdk::lang::dmi::ClazzMethodInfo " + clsname + "_method_" + getJavaSignature(true, argcount) + " = \n{\n");
out->print(RString(" ") + MetaInfo::flagsToString((flags | MiMethodInfo) & ~MiMcKnownType, MethodInfoExtFlags(0), TpFtFqName | TpFtAcdkType) + ",// class flags, like static, \n");
out->print(" 0, //AttributesRes\n");
out->print(RString(" \"") + getDmiName() + "\", // name of method\n");
out->print(" -1, // hashCode\n");
out->print(" \"\", // ns\n");
out->print(" 0, // _scopeParent\n");
out->print(" 0, // _nextSibling\n");
if (isConstructor() == true)
out->print(RString(" ") + clsname + "::clazzInfo(), // return type\n");
else
out->print(RString(" ") + clazzInfoExpr(returnType) + ", // return type\n");
if (_altName != Nil)
out->print(RString(" \"") + _altName + "\", // alternative name of method\n");
else
out->print(" 0, // alternative name of method\n");
out->print(" -1, // altlabelHashCode\n");
//out->print(RString(" \"") + getJavaSignature(false, argcount) + "\", //java_signature\n");
out->print(RString(" ") + clsname + "_methods_" + getJavaSignature(true, argcount) + "_args, // the arguments\n");
out->print(" 0, //arguments count\n");
out->print(" " + clsname + "_methods_" + getJavaSignature(true, argcount) + "_exceptions, // the declared exceptions\n");
if (MetaCompiler::externalMetaInfo == true)
{
RString clssig = clsinfo->getDispatchSignature(MetaInfo::isStatic(flags));
RString sig = getDispatchSignature(MetaInfo::isStatic(flags));
if ((clsinfo->flags & MiCiAbstract) != MiCiAbstract || (isConstructor() == false && (clssig == Nil || sig != Nil)))
{
if (sig == Nil)
out->print(" " + clsinfo->name + "_MetainfoWrapper::" + getMetaInfoCIdentifier() + "_dispatch, // invoke this method\n");
else
out->print(" " + sig + ", // invoke this method\n");
}
else
{
if (clssig != Nil)
out->print(" " + clssig + ", // invoke this method");
else
{
//ACDK_LOG(Warn, "This method cannot be invoked directly: " + toString());
out->print(" 0, // this method cannot be invoked because abstract\n");
/*if (MetaInfo::isStatic(flags) == true)
out->print(" ::acdk::lang::dmi::StdDispatch::_invoke_static, // invoke this method\n");
else
out->print(" ::acdk::lang::dmi::StdDispatch::_invoke_dynamic, // invoke this method\n");
*/
//clsinfo->getDispatchSignature(MetaInfo::isStatic(flags));
}
}
}
if (_throws->size() > 0)
{
out->print(" " + clsname + "_" + getJavaSignature(true, argcount) + "_throwDispatch, // dispatch throwing exceptions\n");
}
else
{
out->print(" ::acdk::lang::dmi::ClazzMethodInfo::DefaultDispatchThrowableFunc, // dispatch throwing exceptions\n");
}
out->print(" 0 // cached method signature hash\n");
out->print("};\n\n");
}
void
MethodInfo::writeInfo(IN(RPrintWriter) out, IN(RClassInfo) clsinfo)
{
writeInfo(out, clsinfo, argcount);
/*
int allargslength = args->size();
int nodefargslength = getNoDefaultArgCount();
if (allargslength == nodefargslength) {
writeInfo(out, clsinfo, -1);
return;
}
while (allargslength >= nodefargslength)
{
writeInfo(out, clsinfo, nodefargslength);
++nodefargslength;
}*/
}
void
MethodInfo::writeMethodList(IN(RPrintWriter) out, IN(RClassInfo) clsinfo)
{
if (ClassInfo::isCompatibleType(flags) == false || (isDestructor() == true))
return;
out->print(" &" + clsinfo->name + "_method_" + getJavaSignature(true, argcount) + ",\n");
}
static
RString
getRetConverter(IN(RMethodInfo) mi)
{
if (mi->flags & MiAiOut)
{
if (mi->flags & MiAiIn)
return "inoutOf(";
else
return "outOf(";
}
return "";
}
RString
getVarConverter(IN(RString) tn, IN(RString) vn, int flags, bool isEnum)
{
if (MiAiOut & flags /*&& !(MiAiByVal & flags)*/)
{
if (isEnum == true)
return "(" + tn + "&)::acdk::lang::dmi::castToRef<int>(" + vn + ", dc)";
if (tn->equals("bool") == true)
return "::acdk::lang::dmi::castToBoolRef(" + vn + ", dc)";// return vn + ".getBoolRef()";
if (tn->equals("char") == true)
return "::acdk::lang::dmi::castToCharRef(" + vn + ", dc)"; //return vn + ".getCharRef()";
if (tn->equals("ucchar") == true || tn->equals("uc2char") == true)
return "::acdk::lang::dmi::castToUcCharRef(" + vn + ", dc)"; //return vn + ".getUcCharRef()";
if (tn->equals("byte") == true)
return "::acdk::lang::dmi::castToByteRef(" + vn + ", dc)"; //return vn + ".getByteRef()";
if (tn->equals("short") == true)
return "::acdk::lang::dmi::castToShortRef(" + vn + ", dc)"; //return vn + ".getShortRef()";
if (tn->equals("int") == true)
return "::acdk::lang::dmi::castToIntRef(" + vn + ", dc)"; //return vn + ".getIntRef()";
if (tn->equals("jlong") == true)
return "::acdk::lang::dmi::castToLongRef(" + vn + ", dc)"; //return vn + ".getLongRef()";
if (tn->equals("float") == true)
return "::acdk::lang::dmi::castToFloatRef(" + vn + ", dc)"; //return vn + ".getFloatRef()";
if (tn->equals("double") == true)
return "::acdk::lang::dmi::castToDoubleRef(" + vn + ", dc)"; //return vn + ".getDoubleRef()";
return "::acdk::lang::dmi::castToObjectRef< " + tn + ">(" + vn + ", dc)";
//return " ::acdk::lang::getTypedObjectRef< " + tn + " >(" + vn + ")";
}
if (isEnum == true)
return "(" + tn + ")::acdk::lang::dmi::castTo<int>(" + vn + ", dc)";
return "::acdk::lang::dmi::castTo< " + tn + ">(" + vn + ", dc)";
/*
//return "(" + tn + ")" + vn + ".getIntVar()";
if (tn->equals("bool") == true)
return vn + ".getBoolVar()";
if (tn->equals("char") == true)
return vn + ".getCharVar()";
if (tn->equals("ucchar") == true || tn->equals("uc2char") == true)
return vn + ".getUcCharVar()";
if (tn->equals("byte") == true)
return vn + ".getByteVar()";
if (tn->equals("short") == true)
return vn + ".getShortVar()";
if (tn->equals("int") == true)
return vn + ".getIntVar()";
if (tn->equals("jlong") == true)
return vn + ".getLongVar()";
if (tn->equals("float") == true)
return vn + ".getFloatVar()";
if (tn->equals("double") == true)
return vn + ".getDoubleVar()";
return "(" + tn + ")" + vn + ".getObjectVar()";
*/
}
static
RString
getArgConverter(IN(RArgumentInfo) ai, int argcount)
{
RString tn = ai->getOrgType();
int flags = ai->flags;
return getVarConverter(tn, RString("args[") + argcount + "]", flags, ai->isEnum());
/*
if (MiAiOut & flags )
{
if (tn->equals("bool") == true)
return RString("args[") + argcount + "].getBoolRef()";
if (tn->equals("char") == true)
return RString("args[") + argcount + "].getCharRef()";
if (tn->equals("ucchar") == true || tn->equals("uc2char") == true)
return RString("args[") + argcount + "].getUcCharRef()";
if (tn->equals("byte") == true)
return RString("args[") + argcount + "].getByteRef()";
if (tn->equals("short") == true)
return RString("args[") + argcount + "].getShortRef()";
if (tn->equals("int") == true)
return RString("args[") + argcount + "].getIntRef()";
if (tn->equals("jlong") == true)
return RString("args[") + argcount + "].getLongRef()";
if (tn->equals("float") == true)
return RString("args[") + argcount + "].getFloatRef()";
if (tn->equals("double") == true)
return RString("args[") + argcount + "].getDoubleRef()";
if (ai->isEnum() == true)
return "(" + tn + "&)args[" + argcount + "].getIntRef()";
return " ::acdk::lang::getTypedObjectRef< " + tn + " >(" + RString("args[") + argcount + "])";
}
if (ai->isEnum() == true)
return "(" + tn + ")args[" + argcount + "].getIntVar()";
if (tn->equals("bool") == true)
return RString("args[") + argcount + "].getBoolVar()";
if (tn->equals("char") == true)
return RString("args[") + argcount + "].getCharVar()";
if (tn->equals("ucchar") == true || tn->equals("uc2char") == true)
return RString("args[") + argcount + "].getUcCharVar()";
if (tn->equals("byte") == true)
return RString("args[") + argcount + "].getByteVar()";
if (tn->equals("short") == true)
return RString("args[") + argcount + "].getShortVar()";
if (tn->equals("int") == true)
return RString("args[") + argcount + "].getIntVar()";
if (tn->equals("jlong") == true)
return RString("args[") + argcount + "].getLongVar()";
if (tn->equals("float") == true)
return RString("args[") + argcount + "].getFloatVar()";
if (tn->equals("double") == true)
return RString("args[") + argcount + "].getDoubleVar()";
return "(" + tn + ")" + RString("args[") + argcount + "].getObjectVar()";
*/
}
void
MethodInfo::writeDispatchBody2(IN(RPrintWriter) out, IN(RClassInfo) clsinfo, int argcount, bool novirtual)
{
bool hasret = false;
RString nativeMethodName = name;
if (_operatorName != Nil)
nativeMethodName = "operator" + _operatorName;
if (MetaCompiler::externalMetaInfo == true)
{
if (isStatic() == true)
{
nativeMethodName = clsinfo->name + "::" + nativeMethodName;
}
else if (novirtual == true)
nativeMethodName = "This->" + clsinfo->name + "::" + nativeMethodName;
else
{
nativeMethodName = "This->" + nativeMethodName;
}
}
if (isConstructor() == true)
{
if (clsinfo->isAbstract() == true)
return;
out->print(" ret = (::acdk::lang::RObject)new " + name + "(");
}
else if (returnType->equals("void") == true)
out->print(" " + nativeMethodName + "(");
else
{
if (flags & MiAiOut)
{
out->print(" ret = " + getRetConverter(this) + nativeMethodName + "(");
}
else if (isBasicType(mappedReturnType()) == true)
{
if (hasType(returnType) == TsEnum)
out->print(" ret = (" + returnType + ")" + nativeMethodName + "(");
else
out->print(" ret = " + nativeMethodName + "(");
hasret = true;
} else
out->print(" ret = (::acdk::lang::RObject)" + nativeMethodName + "(");
}
RIterator ait = args->iterator();
int ac = 0;
int argmaxcount = argcount;
while (ait->hasNext() == true && argmaxcount > 0) {
if (ac > 0)
out->print(", ");
RArgumentInfo ai = (RArgumentInfo)ait->next();
out->print(getArgConverter(ai, ac));
++ac;
--argmaxcount;
}
if (flags & MiAiOut)
out->print("));\n");
else
out->print(");\n");
}
void
MethodInfo::writeDispatchBody(IN(RPrintWriter) out, IN(RClassInfo) clsinfo, int argcount)
{
if (MetaCompiler::externalMetaInfo == false)
out->print(" if (&" + clsinfo->name + "_method_" + getJavaSignature(true, argcount) + " == methinf) {\n");
//out->print(" if (strcmp(methinf->java_signature, \"" + mi->getJavaSignature(false) + "\") == 0) {\n");
if (/*isVirtual() == true && */isAbstract() == false && isStatic() == false && isConstructor() == false)
{
out->print(" if (flags & ::acdk::lang::dmi::MiIvNoWeakBind)\n ");
writeDispatchBody2(out, clsinfo, argcount, true);
out->print(" else\n ");
writeDispatchBody2(out, clsinfo, argcount, false);
}
else
writeDispatchBody2(out, clsinfo, argcount, false);
out->print(" return methinf;\n");
if (MetaCompiler::externalMetaInfo == false)
out->print(" }\n");
}
void
MethodInfo::writeDispatchBody(IN(RPrintWriter) out, IN(RClassInfo) clsinfo)
{
writeDispatchBody(out, clsinfo, argcount);
/*
int nodefargslength = getNoDefaultArgCount();
int allargslength = args->size();
while (allargslength >= nodefargslength) {
writeDispatchBody(out, clsinfo, nodefargslength);
++nodefargslength;
}
*/
}
void
MethodInfo::writeProxyConstructor(IN(RPrintWriter) out, IN(RClassInfo) clsinfo)
{
if (argcount != args->size())
return;
if (flags & MiPublic)
out->print(" public:\n ");
else if (flags & MiProtected)
out->print(" protected:\n ");
else
out->print(" public:\n ");
out->print(clsinfo->name + "_MetainfoWrapper(IN(::acdk::lang::RObject) _acdk_dmi_server_");
RIterator ait = args->iterator();
int ac = 0;
while (ait->hasNext() == true)
{
out->print(", ");
RArgumentInfo ai = (RArgumentInfo)ait->next();
out->print(ai->toCode());
++ac;
}
out->print(", ::acdk::lang::dmi::DmiClient* _acdk_dmi_client_)\n : ");
out->print(clsinfo->name + "(");
ait = args->iterator();
ac = 0;
while (ait->hasNext() == true)
{
if (ac != 0)
out->print(", ");
RArgumentInfo ai = (RArgumentInfo)ait->next();
out->print(ai->name);
++ac;
}
out->print(")\n , DmiProxyBase(_acdk_dmi_server_, _acdk_dmi_client_)\n {\n }\n");
}
void
MethodInfo::writeProxyMethod(IN(RPrintWriter) out, IN(RClassInfo) clsinfo)
{
if (argcount != args->size())
return;
if (flags & MiPublic)
out->print(" public:\n ");
else if (flags & MiProtected)
out->print(" protected:\n ");
else
out->print(" public:\n ");
StringBuffer sb;
RMethodInfo mi = this;
sb.append(mi->returnType + " " + mi->name + "(");
RIterator ait = mi->args->iterator();
int ac = 0;
while (ait->hasNext() == true)
{
if (ac > 0)
sb.append(", ");
RArgumentInfo ai = (RArgumentInfo)ait->next();
sb.append(ai->toCode());
++ac;
}
sb.append(")");
if (mi->_throws->size() > 0)
{
sb.append(RString(" THROWS") + mi->_throws->size() + "(");
ac = 0;
RIterator throws = mi->_throws->iterator();
while (throws->hasNext() == true)
{
RString ct = (RString)throws->next();
if (ac > 0)
sb.append(", ");
sb.append(ct);
++ac;
}
sb.append(")");
}
sb.append("\n {\n");
sb.append(" ::acdk::lang::dmi::ScriptVar __acdk_retval;\n");
sb.append(" ::acdk::lang::dmi::ScriptVarArray __acdk_args(");
sb.append(mi->args->size());
sb.append(");\n");
ait = mi->args->iterator();
int i = 0;
while (ait->hasNext() == true)
{
RArgumentInfo ai = (RArgumentInfo)ait->next();
sb.append(RString(" __acdk_args[") + i + "] = ");
if (ai->flags & MiAiOut && ai->flags & MiAiIn)
{
sb.append("::acdk::lang::inoutOf(" + ai->name + ");\n");
} else if (ai->flags & MiAiOut)
sb.append("::acdk::lang::outOf(" + ai->name + ");\n");
else
sb.append("::acdk::lang::inOf(" + ai->name + ");\n");
++i;
}
sb.append(" _acdk_dmi_server->standardDispatch(" + STDDSP_STRING_CASTPLS(mi->name) + ", __acdk_retval, __acdk_args, DmiProxyBase::getDmiClient(), Nil, 0, _acdk_dmi_server->getClazzInfo(), 0);\n");
if (mi->returnType->equals("void") == false)
{
sb.append(" return ");
if (mi->hasType(mi->returnType) == TsEnum)
{
sb.append("(" + mi->returnType + ")(int)");
}
else if (mi->isBasicType(mi->returnType) == false)
{
sb.append("(" + mi->returnType + ")(::acdk::lang::RObject)");
}
sb.append("__acdk_retval;\n");
}
sb.append(" }\n");
out->print(sb.toString());
}
bool
MethodInfo::invokeCodeAttributes(IN(RModuleInfo) cm, IN(RClassInfo) ci)
{
int argmaxcount = argcount;
RIterator it = args->iterator();
while (it->hasNext() == true && argmaxcount > 0)
{
if (RArgumentInfo(it->next())->invokeCodeAttributes(cm, ci, this) == false)
return false;
--argmaxcount;
}
CodeInfo::invokeCodeAttributes();
return true;
}
void
MethodInfo::writeCodes(IN(RPrintWriter) out, CodeWhere where)
{
if (_genCode == -1)
return;
if ((flags & MiMcKnownType) == 0)
return;
int argmaxcount = argcount;
RIterator it = args->iterator();
while (it->hasNext() == true && argmaxcount > 0)
{
RArgumentInfo(it->next())->writeCode(out, where);
--argmaxcount;
}
writeCode(out, where);
}
} // namespace mc
} // namespace tools
} // namespace acdk
|