Commit f2fd56ff authored by Alexander A. Maly's avatar Alexander A. Maly

Refactored VM abstract handlers

Moved code to a new realization file.
Return value of the main argument is now always followed by a new line.
parent ade55ad6
Pipeline #2582 failed with stages
in 3 minutes and 32 seconds
......@@ -8,6 +8,7 @@ set(SOURCES
vm_bytecode.cpp
vm_breakpoints_table.cpp
vm_console_handlers.cpp
vm_abstract_handlers.cpp
variant.cpp
vm.cpp
)
......
#include <vm_abstract_handlers.h>
#if defined(WIN32) || defined(_WIN32)
# include <windows.h>
#else
# include <unistd.h>
#endif
namespace VM
{
void ExternalModuleResetFunctor::operator()(
const std::string & /*moduleName*/,
const Kumir::String &localizedName,
Kumir::String *error
) {
Kumir::String errorMessage =
Kumir::Core::fromUtf8("Невозможно использовать \"") +
localizedName +
Kumir::Core::fromUtf8("\": исполнители не поддерживаются");
if (error) {
error->assign(errorMessage);
}
}
std::deque<std::string> ExternalModuleLoadFunctor::operator()(
const std::string & /*moduleAsciiName*/,
const Kumir::String &moduleName,
Kumir::String *error
) {
Kumir::String errorMessage =
Kumir::Core::fromUtf8("Невозможно использовать \"") +
moduleName +
Kumir::Core::fromUtf8("\": исполнители не поддерживаются");
if (error) {
error->assign(errorMessage);
}
return NamesList();
}
AnyValue ExternalModuleCallFunctor::operator()(
const std::string & /*asciiModuleName*/,
const Kumir::String &localizedModuleName,
const uint16_t /*alogrithmId*/,
VariableReferencesList /*arguments*/,
Kumir::String *error
) {
Kumir::String errorMessage =
Kumir::Core::fromUtf8("Невозможно вызвать алгоритм исполнителя \"") +
localizedModuleName +
Kumir::Core::fromUtf8("\": исполнители не поддерживаются");
if (error) {
error->assign(errorMessage);
}
return AnyValue();
}
Kumir::String CustomTypeToStringFunctor::operator()(
const Variable &variable,
Kumir::String *error
) {
const Kumir::String errorMessage =
Kumir::Core::fromUtf8("Не могу вывести значение типа \"") +
variable.recordClassLocalizedName() + Kumir::Core::fromAscii("\"");
if (error) {
error->assign(errorMessage);
}
return Kumir::String();
}
VM::AnyValue CustomTypeFromStringFunctor::operator()(
const Kumir::String & /*source*/,
const std::string & /*moduleAsciiName*/,
const Kumir::String & /*moduleName*/,
const std::string & /* typeAsciiName */,
const Kumir::String &typeLocalizedName,
Kumir::String *error
) {
Kumir::String errorMessage =
Kumir::Core::fromUtf8("Не могу разобрать значение типа \"") +
typeLocalizedName + Kumir::Core::fromAscii("\"");
if (error) {
error->assign(errorMessage);
}
return VM::AnyValue();
}
void DelayFunctor::operator()(uint32_t msec)
{
#if defined(WIN32) || defined(_WIN32)
Sleep(msec);
#else
uint32_t sec = msec / 1000;
uint32_t usec = (msec - sec * 1000) * 1000;
// usleep works in range [0, 1000000), so
// call sleep(sec) first for long periods
sleep(sec);
usleep(usec);
#endif
}
bool InputFunctor::operator()(
VariableReferencesList /*alist*/,
Kumir::String *error
) {
Kumir::String errorMessage =
Kumir::Core::fromUtf8("Операция ввода не поддерживается");
if (error) {
error->assign(errorMessage);
}
return false;
}
void OutputFunctor::operator()(
VariableReferencesList /*vars*/,
FormatsList /*formats*/,
Kumir::String *error
)
{
Kumir::String errorMessage =
Kumir::Core::fromUtf8("Операция вывода не поддерживается");
if (error) {
error->assign(errorMessage);
}
}
void GetMainArgumentFunctor::operator()(
Variable & /*reference*/,
Kumir::String *error
) {
Kumir::String errorMessage =
Kumir::Core::fromUtf8("Запуск первого алгоритма с аргументами не поддерживается");
if (error) {
error->assign(errorMessage);
}
}
void ReturnMainValueFunctor::operator()(
const Variable & /*reference*/,
Kumir::String *error
) {
Kumir::String errorMessage =
Kumir::Core::fromUtf8("Возвращение значений первого алгоритма не поддерживается");
if (error) {
error->assign(errorMessage);
}
}
} // namespace VM
......@@ -14,11 +14,7 @@
*
*/
#if defined(WIN32) || defined(_WIN32)
# include <windows.h>
#else
# include <unistd.h>
#endif
#include "vm_dll.h"
#ifndef _override
#if defined(_MSC_VER)
......@@ -28,10 +24,6 @@
#endif
#endif
#include <deque>
#include <string>
#include <list>
#include <vector>
#include "variant.hpp"
......@@ -79,7 +71,7 @@ protected:
/* ====== Functors for external modules initialization ====== */
/** A functor to reset external module before execution by a given name */
class ExternalModuleResetFunctor: public Functor
class VM_DLL ExternalModuleResetFunctor: public Functor
{
public:
ExternalModuleResetFunctor(): callFunctor_(0) {}
......@@ -93,15 +85,7 @@ public:
const std::string & /*moduleName*/,
const Kumir::String &localizedName,
Kumir::String *error
) {
Kumir::String errorMessage =
Kumir::Core::fromUtf8("Невозможно использовать \"") +
localizedName +
Kumir::Core::fromUtf8("\": исполнители не поддерживаются");
if (error) {
error->assign(errorMessage);
}
}
);
void setCallFunctor(class ExternalModuleCallFunctor *callFunctor)
{
......@@ -124,7 +108,7 @@ protected:
* from file 'GreatModule.dll' (on Windows).
* --- returns a list of module provided names
*/
class ExternalModuleLoadFunctor: public Functor
class VM_DLL ExternalModuleLoadFunctor: public Functor
{
public:
Type type() const _override
......@@ -132,23 +116,13 @@ public:
return ExternalModuleLoad;
}
typedef std::deque<std::string> NamesList;
virtual NamesList operator()(
const std::string & /*moduleAsciiName*/,
const Kumir::String &moduleName,
Kumir::String *error
)
{
Kumir::String errorMessage =
Kumir::Core::fromUtf8("Невозможно использовать \"") +
moduleName +
Kumir::Core::fromUtf8("\": исполнители не поддерживаются");
if (error) {
error->assign(errorMessage);
}
return NamesList();
}
);
};
......@@ -158,7 +132,7 @@ public:
* calling function return (is any), or a dummy any value (if void).
*
*/
class ExternalModuleCallFunctor: public Functor
class VM_DLL ExternalModuleCallFunctor: public Functor
{
public:
Type type() const _override
......@@ -173,22 +147,13 @@ public:
const uint16_t /*alogrithmId*/,
VariableReferencesList /*arguments*/,
Kumir::String *error
) {
Kumir::String errorMessage =
Kumir::Core::fromUtf8("Невозможно вызвать алгоритм исполнителя \"") +
localizedModuleName +
Kumir::Core::fromUtf8("\": исполнители не поддерживаются");
if (error) {
error->assign(errorMessage);
}
return AnyValue();
}
);
virtual void checkForActorConnected(const std::string & /*asciiModuleName*/) {}
virtual void terminate() {}
};
class CustomTypeToStringFunctor: public Functor
class VM_DLL CustomTypeToStringFunctor: public Functor
{
public:
Type type() const _override
......@@ -199,18 +164,10 @@ public:
virtual Kumir::String operator()(
const Variable &variable,
Kumir::String *error
) {
const Kumir::String errorMessage =
Kumir::Core::fromUtf8("Не могу вывести значение типа \"") +
variable.recordClassLocalizedName() + Kumir::Core::fromAscii("\"");
if (error) {
error->assign(errorMessage);
}
return Kumir::String();
}
);
};
class CustomTypeFromStringFunctor: public Functor
class VM_DLL CustomTypeFromStringFunctor: public Functor
{
public:
Type type() const _override
......@@ -224,15 +181,7 @@ public:
const std::string & /* typeAsciiName */,
const Kumir::String &typeLocalizedName,
Kumir::String *error
) {
Kumir::String errorMessage =
Kumir::Core::fromUtf8("Не могу разобрать значение типа \"") +
typeLocalizedName + Kumir::Core::fromAscii("\"");
if (error) {
error->assign(errorMessage);
}
return VM::AnyValue();
}
);
};
/* ====== Functors for execution control function run ======= */
......@@ -254,26 +203,15 @@ public:
*
* Argument is a sleep time in milliseconds
*/
class DelayFunctor : public Functor
class VM_DLL DelayFunctor : public Functor
{
public:
Type type() const _override
{
return Delay;
}
virtual void operator()(uint32_t msec)
{
#if defined(WIN32) || defined(_WIN32)
Sleep(msec);
#else
uint32_t sec = msec / 1000;
uint32_t usec = (msec - sec * 1000) * 1000;
// usleep works in range [0, 1000000), so
// call sleep(sec) first for long periods
sleep(sec);
usleep(usec);
#endif
}
virtual void operator()(uint32_t msec);
};
/* ====== Functors for user input and output================= */
......@@ -283,7 +221,7 @@ public:
* Argument is a list of Reference-variables to be set.
*
*/
class InputFunctor: public Functor
class VM_DLL InputFunctor: public Functor
{
public:
Type type() const _override
......@@ -292,24 +230,21 @@ public:
}
typedef std::deque<Variable> &VariableReferencesList;
virtual bool operator()(VariableReferencesList /*alist*/, Kumir::String *error)
{
Kumir::String errorMessage =
Kumir::Core::fromUtf8("Операция ввода не поддерживается");
if (error) {
error->assign(errorMessage);
}
return false;
}
virtual bool operator()(
VariableReferencesList /*alist*/,
Kumir::String *error
);
};
/** A functor to output variables values within user interface
*
* Argument is a list of Reference-variables to be shown and
* a list of the same size of int-pairs (format parameters).
*
*/
class OutputFunctor: public Functor
class VM_DLL OutputFunctor: public Functor
{
public:
Type type() const _override
......@@ -319,21 +254,15 @@ public:
typedef const std::deque<Variable> &VariableReferencesList;
typedef const std::deque< std::pair<int, int> > &FormatsList;
virtual void operator()(
VariableReferencesList /*vars*/,
FormatsList /*formats*/,
Kumir::String *error
)
{
Kumir::String errorMessage =
Kumir::Core::fromUtf8("Операция вывода не поддерживается");
if (error) {
error->assign(errorMessage);
}
}
);
};
class GetMainArgumentFunctor: public Functor
class VM_DLL GetMainArgumentFunctor: public Functor
{
public:
Type type() const _override
......@@ -341,17 +270,10 @@ public:
return GetMainArgument;
}
virtual void operator()(Variable & /*reference*/, Kumir::String *error)
{
Kumir::String errorMessage =
Kumir::Core::fromUtf8("Запуск первого алгоритма с аргументами не поддерживается");
if (error) {
error->assign(errorMessage);
}
}
virtual void operator()(Variable & /*reference*/, Kumir::String *error);
};
class ReturnMainValueFunctor: public Functor
class VM_DLL ReturnMainValueFunctor: public Functor
{
public:
Type type() const _override
......@@ -359,14 +281,10 @@ public:
return ReturnMainValue;
}
virtual void operator()(const Variable & /*reference*/, Kumir::String *error)
{
Kumir::String errorMessage =
Kumir::Core::fromUtf8("Возвращение значений первого алгоритма не поддерживается");
if (error) {
error->assign(errorMessage);
}
}
virtual void operator()(
const Variable & /*reference*/,
Kumir::String *error
);
};
/* ====== End all functors declarations ============== */
......
......@@ -47,7 +47,7 @@ bool InputFunctor::operator()(VariableReferencesList alist, Kumir::String *error
} else if (var.baseType() == VM::VT_string) {
var.setValue(VM::AnyValue(IO::readLine(stream)));
} else if (var.baseType() == VM::VT_record) {
const String s = IO::readString(stream);
String s = IO::readString(stream);
if (!stream.hasError()) {
VM::CustomTypeFromStringFunctor *f =
customTypeFromString_;
......@@ -79,8 +79,7 @@ bool InputFunctor::operator()(VariableReferencesList alist, Kumir::String *error
return true;
}
OutputFunctor::OutputFunctor() :
VM::OutputFunctor(),
OutputFunctor::OutputFunctor() : VM::OutputFunctor(),
#if defined(WIN32) || defined(_WIN32)
locale_(CP866),
#else
......@@ -129,6 +128,7 @@ void OutputFunctor::writeRawString(const String &s)
do_output(s, locale_);
}
ReturnMainValueFunctor::ReturnMainValueFunctor() :
VM::ReturnMainValueFunctor(),
#if defined(WIN32) || defined(_WIN32)
......@@ -140,20 +140,27 @@ ReturnMainValueFunctor::ReturnMainValueFunctor() :
quietMode_(false)
{}
void ReturnMainValueFunctor::operator()(const VM::Variable &reference, Kumir::String * /*error*/)
{
void ReturnMainValueFunctor::operator()(
const VM::Variable &reference,
Kumir::String *error
) {
(void) error;
if (!reference.isValid()) {
return;
}
String repr;
VM::CustomTypeToStringFunctor *f = customTypeToString_;
if (reference.baseType() == VM::VT_record && !f) {
static VM::CustomTypeToStringFunctor def;
f = &def;
}
if (!quietMode_) {
do_output(reference.name() + Core::fromAscii(" = "), locale_);
}
String repr;
if (reference.dimension() == 0) {
if (reference.hasValue()) {
repr = reference.value().toString();
......@@ -246,7 +253,7 @@ void ReturnMainValueFunctor::operator()(const VM::Variable &reference, Kumir::St
}
do_output(" }", locale_);
}
if (!quietMode_) {
if (true) {
do_output("\n", locale_);
}
}
......@@ -382,7 +389,7 @@ bool GetMainArgumentFunctor::readScalarArgument(
} else if (type == VM::VT_string) {
val = IO::readString(stream);
} else if (type == VM::VT_record) {
const String s = IO::readString(stream);
String s = IO::readString(stream);
VM::CustomTypeFromStringFunctor *f = customTypeFromString_;
if (!f) {
static VM::CustomTypeFromStringFunctor def;
......@@ -398,21 +405,25 @@ bool GetMainArgumentFunctor::readScalarArgument(
return error ? error->length() == 0 : true; // Core::getError().size()==0;
}
void GetMainArgumentFunctor::operator()(VM::Variable &reference, Kumir::String *error)
{
void GetMainArgumentFunctor::operator()(
VM::Variable &reference,
Kumir::String *error
) {
String message = Core::fromUtf8("Введите ") + reference.name();
static const String errorMessage = Core::fromUtf8("Не все аргументы первого алгоритма введены корректно");
if (reference.dimension() == 0) {
message += Core::fromAscii(": ");
VM::AnyValue val;
if (readScalarArgument(message,
if (readScalarArgument(
message,
reference.name(),
reference.baseType(),
reference.recordModuleAsciiName(),
reference.recordModuleLocalizedName(),
reference.recordClassAsciiName(),
reference.recordClassLocalizedName(),
val, error)) {
val, error
)) {
reference.setValue(val);
} else {
if (error) {
......@@ -429,14 +440,16 @@ void GetMainArgumentFunctor::operator()(VM::Variable &reference, Kumir::String *
message += Core::fromAscii("[");
message += Converter::intToString(x);
message += Core::fromAscii("]: ");
if (readScalarArgument(message,
if (readScalarArgument(
message,
reference.name(),
reference.baseType(),
reference.recordModuleAsciiName(),
reference.recordModuleLocalizedName(),
reference.recordClassAsciiName(),
reference.recordClassLocalizedName(),
val, error)) {
val, error
)) {
reference.setValue(x, val);
} else {
if (error) {
......@@ -487,14 +500,16 @@ void GetMainArgumentFunctor::operator()(VM::Variable &reference, Kumir::String *
message += Core::fromAscii(",");
message += Converter::intToString(x);
message += Core::fromAscii("]: ");
if (readScalarArgument(message,
if (readScalarArgument(
message,
reference.name(),
reference.baseType(),
reference.recordModuleAsciiName(),
reference.recordModuleLocalizedName(),
reference.recordClassAsciiName(),
reference.recordClassLocalizedName(),
val, error)) {
val, error
)) {
reference.setValue(z, y, x, val);
} else {
if (error) {
......
#ifndef VM_CONSOLE_HANDLERS_HPP
#define VM_CONSOLE_HANDLERS_HPP
#include "vm_dll.h"
#include "vm_abstract_handlers.h"
#ifndef _override
#if defined(_MSC_VER)
#define _override
#else
#define _override override
#endif
#endif
namespace VM
{
namespace Console
{
......@@ -93,7 +85,10 @@ class VM_DLL ReturnMainValueFunctor : public VM::ReturnMainValueFunctor
public:
ReturnMainValueFunctor();
void operator()(const VM::Variable &reference, Kumir::String *error