@@ -0,0 +1,5 @@ | |||
#include <map> | |||
#include <string> | |||
#include <vector> | |||
#include "memory.h" | |||
#include "memory_Context.h" |
@@ -0,0 +1 @@ | |||
c++ -o test_memory_C++ -std=c++11 -I. memory.cpp memory_Context.cpp memory_test.cpp main.cpp |
@@ -0,0 +1,2 @@ | |||
echo "python3 main.py" > test_memory_Python | |||
chmod +x test_memory_Python |
@@ -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 |
@@ -0,0 +1,29 @@ | |||
#include <iostream> | |||
#include <string> | |||
#include <vector> | |||
#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 | |||
; | |||
} |
@@ -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()) |
@@ -0,0 +1,123 @@ | |||
OPT_HEADER/OPT_INCLUDES: 'None'/'None' | |||
#include <map> | |||
#include <string> | |||
#include <vector> | |||
#include "memory.h" | |||
#include "memory_Context.h" | |||
//////////////// | |||
// Client initiated input | |||
//////////////// | |||
// Generate constant playfield | |||
memory_Context memory_generateConstPlayfield( | |||
memory_Context c | |||
) { | |||
std::map<int, int> idGroups = { }; | |||
auto id = 0; | |||
for (auto gid = 0; gid < c.playfieldSize; ++gid) { | |||
idGroups[id] = gid; | |||
id += 1; | |||
idGroups[id] = gid; | |||
id += 1; | |||
} | |||
c.playfieldItems = idGroups; | |||
c.recentField = "playfieldItems"; | |||
return c; | |||
} | |||
// 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; | |||
} | |||
@@ -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 |
@@ -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 | |||
#} |
@@ -0,0 +1,5 @@ | |||
#include "memory_Context.h" | |||
memory_Context memory_createContext() { | |||
return memory_Context(); | |||
} |
@@ -0,0 +1,21 @@ | |||
#include <map> | |||
#include <string> | |||
#include <vector> | |||
#ifndef memory_Context_HEADER | |||
#define memory_Context_HEADER | |||
struct memory_Context { | |||
std::vector<int> hiddenItems; | |||
std::vector<int> mismatchedItems; | |||
std::map<int, int> playfieldItems; | |||
int playfieldSize = 0; | |||
std::string recentField = "none"; | |||
int selectedId = -1; | |||
std::vector<int> selectedItems; | |||
bool victory = false; | |||
}; | |||
memory_Context memory_createContext(); | |||
#endif // memory_Context_HEADER |
@@ -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() |
@@ -0,0 +1,212 @@ | |||
OPT_HEADER/OPT_INCLUDES: 'None'/'None' | |||
#include <map> | |||
#include <string> | |||
#include <vector> | |||
#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"; | |||
} | |||
@@ -0,0 +1,15 @@ | |||
#include <string> | |||
#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 |
@@ -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" | |||
#} |
@@ -0,0 +1,186 @@ | |||
from Function import * | |||
def includes(): | |||
return """#include <map> | |||
#include <string> | |||
#include <vector> | |||
#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<X, Y> | |||
if s.startswith("dict["): | |||
kv = s[len("dict["):-len("]")] | |||
parts = kv.split(", ") | |||
return f"std::map<{parts[0]}, {parts[1]}>" | |||
# str -> std::string | |||
if s == "str": | |||
return "std::string" | |||
# Unknown. Return as is. | |||
return s | |||
class CPP: | |||
def __init__(self, fn): | |||
self.fn = fn | |||
self.isIf = False | |||
self.isIfNot = False | |||
self.varNames = {} | |||
def translate(self): | |||
returnType = translateType(self.fn.returnType) | |||
# Parameters. | |||
params = [] | |||
for i in range(0, len(self.fn.parameters)): | |||
p = translateParameter(self.fn.parameters[i]) | |||
# Make Context passed by reference. | |||
#if "Context" in p: | |||
# p = p.replace("Context", "Context&") | |||
params.append(p) | |||
strparams = "\n".join(params) | |||
if (len(strparams) > 0): | |||
strparams += "\n" | |||
# Statements. | |||
sts = [] | |||
for i in range(0, len(self.fn.statements)): | |||
s = translateStatement(self.fn.statements[i], self) | |||
s = replaceAnd(s) | |||
s = 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} | |||
}} | |||
""" | |||
@@ -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}')" |
@@ -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 |
@@ -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) |
@@ -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 |