Überladen von Proceduren

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Überladen von Proceduren

Beitrag von GPI »

ich hab eine Möglichkeit gefunden, zu überprüfen, ob ein Parameter eine Zahl, eine Variable oder eine (bestimmte) Strucktur ist.
man könnte bei der Variable noch weiter zwischen Byte, word, long, string unterschieden werden. Direkte Strings sind leider nicht möglich. Pointer könnte man noch machen...

Leider ist auch kein direkter Rückgabewert möglich.

Der Trick ist, ein Macro zu benutzen.
Als erstes muss man den Parameter in einen String verwandeln, das geht mit einen "dq"-Macros um den Parameter mit " einzuklemmen. Diesen String kann man jetzt mit anderen vergleichen. Zahlen bspw. kann man mit >="0" and <":" finden - das ":" befindet sich genau nach der 9. Damit hat man festgestellt, das wohl das erste Zeichen zwischen 0 und 9 liegen müssen - eine Zahl.

Als nächstes kann man auf Typ testen - das ist jetzt sicher, weil es eine Variable sein muss. das geht einfach mit typeof() erfolgen - wenn es keine Strucktur ist, ist es wohl eine normale Variable.

Als letztes muss man die Strucktur rausfinden. Mein trick ist, das ich ein "dummy"-Member in die Strucktur einbaue (um genau zu sein sogar 8), damit der Speicherplatz nicht hochgeht, nimmt man ein C-Style-Arry mit der größe 0, zb sowas __mytest__.b[0] - den Typ (hier b) kann man wieder abfragen und danach die Struckturen unterscheiden.
ich hab jetzt 8 solcher Dummy-Member eingefügt, um damit eine 8-bit Zahl zu erstellen. Ich nehme dafür .b für 1 und .a für 0. Durch ein "typeof(xxx) & 1" wird das in Null und Eins umgewandelt.

Das schönste an dem ganzen: Das erfolgt komplett auf Compiler-ebene, verbraucht keinen zusätzlichen Speicher.

Ich hoffe mit den Code wirds klarer:

Code: Alles auswählen

CompilerIf (#PB_Byte &1)<>1 Or (#PB_Ascii &1)<>0
  CompilerError "Massives Problem, es muss unten angepasst werden"
CompilerEndIf

Macro _typehelper(nb,dd)
  CompilerIf  (nb>>dd) & 1 = 1
     __type#dd#__.b[0]
  CompilerElse
     __type#dd#__.a[0]
   CompilerEndIf
 EndMacro
 Macro _typehelper2(nb,dd)
   (TypeOf(nb\__type#dd#__)&1)<<dd
 EndMacro
 
Macro StructureAddType(nb)
  CompilerIf nb>255
    CompilerError "NB to big!"
  CompilerEndIf
  _typehelper(nb,0)
  _typehelper(nb,1)
  _typehelper(nb,2)
  _typehelper(nb,3)
  _typehelper(nb,4)
  _typehelper(nb,5)
  _typehelper(nb,6)
  _typehelper(nb,7)  
EndMacro
; 7 1

Macro GetType(nb)
  _typehelper2(nb,0) + _typehelper2(nb,1) + _typehelper2(nb,2) + _typehelper2(nb,3) + _typehelper2(nb,4) + _typehelper2(nb,5) + _typehelper2(nb,6) + _typehelper2(nb,7)
EndMacro
  
    
Macro dq
  "
EndMacro

Macro test(a)
  CompilerIf  (dq#a#dq => "(" And dq#a#dq < ")") Or ;brace = number
              (dq#a#dq => "-" And dq#a#dq < ".") Or ;minus = negativ number
              (dq#a#dq => "0" And dq#a#dq < "9")    ; a number
    Debug dq#a#dq+" number"+StrF(a)
  CompilerElseIf TypeOf(a) <> #PB_Structure
    Debug dq#a#dq+" Variable"     
  CompilerElse
    CompilerSelect GetType(a)
      CompilerCase 0
        Debug dq#a#dq+" s0"
      CompilerCase 1
        Debug dq#a#dq+" s1"
      CompilerDefault
        Debug dq#a#dq+" structure "+Str(GetType(a))
    CompilerEndSelect
    
  CompilerEndIf
EndMacro


Structure ar
  l.l
  StructureAddType(67)
EndStructure

CompilerIf SizeOf(ar)<>SizeOf(long)
  CompilerError "das sollte nicht passieren"
CompilerEndIf

Structure br
  w.w
  StructureAddType(78)
  z.ar
EndStructure

a.ar
*b.br
c.br
d.l
test(a)
test(*b)
test(c)
test(-0.5)
test(d)
;test(c\z) <- not possible...
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!