diff --git a/v4/ctx_test.cpp b/v4/_old/ctx_test.cpp similarity index 100% rename from v4/ctx_test.cpp rename to v4/_old/ctx_test.cpp diff --git a/v4/ctx_test.py b/v4/_old/ctx_test.py similarity index 100% rename from v4/ctx_test.py rename to v4/_old/ctx_test.py diff --git a/v4/ctx_test_Python.py b/v4/_old/ctx_test_Python.py similarity index 100% rename from v4/ctx_test_Python.py rename to v4/_old/ctx_test_Python.py diff --git a/v4/main.py b/v4/main.py index 4409ca9..e3fdb56 100644 --- a/v4/main.py +++ b/v4/main.py @@ -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()) diff --git a/v5/_old/ctx_test.cpp b/v5/_old/ctx_test.cpp new file mode 100644 index 0000000..fc38a80 --- /dev/null +++ b/v5/_old/ctx_test.cpp @@ -0,0 +1,86 @@ + +#include +#include +#include +#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; +} + diff --git a/v5/_old/ctx_test.py b/v5/_old/ctx_test.py new file mode 100644 index 0000000..f20836d --- /dev/null +++ b/v5/_old/ctx_test.py @@ -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 +#} diff --git a/v5/_old/ctx_test_Python.py b/v5/_old/ctx_test_Python.py new file mode 100644 index 0000000..ac0ec6f --- /dev/null +++ b/v5/_old/ctx_test_Python.py @@ -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 + #} +#} diff --git a/v5/any.h b/v5/any.h new file mode 100644 index 0000000..0e6f6fb --- /dev/null +++ b/v5/any.h @@ -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ê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 +#include +#include + + +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(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::type, any>::value>::type> + any(ValueType&& value) + { + static_assert(std::is_copy_constructible::type>::value, + "T shall satisfy the CopyConstructible requirements."); + this->construct(std::forward(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(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::type, any>::value>::type> + any& operator=(ValueType&& value) + { + static_assert(std::is_copy_constructible::type>::value, "T shall satisfy the CopyConstructible requirements."); + any(std::forward(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::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 + struct vtable_dynamic + { + static const std::type_info& type() noexcept + { + return typeid(T); + } + + + static void destroy(storage_union& storage) noexcept + { + delete reinterpret_cast(storage.dynamic); + } + + + static void copy(const storage_union& src, storage_union& dest) + { + dest.dynamic = new T(*reinterpret_cast(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 + struct vtable_stack + { + static const std::type_info& type() noexcept + { + return typeid(T); + } + + + static void destroy(storage_union& storage) noexcept + { + reinterpret_cast(&storage.stack)->~T(); + } + + + static void copy(const storage_union& src, storage_union& dest) + { + new (&dest.stack) T(reinterpret_cast(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(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 + struct requires_allocation : + std::integral_constant::value // N4562 6.3/3 [any.class] + && sizeof(T) <= sizeof(storage_union::stack) + && std::alignment_of::value <= std::alignment_of::value)> + { }; + + + /** + * Returns the pointer to the vtable of the type T. + */ + template + static vtable_type* vtable_for_type() + { + using VTableType = typename std::conditional::value, vtable_dynamic, vtable_stack>::type; + static vtable_type table = { VTableType::type, VTableType::destroy, VTableType::copy, VTableType::move, VTableType::swap }; + return &table; + } + + +protected: + template + friend const T* any_cast(const any* operand) noexcept; + + + template + 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 + const T* cast() const noexcept + { + return requires_allocation::type>::value ? reinterpret_cast(storage.dynamic) : reinterpret_cast(&storage.stack); + } + + + /** + * Casts (with no type_info checks) the storage pointer as T*. + */ + template + T* cast() noexcept + { + return requires_allocation::type>::value ? reinterpret_cast(storage.dynamic) : reinterpret_cast(&storage.stack); + } + + +private: + storage_union storage; // On offset(0) so no padding for align + + vtable_type* vtable; + + + template + typename std::enable_if::value>::type do_construct(ValueType&& value) + { + storage.dynamic = new T(std::forward(value)); + } + + + template + typename std::enable_if::value>::type do_construct(ValueType&& value) + { + new (&storage.stack) T(std::forward(value)); + } + + + /** + * Chooses between stack and dynamic allocation for the type decay_t, + * assigns the correct vtable, and constructs the object on our storage. + */ + template + void construct(ValueType&& value) + { + using T = typename std::decay::type; + + this->vtable = vtable_for_type(); + + do_construct(std::forward(value)); + } +}; + + +namespace detail +{ + template + inline ValueType any_cast_move_if_true(typename std::remove_reference::type* p, std::true_type) + { + return std::move(*p); + } + + + template + inline ValueType any_cast_move_if_true(typename std::remove_reference::type* p, std::false_type) + { + return *p; + } +} + + +/** + * Performs *any_cast>>(&operand), or throws bad_any_cast on failure. + */ +template +inline ValueType any_cast(const any& operand) +{ + auto p = any_cast::type>::type>(&operand); + if(p == nullptr) throw bad_any_cast(); + return *p; +} + + +/** + * Performs *any_cast>(&operand), or throws bad_any_cast on failure. + */ +template +inline ValueType any_cast(any& operand) +{ + auto p = any_cast::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>(&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>(&operand)), otherwise + * *any_cast>(&operand). + * Throws bad_any_cast on failure. + * + * [1] https://cplusplus.github.io/LWG/lwg-active.html#2509 + */ +template +inline ValueType any_cast(any&& operand) +{ +#ifdef ANY_IMPL_ANY_CAST_MOVEABLE + using can_move = std::integral_constant::value && !std::is_lvalue_reference::value>; +#else + using can_move = std::false_type; +#endif + + auto p = any_cast::type>(&operand); + if(p == nullptr) throw bad_any_cast(); + return detail::any_cast_move_if_true(p, can_move()); +} + + +/** + * If operand != nullptr && operand->type() == typeid(ValueType), a pointer to the object + * contained by operand, otherwise nullptr. + */ +template +inline const T* any_cast(const any* operand) noexcept +{ + if(operand == nullptr || !operand->is_typed(typeid(T))) + return nullptr; + else + return operand->cast(); +} + + +/** + * If operand != nullptr && operand->type() == typeid(ValueType), a pointer to the object + * contained by operand, otherwise nullptr. + */ +template +inline T* any_cast(any* operand) noexcept +{ + if(operand == nullptr || !operand->is_typed(typeid(T))) + return nullptr; + else + return operand->cast(); +} + + +inline void swap(any& lhs, any& rhs) noexcept +{ + lhs.swap(rhs); +} + +} + +#endif /* ANY_H */ diff --git a/v5/cli.cpp b/v5/cli.cpp new file mode 100644 index 0000000..0090eef --- /dev/null +++ b/v5/cli.cpp @@ -0,0 +1,220 @@ + +#include +#include +#include +#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 +//////} + diff --git a/v5/cli.py b/v5/cli.py new file mode 100644 index 0000000..1b6637e --- /dev/null +++ b/v5/cli.py @@ -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 +###} diff --git a/v5/cli_test.cpp b/v5/cli_test.cpp new file mode 100644 index 0000000..83c1a18 --- /dev/null +++ b/v5/cli_test.cpp @@ -0,0 +1,309 @@ + +#include +#include +#include +#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" +////} +// + diff --git a/v5/cli_test.py b/v5/cli_test.py new file mode 100644 index 0000000..9aaafdc --- /dev/null +++ b/v5/cli_test.py @@ -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" +##} +# diff --git a/v5/cpp.includes b/v5/cpp.includes new file mode 100644 index 0000000..2765a38 --- /dev/null +++ b/v5/cpp.includes @@ -0,0 +1,6 @@ +#include +#include +#include +#// file unused +#include "memory.h" +#include "memory_Context.h" diff --git a/v5/ctx.h b/v5/ctx.h new file mode 100644 index 0000000..bd9848f --- /dev/null +++ b/v5/ctx.h @@ -0,0 +1,92 @@ +#include +#include +#include + +#ifndef ctx_HEADER +#define ctx_HEADER + +template class ctx_Controller { + std::list > callbacks; + std::list > functions; + std::queue 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 cb) { + callbacks.push_back(cb); + } + + void registerFieldCallback( + const std::string &fieldName, + std::function cb + ) { + auto execCB = [fieldName, cb](T c) { + if (c.recentField == fieldName) { + cb(c); + } + }; + callbacks.push_back(execCB); + } + + void registerFunction(std::function f) { + functions.push_back(f); + } + + void registerFunctions(std::list > funcs) { + for (const auto &f : funcs) { + functions.push_back(f); + } + } + + void reportContext() { + for (const auto &cb : callbacks) { + cb(context); + } + } + + template 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 diff --git a/v5/ctx.py b/v5/ctx.py new file mode 100644 index 0000000..af8f36e --- /dev/null +++ b/v5/ctx.py @@ -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() diff --git a/v5/ctx_test2.cpp b/v5/ctx_test2.cpp new file mode 100644 index 0000000..67cc471 --- /dev/null +++ b/v5/ctx_test2.cpp @@ -0,0 +1,141 @@ +#include +#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 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 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 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 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(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"; +} diff --git a/v5/ctx_test2.h b/v5/ctx_test2.h new file mode 100644 index 0000000..4e372a0 --- /dev/null +++ b/v5/ctx_test2.h @@ -0,0 +1,13 @@ +#include + +#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 diff --git a/v5/ctx_test2.py b/v5/ctx_test2.py new file mode 100644 index 0000000..74720c8 --- /dev/null +++ b/v5/ctx_test2.py @@ -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" +#} diff --git a/v5/cxx-headers b/v5/cxx-headers new file mode 100755 index 0000000..7a69094 --- /dev/null +++ b/v5/cxx-headers @@ -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 diff --git a/v5/cxx-headers.sed b/v5/cxx-headers.sed new file mode 100644 index 0000000..4a02b50 --- /dev/null +++ b/v5/cxx-headers.sed @@ -0,0 +1,15 @@ +# #} -> } +#s|#}|}| + +# # -> // +#s|#|//| + +# dict[X, Y] -> std::map +#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();| + diff --git a/v5/gen-C++ b/v5/gen-C++ new file mode 100755 index 0000000..23c8529 --- /dev/null +++ b/v5/gen-C++ @@ -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 diff --git a/v5/gen-Python b/v5/gen-Python new file mode 100755 index 0000000..44f45f4 --- /dev/null +++ b/v5/gen-Python @@ -0,0 +1,2 @@ +echo "python3 main.py" > test_memory_Python +chmod +x test_memory_Python diff --git a/v5/llm.cpp b/v5/llm.cpp new file mode 100644 index 0000000..808492a --- /dev/null +++ b/v5/llm.cpp @@ -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); +} diff --git a/v5/llm.h b/v5/llm.h new file mode 100644 index 0000000..bd7deab --- /dev/null +++ b/v5/llm.h @@ -0,0 +1,10 @@ +#ifndef llm_HEADER +#define llm_HEADER + +#include + +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 diff --git a/v5/llm.py b/v5/llm.py new file mode 100644 index 0000000..0ca860f --- /dev/null +++ b/v5/llm.py @@ -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) diff --git a/v5/llm_test.cpp b/v5/llm_test.cpp new file mode 100644 index 0000000..5dcc3d3 --- /dev/null +++ b/v5/llm_test.cpp @@ -0,0 +1,39 @@ + +#include +#include +#include +#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"; +} + diff --git a/v5/llm_test.py b/v5/llm_test.py new file mode 100644 index 0000000..17ee0ca --- /dev/null +++ b/v5/llm_test.py @@ -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" +#} diff --git a/v5/llm_test_Python.py b/v5/llm_test_Python.py new file mode 100644 index 0000000..8c0e39c --- /dev/null +++ b/v5/llm_test_Python.py @@ -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" +#} diff --git a/v5/main.cpp b/v5/main.cpp new file mode 100644 index 0000000..7cec81c --- /dev/null +++ b/v5/main.cpp @@ -0,0 +1,119 @@ +#include +#include +#include +#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 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(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); + } +} diff --git a/v5/main.h b/v5/main.h new file mode 100644 index 0000000..3fd1d58 --- /dev/null +++ b/v5/main.h @@ -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 + diff --git a/v5/main.py b/v5/main.py new file mode 100644 index 0000000..e3fdb56 --- /dev/null +++ b/v5/main.py @@ -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) diff --git a/v5/memory.cpp b/v5/memory.cpp new file mode 100644 index 0000000..0448251 --- /dev/null +++ b/v5/memory.cpp @@ -0,0 +1,140 @@ + +#include +#include +#include +#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 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; +} + + diff --git a/v5/memory.py b/v5/memory.py new file mode 100644 index 0000000..e929d44 --- /dev/null +++ b/v5/memory.py @@ -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 +#} + diff --git a/v5/memory_Context.cpp b/v5/memory_Context.cpp new file mode 100644 index 0000000..60a2ed0 --- /dev/null +++ b/v5/memory_Context.cpp @@ -0,0 +1,83 @@ +#include +#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(value); + } else if (fieldName == "exit") { + exit = libany::any_cast(value); + } else if (fieldName == "hiddenItems") { + hiddenItems = libany::any_cast >(value); + } else if (fieldName == "input") { + input = libany::any_cast(value); + } else if (fieldName == "mismatchedItems") { + mismatchedItems = libany::any_cast >(value); + } else if (fieldName == "outputGoOn") { + outputGoOn = libany::any_cast(value); + } else if (fieldName == "outputGreeting") { + outputGreeting = libany::any_cast(value); + } else if (fieldName == "outputHelp") { + outputHelp = libany::any_cast(value); + } else if (fieldName == "outputMatchedItems") { + outputMatchedItems = libany::any_cast(value); + } else if (fieldName == "outputMismatchedItems") { + outputMismatchedItems = libany::any_cast(value); + } else if (fieldName == "outputPromptSelection") { + outputPromptSelection = libany::any_cast(value); + } else if (fieldName == "outputVictory") { + outputVictory = libany::any_cast(value); + } else if (fieldName == "playfieldItems") { + playfieldItems = libany::any_cast >(value); + } else if (fieldName == "playfieldSize") { + playfieldSize = libany::any_cast(value); + } else if (fieldName == "selectedId") { + selectedId = libany::any_cast(value); + } else if (fieldName == "selectedItems") { + selectedItems = libany::any_cast >(value); + } else if (fieldName == "victory") { + victory = libany::any_cast(value); + } +} + +memory_Context memory_createContext() { + return memory_Context(); +} diff --git a/v5/memory_Context.h b/v5/memory_Context.h new file mode 100644 index 0000000..d56910c --- /dev/null +++ b/v5/memory_Context.h @@ -0,0 +1,36 @@ +#include +#include +#include +#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 hiddenItems; + std::string input = ""; + std::vector mismatchedItems; + std::string outputGoOn = ""; + std::string outputGreeting = ""; + std::string outputHelp = ""; + std::string outputMatchedItems = ""; + std::string outputMismatchedItems = ""; + std::string outputPromptSelection = ""; + std::string outputVictory = ""; + std::map playfieldItems; + int playfieldSize = 0; + std::string recentField = "none"; + int selectedId = -1; + std::vector 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 diff --git a/v5/memory_Context.py b/v5/memory_Context.py new file mode 100644 index 0000000..1eeed0d --- /dev/null +++ b/v5/memory_Context.py @@ -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() diff --git a/v5/memory_test.cpp b/v5/memory_test.cpp new file mode 100644 index 0000000..e6d9a99 --- /dev/null +++ b/v5/memory_test.cpp @@ -0,0 +1,238 @@ + +#include +#include +#include +#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"; +} + diff --git a/v5/memory_test.py b/v5/memory_test.py new file mode 100644 index 0000000..faa79ee --- /dev/null +++ b/v5/memory_test.py @@ -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" +#} diff --git a/v5/tPythonC++/CPP.py b/v5/tPythonC++/CPP.py new file mode 100644 index 0000000..944c56e --- /dev/null +++ b/v5/tPythonC++/CPP.py @@ -0,0 +1,195 @@ +from Function import * + +def includes(): + return """ +#include +#include +#include +#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 + 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} +}} +""" + diff --git a/v5/tPythonC++/Function.py b/v5/tPythonC++/Function.py new file mode 100644 index 0000000..2e0bd80 --- /dev/null +++ b/v5/tPythonC++/Function.py @@ -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}')" diff --git a/v5/tPythonC++/process.py b/v5/tPythonC++/process.py new file mode 100755 index 0000000..b6779ae --- /dev/null +++ b/v5/tPythonC++/process.py @@ -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 diff --git a/v5/tPythonC++/translate b/v5/tPythonC++/translate new file mode 100755 index 0000000..0dcc59a --- /dev/null +++ b/v5/tPythonC++/translate @@ -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) diff --git a/v5/translate-py-cxx b/v5/translate-py-cxx new file mode 100755 index 0000000..fa010a3 --- /dev/null +++ b/v5/translate-py-cxx @@ -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