[Date Prev][Date Next][Subject Prev][Subject Next][ Date Index][ Subject Index]

XyBasic (re Robert's skepticism)



Robert wrote:
More fundamentally, I've never understood why you write programs in Basic
language and then "translate" them to XPL. It's incredibly limiting, and the
translation is guaranteed to be unnecessarily prolix.
Well, the translation is pretty much one-to-one (I grant you that there are
one or two exceptions--but I may be able to eliminate some of them). What
we're looking at here is going from:

First_Line-of-Address$ = "14 Maple Lane"

to:



The great advantage of the former is that you know what 16 is.
Also, it does things like For/Next loops, with variables as its start and finish values, and uses English instead of numbers for the Labels and subroutines.
In other words, it's a translator not a compiler. It assigns s/g numbers
for English-language variables and letters for English language Labels and
Subs.
Another value is just speed of typing in entering code. For pfuncs, I use
the same letters with the (easily reached) apostrophe key:

'tf 'wg 'xd

etc.
 A few simple instructions, just for laughs, sure -- but
complex ones?... I mean, let's see your InStrRev-to-XPL routine.
I don't even know what InStrRev is. That's not part of any BASIC that I
learned.

 Mid$.

Well, I do have MID$, but I'm not entirely happy with it:

Here's the result for the following source:

original$ = "abcdef"
b$ = mid$(original$, 2, 3)
'bc print b$

XPLeNCODE v2.0
b-gin [UNTITLED]
{<}SU567,{<}SX561,{<}VANW{>}{>}[BC_]d nw=1[XC_][BC_]ne xybasi
c.$$$[XC_]{<}PV563{>}[TF_][DF_]{<}SX562,1{>}{<}LB;A{>}{<}IF{<
}PV562{>}>{<}PV564{>}-1{>}{<}GL;B{>}{<}EI{>}[CR_]{<}SX562,{<}
PV562{>}+1{>}{<}GL;A{>}{<}LB;B{>}[DF_][RD_]{<}SX562,1{>}{<}LB
;C{>}{<}IF{<}PV562{>}>{<}PV565{>}{>}{<}GL;D{>}{<}EI{>}[CR_]{<
}SX562,{<}PV562{>}+1{>}{<}GL;C{>}{<}LB;D{>}[DF_][BF_][DF_][RD
_][DF_][TF_][DF_]{<}SV566{>}[BC_]ab[XC_][BC_]d nw={<}PV561{>}
[XC_][BC_][NO_]{>}{<}SV01,abcdef{>}{<}SX563,{<}IS01{>}{>}{<}S
X564,2{>}{<}SX565,3{>}{<}GT567{>}{<}SX02,{<}IS566{>}{>}[BC_]{
<}PV02{>}{<}LB_{>}{<}SV50,555-598{>}[JM_]2.clearsgts[Q2_]{<}E
X{>}[cr|lf]
-nd
XPLeNCODE
Chr().

Simple: 'jm "2.Chr$"

A little humor there, but I can and do make such calls to U2 frames.
 Do While. How do you handle something as simple as an Else?

I didn't implement Do While. Else is easy. Allow me to quote from XYBASIC.DOC:
-------------------------------------
IF ... THEN ... ELSE: as in English (and BASIC)--e.g.:
        If name$ = "William" then print "Hello Bill"
        If sum > 999 then total = total + sum : _
           goto routine.to.add.comma
        If sum = 0 then stop else total = total + sum
Note: a common programming error is to forget the THEN, since we often leave it out in English. You absolutely must have a THEN for each IF. Multi-line versions need an ENDIF. (Don't use an ENDIF for single line versions (e.g., not in any of the 3 examples above.) Here is a multiline example:
        If s = 2 then
        y = 3
        z = 4
        endif
Warning: For multiline versions, such as the above, the "then" must end the first line.

You may use either: END IF, ENDIF, or EI--they are interchangeable
        if variable$ = "hello" then
            if next.var$ = "there" then gosub do.it
            else s = 4
            y = 5
        EI
(Nesting: You can nest IF/THEN's but you can't nest IF's with ELSEs: between an ELSE and the next IF must come ENDIF.)
-------------------------------
The examples all translate to straightforward code. E.g., let me take the last one above as an example. Well, I need to define some stuff referenced in this imaginary snippet so here's the source I used (between the lines below)
-----------------------------------------
sub do.it
 print "This is an empty subroutine for illustration purposes only"
return

; Note that comments are preceded by a semi, and that you can use extra
; carriage returns, tabs, and spaces with abandon. I designed a very forgiving syntax.

next.var$ = "foo"
variable$ = "bar"

if variable$ = "hello" then
            if next.var$ = "there" then gosub do.it
            else s = 4
            y = 5
        EI
---------------------------------------

XPLeNCODE v2.0
b-gin [UNTITLED]
{<}SU01,This is an empty subroutine for illustration purposes
 only[NO_]{>}{<}SV02,foo{>}{<}SV03,bar{>}{<}SV568,hello{>};*;
[cr|lf]{<}IF{<}IS03{>}=={<}IS568{>}{>}{<}SV568,there{>};*;[cr
|lf]{<}IF{<}IS02{>}=={<}IS568{>}{>}{<}GT01{>}{<}EI{>};*;[cr|l
f]{<}GL,A{>}{<}EI{>};*;[cr|lf]{<}SX04,4{>}{<}SX05,5{>}{<}LB,A
{>}{<}LB_{>}{<}SV50,555-598{>}[JM_]2.clearsgts[Q2_]{<}EX{>}[c
r|lf]
-nd
XPLeNCODE
The XyBasic translator puts in the ";*;" formatting you see there, and it also puts in (after the of course) a table of variables, subs, and labels. Here's the one it produced for the above:
  Variables & Subs            Labels
 01 = DO.IT
 02 = NEXT.VAR$
 03 = VARIABLE$
 04 = S
 05 = Y
568-585: temp. storage of literal (quoted) stuff for next  in pgm.
I haven't yet fixed XyBasic to take advantage of Xy4's acceptance of syntax like:
+"........">
--i.e., direct inclusion of literals in quotes, so there's the awkward use of the reserved 568-585 region, which is then CLSGTSed at the end.
 And
that's all first-floor basic(sic) stuff! Fuhgeddaboutit.
Uh-huh. Except that I've been using it for 15 1/2 years, in bliss. When I
need to, I can just drop pure XPL right into the source, just putting it
inside quotes.
I have most all the BASIC functions except ASC() and CHR$()--which I
couldn't figure out how to do. But I see from the U2 the obvious solution:
an inbuilt table. I already translated all apostrophe-codes ('tf 'wg, etc.)
by means of a table, so I don't know why I didn't think of that. But I
almost never have needed CHR$(), ASC(), nor even the LEFT$, RIGHT$, and
MID$ that I did put in.
I admit I'm not happy with the INPUT routine, which just inserts a clumsy
XPL subroutine I wrote, but there's an INKEY$ function for one-character
responses.

And I might mention a time-saver for entering commands:

COM "whatever"

produces BC whateverXC

and COMX "whatever" does the same with the BX/Q2 pair.
Hmmm. As an example, let me include the source of my latest venture: EXPAND.BAS and its translation into EXPAND.PGM. Note that I name variables using the period to separate words rather than the more modern underscore character.

user.cursor = curpos <===== CURPOS produces 
comx "es 1"
kiv$ = lft.g$ + "IV" <===== lft.g$ and rt.g$ are built-in constants for the guillemets
block.defined = 0
w.defined$ = ""
'xp 'xd
'tf comx "ci /ÿÀ? /ÿÀ?®IV¯ /" <===== contains the searchable cr/lf plus a tab if okay then 'tf comx "ci /ÿÀ? /ÿÀ?®IV¯ /" ; put in missing except for top level
max.hidden.tabs = 9
1tab$ = " " <===== the tab character is in there in the actual source
w.tabs$ = "     " ; 9 tabs
if va $de = 1 then block.defined = 1 : w.defined$ = "/s" ; search in block
; only way to check if completely expanded is by whether any tabs are unhidden before eof

if block.defined = 0 then 'tf else 'db
'wg comx "se / /"
if error or va $fe = 1 then prompt "Completely collapsed" : comx "jmp " user.cursor : exit
'xp

sub cut.one.tab
 parse w.tabs$, 1tab$, head$, d$, tail$
 w.tabs$ = tail$
return

find.max.hidden.tabs:   ; find largest number of hidden tabs, from 9 down
 if block.defined = 0 then 'tf else 'db
if w.tabs$ = "" then prompt "Completely collapsed!" : comx "jmp " user.cursor : exit
 comx "se /" kiv$ rt.g$ w.tabs$ "/" ; find string of tabs after cr.lf$
 if ok then goto out.find.max.hidden.tabs <==== "ok" produces if @NOT()
 gosub cut.one.tab
decr max.hidden.tabs <=== "decr" is decrement; one can specify steps, default is 1
 goto find.max.hidden.tabs
out.find.max.hidden.tabs:
if max.hidden.tabs = 0 then prompt "Completely... collapsed" : comx "jmp " user.cursor : exit
if block.defined = 0 then 'tf

main.loop:
 comx "se" w.defined$ " /" kiv$ rt.g$ w.tabs$ "/"
 if error then goto out.main.loop
 for i = 1 to max.hidden.tabs
  'cl
 next i
 'bd ;  rubout ">"
 comx "se /" kiv$ "/"
 if error then 'bf print rt.g$ : goto out.main.loop
 'cl 'cl 'cl print rt.g$
 goto main.loop
out.main.loop:
'wg
prompt "All done"
comx "jmp " user.cursor
exit
That produces this code, with the formatting included, and the non-encoded list at the end:

XPLeNCODE v2.0
b-gin [UNTITLED]
{<}SV568,{<}LB{>}{>}{<}SV569,LB{>}{<}XS568,569,595,570,596{>}
{<}SX01,{<}CP{>}{>}[BX_]es 1[Q2_]{<}SV568,IV{>}{<}SX02,{<}IS5
95{>}+{<}IS568{>}{>}{<}SX03,0{>}{<}SV04,{>}[XP_][XD_][TF_][BX
_]ci /[wC]{tab}/[wC]{<}IV{>}{tab}/[Q2_];*;[cr|lf]{<}IF@NOT({<
}ER{>})AY{>}[TF_][BX_]ci /[wC]{tab}/[wC]{<}IV{>}{tab}/[Q2_]{<
}EI{>};*;[cr|lf]{<}SX05,9{>}{<}SV06,{tab}{>}{<}SV07,{tab}{tab
}{tab}{tab}{tab}{tab}{tab}{tab}{tab}{>};*;[cr|lf]{<}IF{<}VA$D
E{>}==1{>}{<}SX03,1{>}W.DEF{238}ED{<}EI{>};*;[cr|lf]{<}SV08,/
s{>};*;[cr|lf]{<}IF{<}PV03{>}==0{>}[TF_]{<}GL,A{>}{<}EI{>};*;
[cr|lf][DB_]{<}LB,A{>}[WG_][BX_]se /{tab}/[Q2_];*;[cr|lf]{<}I
F{<}ER{>}!{<}VA$FE{>}==1{>}{<}PRCompletely collapsed{>}[BX_]j
mp {<}PV01{>}[Q2_]{<}EX{>}{<}EI{>};*;[cr|lf][XP_]{<}SU09,{<}X
S07,06,10,11,12{>}{<}SX07,{<}IS12{>}{>}[NO_]{>};*;[cr|lf]{<}L
BA{>};*; FIND.MAX.HIDDEN.TABS [cr|lf];*;[cr|lf]{<}IF{<}PV03{>
}==0{>}[TF_]{<}GL,B{>}{<}EI{>};*;[cr|lf][DB_]{<}LB,B{>}{<}SV5
68,{>};*;[cr|lf]{<}IF{<}IS07{>}=={<}IS568{>}{>}{<}PRCompletel
y collapsed!{>}[BX_]jmp {<}PV01{>}[Q2_]{<}EX{>}{<}EI{>};*;[cr
|lf][BX_]se /{<}PV02{>}{<}PV596{>}{<}PV07{>}/[Q2_];*;[cr|lf]{
<}IF@NOT({<}ER{>}){>}{<}GLB{>}{<}EI{>};*;[cr|lf]{<}GT09{>}{<}
SX05,{<}PV05{>}-1{>}{<}GLA{>};*;[cr|lf]{<}LBB{>};*; OUT.FIND.
MAX.HIDDEN.TABS [cr|lf];*;[cr|lf]{<}IF{<}PV05{>}==0{>}{<}PRCo
mpletely... collapsed{>}[BX_]jmp {<}PV01{>}[Q2_]{<}EX{>}{<}EI
{>};*;[cr|lf];*;[cr|lf]{<}IF{<}PV03{>}==0{>}[TF_]{<}EI{>};*;[
cr|lf];*;[cr|lf]{<}LBC{>};*; MAIN.LOOP [cr|lf][BX_]se{<}PV04{
>} /{<}PV02{>}{<}PV596{>}{<}PV07{>}/[Q2_];*;[cr|lf]{<}IF{<}ER
{>}{>}{<}GLD{>}{<}EI{>};*;[cr|lf]{<}SX13,1{>}{<}LB-A{>};*;[cr
|lf]{<}IF{<}PV13{>}>{<}PV05{>}{>}{<}
GL-B{>}{<}EI{>};*;[cr|lf][CL_]{<}SX13,{<}PV13{>}+1{>}{<}GL-A{
>}{<}LB-B{>}[BD_][BX_]se /{<}PV02{>}/[Q2_];*;[cr|lf]{<}IF{<}E
R{>}{>}[BF_]{<}PV596{>}{<}GLD{>}{<}EI{>};*;[cr|lf][CL_][CL_][
CL_]{<}PV596{>}{<}GLC{>};*;[cr|lf]{<}LBD{>};*; OUT.MAIN.LOOP{032}
[cr|lf][WG_]{<}PRAll done{>}[BX_]jmp {<}PV01{>}[Q2_]{<}EX{>}{
<}LB_{>}{<}SV50,555-598{>}[JM_]2.clearsgts[Q2_]{<}EX{>}[cr|lf
]
-nd
XPLeNCODE
Variables & Subs Labels <=== horiz. alignment is nice viewed in Xy
 01 = USER.CURSOR           lbA =  FIND.MAX.HIDDEN.TABS
 02 = KIV$               lbB =  OUT.FIND.MAX.HIDDEN.TABS
 03 = BLOCK.DEFINED          lbC =  MAIN.LOOP
 04 = W.DEFINED$            lbD =  OUT.MAIN.LOOP
 05 = MAX.HIDDEN.TABS
 06 = 1TAB$
 07 = W.TABS$
 08 = $
 09 = CUT.ONE.TAB
 10 = HEAD$
 11 = D$
 12 = TAIL$
 13 = I
 595 = ÿAE <====== left guillemet
 596 = ÿAF <====== right guillemet
568-585: temp. storage of literal (quoted) stuff for next  in pgm.
Two caveats: 1. I don't claim to be an elegant programmer. 2. The resultant program doesn't fully work--in particular, the option to collapse only within a DeFined block doesn't work.


Harry Binswanger
hb@xxxxxxxx