Rapid-Q Documentation by William Yu (c)1999-2000 | Chapter 3 |
$TYPECHECK
[ OFF | ON ] Default is OFF
$TYPECHECK is used to tell the compiler whether you want the source code parsed using strict type checking ON (all variables must be declared), or relaxed type checking OFF like traditional BASIC where you don't need to declare your variables. Note, you can turn ON or OFF type checking at anytime, so you can type check a portion of your code and turn it OFF afterwards.
Usage: $TYPECHECK ON
$INCLUDE
[ FileName ]
Using $INCLUDE has the same effect as importing your file directly into your program at the point of call.
You can use $INCLUDE anywhere in your program, except in a SUB or FUNCTION, but is
most often included at the beginning of your source code. Enclosing the filename between quotes will search
for that file in the current directory, and specified include paths. Enclosing the filename between < and >
will search for that file in the current directory, specified include paths and the environment search paths.
Usage:
$INCLUDE "RAPIDQ.INC"
$INCLUDE <RAPIDQ.INC>
$RESOURCE
Handle AS FileName
Most Windows programming languages include support for Resource files.
In Rapid-Q, this is somewhat different. In Rapid-Q, Resource files are just a collection
of graphics files. There is no such thing as resource strings in Rapid-Q.
Anyway, what's great about Resource files is that they are embedded into
your applications. So if you're using 10 different bitmaps, you don't need
to include them in your .ZIP distribution because it's already embedded into the .EXE.
Enclosing the filename between quotes will search
for that file in the current directory, and specified include paths. Enclosing the filename between < and >
will search for that file in the current directory, specified include paths and the environment search paths.
Usage:
$RESOURCE RES_BMP1 AS "CLOUDS.BMP"
$RESOURCE RES_BMP1 AS <CLOUDS.BMP>
$DEFINE
NewDefinition   [OldDefinition]
When you feel like redefining or creating new keywords/tokens, use this directive.
You cannot construct a series of tokens to be redefined.
You cannot redefine operators or punctuations. $DEFINE cannot be used to define a function (like in C).
The OldDefinition parameter is optional, so you can do this just fine: $DEFINE NEWDEF
Usage: $DEFINE INT16 SHORT
$UNDEF
DefName [, DefName]
To undefine a previous call of define, use $UNDEF.
You can specify multiple instances on the same line, separated with commas.
Usage: $UNDEF INT16, INT32
$IFDEF
Definition
This directive is used to specify whether a piece of code should or should
not be compiled. It is used in conjunction with $DEFINE. If the Definition
has been defined, the code within the $IFDEF...($ELSE)...$ENDIF statement will be compiled, otherwise
it is skipped entirely.
Usage:
$IFDEF INT16
' if INT16 has been defined
' compile this portion
$ELSE
' if INT16 has not been defined
' compile this portion
$ENDIF
$IFNDEF
Definition
$IFNDEF has the opposite effect as $IFDEF.
Usage:
$IFNDEF INT16
' if INT16 has not been defined
' compile this portion
$ELSE
' if INT16 has been defined
' compile this portion
$ENDIF
$OPTION
OptionName [Parameters]
BYREF, BYTECODE, DECIMAL, DIM, EXPLICIT, GTK, ICON, INKEY$, and WEAKTYPE are valid OptionNames.
Usage:
$OPTION BYREF
passed. By default, Rapid-Q passes variables
by value. This option reverses that.
Use with caution.
$OPTION BYTECODE
$OPTION DECIMAL ","
$OPTION DECIMAL 64
character for use in VAL.
The default decimal character is the period.
$OPTION DIM BYTE
$OPTION DIM WORD
$OPTION DIM DWORD
$OPTION DIM SHORT
$OPTION DIM INTEGER
$OPTION DIM LONG
$OPTION DIM SINGLE
$OPTION DIM DOUBLE
$OPTION DIM STRING
$OPTION DIM VARIANT
for an undeclared variable.
By default, all undeclared variables are
assumed to be of type DOUBLE
if no suffix is provided.
$OPTION EXPLICIT
Maintained for compatibility with VB
$OPTION GTK
Make sure you have the proper files
$OPTION ICON "path\file.ico"
of your executable file.
$OPTION INKEY$ DEFAULT
$OPTION INKEY$ TRAPALL
certain extended characters.
TRAPALL will trap Shift/Ctrl/Alt/Menu
as well as Caps/Num/Scroll lock.
$OPTION VBDLL ON
$OPTION VBDLL OFF
If VBDLL is enabled (ON), your DLL
declarations in Rapid-Q will mimic VB's
such that your code can be used the
same way in both languages.
This option is OFF by default.
$OPTION WEAKTYPE ON
$OPTION WEAKTYPE OFF
WeakType allows for faster parsing
and may help in porting some VB code.
It should not generally be used,
unless you know the code is okay.
$OPTIMIZE
[ OFF | ON ] Default is OFF
$OPTIMIZE can be used to reduce the byte code size by eliminating unnecessary
instructions. If you use this option, make sure it's one of the first things you call.
Usage: $OPTIMIZE ON
$ESCAPECHARS
[ OFF | ON ] Default is OFF
If $ESCAPECHARS is turned ON, you can use escape sequences in your strings.
Escape sequences can either be character or numeric escapes. Note that case is sensitive.
Usage: $ESCAPECHARS ON
Escape sequence
Details
Examples:
PRINT "\""
Output is "
PRINT "\x41"
Output is A
PRINT "\t\65\66\67\t\68\69\70
Output is ABC   DEF
PRINT "Hey\r\n";
Output is Hey with newline
$MACRO
MacroName[(Parameters, ...)] MacroDefinition
A Macro simply replaces a definition with another. It can be treated
like a function if you supply parameters. Rapid-Q allows Macros to be
embedded within another Macro (foward only to avoid recursion), token pasting using ##,
and even macro overloading.
You can also redefine operators and special characters except quotes.
A definition can extend to multiple lines by using the colon as a line
separator. A $MACRO directive is global if it preceeds any $INCLUDE directives.
ie. the included files have access to those Macro definitions.
A $MACRO directive only affects the module level (ie. the current file)
if used in an $INCLUDE file. So if A depends on B and B has some $MACRO
directives, then those $MACRO directives only affect B and A has no
access to them unless redeclared in module A.
Notes:
If you use the $MACRO directive, you are forcing Rapid-Q to preprocess
your code, which will prolong the compilation process. Rapid-Q normally performs
a single-pass compilation process.
Usage:
$MACRO ~ ,
This redefines the comma character
Try: ? STRING$(10 ~ "A")
$MACRO strcat(a,b) a=a+b
Implements a STRCAT function
strcat(a$,"abc") translates to a$=a$+"abc"
Not
working strcat(a1,b) a1=a1+b
$MACRO VARID(x) V##x
An example of token pasting
DEFINT VARID(1) translates to DEFINT V1
$MACRO TWO_PI (2*PI)
$MACRO PI 3.14159
Embedded Macros (forward only).
Can't embed itself as a parameter.
This avoids rescanning & recursion.
$MACRO ADD(a,b,c,d) ADD(a,b)+ADD(c,d)
$MACRO ADD(x,y) x+y
$MACRO ADD(x,y,z) x+y+z
An example of macro overloading
'MacroPower !!!
'Char presentation of number
Macro as pseudo SUB
DIM M AS
QMemoryStream
$Macro Digit2Char(D,a) _
M.Write(D):za=sizeOf(D):
_
M.Position=0:a=M.ReadBinStr(za) : M.Close
dim LPod as
double
lpod=33.234
Digit2Char(lpod,sss$)
print "Char LPod=",sss$:
dim tst as
integer
tst=33.234
Digit2Char(tst,zz$)
print "Char tst=",zz$:
Cause!
$Macro can not works in large files. (No damages yet)
A% = "Hello" "World" A$ = "Hi World!" A# = 34 + 34 - 324 * 3 / (34 / 5 + 5)If you've never programmed in BASIC before, you're probably wondering what all those symbols after the A mean. Well, since most implementations of BASIC does not restrict you to define your variables before you use them, you can define them by using these symbols:
?, ??, ???, %, &, !, #, $They represent BYTE (?), WORD (??), DWORD (???), SHORT (%), LONG (&) or INTEGER, SINGLE (!), DOUBLE (#), and STRING ($), respectively. Of course, if you didn't put any symbol in front of your undeclared variable, it's automatically assumed that the variable is a DOUBLE. That is the implementation used in Rapid-Q, for other languagues, the default maybe SINGLE, LONG, or what have you. Here's a table for your viewing pleasure:
Type ID Size Range --------- ---- ---- ------------- Byte ? 1 0..255 Word ?? 2 0..65535 Dword ??? 4 Only Linux version for now... Short % 2 -32768..32767 Integer & 4 -2147483648..2147483647 Long & 4 -2147483648..2147483647 Single ! 4 1.5 x 1045..3.4 x 1038 Double # 8 5.0 x 10324..1.7 x 10308If you didn't like the way that was done, you could also use DIM to declare your variables, like so:
DIM Number AS INTEGER DIM S AS STRING DIM B AS BYTEWell, you get the idea. If you turned $TYPECHECK ON, then you will be forced to declare your variables like that. It's a nice habit to pick up, especially if you wanted to switch to languages like C or Pascal. You will be forced to declare all your variables before you use them. Here's something that's valid in Rapid-Q, but can confuse the daylights out of people:
DIM Num$ AS INTEGERYes, try to avoid obfuscated code like that.
'This program demonstrate how to use
'DEF... Instead of DIM even for arrays!
'Boltex <pier..@yahoo.com>
DEFSHORT tour 'ok, define type:SHORT
DEFSHORT a(3) = {1,2,3,4} 'assign value even to arrays...
DEFSHORT b(1,3) = {1,2,3,4,5,6,7,8} 'of more than 1 dimension!
FOR tour=0 TO 3
PRINT "a(";tour;")=";a(tour)
NEXT tour
?
FOR tour=0 TO 3
PRINT "b(0,";tour;")=";b(0,tour)
NEXT tour
?
FOR tour=0 TO 3
PRINT "b(1,";tour;")=";b(1,tour)
NEXT tour
' Outputs to screen:
'
'a(0)=1
'a(1)=2
'a(2)=3
'a(3)=4
'
'b(0,0)=1
'b(0,1)=2
'b(0,2)=3
'b(0,3)=4
'
'b(1,0)=5
'b(1,1)=6
'b(1,2)=7
'b(1,3)=8
3.3 Rapid-Q Components/Objects
Arrays as parameter. DIM Form AS QFORM
Form.ShowModal
Comparing this to a C/C++ program, it's much cleaner, and easier to understand.
There are a lot of supported components in Rapid-Q, like QBUTTON, QIMAGE, QFILESTREAM,
etc. There are also some which aren't supported, that's the restriction involved
in using Rapid-Q. Components are created exactly the same way
you create variables, by using DIM. Each component has its own properties,
methods and events. Properties are like the component's attributes.
For example, Left, Top, Width, and Height are properties common
to all visible controls, which define its placement within the form or Window.
Caption is a property of type STRING. For a QFORM
component, the Caption property defines the title of that form.
Caption for a QBUTTON defines the text of that button. Caption
for something like QFILESTREAM does not exist, since a QFILESTREAM
isn't a visible component. It has its own properties. For a complete guide of
the properties, methods and events for all components, please check the Appendix section.
Here's a quick example of how you can assign properties to your components:
DIM Form AS QFORM
Form.Caption = "My Application"
Form.Left = 100
Form.Top = 100
Be careful to know which properties are Read-Only, and which ones are Write-Only.
An example of a read-only property
is the ITEMCOUNT property of a QLISTBOX. An example if a write-only
property is the ICON property of a QFORM, used to specify the
location of an icon to use as the default. Reading the Write-Only values, or
Writing to Read-Only values have no defined meaning, and may result in a compile error
or more seriously, your program crashing.
3.4 Component Methods & Events
DIM Form AS QFORM
Form.Center
Form.ShowModal
We used 2 methods here, Center, and ShowModal. The Center method
is a SUBROUTINE that accepts no parameters. What it does is center the form on your
desktop. ShowModal is actually a FUNCTION, but we ignore the return value
in this case. It's a method used to Display your form, and wait for the user to
close it. Note: Unlike some BASIC implementations, a FUNCTION can be called like a SUBROUTINE in Rapid-Q,
you just ignore the return value. This is similar to C/C++. Other methods
that you see may require some extra parameters, and some even accept an infinite
number of parameters. You can also write these in Rapid-Q yourself, but I'll
cover that topic later. So basically, methods are functions which perform a
specific task on that component. In our above example, we're centering the form, and
then displaying it.
SUB ButtonClicked
PRINT "Button was clicked"
END SUB
DIM Button AS QBUTTON
DIM Form AS QFORM
Button.Parent = Form ' Property
Button.OnClick = ButtonClicked ' Event
Form.ShowModal ' Method
Seems easy enough right? It really is. Whenever an "OnClick" message/event occurs,
the program jumps into your subroutine ButtonClicked and executes the code
you have waiting in there. The above program is complete, so you can try it out
yourself. For a list of all events that a particular component can receive, just
look at the Appendix section.
3.5 Rapid-Q Subroutines & Functions
FUNCTION FindMax (X AS INTEGER, Y AS INTEGER) AS INTEGER
IF X > Y THEN
FindMax = X '' Return value is X
ELSE
FindMax = Y '' Return value is Y
END IF
END FUNCTION
The above code is valid, as is the following:
FUNCTION FindMax (X%, Y%) AS INTEGER
IF X% > Y% THEN
FindMax = X% '' Return value is X
ELSE
FindMax = Y% '' Return value is Y
END IF
END FUNCTION
However, as you may notice, you can't have FindMax% without attaching an AS INTEGER
to the end of the function.
To pass a variable by reference, attach an @ symbol in front of your variable:
SUB StrCat (Source AS STRING, Text AS STRING)
Source = Source + Text
END SUB
A$ = "Hello"
StrCat(@A$, " World!")
PRINT A$ '-- Should print: Hello World!
Or if you prefer, you can also attach a BYREF keyword in your parameter list like so:
SUB StrCat (BYREF Source AS STRING, Text AS STRING)
Source = Source + Text
END SUB
A$ = "Hello"
StrCat(A$, " World!")
PRINT A$ '-- Should print: Hello World!
Yet another approach you can use instead (note that this is the "old" way, maintained
for compatibility reasons):
SUB Strcat (A$, B$)
A$ = A$ + B$
END SUB
A$ = "Hello"
Strcat(A$, " world!")
A$ = STACK.STR(0)
PRINT A$
The stack contains an array of integers and strings, to access the correct parameter,
you have to specify the number (from left to right). The first element being 0.
You can also pass QObjects, but you can't use it as a return value.
SUB (Button AS QButton)
Button.Left = 100
END SUB
All components/QObjects are passed by reference.
function
AverageSubtract (Dat1!() as
single) as single
'calculate and subtract average value from
function Dat1!()
Npt1 = UBOUND(Dat1!)
ARMid! = Dat1!(0)
FOR p = 0 TO Npt1-1:
ARMid! = ARMid! + Dat1!(p):
NEXT p
average! = ARMid! / Npt1
FOR I = 0 TO Npt1-1:
Dat1!(I) = Dat1!(I) - average!: NEXT I
result=average!
END sub '' function
Heh..It's working too ;-)
DefSng arg!(10) ={0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
DefSng dateTime(1 To
9) = { 1, 2, 3, 4, 5, 6, 7, 8, 9}
for i=0 to 9:
print "arg!(",i,")=",arg!(i)
: next i
abc= AverageSubtract (arg!() )
print "------------------
average=" ,abc
for i=0 to 9:
print "arg!(",i,")=",arg!(i)
: next i
print
for i=1 to 9:
print "dateTime(",i,")=",dateTime(i)
: next i
abc= AverageSubtract (dateTime )
print "------------------
avrage=" ,abc
for i=1 to 9:
print "dateTime(",i,")=",dateTime(i)
: next i
3.6 Rules of Scope
Here's what I mean:
SUB Test
DIM I AS INTEGER
I = 100
PRINT I
END SUB
DIM I AS INTEGER
I = 10
SUB Test2
PRINT I
END SUB
Test '' Call Subroutine
Test2
Here's how the scope works, for the SUB Test, the LOCAL variable I only extends
down as far as the end of that SUB block. The variable I in the main program extends
down all the way to the end of your program. That means SUB Test2 can use the global variable I because it's
within its scope. You can also redeclare the variable I in SUB Test2, in which case the local I is used
instead of the global I. Here's another situation to demonstrate the scope of variable names:
DIM I AS INTEGER
SUB Scope (I AS INTEGER)
DIM I AS INTEGER
PRINT I
END SUB
PRINT I
In fact, the line DIM I AS INTEGER
is a wasted statement, since the variable I is shadowed by the parameter
name I. Rapid-Q will warn you about this, but won't error out.
Prev Chapter
Up
Contents
Next Chapter