Author Topic: A simple command line tool translating DEF FN functions into FUNCTIONs  (Read 6525 times)

0 Members and 1 Guest are viewing this topic.

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Hi guys
cause I see often the request  "  How to solve the porting in QB64 of program written inQbasic and QB with the DEF FN statement?"
I have developed in Qbasic and ported to QB64 this tool
it translates code from Qbasic to QB64...

after compiled into QB64 you can use the program from command line or with drag & drop ...
Here attached the code DEF2FUN.BAS and some Qbasic code with DEF FN on one line and multiline.
There are 2 compressed files .7z and .tar for different software in your possess.
Thanks to try and for feedbacks
* DEF2FUNCTION_for_QB64.7z (Filesize: 2.15 KB, Downloads: 255)
* DEF2FUNCTION_for_QB64.tar (Filesize: 10.5 KB, Downloads: 223)
Programming isn't difficult, only it's  consuming time and coffee

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Request. If this is just one QB64 file (program) would you please edit your post to also include the code?

Example:

Code: QB64: [Select]
  1. PRINT "Ewwwe I hates unzippin' things, varmint!"
  2.  

Pete 
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Request. If this is just one QB64 file (program) would you please edit your post to also include the code?

Example:

Code: QB64: [Select]
  1. PRINT "Ewwwe I hates unzippin' things, varmint!"
  2.  

Pete 

Well I appreciate TempodiBasic having 2 different package options for the 4 bas files included, that is convenient! Thanks TempodiBasic.

But I see Pete's point, would be nice to just view the main bas code, so for that reason I offer this service:
Code: QB64: [Select]
  1. DECLARE SUB OneLine (LineOfCode$, Count%)
  2. DECLARE SUB Multiline (Line$, Count%)
  3. DECLARE FUNCTION Incr% (Intero%)
  4.  
  5. '_________INFO_______________________________________
  6. ' le funzioni DEF FN possono essere monoriga
  7. ' DEF fnP (a%)  = a% + 1
  8.  
  9. ' oppure  multiriga
  10. ' DEF fnP (a%)
  11. '      a% = a% * 3
  12. '      fnP= a% + 1
  13. ' END DEF
  14. ' le definizioni monoriga  o multiriga non si possono impilare a matrioska
  15. ' le DEF Fn devono avere almeno un parametro
  16. ' le DEF Fn non possono accedere alle variabili condivise
  17. ' nŠ avere variabili con lo stesso nome delle variabili condivise o globali
  18. ' ______________END of INFO___________________________
  19.  
  20. ' Project of program__________________________________________
  21. ' pseudocodice per il traduttore di FN a FUNCTION
  22. ' siccome in QB64 FN non Š un token allora lo lasciamo dov'Š
  23. ' e prendiamo una strata pi— semplice
  24.  
  25. ' apri il file da tradurre
  26. ' apri il file da tradotto da scrivere
  27. ' leggi il file riga per riga fino alla fine
  28. ' se c'Š un DEF FN
  29. '               se c'Š = Š una funzione a singola riga
  30. '                     scrivi nel file tradotto
  31. '                               FUNCTION e la parte della riga da FN e =
  32. '                               FNnomefunzione = la parte della riga dopo =
  33. '                               END FUNCTION
  34. '               altrimenti Š una funzione multiriga
  35. '                     scrivi nel file tradotto
  36. '                               FUNCTION e la parte della riga da FN in poi
  37. '                               memorizza il nome della FN
  38. '                               leggi il file riga per riga fino a quando
  39. '                               trova END DEF o ottiene fine file
  40. '                                       se Š presente EXIT DEF scrivi EXIT FUNCTION
  41. '                                       se Š presente END DEF esci dal loop
  42. '                                       scrivi la riga
  43. '                               END FUNCTION
  44. '
  45. ' End of Project of Program____________________________________________________
  46.  
  47.  
  48. ' constants of token to translate
  49. CONST Primo = "DEF FN", Secondo = "=", Terzo = "FN"
  50. CONST Quarto = "EXIT DEF", Quinto = "END DEF", Sesto = "("
  51. ' variable to process lines of code
  52. Counter% = 0 ' it counts how many functions are translated
  53. Fi$ = "" ' File of input
  54. Fo$ = "" ' File of output
  55. Fdef$ = "" ' Temporary file for function translated
  56. LineOfCode$ = "" ' it brings the line of code read from file
  57.  
  58. Fi$ = COMMAND$ ' File of input
  59. IF Fi$ = "" THEN
  60.     CLS
  61.     PRINT "DEF2FUN Help:"
  62.     PRINT " Usage: DEF2FUN NamefileToTranslate"
  63.     PRINT " It needs one parameter at run "
  64.     END
  65.  
  66. LenFi = LEN(Fi$)
  67. IF INSTR(Fi$, ".") THEN
  68.     ' name file has extention
  69.     ExtFi$ = RIGHT$(Fi$, LEN(Fi$) - INSTR(Fi$, ".") + 1)
  70.     NamFi$ = LEFT$(Fi$, INSTR(Fi$, ".") - 1)
  71.     Fo$ = LEFT$(NamFi$, LenFi - 3) + "Tmp" + ExtFi$
  72.     Fdef$ = LEFT$(NamFi$, LenFi - 3) + ".TMP"
  73.     ' name file has no extension
  74.     Fo$ = "Tmp" + LEFT$(Fi$, 3)
  75.     Fdef$ = Fo$ + ".TMP"
  76.  
  77.  
  78. ' open files for input and output
  79. PRINT "Opening files..."
  80. OPEN Fi$ FOR INPUT AS #1
  81. PRINT " Opened Input file..."
  82. OPEN Fo$ FOR OUTPUT AS #2
  83. OPEN Fdef$ FOR OUTPUT AS #3
  84. PRINT " Opened output file..."
  85.  
  86. ' it puts author's sign
  87. PRINT #2, " REM  File made by DEF2FUNC utility by TempodiBasic "
  88. PRINT #2, " REM  DEF2FUNC translate any function DEF FN to the FUNCTION syntax"
  89. PRINT #2, ""
  90.  
  91. ' main loop processing file
  92.     PRINT " Reading file...";
  93.     LINE INPUT #1, LineOfCode$
  94.     PRINT LineOfCode$
  95.     ' search a definition of DEF FN
  96.     IF INSTR(UCASE$(LineOfCode$), Primo) THEN
  97.         PRINT " Found a DEF FN: "; LineOfCode$
  98.         PRINT #3, "FUNCTION ";
  99.         '  is DEF FN in oneline or in multiline?
  100.         IF INSTR(LineOfCode$, Secondo) THEN
  101.             OneLine LineOfCode$, Counter%
  102.         ELSE
  103.             Multiline LineOfCode$, Counter%
  104.         END IF
  105.     ELSE ' no definition of DEF FN
  106.         PRINT #2, LineOfCode$
  107.     END IF
  108. PRINT "End of translation..."
  109. PRINT " Rebuilding the file..."
  110. CLOSE ' closes all files
  111. OPEN Fo$ FOR APPEND AS #1
  112. OPEN Fdef$ FOR INPUT AS #2
  113.     LINE INPUT #2, LineOfCode$
  114.     PRINT #1, LineOfCode$
  115. CLOSE ' closes all files
  116. PRINT " File translated ..."
  117. KILL Fdef$
  118. END ' end of program
  119.  
  120. FUNCTION Incr% (Intero%)
  121.     Incr% = Intero% + 1
  122.  
  123. SUB Multiline (Line$, Counter%)
  124.     PRINT " It is a multiline DEF FN"
  125.     ' this subprogram process a DEF FN on multiline
  126.     NextLine$ = ""
  127.     Counter% = Incr(Counter%)
  128.     NameOfFN$ = RIGHT$(Line$, LEN(Line$) - (INSTR(UCASE$(Line$), Primo) + LEN(Primo) - 3))
  129.     PRINT #3, NameOfFN$
  130.     DO WHILE NOT EOF(1)
  131.         'here it processes multiline DEF FN after the first line of code
  132.         LINE INPUT #1, NextLine$
  133.         IF INSTR(UCASE$(NextLine$), Quarto) THEN
  134.             PRINT #3, " EXIT FUNCTION "
  135.         ELSEIF INSTR(UCASE$(NextLine$), Quinto) THEN
  136.             EXIT DO
  137.         ELSE
  138.             PRINT #3, NextLine$
  139.         END IF
  140.     LOOP
  141.     PRINT #3, "END FUNCTION"
  142.  
  143. SUB OneLine (LineOfCode$, Counter%)
  144.     PRINT " It is a oneline DEF FN"
  145.     ' this subprogram process a DEF FN on oneline
  146.     Counter% = Incr(Counter%)
  147.     Start% = INSTR(UCASE$(LineOfCode$), Primo) + LEN(Primo) - 2
  148.     Lenght% = INSTR(UCASE$(LineOfCode$), Secondo) - Start%
  149.     NameOfFN$ = MID$(LineOfCode$, Start%, Lenght%)
  150.     PRINT "FUNCTION "; NameOfFN$
  151.     PRINT #3, NameOfFN$
  152.     PRINT #3, LEFT$(NameOfFN$, INSTR(NameOfFN$, "(") - 1);
  153.     PRINT #3, RIGHT$(LineOfCode$, LEN(LineOfCode$) - (INSTR(UCASE$(LineOfCode$), Secondo) - 1))
  154.     PRINT #3, "END FUNCTION"
  155.  
  156.  

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Thanks Mark! Yeah, I'm getting on in years, and I can't stand taking extra steps to do things, if there is an easier way. Select - Copy - Paste into the IDE. Those are the only code samples I look at and try these days. One exception. If I see something interesting, and the zip has multiple files and/or is too big to post, because of board limits. Actually, in the case of multiple files, the zip is a step saver. I just would appreciate if all small enough to post code snippets without dependency files, would be posted in code boxes. Now if you will excuse me, this laxative isn't going to drink itself. Oh dam, chocolate again!

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
I am testing TempodiBasic's conversion and I have a question about the old QB45 way to use DEF FN: Didn't it use to be like this:
Code: QB64: [Select]
  1. DEF FN oneTheHardWay(theta) = sin(theta) ^2 + cos(theta) ^2
  2.  
  3. print oneTheHardWay(_pi/4)
  4.  

TempodiBasic has it this way, with the FN as part of the function name:
Code: QB64: [Select]
  1. DEF fnPiuUno (z%) = z% + 1
  2. DEF FNPer2 (z%) = z% * 2
  3. DEF fNPer10 (z%) = z% * 10
  4. DEF FnDiv1 (z%) = z% / 1
  5.  
  6.  
  7. FOR a% = 1 TO 10 STEP 1
  8.    PRINT fnPiuUno(a%), FNPer2(a%), fNPer10(a%), FnDiv1(a%)
  9.  
  10. NEXT a%
  11.  
  12.  
  13.  

It's been like 25 years! Is the FN supposed to be part of the DEF FN name?

I ask because the conversion did this:
Code: QB64: [Select]
  1.  REM  File made by DEF2FUNC utility by TempodiBasic
  2.  REM  DEF2FUNC translate any function DEF FN to the FUNCTION syntax
  3.  
  4.  
  5. print oneTheHardWay(_pi/4)
  6.  
  7. FUNCTION FN oneTheHardWay(theta)
  8. FN oneTheHardWay= sin(theta) ^2 + cos(theta) ^2
  9.  

Which is surely not going to work.
« Last Edit: April 30, 2020, 12:21:20 pm by bplus »

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Nice and neat!

You may want to consider FOR BINARY instead of INPUT. If I ran my older 50K QB programs through this, FOR BINARY would make the conversions a lot faster. Smaller programs, still faster but hardly noticeable.

I like that it appears to handle one or more DEF FN lines. One screw up that could happen is a rare instance of something like this...

Code: QB64: [Select]
  1. REM DEF FN: Pete is the biggest and best function ever created!

Would it stumble on that?

Anyway, this may or may not need any tweaking, but if perfect as is or could be made perfect, this would be a shining star addition to the tool box and would help lay to rest any more "demands" for adding DEF FN to the language. Honestly, it was only added to QB to save the space that language so so limited by.

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Hi Pete, so FN has to be a prefix to the function name ie DEF FNmyFunction and not DEF FN myFunction ?

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
@bplus: Mark, I used to use this for INKEY$ routines, and I still remember adding the variable to the DEF FN as DEF FNb$, so yes, it's been a long time, but I recall you had to combine the variable to the FN part. FN I'm not mistaken!

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Hi guys
Thanks for feedbacks

1. this is the information that I have got from QBASIC and QB45 Help
Quote
'_________INFO_______________________________________
'DEF FN functions can be single-line
'DEF fnP (a%) = a% + 1
 
'or multi-line
'DEF fnP (a%)
'a% = a% * 3
'fnP = a% + 1
'END DEF
'single line or multi line definitions cannot be stacked in matryoshka
'DEF Fn must have at least one parameter
'DEF Fn cannot access shared variables
'no have variables with the same name as shared or global variables
'______________END of INFO___________________________

Using Qbasic, the FN part of Syntax  is not changed by the parser (or syntax's checker) while DEF is uppercased!
In the first attempt I was trying to remove the FN part of the name of the function (I got this), but it is indifferent for QB64 and this task increases time used so I leave FN there.

2.  thanks for suggestion to improve this little tool

about REM or '     it is good to fix that also if  it is rare to find a REM for oneline function but it is possible

about a BINARY access to the file I'll do the update as soon as to make faster the tool

Thanks again
Programming isn't difficult, only it's  consuming time and coffee

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Hi
going deeper to develope the managment of exception of comments with REM or '
I find another exception... when DEF FN is in a string (closed between two " ") and it requires some controls to work well.
Soon DEF2FUN 1.0
Thanks for feedbacks
Programming isn't difficult, only it's  consuming time and coffee

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Hi guys
I'll be back for DEF2FUN 1.0
and it is here!

 
DEF2FUN 1.0.jpg


Thanks to feedbacks and suggestion of Pete and Bplus I have moved to the second pass gaining the 1.0 version
1. added BINARY access to file with LINE INPUT aa only QB64 let's do  http://qb64.org/wiki/LINE_INPUT_(file_statement)
Quote
NOTE: LINE INPUT will work faster in BINARY mode than in INPUT mode.
Using LINE INPUT # in BINARY mode is possible in version 1.000 and up

2. comments issue:
the first is this
Code: QB64: [Select]
  1. REM DEF FN: Pete is the biggest and best function ever created!
that opens the way to a set of issue about
REM and ' as comments operators

Now DEF2FUN manages REM and ' both in first position both as added comments to the line of code

3. String issue:
as for REM and '
Code: QB64: [Select]
  1. PRINT " this is a DEF Fn demo"

Now DEF2FUN manages string containing Keywords of DEF FN

Here the code of this command line tool ( remember that you can drag & drop file to translate)

Code: QB64: [Select]
  1. DECLARE SUB OneLine (LineOfCode$, Count%)
  2. DECLARE SUB Multiline (Line$, Count%)
  3. DECLARE FUNCTION Incr% (Intero%)
  4.  
  5. '_________INFO_______________________________________
  6. ' le funzioni DEF FN possono essere monoriga
  7. ' DEF fnP (a%)  = a% + 1
  8.  
  9. ' oppure  multiriga
  10. ' DEF fnP (a%)
  11. '      a% = a% * 3
  12. '      fnP= a% + 1
  13. ' END DEF
  14. ' le definizioni monoriga  o multiriga non si possono impilare a matrioska
  15. ' le DEF Fn devono avere almeno un parametro
  16. ' le DEF Fn non possono accedere alle variabili condivise
  17. ' nŠ avere variabili con lo stesso nome delle variabili condivise o globali
  18. ' bisogna evitare di tradurre un REM o '
  19. ' se non Š passato il nome del file mostra la info
  20. ' ______________END of INFO___________________________
  21. _TITLE "DEF_FN_2_FUNCTION 1.0"
  22. ' constants of token to translate
  23. CONST Primo = "DEF FN", Secondo = "=", Terzo = "FN"
  24. CONST Quarto = "EXIT DEF", Quinto = "END DEF", Sesto = "("
  25.  
  26. ' variable to process lines of code
  27. Counter% = 0 ' it counts how many functions are translated
  28. Fi$ = "" ' File of input
  29. Fo$ = "" ' File of output
  30. Fdef$ = "" ' Temporary file for function translated
  31. LineOfCode$ = "" ' it brings the line of code read from file
  32.  
  33. Fi$ = COMMAND$ ' File of input
  34. IF Fi$ = "" THEN
  35.     CLS
  36.     PRINT "DEF2FUN Help:"
  37.     PRINT " Usage: DEF2FUN NamefileToTranslate"
  38.     PRINT " It needs one parameter at run "
  39.     END
  40.  
  41. LenFi = LEN(Fi$)
  42. IF INSTR(Fi$, ".") THEN
  43.     ' name file has extention
  44.     ExtFi$ = RIGHT$(Fi$, LEN(Fi$) - INSTR(Fi$, ".") + 1)
  45.     NamFi$ = LEFT$(Fi$, INSTR(Fi$, ".") - 1)
  46.     Fo$ = LEFT$(NamFi$, LenFi - 3) + "Tmp" + ExtFi$
  47.     Fdef$ = LEFT$(NamFi$, LenFi - 3) + ".TMP"
  48.     ' name file has no extension
  49.     Fo$ = "Tmp" + LEFT$(Fi$, 3)
  50.     Fdef$ = Fo$ + ".TMP"
  51.  
  52.  
  53. ' open files for input and output
  54. PRINT "Opening files..."
  55. OPEN Fi$ FOR BINARY AS #1 ' only QB64 1.0 or more can use LINE INPUT in Binary mode
  56. ' suggested by Pete
  57. PRINT " Opened Input file..."
  58. OPEN Fo$ FOR OUTPUT AS #2
  59. OPEN Fdef$ FOR OUTPUT AS #3
  60. PRINT " Opened output file..."
  61.  
  62. ' it puts author's sign
  63. PRINT #2, " REM  File made by DEF2FUNC utility by TempodiBasic "
  64. PRINT #2, " REM  DEF2FUNC translate any function DEF FN to the FUNCTION syntax"
  65. PRINT #2, ""
  66.  
  67. ' main loop processing file
  68.     PRINT " Reading file...";
  69.     LINE INPUT #1, LineOfCode$
  70.     PRINT LineOfCode$
  71.     ' search a definition of DEF FN
  72.     DefPos% = INSTR(UCASE$(LineOfCode$), Primo) ' is there a DEF FN?
  73.     RemPos% = INSTR(UCASE$(LineOfCode$), "REM") ' is there a REM?
  74.     Rem2Pos% = INSTR(UCASE$(LineOfCode$), "'") ' is there an '?
  75.     StringPos% = INSTR(UCASE$(LineOfCode$), CHR$(34)) ' is there an " ?
  76.     StringPos2% = INSTR(StringPos% + 1, UCASE$(LineOfCode$), CHR$(34)) ' is there a second "?
  77.  
  78.     ' if it must be translated
  79.     IF DefPos% > 0 THEN
  80.  
  81.         ' if DEF FN is into a string it'll be put into file
  82.         IF (StringPos% > 0 AND StringPos2% > 0) AND ((DefPos% > StringPos%) AND (DefPos% < StringPos2%)) THEN
  83.             'write to file main
  84.             PRINT #2, LineOfCode$
  85.         ELSEIF (RemPos% > 0) XOR (Rem2Pos% > 0) THEN
  86.             ' there is a comment with REM XOR '
  87.  
  88.             ' if it is a comment so it'll be put into file
  89.             IF (RemPos% = 1 XOR Rem2Pos% = 1) THEN
  90.                 'write to file main
  91.                 PRINT #2, LineOfCode$
  92.  
  93.             ELSEIF ((RemPos% < DefPos% AND RemPos%) XOR (Rem2Pos% < DefPos% AND Rem2Pos%)) THEN
  94.                 ' if there is DEF FN in the same line it is at right of comment's keywords
  95.                 ' it is in the comment so it'll put into file
  96.                 PRINT #2, LineOfCode$
  97.  
  98.             ELSEIF (RemPos% > DefPos%) THEN
  99.                 ' a REM after DEF FN
  100.                 RemLine$ = RIGHT$(LineOfCode$, LEN(LineOfCode$) - RemPos% + 1)
  101.                 LineOfCode$ = LEFT$(LineOfCode$, RemPos% - 1)
  102.                 PRINT #3, RemLine$
  103.                 Extract_DEF_Fn (LineOfCode$)
  104.  
  105.             ELSEIF (Rem2Pos% > DefPos%) THEN
  106.                 ' an ' after DEF FN
  107.                 RemLine$ = RIGHT$(LineOfCode$, LEN(LineOfCode$) - Rem2Pos% + 1)
  108.                 LineOfCode$ = LEFT$(LineOfCode$, Rem2Pos% - 1)
  109.                 PRINT #3, RemLine$
  110.                 Extract_DEF_Fn (LineOfCode$)
  111.             END IF
  112.         ELSE
  113.             ' there is DEF FN and no REM ' " "
  114.             Extract_DEF_Fn (LineOfCode$)
  115.         END IF
  116.     ELSE
  117.         ' it has no DEF FN
  118.         ' write line to the main file because it mustn't be translated
  119.         PRINT #2, LineOfCode$
  120.     END IF
  121. PRINT "End of translation..."
  122. PRINT " Rebuilding the file..."
  123. CLOSE ' closes all files
  124. OPEN Fo$ FOR APPEND AS #1
  125. OPEN Fdef$ FOR INPUT AS #2
  126.     LINE INPUT #2, LineOfCode$
  127.     PRINT #1, LineOfCode$
  128. CLOSE ' closes all files
  129. PRINT " File translated ..."
  130. KILL Fdef$
  131. END ' end of program
  132.  
  133.  
  134. SUB Extract_DEF_Fn (LineOfCode$)
  135.     ' if there is a DEF FN
  136.     PRINT " Found a DEF FN: "; LineOfCode$
  137.     PRINT #3, "FUNCTION ";
  138.     '  is DEF FN in oneline or in multiline?
  139.     IF INSTR(LineOfCode$, Secondo) THEN
  140.         OneLine LineOfCode$, Counter%
  141.     ELSE
  142.         Multiline LineOfCode$, Counter%
  143.     END IF
  144.  
  145.  
  146.  
  147. FUNCTION Incr% (Intero%)
  148.     Incr% = Intero% + 1
  149.  
  150. SUB Multiline (Line$, Counter%)
  151.     PRINT " It is a multiline DEF FN"
  152.     ' this subprogram process a DEF FN on multiline
  153.     NextLine$ = ""
  154.     Counter% = Incr(Counter%)
  155.     NameOfFN$ = RIGHT$(Line$, LEN(Line$) - (INSTR(UCASE$(Line$), Primo) + LEN(Primo) - 3))
  156.     PRINT #3, NameOfFN$
  157.     DO WHILE NOT EOF(1)
  158.         'here it processes multiline DEF FN after the first line of code
  159.         LINE INPUT #1, NextLine$
  160.         IF INSTR(UCASE$(NextLine$), Quarto) THEN
  161.             PRINT #3, " EXIT FUNCTION "
  162.         ELSEIF INSTR(UCASE$(NextLine$), Quinto) THEN
  163.             EXIT DO
  164.         ELSE
  165.             PRINT #3, NextLine$
  166.         END IF
  167.     LOOP
  168.     PRINT #3, "END FUNCTION"
  169.  
  170. SUB OneLine (LineOfCode$, Counter%)
  171.     PRINT " It is an oneline DEF FN"
  172.     ' this subprogram process a DEF FN on oneline
  173.     Counter% = Incr(Counter%)
  174.     Start% = INSTR(UCASE$(LineOfCode$), Primo) + LEN(Primo) - 2
  175.     Lenght% = INSTR(UCASE$(LineOfCode$), Secondo) - Start%
  176.     NameOfFN$ = MID$(LineOfCode$, Start%, Lenght%)
  177.     PRINT "FUNCTION "; NameOfFN$
  178.     PRINT #3, NameOfFN$
  179.     PRINT #3, LEFT$(NameOfFN$, INSTR(NameOfFN$, "(") - 1);
  180.     PRINT #3, RIGHT$(LineOfCode$, LEN(LineOfCode$) - (INSTR(UCASE$(LineOfCode$), Secondo) - 1))
  181.     PRINT #3, "END FUNCTION"
  182.  

here code_files to test it:
DEFFN8.BAS
Code: QB64: [Select]
  1. DEF fnPiuUno (z%) = z% + 1 ' sum demo " Def Fn
  2. DEF FNPer2 (z%) = z% * 2  REM " Def Fn *2"
  3. DEF fNPer10 (z%) = z% * 10  REM multiplication function demo
  4. DEF FnDiv1 (z%) = z% / 1   'division function demo
  5.  
  6.  
  7. ' here main block starts
  8. FOR a% = 1 TO 10 STEP 1
  9.    PRINT " Def Fn Demo"
  10.    PRINT fnPiuUno(a%), FNPer2(a%), fNPer10(a%), FnDiv1(a%)
  11.    REM  PRINT  " All done DEF Fn Demo"
  12. NEXT a%
  13.  

DEFFN9.BAS
Code: QB64: [Select]
  1. DEF fnPiuUno (z%) = z% + 1
  2. DEF FNPer2 (z%) = z% * 2
  3. DEF fNPer10 (z%) = z% * 10
  4. DEF FnDiv1 (z%) = z% / 1   'division function demo
  5.  
  6.  
  7. ' here main block starts
  8. FOR a% = 1 TO 10 STEP 1
  9.    PRINT " Def Fn Demo"
  10.    PRINT fnPiuUno(a%), FNPer2(a%), fNPer10(a%), FnDiv1(a%)
  11.    REM  PRINT  " All done DEF Fn Demo"
  12. NEXT a%
  13.  

DEFFN4.BAS
Code: QB64: [Select]
  1. ' DEF FnP1(z%) = z%+999
  2. ' DEF fNP2(z%)
  3. '      fNP2= z%*1000
  4. ' END DEF
  5.  
  6. DEF fnPiuUno (z%)
  7.         fnPiuUno = z% + 1
  8. DEF fNPer10 (z%) = z% * 10
  9. DEF FNPer2(z%)
  10.     FNPer2 = fNPer10(z%) * 2
  11. DEF FnDiv1 (z%) = z% / 1
  12.  
  13. ' main
  14. PRINT "this is a DEF Fn demo"
  15. FOR a% = 1 TO 10 STEP 1
  16.    PRINT fnPiuUno(a%), FNPer2(a%), fNPer10(a%), FnDiv1(a%)
  17. NEXT a%
  18.  

DEFFN3.BAS
Code: QB64: [Select]
  1. ' DEF FnP1(z%) = z%+999
  2. ' DEF fNP2(z%)
  3. '      fNP2= z%*1000
  4. ' END DEF
  5.  
  6. DEF fnPiuUno (z%)
  7.         fnPiuUno = z% + 1
  8. DEF fNPer10 (z%) = z% * 10
  9. DEF FNPer2(z%)
  10.     FNPer2 = fNPer10(z%) * 2
  11. DEF FnDiv1 (z%) = z% / 1
  12.  
  13. ' main
  14. FOR a% = 1 TO 10 STEP 1
  15.    PRINT fnPiuUno(a%), FNPer2(a%), fNPer10(a%), FnDiv1(a%)
  16. NEXT a%
  17.  

DEFFN2.BAS
Code: QB64: [Select]
  1. REM DEF FnP1(z%) = z%+999
  2. REM DEF fNP2(z%)
  3. REM      fNP2= z%*1000
  4.  
  5. DEF fnPiuUno (z%)
  6.         fnPiuUno = z% + 1
  7. DEF fNPer10 (z%) = z% * 10
  8. DEF FNPer2(z%)
  9.     FNPer2 = fNPer10(z%) * 2
  10. DEF FnDiv1 (z%) = z% / 1
  11.  
  12. ' main
  13. FOR a% = 1 TO 10 STEP 1
  14.    PRINT fnPiuUno(a%), FNPer2(a%), fNPer10(a%), FnDiv1(a%)
  15. NEXT a%
  16.  

DEFFN1.BAS
Code: QB64: [Select]
  1. DEF fnPiuUno (z%) = z% + 1
  2.  
  3.  
  4. FOR a% = 1 TO 10 STEP 1
  5.    PRINT fnPiuUno(a%)
  6. NEXT a%

DEFFN0.BAS
Code: QB64: [Select]
  1. DEF fnPiuUno (z%)
  2.         fnPiuUno = z% + 1
  3. DEF fNPer10 (z%) = z% * 10
  4. DEF FNPer2(z%)
  5.     FNPer2 = fNPer10(z%) * 2
  6. DEF FnDiv1 (z%) = z% / 1
  7.  
  8. ' main
  9. FOR a% = 1 TO 10 STEP 1
  10.    PRINT fnPiuUno(a%), FNPer2(a%), fNPer10(a%), FnDiv1(a%)
  11. NEXT a%
  12.  


Thanks to read and try
Welcome feedbacks

@Pete
No zip or tar or other compressed files, do you like this?
Programming isn't difficult, only it's  consuming time and coffee

FellippeHeitor

  • Guest
One thing you may want to consider is scope. DEF FN procedures can access variables in the main module, since they belong to that scope. When you turn them into a function, older programs may completely break if they rely on the FN accessing local variables.

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
One thing you may want to consider is scope. DEF FN procedures can access variables in the main module, since they belong to that scope. When you turn them into a function, older programs may completely break if they rely on the FN accessing local variables.

Well in that CASE, I think Temp could look into making a variable in DEF FN local, by putting it in a STATIC statement.

DEF FN can only pass variables by value and I recall in my multi-modular programs, they were only global to the module they were contained in. In other words, if you had a 2 module program and you wanted the same DEF FN to work in both, you'd have to define the DEF FN statements in each module, and if you wanted variables passed to the other module, you had to define those variables as COMMON SHARED. Wow, this stuff takes me back to the 90's. Remind me to pick up my hair for the return trip. This Donald Trump comb over is a real pain without access to my dollar store teenage girl hairspray.

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Hi Fellippe and Pete
thanks for feedbacks

@Fellippe
never used into a program DEF Fn so my knowledge about it is purely theoretic

about scope
Quote
One thing you may want to consider is scope. DEF FN procedures can access variables in the main module, since they belong to that scope. When you turn them into a function, older programs may completely break if they rely on the FN accessing local variables.

@Pete
Yes the Help in Qbasic describes the limitation of DEF Fn for the single module where it is declared.

Thanks so these more informations can lead to more development of this little tool.
Programming isn't difficult, only it's  consuming time and coffee

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Hi

I have made some experiments with DEF Fn in QBasic and yes I have missed that feature to access  to the main module's variables without SHARED in DEF Fn or DIM SHARED in main module. Moreover SHARED is forbidden into DEF Fn multiline.
Surely it is impossible to declare  in DEF Fn multiline  a variable  with the same name of those in main module already declared, but as good Qbasic/QB bug you can declare a variable in main and also in DEF Fn multiline with DIM if DEF Fn is before the  declaration in main module!.

So I think that if it is impossible to distinguish between variables of DEF FN multiline and  variables used in DEF fn multiline but declared into main module.
if you run this code into Qbasic
Code: Text: [Select]
  1. DEF FnDue(z%)
  2. DIM  a%
  3. PRINT a%
  4. FnDue = z% * a%
  5. END DEF
  6.  
  7. CLS
  8. a% = 10
  9. PRINT a%
  10. PRINT FnDue(4)
  11. END
  12.  
and after F5 you'll get as output
Quote
10
10
40
This output lets us think that the code is running first main module sequence and after the DEF Fn sequence.
But is it legal in QBasic/QB/QB64 declare a variable with assignation and then declare the same variable with DIM? NO
So the first line of DEF FN multiline
Code: Text: [Select]
  1. DIM a%
must activate the error like we get if in main we type
Code: QB64: [Select]
  1. c% = 1
  2. DIM c%
just if a% in the main module and DIM a% in DEF Fn are the same variable! In the case that the two previous variables  are different (and not the same) we must get as output
Quote
10
0
0
because in DEF Fn a% has no assignment .  Indeed here we found another dual experience of principle of Heisenberg  https://en.wikipedia.org/wiki/Uncertainty_principle  :-) we don't know the whole universe!

Coming back to the translator of DEF Fn to FUNCTION we must admit that the issue of broken correlation between main module and DEF Fn multiline comes out for DEF Fn multiline.
The point of gray is the real possibility to define a variable into DEF FN using DIM with the same name of a variable declared into main module using the assignment statement. (as showed into following code)
Code: Text: [Select]
  1. DEF FnQbasicBug (z%)
  2. DIM a%
  3. FnQbasicBug= z% * a%
  4. END DEF
  5.  
  6. a% = 10
  7. PRINT a%, FnQbasicBug(4)
  8.  

and this strange behaviour is claimed in the same help of Qbasic with a warning don't modify global variable into DEF Fn and don't execute graphic statements into DEF Fn.

Well in conclusion I think that the issue can be solved except for the rare case of a coder that declare in DEF Fn a variable with the same name of another variable declared into the main module .

Waiting suggestions to solve this task for now I have thought  an array for a list of variable of main to shared.

Thanks to read and talk.
Programming isn't difficult, only it's  consuming time and coffee