Skip to content

Commit 76125a8

Browse files
committed
Generate constructor helper
1 parent fa784c1 commit 76125a8

File tree

15 files changed

+533
-79
lines changed

15 files changed

+533
-79
lines changed

bindgen/ir/IR.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,13 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
181181
s << "\n object implicits {\n" << ir.getHelperMethods() << " }\n";
182182
}
183183

184+
for (const auto &str : ir.structs) {
185+
visitedTypes.clear();
186+
if (ir.shouldOutput(str, visitedTypes) && str->hasHelperMethods()) {
187+
s << "\n" << str->getConstructorHelper(ir.locationManager);
188+
}
189+
}
190+
184191
s << "}\n\n";
185192

186193
return s;

bindgen/ir/Struct.cpp

Lines changed: 66 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,6 @@ Struct::generateHelperClass(const LocationManager &locationManager) const {
4444
}
4545
s << " }\n";
4646

47-
/* makes struct instantiation easier */
48-
s << " def "
49-
<< type + "()(implicit z: native.Zone): native.Ptr[" + type + "]"
50-
<< " = native.alloc[" + type + "]\n";
51-
5247
return s.str();
5348
}
5449

@@ -132,7 +127,8 @@ std::string Struct::generateSetterForStructRepresentation(
132127
unsigned fieldIndex, const LocationManager &locationManager) const {
133128
std::shared_ptr<Field> field = fields[fieldIndex];
134129
std::string setter = handleReservedWords(field->getName(), "_=");
135-
std::string parameterType = field->getType()->str(locationManager);
130+
std::string parameterType =
131+
wrapArrayOrRecordInPointer(field->getType())->str(locationManager);
136132
std::string value = "value";
137133
std::vector<std::shared_ptr<const Struct>> structTypesThatShouldBeReplaced =
138134
shouldFieldBreakCycle(field);
@@ -141,9 +137,7 @@ std::string Struct::generateSetterForStructRepresentation(
141137
std::shared_ptr<const Type> typeReplacement = getTypeReplacement(
142138
field->getType(), structTypesThatShouldBeReplaced);
143139
value = value + ".cast[" + typeReplacement->str(locationManager) + "]";
144-
} else if (isAliasForType<ArrayType>(field->getType().get()) ||
145-
isAliasForType<Struct>(field->getType().get())) {
146-
parameterType = "native.Ptr[" + parameterType + "]";
140+
} else if (isArrayOrRecord(field->getType())) {
147141
value = "!" + value;
148142
}
149143
std::stringstream s;
@@ -156,17 +150,16 @@ std::string Struct::generateGetterForStructRepresentation(
156150
unsigned fieldIndex, const LocationManager &locationManager) const {
157151
std::shared_ptr<Field> field = fields[fieldIndex];
158152
std::string getter = handleReservedWords(field->getName());
159-
std::string returnType = field->getType()->str(locationManager);
153+
std::string returnType =
154+
wrapArrayOrRecordInPointer(field->getType())->str(locationManager);
160155
std::string methodBody = "p._" + std::to_string(fieldIndex + 1);
161-
if (isAliasForType<ArrayType>(field->getType().get()) ||
162-
isAliasForType<Struct>(field->getType().get())) {
163-
returnType = "native.Ptr[" + returnType + "]";
164-
} else if (!shouldFieldBreakCycle(field).empty()) {
165-
/* field type is changed to avoid cyclic types in generated code */
166-
methodBody = "(!" + methodBody + ").cast[" +
167-
field->getType()->str(locationManager) + "]";
168-
} else {
156+
if (!isArrayOrRecord(field->getType())) {
169157
methodBody = "!" + methodBody;
158+
if (!shouldFieldBreakCycle(field).empty()) {
159+
/* field type is changed to avoid cyclic types in generated code */
160+
methodBody = "(" + methodBody + ").cast[" +
161+
field->getType()->str(locationManager) + "]";
162+
}
170163
}
171164
std::stringstream s;
172165
s << " def " << getter << ": " << returnType << " = " << methodBody
@@ -182,7 +175,8 @@ std::string Struct::generateSetterForArrayRepresentation(
182175
unsigned int fieldIndex, const LocationManager &locationManager) const {
183176
std::shared_ptr<Field> field = fields[fieldIndex];
184177
std::string setter = handleReservedWords(field->getName(), "_=");
185-
std::string parameterType = field->getType()->str(locationManager);
178+
std::string parameterType =
179+
wrapArrayOrRecordInPointer(field->getType())->str(locationManager);
186180
std::string value = "value";
187181
std::string castedField = "p._1";
188182

@@ -201,9 +195,7 @@ std::string Struct::generateSetterForArrayRepresentation(
201195
std::shared_ptr<const Type> typeReplacement = getTypeReplacement(
202196
field->getType(), structTypesThatShouldBeReplaced);
203197
value = value + ".cast[" + typeReplacement->str(locationManager) + "]";
204-
} else if (isAliasForType<ArrayType>(field->getType().get()) ||
205-
isAliasForType<Struct>(field->getType().get())) {
206-
parameterType = pointerToFieldType.str(locationManager);
198+
} else if (isArrayOrRecord(field->getType())) {
207199
value = "!" + value;
208200
}
209201
std::stringstream s;
@@ -217,7 +209,8 @@ std::string Struct::generateGetterForArrayRepresentation(
217209
unsigned fieldIndex, const LocationManager &locationManager) const {
218210
std::shared_ptr<Field> field = fields[fieldIndex];
219211
std::string getter = handleReservedWords(field->getName());
220-
std::string returnType;
212+
std::string returnType =
213+
wrapArrayOrRecordInPointer(field->getType())->str(locationManager);
221214
std::string methodBody;
222215

223216
PointerType pointerToFieldType = PointerType(field->getType());
@@ -230,17 +223,13 @@ std::string Struct::generateGetterForArrayRepresentation(
230223
methodBody =
231224
methodBody + ".cast[" + pointerToFieldType.str(locationManager) + "]";
232225

233-
if (isAliasForType<ArrayType>(field->getType().get()) ||
234-
isAliasForType<Struct>(field->getType().get())) {
235-
returnType = pointerToFieldType.str(locationManager);
236-
} else if (!shouldFieldBreakCycle(field).empty()) {
237-
/* field type is changed to avoid cyclic types in generated code */
238-
methodBody = "(!" + methodBody + ").cast[" +
239-
field->getType()->str(locationManager) + "]";
240-
returnType = field->getType()->str(locationManager);
241-
} else {
226+
if (!isArrayOrRecord(field->getType())) {
242227
methodBody = "!" + methodBody;
243-
returnType = field->getType()->str(locationManager);
228+
if (!shouldFieldBreakCycle(field).empty()) {
229+
/* field type is changed to avoid cyclic types in generated code */
230+
methodBody = "(" + methodBody + ").cast[" +
231+
field->getType()->str(locationManager) + "]";
232+
}
244233
}
245234
std::stringstream s;
246235
s << " def " << getter << ": " << returnType << " = " << methodBody
@@ -352,3 +341,47 @@ bool Struct::hasBiggestName(const CycleNode &node,
352341
}
353342
return false;
354343
}
344+
345+
std::string
346+
Struct::getConstructorHelper(const LocationManager &locationManager) const {
347+
std::stringstream s;
348+
std::string type = replaceChar(getTypeName(), " ", "_");
349+
s << " object " << type << " {\n"
350+
<< " import implicits._\n";
351+
352+
/* constructor with no parameters */
353+
s << " def apply()(implicit z: native.Zone): native.Ptr[" + type + "]"
354+
<< " = native.alloc[" + type + "]\n";
355+
356+
/* constructor that initializes all fields */
357+
s << " def apply(";
358+
std::string sep = "";
359+
for (const auto &field : fields) {
360+
s << sep << handleReservedWords(field->getName()) << ": "
361+
<< wrapArrayOrRecordInPointer(field->getType())->str(locationManager);
362+
sep = ", ";
363+
}
364+
s << ")(implicit z: native.Zone): native.Ptr[" << type << "] = {\n"
365+
<< " val ptr = native.alloc[" << type << "]\n";
366+
for (const auto &field : fields) {
367+
std::string name = handleReservedWords(field->getName());
368+
s << " ptr." << name << " = " << name << "\n";
369+
}
370+
s << " ptr\n"
371+
<< " }\n"
372+
<< " }\n";
373+
return s.str();
374+
}
375+
376+
bool Struct::isArrayOrRecord(std::shared_ptr<const Type> type) const {
377+
return isAliasForType<ArrayType>(type.get()) ||
378+
isAliasForType<Struct>(type.get());
379+
}
380+
381+
std::shared_ptr<const Type>
382+
Struct::wrapArrayOrRecordInPointer(std::shared_ptr<const Type> type) const {
383+
if (isArrayOrRecord(type)) {
384+
return std::make_shared<PointerType>(type);
385+
}
386+
return type;
387+
}

bindgen/ir/Struct.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ class Struct : public Record {
4141
const std::shared_ptr<const Struct> &startStruct, CycleNode &cycleNode,
4242
std::vector<std::shared_ptr<const Type>> &visitedTypes) const override;
4343

44+
std::string
45+
getConstructorHelper(const LocationManager &locationManager) const;
46+
4447
private:
4548
/** type size is needed if number of fields is bigger than 22 */
4649
uint64_t typeSize;
@@ -121,6 +124,14 @@ class Struct : public Record {
121124
*/
122125
bool hasBiggestName(const CycleNode &node,
123126
std::vector<std::string> namesInCycle) const;
127+
128+
bool isArrayOrRecord(std::shared_ptr<const Type> type) const;
129+
130+
/**
131+
* @return pointer to given type if given type is record or array
132+
*/
133+
std::shared_ptr<const Type>
134+
wrapArrayOrRecordInPointer(std::shared_ptr<const Type> type) const;
124135
};
125136

126137
#endif // SCALA_NATIVE_BINDGEN_STRUCT_H

tests/samples/AnonymousTypes.scala

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,31 +19,68 @@ object AnonymousTypes {
1919
def a: native.CChar = !p._1
2020
def a_=(value: native.CChar): Unit = !p._1 = value
2121
}
22-
def struct_anonymous_0()(implicit z: native.Zone): native.Ptr[struct_anonymous_0] = native.alloc[struct_anonymous_0]
2322

2423
implicit class struct_anonymous_1_ops(val p: native.Ptr[struct_anonymous_1]) extends AnyVal {
2524
def innerUnion: native.Ptr[union_anonymous_0] = !p._1
2625
def innerUnion_=(value: native.Ptr[union_anonymous_0]): Unit = !p._1 = value
2726
}
28-
def struct_anonymous_1()(implicit z: native.Zone): native.Ptr[struct_anonymous_1] = native.alloc[struct_anonymous_1]
2927

3028
implicit class struct_StructWithAnonymousStruct_ops(val p: native.Ptr[struct_StructWithAnonymousStruct]) extends AnyVal {
3129
def innerStruct: native.Ptr[struct_anonymous_1] = !p._1
3230
def innerStruct_=(value: native.Ptr[struct_anonymous_1]): Unit = !p._1 = value
3331
def innerEnum: native.CUnsignedInt = !p._2
3432
def innerEnum_=(value: native.CUnsignedInt): Unit = !p._2 = value
3533
}
36-
def struct_StructWithAnonymousStruct()(implicit z: native.Zone): native.Ptr[struct_StructWithAnonymousStruct] = native.alloc[struct_StructWithAnonymousStruct]
3734

3835
implicit class struct_anonymous_2_ops(val p: native.Ptr[struct_anonymous_2]) extends AnyVal {
3936
def result: native.CInt = !p._1
4037
def result_=(value: native.CInt): Unit = !p._1 = value
4138
}
42-
def struct_anonymous_2()(implicit z: native.Zone): native.Ptr[struct_anonymous_2] = native.alloc[struct_anonymous_2]
4339

4440
implicit class union_anonymous_0_pos(val p: native.Ptr[union_anonymous_0]) extends AnyVal {
4541
def a: native.Ptr[native.CLong] = p.cast[native.Ptr[native.CLong]]
4642
def a_=(value: native.CLong): Unit = !p.cast[native.Ptr[native.CLong]] = value
4743
}
4844
}
45+
46+
object struct_anonymous_0 {
47+
import implicits._
48+
def apply()(implicit z: native.Zone): native.Ptr[struct_anonymous_0] = native.alloc[struct_anonymous_0]
49+
def apply(a: native.CChar)(implicit z: native.Zone): native.Ptr[struct_anonymous_0] = {
50+
val ptr = native.alloc[struct_anonymous_0]
51+
ptr.a = a
52+
ptr
53+
}
54+
}
55+
56+
object struct_anonymous_1 {
57+
import implicits._
58+
def apply()(implicit z: native.Zone): native.Ptr[struct_anonymous_1] = native.alloc[struct_anonymous_1]
59+
def apply(innerUnion: native.Ptr[union_anonymous_0])(implicit z: native.Zone): native.Ptr[struct_anonymous_1] = {
60+
val ptr = native.alloc[struct_anonymous_1]
61+
ptr.innerUnion = innerUnion
62+
ptr
63+
}
64+
}
65+
66+
object struct_StructWithAnonymousStruct {
67+
import implicits._
68+
def apply()(implicit z: native.Zone): native.Ptr[struct_StructWithAnonymousStruct] = native.alloc[struct_StructWithAnonymousStruct]
69+
def apply(innerStruct: native.Ptr[struct_anonymous_1], innerEnum: native.CUnsignedInt)(implicit z: native.Zone): native.Ptr[struct_StructWithAnonymousStruct] = {
70+
val ptr = native.alloc[struct_StructWithAnonymousStruct]
71+
ptr.innerStruct = innerStruct
72+
ptr.innerEnum = innerEnum
73+
ptr
74+
}
75+
}
76+
77+
object struct_anonymous_2 {
78+
import implicits._
79+
def apply()(implicit z: native.Zone): native.Ptr[struct_anonymous_2] = native.alloc[struct_anonymous_2]
80+
def apply(result: native.CInt)(implicit z: native.Zone): native.Ptr[struct_anonymous_2] = {
81+
val ptr = native.alloc[struct_anonymous_2]
82+
ptr.result = result
83+
ptr
84+
}
85+
}
4986
}

0 commit comments

Comments
 (0)