SET(COMMON_FLAGS "-fdiagnostics-color=always -fPIC")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COMMON_FLAGS}")
-SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMMON_FLAGS} -std=c++14")
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMMON_FLAGS} -std=c++14 -g")
# install desktop file & icon
SET(RES_DIR "${CMAKE_INSTALL_PREFIX}/res")
});
}
+std::unordered_map<std::string, std::string> BatchExecutor::getUIElementAttributes(const std::shared_ptr<UIElement> &uiElem)
+{
+ return executeOnMainThread([&]() {
+ auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
+ auto found = atspi->getAttributes(uiElem->getObject());
+ std::unordered_map<std::string, std::string> res;
+ for (auto &it : found)
+ res.insert(std::move(it));
+ return std::move(res);
+ });
+}
+
+unsigned int BatchExecutor::getUIElementRole(const std::shared_ptr<UIElement> &uiElem)
+{
+ return executeOnMainThread([&]() {
+ auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
+ auto found = atspi->getRole(uiElem->getObject());
+ if (found)
+ return static_cast<unsigned int>(*found);
+ throw EvaluationFailure{} << "failed to get at-spi object's role (use dlogutil to get at-spi error message)";
+ });
+}
+
+Atspi::StateSet BatchExecutor::getUIElementStates(const std::shared_ptr<UIElement> &uiElem)
+{
+ return executeOnMainThread([&]() {
+ auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
+ auto states = atspi->getStateSet(uiElem->getObject());
+ if (states) {
+ return std::move(*states);
+ }
+ throw EvaluationFailure{} << "failed to get at-spi state set (use dlogutil to get at-spi error message)";
+ });
+}
+
std::string BatchExecutor::getUIElementName(const std::shared_ptr<UIElement> &uiElem)
{
return executeOnMainThread([&]() {
return std::string(bufor.data(), (size_t)total);
}
-namespace
+//TODO: when switching to c++17 we should use std::filename::path
+std::string getPathRelativeToFile(const std::string &relativePath, const std::string &file)
{
- //TODO: when switching to c++17 we should use std::filename::path
- std::string getPathRelativeToFile(const std::string &relativePath, const std::string &file)
- {
- if (!relativePath.empty() && relativePath[0] == '/') {
- //not a relative path
- return relativePath;
- }
- auto pos = file.rfind('/');
- if (pos == std::string::npos) {
- return relativePath;
- }
- return file.substr(0, pos + 1) + relativePath;
+ if (!relativePath.empty() && relativePath[0] == '/') {
+ //not a relative path
+ return relativePath;
}
+ auto pos = file.rfind('/');
+ if (pos == std::string::npos) {
+ return relativePath;
+ }
+ return file.substr(0, pos + 1) + relativePath;
+}
- std::string errorToStr(int err)
- {
- std::ostringstream tmp;
- bool first = true;
+std::string errorToStr(int err)
+{
+ std::ostringstream tmp;
+ bool first = true;
#define Q(a) \
if (a == err) { \
if (first) first = false; \
else tmp << ", "; \
tmp << #a; \
}
- Q(TIZEN_ERROR_NONE)
- Q(TIZEN_ERROR_NOT_PERMITTED)
- Q(TIZEN_ERROR_NO_SUCH_FILE)
- Q(TIZEN_ERROR_NO_SUCH_PROCESS)
- Q(TIZEN_ERROR_INTERRUPTED_SYS_CALL)
- Q(TIZEN_ERROR_IO_ERROR)
- Q(TIZEN_ERROR_NO_SUCH_DEVICE)
- Q(TIZEN_ERROR_ARGUMENT_LIST_TOO_LONG)
- Q(TIZEN_ERROR_EXEC_FORMAT_ERROR)
- Q(TIZEN_ERROR_BAD_FILE_NUMBER)
- Q(TIZEN_ERROR_TRY_AGAIN)
- Q(TIZEN_ERROR_OUT_OF_MEMORY)
- Q(TIZEN_ERROR_PERMISSION_DENIED)
- Q(TIZEN_ERROR_BAD_ADDRESS)
- Q(TIZEN_ERROR_BLOCK_DEVICE_REQUIRED)
- Q(TIZEN_ERROR_RESOURCE_BUSY)
- Q(TIZEN_ERROR_FILE_EXISTS)
- Q(TIZEN_ERROR_CROSS_DEVICE_LINK)
- Q(TIZEN_ERROR_NOT_A_DIRECTORY)
- Q(TIZEN_ERROR_IS_A_DIRECTORY)
- Q(TIZEN_ERROR_INVALID_PARAMETER)
- Q(TIZEN_ERROR_FILE_TABLE_OVERFLOW)
- Q(TIZEN_ERROR_TOO_MANY_OPEN_FILES)
- Q(TIZEN_ERROR_TOO_NOT_A_TERMINAL)
- Q(TIZEN_ERROR_TOO_TEXT_FILE_BUSY)
- Q(TIZEN_ERROR_FILE_TOO_LARGE)
- Q(TIZEN_ERROR_FILE_NO_SPACE_ON_DEVICE)
- Q(TIZEN_ERROR_ILLEGAL_SEEK)
- Q(TIZEN_ERROR_READ_ONLY_FILESYSTEM)
- Q(TIZEN_ERROR_NO_DATA)
- Q(TIZEN_ERROR_TOO_MANY_LINKS)
- Q(TIZEN_ERROR_BROKEN_PIPE)
- Q(TIZEN_ERROR_ARGUMENT_OUT_OF_DOMAIN)
- Q(TIZEN_ERROR_RESULT_OUT_OF_RANGE)
- Q(TIZEN_ERROR_WOULD_CAUSE_DEADLOCK)
- Q(TIZEN_ERROR_FILE_NAME_TOO_LONG)
- Q(TIZEN_ERROR_FILE_NO_LOCKS_AVAILABLE)
- Q(TIZEN_ERROR_INVALID_OPERATION)
- Q(TIZEN_ERROR_DIR_NOT_EMPTY)
- Q(TIZEN_ERROR_TOO_MANY_SYMBOLIC_LINKS)
- Q(TIZEN_ERROR_WOULD_BLOCK)
- Q(TIZEN_ERROR_CORRUPTED_SHARED_LIB)
- Q(TIZEN_ERROR_LIB_SECTION_CORRUPTED)
- Q(TIZEN_ERROR_LINK_TOO_MANY_SHARED_LIB)
- Q(TIZEN_ERROR_SHARED_LIB_EXEC)
- Q(TIZEN_ERROR_ILLEGAL_BYTE_SEQ)
- Q(TIZEN_ERROR_SYSTEM_CALL_RESTART)
- Q(TIZEN_ERROR_STREAMS_PIPE)
- Q(TIZEN_ERROR_TOO_MANY_USERS)
- Q(TIZEN_ERROR_NON_SOCKET)
- Q(TIZEN_ERROR_NO_DEST_ADDRESS)
- Q(TIZEN_ERROR_MSG_TOO_LONG)
- Q(TIZEN_ERROR_PROTOCOL_WRONG_TYPE)
- Q(TIZEN_ERROR_PROTOCOL_NOT_AVALIABLE)
- Q(TIZEN_ERROR_PROTOCOL_NOT_SUPPORTED)
- Q(TIZEN_ERROR_SOCKET_TYPE_NOT_SUPPORTED)
- Q(TIZEN_ERROR_ENDPOINT_OPERATIN_NOT_SUPPORTED)
- Q(TIZEN_ERROR_PROTOCOL_FAMILY_NOT_SUPPORTED)
- Q(TIZEN_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED)
- Q(TIZEN_ERROR_ADDRES_IN_USE)
- Q(TIZEN_ERROR_CANNOT_ASSIGN_ADDRESS)
- Q(TIZEN_ERROR_NETWORK_DOWN)
- Q(TIZEN_ERROR_NETWORK_UNREACHABLE)
- Q(TIZEN_ERROR_NETWORK_RESET)
- Q(TIZEN_ERROR_CONNECTION_ABORTED)
- Q(TIZEN_ERROR_CONNECTION_RESET_BY_PEER)
- Q(TIZEN_ERROR_BUFFER_SPACE)
- Q(TIZEN_ERROR_ENDPOINT_CONNECTED)
- Q(TIZEN_ERROR_ENDPOINT_NOT_CONNECTED)
- Q(TIZEN_ERROR_ENDPOINT_SHUTDOWN)
- Q(TIZEN_ERROR_TOO_MANY_REFERENCES)
- Q(TIZEN_ERROR_CONNECTION_TIME_OUT)
- Q(TIZEN_ERROR_CONNECTION_REFUSED)
- Q(TIZEN_ERROR_HOST_DOWN)
- Q(TIZEN_ERROR_NO_ROUTE_TO_HOST)
- Q(TIZEN_ERROR_ALREADY_IN_PROGRESS)
- Q(TIZEN_ERROR_NOW_IN_PROGRESS)
- Q(TIZEN_ERROR_STALE_NFS_FILE_HANDLE)
- Q(TIZEN_ERROR_STRUCTURE_UNCLEAN)
- Q(TIZEN_ERROR_NOT_XENIX_NAMED_TYPE_FILE)
- Q(TIZEN_ERROR_NO_XENIX_SEMAPHORES_AVAILABLE)
- Q(TIZEN_ERROR_IS_NAMED_TYPE_FILE)
- Q(TIZEN_ERROR_REMOTE_IO)
- Q(TIZEN_ERROR_QUOTA_EXCEEDED)
- Q(TIZEN_ERROR_NO_MEDIUM)
- Q(TIZEN_ERROR_WRONG_MEDIUM_TYPE)
- Q(TIZEN_ERROR_CANCELED)
- Q(TIZEN_ERROR_KEY_NOT_AVAILABLE)
- Q(TIZEN_ERROR_KEY_EXPIRED)
- Q(TIZEN_ERROR_KEY_REVOKED)
- Q(TIZEN_ERROR_KEY_REJECTED)
- Q(TIZEN_ERROR_OWNER_DEAD)
- Q(TIZEN_ERROR_UNKNOWN)
- Q(TIZEN_ERROR_TIMED_OUT)
- Q(TIZEN_ERROR_NOT_SUPPORTED)
- Q(TIZEN_ERROR_USER_NOT_CONSENTED)
- Q(TIZEN_ERROR_DEVICE_POLICY_RESTRICTION)
- Q(TIZEN_ERROR_END_OF_COLLECTION)
+ Q(TIZEN_ERROR_NONE)
+ Q(TIZEN_ERROR_NOT_PERMITTED)
+ Q(TIZEN_ERROR_NO_SUCH_FILE)
+ Q(TIZEN_ERROR_NO_SUCH_PROCESS)
+ Q(TIZEN_ERROR_INTERRUPTED_SYS_CALL)
+ Q(TIZEN_ERROR_IO_ERROR)
+ Q(TIZEN_ERROR_NO_SUCH_DEVICE)
+ Q(TIZEN_ERROR_ARGUMENT_LIST_TOO_LONG)
+ Q(TIZEN_ERROR_EXEC_FORMAT_ERROR)
+ Q(TIZEN_ERROR_BAD_FILE_NUMBER)
+ Q(TIZEN_ERROR_TRY_AGAIN)
+ Q(TIZEN_ERROR_OUT_OF_MEMORY)
+ Q(TIZEN_ERROR_PERMISSION_DENIED)
+ Q(TIZEN_ERROR_BAD_ADDRESS)
+ Q(TIZEN_ERROR_BLOCK_DEVICE_REQUIRED)
+ Q(TIZEN_ERROR_RESOURCE_BUSY)
+ Q(TIZEN_ERROR_FILE_EXISTS)
+ Q(TIZEN_ERROR_CROSS_DEVICE_LINK)
+ Q(TIZEN_ERROR_NOT_A_DIRECTORY)
+ Q(TIZEN_ERROR_IS_A_DIRECTORY)
+ Q(TIZEN_ERROR_INVALID_PARAMETER)
+ Q(TIZEN_ERROR_FILE_TABLE_OVERFLOW)
+ Q(TIZEN_ERROR_TOO_MANY_OPEN_FILES)
+ Q(TIZEN_ERROR_TOO_NOT_A_TERMINAL)
+ Q(TIZEN_ERROR_TOO_TEXT_FILE_BUSY)
+ Q(TIZEN_ERROR_FILE_TOO_LARGE)
+ Q(TIZEN_ERROR_FILE_NO_SPACE_ON_DEVICE)
+ Q(TIZEN_ERROR_ILLEGAL_SEEK)
+ Q(TIZEN_ERROR_READ_ONLY_FILESYSTEM)
+ Q(TIZEN_ERROR_NO_DATA)
+ Q(TIZEN_ERROR_TOO_MANY_LINKS)
+ Q(TIZEN_ERROR_BROKEN_PIPE)
+ Q(TIZEN_ERROR_ARGUMENT_OUT_OF_DOMAIN)
+ Q(TIZEN_ERROR_RESULT_OUT_OF_RANGE)
+ Q(TIZEN_ERROR_WOULD_CAUSE_DEADLOCK)
+ Q(TIZEN_ERROR_FILE_NAME_TOO_LONG)
+ Q(TIZEN_ERROR_FILE_NO_LOCKS_AVAILABLE)
+ Q(TIZEN_ERROR_INVALID_OPERATION)
+ Q(TIZEN_ERROR_DIR_NOT_EMPTY)
+ Q(TIZEN_ERROR_TOO_MANY_SYMBOLIC_LINKS)
+ Q(TIZEN_ERROR_WOULD_BLOCK)
+ Q(TIZEN_ERROR_CORRUPTED_SHARED_LIB)
+ Q(TIZEN_ERROR_LIB_SECTION_CORRUPTED)
+ Q(TIZEN_ERROR_LINK_TOO_MANY_SHARED_LIB)
+ Q(TIZEN_ERROR_SHARED_LIB_EXEC)
+ Q(TIZEN_ERROR_ILLEGAL_BYTE_SEQ)
+ Q(TIZEN_ERROR_SYSTEM_CALL_RESTART)
+ Q(TIZEN_ERROR_STREAMS_PIPE)
+ Q(TIZEN_ERROR_TOO_MANY_USERS)
+ Q(TIZEN_ERROR_NON_SOCKET)
+ Q(TIZEN_ERROR_NO_DEST_ADDRESS)
+ Q(TIZEN_ERROR_MSG_TOO_LONG)
+ Q(TIZEN_ERROR_PROTOCOL_WRONG_TYPE)
+ Q(TIZEN_ERROR_PROTOCOL_NOT_AVALIABLE)
+ Q(TIZEN_ERROR_PROTOCOL_NOT_SUPPORTED)
+ Q(TIZEN_ERROR_SOCKET_TYPE_NOT_SUPPORTED)
+ Q(TIZEN_ERROR_ENDPOINT_OPERATIN_NOT_SUPPORTED)
+ Q(TIZEN_ERROR_PROTOCOL_FAMILY_NOT_SUPPORTED)
+ Q(TIZEN_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED)
+ Q(TIZEN_ERROR_ADDRES_IN_USE)
+ Q(TIZEN_ERROR_CANNOT_ASSIGN_ADDRESS)
+ Q(TIZEN_ERROR_NETWORK_DOWN)
+ Q(TIZEN_ERROR_NETWORK_UNREACHABLE)
+ Q(TIZEN_ERROR_NETWORK_RESET)
+ Q(TIZEN_ERROR_CONNECTION_ABORTED)
+ Q(TIZEN_ERROR_CONNECTION_RESET_BY_PEER)
+ Q(TIZEN_ERROR_BUFFER_SPACE)
+ Q(TIZEN_ERROR_ENDPOINT_CONNECTED)
+ Q(TIZEN_ERROR_ENDPOINT_NOT_CONNECTED)
+ Q(TIZEN_ERROR_ENDPOINT_SHUTDOWN)
+ Q(TIZEN_ERROR_TOO_MANY_REFERENCES)
+ Q(TIZEN_ERROR_CONNECTION_TIME_OUT)
+ Q(TIZEN_ERROR_CONNECTION_REFUSED)
+ Q(TIZEN_ERROR_HOST_DOWN)
+ Q(TIZEN_ERROR_NO_ROUTE_TO_HOST)
+ Q(TIZEN_ERROR_ALREADY_IN_PROGRESS)
+ Q(TIZEN_ERROR_NOW_IN_PROGRESS)
+ Q(TIZEN_ERROR_STALE_NFS_FILE_HANDLE)
+ Q(TIZEN_ERROR_STRUCTURE_UNCLEAN)
+ Q(TIZEN_ERROR_NOT_XENIX_NAMED_TYPE_FILE)
+ Q(TIZEN_ERROR_NO_XENIX_SEMAPHORES_AVAILABLE)
+ Q(TIZEN_ERROR_IS_NAMED_TYPE_FILE)
+ Q(TIZEN_ERROR_REMOTE_IO)
+ Q(TIZEN_ERROR_QUOTA_EXCEEDED)
+ Q(TIZEN_ERROR_NO_MEDIUM)
+ Q(TIZEN_ERROR_WRONG_MEDIUM_TYPE)
+ Q(TIZEN_ERROR_CANCELED)
+ Q(TIZEN_ERROR_KEY_NOT_AVAILABLE)
+ Q(TIZEN_ERROR_KEY_EXPIRED)
+ Q(TIZEN_ERROR_KEY_REVOKED)
+ Q(TIZEN_ERROR_KEY_REJECTED)
+ Q(TIZEN_ERROR_OWNER_DEAD)
+ Q(TIZEN_ERROR_UNKNOWN)
+ Q(TIZEN_ERROR_TIMED_OUT)
+ Q(TIZEN_ERROR_NOT_SUPPORTED)
+ Q(TIZEN_ERROR_USER_NOT_CONSENTED)
+ Q(TIZEN_ERROR_DEVICE_POLICY_RESTRICTION)
+ Q(TIZEN_ERROR_END_OF_COLLECTION)
#undef Q
- return tmp.str();
- }
+ return tmp.str();
}
void BatchExecutor::killApplication(const std::pair<std::string, std::string> &appInstance)
return {};
}, { {"text"} } };
+ variables["str"] = EvaluationValueFunction{ [&](EvaluationValue e) -> EvaluationValue {
+ std::ostringstream tmp;
+ tmp << e;
+ return tmp.str();
+ }, { {"value"} } };
+
variables["len"] = EvaluationValueFunction{ [&](EvaluationValue e) -> EvaluationValue {
if (e.isString()) return static_cast<int>(e.asString().size());
if (e.isVector()) return static_cast<int>(e.asVector().size());
Optional<EvaluationValue> defValue;
if (tapCount > 1)
defValue = EvaluationValuePoint{ 300, 300 };
- return EvaluationValueFunction{ [ &, tapCount](EvaluationValue target) -> EvaluationValue {
+ return EvaluationValueFunction{ [ &, tapCount](EvaluationValue target, EvaluationValue fingers) -> EvaluationValue {
auto root = getVisibleRoot();
if (!root) throw EvaluationFailure{} << "no visible root (context changed didn't happen)";
ASSERT(root->getObject());
target = this->convertToUIElement(target.convertToString());
}
auto dest = target.convertToUIElement();
+ auto fingerCount = fingers.convertToInteger();
+ if (fingerCount <= 0 || fingerCount > 3)
+ throw EvaluationFailure{} << "invalid finger count (must be between 1 and 3)";
auto sleep_until = std::chrono::high_resolution_clock::now() + std::chrono::milliseconds{ 400 };
for (auto i = 0u; i < tapCount; ++i)
{
executeOnMainThread([&]() {
auto coord = dest->getScanningCoordinates();
- auto res = utils::generateTapGesture(coord.x, coord.y, 0.0f);
+ auto res = utils::generateTapGesture(coord.x, coord.y, 0.0f, fingerCount);
if (!res)
throw EvaluationFailure{} << "failed to execute " << tapCount << " tap gesture, " << res.getError().message;
});
std::this_thread::sleep_until(sleep_until);
return EvaluationValue{};
- }, { { "target" } } };
+ }, { { "target", defValue }, { "fingers", 1 } } };
};
variables["TAP"] = generateTapFunction(1);
variables["DOUBLE_TAP"] = generateTapFunction(2);
exec->outputStream() << "evaluation successed\n";
} catch (ReturnValue &r) {
exec->outputStream() << "script returned: " << r.getResult();
+ } catch (ContinueValue) {
+ exec->outputStream() << "unhandled continue statement";
+ } catch (BreakValue &r) {
+ exec->outputStream() << "unhandled break statement";
} catch (EvaluationFailure &e) {
if (e.hasLocation())
exec->outputStream() << e.location().toString() << ": ";
std::shared_ptr<UIElement> getVisibleRoot() override;
std::shared_ptr<UIElement> convertToUIElement(Point pt) override;
std::string getUIElementName(const std::shared_ptr<UIElement> &uiElem) override;
+ Atspi::StateSet getUIElementStates(const std::shared_ptr<UIElement> &o) override;
+ unsigned int getUIElementRole(const std::shared_ptr<UIElement> &o) override;
+ std::unordered_map<std::string, std::string> getUIElementAttributes(const std::shared_ptr<UIElement> &o) override;
std::string getUIElementUniqueId(const std::shared_ptr<UIElement> &uiElem) override;
std::shared_ptr<UIElement> convertToUIElement(const std::string &requestedName) override;
return *batchPathStack.back();
}
+Atspi::StateSet ExecutorInterface::getUIElementStates(const std::shared_ptr<UIElement> &o)
+{
+ throw EvaluationFailure{} << "getUIElementStates not implemeneted";
+}
+unsigned int ExecutorInterface::getUIElementRole(const std::shared_ptr<UIElement> &o)
+{
+ throw EvaluationFailure{} << "getUIElementRole not implemeneted";
+}
+std::unordered_map<std::string, std::string> ExecutorInterface::getUIElementAttributes(const std::shared_ptr<UIElement> &o)
+{
+ throw EvaluationFailure{} << "getUIElementAttributes not implemeneted";
+}
std::string ExecutorInterface::getUIElementName(const std::shared_ptr<UIElement> &elem)
{
*/
virtual std::string getUIElementName(const std::shared_ptr<UIElement> &);
+ virtual Atspi::StateSet getUIElementStates(const std::shared_ptr<UIElement> &);
+ virtual unsigned int getUIElementRole(const std::shared_ptr<UIElement> &);
+ virtual std::unordered_map<std::string, std::string> getUIElementAttributes(const std::shared_ptr<UIElement> &);
+
/**
* @brief Returns string uniquely identifying given at-spi object
*/
Q(Set)
Q(Dict)
Q(Wait)
+Q(Iterator)
#undef Q
std::string EvaluationValue::typeName() const
return value->oper_negate();
}
+EvaluationValue EvaluationValue::operator + (const EvaluationValue &o) const
+{
+ return value->oper_add(o.value);
+}
+EvaluationValue EvaluationValue::operator - (const EvaluationValue &o) const
+{
+ return value->oper_sub(o.value);
+}
+EvaluationValue EvaluationValue::operator / (const EvaluationValue &o) const
+{
+ return value->oper_div(o.value);
+}
+EvaluationValue EvaluationValue::operator * (const EvaluationValue &o) const
+{
+ return value->oper_mul(o.value);
+}
+EvaluationValue EvaluationValue::operator % (const EvaluationValue &o) const
+{
+ return value->oper_mod(o.value);
+}
+EvaluationValue EvaluationValue::operator & (const EvaluationValue &o) const
+{
+ return value->oper_bit_and(o.value);
+}
+EvaluationValue EvaluationValue::operator | (const EvaluationValue &o) const
+{
+ return value->oper_bit_or(o.value);
+}
+EvaluationValue EvaluationValue::operator ^ (const EvaluationValue &o) const
+{
+ return value->oper_bit_xor(o.value);
+}
+EvaluationValue EvaluationValue::operator << (const EvaluationValue &o) const
+{
+ return value->oper_lshift(o.value);
+}
+EvaluationValue EvaluationValue::operator >> (const EvaluationValue &o) const
+{
+ return value->oper_rshift(o.value);
+}
+EvaluationValue EvaluationValue::operator ~() const
+{
+ return value->oper_bit_neg();
+}
+
EvaluationValue EvaluationValue::attr_get(const std::string &name) const
{
return value->oper_attr_get(name);
return value->oper_attr_set(name, val.value);
}
+EvaluationValue EvaluationValue::iterate() const
+{
+ return value->convertToIterator();
+}
+
+EvaluationValue EvaluationValue::iterator_get_current() const
+{
+ return value->iterator_get();
+}
+
+void EvaluationValue::iterator_next() const
+{
+ value->iterator_next();
+}
+
+Optional<EvaluationValue> EvaluationValueIteratorCopyImpl::get() const
+{
+ if (index >= values.size()) return {};
+ return values[index];
+}
+
+void EvaluationValueIteratorCopyImpl::next()
+{
+ if (index < values.size()) ++index;
+}
+
std::ostream &operator << (std::ostream &s, const EvaluationValue &v)
{
return s << v.value;
mutable std::string cachedText;
};
+class EvaluationFailureIteratorExhaused : public EvaluationFailure
+{
+public:
+ using EvaluationFailure::EvaluationFailure;
+};
+
class EvaluationValue;
namespace std
};
}
+struct EvaluationValueIteratorInterface;
+
class EvaluationValueWaitInterface;
class EvaluationContext;
class EvaluationValueBase;
using EvaluationValueVector = std::vector<EvaluationValue>;
using EvaluationValueSet = std::unordered_set<EvaluationValue>;
using EvaluationValueDict = std::unordered_map<EvaluationValue, EvaluationValue>;
+using EvaluationValueIterator = std::shared_ptr<EvaluationValueIteratorInterface>;
+
+struct EvaluationValueIteratorInterface {
+ virtual ~EvaluationValueIteratorInterface() = default;
+
+ virtual Optional<EvaluationValue> get() const = 0;
+ virtual void next() = 0;
+};
class EvaluationValueWaitInterface
{
Q(Set)
Q(Dict)
Q(Wait)
+ Q(Iterator)
#undef Q
std::string typeName() const;
EvaluationValue index_set(const EvaluationValue &, const EvaluationValue &, const EvaluationValue &value);
EvaluationValue operator - () const;
+ EvaluationValue operator + (const EvaluationValue &o) const;
+ EvaluationValue operator - (const EvaluationValue &o) const;
+ EvaluationValue operator /(const EvaluationValue &o) const;
+ EvaluationValue operator * (const EvaluationValue &o) const;
+ EvaluationValue operator % (const EvaluationValue &o) const;
+ EvaluationValue operator & (const EvaluationValue &o) const;
+ EvaluationValue operator | (const EvaluationValue &o) const;
+ EvaluationValue operator ^ (const EvaluationValue &o) const;
+ EvaluationValue operator << (const EvaluationValue &o) const;
+ EvaluationValue operator >> (const EvaluationValue &o) const;
+ EvaluationValue operator ~() const;
EvaluationValue attr_get(const std::string &name) const;
EvaluationValue attr_set(const std::string &name, const EvaluationValue &value);
+ EvaluationValue iterate() const;
+ EvaluationValue iterator_get_current() const;
+ void iterator_next() const;
+
const auto &getInternalValue() const
{
return value;
}
};
+class EvaluationValueIteratorCopyImpl : public EvaluationValueIteratorInterface
+{
+public:
+ Optional<EvaluationValue> get() const override;
+ void next() override;
+
+ EvaluationValueIteratorCopyImpl(std::vector<EvaluationValue> values) : values(std::move(values)) { }
+private:
+ std::vector<EvaluationValue> values;
+ size_t index = 0;
+};
+
namespace detail
{
template<int ...> struct sequence {};
#define Q(type) \
void EvaluationValueBase::as(EvaluationValue ## type &v, const EvaluationValuePtr &q) { v = q->as ## type(); } \
void EvaluationValueBase::convertTo(EvaluationValue ## type &v, const EvaluationValuePtr &q) { v = q->convertTo ## type()->as ## type(); } \
- const EvaluationValue ## type &EvaluationValueBase::as ## type() { throw EvaluationFailure{} << \
+ const EvaluationValue ## type &EvaluationValueBase::as ## type() const { throw EvaluationFailure{} << \
"unsupported operation, type " << typeName() << " can't be represented as " #type; } \
- EvaluationValuePtr EvaluationValueBase::convertTo ## type() { throw EvaluationFailure{} << \
+ EvaluationValuePtr EvaluationValueBase::convertTo ## type() const { throw EvaluationFailure{} << \
"unsupported operation, can't convert " << typeName() << " to " #type; }
Q(String)
Q(Set)
Q(Dict)
Q(Wait)
+Q(Iterator)
#undef Q
std::ostream &operator << (std::ostream &s, const EvaluationValuePtr &v)
throw EvaluationFailure{} << "unsupported operation, " << typeName() << " doesn't have a " << name << " attribute";
}
+EvaluationValuePtr EvaluationValueBase::iterator_get() const
+{
+ throw EvaluationFailure{} << "unsupported operation: get iterator's current value (" << typeName() << " is not an iterator)";
+}
+
+void EvaluationValueBase::iterator_next()
+{
+ throw EvaluationFailure{} << "unsupported operation: pust iterator to next element (" << typeName() << " is not an iterator)";
+}
+
+EvaluationValuePtr EvaluationValueBase::oper_bit_neg() const
+{
+ throw EvaluationFailure{} << "unsupported operation, " << typeName() << " is not a number";
+}
+
+EvaluationValuePtr EvaluationValueBase::oper_add(const EvaluationValuePtr &o) const
+{
+ throw EvaluationFailure{} << "unsupported operation " << typeName() << " + " << o->typeName();
+}
+
+EvaluationValuePtr EvaluationValueBase::oper_sub(const EvaluationValuePtr &o) const
+{
+ throw EvaluationFailure{} << "unsupported operation " << typeName() << " - " << o->typeName();
+}
+
+EvaluationValuePtr EvaluationValueBase::oper_div(const EvaluationValuePtr &o) const
+{
+ throw EvaluationFailure{} << "unsupported operation " << typeName() << " / " << o->typeName();
+}
+
+EvaluationValuePtr EvaluationValueBase::oper_mul(const EvaluationValuePtr &o) const
+{
+ throw EvaluationFailure{} << "unsupported operation " << typeName() << " * " << o->typeName();
+}
+
+EvaluationValuePtr EvaluationValueBase::oper_mod(const EvaluationValuePtr &o) const
+{
+ throw EvaluationFailure{} << "unsupported operation " << typeName() << " % " << o->typeName();
+}
+
+EvaluationValuePtr EvaluationValueBase::oper_bit_and(const EvaluationValuePtr &o) const
+{
+ throw EvaluationFailure{} << "unsupported operation " << typeName() << " & " << o->typeName();
+}
+
+EvaluationValuePtr EvaluationValueBase::oper_bit_or(const EvaluationValuePtr &o) const
+{
+ throw EvaluationFailure{} << "unsupported operation " << typeName() << " | " << o->typeName();
+}
+
+EvaluationValuePtr EvaluationValueBase::oper_bit_xor(const EvaluationValuePtr &o) const
+{
+ throw EvaluationFailure{} << "unsupported operation " << typeName() << " ^ " << o->typeName();
+}
+
+EvaluationValuePtr EvaluationValueBase::oper_lshift(const EvaluationValuePtr &o) const
+{
+ throw EvaluationFailure{} << "unsupported operation " << typeName() << " << " << o->typeName();
+}
+
+EvaluationValuePtr EvaluationValueBase::oper_rshift(const EvaluationValuePtr &o) const
+{
+ throw EvaluationFailure{} << "unsupported operation " << typeName() << " >> " << o->typeName();
+}
+
EvaluationValuePtr EvaluationValueBase::oper_negate()
{
throw EvaluationFailure{} << "unsupported operation, " << typeName() << " is not a number";
throw EvaluationFailure{} << "unsupported operation, " << typeName() << " is not a wrte-able container";
}
+std::shared_ptr<EvaluationValueBase> EvaluationValueBase::shared_from_this() const
+{
+ return const_cast<EvaluationValueBase *>(this)->std::enable_shared_from_this<EvaluationValueBase>::shared_from_this();
+}
+
class EvaluationValueEmptyImpl : public EvaluationValueBase
{
public:
virtual EvaluationValuePtr oper_index_get(const EvaluationValuePtr &from, const EvaluationValuePtr &to);
virtual EvaluationValuePtr oper_index_set(const EvaluationValuePtr &index, const EvaluationValuePtr &value);
virtual EvaluationValuePtr oper_index_set(const EvaluationValuePtr &from, const EvaluationValuePtr &to, const EvaluationValuePtr &value);
+ virtual EvaluationValuePtr oper_bit_neg() const;
+ virtual EvaluationValuePtr oper_add(const EvaluationValuePtr &o) const;
+ virtual EvaluationValuePtr oper_sub(const EvaluationValuePtr &o) const;
+ virtual EvaluationValuePtr oper_div(const EvaluationValuePtr &o) const;
+ virtual EvaluationValuePtr oper_mul(const EvaluationValuePtr &o) const;
+ virtual EvaluationValuePtr oper_mod(const EvaluationValuePtr &o) const;
+ virtual EvaluationValuePtr oper_bit_and(const EvaluationValuePtr &o) const;
+ virtual EvaluationValuePtr oper_bit_or(const EvaluationValuePtr &o) const;
+ virtual EvaluationValuePtr oper_bit_xor(const EvaluationValuePtr &o) const;
+ virtual EvaluationValuePtr oper_lshift(const EvaluationValuePtr &o) const;
+ virtual EvaluationValuePtr oper_rshift(const EvaluationValuePtr &o) const;
+
+ virtual EvaluationValuePtr iterator_get() const;
+ virtual void iterator_next();
virtual void writeToStream(std::ostream &) const = 0;
static void as(EvaluationValue ## type &v, const EvaluationValuePtr &q); \
static void convertTo(EvaluationValue ## type &v, const EvaluationValuePtr &q); \
static EvaluationValuePtr create(EvaluationValue ## type); \
- virtual EvaluationValuePtr convertTo ## type(); \
- virtual const EvaluationValue ## type &as ## type(); \
+ virtual EvaluationValuePtr convertTo ## type() const; \
+ virtual const EvaluationValue ## type &as ## type() const; \
virtual bool is ## type() const { return false; }
Q(String)
Q(Set)
Q(Dict)
Q(Wait)
+ Q(Iterator)
#undef Q
+ static EvaluationValuePtr create(std::uint64_t v)
+ {
+ return create(static_cast<std::int64_t>(v));
+ }
+ static EvaluationValuePtr create(int v)
+ {
+ return create(static_cast<std::int64_t>(v));
+ }
+ static EvaluationValuePtr create(unsigned int v)
+ {
+ return create(static_cast<std::int64_t>(v));
+ }
size_t getSingleIndex(const EvaluationValuePtr &index, size_t size) const;
std::pair<size_t, size_t> getDoubleIndexes(const EvaluationValuePtr &from, const EvaluationValuePtr &to, size_t size) const;
ContextManager &operator = (const ContextManager &) = delete;
ContextManager &operator = (ContextManager &&) = delete;
};
+protected:
+ std::shared_ptr<EvaluationValueBase> shared_from_this() const;
};
std::ostream &operator << (std::ostream &s, const EvaluationValuePtr &v);
{
return true;
}
- EvaluationValuePtr convertToBoolean() override
+ EvaluationValuePtr convertToBoolean() const override
{
return shared_from_this();
}
- const EvaluationValueBoolean &asBoolean() override
+ const EvaluationValueBoolean &asBoolean() const override
{
return value;
}
{
return true;
}
- EvaluationValuePtr convertToBoolean() override
+ EvaluationValuePtr convertToBoolean() const override
{
return create(!value.empty());
}
- EvaluationValuePtr convertToDict() override
+ EvaluationValuePtr convertToDict() const override
{
return shared_from_this();
}
- const EvaluationValueDict &asDict() override
+ const EvaluationValueDict &asDict() const override
{
return value;
}
{
return value.find(v) != value.end();
}
+ EvaluationValuePtr oper_bit_and(const EvaluationValuePtr &o) const override
+ {
+ auto &r = o->asDict();
+ EvaluationValueDict res;
+ for (auto &q : value) {
+ if (r.find(q.first) != r.end()) {
+ res.insert(q);
+ }
+ }
+ return create(std::move(res));
+ }
+ EvaluationValuePtr oper_bit_or(const EvaluationValuePtr &o) const override
+ {
+ auto res = value;
+ res.insert(o->asDict().begin(), o->asDict().end());
+ return create(std::move(res));
+ }
+ EvaluationValuePtr oper_bit_xor(const EvaluationValuePtr &o) const override
+ {
+ auto &r = o->asDict();
+ EvaluationValueDict res;
+ for (auto &q : value) {
+ if (r.find(q.first) == r.end()) {
+ res.insert(q);
+ }
+ }
+ for (auto &q : r) {
+ if (value.find(q.first) == value.end()) {
+ res.insert(q);
+ }
+ }
+ return create(std::move(res));
+ }
+ EvaluationValuePtr oper_attr_get(const std::string &name) override
+ {
+ if (name == "len") return create(static_cast<EvaluationValueInteger>(value.size()));
+ return EvaluationValueBase::oper_attr_get(name);
+ }
EvaluationValuePtr oper_index_get(const EvaluationValuePtr &index) override
{
auto it = value.find(index);
it.first->second = val;
return val;
}
+ EvaluationValuePtr convertToIterator() const override
+ {
+ std::vector<EvaluationValue> tmp;
+ tmp.reserve(value.size());
+ for (auto &it : value) {
+ tmp.push_back(it.first);
+ }
+ return create(std::make_shared<EvaluationValueIteratorCopyImpl>(tmp));
+ }
private:
EvaluationValueDict value;
};
{
return true;
}
- EvaluationValuePtr convertToBoolean() override
+ EvaluationValuePtr convertToBoolean() const override
{
return create(bool(value));
}
- EvaluationValuePtr convertToDouble() override
+ EvaluationValuePtr convertToDouble() const override
{
return shared_from_this();
}
- EvaluationValuePtr convertToString() override
+ EvaluationValuePtr convertToString() const override
{
return create(std::to_string(value));
}
- EvaluationValuePtr convertToInteger() override
+ EvaluationValuePtr convertToInteger() const override
{
if (static_cast<EvaluationValueInteger>(value) != value)
throw EvaluationFailure{} << "'" << value << "' doesn't fit into integer";
return create(static_cast<EvaluationValueInteger>(value));
}
- const EvaluationValueDouble &asDouble() override
+ const EvaluationValueDouble &asDouble() const override
{
return value;
}
{
return create(-value);
}
+
+#define I(q) ((q)->convertToInteger()->asInteger())
+#define D(q) ((q)->convertToDouble()->asDouble())
+#define U(q) static_cast<uint64_t>(I(q))
+
+ EvaluationValuePtr oper_bit_neg() const override
+ {
+ return create(~U(this));
+ }
+ EvaluationValuePtr oper_bit_and(const EvaluationValuePtr &o) const override
+ {
+ return create(U(this) & U(o));
+ }
+ EvaluationValuePtr oper_bit_or(const EvaluationValuePtr &o) const override
+ {
+ return create(U(this) | U(o));
+ }
+ EvaluationValuePtr oper_bit_xor(const EvaluationValuePtr &o) const override
+ {
+ return create(U(this) ^ U(o));
+ }
+ EvaluationValuePtr oper_lshift(const EvaluationValuePtr &o) const override
+ {
+ return create(U(this) << U(o));
+ }
+ EvaluationValuePtr oper_rshift(const EvaluationValuePtr &o) const override
+ {
+ return create(U(this) >> U(o));
+ }
+ EvaluationValuePtr oper_mod(const EvaluationValuePtr &o) const override
+ {
+ return create(U(this) % U(o));
+ }
+#define Q(op) \
+ if (isInteger() && o->isInteger()) return create(I(this) op I(o)); \
+ return create(D(this) op D(o));
+ EvaluationValuePtr oper_add(const EvaluationValuePtr &o) const override
+ {
+ Q(+)
+ }
+ EvaluationValuePtr oper_sub(const EvaluationValuePtr &o) const override
+ {
+ Q(-)
+ }
+ EvaluationValuePtr oper_div(const EvaluationValuePtr &o) const override
+ {
+ return create(D(this) / D(o));
+ }
+ EvaluationValuePtr oper_mul(const EvaluationValuePtr &o) const override
+ {
+ Q(*)
+ }
+#undef Q
+#undef I
+#undef U
+#undef D
+
private:
EvaluationValueDouble value;
};
{
return true;
}
- EvaluationValuePtr convertToBoolean() override
+ EvaluationValuePtr convertToBoolean() const override
{
assert(value);
return create(bool(value));
}
- EvaluationValuePtr convertToFunction() override
+ EvaluationValuePtr convertToFunction() const override
{
return shared_from_this();
}
- const EvaluationValueFunction &asFunction() override
+ const EvaluationValueFunction &asFunction() const override
{
return value;
}
{
return true;
}
- EvaluationValuePtr convertToBoolean() override
+ EvaluationValuePtr convertToBoolean() const override
{
return create(bool(value));
}
- EvaluationValuePtr convertToInteger() override
+ EvaluationValuePtr convertToInteger() const override
{
return shared_from_this();
}
- EvaluationValuePtr convertToString() override
+ EvaluationValuePtr convertToString() const override
{
return create(std::to_string(value));
}
- EvaluationValuePtr convertToDouble() override
+ EvaluationValuePtr convertToDouble() const override
{
return create(static_cast<double>(value));
}
- const EvaluationValueInteger &asInteger() override
+ const EvaluationValueInteger &asInteger() const override
{
return value;
}
{
return create(-value);
}
+
+#define I(q) ((q)->convertToInteger()->asInteger())
+#define D(q) ((q)->convertToDouble()->asDouble())
+#define U(q) static_cast<uint64_t>(I(q))
+
+ EvaluationValuePtr oper_bit_neg() const override
+ {
+ return create(~U(this));
+ }
+ EvaluationValuePtr oper_bit_and(const EvaluationValuePtr &o) const override
+ {
+ return create(U(this) & U(o));
+ }
+ EvaluationValuePtr oper_bit_or(const EvaluationValuePtr &o) const override
+ {
+ return create(U(this) | U(o));
+ }
+ EvaluationValuePtr oper_bit_xor(const EvaluationValuePtr &o) const override
+ {
+ return create(U(this) ^ U(o));
+ }
+ EvaluationValuePtr oper_lshift(const EvaluationValuePtr &o) const override
+ {
+ return create(U(this) << U(o));
+ }
+ EvaluationValuePtr oper_rshift(const EvaluationValuePtr &o) const override
+ {
+ return create(U(this) >> U(o));
+ }
+ EvaluationValuePtr oper_mod(const EvaluationValuePtr &o) const override
+ {
+ return create(U(this) % U(o));
+ }
+#define Q(op) \
+ if (isInteger() && o->isInteger()) return create(I(this) op I(o)); \
+ return create(D(this) op D(o));
+ EvaluationValuePtr oper_add(const EvaluationValuePtr &o) const override
+ {
+ Q(+)
+ }
+ EvaluationValuePtr oper_sub(const EvaluationValuePtr &o) const override
+ {
+ Q(-)
+ }
+ EvaluationValuePtr oper_div(const EvaluationValuePtr &o) const override
+ {
+ return create(D(this) / D(o));
+ }
+ EvaluationValuePtr oper_mul(const EvaluationValuePtr &o) const override
+ {
+ Q(*)
+ }
+#undef Q
+#undef I
+#undef U
+#undef D
+
private:
EvaluationValueInteger value;
};
--- /dev/null
+/*
+ * Copyright 2018 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "EvaluationValueBase.hpp"
+
+class EvaluationValueIteratorImpl : public EvaluationValueBase
+{
+public:
+ EvaluationValueIteratorImpl(EvaluationValueIterator v) : value(v) { }
+
+ std::string typeName() const override
+ {
+ return "Boolean";
+ }
+ bool isIterator() const override
+ {
+ return true;
+ }
+ EvaluationValuePtr convertToIterator() const override
+ {
+ return shared_from_this();
+ }
+ const EvaluationValueIterator &asIterator() const override
+ {
+ return value;
+ }
+
+ void writeToStream(std::ostream &os) const override
+ {
+ os << "iterator";
+ }
+ bool oper_equal(const EvaluationValuePtr &other) override
+ {
+ return other->isIterator() && value == other->asIterator();
+ }
+ bool oper_is_true() override
+ {
+ return bool(value->get());
+ }
+ EvaluationValuePtr iterator_get() const override
+ {
+ auto v = value->get();
+ if (!v) throw EvaluationFailureIteratorExhaused{} << "iterator exhaused";
+ return v->getInternalValue();
+ }
+ void iterator_next() override
+ {
+ value->next();
+ }
+ EvaluationValuePtr oper_attr_get(const std::string &name) override
+ {
+ if (name == "next") return create([self = shared_from_this()]() -> EvaluationValue {
+ self->iterator_next();
+ return {};
+ });
+ if (name == "get") return create([self = shared_from_this()]() -> EvaluationValue {
+ return self->iterator_get();
+ });
+ return EvaluationValueBase::oper_attr_get(name);
+ }
+private:
+ EvaluationValueIterator value;
+};
+
+EvaluationValuePtr EvaluationValueBase::create(EvaluationValueIterator v)
+{
+ return std::make_shared<EvaluationValueIteratorImpl>(v);
+}
{
return true;
}
- EvaluationValuePtr convertToBoolean() override
+ EvaluationValuePtr convertToBoolean() const override
{
return create(true);
}
- EvaluationValuePtr convertToPoint() override
+ EvaluationValuePtr convertToPoint() const override
{
return shared_from_this();
}
- EvaluationValuePtr convertToUIElement() override
+ EvaluationValuePtr convertToUIElement() const override
{
return create(EvaluationContext::getCurrentEvaluationContext().executionInterface().convertToUIElement(value));
}
- const EvaluationValuePoint &asPoint() override
+ const EvaluationValuePoint &asPoint() const override
{
return value;
}
{
return true;
}
- EvaluationValuePtr convertToBoolean() override
+ EvaluationValuePtr convertToBoolean() const override
{
return create(!value.empty());
}
- EvaluationValuePtr convertToSet() override
+ EvaluationValuePtr convertToSet() const override
{
return shared_from_this();
}
- EvaluationValuePtr convertToVector() override
+ EvaluationValuePtr convertToVector() const override
{
return create(EvaluationValueVector{ value.begin(), value.end() });
}
- const EvaluationValueSet &asSet() override
+ const EvaluationValueSet &asSet() const override
{
return value;
}
}
os << " }";
}
+ EvaluationValuePtr oper_bit_and(const EvaluationValuePtr &o) const override
+ {
+ auto &r = o->asSet();
+ EvaluationValueSet res;
+ for (auto &q : value) {
+ if (r.find(q) != r.end()) {
+ res.insert(q);
+ }
+ }
+ return create(std::move(res));
+ }
+ EvaluationValuePtr oper_bit_or(const EvaluationValuePtr &o) const override
+ {
+ EvaluationValueSet res = value;
+ res.insert(o->asSet().begin(), o->asSet().end());
+ return create(std::move(res));
+ }
+ EvaluationValuePtr oper_bit_xor(const EvaluationValuePtr &o) const override
+ {
+ auto &r = o->asSet();
+ EvaluationValueSet res;
+ for (auto &q : value) {
+ if (r.find(q) == r.end()) {
+ res.insert(q);
+ }
+ }
+ for (auto &q : r) {
+ if (value.find(q) == value.end()) {
+ res.insert(q);
+ }
+ }
+ return create(std::move(res));
+ }
+ EvaluationValuePtr oper_attr_get(const std::string &name) override
+ {
+ if (name == "len") return create(static_cast<EvaluationValueInteger>(value.size()));
+ return EvaluationValueBase::oper_attr_get(name);
+ }
bool oper_equal(const EvaluationValuePtr &other) override
{
return other->isSet() && value == other->asSet();
{
return value.find(v) != value.end();
}
+ EvaluationValuePtr convertToIterator() const override
+ {
+ std::vector<EvaluationValue> tmp{ value.begin(), value.end() };
+ return create(std::make_shared<EvaluationValueIteratorCopyImpl>(tmp));
+ }
private:
EvaluationValueSet value;
};
{
return true;
}
- EvaluationValuePtr convertToBoolean() override
+ EvaluationValuePtr convertToBoolean() const override
{
return create(!value.empty());
}
- EvaluationValuePtr convertToString() override
+ EvaluationValuePtr convertToString() const override
{
return shared_from_this();
}
- EvaluationValuePtr convertToUIElement() override
+ EvaluationValuePtr convertToUIElement() const override
{
return create(EvaluationContext::getCurrentEvaluationContext().executionInterface().convertToUIElement(value));
}
- const EvaluationValueString &asString() override
+ const EvaluationValueString &asString() const override
{
return value;
}
EvaluationValuePtr oper_attr_get(const std::string &name) override
{
if (name == "len") return create(static_cast<EvaluationValueInteger>(value.size()));
+ if (name == "join") {
+ return create(EvaluationValueFunction{
+ [self = std::static_pointer_cast<EvaluationValueStringImpl>(shared_from_this())](EvaluationValue data) -> EvaluationValue {
+ auto join = [](const std::string & mid, auto beg, auto end)
+ {
+ std::ostringstream tmp;
+ bool first = true;
+ while (beg != end) {
+ if (first) first = false;
+ else tmp << mid;
+ tmp << (*beg).convertToString();
+ ++beg;
+ }
+ return tmp.str();
+ };
+ if (data.isVector())
+ return create(join(self->value, data.asVector().begin(), data.asVector().end()));
+ if (data.isSet())
+ return create(join(self->value, data.asSet().begin(), data.asSet().end()));
+ throw EvaluationFailure{} << "can't join " << data.typeName();
+ }, { { "data" } } });
+ }
+
return EvaluationValueBase::oper_attr_get(name);
}
+ EvaluationValuePtr oper_add(const EvaluationValuePtr &o) const override
+ {
+ return create(value + o->asString());
+ }
EvaluationValuePtr oper_index_get(const EvaluationValuePtr &index) override
{
auto i = getSingleIndex(index, value.size());
auto indexes = getDoubleIndexes(from, to, value.size());
return create(value.substr(indexes.first, indexes.second - indexes.first));
}
+ EvaluationValuePtr convertToIterator() const override
+ {
+ std::vector<EvaluationValue> tmp;
+ tmp.reserve(value.size());
+ for (auto q : value)
+ tmp.push_back(create(std::string{ &q, 1 }));
+ return create(std::make_shared<EvaluationValueIteratorCopyImpl>(tmp));
+ }
+
private:
EvaluationValueString value;
};
{
return true;
}
- EvaluationValuePtr convertToBoolean() override
+ EvaluationValuePtr convertToBoolean() const override
{
return create(bool(value->getObject()));
}
- EvaluationValuePtr convertToUIElement() override
+ EvaluationValuePtr convertToUIElement() const override
{
return shared_from_this();
}
- const EvaluationValueUIElement &asUIElement() override
+ const EvaluationValueUIElement &asUIElement() const override
{
return value;
}
{
if (name == "name")
return create(EvaluationContext::getCurrentEvaluationContext().executionInterface().getUIElementName(value));
- if (name == "middle_point")
+ if (name == "center")
return create(value->getScanningCoordinates());
+ if (name == "role")
+ return create(EvaluationContext::getCurrentEvaluationContext().executionInterface().getUIElementRole(value));
+ if (name == "states") {
+ auto tmp = EvaluationContext::getCurrentEvaluationContext().executionInterface().getUIElementStates(value);
+ EvaluationValueSet v;
+ for (auto i = 0u; i < tmp.size(); ++i) {
+ if (tmp[i])
+ v.insert(i);
+ }
+ return create(std::move(v));
+ }
+ if (name == "attributes") {
+ auto tmp = EvaluationContext::getCurrentEvaluationContext().executionInterface().getUIElementAttributes(value);
+ EvaluationValueDict d;
+ for (auto &it : d) {
+ d.insert({ std::move(it.first), std::move(it.second) });
+ }
+ return create(std::move(d));
+ }
return EvaluationValueBase::oper_attr_get(name);
}
private:
{
return true;
}
- EvaluationValuePtr convertToBoolean() override
+ EvaluationValuePtr convertToBoolean() const override
{
return create(!value.empty());
}
- EvaluationValuePtr convertToVector() override
+ EvaluationValuePtr convertToVector() const override
{
return shared_from_this();
}
- const EvaluationValueVector &asVector() override
+ EvaluationValuePtr convertToIterator() const override
+ {
+ return create(std::make_shared<EvaluationValueIteratorCopyImpl>(value));
+ }
+ const EvaluationValueVector &asVector() const override
{
return value;
}
return true;
return false;
}
+ EvaluationValuePtr oper_attr_get(const std::string &name) override
+ {
+ if (name == "len") return create(static_cast<EvaluationValueInteger>(value.size()));
+ if (name == "append") return create([self = std::static_pointer_cast<EvaluationValueVectorImpl>(shared_from_this())](EvaluationValue o) -> EvaluationValue {
+ self->value.push_back(std::move(o));
+ return {};
+ });
+ if (name == "insert") return create([self = std::static_pointer_cast<EvaluationValueVectorImpl>(shared_from_this())]
+ (EvaluationValue index, EvaluationValue o) -> EvaluationValue {
+ auto i = self->getSingleIndex(index.getInternalValue(), self->value.size());
+ self->value.insert(self->value.begin() + i, std::move(o));
+ return {};
+ });
+ if (name == "filter") {
+ return create(EvaluationValueFunction{
+ [self = std::static_pointer_cast<EvaluationValueVectorImpl>(shared_from_this())](EvaluationValue filter) -> EvaluationValue {
+ auto &f = filter.asFunction();
+ auto v = EvaluationValueVector{};
+ for (auto &q : self->value)
+ {
+ if (f({ { q } })) {
+ v.push_back(q);
+ }
+ }
+ return create(std::move(v));
+ }, { {"predicate" } } });
+ }
+ if (name == "pop") {
+ return create(EvaluationValueFunction{
+ [self = std::static_pointer_cast<EvaluationValueVectorImpl>(shared_from_this())](EvaluationValue index) -> EvaluationValue {
+ auto i = self->getSingleIndex(index.getInternalValue(), self->value.size());
+ auto v = std::move(self->value[i]);
+ self->value.erase(self->value.begin() + i);
+ return v;
+ }, { {"index", -1 } } });
+ }
+ return EvaluationValueBase::oper_attr_get(name);
+ }
+ EvaluationValuePtr oper_add(const EvaluationValuePtr &o) const override
+ {
+ auto &v = o->asVector();
+ auto r = EvaluationValueVector{};
+ r.reserve(value.size() + v.size());
+ for (auto &q : value) r.push_back(q);
+ for (auto &q : v) r.push_back(q);
+ return create(std::move(r));
+ }
EvaluationValuePtr oper_index_get(const EvaluationValuePtr &index) override
{
auto i = getSingleIndex(index, value.size());
return shared_from_this();
}
private:
- EvaluationValueVector value;
+ mutable EvaluationValueVector value;
};
EvaluationValuePtr EvaluationValueBase::create(EvaluationValueVector v)
{
return true;
}
- EvaluationValuePtr convertToWait() override
+ EvaluationValuePtr convertToWait() const override
{
return shared_from_this();
}
- const EvaluationValueWait &asWait() override
+ const EvaluationValueWait &asWait() const override
{
return value;
}
void IdentifierEvaluator::printSelfInfo(unsigned int depth) const
{
- printLocationAndIndent(location(), depth) << "identifier " << identifier << "\n";
+ printLocationAndIndent(location(), depth) << "identifier " << identifier;
}
AttributeEvaluator::AttributeEvaluator(TokenLocation tokenLocation, ExprPtr self, std::string identifier) :
void AttributeEvaluator::printSelfInfo(unsigned int depth) const
{
- printLocationAndIndent(location(), depth) << "attribute " << identifier << "\n";
- printLocationAndIndent(location(), depth) << "self is\n";
+ printLocationAndIndent(location(), depth) << "attribute " << identifier;
+ printLocationAndIndent(location(), depth) << "self is";
self->printSelfInfo(depth + 1);
}
void AttributeSetterEvaluator::printSelfInfo(unsigned int depth) const
{
- printLocationAndIndent(location(), depth) << "attribute setter " << identifier << "\n";
- printLocationAndIndent(location(), depth) << "self is\n";
+ printLocationAndIndent(location(), depth) << "attribute setter " << identifier;
+ printLocationAndIndent(location(), depth) << "self is";
self->printSelfInfo(depth + 1);
- printLocationAndIndent(location(), depth) << "value to set is\n";
+ printLocationAndIndent(location(), depth) << "value to set is";
value->printSelfInfo(depth + 1);
}
void SetterEvaluator::printSelfInfo(unsigned int depth) const
{
- printLocationAndIndent(location(), depth) << "setter " << identifier << "\n";
- printLocationAndIndent(location(), depth) << "value to set is\n";
+ printLocationAndIndent(location(), depth) << "setter " << identifier;
+ printLocationAndIndent(location(), depth) << "value to set is";
value->printSelfInfo(depth + 1);
}
void PointEvaluator::printSelfInfo(unsigned int depth) const
{
- printLocationAndIndent(location(), depth) << "point\n";
- printLocationAndIndent(location(), depth) << "x is\n";
+ printLocationAndIndent(location(), depth) << "point";
+ printLocationAndIndent(location(), depth) << "x is";
x->printSelfInfo(depth + 1);
- printLocationAndIndent(location(), depth) << "y is\n";
+ printLocationAndIndent(location(), depth) << "y is";
y->printSelfInfo(depth + 1);
}
void IntegerEvaluator::printSelfInfo(unsigned int depth) const
{
- printLocationAndIndent(location(), depth) << "integer " << value << "\n";
+ printLocationAndIndent(location(), depth) << "integer " << value;
}
void DoubleEvaluator::printSelfInfo(unsigned int depth) const
{
- printLocationAndIndent(location(), depth) << "double " << value << "\n";
+ printLocationAndIndent(location(), depth) << "double " << value;
}
void StringEvaluator::printSelfInfo(unsigned int depth) const
{
- printLocationAndIndent(location(), depth) << "string '" << value << "'\n";
+ printLocationAndIndent(location(), depth) << "string '" << value << "'";
}
auto os = printLocationAndIndent(location(), depth);
switch (kind) {
case Kind::SET:
- os << "set\n";
+ os << "set";
break;
case Kind::VECTOR:
- os << "vector\n";
+ os << "vector";
break;
case Kind::DICT:
- os << "dict\n";
+ os << "dict";
break;
}
}
if (kind == Kind::SET || kind == Kind::VECTOR) {
for (auto i = 0u; i < values.size(); ++i) {
- printLocationAndIndent(location(), depth) << "element " << (i + 1) << "\n";
+ printLocationAndIndent(location(), depth) << "element " << (i + 1);
values[i]->printSelfInfo(depth + 1);
}
} else {
for (auto i = 0u; i < values.size(); i += 2) {
- printLocationAndIndent(location(), depth) << "element " << (i / 2 + 1) << " key\n";
+ printLocationAndIndent(location(), depth) << "element " << (i / 2 + 1) << " key";
values[i]->printSelfInfo(depth + 1);
- printLocationAndIndent(location(), depth) << "element " << (i / 2 + 1) << " value\n";
+ printLocationAndIndent(location(), depth) << "element " << (i / 2 + 1) << " value";
values[i + 1]->printSelfInfo(depth + 1);
}
}
if (vals.size() == 3) return vals[0].index_set(vals[1], vals[1]);
ASSERT(vals.size() == 4);
return vals[0].index_set(vals[1], vals[2], vals[3]);
+ case Kind::ADD:
+ return vals[0] + vals[1];
+ case Kind::SUB:
+ return vals[0] - vals[1];
+ case Kind::MUL:
+ return vals[0] * vals[1];
+ case Kind::DIV:
+ return vals[0] / vals[1];
+ case Kind::MOD:
+ return vals[0] % vals[1];
+ case Kind::LSHIFT:
+ return vals[0] << vals[1];
+ case Kind::RSHIFT:
+ return vals[0] >> vals[1];
+ case Kind::BIT_OR:
+ return vals[0] | vals[1];
+ case Kind::BIT_NOT:
+ return ~vals[0];
+ case Kind::BIT_AND:
+ return vals[0] & vals[1];
+ case Kind::BIT_XOR:
+ return vals[0] ^ vals[1];
+ case Kind::LOG_AND:
+ return bool(vals[0]) && bool(vals[1]);
+ case Kind::LOG_OR:
+ return bool(vals[0]) || bool(vals[1]);
}
ASSERT(0);
throw EvaluationFailure{} << "unknown operator";
case Kind::SET:
desc = "[]=";
break;
+ case Kind::ADD:
+ desc = "+";
+ break;
+ case Kind::SUB:
+ desc = "-";
+ break;
+ case Kind::MUL:
+ desc = "*";
+ break;
+ case Kind::DIV:
+ desc = "/";
+ break;
+ case Kind::MOD:
+ desc = "%";
+ break;
+ case Kind::LSHIFT:
+ desc = "<<";
+ break;
+ case Kind::RSHIFT:
+ desc = ">>";
+ break;
+ case Kind::BIT_OR:
+ desc = "|";
+ break;
+ case Kind::BIT_NOT:
+ desc = "~";
+ break;
+ case Kind::BIT_AND:
+ desc = "&";
+ break;
+ case Kind::BIT_XOR:
+ desc = "^";
+ break;
+ case Kind::LOG_AND:
+ desc = "and";
+ break;
+ case Kind::LOG_OR:
+ desc = "or";
+ break;
}
- os << desc << "\n";
+ os << desc;
}
for (auto i = 0u; i < args.size(); ++i) {
- printLocationAndIndent(location(), depth) << "element " << (i + 1) << " key\n";
+ printLocationAndIndent(location(), depth) << "element " << (i + 1);
args[i]->printSelfInfo(depth + 1);
}
}
}
for (auto i = 0u; i < args.size(); ++i) {
- printLocationAndIndent(location(), depth) << "argument " << (i + 1) << " key\n";
+ printLocationAndIndent(location(), depth) << "argument " << (i + 1) << " key";
args[i]->printSelfInfo(depth + 1);
}
}
void BooleanEvaluator::printSelfInfo(unsigned int depth) const
{
- printLocationAndIndent(location(), depth) << "boolean " << (value ? "true" : "false") << "\n";
+ printLocationAndIndent(location(), depth) << "boolean " << (value ? "true" : "false");
}
void CallEvaluator::printSelfInfo(unsigned int depth) const
{
- printLocationAndIndent(location(), depth) << "function call\n";
+ printLocationAndIndent(location(), depth) << "function call";
function->printSelfInfo(depth + 1);
for (auto i = 0u; i < args.size(); ++i) {
- printLocationAndIndent(location(), depth) << "arg " << i << " is\n";
+ printLocationAndIndent(location(), depth) << "arg " << i << " is";
args[i]->printSelfInfo(depth + 1);
}
}
+LambdaEvaluator::LambdaEvaluator(TokenLocation tokenLocation, std::vector<std::string> argNames, StatPtr codeBlock) :
+ ExpressionEvaluator(std::move(tokenLocation)), argNames(std::move(argNames)), codeBlock(std::move(codeBlock)) { }
+
+EvaluationValue LambdaEvaluator::evaluateImpl() const
+{
+ EvaluationValue tmp;
+ tmp = EvaluationValueFunction {[ = ](EvaluationValueFunction::Args args) -> EvaluationValue {
+ if (this->argNames.size() != args.size())
+ throw EvaluationFailure{} << "invalid number of arguments";
+ EvaluationContext ctx;
+ for (auto i = 0u; i < args.size(); ++i)
+ {
+ ctx.setVariable(argNames[i], args[i]);
+ }
+ try
+ {
+ DebugEvaluator{} << getDebugId() << ": function is called, evaluating";
+ codeBlock->evaluate();
+ } catch (ReturnValue &r)
+ {
+ DebugEvaluator{} << getDebugId() << ": got return value " << r.getResult();
+ return r.getResult();
+ }
+ return {};
+ }
+ };
+ return tmp;
+}
+
+void LambdaEvaluator::printSelfInfo(unsigned int depth) const
+{
+ printLocationAndIndent(location(), depth) << "lambda definition";
+ for (auto i = 0u; i < argNames.size(); ++i) {
+ printLocationAndIndent(location(), depth) << "arg " << i << " is " << argNames[i];
+ }
+ printLocationAndIndent(location(), depth) << "body";
+ codeBlock->printSelfInfo(depth + 1);
+}
+
FunctionEvaluator::FunctionEvaluator(TokenLocation location_, std::string functionName, std::vector<std::string> argNames, StatPtr codeBlock):
StatementEvaluator(location_), functionName(std::move(functionName)), argNames(std::move(argNames)), codeBlock(std::move(codeBlock)) {}
void FunctionEvaluator::evaluateImpl() const
{
- /* TODO: add named parameters
- std::vector<EvaluationValueFunction::Arg> tmp;
- for (auto &arg: argNames) {
- tmp.push_back(arg);
- }
- */
EvaluationContext::getCurrentEvaluationContext().setVariable(functionName,
EvaluationValueFunction {[ = ](EvaluationValueFunction::Args args) -> EvaluationValue {
if (this->argNames.size() != args.size())
void FunctionEvaluator::printSelfInfo(unsigned int depth) const
{
- printLocationAndIndent(location(), depth) << "function definition " << functionName << "\n";
+ printLocationAndIndent(location(), depth) << "function definition " << functionName;
for (auto i = 0u; i < argNames.size(); ++i) {
- printLocationAndIndent(location(), depth) << "arg " << i << " is " << argNames[i] << "\n";
+ printLocationAndIndent(location(), depth) << "arg " << i << " is " << argNames[i];
}
- printLocationAndIndent(location(), depth) << "body\n";
+ printLocationAndIndent(location(), depth) << "body";
codeBlock->printSelfInfo(depth + 1);
}
+
ReturnEvaluator::ReturnEvaluator(TokenLocation location_, ExprPtr result):
StatementEvaluator(location_), result(std::move(result)) {}
void ReturnEvaluator::printSelfInfo(unsigned int depth) const
{
- printLocationAndIndent(location(), depth) << "return ";
- result->printSelfInfo(depth + 1);
+ printLocationAndIndent(location(), depth) << "return";
+ if (result) result->printSelfInfo(depth + 1);
}
void BlockEvaluator::printSelfInfo(unsigned int depth) const
{
- printLocationAndIndent(location(), depth) << "block\n";
+ printLocationAndIndent(location(), depth) << "block";
for (auto &e : evals)
e->printSelfInfo(depth + 1);
}
void WaitEvaluator::printSelfInfo(unsigned int depth) const
{
- printLocationAndIndent(location(), depth) << "wait\n";
+ printLocationAndIndent(location(), depth) << "wait";
exec->printSelfInfo(depth + 1);
for (auto &w : waits) {
- printLocationAndIndent(location(), depth) << "for\n";
+ printLocationAndIndent(location(), depth) << "for";
w->printSelfInfo(depth + 1);
}
}
+
+
+ForEvaluator::ForEvaluator(TokenLocation location_, std::string ident, ExprPtr iterator, StatPtr body, StatPtr else_)
+ : StatementEvaluator(location_), ident(std::move(ident)), iterator(std::move(iterator)), body(std::move(body)), else_(std::move(else_)) {}
+
+void ForEvaluator::evaluateImpl() const
+{
+ auto iter_ = iterator->evaluate();
+ auto iter = iter_.convertToIterator();
+ bool broken = false;
+
+ while (1) {
+ auto v = iter->get();
+ if (!v) break;
+ EvaluationContext::getCurrentEvaluationContext().setVariable(ident, std::move(*v));
+ try {
+ body->evaluate();
+ } catch (ContinueValue) {
+
+ } catch (BreakValue) {
+ broken = true;
+ break;
+ }
+ iter->next();
+ }
+ if (!broken && else_) else_->evaluate();
+}
+
+void ForEvaluator::printSelfInfo(unsigned int depth) const
+{
+ printLocationAndIndent(location(), depth) << "for " << ident << " in";
+ iterator->printSelfInfo(depth + 1);
+ printLocationAndIndent(location(), depth) << "body";
+ body->printSelfInfo(depth + 1);
+ if (else_) {
+ printLocationAndIndent(location(), depth) << "else";
+ else_->printSelfInfo(depth + 1);
+ }
+}
+
+WhileEvaluator::WhileEvaluator(TokenLocation location_, ExprPtr condition, StatPtr body, StatPtr else_)
+ : StatementEvaluator(location_), condition(std::move(condition)), body(std::move(body)), else_(std::move(else_)) {}
+
+void WhileEvaluator::evaluateImpl() const
+{
+ bool broken = false;
+
+ while (1) {
+ auto val = condition->evaluate();
+ if (!val.convertToBoolean()) break;
+ try {
+ body->evaluate();
+ } catch (ContinueValue) {
+ } catch (BreakValue) {
+ broken = true;
+ break;
+ }
+ }
+ if (!broken && else_) else_->evaluate();
+}
+
+void WhileEvaluator::printSelfInfo(unsigned int depth) const
+{
+ printLocationAndIndent(location(), depth) << "while";
+ condition->printSelfInfo(depth + 1);
+ printLocationAndIndent(location(), depth) << "body";
+ body->printSelfInfo(depth + 1);
+ if (else_) {
+ printLocationAndIndent(location(), depth) << "else";
+ else_->printSelfInfo(depth + 1);
+ }
+}
+
+IfEvaluator::IfEvaluator(TokenLocation location_, ExprPtr condition, StatPtr body, StatPtr else_)
+ : StatementEvaluator(location_), condition(std::move(condition)), body(std::move(body)), else_(std::move(else_)) {}
+
+void IfEvaluator::evaluateImpl() const
+{
+ auto v = condition->evaluate();
+ auto v2 = v.convertToBoolean();
+ if (v2) {
+ body->evaluate();
+ } else if (else_) {
+ else_->evaluate();
+ }
+}
+
+void IfEvaluator::printSelfInfo(unsigned int depth) const
+{
+ printLocationAndIndent(location(), depth) << "if";
+ condition->printSelfInfo(depth + 1);
+ printLocationAndIndent(location(), depth) << "body";
+ body->printSelfInfo(depth + 1);
+ if (else_) {
+ printLocationAndIndent(location(), depth) << "else";
+ else_->printSelfInfo(depth + 1);
+ }
+}
+
+BreakEvaluator::BreakEvaluator(TokenLocation location_) : StatementEvaluator(location_) {}
+
+void BreakEvaluator::evaluateImpl() const
+{
+ throw BreakValue{};
+}
+
+void BreakEvaluator::printSelfInfo(unsigned int depth) const
+{
+ printLocationAndIndent(location(), depth) << "break";
+}
+
+ContinueEvaluator::ContinueEvaluator(TokenLocation location_) : StatementEvaluator(location_) {}
+
+void ContinueEvaluator::evaluateImpl() const
+{
+ throw ContinueValue{};
+}
+
+void ContinueEvaluator::printSelfInfo(unsigned int depth) const
+{
+ printLocationAndIndent(location(), depth) << "continue";
+}
EvaluationValue evaluateImpl() const override;
public:
enum class Kind {
- IN, GET, SET, MINUS, NOT
+ IN, GET, SET, MINUS, NOT, LOG_OR, LOG_AND, ADD, SUB, MUL, DIV, MOD, LSHIFT, RSHIFT, BIT_OR, BIT_NOT, BIT_AND, BIT_XOR
};
OperatorEvaluator(TokenLocation location_, ExprPtrs args, Kind kind);
void printSelfInfo(unsigned int depth) const override;
};
+class LambdaEvaluator : public ExpressionEvaluator
+{
+ std::vector<std::string> argNames;
+ StatPtr codeBlock;
+public:
+ LambdaEvaluator(TokenLocation location_, std::vector<std::string> argNames, StatPtr codeBlock);
+protected:
+ EvaluationValue evaluateImpl() const override;
+public:
+ void printSelfInfo(unsigned int depth) const override;
+};
+
+class WhileEvaluator : public StatementEvaluator
+{
+ ExprPtr condition;
+ StatPtr body, else_;
+public:
+ WhileEvaluator(TokenLocation location_, ExprPtr condition, StatPtr body, StatPtr else_);
+protected:
+ void evaluateImpl() const override;
+ void printSelfInfo(unsigned int depth) const override;
+};
+
+class ForEvaluator : public StatementEvaluator
+{
+ std::string ident;
+ ExprPtr iterator;
+ StatPtr body, else_;
+public:
+ ForEvaluator(TokenLocation location_, std::string ident, ExprPtr iterator, StatPtr body, StatPtr else_);
+protected:
+ void evaluateImpl() const override;
+ void printSelfInfo(unsigned int depth) const override;
+};
+
+class IfEvaluator : public StatementEvaluator
+{
+ ExprPtr condition;
+ StatPtr body, else_;
+public:
+ IfEvaluator(TokenLocation location_, ExprPtr condition, StatPtr body, StatPtr else_);
+protected:
+ void evaluateImpl() const override;
+ void printSelfInfo(unsigned int depth) const override;
+};
+
+class BreakEvaluator : public StatementEvaluator
+{
+public:
+ BreakEvaluator(TokenLocation location_);
+protected:
+ void evaluateImpl() const override;
+ void printSelfInfo(unsigned int depth) const override;
+};
+
+class ContinueEvaluator : public StatementEvaluator
+{
+public:
+ ContinueEvaluator(TokenLocation location_);
+protected:
+ void evaluateImpl() const override;
+ void printSelfInfo(unsigned int depth) const override;
+};
+
+
+
#endif
* If found, resulting token will be KEYWORD rather than IDENTIFIER.
*/
static std::unordered_set<std::string> keywords {
- "true", "false", "def", "return"
+ "true", "false", "def", "return", "if", "else", "elif", "for", "in", "break", "continue", "while"
};
/**
* Note, that when adding new operator, you must put it in collection with correct size (first element of the pair).
*/
static std::vector<std::pair<unsigned int, std::unordered_set<std::string>>> operatorsbyLength {
- { 2, { "==", "!=", "<=", ">=", "->" } },
+ { 2, { "==", "!=", "<=", ">=", "->", "<<", ">>" } },
{
1, {
"<", ">", "(", ")", ",", "=", "[", "]", "+", "-", ".", "*", "/", "{", "}",
- "!", "-", ":",
+ "!", "-", ":", "%", "<<", ">>", "&", "|", "^", "~"
}
},
};
auto nextLineIndex = lineStart;
for (; nextLineIndex < source.size() && source[nextLineIndex] != '\n'; ++nextLineIndex);
auto lineContent = source.substr(lineStart, nextLineIndex - lineStart);
+ for (auto &q : lineContent) {
+ if (q < ' ') q = ' ';
+ }
lineInfo = std::make_shared<TokenLocation::LineInfo>(TokenLocation::LineInfo{
lineContent, fileNamePtr, line
});
}
return true;
}
+ bool checkTokenText(const std::string &text1, const std::string &text2)
+ {
+ if (index >= tokens.size()) {
+ error("unexpected end of file");
+ return false;
+ }
+ if (tokens[index].text() != text1 && tokens[index].text() != text2) {
+ error("expected '" + text1 + "' or '" + text2 + "', got '" + tokens[index].text() + "'");
+ return false;
+ }
+ return true;
+ }
/**
* @brief Tries to consume token with type t
*
return true;
}
+ bool consume(const std::string &t1, const std::string &t2)
+ {
+ if (!checkTokenText(t1, t2)) return false;
+ ++index;
+ return true;
+ }
+
/**
* @brief Tries to parse arguments (as in function call), returns true if successful.
*
*/
ExprPtr parseInteger(const Token &t)
{
- size_t pos = 0;
- auto val = std::stoi(t.text(), &pos);
- if (pos != t.text().size()) {
- error("'" + t.text() + "' is not a valid integer");
- return {};
+ std::uint64_t val = 0;
+ for (auto q : t.text()) {
+ if (q >= '0' && q <= '9') {
+ auto val2 = val * 10 + q - '0';
+ if (val2 < val) {
+ error("'" + t.text() + "' is not a valid integer");
+ return {};
+ }
+ val = val2;
+ } else {
+ error("'" + t.text() + "' is not a valid integer");
+ return {};
+ }
}
- return std::make_shared<IntegerEvaluator>(t.location(), val);
+ return std::make_shared<IntegerEvaluator>(t.location(), static_cast<std::int64_t>(val));
}
/**
* @brief Tries to parse token as double
case TokenType::KEYWORD:
if (t.text() == "true") return std::make_shared<BooleanEvaluator>(t.location(), true);
if (t.text() == "false") return std::make_shared<BooleanEvaluator>(t.location(), false);
+ if (t.text() == "def" && index < tokens.size() && tokens[index].text() == "(") return parseLambda();
break;
case TokenType::IDENTIFIER:
if (index < tokens.size() && tokens[index].text() == "=") {
{
static std::unordered_map<std::string, OperatorEvaluator::Kind> opers {
{ "-", OperatorEvaluator::Kind::MINUS },
- { "not", OperatorEvaluator::Kind::NOT },
+ { "~", OperatorEvaluator::Kind::BIT_NOT },
};
if (index < tokens.size()) {
auto it = opers.find(tokens[index].text());
return std::move(e);
}
+ ExprPtr parseExprOper1()
+ {
+ auto v = parsePostfixExpr();
+ while (index < tokens.size()) {
+ OperatorEvaluator::Kind kind;
+ if (tokens[index].text() == "*") kind = OperatorEvaluator::Kind::MUL;
+ else if (tokens[index].text() == "/") kind = OperatorEvaluator::Kind::DIV;
+ else if (tokens[index].text() == "%") kind = OperatorEvaluator::Kind::MOD;
+ else break;
+ ++index;
+ auto v2 = parsePostfixExpr();
+ v = std::make_shared<OperatorEvaluator>(tokens[index].location(), std::vector<ExprPtr> { std::move(v), std::move(v2) }, kind);
+ }
+ return v;
+ }
+
+ ExprPtr parseExprOper2()
+ {
+ auto v = parseExprOper1();
+ while (index < tokens.size()) {
+ OperatorEvaluator::Kind kind;
+ if (tokens[index].text() == "+") kind = OperatorEvaluator::Kind::ADD;
+ else if (tokens[index].text() == "-") kind = OperatorEvaluator::Kind::SUB;
+ else break;
+ ++index;
+ auto v2 = parseExprOper1();
+ v = std::make_shared<OperatorEvaluator>(tokens[index].location(), std::vector<ExprPtr> { std::move(v), std::move(v2) }, kind);
+ }
+ return v;
+ }
+
+ ExprPtr parseExprOper3()
+ {
+ auto v = parseExprOper2();
+ while (index < tokens.size()) {
+ OperatorEvaluator::Kind kind;
+ if (tokens[index].text() == "<<") kind = OperatorEvaluator::Kind::LSHIFT;
+ else if (tokens[index].text() == ">>") kind = OperatorEvaluator::Kind::RSHIFT;
+ else break;
+ ++index;
+ auto v2 = parseExprOper2();
+ v = std::make_shared<OperatorEvaluator>(tokens[index].location(), std::vector<ExprPtr> { std::move(v), std::move(v2) }, kind);
+ }
+ return v;
+ }
+
+ ExprPtr parseExprOper4()
+ {
+ auto v = parseExprOper3();
+ while (index < tokens.size()) {
+ OperatorEvaluator::Kind kind;
+ if (tokens[index].text() == "&") kind = OperatorEvaluator::Kind::BIT_AND;
+ else break;
+ ++index;
+ auto v2 = parseExprOper3();
+ v = std::make_shared<OperatorEvaluator>(tokens[index].location(), std::vector<ExprPtr> { std::move(v), std::move(v2) }, kind);
+ }
+ return v;
+ }
+
+ ExprPtr parseExprOper5()
+ {
+ auto v = parseExprOper4();
+ while (index < tokens.size()) {
+ OperatorEvaluator::Kind kind;
+ if (tokens[index].text() == "^") kind = OperatorEvaluator::Kind::BIT_XOR;
+ else break;
+ ++index;
+ auto v2 = parseExprOper4();
+ v = std::make_shared<OperatorEvaluator>(tokens[index].location(), std::vector<ExprPtr> { std::move(v), std::move(v2) }, kind);
+ }
+ return v;
+ }
+
+ ExprPtr parseExprOper6()
+ {
+ auto v = parseExprOper5();
+ while (index < tokens.size()) {
+ OperatorEvaluator::Kind kind;
+ if (tokens[index].text() == "|") kind = OperatorEvaluator::Kind::BIT_OR;
+ else break;
+ ++index;
+ auto v2 = parseExprOper5();
+ v = std::make_shared<OperatorEvaluator>(tokens[index].location(), std::vector<ExprPtr> { std::move(v), std::move(v2) }, kind);
+ }
+ return v;
+ }
/**
* @brief Proxy function to parse expressions, which doesn't contain comparision operators
*
*/
ExprPtr parseExprAboveComparisions()
{
- return parsePostfixExpr();
+ return parseExprOper6();
}
/**
}
return e;
}
+
+ ExprPtr parseBooleanExp3()
+ {
+ if (index < tokens.size() && tokens[index].text() == "not") {
+ auto location = tokens[index].location();
+ ++index;
+ auto v = parseComparisionsExpr();
+ return std::make_shared<OperatorEvaluator>(location, ExprPtrs{ std::move(v) }, OperatorEvaluator::Kind::NOT);
+ }
+ return parseComparisionsExpr();
+ }
+
+ ExprPtr parseBooleanExp2()
+ {
+ auto v = parseBooleanExp3();
+ while (index < tokens.size() && tokens[index].text() == "or") {
+ auto location = tokens[index].location();
+ ++index;
+ auto v2 = parseBooleanExp3();
+ v = std::make_shared<OperatorEvaluator>(location, ExprPtrs{ std::move(v), std::move(v2) }, OperatorEvaluator::Kind::LOG_OR);
+ }
+ return std::move(v);
+ }
+
+ ExprPtr parseBooleanExp1()
+ {
+ auto v = parseBooleanExp2();
+ while (index < tokens.size() && tokens[index].text() == "and") {
+ auto location = tokens[index].location();
+ ++index;
+ auto v2 = parseBooleanExp2();
+ v = std::make_shared<OperatorEvaluator>(location, ExprPtrs{ std::move(v), std::move(v2) }, OperatorEvaluator::Kind::LOG_AND);
+ }
+ return std::move(v);
+ }
+
/**
* @brief Tries to parse expression - root of expression parsing
*/
ExprPtr parseExpr()
{
- return parseComparisionsExpr();
+ return parseBooleanExp1();
}
/**
{
StatPtrs statements;
auto loc = tokens[index].location();
- while (index < tokens.size()) {
- if (tokens[index].type() == TokenType::END_OF_LINE) {
- ++index;
- continue;
- }
- if (canConsume("}")) break;
- auto e = parseLine();
- if (e) {
- statements.push_back(std::move(e));
- } else {
- while (index < tokens.size() && tokens[index].type() != TokenType::END_OF_LINE) ++index;
- ++index;
+ if (index < tokens.size() && !canConsume("}")) {
+ while (index < tokens.size() && !canConsume("}")) {
+ if (tokens[index].type() == TokenType::END_OF_LINE) {
+ ++index;
+ continue;
+ }
+ auto e = parseLine();
+ if (e) {
+ statements.push_back(std::move(e));
+ } else {
+ while (index < tokens.size() && tokens[index].type() != TokenType::END_OF_LINE) ++index;
+ ++index;
+ }
}
}
return std::make_shared<BlockEvaluator>(std::move(loc), std::move(statements));
return line;
}
+ ExprPtr parseLambda()
+ {
+ auto location = tokens[index].location();
+ auto args = consumeArguments();
+ if (!args)
+ return {};
+ auto block = parseBlock();
+ if (!block)
+ return {};
+ return std::make_shared<LambdaEvaluator>(std::move(location), std::move(*args), std::move(block));
+ }
/**
* @brief Tries to parse single function
*/
return std::make_shared<FunctionEvaluator>(std::move(location), std::move(functionName), std::move(*args), std::move(block));
}
+ StatPtr parseIf()
+ {
+ auto location = tokens[index].location();
+ if (!consume("if", "elif")) return {};
+ if (!consume("(")) return {};
+ auto v = parseExpr();
+ if (!consume(")")) return {};
+ auto block = parseLine();
+ StatPtr else_;
+ if (canConsume("else")) {
+ consume("else");
+ else_ = parseLine();
+ } else if (canConsume("elif")) {
+ else_ = parseIf();
+ }
+ return std::make_shared<IfEvaluator>(std::move(location), std::move(v), std::move(block), std::move(else_));
+ }
+
+ StatPtr parseWhile()
+ {
+ auto location = tokens[index].location();
+ if (!consume("while")) return {};
+ if (!consume("(")) return {};
+ auto expr = parseExpr();
+ if (!consume(")")) return {};
+ auto block = parseLine();
+ StatPtr else_;
+ if (canConsume("else")) {
+ consume("else");
+ else_ = parseLine();
+ }
+ return std::make_shared<WhileEvaluator>(std::move(location), std::move(expr), std::move(block), std::move(else_));
+ }
+
+ StatPtr parseFor()
+ {
+ auto location = tokens[index].location();
+ if (!consume("for")) return {};
+ if (!consume("(")) return {};
+ auto ident = consumeIdentifier();
+ if (!consume("in")) return {};
+ auto expr = parseExpr();
+ if (!consume(")")) return {};
+ auto block = parseLine();
+ StatPtr else_;
+ if (canConsume("else")) {
+ consume("else");
+ else_ = parseLine();
+ }
+ return std::make_shared<ForEvaluator>(std::move(location), std::move(ident), std::move(expr), std::move(block), std::move(else_));
+ }
+
+ StatPtr parseBreak()
+ {
+ auto location = tokens[index].location();
+ if (!consume("break")) return {};
+ return std::make_shared<BreakEvaluator>(std::move(location));
+ }
+
+ StatPtr parseContinue()
+ {
+ auto location = tokens[index].location();
+ if (!consume("continue")) return {};
+ return std::make_shared<ContinueEvaluator>(std::move(location));
+ }
/**
* @brief Tries to parse return statement
*/
if (!consume("return"))
return {};
ExprPtr expression;
- if (!canConsume(TokenType::END_OF_LINE)) {
+ if (!canConsume(TokenType::END_OF_LINE) && !canConsume("}")) {
expression = parseExpr();
if (!expression)
return {};
line = parseBlock();
} else if (tokens[index].text() == "def") {
line = parseFunction();
+ } else if (tokens[index].text() == "break") {
+ line = parseBreak();
+ } else if (tokens[index].text() == "continue") {
+ line = parseContinue();
+ } else if (tokens[index].text() == "while") {
+ line = parseWhile();
+ } else if (tokens[index].text() == "if") {
+ line = parseIf();
+ } else if (tokens[index].text() == "for") {
+ line = parseFor();
} else if (tokens[index].text() == "return") {
line = parseReturn();
} else {
auto expr = parseExpr();
if (!expr) return {};
if (!canConsume("->")) {
- if (!consume(TokenType::END_OF_LINE)) return {};
+ if (!canConsume("}") && !canConsume(TokenType::END_OF_LINE)) return {};
tryWait = false;
}
auto loc = expr->location();
if (!r) return {};
waits.push_back(std::move(r));
}
- if (!consume(TokenType::END_OF_LINE)) return {};
+ if (!canConsume(TokenType::END_OF_LINE)) return {};
line = std::make_shared<WaitEvaluator>(loc, std::move(line), std::move(waits));
}
+ if (canConsume(TokenType::END_OF_LINE)) consume(TokenType::END_OF_LINE);
return std::move(line);
}
public:
EvaluationValue result;
};
+class ContinueValue
+{
+};
+
+class BreakValue
+{
+};
#endif //RETURN_VALUE_HPP
#include "UniversalSwitchLog.hpp"
#include "DoneCallback.hpp"
#include "dbusLocators.hpp"
+#include "batch/Monitor.hpp"
#include <efl_util.h>
#include <bundle_internal.h>
output << ">>> " << val << "\n";
return {};
};
+ vars["str"] = EvaluationValueFunction{ [](EvaluationValue e) -> EvaluationValue {
+ std::ostringstream tmp;
+ tmp << e;
+ return tmp.str();
+ }, { { "value" } } };
}
void SetUp(void) override
std::vector<std::string> errors;
auto result = parseTokens(errors, tokens);
- if (!errors.empty()) {
+ if (!errors.empty() || !result) {
if (printException) {
std::ostringstream tmp;
DebugEvaluatorInterface::setCurrentInterface(std::make_unique<StreamDebugEvaluatorInterface>(std::cout));
- result->printSelfInfo(0);
+ if (result) result->printSelfInfo(0);
DebugEvaluatorInterface::setCurrentInterface(nullptr);
for (auto &e : errors) {
std::cout << e << "\n";
}
throw ParseFailure{};
}
+ if (result) {
+ //DebugEvaluatorInterface::setCurrentInterface(std::make_unique<StreamDebugEvaluatorInterface>(std::cout));
+ //result->printSelfInfo(0);
+ }
return result;
}
while (i < txt.size()) {
auto n = txt.find('\n', i);
if (n == std::string::npos) n = txt.size();
- output << std::setw(2) << c << ": " << txt.substr(i, n - i) << "\n";
+ auto m = txt.substr(i, n - i);
+ for (auto &q : m)
+ if (q < ' ') q = ' ';
+ output << std::setw(2) << c << ": " << m << "\n";
if (e.hasLocation() && c == e.location().lineNum()) {
for (auto i = 1u; i < e.location().offsetNum(); ++i)
output << " ";
}
void executeCountAsserts(std::string txt, size_t count = 1)
{
+
try {
execute(std::move(txt), true);
} catch (EvaluationFailure &e) {
, 12 + 8 + 8 + 8 + 4);
}
+TEST_F(ScriptTest, simpleOperators)
+{
+ executeCountAsserts(
+ R"__(
+ assert(3 + 5 == 8)
+ assert(3 - 5 == -2)
+ assert(3 * 5 == 15)
+ assert(3 / 6 == 0.5)
+ assert(7 % 3 == 1)
+ assert(3 | 5 == 7)
+ assert(3 & 5 == 1)
+ assert(3 ^ 5 == 6)
+ assert(~3 == 18446744073709551612)
+ assert(~(-4) == 3)
+ )__"
+ , 10);
+}
+
TEST_F(ScriptTest, vector)
{
executeCountAsserts(
- "v = [1, 2, 3]\n"
- "assert(v[0] == 1)\n"
- "assert(v[1] == 2)\n"
- "assert(v[2] == 3)\n"
- "assert(v[-1] == 3)\n"
- "assert(v[-2] == 2)\n"
- "assert(v[-3] == 1)\n"
- "assert(v[1:2] == [2])\n"
- "assert(v[-2:-1] == [2])\n"
- "v[1:2] = [4, 5, 6]\n"
- "print(v)\n"
- "assert(v == [1, 4, 5, 6, 3])\n"
- "assert([1] != [2])\n"
- "assert([1] == [1])\n"
- "assert([1] != [])\n"
- "assert([] == [])\n"
- "assert([1, 2, 3] != [1, 2, 3, 4])\n"
- "assert([1, 2, 3] < [1, 2, 3, 4])\n"
- "assert([1, 2, 3] <= [1, 2, 3, 4])\n"
- "assert([1, 2, 3, 5 ] > [1, 2, 3, 4])\n"
- "assert([1, 2, 3, 5 ] >= [1, 2, 3, 4])\n"
- "assert(1 in [1,2,3])\n"
- "assert(1 not in [2,3])\n"
- "assert(not (1 in [2,3]))\n"
- , 21);
+ R"__(
+ v = [1, 2, 3]
+ assert(v[0] == 1)
+ assert(v[1] == 2)
+ assert(v[2] == 3)
+ assert(v[-1] == 3)
+ assert(v[-2] == 2)
+ assert(v[-3] == 1)
+ assert(v[1:2] == [2])
+ assert(v[-2:-1] == [2])
+ v[1:2] = [4, 5, 6]
+ assert(v == [1, 4, 5, 6, 3])
+ assert([1] != [2])
+ assert([1] == [1])
+ assert([1] != [])
+ assert([] == [])
+ assert([1, 2, 3] != [1, 2, 3, 4])
+ assert([1, 2, 3] < [1, 2, 3, 4])
+ assert([1, 2, 3] <= [1, 2, 3, 4])
+ assert([1, 2, 3, 5 ] > [1, 2, 3, 4])
+ assert([1, 2, 3, 5 ] >= [1, 2, 3, 4])
+ assert(1 in [1,2,3])
+ assert(1 not in [2,3])
+ assert(not (1 in [2,3]))
+ v = []
+ v.append(1)
+ v.append(2)
+ v.insert(1, 3)
+ assert(v == [1, 3, 2])
+ assert(v.pop() == 2)
+ assert(v == [1, 3])
+ v.append(4)
+ assert(v == [1, 3, 4])
+ assert(v.pop(1) == 3)
+ assert(v == [1, 4])
+ v = [1, 2, 3, 4, 5]
+ print(v.filter(def(v){ return true }))
+ v = v.filter(def(v) { return (v & 1) })
+ print(v)
+ assert(v == [1, 3, 5])
+ assert([1, 2, 3] + [4, 5] == [1, 2, 3, 4, 5])
+ )__"
+ , 29);
}
TEST_F(ScriptTest, set)
{
executeCountAsserts(
- "v = {1, 2, 3, '1', '2', '3'}\n"
- "assert(1 in v)\n"
- "assert(2 in v)\n"
- "assert(3 in v)\n"
- "assert('1' in v)\n"
- "assert('2' in v)\n"
- "assert('3' in v)\n"
- "assert('4' not in v)\n"
- "assert(not ('4' in v))\n"
- , 8);
+ R"__(
+ v = {1, 2, 3, '1', '2', '3'}
+ assert(1 in v)
+ assert(2 in v)
+ assert(3 in v)
+ assert('1' in v)
+ assert('2' in v)
+ assert('3' in v)
+ assert('4' not in v)
+ assert(not ('4' in v))
+ assert({ 1, 2, 3 } | { 3, 4, 5 } == { 1, 2, 3, 4, 5})
+ assert({ 1, 2, 3 } & { 3, 4, 5 } == { 3})
+ assert({ 1, 2, 3 } ^ { 3, 4, 5 } == { 1, 2, 4, 5})
+ )__"
+ , 11);
}
TEST_F(ScriptTest, map)
{
executeCountAsserts(
- "v = {1: 1, 2: 2, '1': 3}\n"
- "assert(1 in v)\n"
- "assert(2 in v)\n"
- "assert(3 not in v)\n"
- "assert('1' in v)\n"
- "assert('2' not in v)\n"
- "assert(v[1] == 1)\n"
- "assert(v['1'] == 3)\n"
- , 7);
+ R"__(
+ v = {1: 1, 2: 2, '1': 3}
+ assert(1 in v)
+ assert(2 in v)
+ assert(3 not in v)
+ assert('1' in v)
+ assert('2' not in v)
+ assert(v[1] == 1)
+ assert(v['1'] == 3)
+ v1 = { 1:11, 2:22, 3:33 }
+ v2 = { 3:33, 4:44, 5:55 }
+ assert(v1 | v2 == { 1:11, 2:22, 3:33, 4:44, 5:55 })
+ assert(v1 & v2 == { 3:33 })
+ assert(v1 ^ v2 == { 1:11, 2:22, 4:44, 5:55 })
+ )__"
+ , 10);
}
TEST_F(ScriptTest, point)
, 1);
}
+TEST_F(ScriptTest, whileStatement)
+{
+ executeCountAsserts(
+ R"__(
+ def f(q) {
+ v = []
+ a = 0
+ while(a < 2) {
+ a = a + 1
+ if (q == 1) break
+ if (q == 2) {
+ q = -1
+ continue
+ }
+ v.append(str(a))
+ }
+ else {
+ if (q != 3) v.append('3')
+ }
+ v = '.'.join(v)
+ return v
+ }
+ assert(f(0) == '1.2.3')
+ assert(f(1) == '')
+ assert(f(2) == '2.3')
+ assert(f(3) == '1.2')
+ )__"
+ , 4);
+}
+
+TEST_F(ScriptTest, forStatement)
+{
+ executeCountAsserts(
+ R"__(
+ v = []
+ for(a in [1, 2, 3, 4]) {
+ if (a & 1) {
+ v.append(a * 2)
+ print('1')
+ }
+ }
+ print(v)
+ assert(v == [2, 6])
+ )__"
+ , 1);
+}
+
+TEST_F(ScriptTest, forStatement2)
+{
+ executeCountAsserts(
+ R"__(
+ def f(q) {
+ v = []
+ for(a in [1, 2]) {
+ if (q == 1) break
+ if (q == 2) {
+ q = -1
+ continue
+ }
+ v.append(str(a))
+ }
+ else {
+ if (q != 3) v.append('3')
+ }
+ v = '.'.join(v)
+ return v
+ }
+ assert(f(0) == '1.2.3')
+ assert(f(1) == '')
+ assert(f(2) == '2.3')
+ assert(f(3) == '1.2')
+ )__"
+ , 4);
+}
+
+TEST_F(ScriptTest, ifStatement)
+{
+ executeCountAsserts(
+ R"__(
+ def f(q) {
+ if (q == 1) return 11
+ elif (q == 2) return 22
+ else if (q == 3) return 33
+ else {
+ if (q == 4) return 44
+ return 55
+ }
+ }
+ assert(f(1) == 11)
+ assert(f(2) == 22)
+ assert(f(3) == 33)
+ assert(f(4) == 44)
+ assert(f(5) == 55)
+ assert(f(6) == 55)
+ )__"
+ , 6);
+}
+
TEST_F(ScriptTest, defaultArguments)
{
std::tuple<int, int, int, int> val, expected;