comparison Resources/CodeGeneration/stonegentool.py @ 490:6470248790db bgo-commands-codegen

ongoing codegen work
author bgo-osimis
date Mon, 18 Feb 2019 15:38:05 +0100
parents f6b7f113cf27
children 8e7e151ef472
comparison
equal deleted inserted replaced
489:f6b7f113cf27 490:6470248790db
20 """ 20 """
21 1 2 3 4 5 6 7 21 1 2 3 4 5 6 7
22 12345678901234567890123456789012345678901234567890123456789012345678901234567890 22 12345678901234567890123456789012345678901234567890123456789012345678901234567890
23 """ 23 """
24 24
25
26 class GeneratedCode: 25 class GeneratedCode:
27 def __init__(self): 26 def __init__(self):
28 27
29 # file-wide preamble (#include directives, comment...) 28 # file-wide preamble (#include directives, comment...)
30 self.cppPreamble = StringIO() 29 self.cppPreamble = StringIO()
79 fileContent = fp.read() 78 fileContent = fp.read()
80 fileContent = JsonHelpers.removeCommentsFromJsonContent(fileContent) 79 fileContent = JsonHelpers.removeCommentsFromJsonContent(fileContent)
81 return json.loads(fileContent) 80 return json.loads(fileContent)
82 81
83 82
84 def LoadSchema(filePath: str): 83 def LoadSchemaFromJson(filePath: str):
85 return JsonHelpers.loadJsonWithComments(filePath) 84 return JsonHelpers.loadJsonWithComments(filePath)
86
87
88 # class Type:
89 # def __init__(self, canonicalTypeName:str, kind:str):
90 # allowedTypeKinds = ["primitive","enum","struct","collection"]
91 # """dependent type is the list of canonical types this type depends on.
92 # For instance, vector<map<string,int32>> depends on map<string,int32>
93 # that, in turn, depends on string and int32 that, in turn, depend on
94 # nothing"""
95 # self.canonicalTypeName = canonicalTypeName
96 # assert(kind in allowedTypeKinds)
97
98 # def setDependentTypes(self, dependentTypes:List[Type]) -> None:
99 # self.dependentTypes = dependentTypes
100
101 # def getDependentTypes(self) -> List[Type]:
102 # return self.dependentTypes
103
104 85
105 def GetCppTypeNameFromCanonical(canonicalTypeName: str) -> str: 86 def GetCppTypeNameFromCanonical(canonicalTypeName: str) -> str:
106 # C++: prefix map vector and string with std::map, std::vector and 87 # C++: prefix map vector and string with std::map, std::vector and
107 # std::string 88 # std::string
108 # replace int32 by int32_t 89 # replace int32 by int32_t
113 retVal = retVal.replace("vector", "std::vector") 94 retVal = retVal.replace("vector", "std::vector")
114 retVal = retVal.replace("int32", "int32_t") 95 retVal = retVal.replace("int32", "int32_t")
115 retVal = retVal.replace("float32", "float") 96 retVal = retVal.replace("float32", "float")
116 retVal = retVal.replace("float64", "double") 97 retVal = retVal.replace("float64", "double")
117 return retVal 98 return retVal
118
119 99
120 def GetTypeScriptTypeNameFromCanonical(canonicalTypeName: str) -> str: 100 def GetTypeScriptTypeNameFromCanonical(canonicalTypeName: str) -> str:
121 # TS: replace vector with Array and map with Map 101 # TS: replace vector with Array and map with Map
122 # string remains string 102 # string remains string
123 # replace int32 by number 103 # replace int32 by number
130 retVal = retVal.replace("float32", "number") 110 retVal = retVal.replace("float32", "number")
131 retVal = retVal.replace("float64", "number") 111 retVal = retVal.replace("float64", "number")
132 retVal = retVal.replace("bool", "boolean") 112 retVal = retVal.replace("bool", "boolean")
133 return retVal 113 return retVal
134 114
135
136 # class Schema: 115 # class Schema:
137 # def __init__(self, root_prefix : str, defined_types : List[Type]): 116 # def __init__(self, root_prefix : str, defined_types : List[Type]):
138 # self.rootName : str = root_prefix 117 # self.rootName : str = root_prefix
139 # self.definedTypes : str = defined_types 118 # self.definedTypes : str = defined_types
140
141 119
142 def CheckTypeSchema(definedType: Dict) -> None: 120 def CheckTypeSchema(definedType: Dict) -> None:
143 allowedDefinedTypeKinds = ["enum", "struct"] 121 allowedDefinedTypeKinds = ["enum", "struct"]
144 if not "name" in definedType: 122 if not "name" in definedType:
145 raise Exception("type lacks the 'name' key") 123 raise Exception("type lacks the 'name' key")
167 if kind == "struct": 145 if kind == "struct":
168 for field in fields: 146 for field in fields:
169 fieldName = field["name"] 147 fieldName = field["name"]
170 if not "type" in field: 148 if not "type" in field:
171 raise Exception( 149 raise Exception(
172 f"field {fieldName} in type {name} " + "lacks the 'type' key" 150 f"field {fieldName} in type {name} " + "has no 'type' key"
173 ) 151 )
174 152
175 153
176 def CheckSchemaSchema(schema: Dict) -> None: 154 def CheckSchemaSchema(schema: Dict) -> None:
177 if not "root_name" in schema: 155 if not "root_name" in schema:
224 if restOfString == "": 202 if restOfString == "":
225 stillStuffToEat = False 203 stillStuffToEat = False
226 return tokenList 204 return tokenList
227 205
228 206
229 templateRegex = re.compile(r"([a-zA-Z0-9_]*[a-zA-Z0-9_]*)<([a-zA-Z0-9_,:<>]+)>") 207 templateRegex = \
208 re.compile(r"([a-zA-Z0-9_]*[a-zA-Z0-9_]*)<([a-zA-Z0-9_,:<>]+)>")
230 209
231 210
232 def ParseTemplateType(typeName) -> Tuple[bool, str, List[str]]: 211 def ParseTemplateType(typeName) -> Tuple[bool, str, List[str]]:
233 """ If the type is a template like "SOMETHING<SOME<THING,EL<SE>>>", then 212 """ If the type is a template like "SOMETHING<SOME<THING,EL<SE>>>", then
234 it returns (true,"SOMETHING","SOME<THING,EL<SE>>") 213 it returns (true,"SOMETHING","SOME<THING,EL<SE>>")
247 # we need to split with the commas that are outside of the 226 # we need to split with the commas that are outside of the
248 # defined types. Simply splitting at commas won't work 227 # defined types. Simply splitting at commas won't work
249 listOfDependentTypes = SplitListOfTypes(m.group(2)) 228 listOfDependentTypes = SplitListOfTypes(m.group(2))
250 return (True, m.group(1), listOfDependentTypes) 229 return (True, m.group(1), listOfDependentTypes)
251 230
252
253 # def GetPrimitiveType(typeName : str) -> Type:
254 # if typeName in allTypes:
255 # return allTypes[typeName]
256 # else:
257 # primitiveTypes = ['int32', 'float32', 'float64', 'string']
258 # if not (typeName in primitiveTypes):
259 # raise Exception(f"Type {typeName} is unknown.")
260 # typeObject = Type(typeName,'primitive')
261 # # there are no dependent types in a primitive type --> Type object
262 # # constrution is finished at this point
263 # allTypes[typeName] = typeObject
264 # return typeObject
265
266
267 def ProcessTypeTree( 231 def ProcessTypeTree(
268 ancestors: List[str], 232 ancestors: List[str],
269 genOrderQueue: List[str], 233 genOrderQueue: List[str],
270 structTypes: Dict[str, Dict], 234 structTypes: Dict[str, Dict],
271 typeName: str, 235 typeName: str) -> None:
272 ) -> None:
273 if typeName in ancestors: 236 if typeName in ancestors:
274 raise Exception( 237 raise Exception(
275 f"Cyclic dependency chain found: the last of {ancestors} " 238 f"Cyclic dependency chain found: the last of {ancestors} "
276 + f"depends on {typeName} that is already in the list." 239 + f"depends on {typeName} that is already in the list."
277 ) 240 )
311 # been done if someone referenced us earlier) 274 # been done if someone referenced us earlier)
312 if not typeName in genOrderQueue: 275 if not typeName in genOrderQueue:
313 genOrderQueue.append(typeName) 276 genOrderQueue.append(typeName)
314 277
315 def ProcessEnumerationType(outputStreams: GeneratedCode, typeDict: Dict) -> None: 278 def ProcessEnumerationType(outputStreams: GeneratedCode, typeDict: Dict) -> None:
316 tsText: StringIO = StringIO() 279
317 cppText: StringIO = StringIO() 280 # enumeration declarations
318 281 tsDeclText: StringIO = StringIO()
319 tsText.write("enum %s\n" % typeDict["name"]) 282 tsDeclText.write("enum %s\n" % typeDict["name"])
320 tsText.write("{\n") 283 tsDeclText.write("{\n")
321 284
322 cppText.write("enum %s\n" % typeDict["name"]) 285 cppDeclText: StringIO = StringIO()
323 cppText.write("{\n") 286 cppDeclText.write("enum %s\n" % typeDict["name"])
287 cppDeclText.write("{\n")
288
289 cppToStringText: StringIO = StringIO()
290 cppToStringText.write("enum %s\n" % typeDict["name"])
291 cppToStringText.write("{\n")
292
293 cppFromStringText: StringIO = StringIO()
294 cppFromStringText.write("enum %s\n" % typeDict["name"])
295 cppFromStringText.write("{\n")
324 296
325 for i in range(len(typeDict["fields"])): 297 for i in range(len(typeDict["fields"])):
326 field = typeDict["fields"][i] 298 field = typeDict["fields"][i]
327 name = field["name"] 299 name = field["name"]
328 300
334 cppText.write(" %s" % name) 306 cppText.write(" %s" % name)
335 if i < len(typeDict["fields"]) - 1: 307 if i < len(typeDict["fields"]) - 1:
336 cppText.write(",") 308 cppText.write(",")
337 cppText.write("\n") 309 cppText.write("\n")
338 310
339 tsText.write("};\n\n") 311 tsText.write("};\n\n")
340 cppText.write("};\n\n") 312 cppText.write("};\n\n")
341 313
342 outputStreams.tsEnums.write(tsText.getvalue()) 314 outputStreams.tsEnums.write(tsText.getvalue())
343 outputStreams.cppEnums.write(cppText.getvalue()) 315 outputStreams.cppEnums.write(cppText.getvalue())
344 316
345 def GetSerializationCode(typeName: str,valueName: str, tempName: str) 317 def GetSerializationCode(typeName: str,valueName: str, tempName: str)
360 // <--- the calling code will insert collection/field writing here, 332 // <--- the calling code will insert collection/field writing here,
361 // like "parent.set("{fieldName}",val) or parent.append(val) 333 // like "parent.set("{fieldName}",val) or parent.append(val)
362 $collectValue 334 $collectValue
363 } 335 }
364 """ 336 """
365
366 337
367 338
368 339
369 def ProcessStructType(outputStreams: GeneratedCode, typeDict) -> None: 340 def ProcessStructType(outputStreams: GeneratedCode, typeDict) -> None:
370 tsText: StringIO = StringIO() 341 tsText: StringIO = StringIO()