Author Topic: Noob question: does QB64 allow making up variable names at runtime?  (Read 4233 times)

0 Members and 1 Guest are viewing this topic.

Offline FilipeEstima

  • Newbie
  • Posts: 63
    • View Profile
I will try my best to ask this without making it too confusing. I'd like to know if it's possible to make a program, where depending on certain conditions, it creates a new variable. Example: there is no "variable1" in the .bas file, but if certain conditions happen, a variable by that name is created by the program, which then makes part of a routine. It would be more or less like a program trying to expand itself beyong original code. Can this be done?

Offline RhoSigma

  • QB64 Developer
  • Forum Resident
  • Posts: 565
    • View Profile
Re: Noob question: does QB64 allow making up variable names at runtime?
« Reply #1 on: April 19, 2019, 06:32:03 am »
If you talk about something like the parse_str function in PHP, which converts a URL query string into new variables, eg. you call a website as http://www.xyz.com/login.php?user=me&pass=hello, and your login.php script will use parse_str on it to create variables $user containing the value "me" and the variable $pass containing the value "hello", then the clear answer to your question is NO, QB64 is not able to do that.
My Projects:   https://qb64forum.alephc.xyz/index.php?topic=809
GuiTools - A graphic UI framework (can do multiple UI forms/windows in one program)
Libraries - ImageProcess, StringBuffers (virt. files), MD5/SHA2-Hash, LZW etc.
Bonus - Blankers, QB64/Notepad++ setup pack

FellippeHeitor

  • Guest
Re: Noob question: does QB64 allow making up variable names at runtime?
« Reply #2 on: April 19, 2019, 08:26:59 am »
Yeah, can't be done.

The closest you'll get, which is what people who write interpreters with QB64 usually do, is have an expanding set of arrays to store name, type and value. That would emulate creating a new variable at runtime.

Here's an overkill example (it's an actual toy interpreter I've started writing, https://github.com/FellippeHeitor/QB64-interpreter), but it does what I'm suggesting above.

Code: QB64: [Select]
  1. CONST true = -1, false = NOT true
  2. CONST debugging = false
  3.  
  4.  
  5. KEY 2, "LIST" + CHR$(13)
  6. KEY 3, "LOAD "
  7. KEY 4, "SAVE "
  8. KEY 5, "RUN" + CHR$(13)
  9.  
  10. TYPE vartype
  11.     name AS STRING * 40
  12.     type AS _BYTE
  13.     scope AS STRING * 50
  14.     protected AS _BYTE
  15.  
  16. CONST varType_FLOAT = 0
  17. CONST varTypeSTRING = 1
  18. CONST varTypeINTEGER = 2
  19. CONST varTypeSINGLE = 3
  20. CONST varTypeDOUBLE = 4
  21. CONST varType_UBYTE = 5
  22. CONST varType_BYTE = 6
  23. CONST varType_UINTEGER = 7
  24. CONST varType_UINTEGER64 = 8
  25. CONST varType_INTEGER64 = 9
  26. CONST varType_ULONG = 10
  27. CONST varTypeLONG = 11
  28.  
  29.  
  30. REDIM SHARED vars(0) AS vartype
  31. REDIM SHARED strings(0) AS STRING
  32. REDIM SHARED program(0) AS STRING
  33. DIM SHARED totalVars AS _UNSIGNED LONG, varType_DEFAULT AS _BYTE
  34. DIM SHARED thisScope$, currentLine AS _UNSIGNED LONG
  35. DIM doLine AS _UNSIGNED LONG, loopLine AS _UNSIGNED LONG
  36. DIM k AS LONG, externalLimit AS INTEGER
  37. DIM SHARED running AS _BYTE, loaded AS _BYTE, loadedFile$
  38. DIM SHARED CurrentSCREEN%
  39.  
  40. thisScope$ = "MAIN MODULE"
  41. varType_DEFAULT = varTypeSINGLE
  42.  
  43.     loaded = load(COMMAND$)
  44.     IF loaded THEN PRINT "Loaded - "; COMMAND$
  45.     IF LCASE$(RIGHT$(COMMAND$, 4)) <> ".bas" THEN
  46.         IF _FILEEXISTS(COMMAND$ + ".bas") THEN
  47.             loaded = load(COMMAND$ + ".bas")
  48.             IF loaded THEN PRINT "Loaded - "; COMMAND$ + ".bas"
  49.         ELSE
  50.             PRINT "File not found - "; COMMAND$ + ".bas"
  51.         END IF
  52.     ELSE
  53.         PRINT "File not found - "; COMMAND$
  54.     END IF
  55.  
  56. 'internal variables (functions)
  57. varIndex = addVar("val"): vars(varIndex).protected = true
  58. varIndex = addVar("int"): vars(varIndex).protected = true
  59. varIndex = addVar("asc"): vars(varIndex).protected = true
  60. varIndex = addVar("cos"): vars(varIndex).protected = true
  61. varIndex = addVar("sin"): vars(varIndex).protected = true
  62. varIndex = addVar("len"): vars(varIndex).protected = true
  63. varIndex = addVar("rnd"): vars(varIndex).protected = true
  64. varIndex = addVar("timer"): vars(varIndex).protected = true
  65. varIndex = addVar("time$"): vars(varIndex).protected = true
  66. varIndex = addVar("date$"): vars(varIndex).protected = true
  67. varIndex = addVar("inkey$"): vars(varIndex).protected = true
  68. varIndex = addVar("_width"): vars(varIndex).protected = true
  69. varIndex = addVar("_height"): vars(varIndex).protected = true
  70. varIndex = addVar("_mousex"): vars(varIndex).protected = true
  71. varIndex = addVar("_mousey"): vars(varIndex).protected = true
  72. varIndex = addVar("_mousebutton(1)"): vars(varIndex).protected = true
  73. varIndex = addVar("_mousebutton(2)"): vars(varIndex).protected = true
  74.  
  75. SCREEN CurrentSCREEN%
  76.     k = _KEYHIT
  77.  
  78.  
  79.     IF (k = ASC("C") OR k = ASC("c")) AND (_KEYDOWN(100305) OR _KEYDOWN(100306)) THEN
  80.         PRINT "Break."
  81.         IF running THEN running = false
  82.         _KEYCLEAR
  83.     END IF
  84.  
  85.     IF running THEN
  86.         currentLine = currentLine + 1
  87.         IF currentLine > UBOUND(program) THEN
  88.             running = false
  89.         ELSE
  90.             L1$ = program(currentLine)
  91.         END IF
  92.     END IF
  93.  
  94.     IF NOT running THEN _AUTODISPLAY: LINE INPUT "."; L1$
  95.  
  96.     L1$ = LTRIM$(RTRIM$(L1$))
  97.     L$ = UCASE$(L1$)
  98.     IF LEFT$(L$, 5) = "LOAD " THEN
  99.         tryWithExtension:
  100.         IF NOT running THEN
  101.             IF _FILEEXISTS(MID$(L1$, 6)) THEN
  102.                 loaded = load(MID$(L1$, 6))
  103.                 IF loaded THEN PRINT "Loaded."
  104.             ELSE
  105.                 IF RIGHT$(LCASE$(MID$(L1$, 6)), 4) = ".bas" THEN
  106.                     PRINT "File not found - "; MID$(L1$, 6)
  107.                 ELSE
  108.                     L1$ = L1$ + ".bas"
  109.                     GOTO tryWithExtension
  110.                 END IF
  111.             END IF
  112.         END IF
  113.     ELSEIF L$ = "RELOAD" THEN
  114.         IF NOT running THEN
  115.             IF loaded THEN
  116.                 L1$ = "LOAD " + loadedFile$
  117.                 GOTO tryWithExtension
  118.             ELSE
  119.                 PRINT "No program loaded."
  120.             END IF
  121.         END IF
  122.     ELSEIF LEFT$(L$, 7) = "INSERT " AND VAL(MID$(L$, 8)) > 0 THEN
  123.         IF NOT running THEN
  124.             IF loaded THEN
  125.                 IF VAL(MID$(L$, 8)) <= UBOUND(program) THEN
  126.                     REDIM _PRESERVE program(UBOUND(program) + 1) AS STRING
  127.                     FOR i = UBOUND(program) - 1 TO VAL(MID$(L$, 8)) STEP -1
  128.                         program(i + 1) = program(i)
  129.                     NEXT
  130.                     program(VAL(MID$(L$, 8))) = ""
  131.                     L$ = "EDIT " + MID$(L$, 8)
  132.                     GOTO Edit
  133.                 ELSE
  134.                     PRINT "Invalid line number -"; VAL(MID$(L$, 8))
  135.                 END IF
  136.             ELSE
  137.                 PRINT "No program loaded."
  138.             END IF
  139.         END IF
  140.     ELSEIF LEFT$(L$, 6) = "CHDIR " THEN
  141.         CHDIR MID$(L1$, 7)
  142.     ELSEIF LEFT$(L$, 6) = "MKDIR " THEN
  143.         MKDIR MID$(L1$, 7)
  144.     ELSEIF LEFT$(L$, 5) = "KILL " THEN
  145.         KILL MID$(L1$, 6)
  146.     ELSEIF LEFT$(L$, 7) = "DELETE " AND VAL(MID$(L$, 8)) > 0 THEN
  147.         IF NOT running THEN
  148.             IF loaded THEN
  149.                 IF INSTR(MID$(L$, 8), "-") = 0 THEN
  150.                     IF VAL(MID$(L$, 8)) <= UBOUND(program) THEN
  151.                         FOR i = VAL(MID$(L$, 8)) + 1 TO UBOUND(program)
  152.                             program(i - 1) = program(i)
  153.                         NEXT
  154.                         REDIM _PRESERVE program(UBOUND(program) - 1) AS STRING
  155.                     ELSE
  156.                         PRINT "Invalid line number -"; VAL(MID$(L$, 8))
  157.                     END IF
  158.                 ELSE
  159.                     'interval
  160.                     DIM lower AS _UNSIGNED LONG, upper AS _UNSIGNED LONG
  161.                     DIM interval$
  162.                     interval$ = MID$(L$, 8)
  163.                     lower = VAL(LEFT$(interval$, INSTR(interval$, "-") - 1))
  164.                     upper = VAL(MID$(interval$, INSTR(interval$, "-") + 1))
  165.                     IF lower > upper THEN SWAP lower, upper
  166.  
  167.                     IF lower < 1 OR upper > UBOUND(program) THEN
  168.                         PRINT "Invalid interval ("; LTRIM$(RTRIM$(interval$)); ")"
  169.                     ELSE
  170.                         FOR i = upper + 1 TO UBOUND(program)
  171.                             program(lower + (i - (upper + 1))) = program(i)
  172.                         NEXT
  173.                         REDIM _PRESERVE program(UBOUND(program) - (upper - lower) - 1) AS STRING
  174.                     END IF
  175.                 END IF
  176.             ELSE
  177.                 PRINT "No program loaded."
  178.             END IF
  179.         END IF
  180.     ELSEIF L$ = "SAVE" THEN
  181.         IF NOT running THEN
  182.             IF loaded THEN
  183.                 IF loadedFile$ = "" THEN
  184.                     PRINT "Missing: file name."
  185.                 ELSE
  186.                     DIM ff AS INTEGER
  187.                     ff = FREEFILE
  188.                     OPEN loadedFile$ FOR OUTPUT AS ff
  189.                     FOR i = 1 TO UBOUND(program)
  190.                         PRINT #ff, program(i)
  191.                     NEXT
  192.                     CLOSE ff
  193.                     PRINT "Saved - "; loadedFile$
  194.                 END IF
  195.             ELSE
  196.                 PRINT "No program loaded."
  197.             END IF
  198.         END IF
  199.     ELSEIF LEFT$(L$, 5) = "SAVE " THEN
  200.         IF NOT running THEN
  201.             saveFile$ = UCASE$(LTRIM$(RTRIM$(MID$(L$, 6))))
  202.             IF loaded THEN
  203.                 IF saveFile$ <> loadedFile$ THEN
  204.                     IF _FILEEXISTS(saveFile$) THEN
  205.                         INPUT "Overwrite (y/N)?", q$1
  206.                         IF LCASE$(q$1) = "y" THEN
  207.                             GOTO overWrite
  208.                         END IF
  209.                     ELSE
  210.                         GOTO overWrite
  211.                     END IF
  212.                 ELSE
  213.                     overWrite:
  214.                     ff = FREEFILE
  215.                     OPEN saveFile$ FOR OUTPUT AS ff
  216.                     FOR i = 1 TO UBOUND(program)
  217.                         PRINT #ff, program(i)
  218.                     NEXT
  219.                     CLOSE ff
  220.                     loadedFile$ = saveFile$
  221.                     PRINT "Saved - "; loadedFile$
  222.                 END IF
  223.             ELSE
  224.                 PRINT "No program loaded."
  225.             END IF
  226.         END IF
  227.     ELSEIF L$ = "NEW" OR LEFT$(L$, 4) = "NEW " THEN
  228.         IF NOT running THEN
  229.             IF LEN(L$) > 3 THEN loadedFile$ = MID$(L$, 5) ELSE loadedFile$ = ""
  230.             loaded = true
  231.             REDIM SHARED program(1) AS STRING
  232.         END IF
  233.     ELSEIF L$ = "_DISPLAY" THEN
  234.         _DISPLAY
  235.     ELSEIF LEFT$(L$, 5) = "EDIT " AND VAL(MID$(L$, 6)) > 0 THEN
  236.         IF NOT running THEN
  237.             Edit:
  238.             IF loaded THEN
  239.                 IF VAL(MID$(L$, 6)) = UBOUND(program) + 1 THEN
  240.                     REDIM _PRESERVE program(UBOUND(program) + 1) AS STRING
  241.                     'EDIT can be used to increase program size without the need for INSERT
  242.                 END IF
  243.  
  244.                 IF VAL(MID$(L$, 6)) <= UBOUND(program) THEN
  245.                     DIM row AS INTEGER, col AS INTEGER
  246.                     row = CSRLIN: col = POS(1)
  247.                     PRINT LEFT$(program(VAL(MID$(L$, 6))), 80);
  248.                     DO
  249.                         LOCATE row, col, 1
  250.                         k$ = "": WHILE k$ = "": k$ = INKEY$: _LIMIT 30: WEND
  251.                         SELECT CASE k$
  252.                             CASE CHR$(13)
  253.                                 DIM p$
  254.                                 p$ = ""
  255.                                 FOR i = 1 TO 80
  256.                                     p$ = p$ + CHR$(SCREEN(row, i))
  257.                                 NEXT
  258.                                 program(VAL(MID$(L$, 6))) = RTRIM$(p$)
  259.                                 EXIT DO
  260.                             CASE CHR$(27)
  261.                                 EXIT DO
  262.                             CASE CHR$(8)
  263.                                 IF col > 1 THEN
  264.                                     FOR i = col TO 80
  265.                                         LOCATE row, i - 1
  266.                                         PRINT CHR$(SCREEN(row, i));
  267.                                     NEXT
  268.                                     col = col - 1
  269.                                 END IF
  270.                             CASE CHR$(0) + CHR$(83)
  271.                                 FOR i = col TO 79
  272.                                     LOCATE row, i
  273.                                     PRINT CHR$(SCREEN(row, i + 1));
  274.                                 NEXT
  275.                             CASE CHR$(0) + CHR$(75)
  276.                                 IF col > 1 THEN col = col - 1
  277.                             CASE CHR$(0) + CHR$(77)
  278.                                 IF col < 80 THEN col = col + 1
  279.                             CASE ELSE
  280.                                 PRINT k$;
  281.                                 IF col < 80 THEN col = col + 1
  282.                         END SELECT
  283.                     LOOP
  284.                     PRINT
  285.                     LOCATE , , 0
  286.                 ELSE
  287.                     PRINT "Invalid line number -"; VAL(MID$(L$, 6))
  288.                 END IF
  289.             ELSE
  290.                 PRINT "No program loaded."
  291.             END IF
  292.         END IF
  293.     ELSEIF L$ = "LIST VARIABLES" THEN
  294.         IF NOT running THEN
  295.             DIM j AS _UNSIGNED LONG
  296.             j = 0
  297.             FOR i = 1 TO totalVars
  298.                 IF NOT vars(i).protected THEN
  299.                     j = j + 1
  300.                     PRINT RTRIM$(vars(i).name); " = ";
  301.                     IF vars(i).type = varTypeSTRING THEN
  302.                         PRINT CHR$(34); strings(i); CHR$(34)
  303.                     ELSE
  304.                         PRINT nums(i)
  305.                     END IF
  306.  
  307.                     IF j MOD 20 = 0 AND i < totalVars THEN
  308.                         PRINT "-- hit a key --"
  309.                         k$ = "": WHILE k$ = "": k$ = INKEY$: _LIMIT 30: WEND
  310.                         IF k$ = CHR$(3) THEN
  311.                             PRINT "Break."
  312.                             GOTO ListEnd
  313.                         END IF
  314.                         _KEYCLEAR
  315.                     END IF
  316.                 END IF
  317.             NEXT
  318.         END IF
  319.     ELSEIF L$ = "LIST" OR L$ = "LIST PAUSE" THEN
  320.         IF NOT running THEN
  321.             IF loaded THEN
  322.                 DIM maxSpaceBefore AS INTEGER, prevFG AS _UNSIGNED LONG, prevBG AS _UNSIGNED LONG
  323.                 DIM thisLineNum$, screenMaxCols AS INTEGER
  324.  
  325.                 prevFG = _DEFAULTCOLOR
  326.                 prevBG = _BACKGROUNDCOLOR
  327.  
  328.                 IF _PIXELSIZE = 0 THEN
  329.                     screenMaxCols = _WIDTH
  330.                 ELSE
  331.                     screenMaxCols = _WIDTH / _PRINTWIDTH("W")
  332.                 END IF
  333.  
  334.                 maxSpaceBefore = LEN(STR$(UBOUND(program))) + 1
  335.  
  336.                 MyBad = true
  337.                 COLOR , 0
  338.                 MyBad = false
  339.  
  340.                 FOR i = 1 TO UBOUND(program)
  341.                     thisLineNum$ = STR$(i)
  342.                     thisLineNum$ = SPACE$(maxSpaceBefore - LEN(thisLineNum$) - 1) + thisLineNum$ + " "
  343.                     MyBad = true
  344.                     COLOR 8
  345.                     MyBad = false
  346.                     PRINT thisLineNum$;
  347.  
  348.                     MyBad = true
  349.                     COLOR 7
  350.                     MyBad = false
  351.                     PRINT program(i);
  352.  
  353.                     IF POS(1) < screenMaxCols THEN
  354.                         PRINT SPACE$((screenMaxCols + 1) - POS(1));
  355.                     END IF
  356.  
  357.                     IF i MOD 20 = 0 AND L$ = "LIST PAUSE" THEN
  358.                         MyBad = true
  359.                         COLOR 8
  360.                         MyBad = false
  361.  
  362.                         PRINT "-- hit a key --"
  363.                         k$ = "": WHILE k$ = "": k$ = INKEY$: _LIMIT 30: WEND
  364.                         IF k$ = CHR$(3) THEN
  365.                             COLOR prevFG, prevBG
  366.                             PRINT "Break."
  367.                             GOTO ListEnd
  368.                         END IF
  369.                         _KEYCLEAR
  370.                     END IF
  371.                 NEXT
  372.                 COLOR prevFG, prevBG
  373.                 PRINT "End of file - "; loadedFile$
  374.                 ListEnd:
  375.             ELSE
  376.                 PRINT "No program loaded."
  377.             END IF
  378.         END IF
  379.     ELSEIF LEFT$(L$, 5) = "LIST " AND VAL(MID$(L$, 6)) > 0 THEN
  380.         IF NOT running THEN
  381.             IF loaded THEN
  382.                 IF VAL(MID$(L$, 6)) <= UBOUND(program) THEN
  383.                     PRINT program(VAL(MID$(L$, 6)))
  384.                 ELSE
  385.                     PRINT "Invalid line number -"; VAL(MID$(L$, 6))
  386.                 END IF
  387.             ELSE
  388.                 PRINT "No program loaded."
  389.             END IF
  390.         END IF
  391.     ELSEIF LEFT$(L$, 6) = "WIDTH " THEN
  392.         DIM p1$, p2$
  393.         p$ = MID$(L$, 7)
  394.         IF INSTR(p$, ",") THEN
  395.             p1$ = LEFT$(p$, INSTR(p$, ",") - 1)
  396.             p2$ = MID$(p$, INSTR(p$, ",") + 1)
  397.             IF LEN(p1$) = 0 THEN
  398.                 WIDTH , GetVal(p2$)
  399.             ELSE
  400.                 WIDTH GetVal(p1$), GetVal(p2$)
  401.             END IF
  402.         ELSE
  403.             WIDTH GetVal(p$)
  404.         END IF
  405.     ELSEIF LEFT$(L$, 10) = "RANDOMIZE " THEN
  406.         IF GetVal(MID$(L$, 11)) > 0 THEN
  407.             RANDOMIZE GetVal(MID$(L$, 11))
  408.         END IF
  409.     ELSEIF LEFT$(L$, 7) = "_LIMIT " THEN
  410.         IF GetVal(MID$(L$, 8)) > 0 THEN
  411.             externalLimit = GetVal(MID$(L$, 8))
  412.         END IF
  413.     ELSEIF LEFT$(L$, 1) = "'" OR LEFT$(L$, 4) = "REM " OR L$ = "'" OR L$ = "REM" OR L$ = "" THEN
  414.         'it's a comment.
  415.     ELSEIF L$ = "KEY OFF" THEN
  416.         KEY OFF
  417.     ELSEIF L$ = "KEY ON" THEN
  418.         KEY ON
  419.     ELSEIF L$ = "RUN" THEN
  420.         IF NOT running THEN
  421.             IF loaded THEN
  422.                 currentLine = 0
  423.                 externalLimit = 0
  424.                 running = true
  425.             ELSE
  426.                 PRINT "No program loaded."
  427.             END IF
  428.         END IF
  429.     ELSEIF LEFT$(L$, 6) = "COLOR " THEN
  430.         DIM c$, c1$, c2$
  431.         c$ = MID$(L$, 7)
  432.         IF INSTR(c$, ",") THEN
  433.             c1$ = LEFT$(c$, INSTR(c$, ",") - 1)
  434.             c2$ = MID$(c$, INSTR(c$, ",") + 1)
  435.             IF LEN(c1$) > 0 AND LEN(c2$) > 0 THEN
  436.                 COLOR GetVal(c1$), GetVal(c2$)
  437.             ELSEIF LEN(c1$) > 0 AND LEN(c2$) = 0 THEN
  438.                 COLOR GetVal(c1$)
  439.             ELSEIF LEN(c1$) = 0 AND LEN(c2$) > 0 THEN
  440.                 COLOR , GetVal(c2$)
  441.             END IF
  442.         ELSE
  443.             COLOR GetVal(c$)
  444.         END IF
  445.     ELSEIF LEFT$(L$, 7) = "LOCATE " THEN
  446.         c$ = MID$(L$, 8)
  447.         IF INSTR(c$, ",") THEN
  448.             c1$ = LEFT$(c$, INSTR(c$, ",") - 1)
  449.             c2$ = MID$(c$, INSTR(c$, ",") + 1)
  450.             IF LEN(c1$) > 0 AND LEN(c2$) > 0 THEN
  451.                 LOCATE GetVal(c1$), GetVal(c2$)
  452.             ELSEIF LEN(c1$) > 0 AND LEN(c2$) = 0 THEN
  453.                 LOCATE GetVal(c1$)
  454.             ELSEIF LEN(c1$) = 0 AND LEN(c2$) > 0 THEN
  455.                 LOCATE , GetVal(c2$)
  456.             END IF
  457.         ELSE
  458.             LOCATE GetVal(c$)
  459.         END IF
  460.     ELSEIF LEFT$(L$, 6) = "FILES " THEN
  461.         DIM checkVar AS _UNSIGNED LONG, fileSpec$
  462.         checkVar = searchVar(MID$(L1$, 7))
  463.         IF checkVar THEN
  464.             FILES strings(checkVar)
  465.         ELSE
  466.             fileSpec$ = LTRIM$(RTRIM$(MID$(L1$, 7)))
  467.             IF LEFT$(fileSpec$, 1) = CHR$(34) THEN fileSpec$ = MID$(fileSpec$, 2)
  468.             IF RIGHT$(fileSpec$, 1) = CHR$(34) THEN fileSpec$ = LEFT$(fileSpec$, LEN(fileSpec$) - 1)
  469.             FILES fileSpec$
  470.         END IF
  471.     ELSEIF L$ = "FILES" THEN
  472.         FILES
  473.     ELSEIF LEFT$(L$, 8) = "CIRCLE (" THEN
  474.         IF CurrentSCREEN% = 0 THEN PRINT "Invalid mode.": running = false: GOTO Parse.Done
  475.         Comma1% = INSTR(L$, ","): Comma2% = INSTR(Comma1% + 1, L$, ","): Comma3% = INSTR(Comma2% + 1, L$, ",")
  476.  
  477.         XPos1% = INSTR(L$, " (") + 2
  478.         YPos1% = Comma1% + 1
  479.         X1% = GetVal(MID$(L$, XPos1%, Comma1% - XPos1%))
  480.         Y1% = GetVal(MID$(L$, YPos1%, Comma2% - YPos1% - 1))
  481.  
  482.         Rad% = GetVal(MID$(L$, Comma2% + 1, Comma3% - Comma2% - 1))
  483.  
  484.         c$ = LTRIM$(RTRIM$(LEFT$(MID$(L$, Comma3% + 1), 3))) 'Color attribute (variable or constant)
  485.         IF RIGHT$(c$, 1) = "," THEN c$ = LEFT$(c$, LEN(c$) - 1) 'If single-digit attribute
  486.  
  487.         IF INSTR("0123456789", LEFT$(c$, 1)) > 0 THEN DrawClr% = VAL(c$) ELSE DrawClr% = GetVal(c$)
  488.  
  489.         EPos% = INSTR(L$, ", , , ")
  490.  
  491.         IF EPos% > 0 THEN
  492.             EPos% = EPos% + 6: Elipse = GetVal(MID$(L$, EPos%))
  493.         ELSE
  494.             Arc% = INSTR(Comma3% + 1, L$, ",")
  495.  
  496.             IF Arc% > 0 THEN
  497.                 Comma4% = Arc%
  498.                 Comma5% = INSTR(Comma4% + 1, L$, ",")
  499.  
  500.                 ArcBeg = GetVal(MID$(L$, Comma4% + 1, Comma5% - Comma4% - 1)) ': PRINT "ArcBeg:"; ArcBeg;   '* * * * Test PRINT
  501.                 ArcEnd = GetVal(MID$(L$, Comma5% + 1)) ': PRINT " ArcEnd:"; ArcEnd;
  502.  
  503.                 IF INSTR(Comma5% + 1, L$, ",") > 0 THEN EPos% = INSTR(Comma5% + 1, L$, ",") + 1: Elipse = GetVal(MID$(L$, EPos%))
  504.             END IF
  505.         END IF
  506.  
  507.         IF Arc% > 0 AND Elipse = 0 THEN CIRCLE (X1%, Y1%), Rad%, DrawClr%, ArcBeg, ArcEnd: GOTO Circ.Done
  508.         IF Elipse > 0 AND Arc% = 0 THEN CIRCLE (X1%, Y1%), Rad%, DrawClr%, , , Elipse: GOTO Circ.Done
  509.         IF Arc% > 0 AND Elipse > 0 THEN CIRCLE (X1%, Y1%), Rad%, DrawClr%, ArcBeg, ArcEnd, Elipse: GOTO Circ.Done
  510.         CIRCLE (X1%, Y1%), Rad%, DrawClr% 'No arc, no elipse
  511.  
  512.         Circ.Done: Rad% = 0: Arc% = 0: Elipse = 0: c$ = "": DrawClr% = 0: GOTO Parse.Done
  513.     ELSEIF L$ = "SLEEP" THEN
  514.         SLEEP
  515.     ELSEIF LEFT$(L$, 6) = "SLEEP " THEN
  516.         IF GetVal(MID$(L$, 7)) > 0 THEN
  517.             SLEEP GetVal(MID$(L$, 7))
  518.         END IF
  519.     ELSEIF L$ = "PRINT" OR L$ = "?" THEN
  520.         PRINT
  521.     ELSEIF LEFT$(L$, 6) = "PRINT " OR LEFT$(L$, 1) = "?" THEN
  522.         IF LEFT$(L$, 2) = "? " THEN L1$ = "PRINT " + MID$(L1$, 3): L$ = L1$
  523.         IF LEFT$(L$, 1) = "?" THEN L1$ = "PRINT " + MID$(L1$, 2): L$ = L1$
  524.  
  525.         DIM retainCursor AS _BYTE
  526.         IF RIGHT$(L$, 1) = ";" THEN
  527.             retainCursor = true
  528.             L$ = LEFT$(L$, LEN(L$) - 1)
  529.             L1$ = LEFT$(L1$, LEN(L$))
  530.         ELSE
  531.             retainCursor = false
  532.         END IF
  533.  
  534.         varIndex = searchVar(MID$(L1$, 7))
  535.         IF varIndex THEN
  536.             IF hasOperator(MID$(L1$, 7)) THEN
  537.                 PRINT doMath(MID$(L1$, 7));
  538.             ELSE
  539.                 IF vars(varIndex).type = varTypeSTRING THEN
  540.                     PRINT strings(varIndex);
  541.                 ELSE
  542.                     PRINT nums(varIndex);
  543.                 END IF
  544.             END IF
  545.             IF NOT retainCursor THEN PRINT
  546.         ELSE
  547.             q1 = INSTR(7, L1$, CHR$(34))
  548.             IF q1 THEN
  549.                 q2 = INSTR(q1 + 1, L1$, CHR$(34))
  550.                 IF q2 THEN
  551.                     PRINT MID$(L1$, 8, q2 - q1 - 1);
  552.                     IF NOT retainCursor THEN PRINT
  553.                 ELSE
  554.                     PRINT MID$(L1$, 8);
  555.                     IF NOT retainCursor THEN PRINT
  556.                 END IF
  557.             ELSE
  558.                 PRINT doMath(MID$(L1$, 7));
  559.                 IF NOT retainCursor THEN PRINT
  560.             END IF
  561.         END IF
  562.     ELSEIF LEFT$(L$, 7) = "_TITLE " THEN
  563.         q1 = INSTR(8, L1$, CHR$(34))
  564.         IF q1 THEN
  565.             q2 = INSTR(q1 + 1, L1$, CHR$(34))
  566.             IF q2 THEN
  567.                 _TITLE MID$(L1$, 9, q2 - q1 - 1)
  568.             ELSE
  569.                 GOTO syntaxerror
  570.             END IF
  571.         ELSE
  572.             varIndex = searchVar(MID$(L1$, 8))
  573.             IF varIndex THEN
  574.                 IF vars(varIndex).type = varTypeSTRING THEN
  575.                     _TITLE strings(varIndex)
  576.                 ELSE
  577.                     _TITLE STR$(nums(varIndex))
  578.                 END IF
  579.             ELSE
  580.                 _TITLE MID$(L1$, 8)
  581.             END IF
  582.         END IF
  583.     ELSEIF L$ = "CLS" THEN
  584.         CLS
  585.     ELSEIF L$ = "SYSTEM" OR L$ = "EXIT" THEN
  586.         SYSTEM
  587.     ELSEIF L$ = "END" THEN
  588.         IF running THEN running = false
  589.     ELSEIF LEFT$(L$, 6) = "INPUT " THEN
  590.         DIM varName$, d$
  591.         varName$ = MID$(L1$, 7)
  592.         varIndex = addVar(varName$)
  593.         IF vars(varIndex).type = varTypeSTRING THEN
  594.             INPUT "", d$
  595.             strings(varIndex) = d$
  596.         ELSE
  597.             INPUT "", d##
  598.             nums(varIndex) = d##
  599.         END IF
  600.     ELSEIF L$ = "DO" THEN
  601.         IF running THEN doLine = currentLine
  602.     ELSEIF L$ = "LOOP" THEN
  603.         IF running THEN
  604.             loopLine = currentLine
  605.             IF doLine > 0 THEN currentLine = doLine
  606.         END IF
  607.     ELSEIF L$ = "EXIT DO" THEN
  608.         IF running THEN
  609.             IF loopLine > 0 THEN
  610.                 currentLine = loopLine
  611.             ELSE
  612.                 DO
  613.                     currentLine = currentLine + 1
  614.                     IF currentLine > UBOUND(program) THEN PRINT "DO without LOOP on line"; doLine: running = false: GOTO Parse.Done
  615.                     L1$ = program(currentLine)
  616.                     L1$ = LTRIM$(RTRIM$(L1$))
  617.                     L$ = UCASE$(L1$)
  618.                     IF L$ = "LOOP" THEN doLine = 0: EXIT DO
  619.                 LOOP
  620.             END IF
  621.         END IF
  622.     ELSEIF LEFT$(L$, 7) = "SCREEN " THEN
  623.         SELECT CASE VAL(MID$(L$, 8))
  624.             CASE 0 TO 2, 7 TO 13
  625.                 CurrentSCREEN% = VAL(MID$(L$, 8))
  626.                 SCREEN CurrentSCREEN%
  627.             CASE ELSE
  628.                 PRINT "Invalid mode."
  629.         END SELECT
  630.     ELSEIF LEFT$(L$, 6) = "SCREEN" THEN
  631.         PRINT CurrentSCREEN%
  632.     ELSEIF L$ = "END IF" THEN
  633.         IF running THEN
  634.             IF ifLine = 0 THEN
  635.                 PRINT "END IF without IF - on line"; currentLine
  636.                 running = false
  637.             END IF
  638.         ELSE
  639.             PRINT "Not valid in immediate mode."
  640.         END IF
  641.     ELSEIF LEFT$(L$, 3) = "IF " THEN
  642.         IF NOT running THEN
  643.             PRINT "Not valid in immediate mode."
  644.         ELSE
  645.             IF RIGHT$(L$, 5) <> " THEN" THEN GOTO syntaxerror
  646.             DIM i$, i1$, i2$, s$, r AS _BYTE
  647.  
  648.             ifLine = currentLine
  649.  
  650.             i$ = MID$(L$, 4, LEN(L$) - 8)
  651.  
  652.             IF INSTR(i$, "=") THEN
  653.                 s$ = "="
  654.             ELSEIF INSTR(i$, ">") THEN
  655.                 s$ = ">"
  656.             ELSEIF INSTR(i$, "<") THEN
  657.                 s$ = "<"
  658.             ELSE
  659.                 s$ = ""
  660.             END IF
  661.  
  662.             i1$ = LEFT$(i$, INSTR(i$, s$) - 1)
  663.             i2$ = MID$(i$, INSTR(i$, s$) + 1)
  664.  
  665.             r = false
  666.             SELECT CASE s$
  667.                 CASE "="
  668.                     IF GetVal(i1$) = GetVal(i2$) THEN r = true
  669.                 CASE ">"
  670.                     IF GetVal(i1$) > GetVal(i2$) THEN r = true
  671.                 CASE "<"
  672.                     IF GetVal(i1$) < GetVal(i2$) THEN r = true
  673.             END SELECT
  674.  
  675.             IF r = false THEN
  676.                 DO
  677.                     currentLine = currentLine + 1
  678.                     IF currentLine > UBOUND(program) THEN PRINT "IF without END IF on line"; ifLine: running = false: GOTO Parse.Done
  679.                     L1$ = program(currentLine)
  680.                     L1$ = LTRIM$(RTRIM$(L1$))
  681.                     L$ = UCASE$(L1$)
  682.                     IF L$ = "END IF" THEN ifLine = 0: EXIT DO
  683.                 LOOP
  684.             END IF
  685.         END IF
  686.     ELSEIF INSTR(L$, "=") > 0 THEN
  687.         'Assignment
  688.         varName$ = RTRIM$(LEFT$(L1$, INSTR(L1$, "=") - 1))
  689.         varIndex = addVar(varName$) 'either add or acquire existing index
  690.  
  691.         IF vars(varIndex).protected THEN
  692.             PRINT "Variable is protected";
  693.             IF running THEN
  694.                 running = false
  695.                 PRINT " on line "; currentLine
  696.             ELSE
  697.                 PRINT
  698.             END IF
  699.  
  700.             GOTO Parse.Done
  701.         END IF
  702.  
  703.         IF vars(varIndex).type = varTypeSTRING THEN
  704.             strings(varIndex) = RTRIM$(LTRIM$(MID$(L1$, INSTR(L1$, "=") + 1)))
  705.             IF LEFT$(strings(varIndex), 1) = CHR$(34) THEN
  706.                 strings(varIndex) = MID$(strings(varIndex), 2)
  707.                 IF RIGHT$(strings(varIndex), 1) = CHR$(34) THEN strings(varIndex) = LEFT$(strings(varIndex), LEN(strings(varIndex)) - 1)
  708.             ELSE
  709.                 DIM varIndex2 AS _UNSIGNED LONG
  710.                 varIndex2 = searchVar(strings(varIndex))
  711.                 IF varIndex2 THEN
  712.                     strings(varIndex) = strings(varIndex2)
  713.                 END IF
  714.             END IF
  715.         ELSE
  716.             DIM v$, t$
  717.             v$ = MID$(L1$, INSTR(L1$, "=") + 1)
  718.  
  719.             t$ = doMath(v$)
  720.  
  721.             IF vars(varIndex).type = varTypeINTEGER THEN
  722.                 nums(varIndex) = INT(VAL(t$))
  723.             ELSE
  724.                 nums(varIndex) = VAL(t$)
  725.             END IF
  726.         END IF
  727.     ELSE
  728.         syntaxerror:
  729.         IF LEN(L$) THEN PRINT "Syntax error";
  730.         IF running THEN
  731.             PRINT " on line"; currentLine
  732.             running = false
  733.         ELSE
  734.             PRINT
  735.         END IF
  736.     END IF
  737.  
  738.     Parse.Done:
  739.  
  740.     IF externalLimit > 0 AND running THEN _LIMIT externalLimit
  741.  
  742. oops:
  743.  
  744. PRINT "("; _ERRORLINE; ") Error #"; ERR;
  745. IF running THEN
  746.     PRINT " on line"; currentLine
  747.     running = false
  748.     PRINT
  749. RESUME Parse.Done
  750.  
  751. FUNCTION addVar~& (varName$)
  752.     DIM i AS _UNSIGNED LONG, found AS _BYTE
  753.  
  754.     'check if var exists
  755.     found = searchVar(varName$)
  756.  
  757.     IF found THEN addVar~& = found: EXIT FUNCTION
  758.  
  759.     totalVars = totalVars + 1
  760.     IF totalVars > UBOUND(vars) THEN
  761.         REDIM _PRESERVE vars(totalVars + 99) AS vartype
  762.         REDIM _PRESERVE strings(totalVars + 99) AS STRING
  763.         REDIM _PRESERVE nums(totalVars + 99) AS _FLOAT
  764.     END IF
  765.  
  766.     vars(totalVars).name = varName$
  767.  
  768.     'type detection -----------------------------------------------------------
  769.     vars(totalVars).type = detectType(varName$)
  770.     '--------------------------------------------------------------------------
  771.  
  772.     vars(totalVars).scope = thisScope$
  773.     addVar~& = totalVars
  774.  
  775. FUNCTION detectType%% (__varname$)
  776.     DIM varname$
  777.  
  778.     varname$ = LTRIM$(RTRIM$(__varname$))
  779.  
  780.     detectType%% = varType_DEFAULT
  781.  
  782.     IF RIGHT$(varname$, 1) = "$" THEN detectType%% = varTypeSTRING
  783.  
  784.     IF RIGHT$(varname$, 3) = "~%%" THEN
  785.         detectType%% = varType_UBYTE
  786.     ELSEIF RIGHT$(varname$, 2) = "%%" THEN
  787.         detectType%% = varType_BYTE
  788.     ELSEIF RIGHT$(varname$, 2) = "~%" THEN
  789.         detectType%% = varType_UINTEGER
  790.     ELSEIF RIGHT$(varname$, 1) = "%" THEN
  791.         detectType%% = varTypeINTEGER
  792.     END IF
  793.  
  794.     IF RIGHT$(varname$, 1) = "!" THEN
  795.         detectType%% = varTypeSINGLE
  796.     ELSEIF RIGHT$(varname$, 2) = "##" THEN
  797.         detectType%% = varType_FLOAT
  798.     ELSEIF RIGHT$(varname$, 1) = "#" THEN
  799.         detectType%% = varTypeDOUBLE
  800.     END IF
  801.  
  802.     IF RIGHT$(varname$, 3) = "~&&" THEN
  803.         detectType%% = varType_UINTEGER64
  804.     ELSEIF RIGHT$(varname$, 2) = "&&" THEN
  805.         detectType%% = varType_INTEGER64
  806.     ELSEIF RIGHT$(varname$, 2) = "~&" THEN
  807.         detectType%% = varType_ULONG
  808.     ELSEIF RIGHT$(varname$, 1) = "&" THEN
  809.         detectType%% = varType_LONG
  810.     END IF
  811.  
  812. FUNCTION searchVar~& (__varName$)
  813.     DIM i AS _UNSIGNED LONG, found AS _BYTE
  814.     DIM temp##, temp$, special AS _BYTE
  815.     DIM varName$, isString AS _BYTE
  816.  
  817.     varName$ = __varName$
  818.  
  819.     DIM bracket1 AS LONG, bracket2 AS LONG
  820.     bracket1 = INSTR(varName$, "(")
  821.     IF bracket1 > 0 THEN
  822.         FOR i = LEN(varName$) TO 1 STEP -1
  823.             IF ASC(varName$, i) = 41 THEN
  824.                 bracket2 = i
  825.                 EXIT FOR
  826.             END IF
  827.         NEXT
  828.     END IF
  829.  
  830.     IF bracket1 > 0 AND bracket2 > 0 THEN
  831.         'array or function
  832.         temp$ = MID$(varName$, bracket1 + 1, bracket2 - bracket1 - 1)
  833.         IF LEFT$(temp$, 1) = CHR$(34) THEN
  834.             'string literal
  835.             temp$ = MID$(temp$, 2)
  836.             IF RIGHT$(temp$, 1) = CHR$(34) THEN
  837.                 temp$ = LEFT$(temp$, LEN(temp$) - 1)
  838.             END IF
  839.             isString = true
  840.         ELSEIF hasOperator(temp$) THEN
  841.             temp## = VAL(doMath(MID$(varName$, bracket1 + 1, bracket2 - bracket1 - 1)))
  842.         ELSE
  843.             'a variable?
  844.             DIM checkVar AS _UNSIGNED LONG
  845.             checkVar = searchVar(temp$)
  846.             IF checkVar THEN
  847.                 IF vars(checkVar).type = varTypeSTRING THEN
  848.                     temp$ = strings(checkVar)
  849.                     isString = true
  850.                 ELSE
  851.                     temp## = nums(checkVar)
  852.                 END IF
  853.             ELSE
  854.                 'number literal?
  855.                 IF LTRIM$(STR$(VAL(temp$))) = temp$ THEN
  856.                     temp## = VAL(temp$)
  857.                 END IF
  858.             END IF
  859.         END IF
  860.  
  861.         SELECT CASE LCASE$(LTRIM$(RTRIM$(LEFT$(varName$, bracket1 - 1))))
  862.             CASE "val"
  863.                 IF isString = false THEN ERROR 5
  864.                 temp## = VAL(temp$)
  865.                 varName$ = "val"
  866.                 special = true
  867.             CASE "cos"
  868.                 IF isString THEN ERROR 5
  869.                 temp## = COS(temp##)
  870.                 varName$ = "cos"
  871.                 special = true
  872.             CASE "len"
  873.                 IF isString = false THEN ERROR 5
  874.                 temp## = LEN(temp$)
  875.                 varName$ = "len"
  876.                 special = true
  877.             CASE "asc"
  878.                 IF isString = false THEN ERROR 5
  879.                 temp## = ASC(temp$)
  880.                 varName$ = "asc"
  881.                 special = true
  882.             CASE "sin"
  883.                 IF isString THEN ERROR 5
  884.                 temp## = SIN(temp##)
  885.                 varName$ = "sin"
  886.                 special = true
  887.             CASE "int"
  888.                 IF isString THEN ERROR 5
  889.                 temp## = INT(temp##)
  890.                 varName$ = "int"
  891.                 special = true
  892.         END SELECT
  893.     ELSE
  894.         'special cases
  895.         IF LCASE$(LTRIM$(RTRIM$(varName$))) = "rnd" THEN
  896.             temp## = RND
  897.             special = true
  898.         ELSEIF LCASE$(LTRIM$(RTRIM$(varName$))) = "timer" THEN
  899.             temp## = TIMER
  900.             special = true
  901.         ELSEIF LCASE$(LTRIM$(RTRIM$(varName$))) = "time$" THEN
  902.             temp$ = TIME$
  903.             special = true
  904.         ELSEIF LCASE$(LTRIM$(RTRIM$(varName$))) = "inkey$" THEN
  905.             temp$ = INKEY$
  906.             special = true
  907.         ELSEIF LCASE$(LTRIM$(RTRIM$(varName$))) = "date$" THEN
  908.             temp$ = DATE$
  909.             special = true
  910.         ELSEIF LCASE$(LTRIM$(RTRIM$(varName$))) = "_width" THEN
  911.             temp## = _WIDTH
  912.             special = true
  913.         ELSEIF LCASE$(LTRIM$(RTRIM$(varName$))) = "_height" THEN
  914.             temp## = _HEIGHT
  915.             special = true
  916.         ELSEIF LCASE$(LTRIM$(RTRIM$(varName$))) = "_mousex" THEN
  917.             temp## = _MOUSEX
  918.             special = true
  919.         ELSEIF LCASE$(LTRIM$(RTRIM$(varName$))) = "_mousey" THEN
  920.             temp## = _MOUSEY
  921.             special = true
  922.         ELSEIF LCASE$(LTRIM$(RTRIM$(varName$))) = "_mousebutton(1)" THEN
  923.             temp## = _MOUSEBUTTON(1)
  924.             special = true
  925.         ELSEIF LCASE$(LTRIM$(RTRIM$(varName$))) = "_mousebutton(2)" THEN
  926.             temp## = _MOUSEBUTTON(2)
  927.             special = true
  928.         END IF
  929.     END IF
  930.  
  931.     'check if var exists
  932.     FOR i = 1 TO totalVars
  933.         IF LCASE$(LTRIM$(RTRIM$(vars(i).name))) = LCASE$(LTRIM$(RTRIM$(varName$))) THEN
  934.             found = true
  935.             EXIT FOR
  936.         END IF
  937.     NEXT
  938.  
  939.     IF found THEN searchVar~& = i
  940.     IF special AND i <= UBOUND(vars) THEN
  941.         nums(i) = temp##
  942.         strings(i) = temp$
  943.     END IF
  944.  
  945. FUNCTION load%% (file$)
  946.     DIM ff AS INTEGER, l$
  947.     ff = FREEFILE
  948.     OPEN file$ FOR BINARY AS ff
  949.  
  950.     currentLine = 0
  951.     DO
  952.         IF EOF(ff) THEN EXIT DO
  953.         LINE INPUT #ff, l$
  954.         currentLine = currentLine + 1
  955.         IF currentLine > UBOUND(program) THEN REDIM _PRESERVE program(currentLine + 999) AS STRING
  956.         program(currentLine) = l$
  957.     LOOP
  958.  
  959.     CLOSE ff
  960.  
  961.     IF currentLine > 0 THEN
  962.         REDIM _PRESERVE program(currentLine) AS STRING
  963.         currentLine = 0
  964.         load%% = true
  965.         loadedFile$ = file$
  966.     ELSE
  967.         load%% = false
  968.     END IF
  969.  
  970. FUNCTION GetVal## (__c$)
  971.     DIM c$, b1&, b2&, temp##
  972.  
  973.     IF debugging THEN PRINT "entering getval(): "; __c$
  974.  
  975.     c$ = LTRIM$(RTRIM$(__c$))
  976.  
  977.     IF hasOperator(c$) AND firstOperator(c$) > 1 THEN
  978.         c$ = LEFT$(c$, firstOperator(c$) - 1)
  979.         IF debugging THEN PRINT "has operator"
  980.     ELSE
  981.         IF debugging THEN PRINT "no operator"
  982.     END IF
  983.  
  984.     IF VAL(c$) <> 0 THEN
  985.         GetVal## = VAL(c$)
  986.         IF debugging THEN PRINT "returning val()"
  987.     ELSE
  988.         varIndex = searchVar(c$)
  989.         IF debugging THEN PRINT "searching as var: "; c$
  990.         IF varIndex THEN
  991.             IF vars(varIndex).type = varTypeSTRING THEN
  992.                 IF debugging THEN PRINT "found in strings()"
  993.                 ERROR 5
  994.             ELSE
  995.                 GetVal## = nums(varIndex)
  996.                 IF debugging THEN PRINT "returning nums()"
  997.             END IF
  998.         ELSE
  999.             GetVal## = VAL(c$) 'maybe it was 0 anyway...
  1000.             IF debugging THEN PRINT "returning val() anyway"
  1001.         END IF
  1002.     END IF
  1003.  
  1004. FUNCTION doMath$ (__v$)
  1005.     DIM v$, v1$, v2$, temp$, continue AS _BYTE
  1006.  
  1007.     v$ = __v$
  1008.  
  1009.     IF debugging THEN PRINT "doing math on "; v$
  1010.  
  1011.     IF hasOperator(v$) AND firstOperator(v$) > 1 THEN
  1012.         s$ = MID$(v$, firstOperator(v$), 1)
  1013.     ELSE
  1014.         doMath$ = LTRIM$(RTRIM$(STR$(GetVal(v$))))
  1015.         EXIT FUNCTION
  1016.     END IF
  1017.  
  1018.     v1$ = LEFT$(v$, INSTR(v$, s$) - 1)
  1019.     v2$ = MID$(v$, firstOperator(v$) + 1)
  1020.  
  1021.     IF debugging THEN
  1022.         PRINT "found    "; v1$, s$, v2$
  1023.         PRINT "getval():"; GetVal(v1$), GetVal(v2$)
  1024.     END IF
  1025.  
  1026.     SELECT CASE s$
  1027.         CASE "+"
  1028.             temp$ = STR$(GetVal(v1$) + GetVal(v2$))
  1029.         CASE "-"
  1030.             temp$ = STR$(GetVal(v1$) - GetVal(v2$))
  1031.         CASE "*"
  1032.             temp$ = STR$(GetVal(v1$) * GetVal(v2$))
  1033.         CASE "/"
  1034.             temp$ = STR$(GetVal(v1$) / GetVal(v2$))
  1035.         CASE "^"
  1036.             temp$ = STR$(GetVal(v1$) ^ GetVal(v2$))
  1037.     END SELECT
  1038.  
  1039.     IF debugging THEN PRINT "temp$="; temp$
  1040.  
  1041.     DO WHILE hasOperator(v2$) AND firstOperator(v2$) > 1
  1042.         s$ = MID$(v2$, firstOperator(v2$), 1)
  1043.         v2$ = MID$(v2$, firstOperator(v2$) + 1)
  1044.         IF debugging THEN PRINT "passing "; temp$ + s$ + v2$
  1045.         temp$ = doMath$(temp$ + s$ + v2$)
  1046.         v2$ = MID$(v2$, firstOperator(v2$) + LEN(v2$))
  1047.     LOOP
  1048.  
  1049.     doMath$ = LTRIM$(RTRIM$(temp$))
  1050.  
  1051. FUNCTION hasOperator%% (v$)
  1052.     hasOperator%% = INSTR(v$, "+") > 0 OR INSTR(v$, "-") > 0 OR INSTR(v$, "*") > 0 OR INSTR(v$, "/") > 0 OR INSTR(v$, "^") > 0
  1053.  
  1054. FUNCTION firstOperator& (v$)
  1055.     DIM i AS LONG, op$
  1056.  
  1057.     op$ = "+-*/^"
  1058.  
  1059.     FOR i = 1 TO LEN(v$)
  1060.         IF INSTR(op$, MID$(v$, i, 1)) THEN
  1061.             firstOperator = i
  1062.             EXIT FUNCTION
  1063.         END IF
  1064.     NEXT

I have a data TYPE vartype, an array vars(0) AS vartype and two separate arrays to store numbers and text (strings(0) AS STRING and nums(0) AS _FLOAT - I'll probably only need one array in a future release since QB64 now supports variable-width strings in TYPE). There is a function addVar() which expands the arrays then creates a new variable. The code for creating a new variable and assigning a value to it starts at line 698.

If you run the code above, you'll have a "." prompt. Try typing:

Code: QB64: [Select]
  1. a = 5
  2. a = a + 3
« Last Edit: April 19, 2019, 08:33:08 am by FellippeHeitor »

Offline Raven_Singularity

  • Forum Regular
  • Posts: 158
    • View Profile
Re: Noob question: does QB64 allow making up variable names at runtime?
« Reply #3 on: April 19, 2019, 09:57:42 am »
Just to point out, the QB64 IDE is already a recompiler.  You could have your app produce/edit its own source code, then recompile itself.  Not very practical for most usage cases, but interesting nonetheless.

Offline FilipeEstima

  • Newbie
  • Posts: 63
    • View Profile
Re: Noob question: does QB64 allow making up variable names at runtime?
« Reply #4 on: April 19, 2019, 12:35:07 pm »
OK thanks guys, that was just out of curiosity :-)

Offline Dimster

  • Forum Resident
  • Posts: 500
    • View Profile
Re: Noob question: does QB64 allow making up variable names at runtime?
« Reply #5 on: April 19, 2019, 01:20:54 pm »
If you have an idea of a condition that may surface in a future run of your program then you may be able to code in a Redim or Concatenation of strings. If you need to create a new file to hold data then you could plant a series of names in your coding and if the condition does occur where you may need to name a future file your program could review the series of names, concat a few of them and create the new file. Redim of course only works with existing arrays. I have not tried to use a "planted series of names" to create a new variable name, or dimension a newly created variable. But, if you can forsee the possibility of a future condition then perhaps there maybe a way to code for it. The idea that a computer can Think for Itself, almost be sentient - is just around the corner. Now that AI should be able to expand itself.