@@ -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 |