### Author Topic: Macros as Functions: #return  (Read 454 times)

0 Members and 1 Guest are viewing this topic.

#### Charles Pegge

• Posts: 3719
##### Macros as Functions: #return
« on: February 03, 2018, 07:27:33 AM »
One-liner macros are easy to embed in expressions, but multi-line macros require an additional step. Namely to substitute a proxy variable for the macro within the expression, then the macro can be instantiated in advance.

#return specifies the variable to be substituted, carrying the 'output' of the macro. The type of the variable (int here) is placed after the macro name:

Code: [Select]
`'USING MACRO FUNCTIONS'2D ARRAY WITH BOUNDARY CLIPPINGindexbase 0int pix[800*600]''SINGLE-LINE MACRO FUNCTION'macro pix2d(x,y) pix(y*800+x)''MULTI-LINE MACRO RETURNING A UNIQUE VARIABLEmacro pix2d int (x,y,  v,vv)  #return *v 'pointer supports reading and writing in pix  if x>=0 and x<800 and y>=0 and y<600    @v=@pix(y*800+x)  else     int vv=0xffffffff 'value when out of bounds    @v=@vv  end ifend macro''TESTpix2d(1,20)=0xaabbccddprint hex pix2d(1,20)print hex pix2d(800,10)`
Using Oxygen.dll in OxygenProgress.zip and OxygenBasicProgress.zip (from 1 Feb 2018)
https://github.com/Charles-Pegge/OxygenBasic

#### Charles Pegge

• Posts: 3719
##### Re: Macros as Functions: without #return
« Reply #1 on: March 03, 2018, 02:54:39 AM »
A change in notation:

If the macro specifies a return-type in its header, then the first parameter specifies the return-variable. So the example, given above, now becomes:
Code: [Select]
`indexbase 0int pix[800*600]'macro pix2d int* (v,x,y,  vv)=============================  'v  return pixel pointer supporting read/write  'x  horizontal coordinate  'y  vertical coodinate  'vv sink pixel  if x>=0 and x<800 and y>=0 and y<600    @v=@pix(y*800+x)  else    int vv=0xffffffff 'value when out of bounds    @v=@vv  end ifend macro''TESTpix2d(1,20)=0xaabbccddprint hex pix2d(1,20)print hex pix2d(800,10)`
Using Oxygen.dll in OxygenProgress.zip (from 3 Mar 2018)
https://github.com/Charles-Pegge/OxygenBasic/blob/master/OxygenProgress.zip

#### Charles Pegge

• Posts: 3719
##### Re: Macros as Functions: PB asc()
« Reply #2 on: March 03, 2018, 03:36:28 AM »

Using the same technique, we can emulate PB's asc(), which works as both a statement and a function.

Code: [Select]
`  macro asc ubyte* (a, s="",i=1)  ==============================  'a   ascii code return  's   string input  'i   character index expression  '  @a=_asc_(strptr(s),len(s),i)  end macro  '  function _asc_(sys pt,int le,i) as ubyte*  =========================================  'le  string length  'pt  string pointer  'si  sink location for out of bounds ascii  'oo  character offset position  static int si  sys oo=(i)-1  if oo<-1 then oo+=le+1 'offset from right  if oo>=le or oo<0 or pt=0 then    return @si 'sink  else    return pt+oo 'success  end if  end function'#recordof _asc_'TEST=====bstring s="1234"asc(s)=65asc(s,2)=66asc(s,-2)=67print s ", " asc(s,-1) 'ABC4, 52print asc(s,1000)     '0del s`

#### Arnold

• Hero Member
• Posts: 648
##### Re: Macros as Functions: #return
« Reply #3 on: May 01, 2018, 11:59:37 PM »
Hi Charles,

using your example code, I tried to create a 3-dimensional array in three ways. Only using the function iarr will show the correct results. Am I missing something with the macro iarr? I am also not sure if I forgot something with macro arr3d?

Roland
Code: [Select]
`uses console#autodim offindexbase 0 int arr[3*2*4]=            {11, 12, 13, 14,     15, 16, 17, 18,     21, 22, 23, 24,     25, 26, 27, 28,            31, 32, 33, 34,     35, 36, 37, 38}function iarr(int x,y,z) {return x*2*4 + y*4 + z}'macro iarr(x,y,z) (x*2*4 + y*4 + z)macro arr3d int* (r,x,y,z)  'r return value  @r=@arr(x*2*4 + y*4 + z)end macro                printl "- 3D Array Elements - " + cr +crint i, j, kint idxfor i=0 to <3    for j=0 to <2        for k=0 to <4           idx = iarr(i,j,k)           print arr[idx] : print tab'           print arr3d(i,j,k) : print tab        next        printl    next    printlnextprintl "-----------------------------" : printl : printlfor i=0 to <3    for j=0 to <2        for k=0 to <4           idx = i*2*4 +j*4 +k           print idx tab        next        printl    next    printlnextprintl "Enter ..." : waitkey`
« Last Edit: May 02, 2018, 11:23:25 AM by Arnold »

#### Arnold

• Hero Member
• Posts: 648
##### Re: Macros as Functions: #return
« Reply #4 on: May 02, 2018, 11:24:14 AM »
After further considerations I think I can also use a function for arr3d:
...
function arr3d(int x,y,z) as int
int idx=x*2*4 + y*4 + z
sys a*
@a = @arr
return a[idx]
end function
...
print arr3d(i,j,k) : print tab

This will give the expected results and I can also use expressions for the parameters.

#### Charles Pegge

• Posts: 3719
##### Re: Macros as Functions: #return
« Reply #5 on: May 02, 2018, 07:16:16 PM »
Hi Roland,

Thanks for testing macro functions.

If you want to pass expressions to a macro, then they will need to be contained within parentheses, inside the macro:

Code: [Select]
`macro arr3d int* (r,x,y,z)  'r return value  @r=@arr( (x)*2*4 + (y)*4 + (z) )end macro       `

#### Arnold

• Hero Member
• Posts: 648
##### Re: Macros as Functions: #return
« Reply #6 on: May 02, 2018, 11:53:20 PM »
Thank you Charles. The brackets made the difference and the macro works fine.
Perhaps there is also something possible with the macro iarr? To find the index for 2d array is no problem, but for more dimensions only the values of the first loop of i are correct. Unfortunately I am not familiar with your debugging tools and using print statements in macros seems not to be really helpful.

This is the code to get the index of an emulated 2d array:
Code: [Select]
`uses console#autodim offindexbase 0 int ar[6*4] =            {11, 12, 13, 14,     15, 16, 17, 18,     19, 20, 21, 22,     23, 24, 25, 26,            27, 28, 29, 30,     31, 32, 33, 34}macro iar(x,y) (x*4 + y)int i, jint idxfor i=0 to <6    for j=0 to <4       idx = iar(i,j)       print ar[idx] : print tab    next    printlnextprintl "Enter ..." : waitkey`