diff --git a/v4/cpp.includes b/v4/cpp.includes new file mode 100644 index 0000000..f055234 --- /dev/null +++ b/v4/cpp.includes @@ -0,0 +1,5 @@ +#include +#include +#include +#include "memory.h" +#include "memory_Context.h" diff --git a/v4/gen-C++ b/v4/gen-C++ new file mode 100755 index 0000000..d676c37 --- /dev/null +++ b/v4/gen-C++ @@ -0,0 +1 @@ +c++ -o test_memory_C++ -std=c++11 -I. memory.cpp memory_Context.cpp memory_test.cpp main.cpp diff --git a/v4/gen-Python b/v4/gen-Python new file mode 100755 index 0000000..44f45f4 --- /dev/null +++ b/v4/gen-Python @@ -0,0 +1,2 @@ +echo "python3 main.py" > test_memory_Python +chmod +x test_memory_Python diff --git a/v4/llm.py b/v4/llm.py new file mode 100644 index 0000000..ab3067e --- /dev/null +++ b/v4/llm.py @@ -0,0 +1,10 @@ +import copy + +# Make deep copies of arguments to mimic behaviour of strongly typed languages. +# 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 diff --git a/v4/main.cpp b/v4/main.cpp new file mode 100644 index 0000000..561a3f6 --- /dev/null +++ b/v4/main.cpp @@ -0,0 +1,29 @@ +#include +#include +#include +#include "memory_test.h" +#include "memory_Context.h" + +extern memory_Context memory_createContext(); + +int main() { + memory_createContext(); + std::cout + << memory_test_generateConstPlayfield() + << std::endl + << memory_test_selectItem_1x() + << std::endl + << memory_test_selectItem_2x() + << std::endl + << memory_test_selectItem_3x() + << std::endl + << memory_test_shouldDeselectMismatchedItems() + << std::endl + << memory_test_shouldDeselectMismatchedItems_itemTwice() + << std::endl + << memory_test_shouldDetectVictory() + << std::endl + << memory_test_shouldHideMatchingItems() + << std::endl + ; +} diff --git a/v4/main.py b/v4/main.py new file mode 100644 index 0000000..2892f9e --- /dev/null +++ b/v4/main.py @@ -0,0 +1,10 @@ +from memory_test import * + +print(memory_test_generateConstPlayfield()) +print(memory_test_selectItem_1x()) +print(memory_test_selectItem_2x()) +print(memory_test_selectItem_3x()) +print(memory_test_shouldDeselectMismatchedItems()) +print(memory_test_shouldDeselectMismatchedItems_itemTwice()) +print(memory_test_shouldDetectVictory()) +print(memory_test_shouldHideMatchingItems()) diff --git a/v4/memory.cpp b/v4/memory.cpp new file mode 100644 index 0000000..0ad95fd --- /dev/null +++ b/v4/memory.cpp @@ -0,0 +1,123 @@ +OPT_HEADER/OPT_INCLUDES: 'None'/'None' +#include +#include +#include +#include "memory.h" +#include "memory_Context.h" + +//////////////// +// Client initiated input +//////////////// + +// Generate constant playfield +memory_Context memory_generateConstPlayfield( + memory_Context 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; +} + +// Select item +memory_Context memory_selectItem( + memory_Context c +) { + if ( + c.selectedItems.size() == 2 + ) { + c.selectedItems.clear(); + } + c.selectedItems.push_back(c.selectedId); + c.recentField = "selectedItems"; + return c; +} + +//////////////// +// System initiated reaction +//////////////// + +// Deselect 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_shouldDeselectMismatchedItems( + 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_shouldDetectVictory( + 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; +} + +// Hide matching selected items +// +// Conditions: +// 1. Two items are selected and they are of the same group +memory_Context memory_shouldHideMatchingItems( + 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; +} + diff --git a/v4/memory.h b/v4/memory.h new file mode 100644 index 0000000..c234c97 --- /dev/null +++ b/v4/memory.h @@ -0,0 +1,12 @@ +#include "memory_Context.h" + +#ifndef memory_HEADER +#define memory_HEADER + +memory_Context memory_generateConstPlayfield(memory_Context); +memory_Context memory_selectItem(memory_Context); +memory_Context memory_shouldDeselectMismatchedItems(memory_Context); +memory_Context memory_shouldDetectVictory(memory_Context); +memory_Context memory_shouldHideMatchingItems(memory_Context); + +#endif // memory_HEADER diff --git a/v4/memory.py b/v4/memory.py new file mode 100644 index 0000000..1673e06 --- /dev/null +++ b/v4/memory.py @@ -0,0 +1,123 @@ +from memory_Context import * +from llm import * + +######## +# Client initiated input +######## + +# Generate constant playfield +@llm_by_value +def memory_generateConstPlayfield( + c: memory_Context +) -> memory_Context: + 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 +#} + +# Select item +@llm_by_value +def memory_selectItem( + c: memory_Context +) -> memory_Context: + if ( + len(c.selectedItems) == 2 + ): + c.selectedItems.clear() + #} + c.selectedItems.append(c.selectedId) + c.recentField = "selectedItems" + return c +#} + +######## +# System initiated reaction +######## + +# Deselect 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_shouldDeselectMismatchedItems( + 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_shouldDetectVictory( + 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 +#} + +# Hide matching selected items +# +# Conditions: +# 1. Two items are selected and they are of the same group +@llm_by_value +def memory_shouldHideMatchingItems( + 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 +#} diff --git a/v4/memory_Context.cpp b/v4/memory_Context.cpp new file mode 100644 index 0000000..d21fb82 --- /dev/null +++ b/v4/memory_Context.cpp @@ -0,0 +1,5 @@ +#include "memory_Context.h" + +memory_Context memory_createContext() { + return memory_Context(); +} diff --git a/v4/memory_Context.h b/v4/memory_Context.h new file mode 100644 index 0000000..46595ba --- /dev/null +++ b/v4/memory_Context.h @@ -0,0 +1,21 @@ +#include +#include +#include + +#ifndef memory_Context_HEADER +#define memory_Context_HEADER + +struct memory_Context { + std::vector hiddenItems; + std::vector mismatchedItems; + std::map playfieldItems; + int playfieldSize = 0; + std::string recentField = "none"; + int selectedId = -1; + std::vector selectedItems; + bool victory = false; +}; + +memory_Context memory_createContext(); + +#endif // memory_Context_HEADER diff --git a/v4/memory_Context.py b/v4/memory_Context.py new file mode 100644 index 0000000..39af108 --- /dev/null +++ b/v4/memory_Context.py @@ -0,0 +1,19 @@ +class memory_Context: + def __init__(self): + self.hiddenItems = [] + self.mismatchedItems = [] + self.playfieldItems = {} + self.playfieldSize = 0 + self.recentField = "none" + self.selectedId = -1 + self.selectedItems = [] + self.victory = False + + 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/v4/memory_test.cpp b/v4/memory_test.cpp new file mode 100644 index 0000000..09f0b18 --- /dev/null +++ b/v4/memory_test.cpp @@ -0,0 +1,212 @@ +OPT_HEADER/OPT_INCLUDES: 'None'/'None' +#include +#include +#include +#include "memory.h" +#include "memory_Context.h" + +std::string memory_test_generateConstPlayfield( +) { + auto c = memory_createContext(); + c.playfieldSize = 2; + 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_selectItem_1x( +) { + auto c = memory_createContext(); + c.playfieldSize = 2; + c = memory_generateConstPlayfield(c); + // Select the first item. + c.selectedId = 0; + 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 = memory_generateConstPlayfield(c); + // Select the first two items. + c.selectedId = 0; + c = memory_selectItem(c); + c.selectedId = 1; + 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 = memory_generateConstPlayfield(c); + // Select three items. + c.selectedId = 0; + c = memory_selectItem(c); + c.selectedId = 1; + c = memory_selectItem(c); + c.selectedId = 2; + 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"; +} + + + + +std::string memory_test_shouldDeselectMismatchedItems( +) { + auto c = memory_createContext(); + c.playfieldSize = 2; + c = memory_generateConstPlayfield(c); + // Select two items of different groups. + c.selectedId = 0; + c = memory_selectItem(c); + c.selectedId = 2; + c = memory_selectItem(c); + // Detect mismatching. + c = memory_shouldDeselectMismatchedItems(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_shouldDeselectMismatchedItems"; + } + return "ERR: memory_shouldDeselectMismatchedItems"; +} + + + + +std::string memory_test_shouldDeselectMismatchedItems_itemTwice( +) { + auto c = memory_createContext(); + c.playfieldSize = 2; + c = memory_generateConstPlayfield(c); + // Select the same item twice. + c.selectedId = 0; + c = memory_selectItem(c); + c.selectedId = 0; + c = memory_selectItem(c); + // Detect mismatching. + c = memory_shouldDeselectMismatchedItems(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_shouldDeselectMismatchedItems_itemTwice"; + } + return "ERR: memory_shouldDeselectMismatchedItems_itemTwice"; +} + + + + + + + +std::string memory_test_shouldDetectVictory( +) { + auto c = memory_createContext(); + c.playfieldSize = 2; + c = memory_generateConstPlayfield(c); + // Select the first two items of the same group. + c.selectedId = 0; + c = memory_selectItem(c); + c.selectedId = 1; + c = memory_selectItem(c); + // Hide the first pair. + c = memory_shouldHideMatchingItems(c); + // Select the last two items of the same group. + c.selectedId = 2; + c = memory_selectItem(c); + c.selectedId = 3; + c = memory_selectItem(c); + // Hide the second pair. + c = memory_shouldHideMatchingItems(c); + // Detect victory. + c = memory_shouldDetectVictory(c); + // See if victory has been detected. + if ( + c.recentField == "victory" && + c.victory == true + ) { + return "OK: memory_shouldDetectVictory"; + } + return "ERR: memory_shouldDetectVictory"; +} + + + + +std::string memory_test_shouldHideMatchingItems( +) { + auto c = memory_createContext(); + c.playfieldSize = 2; + c = memory_generateConstPlayfield(c); + // Select two items of the same group. + c.selectedId = 0; + c = memory_selectItem(c); + c.selectedId = 1; + c = memory_selectItem(c); + // Hide matching items. + c = memory_shouldHideMatchingItems(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_shouldHideMatchingItems"; + } + return "ERR: memory_shouldHideMatchingItems"; +} + diff --git a/v4/memory_test.h b/v4/memory_test.h new file mode 100644 index 0000000..313d8c5 --- /dev/null +++ b/v4/memory_test.h @@ -0,0 +1,15 @@ +#include + +#ifndef memory_test_HEADER +#define memory_test_HEADER + +std::string memory_test_generateConstPlayfield(); +std::string memory_test_selectItem_1x(); +std::string memory_test_selectItem_2x(); +std::string memory_test_selectItem_3x(); +std::string memory_test_shouldDeselectMismatchedItems(); +std::string memory_test_shouldDeselectMismatchedItems_itemTwice(); +std::string memory_test_shouldDetectVictory(); +std::string memory_test_shouldHideMatchingItems(); + +#endif // memory_test_HEADER diff --git a/v4/memory_test.py b/v4/memory_test.py new file mode 100644 index 0000000..8557dfa --- /dev/null +++ b/v4/memory_test.py @@ -0,0 +1,207 @@ +from memory import * +from memory_Context import * + +def memory_test_generateConstPlayfield( +) -> str: + c = memory_createContext() + c.playfieldSize = 2 + 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_selectItem_1x( +) -> str: + c = memory_createContext() + c.playfieldSize = 2 + c = memory_generateConstPlayfield(c) + + # Select the first item. + c.selectedId = 0 + 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 = memory_generateConstPlayfield(c) + + # Select the first two items. + c.selectedId = 0 + c = memory_selectItem(c) + c.selectedId = 1 + 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 = memory_generateConstPlayfield(c) + + # Select three items. + c.selectedId = 0 + c = memory_selectItem(c) + c.selectedId = 1 + c = memory_selectItem(c) + c.selectedId = 2 + 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" +#} + +def memory_test_shouldDeselectMismatchedItems( +) -> str: + c = memory_createContext() + c.playfieldSize = 2 + c = memory_generateConstPlayfield(c) + + # Select two items of different groups. + c.selectedId = 0 + c = memory_selectItem(c) + c.selectedId = 2 + c = memory_selectItem(c) + + # Detect mismatching. + c = memory_shouldDeselectMismatchedItems(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_shouldDeselectMismatchedItems" + #} + return "ERR: memory_shouldDeselectMismatchedItems" +#} + +def memory_test_shouldDeselectMismatchedItems_itemTwice( +) -> str: + c = memory_createContext() + c.playfieldSize = 2 + c = memory_generateConstPlayfield(c) + + # Select the same item twice. + c.selectedId = 0 + c = memory_selectItem(c) + c.selectedId = 0 + c = memory_selectItem(c) + + # Detect mismatching. + c = memory_shouldDeselectMismatchedItems(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_shouldDeselectMismatchedItems_itemTwice" + #} + return "ERR: memory_shouldDeselectMismatchedItems_itemTwice" +#} + +def memory_test_shouldDetectVictory( +) -> str: + c = memory_createContext() + c.playfieldSize = 2 + c = memory_generateConstPlayfield(c) + + # Select the first two items of the same group. + c.selectedId = 0 + c = memory_selectItem(c) + c.selectedId = 1 + c = memory_selectItem(c) + + # Hide the first pair. + c = memory_shouldHideMatchingItems(c) + + # Select the last two items of the same group. + c.selectedId = 2 + c = memory_selectItem(c) + c.selectedId = 3 + c = memory_selectItem(c) + + # Hide the second pair. + c = memory_shouldHideMatchingItems(c) + + # Detect victory. + c = memory_shouldDetectVictory(c) + + # See if victory has been detected. + if ( + c.recentField == "victory" and + c.victory == True + ): + return "OK: memory_shouldDetectVictory" + #} + return "ERR: memory_shouldDetectVictory" +#} + +def memory_test_shouldHideMatchingItems( +) -> str: + c = memory_createContext() + c.playfieldSize = 2 + c = memory_generateConstPlayfield(c) + + # Select two items of the same group. + c.selectedId = 0 + c = memory_selectItem(c) + c.selectedId = 1 + c = memory_selectItem(c) + + # Hide matching items. + c = memory_shouldHideMatchingItems(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_shouldHideMatchingItems" + #} + return "ERR: memory_shouldHideMatchingItems" +#} diff --git a/v4/tPythonC++/CPP.py b/v4/tPythonC++/CPP.py new file mode 100644 index 0000000..97c551c --- /dev/null +++ b/v4/tPythonC++/CPP.py @@ -0,0 +1,186 @@ +from Function import * + +def includes(): + return """#include +#include +#include +#include "memory.h" +#include "memory_Context.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 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("# ") + 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 + 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 = 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/v4/tPythonC++/Function.py b/v4/tPythonC++/Function.py new file mode 100644 index 0000000..2e0bd80 --- /dev/null +++ b/v4/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/v4/tPythonC++/process.py b/v4/tPythonC++/process.py new file mode 100755 index 0000000..b6779ae --- /dev/null +++ b/v4/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/v4/tPythonC++/translate b/v4/tPythonC++/translate new file mode 100755 index 0000000..d202e44 --- /dev/null +++ b/v4/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/v4/translate-py-cxx b/v4/translate-py-cxx new file mode 100755 index 0000000..01901fc --- /dev/null +++ b/v4/translate-py-cxx @@ -0,0 +1,7 @@ +#!/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