Enum/Enumerator in BMax (Types-basierend)

Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Neue Antwort erstellen

 

Shaman

Betreff: Enum/Enumerator in BMax (Types-basierend)

BeitragFr, Nov 04, 2011 6:15
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo.
Jeder von euch kennt sicher das Problem, dass BlitzMax keine Enums unterstützt.
Dieses Problem wurde häufig dadurch umgangen, dass Enums durch Integer-Konstanten realisiert wurden.
Mir hat diese Lösung nie ganz gefallen, desshalb hab ich mir ein anderes Enum-System überlegt:

Dieses System basiert auf Types, es ist typsicher und unterstützt Standartfunktionen wie toString, fromName, u.s.w., wie aus andren Sprachen wie Java bekannt.

Die Idee ist, dass das Enum ein Type ist, die Elemente des Enums sind Globale Felder mit Zeiger auf eine Instanz des Types.
Somit wird immer ein Zeiger übergeben, und Zeiger verglichen.

Da dieses System sehr schreibintensiv ist, hab ich eine Funktion geschrieben,
die so ein Enum erstellt:
Code: [AUSKLAPPEN]

Function BuildEnum:String(name:String, enums:String[], withID:Int = 1, withName:Int = 1, withToString:Int = 1, generateDoc:Int = 1, autoInit:Int = 1)
   Local file:String = "'This file was built with EnumBuilder ~n'made by Shaman~n"
   'Write Header
   If generateDoc = 1 Then
      file:+"Rem~n"
      file:+"~tbbdoc: Enumerator " + name + "~n"
      file:+"End Rem~n"
   End If
   file:+"Type " + name + "~n~n"
   Local i:Int
   
   'Write Constants
   For i = 0 Until enums.Length
      If generateDoc = 1 Then
         file:+"~tRem~n"
         file:+"~t~tbbdoc: Enumerator item " + enums[i] + "~n"
         file:+"~tEnd Rem~n"
      End If
      file:+"~tGlobal " + enums[i] + ":" + name + "~n"
   Next
   file:+"~n"
   
   'Write ID
   If withID = 1 Then
      file:+"~t'Enum items have an ID~n"
      file:+"~tField _id:Int~n"
      If generateDoc = 1 Then
         file:+"~tRem~n"
         file:+"~t~tbbdoc: Returns the ID of the enum item~n"
         file:+"~tEnd Rem~n"
      EndIf
      file:+"~tMethod getID:Int()~n"
      file:+"~t~tReturn Self._id~n"
      file:+"~tEnd Method~n~n"
   End If
   
   'Write Names
   If withName = 1 Then
      file:+"~t'Enum items have a name~n"
      file:+"~tField _name:String~n"
      If generateDoc = 1 Then
         file:+"~tRem~n"
         file:+"~t~tbbdoc: Returns the name of the enum item~n"
         file:+"~tEnd Rem~n"
      EndIf
      file:+"~tMethod getName:String()~n"
      file:+"~t~tReturn Self._name~n"
      file:+"~tEnd Method~n~n"
   End If
   
   'Write toString
   If withToString = 1 And withName = 1 Then
      file:+"~t'Overloaded toString() -  Method~n"
      file:+"~tConst ENUM_NAME:String = " + Chr(34) + name + Chr(34) + "~n"
      If generateDoc = 1 Then
         file:+"~tRem~n"
         file:+"~t~tbbdoc: Returns the enum name followed by the item name~n"
         file:+"~t~tabout: Example return: " + name + "." + enums[0] + "~n"
         file:+"~tEnd Rem~n"
      End If
      file:+"~tMethod toString:String()~n"
      file:+"~t~tReturn " + name + ".ENUM_NAME + " + Chr(34) + "." + Chr(34) + " + Self._name~n"
      file:+"~tEnd Method~n~n"
   End If
   
   'Generate Function FromID
   If withID = 1 Then
      file:+"~t'Gets the enum element by its ID, opposite of getID()~n"
      If generateDoc = 1 Then
         file:+"~tRem~n"
         file:+"~t~tbbdoc: Returns an element of the enum by its ID~n"
         file:+"~t~tabout: That's the opposite of getID()~n"
         file:+"~tEnd Rem~n"
      End If
      file:+"~tFunction FromID:" + name + "(id:Int)~n"
      file:+"~t~tSelect id~n"
      For i = 0 Until enums.Length
         file:+"~t~t~tCase " + (i + 1) + " Return " + name + "." + enums[i] + "~n"
      Next
      file:+"~t~t~tDefault Return Null~n"
      file:+"~t~tEnd Select~n"
      file:+"~tEnd Function~n~n"
   End If
   
   'generate Function FromName
   If withName = 1 Then
      file:+"~t'Gets the enum element by its name, opposite of getName()~n"
      If generateDoc = 1 Then
         file:+"~tRem~n"
         file:+"~t~tbbdoc: Returns an element of the enum by its Name~n"
         file:+"~t~tabout: Opposite of getName()~n"
         file:+"~tEnd Rem~n"
      End If
      file:+"~tFunction FromName:" + name + "(name:String)~n"
      file:+"~t~tSelect name~n"
      For i = 0 Until enums.Length
         file:+"~t~t~tCase " + Chr(34) + enums[i] + Chr(34) + " Return " + name + "." + enums[i] + "~n"
      Next
      file:+"~t~t~tDefault Return Null~n"
      file:+"~t~tEnd Select~n"
      file:+"~tEnd Function~n~n"
   End If
   
   Local both:Int = 0
   If withID = 1 And withName = 1 Then
      both = 1
      file:+"~t'Create Function for less code~n"
      file:+"~tFunction Create:" + name + "(id:Int,name:String)~n"
      file:+"~t~tLocal e:" + name + " = new " + name + "~n"
      file:+"~t~te._id = id~n"
      file:+"~t~te._name = name~n"
      file:+"~t~tReturn e~n"
      file:+"~tEnd Function~n~n"
   End If
   
   'Write Init
   file:+"~tFunction init()~n"
   For i = 0 Until enums.Length
      If both = 0 Then
         file:+"~t~t" + name + "." + enums[i] + " = new " + name + "~n"
         If withID = 1 Then
            file:+"~t~t" + name + "." + enums[i] + "._id = " + (i + 1) + "~n"
         End If
         If withName = 1 Then
            file:+"~t~t" + name + "." + enums[i] + "._name = " + Chr(34) + enums[i] + Chr(34) + "~n"
         EndIf
      Else
         file:+"~t~t" + name + "." + enums[i] + " = " + name + ".Create(" + (i + 1) + ", " + Chr(34) + enums[i] + Chr(34) + ")~n"
      EndIf
   Next
   file:+"~tEnd Function~n"
   
   'Write End
   file:+"End Type~n"
   
   'Write auto init
   If autoInit = 1 Then
      file:+"~n'automatically initialized~n"
      file:+name + ".init()"
   End If
   
   Return file
End Function

Sie liefert einen String zurück welcher, direkt in eine Datei geschrieben,
die fertige BMX-Datei enthält.

Ein Beispiel:
Der Code:
Code: [AUSKLAPPEN]

Local testEnum:String[] = ["A", "B", "C", "D", "E", "F"]
Local s:String = BuildEnum("TTestEnum", testEnum)
Print s


erzeugt ein Enum mit den Elenenten A,B,C,D,E und F.
der erzeugte Code ist:
Code: [AUSKLAPPEN]

'This file was built with EnumBuilder
'made by Shaman
Rem
   bbdoc: Enumerator TTestEnum
End Rem
Type TTestEnum

   Rem
      bbdoc: Enumerator item A
   End Rem
   Global A:TTestEnum
   Rem
      bbdoc: Enumerator item B
   End Rem
   Global B:TTestEnum
   Rem
      bbdoc: Enumerator item C
   End Rem
   Global C:TTestEnum
   Rem
      bbdoc: Enumerator item D
   End Rem
   Global D:TTestEnum
   Rem
      bbdoc: Enumerator item E
   End Rem
   Global E:TTestEnum
   Rem
      bbdoc: Enumerator item F
   End Rem
   Global F:TTestEnum

   'Enum items have an ID
   Field _id:Int
   Rem
      bbdoc: Returns the ID of the enum item
   End Rem
   Method getID:Int()
      Return Self._id
   End Method

   'Enum items have a name
   Field _name:String
   Rem
      bbdoc: Returns the name of the enum item
   End Rem
   Method getName:String()
      Return Self._name
   End Method

   'Overloaded toString() -  Method
   Const ENUM_NAME:String = "TTestEnum"
   Rem
      bbdoc: Returns the enum name followed by the item name
      about: Example return: TTestEnum.A
   End Rem
   Method toString:String()
      Return TTestEnum.ENUM_NAME + "." + Self._name
   End Method

   'Gets the enum element by its ID, opposite of getID()
   Rem
      bbdoc: Returns an element of the enum by its ID
      about: That's the opposite of getID()
   End Rem
   Function FromID:TTestEnum(id:Int)
      Select id
         Case 1 Return TTestEnum.A
         Case 2 Return TTestEnum.B
         Case 3 Return TTestEnum.C
         Case 4 Return TTestEnum.D
         Case 5 Return TTestEnum.E
         Case 6 Return TTestEnum.F
         Default Return Null
      End Select
   End Function

   'Gets the enum element by its name, opposite of getName()
   Rem
      bbdoc: Returns an element of the enum by its Name
      about: Opposite of getName()
   End Rem
   Function FromName:TTestEnum(name:String)
      Select name
         Case "A" Return TTestEnum.A
         Case "B" Return TTestEnum.B
         Case "C" Return TTestEnum.C
         Case "D" Return TTestEnum.D
         Case "E" Return TTestEnum.E
         Case "F" Return TTestEnum.F
         Default Return Null
      End Select
   End Function

   'Create Function for less code
   Function Create:TTestEnum(id:Int,name:String)
      Local e:TTestEnum = new TTestEnum
      e._id = id
      e._name = name
      Return e
   End Function

   Function init()
      TTestEnum.A = TTestEnum.Create(1, "A")
      TTestEnum.B = TTestEnum.Create(2, "B")
      TTestEnum.C = TTestEnum.Create(3, "C")
      TTestEnum.D = TTestEnum.Create(4, "D")
      TTestEnum.E = TTestEnum.Create(5, "E")
      TTestEnum.F = TTestEnum.Create(6, "F")
   End Function
End Type

'automatically initialized
TTestEnum.init()


Dies kann z.B. so verwendet werden:
Code: [AUSKLAPPEN]

Local enum:TTestEnum
enum = TTestEnum.B
if enum = TTestEnum.C Then Print "enum ist B"
Print "Name: "+enum.getName()
enum = TTestEnum.FromName("D") 'gibt das element zurück, welches D repräsentiert
Print "ID des Enums: "+enum.getID()


Ein Wort zur Geschwindigkeit und Speicher:
Geschwindigkeit ist die gleiche wie Enums mit Integern (auch Vergleiche)
Nur wird ein wenig Speicher beim Initialisieren gebraucht. Dann in der Verwendung ist der Speicher der gleiche wie bei Integer.

Anregung, Kritik erwünscht.

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group