+-----------------------------------------------+ | | | Amiga E v3.1a | | Compiler for The E Language | | By Wouter van Oortmerssen | | | +-----------------------------------------------+ Contents: 0. compiler and introduction A. introduction B. the distribution C. demo restrictions, registration and sites D. using the compiler E. changes from v2.1b to v3.0a, and from v3.0a to v3.1a F. additional information 1. format A. tabs,lf etc. B. comments C. identifiers and types 2. immediate values A. decimal (1) B. hexadecimal ($1) C. binary (%1) D. float (1.0) E. character F. strings ('bla') G. lists ([1,2,3]) and typed lists H. lisp-cells () 3. expressions A. format B. precedence and grouping C. types of expressions D. function calls 4. operators A. math (+ - * /) B. comparison (= <> > < >= <=) C. logical and bitwise (AND OR) D. unary (SIZEOF ` ^ {} ++ -- -) E. triple (IF THEN ELSE) F. structure (.) G. array ([]) H. float operator (!) I. assignments expressions (:=) J. sequencing (BUT) K. dynamic memory allocation (NEW) L. unification (<=>) M. pointer typing (::) 5. statements A. format (;) B. statement labels and gotos (JUMP) C. assignment (:=) D. assembly mnemonics E. conditional statement (IF) F. for-statement (FOR) G. while-statement (WHILE) H. repeat-statement (REPEAT) I. loop-statement (LOOP) J. select-case-statement (SELECT) K. increase statement (INC/DEC) L. void expressions (VOID) M. memory deallocation (END) 6. function definitions and declarations A. proc definition and arguments (PROC) B. local and global definitions: scope (DEF) C. endproc/return D. the `main' function E. built-in system variables F. default arguments to functions G. multiple return values H. function values 7. declaration of constants A. const (CONST) B. enumerations (ENUM) C. sets (SET) D. built-in constants 8. types A. about the `type' system B. the basic type (LONG/PTR) C. the simple type (CHAR/INT/LONG) D. the array type (ARRAY) E. the complex type (STRING/LIST) F. the compound type (OBJECT) G. initialisation H. the essentials of the E typesystem 9. built-in functions A. io functions B. strings and string functions C. lists and list functions D. intuition support functions E. graphics support functions F. system support functions G. math and other functions H. string and list linking functions I. lisp-cells and cell functions 10. library functions and modules A. built-in library calls B. interfacing to the amiga system with the v39 modules C. compiling own modules D. the modulecache 11. quoted expressions A. quoting and scope B. Eval() C. built-in functions 12. floating point support A. float values B. computing with floats C. builtin float functions D. float implementation issues 13. Exception handling A. defining exception handlers (HANDLE/EXCEPT) B. using the Raise() function C. defining exceptions for built-in functions (RAISE/IF) D. use of exception-ID's 14. OO programming A. OO features in E B. object inheritance C. data hiding (EXPORT/PRIVATE/PUBLIC) D. methods and virtual methods E. Constructors, Destructors and Super-Methods (NEW,END,SUPER) 15. inline assembly A. identifier sharing B. the inline assembler compared to a macro assembler C. ways using binary data (INCBIN/CHAR..) D. OPT ASM E. Inline asm and register variables 16. technical and implementation issues A. the OPT keyword B. small/large model C. stack organisation D. hardcoded limits E. error messages, warnings and the unreferenced check F. compiler buffer organisation and allocation G. register allocation 17. Essential E Utilities / Applications A. ShowModule B. ShowHunk C. Pragma2Module / Iconvert D. ShowCache / FlushCache E. ecompile.rexx F. o2m G. E-Yacc H. SrcGen I. EBuild J. EE / Aprof K. EDBG L. EC PreProcessor 18. Appendices A. E Grammar description B. Tutorial C. Mapping E to C/C++/Pascal/Ada/Lisp etc. D. Amiga E FAQ +-----------------------------------------------------------------------+ | 0. COMPILER AND INTRODUCTION | +-----------------------------------------------------------------------+ 0A. introduction ---------------- E is an object oriented / procedural / unpure functional higher programming language, mainly influenced by languages such as C++, Ada, Lisp etc. It is a general-purpose programming language, and the Amiga implementation is specifically targeted at programming system applications. The number of features of the language is really too great to sum up entirely (see 0E where some of the features new in v3 are listed), and include: speed of >20000 lines/minute on a 7 Mhz amiga, inline assembler and linker integrated into compiler, large set of integrated functions, great module concept with v39 includes as modules, flexible type-system, quoted expressions, immediate and typed lists, low-level and object polymorphism, exception handling, inheritance, data-hiding, methods, multiple return values, default arguments, register allocation, fast memory management, unification, LISP-Cells, (macro-) preprocessor, source-level debugger, and much more... This is what 'HelloWorld' looks like in E: /* nominated for Most Boring Example */ PROC main() WriteF('Hello, World!\n') ENDPROC 0B. the distribution -------------------- The distribution includes: bin/ contains the compiler EC and the support utilities modules/ Directory containing all Amiga v39 E modules and useful tools as linkable modules docs/ documentation on E src/ example sources in E tools/ optional tools for use with E This distribution of Amiga E v3.0 including the demo version of the compiler is FreeWare, and may be freely copied. The compiler archive some of you may have received together with this archive, however, is NOT FreeWare and should NOT be copied for anyone but yourself. Distributing copies of E for more than the price of disk+postage (generally <3$), or any other way of distribution with only the slightest aim of making profit, is not allowed. I explicitly forbid Serge Hammouche or his company "France Festival Distribution" to distribute E in any shape or form. He has done so in the past without my permission, misusing my name and stealing money from me on the backs of french E programmers. If you paid him money, claim it back and spread the word. A french translation of this document authorized by me (made by Olivier Anh) is available on aminet. This distribution should always be distributed as a whole, i.e. in the form of the original .lha archive. No additions, modifications, translations, partial distributions or whatever are allowed without my explicit permission. No guarantees, no warranty. If you manage to drown your pet goldfish using E, or E fails to be suitable for ordering pizzas, that's entirely your problem. Whatever happens, don't blame it on me. Fred Fish has special permission to distribute E on his CD-ROM's. 0C. demo restrictions, registration and sites --------------------------------------------- The Amiga E distribution is PD, and contains the demo version of the compiler. registered programmers obtain the full compiler as a separate archive, with only "EC" in it. If you have received the registered EC already, you may wish to put it in the bin directory. The distribution archive may be freely copied for anyone (see 0B on that), but please make sure you do not distribute your registered copy of EC to anyone, not even to friends. I haven't serialised these copies because of the confidence I have in my registered users, so don't break it. Registration is very affordable, and v2.1b is still available, so there's no excuse left for pirating E. So what's "demo" about the included compiler? The compiler will only spit out executables <8k, above that it will present you with a "workspace full" error. Other than that it's fully functional. You are allowed to evaluate this demo for _two weeks_, after which you decide either to register or quit using this demo version, even if you only write programs <8k. [this used to be 12k, yes. guess why it changed.] updates. distribution updates can be found in the PD as normal, and updates to the registered EC will be distributed as patches, also in the PD. ordering a copy. The basic price is 40$. - subtract 5$ if you are prepared to receive your registered EC per uuencoded E-mail instead of on disk. This is the fastest way to get v3. - add 10$ for each major update you wish to receive (if they are released) This is only for people living in Siberia or similar, since updates are available in the PD. - contact me for large quantity orders. I will allow payment in some other currencies as well, to simplify payment for some people. No rare currencies please. examples (US$): 40 Dutch Guilders (highly preferred) 65 German DeutchMark 60 Etc... NOTE: these are calculated from transaction prices on 30 june 94, if your currency starts to plummet, you'll have to adjust. making sure you're 1$ above the guilder-price seems ok. Getting the money to me. This is not simple, since most banks charge a lot for foreign money transfers. Some options: - Sending cash (preferred). This may sound spooky, but it actually is the most succesful way of getting money across. Changing your money to dutch paper-money is always a good idea. If you feel insecure about mailing money, most post-offices offer a service that will report back to you that everything safely arrived at my place. [40$] - Send a "Mandat the poste international". This has worked from for example France and Italy without problems [40$] - within Europe, send a EuroCheque (in guilders). I believe there are no costs for this, but check locally. [make sure you mark "DFL" as currency!] [40$] - Transferring directly to my bank account: 427875951, ABN-AMRO bank, the netherlands or my post-giro account: 6030387, PostBank, the netherlands make sure you cover any transfer costs your bank may charge you, and/or may charge me. for example postbank transfer from outside the netherlands costs 4$, bank transfers can be up to 10$ [44$ to 50$, netherlands: 40$] - Do **NOT** send CHEQUES, MONEY ORDERs or similar methods of payment. Cheques (other than the EuroCheques above) banks here ask 15$ tranfer costs for to cash (if I can cash them at all). [50$ to 55$] You may choose any (other) method, but in general realise that it's YOUR task to make sure I am able to cash the full amount of money _easily_. If you do not take transfer costs into account and the final amount is less than 40$, you'll have to do yet another transfer before you can get your registrated version. Make sure you send as complete info with the money as possible, i.e. full address, internet E-mail, maybe even Amiga-config etc. I'm not going to write out one of those silly registration forms here :-) my address: (see 0F) You can also register at one of the authorized E registration sites in Australia, England, the U.S.A. or Germany (Italy soon): Australia: Rob Nottage (information below) England: Jason R. Hulance (information below) U.S.A.: Barry Wills (information below) Germany: Jörg Wach (no full information yet) Italy: - (no confirmation yet) Below is some information from the various sites, for more info contact them personally. Residents in nearby countries may choose at their option to registrate at these sites as well. Note that generally the same rules go for sites as well: whatever your method of payment, make sure the correct amount is received by the site. GERMANY name: Jörg Wach address: Waitzstr. 75, 24105 Kiel, Deutschland/Germany email: JCL_POWER@freeway.sh.sub.de price: 60dm postal delivery, 54dm via email AUSTRALIA name: Rob Nottage address: 10 Chilver Street, Kewdale, Western Australia, 6105 Fax: (09) 458 0154 FidoNet: 3:690/662.0 AmigaNet: 41:616/662.0 Internet: robbage@cougar.multiline.com.au BBS: (09) 351 8401 v.32, v.42bis. price: AUS$ 55 (postage or fidonet crashmail), AUS$ 50 (internet or fidonet email), depending on current exchange rates payment: - Postal or money order (preferred) - personal or bank cheque (you pay the cost) - direct transfer to bank account (National Australia Bank, fill out a deposite slip for the correct amount, account# 086131 435770223, 'Robert K. Nottage') - Sending cash (your risk) ENGLAND name: Jason R. Hulance (Dept. E) address: Formal Systems (Europe) Ltd, 3 Alfred Street, Oxford OX1 4EH, ENGLAND telephone: (0869) 324350, out of office hours. email: m88jrh@ecs.ox.ac.uk price: 26 UK pounds (on disk) or 23 UK pounds (via E-mail) "Beginner's Guide to Amiga E" (182 pages) is available in AmigaGuide, TeX, PostScript and printed forms with a large index. This costs 5 UK pounds (non-printed forms) or 10 UK pounds (printed form). payment: For safety, please make payment by cheque (payable to "Jason Hulance"), although postal orders/cash/bank transfers will also be accepted U.S.A. name: Barry Wills address: 5528D Pryor Dr., SAFB, IL 62225 email: el269@cleveland.freenet.edu price: 40$ (US mail), 35$ (internet email) payment: - money order or cashier check: preferred method. - cash - Okay, but AT YOUR OWN RISK. - personal check: Okay, but expect delays of up to 3 weeks for shipment of your registered compiler. 0D. using the compiler ---------------------- To install Amiga E on your system, just copy the whole distribution to some place in your system, extend your path to the BIN directory, and assign EMODULES: to the MODULES directory. syntax of the compiler (2.04+): SOURCE/A,REG=NUMREGALLOC/N/K,LARGE/S,SYM=SYMBOLHUNK/S,NOWARN/S,QUIET/S, ASM/S,ERRLINE/S,ERRBYTE/S,SHOWBUF/S,ADDBUF/N/K,IGNORECACHE/S,HOLD/S,WB/S, LINEDEBUG/S,OPTI/S,DEBUG/S: for 1.2 to 2.03: EC [-opts] As an example we'll compile the program 'HelloWorld.e'. The compiler will produce an executable 'HelloWorld'. E:> ec helloworld Amiga E Compiler/Assembler/Linker v2.4f (c) 91/92/93 $#%! lexical analysing ... parsing and compiling ... no errors E:> helloworld Hello, World! E:> list HelloWorld.e 89 ----rwed Oggi 17:37:00 helloworld 656 ----rwed Oggi 17:37:00 2 files - 4 blocks used E:> note: the compiler cannot be made resident Last note on compiling the examples: if a program uses module files for library definitions like: MODULE 'GadTools', 'Reqtools' the compiler needs to know where to find them. Two possible solutions: 1. you make the assignment "emodules:" to the modules directory (best). 2. you state in the source code where to look for modules, like: OPT DIR='dh0:src/e/modules' Options. These are standard AmigaDos options. You can see them at any time by typing 'EC ?'. For 1.2 options the old unix-like switches are used (need to be written together, preceded by a "-"): LARGE -l compiles with large code/data model (see 16A, OPT LARGE). ASM -a puts EC into assembler mode (see 15D, OPT ASM). NOWARN -n suppresses warnings (see 16A, OPT NOWARN) SYM -s adds a symbolhunk to the executable, for use with profilers, debuggers, disassemblers etc. LINEDEBUG -L adds a "LINE" debughunk to the executable, for use with profilers, debuggers etc. (see 17K). REG=N -rN uses N regs per PROC for register-allocation. (default is 0 for the time being, read elsewhere about how to use this!) QUIET -q if there are no errors or warnings, EC won't output anything. WB -w puts wb to front (for scripts) SHOWBUF -b shows buffer memory usage information ADDBUF=X -mX forces EC to allocate more memory for its buffers. X ranges 1..9, the minimum number of 100k blocks to allocate. default is 1 (never needed). ERRLINE -e give the line# the error was on as returnvalue ERRBYTE -E give the byte-offset in the file the error was on as returnvalue IGNORECACHE -c don't use the module-cache in any way HOLD -h wait for a on the commandline before exiting EC. OPTI enable all optimisations (currently equals REG=5) DEBUG attach debug infos to executable/module (see 17K) example: ec large blabla compiles blabla.e with large model. NOTE: in most standard cases you won't need to use any of these options 0E. changes from v2.1b to v3.0a, and from v3.0a to v3.1a -------------------------------------------------------- What's new in v3.0a (for v3.1a, see further below): [separated in four sections. for the description of these refer to the actual chapter] 1. BIG NEW FEATURES. - compilation to modules [!] (see 10C) - oo: object inheritance, private/public, methods etc. (see 14A) - default arguments for PROCs (see 6F) (and some builtins, too). - multiple return values (see 6G) - register variables / allocation (see 16G, 15E, ...). - builtin REALs (see 12) - NEW operator (see 4K), and END (see 5M) (with superfast memory manegement) - powerful syntactic variation of SELECT (see 5J) - unification (see 4L) - allows for more complex types in OBJECTs, PTR TO etc. (see 8F) together with more powerful dereferencing (see 4F, x.y[a].z etc.) - garbage collected Lisp-Cells (see 9I) - function values (call ptrs to PROCs) (see 6H) - module caching (see 17D, showcache) - error reconstruction: pinpoint error at exact spot in line - whole bunch of new builtin functions (see 9A,...) - whole bunch of useful modules (will get loads more soon) - various compiler optimisations to make EC significantly faster - several code optimisations - intelligent linker / module system (see 10C, amongst others) - compiler uses a lot less memory. - symbol and linedebug hunks (see 0D above for switches). - various utilities, such as EE (Barry Wills great E Editor), Build (a make), o2m (converts assembly .o files to modules), E-Yacc etc. - new docs, GREAT tutorial by Jason Hulance (known as 'The Guide'). 2. SMALLER NEW FEATURES. - pointertyping "::" operator (see 4M) - EXCEPT DO: continue at handler (see 13C) - EXIT in WHILE/FOR (see 5F) - single line comments (see 1B) - for some: os v39 modules. - character constants may contain "\n\t\e\a" "\0\\\b\q" now. (\q = ") - warning for flakey "assignments" now with linenum. - dereferencing a PTR TO with a just a [] results in a pointer now (for example x[1] = next object) - variety of smaller code-optimisations. - a lot of string/list/io functions now return useful returnvalues (see 9A,...). - EC's command line is now ReadArgs() style for 2.04+ users (see 0D). - better line-endings (see 5A) - several new builtins (see 9A,...) - expressions with *2 *4 /2 and /4 get optimized into adds and shifts. 3. BUGS / PROBLEMS FIXED. - recognises '.e' also on the command line. - various bugs fixed (and new ones introduced, obviously) - now also a 'stdin' variable is available - dereferencing a PTR TO INT with [] would result in an unsigned integer instead of a signed one (NOTE: this may change behaviour!) - EC could crash on missing ENDIFs: fixed. - CHAR would align incorrectly. - RAISE accepts negative constants. - Div() didn't handle negative numbers. - inline asm bugs: ADD.L ...,Ax became ADDX, various silly little problems. - StringF documentation was missing, InStr() incorrect. - SIZEOF handles CHAR/INT/LONG now too - WaitIMessage() did something silly - EC wouldn't consume some very large sources (>500k) - a WHILE or a UNTIL with an IF-exp as boolean could generate wrong code. - [exp]:CHAR would generate wrong code - some syntactical bugs could previously go unnoticed - console would open in READWRITE mode 4. OTHER CHANGES ONE NEEDS TO BE AWARE OF. - v2.1b "-s" option deleted. - 'OPT' now needs to be first thing in a source; other constructs (like 'CONST', 'RAISE') have stricter checking on their position in a source. - EC may generate 'internal errors' for some cases. If this happens, report, with source what cause it. - keyword "IS" is equivalent to "RETURN" directly after a "PROC" - The inline-assembly register conventions have changed (see 15B) Changes from v3.0a to v3.1a: Bugs fixed in v3.0b (nearly all were tiny problems, with great consequences!) - internal errors on 68000 systems - problems with inherited methods - modules could have 4 superfluous bytes of code in them - default arguments in modules could get lost - method redefinition could cause double declaration errors - ptr's to in objects in modules would get lost [now ec will try to find the correct object, else type = LONG] Bugs fixed in v3.0e: - huge bug: linker wouldn't link modules >32k - enforcer hit in linker - String() could trash a register - errors within an OBJECT were reported on the first line - wrong code generated for AND.L Dn,regvar and similar instructions - .B size on An eas wasn't detected for various instructions - methods could be defined outside of object/module scope - object declarations could start as private for no reason New features in v3.1a: - SourceLevel debugging!!! option DEBUG/S and external debugger EDBG (see 17k) - Built-in preprocessor!!! (conditional compilation & macro preprocessing), Mac2E and Cpp compatible (see 17L) - The SUPER keyword allows calling of superclass methods (see 14E) - Some new example sources, new tool modules (FilledVector, EasyGUI etc.) - new versions of Aprof and EE - docs updated: new features, FAQ etc... Bugs fixed in v3.1a: - obj.unknownmember could give weird error reports - ShowModule could display arguments wrong - Lists [] didn't accept negative floating point numbers - small problems in E module definitions fixed - E-Build executed actions in reverse order :-) - FlushCache wouldn't allow a selective flush - Unification on complex nested LISP-lists could fail - NEW-allocated list deallocation routine was missing (see 9F) - missing closing brackets could cause fuzzy error messages - some constructions of nested method-calls and NEW with constructors could result in wrong code - Both RealF() and RealVal() contained bugs that could give wrong results on machines without a FPU - in some situations method names could clash with members in other modules Hint for users of older versions: do a diff over both versions of reference.doc 0F. additional information -------------------------- The Amiga E Compiler was developed over the course of more than three and a half years, after the author's idea of a good programming language, and a quality amiga-specific compiler for it. It was programmed (as you might have guessed) in 100% assembly, using the AsmOne assembler v1.02. All other support programs were written in E itself. Special thanks go to the following people: Barry Wills - for being the best best betatester ever. Jason Hulance - for his work on 'The Beginners Guide', and betatesting. Rob Verver - for comments/inspiration. I also would like to thank the following people for various reasons (no particular order): Raymond Hoving, Erwin van Breemen, Michael Zuchhi, James Cooper, Jens Gelhar, Paolo Silvera, Sergio Ruocco, Jeroen Vermeulen, Jan van den Baard, Joerg Wach, Norman Kraft, Urban Mueller, Charles McCreary, Olivier Anh, Lionel Vintenat, Rob Nottage, and many more... This compiler was programmed with great care towards reliability, and even more so the code it generates, additionally it has been tested and debugged for a long period. However, it is not impossible that it contains bugs. if you happen to find one, or have other comments/questions, write me at the address below: I _strongly_ prefer E-mail above conventional mail. NOTE WELL: due to the immense popularity of the previous version of Amiga E, I get an almost unreplyable amount of Email, some of which (>90%) are questions that would not have been necessary if people read all the docs carefully. What I mean to say is that I like to receive Email, and I don't mind answering questions and helping people out with programming problems, but be sure to check all other information at your disposal (like the Amiga E docs or the RKRM's) to see if your question is relevant, before mailing me. Especially questions that are not E specific but Amiga specific should not be directed to me. And try and be gentle on me with comments like "I think E should have feature X..." (see 18D, the FAQ) registrations (see 0C) and donations are welcome at the following address: Wouter van Oortmerssen Levendaal 87 2311 JG Leiden HOLLAND or better if you have access to Email: wouter@mars.let.uva.nl wouter@alf.let.uva.nl (if mars bounces) +---------------------------------------------------------------+ | 1. FORMAT | +---------------------------------------------------------------+ 1A. tabs,lf etc. ---------------- E-sources are pure ascii format files, with the linefeed and semicolon ";" being the separators for two statements. Statements that have particularly many arguments, may be spread over several lines by ending a line with a comma (or any other lexical element that can normally never occur at the end of a line), thus ignoring the following (see 5A for line endings). Any lexical element in a source code file may be separated from another by any number of spaces, tabs etc. 1B. comments ------------ comments may be placed anywhere in a source file where normally a space would have been correct. They start with '/*' and end with '*/' and may be nested infinitely. The same goes for one-line comments, which start with a '->' and end at the first . /* this, is a comment */ -> this one too. 1C. identifiers and types ------------------------- identifiers are strings that the programmer uses to denote certain objects, in most cases variables, or even keywords or function names predefined by the compiler. An identifier may consist of: - upper and lowercase characters - "0" .. "9" (except as first character) - "_" (the underscore) All characters are significant, but the compiler just looks at the first two to identify the type of identifier it is dealing with: both uppercase: - keyword like IF, PROC etc. - constant, like MAX_LENGTH - assembly mnemonic, like MOVE first lowercase: - identifier of variable/label/object etc. first upper and second lower: - E system function like: WriteF() - library call: OpenWindow() Note that all identifiers obey this syntax, for example: WBenchToFront() becomes WbenchToFront() +---------------------------------------------------------------+ | 2. IMMEDIATE VALUES | +---------------------------------------------------------------+ Immediate values in E all evaluate to a 32bit result; the only difference among these values (A-G) is either their internal representation, or the fact that they return a pointer rather than a value. 2A. decimal (1) --------------- A decimal value is a sequence of characters "0" .. "9", possibly preceded by a minus "-" sign to denote negative numbers. examples: 1, 100, -12, 1024 2B. hexadecimal ($1) -------------------- A hexadecimal value uses the additional characters "A" .. "F" (or "a" .. "f") and is preceded by a "$" character. Examples: $FC, $DFF180, -$ABCD 2C. binary (%1) --------------- Binary numbers start with a "%" character and use only "1" and "0" to form a value. Examples: %111, %1010100001, -%10101 2D. float (1.0) --------------- Floats differ only from normal decimal numbers in that they have a "." to separate their two parts. Either one may be omitted, not both. Note that floats have a different internal 32bit (IEEE) representation (see 12A for more information on floats). Examples: 3.14159, .1 (=0.1), 1. (=1.0) 2E. character ------------------- The value of a character (enclosed in double "" quotes) is its ascii value, i.e. "A" = 65. In E, character immediate values may be a short string up to 4 characters, for example "FORM", where the first character "F" will be the MSB of the 32bit representation, and "M" the LSB (least significant byte). 2F. string ('bla') ------------------ Strings are any ascii representation, enclosed in single '' quotes. The value of such a string is a pointer to the first character of it. More specific: 'bla' yields a 32bit pointer to a memory area where we find the bytes "b", "l" and "a". ALL strings in E are terminated by a zero byte. Strings may contain format signs introduced by a slash "\", either to introduce characters to the string that are for some reason not displayable, or for use with string formatting functions like WriteF(), TextF() and StringF(), or kick2 Vprintf(). \n a linefeed (ascii 10) \a or '' an apostrophe ' (the one used for enclosing the string) \q a doublequote: " \e escape (ascii 27) \t tab (ascii 9) \\ a backslash \0 a zero byte. Of rare use, as ALL strings are 0-terminated \b a carriage return (ascii 13) Additionally, when used with formatting functions: \d print a decimal number \h print a hexadecimal \s print a string \c print a character \z set fill byte to '0' character \l format to left of field \r format to right of field (these last two act as toggles) Field specifiers may follow the \d,\h and \s codes: [x] specify exact field width x (x,y) specify minimum x and maximum y (strings only) Example: print a hexadecimal number with 8 positions and leading zeroes: WriteF('\z\h[8]\n',num) A string may be extended over several lines by trailing them with a "+" sign and a : 'this specifically long string ' + 'is separated over two lines' 2G. lists ([1,2,3]) and typed lists ----------------------------------- An immediate list is the constant counterpart of the LIST datatype, just as a 'string' is the constant counterpart for the STRING or ARRAY OF CHAR datatype. Example: [3,2,1,4] is an expression that has as value a PTR to an already initialised list, a list as a representation in memory is compatible with an ARRAY OF LONG, with some extra length information at a negative offset. You may use these immediate lists anywhere a function expects a PTR to an array of 32bits values, or a list. Examples: ['string',1.0,2.1] [WA_FLAGS,1,WA_IDCMP,$200,WA_WIDTH,120,WA_HEIGHT,150,TAG_DONE] (see 9C on list-functions for a discussion on typed-immediate lists and detailed information). 2H. lisp-cells () ---------------------- (see 9I to read about cells in detail) +---------------------------------------------------------------+ | 3. EXPRESSIONS | +---------------------------------------------------------------+ 3A. format ---------- An expression is a piece of code held together by operators, functions and parentheses to form a value. They mostly consist of: - immediate values (see 2A,...) - operators (see 4A,...) - function calls (see 3D) - parentheses () (see 3B) - variables or variable-expressions (see 3C) examples of expressions: 1 'hello' $ABCD+(2*6)+Abs(a) (a<1) OR (b>=100) 3B. precedence and grouping --------------------------- The E language has _no_ precedence whatsoever. This means that expressions are evaluated left to right. You may change precedence by parenthesizing some (sub-)expression: 1+2*3 /* =9 */ 1+(2*3) /* =7 */ 2*3+1 /* =7 */ 3C. types of expressions ------------------------ There are three types of expressions that may be used for different purposes; - , consisting of just a variable - , consisting of a variable, possibly with unary operators with it, like "++" (increment) "." (member selection) or [] (array operator). (see 4D, 4G). It denotes a modifiable expression, like Lvalues in C. Note that those (unary) operators are not part of any precedence. - . This includes and , and any other expression. 3D. function calls ------------------ A function call is a temporary suspension of the current code for a jump to a function, this may be either a self-written function (PROC), or a function provided by the system. The format of a function call is the name of the function, followed by two parentheses () enclosing zero to unlimited arguments, separated by commas ",". Note that arguments to functions are again expressions. (see 6A) on how to make your own functions, (see 9A and 10A) on built-in functions. Examples: foo(1,2) Gadget(buffer,glist,2,0,40,80+offset,100,'Cancel') Close(handle) +---------------------------------------------------------------+ | 4. OPERATORS | +---------------------------------------------------------------+ 4A. math (+ - * /) ------------------ These infix operators combine an expression with another value to yield a new value. Examples: 1+2, MAX-1*5 (see 12A on how to overload these operators for use with floats). "-" may be used as the first part of an expression, with an implied 0, i.e. -a or -b+1 is legal. Note that * and / are by default 16bit operators: (see 9G, Mul()) 4B. comparison (= <> > < >= <=) ------------------------------- Equal to math operators, with the difference that they result in either TRUE (32bit value -1), or FALSE. These can also be overloaded for floats. 4C. logical and bitwise (AND OR) -------------------------------- These operators either combine truth values to new ones, or perform bitwise AND and OR operations. Examples: (a>1) AND ((b=2) OR (c>=3)) /* logical */ a:=b AND $FF /* bitwise */ 4D. unary (SIZEOF ^ {} ++ -- `) --------------------------------- - SIZEOF simply returns the size of a certain object or CHAR/INT/LONG. Example: SIZEOF newscreen + SIZEOF INT - {} Returns the address of a variable or label. This is the operator you would use to give a variable as argument to a function by reference, instead of by value, which is default in E. See "^". Example: Val(input,{x}) - ^ The counterpart of {}, writes or reads variables that were given by reference, examples: ^a:=1 b:=^a it may also be used to plainly "peek" or "poke" LONG values from memory, if is pointer to such a value. Example for {} and ^: write your own assignment function; PROC set(var,exp) ^var:=exp ENDPROC and call it with: set({a},1) /* equals a:=1 */ - ++ and -- Increases (++) or decreases (--) the pointer that is denoted by by the size of the data it points to. This has the effect that that pointer points to the next or previous item. When used on variables that are not pointers, these will simply be changed by one. Note that ++ always takes effect _after_ the calculation of , -- always _before_. Examples: a++ /* return value of a, then increase by one */ sp[]-- /* decrease pointer sp by 4 (if it were an array of long), and read value pointed at by sp */ - ` This is called a quoted expression, from LISP. is not evaluated, but instead returns the address of the expression, which can later be evaluated when required. More on this special feature in chapter 11 4E. triple (IF THEN ELSE) ------------------------- The IF operator has quite the same function as the IF statement, only it selects between two expressions instead of two statements or blocks of statements. It equals the x?y:z operator in C. IF THEN ELSE returns exp1 or exp2, according to boolexp. For example, instead of: IF a<1 THEN b:=2 ELSE b:=3 IF x=3 THEN WriteF('x is 3\n') ELSE WriteF('x is something else\n') write: b:=IF a<1 THEN 2 ELSE 3 WriteF(IF x=3 THEN 'x is 3\n' ELSE 'x is something else\n') 4F. structure (.) ----------------- . builds a The pointer has to be declared as PTR TO or ARRAY OF (see 8D for these), and the member has to be a legal object identifier. Note that reading a subobject in an object this way results in a pointer to that object. Examples: thistask.userdata:=1 rast:=myscreen.rastport If the member you select is of type PTR TO , you may use "." and "[]" to dereference further values. If you select an ARRAY or substructure in an OBJECT, the result is again a PTR. 4G. array ([]) -------------- [] (is a ) This operator reads the value from the array points to, with index . The index may be just about any expression. Note1: "[]" is a shortcut for "[0]" Note2: with an array of n elements, the index is 0 .. n-1 Examples: a[1]:=10 /* sets second element to 10 */ x:=table[y*4+1] /* reads from array */ x.y[3] /* accesses array in an object */ 4H. float operator (!) ---------------------- ! Converts expressions from integer to float and back, and overloads operators + - * / = <> < > <= >= with float equivalents. (see 12A to read all about floats and this operator). 4I. assignments expressions (:=) -------------------------------- Assignments (setting a variable to a value) exist as statement and as expression. The only difference is that the statement version has the form := and the expression :=. The latter has the value of as result. Note that as := takes on an expression, you will often need parentheses to force correct interpretation, like: IF mem:=New(100)=NIL THEN error() is interpreted like: IF mem:=(New(100)=NIL) THEN error() which is not what you mean: mem should be a pointer, not a boolean. but you should write: IF (mem:=New(100))=NIL THEN error() it's a good habit to parenthesize any assignment expression that is part of another one, if not already disambiguated by other constructs such as "bla(a:=1)", "b:=a:=1" etc. 4J. sequencing (BUT) -------------------- The sequencing operator "BUT" allows two expressions to be written in a construction that allows for only one. Often in writing complex expressions/function calls, one would like to do a second thing on the spot, like an assignment. Syntax: BUT this says: evaluate exp1, but return the value of exp2. Example: myfunc((x:=2) BUT x*x) assign 2 to x and then calls myfunc with x*x. The () around the assignment are again needed to prevent the := operator from taking (2 BUT x*x) as an expression. 4K. dynamic memory allocation (NEW) ----------------------------------- the NEW operator is a powerful operator for dynamic memory allocation. it has various forms: (assuming DEF p:PTR TO whateverobj, q:PTR TO INT) NEW p is an expression that will allocate zero-ised memory for the object-size p points to. the resulting pointer will be put in p, and is also the value of the expression. if NEW fails to get memory, it raises a "NEW" exception. 'NEW p' is therefore roughly equivalent with: IF (p:=New(SIZEOF whateverobj))=NIL THEN Raise("MEM") with the difference that p never gets any value if an exception is raised, and that the former is of course an expression, not a statement but there's more: one can also allocate an array dynamically: NEW p[10] /* array of 10 objects */ NEW q[a+1] /* array of INT, size is runtime computed */ (this doesn't work when instantiating classes) A problem with list [1,2,3] expressions sometimes is that they are static, and when using these to build large datastructures they would need to be created at run-time. one may then use the dynamic equivalent to static lists: p:=[1,2,3]:whateverobj /* static structure */ p:=NEW [1,2,3]:whateverobj /* dynamicly allocated! */ this works with both lists and typed-lists, and also with arrays: NEW [1,2,3] /* constant-list, dyn. (note: not a like a listvar!) */ NEW [1,2,3]:obj /* object */ NEW [1,2,3]:INT /* array of INTs */ freeing memory allocated with any variations of NEW is done automatically at the end of the program, or by hand with END or FastDispose(). (note: the only exception is NEW , use FastDisposeList()) If you use NEW [...]:obj, and the number of fields is less than the one present in the object, additional 0/NIL/"\0" whatever fields will be added. this allows one to extend objects without getting into trouble with allocations like these. (note that this is different from the static [...]:obj) when you use NEW as a statement, multiple pointers may follow, i.e.: NEW a,b.create(),c is valid. (see 5M, END) (see 9F for the fast memory allocation functions NEW makes use of) 4L. unification (<=>) --------------------- Unification allows a totally different style of programming that will be familiar to you if you're used to either Logic (ProLog), equational or functional (Miranda/Gofer/Haskell) programming. Most of us when using structures/arrays whatever are used to get values from it by selection ("." and "[]"), in these languages however pattern matching is used. in E: exp <=> uni_exp exp can be any expression, but in v3 it's only really useful if it somehow is a pointer to a list. uni_exp is the pattern that is used to match exp. All constants in uni_exp much match to values in exp, variables are set to their respective values. if something doesn't match, no variables get a value, and the expression has the result FALSE. otherwise TRUE. example: a:=[1,2,3] ... IF a <=> [1,x,y] THEN ... this will succeed with x=2 and y=3. If list a were to be another lenght than 3, the match would fail too. The fact that a is a list in the first place is something you need to assure by yourself, EC simply tries to fit the uni_exp on whatever value it gets as exp. examples of FALSE: a <=> [1,x] -> wrong list-len a <=> [1,4,x] -> 4=2 fails 'bla' <=> [1,2] -> unpredictable result / crash ? The fun thing with unification is that you can do very complex matches, and that if you take the first field or so as a constant telling what the structure is, you have a nice form of dynamic typing. And, all the time without using PTRs! a slightly nicer example: [BLA,[1,'burp'],['bla',"bla"]] <=> [BLA,[1,x],y] binds: x='burp', y=['bla',"bla"] or even: IF myexp <=> [PLUS,[MUL,a,1],[SUBS,[PLUS,c,d],e]] THEN RETURN a+c+d-e maybe a silly example, but one could imagine doing complex stuff like this in a compiler's code-optimizer. it equals this traditional code: IF ListLen(myexp)=3 IF myexp[]=PLUS IF ListLen(dummy:=myexp[1])=3 IF (dummy[]=MUL) AND (dummy[2]=1) a:=dummy[1] IF ListLen(dummy:=myexp[2])=3 IF dummy[]=SUBS e:=dummy[2] IF ListLen(dummy2:=dummy[1])=3 IF dummy2[]=PLUS c:=dummy2[1] d:=dummy2[2] RETURN a+c+d-e ENDIF ENDIF ENDIF ENDIF ENDIF ENDIF ENDIF ENDIF only then a bit more optimal. As you see there's a lot of expressive power involved in unification as compared to traditional selection-based programming. For now, the only thing allowed in unification are untyped lists, (integer) constants, variables and LISP-Cells (see 9I for that). The future will see this expanded with strings, typed-lists/objects, and even expressions [!] 4M. pointer typing (::) ----------------------- when you write an expression like 'p' where p is a PTR TO object, this allows you to dereference it as such. The pointer typing operator allows you to change such a type on the fly: DEF p:PTR TO mp -> message port p.sigbit -> access it p::ln.name -> access pointer as if it were a node this is very useful for pointers that can point to different sorts of things or objects that are part of each other, where of course only one declaration is possible. A second handy use is in OBJECTs that have members declared as LONG, which are actually pointers. You may type it on the fly to dereference it anyway: mywindow.userport::mp.sigbit here the window OBJECT has userport defined as LONG, so you wouldn't be able to dereference it normally. +---------------------------------------------------------------+ | 5. STATEMENTS | +---------------------------------------------------------------+ 5A. format (;) -------------- As suggested in chapter 1A, a statement generally stands in its own line, but several of them may be put together on one line by separating them with semicolon, or one may be spread over more than one line by ending each line in a comma ",". Examples: a:=1; WriteF('hello!\n') DEF a,b,c,d, /* too many args for one line (faked) */ e,f,g statements may be: - assignments - conditional statements, for statements and the like, (see 5E-5K) - void expressions - labels - assembly instructions The comma is the primary character to show that you do not wish to end the statement with the next linefeed, but from v3 on, any token that cannot legally be the end of a line causes the statement to continue. Furthermore, if not all "[" and "(" occuring in a statement have been closed off, a statement will continue also. examples of such tokens: + - * / = < >= <= := . <=> :: { [ ( AND OR BUT THEN IS -> others too, but these are most useful example of bracketing: a:=[ [1,2], [3,4] ] -> assignment ends here. 5B. statement labels and gotos (JUMP) ------------------------------------- Labels are global-scoped identifiers with a ':' added to them, as in: mylabel: they may be used by instructions such as JUMP, and to reference static data. They may be used to jump out of all types of loops (although this technique is not encouraged, (see 5F, EXIT), but not out of procedures. In normal E programs they are mostly used with inline assembly. Labels are always globally visible. Usage of JUMP: JUMP