Skip to content

Commit c2f9223

Browse files
committed
feat(Lib): enum_impl intEnum, enumType
1 parent 05e1e70 commit c2f9223

File tree

2 files changed

+82
-0
lines changed

2 files changed

+82
-0
lines changed

src/pylib/Lib/enum_impl/enumType.nim

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#
2+
import std/[hashes, tables, strformat]
3+
import ../../pyerrors/simperr
4+
5+
template GenPyEnumMeth*(Self, Value: typedesc; genObjMeth = true, nameError = NameError, Str = string){.dirty.} =
6+
## XXX: NIM-BUG: as `std/tables` is not working with `bind` once required at compile time,
7+
## `import std/tables` is a must before using this template.
8+
bind contains, `[]`
9+
bind hash, Table, Hash, withValue, `[]=`, `$`, items, len, fmt, formatValue
10+
11+
var `Self.names`{.genSym, compileTime.}: Table[Value, string] ## self._name_
12+
var `Self.member_map`{.genSym, compileTime.}: Table[Str, Self] ## cls._member_map_
13+
14+
using self: Self
15+
using cls: typedesc[Self]
16+
proc value*(self): Value{.inline.} = Value(self)
17+
18+
proc name*(self): Str{.inline.} = `Self.names`[self.value]
19+
proc `name=`(self; name: Str){.inline.} = `Self.names`[self.value] = name
20+
proc repr*(self): Str =
21+
let vr = when compiles(typeof(self).value_repr(self.value)):
22+
typeof(self).value_repr(self.value)
23+
else:
24+
repr(self.value)
25+
fmt"<{$typeof(self)} {self.name}: {vr}>"
26+
27+
proc `$`*(self): string =
28+
fmt"{$typeof(self)}.{self.name}"
29+
proc hash*(self): Hash = hash(`Self.names`[self.value])
30+
when genObjMeth:
31+
proc `==`*(self; other: Self): bool = self.value == other.value
32+
proc add_member(cls; name: Str, self) =
33+
if name in `Self.member_map`:
34+
if `Self.member_map`[name] != self:
35+
let s = repr(`Self.member_map`[name])
36+
raise newException(nameError, fmt"{repr(name)} is already bound: {s}")
37+
return
38+
# XXX: Python here also need to handle property and class attribute
39+
`Self.member_map`[name] = self
40+
proc add_alias*(self; name: Str) = Self.add_member(name, self)
41+
42+
43+
# _simple_enum's convert_class's Enum / IntEnum / StrEnum branch
44+
proc add_member*(enum_class: typedesc[Self]; name: Str, value: Value): Self =
45+
let member = Self(value)
46+
`Self.member_map`.withValue name, contained:
47+
# an alias to an existing member
48+
contained[].add_alias(name)
49+
result = contained[]
50+
do:
51+
# finish creating member
52+
member.name = name
53+
enum_class.add_member(name, member)
54+
result = member
55+
56+
57+
58+
proc `[]`*(cls; name: string): Self = `Self.member_map`[name]
59+
proc len*(cls): int = len `Self.names`
60+
iterator items*(cls): Self =
61+
for k in `Self.names`.keys(): yield k
62+
63+
template contains*(cls; value: Self): bool = true
64+
proc contains*(cls; value: Value): bool =
65+
`Self.names`.withValue value, name:
66+
return name in `Self.member_map`
67+

src/pylib/Lib/enum_impl/intEnum.nim

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
import ./enumType
3+
4+
5+
6+
7+
template GenIntEnumMeth*(Self: typedesc; Int = int){.dirty.} =
8+
bind GenPyEnumMeth
9+
GenPyEnumMeth(Self, Int)
10+
converter toInt*(self: Self): Int = self.Int
11+
12+
template DeclIntEnumMeth*(Self; Int = int){.dirty.} =
13+
bind GenIntEnumMeth
14+
type Self = distinct Int
15+
GenIntEnumMeth(Self, Int)

0 commit comments

Comments
 (0)