Mercurial > hg > orthanc-stone
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() |