Skip to content

Commit 9798d8b

Browse files
committed
Swift: add ?* modifier to schema specification
This indicates a list of optional entries. This is different than simply repeatind entries because of the indexing.
1 parent c2d3aac commit 9798d8b

File tree

15 files changed

+102
-39
lines changed

15 files changed

+102
-39
lines changed

swift/codegen/dbschemegen.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,24 +38,24 @@ def cls_to_dbscheme(cls: schema.Class):
3838
)
3939
# use property-specific tables for 1-to-many and 1-to-at-most-1 properties
4040
for f in cls.properties:
41-
if f.is_optional:
41+
if f.is_repeated:
4242
yield Table(
43-
keyset=KeySet(["id"]),
43+
keyset=KeySet(["id", "index"]),
4444
name=inflection.tableize(f"{cls.name}_{f.name}"),
4545
columns=[
4646
Column("id", type=dbtype(cls.name)),
47-
Column(f.name, dbtype(f.type)),
48-
],
47+
Column("index", type="int"),
48+
Column(inflection.singularize(f.name), dbtype(f.type)),
49+
]
4950
)
50-
elif f.is_repeated:
51+
elif f.is_optional:
5152
yield Table(
52-
keyset=KeySet(["id", "index"]),
53+
keyset=KeySet(["id"]),
5354
name=inflection.tableize(f"{cls.name}_{f.name}"),
5455
columns=[
5556
Column("id", type=dbtype(cls.name)),
56-
Column("index", type="int"),
57-
Column(inflection.singularize(f.name), dbtype(f.type)),
58-
]
57+
Column(f.name, dbtype(f.type)),
58+
],
5959
)
6060

6161

swift/codegen/lib/cpp.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class Field:
4141
def __post_init__(self):
4242
if self.is_optional:
4343
self.type = f"std::optional<{self.type}>"
44-
elif self.is_repeated:
44+
if self.is_repeated:
4545
self.type = f"std::vector<{self.type}>"
4646

4747
@property

swift/codegen/lib/ql.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class Property:
2222
params: List[Param] = field(default_factory=list)
2323
first: bool = False
2424
local_var: str = "x"
25+
is_optional: bool = False
2526

2627
def __post_init__(self):
2728
if self.params:
@@ -43,6 +44,10 @@ def indefinite_article(self):
4344
def type_is_class(self):
4445
return self.type[0].isupper()
4546

47+
@property
48+
def is_repeated(self):
49+
return bool(self.plural)
50+
4651

4752
@dataclass
4853
class Class:

swift/codegen/lib/schema.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ class RepeatedProperty(Property):
3535
is_repeated: ClassVar = True
3636

3737

38+
@dataclass
39+
class RepeatedOptionalProperty(Property):
40+
is_optional: ClassVar = True
41+
is_repeated: ClassVar = True
42+
43+
3844
@dataclass
3945
class Class:
4046
name: str
@@ -51,7 +57,10 @@ class Schema:
5157

5258

5359
def _parse_property(name, type):
54-
if type.endswith("*"):
60+
if type.endswith("?*"):
61+
cls = RepeatedOptionalProperty
62+
type = type[:-2]
63+
elif type.endswith("*"):
5564
cls = RepeatedProperty
5665
type = type[:-1]
5766
elif type.endswith("?"):

swift/codegen/qlgen.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,6 @@ def get_ql_property(cls: schema.Class, prop: schema.Property):
1818
tablename=inflection.tableize(cls.name),
1919
tableparams=["this"] + ["result" if p is prop else "_" for p in cls.properties if p.is_single],
2020
)
21-
elif prop.is_optional:
22-
return ql.Property(
23-
singular=inflection.camelize(prop.name),
24-
type=prop.type,
25-
tablename=inflection.tableize(f"{cls.name}_{prop.name}"),
26-
tableparams=["this", "result"],
27-
)
2821
elif prop.is_repeated:
2922
return ql.Property(
3023
singular=inflection.singularize(inflection.camelize(prop.name)),
@@ -33,6 +26,15 @@ def get_ql_property(cls: schema.Class, prop: schema.Property):
3326
tablename=inflection.tableize(f"{cls.name}_{prop.name}"),
3427
tableparams=["this", "index", "result"],
3528
params=[ql.Param("index", type="int")],
29+
is_optional=prop.is_optional,
30+
)
31+
elif prop.is_optional:
32+
return ql.Property(
33+
singular=inflection.camelize(prop.name),
34+
type=prop.type,
35+
tablename=inflection.tableize(f"{cls.name}_{prop.name}"),
36+
tableparams=["this", "result"],
37+
is_optional=True,
3638
)
3739

3840

swift/codegen/schema.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ OperatorDecl:
256256

257257
PatternBindingDecl:
258258
_extends: Decl
259-
inits: Expr*
259+
inits: Expr?*
260260
patterns: Pattern*
261261

262262
PoundDiagnosticDecl:

swift/codegen/templates/cpp_classes.mustache

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,19 @@ struct {{name}}{{#final}} : Binding<{{name}}Tag>{{#bases}}, {{ref.name}}{{/bases
3434
{{/trap_name}}
3535
{{#fields}}
3636
{{#is_optional}}
37+
{{^is_repeated}}
3738
if ({{name}}) out << {{trap_name}}{id, *{{name}}} << '\n';
39+
{{/is_repeated}}
3840
{{/is_optional}}
3941
{{#is_repeated}}
40-
for (auto i = 0u; i < {{name}}.size(); ++i) out << {{trap_name}}{id, i, {{name}}[i]};
42+
for (auto i = 0u; i < {{name}}.size(); ++i) {
43+
{{^is_optional}}
44+
out << {{trap_name}}{id, i, {{name}}[i]};
45+
{{/is_optional}}
46+
{{#is_optional}}
47+
if ({{name}}[i]) out << {{trap_name}}{id, i, *{{name}}[i]};
48+
{{/is_optional}}
49+
}
4150
{{/is_repeated}}
4251
{{/fields}}
4352
}

swift/codegen/templates/ql_class.mustache

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,28 +20,28 @@ class {{name}}Base extends {{db_id}}{{#bases}}, {{.}}{{/bases}} {
2020
{{/final}}
2121
{{#properties}}
2222

23-
{{#type_is_class}}
24-
{{type}} get{{singular}}({{#params}}{{^first}}, {{/first}}{{type}} {{param}}{{/params}}) {
23+
{{type}} get{{singular}}({{#is_repeated}}int index{{/is_repeated}}) {
24+
{{#type_is_class}}
2525
exists({{type}} {{local_var}} |
2626
{{tablename}}({{#tableparams}}{{^first}}, {{/first}}{{param}}{{/tableparams}})
2727
and
2828
result = {{local_var}}.resolve())
29-
}
30-
{{/type_is_class}}
31-
{{^type_is_class}}
32-
{{type}} get{{singular}}({{#params}}{{^first}}, {{/first}}{{type}} {{param}}{{/params}}) {
29+
{{/type_is_class}}
30+
{{^type_is_class}}
3331
{{tablename}}({{#tableparams}}{{^first}}, {{/first}}{{param}}{{/tableparams}})
32+
{{/type_is_class}}
3433
}
35-
{{/type_is_class}}
36-
{{#indefinite_article}}
34+
{{#is_repeated}}
3735

38-
{{type}} get{{.}}{{singular}}() {
39-
result = get{{singular}}({{#params}}{{^first}}, {{/first}}_{{/params}})
36+
{{type}} get{{indefinite_article}}{{singular}}() {
37+
result = get{{singular}}(_)
4038
}
39+
{{^is_optional}}
4140

4241
int getNumberOf{{plural}}() {
43-
result = count(get{{.}}{{singular}}())
42+
result = count(get{{indefinite_article}}{{singular}}())
4443
}
45-
{{/indefinite_article}}
44+
{{/is_optional}}
45+
{{/is_repeated}}
4646
{{/properties}}
4747
}

swift/codegen/test/test_cpp.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ def test_field_is_single(is_optional, is_repeated, expected):
4242
(False, False, "bar"),
4343
(True, False, "std::optional<bar>"),
4444
(False, True, "std::vector<bar>"),
45+
(True, True, "std::vector<std::optional<bar>>"),
4546
])
4647
def test_field_modal_types(is_optional, is_repeated, expected):
4748
f = cpp.Field("name", "bar", is_optional=is_optional, is_repeated=is_repeated)

swift/codegen/test/test_cppgen.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ def test_complex_hierarchy_topologically_ordered(generate):
7272
(schema.SingleProperty, False, False, None),
7373
(schema.OptionalProperty, True, False, "MyClassPropsTrap"),
7474
(schema.RepeatedProperty, False, True, "MyClassPropsTrap"),
75+
(schema.RepeatedOptionalProperty, True, True, "MyClassPropsTrap"),
7576
])
7677
def test_class_with_field(generate, type, expected, property_cls, optional, repeated, trap_name):
7778
assert generate([

0 commit comments

Comments
 (0)