@ -6,6 +6,8 @@ export @enumx
@@ -6,6 +6,8 @@ export @enumx
abstract type Enum { T } <: Base . Enum { T } end
panic ( x ) = throw ( ArgumentError ( x ) )
macro enumx ( args ... )
return enumx ( __module__ , args ... )
end
@ -14,11 +16,12 @@ function enumx(_module_, name, args...)
@@ -14,11 +16,12 @@ function enumx(_module_, name, args...)
if name isa Symbol
modname = name
baseT = Int32
elseif name isa Expr && name . head == : ( :: ) && name . args [ 1 ] isa Symbol && length ( name . args ) == 2
elseif name isa Expr && name . head == : ( :: ) && name . args [ 1 ] isa Symbol &&
length ( name . args ) == 2
modname = name . args [ 1 ]
baseT = Core . eval ( _module_ , name . args [ 2 ] )
else
throw ( ArgumentError ( " invalid EnumX.@enumx type specification: $ ( name ) " ) )
panic ( " invalid EnumX.@enumx type specification: $ ( name ) . " )
end
name = modname
if length ( args ) == 1 && args [ 1 ] isa Expr && args [ 1 ] . head === :block
@ -27,18 +30,49 @@ function enumx(_module_, name, args...)
@@ -27,18 +30,49 @@ function enumx(_module_, name, args...)
syms = args
end
namemap = Dict { baseT , Symbol } ( )
next = 0
next = zero ( baseT )
for s in syms
s isa LineNumberNode && continue
s isa Symbol || throw ( ArgumentError ( " invalid member expression: $ ( s ) " ) )
namemap [ next ] = s
next += 1
local sym
if s isa Symbol
if next == typemin ( baseT )
panic ( " value overflow for Enum $ ( modname ) : $ ( modname ) . $ ( s ) = $ ( next ) . " )
end
sym = s
elseif s isa Expr && s . head === : ( = ) && s . args [ 1 ] isa Symbol && length ( s . args ) == 2
nx = Core . eval ( _module_ , s . args [ 2 ] )
if ! ( nx isa Integer && typemin ( baseT ) <= nx <= typemax ( baseT ) )
panic (
" invalid value for Enum $ ( modname ) { $ ( baseT ) }: " *
" $ ( modname ) . $ ( s . args [ 1 ] ) = $ ( repr ( nx ) ) . "
)
end
next = convert ( baseT , nx )
sym = s . args [ 1 ]
else
panic ( " invalid EnumX.@enumx entry: $ ( s ) " )
end
if next in keys ( namemap )
panic (
" duplicate value for Enum $ ( modname ) : $ ( modname ) . $ ( sym ) = $ ( next ) , " *
" value already used for $ ( modname ) . $ ( namemap [ next ] ) = $ ( next ) . "
)
elseif sym in values ( namemap )
value = findfirst ( x -> x === sym , namemap )
panic (
" duplicate name for Enum $ ( modname ) : $ ( modname ) . $ ( sym ) = $ ( next ) , " *
" name already used for $ ( modname ) . $ ( namemap [ value ] ) = $ ( value ) . "
)
end
namemap [ next ] = sym
next += oneunit ( baseT )
end
module_block = quote
primitive type Type <: Enum { $ ( baseT ) } $ ( sizeof ( baseT ) * 8 ) end
let namemap = $ ( namemap )
check_valid ( x ) = x in keys ( namemap ) ||
throw ( ArgumentError ( " invalid value $ ( x ) for Enum $ ( $ ( QuoteNode ( modname ) ) ) " ) )
throw ( ArgumentError ( " invalid value for Enum $ ( $ ( QuoteNode ( modname ) ) ) : $ ( x ) . " ) )
global function $ ( esc ( :Type ) ) ( x :: Integer )
check_valid ( x )
return Base . bitcast ( $ ( esc ( :Type ) ) , convert ( $ ( baseT ) , x ) )
@ -68,7 +102,10 @@ function Base.show(io::IO, ::MIME"text/plain", ::Base.Type{E}) where E <: Enum
@@ -68,7 +102,10 @@ function Base.show(io::IO, ::MIME"text/plain", ::Base.Type{E}) where E <: Enum
string ( " $ ( nameof ( parentmodule ( E ) ) ) . " , v ) => k for ( k , v ) in Base . Enums . namemap ( E )
)
mx = maximum ( textwidth , keys ( stringmap ) ; init = 0 )
print ( iob , " Enum type $ ( nameof ( parentmodule ( E ) ) ) .Type <: Enum{ $ ( Base . Enums . basetype ( E ) ) } with $ ( n ) instance $ ( n == 1 ? " " : " s " ) : " )
print ( iob ,
" Enum type $ ( nameof ( parentmodule ( E ) ) ) .Type <: " ,
" Enum{ $ ( Base . Enums . basetype ( E ) ) } with $ ( n ) instance $ ( n == 1 ? " " : " s " ) : "
)
for ( k , v ) in stringmap
print ( iob , " \n " , rpad ( k , mx ) , " = $ ( v ) " )
end