From 3a24d68174d3edbfb991bef8ae4f204088b6e09d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B8=D1=85=D0=B0=D0=B8=D0=BB=20=D0=9A=D0=B0=D0=BF?= =?UTF-8?q?=D0=B5=D0=BB=D1=8C=D0=BA=D0=BE?= Date: Wed, 24 Apr 2024 22:24:37 +0300 Subject: [PATCH] d --- v3/gen-C++ | 1 + v3/main.cpp | 10 ++ v3/memory.cpp | 120 ++++++++++++++++++++++ v3/memory_Context.cpp | 7 ++ v3/memory_test.cpp | 209 ++++++++++++++++++++++++++++++++++++++ v3/tPythonC++/CPP.py | 153 ++++++++++++++++++++++++++++ v3/tPythonC++/Function.py | 76 ++++++++++++++ v3/tPythonC++/process.py | 37 +++++++ v3/tPythonC++/translate | 17 ++++ v3/translate-py-cxx | 7 ++ 10 files changed, 637 insertions(+) create mode 100755 v3/gen-C++ create mode 100644 v3/main.cpp create mode 100644 v3/memory.cpp create mode 100644 v3/memory_Context.cpp create mode 100644 v3/memory_test.cpp create mode 100644 v3/tPythonC++/CPP.py create mode 100644 v3/tPythonC++/Function.py create mode 100755 v3/tPythonC++/process.py create mode 100755 v3/tPythonC++/translate create mode 100755 v3/translate-py-cxx diff --git a/v3/gen-C++ b/v3/gen-C++ new file mode 100755 index 0000000..cbf52cd --- /dev/null +++ b/v3/gen-C++ @@ -0,0 +1 @@ +c++ -o test_memory_C++ -std=c++11 main.cpp diff --git a/v3/main.cpp b/v3/main.cpp new file mode 100644 index 0000000..0f98d1b --- /dev/null +++ b/v3/main.cpp @@ -0,0 +1,10 @@ +#include +#include +#include + +int main() { + std::cout << + "check" //memory_test_generateConstPlayfield() + << std::endl + ; +} diff --git a/v3/memory.cpp b/v3/memory.cpp new file mode 100644 index 0000000..cff44ad --- /dev/null +++ b/v3/memory.cpp @@ -0,0 +1,120 @@ +#include +#include +#include "entities.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 = []; + 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; +} + diff --git a/v3/memory_Context.cpp b/v3/memory_Context.cpp new file mode 100644 index 0000000..623a573 --- /dev/null +++ b/v3/memory_Context.cpp @@ -0,0 +1,7 @@ +#include +#include +#include "entities.h" + + + + diff --git a/v3/memory_test.cpp b/v3/memory_test.cpp new file mode 100644 index 0000000..c307f30 --- /dev/null +++ b/v3/memory_test.cpp @@ -0,0 +1,209 @@ +#include +#include +#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"; +} + diff --git a/v3/tPythonC++/CPP.py b/v3/tPythonC++/CPP.py new file mode 100644 index 0000000..4d4ab65 --- /dev/null +++ b/v3/tPythonC++/CPP.py @@ -0,0 +1,153 @@ +from Function import * + +def includes(): + return """#include +#include +#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 + 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} +}} +""" + diff --git a/v3/tPythonC++/Function.py b/v3/tPythonC++/Function.py new file mode 100644 index 0000000..2e0bd80 --- /dev/null +++ b/v3/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/v3/tPythonC++/process.py b/v3/tPythonC++/process.py new file mode 100755 index 0000000..b6779ae --- /dev/null +++ b/v3/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/v3/tPythonC++/translate b/v3/tPythonC++/translate new file mode 100755 index 0000000..525e884 --- /dev/null +++ b/v3/tPythonC++/translate @@ -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) diff --git a/v3/translate-py-cxx b/v3/translate-py-cxx new file mode 100755 index 0000000..01901fc --- /dev/null +++ b/v3/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