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} }} """