Table of Contents
This document describes yabasic. You will find information about the yabasic interpreter (the program yabasic under Unix or yabasic.exe under Windows) as well as the language (which is, of course, a sort of basic) itself.
This document applies to version 2.760 of yabasic
However, this document does not contain the latest news about yabasic or a FAQ. As such information tends to change rapidly, it is presented online only at www.yabasic.de.
Although basic has its reputation as a language for beginning programmers, this is not an introduction to programming at large. Rather this text assumes, that the reader has some (moderate) experience with writing and starting computer programs.
yabasic is a traditional basic interpreter. It understands most of the typical basic-constructs, like goto, gosub, line numbers, read, data or string-variables with a trailing '$'. But on the other hand, yabasic implements some more advanced programming-constructs like subroutines or libraries (but not objects). yabasic works much the same under Unix and Windows.
yabasic puts emphasis on giving results quickly and easily; therefore simple commands are provided to open a graphic window, print the graphics or control the console screen and get keyboard or mouse information. The example below opens a window, draws a circle and prints the graphic:
open window 100,100 open printer circle 50,50,40 text 10,50,"Press any key to get a printout" clear screen inkey$ close printer close window
This example has fewer lines, than it would have in many other programming languages. In the end however yabasic lacks behind more advanced and modern programming languages like C++ or Java. But as far as it goes it tends to give you results more quickly and easily.
Once, yabasic has been set up correctly, there are three ways to start it:
Rightclick on your desktop: The desktop menu appears with a submenu named new. From this submenu choose yabasic. This will create a new icon on your desktop. If you rightclick on this icon, its context menu will appear; choose Execute to execute the program.
As a variant of the way described above, you may simply create a file with the ending .yab (e.g. with your favorite editor). Everything else then works as described above.
From the start-menu: Choose yabasic from your start-menu. A console-window will open and you will be asked to type in your program. Once you are finished, you need to type return twice, and yabasic will parse and execute your program.
This is not the preferred way of starting yabasic ! Simply because the program, that you have typed, can not be saved and will be lost inevitably ! There is no such thing as a save-command and therefore no way to conserve the program, that you have typed. This mode is only intended for quick hacks, and short programs.
Under Windows yabasic will mostly be invoked by double-clicking on an appropriate icon; this way you do not have a chance to specify any of the commandline options below. However, advanced users may add some of those options to the appropriate entries in the registry.
All the options below may be abbreviated, as long as the abbreviation does not become ambiguous. For example, you may write -e instead of -execute.
-help or -?Prints a short help message, which itself describes two further help-options.
-versionPrints the version of yabasic.
-geometry +X-POSITION+Y-POSITIONSets the position of the graphic window, that is opened by open window (the size of this window, of course, is specified within the open window-command). An example would be -geometry +20+10, which would place the graphic window 10 pixels below the upper border and 20 pixels right of the left border of the screen. This value cannot be changed, once yabasic has been started.
-font NAME-OF-FONTName of the font, which will be used for graphic-text; can be any of decorative, dontcare, modern, roman, script, swiss. You may append a fontsize (measured in pixels) to any of those fontnames; for example -font swiss30 chooses a swiss-type font with a size of 30 pixels.
-bind NAME-OF-STANDALONE-PROGRAMCreate a standalone program (whose name is specified by NAME-OF-STANDALONE-PROGRAM) from the yabasic-program, that is specified on the commandline. See the section about creating a standalone-program for details.
-execute A-PROGRAM-AS-A-SINGLE-STRINGWith this option you may specify some yabasic-code to be executed rigth away.This is useful for very short programs, which you do not want to save within a file. If this option is given, yabasic will not read any code from a file. Let's say, you have forgotten some of the square numbers between 1 and 10; in this case the command yabasic -e 'for a=1 to 10:print a*a:next a' will give you the answer immediately.
-infolevel INFOLEVELChange the infolevel of yabasic, where INFOLEVEL can be one of debug, note, warning, error and fatal (the default is warning). This option changes the amount of debugging-information yabasic produces. However, normally only the author of yabasic (me !) would want to change this.
-doc NAME-OF-A-PROGRAMPrint the embedded documentation of the named program. The embedded documentation of a program consists of all the comments within the program, which start with the special keyword doc. This documentation can also be seen by choosing the corresponding entry from the context-menu of any yabasic-program.
-librarypath DIRECTORY-WITH-LIBRARIESChange the directory, wherein libraries will be searched and imported (with the import-command). See also this entry for more information about the way, libraries are searched.
Like every other icon under Windows, the icon of every yabasic-program has a context menu offering the most frequent operations, that may be applied to a yabasic-program.
This will invoke yabasic to execute your program. The same happens, if you doubleclick on the icon.
notepad will be invoked, allowing you to edit your program.
This will present the embedded documentation of your program. Embedded documentation is created with the special comment doc.
If your system administrator (vulgo root) has installed yabasic correctly, there are three ways to start it:
You may use your favorite editor (emacs, vi ?) to put your program into a file (e.g. foo). Make sure that the very first line starts with the characters '#!' followed by the full pathname of yabasic (e.g. '#!/usr/local/bin/yabasic'). This she-bang-line ensures, that your Unix will invoke yabasic to execute your program (see also the entry for the hash-character). Moreover, you will need to change the permissions of your yabasic-program foo, e.g. chmod u+x foo. After that you may invoke yabasic to invoke your program by simply typing foo (without even mentioning yabasic). However, if your PATH-variable does not contain a single dot ('.') you will have to type the full pathname of your program: e.g. /home/ihm/foo (or at least ./foo).
Save your program into a file (e.g. foo) and type yabasic foo. This assumes, that the directory, where yabasic resides, is contained within your PATH-variable.
Finally your may simply type yabasic (maybe it will be necessary to include its full pathname). This will make yabasic come up and you will be asked to type in your program. Once you are finished, you need to type return twice, and yabasic will parse and execute your program.
This is not the preferred way of starting yabasic ! Simply because the program, that you have typed, can not be saved and will be lost inevitably ! There is no such thing as a save-command and therefore no way to conserve the program, that you have typed. This mode is only intended for quick hacks, and short programs, i.e. for using yabasic as some sort of fancy desktop calculator.
yabasic accepts a number of options on the commandline. All these options below may be abbreviated, as long as the abbreviation does not become ambigous. For example you may write -e instead of -execute.
-help or -?Prints a short help message, which itself describes two further help-options.
-versionPrints the version of yabasic.
-fg FOREGROUND-COLOR or -foreground FOREGROUND-COLORDefine the foreground color for the graphics-window (that will be opened with open window). The usual X11 colornames, like red, green, … are accepted. This value cannot be changed, once yabasic has been started.
-bg BACKGROUND-COLOR or -background BACKGROUND-COLORDefine the background color for the graphics-window. The usual X11 colornames are accepted. This value cannot be changed, once yabasic has been started.
-geometry +X-POSITION+Y-POSITIONSets the position of the graphic window, that is opened by open window (the size of this window, of course, is specified with the open window-command). An example would be +20+10, which would place the graphic window 10 pixels below the upper border and 20 pixels right of the left border of the screen. Note, that the size of the window may not be specified here (well it may, but it will be ignored anyway). This value cannot be changed, once yabasic has been started.
-display BACKGROUND-COLORSpecify the display, where the graphics window of yabasic should appear. Normally, however this value will be already present within the environment variable DISPLAY.
-font NAME-OF-FONTName of the font, which will be used for text within the graphics window.
-execute A-PROGRAM-AS-A-SINGLE-STRINGWith this option you may specify some yabasic-code to be executed rigth away.This is useful for very short programs, which you do not want to save to a file. If this option is given, yabasic will not read any code from a file. E.g.
yabasic -e 'for a=1 to 10:print a*a:next a'
prints the square numbers from 1 to 10.
-bind NAME-OF-STANDALONE-PROGRAMCreate a standalone program (whose name is specified by NAME-OF-STANDALONE-PROGRAM) from the yabasic-program, that is specified on the commandline. See the section about creating a standalone-program for details.
-infolevel INFOLEVELChange the infolevel of yabasic where INFOLEVEL can be one of debug, note, warning, error and fatal (the default is warning). This option changes the amount of debugging-information yabasic produces. However, normally only the author of yabasic (me !) would want to change this.
-doc NAME-OF-A-PROGRAMPrint the embedded documentation of the named program. The embedded documentation of a program consists of all the comments within the program, which start with the special keyword doc.
-librarypath DIRECTORY-WITH-LIBRARIESChange the directory from which libraries will be imported (with the import-command). See also this entry for more information about the way, libraries will be searched.
If you want to set some options once for all, you may put them into your X-Windows resource file. This is usually the file .Xresources or some such within your home directory (type man X for details).
Here is a sample section, which may appear within this file:
yabasic*foreground: blue yabasic*background: gold yabasic*geometry: +10+10 yabasic*font: 9x15
This will set the foreground color of the graphic-window to blue and the background color to gold. The window will appear at position 10,10 and the text font will be 9x15.
This chapter has sections for some of the major features of yabasic and names a few commands related with each area. So, depending on your interest, you find the most important commands of this area named; the other commands from this area may then be discovered through the links in the see also-section.
The print-command is used to put text on the text screen. Here, the term text screen stands for your terminal (under Unix) or the console window (under Windows).
At the bottom line, print simply outputs its argument to the text window. However, once you have called clear screen you may use advanced features like printing colors or copying areas of text with getscreen$ or putscreen.
You may ask the user for input with the input-command; use inkey$ to get each key as soon as it is pressed.
Of course, yabasic has the goto- and gosub-statements; you may go to a label or a line number (which is just a special kind of label). goto, despite its bad reputation ([goto considered harmful]), has still its good uses; however in many cases you are probably better off with loops like repeat-until, while-wend or do-loop; you may leave any of these loops with the break-statement or start the next iteration immediately with continue.
Decisions can be made with the if-statement, which comes either in a short and a long form. The short form has no then-keyword and extends up to the end of the line. The long form extends up to the final endif and may use some of the keywords then (which introduces the long form), else or elsif.
If you want to test the result of an expression against many different values, you should probably use the switch-statement.
You need to call open window before you may draw anything with either line, circle, rectangle or triangle; all of these statements may be decorated with clear or fill. If you want to change the colour for drawing, use colour. Note however, that there can only be a single window open at any given moment in time.
Everything you have drawn can be send to your printer too, if you use the open printer command.
To allow for some (very) limited version of animated graphics, yabasic offers the commands getbit$ and putbit, which retrieve rectangular regions from the graphics-window into a string or vice versa.
If you want to sense mouse-clicks, you may use the inkey$-function.
Before you may read or write a file, you need to open it; once you are done, you should close it. Each open file is designated by a simple number, which might be stored within a variable and must be supplied if you want to access the file. This is simply done by putting a hash ('#') followed by the number of the file after the keyword input (for reading from) or print (for writing to a file) respectively.
If you need more control, you may consider reading and writing one byte at a time, using the multi-purpose commands peek and poke.
The best way to break any yabasic-program into smaller, more manageable chunks are subroutines and libraries. They are yabasic's most advanced means of structuring a program.
Subroutines are created with the command sub. they accept parameters and may return a value. Subroutines can be called much like any builtin function of yabasic; therefore they allow to extend the language itself.
Once you have created a set of related subroutines and you feel that they could be useful in other programs too, you may collect them into a library. Such a library is contained within a separate file and may be included in any of your programs, using the keyword import.
yabasic has the usual functions to extract parts from a string: left$, mid$ and right$. Note, that all of them can be assigned to, i.e. they may change part of a string.
If you want to split a string into tokens you should use the functions token or split.
There is quite a bunch of other string-processing functions like upper$ (converting to upper case), instr (finding one string within the other), chr$ (converting an ascii-code into a character), glob (testing a string against a pattern) and more. Just follow the links.
Yabasic handles numbers and arithmetic: You may calculate trigonometric functions like sin or atan, or logarithms (with log). Bitwise operations, like and or or are available as well min or max (calculate the minimum or maximum of its argument) or mod or int (reminder of a division or integer part or a number).
You may store data within your program within data-statements; during execution you will probably want to read it into arrays, which must have been dimed before.
and2.718281828643.14159switch-statement
for-, do-, repeat- or while-loop
switch-statement
do-loopif-statement
if-statement
if-statement
endiffor-loop
goto, gosub or restore!gosub-targets
goto-targets
repeat-loop
if-statement
repeat-loop
while-loop
while-loop
data-statements
dimdata-pointer
print-command to place the output at a specified position
bellbeep)
print colorclear screen clears the text window
atprint-statement
rectanglecircles, rectangles or triangless
line-command
circles, rectangles or triangles
inkey$line-command
abs() — returns the absolute value of its numeric argument
y=abs(x)
acos() — returns the arcus cosine of its numeric argument
x=acos(angle)
acos is the arcus cosine-function, i.e. the inverse of the cos-function. Or, more elaborate: It Returns the angle (in radian, not degree !), which, fed to the cosine-function will produce the argument passed to the acos-function.
and — logical and, used in conditions
if (a and b) … while (a and b) …
Used in conditions (e.g within if, while or until) to join two expressions. Returns true, if and only if its left and right argument are both true and false otherwise.
Note, that logical shortcuts may take place.
and() — the bitwise arithmetic and
x=and(a,b)
Used to compute the bitwise and of both its argument. Both arguments are treated as binary numbers (i.e. a series of 0 and 1); a bit of the resulting value will then be 1, if both arguments have a 1 at this position in their binary representation.
Note, that both arguments are silently converted to integer values and that negative numbers have their own binary representation and may lead to unexpected results when passed to and.
arraydim() — returns the dimension of the array, which is passed as an array reference
a=arraydim(b())
If you apply the arraydim()-function on a one-dimensional array (i.e. a vector) it will return 1, on a two-dimensional array (i.e. a matrix) it will return 2, and so on.
This is mostly used within subroutines, which expect an array among their parameters. Such subroutines tend to use the arraydim-function to check, if the array which has been passed, has the right dimension. E.g. a subroutine to multiply two matrices may want to check, if it really is invoked with two 2-dimensional arrays.
dim a(10,10),b(10)
print arraydim(a()),arraydim(b())
This will print 2 1, which are the dimension of the arrays a() and b(). You may check out the function arraysize for a full-fledged example.
arraysize() — returns the size of a dimension of an array
x=arraysize(a(),b)
The arraysize-function computes the size of a specified dimension of a specified array. Here, size stands for the maximum number, that may be used as an index for this array. The first argument to this function must be an reference to an array, the second one specifies, which of the multiple dimensions of the array should be taken to calculate the size.
An Example involving subroutines: Let's say, an array has been declared as dim a(10,20) (that is a two-dimensional array or a matrix). If this array is passed as an array reference to a subroutine, this sub will not know, what sort of array has been passed. With the arraydim-function the sub will be able to find the dimension of the array, with the arraysize-function it will be able to find out the size of this array in its two dimensions, which will be 10 and 20 respectively.
Our sample array is two dimensional; if you envision it as a matrix this matrix has 10 lines and 20 columns (see the dim-statement above. To state it more formally: The first dimension (lines) has a size of 10, the second dimension (columns) has a size of 20; these numbers are those returned by arraysize(a(),1) and arraysize(a(),2) respectively. Refer to the example below for a typical usage.
rem
rem This program adds two matrices elementwise.
rem
dim a(10,20),b(10,20),c(10,20)
rem initialization of the arrays a() and b()
for y=1 to 10:for x=1 to 20
a(y,x)=int(ran(4)):b(y,x)=int(ran(4))
next x:next y
matadd(a(),b(),c())
print "Result:"
for x=1 to 20
for y=10 to 1 step -1
print c(y,x)," ";
next y
print
next x
sub matadd(m1(),m2(),r())
rem This sub will add the matrices m1() and m2()
rem elementwise and store the result within r()
rem This is not very useful but easy to implement.
rem However, this sub excels in checking its arguments
rem with arraydim() and arraysize()
local x:local y
if (arraydim(m1())<>2 or arraydim(m2())<>2 or arraydim(r())<>2) then
error "Need two dimensional arrays as input"
endif
y=arraysize(m1(),1):x=arraysize(m1(),2)
if (arraysize(m2(),1)<>y or arraysize(m2(),2)<>x) then
error "The two matrices cannot be added elementwise"
endif
if (arraysize(r(),1)<>y or arraysize(r(),2)<>x) then
error "The result cannot be stored in the third argument"
endif
local xx:local yy
for xx=1 to x
for yy=1 to y
r(yy,xx)=m1(yy,xx)+m2(yy,xx)
next yy
next xx
end sub
asc() — accepts a string and returns the position of its first character within the ascii charset
a=asc(char$)
The asc-function accepts a string, takes its first character and looks it up within the ascii-charset; this position will be returned. The asc-function is the opposite of the chr$-function. There are valid uses for asc, however, comparing strings (i.e. to bring them into alphabetical sequence) is not among them; in such many cases you might consider to compare strings directly with <, = and > (rather than converting a string to a number and comparing this number).
asin() — returns the arcus sine of its numeric argument
angle=asin(x)
acos is the arcus sine-function, i.e. the inverse of the sin-function. Or, more elaborate: It Returns the angle (in radian, not degree !), which, fed to the sine-function will produce the argument passed to the asin-function.
at() — can be used in the print-command to place the output at a specified position
clear screen … print at(a,b) print @(a,b)
The at-clause takes two numeric arguments (e.g. at(2,3)) and can be inserted after the print-keyword. at() can be used only if clear screen has been executed at least once within the program (otherwise you will get an error).
The two numeric arguments of the at-function may range from 0 to the width of your terminal minus 1, and from 0 to the height of your terminal minus 1; if any argument exceeds these values, it will be truncated accordingly. However, yabasic has no influence on the size of your terminal (80x25 is a common, but not mandatory), the size of your terminal and the maximum values acceptable within the at-clause may vary. To get the size of your terminal you may use the peek-function: peek("screenwidth") returns the width of your terminal and peek("screenheight") its height.
atan() — returns the arctangent of its numeric argument
angle=atan(a,b) angle=atan(a)
atan is the arctangent-function, i.e. the inverse of the tan-function. Or, more elaborate: It Returns the angle (in radian, not degree !), which, fed to the tan-function will produce the argument passed to the atan-function.
The atan-function has a second form, which accepts two arguments: atan(a,b) which is (mostly) equivalent to atan(a/b) except for the fact, that the two-argument-form returns an angle in the range -π to π, whereas the one-argument-form returns an angle in the range -π/2 to π/2. To understand this you have to be good at math.
color — change color for background of graphic window
backcolour red,green,blue backcolour "red,green,blue"
Change the color, that becomes visible, if any portion of the window is erased, e.g. after clear window or clear line. Note however, that parts of the window, that display the old background color will not change.
As with the color-command, the new background color can either be specified as a triple of three numbers or as a single string, that contains those three numbers sperated by commas.
beep — ring the bell within your computer; a synonym for bell
beep
The bell-command rings the bell within your computer once. This command is not a sound-interface, so you can neither vary the length or the height of the sound (technically, it just prints \a). bell is exactly the same as beep.
bin$() — converts a number into a sequence of binary digits
hexadecimal$=bin$(decimal)
The bin$-function takes a single numeric argument an converts it into a string of binary digits (i.e. zeroes and ones). If you pass a negative number to bin$, the resulting string will be preceded by a '-'.
If you want to convert the other way around (i.e. from binary to decimal) you may use the dec-function.
bind() — Binds a yabasic-program and the yabasic-interpreter together into a standalone program.
bind("foo.exe")The bind-command combines your own yabasic-program (plus all the libraries it does import) and the interpreter by copying them into a new file, whose name is passed as an argument. This new program may then be executed on any computer, even if it does not have yabasic installed.
Please see the section about creating a standalone-program for details.
if (!peek("isbound")) then
bind "foo"
print "Successfully created the standalone executable 'foo' !"
exit
endif
print "Hello World !"
This example creates a standalone program foo from itself.
The section about creating a standalone-program, the peek-function and the commandline options for Unix and Windows.
break — breaks out of a switch statement or a loop
break
break transfers control immediately outside the enclosing loop or switch statement. This is the preferred way of leaving a such a statement (rather than goto, which is still possible in most cases).
for a=1 to 10
break
print "Hi"
next a
while(1)
break
print "Hi"
wend
repeat
break
print "Hi"
until(0)
switch 1
case 1:break
case 2:case 3:print "Hi"
end switch
This example prints nothing at all, because each of the loops (and the switch-statement) does an immediate break (before it could print any "Hi").
case — mark the different cases within a switch-statement
switch a case 1 case 2 … end switch … switch a$ case "a" case "b" … end switch
chr$() — accepts a number and returns the character at this position within the ascii charset
character$=chr$(ascii)
The chr$-function is the opposite of the asc-function. It looks up and returns the character at the given position within the ascii-charset. It's typical use is to construct nonprintable characters which do not occur on your keyboard.
Nevertheless you won't use chr$ as often as you might think, because the most important nonprintable characters can be constructed using escape-sequences using the \-character (e.g. you might use \n instead of chr$(10) wherever you want to use the newline-character).
circle — draws a circle in the graphic-window
circle x,y,r clear circle x,y,r fill circle x,y,r clear fill circle x,y,r
The circle-command accepts three parameters: The x- and y-coordinates of the center and the radius of the circle.
Some more observations related with the circle-command:
The graphic-window must have been opened already.
The circle may well extend over the boundaries of the window.
If you have issued open printer before, the circle
will finally appear in the printed hard copy of the window.
fill circle will draw a filled (with black ink) circle.
clear circle will erase (or clear) the outline of the circle.
clear fill circle or fill clear circle will erase the full area of the circle.
open window 200,200
for n=1 to 2000
x=ran(200)
y=ran(200)
fill circle x,y,10
clear fill circle x,y,8
next n
This code will open a window and draw 2000 overlapping circles within. Each circle is drawn in two steps: First it is filled with black ink (fill circle x,y,10), then most of this circle is erased again (clear fill circle x,y,8). As a result each circle is drawn with an opaque white interior and a 2-pixel outline (2-pixel, because the radii differ by two).
clear — Erase circles, rectangles or triangles
clear rectangle 10,10,90,90 clear fill circle 50,50,20 clear triangle 10,10,20,20,50,30
May be used within the circle, rectangle or triangle command and causes these shapes to be erased (i.e. be drawn in the colour of the background).
fill can be used in conjunction with and wherever the fill-clause may appear. Used alone, clear will erase the outline (not the interior) of the shape (circle, rectangle or triangle); together with fill the whole shape (including its interior) is erased.
clear screen — erases the text window
clear screen
clear screen erases the text window (the window where the output of print appears).
It must be issued at least once, before some advanced screen-commands (e.g. print at or inkey$) may be called; this requirement is due to some limitations of the curses-library, which is used by yabasic under Unix for some commands.
clear window — clear the graphic window and begin a new page, if printing is under way
clear window
clear window clears the graphic window. If you have started printing the graphic via open printer, the clear window-command starts a new page as well.
open window 200,200
open printer "t.ps"
for a=1 to 10
if (a>1) clear window
text 100,100,"Hallo "+str$(a)
next a
close printer
close window
This example prints 10 pages, with the text "Hello 1", "Hello 2", … and so on. The clear screen-command clears the graphics window and starts a new page.
close — close a file, which has been opened before
close filenum close # filenum
The close-command closes an open file. You should issue this command as soon as you are done with reading from or writing to a file.
close curve — close a curve, that has been drawn by the line-command
new curve line to x1,y1 … close curve
The close curve-command closes a sequence of lines, that has been drawn by repeated line to-commands.
close printer — stops printing of graphics
close printer
The close printer-command ends the printing graphics. Between open printer and close printer everything you draw (e.g. circles, lines …) is sent to your printer. close printer puts an end to printing and will make your printer eject the page.
close window — close the graphics-window
close window
The close window-command closes the graphics-window, i.e. it makes it disappear from your screen. It includes an implicit close printer, if a printer has been opened previously.
color — change color for any subsequent drawing-command
colour red,green,blue colour "red,green,blue"
Change the color, in which lines, dots, circles, rectangles or triangles are drawn. The color-command accepts three numbers in the range 0 … 255 (as in the first line of the synopsis above). Those numbers specify the intensity for the primary colors red, green and blue respectively. As an example 255,0,0 is red and 255,255,0 is yellow.
Alternatively you may specify the color with a single string (as in the second line of the synopsis above); this string should contain three numbers, separated by commas. As an example "255,0,255" would be violet. Using this variant of the colour-command, you may use symbolic names for colours:
open window 100,100 yellow$="255,255,0" color yellow$ text 50,50,"Hallo"
, which reads much clearer.
open window 255,255
for x=10 to 235 step 10:for y=10 to 235 step 10
colour x,y,0
fill rectangle x,y,x+10,y+10
next y:next x
This fills the window with colored rectangles. However, none of the used colours contains any shade of blue, because the color-command has always 0 as a third argument.
compile — compile a string with yabasic-code on the fly
compile(code$)
This is an advanced command (closely related with the execute-command). It allows you to compile a string of yabasic-code (which is the only argument). Afterwards the compiled code is a normal part of your program.
Note, that there is no way to remove the compiled code.
continue — start the next iteration of a for-, do-, repeat- or while-loop
continue
You may use continue within any loop to start the next iteration immediately. Depending on the type of the loop, the loop-condition will or will not be checked. Especially: for- and while-loops will evaluate their respective conditions, do- and repeat-loops will not.
Remark: Another way to change the flow of execution within a loop, is the break-command.
data — introduces a list of data-items
data 9,"world" … read b,a$
The data-keyword introduces a list of comma-separated list of strings or numbers, which may be retrieved with the read-command.
The data-command itself does nothing; it just stores data. A single data-command may precede an arbitrarily long list of values, in which strings or numbers may be mixed at will.
yabasic internally uses a data-pointer to keep track of the current location within the data-list; this pointer may be reset with the restore-command.
do
restore
for a=1 to 4
read num$,num
print num$,"=",num
next a
loop
data "eleven",11,"twelve",12,"thirteen",13,"fourteen",14
This example just prints a series of lines eleven=11 up to fourteen=14 and so on without end.
The restore-command ensures that the list of data-items is read from the start with every iteration.
date$ — returns a string with various components of the current date
a$=date$
The date$-function (which must be called without parentheses; i.e. date$() would be an error) returns a string containing various components of a date; an example would be 4-05-27-2004-Thu-May. This string consists of various fields separated by hyphens ("-"):
The day within the week as a number in the range 0 (=Sunday) to 6 (=Saturday) (in the example above: 4, i.e. thursday).
The month as a number in the range 1 (=January) to 12 (=December) (in the example: 5 which stands for May).
The day within the month as a number in the range 1 to 31 (in the example: 27).
The full, 4-digit year (in the example: 2004, which reminds me that I should adjust the clock within my computer …).
The abbreviated name of the day within the week (Mon to Sun).
The abbreviated name of the month (Jan to Dec).
Therefore the whole example above (4-05-27-2004-Thu-May) would read: day 4 in the week (counting from 0), May 27 in the year 2004, which is a Thursday in May.
Note, that all fields within the string returned by date$ have a fixed with (numbers are padded with zeroes); therefore it is easy to extract the various fields of a date format with mid$.
rem Two ways to print the same ...
print mid$(date$,3,10)
dim fields$(6)
a=split(date$,fields$(),"-")
print fields$(2),"-",fields$(3),"-",fields$(4)
This example shows two different techniques to extract components from the value returned by date$. The mid$-function is the preferred way, but you could just as well split the return-value of date$ at every "-" and store the result within an array of strings.
dec() — convert a base 2 or base 16 number into decimal form
a=dec(number$) a=dec(number$,base)
default — mark the default-branch within a switch-statement
switch a+3 case 1 … case 2 … default … end switch
The default-clause is an optional part of the switch-statement (see there for more information). It introduces a series of statements, that should be executed, if none of the cases matches, that have been specified before (each with its own case-clause).
So default specifies a default to be executed, if none of the explicitly named cases matches; hence its name.
print "Please enter a number between 0 and 6,"
print "specifying a day in the week."
input d
switch d
case 0:print "Monday":break
case 1:print "Tuesday":break
case 2:print "Wednesday":break
case 3:print "Thursday":break
case 4:print "Friday":break
case 5:print "Saturday":break
case 6:print "Sunday":break
default:print "Hey you entered something invalid !"
end switch
This program translates a number between 0 and 6 into the name of a weekday; the default-case is used to detect (and complain about) invalid input.
dim — create an array prior to its first use
dim array(x,y) dim array$(x,y)
The dim-command prepares one or more arrays (of either strings or numbers) for later use. This command can also be used to enlarges an existing array.
When an array is created with the dim-statement, memory is allocated and all elements are initialized with either 0 (for numerical arrays) or "" (for string arrays).
If the array already existed, and the dim-statement specifies a larger size than the current size, the array is enlarged and any old content is preserved.
Note, that dim cannot be used to shrink an array: If you specify a size, that is smaller than the current size, the dim-command does nothing.
Finally: To create an array, that is only known within a single subroutine, you should use the command local, which creates local variables as well as local arrays.
dim a(5,5)
for x=1 to 5:for y=1 to 5
a(x,y)=int(ran(100))
next y:next x
printmatrix(a())
dim a(7,7)
printmatrix(a())
sub printmatrix(ar())
local x,y,p,q
x=arraysize(ar(),1)
y=arraysize(ar(),2)
for q=1 to y
for p=1 to y
print ar(p,q),"\t";
next p
print
next q
end sub
This example creates a 2-dimenional array (i.e. a matrix) with the dim-statement and fills it with random numbers. The second dim-statement enlarges the array, all new elements are filled with 0.
The subroutine printmatrix just does, what its name says.
do — start a (conditionless) do-loop
do … loop
Starts a loop, which is terminated by loop; everything between do and loop will be repeated forever. This loop has no condition, so it is an infinite loop; note however, that a break- or goto-statement might be used to leave this loop anytime.
doc — special comment, which might be retrieved by the program itself
doc This is a comment docu This is another comment
Introduces a comment, which spans up to the end of the line. But other than the rem-comment, any docu-comment is collected within the special docu$-array and might be retrieved later on. Moreover you might invoke yabasic -docu foo.yab on the commandline to retrieve the embedded documentation within the program foo.yab.
Instead of doc you may just as well write docu or even documentation.
rem Hi, this has been written by me
rem
doc This program asks for a number and
doc prints this number multiplied with 2
rem
rem Print out rhe above message
for a=1 to arraysize(docu$()):print docu$(a):next a
rem Read and print the number
input "Please input a number: " x
print x*2
This program uses the comments within its code to print out a help message for the user.
The contents of the doc-lines are retrieved from the docu$-array; if you do not want a comment to be collected within this array, use the rem-statement instead.
docu$ — special array, containing the contents of all docu-statement within the program
a$=docu$(1)
Before your program is executed, yabasic collects the content of all the doc-statements within your program within this 1-dimensional array (well only those within the main-program, libraries are skipped).
You may use the arraysize function to find out, how many lines it contains.
docu
docu This program reads two numbers
docu and adds them.
docu
rem retrieve and print the embedded documentation
for a=1 to arraysize(docu$(),1)
print docu$(a)
next a
input "First number: " b
input "Second number: " c
print "The sum of ",b," and ",c," is ",b+c
This program uses the embedded documentation to issue a usage-message.
dot — draw a dot in the graphic-window
dot x,y clear dot x,y
Draws a dot at the specified coordinates within your graphic-window. If printing is in effect, the dot appears on your printout too.
Use the functions peek("winheight") or peek("winwidth") to get the size of your window and hence the boundaries of the coordinates specified for the dot-command.
else — mark an alternative within an if-statement
if (…) then … else … endif
The else-statement introduces the alternate branch of an if-statement. I.e. it starts the sequence of statements, which is executed, if the condition of the if-statement is not true.
elsif — starts an alternate condition within an if-statement
if (…) then … elseif (…) … elsif (…) then … else … endif
The elsif-statement is used to select a single alternative among a series of choices.
With each elsif-statement you may specify a condition, which is tested, if the main condition (specified with the if-statement) has failed. Note that elsif might be just as well written as elseif.
Within the example below, two variables a and b are tested against a range of values. The variable a is tested with the elsif-statement. The very same tests are performed for the variable b too; but here an involved series of if-else-statements is employed, making the tests much more obscure.
input "Please enter a number: " a
if (a<0) then
print "less than 0"
elseif (a<=10) then
print "between 0 and 10"
elsif (a<=20)
print "between 11 and 20"
else
print "over 20"
endif
input "Please enter another number: " b
if (b<0) then
print "less than 0"
else
if (b<=10) then
print "between 0 and 10"
else
if (b<=20) then
print "between 11 and 20"
else
print "over 20"
endif
endif
endif
Note, that the very same tests are performed for the variables a and b, but can be stated much more clearly with the elsif-statement.
Note, that elsif might be written as elseif too, and that the keyword then is optional.
end — terminate your program
end
Terminate your program. Much (but not exactly) like the exit command.
Note, that end may not end your program immediately; if you have opened a window or called clear screen, yabasic assumes, that your user wants to study the output of your program after it has ended; therefore it issues the line ---Program done, press RETURN--- and waits for a key to be pressed. If you do not like this behaviour, consider using exit.
endif — ends an if-statement
if (…) then … endif
The endif-statement closes (or ends) an if-statement.
Note, that endif may be written in a variety of other ways: end if, end-if or even fi.
The endif-statement must be omitted, if the if-statement does not contain the keyword then (see the example below). Such an if-statement without endif extends only over a single line.
end sub — ends a subroutine definition
sub foo(…) … end sub
Marks the end of a subroutine-definition (which starts with the sub-keyword).
The whole concept of subroutines is explained within the entry for sub.
eof — check, if an open file contains data
open 1,"foo.bar" if (eof(1)) then … end if
The eof-function checks, if there is still data left within an open file. As an argument it expects the file-number as returned by (or used within) the open-function (or statement).
eor() — compute the bitwise exclusive or of its two arguments
print eor(a,b)
The eor-function takes two arguments and computes their bitwise exclusive or. See your favorite introductory text on informatics for an explanation of this function.
The xor-function is the same as the eor function; both are synonymous; however they have each their own description, so you may check out the entry of xor for a slightly different view.
error — raise an error and terminate your program
error "Wrong, wrong, wrong !!"
Produces the same kind or error messages, that yabasic itself produces (e.g. in case of a syntax-error). The single argument is issued along with the current line-number.
input "Please enter a number between 1 and 10: " a
if (a<1 or a>10) error "Oh no ..."
This program is very harsh in checking the users input; instead of just asking again, the program terminates with an error, if the user enters something wrong.
The error message would look like this:
---Error in t.yab, line 2: Oh no ... ---Error: Program stopped due to an error
euler — another name for the constant 2.71828182864
foo=euler
execute$() — execute a user defined subroutine, which must return a string
print execute$("foo$","arg1","arg2")execute$ can be used to execute a user defined subroutine, whose name may be specified as a string expression.
This feature is the only way to execute a subroutine, whose name is not known by the time you write your program. This might happen, if you want to execute a subroutine, which is compiled (using the compile command) during the course of execution of your program.
Note however, that the execute$-function is not the preferred method to execute a user defined subroutine; almost all cases you should just execute a subroutine by writing down its name within your yabasic program (see the example).
execute() — execute a user defined subroutine, which must return a number
print execute("bar","arg1","arg2")The execute-function is the counterpart of the execute$-function (please see there for some caveats). execute executes subroutines, which returns a number.
exit — terminate your program
exit exit 1
Terminate your program and return any given value to the operating system. exit is similar to end, but it will terminate your program immediately, no matter what.
exp() — compute the exponential function of its single argument
foo=exp(bar)
This function computes e to the power of its argument, where e is the well known euler constant 2.71828182864.
The exp-function is the inverse of the log-function.
export — mark a function as globally visible
export sub foo(bar) … end sub
The export-statement is used within libraries to mark a user defined subroutine as visible outside the library wherein it is defined. Subroutines, which are not exported, must be qualified with the name of the library, e.g. foo.baz (where foo is the name of the library and baz the name of the subroutine); exported subroutines may be used without specifying the name of the library, e.g. bar.
Therefore export may only be useful within libraries.
The library foo.bar (which is listed below) defines two functions bar and baz, however only the function bar is exported and therefore visible even outside the library; baz is not exported and may only be used within the library foo.yab:
export sub bar()
print "Hello"
end sub
sub baz()
print "World"
end sub
Now within your main program cux.yab (which imports the library foo.yab); note that this program produces an error:
import foo print "Calling subroutine foo.bar (okay) ..." foo.bar() print "done." print "Calling subroutine bar (okay) ..." bar() print "done." print "Calling subroutine foo.baz (okay) ..." foo.baz() print "done." print "Calling subroutine baz (NOT okay) ..." baz() print "done."
The output when executing yabasic foo.yab is this:
Calling subroutine foo.bar (okay) ... Hello done. Calling subroutine bar (okay) ... Hello done. Calling subroutine foo.baz (okay) ... World done. Calling subroutine baz (NOT okay) ... ---Error in main.yab, line 16: can't find subroutine 'baz' ---Dump: sub baz() called in main.yab,16 ---Error: Program stopped due to an error
As the error message above shows, the subroutine baz must be qualified with the name of the library, if used outside the library, wherein it is defined (e.g. foo.baz. I.e. outside the library foo.yab you need to write foo.baz. baz alone would be an error.
The subroutine bar (without adding the name of the library) however may (and probably should) be used in any program, which imports the library foo.yab.
In some sense the set of exported subroutines constitutes the interface of a library.
false — a constant with the value of 0
okay=false
The constant false can be assigned to variables which later appear in conditions (e.g. within an if-statement.
false may also be written as FALSE or even FaLsE.
fi — another name for endif
if (…) … fi
fi marks the end of an if-statement and is exactly equivalent to endif, please see there for further information.
fill — draw a filled circles, rectangles or triangles
fill rectangle 10,10,90,90 fill circle 50,50,20 fill triangle 10,20,20,10,20,20
The keyword fill may be used within the circle, rectangle or triangle command and causes these shapes to be filled.
fill can be used in conjunction with and wherever the clear-clause may appear. Used alone, fill will fill the interior of the shape (circle, rectangle or triangle); together with clear the whole shape (including its interior) is erased.
for — starts a for-loop
for a=1 to 100 step 2 … next a
The for-loop lets its numerical variable (a in the synopsis) assume all values within the given range. The optional step-clause may specify a value (default: 1) by which the variable will be incremented (or decremented, if step is negative).
Any for-statement can be replaced by a set of ifs and gotos; as you may infer from the example below this is normally not feasible. However if you want to know in detail how the for-statement works, you should study this example, which presents a for-statement and an exactly equivalant series of ifs and gotos.
frac() — return the fractional part of its numeric argument
x=frac(y)
The frac-function takes its argument, removes all the digits to the left of the comma and just returns the digits right of the comma, i.e. the fractional part.
Refer to the example to learn how to rewrite frac by employing the int-function.
for a=1 to 10
print frac(sqr(a))
print sqr(a)-int(sqr(a))
next a
The example prints the fractional part of the square root of the numbers between 1 and 10. Each result is computed (and printed) twice: Once by employing the frac-function and once by employing the int-function.
getbit$() — return a string representing the bit pattern of a rectangle within the graphic window
a$=getbit$(10,10,20,20) a$=getbit$(10,10 to 20,20)
The function getbit returns a string, which contains the encoded bit-pattern of a rectangle within graphic window; the four arguments represent the borders of the rectangle. The string returned might later be fed to the putbit-command.
The getbit$-function might be used for simple animations (as in the example below).
getscreen$() — returns a string representing a rectangular section of the text terminal
a$=getscreen$(2,2,20,20)
The getscreen$ function returns a string representing the area of the screen as specified by its four arguments (which specify two corners). I.e. everything you have printed within this rectangle will be encoded in the string returned (including any colour-information).
Like most other commands dealing with advanced text output, getscreen$ requires, that you have called clear screen before.
clear screen
for a=1 to 1000:
print color("red") "1";
print color("green") "2";
print color("blue") "3";
next a
screen$=getscreen$(10,10,40,10)
print at(10,10) " Please Press 'y' or 'n' ! "
a$=inkey$
putscreen screen$,10,10
This program fills the screen with colored digits and afterwards asks the user for a choice ( Please press 'y' or 'n' ! ). Afterwards the area of the screen, which has been overwritten by the question will be restored with its previous contents, whhch had been saved via getscreen$.
glob() — check if a string matches a simple pattern
if (glob(string$,pattern$)) …
The glob-function takes two arguments, a string and a (glob-) pattern, and checks if the string matches the pattern. However glob does not employ the powerful rules of regular expressions; rather it has only two special characters: * (which matches any number (even zero) of characters) and ? (which matches exactly a single character).
for a=1 to 10
read string$,pattern$
if (glob(string$,pattern$)) then
print string$," matches ",pattern$
else
print string$," does not match ",pattern$
endif
next a
data "abc","a*"
data "abc","a?"
data "abc","a??"
data "abc","*b*"
data "abc","*"
data "abc","???"
data "abc","?"
data "abc","*c"
data "abc","A*"
data "abc","????"
This program checks the string abc against various patterns and prints the result. The output is:
abc matches a* abc does not match a? abc matches a?? abc matches *b* abc matches * abc matches ??? abc does not match ? abc matches *c abc does not match A* abc does not match ????
gosub — continue execution at another point within your program (and return later)
gosub foo … label foo … return
gosub remembers the current position within your program and then passes the flow of execution to another point (which is normally marked with a label). Later, when a return-statement is encountered, the execution is resumed at the previous location.
gosub is the traditional command for calling code, which needs to be executed from various places within your program. However, with subroutines yabasic offers a much more flexible way to achieve this (and more). Therefore gosub must to be considered obsolete.
goto — continue execution at another point within your program (and never come back)
goto foo … label foo
The goto-statement passes the flow of execution to another point within your program (which is normally marked with a label).
goto is normally considered obsolete and harmful, however in yabasic it may be put to the good use of leaving loops (e.g. while or for) prematurely. Note however, that subroutines may not be left with the goto-statement.
hex$() — convert a number into hexadecimal
print hex$(foo)
The hex$-function converts a number into a string with its hexadecimal representation. hex$ is the inverse of the dec-function.
if — evaluate a condition and execute statements or not, depending on the result
if (…) then … endif if (…) … if (…) then … else … endif if (…) then … elsif (…) … elsif (…) then … else … endif
The if-statement is used to evaluate a conditions and take actions accordingly. (As an aside, please note that there is no real difference between conditions and expressions.)
There are two major forms of the if-statement:
The one-line-form without the keyword then:
if (…) …
This form evaluates the condition and if the result is true executes all commands (separated by colons) upt to the end of the line. There is neither an endif keyword nor an else-branch.
The multi-line-form with the keyword then:
if (…) then … elsif (…) … else … endif
(where elsif and else are optional, whereas endif is not.
According to the requirements of your program, you may specify:
elsif(…), which specifies a condition, that will be evaluated only if the condition(s) whithin if or any preceding elsif did not match.
else, which introduces a sequence of commands, that will be executed, if none of the conditions above did match.
endif is required and ends the if-statement.
input "Please enter a number between 1 and 4: " a
if (a<=1 or a>=4) error "Wrong, wrong !"
if (a=1) then
print "one"
elsif (a=2)
print "two"
elsif (a=3)
print "three"
else
print "four"
endif
The input-number between 1 and 4 is simply echoed as text (one, two, …). The example demonstrates both forms (short and long) of the if-statement (Note however, that the same thing can be done, probably somewhat more elegant, with the switch-statement).
import — import a library
import foo
The import-statement imports a library. It expects a single argument, which must be the name of a library (without the trailing .yab). This library will then be read and parsed and its subroutines (and variables) will be made available within the main program.
Libraries will first be searched within the current directory (i.e. the directory within which you have invoked yabasic), then within a special directory, whose exact location depends on your system. Typical values would be /usr/lib under Unix or C:\yabasic\lib under Windows. However only yabasic -help-usage may tell the truth. The location of this second directory may be changed with the option -library (either under Windows or Unix).
Lets say you have a yabasic-program foo.yab, which imports a library lib.yab. foo.yab reads:
import lib
rem This works ...
lib.x(0)
rem This works too ..
x(1)
rem And this.
lib.y(2)
rem But this not !
y(3)
Now the library lib.yab reads:
rem Make the subroutine x easily available outside this library export sub x(a) print a return end sub rem sub y must be referenced by its full name rem outside this library sub y(a) print a return end sub
This program produces an error:
0 1 2 ---Error in foo.yab, line 13: can't find subroutine 'y' ---Dump: sub y() called in foo.yab,13 ---Error: Program stopped due to an error
As you may see from the error message, yabasic is unable to find the subroutine y without specifying the name of the library (i.e. lib.y). The reason for this is, that y, other than x, is not exported from the library lib.yab (using the export-statement).
inkey$ — wait, until a key is pressed
clear screen foo$=inkey$ inkey$ foo$=inkey$(bar) inkey$(bar)
The inkeys$-function waits, until the user presses a key on the keyboard or a button of his mouse, and returns this very key. An optional argument specifies the number of seconds to wait; if omitted, inkey$ will wait indefinitely.
inkey$ may only be used, if clear screen has been called at least once.
For normal keys, yabasic simply returns the key, e.g. a, 1 or !. For function keys you will get f1, f2 and so on. Other special keys will return these strings respectively: enter, backspace, del, esc, scrnup (for screen up), scrndown and tab. Modifier keys (e.g. ctrl, alt or shift) by themselves can not be detected (however, if you press shift and e.g. a simultaniously, inkey$ will return the letter A instead of a of course).
If a graphical window has been opened (via open window) any mouseclick within this window will be returned by inkey$ too. The string returned (e.g. MB1d+0:0028,0061, MB2u+0:0028,0061 or MB1d+1:0028,0061) is constructed as follows:
Every string associated with a mouseclick will start with the fixed string MB
The next digit (1, 2 or 3) specifies the mousebutton pressed.
A single letter, d or u, specifies, if the mousebutton has been pressed or released: d stands for down, i.e. the mousebutton has been pressed; u means up, i.e. the mousebutton has been released.
The plus-sign ('+'), which follows is always fixed.
The next digit (in the range 0 to 7) encodes the modifier keys pressed, where 1 stands for shift, 2 stands for alt and 4 stands for ctrl.
The next four digits (e.g. 0028) contain the x-position, where the mousebutton has been pressed.
The comma to follow is always fixed.
The last four digits (e.g. 0061) contain the y-position, where the mousebutton has been pressed.
All those fields are of fixed length, so you may use functions like mid$ to extract certain fields. However, note that with mousex, mousey, mouseb and mousemod there are specialized functions to return detailed information about the mouseclick. Finally it should be noted, that inkey$ will only register mouseclicks within the graphic-window; mouseclicks in the text-window cannot be detected.
inkey$ accepts an optional argument, specifying a timeout in seconds; if no key has been pressed within this span of time, an empty string is returned. If the timeout-argument is omitted, inkey$ will wait for ever.
input — read input from the user (or from a file) and assign it to a variable
input a input a,b,c input a$ input "Hello" a input #1 a$
input reads the new contents of one or many (numeric- or string-) variables, either from the keyboard (i.e. from you) or from a file. An optional first string-argument specifies a prompt, which will be issued before reading any contents.
If you want to read from an open file, you need to specify a hash ('#'), followed by the number, under which the file has been opened.
Note, that the input is split at spaces, i.e. if you enter a whole line consisting of many space-separated word, the first input-statement will only return the first word; the other words will only be returned on subsequent calls to input; the same applies, if a single input reads multiple variables: The first variable gets only the first word, the second one the second word, and so on. If you don't like this behaviour, you may use line input, which returns a whole line (including embedded spaces) at once.
input "Please enter the name of a file to read: " a$
open 1,a$
while(!eof(1))
input #1 b$
print b$
wend
If this program is stored within a file test.yab and you enter this name when prompted for a file to read, you will see this output:
Please enter the name of a file to read: t.yab input "Please enter the name of a file to read: " a$ open 1,a$ while(!eof(1)) input #1 b$ print b$ wend
instr() — searches its second argument within the first; returns its position if found
print instr(a$,b$) if (instr(a$,b$)) … pos=instr(a$,b$,x)
The instr-functions requires two string arguments and searches the second argument within the first. If the second argument can be found within the first, the position is returned (counting from one). If it can not be found, the instr-function returns 0; this makes this function usable within the condition of an if-statement (see the example below).
If you supply a third, numeric argument to the instr-function, it will be used as a starting point for the search. Therefore instr("abcdeabcdeabcde","e",8) will return 10, because the search for an "e" starts at position 8 and finds the "e" at position 10 (and not the one at position 5).
int() — return the integer part of its single numeric argument
print int(a)
The int-function returns only the digits before the comma; int(2.5) returns 2 and int(-2.3) returns -2.
label — mark a specific location within your program for goto, gosub or restore
label foo … goto foo
The label-command can be used to give a name to a specific location within your program. Such a position might be referred from one of three commands: goto, gosub and restore.
You may use labels safely within libraries, because a label (e.g. foo) does not collide with a label with the same name within the main program or within another library; yabasic will not mix them up.
As an aside, please note, that line numbers are a special (however deprecated) case of labels; see the second example below.
left$() — return (or change) left end of a string
print left$(a$,2) left$(b$,3)="foobar"
The left$-function accepts two arguments (a string and a number) and returns the part from the left end of the string, whose length is specified by its second argument. Loosely spoken, it simply returns the requested number of chars from the left end of the given string.
Note, that the left$-function can be assigned to, i.e. it may appear on the left hand side of an assignment. In this way it is possible to change a part of the variable used within the left$-function. Note, that that way the length of the string cannot be changed, i.e. characters might be overwritten, but not added. For an example see below.
input "Please answer yes or no: " a$
l=len(a$):a$=lower$(a$):print "Your answer is ";
if (left$("yes",l)=a$ and l>=1) then
print "yes"
elsif (left$("no",l)=a$ and l>=1) then
print "no"
else
print "?"
endif
This example asks a simple yes/no question and goes some way to accept even incomplete input, while still being able to reject invalid input.
This second example demonstrates the capability to assign to the left$-function.
a$="Heiho World !" print a$ left$(a$,5)="Hello" print a$
len() — return the length of a string
x=len(a$)
line — draw a line
open window 100,100 line 0,0,100,100 line 0,0 to 100,100 new curve line 100,100 line to 100,100 open window 100,100 clear line 0,0,100,100 clear line 0,0 to 100,100 new curve clear line 100,100 clear line to 100,100
The line-command draws a line. Simple as this is, the line-command has a large variety of forms as they are listed in the synopsis above. Lets look at them a little closer:
A line has a starting and an end point; therefore the line-command (normally) needs four numbers as arguments, representing these two points. This is the first form appearing within the synopsis.
You may separate the two points with either ',' or to, which accounts for the second form of the line-command.
The line-command may be used to draw a connected sequence of lines with a sequence of commands like line x,y; Each command will draw a line from the point where the last line-command left off, to the point specified in the arguments. Note, that you need to use the command new curve before you may issue such a line-command. See the example below.
You may insert the word to for beauty: line to x,y, which does exactly the same as line x,y
Finally, you may choose not to draw, but to erase the lines; this can be done by prepending the phrase clear. This account for all the other forms of the line-command.
open window 200,200
line 10,10 to 10,190
line 10,190 to 190,190
new curve
for a=0 to 360
line to 10+a*180/360,100+60*sin(a*pi/180)
next a
This example draws a sine-curve (with an offset in x- and y-direction). Note, that the first line-command after new curve does not draw anything. Only the coordinates will be stored. The second iteration of the loop then uses these coordinates as a starting point for the first line.
line input — read in a whole line of text and assign it to a variable
line input a line input a$ line input "Hello" a line input #1 a$
In most respects line input is like the input-command: It reads the new contents of a variable, either from keyboard or from a file. However, line input always reads a complete line and assigns it to its variable. line input does not stop reading at spaces and is therefore the best way to read in a string which might contain whitespace. Note, that the final newline is stripped of.
local — mark a variable as local to a subroutine
sub foo() local a,b,c$,d(10),e$(5,5) … end sub
The local-command can (and should be) used to mark a variable (or array) as local to the containing subroutine. This means, that a local variable in your subroutine is totally different from a variable with the same name within your main program. Variables which are known everywhere within your program are called global in contrast.
Declaring variables within the subroutine as local helps to avoid hard to find bugs; therefore local variables should be used whenever possible.
Note, that the parameters of your subroutines are always local.
As you may see from the example, local arrays may be created without using the keyword dim (which is required only for global arrays).
a=1
b=1
print a,b
foo()
print a,b
sub foo()
local a
a=2
b=2
end sub
This example demonstrates the difference between local and global variables; it produces this output:
1 1 1 2
As you may see, the content of the global variable a is unchanged after the subroutine foo; this is because the assignment a=2 within the subroutine affects the local variable a only and not the global one. However, the variable b is never declared local and therefore the subroutine changes the global variable, which is reflected in the output of the second print-statement.
log() — compute the natural logarithm
a=log(x) a=log(x,base)
The log-function computes the logarithm of its first argument. The optional second argument gives the base for the logarithm; if this second argument is omitted, the euler-constant 2.71828… will be taken as the base.
loop — marks the end of an infinite loop
do … loop
The loop-command marks the ends of a loop (which is started by do), wherein all statements within the loop are repeated forever. In this respect the do loop-loop is infinite, however, you may leave it anytime via break or goto.
lower$() — convert a string to lower case
l$=lower$(a$)
ltrim$() — trim spaces at the left end of a string
a$=ltrim$(b$)
The ltrim$-function removes all whitespace from the left end of a string and returns the result.
input "Please answer 'yes' or 'no' : " a$
a$=lower$(ltrim$(rtrim$(a$)))
if (len(a$)>0 and a$=left$("yes",len(a$))) then
print "Yes ..."
else
print "No ..."
endif
This example prompts for an answer and removes any spaces, which might precede the input; therefore it is even prepared for the (albeit somewhat pathological case, that the user first hits space before entering his answer.
max() — return the larger of its two arguments
print max(a,b)
dim m(10)
for a=1 to 1000
m=0
For b=1 to 10
m=max(m,ran(10))
next b
m(m)=m(m)+1
next a
for a=1 to 9
print a,": ",m(a)
next a
Within the inner for-loop (the one with the loop-variable b), the example computes the maximum of 10 random numbers. The outer loop (with the loop variable a) now repeats this process 1000 times and counts, how often each maximum appears. The last loop finally reports the result.
Now, the interesting question would be, which will be approached, when we increase the number of iterations from thousand to infinity. Well, maybe someone could just tell me :-)
mid$() — return (or change) characters from within a string
print mid$(a$,2,1) print mid$(a$,2) mid$(a$,5,3)="foo" mid$(a$,5)="foo"
The mid$-function requires three arguments: a string and two numbers, where the first number specifies a position within the string and the second one gives the number of characters to be returned; if you omit the second argument, the mid$-function returns all characters up to the end of the string.
Note, that you may assign to the mid$-function, i.e. mid$ may appear on the left hand side of an assignment. In this way it is possible to change a part of the variable used within the mid$-function. Note, that that way the length of the string cannot be changed, i.e. characters might be overwritten, but not added. For an example see below.
input "Please enter a string: " a$
for a=1 to len(a$)
if (instr("aeiou",lower$(mid$(a$,a,1)))) mid$(a$,a,1)="e"
next a
print "When you turn everything to lower case and"
print "replace every vowel with 'e', your input reads:"
print
print a$
This example transforms the input string a bit, using the mid$-function to retrieve a character from within the string as well as to change it.
min() — return the smaller of its two arguments
print min(a,b)
mod() — compute the remainder of a division
print mod(a,b)
The mod-function divides its two arguments and computes the remainder. Note, that a/b-int(a/b) and mod(a,b) are always equal.
clear screen
print at(10,10) "Please wait ";
p$="-\|/"
for a=1 to 100
rem ... do something lengthy here, or simply sleep :-)
pause(1)
print at(22,10) mid$(p$,1+mod(a,4))
next a
This example executes some time consuming action within a loop (in fact, it simply sleeps) and gives the user some indication of progress by displaying a turning bar (thats where the mod()-function comes into play).
mouseb — extract the state of the mousebuttons from a string returned by inkey$
inkey$ print mouseb() print mouseb a$=inkey$ print mouseb(a$)
The mouseb-function is a helper function for decoding part of the (rather complicated) strings, which are returned by the inkey$-function. If a mousebutton has been pressed, the mouseb-function returns the number (1,2 or 3) of the mousebutton, when it is pressed and returns its negative (-1,-2 or -3), when it is released.
The mouseb-function accepts zero or one arguments. A single argument should be a string returned by the inkey$-function; if mouseb is called without any arguments, it returns the values from the last call to inkey$, which are stored implicitly and internally by yabasic.
Note however, that the value returned by the mouseb-function does not reflect the current state of the mousebuttons. It rather extracts the information from the string passed as an argument (or from the last call to the inkey$-function, if no argument is passed). So the value returned by mouseb reflects the state of the mousebuttons at the time the inkey$-function has been called; as opposed to the time the mouseb-function is called.
open window 200,200
clear screen
print "Please draw lines; press (and keep it pressed)"
print "the left mousebutton for the starting point,"
print "release it for the end-point."
do
if (mouseb(release$)=1) press$=release$
release$=inkey$
if (mouseb(release$)=-1) then
line mousex(press$),mousey(press$) to mousex(release$),mousey(release$)
endif
loop
This is a maybe the most simplistic line-drawing program possible, catching presses as well as releases of the first mousebutton.
mousemod — return the state of the modifier keys during a mouseclick
inkey$ print mousemod() print mousemod a$=inkey$ print mousemod(a$)
The mousemod-function is a helper function for decoding part of the (rather complicated) strings, which are returned by the inkey$-function if a mousebutton has been pressed. It returns the state of the keyboard modifiers (shift, ctrl or alt): If the shift-key is pressed, mousemod returns 1, for the alt-key 2 and for the ctrl-key 4. If more than one key is pressed, the sum of these values is returned, e.g. mousemod returns 5, if shift and ctrl are pressed simultaneously.
The mousemod-function accepts zero or one arguments. A single argument should be a string returned by the inkey$-function; if mousemod is called without any arguments, it returns the values from the last call to inkey$ (which are stored implicitly and internally by yabasic).
Please see also the Note within the mouseb-function.
open window 200,200
clear screen
do
a$=inkey$
if (left$(a$,2)="MB") then
x=mousex(a$)
y=mousey(a$)
if (mousemod(a$)=0) then
circle x,y,20
else
fill circle x,y,20
endif
endif
loop
This program draws a circle, whenever a mousebutton is pressed; the circles are filled, when any modifier is pressed, and empty if not.
mousex — return the x-position of a mouseclick
inkey$ print mousex() print mousex a$=inkey$ print mousex(a$)
The mousex-function is a helper function for decoding part of the (rather complicated) strings, which are returned by the inkey$-function; It returns the x-position of the mouse as encoded within its argument.
The mousex-function accepts zero or one arguments. A single argument should be a string returned by the inkey$-function; if mousex is called without any arguments, it returns the values from the last call to inkey$ (which are stored implicitly and internally by yabasic).
Please see also the Note within the mouseb-function.
mousey — return the y-position of a mouseclick
inkey$ print mousey() print mousey a$=inkey$ print mousey(a$)
The mousey-function is a helper function for decoding part of the (rather complicated) strings, which are returned by the inkey$-function. mousey returns the y-position of the mouse as encoded within its argument.
The mousey-function accepts zero or one arguments. A single argument should be a string returned by the inkey$-function; if mousey is called without any arguments, it returns the values from the last call to inkey$ (which are stored implicitly and internally by yabasic).
Please see also the Note within the mouseb-function.
new curve — start a new curve, that will be drawn with the line-command
new curve line to x,y
The new curve-function starts a new sequence of lines, that will be drawn by repeated line to-commands.
open window 200,200
ellipse(100,50,30,60)
ellipse(150,100,60,30)
sub ellipse(x,y,xr,yr)
new curve
for a=0 to 2*pi step 0.2
line to x+xr*cos(a),y+yr*sin(a)
next a
close curve
end sub
This example defines a subroutine ellipse that draws an ellipse. Within this subroutine, the ellipse is drawn as a sequence of lines started with the new curve command and closed with close curve.
next — mark the end of a for loop
for a=1 to 10 next a
The next-keyword marks the end of a for-loop. All statements up to the next-keyword will be repeated as specified with the for-clause. Note, that the name of the variable is optional; so instead of next a you may write next.
not — negate an expression; can be written as !
if (not a<b) then … bad=!okay
The keyword not (or ! for short) is mostly used within conditions (e.g. within if- or while-statements). There it is employed to negate the condition or expression (i.e. turn TRUE into FALSE and vice versa)
However not can be used within arithmetic calculations too., simply because there is no difference between arithmetic and logical expressions.
numparams — return the number of parameters, that have been passed to a subroutine
sub foo(a,b,c) if (numparams=1) … … end sub
Within a subroutine the local variable numparam or numparams contains the number of parameters, that have been passed to the subroutine. This information can be useful, because the subroutine may have been called with fewer parameters than actually declared. The number of values that actually have been passed while calling the subroutine, can be found in numparams.
Note, that arguments which are used in the definition of a subroutine but are left out during a call to it (thereby reducing the value of numparams) receive a value of 0 or "" (empty string) respectively.
a$="123456789"
print part$(a$,4)
print part$(a$,3,7)
sub part$(a$,f,t)
if (numparams=2) then
return mid$(a$,f)
else
return mid$(a$,f,t-f+1)
end if
end sub
When you run this example, it will print 456789 and 34567. Take a look at the subroutine part$, which returns part of the string which has been passed as an argument. If (besides the string) two numbers are passed, they define the starting and end position of the substring, that will be returned. However, if only one number is passed, the rest of the string, starting from this position will be returned. Each of these cases is recognized with the help of the numparams variable.
on goto — jump to one of multiple gosub-targets
on a gosub foo,bar,baz … label foo … return label bar … return label baz … return
The on gosub statement uses its numeric argument (the one between on and gosub) to select an element from the list of labels, which follows after the gosub-keyword: If the number is 1, the program does a gosub to the first label; if the number is 2, to the second and, so on. if the number is zero or less, the program continues at the position of the first label; if the number is larger than the total count of labels, the execution continues at the position of the last label; i.e. the first and last label in the list constitute some kind of fallback-slot.
Note, that the on gosub-command can no longer be considered state of the art; people (not me !) may even start to mock you, if you use it.
do
print "Please enter a number between 1 and 3: "
print
input "Your choice " a
on a gosub bad,one,two,three,bad
loop
label bad
print "No. Please between 1 and 3"
return
label one
print "one"
return
label two
print "two"
return
label three
print "three"
return
Note, how invalid input (a number less than 1, or larger than 3) is automatically detected.
on goto — jump to one of many goto-targets
on a goto foo,bar,baz … label foo … label bar … label baz …
The on goto statement uses its numeric argument (the one between on and goto to select an element from the list of labels, which follows after the goto-keyword: If the number is 1, the execution continues at the first label; if the number is 2, at the second, and so on. if the number is zero or less, the program continues at the position of the first label; if the number is larger than the total count of labels, the execution continues at the position of the last label; i.e. the first and last label in the list constitute some kind of fallback-slot.
Note, that (unlike the goto-command) the on goto-command can no longer be considered state of the art; people may (not me !) even start to mock you, if you use it.
label over
print "Please Select one of these choices: "
print
print " 1 -- show time"
print " 2 -- show date"
print " 3 -- exit"
print
input "Your choice " a
on a goto over,show_time,show_date,terminate,over
label show_time
print time$()
goto over
label show_date
print date$()
goto over
label terminate
exit
Note, how invalid input (a number less than 1, or larger than 3) is automatically detected; in such a case the question is simply issued again.
on interrupt — change reaction on keyboard interrupts
on interrupt break … on interrupt continue
With the on interrupt-command you may change the way, how yabasic reacts on a keyboard interrupt; it comes in two variants: on interrupt break and on interrupt continue. A keyboard interrupt is produced, if you press ctrl-C on your keyboard; normally (and certainly after you have called on interrupt break), yabasic will terminate with an error message. However after the command on interrupt continue yabasic ignores any keyboard interrupt. This may be useful, if you do not want your program being interruptible during certain critical operations (e.g. updating of files).
print "Please stand by while writing a file with random data ..."
on interrupt continue
open "random.data" for writing as #1
for a=1 to 100
print #1 ran(100)
print a," percent done."
sleep 1
next a
close #1
on interrupt continue
This program writes a file with 100 random numbers. The on interrupt continue command insures, that the program will not be terminated on a keyboard interrupt and the file will be written entirely in any case. The sleep-command just stretches the process artificially to give you a chance to try a ctrl-C.
open — open a file
open a,"file","r"
open #a,"file","w"
open #a,printer
open "file" for reading as a
open "file" for writing as #a
a=open("file")
a=open("file","r")
if (open(a,"file")) …
if (open(a,"file","w")) …
The open-command opens a file for reading or writing or a printer for printing text. open comes in a wide variety of ways; it requires these arguments:
In the synopsis this is a or #a. In yabasic each file is associated with a number between 1 and a maximum value, which depends on the operating system. For historical reasons the filenumber can be preceded by a hash ('#'). Note, that specifying a filenumber is optional; if it is omitted, the open-function will return a filenumber, which should then be stored in a variable for later reference. This filenumber can be a simple number or an arbitrary complex arithmetic expression, in which case braces might be necessary to save yabasic from getting confused.
In the synopsis above this is "file". This string specifies the name of the file to open (note the important caveat on specifying these filenames).
In the synopsis this is "r", "w", for reading or for writing. This string or clause specifies the mode in which the file is opened; it may be one of:
Open the file for reading (may also be written as for reading). If the file does not exist, the command will fail. This mode is the default, i.e. if no mode is specified with the open-command, the file will be opened with this mode.
Open the file for writing (may also be written as for writing). If the file does not exist, it will be created.
Open the file for appending, i.e. what you write to the file will be appended after its initial contents. If the file does not exist, it will be created.
This letter may not appear alone, but may be combined with the other letters (e.g. "rb") to open a file in binary mode (as opposed to text mode).
As you may see from the synopsis, the open-command may either be called as a command (without braces) or as a function (with braces). If called as a function, it will return the filenumber or zero if the operation fails. Therefore the open-function may be used within the condition of an if-statement.
If the open-command fails, you may use peek("error") to retrieve the exact nature of the error.
Furthermore note, that there is another, somewhat separate usage of the open-command; if you specify the bareword printer instead of a filename, the command opens a printer for printing text. Every text (and only text) you print to this file will appear on your printer. Note, that this is very different from printing graphics, as can be done with open printer.
Finally you may read the description for peek("error") to learn which errors may have happened during an open-call.
open printer — open printer for printing graphics
open printer open printer "file"
The open printer-command opens a printer for printing graphics. The command requires, that a graphic window has been opened before. Everything that is drawn into this window will then be sent to the printer too.
A new piece of paper may be started with the clear window-command; the final (or only) page will appear after the close printer-command.
Note, that you may specify a filename with open printer; in that case the printout will be sent to a filename instead to a printer. Your program or the user will be responsible for sending this file to the printer afterwards.
If you use yabasic under Unix, you will need a postscript printer (because yabasic produces postscript output). Alternatively you may use ghostscript to transform the postscript file into a form suitable for your printer; but that is beyond the responsibility of yabasic.
open window — open a graphic window
open window x,y open window x,y,"font"
The open window-command opens a window of the specified size. Only one window can be opened at any given moment of time.
An optional third argument specifies a font to be used for any text within the window. It can however be changed with any subsequent text-command.
or — logical or, used in conditions
if (a or b) … while (a or b) …
or() — arithmetic or, used for bit-operations
x=or(a,b)
Used to compute the bitwise or of both its argument. Both arguments are treated as binary numbers (i.e. a series of 0 and 1); a bit of the resulting value will then be 1, if any of its arguments has 1 at this position in their binary representation.
Note, that both arguments are silently converted to integer values and that negative numbers have their own binary representation and may lead to unexpected results when passed to or.
pause — pause, sleep, wait for the specified number of seconds
pause 5
The pause-command has many different names: You may write pause, sleep or wait interchangeably; whatever you write, yabasic will always do exactly the same.
The pause-command will simply wait for the specified number of seconds. This may be a fractional number, so you may well wait less than a second. However, if you try to pause for a smaller and smaller interval (e.g. 0.1 seconds, 0.01 seconds, 0.001 seconds and so on) you will find that at some point yabasic will not wait at all. The minimal interval that can be waited depends on the system (Unix, Windows) you are using.
The pause-command cannot be interrupted. However, sometimes you may want the wait to be interruptible by simply pressing a key on the keyboard. In such cases you should consider using the inkey$-function, with a number of seconds as an argument).
deg=0
do
maxx=44+40*sin(deg)
for x=1 to maxx
print "*";
next x
pause 0.1+(maxx*maxx/(4*84*84))
print
deg=deg+0.1
loop
This example draws a sine-curve; due to the pause-statement the speed of drawing varies in the same way as the speed of a ball might vary, if it would roll along this curve under the influence of gravity.
peek — retrieve various internal informations
print peek("foo")
a=peek(#1)
or — logical or, used in conditions
if (a or b) … while (a or b) …
or() — arithmetic or, used for bit-operations
x=or(a,b)
Used to compute the bitwise or of both its argument. Both arguments are treated as binary numbers (i.e. a series of 0 and 1); a bit of the resulting value will then be 1, if any of its arguments has 1 at this position in their binary representation.
Note, that both arguments are silently converted to integer values and that negative numbers have their own binary representation and may lead to unexpected results when passed to or.
pause — pause, sleep, wait for the specified number of seconds
pause 5
The pause-command has many different names: You may write pause, sleep or wait interchangeably; whatever you write, yabasic will always do exactly the same.
The pause-command will simply wait for the specified number of seconds. This may be a fractional number, so you may well wait less than a second. However, if you try to pause for a smaller and smaller interval (e.g. 0.1 seconds, 0.01 seconds, 0.001 seconds and so on) you will find that at some point yabasic will not wait at all. The minimal interval that can be waited depends on the system (Unix, Windows) you are using.
The pause-command cannot be interrupted. However, sometimes you may want the wait to be interruptible by simply pressing a key on the keyboard. In such cases you should consider using the inkey$-function, with a number of seconds as an argument).
deg=0
do
maxx=44+40*sin(deg)
for x=1 to maxx
print "*";
next x
pause 0.1+(maxx*maxx/(4*84*84))
print
deg=deg+0.1
loop
This example draws a sine-curve; due to the pause-statement the speed of drawing varies in the same way as the speed of a ball might vary, if it would roll along this curve under the influence of gravity.
peek — retrieve various internal informations
print peek("foo")
a=peek(#1)
or — logical or, used in conditions
if (a or b) … while (a or b) …
or() — arithmetic or, used for bit-operations
x=or(a,b)
Used to compute the bitwise or of both its argument. Both arguments are treated as binary numbers (i.e. a series of 0 and 1); a bit of the resulting value will then be 1, if any of its arguments has 1 at this position in their binary representation.
Note, that both arguments are silently converted to integer values and that negative numbers have their own binary representation and may lead to unexpected results when passed to or.
pause — pause, sleep, wait for the specified number of seconds
pause 5
The pause-command has many different names: You may write pause, sleep or wait interchangeably; whatever you write, yabasic will always do exactly the same.
The pause-command will simply wait for the specified number of seconds. This may be a fractional number, so you may well wait less than a second. However, if you try to pause for a smaller and smaller interval (e.g. 0.1 seconds, 0.01 seconds, 0.001 seconds and so on) you will find that at some point yabasic will not wait at all. The minimal interval that can be waited depends on the system (Unix, Windows) you are using.
The pause-command cannot be interrupted. However, sometimes you may want the wait to be interruptible by simply pressing a key on the keyboard. In such cases you should consider using the inkey$-function, with a number of seconds as an argument).
deg=0
do
maxx=44+40*sin(deg)
for x=1 to maxx
print "*";
next x
pause 0.1+(maxx*maxx/(4*84*84))
print
deg=deg+0.1
loop
This example draws a sine-curve; due to the pause-statement the speed of drawing varies in the same way as the speed of a ball might vary, if it would roll along this curve under the influence of gravity.
peek — retrieve various internal informations
print peek("foo")
a=peek(#1)