quakeforge/tools/qfcc/doc/qfcc.lyx

1455 lines
26 KiB
Plaintext

#LyX 1.1 created this file. For more info see http://www.lyx.org/
\lyxformat 218
\textclass scrbook
\language american
\inputencoding latin1
\fontscheme pslatex
\graphics default
\paperfontsize 12
\spacing single
\papersize Default
\paperpackage a4
\use_geometry 1
\use_amsmath 0
\paperorientation portrait
\secnumdepth 2
\tocdepth 2
\paragraph_separation skip
\defskip medskip
\quotes_language english
\quotes_times 2
\papercolumns 1
\papersides 2
\paperpagestyle headings
\layout Title
The Ruamoko Programming Language
\layout Author
Bill Currie
\begin_inset Formula \( \bullet \)
\end_inset
Jeff Teunissen
\layout Publishers
QuakeForge Press
\newline
;-)
\layout Uppertitleback
This manual is free; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
\newline
\newline
This manual is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
\newline
\newline
You should have received a copy of the GNU General Public License along
with this manual: if not, write to:
\newline
\newline
Free Software Foundation, Inc.
\newline
59 Temple Place - Suite 330
\newline
Boston MA 02111-1307
\newline
USA
\layout Lowertitleback
Copyright © 2002 Bill Currie and Jeff Teunissen
\layout Standard
\begin_inset LatexCommand \tableofcontents{}
\end_inset
\layout Addchap
Preface
\layout Standard
In December 1996, Id Software released
\emph on
Quake
\emph default
to the world.
It's doubtful that they knew at the time that it would spark a revolution
-- but such a revolution happened.
To the game industry's surprise, people were getting the game not just
to play it, but to
\emph on
change
\emph default
it\SpecialChar \@.
For the first time, people could make whole new games based on the Quake
engine without having to rewrite the whole game -- and in fact you couldn't
rewrite the whole game, because the main source code wasn't available to
the general public.
What
\series bold
was
\series default
available was something new -- the game wasn't just a game, it was a virtual
machine that had a byte-code instruction set -- and it had a compiler that
you could use to make new games to run inside that engine.
The language (called
\emph on
QuakeC
\emph default
) was kind of crude, and the compiler was even more crude -- but it was
a revolutionary development.
\layout Standard
Now, let's fast-forward to another December -- this time, December 1999.
In another revolutionary move, Id Software released the source code to
the complete Quake engine.
This gave many people the opportunity to do a lot more than just make
\begin_inset Quotes eld
\end_inset
mods
\begin_inset Quotes erd
\end_inset
for Quake.
Instead, people could make all-new games without using Quake itself.
Many projects started up around this source code, with many aims\SpecialChar \ldots{}
but one
project grew to be the most dominant: That project is
\emph on
QuakeForge
\emph default
.
\layout Standard
QuakeForge has developed a number of interesting things involving the Quake
engine, but most of them are beyond the scope of this manual.
This manual documents the
\emph on
Ruamoko
\begin_float footnote
\layout Standard
The name Ruamoko comes from the Maori name for their god of volcanoes and
earthquakes.
According to myth, Ruamoko is not yet born, and when he shakes inside the
Earth-mother, the world shakes.
\end_float
language, a language based on Id Software's QuakeC, but which has been
expanded in ways far beyond the original language.
\layout Standard
The idea behind this book is to give new programmers a solid foundation
in both of the programming models (procedural and object-oriented) supported
by the Ruamoko language, while giving experienced Ruamoko programmers a
complete reference for development of game code.
\layout Chapter
A Tutorial Introduction
\layout Standard
Let us begin with a quick introduction to Ruamoko.
Our aim here is to show the basic elements of the language in real programs,
but without getting bogged down in details or rules.
At this point, we're not even trying to be complete, or even precise (except
that the examples are meant to be correct).
We want to get you as quickly as possible to the point where you can write
useful programs, and to do that we have to concentrate on the basics: variables
and constants, arithmetic, flow control, functions, and the rudiments of
input and output.
We are intentionally leaving out of this chapter features of Ruamoko that
are important for writing bigger programs, or programs to run in an actual
Quake engine.
These include entities, structures, pointers, most of the operators, objects,
and the standard builtin library.
\layout Standard
This approach has its drawbacks.
Most notable is that the complete story on any particular language feature
is not found here, and the brief tutorial, just by being brief, may be
misleading.
And because the examples don't use the full power of Ruamoko, they may
not be as elegant or concise as they could be; we
\series bold
have
\series default
tried to minimize these effects, but be warned.
Another drawback is that later chapters will repeat some of what's presented
here.
We hope that the repetition will help more than it annoys.
\layout Standard
In any case, experienced programmers should be able to get an idea, from
this chapter, of some of the things that can be done in Ruamoko, for their
own needs.
Beginners should supplement it by writing small, similar programs of their
own.
Both groups can use it as a framework on which to hang the more detailed
descriptions that begin in later chapters.
\layout Section
Getting Started
\layout Standard
The best way to learn a new programming language is by writing programs
in it.
The first program one writes is almost always the same for all new languages:
print the phrase
\begin_inset Quotes eld
\end_inset
Hello, world!
\begin_inset Quotes erd
\end_inset
on the screen.
\layout Standard
This is the big hurdle.
To get past it, you have to be able to create the program text somewhere,
compile it, load it successfully, load it, run it, and find out where the
output went.
With these mechanical details mastered, everything else is relatively easy.
\layout Standard
In Ruamoko, the program to print
\begin_inset Quotes eld
\end_inset
Hello, world!
\begin_inset Quotes erd
\end_inset
is:
\layout LyX-Code
#include <qwaq/globals.rh>
\newline
#include <qwaq/fields.rh>
\newline
#include <qwaq/builtins.rh>
\newline
\newline
void () main =
\newline
{
\newline
printf ("Hello, world!
\backslash
n");
\newline
};
\layout Standard
To run this program, you first have to compile it.
To compile it, you need to save the source code into a file (for example,
\family typewriter
hello.r
\family default
), and create a
\family typewriter
progs.src
\family default
file to tell the compiler how to compile it.
Here is an example
\family typewriter
progs.src
\family default
file:
\layout LyX-Code
qwaq.dat
\newline
hello.r
\layout Standard
The first line of
\family typewriter
progs.src
\family default
tells the compiler the name of the compiled object file that it is supposed
to save to disk after compilation.
Following lines tell it the names of files that are to be used to compile
that object file.
To compile the source, issue the command
\layout LyX-Code
qfcc
\layout Standard
If you haven't screwed anything up, such as omitting a character or misspelling
something, the compilation will proceed silently.
You should be rewarded with something that looks something like the following:
\layout LyX-Code
208 strofs
\newline
4 statements
\newline
14 functions
\newline
30 globaldefs
\newline
0 locals size ((null))
\newline
8 fielddefs
\newline
52 pr_globals
\newline
6 entityfields
\newline
1316 TOTAL SIZE
\newline
Compilation time: 0.0365 seconds.
\layout Standard
You run
\family typewriter
qwaq.dat
\family default
by issuing the command
\layout LyX-Code
qwaq
\layout Standard
the program should print
\layout LyX-Code
Hello, world!
\layout Standard
to your screen.
\layout Standard
Now, for some explanations regarding the program itself.
All Ruamoko programs, regardless of size, consist mainly of
\emph on
functions
\emph default
and
\emph on
variables
\emph default
.
A function contains statements that tell the compiler what computing operations
you want to do, and variables store values used during the operation of
the program.
Ruamoko functions are roughly equivalent to C's functions, or Pascal's
procedures and functions.
Our example is a function called
\family typewriter
main
\family default
.
You can create functions with just about any name you like, but
\begin_inset Quotes eld
\end_inset
\family typewriter
main
\family default
\begin_inset Quotes erd
\end_inset
is special -- program execution begins there
\begin_float footnote
\layout Standard
This is not precisely true.
When used in a game engine, there are certain other functions that are
called by the engine during the course of a game.
\end_float
.
This means that every program must have a
\family typewriter
main
\family default
function somewhere.
\layout Standard
Main will usually call other functions to do its job -- some of them you
write, and some of them are provided by the virtual machine your program
runs inside.
The first lines of the program,
\layout LyX-Code
#include <qwaq/globals.rh>
\newline
#include <qwaq/fields.rh>
\newline
#include <qwaq/builtins.rh>
\layout Standard
tell the compiler to include information about the standard variables, constants
,
\emph on
fields
\emph default
, and
\emph on
builtins
\emph default
(also known as
\emph on
engine functions
\emph default
) provided by the environment
\begin_float footnote
\layout Standard
The environment will be described later.
\end_float
.
\layout Standard
One way of communicating data between functions is for the calling function
to provide a list of values, called arguments, to the function it calls.
The parentheses after the function's name surround the argument list.
In this example, main is defined to be a function that expects no arguments,
which is indicated by an empty list:\SpecialChar ~
\family typewriter
()
\family default
.
\layout Standard
The statements of a function are enclosed in curly braces,\SpecialChar ~
\family typewriter
{}
\family default
.
The function
\family typewriter
main
\family default
contains only one statement,
\layout LyX-Code
printf ("Hello, world!
\backslash
n");
\layout Standard
A function is called by giving its name, followed by a list of arguments
enclosed by parentheses, so this calls the function
\family typewriter
printf
\family default
with the argument
\family typewriter
"Hello, world!
\backslash
n"
\family default
.
\family typewriter
printf
\family default
is a builtin function that prints output, in this case the string of characters
between the quotes.
\layout Standard
A sequence of characters between double quotes, like
\family typewriter
"Hello, world!
\backslash
n"
\family default
, is called a
\emph on
string constant
\emph default
or simply a
\emph on
string
\emph default
.
For the moment, our only use of strings will be as arguments for
\family typewriter
printf
\family default
and other functions.
\layout Standard
The sequence
\family typewriter
\backslash
n
\family default
in the string is Ruamoko notation for the
\emph on
newline character
\emph default
, which when printed tells the terminal (or a game client) to advance to
the next line in the output.
If you leave out the
\family typewriter
\backslash
n
\family default
, you will find that there is no advance after the character string is printed.
You must use
\family typewriter
\backslash
n
\family default
to include a newline character in the printf argument; if you try something
like
\layout LyX-Code
printf ("Hello, world!
\newline
");
\layout Standard
the Ruamoko compiler will give you an error message.
\layout Standard
\family typewriter
printf
\family default
never supplies a newline automatically, so several calls may be used to
build up an output line in stages.
Our first program could just as easily been written as
\layout LyX-Code
#include <qwaq/globals.rh>
\newline
#include <qwaq/fields.rh>
\newline
#include <qwaq/builtins.rh>
\newline
\newline
void () main =
\newline
{
\newline
printf ("Hello, ");
\newline
printf ("world!");
\newline
printf ("
\backslash
n");
\newline
};
\layout Standard
and it would have produced identical output.
\layout Standard
Note that
\backslash
n represents only a single character.
An escape character like
\backslash
n gives you a general way to express hard-to-type or invisible characters.
Among the others are
\backslash
t for a tab,
\backslash
b for a backspace,
\backslash
" for a double-quote, and
\backslash
\backslash
for the backslash character itself.
There is a complete list in [section]
\layout Section
Variables and Mathematical Expressions
\layout Chapter
Language Reference
\layout Standard
This is currently just new stuff in
\family typewriter
\series bold
qfcc
\family default
\series default
.
\layout Section
New Type Features
\layout Subsection
New Types
\layout List
\labelwidthstring 00.00.0000
\family typewriter
integer
\family default
32 bit signed integer
\layout List
\labelwidthstring 00.00.0000
\family typewriter
id
\family default
generic object pointer
\layout List
\labelwidthstring 00.00.0000
\family typewriter
Class
\family default
class object pointer
\layout List
\labelwidthstring 00.00.0000
\family typewriter
Protocol
\family default
protocol object pointer
\layout List
\labelwidthstring 00.00.0000
\family typewriter
Method
\family default
method pointer
\layout List
\labelwidthstring 00.00.0000
\family typewriter
SEL
\family default
selector
\layout List
\labelwidthstring 00.00.0000
\family typewriter
IMP
\family default
message implementation
\layout Standard
\family typewriter
id
\family default
,
\family typewriter
Class
\family default
,
\family typewriter
Protocol
\family default
,
\family typewriter
Method
\family default
,
\family typewriter
SEL
\family default
and
\family typewriter
IMP
\family default
are part of
\family typewriter
\series bold
qfcc
\family default
\series default
's Objective-QC extensions.
\layout Subsection
Enumerators
\layout Standard
as per C
\layout Subsection
Structures
\layout LyX-Code
struct foo {
\newline
integer bar;
\newline
float baz;
\newline
void () func;
\newline
};
\layout Standard
Structures with no elements can be declared for making opaque types (particularl
y useful for engine interface functions).
\layout Subsection
Arrays
\layout LyX-Code
integer [13] array;
\layout Subsection
Pointers
\layout Standard
Pointers are declared the same way as arrays, but with no number in the
\family typewriter
[]
\family default
s.
In fact, arrays are just pointers with limited (compile-time) bounds checking
(constant indices).
\layout Subsection
Complex types
\layout Standard
Complex types can be created by nesting type declarations within
\family typewriter
()
\family default
s.
e.g.:
\layout LyX-Code
(.float) (string name) find_field;
\layout Standard
declares a function (
\family typewriter
find_field
\family default
) taking a string parameter and returning a float field `offset'.
Without the
\family typewriter
()
\family default
s around the
\family typewriter
.float
\family default
, the declaration would be a function field.
\layout Subsection
\family typewriter
typedef
\layout Standard
By using
\family typewriter
typedef
\family default
complex types can be given symbolic names.
e.g.:
\layout LyX-Code
struct foo_s {};
\newline
typedef foo_s [] foo_t;
\layout Standard
creates type
\family typewriter
foo_t
\family default
which is a pointer to the structure
\family typewriter
foo_s
\family default
(which happens to be opaque).
\layout Subsection
Variable-argument functions
\layout Standard
Typed parameters preceding the ellipsis are allowed, e.g.:
\family typewriter
void (string fmt, ...) printf;
\layout Standard
More importantly, it is now possible to write vararg functions in QC.
\family typewriter
@argc
\family default
gives the number of parameters passed through the ellipsis and
\family typewriter
@argv
\family default
is an array of vectors representing the parameters passed through
\family typewriter
...
\family default
.
\layout Standard
\series bold
\emph on
Warning: attempting to pass
\family typewriter
@argv
\family default
to a non-engine function will not work.
This is because of changes in how local variables are handled by the compiler.
\layout Subsection
Improved type checking
\layout Standard
Function parameters and return types are are fully checked, including the
number of parameters passed to a function.
Functions with different return types and/or different parameter types
or counts are distinct types and mixing them up will cause a type mismatch
error.
Similar for pointers to various types.
\layout Section
Variables
\layout Subsection
Local variables
\layout Subsubsection
Initialization
\layout Standard
Local variables of basic types can now be initialized when declared.
e,g,
\layout Verse
\family typewriter
local integer elite = 31337;
\layout Subsubsection
Unused variables
\layout Standard
Local variables that are declared but not used produce a warning.
\layout Subsubsection
Uninitialized variables
\layout Standard
Checks are done to ensure that local variables have been initialized before
being used.
However, these checks are not perfect and false positives are very likely
in complex code.
Occurrences of false negatives are not known, but the possibility of their
existence remains and any examples of false negatives should be reported
as bugs.
\layout Subsection
Complex global variables
\layout Standard
Global array variables can be initialized using
\family typewriter
= {
\emph on
element-list
\emph default
};
\family default
.
Element lists may be nested using
\family typewriter
{}
\family default
.
Structures cannot currently be initialized, but this is a FIXME :)
\layout Subsection
Magic variables
\layout List
\labelwidthstring 00.00.0000
\family typewriter
@self
\family default
Automagically declared entity variable the engine will use for
\family typewriter
touch
\family default
and
\family typewriter
think
\family default
functions.
This allows
\family typewriter
self
\family default
to be used as the object hidden parameter in methods.
\layout List
\labelwidthstring 00.00.0000
\family typewriter
@this
\family default
Automagically declared
\family typewriter
id
\family default
field that the engine expects to point to the object associated with the
entity.
The engine will use this field, if it exists, to set the
\family typewriter
self
\family default
parameter to
\family typewriter
touch
\family default
and
\family typewriter
think
\family default
methods (the engine assumes it's calling a method rather than a function
if the @this field is used.
\layout List
\labelwidthstring 00.00.0000
\family typewriter
@argc
\family default
Number of parameters passed through
\family typewriter
...
\family default
in vararg functions.
Not valid elsewhere.
\layout List
\labelwidthstring 00.00.0000
\family typewriter
@argv
\family default
Array of vectors representing the parameters passed through
\family typewriter
...
\family default
in vararg functions.
Not valid elsewhere.
\layout Section
Code constructs
\layout Subsection
\family typewriter
break
\layout Standard
The
\family typewriter
break
\family default
statement can be used to leave a loop (
\family typewriter
while
\family default
,
\family typewriter
do
\family default
...
\family typewriter
while
\family default
, or
\family typewriter
for
\family default
) prematurely.
The
\family typewriter
break
\family default
statement is also used to leave a
\family typewriter
switch
\family default
statement.
\layout Subsection
\family typewriter
continue
\layout Standard
The
\family typewriter
continue
\family default
statement is used to jump to the beginning of a loop.
In
\family typewriter
for
\family default
loops, the test and post expressions are evaluated before continuing with
the loop.
\layout Subsection
\family typewriter
for
\layout Standard
The
\family typewriter
for
\family default
loop is:
\layout LyX-Code
for (
\emph on
initialization-expression
\emph default
;
\emph on
test-expression
\emph default
;
\emph on
post-expression
\emph default
)
\layout LyX-Code
\emph on
statement
\layout Standard
and is equivalent to
\layout LyX-Code
\emph on
initialization expression
\layout LyX-Code
while (
\emph on
test expression
\emph default
) {
\layout LyX-Code
\emph on
statement
\layout LyX-Code
\emph on
post expression
\layout LyX-Code
}
\layout Subsection
\family typewriter
switch
\layout Standard
The
\family typewriter
switch
\family default
statement is used to select between multiple code blocks based on the value
of an expression.
\layout LyX-Code
switch (
\emph on
test expression
\emph default
) {
\newline
case
\emph on
value
\emph default
:
\newline
\emph on
optional statements
\newline
\emph default
case
\emph on
value
\emph default
:
\newline
\emph on
optional statements
\emph default
\newline
default:
\newline
\emph on
optional statements
\emph default
\newline
}
\layout Standard
Code execution starts at the selected
\family typewriter
case
\family default
and continues on to the end of the switch block.
Following
\family typewriter
case
\family default
s do
\emph on
not
\emph default
affect code execution.
If this behavior is not desired, as is usual, then a
\family typewriter
break
\family default
statement is required to cause the code to jump to the end of the
\family typewriter
switch
\family default
, skipping any intervening code.
That is, just like C.
\layout Subsubsection
\family typewriter
\emph on
test expression
\layout Standard
The test expression may result in a float, string or integer value.
\layout Subsubsection
\family typewriter
case
\emph on
value
\layout Verse
\family typewriter
case
\emph on
value
\emph default
:
\layout Standard
The case value may be of any constant type consistent with the test expression
of the
\family typewriter
switch
\family default
.
\layout Subsubsection
\family typewriter
default
\layout Standard
If specified, this is where execution will go when no
\family typewriter
case
\family default
has been selected by the test expression.
If not specified, and no
\family typewriter
case
\family default
has been selected by the test expression, the
\family typewriter
switch
\family default
does not execute any code within the block.
\layout Section
Expressions
\layout Subsection
Binary
\layout List
\labelwidthstring 00.00.0000
\family typewriter
<<\SpecialChar ~
>>
\family default
bit shift left and right
\layout List
\labelwidthstring 00.00.0000
\family typewriter
^
\family default
bitwise exclusive or
\layout List
\labelwidthstring 00.00.0000
\family typewriter
%
\family default
modulus
\layout Subsubsection
Assignment
\layout List
\labelwidthstring 00.00.0000
\family typewriter
\emph on
op
\emph default
=
\family default
equivalent to
\family typewriter
a = a
\emph on
op
\emph default
b
\family default
.
\layout Subsection
Unary
\layout List
\labelwidthstring 00.00.0000
\family typewriter
~
\family default
bitwise not
\layout List
\labelwidthstring 00.00.0000
\family typewriter
&
\family default
address
\layout List
\labelwidthstring 00.00.0000
\family typewriter
++
\emph on
e
\emph default
\SpecialChar ~
--
\emph on
e
\family default
\emph default
pre-increment and decrement
\layout List
\labelwidthstring 00.00.0000
\family typewriter
\emph on
e
\emph default
++\SpecialChar ~
\emph on
e
\emph default
--
\family default
post-increment and decrement
\layout Subsection
Other
\layout List
\labelwidthstring 00.00.0000
\family typewriter
\emph on
type\SpecialChar ~
\emph default
(
\emph on
expr
\emph default
)
\family default
cast expression.
Only works for converting between integer and float types and between pointer
types.
\layout List
\labelwidthstring 00.00.0000
\family typewriter
\emph on
expr
\emph default
[
\emph on
expr
\emph default
]
\family default
array indexing.
\layout List
\labelwidthstring 00.00.0000
\family typewriter
\emph on
expr
\emph default
?
\emph on
expr
\emph default
:
\emph on
expr
\family default
\emph default
C's trinary expression
\layout List
\labelwidthstring 00.00.0000
\family typewriter
[
\emph on
expr
\emph default
\SpecialChar ~
\emph on
exprs
\emph default
]
\family default
Objective-QC message
\layout List
\labelwidthstring 00.00.0000
\family typewriter
@selector(
\emph on
exprs
\emph default
)
\family default
Objective-QC selector expression
\layout List
\labelwidthstring 00.00.0000
\family typewriter
@protocol(
\emph on
name
\emph default
)
\family default
Objective-QC protocol expression
\layout List
\labelwidthstring 00.00.0000
\family typewriter
@encode(
\emph on
type
\emph default
)
\family default
Objective-QC type encoding expression
\layout List
\labelwidthstring 00.00.0000
\family typewriter
@
\emph on
string
\family default
\emph default
Objective-QC string object.
Currently identical to a normal QC string.
\the_end