Amiga E v3.0a +-----------------------------------------------+ | | | Amiga E v3.2a | | 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 / history / new features 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 v40 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 M. EC Library mode 18. Appendices A. E Grammar description B. Tutorial C. Mapping E to C/C++/Pascal/Ada/Lisp etc. D. Amiga E FAQ 0A. 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, 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, parametric and inclusion polymorphism, exception handling, inheritance, data-hiding, methods, multiple return values, default arguments, register allocation, fast memory management, unification, LISP-Cells, gui-toolkit, (macro-) preprocessor, very intuitive and powerful source-level debugger, easy .library linking, 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 0B. the distribution -------------------- The distribution includes: Bin/ contains the compiler EC and the support utilities Modules/ directory containing all Amiga v40 E modules and useful tools as linkable modules Docs/ documentation on E Src/ example sources in E The extras archive includes: RkrmSrc/ example sources from the RKRMs, in E ModuleSrc/ sources to the module files, for reference Tools/ optional tools for use with E PdSrc/ a collection of E sources from the PD Rexx/ scripts for various editors Fonts/ fonts 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, distribution on Aminet CDROMs is also permitted. 0C. demo restrictions, registration and sites 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, was, and will always be 65 dutch guilders. This used to be equivalent to 40$, now its more like 45$. - subtract 5 guilders if you are prepared to receive your registered EC per uuencoded E-mail instead of on disk. This is the fastest way to receive a registered version. - add 10 guilders 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. If you send money in your currency, make sure it's well above 65 guilders, according to _current_ exchange rates. 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. [65 guilders] - Send a "Mandat de poste international". This has worked from for example France and Italy without problems [65 guilders] - 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!] [65 guilders] - 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 7 guilders, bank transfers can be up to 22 guilders. [75 to 90, netherlands 65 guilders] - Do **NOT** send CHEQUES, MONEY ORDERs or similar methods of payment. Cheques (other than the EuroCheques above) banks here ask 25 guilders tranfer costs for to cash (if I can cash them at all). [90 guilders] 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 65 guilders, you'll have to do yet another transfer before you can get your registered 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: Rob Nottage England: Jason R. Hulance U.S.A.: Barry Wills Germany: Jörg Wach Italy: Mirko Lalli/AET Sweden: Jonas Tehler 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. 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, bwills@picard.ike.safb.af.mil 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. GERMANY name: Jörg Wach address: Waitzstr. 75, 24105 Kiel, Deutschland/Germany email: JCL_POWER@freeway.shnet.org price: 60dm postal delivery, 54dm via email ITALY name: Mirko Lalli / AET address: via Vecchia Aretina 64, 52020 Montalto Pergine Valdarno, Arezzo phone: 0575-899798 price: 70.000 lire, depending on exchange rates payment: C/C postale n. 11794526 SWEDEN name: Jonas Tehler address: Avagen 1, 191 77 Sollentuna internet: jegt@algonet.se phone: +46-(0)8-7542434 BBS: +46-(0)8-7546400, v32bis, v42bis, 24h price: 300skr (smail), 260skr (email, netmail or BBS), depending on current exchange rates payment: - PostGiro nr 6106998-5 (preferred) - Sending cash (at your risk) 0D. using the 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,NILCHECK/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'. 1> cd e:src E:Src> ec helloworld Amiga E Compiler/Assembler/Linker v2.4f (c) 91/92/93 $#%! lexical analysing ... parsing and compiling ... no errors E:Src> helloworld Hello, World! E:Src> list HelloWorld.e 89 ----rwed Oggi 17:37:00 helloworld 656 ----rwed Oggi 17:37:00 2 files - 4 blocks used E:Src> note: the compiler cannot be made resident 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 ) NILCHECK insert code at every "." or "[]" dereference to check for a NIL pointer. Will throw an exception of the form Throw("NIL",source_line_number) 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 / history / new features 0E. changes / history / new features ------------------------------------ New features in v3.2a: - EC can now output .library files!!! (see 17M ) - new EDBG with a massive amount of new features! (see 17K ) - enhanced EasyGUI (have a look) - NEW and END now work on subobjects as well (see 4K ). - NILCHECK/S, will insert code to check all "." and "[]" dereferences for NIL pointers (see 0D ) - v40 emodules, with types! - new modules (Src/Class/ScrollWin/ and others) - new docs / beginners guide - extended distribution with Jason's RKRM examples etc. Bugs fixed in v3.2a: - IGNORECACHE was broken - silly bug in /2 - asm -xx(Ax,Dx.w) addressing mode assembled wrong - a-- where a:PTR TO o where SIZEOF o>8 translated into ADDI ipv SUBI - globals in modules used in inline asm were not exported / offsets adjusted - exp*globvar in module not compiled ok - macros of other module would be saved again in current module - and quite a few smaller ones... New features in v3.1a: - SourceLevel debugging!!! option DEBUG/S and external debugger EDBG (see - 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... New features in v3.0a: - 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 - 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'). - 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. Hint for users of older versions: do a diff over both versions of reference.doc a version history: vers date EC k comment v0.3 sep 91 5 first version that outputs executables v1.0 may 92 20 builtins and library calls, usable for small tools v2.0 okt 92 38 v37 modules usable, language pretty "complete" v2.1a jan 93 44 first public release v2.1b apr 93 45 bug fix, few new features. current version for >1 year v3.0a jul 94 82 enormous amount of new features. E gets a price tag. v3.0b sep 94 82 bug fix v3.0e nov 94 83 bug fix v3.1a dec 94 85 EDBG, preprocessor etc. v3.2a jul 95 85 .library mode, new EDBG etc. 0F. additional information 0F. additional information -------------------------- The Amiga E Compiler was developed over the course of more than four years, after the author's idea of a good programming language, and a quality amiga specific compiler for it. It started out as quite a small project and evolved over the years into the large development environment it is now. EC was programmed (as you might have guessed) in 100% assembly, using the AsmOne assembler v1.02. All other support programs and tools (such as EDBG) were written in E itself. Special thanks go to the following people: Jason Hulance - for 'The Beginners Guide', modules/examples and betatesting. Barry Wills - for EE and being such a good betatester. Rob Verver - for comments/inspiration. Jörg Wach - for EPD and general support I also would like to thank the following people for various reasons (no particular order): Raymond Hoving, Erwin van Breemen, Michael Zucchi, 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, Mirko Lalli, Jonas Tehler, Paul Nolan, Antonio J. Gomez Glez 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 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 (main account) w.v.oortmerssen@let.uva.nl (if mars bounces) wouter@alf.let.uva.nl (bound to dissapear in a while) wvo95v@louis.ecs.soton.ac.uk (read only occasionally) 1A. tabs,lf etc. 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 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 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() 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) 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) 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) 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) 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 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') 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 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 () 2H. lisp-cells () ---------------------- (see 9I to read about cells in detail) 3A. format 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 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 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 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) 4A. math (+ - * /) 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 (= <> > < >= <=) 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) 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 ^ {} ++ -- `) 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) 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 (.) 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 ([]) 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 (!) 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 (:=) 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) 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, it would be nice 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) 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: it's also possible to 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. The dynamic equivalent to static lists may then be used: 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 extending 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. special forms of NEW and END allow to use a PTR within an object, so you can write things like NEW a.b.create() NEW a.b[50] END a.b in the examples, the pointer `a' is not affected, the pointer `b' in the `a' object is used. (see 5M , END) (see 9F for the fast memory allocation functions NEW makes use of) 4L. unification (<=>) 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 (::) 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. 5A. format (;) 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) 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