home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-07-10 | 71.5 KB | 1,888 lines |
-
- ---------
- ACE v1.1a
- ---------
-
- CONTENTS LINE
- -------- ----
-
- (i) Getting started
-
- What is ACE?..................................53
- Who should use it?...........................124
- Installation.................................164
- Using the compiler...........................199
- Compiler options.............................233
- The pre-processor and #include files.........289
- Running ACE programs.........................327
- About the example programs...................337
-
- (ii) A hitch-hiker's guide to ACE
-
- General comments.............................364
- Data types, expressions, constants...........399
- Precedence of operators......................472
- Identifiers..................................501
- Indirection operators........................599
- Structures...................................634
- Subprograms..................................726
- Shared library function calls................940
- Machine code calls..........................1034
- External references.........................1103
- Program arguments...........................1143
- Windows.....................................1183
- Screens.....................................1224
- Files.......................................1263
- Sound.......................................1354
- Turtle Graphics.............................1443
- Event trapping..............................1542
- Error handling..............................1609
-
- (iii) Stop bits
-
- Notes for assembly programmers..............1637
- Limitations.................................1677
- Known bugs..................................1726
- Future versions.............................1750
- Disclaimer..................................1767
- References..................................1774
- Final word..................................1816
-
- ================================================
-
- What is ACE?
- ------------
- AmigaBASIC Compiler with Extras?
- A Creative Environment?
- A Compiler for Everyone?
- Automatic Computing Engine (ala Alan Turing)?
- Dr Who's companion?
-
- Seriously...
-
- ACE is a freely distributable, recursive descent, peephole-optimising Amiga
- BASIC compiler which produces A68K-compatible assembly source code. ACE runs
- under Wb 1.3, 2.04 and up, as do the executables it produces. ACE will run
- on 512K machines, but at least 1M is required for medium to large programs.
-
- ACE is both a subset and a superset of AmigaBASIC which, in most cases
- produces very similar results to the latter. Any differences between the
- two are discussed in this document and the command and function reference.
-
- The following files constitute a complete ACE archive:
-
- executables
- -----------
- app - A simple pre-processor.
- ace - The BASIC compiler.
- a68k - Charlie Gibbs' 68000 assembler.
- blink - The Software Distillery's linker.
- bas - A shell script which automates
- the compile-assemble-link process.
- documents
- ---------
- ace.doc - This document.
- ref.doc - A command and function reference for ACE.
- history - A history of ACE's development.
- a68k.doc - Documentation for the assembler.
- blink.doc - Documentation for the linker.
-
- scanned libraries
- -----------------
- ami.lib - A freely distributable version of amiga.lib.
- startup.lib - A library of routines needed at start/end of
- an ACE program run (eg: opening libraries).
- db.lib - A library of assorted routines used by ACE
- programs.
-
- other stuff
- -----------
- includes - Some useful ACE include files.
- icons - ACE tool and document icons.
- examples - A selection of example programs used during
- testing which demonstrate ACE's capabilities.
-
- ACE programs do NOT require any special run-time shared libraries, so the
- executables which the compiler produces (via the assembler and linker)
- are completely portable, requiring only the standard Amiga shared libraries
- in your libs directory. The three ".lib" files mentioned above are scanned
- libraries, so code from these is incorporated at link time.
-
- ACE is written in Sozobon C (ZC v1.01), while db.lib and startup.lib are
- written in assembler (~75%) and C.
-
- A68K and Blink are used to assemble and link the code produced by ACE.
- The MicroEmacs (v1.3 & v2.1) editor has been used throughout every stage
- of ACE's development. It works for me.
-
- The complete ACE package may be freely distributed but I retain the copyright
- to the C and assembly source code (not yet included in the archive). No profit
- may be made from such distribution but a minimal fee of no more than $5.00
- (Australian) may be charged to cover the cost of a disk based distribution.
-
-
- Who should use it?
- ------------------
- ACE is intended for anyone who already knows BASIC and wants one or more of
- the following:
-
- - Faster program execution.
- - Independence from the BASIC interpreter, ie: standalone programs
- which are runnable from the CLI/Shell and Workbench.
- - Extra commands, functions and features: turtle graphics,
- command-line and Workbench arguments, recursion, SUBs with
- return values, external references, defined constants, structures,
- include files, better WAVE and SAY features, among other things.
-
- Maybe you don't wish to learn another high-level language, or perhaps you
- already know C or assembler but prefer to use BASIC for some tasks while
- still having the power of a compiled language.
-
- ACE is a general purpose language so in theory at least, it can be applied
- to any programming task you like. In practice however, I find ACE to be most
- useful for writing small to medium sized programs where speed is important
- but so is ease of programming.
-
- ACE is also a useful prototyping language. It allows you to get something
- up and running quickly to test an idea. You may later decide to re-code in
- C or assembler, or you may just add some polish to the exisiting ACE program.
-
- Once again, in practice, ACE is not intended for writing AMOS-like demos/games,
- nor - at this stage - is it really suitable for producing slick commercial
- applications. As ACE improves, the latter will no longer be true I hope.
-
- I have written the following kinds of programs with ACE:
-
- - Shell utilities.
- - Fractal graphics programs.
- - Simple neural networks.
- - A sound sample player.
- - Astronomy programs, eg: galaxy collision simulator,
- planetary ephemeride calculator, Yale Bright Star Catalog plotter.
-
-
- Installation
- ------------
- Starting with the supplied archive, you just need to "unarc" it thus:
-
- lha -a x ace
-
- after cd'ing to a blank ACE disk or hard disk directory you've created.
-
- The appropriate directories (bin,lib,include,docs,prgs,run,icons) and files
- will be extracted from the archive.
-
- Then add the following lines to your user-startup or startup-sequence script:
-
- assign ACE: <volume or directory name>
- path ACE:bin add
-
- where <volume or directory name> is the name of the disk or directory where
- the ACE files now reside.
-
- In addition, you need to add three more statements to your startup-sequence
- or user-startup script:
-
- assign ACElib: - bas uses this for linked libraries.
- assign ACEbmaps: - ace uses this for .bmap files.
- assign ACEinclude: - app uses this for include files.
-
- Typically, they will be something like this:
-
- assign ACElib: ACE:lib
- assign ACEbmaps: ACE:bmaps/2.0
- assign ACEinclude: ACE:include
-
- That's it! Now reboot your Amiga and you're away.
-
-
- Using the compiler
- ------------------
- ACE currently expects all BASIC source files to have a ".b" extension.
-
- If you wrote a program called foo.b, you would invoke the compiler thus:
-
- ace foo
-
- which would produce foo.s, an A68K-compatible assembly source (text) file which
- can be inspected and/or hand-optimised if so desired.
-
- If you wanted to pre-process, compile, assemble and link foo.b, you would type:
-
- bas foo
-
- which would yield foo (the executable).
-
- The bas script sets the stack to 40000 bytes. Before running ACE by itself,
- you will need to set this. A minimum stack size seems to be around 5000
- for many ACE compilations, but I recommend 20000 to 40000 bytes to be safe.
-
- If your Amiga GURUs or hangs during a compile or produces garbage in the shell,
- you can be pretty sure that the stack is too small. However with a stack of
- 40000 I've had no problems.
-
- You can either create a BASIC source file using an editor or in the AmigaBASIC
- environment. If you want to compile a program developed with the interpreter,
- just save the program in ASCII format thus:
-
- save "foo.b",a
-
- ACE will ONLY compile ASCII source files, not AmigaBASIC's compressed format.
-
-
- Compiler options
- ----------------
- The full command line syntax for ACE is:
-
- ace [-bcEilO] <sourcefile>
-
- which indicates that there are currently three optional compiler switches.
-
- The switches can appear in any combination (ie: -bi, -clb, -O, -ObE) but are
- case sensitive (eg: -b is NOT the same as -B).
-
- The -b switch tells the compiler to include code to check for ctrl-c breaks
- by the user. The inclusion of this code can result in noticeably larger
- assembly source files, but execution speed doesn't seem to suffer appreciably.
- When a ctrl-c is detected, the program will clean up and exit, but user-created
- windows will remain open. The use of ON BREAK can get around this though (see
- the "Event Trapping" section).
-
- The -c switch includes each line of ACE source code as a comment in the
- final assembly source file. This was requested as a debugging aid. Warning:
- the presence of such comments interferes with peephole optimisation. Also be
- aware that ACE sometimes includes extra code apart from that which you would
- expect purely on the basis of the source code, so the comments can appear to
- be in strange places.
-
- The -E switch creates a file in the current directory called ace.err which
- contains all compiler error messages at the end of an ACE run. Error messages
- will still be displayed during compilation.
-
- The -i switch tells ACE to make an icon for the executable resulting from
- the compilation. The file "ACE:icons/exe.info" must exist as it is used as
- the source file for the icon. This allows you to use an icon of your own if
- you so wish.
-
- The -l switch causes the compiler to display each line of ACE source code
- before it is compiled.
-
- The -O switch causes the assembly source code produced by ACE to be optimised.
- At present, simple peephole optimisation is carried out. Assembly code size
- reductions of around 5% to 10% are usual. Speed improvements vary, depending
- upon the program, however I recommend the use of the -O switch for all programs
- where speed is the least bit important. As time goes by, ACE's optimiser will
- be improved.
-
- The syntax for the bas script is:
-
- bas [-bcEilO] <sourcefile> [<objectfile>]
-
- where <sourcefile> is the program to be compiled (without the .b extension)
- as with the ACE syntax, and <objectfile> is a C or assembly module which has
- been (compiled and) assembled to produce an object file. This is used when
- you are calling an external function. The <objectfile> is linked with the
- output of ACE and A68K along with db.lib, startup.lib and ami.lib. For more
- about external functions, see the section "External references".
-
-
- The pre-processor and #include files
- ------------------------------------
- The ACE pre-processor: APP, is modest when compared with the C pre-processor.
-
- Its main function thus far is for the C-style inclusion of files with the
- #include directive. As in C, #include "filename" looks for the file as
- specified, while #include <filename> looks for the file in a local include
- directory (see "Installing ACE"). A file will only ever be included once.
-
- The #include directive can be used in included files, but since file inclusion
- is recursive, watch your stack size (20000 to 40000 bytes should be plenty).
-
- APP also handles single-line comments (lines starting with "'") and block
- comments (starting with "{" and ending with "}"). This is partly to allow
- #include commands to be commented out and also to make less work for the
- compiler. However, the compiler does still handle comments in case the pre-
- processor isn't invoked. APP does not handle REM since this is a BASIC
- statement.
-
- The syntax for APP is: app <source> <dest> and APP commands are case
- insensitive.
-
- The bas script uses APP by first pre-processing an ACE source file to RAM:t.
-
- Use of #include can have the effect of adding lines to the pre-processed ACE
- source file in the ram:t directory. Line numbers referred to in compilation
- errors pertain to this file. Comments don't change the line numbering.
-
- APP will be improved and added to as time goes by.
-
- ACE include files have two purposes. First, like C they can be used to include
- constants and structure definitions etc. Second, as with files like WBarg.h and
- req.h, ACE include files may contain subprogram definitions and although this
- is quite possible in C, it seems to be less often done under the guise of .h
- files. I have arbitrarily chosen to append all include files with .h but there
- is no reason why this need be so. Purists will probably be aghast at this.
-
-
- Running ACE programs
- --------------------
- ACE programs can be run from either a shell/CLI or Workbench. In the latter
- case a tool icon must be created for the executable. One has been provided
- with the archive in the icons directory (exe.info).
-
- As far as I can tell, ACE programs are pure and so can be made resident once
- the pure bit is set with the protect command. I've had no problems so far.
-
-
- About the example programs
- --------------------------
- I have written a number of programs which illustrate most of the capabilities
- of ACE up to this point and you should find these with the ACE archive.
-
- Several programs are related to chaos theory and fractals, which is a pet
- interest of mine (and thousands of other programmers :). The other programs
- are an assorted bunch, designed to demonstrate the features supported by ACE.
-
- Some are optimised (at the source level) and some are not. You'll find that
- using integer variables can often result in quite dramatic improvements
- in program execution speed (eg: try replacing op% with op and k% with k in
- ifs.b and you'll see what I mean). However, this depends a bit on the data
- types *expected* by various routines, so you'll have to experiment a bit.
-
- There are several examples which demonstrate the use of recursive
- subprograms in ACE (eg: fact.b). See the section on subprograms below.
-
- Another area of interest for me is neural networks and you'll find a
- program called hopnet.b, which shows graphically how a simple Hopfield
- network changes under various conditions. This program uses many of ACE's
- features and so is a good test of the compiler.
-
- Other programs include tic-tac-toe (ttt.b), a talking clock (tclock.b),
- a sound sample player (play.b) and a Tiny BASIC interpreter.
-
-
- General comments
- ----------------
- I made a decision very early on in the project to allow standard I/O (to shell
- or CLI) because this feature was lacking in other BASIC compilers I'd seen
- (except HiSoft's). ACE's standard output routines expect the default topaz 8
- font and the use of other fonts may have weird effects upon your display.
-
- The execution speed of most programs (especially with graphics, eg: ifs.b) is
- _fast_ compared to interpreted AmigaBASIC.
-
- No error messages are given at run-time yet, nor is there any stack overflow
- or array bounds checking. This means that executables are fast on the whole,
- but a rogue program will very likely stomp all over memory and invoke
- the GURU (or its Wb 2.04 equivalent). Still, the nature of BASIC doesn't
- encourage rogue programs.
-
- Labels are supported and can be used with GOSUB and GOTO. Line numbers are
- now supported, but are only necessary for old BASIC programs. Also, ACE's
- rich assortment of control constructs makes the use of GOTO rarely necessary.
-
- Available control constructs are: WHILE..WEND, REPEAT..UNTIL, IF..THEN..ELSE,
- IF..THEN..ELSE..END IF, CASE..END CASE, ON..GOTO, ON..GOSUB, SUB..END SUB and
- GOSUB..RETURN.
-
- Apart from single line comments with REM and ' ACE allows block comments with
- "{" and "}" ala Pascal. For example:
-
- { comments can span more than
- one line like this }
-
- Multi-statements are also supported by ACE, eg:
-
- x$="hello":y$="there":say translate$(x$+" "+y$)
-
-
- Data types, expressions and constants
- -------------------------------------
- The following data types are currently supported:
-
- - signed short integers (2 bytes)
- - signed long integers (4 bytes)
- - single precision: Motorola fast floating point (4 bytes)
- - strings (1024 bytes including ASCII 0 end-of-string marker)
-
- Exponential and fixed-point formats are now recognised by all ACE functions
- and in program text for single-precision numbers.
-
- Expression parsing is the same as for AmigaBASIC, as is the precedence of
- operators. Evaluation of _all_ expressions proceeds from left to right.
- This includes exponentiation, so 2^3^2 will be evaluated as (2^3)^2.
-
- In addition, due to the higher precedence of exponentiation over unary
- negation and the way ACE's recursive descent parser works, 4^(-2) is okay,
- but 4^-2 isn't. This is actually better than AmigaBASIC which doesn't even
- allow the former syntax.
-
- ACE supports full 32-bit and single-precision floating point math:
-
- addition, subtraction, multiplication:
-
- - 16 bit integer
- - 32 bit integer
- - single precision
-
- division & modulo arithmetic:
-
- - 32 bit integer
- - single precision
-
- Increment and decrement operators are provided in ACE in the following form:
-
- ++<variable> OR --<variable>
-
- The value of the simple or external variable is incremented or decremented by 1.
-
- Notice that ++ and -- are pre-increment & pre-decrement operators ONLY. Those
- familiar with C will recognise these operators and their utility. In terms of
- efficiency: ++x is better than x=x+1.
-
- Unlike interpreted AmigaBASIC, hexadecimal and octal constants can be either
- short or long values. This makes for nicer addressing with PEEK & POKE.
-
- Trailing characters (%&!#) after constants cause coercion from one numeric
- data type to another, as in AmigaBASIC, eg:
-
- Delay(50&) '..50 is coerced from short to long integer
- x=12.5*65! '..65 is coerced from short integer to single-precision
-
- As in AmigaBASIC expression evaluation, all operands are converted to the
- data type of the most precise operand. Logical operators convert their
- operands to integer values. Relational operations result in long integers.
-
- ACE's boolean values are as follows: 0=false, N=true where N is any non-zero
- long integer. Note that relational operations yield -1 for true (NOT -1 = 0).
-
- ACE allows you to define global signed numeric constants with the CONST
- directive (see command and function reference).
-
- Strings have a default length of 1K instead of the usual 32K, since ACE
- programs reserve memory for each string immediately at run-time which could
- result in quite memory hungry executables if strings were too large. It is
- possible however, to define strings which are longer or shorter than 1K (see
- STRING command).
-
- ACE strings are NULL terminated as in C (ie: the last character is an ASCII 0).
- A string literal without a final '"' will be truncated at the end of the line.
-
-
- Precedence of operators
- -----------------------
- This is the same as AmigaBASIC with the addition of structure dereferencing
- and indirection operators.
-
- operators
- ---------
-
- 1. Structure Member Dereferencing ->
- Parentheses and Address Operator () @
- 2. Indirection Operators *% *& *!
- 3. Exponentiation ^
- 4. Unary Negation -
- 5. Multiplication and Floating-Point Division * /
- 6. Integer Division \
- 7. Modulo Arithmetic MOD
- 8. Addition and Subtraction + -
- 9. Relational Operators = < > <= >= <>
- 10. NOT
- 11. AND
- 12. OR and XOR
- 13. EQV
- 14. IMP
-
- The use of parentheses in an expression forces the enclosed term to be
- evaluated before adjacent terms. Expression evaluation always proceeds from
- left to right in ACE and AmigaBASIC.
-
-
- Identifiers
- -----------
- In ACE, as in AmigaBASIC an identifier can consist of a combination of
- letters, numbers and periods (".") up to a maximum length of 40 characters.
- In addition, in ACE the underline ("_") character is also legal. An ACE
- identifier must start with either a letter or underline character.
-
- An identifier can be used to represent the following:
-
- - labels
- - variables
- - arrays
- - structures
- - subprograms
- - parameters
- - defined constants
- - shared library functions
- - external functions or variables
-
- Labels are global in ACE, so a main program label and a SUB label cannot have
- the same name.
-
- Identifiers can have a qualifier character (%&$!#) appended in order to
- indicate data type, where:
-
- % = short integer (2 bytes)
- & = long integer (4 bytes)
- ! = single precision (4 bytes)
- # = double precision (8 bytes) -> not supported yet
- $ = string (1024 bytes including end-of-string)
-
- Examples of valid identifiers are:
-
- x3
- num&
- _putchar
- play.sound
-
- An identifer with no qualifier has a default type of single-precision. The
- DEFxxx compiler directives (see command and function reference) have the
- same effect as the qualifier characters except they affect all identifiers
- starting with a certain letter or letters. Qualifier characters have higher
- precedence than DEFxxx directives.
-
- For shared library functions and external references, a qualifier is used
- merely to declare data type. So, for example, an external function _RangeRand
- might be defined thus:
-
- external function _RangeRand%
-
- but can later be referred as _RangeRand or RangeRand%.
-
- The declaration of external functions/variables and shared library functions
- is global no matter where the declaration occurs.
-
- Defined constants are unaffected by qualifier characters. The _value_ of a
- defined constant determines its type. Thus CONST x&=1.2 is a single-precision
- - NOT a long integer - constant.
-
- The declaration of constants (with CONST) is always global whether the
- declaration takes place in the main program or a subprogram.
-
- Structure variables always hold a long integer value (address), so trailing
- characters have no effect.
-
- Structure type declarations are global, but structure variable declarations
- are local.
-
- ACE allows for *optional* variable declarations with the SHORTINT, LONGINT,
- ADDRESS, SINGLE and STRING directives. Such declarations are useful in that:
-
- - they ensure that a variable has a NULL or zero value.
- - they provide a "cleaner" way of establishing a variable
- which is to be shared by a subprogram.
- - most languages have them and they serve to document
- variable usage explicitly.
-
- Variable declarations override the DEFxxx compiler directives and qualifier
- characters and are local to the main program or a subprogram.
-
- Summary of identifier properties:
-
- +---------------+---------------+------------------+
- | Identifier | Local/Global | Affected by %&!$ |
- +---------------+---------------+------------------+
- | ARRAY | LOCAL | YES |
- | SIMPLE VAR | LOCAL | YES |
- | STRUCTURE VAR | LOCAL | NO |
- | PARAMETER | LOCAL | YES |
- | STRUCTURE DEF | GLOBAL | NO |
- | LABEL | GLOBAL | NO |
- | DEF'D CONST | GLOBAL | NO |
- | SUBPROGRAM | GLOBAL | YES |
- | SH'D LIB FUNC | GLOBAL | YES (declaration)|
- | EXT VAR/FUNC | GLOBAL | YES (declaration)|
- +---------------+---------------+------------------+
-
-
- Indirection operators
- ---------------------
- ACE has four indirection operators: @,*%,*&, and *!. These are _similar_
- to C pointers.
-
- @<object> - returns the absolute address of a data object.
- - note that this is identical to VARPTR(<object>).
- *%<address> - peeks or pokes a short value at the specified address.
- *&<address> - peeks or pokes a long value at the specified address.
- *!<address> - peeks or pokes a single value at the specified address.
-
- The indirection operators can therefore be used in a statement (poke) and/or
- as part of an expression (peek), for example:
-
- deflng x
- y=23.25
- x=@y
- *!x := *!x + 2
- print y
-
- will print a value of 25.25.
-
- There are two things to notice here. First, the pointers are to addresses,
- not necessarily connected to variables. It would be quite legal to allocate
- an area of memory and then dereference it with these operators.
-
- Second, when assigning a value to a dereferenced memory location as in the
- above example, the ":=" symbol must be used, simply because of the way the
- parser processes statements. Pascal programmers will recognise this as
- the assignment operator.
-
- See also the section below for information about how to use these operators
- to implement variable parameters (call-by-reference) in ACE subprograms.
-
-
- Structures
- ----------
- Structures have been included in ACE mainly because of their utility in
- gaining access to operating system functions.
-
- Legal structure members are of the following type: BYTE (in structures only),
- SHORTINT, LONGINT, ADDRESS, SINGLE, STRING. The latter can have an optional
- size specification. BYTE members are coerced to and from SHORTINTs.
-
- If an array or structure is required as a structure member, it is necessary
- to use STRING <ident> SIZE <bytes>. The address of the member can then be
- found with @ or VARPTR and assigned to an array or structure variable.
-
- If you want to have an address (ie: pointer to an object) as a structure
- member simply declare it as an item of type ADDRESS (or LONGINT).
-
- When declaring a structure, the only difference between the following two
- forms:
-
- DECLARE STRUCT mystructtype mystruct
- and
- DECLARE STRUCT mystructtype *mystruct
-
- is that for the former, an appropriate data object is created, but not for
- the latter. In both cases, mystruct contains the start address of a structure
- of type mystructtype. In the second case, the address is NULL until assigned
- a value (eg: with ALLOC). In both cases, the address can be reassigned at
- will, although this should only really be done for structure pointers (the
- second form).
-
- Since both forms of structure declaration result in an address being stored
- (in mystruct in the example), the dereferencing operator is always "->".
-
- examples:
- --------
-
- PRINT mystruct - prints the start address of the structure.
-
- PRINT mystruct->mins - prints the value of a member called mins.
-
- The SIZEOF function can be used to determine the size of a structure type
- if allocating memory for a structure (see linkedlist.b).
-
- ACE structures are stand-alone data objects, and cannot be elements in an
- array (although structure addresses can be). ACE structures can be SHARED,
- or a structure's address can be passed to a subprogram, eg:
-
- struct my
- longint one
- longint two
- end struct
-
- declare struct my first
-
- sub test(addr&)
- declare struct my *second
- second=addr&
- print second->one
- end sub
-
- '..main
- first->one=12
- print first->one
- test(first)
-
- which will print 12 twice.
-
- The following code allocates enough memory to hold a structure of type "my",
- zeros the structure's two LONGINT members, and changes the address held by
- the structure variable "third" to the newly allocated memory:
-
- const PUBLIC=2
-
- declare struct my *third
-
- sub create(ADDRESS a_struct)
- declare struct my *temp
- temp = Alloc(sizeof(my),PUBLIC)
- temp->one = 0
- temp->two = 0
- *&a_struct := temp '..change structure variable's value
- end sub
-
- '..main
- create(@third)
- .
- .
-
- Finally, it is not currently possible to use INPUT, (LINE) INPUT# or READ in
- conjunction with structures.
-
-
- Subprograms
- -----------
- Subprograms are supported by ACE, but differ from AmigaBASIC subprograms in
- a number of ways. Namely, ACE subprograms:
-
- - are non-static
- - allow recursion
- - can be assigned return values
-
- By way of explanation, being non-static means that once a subprogram has
- finished execution, its local variables and parameters (effectively or
- actually) cease to exist.
-
- Recursion is (in my opinion) an important feature of modern general
- programming languages. For several examples of the use of recursion, see
- the included programs (eg: fact.b, hanoi.b and tree.b).
-
- A word of warning about recursion: it can be stack hungry, so it's a good
- idea to set your stack to 20000 or so, just to be safe, although in most
- cases, this will be a lot more than you need. From Workbench, simply change
- the tool's stack size with Info, or with the stack command in a shell.
-
- As with AmigaBASIC, ACE subprogram declarations cannot be nested.
-
- The syntax of a subprogram call is the same as in AmigaBASIC:
-
- [CALL] sub-name[(parameter-list)]
-
- The only difference is that the parentheses around the parameter list are
- not optional when CALL is omitted -- unless there are NO parameters.
-
- CALL must be used after THEN in a single-line IF..THEN statement.
-
- By default, every subprogram has a return type of single-precision (just like
- variables). DEFINT,DEFLNG etc can be used to change the default data type of
- subprograms, as can the trailing characters !#$&%.
-
- This pretty much obviates the need for DEF FN which is not supported in ACE.
- If you really need to you can create a subprogram with a name starting with
- FN for an old BASIC program in which DEF FN was used.
-
- A subprogram is given a value either inside the body of the relevant
- subprogram or in the main program (eg: to zero it) - ala Pascal - thus:
-
- sub-name = <expression>
-
- However, subprograms cannot be assigned a value in any other way (eg: with
- INPUT or READ).
-
- A subprogram can be used in an expression, whereupon the subprogram is called
- and its value pushed onto the stack for inclusion in the final result of the
- expression. An example of this might be:
-
- x=n*pow(n)
-
- where "pow" is a subprogram with one parameter.
-
- While subprogram declarations can appear anywhere within the program text,
- ACE requires that declarations precede calls. So:
-
- sub test
- print "hello"
- end sub
-
- test
-
- is legal, but:
-
- test
-
- sub test
- print "hello"
- end sub
-
- is not, and will yield an "undeclared subprogram" error. To get around this,
- a forward declaration is used:
-
- declare sub test
-
- test
-
- sub test
- print "hello"
- end sub
-
- Forward declarations can include a parameter list. If you later declare
- the actual SUB with a different parameter list and you've already called
- the subprogram after a forward declaration, the results will be unpredictable.
- I may place tighter controls on this at some stage.
-
- Actual parameters are checked for number and type against formals, and
- parameter count mismatches result in a compilation error. An actual parameter
- is coerced to the formal parameter's type.
-
- ACE's parameter passing mechanism for subprograms is NOT the same as that
- used for machine code routines or external functions. In other words, the
- standard C parameter passing mechanism is not used for SUBs. This may be
- changed in the future as it makes object modules written in ACE incompatible
- with C or assembler object modules in this respect.
-
- Changes made to a formal parameter have no effect upon the actual parameter
- in a simple call to an ACE subprogram (see "Limitations" re: overwriting of
- string parameters during recursive calls). The formal parameter list consists
- of identifiers separated by commas. Each identifier may also be preceded by:
- SHORTINT,LONGINT,ADDRESS,SINGLE or STRING to avoid use of a qualifier (%&!$).
-
- Currently, actual parameters can be expressions, simple variables,
- parameters (when calling one subprogram from another) and subprograms
- (the equivalent of passing a C or Pascal function), but not arrays. Array
- _elements_ can be passed as actual parameters however.
-
- There is an arbitrary upper limit of 40 parameters per subprogram at the
- moment, which may be removed at some stage. This limit also applies to
- SHARED variables (see below).
-
- Main program variables and arrays can be accessed and modified within
- subprograms via the SHARED directive. All shared variables are passed by
- reference to a subprogram.
-
- Multiple SHARED statements are allowed within a single subprogram.
-
- DIM SHARED is not allowed. An array is declared to be shared in exactly the
- same way as simple variables, for example:
-
- DIM x(10)
-
- sub thing
- shared x
- .
- .
- end sub
-
- Note that parentheses are not required after an array in the shared statement,
- nor are they legal.
-
- The differences between variable parameters and shared variables in ACE
- are that:
-
- - shared variables only allow access to main program
- variables from a subprogram, and do not provide a
- mechanism for changing the value of variables in
- one subprogram from another.
- - the name of a variable to be shared must correspond
- to the name of an existing (ie: already referenced/declared)
- main program variable.
-
- Although variable parameters are not explictly provided by ACE there are
- two ways to implement them: using indirection operators for simple variables
- and the ADDRESS option of DIM and STRING (see also "Structures" section above).
-
- Here's an example of call-by-reference parameters for simple variables
- (note: DEFxxx directives are used here for clarity only):
-
- deflng x '..x is address holder
- defsng n '..n is a single-precision variable
-
- sub doub(x)
- *!x := *!x * 2 '...n=n*2 [note the ":=" symbol!]
- end sub
-
- n=22.5
- print n
- doub(@n) '..pass the address of n
- print n
-
- which passes the single-precision variable n by reference to the subprogram
- doub, where n is doubled. This will first print 22.5 and then 45.
-
- For an array, the following could be done:
-
- deflng x '..x is address holder
-
- sub test(x)
- dim a(10) address x '..points to n
- a(3)=a(3)+12
- end sub
-
- dim n(10)
- n(3)=2
- print n(3)
- test(@n)
- print n(3)
-
- which would print first 2 and then 14.
-
- These variable parameter mechanisms are most useful when used to pass data
- *between* subprograms, otherwise it is simpler to use SHARED variables.
-
- The following table shows the possibilities regarding parameters and shared
- variables in ACE:
-
- +---------------------+---------+-------------+-----------------------------+
- | Data Type / Object | Shared | Value param | Variable param |
- +---------------------+---------+-------------+-----------------------------+
- | SHORTINT VARIABLE | YES | YES | YES - *%addr |
- | | | | |
- | LONGINT/ADDRESS VAR | YES | YES | YES - *&addr |
- | | | | |
- | SINGLE VARIABLE | YES | YES | YES - *!addr |
- | | | | |
- | STRING VARIABLE | YES | YES | YES - STRING x ADDRESS addr |
- | | | | |
- | EXTERNAL VARIABLE | NO | YES | YES - *%, *&, *!, STRING .. |
- | | | | |
- | ARRAY | YES | NO | YES - DIM x ADDRESS addr |
- | | | | |
- | STRUCTURE | YES | NO | YES - *&addr (see above) |
- +---------------------+---------+-------------+-----------------------------+
-
- Note: In the above table, "addr" is a long integer address. VARPTR or @
- can be used to obtain this. The address is passed to the SUB by value.
- Strings and arrays use the same method, an example of which was given above.
-
-
- Shared library function calls
- -----------------------------
- ACE provides access to shared libraries in much the same way as
- AmigaBASIC does except that you are required to be a bit more specific
- when declaring functions in ACE.
-
- The commands are as follows:
-
- LIBRARY libname
-
- - where libname is NOT a quote-enclosed string, but the name
- of a shared library in ROM or in your libs directory
- (eg: LIBRARY graphics). Don't add the ".library" suffix.
- - the LIBRARY command opens the shared library and provides
- its base address for use by functions.
- - if a library can't be opened at run-time, the ACE program
- will quit.
-
- LIBRARY CLOSE libname
-
- - closes the shared library libname.
-
- DECLARE FUNCTION funcname LIBRARY libname
-
- - where funcname is the case sensitive name of a function in
- the library libname (eg: DECLARE FUNCTION Move LIBRARY graphics).
- - funcname may have a trailing character (&%#!$) to indicate type
- otherwise default data type rules apply for the function's
- return type. This character is optional when CALLing the function.
-
- [CALL] funcname[(parameter-list)]
-
- - transfers control to the function funcname, loading the
- appropriate registers before doing so, according to the
- information about that function in the library's bmap file
- (in the ACE:bmaps directory - see "Installing ACE" section).
- - the return value of a function can be accessed by calling
- a function as part of an expression (r-value)
- (eg: addr&=Alloc(100,2).
-
- Function declarations are GLOBAL. They are are NOT optional.
-
- ** PLEASE NOTE ***
- No type checking of parameters is performed, so expect weirdness if you pass
- values of the wrong type. If the RKM or whatever reference you are using for
- library functions says to use a long integer, then do so. Don't assume that
- a short integer will be coerced to a long integer. It won't.
-
- When passing strings as parameters it is not necessary to add a CHR$(0)
- to the end of a string since ACE strings are already NULL terminated.
-
- Either VARPTR or SADD can safely be used to find the address of a string
- variable or constant. Actually, the use of SADD or VARPTR for strings
- passed to library functions is optional, but it's probably a good idea to
- use one or the other all the time, for consistency's sake. These comments
- also apply to calling machine code routines and external functions.
-
- The library itself MUST be in sys:libs (unless it's in ROM).
-
- It is up to YOU to open and close libraries correctly. ACE doesn't keep
- track of this, and will try to jump to a library function so long as
- it finds a reference to it in a .bmap file even if the library hasn't
- been opened! It is not necessary to open and close the dos.library because
- every ACE program does this.
-
- ACE expects the .bmap file for a library to be in the directory ACEbmaps:
- (see "Installing ACE"). I have been advised by Commodore Australia that
- these files may be distributed with ACE but I will wait until I have this
- in writing before providing them with the archive.
-
- In a future release I intend to provide a program which is functionally
- equivalent to ConvertFD (since this may NOT be freely redistributed) so that
- .bmap files for new libraries can be created. If you have the 1.3 Extras disk,
- you can use ConvertFD anyway, along with the .FD files Both are to be found in
- the BasicDemos drawer.
-
- AmigaBASIC cannot handle functions which use address register a5. This is
- not true for ACE. Neither ACE nor AmigaBASIC allow the use of functions which
- use register a6. The use of this register for parameters seems to be restricted
- to the cia.device anyway.
-
- See library.b for an example of how to use shared library functions in ACE.
-
- In all ACE programs, there are typically a couple of shared libraries opened
- at the start of execution (at least one anyway: dos.library) and closed at the
- end of execution. If you issue a LIBRARY command to open/close a standard
- library which ACE had to open at start-up, the library won't be opened/closed
- at the time you think it should be (eg: mid-execution). Rather, such a library
- will be opened at the start of execution and closed at the end of the program
- run.
-
- An ACE program will abort if a library doesn't exist or can't be opened.
-
-
- Machine code calls
- ------------------
- ACE supports AmigaBASIC's mechanism for calling machine code routines and
- the passing of parameters to such routines. AmigaBASIC's stack conventions
- are also followed (ie: C style parameter passing).
-
- The syntax for calling such a routine is:
-
- CALL long-integer-variable-name[(parameter-list)]
-
- Note that CALL is NOT optional and the variable containing the address of
- the routine *must* be a long integer.
-
- For example,
-
- CALL caps&(length&,addr&)
-
- will set up the stack like this:
-
- 8(sp) = addr&
- 4(sp) = length&
- 0(sp) = return address
-
- on entry to the machine code subroutine caps&.
-
- On exit from a routine, ACE cleans up the stack by POPping all parameters.
-
- You can use a short integer array, a string or an allocated area of memory
- (with ACE's ALLOC function) to poke the bytes of a machine code routine into.
- I prefer the latter method.
-
- Note that because ACE treats ASCII 0 as the end-of-string character, don't
- use the string-building method, eg:
-
- z$=""
- for i=1 to N
- read b
- z$=z$+chr$(b)
- next
-
- since if b=0, chr$(b) will be the NULL string. If you want to use a string,
- do the following:
-
- z$="" '..or STRING z$ SIZE 100 (if there are 100 bytes of MC).
- addr&=sadd(z$)
- for i&=0 to N-1
- read b%
- poke addr&+i&,b%
- next
- call addr&
-
- The latter should be okay, so long as you don't allocate other strings with
- odd sizes. But if you want to be sure that you have an area of memory which
- is long-word aligned, use ALLOC, eg:
-
- addr&=Alloc(100,2) '..100 bytes of PUBLIC memory
- for i&=0 to N-1
- read b%
- poke addr&+i&,b%
- next
- CALL addr&
-
- The above examples assume the presence of appropriate DATA statements. See
- ledflash.b and caps.b for examples.
-
- ACE also supports inline assembly code inclusion. See ASSEM..END ASSEM in
- ref.doc for details.
-
-
- External references
- -------------------
- Reference can be made to a variable or function in another file which is
- resolved at link time. You may for instance, have written a function in C
- or assembler. It is possible to pass parameters to, call and obtain return
- values (as with ACE SUBs) from such a function in ACE after declaring an
- external reference to the function with the EXTERNAL FUNCTION directive
- (see command and function reference for syntax).
-
- When passing parameters, standard C parameter passing conventions are
- observed. Although some C compilers seem to pass all parameters as
- 4 bytes per parameter on the stack, ACE allows 2 (short words) or 4
- byte parameters. Be aware of this! See func.b and func2.b for examples.
-
- External variables can be assigned values like normal variables, for example:
-
- external RangeSeed&
- RangeSeed=5276&
-
- All external reference identifiers have an underscore prefixed by ACE but
- this is optional when declaring or using an external reference. C compilers
- prepend an underscore to external symbols, so ACE does too.
-
- Note that the names of external references ARE case sensitive.
-
- Also, the bas script can take as a third argument, the name of the object
- file produced from the original C or assembly source (ie: .o or .lib file)
- which contains the external function or variable to be linked with your
- ACE program.
-
- It's not easy to call ACE SUBs from C or assembler for two reasons:
-
- 1. ACE SUBs don't currently use C parameter passing conventions.
- 2. ACE produces whole assembly source programs, not just functions
- like a C compiler does.
-
- For now, you'll have to get your hands dirty with the assembly source code
- produced by ACE. ACE's -c switch may be of some help here.
-
-
- Program arguments
- -----------------
- When called from a Shell or CLI, an ACE program may have arguments, eg:
-
- tree 30
-
- Arguments can be accessed by two ACE functions:
-
- ARGCOUNT and ARG$(n)
-
- The former returns a short integer value indicating the number of arguments
- for the current program, while the latter returns the nth argument as a string,
- where n ranges from 0 to argcount. The zeroth argument (ie: ARG$(0)) is the
- name of the program.
-
- Workbench arguments are supported by ACE in the form of four functions in the
- include file WBarg.h: WBargcount, WBarg$(n), WBargPath$(n) and WBargLock&(n).
-
- The first three are most useful. The fourth is mainly for use by WBargPath$(n).
- WBargcount returns the number of arguments passed to a program as single
- clicked icons. The zeroth argument is the name of the program and thereafter
- are the names of those icons which have been activated (single clicked).
-
- To pass arguments to a program via Workbench a shift key is held while the
- icons which represent the arguments to be passed are activated. While still
- depressing the shift key, the application icon is double clicked.
-
- An alternative method of passing arguments is to change the default tool of a
- project icon (document etc) with the Info option from Workbench.
-
- When this project icon is double clicked, the default tool will be loaded.
- In this case, if the default tool (the program) had a line such as x$=WBarg$(1)
- x$ would contain the name of the project icon.
-
- WBargPath$(n) is used to find the full path of the file name and includes
- trailing ":" and "/" characters.
-
- See the include file WBarg.h for further descriptions of each function.
-
-
- Windows
- -------
- You can open up to nine user-defined windows on the Workbench screen.
- See the command and function reference for the syntax of the WINDOW
- statement.
-
- All user-defined windows in ACE are currently RAW: windows and any such
- window will have the standard RAW: gadgets, so the "type" parameter in
- the AmigaBASIC syntax has no relevance in ACE. As mentioned earlier, I
- have relied heavily on standard I/O in ACE, and the use of such windows
- is consistent with this.
-
- In ACE, the current output window and the selected output window are
- identical (see WINDOW(0) & WINDOW(1)).
-
- The WINDOW function takes a single parameter and returns information about
- the current output window:
-
- WINDOW(0) - same as window(1)
- WINDOW(1) - window-id of current output window.
- WINDOW(2) - present width of current output window.
- WINDOW(3) - present height of current output window.
- WINDOW(4) - x-coordinate in current output window where next
- pixel will be plotted (always.
- WINDOW(5) - y-coordinate in current output window where next
- pixel will be plotted.
- WINDOW(6) - maximum legal colour-id for current output window.
- WINDOW(7) - pointer to Intuition Window for current output window.
- WINDOW(8) - pointer to Rastport of current output window.
- WINDOW(9) - pointer to AmigaDOS file handle for current output window.
- WINDOW(10) - foreground pen in current output window.
- WINDOW(11) - background pen in current output window.
-
- Note that the WINDOW function can also be used for a SCREEN (see below), but
- only the arguments 2,3,4,5,6,7,8,10 and 11 are meaningful.
-
- When called from a console window (opened with the WINDOW command), WINDOW(4)
- and WINDOW(5) return zero, presumably because of the AmigaDOS manipulation
- of the Intuition environment.
-
-
- Screens
- -------
- Screens are implemented, but currently have some limitations. You can open
- 9 screens at once (memory permitting!).
-
- Currently, when a screen is opened, a BORDERLESS window the same size as
- the screen is also opened. All subsequent graphics commands send their
- output to the newly created screen's window (until the latter is closed).
- In order to print to such a window, a special command is needed: PRINTS
- (see ref.doc for details about PRINTS).
-
- The existence of an Intuition window allows an ACE program to read keyboard
- events. At the moment, the only way of getting input from a screen's window
- is with ACE's INKEY$ function, but I have written an include file (inputs.h)
- which consists of screen INPUT functions.
-
- When a screen is first opened, it is set to black. This can be changed with
- a combination of COLOR and CLS or by changing the values in PALETTE 0.
-
- When a screen and its window are closed, ACE makes the screen with the next
- highest screen-id the current output screen, so it is advisable to open and
- close screens in ascending and descending order.
-
- While in screen mode, don't use WINDOW OUTPUT as there will be no way of
- directing output back to the screen. A future revision of ACE will probably
- allow user-defined windows on screens.
-
- A special SCREEN(n) function exists in ACE which returns pointers to various
- Intuition structures (window,screen,rastport,viewport). This is detailed in
- the command and function reference (ref.doc) as are the following commands:
- SCREEN, SCREEN CLOSE, PALETTE and PRINTS.
-
- Finally, the following ACE commands and functions can be used in either window
- or screen mode transparently: INKEY$,LOCATE,CLS,PSET,LINE,CIRCLE,PAINT,PALETTE,
- COLOR,MOUSE,POINT,PRINTS,AREA,AREAFILL,PATTERN and the turtle graphics commands.
-
- See also WINDOW(n) in the above section on windows.
-
-
- Files
- -----
- AmigaBASIC sequential files are implemented and random files are on the list
- of things to do.
-
- The commands and functions for manipulating sequential files in ACE are:
-
- commands:
- - OPEN
- - CLOSE
- - PRINT#
- - WRITE#
- - INPUT#
- - LINE INPUT#
-
- functions:
- - INPUT$
- - EOF
- - LOF
- - HANDLE *
-
- * not found in AmigaBASIC
-
- Note that for any command which is immediately followed by a # there should be
- at least one space between the keyword and the #, even though I refer to such
- commands as <command># in the text of this document and ref.doc.
-
- See the command and function reference for details of each of these.
-
- When WRITE# is used, the result is identical to AmigaBASIC. For example:
-
- X=12 : Y=-3.2 : Z$="fun eh?"
- OPEN "O",#1,"stuff"
- WRITE #1,X,Y,Z$
- CLOSE #1
-
- results in a one-line file of the following format:
-
- 12,-3.2,"fun eh?"
-
- On the other hand, if the following is used instead:
-
- PRINT #1,X,Y,Z$
-
- the file format will be:
-
- 12 -3.2 fun eh?
-
- while if semicolons are used:
-
- PRINT #1,X;Y;Z$
-
- the file format becomes:
-
- 12 -3.2 fun eh?
-
- INPUT# (eg: INPUT #1,X,Y,Z$) can be used to read values from a file in any of
- the above formats, but bear in mind that strings that are not delimited by
- quotes, but contain spaces or tabs will be seen as more than one string by
- INPUT#. So, in the example formats above, while
-
- "fun eh?"
-
- is one string,
-
- fun eh?
-
- is two strings as far as INPUT# is concerned.
-
- The formats of sequential files in ACE and AmigaBASIC are now very nearly
- identical, the only differences being in ACE tabs (produced by comma
- delimiters in PRINT -- see PRINT in ref.doc) and the number of decimal
- places written for single-precision values (usually more in ACE).
-
- Notice that strings are delimited with double quotation marks by WRITE
- but not by PRINT. For better or worse, this is what AmigaBASIC and ACE do.
-
- If you find ACE file I/O too slow, you may want to use the dos.library
- functions (eg: xRead, xWrite). For this reason, I have included the HANDLE(n)
- function which returns the AmigaDOS handle of a file opened with ACE's OPEN
- command. You may also wish to use the ami.lib buffered file I/O functions which
- also require this AmigaDOS handle. If HANDLE returns 0, the file doesn't exist.
-
- See print.b for an example of opening a sequential file to a printer (PRT:).
-
- Although SER: may be opened as a sequential file, it is not yet possible to
- specify parameters for the serial port (baud rate etc) by this method as is
- possible in AmigaBASIC. I am still thinking about the best way to implement
- this.
-
-
- Sound
- -----
- ACE provides you with similar functionality as AmigaBASIC for sound
- generation. It also allows you to do some things that AmigaBASIC doesn't.
-
- How many times have you wished that AmigaBASIC would let you produce
- white noise easily like the good ol' C64 and Vic-20 did?
-
- Well, you'll be pleased to know that ACE allows you to do this. All you
- have to do is allocate about 4000 or more bytes of Chip RAM (upwards of
- 4000 bytes yields better quality white noise), poke it with random values,
- (between -128 and 127) call WAVE and you're set (see sound.b)!
-
- Moreover, you can actually play sound samples (IFF or otherwise) in the
- same way, using just the two commands WAVE and SOUND. In fact, I've written
- a program in ACE that plays sound samples and recognises IFF 8SVX samples
- (see play.b).
-
- See sound.b for an example of how to use ACE's sound facilities in general.
-
- As with AmigaBASIC, a sine waveform is the default, but through the WAVE
- statement you can create any waveform you wish including sawtooth, triangle
- and square.
-
- WAVE has the following syntaxes:
-
- WAVE voice,SIN
-
- and
-
- WAVE voice,waveform-address,byte-count
-
- where waveform-address is the beginning of a block of memory where the waveform
- resides (an area of Alloc'd CHIP memory) and byte-count is the number of bytes
- in the waveform table.
-
- The SOUND statement syntax is as follows:
-
- SOUND period,duration[,volume][,voice]
-
- This is different to AmigaBASIC in a number of ways. First, in ACE you
- specify the sampling period NOT the frequency. This was easier to implement
- and still provides the same functionality, but if you want specific notes,
- you'll have to do the calculations yourself (see equations below).
-
- Sampling period is inversely proportional to frequency, so a high sampling
- rate corresponds to a low frequency and vice-versa. ACE allows you to
- specify a sampling period in the range 124..32767.
-
- The duration is a single-precision value as in AmigaBASIC but can range from
- 0..999 (instead of 0..77). This range is somewhat arbitrary, but gives plenty
- of scope for large sound samples. This specifies the length of time that a
- tone should be played for. A duration of 18.2 corresponds to about 1 second.
-
- Volume defaults to 64 if not specified and can range from 0..64.
-
- The voice can be in the range 0..3 - since there are 4 audio channels -
- with 0 & 3 corresponding to the left speaker and 1 & 2 to the right.
- The default voice is 0.
-
- At the moment, ACE's SOUND statement isn't very good when used to produce a
- series of short pulses, although this is somewhat dependent upon the waveform
- in use. In any case, more work needs to be done in this area to prevent
- "popping" between SOUND statements when the audio hardware is turned on and
- off in rapid sequence.
-
- ACE sound is produced by programming the hardware directly. A future version
- will probably utilise the audio device instead.
-
- Finally, here's some useful equations for use in conjunction with ACE's SOUND
- statement:
-
- samples/second to period:
- ------------------------
- period = 3579546 / samples-per-second
-
- musical note to period:
- ----------------------
- period = 3579546 / (length * frequency)
-
- where length is the size of the waveform table in bytes
- (32 bytes for ACE's sine waveform) and frequency is the
- note itself (eg: middle C is 523.25 Hz).
-
- duration value for one waveform cycle:
- -------------------------------------
- duration = .279365 * period * length / 1E6 * 18.2
-
-
- Turtle Graphics
- ---------------
- You may be wondering some of these things:
-
- - what the heck is Turtle Graphics?
- - isn't that for kids?
- - why did he include THAT?
-
- To answer the first question: Turtle Graphics (TG) originated as a subset of
- the language LOGO invented by Seymour Papert at MIT. LOGO was originally
- intended as a language for learning. Children are able to write simple programs
- to draw shapes on the computer's screen or move a Turtle - a dome-shaped robot
- - on a sheet of paper on the floor, thereby learning about geometry by doing.
-
- LOGO also has many Lisp-like qualities and so can be used as a serious
- language for AI work, although it isn't to my knowledge.
-
- But I digress. Apart from the fun kids can have with TG, it's actually
- possible to construct quite complex shapes with it. Combined with recursion,
- TG is a powerful tool. It is particularly useful in plotting many fractal
- shapes (see snowflake.b, dragon.b).
-
- Since the first LOGO, there have been many manifestations of TG. Turbo Pascal
- for the PC and the Mac have both had TG.
-
- A couple of years ago, I wrote a pure TG subset of LOGO which used the same
- syntax as the original language and allowed recursive procedures. I've also
- written TG functions in C. Both of these have been useful to me and I've often
- wished that BASIC came with TG built-in. Well, now one dialect does!
-
- For some examples of the use of Turtle Graphics in ACE, see the following
- programs:
-
- - tree.b
- - flower.b
- - boxit.b
- - torus.b
- - dragon.b
- - snowflake.b
-
- The above discussion should have answered the second question. As for
- the third, the answer is: because I wanted to!! :^)
-
- Okay, enough philosophy. Here's the ACE stuff:
-
- BACK n - move turtle back by n.
- FORWARD n - move turtle forward by n.
- HEADING - return turtle's current heading in degrees (0..359).
- HOME - move turtle back to its home position.
- PENDOWN - put turtle's pen down.
- PENUP - lift turtle's pen up.
- SETHEADING degs - change turtle's heading to degs.
- SETXY x,y - change turtle's current x,y location.
- TURN degs - rotate turtle by degs.
- TURNLEFT degs - turn turtle left by degs.
- TURNRIGHT degs - turn turtle right by degs.
- XCOR - return turtle's current x-coordinate.
- YCOR - return turtle's current y-coordinate.
-
- where:
- - n is pixels (x:y ratio is 2.25:1 -- assumes hi-res screen).
- - degs is a signed short integer representing degrees with
- the turtle starting at a 270 degree orientation -- pointing up).
- - home is the turtle's x,y start location (0,0).
-
- Note that the X:Y ratio can be modified thus:
-
- EXTERNAL _tg_xy_ratio!
- _tg_xy_ratio = 1.125 '..1.125 is about right for a lo-res screen
-
- Most LOGO environments use a coordinate system where 0,0 is at the center of
- the screen and positions to the left and down of this origin are negative while
- those up and to the right are positive. ACE's TG system however, uses the
- Amiga's normal graphics coordinate system with 0,0 at the top left of the
- screen/window, so as to maintain consistency with other graphics commands
- such as PSET, LINE and CIRCLE.
-
- If a negative value is specified for the turnleft or turnright commands,
- the turtle will be rotated in the opposite direction to that indicated by
- the the command name. Note that there is also a turn command.
-
- When using these commands, it's best to think of an imaginary turtle (in LOGO
- it's usually a small triangle on the screen) which rotates and moves according
- to your whim. The turtle can either have its pen lowered or raised - and will
- therefore draw or not - which is useful when you need to move in a relative
- fashion from one location to another without drawing anything.
-
- SetXY is like the graphics library Move() command and may need to be preceded
- by PENUP unless you want to draw a line.
-
- To change the colour of the pen, use the COLOR command.
-
- That's probably enough about Turtle Graphics. Oh, by the way, if you ever
- get the chance to read Papert's "Mindstorms", do so. It's good value.
- While I think of it, Sherry Turkle - that's Papert's wife - wrote a book
- called "The Second Self: Computers and the human spirit", which I recommend
- if you're at all interested in the psychological/social effects of computing.
-
-
- Event trapping
- --------------
- ACE provides for AmigaBASIC-style event trapping. The following event
- types are supported:
-
- BREAK - ctrl-c (user break).
- MOUSE - left mouse button.
- TIMER(n) - cause a trap every n seconds.
- MENU - right mouse (menu) button -- not implemented yet.
-
- Since ACE has no sprite support, ON COLLISION is not included as yet.
-
- Event trapping in ACE works by checking for a given event at strategic points
- in a program (before NEXT, WEND, GOTO, CALL, PRINT etc) and if an event is
- detected, control is passed to a trap handling routine. Hence, trapping here
- does not refer to software traps (exceptions).
-
- The specification for the trapping of an event is:
-
- ON <event> GOSUB | GOTO <label>|<line-number> (eg: ON BREAK GOTO quit)
-
- which indicates the routine to which control is to be passed when a trap
- occurs. This is followed at some stage by:
-
- <event> ON (eg: BREAK ON)
-
- which causes all code from that point in a program - UNTIL the trap handling
- routine - to contain (at the object code level) event trapping code.
-
- It is a good idea to put trap handlers at the end of a program, since once the
- handler for an event is found by the compiler, no more event trapping code is
- generated for that event even if there is code below the handing routine. In
- other words, the equivalent of an <event> OFF (see below) command is issued
- once the trap handing code is entered.
-
- Other commands are:
-
- <event> STOP
-
- which disables trapping for the event until another <event> ON is issued,
- and:
-
- <event> OFF
-
- which disables trapping for the event permanently.
-
- Just so there is no misunderstanding, the latter two commands prevent the
- inclusion of event trapping code for a specific event in your program at the
- assembly source level. They do this from the point in an ACE program at
- which they are issued.
-
- Here's a typical example:
-
- ON BREAK GOTO quit
- BREAK ON
-
- for i=1 to 1000000
- print i
- next
-
- quit:
- PRINT "**break!"
- STOP
-
- ACE event trapping will be improved as time goes by (eg: ON MENU).
-
-
- Error Handling
- --------------
- The error messages generated by ACE are mostly different to the ones in the
- AmigaBASIC interpreter (and ACE doesn't beep at you :) but are usually fairly
- clear.
-
- Syntactically incorrect programs can lead ACE to produce a bunch of spurious
- error messages. In such cases, it's best to ignore all but the first one or
- two, unless there are "clusters" of messages which are separated by periods
- of error-free compilation.
-
- If you leave out END IF, WEND, UNTIL, NEXT, END SUB, END STRUCT or END CASE,
- there will be a corresponding number of error messages at the end of the
- compile. If you leave off two WENDs, you'll get 2 "WHILE without WEND" error
- messages.
-
- ACE only reports the first error in a line of code and ignores the remainder
- of the "bad" line. A typical message consists of the line containing the error,
- a carat ("^") marker, and the error message itself. More work still needs to
- be done on ACE's compile-time error handling, but it's not too bad.
-
- No error messages are issued by ACE programs at run-time yet. Generally,
- when a program runs into something it can't do, or an erroneous request - like
- trying to open two files to the same file number or trying to open a library
- that doesn't exist - the program will either quit or just not have the desired
- effect. I intend to have run-time errors generate an autorequester in future.
-
-
- Notes for assembly programmers
- ------------------------------
- I've tried to make the assembly source files that ACE produces as
- readable as possible by using meaningful data object names. See also
- "Compiler options" re: the compiler's -c switch.
-
- Linked library routines use data registers d0-d6 and address registers
- a0-a3, while d7 is used for array index calculations. Also, a4 and a5 are
- used as stack frame pointers for variables and parameters.
-
- db.lib routines don't save and restore registers via the stack, but the
- use of registers is internally consistent.
-
- The use of linked libraries means that the size of all executables is
- fairly large. But given that disk space and memory are cheap, I'd rather
- this than the alternative of having every executable be dependent upon one
- or more special shared libraries at run-time. However, I will try to reduce
- the size of executables.
-
- Due to BASIC's tendancy to coerce data types so much for the programmer,
- the resulting code can look a little nasty, and big increases in efficiency
- can be gained by careful combinations of data types in expressions.
-
- Writing ACE has so far been a learning experience for me and if when I started,
- I knew what I know now, I would have done many things differently.
-
- My original rationale for passing parameters via registers to ACE (and shared)
- library functions was to improve execution speed. However, since I call lots
- of other functions (eg: in ami.lib) which require their parameters to be on
- the stack, I would probably call ALL functions in this way if I did it again.
- Oh well.
-
- Moreover, my desire for internal consistency led me to a rather odd method of
- passing parameters to SUBs. This allowed me to treat parameters in the same way
- as variables which is all very nice, but it led to other problems, chief among
- them being the need to use a Forbid()/Permit() pair when sending parameters to
- a SUB. This works fine however, so I'm taking the view that if it 'aint broke,
- I probably shouldn't fix it.
-
-
- Limitations
- -----------
- Although ACE can theoretically handle arrays with up to 255 dimensions, I
- have set an arbitrary limit of 10 dimensions (hands up how many of you ever
- use more than 3?), mainly in the interest of minimising symbol table size.
- However, I will probably remove this limit at some stage.
-
- Variables do NOT get a default zero or NULL value, so don't assume ANYTHING
- about the contents of an uninitialised variable. For example: PRINT X will
- yield garbage if X has not been given a value. The optional variable
- declarations provided in ACE are therefore worth using since they DO give
- variables an initial zero or NULL value.
-
- The precision of exponentiation begins to falter with large numbers because
- all exponentiation is currently done with the single-precision math library
- function SPPow().
-
- While strings can be defined to be longer (or shorter) than 1K, there
- are some ACE commands and functions which still assume a 1K limit, namely:
- STRING$, SPACE$, LINE INPUT#, INPUT and SWAP.
-
- Recursive activations of a subprogram will allow local strings and arrays
- to be overwritten. The same applies to string parameters. In all these cases
- a single static data item is being referenced.
-
- If you issue RETURN from within a FOR loop, the return address will *not* be
- the top item on the stack. Instead, FOR..NEXT loop data will be. A GURU will
- almost certainly result. Use a while or repeat loop if you must RETURN. In
- general, don't branch out of a FOR loop, never to return. GOSUB & CALL are
- okay since they both return control back to the next statement in the loop.
-
- A shared variable cannot be used as a FOR loop index in ACE. Any attempt to
- do so will result in a compilation error. There is no need to do this anyway.
-
- IF..THEN NEXT will not have the desired effect (it's bad coding anyway).
- NEXT must always appear on a line by itself or as part of a multi-statement.
-
- Expressions and parameter lists cannot currently be split over more than
- one line. I intend to change this.
-
- The compiler currently only responds to ctrl-c during the main compilation
- phase, and not during optimisation or when target code is being written.
-
- ON BREAK and ctrl-c trapping currently only works from windows, not screens.
-
- Don't mix the compiler's -b option with BREAK event trapping, as they will
- conflict.
-
-
- Known Bugs
- ----------
- When ACE aborts due to internal list allocation errors (on 512K machines
- typically, or with big programs), there is sometimes a small memory leak.
- Although this doesn't cause me problems, it might do so on a 512K machine
- after several compilations, and is obviously undesirable in any case.
-
- There seems to be a ctrl-c trapping mechanism produced by ZC which sometimes
- competes with my own ctrl-c trapping code in ACE and APP. I've fixed this to
- some extent and the bug surfaces far less often now. If you get the "ace/app
- terminating" message, all is well, otherwise memory won't be properly cleaned
- up. Please note that this is a problem with the compiler, not the executables
- generated by ACE/A68K/Blink.
-
- The SAY(n) _function_ works under Workbench 2.04 but not under 1.3. Since the
- function uses no 2.04-specific code, this is puzzling. The SAY command works
- under both 1.3 and 2.04 however.
-
- I'm working on these problems, so please be patient.
-
- A68K sometimes complains about string literal definitions produced by ACE
- which are much longer than a single line.
-
-
- Future versions
- ---------------
- Double-precision floating-point and menus are high on the agenda.
-
- Other plans include more graphics commands, random files plus miscellaneous
- other commands and functions.
-
- Use of PRINT and INPUT will eventually be screen/window transparent.
-
- ACE's WINDOW command may allow for user-defined windows on screens.
-
- I may provide support for gadgets and sprites at some stage.
-
- Thus far, I've taken the approach of implementing what I most often use
- and what I have often wished for in BASIC.
-
-
- Disclaimer
- ----------
- Although every care has been taken in the development and testing of the
- compiler and its libraries, the author will not be held liable for damages
- caused either directly or indirectly as a result of the use of ACE.
-
-
- References
- ----------
- The following references have been used throughout the development of ACE:
-
- =============
- "Amiga BASIC", 1985, Commodore-Amiga Inc. and Microsoft Inc.
-
- "Amiga ROM Kernel Reference Manual: Libraries and Devices", Commodore-Amiga
-
- Anderson, Thompson, 1990, "Mapping the Amiga", COMPUTE! Publications Inc.
-
- Berry, 1986, "Inside the Amiga with C", SAMS
-
- Bleek, Jenrich, Schulz, 1989, "Amiga C for Advanced Programmers", Abacus
-
- Bleek, Jenrich, Schulz, 1989, "Advanced System Programmers Guide", Abacus
-
- Choi, 1990, "Advanced Programming Techniques", University of Tasmania
-
- Commander, 1987, "Amiga Assembly Language Programming", TAB Books Inc.
-
- Dittrich, 1989, "Amiga Machine Language", Abacus
-
- Schaun, 1990, "Amiga C for Beginners", Abacus
- =============
-
- The most frequently used of these has been "Mapping the Amiga". Despite
- it's not infrequent errors, it remains an excellent resource. I have
- also referred quite often to the two machine language books as well as to
- the Advanced C programming book by Bleek et al.
-
- Although not listed, Commodore's Autodocs for the Amiga (supplied with the
- Native Developer Kit) are constantly used.
-
- Young Choi's Advanced Programming notes were in many ways the impetus for
- the development of ACE. They were used in a compiler construction course
- I took as an undergraduate. I thank Young for introducing me to the joys
- of compiler writing. Including the Pascal Minus compiler I wrote for that
- course, and the BASIC interpreter I wrote in the same period, I've since
- written a Logo interpreter, a Forth interpreter and ACE.
-
-
- Final word
- ----------
- Let me offer my thanks to Charlie Gibbs for his reliable assembler and to
- the Software Distillery for Blink. Without these excellent programs, far
- fewer compilers would have seen the light of day, including ACE.
-
- Sozobon C (ZC) has always been a reliable workhorse for me, so a vote of
- thanks goes to Sozobon as well. Isn't PD great?
-
- I'd like to thank those people who have tested ACE so far: Addison Laurent,
- Byron Montgomerie, Juergen Weinelt, Alan Peyton-Smith, Michael Zielinski,
- Ken Thompson and others.
-
- These guys have given ACE a good workout on a variety of platforms ranging
- from an A1000 running Wb 1.3 to 68030 machines running Wb 3.0. They have
- all pointed out a number of bugs/problems to me which have either been fixed
- or put on the list of things to fix.
-
- I'd especially like to thank Michael Zielinski for discovering a particularly
- serious bug which prevented branches of greater than 32K in length prior
- to v1.02. Also, Enforcer hits reported by him started me on a trail which led
- to a nasty string-related bug (see entry for 13/4/93 in docs/history).
-
- Jarto 'Robin' Tarp pointed out how inefficient my first implementation
- of INSTR was. It's considerably faster now.
-
- Let me stress that any remaining bugs in ACE are entirely my fault.
-
- Many others have given me a great deal of encouragement and made useful
- comments in recent times. I hope this continues.
-
- I'd also like to thank my fiancee, Karen Lacey, for her encouragement and
- support and for putting up with the number of hours I spend at the computer.
-
- Despite ACE's problems (see "Limitations" and "Known Bugs") it is already
- proving to be a useful tool for me, and if others can derive benefit from it,
- well, that's great. Although ACE has a long way to go before it can be called
- complete (if ever!), I'm not terribly concerned about that. As long as it does
- most of what you want and is extensible, I guess that's the main thing.
-
- The provision of calls to shared library functions, external functions,
- machine code routines, inline assembly code, and #include files should
- go a long way towards making up for ACE's intrinsic shortcomings.
-
- I hope you enjoy ACE and find it useful. I'm learning a great deal by
- developing it and having a lot of fun in the process, so I'm not after
- monetary rewards. Of course, please feel free to donate if you wish!
-
- What I DO want is feedback. If you have any problems, requests, queries or
- suggestions, I want to hear from you and I'd like to hear about interesting
- programs you've written with ACE (e-mail the source to me if you like!).
-
- Obviously I want to know about bugs too.
-
- Remember that ACE is FreeWare, so redirect flames to /dev/null (ie: be nice).
-
- Happy ACEing!
-
- Regards, David Benn
- 10th July 1993
-
- +-----------------------------------------------+
- | Internet: dbenn@leven.appcomp.utas.edu.au |
- | Compuserve: 100033,605 |
- | Discovery 40: 032432850 |
- | |
- | Phone: (003) 317 680 [home] |
- | (003) 243 285 [work] |
- | |
- | Address: 181 St John Street, Launceston, |
- | Tasmania, Australia, 7250 |
- +-----------------------------------------------+
-