public macro scope, and visibility

Coding and general discussion relating to the compiler

Moderators: David Barker, Jerry Messina

Post Reply
Jerry Messina
Swordfish Developer
Posts: 1473
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

public macro scope, and visibility

Post by Jerry Messina » Wed Oct 06, 2010 3:04 pm

I'm a little unclear on the scoping and usage of macros.

If I have a macro declared as public in file1.bas (ie 'public macro mymac()'), if I include file1.bas in other files should I be able to reference the macro with the same syntax used for other public entities (ie 'file1.mymac')?

To make it clearer, I have a module with a macro in it:

mymacro.bas

Code: Select all

module mymac

public macro mymacro(param1, param2)
    param1 = param2
end macro

end module
I'm trying to reference that macro in three other files:

mod1.bas

Code: Select all

module mod1

// has macro definition
include "mymacro.bas"

dim a, b as byte

public sub initialize()

    b = 0
    
    mymac.mymacro(a, b)
    
end sub

end module
and

mod2.bas

Code: Select all

module mod2

// has macro definition
include "mymacro.bas"

dim a, b as byte

public sub initialize()

    b = 0
    
    mymac.mymacro(a, b)
    
end sub

end module

and my main routine:

main.bas

Code: Select all

program test

device = 18F4685
clock = 40

include "mymacro.bas"

include "mod1.bas"
include "mod2.bas"

dim a, b as byte

b = 0

mod1.initialize()
mod2.initialize()

mymac.mymacro(a, b)


It doesn't seem to like the references to 'mymacro' in mod1 and mod2 no matter what syntax I try. However, it seems ok with the reference in main, using either 'mymac.mymacro(a, b)' or just 'mymacro(a, b)'.

It seems happy if I get rid of the mymacro.bas file and just place a private local copy of the macro in each of the files, but I was trying to get away from that.

Am I using it incorrectly?

User avatar
David Barker
Swordfish Developer
Posts: 1214
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Post by David Barker » Wed Oct 06, 2010 3:18 pm

Jerry

Given that you have a BETA version of the compiler, I've updated your status to BETA tester so that you can post in the BETA section of the forum.

User avatar
David Barker
Swordfish Developer
Posts: 1214
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Post by David Barker » Wed Oct 06, 2010 3:19 pm

I should add that I'll take a look at the above ASAP...

bitfogav
Registered User
Registered User
Posts: 169
Joined: Sat Oct 09, 2010 1:39 pm
Location: United Kingdom

Post by bitfogav » Sat Dec 17, 2011 1:59 pm

Im also a little unclear on the scoping and usage of macros with the SF Compiler, would someone mind explaning how/why we would use a macro with the SF Compiler? :)

Jerry Messina
Swordfish Developer
Posts: 1473
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Post by Jerry Messina » Mon Dec 19, 2011 6:42 pm

David has fixed most of the issues I ran across, so macros pretty much follow the same sort of Public and Private
rules that apply to subroutines and functions.

Macros work much like declaring a subroutine 'inline' would. The code is placed inline where you invoke the macro,
so you don't have the overhead of the call/return. They work a bit different, though, when it comes to parameters,
and that's where they shine. The macro code is evaluated at the point where it's used, and any unused/redundant
statements are removed.

For example, consider some macros that I use to access the timer registers when using them in 16-bit mode, where you
have to read and write the registers in a particular order:

Code: Select all

// write 16-bit timer specified by 'tmr' with the value 'wval'
public macro write_tmr16(tmr, wval)
    if (tmr = 0) then
        TMR0H = (wval >> 8)
        TMR0L = byte(wval)
    elseif (tmr = 1) then
        TMR1H = (wval >> 8)
        TMR1L = byte(wval)
    elseif (tmr = 3) then
        TMR3H = (wval >> 8)
        TMR3L = byte(wval)
    else
        checkparam(etError, "unsupported TMR select")
    endif
end macro

// reads 16-bit timer specified by 'tmr', stores it in 'wresult'
public macro read_tmr16(tmr, wresult)
    if (tmr = 0) then
        wresult.byte0 = TMR0L
        wresult.byte1 = TMR0H
    elseif (tmr = 1) then
        wresult.byte0 = TMR1L
        wresult.byte1 = TMR1H
    elseif (tmr = 3) then
        wresult.byte0 = TMR3L
        wresult.byte1 = TMR3H
    else
        checkparam(etError, "unsupported TMR select")
    endif
end macro
If you were to say 'write_tmr16(1, $55AA)', that would end up translating to the following code:

Code: Select all

	TMR1H = $55
	TMR1L = $AA
All of the code for the 'if/elseif' tests disappear. You could also use the macro with a word variable instead of a constant value.

The 'read_tmr16' macro works much the same way

Code: Select all

	dim w as word
	read_tmr16(3, w)
	
	// would translate to
	w.byte0 = TMR3L
	w.byte1 = TMR3H
I use them mostly for routines that access hardware functions since they're quick.

bitfogav
Registered User
Registered User
Posts: 169
Joined: Sat Oct 09, 2010 1:39 pm
Location: United Kingdom

Post by bitfogav » Mon Dec 19, 2011 9:44 pm

Thanks for explaining all that Jerry, makes more sense now :)

Post Reply