comparison Resources/CodeGeneration/stonegentool.py @ 628:84af39146e76 am-dev

CodeGeneration: support default values
author Alain Mazy <alain@mazy.be>
date Wed, 08 May 2019 16:32:57 +0200
parents 8432926e9db9
children 5dd496343fad
comparison
equal deleted inserted replaced
627:b7fd0471281c 628:84af39146e76
67 with open(path, "r") as fp: 67 with open(path, "r") as fp:
68 fileContent = fp.read() 68 fileContent = fp.read()
69 fileContent = JsonHelpers.removeCommentsFromJsonContent(fileContent) 69 fileContent = JsonHelpers.removeCommentsFromJsonContent(fileContent)
70 return json.loads(fileContent) 70 return json.loads(fileContent)
71 71
72 class FieldDefinition:
73
74 def __init__(self, name: str, type: str, defaultValue: str):
75 self.name = name
76 self.type = type
77 self.defaultValue = defaultValue
78
79 @staticmethod
80 def fromKeyValue(key: str, value: str):
81
82 if "=" in value:
83 splitValue = value.split(sep="=")
84 type = splitValue[0].strip(" ")
85 defaultValue = splitValue[1].strip(" ")
86 else:
87 type = value
88 defaultValue = None
89
90 return FieldDefinition(name = key, type = type, defaultValue = defaultValue)
91
72 92
73 def LoadSchemaFromJson(filePath): 93 def LoadSchemaFromJson(filePath):
74 return JsonHelpers.loadJsonWithComments(filePath) 94 return JsonHelpers.loadJsonWithComments(filePath)
75 95
76 def CanonToCpp(canonicalTypename): 96 def CanonToCpp(canonicalTypename):
127 return True 147 return True
128 148
129 def NeedsCppConstruction(canonTypename): 149 def NeedsCppConstruction(canonTypename):
130 return False 150 return False
131 151
152 def DefaultValueToTs(enums, field:FieldDefinition):
153 tsType = CanonToTs(field.type)
154
155 enumNames = []
156 for enum in enums:
157 enumNames.append(enum['name'])
158
159 if tsType in enumNames:
160 return tsType + "." + field.defaultValue
161 else:
162 return field.defaultValue
163
164 def DefaultValueToCpp(root, enums, field:FieldDefinition):
165 cppType = CanonToCpp(field.type)
166
167 enumNames = []
168 for enum in enums:
169 enumNames.append(enum['name'])
170
171 if cppType in enumNames:
172 return root + "::" + cppType + "_" + field.defaultValue
173 else:
174 return field.defaultValue
175
132 def RegisterTemplateFunction(template,func): 176 def RegisterTemplateFunction(template,func):
133 """Makes a function callable by a jinja2 template""" 177 """Makes a function callable by a jinja2 template"""
134 template.globals[func.__name__] = func 178 template.globals[func.__name__] = func
135 return func 179 return func
136 180
138 template = Template(templateStr) 182 template = Template(templateStr)
139 RegisterTemplateFunction(template,CanonToCpp) 183 RegisterTemplateFunction(template,CanonToCpp)
140 RegisterTemplateFunction(template,CanonToTs) 184 RegisterTemplateFunction(template,CanonToTs)
141 RegisterTemplateFunction(template,NeedsTsConstruction) 185 RegisterTemplateFunction(template,NeedsTsConstruction)
142 RegisterTemplateFunction(template,NeedsCppConstruction) 186 RegisterTemplateFunction(template,NeedsCppConstruction)
187 RegisterTemplateFunction(template, DefaultValueToTs)
188 RegisterTemplateFunction(template, DefaultValueToCpp)
143 return template 189 return template
144 190
145 def MakeTemplateFromFile(templateFileName): 191 def MakeTemplateFromFile(templateFileName):
146 templateFile = open(templateFileName, "r") 192
147 templateFileContents = templateFile.read() 193 with open(templateFileName, "r") as templateFile:
148 return MakeTemplate(templateFileContents) 194 templateFileContents = templateFile.read()
149 templateFile.close() 195 return MakeTemplate(templateFileContents)
196
150 197
151 def EatToken(sentence): 198 def EatToken(sentence):
152 """splits "A,B,C" into "A" and "B,C" where A, B and C are type names 199 """splits "A,B,C" into "A" and "B,C" where A, B and C are type names
153 (including templates) like "int32", "TotoTutu", or 200 (including templates) like "int32", "TotoTutu", or
154 "map<map<int32,vector<string>>,map<string,int32>>" """ 201 "map<map<int32,vector<string>>,map<string,int32>>" """
361 if fieldDict == None: 408 if fieldDict == None:
362 return fieldDict 409 return fieldDict
363 ret = {} 410 ret = {}
364 for k,v in fieldDict.items(): 411 for k,v in fieldDict.items():
365 if k != "__handler": 412 if k != "__handler":
366 ret[k] = v 413 ret[k] = FieldDefinition.fromKeyValue(k, v)
367 if k.startswith("__") and k != "__handler": 414 if k.startswith("__") and k != "__handler":
368 raise RuntimeError("Fields starting with __ (double underscore) are reserved names!") 415 raise RuntimeError("Fields starting with __ (double underscore) are reserved names!")
369 return ret 416 return ret
370 417
371 def GetStructMetadata(fieldDict): 418 def GetStructMetadata(fieldDict):
471 # TL;DR: all 256 values are mapped to characters in latin-1 so the file 518 # TL;DR: all 256 values are mapped to characters in latin-1 so the file
472 # contents never cause an error. 519 # contents never cause an error.
473 with open(fn, 'r', encoding='latin-1') as f: 520 with open(fn, 'r', encoding='latin-1') as f:
474 schemaText = f.read() 521 schemaText = f.read()
475 assert(type(schemaText) == str) 522 assert(type(schemaText) == str)
523 return LoadSchemaFromString(schemaText = schemaText)
524
525 def LoadSchemaFromString(schemaText:str):
476 # ensure there is a space after each colon. Otherwise, dicts could be 526 # ensure there is a space after each colon. Otherwise, dicts could be
477 # erroneously recognized as an array of strings containing ':' 527 # erroneously recognized as an array of strings containing ':'
478 for i in range(len(schemaText)-1): 528 for i in range(len(schemaText)-1):
479 ch = schemaText[i] 529 ch = schemaText[i]
480 nextCh = schemaText[i+1] 530 nextCh = schemaText[i+1]
481 if ch == ':': 531 if ch == ':':
482 if not (nextCh == ' ' or nextCh == '\n'): 532 if not (nextCh == ' ' or nextCh == '\n'):
483 lineNumber = schemaText.count("\n",0,i) + 1 533 lineNumber = schemaText.count("\n",0,i) + 1
484 raise RuntimeError("Error at line " + str(lineNumber) + " in the schema: colons must be followed by a space or a newline!") 534 raise RuntimeError("Error at line " + str(lineNumber) + " in the schema: colons must be followed by a space or a newline!")
485 schema = yaml.load(schemaText) 535 schema = yaml.load(schemaText)
486 return schema 536 return schema
487 537
488 def GetTemplatingDictFromSchemaFilename(fn): 538 def GetTemplatingDictFromSchemaFilename(fn):
489 obj = LoadSchema(fn) 539 return GetTemplatingDictFromSchema(LoadSchema(fn))
490 genOrder = ComputeRequiredDeclarationOrder(obj) 540
491 templatingDict = ProcessSchema(obj, genOrder) 541 def GetTemplatingDictFromSchema(schema):
542 genOrder = ComputeRequiredDeclarationOrder(schema)
543 templatingDict = ProcessSchema(schema, genOrder)
492 currentDT = datetime.datetime.now() 544 currentDT = datetime.datetime.now()
493 templatingDict['currentDatetime'] = str(currentDT) 545 templatingDict['currentDatetime'] = str(currentDT)
494 return templatingDict 546 return templatingDict
495 547
496 # +-----------------------+ 548 # +-----------------------+