mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 20:03:02 +01:00
Added method's attribute "stub": makes it possible to have default trivial implementation for new methods in new versions of interfaces
This commit is contained in:
parent
314cb34358
commit
8b7ef73688
59
extern/cloop/src/cloop/Action.cpp
vendored
59
extern/cloop/src/cloop/Action.cpp
vendored
@ -94,39 +94,84 @@ void DefAction::generate(const ActionParametersBlock& apb, unsigned ident)
|
||||
switch(apb.language)
|
||||
{
|
||||
case LANGUAGE_C:
|
||||
if (!apb.statusName.empty())
|
||||
if (!apb.method->statusName.empty())
|
||||
{
|
||||
identify(apb, ident);
|
||||
fprintf(apb.out, "CLOOP_setVersionError(%s, \"%s%s\", cloopVTable->version, %d);\n",
|
||||
apb.statusName.c_str(), apb.prefix.c_str(),
|
||||
apb.method->statusName.c_str(), apb.prefix.c_str(),
|
||||
apb.interface->name.c_str(), apb.method->version);
|
||||
}
|
||||
break;
|
||||
|
||||
case LANGUAGE_CPP:
|
||||
if (!apb.statusName.empty())
|
||||
if (!apb.method->statusName.empty())
|
||||
{
|
||||
identify(apb, ident);
|
||||
fprintf(apb.out, "%s::setVersionError(%s, \"%s%s\", cloopVTable->version, %d);\n",
|
||||
apb.exceptionClass.c_str(), apb.statusName.c_str(), apb.prefix.c_str(),
|
||||
apb.exceptionClass.c_str(), apb.method->statusName.c_str(), apb.prefix.c_str(),
|
||||
apb.interface->name.c_str(), apb.method->version);
|
||||
identify(apb, ident);
|
||||
fprintf(apb.out, "%s::checkException(%s);\n",
|
||||
apb.exceptionClass.c_str(), apb.statusName.c_str());
|
||||
apb.exceptionClass.c_str(), apb.method->statusName.c_str());
|
||||
}
|
||||
break;
|
||||
|
||||
case LANGUAGE_PASCAL:
|
||||
if (!apb.statusName.empty() && !apb.exceptionClass.empty())
|
||||
if (!apb.method->statusName.empty() && !apb.exceptionClass.empty())
|
||||
{
|
||||
identify(apb, ident);
|
||||
fprintf(apb.out, "%s.setVersionError(%s, \'%s%s\', vTable.version, %d);\n",
|
||||
apb.exceptionClass.c_str(), apb.statusName.c_str(), apb.prefix.c_str(),
|
||||
apb.exceptionClass.c_str(), apb.method->statusName.c_str(), apb.prefix.c_str(),
|
||||
apb.interface->name.c_str(), apb.method->version);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case DEF_IGNORE:
|
||||
if (apb.method->returnTypeRef.token.type != Token::TYPE_VOID ||
|
||||
apb.method->returnTypeRef.isPointer)
|
||||
{
|
||||
identify(apb, ident);
|
||||
|
||||
switch(apb.language)
|
||||
{
|
||||
case LANGUAGE_C:
|
||||
case LANGUAGE_CPP:
|
||||
fprintf(apb.out, "return 0;\n");
|
||||
break;
|
||||
|
||||
case LANGUAGE_PASCAL:
|
||||
{
|
||||
const char* sResult = "nil";
|
||||
if (!apb.method->returnTypeRef.isPointer)
|
||||
{
|
||||
switch (apb.method->returnTypeRef.token.type)
|
||||
{
|
||||
case Token::TYPE_STRING:
|
||||
break;
|
||||
|
||||
case Token::TYPE_BOOLEAN:
|
||||
sResult = "false";
|
||||
break;
|
||||
|
||||
case Token::TYPE_IDENTIFIER:
|
||||
if (apb.method->returnTypeRef.type == BaseType::TYPE_INTERFACE)
|
||||
break;
|
||||
|
||||
// fallthru
|
||||
default:
|
||||
sResult = "0";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(apb.out, "Result := %s;\n", sResult);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
3
extern/cloop/src/cloop/Action.h
vendored
3
extern/cloop/src/cloop/Action.h
vendored
@ -37,7 +37,6 @@ struct ActionParametersBlock
|
||||
Language language;
|
||||
const std::string& prefix;
|
||||
const std::string& exceptionClass;
|
||||
const std::string& statusName;
|
||||
Interface* interface;
|
||||
Method* method;
|
||||
};
|
||||
@ -91,7 +90,7 @@ public:
|
||||
class DefAction : public Action
|
||||
{
|
||||
public:
|
||||
enum DefType { DEF_NOT_IMPLEMENTED };
|
||||
enum DefType { DEF_NOT_IMPLEMENTED, DEF_IGNORE };
|
||||
|
||||
DefAction(DefType dt)
|
||||
: defType(dt)
|
||||
|
117
extern/cloop/src/cloop/Generator.cpp
vendored
117
extern/cloop/src/cloop/Generator.cpp
vendored
@ -357,15 +357,8 @@ void CppGenerator::generate()
|
||||
|
||||
fprintf(out, "\n\t\t");
|
||||
|
||||
string statusName;
|
||||
|
||||
if (!method->parameters.empty() &&
|
||||
parser->exceptionInterface &&
|
||||
method->parameters.front()->typeRef.token.text == parser->exceptionInterface->name)
|
||||
{
|
||||
statusName = method->parameters.front()->name;
|
||||
if (!method->statusName.empty())
|
||||
fprintf(out, "template <typename StatusType> ");
|
||||
}
|
||||
|
||||
fprintf(out, "%s %s(",
|
||||
convertType(method->returnTypeRef).c_str(), method->name.c_str());
|
||||
@ -379,7 +372,7 @@ void CppGenerator::generate()
|
||||
if (k != method->parameters.begin())
|
||||
fprintf(out, ", ");
|
||||
|
||||
if (k == method->parameters.begin() && !statusName.empty())
|
||||
if (k == method->parameters.begin() && !method->statusName.empty())
|
||||
fprintf(out, "StatusType* %s", parameter->name.c_str());
|
||||
else
|
||||
{
|
||||
@ -397,7 +390,7 @@ void CppGenerator::generate()
|
||||
fprintf(out, "\t\t\t{\n");
|
||||
|
||||
const string exceptionClass("StatusType");
|
||||
ActionParametersBlock apb = {out, LANGUAGE_CPP, prefix, exceptionClass, statusName, interface, method};
|
||||
ActionParametersBlock apb = {out, LANGUAGE_CPP, prefix, exceptionClass, interface, method};
|
||||
|
||||
if (method->notImplementedAction)
|
||||
method->notImplementedAction->generate(apb, 4);
|
||||
@ -419,11 +412,11 @@ void CppGenerator::generate()
|
||||
fprintf(out, "\t\t\t}\n");
|
||||
}
|
||||
|
||||
if (!statusName.empty())
|
||||
if (!method->statusName.empty())
|
||||
{
|
||||
fprintf(out, "\t\t\t");
|
||||
|
||||
fprintf(out, "StatusType::clearException(%s)", statusName.c_str());
|
||||
fprintf(out, "StatusType::clearException(%s)", method->statusName.c_str());
|
||||
|
||||
fprintf(out, ";\n");
|
||||
}
|
||||
@ -694,7 +687,19 @@ void CppGenerator::generate()
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(out, ")%s = 0;\n", (method->isConst ? " const" : ""));
|
||||
fprintf(out, ")%s", (method->isConst ? " const" : ""));
|
||||
|
||||
if (method->stubAction)
|
||||
{
|
||||
const string exceptionClass("StatusType");
|
||||
ActionParametersBlock apb = {out, LANGUAGE_CPP, prefix, exceptionClass, interface, method};
|
||||
|
||||
fprintf(out, "\n\t\t{\n");
|
||||
method->stubAction->generate(apb, 3);
|
||||
fprintf(out, "\t\t}\n");
|
||||
}
|
||||
else
|
||||
fprintf(out, " = 0;\n");
|
||||
}
|
||||
|
||||
fprintf(out, "\t};\n");
|
||||
@ -1184,7 +1189,10 @@ void PascalGenerator::generate()
|
||||
if (!isProcedure)
|
||||
fprintf(out, ": %s", convertType(method->returnTypeRef).c_str());
|
||||
|
||||
fprintf(out, "; virtual; abstract;\n");
|
||||
fprintf(out, "; virtual;");
|
||||
if (!method->stubAction)
|
||||
fprintf(out, " abstract;");
|
||||
fprintf(out, "\n");
|
||||
}
|
||||
|
||||
fprintf(out, "\tend;\n\n");
|
||||
@ -1209,15 +1217,6 @@ void PascalGenerator::generate()
|
||||
bool isProcedure = method->returnTypeRef.token.type == Token::TYPE_VOID &&
|
||||
!method->returnTypeRef.isPointer;
|
||||
|
||||
string statusName;
|
||||
|
||||
if (!method->parameters.empty() &&
|
||||
parser->exceptionInterface &&
|
||||
method->parameters.front()->typeRef.token.text == parser->exceptionInterface->name)
|
||||
{
|
||||
statusName = method->parameters.front()->name;
|
||||
}
|
||||
|
||||
fprintf(out, "%s %s.%s(",
|
||||
(isProcedure ? "procedure" : "function"),
|
||||
escapeName(interface->name, true).c_str(),
|
||||
@ -1248,8 +1247,7 @@ void PascalGenerator::generate()
|
||||
{
|
||||
fprintf(out, "\tif (vTable.version < %d) then begin\n", method->version);
|
||||
|
||||
ActionParametersBlock apb = {out, LANGUAGE_PASCAL, prefix, exceptionClass,
|
||||
statusName, interface, method};
|
||||
ActionParametersBlock apb = {out, LANGUAGE_PASCAL, prefix, exceptionClass, interface, method};
|
||||
|
||||
if (method->notImplementedAction)
|
||||
method->notImplementedAction->generate(apb, 2);
|
||||
@ -1290,8 +1288,8 @@ void PascalGenerator::generate()
|
||||
if (ident > 1)
|
||||
fprintf(out, "\tend;\n");
|
||||
|
||||
if (!statusName.empty() && !exceptionClass.empty())
|
||||
fprintf(out, "\t%s.checkException(%s);\n", exceptionClass.c_str(), escapeName(statusName).c_str());
|
||||
if (!method->statusName.empty() && !exceptionClass.empty())
|
||||
fprintf(out, "\t%s.checkException(%s);\n", exceptionClass.c_str(), escapeName(method->statusName).c_str());
|
||||
|
||||
fprintf(out, "end;\n\n");
|
||||
}
|
||||
@ -1315,6 +1313,8 @@ void PascalGenerator::generate()
|
||||
bool isProcedure = method->returnTypeRef.token.type == Token::TYPE_VOID &&
|
||||
!method->returnTypeRef.isPointer;
|
||||
|
||||
ActionParametersBlock apb = {out, LANGUAGE_PASCAL, prefix, exceptionClass, interface, method};
|
||||
|
||||
fprintf(out, "%s %sImpl_%sDispatcher(this: %s",
|
||||
(isProcedure ? "procedure" : "function"),
|
||||
escapeName(interface->name, true).c_str(),
|
||||
@ -1337,39 +1337,7 @@ void PascalGenerator::generate()
|
||||
|
||||
fprintf(out, "; cdecl;\n");
|
||||
fprintf(out, "begin\n");
|
||||
|
||||
if (!isProcedure)
|
||||
{
|
||||
if (method->returnTypeRef.isPointer) {
|
||||
fprintf(out, "\tResult := nil;\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* sResult;
|
||||
switch (method->returnTypeRef.token.type)
|
||||
{
|
||||
case Token::TYPE_STRING:
|
||||
sResult = "nil";
|
||||
break;
|
||||
|
||||
case Token::TYPE_BOOLEAN:
|
||||
sResult = "false";
|
||||
break;
|
||||
|
||||
case Token::TYPE_IDENTIFIER:
|
||||
if (method->returnTypeRef.type == BaseType::TYPE_INTERFACE)
|
||||
{
|
||||
sResult = "nil";
|
||||
break;
|
||||
}
|
||||
// fallthru
|
||||
default:
|
||||
sResult = "0";
|
||||
break;
|
||||
}
|
||||
fprintf(out, "\tResult := %s;\n", sResult);
|
||||
}
|
||||
}
|
||||
DefAction(DefAction::DEF_IGNORE).generate(apb, 1);
|
||||
|
||||
if (!exceptionClass.empty())
|
||||
fprintf(out, "\ttry\n\t");
|
||||
@ -1411,8 +1379,35 @@ void PascalGenerator::generate()
|
||||
|
||||
fprintf(out, "\tend\n");
|
||||
}
|
||||
|
||||
fprintf(out, "end;\n\n");
|
||||
|
||||
if (method->stubAction)
|
||||
{
|
||||
fprintf(out, "%s %sImpl.%s(",
|
||||
(isProcedure ? "procedure" : "function"),
|
||||
escapeName(interface->name, true).c_str(),
|
||||
escapeName(method->name).c_str());
|
||||
|
||||
for (vector<Parameter*>::iterator k = method->parameters.begin();
|
||||
k != method->parameters.end();
|
||||
++k)
|
||||
{
|
||||
Parameter* parameter = *k;
|
||||
|
||||
fprintf(out, "%s%s",
|
||||
k == method->parameters.begin() ? "" : "; ",
|
||||
convertParameter(*parameter).c_str());
|
||||
}
|
||||
|
||||
fprintf(out, ")");
|
||||
if (!isProcedure)
|
||||
fprintf(out, ": %s", convertType(method->returnTypeRef).c_str());
|
||||
fprintf(out, ";\n");
|
||||
|
||||
fprintf(out, "begin\n");
|
||||
method->stubAction->generate(apb, 1);
|
||||
fprintf(out, "end;\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(out, "var\n");
|
||||
|
2
extern/cloop/src/cloop/Lexer.cpp
vendored
2
extern/cloop/src/cloop/Lexer.cpp
vendored
@ -112,6 +112,8 @@ Token& Lexer::getToken(Token& token)
|
||||
token.type = Token::TYPE_CALL;
|
||||
else if (token.text == "defaultAction")
|
||||
token.type = Token::TYPE_DEFAULT_ACTION;
|
||||
else if (token.text == "stub")
|
||||
token.type = Token::TYPE_STUB;
|
||||
// types
|
||||
else if (token.text == "void")
|
||||
token.type = Token::TYPE_VOID;
|
||||
|
1
extern/cloop/src/cloop/Lexer.h
vendored
1
extern/cloop/src/cloop/Lexer.h
vendored
@ -47,6 +47,7 @@ struct Token
|
||||
TYPE_INTERFACE,
|
||||
TYPE_NOT_IMPLEMENTED,
|
||||
TYPE_NOT_IMPLEMENTED_ACTION,
|
||||
TYPE_STUB,
|
||||
TYPE_STRUCT,
|
||||
TYPE_TYPEDEF,
|
||||
TYPE_VERSION,
|
||||
|
21
extern/cloop/src/cloop/Parser.cpp
vendored
21
extern/cloop/src/cloop/Parser.cpp
vendored
@ -94,7 +94,7 @@ void Parser::parse()
|
||||
}
|
||||
}
|
||||
|
||||
// Check types.
|
||||
// Check types, assign statusName to methods.
|
||||
|
||||
for (vector<Interface*>::iterator i = interfaces.begin(); i != interfaces.end(); ++i)
|
||||
{
|
||||
@ -115,6 +115,13 @@ void Parser::parse()
|
||||
Parameter* parameter = *k;
|
||||
checkType(parameter->typeRef);
|
||||
}
|
||||
|
||||
if (!method->parameters.empty() &&
|
||||
exceptionInterface &&
|
||||
method->parameters.front()->typeRef.token.text == exceptionInterface->name)
|
||||
{
|
||||
method->statusName = method->parameters.front()->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -194,6 +201,7 @@ void Parser::parseItem()
|
||||
{
|
||||
Expr* notImplementedExpr = nullptr;
|
||||
Action* notImplementedAction = nullptr;
|
||||
Action* stubAction = nullptr;
|
||||
std::string onError;
|
||||
|
||||
while (lexer->getToken(token).type == TOKEN('['))
|
||||
@ -224,6 +232,12 @@ void Parser::parseItem()
|
||||
notImplementedAction = parseAction(DefAction::DEF_NOT_IMPLEMENTED);
|
||||
break;
|
||||
|
||||
case Token::TYPE_STUB:
|
||||
if (stubAction)
|
||||
syntaxError(token);
|
||||
stubAction = parseAction(DefAction::DEF_IGNORE);
|
||||
break;
|
||||
|
||||
default:
|
||||
syntaxError(token);
|
||||
break;
|
||||
@ -248,7 +262,7 @@ void Parser::parseItem()
|
||||
}
|
||||
|
||||
getToken(token, TOKEN('('));
|
||||
parseMethod(typeRef, name, notImplementedExpr, onError, notImplementedAction);
|
||||
parseMethod(typeRef, name, notImplementedExpr, onError, notImplementedAction, stubAction);
|
||||
}
|
||||
|
||||
void Parser::parseConstant(const TypeRef& typeRef, const string& name)
|
||||
@ -326,7 +340,7 @@ Action* Parser::parseDefAction(DefAction::DefType dt)
|
||||
}
|
||||
|
||||
void Parser::parseMethod(const TypeRef& returnTypeRef, const string& name, Expr* notImplementedExpr,
|
||||
const string& onError, Action* notImplementedAction)
|
||||
const string& onError, Action* notImplementedAction, Action* stubAction)
|
||||
{
|
||||
Method* method = new Method();
|
||||
interface->methods.push_back(method);
|
||||
@ -336,6 +350,7 @@ void Parser::parseMethod(const TypeRef& returnTypeRef, const string& name, Expr*
|
||||
method->version = interface->version;
|
||||
method->notImplementedExpr = notImplementedExpr;
|
||||
method->notImplementedAction = notImplementedAction;
|
||||
method->stubAction = stubAction;
|
||||
method->onErrorFunction = onError;
|
||||
|
||||
if (lexer->getToken(token).type != TOKEN(')'))
|
||||
|
5
extern/cloop/src/cloop/Parser.h
vendored
5
extern/cloop/src/cloop/Parser.h
vendored
@ -101,6 +101,7 @@ public:
|
||||
Method()
|
||||
: notImplementedExpr(NULL),
|
||||
notImplementedAction(NULL),
|
||||
stubAction(NULL),
|
||||
version(0),
|
||||
isConst(false)
|
||||
{
|
||||
@ -111,9 +112,11 @@ public:
|
||||
std::vector<Parameter*> parameters;
|
||||
Expr* notImplementedExpr;
|
||||
Action* notImplementedAction;
|
||||
Action* stubAction;
|
||||
unsigned version;
|
||||
bool isConst;
|
||||
std::string onErrorFunction;
|
||||
std::string statusName;
|
||||
};
|
||||
|
||||
|
||||
@ -178,7 +181,7 @@ public:
|
||||
void parseItem();
|
||||
void parseConstant(const TypeRef& typeRef, const std::string& name);
|
||||
void parseMethod(const TypeRef& returnTypeRef, const std::string& name, Expr* notImplementedExpr,
|
||||
const std::string& onErrorFunction, Action* notImplementedAction);
|
||||
const std::string& onErrorFunction, Action* notImplementedAction, Action* stubAction);
|
||||
|
||||
Expr* parseExpr();
|
||||
Expr* parseLogicalExpr();
|
||||
|
Loading…
Reference in New Issue
Block a user