Author Topic: oh One-Handed Interpreter  (Read 13773 times)

0 Members and 1 Guest are viewing this topic.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
oh One-Handed Interpreter
« on: March 07, 2021, 10:51:11 pm »
OMG! It was one year to the day when @STxAxTIC posted an Intro to the SB project here:
https://www.qb64.org/forum/index.php?topic=2308.msg115317#msg115317
and I revisioned the project here:

I completely gutted SB1 of the numeric evaluator and replaced it with a much slicker Fval$ (Function Value$) evaluator, so now I can mix and nest numeric and string functions.

Basic Syntax is myVar = SF[a1,a2,a3,...] And a1,a2,a3 can be more nested SF[ ] String Functions.

And you can do everything one handed because you only need shift key for printing nice labels on screen.

Here is new Fval$ evaluator (it's more developed in oh):
Code: QB64: [Select]
  1. _Title "Fval$" 'restart for oh one-handed interpreter 2021-03-07 My Dad's B-day would be 96
  2. ' need a evaluator to handle any function and return the value as a string
  3.  
  4.  
  5. ReDim Shared Err$, Vnames$(1 To 1000), Vvalues$(1 To 1000)
  6. ReDim Shared SA$(1 To 1), NA#(1 To 1)
  7. ReDim Shared As Long Vindex, Debug
  8. ReDim f$, d$, r1$, r2$
  9.  
  10. f$ = "add[30, add[1, 2, 3, 4, 5], pow[2, 5]" ' > 15
  11.  
  12. Vnames$(1) = "A": Vvalues$(1) = "2" '(x + 5) (2x + 6) = 2x^2 + 16x + 30 roots -5, -3
  13. Vnames$(2) = "B": Vvalues$(2) = "16"
  14. Vnames$(3) = "C": Vvalues$(3) = "30"
  15. d$ = "p[s[x[b,b],x[4,a,c]],.5]"
  16. r1$ = "d[a[s[0, b],p[s[x[b,b],x[4,a,c]],.5]],x[2,a]]" 'yeah
  17. r2$ = "d[s[s[0, b],p[s[x[b,b],x[4,a,c]],.5]],x[2,a]]" 'yeah
  18. Print Fval$(r2$), Fval(r1$) 'nice! roots are right
  19. Print Fval$("bnd[mid3[cap[hello world], 7, 3],cap[d]]")
  20. Print Fval$("join[_,a,b,c]") 'nice!
  21.  
  22. Function Fval$ (S$)
  23.     'updated from oh because Fval$ was destroying the original S$ string PLUS sometimes just want to return S$ or if variable, it's value
  24.     If Debug Then Print "Fval$ rec'd: "; S$
  25.     ReDim As Long bo, bc, i
  26.     ReDim char$, copyS$
  27.     'find deepest nested [] , isolate string and give it to FunHandler to get the replacement string
  28.     ' stick replacement back into copyS$ (of = sign)
  29.     ' look for more [] when none exist then done
  30.     copyS$ = S$
  31.     bo = InStr(copyS$, "[") ' bracket open
  32.     If bo Then
  33.         While bo
  34.             For i = bo + 1 To Len(copyS$)
  35.                 char$ = Mid$(copyS$, i, 1)
  36.                 If char$ = "[" Then bo = i
  37.                 If char$ = "]" Then
  38.                     bc = i
  39.                     Exit For
  40.                 End If
  41.             Next
  42.             'now from bo go back until hit 1 or a ] or a comma
  43.             While bo - 1 >= 1 And Mid$(copyS$, bo - 1, 1) <> "," And Mid$(copyS$, bo - 1, 1) <> "["
  44.                 bo = bo - 1
  45.             Wend
  46.             copyS$ = Mid$(copyS$, 1, bo - 1) + FunHandler$(Mid$(copyS$, bo, bc - bo + 1)) + Mid$(copyS$, bc + 1)
  47.             bo = InStr(copyS$, "[")
  48.         Wend
  49.         Fval$ = copyS$
  50.     Else
  51.         If VarIndex&(copyS$) Then Fval$ = Vvalues$(VarIndex&(copyS$)) Else Fval$ = copyS$
  52.     End If
  53.     If Debug Then Print "Fval$ returning: "; Fval$
  54.  
  55. Function FunHandler$ (fun$) ' fun$ looks like this fun$ = funName[comma, delim, args]
  56.     'needs LeftOf$, RightOf$, Split, VarIndex& (from SB1)
  57.     Dim func$, aLine$, temp$
  58.     Dim As Long i, uba, idx
  59.     Dim As Double tmp
  60.     'needs LeftOf$, RightOf$, Split
  61.     func$ = UCase$(_Trim$(LeftOf$(fun$, "[")))
  62.     aLine$ = LeftOf$(RightOf$(fun$, "["), "]")
  63.     ReDim a$(1 To 1)
  64.     Split aLine$, ",", a$()
  65.     uba = UBound(a$)
  66.     ' now is good time to subst back values for variables
  67.     For i = 1 To uba
  68.         idx = VarIndex&(a$(i))
  69.         If idx Then a$(i) = Vvalues$(idx)
  70.     Next
  71.     Select Case func$
  72.         Case "BND" 'concatenate Bond or Bind same thing                    any number of arguments
  73.             For i = 1 To uba
  74.                 temp$ = temp$ + a$(i)
  75.             Next
  76.             FunHandler$ = temp$
  77.         Case "A"
  78.             For i = 1 To uba
  79.                 tmp = tmp + Val(a$(i))
  80.             Next
  81.             FunHandler$ = TD$(tmp)
  82.         Case "X": FunHandler$ = TD$(Val(a$(1)) * Val(a$(2)))
  83.             tmp = 1
  84.             For i = 1 To uba
  85.                 tmp = tmp * Val(a$(i))
  86.             Next
  87.             FunHandler$ = TD$(tmp)
  88.         Case "JOIN"
  89.             temp$ = a$(2) 'JOIN[deli$, a2, a3, a4..]
  90.             For i = 3 To uba
  91.                 temp$ = temp$ + a$(1) + a$(i)
  92.             Next
  93.             FunHandler$ = temp$
  94.         Case "MID3": FunHandler$ = Mid$(a$(1), Val(a$(2)), Val(a$(3))) '      3 argument functions
  95.         Case "IN3": FunHandler$ = TD$(InStr(Val(a$(1)), a$(2), a$(3)))
  96.         Case "SEQ": If (a$(1)) = a$(2) Then FunHandler$ = "-1" Else FunHandler$ = "0"
  97.         Case "MID1": FunHandler$ = Mid$(a$(1), Val(a$(2)), 1) '               2 argument functions
  98.         Case "MID2": FunHandler$ = Mid$(a$(1), Val(a$(2))) ' mid$ S$, place#
  99.         Case "IN2": FunHandler$ = TD$(InStr(a$(1), a$(2))) ' instr s$, match$
  100.         Case "COP": FunHandler$ = NumCopies$(Val(a$(1)), a$(2)) ' nCop, s$
  101.         Case "HEAD": FunHandler$ = LeftOf$(a$(1), a$(2)) ' s$, lefts$
  102.         Case "TAIL": FunHandler$ = RightOf$(a$(1), a$(2)) ' s$, right$
  103.         Case "GET": FunHandler$ = GetVS$(Chr$(1), Val(a$(2)), a$(1)) ' aString$, idx
  104.         Case "SPLIT": FunHandler$ = SplitWrapper$(a$(1), a$(2)) ' stringToSplit$, Deli$
  105.         Case "REJOIN": FunHandler$ = JoinWrapper$(a$(1), a$(2)) ' Astring$, newDeli$
  106.         Case "S": FunHandler$ = TD$(Val(a$(1)) - Val(a$(2))) '               2 number functions
  107.         Case "D"
  108.             If Val(a$(2)) <> 0 Then
  109.                 FunHandler$ = TD$(Val(a$(1)) / Val(a$(2)))
  110.             Else
  111.                 Err$ = "Error: Div by 0"
  112.             End If
  113.         Case "EQ": If Val(a$(1)) = Val(a$(2)) Then FunHandler$ = "-1" Else FunHandler$ = "0"
  114.         Case "LT": If Val(a$(1)) < Val(a$(2)) Then FunHandler$ = "-1" Else FunHandler$ = "0"
  115.         Case "LTE": If Val(a$(1)) <= Val(a$(2)) Then FunHandler$ = "-1" Else FunHandler$ = "0"
  116.         Case "GTE": If Val(a$(1)) >= Val(a$(2)) Then FunHandler$ = "-1" Else FunHandler$ = "0"
  117.         Case "GT": If Val(a$(1)) > Val(a$(2)) Then FunHandler$ = "-1" Else FunHandler$ = "0"
  118.         Case "NOTEQ": If Val(a$(1)) <> Val(a$(2)) Then FunHandler$ = "-1" Else FunHandler$ = "0"
  119.         Case "OR": If Val(a$(1)) Or Val(a$(2)) Then FunHandler$ = "-1" Else FunHandler$ = "0"
  120.         Case "AND": If Val(a$(1)) And Val(a$(2)) Then FunHandler$ = "-1" Else FunHandler$ = "0"
  121.         Case "M"
  122.             If Val(a$(2)) >= 2 Then
  123.                 FunHandler$ = TD$(Int(Val(a$(1))) Mod Int(Val(a$(2))))
  124.             Else
  125.                 Err$ = "Error: for A Mod B, b < 2"
  126.             End If
  127.         Case "P"
  128.             If Int(Val(a$(2))) = Val(a$(2)) Or Val(a$(1)) >= 0 Then
  129.                 FunHandler$ = TD$(Val(a$(1)) ^ Val(a$(2)))
  130.             Else
  131.                 Err$ = "Error: for A ^ B, A needs to be > 0 when B not Integer"
  132.             End If
  133.         Case "ASSORT": FunHandler$ = SortWrapper$(a$(1), 1)
  134.         Case "DSSORT": FunHandler$ = SortWrapper$(a$(1), 2)
  135.         Case "ANSORT": FunHandler$ = SortWrapper$(a$(1), 3)
  136.         Case "DNSORT": FunHandler$ = SortWrapper$(a$(1), 4)
  137.         Case "ASC": FunHandler$ = TD$(Asc(a$(1))) '                                 1   arguments
  138.         Case "CHR": FunHandler$ = Chr$(Val(a$(1)))
  139.         Case "LEN": FunHandler$ = TD$(Len(a$(1)))
  140.         Case "LTR": FunHandler$ = LTrim$(a$(1))
  141.         Case "RTR": FunHandler$ = RTrim$(a$(1))
  142.         Case "TRIM": FunHandler$ = _Trim$(a$(1))
  143.         Case "CAP": FunHandler$ = UCase$(a$(1))
  144.         Case "LOW": FunHandler$ = LCase$(a$(1))
  145.         Case "INT": FunHandler$ = TD$(Int(Val(a$(1)))) '                                 1 number
  146.         Case "SIN": FunHandler$ = TD$(Sin(Val(a$(1))))
  147.         Case "COS": FunHandler$ = TD$(Cos(Val(a$(1))))
  148.         Case "TAN": FunHandler$ = TD$(Tan(Val(a$(1))))
  149.         Case "ASIN": FunHandler$ = TD$(_Asin(Val(a$(1))))
  150.         Case "ACOS": FunHandler$ = TD$(_Acos(Val(a$(1))))
  151.         Case "ATAN": FunHandler$ = TD$(Atn(Val(a$(1))))
  152.         Case "LOG": FunHandler$ = TD$(Log(Val(a$(1))))
  153.         Case "EXP": FunHandler$ = TD$(Exp(Val(a$(1))))
  154.         Case "SQR": FunHandler$ = TD$(Sqr(Val(a$(1))))
  155.         Case "RAD": FunHandler$ = TD$(_D2R(Val(a$(1))))
  156.         Case "DEG": FunHandler$ = TD$(_R2D(Val(a$(1))))
  157.         Case "PI": FunHandler$ = TD$(_Pi(Val(a$(1))))
  158.         Case "NOT": If Val(a$(1)) = 0 Then FunHandler$ = "-1" Else FunHandler$ = "0"
  159.         Case "DATE": FunHandler$ = Date$ '                                             0 arguments
  160.         Case "TIME": FunHandler$ = Time$
  161.         Case "RND": FunHandler$ = TD$(Rnd)
  162.     End Select
  163.  
  164. Function VarIndex& (Vname$)
  165.     Dim i As Long, name$
  166.     name$ = UCase$(_Trim$(Vname$))
  167.     For i = 1 To UBound(Vnames$) ' see if we have that name yet
  168.         If name$ = Vnames$(i) Then VarIndex& = i: Exit Function
  169.     Next
  170.  
  171. ' update these 2 in case of$ is not found! 2021-02-13
  172. Function LeftOf$ (source$, of$)
  173.     If InStr(source$, of$) > 0 Then LeftOf$ = Mid$(source$, 1, InStr(source$, of$) - 1) Else LeftOf$ = source$
  174.  
  175. ' update these 2 in case of$ is not found! 2021-02-13
  176. Function RightOf$ (source$, of$)
  177.     If InStr(source$, of$) > 0 Then RightOf$ = Mid$(source$, InStr(source$, of$) + Len(of$)) Else RightOf$ = ""
  178.  
  179. ' note: I buggered this twice now, FOR base 1 array REDIM MyArray (1 to 1) AS ... the (1 to 1) is not same as (1) which was the Blunder!!!
  180. 'notes: REDIM the array(0) to be loaded before calling Split '<<<< IMPORTANT dynamic array and empty, can use any lbound though
  181. 'This SUB will take a given N delimited string, and delimiter$ and create an array of N+1 strings using the LBOUND of the given dynamic array to load.
  182. 'notes: the loadMeArray() needs to be dynamic string array and will not change the LBOUND of the array it is given.  rev 2019-08-27
  183. Sub Split (SplitMeString As String, Delim As String, LoadMeArray() As String)
  184.     Dim curpos As Long, arrpos As Long, LD As Long, dpos As Long 'fix use the Lbound the array already has
  185.     curpos = 1: arrpos = LBound(loadMeArray): LD = Len(Delim)
  186.     dpos = InStr(curpos, SplitMeString, Delim)
  187.     Do Until dpos = 0
  188.         LoadMeArray(arrpos) = Mid$(SplitMeString, curpos, dpos - curpos)
  189.         arrpos = arrpos + 1
  190.         If arrpos > UBound(loadMeArray) Then ReDim _Preserve LoadMeArray(LBound(loadMeArray) To UBound(loadMeArray) + 1000) As String
  191.         curpos = dpos + LD
  192.         dpos = InStr(curpos, SplitMeString, Delim)
  193.     Loop
  194.     LoadMeArray(arrpos) = Mid$(SplitMeString, curpos)
  195.     ReDim _Preserve LoadMeArray(LBound(loadMeArray) To arrpos) As String 'get the ubound correct
  196.  
  197. Function SplitWrapper$ (s$, deli$)
  198.     ReDim temp$(1 To 1)
  199.     Split s$, deli$, temp$()
  200.     SplitWrapper$ = Join$(temp$(), Chr$(1))
  201.  
  202. Function JoinWrapper$ (Astring$, Deli$) ' take an "array" and change it back to a long string
  203.     ReDim temp$(1 To 1)
  204.     Split Astring$, Chr$(1), temp$()
  205.     JoinWrapper$ = Join$(temp$(), Deli$) ' return string with user requested delimiter
  206.  
  207. Function Join$ (Arr() As String, D$) 'created for this app D$ is delimiter$ to link items
  208.     ReDim i As Long, lb As Long, ub As Long, b$
  209.     lb = LBound(arr): ub = UBound(arr)
  210.     b$ = Arr(lb)
  211.     For i = lb + 1 To ub
  212.         b$ = b$ + D$ + Arr(i)
  213.     Next
  214.     Join$ = b$
  215.  
  216. Function TD$ (Dbl As Double) 'Trim Double
  217.     TD$ = _Trim$(Str$(Dbl))
  218.  
  219. Function NumCopies$ (NumberOfCopies&, S$) ' Concatenate repeated copies of S$
  220.     Dim i&
  221.     For i& = 1 To NumberOfCopies&
  222.         NumCopies$ = NumCopies$ + S$
  223.     Next
  224. ' ------------ GetVS$ and SetVS$    Hot of the presses Version 2021-02-20  of the freshly redone from scratch subs
  225.  
  226. Function SetVS$ (Delimiter$, Insert$, NthPlace&, AStringCopy$) ' VS = Variable Siring Lengths
  227.     'use: FUNCTION StrCount& (S$, AString$)
  228.     'use: FUNCTION StrPlace& (S$, Index AS LONG, Astring$)
  229.     'use: FUNCTION StrCopies$ (NumberOfCopies&, S$)
  230.  
  231.     ReDim Astring$, wCnt&, nthPlaceAt&, nextAt&
  232.     Astring$ = AStringCopy$ 'AstringCopy$ gets changed so return result through function name$
  233.     wCnt& = StrCount&(Delimiter$, Astring$) + 1
  234.     'make sure we have enough delimiters
  235.     If wCnt& <= NthPlace& Then Astring$ = Astring$ + NumCopies$(NthPlace& - wCnt&, Delimiter$) ' string$ is the problem!!!!!
  236.     If NthPlace& > wCnt& Then ' AString$ will be modified such that only insert has to be tacked to end after delimiter
  237.         Astring$ = Astring$ + Insert$
  238.     ElseIf wCnt& = 1 Then 'If something there then it comes before but if nothing probably just starting out.
  239.         Astring$ = Insert$
  240.     Else ' NthPlace& is between 2 delimiters
  241.         nthPlaceAt& = StrPlace&(Delimiter$, NthPlace& - 1, Astring$)
  242.         nextAt& = StrPlace&(Delimiter$, NthPlace&, Astring$)
  243.         If NthPlace& = wCnt& Then 'no delim  on right end
  244.             Astring$ = Mid$(Astring$, 1, nthPlaceAt& + Len(Delimiter$) - 1) + Insert$
  245.         ElseIf NthPlace& <= 1 Then 'no delim of left end
  246.             If nextAt& Then Astring$ = Insert$ + Mid$(Astring$, nextAt&) Else Astring$ = Insert$
  247.         Else 'between 2 delimiters
  248.             Astring$ = Mid$(Astring$, 1, nthPlaceAt& + Len(Delimiter$) - 1) + Insert$ + Mid$(Astring$, nextAt&)
  249.         End If
  250.     End If
  251.     SetVS$ = Astring$
  252.  
  253. Function GetVS$ (Delimiter$, Index As Long, AString$) ' VS for Variable length string,
  254.     'use: FUNCTION StrCount& (S$, AString$)
  255.     'use: FUNCTION StrPlace& (S$, Index AS LONG, Astring$)
  256.     ReDim cnt As Long, p1 As Long, p2 As Long
  257.     cnt = StrCount&(Delimiter$, AString$) + 1
  258.     p1 = StrPlace&(Delimiter$, Index - 1, AString$)
  259.     p2 = StrPlace&(Delimiter$, Index, AString$)
  260.     If Index > cnt Or Index < 1 Then
  261.         Exit Function ' beyond the limit of string
  262.     ElseIf Index = 1 Then
  263.         GetVS$ = Mid$(AString$, 1, p2 - 1)
  264.     ElseIf Index = cnt Then
  265.         GetVS$ = Mid$(AString$, p1 + Len(Delimiter$))
  266.     Else 'between
  267.         GetVS$ = Mid$(AString$, p1 + Len(Delimiter$), p2 - p1 - Len(Delimiter$))
  268.     End If
  269.  
  270. Function StrCount& (S$, AString$) ' Count S$ in Astring$
  271.     ReDim place As Long, cnt As Long, lenS As Long
  272.     place = InStr(AString$, S$): lenS = Len(S$)
  273.     While place
  274.         cnt = cnt + 1
  275.         place = InStr(place + lenS, AString$, S$)
  276.     Wend
  277.     StrCount& = cnt
  278.  
  279. Function StrPlace& (S$, Index As Long, Astring$) ' Locate the Index number S$ in Astrin$
  280.     ReDim place As Long, cnt As Long, lenS As Long
  281.     place = InStr(Astring$, S$): lenS = Len(S$)
  282.     While place
  283.         cnt = cnt + 1
  284.         If cnt = Index Then StrPlace& = place: Exit Function
  285.         place = InStr(place + lenS, Astring$, S$)
  286.     Wend
  287. End Function '--------------------------------------------- END OF  subs for Get and Set Variable
  288.  
  289. Function SortWrapper$ (Astring$, SortType1to4 As Long) '------------------------------- Sorts Stuff
  290.     Dim i As Long
  291.     ' type 1 string ascending, 2 string descending, 3 numeric ascending, 4 numeric descending
  292.     'the arrays SA$ and NA# have been dim shared (1 to 1) need to unzip astring$
  293.     Split Astring$, Chr$(1), SA$()
  294.     ReDim NA#(1 To UBound(sa$))
  295.     If SortType1to4 > 2 Then 'convert into number
  296.         For i = 1 To UBound(sa$)
  297.             NA#(i) = Val(SA$(i))
  298.         Next
  299.     End If
  300.     Select Case SortType1to4
  301.         Case 1: ASQSort LBound(sa$), UBound(sa$)
  302.         Case 2: DSQSort LBound(sa$), UBound(sa$)
  303.         Case 3: ANQSort LBound(NA#), UBound(NA#)
  304.         Case 4: DNQSort LBound(NA#), UBound(NA#)
  305.     End Select
  306.     'now pack it backup in an Astring$
  307.     If SortType1to4 > 2 Then 'convert back into string
  308.         For i = LBound(NA#) To UBound(NA#)
  309.             SA$(i) = _Trim$(Str$(NA#(i)))
  310.         Next
  311.     End If
  312.     SortWrapper$ = Join$(SA$(), Chr$(1))
  313.  
  314. Sub ASQSort (Start, Finish) 'sa$ needs to be   DIM SHARED !!!!     array
  315.     Dim i As Long, j As Long, x$
  316.     i = Start: j = Finish: x$ = SA$(Int((i + j) / 2))
  317.     While i <= j
  318.         While SA$(i) < x$: i = i + 1: Wend
  319.         While SA$(j) > x$: j = j - 1: Wend
  320.         If i <= j Then
  321.             Swap SA$(i), SA$(j)
  322.             i = i + 1: j = j - 1
  323.         End If
  324.     Wend
  325.     If j > Start Then ASQSort Start, j
  326.     If i < Finish Then ASQSort i, Finish
  327. Sub DSQSort (Start, Finish) 'sa$ needs to be   DIM SHARED !!!!     array
  328.     Dim i As Long, j As Long, x$
  329.     i = Start: j = Finish: x$ = SA$(Int((i + j) / 2))
  330.     While i <= j
  331.         While SA$(i) > x$: i = i + 1: Wend
  332.         While SA$(j) < x$: j = j - 1: Wend
  333.         If i <= j Then
  334.             Swap SA$(i), SA$(j)
  335.             i = i + 1: j = j - 1
  336.         End If
  337.     Wend
  338.     If j > Start Then DSQSort Start, j
  339.     If i < Finish Then DSQSort i, Finish
  340. Sub ANQSort (Start, Finish) 'na#  needs to be   DIM SHARED !!!!     array
  341.     Dim i As Long, j As Long, x#
  342.     i = Start: j = Finish: x# = NA#(Int((i + j) / 2))
  343.     While i <= j
  344.         While NA#(i) < x#: i = i + 1: Wend
  345.         While NA#(j) > x#: j = j - 1: Wend
  346.         If i <= j Then
  347.             Swap NA#(i), NA#(j)
  348.             i = i + 1: j = j - 1
  349.         End If
  350.     Wend
  351.     If j > Start Then ANQSort Start, j
  352.     If i < Finish Then ANQSort i, Finish
  353. Sub DNQSort (Start, Finish) 'sa$ needs to be   DIM SHARED !!!!     array
  354.     Dim i As Long, j As Long, x#
  355.     i = Start: j = Finish: x# = NA#(Int((i + j) / 2))
  356.     While i <= j
  357.         While NA#(i) > x#: i = i + 1: Wend
  358.         While NA#(j) < x#: j = j - 1: Wend
  359.         If i <= j Then
  360.             Swap NA#(i), NA#(j)
  361.             i = i + 1: j = j - 1
  362.         End If
  363.     Wend
  364.     If j > Start Then DNQSort Start, j
  365.     If i < Finish Then DNQSort i, Finish
  366. End Sub '------------------------------------------------------------------------ Sorts Stuff End
  367.  
  368.  

And all the test code for SB1 has been rewritten and tested for the oh Interpreter (see attached zip):

So how can you possibly do math stuff without those upper row shifted chars? Check it out :)

Look here for most recent zip package to Download, bas source + Windows 10 .exe, Cheat Sheet & Change Log and dozens of test txt programs that demo different features of using oh:

Updated 2021-03-14 you should be able to use SFunctions anywhere an argument is used in a command or another SFunction, menu fixed up a little, Simplicity File Load and Save, nItems[Astring], Right[ , ], Left[,] see Change Log next post (at end)    Oh yeah, Poll command for updating mouse status and last Key press. :)

Updates 2021-03-16 Extended maths for Add, Subtract, Mult, Divide and 2 output commands to clipboard and 1 SFunction clip[] no arguments for Clipboard Contents into a variable.

Update 2021-03-17 Featuring Donut.txt, some fixes and tweaks to get that all nice and pretty!

Update 2021-03-19 Featuring: Mouse Action Shooter - Target Practice
Changes mostly to get that going including Atan2[deltaY,deltaX ], Mouse TF (display or not), ABS[], Beep, Timer[]

Update 2021-03-22 Whole new front end, a scroller displays file contents, at least 128 chars per line (unless has tabs) and menu for: New, Edit, Load, Run, Quit mouse or keypress. Now have files[] that lists the current directory files in an AString! Extended math inverse[posInteger,numberOfDecimals] for customizing division if you need more or less than 100 decimal places that the extended math divide[a$,b$] uses. The handy replace[source$,replace$,new$] added. Linelabels now end with \ instead of colon.

Update 2021-03-27 A number of fixes and syntax checking, specially useful after editing a program.

Update 2021-03-27A Fix sloppy closing bracket checking (was assuming end of line if none found) and also flag unrecognized SFunctions. This should help better point to code errors before the run.

Update 2021-06-03 Fix divide$ new program calculates the Square root of a number to 100 digit places, this program is when I discovered divide$ had a problem, it now runs fine!

Update 2021-06-15 String Math update replaces old String Math with fixed and inproved routines including the new sqrroot[] routine fro precision square roots.

You will need direntry.h in your QB64 Folder, a copy is included in zip package. This enables cross platform directory and file access, Thanks @SMcNeill
* oh v 2021-06-15 String Math Update.zip (Filesize: 63.76 KB, Downloads: 242)
« Last Edit: June 15, 2021, 10:17:28 pm by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: oh One-Handed Interpreter
« Reply #1 on: March 08, 2021, 12:20:02 pm »
oh Cheat Sheet | Help | Manual | Document
Update for v 2021-06-15 String Math update

Code: [Select]
oh cheat sheet(s) txt file, b+ rev 2021-06-15 String Math Update

                      ***  oh = One Handed Interpreter ***

Create your oh program in your favorite Word Processor, I am using Notepad++.
Drag and drop the file onto the compiled oh.exe to run it (old way).

oh Menu:
oh now displays the contents of a program on a scroller if get one off Command$.
All files selected from Load with be displayed on scroller with Menu on top line:
(in yellow and red) New, Edit, Load, Run, Quit ; click or press first letter of
menu item to select it. Edit or New should load up the file in your default .Txt
Editor from a Shell call.

Commands, variables, line labels are case insensitive.

Re: Comments
' at start of a line, formally tells oh to ignore the line, it's a comment.
You can probably write comments in at your own risk without the '
 as long as they don't start with a command word or symbol or have = sign
 after first word.

Re: oh color settings, in case you need to get back to them:
Ink 100;180;225
Paper 0;0;39

*** Preloaded Variables and their Values:
"MouseX"  ' use the poll command to update x pix see demo ao 3/14
"MouseY"  ' use the poll command to update y pix
"MouseL"  ' use the poll command to update Left button down = -1 or 0
"MouseR"  ' use the poll command to update Right button status
"Key"     ' use the poll command to update Last non empty key pressed, not sure about this one
"MT"   = ""  ' constant, handy name for nut'n which you can compare to inps (Input String)
"XMAX" = "1024"  screen pixel width, constant
"YMAX" = "672"   screen pixel height, constant
"RMAX" = "42"    screen print rows, constant
"CMAX" = "128"   screen print columns, constant
"NL"   = Chr$(13) + Chr$(10)  for .txt file delimiter
(note: I say constant but these are variable not wise to change them though.)

*** Print commands which use ; to delimit variables inside text
. normal print and carriage return line feed use / one space after . or after ; to set spaces
; print and next print position is right where it is, dont forget to finish line with a . line
, tab built in columns
tab columnWidth;item;item;item;...
cpr row;textgoes here with plug-in variables ';here; and ;here;.   
        Center Print Row print a line of text.
clipout args1 - replace Clipboard contents from any variable or literal
clipadd args1 - Append tp Clipboard contents any variable or literal,
the command does the first NL$ = Chr$(13) + Chr$(10),
you must do manually any inside the stuff you are appending, if needed.

*** Input commands also ; to delimit prompt and variable
inps this is a sample prompt;var   s on end signals string expected and will return mt for just enter keypress
inpn this is a sample number prompt;var  n on end will turn an empty string entered to 0

*** Screen stuff now semi-colon delimited arguments to allow each argument to be evaluated:
loc row;col            AKA Locate for print chars 8x16
at  col;row            Alternate that corresponds to graphics x, y but in char cells 8x16
tag pixX;pixY;text$    AKA _PrintString
cpr row;text           Center Print atRow;text with variables;embedded;I think.

*** Screen Drawing now semi-colon delimited arguments to allow each argument to be evaluated:
ink r;g;b;a          fore-color for printing or drawing
paper r;g;b;a        back-color usually set at start
pix x;y               AKA Pset(x, y)
line x1;y1;x2;y2      AKA Line(x1, y1)-(x2, y2)
box x1;y1;w;h          AKA Line(x1, y1)-Step(x2, y2), ,B
fbox x1;y1;w;h         AKA Line(x1, y1)-Step(x2, y2), ,BF
circ x1;y1;r            AKA Circle (x1, y1), r
fcirc x1;y1;rr          AKA For r = 0 To rr Step .25 : Circle (x, y), r : Next
ftri x1;y1;x2;y2;x3;y3  Special MapTriangle command for

*** Misc:
poll           Updates preset mouse and key variables
cls            AKA Cls
zzz            AKA Sleep
beep           AKA Beep this comes in handy for debugging
wait nSecs     AKA _Delay
show TF        AKA _Display, AutoDisplay Boolean: True = stops blinking, False = immediate draw/print
mouse TF       Mouse Hide if False = 0, Show Mouse if True <> 0 
set Astring;index;itemValue   compare to A(i) = itemValue
also see var = get[astring,index] SFunction below
rndPt (arg = variableContainer) gets the next rndPt from a deck of all points on screen,
       this helps distribute graphics "randomly" on screen, covers every point
   then deck is reshuffled for next layer
   rp = rndPt
   x = rp mod xmax   or as we like to say at oh, m[rp,xmax]
   y = int(rp/ymax)  or as we like to say at oh, int[d[rp,ymax]] 
   
*** Boolean IF blocks
if BooleanExpression
ei BooleanExpression     AKA ElseIf
el                       AKA Else
fi                       AKA End If

*** Loop structure only one unless count goto
[  - starts loop
]  - ends loop

*** only ways out of loops are:
jmp BooleanExpression   Jump! out of the current loop level the command is in.
exit   usually from inner if block, exits current loop level
end    stop run
goto labelName:

*** GoSub
gs labelName\ AKA GoSub (3/21 : changed to \ as line label marker)
rtn           AKA Return

labelName\   for gs and goto (3/21 : changed to \ as line label marker)

*** File simplicity:
Save Astring;toFileName       - command
AstringVar = load[fileName]   - SFunction
files[]                       - AString list of the files in the current directory

*** SFunctions Syntax:
var = SFunction[a1, a2, a3,...]   variables setting or reassigning

*** Booleans:
and[a1, a2, a3,... ]  only returns -1 when all are <> 0
or[a1, a2, a3,... ]   returns -1 if any one is <> 0
seq[a1, a2] does a string compare a1 = a2? -1 if true, 0 if not
eq[a1, a2] does a numeric compare a1 = a2? -1 if true, 0 if not
lt[a1, a2] less than  a1<a2                -1 if true, 0 if not
lte[a1, a2] less than or equal a1<=a2      -1 if true, 0 if not
gt[a1, a2] greater than a1>a2              -1 if true, 0 if not
gte[a1, a2] greater than or equal a1>=a2   -1 if true, 0 if not
noteq[a1, a2] not equal a1<>a2             -1 if true, 0 if not
not[a1]         if a1 = 0 then Not returns -1 else Not returns 0

*** Arithmetics:
a[a1, a2, a3,...]  adds them all,        a is for add
x[a1, a2, a3,...]  multiplies all,       x is for mult.
s[a1, a2]          a1 - a2               s is for subtract
d[a1, a2]          a1 / a2  if a2 <> 0   d is for divide
m[a1, a2]          a1 mod a2             m is for mod  AKA the remainder
p[a1, a2]          a1 ^ a2               p is for power

*** Extended Arithmetics extended math so extended the names ;-))
add[a1,a2]
subtract[a1,a2] - should this be subtract or subtr? I don't like sub
mult[a1,a2]    - I am sure this is OK for multiply
divide[a1,a2]  - handles approx 100 decimal places (got to set a limit or it'd go on forever!),
                  the 3 binary's above are arbitrary.
inverse[PosInteger,NumberOfDecimals] - for custom designed division when 100 decimals wont do.
sqrroot[a1] - working independently from Mr$ Function like inverse.
(The extended math had 14 Routines, MR$ is controller of the Big 4 and stands for Math Regulator.)  

*** Maths misc:
int[a1]   converts to Integer, remove floating point decimal end if any
sqr[a1]   returns square root if a1 is positive or 0
log[a1]   QB64's Log, natural logarithm, see wiki Log to convert to Log(base 10)
exp[a1]   QB64's Exp, Exp(1) = e
rnd[a1]   a1 is multiplier of Rnd (0 to almost 1) * a1
abs[a1]   Absolute value of a1

*** Trigs (Radian angle units)
sin[a1]  a1 angle in radians, returns unique ratio
cos[a1]  a1 angle in radians, returns unique ratio
tan[a1]  a1 angle in radians, returns unique ratio
asin[a1] a1 is ratio, returns angle in radian units
acos[a1] a1 is ratio, returns angle in radian units
atan[a1] a1 is ratio, returns angle in radian units
rad[a1]  a1 is usually an angle in degrees needing to be changed to radian units
deg[a1]  a1 is usually an angle in radians needing to be converted to degree units
pi[a1]   a1 is a multiplier or fraction of Pi
atan2[a1 (=deltaY's) , a2 (=deltaX's) ] SFunction with 2 args, definitely a plus!
note: delta usu. means difference
Find the angle of point 1 (x1,y1) from point 2 (x2, y2) )
Basic: var = _atan2(y1-y2,x1-x2) or oh: var = atan2[s[y1,y2],s[x1,x2]]
( You can figure the rest of the Trig Functions from these. )

*** String functions:

bnd[a1, a2, a3,...]  bind, bond, bound this concatenates a1, a2, a3,...

join[delimiter$, a2, a3,...] like the above but links the with delimiter,
                             for comma or space separated items or Chr$(10) line separators

Allot of string functions have counterparts joins counterpart is:

split[a1, a2] a1 is string to split, a2 is the delimiter, splits usually go into arrays
for oh we are using Astrings, strings that can be indexed to retrieve items using the "get" function.

Another way to build giant strings from building block is:
cop[a1, a2] better than String$ command because it makes a1 concatenated copies of string a2

rejoin[a1, a2] will take the special Astring, a1, formed from split or cop maybe bnd and split
and rejoin using the the delimiters given as a2. Say you have processed an Astring of data and
wish to save it in a file as comma separated or as line by line.
 

*** String slices:
mid1[a1, a2]      AKA Mid$(a1, a2, 1) a 1 char return in a1 at a2
mid2[a1, a2]      AKA standard Mid$(a1, a2) 2 argument return remainder of a1 starting at a2
mid3[a1, a2, a3]  AKA standard 3 argument MID$

left[a1, num of chars]  AKA Left$
right[a1, num of chars] AKA Right$

head[a1, a2] from a1 find a2 and take the part that comes before a2
tail[a1, a2] from a1 find a2 (end) and take the remainder of string from there.

*** String finds:
in2[a1, a2] position of first a2 found in a1
in3[a1, a2, a3] starting at a1, find and return a3 position in a2

*** Chars:
asc[a1] returns ascii value of char, space = 32, enter = 13, tab = 9, dbl quote = 34, hyphen = 45
chr[a1] returns char of ascii number chr(65) = A, chr(48) = 0

*** Trimming spaces:
rtr[a1] removes spaces from right
ltr[a1] removes spaces from left
trim[a1] removes spaces left and right

*** Shouting, whispering, modifying:
cap[a1] a1 in all capitals
low[a1] a1 all lower case
replace[source$,replace$,new$] - replaces a string with new$ wherever found in source$

*** Astrings: like arrays, these are strings you can "get" an item value by index #
Set Astring;index;itemToAddOrReassign - this is a command as opposed to an SFunction

so sets counterpart is get:
get[a1, a2] from Astring, a1, get the item at index, a2. Compare to var = A(i), var = get[astring, index]

nItems[Astring]  number of Items in the Astring (counts delimiters and adds 1)

*** Now for some easy string functions:
len[a1] returns the length in chars of a1
spc[a1] returns a1 block of spaces
date[] no argument Date$
time[] no argument Time$
clip[] no argument get contents of _ClipBoard
timer[] no argument still need [] this the number of secs since midnight, 3 decimals at least.

*** Special Order String Functions:
ASSORT[a1] ascending string sort of astring, a1
DSSORT[a1] descending string sort of astring, a1
ANSORT[a1] ascending numeric sort of astring, a1
DNSORT[a1] descending numeric sort of astring, a1

Fval[a1] will attempt to evaluate a string or numeric expression of functions and literals.

*** File simplicity:
Save Astring;toFileName
AstringVar = load[fileName]
files[]                       - AString list of the files in the current directory

Change Log: ==============================================================================================

*** 2021-03-09 The "Screen" commands are now ; delimited to allow each argument to be evaluated.
Commands effected: loc at tag ink pix line box fbox circ fcirc ftri wait show paper
All demos effected have been updated.

New command: cpr for centering print on a row: cpr row;my text is this with a variable ;here; to plug in.
See: Test ac Fval$ Tester.txt, demo as this has been completely rewritten for cpr and first
test of using Fval$ to check arguments to commands.

A Splash screen for Oh?

*** 2021-03-10 Added 300 plus lines for File Dialog & Company including a very nice array displayer for showing the
loaded programs, maybe I could do a help? No that is better in tabbed Notepad++

Internal Splash is gone and the other internal test programs, net effect 1300 LOC including the start
 of oh's menu system

direntry.h has been added to the zip package, please copy | paste into your QB64 folder for cross platform
 directory and files access if you dont have a copy there already. This allows the File Dialog part of oh to
 work correctly.

*** 2021-03-14
Dumped checking the _ClipBoard for a program now with File Dialog and all.

Tidied up oh's menu a tiny bit.

Check cpr handling of embedded variables and or SF[]'s, OK that is fixed up but not sure I want to
 do that for the other print commands? Oh yes!!! I do want that! (Done)
 
Note: it you call edit without a file name you will wind up on the command line, just type exit.
 
Add Command:
Save Astring;Filename
Reminder: Astring is my term for a string with indexed variable length string items.
Save will store each item as a line in given filename.

Add SFunction:
Astring = Load[filename]
So that you can load a file into an Astring for indexed access to lines.

Consolidate Set and RndPt (even though RndPt takes no arguments it assigns a var)
commands with all the other ; delimited commands that do calculations. So now,
you don't have to have middleman variables in the commands, you can calc directly
in the command.

Add preloaded Mouse variables:
MouseX, MouseY, MouseL, MouseR
Locate (x, y) mouse in pix and Boolean Left or Right Button Down

Add preloaded variable:
Key
For keypress detection.

New Poll command to update all those preloaded variables with mouse and Key status.

Left$ and Right$ var = Right[a1$, val(a2$)

Ubound of Astring amount = nItems[AString]

*** 2021-03-16
Added: string math for extended arithmetics in SFunctions
add[a1,a2]
subtract[a1,a2]
mult[a1,a2]
divide[a1,a2]
(Divide: numerator/denominator, is calc'd by multiplying numerator by inverse of denominator).
(So the inverse is calculated to 100 Decimal Places, but sometimes 100 decimal places wont do
 so inverse[posInteger,NumberOfDecimals] is added to do custom "division" by controlling the
 decimals in inverse and to be then multiplied by numerator in a hand made division calculation.)


Added command:
clipout a1 + whatever argument 1 is holding: literal, variable value substitution
               or expression of SFunctions replaces contents of Clipboard

Added command:
clipadd a1 appends to, instead of replaces, Clipboard data.

Added SFunction clip[] no argument SFunction, you still need the brackets.
 This puts the contents of the contents of the Clipboard into the spec'd var.
 eg var = clip[]
 
*** 2021-03-17
 Basically just a few fixes and tweaks to get Donut.txt to work. Fixed the file line count
  with a different load of a file. Fixed bug from reading the Len[] of a file, thrown off by
  the file containing []'s!!! So a new SafeBS$ Function filter/converter created that
  converts [] to {}. Needed to fix the Ink, Paper and color restoring after Run.
 
*** 2021-03-19
 For Mouse Action Shooter - Target Practice (Graphics Game #2 attempt)
3/18 added mouse TF  - command with 1 argument. True to Show Mouse, False to Hide Mouse
3/18 added abs[arg1] - SFunction with 1 argument. Kind of surprised how much I use ABS.
3/18 added timer[]   - SFunction no argument, still need brackets.
3/18 added atan2[a1 (=deltaY's) , a2 (=deltaX's) ] SFunction with 2 args, definitely a plus!
Find the angle of point 1 (x1,y1) from point 2 (x2, y2)
Basic: var = _atan2(y1-y2,x1-x2) or oh: var = atan2[s[y1,y2],s[x1,x2]]
3/19 added beep (command) no args, main reason: to help debug.

*** 2021-03-22
3/20 added inverse[PosInteger,NumberOfDecimals] for custom division or control of decimals.
     This is = 1/PosNumber to a set amount of decimals.
3/21 added files[] - no argument SFunction that loads the files of current directory into an AString.
3/21 added replace[stringSource,stringToReplace,StringToRplaceWith] - 3 arguments SFunction.
3/21 fix? load[] renders [ brackets impotent by swapping them with { brackets
save Astring;FileName sort of needs to reverse that by replacing { back to [
This is messy, in future something else may be a better solution.
3/21 Line labels now end with \ instead of colon. This is to be consistent to oh rule, no shifts.
3/21 Added another preloaded variable nl (Next Line) for file line delimiter.
Vnames$(11) = "NL": Vvalues$(10) = Chr$(13) + Chr$(10)
3/21 Gutted out opening code and rewrote the code to display files on a scroller when have a
     filename and existing file. Now the menu runs across top line in yellow and red and can
click menu item or key press first letter for New, Edit, Load, Run, or Quit.
Much better if I do say so myself :) This completes my goals for this revision.

*** 2021-03-27
3/23 Fix file display scroller to accept PgUp, PgDn, Home, End Keypresses.
Also run file lines through filter JIT to replace tabs with 4 spaces and other
chars < 32 with *. This enables the display of 39 lines on 39 lines without screen
scrolling and menu line lost.
3/23 NL fixed and working as expected in: Test oh replace and nl.txt file.
3/23 Adding SHARED Lists: CmdList$ and FunList$ for Function OK$ a line Syntax checker function
that will return nothing (OK) if the line is fine, or what it found wrong with proposed
program line. Inventory: 40 commands (fix 4 more), 74 SFunctions
3/26 Added 3 more procedures for Syntax checking and immediately learned I missed 4 commands in
     command list. The only line it caught after that was an title line without a formal comment.
I started editing Particle Fountain (it is hopelessly S L O W) and the syntax checker caught
a missing argument in an Or line when I mistakenly typed a } instead of a regular ] bracket.
Good, it catches at least something. So now lines start with comments, commands, variables
or line labels\ (\ ends a line label now).
3/27 Fixed - Mouse Action Shooter - the first bullet fired was always nothing?? and yet 10 points
     is deducted from the score as it should be. Show me the bullet! I just initialized all the
bullets properties instead of only the bLive AStrings (arrays).
3/27 Fixed. After editing a file, you have to change directory and change back to get the new
     file loaded with the changes. I now do that automatically in code after an Edit.

*** 2021-03-27A
3/27A Syntax checking had a little sloppy handling of closing ] assuming it was at end of line
     instead of checking if one was actually there to match opening [. I found 4
working programs that were missing a final bracket at the end. I also found a program
that used [] instead of parenthesis and it was flagged for unknown SFunction. So that part
of syntax checking is also fixed, you will be flagged for unrecognized functions.
So I went through all working programs and they now fly through syntax checking right into
a successful run.

*** 2021-06-03 fix divide$
6/03 Fix the divide$ Function so that, Test oh High Precision Square Root.txt, file program works.
Also found the clipout and clipadd help in, oh Cheat Sheet.txt in error and fixed (no square
brackets to enclose the argument).

*** 2021-06-15 String Math update
6/15 A number of fixes and improvements to the String Math package including new sqrroot[number]
     Function. Unfortunately with the new fixes the inverse of STx number takes a bit longer than
it did, it's a wonder it was getting correct results originally. When testing all the
programs I noticed the nl "constant" I had forgotten all about. This is doing double spaced
lines because it is Chr$(13)+Chr$(10) probably should be one or other, not both together.
Since last update we created new programs:
Aurels Henon code, Bresenham Circle Fill, First 100 digit Fibonacci, Sqr Root estimating.
A version of the last program became part of the String Math package update!

« Last Edit: June 15, 2021, 10:18:50 pm by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: oh One-Handed Interpreter
« Reply #2 on: March 08, 2021, 08:43:00 pm »
Fix for: Test oh Sort Tests.txt - the way it was supposed to build random strings with a max of 11 Capital letters (and definitely no numbers):
Code: QB64: [Select]
  1. 'Test oh aj Sort Tests.txt b+ mod for oh 2021-03-07
  2. ' build test strings and numbers and display
  3. [
  4.         cnt = a[cnt,1]
  5.         jmp gt[cnt,20]
  6.         rLen = a[int[rnd[10]],2]
  7.         ' change variable name from b to bstring
  8.         bString = mt
  9.         cnt2 = 0
  10.         [
  11.                 cnt2 = a[cnt2,1]
  12.                 jmp gt[cnt2,rLen]
  13.                
  14.                 ' bstring was getting B or R from this random choosing of letter
  15.                 ' and substituting back current value of b or r variable!!! Yikes
  16.                 ' no wonder bstring had numbers inserted or extra strings!!!
  17.                 bString = bnd[bString,chr[a[int[rnd[26]],65]]]
  18.         ]
  19.         set AstringS,cnt,bString
  20.         ' change variable r to rNumber
  21.         rNumber = int[rnd[x[100,100]]]
  22.         set AstringN, cnt, rNumber
  23.         loc cnt, 1
  24.         ; bString
  25.         row = a[cnt,21]
  26.         loc row, 1
  27.         ; rNumber
  28. ]
  29. ' sort into 4 groups 2 string 2 number, ascending and descending
  30. sa = assort[AstringS]
  31. sd = dssort[AstringS]
  32. na = ansort[AstringN]
  33. nd = dnSort[AstringN]
  34. ' display sorted groups
  35. cnt = 0
  36. [
  37.         cnt = a[cnt,1]
  38.         jmp gt[cnt,20]
  39.         sai = get[sa,cnt]
  40.         sdi = get[sd,cnt]
  41.         nai = get[na,cnt]
  42.         ndi = get[nd,cnt]
  43.         at 20, cnt
  44.         ; sai
  45.         at 40, cnt
  46.         ; sdi
  47.         row = a[cnt,21]
  48.         at 20, row
  49.         ; nai
  50.         at 40, row
  51.         ; ndi
  52. ]
  53. Zzz
  54.  

Once again I am burned by using 1 letter variables.

I was testing a possible rework of the set command and discovered an odd thing happening with the random string being built to sort. Some were becoming gigantic and others were having numbers inserted from the random number I was generating.

Turns out my 1 letter variables b and r were getting their values substituted back when the random letter generated one of them to add the the build string, so instead of the letter being added, it's stored value was!

LOL, yeah funny now, quite a shock when I first discovered the bug in the test code for oh late this afternoon.

BTW the set command stays as is, no need to say:
Code: [Select]
astringName = set[astringName, index, newValue$]
when
Code: [Select]
set astringName, index, newValue$will do.
« Last Edit: March 08, 2021, 08:54:55 pm by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: oh One-Handed Interpreter
« Reply #3 on: March 09, 2021, 02:17:01 am »
Update: I now have the arguments to the Screen and Graphics commands being run through Fval$ so you don't need to create extra variables for simple row, col cals or x, y's for a graphic but this required making the argument delimiter a semi-colon to distinguish from the comma delimiter in all SFunctions.

A new command for center printing a line with plug-in variables,
Code: [Select]
cpr row; my text with plug-in ;here1; and ;here2;.
All the demos have been updated with new delimiter for appropriate commands and Test oh ac Fval$ Tester has been rewritten and I feature it now:

Code: [Select]
'Test ac Fval$ Tester.txt by b+ 2020-03-07 mod 2021-02-21 mod 2021-03-09
' I wrote in cpr just for this demo! Plus
[
cpr 2;*** Fval$ Tester ***
cpr 5;Arith: a[1,1] > 2,  s[1,1] > 0,  x[2,3] > 6,  d[12,4] > 3     Constants: e = exp[1], pi = pi[1]
cpr 7;Math: modulus use m[3,2] > 1   power use p[2,3] > 8   log[], exp[], sqr[], int[], rnd[multiplier]
cpr 9;Trig (radians): sin[], cos[], tan[], asin[], acos[], atan[]     Angle Conversion: rad[degrees], deg[radians]
cpr 11;Boolean: #=# use eq[ , ] for = numbers    noteq[ , ] for <>    lt[ , ] for <    lte[ , ] for <= 
cpr 13; gt[ , ] for >   gte[ , ] for >=   and[,,, ]   or[,,, ]   not[ ]    seq[$,$] for string equal
cpr 16;Get the cheat sheet and test string functions! Here a most:
cpr 17;mid1, mid2, mid3, in2, in3, time, date, CAP, low, rtrim, ltrim, trim, spc, len

' first test ever of fval$ working on arguments to loc, at, tag, graphics...
loc a[17,3];5

inps (just enter to quit) Enter an expression to evaluate; expression
Jmp seq[expression,mt]
result = fval[expression]
at 5;22
cpr 22;The Tester came up with this: ;result
cpr 25;Wait 5 secs...
Wait 5
Cls
]
.
. Goodbye!

 
Test oh ac Fval$ Tester.PNG


New zip package contains bas, exe for Windows 10, demo.txts and updated, oh cheat sheet.txt with change log now.

Update:
See the first post of this thread for most recent version of oh.bas and zip package.
« Last Edit: March 10, 2021, 01:39:55 pm by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: oh One-Handed Interpreter
« Reply #4 on: March 09, 2021, 02:25:57 am »
Oh yeah, new Internal Splash Screen:
 
New Internal Splash.PNG

Offline Ed Davis

  • Newbie
  • Posts: 40
    • View Profile
Re: oh One-Handed Interpreter
« Reply #5 on: March 09, 2021, 10:23:59 am »
This is _really_, _really_ cool!
I'm having fun looking at it!

Thanks for sharing it!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: oh One-Handed Interpreter
« Reply #6 on: March 09, 2021, 11:00:31 am »
This is _really_, _really_ cool!
I'm having fun looking at it!

Thanks for sharing it!


The sharing is my pleasure :)

Your looking over it is great, so far I know it works for some 1.5 dozen little tests about 50 times over in various versions over the past weeks. I am wondering what surprises are in store from the last change, evaluating the arguments coming in other than after an = space sign.

I personally luv the simplicity of the Fval$ function that gets right to the business of isolating the deepest nested SFunction and handing it off to FunHandler$.

Offline Aurel

  • Forum Regular
  • Posts: 167
    • View Profile
Re: oh One-Handed Interpreter
« Reply #7 on: March 09, 2021, 11:23:28 am »
OK Mark
very nice...btw.
i modify it to work with my old v1.3 and seems that all work well ;)
//////////////////////////////////////////////////////////////////
https://aurelsoft.ucoz.com
https://www.facebook.com/groups/470369984111370
//////////////////////////////////////////////////////////////////

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: oh One-Handed Interpreter
« Reply #8 on: March 09, 2021, 11:42:55 am »
Thanks for testing Aurel.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: oh One-Handed Interpreter
« Reply #9 on: March 10, 2021, 10:44:03 am »
Update: I have installed newly created cross platform File Dialog so you and mainly me are relieved of drag and drop one time file Runs. So theoretically we can expand out from one folder and scan whole hard disk of folders and files if we have a mind to.

It was not playing nice last night but I think I have it tamed now. I have employed Steve's ScnState idea for saving and restoring screen conditions before and after doing things to it ie File Dialog and Runs and that seems to have smoothed things out considerable.

A little more testing to go, hope to tap into an editor. Since I couldn't get Notepad++ to run SB1.exe (with the active file I just edited in it), I will Run it (or whatever default editor does your txt files) through oh.

Update: Ok it seems everything is working as intended (on my Windows 10 laptop), could use more testing. Most curious to know if this thing is working in Linux? It should have proper cross platform file and directory access.

Be sure to add direntry.h file to your QB64.exe folder so it may find this header file. A copy is included in zip package that you can copy/paste into that folder if you don't have it there already :)

See first post of this thread for most recent version of oh.
« Last Edit: March 10, 2021, 02:05:14 pm by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: oh One-Handed Interpreter
« Reply #10 on: March 14, 2021, 12:03:29 am »
Update: modified the printing commands to handle calculations if instr "[" is found, this is very handy for formatting with spaces.

Added command:
save Astring;toFileName

Added SFunction Load
AstringVar = Load[filename]

And so this program:
Code: [Select]
' Test oh an file load and save quadratic data.txt b+ 2021-03-13
. Quadrartic = (x + 5) (2x + 6) = 2x^2 + 16x + 30
set file,1,Quadrartic = (x + 5) (2x + 6) = 2x^2 + 16x + 30
. expected roots are -3, -5
set file,2,expected roots are -3 and -5
a = 2
b = 16
c = 30
set file,3,a = 2  b = 16  c = 30
d = p[s[x[b,b],x[4,a,c]],.5]
root1 = d[a[s[0, b],d],x[2,a]]
root2 = d[s[s[0, b],d],x[2,a]]
.     d = ;d
. root1 = ;root1
. root2 = ;root2
temp = bnd[    d = ,d]
set file,4,temp
temp = bnd[root1 = ,root1]
set file,5,temp
temp = bnd[root2 = ,root2]
set file,6,temp

'calc a small table of F(x)
x = -11
i = 7
[
x = a[x,1]
jmp gt[x,10]
i = a[i,1]
fx = a[x[2,x,x],x[16,x],30]
fline = bnd[x,:,fx]
. x;spc[2];fx;spc[2];fline
set file,i,fline
]
. number of lines = ;i
numberOfLines = i
save file;Quadratic Data 2x^2+16x+30.Dat
. data saved to file, press any to load data file and display...
zzz
cls
fdata = load[Quadratic Data 2x^2+16x+30.Dat]
i = 0
[
i = a[i,1]
jmp gt[i,numberOfLines]
fline = get[fdata,i]
. fline
]


Wrote this file:
Code: [Select]
Quadrartic = (x + 5) (2x + 6) = 2x^2 + 16x + 30
expected roots are -3 and -5
a = 2  b = 16  c = 30
    d = 4
root1 = -3
root2 = -5

-10:70
-9:48
-8:30
-7:16
-6:6
-5:0
-4:-2
-3:0
-2:6
-1:16
0:30
1:48
2:70
3:96
4:126
5:160
6:198
7:240
8:286
9:336
10:390

Misspelling and all ;-))

Oh shoot, I might not need to preset those temp's for file lines but calculate them directly in the set lines.
retesting...

Nope, the set command is in it's own little niche with rndpt, time to reconsolidate more ; delimited commands!
So this part will work without the temp variable serving as a middleman.
Code: [Select]
'temp = bnd[    d = ,d]
set file,4,bnd[    d = ,d]
'temp = bnd[root1 = ,root1]
set file,5,bnd[root1 = ,root1]
'temp = bnd[root2 = ,root2]
set file,6,bnd[root2 = ,root2]

Also need the equivalent of an UBound command for Astrings, though wont get out of bounds errors would be handy for knowing the number of lines you just loaded from a file.

I'm also dreaming of an IDE. Notepad++ is being a bit annoying with all the auto-fills it automatically makes when I press Enter to start the next line.
« Last Edit: March 14, 2021, 12:36:12 am by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: oh One-Handed Interpreter
« Reply #11 on: March 14, 2021, 01:23:32 am »
Oh that's so nice:
Code: [Select]
set file;4;bnd[    d = ,d]
set file;5;bnd[root1 = ,root1]
set file;6;bnd[root2 = ,root2]

Works now without the middleman! and now I think all the commands are ; delimited so that makes it easier to remember.

And I improved the output to screen and file:
 
Quadratic.PNG
« Last Edit: March 14, 2021, 01:25:21 am by bplus »

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: oh One-Handed Interpreter
« Reply #12 on: March 14, 2021, 10:32:49 am »
Hey bplus,

I appreciate you keeping us up to date with this thing. It's been about 4 or 5 days since I've given it a test run, and would like to try it again. Now that you're messing with polynomials, I should be able to test a few things. Gotta say though, it's damn near impossible to actually follow your updates. What was wrong with the old names for this project, and why is it being renamed again? Where is the latest full code? (The zip is 4 days old at the time of this post) Etc etc etc. The usual questions. We're also spread across several threads. Are the old threads obsolete now? Maybe a good practice is to make the last post on each of those point to this one, if you haven't already.

Opinion section: Make a webpage for this project!

EDIT (sorry I keep editing this post): Explain like I'm 5 please: How do I write a function in your syntax? Like f(x) = x^3 + cos(2x) Has this changed drastically over the months?

It seems like factorialMe is some kind of global in your factorial code, for instance:

Code: [Select]
F!:
If gt[factorialMe,1]
fac = x[fac,factorialMe]
factorialMe = s[factorialMe,1]
GS F!:
Fi
Rtn

I guess my question is: can functions have private scope? Can they have a return value or do they just effect a global, like GOSUB? (Sorry if this is super obvious to you.)
« Last Edit: March 14, 2021, 11:08:53 am by STxAxTIC »
You're not done when it works, you're done when it's right.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: oh One-Handed Interpreter
« Reply #13 on: March 14, 2021, 12:32:17 pm »
Hey bplus,

I appreciate you keeping us up to date with this thing. It's been about 4 or 5 days since I've given it a test run, and would like to try it again. Now that you're messing with polynomials, I should be able to test a few things. Gotta say though, it's damn near impossible to actually follow your updates. What was wrong with the old names for this project, and why is it being renamed again? Where is the latest full code? (The zip is 4 days old at the time of this post) Etc etc etc. The usual questions. We're also spread across several threads. Are the old threads obsolete now? Maybe a good practice is to make the last post on each of those point to this one, if you haven't already.

Opinion section: Make a webpage for this project!

EDIT (sorry I keep editing this post): Explain like I'm 5 please: How do I write a function in your syntax? Like f(x) = x^3 + cos(2x) Has this changed drastically over the months?

It seems like factorialMe is some kind of global in your factorial code, for instance:

Code: [Select]
F!:
If gt[factorialMe,1]
fac = x[fac,factorialMe]
factorialMe = s[factorialMe,1]
GS F!:
Fi
Rtn

I guess my question is: can functions have private scope? Can they have a return value or do they just effect a global, like GOSUB? (Sorry if this is super obvious to you.)

Hi @STxAxTIC

Thanks for your interest as always.

Where to begin? The name change from SB1 (Shorthand "Basic" for want of a better term) was limited by the Eval function. On the plus side the Eval function did keep the right side of the = looking "Basic" with Fortran like formulas.
On the negative side, for me, I was limited to numeric evaluations.

Here in oh, the eval function has been removed and replaced with an easy and versatile Fval$. The name change is completely appropriate in my view because it's a different animal now. It's got a different base structure, around Fval$ instead of Eval. It's not "Basic" with formula like structures on the right side of = my guess is it's more like Lambda functions from my brief scans of that on Internet. It's all string functions and you may nest them as arguments to other functions, really easy and really cool. No need to do binary operations in order, you just do deepest nested [] first and work up to no brackets level. No stacks or recursion needed to process a program line of code.

The name also reflects another Big Change: No need to use shift key for any commands or functions. You can write all your code with One Hand and that is where the name oh comes from, One Handed. Hold your coffee in one hand and write code with the other ;-)) OH = One Handed

One reason to keep these updates going is this is rather big change from Basic. To download the zip package and know what to do with it is too much to expect. So follow this thread and see why or how things end up the way they do. I am just settling in to a consistent ; delimited command line.

The newest updated zip package is at the First Post of this thread, a cheat sheet | manual | document | Change Log is in the very next post.

Like f(x) = x^3 + cos(2x)

y = a[p[x,3],cos[x[2,x]]] 
'yeah not so Basic like anymore! The coder is doing the work of precompiling.
Ever wonder what math would be like if formulas looked like this instead of current?
poly = a[x[n1,x,x,x...],x[n2,x,x,x...],x[n3,x,x,x,,],... ,nN]


There are no functions/subs/procedures yet, to keep variables local in a GoSub (gs lineLabel:)
Do what they do under-the-hood, prefix them with the GoSub lineLabel eg lineLabel:_VarName.
But be sure to initialize as you would have to with a GoSub procedure.
You can set a variable with the name of the GoSub lineLabel! just don't put a colon on the end of it!

Yeah, kind of rinky-dink, but at moment I am enjoying the wealth and richness of having all the string functions I need at my disposal.

I want mouse and keypresses before fancy procedures with local scope.



Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: oh One-Handed Interpreter
« Reply #14 on: March 14, 2021, 12:52:43 pm »
Thanks bplus for such an informative reply. I agree that strictly trying to maintain BASIC syntax has its uses, i.e. making a BASIC interpreter. However, once you step off that path, and enter the pseudo-Churchian topology of string space (just to call it something), suddenly your code merges with the very data it manages, and vice-versa. This is like the General Relativity of computer programming: in the same sense that Einstein realized that gravity equals geometry, functional programmers realize that data equals code. Two seemingly unrelated ingredients turned out to be *equal*.

All that said, if you want my humble opinion, get the language part perfect before you worry about mouse input. In fact never worry about mouse input, or graphics, or any of that. Now that you've become a master of string space, stay there and master it.
You're not done when it works, you're done when it's right.