Skip to content

Commit 6a44929

Browse files
committed
Support map and union types
1 parent 099b8e0 commit 6a44929

File tree

1 file changed

+58
-16
lines changed

1 file changed

+58
-16
lines changed

schema_salad/dlang_codegen.py

Lines changed: 58 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from . import _logger, schema
1010
from .codegen_base import CodeGenBase, TypeDef
11-
from .cpp_codegen import isArray, isEnumSchema, isRecordSchema, pred
11+
from .cpp_codegen import isArray, isEnumSchema, isMapSchema, isRecordSchema, isUnionSchema, pred
1212
from .exceptions import SchemaException
1313
from .schema import shortname
1414

@@ -63,11 +63,10 @@ def prologue(self) -> None:
6363
self.target.write(
6464
f"""module {self.package};
6565
66-
import salad.meta.dumper : genDumper;
67-
import salad.meta.impl : genCtor_, genIdentifier, genOpEq;
66+
import salad.meta.impl : genBody_;
6867
import salad.meta.parser : import_ = importFromURI;
6968
import salad.meta.uda : defaultValue, documentRoot, id, idMap, link, LinkResolver, secondaryFilesDSL, typeDSL;
70-
import salad.primitives : SchemaBase;
69+
import salad.primitives : EnumSchemaBase, MapSchemaBase, RecordSchemaBase, UnionSchemaBase;
7170
import salad.type : None, Union;
7271
7372
"""
@@ -83,9 +82,9 @@ def prologue(self) -> None:
8382
f"""
8483
enum saladVersion = "{self.salad_version}";
8584
86-
mixin template genCtor()
85+
mixin template genBody()
8786
{{
88-
mixin genCtor_!saladVersion;
87+
mixin genBody_!saladVersion;
8988
}}
9089
""" # noqa: B907
9190
)
@@ -225,6 +224,9 @@ def parse_record_field_type(
225224
return annotate_str, shortname(type_.get("name", "record"))
226225
elif shortname(type_["type"]) == "enum":
227226
return annotate_str, "'not yet implemented'"
227+
elif shortname(type_["type"]) == "map":
228+
value_type = self.parse_record_field_type(type_["values"], None, parent_has_idmap=has_idmap, has_default=True)[1]
229+
type_str = f"{value_type}[string]"
228230
return annotate_str, type_str
229231

230232
def parse_record_field(self, field: Dict[str, Any], parent_name: Optional[str] = None) -> str:
@@ -242,7 +244,7 @@ def parse_record_field(self, field: Dict[str, Any], parent_name: Optional[str] =
242244
value = cast(str, parent_name)
243245
return f'{doc_comment}static immutable {fname} = "{value}";' # noqa: B907
244246

245-
if field.get("default", None):
247+
if field.get("default", None) is not None:
246248
default_value = json.dumps(field["default"])
247249
default_str = f'@defaultValue(q"<{default_value}>") '
248250
else:
@@ -271,13 +273,11 @@ def parse_record_schema(self, stype: Dict[str, Any]) -> str:
271273
doc_comment = self.to_doc_comment(stype.get("doc", None))
272274

273275
return f"""
274-
{doc_comment}{doc_root_annotation}class {classname} : SchemaBase
276+
{doc_comment}{doc_root_annotation}class {classname} : RecordSchemaBase
275277
{{
276278
{decl_str}
277279
278-
mixin genCtor;
279-
mixin genIdentifier;
280-
mixin genDumper;
280+
mixin genBody;
281281
}}"""
282282

283283
def parse_enum(self, stype: Dict[str, Any]) -> str:
@@ -308,7 +308,7 @@ def parse_enum(self, stype: Dict[str, Any]) -> str:
308308
doc_comment = ""
309309

310310
return f"""
311-
{doc_comment}{doc_root_annotation}class {classname} : SchemaBase
311+
{doc_comment}{doc_root_annotation}class {classname} : EnumSchemaBase
312312
{{
313313
///
314314
enum Symbol
@@ -318,9 +318,47 @@ def parse_enum(self, stype: Dict[str, Any]) -> str:
318318
319319
Symbol value;
320320
321-
mixin genCtor;
322-
mixin genOpEq;
323-
mixin genDumper;
321+
mixin genBody;
322+
}}"""
323+
324+
def parse_union(self, stype: Dict[str, Any]) -> str:
325+
"""Return a declaration string for a given union schema."""
326+
name = cast(str, stype["name"])
327+
classname = self.safe_name(name)
328+
329+
types = self.parse_record_field_type(stype["names"], None)[1]
330+
331+
if "doc" in stype:
332+
doc_comment = self.to_doc_comment(stype["doc"])
333+
else:
334+
doc_comment = ""
335+
336+
return f"""
337+
{doc_comment}class {classname} : UnionSchemaBase
338+
{{
339+
{types} payload;
340+
341+
mixin genBody;
342+
}}"""
343+
344+
def parse_map(self, stype: Dict[str, Any]) -> str:
345+
"""Return a declaration string for a given map schema."""
346+
name = cast(str, stype["name"])
347+
classname = self.safe_name(name)
348+
349+
values = self.parse_record_field_type(stype["values"], None, has_default=True)[1]
350+
351+
if "doc" in stype:
352+
doc_comment = self.to_doc_comment(stype["doc"])
353+
else:
354+
doc_comment = ""
355+
356+
return f"""
357+
{doc_comment}class {classname} : MapSchemaBase
358+
{{
359+
{values}[string] payload;
360+
361+
mixin genBody;
324362
}}"""
325363

326364
def parse(self, items: List[Dict[str, Any]]) -> None:
@@ -343,8 +381,12 @@ def parse(self, items: List[Dict[str, Any]]) -> None:
343381
dlang_defs.append(self.parse_record_schema(stype))
344382
elif isEnumSchema(stype):
345383
dlang_defs.append(self.parse_enum(stype))
384+
elif isUnionSchema(stype):
385+
dlang_defs.append(self.parse_union(stype))
386+
elif isMapSchema(stype):
387+
dlang_defs.append(self.parse_map(stype))
346388
else:
347-
_logger.error("not parsed %s", stype)
389+
_logger.error("not parsed %s", json.dumps(stype))
348390

349391
self.target.write("\n".join(dlang_defs))
350392
self.target.write("\n")

0 commit comments

Comments
 (0)