Page 2 of 3

Posted: Tue Nov 28, 2006 3:35 pm
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.

Posted: Wed Nov 29, 2006 6:32 pm
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.

Posted: Wed Nov 29, 2006 7:00 pm
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.

Posted: Thu Dec 21, 2006 8:05 pm
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

Posted: Thu Dec 21, 2006 8:29 pm
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.

Posted: Thu Dec 21, 2006 11:36 pm
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

Posted: Fri Dec 22, 2006 12:13 am
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.

Posted: Wed Jan 10, 2007 3:28 pm
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

Posted: Wed Jan 10, 2007 6:12 pm
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

Posted: Tue Jul 29, 2008 1:29 pm
by mback2k
I just wanted to say thanks for this perfect code, thanks Trond! :)

Posted: Wed Aug 06, 2008 2:38 pm
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

Posted: Sun Mar 01, 2009 2:50 pm
by kinglestat
Hi there,

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

cheers

Posted: Sun Mar 01, 2009 5:24 pm
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.

Posted: Mon Mar 02, 2009 3:14 pm
by kinglestat
ah pity
was quite usefull
I appreciate the effort

cheers

Posted: Mon Mar 02, 2009 7:48 pm
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()).