Skip to content

Commit d5ee728

Browse files
committed
Codegen: implement set in qlgen (excluding QL tests)
1 parent 00b59f8 commit d5ee728

File tree

7 files changed

+69
-13
lines changed

7 files changed

+69
-13
lines changed

misc/codegen/generators/qlgen.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ def get_ql_property(cls: schema.Class, prop: schema.Property, prev_child: str =
109109
prev_child=prev_child if prop.is_child else None,
110110
is_optional=prop.is_optional,
111111
is_predicate=prop.is_predicate,
112+
is_unordered=prop.is_unordered,
112113
description=prop.description
113114
)
114115
if prop.is_single:
@@ -123,7 +124,7 @@ def get_ql_property(cls: schema.Class, prop: schema.Property, prev_child: str =
123124
singular=inflection.singularize(inflection.camelize(prop.name)),
124125
plural=inflection.pluralize(inflection.camelize(prop.name)),
125126
tablename=inflection.tableize(f"{cls.name}_{prop.name}"),
126-
tableparams=["this", "index", "result"],
127+
tableparams=["this", "index", "result"] if not prop.is_unordered else ["this", "result"],
127128
doc=_get_doc(cls, prop, plural=False),
128129
doc_plural=_get_doc(cls, prop, plural=True),
129130
)

misc/codegen/lib/ql.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class Property:
3636
first: bool = False
3737
is_optional: bool = False
3838
is_predicate: bool = False
39+
is_unordered: bool = False
3940
prev_child: Optional[str] = None
4041
qltest_skip: bool = False
4142
description: List[str] = field(default_factory=list)
@@ -49,7 +50,11 @@ def __post_init__(self):
4950

5051
@property
5152
def getter(self):
52-
return f"get{self.singular}" if not self.is_predicate else self.singular
53+
if self.is_predicate:
54+
return self.singular
55+
if self.is_unordered:
56+
return self.indefinite_getter
57+
return f"get{self.singular}"
5358

5459
@property
5560
def indefinite_getter(self):
@@ -77,6 +82,10 @@ def is_child(self):
7782
def has_description(self) -> bool:
7883
return bool(self.description)
7984

85+
@property
86+
def is_indexed(self) -> bool:
87+
return self.is_repeated and not self.is_unordered
88+
8089

8190
@dataclass
8291
class Base:

misc/codegen/templates/ql_class.mustache

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@ module Generated {
6666
* This includes nodes from the "hidden" AST. It can be overridden in subclasses to change the
6767
* behavior of both the `Immediate` and non-`Immediate` versions.
6868
*/
69-
{{type}} getImmediate{{singular}}({{#is_repeated}}int index{{/is_repeated}}) {
69+
{{type}} get{{#is_unordered}}An{{/is_unordered}}Immediate{{singular}}({{#is_indexed}}int index{{/is_indexed}}) {
7070
{{^ipa}}
71-
result = Synth::convert{{type}}FromRaw(Synth::convert{{name}}ToRaw(this){{^root}}.(Raw::{{name}}){{/root}}.{{getter}}({{#is_repeated}}index{{/is_repeated}}))
71+
result = Synth::convert{{type}}FromRaw(Synth::convert{{name}}ToRaw(this){{^root}}.(Raw::{{name}}){{/root}}.{{getter}}({{#is_indexed}}index{{/is_indexed}}))
7272
{{/ipa}}
7373
{{#ipa}}
7474
none()
@@ -83,8 +83,8 @@ module Generated {
8383
{{/description}}
8484
{{/has_description}}
8585
*/
86-
final {{type}} {{getter}}({{#is_repeated}}int index{{/is_repeated}}) {
87-
result = getImmediate{{singular}}({{#is_repeated}}index{{/is_repeated}}).resolve()
86+
final {{type}} {{getter}}({{#is_indexed}}int index{{/is_indexed}}) {
87+
result = get{{#is_unordered}}An{{/is_unordered}}Immediate{{singular}}({{#is_indexed}}index{{/is_indexed}}).resolve()
8888
}
8989

9090
{{/type_is_class}}
@@ -97,9 +97,9 @@ module Generated {
9797
{{/description}}
9898
{{/has_description}}
9999
*/
100-
{{type}} {{getter}}({{#is_repeated}}int index{{/is_repeated}}) {
100+
{{type}} {{getter}}({{#is_indexed}}int index{{/is_indexed}}) {
101101
{{^ipa}}
102-
{{^is_predicate}}result = {{/is_predicate}}Synth::convert{{name}}ToRaw(this){{^root}}.(Raw::{{name}}){{/root}}.{{getter}}({{#is_repeated}}index{{/is_repeated}})
102+
{{^is_predicate}}result = {{/is_predicate}}Synth::convert{{name}}ToRaw(this){{^root}}.(Raw::{{name}}){{/root}}.{{getter}}({{#is_indexed}}index{{/is_indexed}})
103103
{{/ipa}}
104104
{{#ipa}}
105105
none()
@@ -115,7 +115,7 @@ module Generated {
115115
exists({{getter}}({{#is_repeated}}index{{/is_repeated}}))
116116
}
117117
{{/is_optional}}
118-
{{#is_repeated}}
118+
{{#is_indexed}}
119119

120120
/**
121121
* Gets any of the {{doc_plural}}.
@@ -132,7 +132,15 @@ module Generated {
132132
result = count(int i | exists({{getter}}(i)))
133133
}
134134
{{/is_optional}}
135-
{{/is_repeated}}
135+
{{/is_indexed}}
136+
{{#is_unordered}}
137+
/**
138+
* Gets the number of {{doc_plural}}.
139+
*/
140+
final int getNumberOf{{plural}}() {
141+
result = count({{getter}}())
142+
}
143+
{{/is_unordered}}
136144
{{/properties}}
137145
}
138146
}

misc/codegen/templates/ql_db.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ module Raw {
1313
{{/description}}
1414
{{/has_description}}
1515
*/
16-
{{type}} {{getter}}({{#is_repeated}}int index{{/is_repeated}}) {
16+
{{type}} {{getter}}({{#is_indexed}}int index{{/is_indexed}}) {
1717
{{tablename}}({{#tableparams}}{{^first}}, {{/first}}{{param}}{{/tableparams}})
1818
}
1919
{{/properties}}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
{{^is_predicate}}
2+
{{^is_unoredered}}
23
Gets the {{#is_repeated}}`index`th {{/is_repeated}}{{doc}}{{#is_repeated}} (0-based){{/is_repeated}}{{#is_optional}}, if it exists{{/is_optional}}.
4+
{{/is_unoredered}}
35
{{/is_predicate}}
46
{{#is_predicate}}
57
Holds if {{doc}}.
68
{{/is_predicate}}
9+
{{#is_unordered}}
10+
Gets any of the {{doc_plural}}.
11+
{{/is_unordered}}

misc/codegen/test/test_ql.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,26 @@ def test_property_is_a_class(type, expected):
2727
assert [p.param for p in prop.tableparams] == expected_tableparams
2828

2929

30-
@pytest.mark.parametrize("name,expected_getter", [
30+
indefinite_getters = [
3131
("Argument", "getAnArgument"),
3232
("Element", "getAnElement"),
3333
("Integer", "getAnInteger"),
3434
("Operator", "getAnOperator"),
3535
("Unit", "getAUnit"),
3636
("Whatever", "getAWhatever"),
37-
])
37+
]
38+
39+
@pytest.mark.parametrize("name,expected_getter", indefinite_getters)
3840
def test_property_indefinite_article(name, expected_getter):
3941
prop = ql.Property(name, plural="X")
4042
assert prop.indefinite_getter == expected_getter
4143

4244

45+
@pytest.mark.parametrize("name,expected_getter", indefinite_getters)
46+
def test_property_unordered_getter(name, expected_getter):
47+
prop = ql.Property(name, plural="X", is_unordered=True)
48+
assert prop.getter == expected_getter
49+
4350
@pytest.mark.parametrize("plural,expected", [
4451
(None, False),
4552
("", False),
@@ -49,6 +56,16 @@ def test_property_is_repeated(plural, expected):
4956
prop = ql.Property("foo", "Foo", "props", ["result"], plural=plural)
5057
assert prop.is_repeated is expected
5158

59+
@pytest.mark.parametrize("plural,unordered,expected", [
60+
(None, False, False),
61+
("", False, False),
62+
("X", False, True),
63+
("X", True, False),
64+
])
65+
def test_property_is_indexed(plural, unordered, expected):
66+
prop = ql.Property("foo", "Foo", "props", ["result"], plural=plural, is_unordered=unordered)
67+
assert prop.is_indexed is expected
68+
5269

5370
@pytest.mark.parametrize("is_optional,is_predicate,plural,expected", [
5471
(False, False, None, True),

misc/codegen/test/test_qlgen.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,22 @@ def test_repeated_property(generate_classes, is_child, prev_child):
337337
])),
338338
}
339339

340+
def test_repeated_unordered_property(generate_classes):
341+
assert generate_classes([
342+
schema.Class("FakeRoot"),
343+
schema.Class("MyObject", properties=[
344+
schema.RepeatedUnorderedProperty("foo", "bar")]),
345+
]) == {
346+
"FakeRoot.qll": (a_ql_stub(name="FakeRoot", base_import=gen_import_prefix + "FakeRoot"),
347+
a_ql_class(name="FakeRoot", final=True)),
348+
"MyObject.qll": (a_ql_stub(name="MyObject", base_import=gen_import_prefix + "MyObject"),
349+
a_ql_class(name="MyObject", final=True, properties=[
350+
ql.Property(singular="Foo", plural="Foos", type="bar", tablename="my_object_foos",
351+
tableparams=["this", "result"], is_unordered=True,
352+
doc="foo of this my object", doc_plural="foos of this my object"),
353+
])),
354+
}
355+
340356

341357
@pytest.mark.parametrize("is_child,prev_child", [(False, None), (True, "")])
342358
def test_repeated_optional_property(generate_classes, is_child, prev_child):

0 commit comments

Comments
 (0)