Dynamic LinkedList / Array of LinkedList

Share your advanced PureBasic knowledge/code with the community.
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

Konne wrote:Ah OK thx

If 0

wouldn't a goto be faster?
No. If 0 results in the same code as goto except that I don't have to create the labels myself.
Konne
Enthusiast
Enthusiast
Posts: 434
Joined: Thu May 12, 2005 9:15 pm

Post by Konne »

Nope there is also a asm if if 0 is 1.
(I don't think PB is optimizing such things).

But onj the other hand a BIG or better HUGE tanks to u! Your Macros really rock! Use them in a big program without having problems yet very good work.
Apart from that Mrs Lincoln, how was the show?
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

Konne wrote:Nope there is also a asm if if 0 is 1.
(I don't think PB is optimizing such things).

But onj the other hand a BIG or better HUGE tanks to u! Your Macros really rock! Use them in a big program without having problems yet very good work.
Thanks for the compliments. But I'm sure PB optimizes it. You're right, there is a jump instruction for If 0, but this jump instruction is the same jump instruction as PB generates for a Goto. So it's impossible to get it faster.

It's also good to hear that you're using them in a big program without problems, because I'm doing that as well, and I have almost been expecting everything to suddenly mess up badly, but so far they're working very well.
xgp
Enthusiast
Enthusiast
Posts: 128
Joined: Mon Jun 13, 2005 6:03 pm

Post by xgp »

Congratulations Trond!
If found your work very pleasent and simple to understand and follow.
Now, i think i really understand the power of macros!

But, i don't get one thing...
Here is what i am trying to archieve:

Create a rules/exceptions 'system' like.
Adding rules, and each rule, would have a list of exceptions.

Code: Select all

...included your Macros...

Structure Rule
  ByteField.b
  StringField.s
  ExceptionsList.q
EndStructure

Structure Exception
  ByteField.b
  StringField.s
EndStructure

UseListType(Exception)

Global  NewList RulesList.Rule()
AddElement(RulesList())
RulesList()\ByteField = 2
RulesList()\StringField = "rule 1"
RulesList()\ExceptionsList  = DynamicNewListException()
What am i doing wrong here? Each time i try to compile or debug, i get the following error:
PureBasic - Assembler error

PureBasic.asm[158]:
MP0
PureBasic.asm[63]: MP0 [8]:
MOV Eax, [p.v_ID]
error: undefined symbol.
I have already used sucessfully your work, but it was until the use of Macros.(Where we had to modify the procedure manually).
But, i think that's not the reason why this happens.
I am afraid i'm not using your work correctly, if so, please, Trond or someone else, show me my mistakes.
Glad you could take the time to read.

xgp
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

You paste the macros above your code and run it and then you get that error? Because I don't get that error here, so that's weird.

Did you enable inline asm in the compiler options and then remove the ! signs? Because that's wont work without some changes to the code.
xgp
Enthusiast
Enthusiast
Posts: 128
Joined: Mon Jun 13, 2005 6:03 pm

Post by xgp »

Thanks for your reply!
I've been trying(the last 30 minutes) all possibilities i could imagine (even reinstalled PureBasic).

Finally, i realized that the error was due to a typo!!

I use jaPBe and after having copied your macros, it(jaPBe) assumed that:

Code: Select all

Macro BindListTemplate(Type) 
  Procedure BindList#Type(List.Type(), ID.q) 
    !mov eax, [p.v_ID] 
    !mov edx, [p.v_ID+4] 
    !mov ecx, [p.v_ID-4] 
    !mov [ecx], eax 
    !add ecx, 4 
    !mov [ecx], edx 
  EndProcedure 
EndMacro 
should be like this:

Code: Select all

Macro BindListTemplate(Type) 
  Procedure BindList#Type(List.Type(), id.q) ; <-- notice the lowercase of 'id.q'
    !mov eax, [p.v_ID]  ; <-- different from the following inline asm code
    !mov edx, [p.v_ID+4] 
    !mov ecx, [p.v_ID-4] 
    !mov [ecx], eax 
    !add ecx, 4 
    !mov [ecx], edx 
  EndProcedure 
EndMacro
I just noticed this, after the reinstall of PureBasic. I copied my example given here to the PB's editor and it just run perfectly. (Like you said you have tested!)
So, the only difference from the source that was incorrect to the correct one, was, only the different case of the variable 'id.q'.

I still love jaPBe(don't mean with this post to 'lower' jaPBe), after all, the mistake was mine all the time.
Sorry to bother some great coding minds like the one who built this macros with something so stupid, like a typo! :oops:

Anyway, i appreciate very much the fast reply and the time you took to help me.

xgp
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

No problem, I have spent the last two days hunting typos myself. (I couldn't understand why I sometimes needed [ and ] around my asm argument and sometimes not for the same instruction, and when I understood it I typed it wrong over and over nevertheless.)
don't mean with this post to 'lower' jaPBe
Like it lowered the case the of the parameter! HAHA! <- That wasn't funny.
MidSilence
New User
New User
Posts: 1
Joined: Tue Jan 09, 2007 12:36 pm

Post by MidSilence »

Hi,

I´m trying to use the Macros using NewDynamicListPointer instead of GlobalNewDynamicListPointer but it doesn´t work. Using the following code the debug window shows that the linked list count is always 1. If I change to GlobalNewDynamicListPointer in Add Procedure, I´m getting 1 and 2:

Macro GlobalNewDynamicListPointer(Name, Type)
If 0
Global NewList Name.Type()
EndIf
EndMacro

Macro NewDynamicListPointer(Name, Type)
If 0
NewList Name.Type()
EndIf
EndMacro

Macro BindListTemplate(Type)
Procedure BindList#Type(List.Type(), ID.q)
!mov eax, [p.v_ID]
!mov edx, [p.v_ID+4]
!mov ecx, [p.v_ID-4]
!mov [ecx], eax
!add ecx, 4
!mov [ecx], edx
EndProcedure
EndMacro

Macro DynamicNewListTemplate(Type)
Procedure.q DynamicNewList#Type()
Protected NewList Local.Type()
!mov eax, [esp]
!mov edx, [esp+4]
!add esp, 8
!ret
EndProcedure
EndMacro

Macro FreeListTemplate(Type)
Procedure FreeList#Type(ID.q)
If 0
NewList Dummy.Type()
EndIf
BindList#Type(Dummy(), ID.q)
EndProcedure
EndMacro

Macro UseListType(Type)
BindListTemplate(Type)
DynamicNewListTemplate(Type)
FreeListTemplate(Type)
EndMacro

UseListType(S)


;-------------------------------------------------------------------------------
Procedure CreateList()
;-------------------------------------------------------------------------------

Global list.q
list.q = DynamicNewListS()

EndProcedure
;-------------------------------------------------------------------------------

;-------------------------------------------------------------------------------
Procedure Add()
;-------------------------------------------------------------------------------

;GlobalNewDynamicListPointer(listDyn, S)
NewDynamicListPointer(listDyn, S)
BindListS(listDyn(), list)

AddElement(listDyn())
listDyn() = "Teste"
Debug CountList(listDyn())

EndProcedure
;-------------------------------------------------------------------------------

If (OpenConsole())

CreateList()

Add()
Add()

Input()

EndIf

TIA,

--
Andre Azevedo
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

It's because local lists gets freed when you reach the end of the procedure:

Code: Select all

Procedure Add()
  NewDynamicListPointer(listDyn, S)
  BindListS(listDyn(), NewDynamicListS())
EndProcedure ; Here, the list pointed to by listDyn() is freed
You can unbind listDyn() from list.q before ending the procedure to prevent this: (I added a UnbindListTemplate() and modified UseListType())

Code: Select all

Macro GlobalNewDynamicListPointer(Name, Type) 
  If 0 
    Global NewList Name.Type() 
  EndIf 
EndMacro 

Macro NewDynamicListPointer(Name, Type) 
  If 0 
    NewList Name.Type() 
  EndIf 
EndMacro 

Macro BindListTemplate(Type) 
  Procedure BindList#Type(List.Type(), ID.q) 
    !mov eax, [p.v_ID] 
    !mov edx, [p.v_ID+4] 
    !mov ecx, [p.v_ID-4] 
    !mov [ecx], eax 
    !add ecx, 4 
    !mov [ecx], edx 
  EndProcedure 
EndMacro 

Macro UnbindListTemplate(Type)
  Procedure UnbindList#Type(List.Type())
    BindList#Type(List(), 0)
  EndProcedure
EndMacro

Macro DynamicNewListTemplate(Type) 
  Procedure.q DynamicNewList#Type() 
    Protected NewList Local.Type() 
    !mov eax, [esp] 
    !mov edx, [esp+4] 
    !add esp, 8 
    !ret 
  EndProcedure 
EndMacro 

Macro FreeListTemplate(Type) 
  Procedure FreeList#Type(ID.q) 
    If 0 
      NewList Dummy.Type() 
    EndIf 
    BindList#Type(Dummy(), ID.q) 
  EndProcedure 
EndMacro 

Macro UseListType(Type) 
  BindListTemplate(Type) 
  UnbindListTemplate(Type)
  DynamicNewListTemplate(Type) 
  FreeListTemplate(Type) 
EndMacro

UseListType(S)
; -------

Procedure CreateList()
  Global list.q
  list.q = DynamicNewListS()
EndProcedure

Procedure Add()
  NewDynamicListPointer(listDyn, S)
  BindListS(listDyn(), list)
  AddElement(listDyn())
  listDyn() = "Teste"
  Debug CountList(listDyn())
  UnbindListS(listDyn()) ; Since listDyn() no longer points to list, list will not
EndProcedure ; get freed at the end of the procedure


If (OpenConsole())
  CreateList()
  Add()
  Add()
EndIf
User avatar
mback2k
Enthusiast
Enthusiast
Posts: 257
Joined: Sun Dec 02, 2007 12:11 pm
Location: Germany

Post by mback2k »

I just wanted to say thanks for this perfect code, thanks Trond! :)
kinglestat
Enthusiast
Enthusiast
Posts: 746
Joined: Fri Jul 14, 2006 8:53 pm
Location: Malta
Contact:

Post by kinglestat »

I've also been using them...and really forgot exactly what it does or how it works...and never had probs. A really nice piece of code there Trond. The only addition was the sorted insertion...whch I had posted
I may not help with your coding
Just ask about mental issues!

http://www.lulu.com/spotlight/kingwolf
http://www.sen3.net
kinglestat
Enthusiast
Enthusiast
Posts: 746
Joined: Fri Jul 14, 2006 8:53 pm
Location: Malta
Contact:

Post by kinglestat »

Hi there,

seems this code doesnt work anymore in PB4.30
you think you could have time to fix that?

cheers
I may not help with your coding
Just ask about mental issues!

http://www.lulu.com/spotlight/kingwolf
http://www.sen3.net
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

Seems like something was changed in the way lists are passed to procedures. I don't know if I can still get it to work.

It would help if I knew what the second long of the list is for (a list is 8 bytes, but when you pass it to a procedure, only 4 are passed in). I don't know if it it's important or not.

Edit: I think I'm close to getting it now, but no promises.
Edit: It seems to be almost impossible because lists are passed to procedures in a strange way now (a null pointer is passed in for uninitialized lists). And also referencing list by name doesn't work in inline asm (unlike normal variables). To replace the procedure with a macro I'd need that working.
kinglestat
Enthusiast
Enthusiast
Posts: 746
Joined: Fri Jul 14, 2006 8:53 pm
Location: Malta
Contact:

Post by kinglestat »

ah pity
was quite usefull
I appreciate the effort

cheers
I may not help with your coding
Just ask about mental issues!

http://www.lulu.com/spotlight/kingwolf
http://www.sen3.net
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

I just thought of something... do you need NewDynamicListPointer()? If you can do with only GlobalNewDynamicListPointer() maybe it could work. But even in that case there would be a problem with passing the bound list to a procedure (although you could just pass the unbound list and, inside the procedure, bind it to a name created with GlobalNewDynamicListPointer()).
Post Reply