Commit 228404dd authored by Victor Yacovlev's avatar Victor Yacovlev

ActorInterface: changed functions declarations from Kumir/Russian to

Abstract/ASCII semantics
parent beada9ea
......@@ -270,6 +270,8 @@ class Name:
return "OperatorSLASH"
elif ascii == "=":
return "OperatorEQUAL"
elif ascii == "<>":
return "OperatorNOTEQUAL"
elif ascii == "<":
return "OperatorLESS"
elif ascii == ">":
......@@ -444,7 +446,7 @@ $fields
};
""", {"name": nameDecl, "fields": fieldsDecl})
def cppCustomTypeCreation(self, variableToAppend):
def cppCustomTypeCreation(self, variableToAppend, variableToAssign):
"""
For non-standard types creates kumir type declaration, an empty string otherwise
......@@ -456,7 +458,9 @@ $fields
if self._standard:
return ""
else:
assert isinstance(variableToAppend, str)
assert variableToAppend is None or isinstance(variableToAppend, str)
assert variableToAssign is None or isinstance(variableToAssign, str)
assert variableToAssign or variableToAppend
result = "{\n"
result += " Shared::ActorInterface::CustomType custom;\n"
result += " Shared::ActorInterface::Record record;\n"
......@@ -469,10 +473,54 @@ $fields
if typee[0].lower() == 'q':
typee = typee[1:]
typee = typee[0].upper() + typee[1:]
result += " record.push_back(Field(QString::fromUtf8(\"%s\"), %s));\n" % (name, typee)
result += " record.push_back(Field(QByteArray(\"%s\"), %s));\n" % (name, typee)
typeName = self._name.kumirValue()
result += " custom = Shared::ActorInterface::CustomType(QString::fromUtf8(\"%s\"), record);\n" % typeName
result += " %s.push_back(custom);\n" % variableToAppend
if variableToAppend:
result += " %s.push_back(custom);\n" % variableToAppend
elif variableToAssign:
result += " %s = custom;\n" % variableToAssign
result += "}\n"
return result
def cppRecordSpecCreation(self, variableToAppend, variableToAssign):
"""
For non-standard types creates kumir type declaration, an empty string otherwise
:type variableToAppend: str
:param variableToAppend: C++ variable name (std::list or QList) to store result
:rtype: unicode
:return: an empty string for standard type or Shared::ActorInterface::CustomType implementation code
"""
if self._standard:
return ""
else:
assert variableToAppend is None or isinstance(variableToAppend, str)
assert variableToAssign is None or isinstance(variableToAssign, str)
assert variableToAssign or variableToAppend
result = "{\n"
result += " Shared::ActorInterface::RecordSpecification recordSpec;\n"
for fieldName, fieldType in self._fields:
assert isinstance(fieldName, Name)
assert isinstance(fieldType, BaseType)
assert fieldType.qtName() in ["int", "qreal", "bool", "QChar", "QString"]
name = fieldName.kumirValue()
typee = fieldType.qtName()
if typee[0].lower() == 'q':
typee = typee[1:]
typee = typee[0].upper() + typee[1:]
result += " recordSpec.record.push_back(Field(QByteArray(\"%s\"), %s));\n" % (name, typee)
result += " recordSpec.asciiName = QByteArray(\"%s\");\n" % self._name.asciiValue()
for key, value in self._name.data.items():
qlocale = None
if key == "ru_RU":
qlocale = "QLocale::Russian"
if qlocale:
result += " recordSpec.localizedNames[%s] = QString::fromUtf8(\"%s\");\n" % (qlocale, value)
if variableToAppend:
result += " %s.push_back(recordSpec);\n" % variableToAppend
elif variableToAssign:
result += " %s = recordSpec;\n" % variableToAssign
result += "}\n"
return result
......@@ -1064,7 +1112,7 @@ class Settings:
result += entry.cppEntryImplementation("entries")
result += """
%s = new Widgets::DeclarativeSettingsPage(
name(),
localizedModuleName(QLocale::Russian),
mySettings(),
entries
);
......@@ -1381,7 +1429,15 @@ private:
}
""" % (self.className, guiRequired)
def nameCppImplementation(self):
def asciiModuleNameCppImplementation(self):
return """
/* public */ QByteArray %s::asciiModuleName() const
{
return QByteArray("%s");
}
""" % (self.className, self._module.name.asciiValue())
def localizedModuleNameCppImplementation(self):
"""
Creates implementation of name
......@@ -1389,32 +1445,83 @@ private:
:return: implementation of QString name() const
"""
# TODO non-Russian language implementation
body = "return QString::fromUtf8(\"%s\");" % self._module.name.kumirValue()
return """
/* public */ QString %s::name() const
/* public */ QString %s::localizedModuleName(const QLocale::Language ) const
{
%s
// TODO non-Russian languages not implemented yet
return QString::fromUtf8("%s");
}
""" % (self.className, _addIndent(body))
def funcListCppImplementation(self):
"""
Creates implementation of funcList
""" % (self.className, self._module.name.kumirValue())
:rtype: unicode
:return: implementation of QStringList funcList() const
"""
@property
def functionListCppImplementation(self):
methods = self._module.methods
lines = map(lambda x: "result << QString::fromUtf8(\"" + x.kumirDeclaration() + "\");", methods)
body = _addIndent(string.join(lines, '\n'))
body = ""
for method in methods:
body += "\n/* " + method.kumirDeclaration() + " */\n"
body += "result.push_back(Function());\n"
body += "result.last().id = result.size() - 1;\n"
if method.name.kumirValue().startswith("@"):
body += "result.last().accessType = TeacherModeFunction;\n"
else:
body += "result.last().accessType = PublicFunction;\n"
body += 'result.last().asciiName = QByteArray("%s");\n' % method.name.asciiValue()
assert isinstance(method.name.data, dict)
for key, value in method.name.data.items():
qlocale = None
if key == "ru_RU":
qlocale = "QLocale::Russian"
if qlocale:
body += 'result.last().localizedNames[%s] = QString::fromUtf8("%s");\n' % (qlocale, value)
if method.returnType:
assert isinstance(method.returnType, BaseType)
if method.returnType._name.asciiValue() == "int":
body += "result.last().returnType = Int;\n"
elif method.returnType._name.asciiValue() == "double":
body += "result.last().returnType = Real;\n"
elif method.returnType._name.asciiValue() == "bool":
body += "result.last().returnType = Bool;\n"
elif method.returnType._name.asciiValue() == "char":
body += "result.last().returnType = Char;\n"
elif method.returnType._name.asciiValue() == "string":
body += "result.last().returnType = String;\n"
else:
body += "result.last().returnType = RecordType;\n"
body += method.returnType.cppRecordSpecCreation(None, "result.last().returnTypeSpecification")
else:
body += "result.last().returnType = Void;\n"
for argument in method.arguments:
body += "result.last().arguments.push_back(Argument());\n"
if argument.kumirArgumentDeclaration().startswith(u'аргрез '):
body += "result.last().arguments.last().accessType = InOutArgument;\n"
elif argument.kumirArgumentDeclaration().startswith(u'рез '):
body += "result.last().arguments.last().accessType = OutArgument;\n"
else:
body += "result.last().arguments.last().accessType = InArgument;\n"
assert isinstance(argument.baseType._name, Name)
if argument.baseType._name.asciiValue() == "int":
body += "result.last().arguments.last().type = Int;\n"
elif argument.baseType._name.asciiValue() == "double":
body += "result.last().arguments.last().type = Real;\n"
elif argument.baseType._name.asciiValue() == "bool":
body += "result.last().arguments.last().type = Bool;\n"
elif argument.baseType._name.asciiValue() == "char":
body += "result.last().arguments.last().type = Char;\n"
elif argument.baseType._name.asciiValue() == "string":
body += "result.last().arguments.last().type = String;\n"
else:
body += "result.last().arguments.last().type = RecordType;\n"
body += argument.baseType.cppRecordSpecCreation(None, "result.last().arguments.last().typeSpecification")
body += "result.last().arguments.last().dimension = %du;\n" % argument.dimension
return """
/* public */ QStringList %s::funcList() const
/* public */ Shared::ActorInterface::FunctionList %s::functionList() const
{
QStringList result;
FunctionList result;
%s;
return result;
}
""" % (self.className, body)
""" % (self.className, _addIndent(body))
def typeListCppImplementation(self):
"""
......@@ -1430,8 +1537,8 @@ private:
for typee in self._module.types:
assert isinstance(typee, BaseType)
if typee._module == self._module:
if typee.cppCustomTypeCreation("result"):
body += typee.cppCustomTypeCreation("result")
if typee.cppRecordSpecCreation("result", None):
body += typee.cppRecordSpecCreation("result", None)
return """
/* public */ Shared::ActorInterface::TypeList %s::typeList() const
{
......@@ -1462,11 +1569,11 @@ private:
assert not argument.baseType.isStandardType()
if body:
body += " else "
body += " if (clazz.first==QString::fromUtf8(\"%s\")) {\n" % argument.baseType.kumirName()
body += " if (clazz==QByteArray(\"%s\")) {\n" % argument.baseType._name.asciiValue()
body += " %s x = decode(value);\n" % argument.baseType.qtName()
body += " result = module_->runOperatorOUTPUT(x);\n }\n"
return """
/* public */ QString %s::customValueToString(const CustomType & %s, const QVariant & %s) const
/* public */ QString %s::customValueToString(const QByteArray & %s, const QVariant & %s) const
{
QString result;
%s
......@@ -1497,7 +1604,7 @@ private:
assert argument.baseType.qtName() == "QString"
if body:
body += " else "
body += " if (clazz.first==QString::fromUtf8(\"%s\")) {\n" % rtype.kumirName()
body += " if (clazz==QByteArray(\"%s\")) {\n" % rtype._name.asciiValue()
body += " %s x; bool ok = false;\n" % rtype.qtName()
body += " x = module_->runOperatorINPUT(stringg, ok);\n"
body += " if (ok) {\n"
......@@ -1505,7 +1612,7 @@ private:
body += " }\n"
body += " }\n"
return """
/* public */ QVariant %s::customValueFromString(const CustomType & %s, const QString & %s) const
/* public */ QVariant %s::customValueFromString(const QByteArray & %s, const QString & %s) const
{
QVariant result;
%s
......
......@@ -33,6 +33,14 @@
{ "name": "x", "baseType": "color" },
{ "name": "y", "baseType": "color" }
]
},
{
"name": {"ascii": "<>"},
"returnType": "bool",
"arguments": [
{ "name": "x", "baseType": "color" },
{ "name": "y", "baseType": "color" }
]
}
]
}
......@@ -255,6 +255,11 @@ bool _ColorerModule::runOperatorEQUAL(const Color &x, const Color &y)
x.b == y.b;
}
bool _ColorerModule::runOperatorNOTEQUAL(const Color &x, const Color &y)
{
return ! runOperatorEQUAL(x, y);
}
} // namespace Actor_Colorer
......@@ -37,6 +37,7 @@ public slots:
Color runOperatorINPUT(const QString& x, bool& ok);
QString runOperatorOUTPUT(const Color& x);
bool runOperatorEQUAL(const Color& x, const Color& y);
bool runOperatorNOTEQUAL(const Color& x, const Color& y);
/* ========= CLASS PRIVATE ========= */
......
......@@ -274,7 +274,7 @@ QString Plugin::initialize(const QStringList & parameters, const ExtensionSystem
l_plugin_actors << actor;
QWidget * w = 0;
const QString actorHelpFile = helpPath + o->pluginSpec().name + ".xml";
if (!actor->name().startsWith("_") && QFile(actorHelpFile).exists()) {
if (!actor->localizedModuleName(QLocale::Russian).startsWith("_") && QFile(actorHelpFile).exists()) {
helpViewer_->addDocument(QUrl::fromLocalFile(actorHelpFile));
}
if (actor->mainWidget()) {
......@@ -296,7 +296,7 @@ QString Plugin::initialize(const QStringList & parameters, const ExtensionSystem
Widgets::SecondaryWindow * actorWindow =
Widgets::SecondaryWindow::createSecondaryWindow(
actorWidget,
actor->name(),
actor->localizedModuleName(QLocale::Russian),
mainIcon,
mainWindow_,
mainWindow_->actorsPlace_,
......@@ -308,7 +308,7 @@ QString Plugin::initialize(const QStringList & parameters, const ExtensionSystem
QAction * showActor =
mainWindow_->ui->menuWindow->addAction(
actor->name(),
actor->localizedModuleName(QLocale::Russian),
actorWindow,
SLOT(activate())
);
......@@ -332,7 +332,7 @@ QString Plugin::initialize(const QStringList & parameters, const ExtensionSystem
Widgets::SecondaryWindow * pultWindow =
Widgets::SecondaryWindow::createSecondaryWindow(
actor->pultWidget(),
actor->name() + " - " + tr("Remote Control"),
actor->localizedModuleName(QLocale::Russian) + " - " + tr("Remote Control"),
pultIcon,
mainWindow_,
nullptr,
......@@ -343,7 +343,7 @@ QString Plugin::initialize(const QStringList & parameters, const ExtensionSystem
QAction * showPult =
mainWindow_->ui->menuWindow->addAction(
actor->name() + " - " + tr("Remote Control"),
actor->localizedModuleName(QLocale::Russian) + " - " + tr("Remote Control"),
pultWindow,
SLOT(activate())
);
......
......@@ -866,14 +866,15 @@ void OneSession::tryFinishInput()
else if (format.contains("::")) {
const QStringList typeName = format.split("::", QString::KeepEmptyParts);
const QString & moduleName = typeName[0];
const QString & className = typeName[1];
const QByteArray classAsciiName = typeName[1].toAscii();
const QString & className = typeName[2];
QList<ExtensionSystem::KPlugin*> plugins =
ExtensionSystem::PluginManager::instance()->loadedPlugins("Actor*");
Shared::ActorInterface * actor = 0;
for (int i=0; i<plugins.size(); i++) {
actor = qobject_cast<Shared::ActorInterface*>(plugins[i]);
if (actor) {
if (actor->name()==moduleName)
if (actor->localizedModuleName(QLocale::Russian)==moduleName)
break;
else
actor = 0;
......@@ -885,9 +886,7 @@ void OneSession::tryFinishInput()
QString lexem = QString::fromStdWString(Kumir::IO::readString(stream));
QVariant value;
if (!stream.hasError()) {
Shared::ActorInterface::CustomType ct;
ct.first = className;
value = actor->customValueFromString(ct, lexem);
value = actor->customValueFromString(classAsciiName, lexem);
if (!value.isValid()) {
conversionError = true;
conversionErrorLength = lexem.length();
......
......@@ -117,8 +117,8 @@ AI * Plugin::getActor(QString name)
qDebug()<<"ActorName"<<name;
for(int i=0;i<Actors.count();i++)
{
qDebug()<<"Cname:"<<Actors.at(i)->name();
if(Actors.at(i)->name()==name)return Actors.at(i);
qDebug()<<"Cname:"<<Actors.at(i)->localizedModuleName(QLocale::Russian);
if(Actors.at(i)->localizedModuleName(QLocale::Russian)==name)return Actors.at(i);
}
return NULL;
......
......@@ -308,8 +308,8 @@ void Editor::loadMacros()
foreach (const KPlugin* plugin, actorPlugins) {
ActorInterface * actor = qobject_cast<ActorInterface*>(plugin);
if (actor && !actor->name().startsWith("_")) {
availableActorNames.push_back(actor->name());
if (actor && !actor->localizedModuleName(QLocale::Russian).startsWith("_")) {
availableActorNames.push_back(actor->localizedModuleName(QLocale::Russian));
}
}
......
......@@ -342,17 +342,22 @@ void AnalizerPrivate::createModuleFromActor_stage1(Shared::ActorInterface * acto
AST::ModulePtr mod = AST::ModulePtr(new AST::Module());
mod->builtInID = forcedId;
mod->header.type = AST::ModTypeExternal;
mod->header.name = actor->name();
mod->header.name = actor->localizedModuleName(QLocale::Russian);
mod->header.asciiName = actor->asciiModuleName();
mod->impl.actor = AST::ActorPtr(actor);
ast->modules << ModulePtr(mod);
const Shared::ActorInterface::TypeList typeList = actor->typeList();
for (int i=0; i<typeList.size(); i++) {
typedef Shared::ActorInterface AI;
AI::CustomType ct = typeList[i];
AI::RecordSpecification ct = typeList[i];
AST::Type tp;
tp.name = ct.first;
if (ct.localizedNames.contains(QLocale::Russian))
tp.name = ct.localizedNames[QLocale::Russian];
else
tp.name = QString::fromAscii(ct.asciiName);
tp.actor = AST::ActorPtr(actor);
AI::Record record = ct.second;
tp.asciiName = ct.asciiName;
AI::Record record = ct.record;
for (int j=0; j<record.size(); j++) {
AI::Field field = record[j];
AI::FieldType ft = field.second;
......@@ -374,6 +379,44 @@ void AnalizerPrivate::createModuleFromActor_stage1(Shared::ActorInterface * acto
}
}
static AST::Type actorTypeToASTType(const Shared::ActorInterface::FieldType ft,
const Shared::ActorInterface::RecordSpecification & spec)
{
AST::Type result;
if (ft == Shared::ActorInterface::Void) {
result = AST::TypeNone;
}
else if (ft == Shared::ActorInterface::Bool) {
result = AST::TypeBoolean;
}
else if (ft == Shared::ActorInterface::Char) {
result = AST::TypeCharect;
}
else if (ft == Shared::ActorInterface::Int) {
result = AST::TypeInteger;
}
else if (ft == Shared::ActorInterface::Real) {
result = AST::TypeReal;
}
else if (ft == Shared::ActorInterface::String) {
result = AST::TypeString;
}
else if (ft == Shared::ActorInterface::RecordType) {
result.kind = AST::TypeUser;
result.name = spec.localizedNames.contains(QLocale::Russian)
? spec.localizedNames[QLocale::Russian]
: QString::fromAscii(spec.asciiName);
result.asciiName = spec.asciiName;
foreach (const Shared::ActorInterface::Field & field, spec.record) {
AST::Field kfield;
kfield.first = QString::fromAscii(field.first);
kfield.second = actorTypeToASTType(field.second, Shared::ActorInterface::RecordSpecification());
result.userTypeFields.push_back(kfield);
}
}
return result;
}
void AnalizerPrivate::createModuleFromActor_stage2(Shared::ActorInterface * actor)
{
// Stage 2 -- build functions list
......@@ -383,32 +426,49 @@ void AnalizerPrivate::createModuleFromActor_stage2(Shared::ActorInterface * acto
AST::ModulePtr dmod = moduleByActor(ast, dep);
dmod->header.usedBy.append(mod.toWeakRef());
}
const QStringList funcList = actor->funcList();
for (int i=0; i<funcList.size(); i++) {
foreach (const Shared::ActorInterface::Function & function, actor->functionList()) {
static const QList<QByteArray> Operators = QList<QByteArray>()
<< "input" << "output" << "+" << "-" << "*" << "/" << "**"
<< "=" << "<>" << "<" << ">";
AST::AlgorithmPtr alg = AST::AlgorithmPtr(new AST::Algorithm);
alg->header.implType = AST::AlgorhitmExternal;
alg->header.external.moduleName = actor->name();
alg->header.external.id = i;
QList<TextStatementPtr> sts;
lexer->splitIntoStatements(QStringList() << funcList[i], -1, sts, gatherExtraTypeNames(mod));
Q_ASSERT_X(sts.size()==1
, "AnalizerPrivate::createModuleFromActor"
, QString("Algorhitm %1 in module %2 has syntax error")
.arg(funcList[i])
.arg(actor->name()).toLocal8Bit().data());
alg->impl.headerLexems = sts[0]->data;
sts[0]->alg = alg;
sts[0]->mod = mod;
analizer->init(sts, ast);
analizer->buildTables(true);
foreach (const LexemPtr lx, sts[0]->data) {
if (!lx->error.isEmpty()) {
Q_ASSERT_X(sts.size()==1
, "AnalizerPrivate::createModuleFromActor"
, QString("Algorhitm %1 in module %2 has syntax error")
.arg(funcList[i])
.arg(actor->name()).toLocal8Bit().data());
alg->header.external.moduleName = actor->localizedModuleName(QLocale::Russian);
alg->header.external.moduleAsciiName = actor->asciiModuleName();
alg->header.external.id = function.id;
alg->header.name = function.localizedNames.contains(QLocale::Russian)
? function.localizedNames[QLocale::Russian]
: QString::fromAscii(function.asciiName);
alg->header.broken = false;
alg->header.specialType = function.accessType == Shared::ActorInterface::TeacherModeFunction
? AST::AlgorithmTypeTeacher : AST::AlgorithmTypeRegular;
alg->header.returnType = actorTypeToASTType(function.returnType, function.returnTypeSpecification);
foreach (const Shared::ActorInterface::Argument & arg, function.arguments) {
AST::VariablePtr karg = AST::VariablePtr(new AST::Variable);
karg->name = arg.localizedNames.contains(QLocale::Russian)
? arg.localizedNames[QLocale::Russian]
: QString::fromAscii(arg.asciiName);
karg->baseType = actorTypeToASTType(arg.type, arg.typeSpecification);
karg->dimension = arg.dimension;
if (arg.accessType == Shared::ActorInterface::InOutArgument) {
karg->accessType = AST::AccessArgumentInOut;
}
else if (arg.accessType == Shared::ActorInterface::OutArgument) {
karg->accessType = AST::AccessArgumentOut;
}
else {
karg->accessType = AST::AccessArgumentIn;
}
alg->header.arguments.push_back(karg);
}
if (Operators.contains(function.asciiName)) {
mod->header.operators.push_back(alg);
}
else {
mod->header.algorhitms.push_back(alg);
}
}
}
......
This diff is collapsed.
......@@ -245,7 +245,7 @@ SyntaxAnalizer::suggestInputOutputAutoComplete(
}
}
if (filesModuleAvailable) {
static const AST::Type FileType = AST::Type(QString::fromUtf8("файл"));
static const AST::Type FileType = AST::Type(QString::fromUtf8("файл"), QByteArray("file"));
QList<Shared::Analizer::Suggestion> fileSuggestions =
suggestExpressionAutoComplete(
lineNo,
......@@ -2829,7 +2829,7 @@ void SyntaxAnalizer::parseAlgHeader(int str, bool onlyName, bool internalBuildFl
AST::Type typee;
QVariant cvalue;
if (tryInputOperatorAlgorithm(name, typee, cvalue, st.mod)) {
const QString error = _("Name is used by module %1", typee.actor->name());
const QString error = _("Name is used by module %1", typee.actor->localizedModuleName(QLocale::Russian));
for (int i=1; i<st.data.size(); i++) {
if (st.data[i]->type==LxNameAlg)
st.data[i]->error = error;
......@@ -2875,17 +2875,17 @@ void SyntaxAnalizer::parseAlgHeader(int str, bool onlyName, bool internalBuildFl
}
if (/*alg->header.specialType==AST::AlgorhitmTypeTeacher && */alg->header.name==lexer_->testingAlgorhitmName()) {
alg->header.specialType = AST::AlgorhitmTypeTesting;
alg->header.specialType = AST::AlgorithmTypeTesting;
}
if (teacherMode_ && alg->header.name==lexer_->testingAlgorhitmName()) {
alg->header.specialType = AST::AlgorhitmTypeTesting;
alg->header.specialType = AST::AlgorithmTypeTesting;
}
else if ( (teacherMode_ || internalBuildFlag) && alg->header.name.startsWith("@")) {
alg->header.specialType = AST::AlgorhitmTypeTeacher;
alg->header.specialType = AST::AlgorithmTypeTeacher;
}
if (!(teacherMode_ || internalBuildFlag) && alg->header.specialType!=AST::AlgorhitmTypeTesting
if (!(teacherMode_ || internalBuildFlag) && alg->header.specialType!=AST::AlgorithmTypeTesting
&& alg->header.name.startsWith("@"))
{
for (int i=1; i<st.data.size(); i++) {
......@@ -3348,7 +3348,7 @@ QList<AST::VariablePtr> SyntaxAnalizer::parseVariables(int statementIndex, Varia
AST::Type typee;
QVariant cvalue;
if (tryInputOperatorAlgorithm(cName, typee, cvalue, mod)) {
group.lexems[nameStart]->error = _("Name is used by module %1", typee.actor->name());