@@ -0,0 +1 @@ | |||||
c++ -o test_memory_C++ -std=c++11 main.cpp |
@@ -0,0 +1,10 @@ | |||||
#include <iostream> | |||||
#include <string> | |||||
#include <vector> | |||||
int main() { | |||||
std::cout << | |||||
"check" //memory_test_generateConstPlayfield() | |||||
<< std::endl | |||||
; | |||||
} |
@@ -0,0 +1,120 @@ | |||||
#include <map> | |||||
#include <string> | |||||
#include "entities.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 = []; | |||||
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 | |||||
// 1. Selected items are of different groups | |||||
memory_Context memory_shouldDeselectMismatchedItems( | |||||
memory_Context& c | |||||
) { | |||||
if not (; | |||||
c.recentField == "selectedItems" &&; | |||||
c.selectedItems.size() == 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 | |||||
memory_Context memory_shouldDetectVictory( | |||||
memory_Context& c | |||||
) { | |||||
if ( | |||||
c.recentField == "hiddenItems" && | |||||
c.hiddenItems.size() == 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 | |||||
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.append(c.selectedItems[0]); | |||||
c.hiddenItems.append(c.selectedItems[1]); | |||||
c.recentField = "hiddenItems"; | |||||
return c; | |||||
c.recentField = None; | |||||
return c; | |||||
} | |||||
@@ -0,0 +1,7 @@ | |||||
#include <map> | |||||
#include <string> | |||||
#include "entities.h" | |||||
@@ -0,0 +1,209 @@ | |||||
#include <map> | |||||
#include <string> | |||||
#include "entities.h" | |||||
std::string memory_test_generateConstPlayfield( | |||||
) { | |||||
auto c = memory_createContext(); | |||||
c.playfieldSize = 2; | |||||
auto 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; | |||||
auto c = memory_generateConstPlayfield(c); | |||||
# Select the first item.; | |||||
c.selectedId = 0; | |||||
auto 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; | |||||
auto c = memory_generateConstPlayfield(c); | |||||
# Select the first two items.; | |||||
c.selectedId = 0; | |||||
auto c = memory_selectItem(c); | |||||
c.selectedId = 1; | |||||
auto 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; | |||||
auto c = memory_generateConstPlayfield(c); | |||||
# Select three items.; | |||||
c.selectedId = 0; | |||||
auto c = memory_selectItem(c); | |||||
c.selectedId = 1; | |||||
auto c = memory_selectItem(c); | |||||
c.selectedId = 2; | |||||
auto 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; | |||||
auto c = memory_generateConstPlayfield(c); | |||||
# Select two items of different groups.; | |||||
c.selectedId = 0; | |||||
auto c = memory_selectItem(c); | |||||
c.selectedId = 2; | |||||
auto c = memory_selectItem(c); | |||||
# Detect mismatching.; | |||||
auto 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; | |||||
auto c = memory_generateConstPlayfield(c); | |||||
# Select the same item twice.; | |||||
c.selectedId = 0; | |||||
auto c = memory_selectItem(c); | |||||
c.selectedId = 0; | |||||
auto c = memory_selectItem(c); | |||||
# Detect mismatching.; | |||||
auto 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; | |||||
auto c = memory_generateConstPlayfield(c); | |||||
# Select the first two items of the same group.; | |||||
c.selectedId = 0; | |||||
auto c = memory_selectItem(c); | |||||
c.selectedId = 1; | |||||
auto c = memory_selectItem(c); | |||||
# Hide the first pair.; | |||||
auto c = memory_shouldHideMatchingItems(c); | |||||
# Select the last two items of the same group.; | |||||
c.selectedId = 2; | |||||
auto c = memory_selectItem(c); | |||||
c.selectedId = 3; | |||||
auto c = memory_selectItem(c); | |||||
# Hide the second pair.; | |||||
auto c = memory_shouldHideMatchingItems(c); | |||||
# Detect victory.; | |||||
auto 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; | |||||
auto c = memory_generateConstPlayfield(c); | |||||
# Select two items of the same group.; | |||||
c.selectedId = 0; | |||||
auto c = memory_selectItem(c); | |||||
c.selectedId = 1; | |||||
auto c = memory_selectItem(c); | |||||
# Hide matching items.; | |||||
auto 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,153 @@ | |||||
from Function import * | |||||
def includes(): | |||||
return """#include <map> | |||||
#include <string> | |||||
#include "entities.h" | |||||
""" | |||||
def replaceAnd(s): | |||||
return s.replace("and", "&&") | |||||
def replaceComment(s): | |||||
return s.replace("#", "//") | |||||
def replaceLen(s): | |||||
posLen = s.find("len(") | |||||
posEnd = s.find(")") | |||||
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 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(", ") | |||||
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 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] | |||||
value = ss[posEqual + len(" = "):] | |||||
return f"{indentation}auto {name} = {value};" | |||||
# Keep "if (" | |||||
if ss == "if (": | |||||
state.isIf = True | |||||
return s | |||||
# ): -> } | |||||
if ss == "):": | |||||
state.isIf = False | |||||
return f"{indentation}) {{" | |||||
ending = ";" | |||||
if state.isIf: | |||||
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 | |||||
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 = replaceLen(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,17 @@ | |||||
#!/usr/bin/env python3 | |||||
import os | |||||
import sys | |||||
from process import * | |||||
DIR = os.path.dirname(os.path.realpath(sys.argv[0])) | |||||
# Demand file as input | |||||
if len(sys.argv) < 2: | |||||
print("Usage: /path/to/translate PYTHON_FILE") | |||||
sys.exit(1) | |||||
FILE_IN = sys.argv[1] | |||||
# Translate file. | |||||
out = process(FILE_IN) | |||||
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 |