Mercurial > hg > orthanc-stone
comparison Resources/CodeGeneration/stonegentool.py @ 493:6fbf2eae7c88 bgo-commands-codegen
All unit tests pass for generation, including handler and dispatcher
author | bgo-osimis |
---|---|
date | Fri, 22 Feb 2019 10:48:43 +0100 |
parents | 8e7e151ef472 |
children | fc17251477d6 |
comparison
equal
deleted
inserted
replaced
491:8e7e151ef472 | 493:6fbf2eae7c88 |
---|---|
106 | 106 |
107 | 107 |
108 def LoadSchemaFromJson(filePath: str): | 108 def LoadSchemaFromJson(filePath: str): |
109 return JsonHelpers.loadJsonWithComments(filePath) | 109 return JsonHelpers.loadJsonWithComments(filePath) |
110 | 110 |
111 def GetCppTypenameFromCanonical(canonicalTypename: str) -> str: | 111 def CanonToCpp(canonicalTypename: str) -> str: |
112 # C++: prefix map vector and string with std::map, std::vector and | 112 # C++: prefix map vector and string with std::map, std::vector and |
113 # std::string | 113 # std::string |
114 # replace int32 by int32_t | 114 # replace int32 by int32_t |
115 # replace float32 by float | 115 # replace float32 by float |
116 # replace float64 by double | 116 # replace float64 by double |
117 retVal: str = canonicalTypename | 117 retVal: str = canonicalTypename |
118 retVal = retVal.replace("map", "std::map") | 118 retVal = retVal.replace("map", "std::map") |
119 retVal = retVal.replace("vector", "std::vector") | 119 retVal = retVal.replace("vector", "std::vector") |
120 retVal = retVal.replace("int32", "int32_t") | 120 retVal = retVal.replace("int32", "int32_t") |
121 retVal = retVal.replace("float32", "float") | 121 retVal = retVal.replace("float32", "float") |
122 retVal = retVal.replace("float64", "double") | 122 retVal = retVal.replace("float64", "double") |
123 return retVal | 123 return retVal |
124 | 124 |
125 def GetTypeScriptTypenameFromCanonical(canonicalTypename: str) -> str: | 125 def CanonToTs(canonicalTypename: str) -> str: |
126 # TS: replace vector with Array and map with Map | 126 # TS: replace vector with Array and map with Map |
127 # string remains string | 127 # string remains string |
128 # replace int32 by number | 128 # replace int32 by number |
129 # replace float32 by number | 129 # replace float32 by number |
130 # replace float64 by number | 130 # replace float64 by number |
131 retVal: str = canonicalTypename | 131 retVal: str = canonicalTypename |
132 retVal = retVal.replace("map", "Map") | 132 retVal = retVal.replace("map", "Map") |
133 retVal = retVal.replace("vector", "Array") | 133 retVal = retVal.replace("vector", "Array") |
134 retVal = retVal.replace("int32", "number") | 134 retVal = retVal.replace("int32", "number") |
135 retVal = retVal.replace("float32", "number") | 135 retVal = retVal.replace("float32", "number") |
136 retVal = retVal.replace("float64", "number") | 136 retVal = retVal.replace("float64", "number") |
137 retVal = retVal.replace("bool", "boolean") | 137 retVal = retVal.replace("bool", "boolean") |
138 return retVal | 138 return retVal |
139 | |
140 def NeedsConstruction(canonTypename): | |
141 return True | |
142 | |
143 def RegisterTemplateFunction(template,func): | |
144 """Makes a function callable by a jinja2 template""" | |
145 template.globals[func.__name__] = func | |
146 return func | |
147 | |
148 def MakeTemplate(templateStr): | |
149 template = Template(templateStr) | |
150 RegisterTemplateFunction(template,CanonToCpp) | |
151 RegisterTemplateFunction(template,CanonToTs) | |
152 RegisterTemplateFunction(template,NeedsConstruction) | |
153 return template | |
154 | |
155 def MakeTemplateFromFile(templateFileName): | |
156 templateFile = open(templateFileName, "r") | |
157 templateFileContents = templateFile.read() | |
158 return MakeTemplate(templateFileContents) | |
159 templateFile.close() | |
139 | 160 |
140 def EatToken(sentence: str) -> Tuple[str, str]: | 161 def EatToken(sentence: str) -> Tuple[str, str]: |
141 """splits "A,B,C" into "A" and "B,C" where A, B and C are type names | 162 """splits "A,B,C" into "A" and "B,C" where A, B and C are type names |
142 (including templates) like "int32", "TotoTutu", or | 163 (including templates) like "int32", "TotoTutu", or |
143 "map<map<int32,vector<string>>,map<string,int32>>" """ | 164 "map<map<int32,vector<string>>,map<string,int32>>" """ |
305 raise RuntimeError \ | 326 raise RuntimeError \ |
306 (f'Type "{name}" should start with "enum " or "struct "') | 327 (f'Type "{name}" should start with "enum " or "struct "') |
307 | 328 |
308 # TODO: check enum fields are unique (in whole namespace) | 329 # TODO: check enum fields are unique (in whole namespace) |
309 # TODO: check struct fields are unique (in each struct) | 330 # TODO: check struct fields are unique (in each struct) |
331 # TODO: check that in the source schema, there are spaces after each colon | |
310 | 332 |
311 # +-----------------------+ | 333 # +-----------------------+ |
312 # | Main processing logic | | 334 # | Main processing logic | |
313 # +-----------------------+ | 335 # +-----------------------+ |
314 | 336 |
393 # def WriteStreamsToFiles(rootName: str, genc: Dict[str, StringIO]) \ | 415 # def WriteStreamsToFiles(rootName: str, genc: Dict[str, StringIO]) \ |
394 # -> None: | 416 # -> None: |
395 # pass | 417 # pass |
396 | 418 |
397 def LoadSchema(fn): | 419 def LoadSchema(fn): |
398 with open(fn, 'rb') as f: | 420 # latin-1 is a trick, when we do NOT care about NON-ascii chars but |
399 schema = yaml.load(f) | 421 # we wish to avoid using a decoding error handler |
422 # (see http://python-notes.curiousefficiency.org/en/latest/python3/text_file_processing.html#files-in-an-ascii-compatible-encoding-best-effort-is-acceptable) | |
423 # TL;DR: all 256 values are mapped to characters in latin-1 so the file | |
424 # contents never cause an error. | |
425 with open(fn, 'r', encoding='latin-1') as f: | |
426 schemaText = f.read() | |
427 assert(type(schemaText) == str) | |
428 # ensure there is a space after each colon. Otherwise, dicts could be | |
429 # erroneously recognized as an array of strings containing ':' | |
430 for i in range(len(schemaText)-1): | |
431 ch = schemaText[i] | |
432 nextCh = schemaText[i+1] | |
433 if ch == ':': | |
434 if not (nextCh == ' ' or nextCh == '\n'): | |
435 assert(False) | |
436 schema = yaml.load(schemaText) | |
400 return schema | 437 return schema |
401 | 438 |
402 def GetTemplatingDictFromSchemaFilename(fn): | 439 def GetTemplatingDictFromSchemaFilename(fn): |
403 obj = LoadSchema(fn) | 440 obj = LoadSchema(fn) |
404 genOrder: str = ComputeRequiredDeclarationOrder(obj) | 441 genOrder: str = ComputeRequiredDeclarationOrder(obj) |
656 # # let's generate the code according to the | 693 # # let's generate the code according to the |
657 # struct = schema[name] | 694 # struct = schema[name] |
658 | 695 |
659 # if not IsStructType(name): | 696 # if not IsStructType(name): |
660 # raise Exception(f'{typename} should start with "struct "') | 697 # raise Exception(f'{typename} should start with "struct "') |
698 | |
699 |