Skip to content

Commit 34ff98a

Browse files
committed
Move enums to main object
1 parent d97e6b9 commit 34ff98a

22 files changed

+278
-196
lines changed

bindgen/ir/Enum.cpp

Lines changed: 53 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -7,57 +7,72 @@ std::string Enumerator::getName() { return name; }
77

88
int64_t Enumerator::getValue() { return value; }
99

10-
Enum::Enum(std::string name, std::string type,
11-
std::vector<Enumerator> enumerators,
10+
Enum::Enum(std::string type, std::vector<Enumerator> enumerators,
1211
std::shared_ptr<Location> location)
1312
: PrimitiveType(std::move(type)), LocatableType(std::move(location)),
14-
name(std::move(name)), enumerators(std::move(enumerators)) {}
13+
enumerators(std::move(enumerators)) {}
1514

16-
bool Enum::isAnonymous() const { return name.empty(); }
17-
18-
std::string Enum::getDefinition() {
19-
return " type " + getTypeAlias() + " = " + PrimitiveType::str() + "\n";
15+
std::string Enum::getEnumerators() const {
16+
std::stringstream s;
17+
std::string typeCastSuffix = getTypeCastSuffix();
18+
s << " object " << getObjectName() << " {\n";
19+
for (auto enumerator : enumerators) {
20+
std::string enumeratorsType = getEnumeratorsType();
21+
s << " final val " << enumerator.getName();
22+
s << ": " << enumeratorsType << " = "
23+
<< std::to_string(enumerator.getValue()) << typeCastSuffix << "\n";
24+
}
25+
s << " }\n";
26+
return s.str();
2027
}
2128

22-
llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const Enum &e) {
23-
for (auto enumerator : e.enumerators) {
24-
std::string enumeratorName;
25-
if (!e.name.empty()) {
26-
enumeratorName = "enum_" + e.name + "_" + enumerator.getName();
27-
} else {
28-
enumeratorName = "enum_" + enumerator.getName();
29-
}
30-
s << " final val " << enumeratorName;
31-
std::string type;
32-
if (e.isAnonymous()) {
33-
type = e.getType();
34-
} else {
35-
type = "enum_" + e.name;
36-
}
37-
s << ": " << type << " = " << std::to_string(enumerator.getValue());
38-
39-
if (e.getType() == "native.CLong") {
40-
s << "L";
41-
} else if (e.getType() == "native.CUnsignedInt") {
42-
s << ".toUInt";
43-
} else if (e.getType() == "native.CUnsignedLong") {
44-
s << "L.toULong";
45-
}
46-
s << "\n";
29+
std::string Enum::getTypeCastSuffix() const {
30+
std::string primitiveType = PrimitiveType::getType();
31+
if (primitiveType == "native.CLong") {
32+
return "L";
33+
} else if (primitiveType == "native.CUnsignedInt") {
34+
return ".toUInt";
35+
} else if (primitiveType == "native.CUnsignedLong") {
36+
return "L.toULong";
4737
}
48-
return s;
38+
return "";
4939
}
5040

51-
std::string Enum::getName() const { return name; }
41+
AnonymousEnum::AnonymousEnum(uint id, std::string type,
42+
std::vector<Enumerator> enumerators,
43+
std::shared_ptr<Location> location)
44+
: Enum(std::move(type), std::move(enumerators), std::move(location)),
45+
id(id) {}
5246

53-
std::string Enum::getTypeAlias() const {
54-
assert(!isAnonymous());
55-
return "enum_" + name;
47+
std::string AnonymousEnum::getObjectName() const {
48+
return "anonymous_enum_" + std::to_string(id);
5649
}
5750

58-
std::string Enum::str(const LocationManager &locationManager) const {
51+
std::string AnonymousEnum::getEnumeratorsType() const {
52+
return PrimitiveType::getType();
53+
}
54+
55+
NamedEnum::NamedEnum(std::string name, std::string type,
56+
std::vector<Enumerator> enumerators,
57+
std::shared_ptr<Location> location)
58+
: Enum(std::move(type), std::move(enumerators), std::move(location)),
59+
name(std::move(name)) {}
60+
61+
std::string NamedEnum::str(const LocationManager &locationManager) const {
5962
if (locationManager.isImported(*location)) {
6063
return locationManager.getImportedType(*location, getTypeAlias());
6164
}
6265
return getTypeAlias();
6366
}
67+
68+
std::string NamedEnum::getTypeAlias() const { return "enum_" + name; }
69+
70+
std::string NamedEnum::getDefinition() const {
71+
return " type " + getTypeAlias() + " = " + PrimitiveType::str() + "\n";
72+
}
73+
74+
std::string NamedEnum::getEnumeratorsType() const { return getTypeAlias(); }
75+
76+
std::string NamedEnum::getObjectName() const { return getTypeAlias(); }
77+
78+
std::string NamedEnum::getName() const { return name; }

bindgen/ir/Enum.h

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,66 @@ class Enumerator {
2121

2222
class Enum : public PrimitiveType, public LocatableType {
2323
public:
24-
Enum(std::string name, std::string type,
25-
std::vector<Enumerator> enumerators,
24+
Enum(std::string type, std::vector<Enumerator> enumerators,
2625
std::shared_ptr<Location> location);
2726

28-
bool isAnonymous() const;
27+
/**
28+
* @return a string that contains all enumerators.
29+
* If enum is not anonymous then enumerators are inside an object
30+
* with the same name as enum type.
31+
*/
32+
std::string getEnumerators() const;
2933

30-
std::string getDefinition();
34+
protected:
35+
/**
36+
* @return name of object that contains enumerators.
37+
*/
38+
virtual std::string getObjectName() const = 0;
3139

32-
std::string getName() const;
40+
virtual std::string getEnumeratorsType() const = 0;
41+
42+
private:
43+
std::vector<Enumerator> enumerators;
3344

34-
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const Enum &e);
45+
std::string getTypeCastSuffix() const;
46+
};
3547

36-
std::string getTypeAlias() const;
48+
class AnonymousEnum : public Enum {
49+
public:
50+
AnonymousEnum(uint id, std::string type,
51+
std::vector<Enumerator> enumerators,
52+
std::shared_ptr<Location> location);
53+
54+
protected:
55+
std::string getObjectName() const override;
56+
57+
std::string getEnumeratorsType() const override;
58+
59+
private:
60+
uint id;
61+
};
62+
63+
class NamedEnum : public Enum {
64+
public:
65+
NamedEnum(std::string name, std::string type,
66+
std::vector<Enumerator> enumerators,
67+
std::shared_ptr<Location> location);
3768

3869
std::string str(const LocationManager &locationManager) const override;
3970

71+
std::string getName() const;
72+
73+
std::string getDefinition() const;
74+
75+
protected:
76+
std::string getObjectName() const override;
77+
78+
std::string getEnumeratorsType() const override;
79+
4080
private:
41-
std::string name; // might be empty
42-
std::vector<Enumerator> enumerators;
81+
std::string name;
82+
83+
std::string getTypeAlias() const;
4384
};
4485

4586
#endif // SCALA_NATIVE_BINDGEN_ENUM_H

bindgen/ir/IR.cpp

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,23 @@ std::shared_ptr<TypeDef> IR::addTypeDef(std::string name,
2222
return typeDefs.back();
2323
}
2424

25-
std::shared_ptr<Enum> IR::addEnum(std::string name, const std::string &type,
26-
std::vector<Enumerator> enumerators,
27-
std::shared_ptr<Location> location) {
28-
std::shared_ptr<Enum> e = std::make_shared<Enum>(
25+
std::shared_ptr<NamedEnum> IR::addEnum(std::string name,
26+
const std::string &type,
27+
std::vector<Enumerator> enumerators,
28+
std::shared_ptr<Location> location) {
29+
std::shared_ptr<NamedEnum> e = std::make_shared<NamedEnum>(
2930
std::move(name), type, std::move(enumerators), std::move(location));
30-
3131
enums.push_back(e);
32+
return e;
33+
}
3234

35+
std::shared_ptr<AnonymousEnum> IR::addEnum(uint id, const std::string &type,
36+
std::vector<Enumerator> enumerators,
37+
std::shared_ptr<Location> location) {
38+
std::shared_ptr<AnonymousEnum> e = std::make_shared<AnonymousEnum>(
39+
id, type, std::move(enumerators), std::move(location));
40+
41+
enums.push_back(e);
3342
return e;
3443
}
3544

@@ -122,8 +131,12 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
122131

123132
for (const auto &e : ir.enums) {
124133
visitedTypes.clear();
125-
if (!e->isAnonymous() && ir.shouldOutput(e, visitedTypes)) {
126-
s << e->getDefinition();
134+
if (ir.shouldOutput(e, visitedTypes)) {
135+
auto namedEnumPtr = std::dynamic_pointer_cast<NamedEnum>(e);
136+
if (namedEnumPtr) {
137+
s << namedEnumPtr->getDefinition();
138+
}
139+
s << e->getEnumerators() << "\n";
127140
}
128141
}
129142

@@ -184,25 +197,10 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
184197
s << "}\n\n";
185198
}
186199

187-
if (ir.shouldOutputType(ir.enums) || ir.hasHelperMethods()) {
200+
if (ir.hasHelperMethods()) {
188201
s << "import " << objectName << "._\n\n";
189202
}
190203

191-
if (ir.shouldOutputType(ir.enums)) {
192-
s << "object " << ir.libName << "Enums {\n";
193-
194-
std::string sep = "";
195-
for (const auto &e : ir.enums) {
196-
visitedTypes.clear();
197-
if (ir.shouldOutput(e, visitedTypes)) {
198-
s << sep << *e;
199-
sep = "\n";
200-
}
201-
}
202-
203-
s << "}\n\n";
204-
}
205-
206204
if (ir.hasHelperMethods()) {
207205
s << "object " << ir.libName << "Helpers {\n";
208206

@@ -443,7 +441,13 @@ std::shared_ptr<TypeDef> IR::getTypeDefWithName(const std::string &name) const {
443441
}
444442

445443
std::shared_ptr<Enum> IR::getEnumWithName(const std::string &name) const {
446-
return getDeclarationWithName(enums, name);
444+
for (const auto &e : enums) {
445+
auto namedEnumPtr = std::dynamic_pointer_cast<NamedEnum>(e);
446+
if (namedEnumPtr && namedEnumPtr->getName() == name) {
447+
return namedEnumPtr;
448+
}
449+
}
450+
return nullptr;
447451
}
448452

449453
template <typename T>

bindgen/ir/IR.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,14 @@ class IR {
2929
std::shared_ptr<Type> type,
3030
std::shared_ptr<Location> location);
3131

32-
std::shared_ptr<Enum> addEnum(std::string name, const std::string &type,
33-
std::vector<Enumerator> enumerators,
34-
std::shared_ptr<Location> location);
32+
std::shared_ptr<NamedEnum> addEnum(std::string name,
33+
const std::string &type,
34+
std::vector<Enumerator> enumerators,
35+
std::shared_ptr<Location> location);
36+
37+
std::shared_ptr<AnonymousEnum> addEnum(uint id, const std::string &type,
38+
std::vector<Enumerator> enumerators,
39+
std::shared_ptr<Location> location);
3540

3641
std::shared_ptr<TypeDef>
3742
addStruct(std::string name, std::vector<std::shared_ptr<Field>> fields,

bindgen/visitor/TreeVisitor.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,14 @@ bool TreeVisitor::VisitEnumDecl(clang::EnumDecl *enumDecl) {
7474
std::string scalaType = typeTranslator.getTypeFromTypeMap(
7575
enumDecl->getIntegerType().getUnqualifiedType().getAsString());
7676

77-
std::shared_ptr<Enum> e =
78-
ir.addEnum(name, scalaType, std::move(enumerators),
79-
typeTranslator.getLocation(enumDecl));
77+
std::shared_ptr<Location> location = typeTranslator.getLocation(enumDecl);
78+
std::shared_ptr<Enum> e;
79+
if (name.empty()) {
80+
e = ir.addEnum(anonymousEnumId++, scalaType, std::move(enumerators),
81+
location);
82+
} else {
83+
e = ir.addEnum(name, scalaType, std::move(enumerators), location);
84+
}
8085

8186
if (typedefName) {
8287
ir.addTypeDef(name, e, typeTranslator.getLocation(typedefName));

bindgen/visitor/TreeVisitor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ class TreeVisitor : public clang::RecursiveASTVisitor<TreeVisitor> {
1010
clang::ASTContext *astContext;
1111
TypeTranslator typeTranslator;
1212
IR &ir;
13+
uint anonymousEnumId = 0;
1314

1415
bool isAliasForAnonymousEnum(clang::TypedefDecl *tpdef) const;
1516

tests/samples/CustomNames.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ import scala.scalanative.native._
66
@native.link("bindgentests")
77
@native.extern
88
object CustomNames {
9+
type enum_enumWithTypedef = native.CUnsignedInt
10+
object enum_enumWithTypedef {
11+
final val CONST: enum_enumWithTypedef = 0.toUInt
12+
}
13+
14+
type EnumWithTypedef = enum_enumWithTypedef
915
type page = native.CStruct2[native.CString, native.Ptr[Byte]]
1016
type book = native.CStruct1[native.Ptr[page]]
1117
type MY_INT = native.CInt

tests/samples/Enum.scala

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,33 +7,39 @@ import scala.scalanative.native._
77
@native.extern
88
object Enum {
99
type enum_days = native.CUnsignedInt
10-
type enum_bigValues = native.CUnsignedLong
11-
type enum_negativeValues = native.CInt
12-
type enum_bigNegativeValues = native.CLong
13-
def get_WEDNESDAY(): enum_days = native.extern
14-
def check_BIG_NEG_A(big_neg_a: enum_bigNegativeValues): native.CString = native.extern
15-
}
10+
object enum_days {
11+
final val MONDAY: enum_days = 0.toUInt
12+
final val TUESDAY: enum_days = 200.toUInt
13+
final val WEDNESDAY: enum_days = 201.toUInt
14+
final val THURSDAY: enum_days = 4.toUInt
15+
final val FRIDAY: enum_days = 5.toUInt
16+
final val SATURDAY: enum_days = 3.toUInt
17+
final val SUNDAY: enum_days = 4.toUInt
18+
}
1619

17-
import Enum._
18-
19-
object EnumEnums {
20-
final val enum_days_MONDAY: enum_days = 0.toUInt
21-
final val enum_days_TUESDAY: enum_days = 200.toUInt
22-
final val enum_days_WEDNESDAY: enum_days = 201.toUInt
23-
final val enum_days_THURSDAY: enum_days = 4.toUInt
24-
final val enum_days_FRIDAY: enum_days = 5.toUInt
25-
final val enum_days_SATURDAY: enum_days = 3.toUInt
26-
final val enum_days_SUNDAY: enum_days = 4.toUInt
20+
type enum_bigValues = native.CUnsignedLong
21+
object enum_bigValues {
22+
final val BIG_A: enum_bigValues = 10000000000L.toULong
23+
final val BIG_B: enum_bigValues = 1L.toULong
24+
}
2725

28-
final val enum_bigValues_BIG_A: enum_bigValues = 10000000000L.toULong
29-
final val enum_bigValues_BIG_B: enum_bigValues = 1L.toULong
26+
object anonymous_enum_0 {
27+
final val ANON_A: native.CUnsignedInt = 0.toUInt
28+
final val ANON_B: native.CUnsignedInt = 1.toUInt
29+
}
3030

31-
final val enum_ANON_A: native.CUnsignedInt = 0.toUInt
32-
final val enum_ANON_B: native.CUnsignedInt = 1.toUInt
31+
type enum_negativeValues = native.CInt
32+
object enum_negativeValues {
33+
final val NEG_A: enum_negativeValues = -1
34+
final val NEG_B: enum_negativeValues = -2
35+
}
3336

34-
final val enum_negativeValues_NEG_A: enum_negativeValues = -1
35-
final val enum_negativeValues_NEG_B: enum_negativeValues = -2
37+
type enum_bigNegativeValues = native.CLong
38+
object enum_bigNegativeValues {
39+
final val BIG_NEG_A: enum_bigNegativeValues = -10000000000L
40+
final val BIG_NEG_B: enum_bigNegativeValues = -1L
41+
}
3642

37-
final val enum_bigNegativeValues_BIG_NEG_A: enum_bigNegativeValues = -10000000000L
38-
final val enum_bigNegativeValues_BIG_NEG_B: enum_bigNegativeValues = -1L
43+
def get_WEDNESDAY(): enum_days = native.extern
44+
def check_BIG_NEG_A(big_neg_a: enum_bigNegativeValues): native.CString = native.extern
3945
}

0 commit comments

Comments
 (0)