start: v5
This commit is contained in:
@@ -9,7 +9,7 @@ from llm_test_Python import *
|
||||
from memory_test import *
|
||||
import sys
|
||||
|
||||
print(ctx_test_Controller_executeFunctions_set())
|
||||
print(ctx_test_Controller_executeFunctions_registerFunction_set())
|
||||
print(ctx_test_Controller_processQueue())
|
||||
print(ctx_test_Controller_registerFieldCallback_match())
|
||||
print(ctx_test_Controller_registerFieldCallback_mismatch())
|
||||
|
||||
86
v5/_old/ctx_test.cpp
Normal file
86
v5/_old/ctx_test.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "ctx.h"
|
||||
#include "llm.h"
|
||||
#include "memory_Context.h"
|
||||
#include "main.h"
|
||||
|
||||
std::string ctx_test_Controller_executeFunctions_set(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
auto ctrl = ctx_Controller(c);
|
||||
// Disable automatic invocation of executeFunctions.
|
||||
ctrl.isProcessingQueue = true;
|
||||
ctrl.set("input", "123");
|
||||
ctrl.registerFunction(__processInput);
|
||||
// Apply 'input'.
|
||||
ctrl.executeFunctions();
|
||||
// Apply 'outputHelp'.
|
||||
ctrl.executeFunctions();
|
||||
if (
|
||||
c.input == "123" &&
|
||||
c.outputHelp == "Checked"
|
||||
) {
|
||||
return "OK: ctx_Controller_executeFunctions_set";
|
||||
}
|
||||
return "ERR: ctx_Controller_executeFunctions_set";
|
||||
}
|
||||
|
||||
std::string ctx_test_Controller_processQueue(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
auto ctrl = ctx_Controller(c);
|
||||
ctrl.registerFunction(__processInput);
|
||||
ctrl.set("input", "abc");;
|
||||
if (
|
||||
c.input == "abc" &&
|
||||
c.outputHelp == "Checked"
|
||||
) {
|
||||
return "OK: ctx_Controller_processQueue";
|
||||
}
|
||||
return "ERR: ctx_Controller_processQueue";
|
||||
}
|
||||
|
||||
std::string ctx_test_memoryContext_field(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.input = "abc";
|
||||
if (
|
||||
c.field("input") == "abc"
|
||||
) {
|
||||
return "OK: ctx_memoryContext_field";
|
||||
}
|
||||
return "ERR: ctx_memoryContext_field";
|
||||
}
|
||||
|
||||
std::string ctx_test_memoryContext_setField(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.input = "abc";
|
||||
c.setField("input", "123");
|
||||
if (
|
||||
c.field("input") == "123"
|
||||
) {
|
||||
return "OK: ctx_memoryContext_setField";
|
||||
}
|
||||
return "ERR: ctx_memoryContext_setField";
|
||||
}
|
||||
|
||||
// Auxiliary functions.
|
||||
|
||||
memory_Context __processInput(
|
||||
memory_Context c
|
||||
) {
|
||||
if (
|
||||
c.recentField == "input"
|
||||
) {
|
||||
c.outputHelp = "Checked";
|
||||
c.recentField = "outputHelp";
|
||||
return c;
|
||||
}
|
||||
c.recentField = "none";
|
||||
return c;
|
||||
}
|
||||
|
||||
81
v5/_old/ctx_test.py
Normal file
81
v5/_old/ctx_test.py
Normal file
@@ -0,0 +1,81 @@
|
||||
from ctx import *
|
||||
from memory import *
|
||||
from memory_Context import *
|
||||
|
||||
def ctx_test_Controller_executeFunctions_set(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
ctrl = ctx_Controller(c)
|
||||
# Disable automatic invocation of executeFunctions.
|
||||
ctrl.isProcessingQueue = True
|
||||
ctrl.set("input", "123")
|
||||
ctrl.registerFunction(__processInput)
|
||||
# Apply 'input'.
|
||||
ctrl.executeFunctions()
|
||||
# Apply 'outputHelp'.
|
||||
ctrl.executeFunctions()
|
||||
if (
|
||||
c.input == "123" and
|
||||
c.outputHelp == "Checked"
|
||||
):
|
||||
return "OK: ctx_Controller_executeFunctions_set"
|
||||
#}
|
||||
return "ERR: ctx_Controller_executeFunctions_set"
|
||||
#}
|
||||
|
||||
def ctx_test_Controller_processQueue(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
ctrl = ctx_Controller(c)
|
||||
ctrl.registerFunction(__processInput)
|
||||
ctrl.set("input", "abc");
|
||||
if (
|
||||
c.input == "abc" and
|
||||
c.outputHelp == "Checked"
|
||||
):
|
||||
return "OK: ctx_Controller_processQueue"
|
||||
#}
|
||||
return "ERR: ctx_Controller_processQueue"
|
||||
#}
|
||||
|
||||
def ctx_test_memoryContext_field(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.input = "abc"
|
||||
if (
|
||||
c.field("input") == "abc"
|
||||
):
|
||||
return "OK: ctx_memoryContext_field"
|
||||
#}
|
||||
return "ERR: ctx_memoryContext_field"
|
||||
#}
|
||||
|
||||
def ctx_test_memoryContext_setField(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.input = "abc"
|
||||
c.setField("input", "123")
|
||||
if (
|
||||
c.field("input") == "123"
|
||||
):
|
||||
return "OK: ctx_memoryContext_setField"
|
||||
#}
|
||||
return "ERR: ctx_memoryContext_setField"
|
||||
#}
|
||||
|
||||
# Auxiliary functions.
|
||||
|
||||
@llm_by_value
|
||||
def __processInput(
|
||||
c: memory_Context
|
||||
) -> memory_Context:
|
||||
if (
|
||||
c.recentField == "input"
|
||||
):
|
||||
c.outputHelp = "Checked"
|
||||
c.recentField = "outputHelp"
|
||||
return c
|
||||
#}
|
||||
c.recentField = "none"
|
||||
return c
|
||||
#}
|
||||
53
v5/_old/ctx_test_Python.py
Normal file
53
v5/_old/ctx_test_Python.py
Normal file
@@ -0,0 +1,53 @@
|
||||
from ctx import *
|
||||
from memory import *
|
||||
from memory_Context import *
|
||||
|
||||
def ctx_test_Python_Controller_registerFieldCallback_match(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
ctrl = ctx_Controller(c)
|
||||
c.input = "123"
|
||||
c.recentField = "input"
|
||||
globals()["__callbackInput"] = ""
|
||||
ctrl.registerFieldCallback("input", __setCallbackInput)
|
||||
ctrl.reportContext()
|
||||
val = globals()["__callbackInput"]
|
||||
if (
|
||||
c.input == globals()["__callbackInput"]
|
||||
):
|
||||
return "OK: ctx_Python_Controller_registerFieldCallback_match"
|
||||
#}
|
||||
return f"ERR: ctx_Python_Controller_registerFieldCallback_match"
|
||||
#}
|
||||
|
||||
def ctx_test_Python_Controller_registerFieldCallback_mismatch(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
ctrl = ctx_Controller(c)
|
||||
c.input = "123"
|
||||
c.outputHelp = "you"
|
||||
c.recentField = "outputHelp"
|
||||
globals()["__callbackInput"] = ""
|
||||
ctrl.registerFieldCallback("input", __setCallbackInput)
|
||||
ctrl.reportContext()
|
||||
val = globals()["__callbackInput"]
|
||||
if (
|
||||
globals()["__callbackInput"] == ""
|
||||
):
|
||||
return "OK: ctx_Python_Controller_registerFieldCallback_mismatch"
|
||||
#}
|
||||
return f"ERR: ctx_Python_Controller_registerFieldCallback_mismatch"
|
||||
#}
|
||||
|
||||
# Auxiliary.
|
||||
|
||||
__callbackInput = ""
|
||||
|
||||
@llm_by_value
|
||||
def __setCallbackInput(c):
|
||||
if (
|
||||
c.recentField == "input"
|
||||
):
|
||||
globals()["__callbackInput"] = c.input
|
||||
#}
|
||||
#}
|
||||
549
v5/any.h
Normal file
549
v5/any.h
Normal file
@@ -0,0 +1,549 @@
|
||||
/**
|
||||
* Implementation of N4562 std::experimental::any (merged into C++17 as std::any)
|
||||
* for C++11 compilers.
|
||||
*
|
||||
* See also:
|
||||
* + http://en.cppreference.com/w/cpp/any
|
||||
* + http://en.cppreference.com/w/cpp/experimental/any
|
||||
* + http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4562.html#any
|
||||
* + https://cplusplus.github.io/LWG/lwg-active.html#2509
|
||||
*
|
||||
* Copyright (c) 2016 Denilson das Merc<72>s Amorim
|
||||
* Copyright (c) 2018 Claudio Fantacci
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE.md or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#ifndef ANY_H
|
||||
#define ANY_H
|
||||
|
||||
#include <stdexcept>
|
||||
#include <typeinfo>
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
namespace libany
|
||||
{
|
||||
|
||||
class bad_any_cast : public std::bad_cast
|
||||
{
|
||||
public:
|
||||
const char* what() const noexcept override
|
||||
{
|
||||
return "bad any_cast";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class any final
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructs an object of type any with an empty state.
|
||||
*/
|
||||
any() :
|
||||
vtable(nullptr)
|
||||
{ }
|
||||
|
||||
|
||||
/**
|
||||
* Constructs an object of type any with an equivalent state as other.
|
||||
*/
|
||||
any(const any& rhs) :
|
||||
vtable(rhs.vtable)
|
||||
{
|
||||
if(rhs.has_value())
|
||||
{
|
||||
rhs.vtable->copy(rhs.storage, this->storage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs an object of type any with a state equivalent to the original state of other.
|
||||
* rhs is left in a valid but otherwise unspecified state.
|
||||
*/
|
||||
any(any&& rhs) noexcept :
|
||||
vtable(rhs.vtable)
|
||||
{
|
||||
if(rhs.has_value())
|
||||
{
|
||||
rhs.vtable->move(rhs.storage, this->storage);
|
||||
rhs.vtable = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Same effect as this->clear().
|
||||
*/
|
||||
~any()
|
||||
{
|
||||
this->reset();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs an object of type any that contains an object of type T direct-initialized with std::forward<ValueType>(value).
|
||||
* T shall satisfy the CopyConstructible requirements, otherwise the program is ill-formed.
|
||||
* This is because an `any` may be copy constructed into another `any` at any time, so a copy should always be allowed.
|
||||
*/
|
||||
template<typename ValueType, typename = typename std::enable_if<!std::is_same<typename std::decay<ValueType>::type, any>::value>::type>
|
||||
any(ValueType&& value)
|
||||
{
|
||||
static_assert(std::is_copy_constructible<typename std::decay<ValueType>::type>::value,
|
||||
"T shall satisfy the CopyConstructible requirements.");
|
||||
this->construct(std::forward<ValueType>(value));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Has the same effect as any(rhs).swap(*this). No effects if an exception is thrown.
|
||||
*/
|
||||
any& operator=(const any& rhs)
|
||||
{
|
||||
any(rhs).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Has the same effect as any(std::move(rhs)).swap(*this).
|
||||
* The state of *this is equivalent to the original state of rhs and rhs is left in a valid
|
||||
* but otherwise unspecified state.
|
||||
*/
|
||||
any& operator=(any&& rhs) noexcept
|
||||
{
|
||||
any(std::move(rhs)).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Has the same effect as any(std::forward<ValueType>(value)).swap(*this). No effect if a exception is thrown.
|
||||
* T shall satisfy the CopyConstructible requirements, otherwise the program is ill-formed.
|
||||
* This is because an `any` may be copy constructed into another `any` at any time, so a copy should always be allowed.
|
||||
*/
|
||||
template<typename ValueType, typename = typename std::enable_if<!std::is_same<typename std::decay<ValueType>::type, any>::value>::type>
|
||||
any& operator=(ValueType&& value)
|
||||
{
|
||||
static_assert(std::is_copy_constructible<typename std::decay<ValueType>::type>::value, "T shall satisfy the CopyConstructible requirements.");
|
||||
any(std::forward<ValueType>(value)).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If not empty, destroys the contained object.
|
||||
*/
|
||||
void reset() noexcept
|
||||
{
|
||||
if(has_value())
|
||||
{
|
||||
this->vtable->destroy(storage);
|
||||
this->vtable = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if *this has no contained object, otherwise false.
|
||||
*/
|
||||
bool has_value() const noexcept
|
||||
{
|
||||
return this->vtable != nullptr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If *this has a contained object of type T, typeid(T); otherwise typeid(void).
|
||||
*/
|
||||
const std::type_info& type() const noexcept
|
||||
{
|
||||
return has_value()? this->vtable->type() : typeid(void);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Exchange the states of *this and rhs.
|
||||
*/
|
||||
void swap(any& other) noexcept
|
||||
{
|
||||
if(this->vtable != other.vtable)
|
||||
{
|
||||
any tmp(std::move(other));
|
||||
|
||||
other.vtable = this->vtable;
|
||||
if(this->vtable != nullptr)
|
||||
this->vtable->move(this->storage, other.storage);
|
||||
|
||||
this->vtable = tmp.vtable;
|
||||
if(tmp.vtable != nullptr)
|
||||
{
|
||||
tmp.vtable->move(tmp.storage, this->storage);
|
||||
tmp.vtable = nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(this->vtable != nullptr)
|
||||
this->vtable->swap(this->storage, other.storage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
union storage_union
|
||||
{
|
||||
using stack_storage_t = typename std::aligned_storage<2 * sizeof(void*), std::alignment_of<void*>::value>::type;
|
||||
|
||||
void* dynamic;
|
||||
|
||||
stack_storage_t stack;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Base VTable specification.
|
||||
*
|
||||
* Note: The caller is responsible for doing .vtable = nullptr after destructful operations
|
||||
* such as destroy() and/or move().
|
||||
*/
|
||||
struct vtable_type
|
||||
{
|
||||
/**
|
||||
* The type of the object this vtable is for.
|
||||
*/
|
||||
const std::type_info& (*type)() noexcept;
|
||||
|
||||
|
||||
/**
|
||||
* Destroys the object in the union.
|
||||
* The state of the union after this call is unspecified, caller must ensure not to use src anymore.
|
||||
*/
|
||||
void(*destroy)(storage_union&) noexcept;
|
||||
|
||||
|
||||
/**
|
||||
* Copies the **inner** content of the src union into the yet unitialized dest union.
|
||||
* As such, both inner objects will have the same state, but on separate memory locations.
|
||||
*/
|
||||
void(*copy)(const storage_union& src, storage_union& dest);
|
||||
|
||||
|
||||
/**
|
||||
* Moves the storage from src to the yet unitialized dest union.
|
||||
* The state of src after this call is unspecified, caller must ensure not to use src anymore.
|
||||
*/
|
||||
void(*move)(storage_union& src, storage_union& dest) noexcept;
|
||||
|
||||
|
||||
/**
|
||||
* Exchanges the storage between lhs and rhs.
|
||||
*/
|
||||
void(*swap)(storage_union& lhs, storage_union& rhs) noexcept;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* VTable for dynamically allocated storage.
|
||||
*/
|
||||
template<typename T>
|
||||
struct vtable_dynamic
|
||||
{
|
||||
static const std::type_info& type() noexcept
|
||||
{
|
||||
return typeid(T);
|
||||
}
|
||||
|
||||
|
||||
static void destroy(storage_union& storage) noexcept
|
||||
{
|
||||
delete reinterpret_cast<T*>(storage.dynamic);
|
||||
}
|
||||
|
||||
|
||||
static void copy(const storage_union& src, storage_union& dest)
|
||||
{
|
||||
dest.dynamic = new T(*reinterpret_cast<const T*>(src.dynamic));
|
||||
}
|
||||
|
||||
|
||||
static void move(storage_union& src, storage_union& dest) noexcept
|
||||
{
|
||||
dest.dynamic = src.dynamic;
|
||||
src.dynamic = nullptr;
|
||||
}
|
||||
|
||||
|
||||
static void swap(storage_union& lhs, storage_union& rhs) noexcept
|
||||
{
|
||||
std::swap(lhs.dynamic, rhs.dynamic);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* VTable for stack allocated storage.
|
||||
*/
|
||||
template<typename T>
|
||||
struct vtable_stack
|
||||
{
|
||||
static const std::type_info& type() noexcept
|
||||
{
|
||||
return typeid(T);
|
||||
}
|
||||
|
||||
|
||||
static void destroy(storage_union& storage) noexcept
|
||||
{
|
||||
reinterpret_cast<T*>(&storage.stack)->~T();
|
||||
}
|
||||
|
||||
|
||||
static void copy(const storage_union& src, storage_union& dest)
|
||||
{
|
||||
new (&dest.stack) T(reinterpret_cast<const T&>(src.stack));
|
||||
}
|
||||
|
||||
|
||||
static void move(storage_union& src, storage_union& dest) noexcept
|
||||
{
|
||||
/**
|
||||
* One of the conditions for using vtable_stack is a nothrow move constructor,
|
||||
* so this move constructor will never throw a exception.
|
||||
*/
|
||||
new (&dest.stack) T(std::move(reinterpret_cast<T&>(src.stack)));
|
||||
destroy(src);
|
||||
}
|
||||
|
||||
|
||||
static void swap(storage_union& lhs, storage_union& rhs) noexcept
|
||||
{
|
||||
storage_union tmp_storage;
|
||||
move(rhs, tmp_storage);
|
||||
move(lhs, rhs);
|
||||
move(tmp_storage, lhs);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Whether the type T must be dynamically allocated or can be stored on the stack.
|
||||
*/
|
||||
template<typename T>
|
||||
struct requires_allocation :
|
||||
std::integral_constant<bool, !(std::is_nothrow_move_constructible<T>::value // N4562 6.3/3 [any.class]
|
||||
&& sizeof(T) <= sizeof(storage_union::stack)
|
||||
&& std::alignment_of<T>::value <= std::alignment_of<storage_union::stack_storage_t>::value)>
|
||||
{ };
|
||||
|
||||
|
||||
/**
|
||||
* Returns the pointer to the vtable of the type T.
|
||||
*/
|
||||
template<typename T>
|
||||
static vtable_type* vtable_for_type()
|
||||
{
|
||||
using VTableType = typename std::conditional<requires_allocation<T>::value, vtable_dynamic<T>, vtable_stack<T>>::type;
|
||||
static vtable_type table = { VTableType::type, VTableType::destroy, VTableType::copy, VTableType::move, VTableType::swap };
|
||||
return &table;
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
template<typename T>
|
||||
friend const T* any_cast(const any* operand) noexcept;
|
||||
|
||||
|
||||
template<typename T>
|
||||
friend T* any_cast(any* operand) noexcept;
|
||||
|
||||
|
||||
/**
|
||||
* Same effect as is_same(this->type(), t);
|
||||
*/
|
||||
bool is_typed(const std::type_info& t) const
|
||||
{
|
||||
return is_same(this->type(), t);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if two type infos are the same.
|
||||
* If ANY_IMPL_FAST_TYPE_INFO_COMPARE is defined, checks only the address of the
|
||||
* type infos, otherwise does an actual comparision. Checking addresses is
|
||||
* only a valid approach when there's no interaction with outside sources
|
||||
* (other shared libraries and such).
|
||||
*/
|
||||
static bool is_same(const std::type_info& a, const std::type_info& b)
|
||||
{
|
||||
#ifdef ANY_IMPL_FAST_TYPE_INFO_COMPARE
|
||||
return &a == &b;
|
||||
#else
|
||||
return a == b;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Casts (with no type_info checks) the storage pointer as const T*.
|
||||
*/
|
||||
template<typename T>
|
||||
const T* cast() const noexcept
|
||||
{
|
||||
return requires_allocation<typename std::decay<T>::type>::value ? reinterpret_cast<const T*>(storage.dynamic) : reinterpret_cast<const T*>(&storage.stack);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Casts (with no type_info checks) the storage pointer as T*.
|
||||
*/
|
||||
template<typename T>
|
||||
T* cast() noexcept
|
||||
{
|
||||
return requires_allocation<typename std::decay<T>::type>::value ? reinterpret_cast<T*>(storage.dynamic) : reinterpret_cast<T*>(&storage.stack);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
storage_union storage; // On offset(0) so no padding for align
|
||||
|
||||
vtable_type* vtable;
|
||||
|
||||
|
||||
template<typename ValueType, typename T>
|
||||
typename std::enable_if<requires_allocation<T>::value>::type do_construct(ValueType&& value)
|
||||
{
|
||||
storage.dynamic = new T(std::forward<ValueType>(value));
|
||||
}
|
||||
|
||||
|
||||
template<typename ValueType, typename T>
|
||||
typename std::enable_if<!requires_allocation<T>::value>::type do_construct(ValueType&& value)
|
||||
{
|
||||
new (&storage.stack) T(std::forward<ValueType>(value));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Chooses between stack and dynamic allocation for the type decay_t<ValueType>,
|
||||
* assigns the correct vtable, and constructs the object on our storage.
|
||||
*/
|
||||
template<typename ValueType>
|
||||
void construct(ValueType&& value)
|
||||
{
|
||||
using T = typename std::decay<ValueType>::type;
|
||||
|
||||
this->vtable = vtable_for_type<T>();
|
||||
|
||||
do_construct<ValueType,T>(std::forward<ValueType>(value));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template<typename ValueType>
|
||||
inline ValueType any_cast_move_if_true(typename std::remove_reference<ValueType>::type* p, std::true_type)
|
||||
{
|
||||
return std::move(*p);
|
||||
}
|
||||
|
||||
|
||||
template<typename ValueType>
|
||||
inline ValueType any_cast_move_if_true(typename std::remove_reference<ValueType>::type* p, std::false_type)
|
||||
{
|
||||
return *p;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Performs *any_cast<add_const_t<remove_reference_t<ValueType>>>(&operand), or throws bad_any_cast on failure.
|
||||
*/
|
||||
template<typename ValueType>
|
||||
inline ValueType any_cast(const any& operand)
|
||||
{
|
||||
auto p = any_cast<typename std::add_const<typename std::remove_reference<ValueType>::type>::type>(&operand);
|
||||
if(p == nullptr) throw bad_any_cast();
|
||||
return *p;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Performs *any_cast<remove_reference_t<ValueType>>(&operand), or throws bad_any_cast on failure.
|
||||
*/
|
||||
template<typename ValueType>
|
||||
inline ValueType any_cast(any& operand)
|
||||
{
|
||||
auto p = any_cast<typename std::remove_reference<ValueType>::type>(&operand);
|
||||
if(p == nullptr) throw bad_any_cast();
|
||||
return *p;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If ANY_IMPL_ANYCAST_MOVEABLE is not defined, does as N4562 specifies:
|
||||
* Performs *any_cast<remove_reference_t<ValueType>>(&operand), or throws bad_any_cast on failure.
|
||||
*
|
||||
* If ANY_IMPL_ANYCAST_MOVEABLE is defined, does as LWG Defect 2509 specifies [1]:
|
||||
* If ValueType is MoveConstructible and isn't a lvalue reference, performs
|
||||
* std::move(*any_cast<remove_reference_t<ValueType>>(&operand)), otherwise
|
||||
* *any_cast<remove_reference_t<ValueType>>(&operand).
|
||||
* Throws bad_any_cast on failure.
|
||||
*
|
||||
* [1] https://cplusplus.github.io/LWG/lwg-active.html#2509
|
||||
*/
|
||||
template<typename ValueType>
|
||||
inline ValueType any_cast(any&& operand)
|
||||
{
|
||||
#ifdef ANY_IMPL_ANY_CAST_MOVEABLE
|
||||
using can_move = std::integral_constant<bool, std::is_move_constructible<ValueType>::value && !std::is_lvalue_reference<ValueType>::value>;
|
||||
#else
|
||||
using can_move = std::false_type;
|
||||
#endif
|
||||
|
||||
auto p = any_cast<typename std::remove_reference<ValueType>::type>(&operand);
|
||||
if(p == nullptr) throw bad_any_cast();
|
||||
return detail::any_cast_move_if_true<ValueType>(p, can_move());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If operand != nullptr && operand->type() == typeid(ValueType), a pointer to the object
|
||||
* contained by operand, otherwise nullptr.
|
||||
*/
|
||||
template<typename T>
|
||||
inline const T* any_cast(const any* operand) noexcept
|
||||
{
|
||||
if(operand == nullptr || !operand->is_typed(typeid(T)))
|
||||
return nullptr;
|
||||
else
|
||||
return operand->cast<T>();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If operand != nullptr && operand->type() == typeid(ValueType), a pointer to the object
|
||||
* contained by operand, otherwise nullptr.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T* any_cast(any* operand) noexcept
|
||||
{
|
||||
if(operand == nullptr || !operand->is_typed(typeid(T)))
|
||||
return nullptr;
|
||||
else
|
||||
return operand->cast<T>();
|
||||
}
|
||||
|
||||
|
||||
inline void swap(any& lhs, any& rhs) noexcept
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* ANY_H */
|
||||
220
v5/cli.cpp
Normal file
220
v5/cli.cpp
Normal file
@@ -0,0 +1,220 @@
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "ctx.h"
|
||||
#include "llm.h"
|
||||
#include "memory_Context.h"
|
||||
#include "main.h"
|
||||
|
||||
// Exit
|
||||
//
|
||||
// Conditions:
|
||||
// 1. `e`, `exit`, `q`, or `quit` was entered
|
||||
// 2. Victory has just been reported
|
||||
memory_Context cli_exit(
|
||||
memory_Context c
|
||||
) {
|
||||
if (
|
||||
c.recentField == "input" &&
|
||||
(
|
||||
c.input == "e" ||
|
||||
c.input == "exit" ||
|
||||
c.input == "q" ||
|
||||
c.input == "quit"
|
||||
)
|
||||
) {
|
||||
c.exit = true;
|
||||
c.recentField = "exit";
|
||||
return c;
|
||||
}
|
||||
if (
|
||||
c.recentField == "outputVictory"
|
||||
) {
|
||||
c.exit = true;
|
||||
c.recentField = "exit";
|
||||
return c;
|
||||
}
|
||||
c.recentField = "none";
|
||||
return c;
|
||||
}
|
||||
|
||||
// Ask user to go on
|
||||
//
|
||||
// Conditions:
|
||||
// 1. Items have just matched and there are still items left to select
|
||||
memory_Context cli_goOn(
|
||||
memory_Context c
|
||||
) {
|
||||
if (
|
||||
c.recentField == "outputMatchedItems" &&
|
||||
c.hiddenItems.size() != c.playfieldItems.size()
|
||||
) {
|
||||
c.outputGoOn = "Go on:";
|
||||
c.recentField = "outputGoOn";
|
||||
return c;
|
||||
}
|
||||
c.recentField = "none";
|
||||
return c;
|
||||
}
|
||||
|
||||
// Greet the user
|
||||
//
|
||||
// Conditions:
|
||||
// 1. Just launched
|
||||
memory_Context cli_greetUser(
|
||||
memory_Context c
|
||||
) {
|
||||
if (
|
||||
c.recentField == "didLaunch" &&
|
||||
c.didLaunch == true
|
||||
) {
|
||||
c.outputGreeting = "OGS Memory Command Line Interface";
|
||||
c.recentField = "outputGreeting";
|
||||
return c;
|
||||
}
|
||||
c.recentField = "none";
|
||||
return c;
|
||||
}
|
||||
|
||||
// Ask user to select second item to have a pair of selected items
|
||||
//
|
||||
// Conditions:
|
||||
// 1. Single item has just been selected
|
||||
memory_Context cli_promptSecondItemSelection(
|
||||
memory_Context c
|
||||
) {
|
||||
if (
|
||||
c.recentField == "selectedItems" &&
|
||||
c.selectedItems.size() == 1
|
||||
) {
|
||||
c.outputPromptSelection = "Select the second item now:";
|
||||
c.recentField = "outputPromptSelection";
|
||||
return c;
|
||||
}
|
||||
c.recentField = "none";
|
||||
return c;
|
||||
}
|
||||
|
||||
// Report matched items
|
||||
//
|
||||
// Conditions:
|
||||
// 1. Items were hidden (i.e., they matched)
|
||||
memory_Context cli_reportMatchedItems(
|
||||
memory_Context c
|
||||
) {
|
||||
if (
|
||||
c.recentField == "hiddenItems"
|
||||
) {
|
||||
c.outputMatchedItems = "Items matched!";
|
||||
c.recentField = "outputMatchedItems";
|
||||
return c;
|
||||
}
|
||||
c.recentField = "none";
|
||||
return c;
|
||||
}
|
||||
|
||||
// Report victory
|
||||
memory_Context cli_reportVictory(
|
||||
memory_Context c
|
||||
) {
|
||||
if (
|
||||
c.recentField == "victory"
|
||||
) {
|
||||
c.outputVictory = "VICTORY! The game is over now";
|
||||
c.recentField = "outputVictory";
|
||||
return c;
|
||||
}
|
||||
c.recentField = "none";
|
||||
return c;
|
||||
}
|
||||
|
||||
// Select item
|
||||
//
|
||||
// Conditions:
|
||||
// 1. Id is digit
|
||||
memory_Context cli_selectItem(
|
||||
memory_Context c
|
||||
) {
|
||||
if (
|
||||
c.recentField == "input" &&
|
||||
llm_isDigit(c.input)
|
||||
) {
|
||||
// CLI ids start with 1 while memory module has ids starting with 0
|
||||
// Convert CLI id to memory id
|
||||
c.selectedId = llm_strToInt(c.input) - 1;
|
||||
c.recentField = "selectedId";
|
||||
return c;
|
||||
}
|
||||
c.recentField = "none";
|
||||
return c;
|
||||
}
|
||||
|
||||
// Show help (aka commands)
|
||||
//
|
||||
// Conditions:
|
||||
// 1. Just launched
|
||||
// 1. `h` or `help` was entered
|
||||
memory_Context cli_showHelp(
|
||||
memory_Context c
|
||||
) {
|
||||
if (
|
||||
(
|
||||
c.recentField == "didLaunch" &&
|
||||
c.didLaunch == true
|
||||
) ||
|
||||
(
|
||||
c.recentField == "input" &&
|
||||
c.input == "h"
|
||||
) ||
|
||||
(
|
||||
c.recentField == "input" &&
|
||||
c.input == "help"
|
||||
)
|
||||
) {
|
||||
c.outputHelp = "Commands:\n\te, exit, q, quit\n\t\tExit\n\th, help\n\t\tList commands\n\t1, 2, 3, ...\n\t\tSelect item\nEnter your choice:";
|
||||
c.recentField = "outputHelp";
|
||||
return c;
|
||||
}
|
||||
c.recentField = "none";
|
||||
return c;
|
||||
}
|
||||
|
||||
// Report mismatched items
|
||||
memory_Context cli_reportMismatchedItems(
|
||||
memory_Context c
|
||||
) {
|
||||
if (
|
||||
c.recentField == "mismatchedItems"
|
||||
) {
|
||||
c.outputMismatchedItems = "Wrong! Try again:";
|
||||
c.recentField = "outputMismatchedItems";
|
||||
return c;
|
||||
}
|
||||
c.recentField = "none";
|
||||
return c;
|
||||
}
|
||||
|
||||
//// Report selection of invalid item ids
|
||||
////
|
||||
//// Conditions:
|
||||
//// 1. Index out of bounds: less than minimum
|
||||
//// 2. Index out of bounds: greater than maximum
|
||||
//// 3. Item is already hidden
|
||||
////@llm_by_value
|
||||
////def cli_shouldReportInvalidItemSelection(
|
||||
//// c: cli_Context
|
||||
////) -> cli_Context:
|
||||
//// if (
|
||||
//// c.recentField == "cMemory" and
|
||||
//// c.cMemory.recentField == "selectedItems" and
|
||||
//// len(c.cMemory.selectedItems) == 1
|
||||
//// ):
|
||||
//// c.outputPromptSelection = "Select the second item now:"
|
||||
//// c.recentField = "outputPromptSelection"
|
||||
//// return c
|
||||
//// //}
|
||||
//// c.recentField = "none"
|
||||
//// return c
|
||||
//////}
|
||||
|
||||
222
v5/cli.py
Normal file
222
v5/cli.py
Normal file
@@ -0,0 +1,222 @@
|
||||
from memory_Context import *
|
||||
from llm import *
|
||||
|
||||
# Exit
|
||||
#
|
||||
# Conditions:
|
||||
# 1. `e`, `exit`, `q`, or `quit` was entered
|
||||
# 2. Victory has just been reported
|
||||
@llm_by_value
|
||||
def cli_exit(
|
||||
c: memory_Context
|
||||
) -> memory_Context:
|
||||
if (
|
||||
c.recentField == "input" and
|
||||
(
|
||||
c.input == "e" or
|
||||
c.input == "exit" or
|
||||
c.input == "q" or
|
||||
c.input == "quit"
|
||||
)
|
||||
):
|
||||
c.exit = True
|
||||
c.recentField = "exit"
|
||||
return c
|
||||
#}
|
||||
if (
|
||||
c.recentField == "outputVictory"
|
||||
):
|
||||
c.exit = True
|
||||
c.recentField = "exit"
|
||||
return c
|
||||
#}
|
||||
c.recentField = "none"
|
||||
return c
|
||||
#}
|
||||
|
||||
# Ask user to go on
|
||||
#
|
||||
# Conditions:
|
||||
# 1. Items have just matched and there are still items left to select
|
||||
@llm_by_value
|
||||
def cli_goOn(
|
||||
c: memory_Context
|
||||
) -> memory_Context:
|
||||
if (
|
||||
c.recentField == "outputMatchedItems" and
|
||||
len(c.hiddenItems) != len(c.playfieldItems)
|
||||
):
|
||||
c.outputGoOn = "Go on:"
|
||||
c.recentField = "outputGoOn"
|
||||
return c
|
||||
#}
|
||||
c.recentField = "none"
|
||||
return c
|
||||
#}
|
||||
|
||||
# Greet the user
|
||||
#
|
||||
# Conditions:
|
||||
# 1. Just launched
|
||||
@llm_by_value
|
||||
def cli_greetUser(
|
||||
c: memory_Context
|
||||
) -> memory_Context:
|
||||
if (
|
||||
c.recentField == "didLaunch" and
|
||||
c.didLaunch == True
|
||||
):
|
||||
c.outputGreeting = "OGS Memory Command Line Interface"
|
||||
c.recentField = "outputGreeting"
|
||||
return c
|
||||
#}
|
||||
c.recentField = "none"
|
||||
return c
|
||||
#}
|
||||
|
||||
# Ask user to select second item to have a pair of selected items
|
||||
#
|
||||
# Conditions:
|
||||
# 1. Single item has just been selected
|
||||
@llm_by_value
|
||||
def cli_promptSecondItemSelection(
|
||||
c: memory_Context
|
||||
) -> memory_Context:
|
||||
if (
|
||||
c.recentField == "selectedItems" and
|
||||
len(c.selectedItems) == 1
|
||||
):
|
||||
c.outputPromptSelection = "Select the second item now:"
|
||||
c.recentField = "outputPromptSelection"
|
||||
return c
|
||||
#}
|
||||
c.recentField = "none"
|
||||
return c
|
||||
#}
|
||||
|
||||
# Report matched items
|
||||
#
|
||||
# Conditions:
|
||||
# 1. Items were hidden (i.e., they matched)
|
||||
@llm_by_value
|
||||
def cli_reportMatchedItems(
|
||||
c: memory_Context
|
||||
) -> memory_Context:
|
||||
if (
|
||||
c.recentField == "hiddenItems"
|
||||
):
|
||||
c.outputMatchedItems = "Items matched!"
|
||||
c.recentField = "outputMatchedItems"
|
||||
return c
|
||||
#}
|
||||
c.recentField = "none"
|
||||
return c
|
||||
#}
|
||||
|
||||
# Report victory
|
||||
@llm_by_value
|
||||
def cli_reportVictory(
|
||||
c: memory_Context
|
||||
) -> memory_Context:
|
||||
if (
|
||||
c.recentField == "victory"
|
||||
):
|
||||
c.outputVictory = "VICTORY! The game is over now"
|
||||
c.recentField = "outputVictory"
|
||||
return c
|
||||
#}
|
||||
c.recentField = "none"
|
||||
return c
|
||||
#}
|
||||
|
||||
# Select item
|
||||
#
|
||||
# Conditions:
|
||||
# 1. Id is digit
|
||||
@llm_by_value
|
||||
def cli_selectItem(
|
||||
c: memory_Context
|
||||
) -> memory_Context:
|
||||
if (
|
||||
c.recentField == "input" and
|
||||
llm_isDigit(c.input)
|
||||
):
|
||||
# CLI ids start with 1 while memory module has ids starting with 0
|
||||
# Convert CLI id to memory id
|
||||
c.selectedId = llm_strToInt(c.input) - 1
|
||||
c.recentField = "selectedId"
|
||||
return c
|
||||
#}
|
||||
c.recentField = "none"
|
||||
return c
|
||||
#}
|
||||
|
||||
# Show help (aka commands)
|
||||
#
|
||||
# Conditions:
|
||||
# 1. Just launched
|
||||
# 1. `h` or `help` was entered
|
||||
@llm_by_value
|
||||
def cli_showHelp(
|
||||
c: memory_Context
|
||||
) -> memory_Context:
|
||||
if (
|
||||
(
|
||||
c.recentField == "didLaunch" and
|
||||
c.didLaunch == True
|
||||
) or
|
||||
(
|
||||
c.recentField == "input" and
|
||||
c.input == "h"
|
||||
) or
|
||||
(
|
||||
c.recentField == "input" and
|
||||
c.input == "help"
|
||||
)
|
||||
):
|
||||
c.outputHelp = "Commands:\n\te, exit, q, quit\n\t\tExit\n\th, help\n\t\tList commands\n\t1, 2, 3, ...\n\t\tSelect item\nEnter your choice:"
|
||||
c.recentField = "outputHelp"
|
||||
return c
|
||||
#}
|
||||
c.recentField = "none"
|
||||
return c
|
||||
#}
|
||||
|
||||
# Report mismatched items
|
||||
@llm_by_value
|
||||
def cli_reportMismatchedItems(
|
||||
c: memory_Context
|
||||
) -> memory_Context:
|
||||
if (
|
||||
c.recentField == "mismatchedItems"
|
||||
):
|
||||
c.outputMismatchedItems = "Wrong! Try again:"
|
||||
c.recentField = "outputMismatchedItems"
|
||||
return c
|
||||
#}
|
||||
c.recentField = "none"
|
||||
return c
|
||||
#}
|
||||
|
||||
## Report selection of invalid item ids
|
||||
##
|
||||
## Conditions:
|
||||
## 1. Index out of bounds: less than minimum
|
||||
## 2. Index out of bounds: greater than maximum
|
||||
## 3. Item is already hidden
|
||||
##@llm_by_value
|
||||
##def cli_shouldReportInvalidItemSelection(
|
||||
## c: cli_Context
|
||||
##) -> cli_Context:
|
||||
## if (
|
||||
## c.recentField == "cMemory" and
|
||||
## c.cMemory.recentField == "selectedItems" and
|
||||
## len(c.cMemory.selectedItems) == 1
|
||||
## ):
|
||||
## c.outputPromptSelection = "Select the second item now:"
|
||||
## c.recentField = "outputPromptSelection"
|
||||
## return c
|
||||
## #}
|
||||
## c.recentField = "none"
|
||||
## return c
|
||||
###}
|
||||
309
v5/cli_test.cpp
Normal file
309
v5/cli_test.cpp
Normal file
@@ -0,0 +1,309 @@
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "ctx.h"
|
||||
#include "llm.h"
|
||||
#include "memory_Context.h"
|
||||
#include "main.h"
|
||||
|
||||
std::string cli_test_exit_e(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.input = "e";
|
||||
c.recentField = "input";
|
||||
c = cli_exit(c);
|
||||
if (
|
||||
c.recentField == "exit"
|
||||
) {
|
||||
return "OK: cli_exit_e";
|
||||
}
|
||||
return "ERR: cli_exit_e";
|
||||
}
|
||||
|
||||
std::string cli_test_exit_exit(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.input = "exit";
|
||||
c.recentField = "input";
|
||||
c = cli_exit(c);
|
||||
if (
|
||||
c.recentField == "exit"
|
||||
) {
|
||||
return "OK: cli_exit_exit";
|
||||
}
|
||||
return "ERR: cli_exit_e";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
std::string cli_test_exit_victory(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.playfieldSize = 2;
|
||||
c.recentField = "playfieldSize";
|
||||
c = memory_generateConstPlayfield(c);
|
||||
// Match the first pair of tiles.
|
||||
c.input = "1";
|
||||
c.recentField = "input";
|
||||
c = cli_selectItem(c);
|
||||
c = memory_selectItem(c);
|
||||
c.input = "2";
|
||||
c.recentField = "input";
|
||||
c = cli_selectItem(c);
|
||||
c = memory_selectItem(c);
|
||||
c = memory_hideMatchingItems(c);
|
||||
// Match the second pair of tiles.
|
||||
c.input = "3";
|
||||
c.recentField = "input";
|
||||
c = cli_selectItem(c);
|
||||
c = memory_selectItem(c);
|
||||
c.input = "4";
|
||||
c.recentField = "input";
|
||||
c = cli_selectItem(c);
|
||||
c = memory_selectItem(c);
|
||||
c = memory_hideMatchingItems(c);
|
||||
c = memory_detectVictory(c);
|
||||
c = cli_reportVictory(c);
|
||||
c = cli_exit(c);
|
||||
if (
|
||||
c.recentField == "exit"
|
||||
) {
|
||||
return "OK: cli_exit_victory";
|
||||
}
|
||||
return "ERR: cli_exit_victory";
|
||||
}
|
||||
|
||||
std::string cli_test_exit_q(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.input = "q";
|
||||
c.recentField = "input";
|
||||
c = cli_exit(c);
|
||||
if (
|
||||
c.recentField == "exit"
|
||||
) {
|
||||
return "OK: cli_exit_q";
|
||||
}
|
||||
return "ERR: cli_exit_q";
|
||||
}
|
||||
|
||||
std::string cli_test_exit_quit(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.input = "quit";
|
||||
c.recentField = "input";
|
||||
c = cli_exit(c);
|
||||
if (
|
||||
c.recentField == "exit"
|
||||
) {
|
||||
return "OK: cli_exit_quit";
|
||||
}
|
||||
return "ERR: cli_exit_quit";
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string cli_test_goOn(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.playfieldSize = 2;
|
||||
c.recentField = "playfieldSize";
|
||||
c = memory_generateConstPlayfield(c);
|
||||
// Match the first pair of items.
|
||||
c.input = "1";
|
||||
c.recentField = "input";
|
||||
c = cli_selectItem(c);
|
||||
c = memory_selectItem(c);
|
||||
c.input = "2";
|
||||
c.recentField = "input";
|
||||
c = cli_selectItem(c);
|
||||
c = memory_selectItem(c);
|
||||
c = memory_hideMatchingItems(c);
|
||||
c = cli_reportMatchedItems(c);
|
||||
c = cli_goOn(c);
|
||||
if (
|
||||
c.recentField == "outputGoOn"
|
||||
) {
|
||||
return "OK: cli_goOn";
|
||||
}
|
||||
return "ERR: cli_goOn";
|
||||
}
|
||||
|
||||
std::string cli_test_greetUser(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.didLaunch = true;
|
||||
c.recentField = "didLaunch";
|
||||
c = cli_greetUser(c);
|
||||
if (
|
||||
c.recentField == "outputGreeting"
|
||||
) {
|
||||
return "OK: cli_greetUser";
|
||||
}
|
||||
return "ERR: cli_greetUser";
|
||||
}
|
||||
|
||||
std::string cli_test_promptSecondItemSelection(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.input = "1";
|
||||
c.recentField = "input";
|
||||
c = cli_selectItem(c);
|
||||
c = memory_selectItem(c);
|
||||
c = cli_promptSecondItemSelection(c);
|
||||
if (
|
||||
c.recentField == "outputPromptSelection"
|
||||
) {
|
||||
return "OK: cli_promptSecondItemSelection";
|
||||
}
|
||||
return "ERR: cli_promptSecondItemSelection";
|
||||
}
|
||||
|
||||
std::string cli_test_reportMatchedItems(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.playfieldSize = 2;
|
||||
c.recentField = "playfieldSize";
|
||||
c = memory_generateConstPlayfield(c);
|
||||
c.input = "1";
|
||||
c.recentField = "input";
|
||||
c = cli_selectItem(c);
|
||||
c = memory_selectItem(c);
|
||||
c.input = "2";
|
||||
c.recentField = "input";
|
||||
c = cli_selectItem(c);
|
||||
c = memory_selectItem(c);
|
||||
c = memory_hideMatchingItems(c);
|
||||
c = cli_reportMatchedItems(c);
|
||||
if (
|
||||
c.recentField == "outputMatchedItems"
|
||||
) {
|
||||
return "OK: cli_reportMatchedItems";
|
||||
}
|
||||
return "ERR: cli_reportMatchedItems";
|
||||
}
|
||||
|
||||
std::string cli_test_reportMismatchedItems(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.playfieldSize = 2;
|
||||
c.recentField = "playfieldSize";
|
||||
c = memory_generateConstPlayfield(c);
|
||||
c.input = "1";
|
||||
c.recentField = "input";
|
||||
c = cli_selectItem(c);
|
||||
c = memory_selectItem(c);
|
||||
c.input = "3";
|
||||
c.recentField = "input";
|
||||
c = cli_selectItem(c);
|
||||
c = memory_selectItem(c);
|
||||
c = memory_detectMismatchedItems(c);
|
||||
c = cli_reportMismatchedItems(c);
|
||||
if (
|
||||
c.recentField == "outputMismatchedItems"
|
||||
) {
|
||||
return "OK: cli_reportMismatchedItems";
|
||||
}
|
||||
return "ERR: cli_reportMismatchedItems";
|
||||
}
|
||||
|
||||
std::string cli_test_selectItem(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.input = "1";
|
||||
c.recentField = "input";
|
||||
c = cli_selectItem(c);
|
||||
if (
|
||||
c.recentField == "selectedId" &&
|
||||
c.selectedId == 0
|
||||
) {
|
||||
return "OK: cli_selectItem";
|
||||
}
|
||||
return "ERR: cli_selectItem";
|
||||
}
|
||||
|
||||
std::string cli_test_showHelp_h(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.input = "h";
|
||||
c.recentField = "input";
|
||||
c = cli_showHelp(c);
|
||||
if (
|
||||
c.recentField == "outputHelp"
|
||||
) {
|
||||
return "OK: cli_showHelp_h";
|
||||
}
|
||||
return "ERR: cli_showHelp_h";
|
||||
}
|
||||
|
||||
std::string cli_test_showHelp_help(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.input = "help";
|
||||
c.recentField = "input";
|
||||
c = cli_showHelp(c);
|
||||
if (
|
||||
c.recentField == "outputHelp"
|
||||
) {
|
||||
return "OK: cli_showHelp_help";
|
||||
}
|
||||
return "ERR: cli_showHelp_help";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
std::string cli_test_reportVictory(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.playfieldSize = 2;
|
||||
c.recentField = "playfieldSize";
|
||||
c = memory_generateConstPlayfield(c);
|
||||
// Match the first pair of tiles.
|
||||
c.input = "1";
|
||||
c.recentField = "input";
|
||||
c = cli_selectItem(c);
|
||||
c = memory_selectItem(c);
|
||||
c.input = "2";
|
||||
c.recentField = "input";
|
||||
c = cli_selectItem(c);
|
||||
c = memory_selectItem(c);
|
||||
c = memory_hideMatchingItems(c);
|
||||
// Match the second pair of tiles.
|
||||
c.input = "3";
|
||||
c.recentField = "input";
|
||||
c = cli_selectItem(c);
|
||||
c = memory_selectItem(c);
|
||||
c.input = "4";
|
||||
c.recentField = "input";
|
||||
c = cli_selectItem(c);
|
||||
c = memory_selectItem(c);
|
||||
c = memory_hideMatchingItems(c);
|
||||
c = memory_detectVictory(c);
|
||||
c = cli_reportVictory(c);
|
||||
if (
|
||||
c.recentField == "outputVictory"
|
||||
) {
|
||||
return "OK: cli_reportVictory";
|
||||
}
|
||||
return "ERR: cli_reportVictory";
|
||||
}
|
||||
|
||||
//def cli_test_shouldReportIvalidItemSelection_outOfBoundsMin(
|
||||
//) -> str:
|
||||
// c = cli_createContext()
|
||||
// c.cMemory = memory_createContext()
|
||||
// c.input = "0"
|
||||
// c = cli_selectItem(c)
|
||||
// c = cli_shouldReportInvalidItemSelection(c)
|
||||
// if (
|
||||
// c.recentField == "outputInvalidItemSelection"
|
||||
// ):
|
||||
// return "OK: cli_shouldReportInvalidItemSelection"
|
||||
// //}
|
||||
// return "ERR: cli_shouldReportInvalidItemSelection"
|
||||
////}
|
||||
//
|
||||
|
||||
303
v5/cli_test.py
Normal file
303
v5/cli_test.py
Normal file
@@ -0,0 +1,303 @@
|
||||
from cli import *
|
||||
from memory import *
|
||||
from memory_Context import *
|
||||
|
||||
def cli_test_exit_e(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.input = "e"
|
||||
c.recentField = "input"
|
||||
c = cli_exit(c)
|
||||
if (
|
||||
c.recentField == "exit"
|
||||
):
|
||||
return "OK: cli_exit_e"
|
||||
#}
|
||||
return "ERR: cli_exit_e"
|
||||
#}
|
||||
|
||||
def cli_test_exit_exit(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.input = "exit"
|
||||
c.recentField = "input"
|
||||
c = cli_exit(c)
|
||||
if (
|
||||
c.recentField == "exit"
|
||||
):
|
||||
return "OK: cli_exit_exit"
|
||||
#}
|
||||
return "ERR: cli_exit_e"
|
||||
#}
|
||||
|
||||
def cli_test_exit_victory(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.playfieldSize = 2
|
||||
c.recentField = "playfieldSize"
|
||||
c = memory_generateConstPlayfield(c)
|
||||
|
||||
# Match the first pair of tiles.
|
||||
c.input = "1"
|
||||
c.recentField = "input"
|
||||
c = cli_selectItem(c)
|
||||
c = memory_selectItem(c)
|
||||
c.input = "2"
|
||||
c.recentField = "input"
|
||||
c = cli_selectItem(c)
|
||||
c = memory_selectItem(c)
|
||||
c = memory_hideMatchingItems(c)
|
||||
|
||||
# Match the second pair of tiles.
|
||||
c.input = "3"
|
||||
c.recentField = "input"
|
||||
c = cli_selectItem(c)
|
||||
c = memory_selectItem(c)
|
||||
c.input = "4"
|
||||
c.recentField = "input"
|
||||
c = cli_selectItem(c)
|
||||
c = memory_selectItem(c)
|
||||
c = memory_hideMatchingItems(c)
|
||||
c = memory_detectVictory(c)
|
||||
c = cli_reportVictory(c)
|
||||
c = cli_exit(c)
|
||||
|
||||
if (
|
||||
c.recentField == "exit"
|
||||
):
|
||||
return "OK: cli_exit_victory"
|
||||
#}
|
||||
return "ERR: cli_exit_victory"
|
||||
#}
|
||||
|
||||
def cli_test_exit_q(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.input = "q"
|
||||
c.recentField = "input"
|
||||
c = cli_exit(c)
|
||||
if (
|
||||
c.recentField == "exit"
|
||||
):
|
||||
return "OK: cli_exit_q"
|
||||
#}
|
||||
return "ERR: cli_exit_q"
|
||||
#}
|
||||
|
||||
def cli_test_exit_quit(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.input = "quit"
|
||||
c.recentField = "input"
|
||||
c = cli_exit(c)
|
||||
if (
|
||||
c.recentField == "exit"
|
||||
):
|
||||
return "OK: cli_exit_quit"
|
||||
#}
|
||||
return "ERR: cli_exit_quit"
|
||||
#}
|
||||
|
||||
def cli_test_goOn(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.playfieldSize = 2
|
||||
c.recentField = "playfieldSize"
|
||||
c = memory_generateConstPlayfield(c)
|
||||
|
||||
# Match the first pair of items.
|
||||
c.input = "1"
|
||||
c.recentField = "input"
|
||||
c = cli_selectItem(c)
|
||||
c = memory_selectItem(c)
|
||||
c.input = "2"
|
||||
c.recentField = "input"
|
||||
c = cli_selectItem(c)
|
||||
c = memory_selectItem(c)
|
||||
c = memory_hideMatchingItems(c)
|
||||
c = cli_reportMatchedItems(c)
|
||||
|
||||
c = cli_goOn(c)
|
||||
if (
|
||||
c.recentField == "outputGoOn"
|
||||
):
|
||||
return "OK: cli_goOn"
|
||||
#}
|
||||
return "ERR: cli_goOn"
|
||||
#}
|
||||
|
||||
def cli_test_greetUser(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.didLaunch = True
|
||||
c.recentField = "didLaunch"
|
||||
c = cli_greetUser(c)
|
||||
if (
|
||||
c.recentField == "outputGreeting"
|
||||
):
|
||||
return "OK: cli_greetUser"
|
||||
#}
|
||||
return "ERR: cli_greetUser"
|
||||
#}
|
||||
|
||||
def cli_test_promptSecondItemSelection(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.input = "1"
|
||||
c.recentField = "input"
|
||||
c = cli_selectItem(c)
|
||||
c = memory_selectItem(c)
|
||||
c = cli_promptSecondItemSelection(c)
|
||||
if (
|
||||
c.recentField == "outputPromptSelection"
|
||||
):
|
||||
return "OK: cli_promptSecondItemSelection"
|
||||
#}
|
||||
return "ERR: cli_promptSecondItemSelection"
|
||||
#}
|
||||
|
||||
def cli_test_reportMatchedItems(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.playfieldSize = 2
|
||||
c.recentField = "playfieldSize"
|
||||
c = memory_generateConstPlayfield(c)
|
||||
c.input = "1"
|
||||
c.recentField = "input"
|
||||
c = cli_selectItem(c)
|
||||
c = memory_selectItem(c)
|
||||
c.input = "2"
|
||||
c.recentField = "input"
|
||||
c = cli_selectItem(c)
|
||||
c = memory_selectItem(c)
|
||||
c = memory_hideMatchingItems(c)
|
||||
c = cli_reportMatchedItems(c)
|
||||
if (
|
||||
c.recentField == "outputMatchedItems"
|
||||
):
|
||||
return "OK: cli_reportMatchedItems"
|
||||
#}
|
||||
return "ERR: cli_reportMatchedItems"
|
||||
#}
|
||||
|
||||
def cli_test_reportMismatchedItems(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.playfieldSize = 2
|
||||
c.recentField = "playfieldSize"
|
||||
c = memory_generateConstPlayfield(c)
|
||||
c.input = "1"
|
||||
c.recentField = "input"
|
||||
c = cli_selectItem(c)
|
||||
c = memory_selectItem(c)
|
||||
c.input = "3"
|
||||
c.recentField = "input"
|
||||
c = cli_selectItem(c)
|
||||
c = memory_selectItem(c)
|
||||
c = memory_detectMismatchedItems(c)
|
||||
c = cli_reportMismatchedItems(c)
|
||||
if (
|
||||
c.recentField == "outputMismatchedItems"
|
||||
):
|
||||
return "OK: cli_reportMismatchedItems"
|
||||
#}
|
||||
return "ERR: cli_reportMismatchedItems"
|
||||
#}
|
||||
|
||||
def cli_test_selectItem(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.input = "1"
|
||||
c.recentField = "input"
|
||||
c = cli_selectItem(c)
|
||||
if (
|
||||
c.recentField == "selectedId" and
|
||||
c.selectedId == 0
|
||||
):
|
||||
return "OK: cli_selectItem"
|
||||
#}
|
||||
return "ERR: cli_selectItem"
|
||||
#}
|
||||
|
||||
def cli_test_showHelp_h(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.input = "h"
|
||||
c.recentField = "input"
|
||||
c = cli_showHelp(c)
|
||||
if (
|
||||
c.recentField == "outputHelp"
|
||||
):
|
||||
return "OK: cli_showHelp_h"
|
||||
#}
|
||||
return "ERR: cli_showHelp_h"
|
||||
#}
|
||||
|
||||
def cli_test_showHelp_help(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.input = "help"
|
||||
c.recentField = "input"
|
||||
c = cli_showHelp(c)
|
||||
if (
|
||||
c.recentField == "outputHelp"
|
||||
):
|
||||
return "OK: cli_showHelp_help"
|
||||
#}
|
||||
return "ERR: cli_showHelp_help"
|
||||
#}
|
||||
|
||||
def cli_test_reportVictory(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.playfieldSize = 2
|
||||
c.recentField = "playfieldSize"
|
||||
c = memory_generateConstPlayfield(c)
|
||||
|
||||
# Match the first pair of tiles.
|
||||
c.input = "1"
|
||||
c.recentField = "input"
|
||||
c = cli_selectItem(c)
|
||||
c = memory_selectItem(c)
|
||||
c.input = "2"
|
||||
c.recentField = "input"
|
||||
c = cli_selectItem(c)
|
||||
c = memory_selectItem(c)
|
||||
c = memory_hideMatchingItems(c)
|
||||
|
||||
# Match the second pair of tiles.
|
||||
c.input = "3"
|
||||
c.recentField = "input"
|
||||
c = cli_selectItem(c)
|
||||
c = memory_selectItem(c)
|
||||
c.input = "4"
|
||||
c.recentField = "input"
|
||||
c = cli_selectItem(c)
|
||||
c = memory_selectItem(c)
|
||||
c = memory_hideMatchingItems(c)
|
||||
c = memory_detectVictory(c)
|
||||
c = cli_reportVictory(c)
|
||||
|
||||
if (
|
||||
c.recentField == "outputVictory"
|
||||
):
|
||||
return "OK: cli_reportVictory"
|
||||
#}
|
||||
return "ERR: cli_reportVictory"
|
||||
#}
|
||||
|
||||
#def cli_test_shouldReportIvalidItemSelection_outOfBoundsMin(
|
||||
#) -> str:
|
||||
# c = cli_createContext()
|
||||
# c.cMemory = memory_createContext()
|
||||
# c.input = "0"
|
||||
# c = cli_selectItem(c)
|
||||
# c = cli_shouldReportInvalidItemSelection(c)
|
||||
# if (
|
||||
# c.recentField == "outputInvalidItemSelection"
|
||||
# ):
|
||||
# return "OK: cli_shouldReportInvalidItemSelection"
|
||||
# #}
|
||||
# return "ERR: cli_shouldReportInvalidItemSelection"
|
||||
##}
|
||||
#
|
||||
6
v5/cpp.includes
Normal file
6
v5/cpp.includes
Normal file
@@ -0,0 +1,6 @@
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#// file unused
|
||||
#include "memory.h"
|
||||
#include "memory_Context.h"
|
||||
92
v5/ctx.h
Normal file
92
v5/ctx.h
Normal file
@@ -0,0 +1,92 @@
|
||||
#include <list>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
|
||||
#ifndef ctx_HEADER
|
||||
#define ctx_HEADER
|
||||
|
||||
template <class T> class ctx_Controller {
|
||||
std::list<std::function<void(T)> > callbacks;
|
||||
std::list<std::function<T(T)> > functions;
|
||||
std::queue<T> queue;
|
||||
|
||||
public:
|
||||
T context;
|
||||
bool isProcessingQueue = false;
|
||||
|
||||
ctx_Controller(const T &c) {
|
||||
context = c;
|
||||
}
|
||||
|
||||
void executeFunctions() {
|
||||
auto c = queue.front();
|
||||
queue.pop();
|
||||
for (const auto &f : functions) {
|
||||
auto ctx = f(c);
|
||||
if (ctx.recentField != "none") {
|
||||
queue.push(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
context.recentField = c.recentField;
|
||||
context.setField(c.recentField, c.field(c.recentField));
|
||||
reportContext();
|
||||
}
|
||||
|
||||
void processQueue() {
|
||||
// Decline recursion.
|
||||
if (isProcessingQueue) {
|
||||
return;
|
||||
}
|
||||
isProcessingQueue = true;
|
||||
while (!queue.empty()) {
|
||||
executeFunctions();
|
||||
}
|
||||
isProcessingQueue = false;
|
||||
}
|
||||
|
||||
void registerCallback(std::function<void(T)> cb) {
|
||||
callbacks.push_back(cb);
|
||||
}
|
||||
|
||||
void registerFieldCallback(
|
||||
const std::string &fieldName,
|
||||
std::function<void(T)> cb
|
||||
) {
|
||||
auto execCB = [fieldName, cb](T c) {
|
||||
if (c.recentField == fieldName) {
|
||||
cb(c);
|
||||
}
|
||||
};
|
||||
callbacks.push_back(execCB);
|
||||
}
|
||||
|
||||
void registerFunction(std::function<T(T)> f) {
|
||||
functions.push_back(f);
|
||||
}
|
||||
|
||||
void registerFunctions(std::list<std::function<T(T)> > funcs) {
|
||||
for (const auto &f : funcs) {
|
||||
functions.push_back(f);
|
||||
}
|
||||
}
|
||||
|
||||
void reportContext() {
|
||||
for (const auto &cb : callbacks) {
|
||||
cb(context);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U> void set(
|
||||
const std::string &fieldName,
|
||||
const U &value
|
||||
) {
|
||||
auto c = context;
|
||||
c.setField(fieldName, value);
|
||||
c.recentField = fieldName;
|
||||
queue.push(c);
|
||||
processQueue();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // ctx_HEADER
|
||||
53
v5/ctx.py
Normal file
53
v5/ctx.py
Normal file
@@ -0,0 +1,53 @@
|
||||
import copy
|
||||
|
||||
class ctx_Controller:
|
||||
def __init__(self, c):
|
||||
self.callbacks = []
|
||||
self.context = c
|
||||
self.functions = []
|
||||
self.isProcessingQueue = False
|
||||
self.queue = []
|
||||
|
||||
def executeFunctions(self):
|
||||
c = self.queue.pop(0)
|
||||
for f in self.functions:
|
||||
ctx = f(c)
|
||||
if ctx.recentField != "none":
|
||||
self.queue.append(ctx)
|
||||
|
||||
self.context.recentField = c.recentField
|
||||
self.context.setField(c.recentField, c.field(c.recentField))
|
||||
self.reportContext()
|
||||
|
||||
def processQueue(self):
|
||||
# Decline recursion.
|
||||
if self.isProcessingQueue:
|
||||
return
|
||||
self.isProcessingQueue = True
|
||||
while len(self.queue) > 0:
|
||||
self.executeFunctions()
|
||||
self.isProcessingQueue = False
|
||||
|
||||
def registerCallback(self, cb):
|
||||
self.callbacks.append(cb)
|
||||
|
||||
def registerFieldCallback(self, fieldName, cb):
|
||||
self.callbacks.append(lambda c: cb(c) if c.recentField == fieldName else None)
|
||||
|
||||
def registerFunction(self, f):
|
||||
self.functions.append(f)
|
||||
|
||||
def registerFunctions(self, funcs):
|
||||
for f in funcs:
|
||||
self.functions.append(f)
|
||||
|
||||
def reportContext(self):
|
||||
for cb in self.callbacks:
|
||||
cb(self.context)
|
||||
|
||||
def set(self, fieldName, value):
|
||||
c = copy.deepcopy(self.context)
|
||||
c.setField(fieldName, value)
|
||||
c.recentField = fieldName
|
||||
self.queue.append(c)
|
||||
self.processQueue()
|
||||
141
v5/ctx_test2.cpp
Normal file
141
v5/ctx_test2.cpp
Normal file
@@ -0,0 +1,141 @@
|
||||
#include <string>
|
||||
#include "any.h"
|
||||
#include "ctx.h"
|
||||
#include "memory_Context.h"
|
||||
|
||||
std::string s(const char *str) {
|
||||
return std::string(str);
|
||||
}
|
||||
|
||||
std::string test_ctx_Controller_executeFunctions_registerFunction_set() {
|
||||
auto c = memory_createContext();
|
||||
ctx_Controller<memory_Context> ctrl(c);
|
||||
// Disable automatic invocation of executeFunctions.
|
||||
ctrl.isProcessingQueue = true;
|
||||
ctrl.set("input", s("123"));
|
||||
|
||||
auto processInput = [](memory_Context c) -> memory_Context {
|
||||
if (c.recentField == "input") {
|
||||
c.outputHelp = "Checked";
|
||||
c.recentField = "outputHelp";
|
||||
return c;
|
||||
}
|
||||
c.recentField = "none";
|
||||
return c;
|
||||
};
|
||||
|
||||
ctrl.registerFunction(processInput);
|
||||
// Apply 'input'.
|
||||
ctrl.executeFunctions();
|
||||
// Apply 'outputHelp'.
|
||||
ctrl.executeFunctions();
|
||||
if (
|
||||
ctrl.context.input == "123" &&
|
||||
ctrl.context.outputHelp == "Checked"
|
||||
) {
|
||||
return "OK: ctx_Controller_executeFunctions_set";
|
||||
}
|
||||
return "ERR: ctx_Controller_executeFunctions_set";
|
||||
}
|
||||
|
||||
std::string test_ctx_Controller_processQueue() {
|
||||
auto c = memory_createContext();
|
||||
ctx_Controller<memory_Context> ctrl(c);
|
||||
|
||||
auto processInput = [](memory_Context c) -> memory_Context {
|
||||
if (c.recentField == "input") {
|
||||
c.outputHelp = "Checked";
|
||||
c.recentField = "outputHelp";
|
||||
return c;
|
||||
}
|
||||
c.recentField = "none";
|
||||
return c;
|
||||
};
|
||||
|
||||
ctrl.registerFunction(processInput);
|
||||
ctrl.set("input", s("abc"));
|
||||
if (
|
||||
ctrl.context.input == "abc" &&
|
||||
ctrl.context.outputHelp == "Checked"
|
||||
) {
|
||||
return "OK: ctx_Controller_processQueue";
|
||||
}
|
||||
return "ERR: ctx_Controller_processQueue";
|
||||
}
|
||||
|
||||
std::string test_ctx_Controller_registerFieldCallback_match() {
|
||||
auto c = memory_createContext();
|
||||
ctx_Controller<memory_Context> ctrl(c);
|
||||
|
||||
c.input = "123";
|
||||
c.recentField = "input";
|
||||
std::string callbackInput = "";
|
||||
|
||||
auto setCallbackInput = [&callbackInput](memory_Context c) {
|
||||
if (
|
||||
c.recentField == "input"
|
||||
) {
|
||||
callbackInput = c.input;
|
||||
}
|
||||
};
|
||||
|
||||
ctrl.registerFieldCallback("input", setCallbackInput);
|
||||
ctrl.reportContext();
|
||||
if (
|
||||
ctrl.context.input == callbackInput
|
||||
) {
|
||||
return "OK: ctx_Controller_registerFieldCallback_match";
|
||||
}
|
||||
return "ERR: ctx_Controller_registerFieldCallback_match";
|
||||
}
|
||||
|
||||
std::string test_ctx_Controller_registerFieldCallback_mismatch() {
|
||||
auto c = memory_createContext();
|
||||
ctx_Controller<memory_Context> ctrl(c);
|
||||
|
||||
c.input = "123";
|
||||
c.outputHelp = "you";
|
||||
// A field other than 'input' is marked recent.
|
||||
c.recentField = "outputHelp";
|
||||
std::string callbackInput = "";
|
||||
|
||||
auto setCallbackInput = [&callbackInput](memory_Context c) {
|
||||
if (
|
||||
c.recentField == "input"
|
||||
) {
|
||||
callbackInput = c.input;
|
||||
}
|
||||
};
|
||||
|
||||
ctrl.registerFieldCallback("input", setCallbackInput);
|
||||
ctrl.reportContext();
|
||||
if (
|
||||
callbackInput == ""
|
||||
) {
|
||||
return "OK: ctx_Controller_registerFieldCallback_mismatch";
|
||||
}
|
||||
return "ERR: ctx_Controller_registerFieldCallback_mismatch";
|
||||
}
|
||||
|
||||
std::string test_memory_Context_field() {
|
||||
auto c = memory_createContext();
|
||||
c.input = "abc";
|
||||
if (
|
||||
libany::any_cast<std::string>(c.field("input")) == "abc"
|
||||
) {
|
||||
return "OK: memory_Context_field";
|
||||
}
|
||||
return "ERR: memory_Context_field";
|
||||
}
|
||||
|
||||
std::string test_memory_Context_setField() {
|
||||
auto c = memory_createContext();
|
||||
c.input = "abc";
|
||||
c.setField("input", s("123"));
|
||||
if (
|
||||
c.input == "123"
|
||||
) {
|
||||
return "OK: memory_Context_setField";
|
||||
}
|
||||
return "ERR: memory_Context_setField";
|
||||
}
|
||||
13
v5/ctx_test2.h
Normal file
13
v5/ctx_test2.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#include <string>
|
||||
|
||||
#ifndef ctx_test_HEADER
|
||||
#define ctx_test_HEADER
|
||||
|
||||
std::string test_ctx_Controller_executeFunctions_registerFunction_set();
|
||||
std::string test_ctx_Controller_processQueue();
|
||||
std::string test_ctx_Controller_registerFieldCallback_match();
|
||||
std::string test_ctx_Controller_registerFieldCallback_mismatch();
|
||||
std::string test_memory_Context_field();
|
||||
std::string test_memory_Context_setField();
|
||||
|
||||
#endif // ctx_test_HEADER
|
||||
142
v5/ctx_test2.py
Normal file
142
v5/ctx_test2.py
Normal file
@@ -0,0 +1,142 @@
|
||||
from ctx import *
|
||||
from memory import *
|
||||
from memory_Context import *
|
||||
|
||||
def ctx_test_Controller_executeFunctions_registerFunction_set(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
ctrl = ctx_Controller(c)
|
||||
# Disable automatic invocation of executeFunctions.
|
||||
ctrl.isProcessingQueue = True
|
||||
ctrl.set("input", "123")
|
||||
|
||||
@llm_by_value
|
||||
def processInput(c):
|
||||
if (
|
||||
c.recentField == "input"
|
||||
):
|
||||
c.outputHelp = "Checked"
|
||||
c.recentField = "outputHelp"
|
||||
return c
|
||||
#}
|
||||
c.recentField = "none"
|
||||
return c
|
||||
#}
|
||||
|
||||
ctrl.registerFunction(processInput)
|
||||
# Apply 'input'.
|
||||
ctrl.executeFunctions()
|
||||
# Apply 'outputHelp'.
|
||||
ctrl.executeFunctions()
|
||||
if (
|
||||
c.input == "123" and
|
||||
c.outputHelp == "Checked"
|
||||
):
|
||||
return "OK: ctx_Controller_executeFunctions_set"
|
||||
#}
|
||||
return "ERR: ctx_Controller_executeFunctions_set"
|
||||
#}
|
||||
|
||||
def ctx_test_Controller_processQueue(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
ctrl = ctx_Controller(c)
|
||||
|
||||
@llm_by_value
|
||||
def processInput(c):
|
||||
if (
|
||||
c.recentField == "input"
|
||||
):
|
||||
c.outputHelp = "Checked"
|
||||
c.recentField = "outputHelp"
|
||||
return c
|
||||
#}
|
||||
c.recentField = "none"
|
||||
return c
|
||||
#}
|
||||
|
||||
ctrl.registerFunction(processInput)
|
||||
ctrl.set("input", "abc");
|
||||
if (
|
||||
c.input == "abc" and
|
||||
c.outputHelp == "Checked"
|
||||
):
|
||||
return "OK: ctx_Controller_processQueue"
|
||||
#}
|
||||
return "ERR: ctx_Controller_processQueue"
|
||||
#}
|
||||
|
||||
def ctx_test_Controller_registerFieldCallback_match(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
ctrl = ctx_Controller(c)
|
||||
c.input = "123"
|
||||
c.recentField = "input"
|
||||
|
||||
globals()["callbackInput"] = ""
|
||||
def setCallbackInput(c):
|
||||
if (
|
||||
c.recentField == "input"
|
||||
):
|
||||
globals()["callbackInput"] = c.input
|
||||
|
||||
ctrl.registerFieldCallback("input", setCallbackInput)
|
||||
ctrl.reportContext()
|
||||
if (
|
||||
c.input == globals()["callbackInput"]
|
||||
):
|
||||
return "OK: ctx_Controller_registerFieldCallback_match"
|
||||
#}
|
||||
return "ERR: ctx_Controller_registerFieldCallback_match"
|
||||
#}
|
||||
|
||||
def ctx_test_Controller_registerFieldCallback_mismatch(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
ctrl = ctx_Controller(c)
|
||||
c.input = "123"
|
||||
c.outputHelp = "you"
|
||||
# A field other than 'input' is marked recent.
|
||||
c.recentField = "outputHelp"
|
||||
|
||||
globals()["callbackInput"] = ""
|
||||
def setCallbackInput(c):
|
||||
if (
|
||||
c.recentField == "input"
|
||||
):
|
||||
globals()["callbackInput"] = c.input
|
||||
|
||||
ctrl.registerFieldCallback("input", setCallbackInput)
|
||||
ctrl.reportContext()
|
||||
if (
|
||||
globals()["callbackInput"] == ""
|
||||
):
|
||||
return "OK: ctx_Controller_registerFieldCallback_mismatch"
|
||||
#}
|
||||
return "ERR: ctx_Controller_registerFieldCallback_mismatch"
|
||||
#}
|
||||
|
||||
def ctx_test_memoryContext_field(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.input = "abc"
|
||||
if (
|
||||
c.field("input") == "abc"
|
||||
):
|
||||
return "OK: ctx_memoryContext_field"
|
||||
#}
|
||||
return "ERR: ctx_memoryContext_field"
|
||||
#}
|
||||
|
||||
def ctx_test_memoryContext_setField(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.input = "abc"
|
||||
c.setField("input", "123")
|
||||
if (
|
||||
c.input == "123"
|
||||
):
|
||||
return "OK: ctx_memoryContext_setField"
|
||||
#}
|
||||
return "ERR: ctx_memoryContext_setField"
|
||||
#}
|
||||
27
v5/cxx-headers
Executable file
27
v5/cxx-headers
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
|
||||
DIR=$(cd "$(dirname "$0")" ; pwd -P)
|
||||
TMP=/tmp/cxx-headers.tmp
|
||||
|
||||
grep '^memory_Context ' memory.cpp > $TMP
|
||||
grep '^std::string ' memory_test.cpp >> $TMP
|
||||
grep '^memory_Context ' cli.cpp >> $TMP
|
||||
grep '^std::string ' cli_test.cpp >> $TMP
|
||||
grep '^std::string ' ctx_test.cpp >> $TMP
|
||||
grep '^std::string ' llm_test.cpp >> $TMP
|
||||
|
||||
IN=$TMP
|
||||
OUT=$DIR/main.h
|
||||
|
||||
echo '
|
||||
#include "memory_Context.h"
|
||||
|
||||
#ifndef main_HEADER
|
||||
#define main_HEADER
|
||||
' > $OUT
|
||||
|
||||
sed -Ef cxx-headers.sed <$IN >>$OUT
|
||||
|
||||
echo '
|
||||
#endif // main_HEADER
|
||||
' >> $OUT
|
||||
15
v5/cxx-headers.sed
Normal file
15
v5/cxx-headers.sed
Normal file
@@ -0,0 +1,15 @@
|
||||
# #} -> }
|
||||
#s|#}|}|
|
||||
|
||||
# # -> //
|
||||
#s|#|//|
|
||||
|
||||
# dict[X, Y] -> std::map<X, Y>
|
||||
#s_dict\[(.*), (.*)\]_std::map<\1, \2>_
|
||||
|
||||
# def functionName(X) -> Y -> Y functionName(X) {
|
||||
#s|def (.*) -> (.*):|\2 \1 {|
|
||||
|
||||
s|memory_Context (.*)\(|memory_Context \1(memory_Context);|
|
||||
s|std::string (.*)\(|std::string \1();|
|
||||
|
||||
10
v5/gen-C++
Executable file
10
v5/gen-C++
Executable file
@@ -0,0 +1,10 @@
|
||||
c++ -o test_memory_C++ -std=c++11 -I. \
|
||||
memory.cpp \
|
||||
memory_Context.cpp \
|
||||
memory_test.cpp \
|
||||
llm.cpp \
|
||||
llm_test.cpp \
|
||||
cli.cpp \
|
||||
cli_test.cpp \
|
||||
ctx_test2.cpp \
|
||||
main.cpp
|
||||
2
v5/gen-Python
Executable file
2
v5/gen-Python
Executable file
@@ -0,0 +1,2 @@
|
||||
echo "python3 main.py" > test_memory_Python
|
||||
chmod +x test_memory_Python
|
||||
19
v5/llm.cpp
Normal file
19
v5/llm.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "llm.h"
|
||||
|
||||
bool llm_isDigit(const std::string &str) {
|
||||
return
|
||||
!str.empty() &&
|
||||
str.find_first_not_of("0123456789") == std::string::npos;
|
||||
}
|
||||
|
||||
bool llm_startsWith(
|
||||
const std::string &str,
|
||||
const std::string &prefix
|
||||
) {
|
||||
// https://stackoverflow.com/a/40441240
|
||||
return str.rfind(prefix, 0) == 0;
|
||||
}
|
||||
|
||||
int llm_strToInt(const std::string &str) {
|
||||
return std::stoi(str);
|
||||
}
|
||||
10
v5/llm.h
Normal file
10
v5/llm.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef llm_HEADER
|
||||
#define llm_HEADER
|
||||
|
||||
#include <string>
|
||||
|
||||
bool llm_isDigit(const std::string &str);
|
||||
bool llm_startsWith(const std::string &str, const std::string &prefix);
|
||||
int llm_strToInt(const std::string &str);
|
||||
|
||||
#endif // llm_HEADER
|
||||
22
v5/llm.py
Normal file
22
v5/llm.py
Normal file
@@ -0,0 +1,22 @@
|
||||
import copy
|
||||
|
||||
# Make deep copies of arguments to treat the arguments as structs.
|
||||
# https://stackoverflow.com/a/15398021
|
||||
def llm_by_value(f):
|
||||
def _f(*args, **kwargs):
|
||||
argsCopy = copy.deepcopy(args)
|
||||
kwargsCopy = copy.deepcopy(kwargs)
|
||||
return f(*argsCopy, **kwargsCopy)
|
||||
return _f
|
||||
|
||||
# Tell if string is a digit
|
||||
def llm_isDigit(s):
|
||||
return s.isdigit()
|
||||
|
||||
# Tell if string starts with certain prefix.
|
||||
def llm_startsWith(s, prefix):
|
||||
return s.startswith(prefix)
|
||||
|
||||
# Convert string to integer
|
||||
def llm_strToInt(s):
|
||||
return int(s)
|
||||
39
v5/llm_test.cpp
Normal file
39
v5/llm_test.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "ctx.h"
|
||||
#include "llm.h"
|
||||
#include "memory_Context.h"
|
||||
#include "main.h"
|
||||
|
||||
std::string llm_test_isDigit_digit(
|
||||
) {
|
||||
if (
|
||||
llm_isDigit("123")
|
||||
) {
|
||||
return "OK: llm_isDigit_digit";
|
||||
}
|
||||
return "ERR: llm_isDigit_digit";
|
||||
}
|
||||
|
||||
std::string llm_test_isDigit_notDigit(
|
||||
) {
|
||||
if (
|
||||
llm_isDigit("abc")
|
||||
) {
|
||||
return "ERR: llm_isDigit_notDigit";
|
||||
}
|
||||
return "OK: llm_isDigit_notDigit";
|
||||
}
|
||||
|
||||
std::string llm_test_strToInt(
|
||||
) {
|
||||
if (
|
||||
llm_strToInt("123") == 123
|
||||
) {
|
||||
return "OK: llm_strToInt";
|
||||
}
|
||||
return "ERR: llm_strToInt";
|
||||
}
|
||||
|
||||
31
v5/llm_test.py
Normal file
31
v5/llm_test.py
Normal file
@@ -0,0 +1,31 @@
|
||||
from llm import *
|
||||
|
||||
def llm_test_isDigit_digit(
|
||||
) -> str:
|
||||
if (
|
||||
llm_isDigit("123")
|
||||
):
|
||||
return "OK: llm_isDigit_digit"
|
||||
#}
|
||||
return "ERR: llm_isDigit_digit"
|
||||
#}
|
||||
|
||||
def llm_test_isDigit_notDigit(
|
||||
) -> str:
|
||||
if (
|
||||
llm_isDigit("abc")
|
||||
):
|
||||
return "ERR: llm_isDigit_notDigit"
|
||||
#}
|
||||
return "OK: llm_isDigit_notDigit"
|
||||
#}
|
||||
|
||||
def llm_test_strToInt(
|
||||
) -> str:
|
||||
if (
|
||||
llm_strToInt("123") == 123
|
||||
):
|
||||
return "OK: llm_strToInt"
|
||||
#}
|
||||
return "ERR: llm_strToInt"
|
||||
#}
|
||||
21
v5/llm_test_Python.py
Normal file
21
v5/llm_test_Python.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from llm import *
|
||||
from memory_Context import *
|
||||
|
||||
def llm_test_Python_copyByValue(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.input = "abc"
|
||||
|
||||
@llm_by_value
|
||||
def alterValue(c):
|
||||
c.input = "alteredValue"
|
||||
|
||||
alterValue(c)
|
||||
|
||||
if (
|
||||
c.input == "abc"
|
||||
):
|
||||
return "OK: llm_Python_copyByValue"
|
||||
#}
|
||||
return "ERR: llm_Python_copyByValue"
|
||||
#}
|
||||
119
v5/main.cpp
Normal file
119
v5/main.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "any.h"
|
||||
#include "ctx_test2.h"
|
||||
#include "llm.h"
|
||||
#include "main.h"
|
||||
#include "memory_Context.h"
|
||||
|
||||
int main() {
|
||||
std::cout
|
||||
<< test_ctx_Controller_executeFunctions_registerFunction_set()
|
||||
<< std::endl
|
||||
<< test_ctx_Controller_processQueue()
|
||||
<< std::endl
|
||||
<< test_ctx_Controller_registerFieldCallback_match()
|
||||
<< std::endl
|
||||
<< test_ctx_Controller_registerFieldCallback_mismatch()
|
||||
<< std::endl
|
||||
<< test_memory_Context_field()
|
||||
<< std::endl
|
||||
<< test_memory_Context_setField()
|
||||
<< std::endl
|
||||
<< llm_test_isDigit_digit()
|
||||
<< std::endl
|
||||
<< llm_test_isDigit_notDigit()
|
||||
<< std::endl
|
||||
<< llm_test_strToInt()
|
||||
<< std::endl
|
||||
;
|
||||
|
||||
std::cout
|
||||
<< memory_test_detectMismatchedItems()
|
||||
<< std::endl
|
||||
<< memory_test_detectMismatchedItems_itemTwice()
|
||||
<< std::endl
|
||||
<< memory_test_detectVictory()
|
||||
<< std::endl
|
||||
<< memory_test_generateConstPlayfield()
|
||||
<< std::endl
|
||||
<< memory_test_hideMatchingItems()
|
||||
<< std::endl
|
||||
<< memory_test_selectItem_1x()
|
||||
<< std::endl
|
||||
<< memory_test_selectItem_2x()
|
||||
<< std::endl
|
||||
<< memory_test_selectItem_3x()
|
||||
<< std::endl
|
||||
;
|
||||
|
||||
std::cout
|
||||
<< cli_test_exit_e()
|
||||
<< std::endl
|
||||
<< cli_test_exit_exit()
|
||||
<< std::endl
|
||||
<< cli_test_exit_victory()
|
||||
<< std::endl
|
||||
<< cli_test_exit_q()
|
||||
<< std::endl
|
||||
<< cli_test_exit_quit()
|
||||
<< std::endl
|
||||
<< cli_test_goOn()
|
||||
<< std::endl
|
||||
<< cli_test_greetUser()
|
||||
<< std::endl
|
||||
<< cli_test_showHelp_h()
|
||||
<< std::endl
|
||||
<< cli_test_showHelp_help()
|
||||
<< std::endl
|
||||
<< cli_test_selectItem()
|
||||
<< std::endl
|
||||
<< cli_test_promptSecondItemSelection()
|
||||
<< std::endl
|
||||
<< cli_test_reportMatchedItems()
|
||||
<< std::endl
|
||||
<< cli_test_reportMismatchedItems()
|
||||
<< std::endl
|
||||
<< cli_test_reportVictory()
|
||||
<< std::endl
|
||||
;
|
||||
|
||||
ctx_Controller<memory_Context> ctrl(memory_createContext());
|
||||
ctrl.registerFunctions({
|
||||
cli_exit,
|
||||
cli_goOn,
|
||||
cli_greetUser,
|
||||
cli_promptSecondItemSelection,
|
||||
cli_reportMatchedItems,
|
||||
cli_reportMismatchedItems,
|
||||
cli_reportVictory,
|
||||
cli_selectItem,
|
||||
cli_showHelp,
|
||||
memory_detectMismatchedItems,
|
||||
memory_detectVictory,
|
||||
memory_generateConstPlayfield,
|
||||
memory_hideMatchingItems,
|
||||
memory_selectItem,
|
||||
});
|
||||
|
||||
|
||||
auto printOutput = [](memory_Context c) {
|
||||
if (llm_startsWith(c.recentField, "output")) {
|
||||
std::cout
|
||||
<< libany::any_cast<std::string>(c.field(c.recentField))
|
||||
<< std::endl;
|
||||
}
|
||||
};
|
||||
ctrl.registerCallback(printOutput);
|
||||
ctrl.registerFieldCallback("exit", [](memory_Context c) { exit(0); });
|
||||
|
||||
ctrl.set("didLaunch", true);
|
||||
ctrl.set("playfieldSize", 2);
|
||||
|
||||
while (true) {
|
||||
std::string ln;
|
||||
getline(std::cin, ln);
|
||||
ctrl.set("input", ln);
|
||||
}
|
||||
}
|
||||
52
v5/main.h
Normal file
52
v5/main.h
Normal file
@@ -0,0 +1,52 @@
|
||||
|
||||
#include "memory_Context.h"
|
||||
|
||||
#ifndef main_HEADER
|
||||
#define main_HEADER
|
||||
|
||||
memory_Context memory_detectMismatchedItems(memory_Context);
|
||||
memory_Context memory_detectVictory(memory_Context);
|
||||
memory_Context memory_generateConstPlayfield(memory_Context);
|
||||
memory_Context memory_hideMatchingItems(memory_Context);
|
||||
memory_Context memory_selectItem(memory_Context);
|
||||
std::string memory_test_detectMismatchedItems();
|
||||
std::string memory_test_detectMismatchedItems_itemTwice();
|
||||
std::string memory_test_detectVictory();
|
||||
std::string memory_test_generateConstPlayfield();
|
||||
std::string memory_test_hideMatchingItems();
|
||||
std::string memory_test_selectItem_1x();
|
||||
std::string memory_test_selectItem_2x();
|
||||
std::string memory_test_selectItem_3x();
|
||||
memory_Context cli_exit(memory_Context);
|
||||
memory_Context cli_goOn(memory_Context);
|
||||
memory_Context cli_greetUser(memory_Context);
|
||||
memory_Context cli_promptSecondItemSelection(memory_Context);
|
||||
memory_Context cli_reportMatchedItems(memory_Context);
|
||||
memory_Context cli_reportVictory(memory_Context);
|
||||
memory_Context cli_selectItem(memory_Context);
|
||||
memory_Context cli_showHelp(memory_Context);
|
||||
memory_Context cli_reportMismatchedItems(memory_Context);
|
||||
std::string cli_test_exit_e();
|
||||
std::string cli_test_exit_exit();
|
||||
std::string cli_test_exit_victory();
|
||||
std::string cli_test_exit_q();
|
||||
std::string cli_test_exit_quit();
|
||||
std::string cli_test_goOn();
|
||||
std::string cli_test_greetUser();
|
||||
std::string cli_test_promptSecondItemSelection();
|
||||
std::string cli_test_reportMatchedItems();
|
||||
std::string cli_test_reportMismatchedItems();
|
||||
std::string cli_test_selectItem();
|
||||
std::string cli_test_showHelp_h();
|
||||
std::string cli_test_showHelp_help();
|
||||
std::string cli_test_reportVictory();
|
||||
std::string ctx_test_Controller_executeFunctions_set();
|
||||
std::string ctx_test_Controller_processQueue();
|
||||
std::string ctx_test_memoryContext_field();
|
||||
std::string ctx_test_memoryContext_setField();
|
||||
std::string llm_test_isDigit_digit();
|
||||
std::string llm_test_isDigit_notDigit();
|
||||
std::string llm_test_strToInt();
|
||||
|
||||
#endif // main_HEADER
|
||||
|
||||
77
v5/main.py
Normal file
77
v5/main.py
Normal file
@@ -0,0 +1,77 @@
|
||||
from cli import *
|
||||
from cli_test import *
|
||||
from ctx import *
|
||||
from ctx_test2 import *
|
||||
#from ctx_test import *
|
||||
#from ctx_test_Python import *
|
||||
from llm_test import *
|
||||
from llm_test_Python import *
|
||||
from memory_test import *
|
||||
import sys
|
||||
|
||||
print(ctx_test_Controller_executeFunctions_registerFunction_set())
|
||||
print(ctx_test_Controller_processQueue())
|
||||
print(ctx_test_Controller_registerFieldCallback_match())
|
||||
print(ctx_test_Controller_registerFieldCallback_mismatch())
|
||||
print(ctx_test_memoryContext_field())
|
||||
print(ctx_test_memoryContext_setField())
|
||||
|
||||
print(llm_test_Python_copyByValue())
|
||||
print(llm_test_isDigit_digit())
|
||||
print(llm_test_isDigit_notDigit())
|
||||
print(llm_test_strToInt())
|
||||
|
||||
print(memory_test_detectMismatchedItems())
|
||||
print(memory_test_detectMismatchedItems_itemTwice())
|
||||
print(memory_test_detectVictory())
|
||||
print(memory_test_generateConstPlayfield())
|
||||
print(memory_test_hideMatchingItems())
|
||||
print(memory_test_selectItem_1x())
|
||||
print(memory_test_selectItem_2x())
|
||||
print(memory_test_selectItem_3x())
|
||||
|
||||
print(cli_test_exit_e())
|
||||
print(cli_test_exit_exit())
|
||||
print(cli_test_exit_victory())
|
||||
print(cli_test_exit_q())
|
||||
print(cli_test_exit_quit())
|
||||
print(cli_test_goOn())
|
||||
print(cli_test_greetUser())
|
||||
print(cli_test_showHelp_h())
|
||||
print(cli_test_showHelp_help())
|
||||
print(cli_test_selectItem())
|
||||
print(cli_test_promptSecondItemSelection())
|
||||
print(cli_test_reportMatchedItems())
|
||||
print(cli_test_reportMismatchedItems())
|
||||
print(cli_test_reportVictory())
|
||||
|
||||
ctrl = ctx_Controller(memory_createContext())
|
||||
ctrl.registerFunctions([
|
||||
cli_exit,
|
||||
cli_goOn,
|
||||
cli_greetUser,
|
||||
cli_promptSecondItemSelection,
|
||||
cli_reportMatchedItems,
|
||||
cli_reportMismatchedItems,
|
||||
cli_reportVictory,
|
||||
cli_selectItem,
|
||||
cli_showHelp,
|
||||
memory_detectMismatchedItems,
|
||||
memory_detectVictory,
|
||||
memory_generateConstPlayfield,
|
||||
memory_hideMatchingItems,
|
||||
memory_selectItem,
|
||||
])
|
||||
|
||||
def printOutput(c):
|
||||
if c.recentField.startswith("output"):
|
||||
print(c.field(c.recentField))
|
||||
ctrl.registerCallback(printOutput)
|
||||
ctrl.registerFieldCallback("exit", lambda c: sys.exit(0))
|
||||
|
||||
ctrl.set("didLaunch", True)
|
||||
ctrl.set("playfieldSize", 2)
|
||||
|
||||
for line in sys.stdin:
|
||||
ln = line.rstrip()
|
||||
ctrl.set("input", ln)
|
||||
140
v5/memory.cpp
Normal file
140
v5/memory.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "ctx.h"
|
||||
#include "llm.h"
|
||||
#include "memory_Context.h"
|
||||
#include "main.h"
|
||||
|
||||
// Detect mismatched items
|
||||
//
|
||||
// Conditions:
|
||||
// 0. Two items has just been selected
|
||||
// 1. The same item has been selected twice
|
||||
// 2. Selected items are of different groups
|
||||
memory_Context memory_detectMismatchedItems(
|
||||
memory_Context c
|
||||
) {
|
||||
if (!(
|
||||
c.recentField == "selectedItems" &&
|
||||
c.selectedItems.size() == 2
|
||||
)) {
|
||||
c.recentField = "none";
|
||||
return c;
|
||||
}
|
||||
if (
|
||||
c.selectedItems[0] == c.selectedItems[1]
|
||||
) {
|
||||
c.mismatchedItems.clear();
|
||||
c.mismatchedItems.push_back(c.selectedItems[0]);
|
||||
c.recentField = "mismatchedItems";
|
||||
return c;
|
||||
}
|
||||
if (
|
||||
c.playfieldItems[c.selectedItems[0]] != c.playfieldItems[c.selectedItems[1]]
|
||||
) {
|
||||
c.mismatchedItems.clear();
|
||||
c.mismatchedItems.push_back(c.selectedItems[0]);
|
||||
c.mismatchedItems.push_back(c.selectedItems[1]);
|
||||
c.recentField = "mismatchedItems";
|
||||
return c;
|
||||
}
|
||||
c.recentField = "none";
|
||||
return c;
|
||||
}
|
||||
|
||||
// Detect victory
|
||||
//
|
||||
// Conditions:
|
||||
// 1. Matching items have just been hidden and all items are hidden now
|
||||
memory_Context memory_detectVictory(
|
||||
memory_Context c
|
||||
) {
|
||||
if (
|
||||
c.recentField == "hiddenItems" &&
|
||||
c.hiddenItems.size() == c.playfieldItems.size()
|
||||
) {
|
||||
c.victory = true;
|
||||
c.recentField = "victory";
|
||||
return c;
|
||||
}
|
||||
c.recentField = "none";
|
||||
return c;
|
||||
}
|
||||
|
||||
// Generate constant playfield
|
||||
//
|
||||
// Conditions:
|
||||
// 1. Size has just been specified
|
||||
//
|
||||
// Both ids and group ids start with 0
|
||||
|
||||
memory_Context memory_generateConstPlayfield(
|
||||
memory_Context c
|
||||
) {
|
||||
if (!(
|
||||
c.recentField == "playfieldSize"
|
||||
)) {
|
||||
c.recentField = "none";
|
||||
return c;
|
||||
}
|
||||
std::map<int, int> idGroups = { };
|
||||
auto id = 0;
|
||||
for (auto gid = 0; gid < c.playfieldSize; ++gid) {
|
||||
idGroups[id] = gid;
|
||||
id += 1;
|
||||
idGroups[id] = gid;
|
||||
id += 1;
|
||||
}
|
||||
c.playfieldItems = idGroups;
|
||||
c.recentField = "playfieldItems";
|
||||
return c;
|
||||
}
|
||||
|
||||
// Hide matching selected items
|
||||
//
|
||||
// Conditions:
|
||||
// 1. Two items are selected and they are of the same group
|
||||
memory_Context memory_hideMatchingItems(
|
||||
memory_Context c
|
||||
) {
|
||||
if (
|
||||
c.recentField == "selectedItems" &&
|
||||
c.selectedItems.size() == 2 &&
|
||||
c.playfieldItems[c.selectedItems[0]] == c.playfieldItems[c.selectedItems[1]]
|
||||
) {
|
||||
c.hiddenItems.push_back(c.selectedItems[0]);
|
||||
c.hiddenItems.push_back(c.selectedItems[1]);
|
||||
c.recentField = "hiddenItems";
|
||||
return c;
|
||||
}
|
||||
c.recentField = "none";
|
||||
return c;
|
||||
}
|
||||
|
||||
// Select item
|
||||
//
|
||||
// Conditions:
|
||||
// 1. Id has just been specified for selection
|
||||
|
||||
memory_Context memory_selectItem(
|
||||
memory_Context c
|
||||
) {
|
||||
if (!(
|
||||
c.recentField == "selectedId"
|
||||
)) {
|
||||
c.recentField = "none";
|
||||
return c;
|
||||
}
|
||||
if (
|
||||
c.selectedItems.size() == 2
|
||||
) {
|
||||
c.selectedItems.clear();
|
||||
}
|
||||
c.selectedItems.push_back(c.selectedId);
|
||||
c.recentField = "selectedItems";
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
138
v5/memory.py
Normal file
138
v5/memory.py
Normal file
@@ -0,0 +1,138 @@
|
||||
from memory_Context import *
|
||||
from llm import *
|
||||
|
||||
# Detect mismatched items
|
||||
#
|
||||
# Conditions:
|
||||
# 0. Two items has just been selected
|
||||
# 1. The same item has been selected twice
|
||||
# 2. Selected items are of different groups
|
||||
@llm_by_value
|
||||
def memory_detectMismatchedItems(
|
||||
c: memory_Context
|
||||
) -> memory_Context:
|
||||
if not (
|
||||
c.recentField == "selectedItems" and
|
||||
len(c.selectedItems) == 2
|
||||
):
|
||||
c.recentField = "none"
|
||||
return c
|
||||
#}
|
||||
if (
|
||||
c.selectedItems[0] == c.selectedItems[1]
|
||||
):
|
||||
c.mismatchedItems.clear()
|
||||
c.mismatchedItems.append(c.selectedItems[0])
|
||||
c.recentField = "mismatchedItems"
|
||||
return c
|
||||
#}
|
||||
if (
|
||||
c.playfieldItems[c.selectedItems[0]] != c.playfieldItems[c.selectedItems[1]]
|
||||
):
|
||||
c.mismatchedItems.clear()
|
||||
c.mismatchedItems.append(c.selectedItems[0])
|
||||
c.mismatchedItems.append(c.selectedItems[1])
|
||||
c.recentField = "mismatchedItems"
|
||||
return c
|
||||
#}
|
||||
c.recentField = "none"
|
||||
return c
|
||||
#}
|
||||
|
||||
# Detect victory
|
||||
#
|
||||
# Conditions:
|
||||
# 1. Matching items have just been hidden and all items are hidden now
|
||||
@llm_by_value
|
||||
def memory_detectVictory(
|
||||
c: memory_Context
|
||||
) -> memory_Context:
|
||||
if (
|
||||
c.recentField == "hiddenItems" and
|
||||
len(c.hiddenItems) == len(c.playfieldItems)
|
||||
):
|
||||
c.victory = True
|
||||
c.recentField = "victory"
|
||||
return c
|
||||
#}
|
||||
c.recentField = "none"
|
||||
return c
|
||||
#}
|
||||
|
||||
# Generate constant playfield
|
||||
#
|
||||
# Conditions:
|
||||
# 1. Size has just been specified
|
||||
#
|
||||
# Both ids and group ids start with 0
|
||||
@llm_by_value
|
||||
def memory_generateConstPlayfield(
|
||||
c: memory_Context
|
||||
) -> memory_Context:
|
||||
if not (
|
||||
c.recentField == "playfieldSize"
|
||||
):
|
||||
c.recentField = "none"
|
||||
return c
|
||||
#}
|
||||
|
||||
idGroups: dict[int, int] = { }
|
||||
id = 0
|
||||
for gid in range(0, c.playfieldSize):
|
||||
idGroups[id] = gid
|
||||
id += 1
|
||||
idGroups[id] = gid
|
||||
id += 1
|
||||
#}
|
||||
c.playfieldItems = idGroups
|
||||
c.recentField = "playfieldItems"
|
||||
return c
|
||||
#}
|
||||
|
||||
# Hide matching selected items
|
||||
#
|
||||
# Conditions:
|
||||
# 1. Two items are selected and they are of the same group
|
||||
@llm_by_value
|
||||
def memory_hideMatchingItems(
|
||||
c: memory_Context
|
||||
) -> memory_Context:
|
||||
if (
|
||||
c.recentField == "selectedItems" and
|
||||
len(c.selectedItems) == 2 and
|
||||
c.playfieldItems[c.selectedItems[0]] == c.playfieldItems[c.selectedItems[1]]
|
||||
):
|
||||
c.hiddenItems.append(c.selectedItems[0])
|
||||
c.hiddenItems.append(c.selectedItems[1])
|
||||
c.recentField = "hiddenItems"
|
||||
return c
|
||||
#}
|
||||
c.recentField = "none"
|
||||
return c
|
||||
#}
|
||||
|
||||
# Select item
|
||||
#
|
||||
# Conditions:
|
||||
# 1. Id has just been specified for selection
|
||||
@llm_by_value
|
||||
def memory_selectItem(
|
||||
c: memory_Context
|
||||
) -> memory_Context:
|
||||
if not (
|
||||
c.recentField == "selectedId"
|
||||
):
|
||||
c.recentField = "none"
|
||||
return c
|
||||
#}
|
||||
|
||||
if (
|
||||
len(c.selectedItems) == 2
|
||||
):
|
||||
c.selectedItems.clear()
|
||||
#}
|
||||
c.selectedItems.append(c.selectedId)
|
||||
c.recentField = "selectedItems"
|
||||
return c
|
||||
#}
|
||||
|
||||
83
v5/memory_Context.cpp
Normal file
83
v5/memory_Context.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
#include <utility>
|
||||
#include "any.h"
|
||||
#include "memory_Context.h"
|
||||
|
||||
libany::any memory_Context::field(const std::string &fieldName) {
|
||||
if (fieldName == "didLaunch") {
|
||||
return didLaunch;
|
||||
} else if (fieldName == "exit") {
|
||||
return exit;
|
||||
} else if (fieldName == "hiddenItems") {
|
||||
return hiddenItems;
|
||||
} else if (fieldName == "input") {
|
||||
return input;
|
||||
} else if (fieldName == "mismatchedItems") {
|
||||
return mismatchedItems;
|
||||
} else if (fieldName == "outputGoOn") {
|
||||
return outputGoOn;
|
||||
} else if (fieldName == "outputGreeting") {
|
||||
return outputGreeting;
|
||||
} else if (fieldName == "outputHelp") {
|
||||
return outputHelp;
|
||||
} else if (fieldName == "outputMatchedItems") {
|
||||
return outputMatchedItems;
|
||||
} else if (fieldName == "outputMismatchedItems") {
|
||||
return outputMismatchedItems;
|
||||
} else if (fieldName == "outputPromptSelection") {
|
||||
return outputPromptSelection;
|
||||
} else if (fieldName == "outputVictory") {
|
||||
return outputVictory;
|
||||
} else if (fieldName == "playfieldItems") {
|
||||
return playfieldItems;
|
||||
} else if (fieldName == "playfieldSize") {
|
||||
return playfieldSize;
|
||||
} else if (fieldName == "selectedId") {
|
||||
return selectedId;
|
||||
} else if (fieldName == "selectedItems") {
|
||||
return selectedItems;
|
||||
}
|
||||
// victory
|
||||
return victory;
|
||||
}
|
||||
|
||||
void memory_Context::setField(const std::string &fieldName, libany::any value) {
|
||||
if (fieldName == "didLaunch") {
|
||||
didLaunch = libany::any_cast<bool>(value);
|
||||
} else if (fieldName == "exit") {
|
||||
exit = libany::any_cast<bool>(value);
|
||||
} else if (fieldName == "hiddenItems") {
|
||||
hiddenItems = libany::any_cast<std::vector<int> >(value);
|
||||
} else if (fieldName == "input") {
|
||||
input = libany::any_cast<std::string>(value);
|
||||
} else if (fieldName == "mismatchedItems") {
|
||||
mismatchedItems = libany::any_cast<std::vector<int> >(value);
|
||||
} else if (fieldName == "outputGoOn") {
|
||||
outputGoOn = libany::any_cast<std::string>(value);
|
||||
} else if (fieldName == "outputGreeting") {
|
||||
outputGreeting = libany::any_cast<std::string>(value);
|
||||
} else if (fieldName == "outputHelp") {
|
||||
outputHelp = libany::any_cast<std::string>(value);
|
||||
} else if (fieldName == "outputMatchedItems") {
|
||||
outputMatchedItems = libany::any_cast<std::string>(value);
|
||||
} else if (fieldName == "outputMismatchedItems") {
|
||||
outputMismatchedItems = libany::any_cast<std::string>(value);
|
||||
} else if (fieldName == "outputPromptSelection") {
|
||||
outputPromptSelection = libany::any_cast<std::string>(value);
|
||||
} else if (fieldName == "outputVictory") {
|
||||
outputVictory = libany::any_cast<std::string>(value);
|
||||
} else if (fieldName == "playfieldItems") {
|
||||
playfieldItems = libany::any_cast<std::map<int, int> >(value);
|
||||
} else if (fieldName == "playfieldSize") {
|
||||
playfieldSize = libany::any_cast<int>(value);
|
||||
} else if (fieldName == "selectedId") {
|
||||
selectedId = libany::any_cast<int>(value);
|
||||
} else if (fieldName == "selectedItems") {
|
||||
selectedItems = libany::any_cast<std::vector<int> >(value);
|
||||
} else if (fieldName == "victory") {
|
||||
victory = libany::any_cast<bool>(value);
|
||||
}
|
||||
}
|
||||
|
||||
memory_Context memory_createContext() {
|
||||
return memory_Context();
|
||||
}
|
||||
36
v5/memory_Context.h
Normal file
36
v5/memory_Context.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "any.h"
|
||||
#include "ctx.h"
|
||||
|
||||
#ifndef memory_Context_HEADER
|
||||
#define memory_Context_HEADER
|
||||
|
||||
struct memory_Context {
|
||||
bool didLaunch = false;
|
||||
bool exit = false;
|
||||
std::vector<int> hiddenItems;
|
||||
std::string input = "";
|
||||
std::vector<int> mismatchedItems;
|
||||
std::string outputGoOn = "";
|
||||
std::string outputGreeting = "";
|
||||
std::string outputHelp = "";
|
||||
std::string outputMatchedItems = "";
|
||||
std::string outputMismatchedItems = "";
|
||||
std::string outputPromptSelection = "";
|
||||
std::string outputVictory = "";
|
||||
std::map<int, int> playfieldItems;
|
||||
int playfieldSize = 0;
|
||||
std::string recentField = "none";
|
||||
int selectedId = -1;
|
||||
std::vector<int> selectedItems;
|
||||
bool victory = false;
|
||||
|
||||
libany::any field(const std::string &fieldName);
|
||||
void setField(const std::string &fieldName, libany::any value);
|
||||
};
|
||||
|
||||
memory_Context memory_createContext();
|
||||
|
||||
#endif // memory_Context_HEADER
|
||||
35
v5/memory_Context.py
Normal file
35
v5/memory_Context.py
Normal file
@@ -0,0 +1,35 @@
|
||||
class memory_Context:
|
||||
def __init__(self):
|
||||
self.didLaunch = False
|
||||
self.exit = False
|
||||
self.hiddenItems = []
|
||||
self.input = ""
|
||||
self.mismatchedItems = []
|
||||
self.outputGoOn = ""
|
||||
self.outputGreeting = ""
|
||||
self.outputHelp = ""
|
||||
self.outputMatchedItems = ""
|
||||
self.outputMismatchedItems = ""
|
||||
self.outputPromptSelection = ""
|
||||
self.outputVictory = ""
|
||||
self.playfieldItems = {}
|
||||
self.playfieldSize = 0
|
||||
self.recentField = "none"
|
||||
self.selectedId = -1
|
||||
self.selectedItems = []
|
||||
self.victory = False
|
||||
|
||||
def field(self, fieldName):
|
||||
return getattr(self, fieldName)
|
||||
|
||||
def setField(self, fieldName, value):
|
||||
setattr(self, fieldName, value)
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
return f"memory_Context(playfieldI/playfieldS/recentF/selectedId/selectedI: '{self.playfieldItems}'/'{self.playfieldSize}'/'{self.recentField}'/'{self.selectedId}'/'{self.selectedItems}')"
|
||||
|
||||
def memory_createContext():
|
||||
return memory_Context()
|
||||
238
v5/memory_test.cpp
Normal file
238
v5/memory_test.cpp
Normal file
@@ -0,0 +1,238 @@
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "ctx.h"
|
||||
#include "llm.h"
|
||||
#include "memory_Context.h"
|
||||
#include "main.h"
|
||||
|
||||
|
||||
|
||||
|
||||
std::string memory_test_detectMismatchedItems(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.playfieldSize = 2;
|
||||
c.recentField = "playfieldSize";
|
||||
c = memory_generateConstPlayfield(c);
|
||||
// Select two items of different groups.
|
||||
c.selectedId = 0;
|
||||
c.recentField = "selectedId";
|
||||
c = memory_selectItem(c);
|
||||
c.selectedId = 2;
|
||||
c.recentField = "selectedId";
|
||||
c = memory_selectItem(c);
|
||||
// Detect mismatching.
|
||||
c = memory_detectMismatchedItems(c);
|
||||
// See if the two selected items do not match.
|
||||
if (
|
||||
c.recentField == "mismatchedItems" &&
|
||||
c.mismatchedItems.size() == 2 &&
|
||||
c.mismatchedItems[0] == 0 &&
|
||||
c.mismatchedItems[1] == 2
|
||||
) {
|
||||
return "OK: memory_detectMismatchedItems";
|
||||
}
|
||||
return "ERR: memory_detectMismatchedItems";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
std::string memory_test_detectMismatchedItems_itemTwice(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.playfieldSize = 2;
|
||||
c.recentField = "playfieldSize";
|
||||
c = memory_generateConstPlayfield(c);
|
||||
// Select the same item twice.
|
||||
c.selectedId = 0;
|
||||
c.recentField = "selectedId";
|
||||
c = memory_selectItem(c);
|
||||
c.selectedId = 0;
|
||||
c.recentField = "selectedId";
|
||||
c = memory_selectItem(c);
|
||||
// Detect mismatching.
|
||||
c = memory_detectMismatchedItems(c);
|
||||
// See if the two selected items do not match.
|
||||
if (
|
||||
c.recentField == "mismatchedItems" &&
|
||||
c.mismatchedItems.size() == 1 &&
|
||||
c.mismatchedItems[0] == 0
|
||||
) {
|
||||
return "OK: memory_detectMismatchedItems_itemTwice";
|
||||
}
|
||||
return "ERR: memory_detectMismatchedItems_itemTwice";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
std::string memory_test_detectVictory(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.playfieldSize = 2;
|
||||
c.recentField = "playfieldSize";
|
||||
c = memory_generateConstPlayfield(c);
|
||||
// Select the first two items of the same group.
|
||||
c.selectedId = 0;
|
||||
c.recentField = "selectedId";
|
||||
c = memory_selectItem(c);
|
||||
c.selectedId = 1;
|
||||
c.recentField = "selectedId";
|
||||
c = memory_selectItem(c);
|
||||
// Hide the first pair.
|
||||
c = memory_hideMatchingItems(c);
|
||||
// Select the last two items of the same group.
|
||||
c.selectedId = 2;
|
||||
c.recentField = "selectedId";
|
||||
c = memory_selectItem(c);
|
||||
c.selectedId = 3;
|
||||
c.recentField = "selectedId";
|
||||
c = memory_selectItem(c);
|
||||
// Hide the second pair.
|
||||
c = memory_hideMatchingItems(c);
|
||||
// Detect victory.
|
||||
c = memory_detectVictory(c);
|
||||
// See if victory has been detected.
|
||||
if (
|
||||
c.recentField == "victory" &&
|
||||
c.victory == true
|
||||
) {
|
||||
return "OK: memory_detectVictory";
|
||||
}
|
||||
return "ERR: memory_detectVictory";
|
||||
}
|
||||
|
||||
std::string memory_test_generateConstPlayfield(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.playfieldSize = 2;
|
||||
c.recentField = "playfieldSize";
|
||||
c = memory_generateConstPlayfield(c);
|
||||
if (
|
||||
c.recentField == "playfieldItems" &&
|
||||
c.playfieldItems.size() == 4 &&
|
||||
c.playfieldItems[0] == 0 &&
|
||||
c.playfieldItems[1] == 0 &&
|
||||
c.playfieldItems[2] == 1 &&
|
||||
c.playfieldItems[3] == 1
|
||||
) {
|
||||
return "OK: memory_generateConstPlayfield";
|
||||
}
|
||||
return "ERR: memory_generateConstPlayfield";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
std::string memory_test_hideMatchingItems(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.playfieldSize = 2;
|
||||
c.recentField = "playfieldSize";
|
||||
c = memory_generateConstPlayfield(c);
|
||||
// Select two items of the same group.
|
||||
c.selectedId = 0;
|
||||
c.recentField = "selectedId";
|
||||
c = memory_selectItem(c);
|
||||
c.selectedId = 1;
|
||||
c.recentField = "selectedId";
|
||||
c = memory_selectItem(c);
|
||||
// Hide matching items.
|
||||
c = memory_hideMatchingItems(c);
|
||||
// See if the two selected items match.
|
||||
if (
|
||||
c.recentField == "hiddenItems" &&
|
||||
c.hiddenItems.size() == 2 &&
|
||||
c.hiddenItems[0] == 0 &&
|
||||
c.hiddenItems[1] == 1
|
||||
) {
|
||||
return "OK: memory_hideMatchingItems";
|
||||
}
|
||||
return "ERR: memory_hideMatchingItems";
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string memory_test_selectItem_1x(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.playfieldSize = 2;
|
||||
c.recentField = "playfieldSize";
|
||||
c = memory_generateConstPlayfield(c);
|
||||
// Select the first item.
|
||||
c.selectedId = 0;
|
||||
c.recentField = "selectedId";
|
||||
c = memory_selectItem(c);
|
||||
// See if it's in selectedItems now.
|
||||
if (
|
||||
c.recentField == "selectedItems" &&
|
||||
c.selectedItems.size() == 1 &&
|
||||
c.selectedItems[0] == 0
|
||||
) {
|
||||
return "OK: memory_selectItem_1x";
|
||||
}
|
||||
return "ERR: memory_selectItem_1x";
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string memory_test_selectItem_2x(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.playfieldSize = 2;
|
||||
c.recentField = "playfieldSize";
|
||||
c = memory_generateConstPlayfield(c);
|
||||
// Select the first two items.
|
||||
c.selectedId = 0;
|
||||
c.recentField = "selectedId";
|
||||
c = memory_selectItem(c);
|
||||
c.selectedId = 1;
|
||||
c.recentField = "selectedId";
|
||||
c = memory_selectItem(c);
|
||||
// See if both items are selected now.
|
||||
if (
|
||||
c.recentField == "selectedItems" &&
|
||||
c.selectedItems.size() == 2 &&
|
||||
c.selectedItems[0] == 0 &&
|
||||
c.selectedItems[1] == 1
|
||||
) {
|
||||
return "OK: memory_selectItem_2x";
|
||||
}
|
||||
return "ERR: memory_selectItem_2x";
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string memory_test_selectItem_3x(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.playfieldSize = 2;
|
||||
c.recentField = "playfieldSize";
|
||||
c = memory_generateConstPlayfield(c);
|
||||
// Select three items.
|
||||
c.selectedId = 0;
|
||||
c.recentField = "selectedId";
|
||||
c = memory_selectItem(c);
|
||||
c.selectedId = 1;
|
||||
c.recentField = "selectedId";
|
||||
c = memory_selectItem(c);
|
||||
c.selectedId = 2;
|
||||
c.recentField = "selectedId";
|
||||
c = memory_selectItem(c);
|
||||
// See if only one (last) item is selected now.
|
||||
if (
|
||||
c.recentField == "selectedItems" &&
|
||||
c.selectedItems.size() == 1 &&
|
||||
c.selectedItems[0] == 2
|
||||
) {
|
||||
return "OK: memory_selectItem_3x";
|
||||
}
|
||||
return "ERR: memory_selectItem_3x";
|
||||
}
|
||||
|
||||
231
v5/memory_test.py
Normal file
231
v5/memory_test.py
Normal file
@@ -0,0 +1,231 @@
|
||||
from memory import *
|
||||
from memory_Context import *
|
||||
|
||||
def memory_test_detectMismatchedItems(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.playfieldSize = 2
|
||||
c.recentField = "playfieldSize"
|
||||
c = memory_generateConstPlayfield(c)
|
||||
|
||||
# Select two items of different groups.
|
||||
c.selectedId = 0
|
||||
c.recentField = "selectedId"
|
||||
c = memory_selectItem(c)
|
||||
c.selectedId = 2
|
||||
c.recentField = "selectedId"
|
||||
c = memory_selectItem(c)
|
||||
|
||||
# Detect mismatching.
|
||||
c = memory_detectMismatchedItems(c)
|
||||
|
||||
# See if the two selected items do not match.
|
||||
if (
|
||||
c.recentField == "mismatchedItems" and
|
||||
len(c.mismatchedItems) == 2 and
|
||||
c.mismatchedItems[0] == 0 and
|
||||
c.mismatchedItems[1] == 2
|
||||
):
|
||||
return "OK: memory_detectMismatchedItems"
|
||||
#}
|
||||
return "ERR: memory_detectMismatchedItems"
|
||||
#}
|
||||
|
||||
def memory_test_detectMismatchedItems_itemTwice(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.playfieldSize = 2
|
||||
c.recentField = "playfieldSize"
|
||||
c = memory_generateConstPlayfield(c)
|
||||
|
||||
# Select the same item twice.
|
||||
c.selectedId = 0
|
||||
c.recentField = "selectedId"
|
||||
c = memory_selectItem(c)
|
||||
c.selectedId = 0
|
||||
c.recentField = "selectedId"
|
||||
c = memory_selectItem(c)
|
||||
|
||||
# Detect mismatching.
|
||||
c = memory_detectMismatchedItems(c)
|
||||
|
||||
# See if the two selected items do not match.
|
||||
if (
|
||||
c.recentField == "mismatchedItems" and
|
||||
len(c.mismatchedItems) == 1 and
|
||||
c.mismatchedItems[0] == 0
|
||||
):
|
||||
return "OK: memory_detectMismatchedItems_itemTwice"
|
||||
#}
|
||||
return "ERR: memory_detectMismatchedItems_itemTwice"
|
||||
#}
|
||||
|
||||
def memory_test_detectVictory(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.playfieldSize = 2
|
||||
c.recentField = "playfieldSize"
|
||||
c = memory_generateConstPlayfield(c)
|
||||
|
||||
# Select the first two items of the same group.
|
||||
c.selectedId = 0
|
||||
c.recentField = "selectedId"
|
||||
c = memory_selectItem(c)
|
||||
c.selectedId = 1
|
||||
c.recentField = "selectedId"
|
||||
c = memory_selectItem(c)
|
||||
|
||||
# Hide the first pair.
|
||||
c = memory_hideMatchingItems(c)
|
||||
|
||||
# Select the last two items of the same group.
|
||||
c.selectedId = 2
|
||||
c.recentField = "selectedId"
|
||||
c = memory_selectItem(c)
|
||||
c.selectedId = 3
|
||||
c.recentField = "selectedId"
|
||||
c = memory_selectItem(c)
|
||||
|
||||
# Hide the second pair.
|
||||
c = memory_hideMatchingItems(c)
|
||||
|
||||
# Detect victory.
|
||||
c = memory_detectVictory(c)
|
||||
|
||||
# See if victory has been detected.
|
||||
if (
|
||||
c.recentField == "victory" and
|
||||
c.victory == True
|
||||
):
|
||||
return "OK: memory_detectVictory"
|
||||
#}
|
||||
return "ERR: memory_detectVictory"
|
||||
#}
|
||||
|
||||
def memory_test_generateConstPlayfield(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.playfieldSize = 2
|
||||
c.recentField = "playfieldSize"
|
||||
c = memory_generateConstPlayfield(c)
|
||||
if (
|
||||
c.recentField == "playfieldItems" and
|
||||
len(c.playfieldItems) == 4 and
|
||||
c.playfieldItems[0] == 0 and
|
||||
c.playfieldItems[1] == 0 and
|
||||
c.playfieldItems[2] == 1 and
|
||||
c.playfieldItems[3] == 1
|
||||
):
|
||||
return "OK: memory_generateConstPlayfield"
|
||||
#}
|
||||
return "ERR: memory_generateConstPlayfield"
|
||||
#}
|
||||
|
||||
def memory_test_hideMatchingItems(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.playfieldSize = 2
|
||||
c.recentField = "playfieldSize"
|
||||
c = memory_generateConstPlayfield(c)
|
||||
|
||||
# Select two items of the same group.
|
||||
c.selectedId = 0
|
||||
c.recentField = "selectedId"
|
||||
c = memory_selectItem(c)
|
||||
c.selectedId = 1
|
||||
c.recentField = "selectedId"
|
||||
c = memory_selectItem(c)
|
||||
|
||||
# Hide matching items.
|
||||
c = memory_hideMatchingItems(c)
|
||||
|
||||
# See if the two selected items match.
|
||||
if (
|
||||
c.recentField == "hiddenItems" and
|
||||
len(c.hiddenItems) == 2 and
|
||||
c.hiddenItems[0] == 0 and
|
||||
c.hiddenItems[1] == 1
|
||||
):
|
||||
return "OK: memory_hideMatchingItems"
|
||||
#}
|
||||
return "ERR: memory_hideMatchingItems"
|
||||
#}
|
||||
|
||||
def memory_test_selectItem_1x(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.playfieldSize = 2
|
||||
c.recentField = "playfieldSize"
|
||||
c = memory_generateConstPlayfield(c)
|
||||
|
||||
# Select the first item.
|
||||
c.selectedId = 0
|
||||
c.recentField = "selectedId"
|
||||
c = memory_selectItem(c)
|
||||
|
||||
# See if it's in selectedItems now.
|
||||
if (
|
||||
c.recentField == "selectedItems" and
|
||||
len(c.selectedItems) == 1 and
|
||||
c.selectedItems[0] == 0
|
||||
):
|
||||
return "OK: memory_selectItem_1x"
|
||||
#}
|
||||
return "ERR: memory_selectItem_1x"
|
||||
#}
|
||||
|
||||
def memory_test_selectItem_2x(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.playfieldSize = 2
|
||||
c.recentField = "playfieldSize"
|
||||
c = memory_generateConstPlayfield(c)
|
||||
|
||||
# Select the first two items.
|
||||
c.selectedId = 0
|
||||
c.recentField = "selectedId"
|
||||
c = memory_selectItem(c)
|
||||
c.selectedId = 1
|
||||
c.recentField = "selectedId"
|
||||
c = memory_selectItem(c)
|
||||
|
||||
# See if both items are selected now.
|
||||
if (
|
||||
c.recentField == "selectedItems" and
|
||||
len(c.selectedItems) == 2 and
|
||||
c.selectedItems[0] == 0 and
|
||||
c.selectedItems[1] == 1
|
||||
):
|
||||
return "OK: memory_selectItem_2x"
|
||||
#}
|
||||
return "ERR: memory_selectItem_2x"
|
||||
#}
|
||||
|
||||
def memory_test_selectItem_3x(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.playfieldSize = 2
|
||||
c.recentField = "playfieldSize"
|
||||
c = memory_generateConstPlayfield(c)
|
||||
|
||||
# Select three items.
|
||||
c.selectedId = 0
|
||||
c.recentField = "selectedId"
|
||||
c = memory_selectItem(c)
|
||||
c.selectedId = 1
|
||||
c.recentField = "selectedId"
|
||||
c = memory_selectItem(c)
|
||||
c.selectedId = 2
|
||||
c.recentField = "selectedId"
|
||||
c = memory_selectItem(c)
|
||||
|
||||
# See if only one (last) item is selected now.
|
||||
if (
|
||||
c.recentField == "selectedItems" and
|
||||
len(c.selectedItems) == 1 and
|
||||
c.selectedItems[0] == 2
|
||||
):
|
||||
return "OK: memory_selectItem_3x"
|
||||
#}
|
||||
return "ERR: memory_selectItem_3x"
|
||||
#}
|
||||
195
v5/tPythonC++/CPP.py
Normal file
195
v5/tPythonC++/CPP.py
Normal file
@@ -0,0 +1,195 @@
|
||||
from Function import *
|
||||
|
||||
def includes():
|
||||
return """
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "ctx.h"
|
||||
#include "llm.h"
|
||||
#include "memory_Context.h"
|
||||
#include "main.h"
|
||||
"""
|
||||
|
||||
def replaceAnd(s):
|
||||
return s.replace(" and", " &&")
|
||||
|
||||
def replaceAppend(s):
|
||||
return s.replace(".append(", ".push_back(")
|
||||
|
||||
def replaceComment(s):
|
||||
return s.replace("#", "//")
|
||||
|
||||
def replaceLen(s):
|
||||
posLen = s.find("len(")
|
||||
posEnd = s.find(")", posLen)
|
||||
if (
|
||||
posLen == -1 or
|
||||
posEnd == -1
|
||||
):
|
||||
return s
|
||||
before = s[:posLen]
|
||||
name = s[posLen + len("len("):posEnd]
|
||||
after = s[posEnd + len(")"):]
|
||||
return f"{before}{name}.size(){after}"
|
||||
|
||||
def replaceOr(s):
|
||||
return s.replace(" or", " ||")
|
||||
|
||||
def replaceTrue(s):
|
||||
return s.replace("True", "true")
|
||||
|
||||
def translateParameter(s):
|
||||
# name: type -> type name
|
||||
parts = s.split(": ")
|
||||
indent = len(s) - len(s.lstrip())
|
||||
name = parts[0].lstrip()
|
||||
t = translateType(parts[1])
|
||||
indentation = "".join(" " * indent)
|
||||
return f"{indentation}{t} {name}"
|
||||
|
||||
def translateStatement(s, state):
|
||||
indent = len(s) - len(s.lstrip())
|
||||
indentation = "".join(" " * indent)
|
||||
ss = s.lstrip()
|
||||
posColon = ss.find(": ")
|
||||
posComma = ss.find(", ")
|
||||
posComment = ss.find("# ")
|
||||
posCtrl = ss.find("ctrl.")
|
||||
posCtx = ss.find("c.")
|
||||
posEqual = ss.find(" = ")
|
||||
posFor = ss.find("for ")
|
||||
posIn = ss.find(" in ")
|
||||
posRange = ss.find("range(")
|
||||
posRangeEnd = ss.find("):")
|
||||
posClosingScope = ss.find("#}")
|
||||
posOpenSquareBracket = ss.find("[")
|
||||
|
||||
# # -> //
|
||||
if posComment != -1:
|
||||
return replaceComment(s)
|
||||
|
||||
# #} -> }
|
||||
if posClosingScope != -1:
|
||||
return f"{indentation}}}"
|
||||
|
||||
# for name in range(x, y): -> for (auto name = x; name < y; ++name) {
|
||||
if (
|
||||
posFor >= 0 and
|
||||
posIn >= 0 and
|
||||
posRange >= 0
|
||||
):
|
||||
name = ss[posFor + len("for "):posIn]
|
||||
x = ss[posRange + len("range("):posComma]
|
||||
y = ss[posComma + len(", "):posRangeEnd]
|
||||
return f"{indentation}for (auto {name} = {x}; {name} < {y}; ++{name}) {{"
|
||||
|
||||
# name: type = value -> type name = value
|
||||
if (
|
||||
posColon >= 0 and
|
||||
posEqual >= 0
|
||||
):
|
||||
name = ss[:posColon]
|
||||
type = ss[posColon + len(": "):posEqual]
|
||||
t = translateType(type)
|
||||
value = ss[posEqual + len(" = "):]
|
||||
return f"{indentation}{t} {name} = {value};"
|
||||
|
||||
# name = value -> auto name = value
|
||||
if (
|
||||
posCtx == -1 and
|
||||
posCtrl == -1 and
|
||||
posColon == -1 and
|
||||
posOpenSquareBracket == -1 and
|
||||
posEqual >= 0
|
||||
):
|
||||
name = ss[:posEqual]
|
||||
# Skip prepending 'auto' each time variable is assigned,
|
||||
# only do it the first time
|
||||
if name not in state.varNames:
|
||||
state.varNames[name] = True
|
||||
value = ss[posEqual + len(" = "):]
|
||||
return f"{indentation}auto {name} = {value};"
|
||||
|
||||
# Keep "if ("
|
||||
if ss == "if (":
|
||||
state.isIf = True
|
||||
return s
|
||||
|
||||
# Keep "if not ("
|
||||
if ss == "if not (":
|
||||
state.isIfNot = True
|
||||
return f"{indentation}if (!("
|
||||
|
||||
# ): -> }
|
||||
if ss == "):":
|
||||
# if
|
||||
if state.isIf:
|
||||
state.isIf = False
|
||||
return f"{indentation}) {{"
|
||||
# if not
|
||||
state.isIfNot = False
|
||||
return f"{indentation})) {{"
|
||||
|
||||
ending = ";"
|
||||
if state.isIf or state.isIfNot:
|
||||
ending = ""
|
||||
|
||||
# Unknown.
|
||||
return f"{s}{ending}"
|
||||
|
||||
def translateType(s):
|
||||
# dict[X, Y] -> std::map<X, Y>
|
||||
if s.startswith("dict["):
|
||||
kv = s[len("dict["):-len("]")]
|
||||
parts = kv.split(", ")
|
||||
return f"std::map<{parts[0]}, {parts[1]}>"
|
||||
# str -> std::string
|
||||
if s == "str":
|
||||
return "std::string"
|
||||
|
||||
# Unknown. Return as is.
|
||||
return s
|
||||
|
||||
class CPP:
|
||||
def __init__(self, fn):
|
||||
self.fn = fn
|
||||
self.isIf = False
|
||||
self.isIfNot = False
|
||||
self.varNames = {}
|
||||
|
||||
def translate(self):
|
||||
returnType = translateType(self.fn.returnType)
|
||||
|
||||
# Parameters.
|
||||
params = []
|
||||
for i in range(0, len(self.fn.parameters)):
|
||||
p = translateParameter(self.fn.parameters[i])
|
||||
# Make Context passed by reference.
|
||||
#if "Context" in p:
|
||||
# p = p.replace("Context", "Context&")
|
||||
params.append(p)
|
||||
strparams = "\n".join(params)
|
||||
if (len(strparams) > 0):
|
||||
strparams += "\n"
|
||||
|
||||
# Statements.
|
||||
sts = []
|
||||
for i in range(0, len(self.fn.statements)):
|
||||
s = translateStatement(self.fn.statements[i], self)
|
||||
s = replaceAnd(s)
|
||||
s = replaceOr(s)
|
||||
s = replaceAppend(s)
|
||||
# Replace len twice to account for double invocation.
|
||||
s = replaceLen(s)
|
||||
s = replaceLen(s)
|
||||
s = replaceTrue(s)
|
||||
sts.append(s)
|
||||
strstatements = "\n".join(sts)
|
||||
|
||||
return f"""{returnType} {self.fn.name}(
|
||||
{strparams}) {{
|
||||
{strstatements}
|
||||
}}
|
||||
"""
|
||||
|
||||
76
v5/tPythonC++/Function.py
Normal file
76
v5/tPythonC++/Function.py
Normal file
@@ -0,0 +1,76 @@
|
||||
class Function:
|
||||
def __init__(self):
|
||||
self.isBody = False
|
||||
self.isComplete = False
|
||||
self.isSignature = False
|
||||
self.name = None
|
||||
self.parameters = []
|
||||
self.returnType = None
|
||||
self.statements = []
|
||||
|
||||
def parseLine(self, ln):
|
||||
parts = ln.split(" ")
|
||||
count = len(parts)
|
||||
lastPart = parts[count - 1]
|
||||
|
||||
# Complete.
|
||||
if (
|
||||
self.isBody and
|
||||
ln.startswith("#}")
|
||||
):
|
||||
self.isComplete = True
|
||||
|
||||
# Statements.
|
||||
if (
|
||||
self.isBody and
|
||||
not ln.startswith("#}")
|
||||
):
|
||||
self.statements.append(ln)
|
||||
|
||||
# Parameters.
|
||||
if (
|
||||
self.isSignature and
|
||||
not ln.endswith(":")
|
||||
):
|
||||
p = ln
|
||||
# Remove comma if present.
|
||||
if p.endswith(","):
|
||||
p = p[:-1]
|
||||
self.parameters.append(p)
|
||||
|
||||
# Beginning of signature.
|
||||
if (
|
||||
self.returnType is None and
|
||||
self.name is None
|
||||
and lastPart.endswith("(")
|
||||
):
|
||||
self.isSignature = True
|
||||
|
||||
# Return type.
|
||||
if (
|
||||
self.isSignature and
|
||||
ln.startswith(") -> ") and
|
||||
ln.endswith(":")
|
||||
):
|
||||
self.returnType = ln[len(") -> "):-len(":")]
|
||||
|
||||
# End of parameters/signature.
|
||||
if (
|
||||
self.isSignature and
|
||||
ln.startswith(") -> ") and
|
||||
ln.endswith(":")
|
||||
):
|
||||
self.isSignature = False
|
||||
self.isBody = True
|
||||
|
||||
# Name.
|
||||
if (
|
||||
self.isSignature and
|
||||
lastPart.endswith("(")
|
||||
):
|
||||
self.name = lastPart[:-1]
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
def __str__(self):
|
||||
return f"Function(name/returnT/parameters/statements: '{self.name}'/'{self.returnType}'/'{self.parameters}'/'{self.statements}')"
|
||||
37
v5/tPythonC++/process.py
Executable file
37
v5/tPythonC++/process.py
Executable file
@@ -0,0 +1,37 @@
|
||||
from CPP import *
|
||||
from Function import *
|
||||
|
||||
def process(FILE_IN):
|
||||
# Read file.
|
||||
lines_in = []
|
||||
with open(FILE_IN) as file:
|
||||
for line in file:
|
||||
lines_in.append(line.rstrip())
|
||||
|
||||
f = Function()
|
||||
out = includes()
|
||||
|
||||
# Parse.
|
||||
for ln in lines_in:
|
||||
ln = ln.rstrip()
|
||||
|
||||
# Empty line.
|
||||
if ln == "":
|
||||
out += "\n"
|
||||
# Comment.
|
||||
elif (
|
||||
ln.startswith("#") and
|
||||
not f.isBody
|
||||
):
|
||||
out += replaceComment(ln) + "\n"
|
||||
# Function.
|
||||
else:
|
||||
f.parseLine(ln)
|
||||
|
||||
if f.isComplete:
|
||||
cpp = CPP(f)
|
||||
out += cpp.translate()
|
||||
# Create new function instance.
|
||||
f = Function()
|
||||
|
||||
return out
|
||||
25
v5/tPythonC++/translate
Executable file
25
v5/tPythonC++/translate
Executable file
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import sys
|
||||
from process import *
|
||||
|
||||
DIR = os.path.dirname(os.path.realpath(sys.argv[0]))
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: /path/to/translate [OPTIONS] PYTHON_FILE")
|
||||
sys.exit(1)
|
||||
|
||||
FILE_IN = sys.argv[-1]
|
||||
|
||||
# Parse options
|
||||
# TODO Use options
|
||||
OPT_HEADER = "--header" in sys.argv
|
||||
OPT_INCLUDES = None
|
||||
OPT_PREFIX_INCLUDES = "--includes="
|
||||
for arg in sys.argv:
|
||||
if arg.startswith(OPT_PREFIX_INCLUDES):
|
||||
OPT_INCLUDES = arg[len(OPT_PREFIX_INCLUDES):]
|
||||
|
||||
# Translate file.
|
||||
out = process(FILE_IN)#, OPT_HEADER, OPT_INCLUDES)
|
||||
print(out)
|
||||
12
v5/translate-py-cxx
Executable file
12
v5/translate-py-cxx
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
|
||||
DIR=$(cd "$(dirname "$0")" ; pwd -P)
|
||||
TR=$DIR/tPythonC++/translate
|
||||
|
||||
$TR $DIR/memory.py > $DIR/memory.cpp
|
||||
$TR $DIR/memory_test.py > $DIR/memory_test.cpp
|
||||
$TR $DIR/cli.py > $DIR/cli.cpp
|
||||
$TR $DIR/cli_test.py > $DIR/cli_test.cpp
|
||||
$TR $DIR/ctx_test.py > $DIR/ctx_test.cpp
|
||||
$TR $DIR/llm_test.py > $DIR/llm_test.cpp
|
||||
$DIR/cxx-headers
|
||||
Reference in New Issue
Block a user