____ ______ / \ \ \\ | | | Scripting engine \____ ____ ___| | \/ \\ \\____/ v 0.94a / |_____|___| \ | /\ \ | | \____/ \___/\___/ \by Przemyslaw Podsiadly 1998-99
#include <std_disclaimer.h>
"I do not accept responsibility for any effects, adverse or otherwise,
that this code may have on you, your computer, your sanity, your dog,
and anything else that you can think of. Use it at your own risk."
The idea was to make a script engine for any purpose you would need.
This can be for AI in the game, for macros in an editor or whatever.
This is for things you cannot (or don't want to) have compiled
(hard-coded) inside your program. The idea was to make it easy to
learn, and though it's a C library, SeeR is (or will be) an almost
complete C/C++ compiler.
For GENERAL RELEASE INFORMATION see readme.txt. There you will find general introduction, copyright details, and information about how to install SeeR and link your program with it. There is all about seerc compiler, examples and so on.
This document is only the manual of SeeR the scripting lib.
But first I would like to explain some vocabulary. So:
#include < seer.h >
Then init SeeR (some functions may try to initialize SeeR if you haven't done this before, like compilation routines, but some may crash!):
scInit_SeeR();
Using scSeeR_Get(...) and scSeeR_Set(...) functions you may get some SeeR informations, like SeeR version and release mode (release, debug), the number of lines compiled recently. There are also some options you may alter, like optimization flags, dispatcher functions, callback function etc.
What next? You may export all symbols your scripts may use. SeeR can use any main-program function or variable (I call them symbols) you give him. Use scAdd_External_Symbol (scAddExtSym for shorter) or scAdd_Member_Symbol to do this.Examples:
scAdd_External_Symbol("printf",printf); scAddExtSym(scanf);//this is the shorter version scAdd_External_Symbol("cls",my_clear_screen);//the names can differ
In the script you can import also class member functions. But to import such a function your main program does not have to be written in C++. With non-objective C you can have objective scripts without any problems. Below you see two member-functions imported: from the normal C++ member and from the C function pretending to be member-function.
scAdd_Member_Symbol("string.append",string::append); scAdd_Member_Symbol("string.operator[]",string_operatorINDEX);
You may also make some internal headers. In a script you can #include files (like #include "file.h") or include special internal headers (#include internal). The internal header is just a string (char *) in the program, which contains what a normal header files use to.
You can provide also custom dispatchers (quite advanced, only for experienced, but see exclassc for details).
When you have a script-source, you may compile it. The compiled script is stored in a variable of type scScript. There are two special functions for this : scCompile_File and scCompile_Text. Examples:
scScript s1,s2;or the text versions1=scCompile_File("script.sc");
if (!s1) {printf("Error during compilation:\n%s\nIn line:%s\n",scErrorMsg,scErrorLine); exit(scErrorNo); }
s2=scCompile_Text( "#title \"The textual script\"\n""import int printf(char *,...);\n"
"export Info;\n" "export life;\n"
"int life=21;\n"
"int Info(int age)\n" "{\n" " life+=age;\n" " printf(\"I'm Goldfryd. I'm %d years old.\",life);\n" " return life;\n" "}\n" );
if (!s2) {printf("Error during compilation:\n%s\nIn line:%s\n",scErrorMsg,scErrorLine); exit(scErrorNo); }
Now create instances (scCreate_Instance) for the scripts (each script can have plenty of them). The instance is of type scInstance. Here the script s2 has two instances: in1 and in2.
scInstance *in1,*in2;in1=scCreate_Instance(s2,"");
if (scErrorNo) //in scErrorNo there is an error numer printf("Runtime error :\n%s\n",scErrorMsg);
in2=scCreate_Instance(s2,"");
if (scErrorNo) printf("Runtime error :\n%s\n",scErrorMsg);
Since now you can access variables from the instances, call functions,
and so on. You can do even multitasking (several instances running together
in peace).
The first thing is that the symbol has to be exported.
That is done in the script-source using keyword export:
export life; int life=21;To access such a function/variable, the program has to find out its address. You do it with scGet_Symbol.
scVar(in1,scGet_Symbol(in1,"life"),int)=24; or scNameVar(in1,"life",int)=24;Or, when you access the variable more often, you can get the address only once to make it faster:
int address=scGet_Symbol(in1,"life");To call a function:for(i=0;i<50;i++); scVar(in1,address,int)=i;
i=scCall_Instance(in1,scGet_Symbol(in1,"Info"),1);Above, the 1 is the parameter to script-function Info. This is the normal way of calling. In this situation SeeR knows how many arguments the function Info needs.
int argument=1; i=scVCall_Instance(in1,scGet_Symbol(in1,"Info"),sizeof(int),&argument);This function does not take the arguments to script-function explicitly, but needs the pointer to arguments. That's why &argument is given.
When you are finished with this, you can deallocate instance with
scFree_Instance(in1); scFree_Instance(in2);The script you deallocate with standard C free:
free(s1); free(s2);
#define SeeR_VERSION 100
#define SeeR_VERSION_STR "1.00"
#define SeeR_DATE 20000101
#define SeeR_DATE_STR "2000-01-01"
The SeeR defines SeeR version and date. To obtain numeric version, write:
SeeR_VERSION/100.0SeeR_DATE stores the date in yyyymmdd format. There are also string versions of above (*_STR).
void scInit_SeeR(void)
Initialises the SeeR library. A good thing is to call this before any
play with SeeR. But you may also forget it. Some functions just check if
SeeR has been inited, and if not they init it (so call this function).
int scSeeR_Get(int,...);
This function is provided for common unified method of getting
state of SeeR.
The first parameter is the option which state you want to get.
Following parameters are just parameters to those options.
This is the list of valid get-only options. If it is not stated explicitly what parameters they require, they take no parameters.
This is the list of valid set-only options. If it is not stated explicitly what parameters they require, they take no parameters.
if (!scSeeR_Set(scSeeR_OpenDebug,"debug.txt")) {printf("Unable to start debugging.!\n");exit(1);}if (scSeeR_Get(scSeeR_Debugging)) {scSeeR_Set(scSeeR_CloseDebug);}
scSeeR_Set(scSeeR_StackSize,512);
WARNING: Debug does work only in debug version of library. In release version these 3 functions do completely NOTHING. This restriction is set for speed reasons.
void scOpen_Debug(char *filename);
Opens a debug file named filename and toggles debugging on.
This can be also done with -->scSeeR_Set.
void scClose_Debug();
Closes debug file and also turns debugging off.
This can be also done with -->scSeeR_Set.
scScript scCompile_File(char *);
scScript scCompile_Text(char *);
Compiles the source loaded from File or from memory (stored simply as
char* ended with 0).
Return the compiled script in scScript (which is btw. simply a char*).
If return NULL, that means something went wrong. The scErrorNo contains the info on this.
scScript scLoad_Script(char *);
This one only loads precompiled (e.g using SeeRC) script to memory. It's
now ready to be used as instance.
It can be useful when you have many scripts and compilation of them take
some time or you don't want final users to change them. In these situations
you simply compile the script using SeeRC (or WSeeRC) or with your custom-
built "level-designer", or something...
This function is very simple thingy. As this loads only from normal files, you may be in need of loading a script from for example datafile. You may implement it very easly. Follow this (I hope I'm not wrong somewhere there):
scScript MyLoad(char *filename) {int size=my_file_size(filename); scScript JA=malloc(size+1); MyFile *f=my_open_file(filename); my_fileread(f,JA,size); my_close_file(f); JA[size]=0;//remember to add this!! }(if you have problems, see to the sources before mailing me;-)
scInstance* scCreate_Instance(scScript script,char* variables,...);
To run a script, first you have to create instance of it using this routine.
Having an instance, you can then call any function, access any variable from
the script.
(Not implemented:)
Variables is a list of variables in script you want to initialize with
specific values,like this:
Character* Human[2]; Human[1].inst=scCreate_Instance(scrpt,"this group",&Human[1],1);
void scFree_Instance(scInstance *sci);
Frees memory allocated to the instance (WARNING:first it should be killed
if in multitasking mode!!!).
int scGet_Script_Size(scScript);
Returns size of script in bytes (e.g. for storing in file), or 0 if not
a valid SeeR script.
scInstance* scGet_This();
Returns scActual_Instance, that is an instance being actually run
(the instance that called an imported function calling scGet_This).
If none is actually running, it returns NULL.
scInstance* scActual_Instance;
This is set every time you call scCall_Instance, scVCall_Instance and
for every instance in scContinue_Instances. When these functions exit,
it's set to NULL. It points to an instance being actually executed.
int scGet_Symbol(scInstance*,char *);
Returns an address of specified symbol in instance - not a valid pointer,
just address relative to the script address. It may be different for
two different instances of the same script, but doesn't change in time.
So you can read address only once per instance, and then use stored address
(that will significantly increase speed of accessing variables and calling
functions).
If symbol hasn't been found in the instance, it returns -1.
int scCall_Instance(scInstance*,int address,...);
Starts a function from specified address in the script. Parameters after
address are parameters to this function. The function address can be obtained
using scGet_Symbol(...),e.g.
x=scCall_Instance(inst,scGet_Symbol(inst,"move"),10);//10 is a parameterThe function returns the return value of this function (only if it's 4-bytes long, so it cant be long long, double or struct). It also sets -->scErrorNo if any error happens during execution.
int scVCall_Instance(scInstance* inst,int address,int paramc,int *params);
Alike previous function it calls a function, but parameters are passed
via params pointer(paramc is size of parameters in BYTES).
void scStart_Instance(scInstance *,...);
Starts `main' function in the script.
macro scVar(scInstance* inst,int adr,type)
Macro for accessing a variable exported in script of inst-instance. e.g x=scVar(inst,scGet_Symbol(inst,"x"),int); or scVar(inst,scGet_Symbol(inst,"x"),int)=5;
macro scNameVar(scInstance *ins,char *name,type)
This macro is just shortcut for: scVar(ins,scGet_Symbol(ins,name),type).
void scAdd_Internal_Header(char *name,char *contents);
Specifies the include contents of a header "file" that can be included
in script using #include name (without ""!).
void scAdd_External_Symbol(char *,void *);
Specifies the symbol (function or variable) you give (export to)
your scripts.
This affects all instances & scripts.
e.g.
Add_External_Symbol("printf",printf); //for a function Add_External_Symbol("gamelogic",&gamelogic);// for a variable
Add_Member_Symbol("NPC.move",NPC::move);
char* scGet_Title(scScript);
char* scGet_Author(scScript);
char* scGet_Instance_Title(scInstance*);
Retrieves author and title information out of the script or instance.
Not existing scGet_Instance_Author(i) would be equivalent to
scGet_Author(i->code).
void scStandardDispatcher
(int *result,void *function,int *params,int paramcount,unsigned int options);
Dispatchers have been introduced in SeeR 0.93. It happened that I wanted
SeeR to be used in a bigger project. And they wanted it to be portable.
Problem! While I had written routines for calling functions/member functions
for GCC and VC on Intels only, to make it portable I wrote some C equivalents.
But they are still not portable (they would although work on many systems).
That's why I made DISPATCHERs. This is the way to let the user implement
the calling convention mechanism himself.
When you import a function normally, the dispatcher # 0 will be used to call it (which is btw scStandardDispatcher). But when you use "import(1)", the dispatcher # 1 will be used. SeeR implements both dispatchers number 0 and 1. You may implement some more dispatchers - up to 15 (14 should be enough for everyone ;-).
So the dispatcher must be something like this:
typedef void (*scFunctionDispatcher) (int *result,void *function,int *params,int paramcount,unsigned int options);What the arguments mean:
void scCDispatcher (int *result,void *function,int *params,int paramcount,unsigned int options) { if (options&scDispatch_Member) {//C++ call - convert to typical C call, so 'this' is the first param. options^=scDispatch_Member;//erase member flag } //call the default dispatcher scStandardDispatcher(result,function,params,paramcount,options); }and somewhere below I set scCDispatcher as dispatcher # 1:
scSeeR_Set(scSeeR_Dispatcher,1,scCDispatcher);
bool scIgnore_Rights;
If true, makes all the functions ignore priorities at all, even if they
check the priority via scPriority_Guard or scKernel_Only.
void scSet_Priority(scInstance*, int priority_level);
Sets the priority to an instance. Priority is simply an int number.
Here are the standard values:
scrights_USER 0 lowest priority scrights_KERNEL 256 scrights_TOP MAXINT maximum priority - no instance is being run
int scGet_Actual_Priority();
=scGet_Priority(scActual_Instance);
#define scPriorityGuard(priority,rets)
This macro is to be used in functions that are protected, i.e that
cannot be called by instances that do not have enough priority.
This sets a runtime error and returns rets (can be `;' for functions
returning void). See exmulti.
#define scKernelOnly(rets)
=scPriorityGuard(scrights_KERNEL,rets);
Multitasking mode is a simple way to run many instance at the same time. For example, when you make RPG engine, each character (NPC) has it's own instance running. He is also able to have more instances of the same script operating on the same data (by forking).
The scheduler (scScheduler) contains list of all running instances (processes). It is used by scContinue_Instances() to run all of them. Now you are able to switch schedulers, so you can set up two or more schedulers being run in different frequency. For example you can have scheduler for real-time instances, that move characters, and more rare ones, that do more complex operations, like working out the main tactics and sending orders to computer's characters. In regulation-systems this is called a layer model (OK, maybe it has a different term in English, I only know the Polish terms in this matter :-(.
scScheduler* scGet_Scheduler();
Returns actual scheduler.
scScheduler* scSet_Scheduler(scScheduler*);
Sets new scheduler. It returns the previous one.
If you pass NULL to it, it'll create a new empty one.
void scPause_Instance(scInstance*,int pause);
If (pause) freezes the instance in scheduler queue, else unfreezes.
Freezed (paused) instance is not processed by the scheduler.
void scKill_Instance(scInstance*);
Removes an instance from the scheduler queue - it won't run in all
further calls of scContinue_Instance until next scLaunch_Instance.
int scGet_Instance_Status(scInstance *);
Returns status of an instance:
scstatus_FREE - instance is not run or does not exist scstatus_RUNNING - it's in scheduler and is not paused scstatus_PAUSED - it's paused
int scLaunch_Instance(scInstance* inst,int spd,int address,...);
Tells SeeR scheduler that you want the instance and function at
address to be processed in multitasking mode. It's not executed
yet. You have to call scContinue_Instances to execute the scheduler -
a list of instances (you can launch many simoultanously running different
instances).
WARNING:You cannot launch previously launched and not killed instance!!!
(to launch instance twice at the same time, use forking-desc. below)
The error will be returned.
The spd parameter is speed of instance running
(ie spd=10 - every 10th instruction or WAIT instruction, scheduler
freezes instance and calls next one in scContinue_Instances function).
int scContinue_Instances(void);
Continues running all previously launched instances. Returns number of
running instances (ie 0 if none). If it returns -1 - an error must have
occured during process of running any instance. Flag scErrorNo is then
set to appropriate error value. The instance that caused a problem is
removed (killed) from the running queue and scheduler doesn't process further
instances till the next call of scContinue_Instances.
Fork is a way to create instances from already existing instance (parent).
But these instances aren't typical - they use the same data segment as it's
parent. There are many ways to fork an instance and operate on them.
Each forked instance has it's number.
scInstance* scFork_Instance(scInstance*);
It's one of the ways to create a forked instance. It returns forked instance,
that has it's number (identifying it). Now these instances (parent and child)
can be executed independently. They share only common data segment (global
script variables).
scInstance* scGet_Forked(scInstance* parent,int no);
Returns instance forked from parent and has number no. If there is not
such an instance, it returns NULL.
scInstance* scGet_Actual_Forked(int);
The same as scGet_Forked, but for actually running instance (scGet_This()).
void scKill_Forked_Instances(scInstance* parent);
Kills and frees (scFree_Instance) all instances forked from parent. Of
course you can also kill each forked one by one. When you kill an
instance that has children (forks), one of children will become a parent
of others.
int scGet_Forked_Status(int);
void scKill_My_Forked_Instances();
void scKill_Forked(int);
All these functions operate on scActual_Instance. They do
what is done by scGet_Instance_Status, scKill_Forked_Instances and
scKill_Instance, but operate on scActual_Instance or it's forks.
When the compilation finishes, in scErrorNo holds the status of operation. Also after creating or executing an instance scErrorNo is set.
WARNING: all compile, run (call & continueing intance) instructions clear scErrorNo flag at their begining!
int scErrorNo;
May holds following value:
char *scErrorLine;
Here is stored a copy of line that caused an error (valid if error appeared
during compilation).
The language is almost like C. See restrictions for not implemented features of the language.
NOTE: when I write something in {}, it does not mean you have to put this in {}, but I want to accent that it's not a keyword. So
import {declaration}may extend to
import int x;and not
import {int x;}
keyword import
Usage:
import {declaration}
import (dispatcher_number) {declaration}
import (dispatcher_number)(import_name) {declaration}
The declaration of imported from outside (the program) function or variable. Default import uses dispatcher 0.
In the second version (with a number) you can explicitly put the dispatcher number. See also dispatcher.
WARNING:dispatcher 0 and 1 are both implemented in SeeR and we recommend you don't change them. Use 2nd and above (up to 15).
If you want to import functions with the same name, but different parameters, you will have problem with import names (they will be the same). In such situation you use the third variant, where you can explicitly state the import name. Example:
class string{ import string operator+(string& x); import(operator+(char*)) string operator+(char *x); };
Specifies symbol (function or variable) that can be accessed from outside the script. Example: script.sc
export main; int go() {printf("go()\n");return 0;} int main() {printf("main()\n");return 1;}In prog.c you may use
i=scCall_Instance(in,scGet_Symbol(in,"main"));but not
i=scCall_Instance(in,scGet_Symbol(in,"go"));(where in is a valid scInstance* ).
keyword secured
Usage:
secured statement
The group of instructions specified after `secured' are embrased with CLI ... STI (virtual opcodes, not processor) - this group (and all functions called inside) cannot be interrupted while multitasking. This can be helpful when you compute some numbers inside a script, and while doing so script is interrupted and you use those numbers, they may contain quite undefined values.
keyword __vcpu
Usage:
__vcpu(i1,...)
Generate VCPU opcode(s) specified as integers, eg. 56 - wait 57 - cli 58 - sti 61 - nop
CAUTION: wait (opcode 56) has to be passed alone, e.g __vcpu(57,56,58); won't work OK(but separately 3 x __vcpu will)!!!
WARNING: Better not use it other way that via macro WAIT. The numbers, that SeeRVitualCPU stores its instructions may change in next version of SeeR.
keyword fork
Usage:
fork statement
fork (int_variable) statement
Only in multitasking mode: creates fork instance that will execute the statement and exit while actual instance continues.
See also forking in Multitasking section above.
The int_variable will contain the number of forked instance, so later we can check if it has finished.
Example
int main(int c) {int i,x,y; fork(i) //creates new process {int l; for (l=0;l<100;l++)x=l*2; } y=5*c+12; while (scGet_Forked_Status(i));//wait till fork ends. //we can also fork like below, when we don't care about the number of forked inst. fork y+=x;//equal to: fork {y+=x;} }
Sets the author to be stored in script. This information may be retrieved with scGet_Author.
Examples:
#author "William Shakespeare"or
#author Billy(but not #author William Shakespeare! (that's more than one word) directive #title
Sets the title to be stored in script. This information is used in error-reporting. It may be retrieved with scGet_Title.
keyword typeof
Usage:
typeof(type-declaration)
Returns text description of a type, e.g.
"int" "double*" "char[256]" "struct{int int int}" "script{name name name}"It was created specially for the type script. When you initialize the script, you have to pass the 'typeof' to the function that does it, so that it knows which functions or variables you may need.
type script
There was always a problem how to easy communicate between scripts.
To solve this I created the script type.
#define SeeR "1.00" // the current version
#define WAIT __vcpu(56)
#define NULL (void *)0
#define c_import import(1)
directive #include
Usage:
#include "file"
#include internal-header
Internal headers is a feature of SeeR, that lets you make a header-file inside your program as (char *) variable. Use scAdd_Internal_Header to let SeeR know about specific header (and to assign it a name).
Structures can be declared in C++ way:
struct TYPE_NAME{ ... };
void Foo(struct TYPE_NAME x);but simply in a C++ way
void Foo(TYPE_NAME x);So all those typedefs to make the life easy are now unnecessary.
List of unimplemented C features:
#include Instances
This header is used to make some operations on SeeR instances (other than
fork) available in scripts as a standard. The instructions don't operate on
true scInstance*, so they seem safe that one instance won't kill all the
others.
char *hdrInstances= " #ifndef SeeR_Internal_Instances #define scstatus_FREE 0 #define scstatus_RUNNING 1 #define scstatus_PAUSED 2import void scKill_My_Forked_Instances(); import void scKill_Forked(int); import int scGet_Forked_Status(int); import int scGet_Actual_Priority(); #define SeeR_Internal_Instances #endif ";
char *hdrKernel= " #ifndef SeeR_Internal_Kernel #include Instances //can call all imported kernel API function #define scrights_KERNEL 256 //cannot --- #define scrights_USER 0 //when no instance is being run: #define scrights_TOP MAXINTtypedef void scInstance; typedef void* scScript; import scInstance* scCreate_Instance(scScript,char*,...); import scInstance* scFork_Instance(scInstance*); import void scFree_Instance(scInstance *);
import scScript scCompile_File(char *); import scScript scCompile_Text(char *); import scScript scLoad_Script(char *);
import scInstance* scGet_This(); import scInstance* scGet_Forked(scInstance*,int); import scInstance* scGet_Actual_Forked(int); import void scPause_Instance(scInstance*,int); import void scKill_Instance(scInstance*); import void scKill_Forked_Instances(scInstance*);
import int scGet_Script_Size(scScript); import int scCall_Instance(scInstance*,int address,...); import int scVCall_Instance(scInstance*,int,int,int*); import int scStart_Instance(scInstance *,...); import int scGet_Symbol(scInstance*,char*); import int scLaunch_Instance(scInstance* inst,int spd,int address,...);
import void scSet_Priority(scInstance*, int priority_level); import int scGet_Priority(scInstance*);
#define SeeR_Internal_Kernel #endif ";
string x,y="eagle"; x=y+" is flying"; //You can normally pass it as char*. printf("%s\n",x); if (y=="eagle") y="hawk"; x=y+" and "+x; printf("%s\n",x(5,3));//"and" if (x(9,5)=="eagle") is_eagle=1;
vector x(1,2,3),y(3,4,5); x+=y; if (x+y>vector(10,11,12)) {x-=y;} else {x+=y;}
hashInt x; (int)x[1000000]=1; (int)x[-100000]=-1; if (x.exists(1000000)) printf("OK.\n");
hashStr x; (int)x["Jola"]=1; (int)x["Jas"]=-1; if (x.exists("Yaga")) printf("Danger\n");
char *hdrStdLib= " #ifndef SeeR_Internal_StdLib #include Instances/* class string */ class string{
public:
char *cstr;
c_import(string) string(); c_import(string_SZ) string(char *x); c_import(string_I) string(int x); c_import(stringCC) string(string& f);
c_import ~string();
c_import(operator=(int)) string& operator=(int x); c_import string& operator=(string& s); c_import(operator=(char*)) string& operator=(char *s);
c_import string operator+(string& x); c_import(operator+(char*)) string operator+(char *s);
c_import string sub(int start,int len); c_import string operator()(int start,int len);
c_import int cmp(string& x); c_import bool operator==(string& x); c_import bool operator!=(string& x); c_import(operator==(char*)) bool operator==(char *x); c_import bool operator>(string& x); c_import bool operator<(string& x); c_import bool operator>=(string& x); c_import bool operator<=(string& x); c_import void operator+=(string& x); c_import(operator+=(char*)) void operator+=(char* x);
c_import void del(int start,int len); c_import void insert(int start,string& x); //index of first found occurance c_import int find(string& x); //returns number of replaces //when global==false, it replaces only once c_import int replace(string& what,string& with,bool global=false); //returns length of a string c_import int length();
/* operators */ c_import int toInt();//toint c_import int operator(int)();//toint c_import char& operator[](int idx); /* for future, actually does nothing */ c_import void reconstruct();
// class hashInt class hashInt{ public: c_import hashInt(); c_import ~hashInt();
c_import void*& operator[](int id);
c_import void add(int id,void *data); c_import bool exists(int id); c_import void *remove(int id); c_import void *get(int id);
c_import bool empty();
c_import int first(); c_import int next();
};
// class hashStr class hashStr{ public: c_import hashStr(); c_import ~hashStr();
c_import void*& operator[](char *id);
c_import void add(char* id,void *data); c_import bool exists(char* id); c_import void *remove(char* id); c_import void *get(char* id);
c_import bool empty();
c_import char *first(); c_import char *next(); };
struct vector{ double x,y,z; public: c_import(vectorVOID) vector(); c_import vector(double,double,double); c_import(vectorCC) vector(vector& v);
c_import vector& operator=(vector& v);
c_import vector operator+(vector& v); c_import vector operator-(vector& v); c_import vector operator*(vector& v);//cross product
c_import void operator+=(vector& v); c_import void operator-=(vector& v); c_import void operator*=(vector& v);
c_import bool operator==(vector& v); c_import bool operator<(vector& v); c_import bool operator>(vector& v); c_import bool operator<=(vector& v); c_import bool operator>=(vector& v);
c_import void normalize(); c_import double length();
};
#define SeeR_Internal_StdLib #endif "
That's all for now (sorry if you find it not complete).
If you find something unclear in the documentation, first look
at the examples. They show almost every feature of SeeR. Then,
if you're still confused, email me.
By Przemyslaw Podsiadly (just Przemek)
12 Modrzewiowa Street,
08-110 Siedlce, Poland.
http://home.elka.pw.edu.pl/~ppodsiad/seer/