Two DEFPROCs, one ENDPROC?

bbc micro/electron/atom/risc os coding queries and routines
Post Reply
julie_m
Posts: 237
Joined: Wed Jul 24, 2019 9:53 pm
Location: Derby, UK
Contact:

Two DEFPROCs, one ENDPROC?

Post by julie_m » Wed Sep 02, 2020 9:38 pm

I think we've all seen assembler code like this:

Code: Select all

.add16
CLC
.adc16
JSRadd16_1
.add16_1
LDAwkspace,X
ADCwkspace,Y
STAwkspace,X
INX
INY
RTS
with multiple entry points into the same code, so two JSRs can hit the same RTS.

Can you do something similar in BASIC, with a DEFPROC between another DEFPROC and an ENDPROC, to give the option to execute or skip a section of code? Something like

Code: Select all

DEFPROCexport
OSCLI"SP."+V$
DEFPROCfake_export
L%=0
*/VDUMP
*SP.
ENDPROC
and then PROCfake_export will perform a "fake" variable dump (allowing any egregious errors to be spotted), but PROCexport will do it for real?

cmorley
Posts: 1322
Joined: Sat Jul 30, 2016 8:11 pm
Location: Oxford
Contact:

Re: Two DEFPROCs, one ENDPROC?

Post by cmorley » Wed Sep 02, 2020 9:47 pm

Just try it:

Code: Select all

   10PROCA
   20PROCB
   30END
   40DEFPROCA
   50PRINT"a";
   60DEFPROCB
   70PRINT"b"
   80ENDPROC

User avatar
roland
Posts: 4051
Joined: Thu Aug 29, 2013 9:29 pm
Location: Born (NL)
Contact:

Re: Two DEFPROCs, one ENDPROC?

Post by roland » Wed Sep 02, 2020 9:53 pm

I must say that the result surprises me. I didn't expect that....
FPGAtom: 512 KB RAM, Real Time Clock and 64 colours
MAN WOMAN :shock:

User avatar
Richard Russell
Posts: 1668
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: Two DEFPROCs, one ENDPROC?

Post by Richard Russell » Wed Sep 02, 2020 10:06 pm

This is a pattern I commonly use:

Code: Select all

      DEF PROCone : LOCAL type% : type% = 1
      DEF PROCtwo : LOCAL type% : type% = 2
      DEF PROCthree : LOCAL type% : type% = 3
      ...
      REM rest of procedure
      ...
      ENDPROC
This is particularly handy when the multiple procedures share common local state, typically (in BBC BASIC for Windows or BBC BASIC for SDL 2.0) some PRIVATE variables:

Code: Select all

      DEF PROCone : LOCAL type% : type% = 1
      DEF PROCtwo : LOCAL type% : type% = 2
      DEF PROCthree : LOCAL type% : type% = 3
      PRIVATE shared_variables, arrays(), structures{}
It's actually quite tricky to achieve shared local state between multiple PROCs/FNs any other way in BBC BASIC.

They don't all have to be PROCs (or all FNs) either:

Code: Select all

      DEF PROCone : LOCAL type% : type% = 1
      DEF FNtwo : LOCAL type% : type% = 2
      ...
      IF type% = 1 THEN ENDPROC ELSE = result
This is the kind of thing a compiler would find difficult!

User avatar
lurkio
Posts: 2933
Joined: Wed Apr 10, 2013 12:30 am
Location: Doomawangara
Contact:

Re: Two DEFPROCs, one ENDPROC?

Post by lurkio » Wed Sep 02, 2020 10:47 pm

Richard Russell wrote:
Wed Sep 02, 2020 10:06 pm

Code: Select all

      DEF PROCone : LOCAL type% : type% = 1
      DEF PROCtwo : LOCAL type% : type% = 2
      DEF PROCthree : LOCAL type% : type% = 3
      ...
      REM rest of procedure
      ...
      ENDPROC
Ah, yes. This is possible thanks to the fact that DEF is treated like REM, which is a fact that I learnt from this unforgettable exchange in 2014:

viewtopic.php?f=2&t=8388&p=89696&hilit= ... rem#p89696

:idea:

julie_m
Posts: 237
Joined: Wed Jul 24, 2019 9:53 pm
Location: Derby, UK
Contact:

Re: Two DEFPROCs, one ENDPROC?

Post by julie_m » Wed Sep 02, 2020 10:59 pm

Well, it seems to work, behaves exactly as expected and does not do anything too crazy with the stack either (as shown by selecting a graphics mode and changing HIMEM to somewhere inside the framebuffer).

User avatar
Richard Russell
Posts: 1668
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: Two DEFPROCs, one ENDPROC?

Post by Richard Russell » Thu Sep 03, 2020 1:01 am

lurkio wrote:
Wed Sep 02, 2020 10:47 pm
Ah, yes. This is possible thanks to the fact that DEF is treated like REM, which is a fact that I learnt from this unforgettable exchange in 2014:
There's a good reason why DEF behaves as REM, it's not the whim that Jonathan implies. It was a requirement of the BBC's specification that BBC BASIC should be substantially compatible with Microsoft BASIC (of the day) and Microsoft BASIC supports single-line functions that can go anywhere in the program. Indeed I think single-line functions of this sort pre-date multi-line functions in BASIC generally.

So this kind of code was required to be acceptable:

Code: Select all

      numerator = 22
      denominator = 7
      DEF FNdivide(a,b) = a/b
      PRINT FNdivide(numerator, denominator)
Hence DEF, if encountered in normal execution, must behave as REM.

User avatar
BeebMaster
Posts: 3640
Joined: Sun Aug 02, 2009 5:59 pm
Location: Lost in the BeebVault!
Contact:

Re: Two DEFPROCs, one ENDPROC?

Post by BeebMaster » Thu Sep 03, 2020 11:28 am

I use this construction occasionally, as in:

Code: Select all

 5200DEFFNread(buffer,start,blockcount,drive):opcode=8
 5300DEFFNwrite(buffer,start,blockcount,drive):opcode=&A
 5400=FNosword(buffer,start,blockcount,drive,opcode)
Actually I was a bit worried about that in case when calling FNread it did process the FNwrite line and set the opcode to &A which would have been disastrous - but it works.
Image

Soruk
Posts: 800
Joined: Mon Jul 09, 2018 11:31 am
Location: Basingstoke, Hampshire
Contact:

Re: Two DEFPROCs, one ENDPROC?

Post by Soruk » Thu Sep 03, 2020 1:54 pm

I love threads like this. I decided to test this in Matrix Brandy, and while multi-entry procedures worked as expected, the REM behaviour of the DEF line wasn't... (it is now)
Matrix Brandy BASIC VI (work in progress)

Post Reply

Return to “programming”