Amiblitz3 Manual - Aros the OpenSource OS running on UAE and real hardware

Elektrotechnik Zenker
Direkt zum Seiteninhalt
Amiblitz


Amiblitz3 manual

1 Introduction

1.1 What is AmiBlitz³?

 AmiBlitz³ is a free, open-source programming language for AmigaOS3.x and
 compatible. It comes with its own integrated development environment called
 PED (Program EDitor). PED includes a texteditor, multi-source handling and
 various browsers for functions and documentation. The compiler itself is
 called AmiBlitz³ and generates 68K executables or shared libraries.
 Executables can be debugged using a source code level runtime debugger.
 There are two types of runtime libraries, the so called BlitzLibs
 (68K static libraries) and the Includes (source code libraries).
 
1.2 Design Issues

 AmiBlitz³ is the non-commercial follower of BlitzBasic2 on the Amiga,
 published by AcidSoft. BlitzBasic was designed to develop games for Classic
 Amigas, with direct support for the classic hardware, such as OCS/AGA
 chipset or Paula for audio. Over the years, especially when BlitzBasic became
 Amiblitz, the system conform parts were more and more developed, leading to
 a programming language that can be used for other hardware too, such as x86
 running Amithlon or WinUAE, PPCs running AmigaOS4 or MorphOS, as long as the
 OS API is compatible and the OS is able to execute 68K code.
 The runtime libraries of AmiBlitz³ are splitted up into:

 AcidLibs (BlitzLibs)
   AcidLibs are the original BlitzLibs (something like "linker" libs)
   from AcidSoft. All the basic functionality can be found here, that AcidSoft
   wanted to have in BlitzBasic.
   The AcidLibs (like all other BlitzLibs) come as binary 68K code and are
   automatically loaded during IDE startup. There is no need to link/include
   them manually.

 DefLibs (BlitzLibs)
   DefLibs are BlitzLibs that extent the functionality on certain topics, most
   of them are 3rd party developments and were intended to be configurable
   via the "MakeDefLibs" tool.
   However in reality, and to keep the source code cross-installation
   compatible, they are part of the distribution and should not be changed
   anymore, if there is no vital reason to do so. It is very likely that there
   won't be any new DefLibs in the future.
   
 AmigaLibs (BlitzLibs, aka FD-Converted Libs)
   AmigaLibs are BlitzLibs too, but they do no contain real code, they are just
   wrappers to integrate an Amiga Shared Library into AmiBlitz³.
   The AmigaOS3.x API plus some other important Shared Libraries are
   integrated that way. All AmigaLibs are part of the Deflibs.

 Includes (Source Code)
   Includes are NOT BlitzLibs. They are AmiBlitz³ source code files that are
   included (usually at the beginning) in the source code of a program.
   Unlike BlitzLibs, they are coded in AmiBlitz³ and not in 68K Assembler.
   This makes them debugable, user-expandable and, in the future, maybe
   CPU-retargetable.
   
 BlitzLibs have the followig shortcommings:
 - maximum 128 tokens (instructions/functions/directives/keywords) per library
 - maximum 256 libraries installed at the same time
 - fix IDs for libraries (most of them are already in use)
 - coded 100% in Assembler, bad maintainability
 - many BlitzLib source codes are not available and are not maintained anymore
   
 This is why future projects should use Includes to expand the runtime of
 AmiBlitz³.
 Includes are always included on source code level and therefore maintainable.
 There is no limit for the amount of includes or their tokens.
 Amiga Shared Libraries can be made availabe in AmiBlitz³ programs as Includes,
 like the SDL.library, bsdsocket.library or amissl.library.
   
1.3 Comparism AmiBlitz³, C and BASIC

1.3.1 How does AmiBlitz³ compare to BASIC?

 Pros:
 - AmiBlitz³ compiler is insanely fast, the fastest compiler I have ever seen.
 - AmiBlitz³ generates highly optimized 68K code, probably much faster than
   any BASIC dialect does.
 - AmiBlitz³ allows forced variable declaration.
 - huge Runtime Library (BlitzLibs/Includes)
 
 Cons:
 - AmiBlitz³ does not conform to BASIC standards.
   (your BASIC specific knowledge is pretty much useless).
 - AmiBlitz³ is only available for AmigaOS3.x and compatible.

1.3.2 How does AmiBlitz³ compare to C/C++?

 Pros:
 - AmiBlitz³ compiler is much faster than e.g. GCC.
 - AmiBlitz³ does not use ";" (semicolon) to seperate expressions.
   Authors' opinion: Generally, the semicolon as an expression delimiter is
         a good idea, but practically it creates unnecessary attention
         the coder has to pay.
 - An AmiBlitz³ project is much simplier set up than a C makefile.
   (actually, you just compile the main file)                                            
 - Every source code file can have a build-in demo that is ignored if the
   file is used as an include (#__include compiler constant).
 - Strings are primitive types and as easy to handle as integers.
 - AmiBlitz³ is less complex and higher leveled.
 - Variables can be declared during usage, in 68K ASM style by using
   a type extension (a.l = 0), no declaration monsters like
   "unsigned static const char * myVar".
 - Variables are initialized, no random bugs due to uninitialized variables.

 Cons:
 - C is widely spread and much more examples and documentation is out there.
 - C is available for almost every OS/CPU.
 - AmiBlitz³ does not support object oriented programming.
 - AmiBlitz³ is not type safe.
 - AmiBlitz³ does not allow forward declaration.
 
2 Syntax

 An AmiBlitz³ program is a sequence of expressions (and definitions/
 compiler directives).
 Two expressions are separated by a new line or by a ":" (colon).

 +-----------------------------------------------------------------------------
 |
 | expression
 | expression : expression
 |
 +-----------------------------------------------------------------------------

 An expression is usually a BlitzLib instruction, variable assignment or
 a function call.
 Example:
 +-----------------------------------------------------------------------------
 |
 | DEFTYPE.s myStringVar
 | myStringVar = "Hello World!" : NPrint a.s
 | End
 |
 +-----------------------------------------------------------------------------

2.0.1 Comments  

 A comment is added by using the ";" (semicolon), and always ends at
 the end of line:
 +-----------------------------------------------------------------------------
 |
 | expression ; this is a comment
 |
 +-----------------------------------------------------------------------------
 
2.0.2 Multi-Line Expressions  

 An expression can be spanned over multiple lines, if the new line is escaped
 by "@@" (two at-signs):
 +-----------------------------------------------------------------------------
 |
 | expression part1 @@
 | expression part2
 |
 +-----------------------------------------------------------------------------
 Note: AmiBlitz³ needs "new syntax mode" enabled by using optimize 4.

2.0.3 Blocks of Expressions  

 The "End something" instruction is used terminate a block of expressions
 that have been grouped together, e.g. if they make up the body of a loop,
 function, or the conditional block of an "If":
 +-----------------------------------------------------------------------------
 |
 | If condition
 |   expression
 |   expression
 |   ...
 | End If
 |
 | Function.t name{...}
 |   expression
 |   expression
 |   ...
 | End Function
 |  
 +-----------------------------------------------------------------------------
 Note: "condition" is an expression that evaluates to a boolean (true/false).
 Note: A single "End" terminates the whole program.
 Note: Some types of blocks (but not all) have a single-token shortcut, e.g.
       "End While" can be written as "Wend", "End If" as "EndIf".

 See section 2.1 Program Flow for more details.
 
2.1 Program Flow

 The program flow is from top down. The program starts with the first
 expression in the source code and keeps on running until it exits with
 "End".
 An "End" is forced if the execution runs into the void. When the
 debugger is used, this will cause a runtime error.
 Be careful that you program does not run into data sections.

2.1.1 Labels

 +-----------------------------------------------------------------------------
 |
 | ['][.]label[:]
 |
 +-----------------------------------------------------------------------------
 
 A label is specified by stating its name with an optional . (full stop) or '
 (apostrophe) in front. It is a good style to use a seperating ":" (colon)
 after the label, however, it is not necessary.

 To avoid clashes of label names, a label can be made locally unique by using
 the ' (apostrophe) modifier. The label name will be concatenated with the
 previous label, thus being locally unique.
 
 The leading full stop is used to indicate that the label should be visible
 in the source browser of the IDE for quick access.

 Example:
 +-----------------------------------------------------------------------------
 |
 | John:         ; this is a normal label
 |
 | 'Smith:       ; actual label name becomes "JohnSmith"
 |
 | .Jack:        ; this is another label, visible in source browser
 |
 | 'Smith:       ; actual label name becomes "JackSmith" and does not clash with
 |               ; above 'Smith, thus being locally unique.
 |
 +-----------------------------------------------------------------------------

2.1.2 Goto

 +-----------------------------------------------------------------------------
 |
 | Goto label
 |
 +-----------------------------------------------------------------------------
 
 A simple branch is performed. Program execution will continue
 at the position after the label.

 Example:
 +-----------------------------------------------------------------------------
 |
 | myLabel:
 |
 | ...
 |
 | Goto myLabel
 |
 +-----------------------------------------------------------------------------
 Note: "Goto" is usually considered as a beginner's programming style and
       theoretically can be always avoided. However, there might be
       situation where a "Goto" is handy and makes life easier.

2.1.3 Gosub/Return

 +-----------------------------------------------------------------------------
 |
 | Gosub label
 |
 | Return
 |
 +-----------------------------------------------------------------------------
 
 A branch to a subroutine is performed. Program execution will continue
 at the position of the label, and the address of the calling "Gosub" is
 remembered. When the program execution reaches a "Return", it will jump back
 to the position after the calling Gosub. This is used for subroutines, that
 should be executed in the global context rather than a function that uses its
 own, local context.

 Example:
 +-----------------------------------------------------------------------------
 |
 | ...
 |
 | Gosub mySubRoutine  ; jump to label "mySubRoutine"
 |
 | ...
 |
 | End                 ; end of program
 |
 |
 | mySubRoutine:
 |
 | ...                 ; do something ...
 |
 | Return              ; jump back to the calling Gosub
 |
 +-----------------------------------------------------------------------------
 Note: "Gosub" is usually considered as a beginner's programming style.
       Gosub is sometimes handy but makes your code unmaintainable if the
       project grows. Usage is only recommended in very small, script-like
       applications. Ohterwise, use functions instead.
       
2.1.4 If/Then/Else

 To make the execution of a block of statements dependent on a condition
 (expression that evaluates to type boolean), use "If":

 +-----------------------------------------------------------------------------
 |
 | If condition : ... : End If
 |
 | If condition Then ...
 |
 +-----------------------------------------------------------------------------

 The code in the "If" block is only executed, if the condition evaluates to
 true. If the condition is not the result of an comparator, e.g. a number,
 anything else than a 0 (zero) is interpreted as true, while the 0 is
 interpreted as false. In case of strings, all strings are true, except the
 empty string is interpreted as false.
 
 The "End If" is only needed, if the block spans over multiple lines.
 Otherwise they can be omitted and a "Then" is used. All expressions in the
 same line belong then to the conditional block.

 Example:
 +-----------------------------------------------------------------------------
 |
 | If a=0 Then a=1 : Print "Hello!" ; single line If-block
 |  
 | If a=0                           ; multi line If-block
 |   a=1
 |   Print "Hello!"
 | End If
 |
 +-----------------------------------------------------------------------------

 For every "If", you can define an alternative "Else" block:

 +-----------------------------------------------------------------------------
 |
 | If condition : ... : Else : ... : End If
 |
 | If condition Then ... : Else ...
 |
 +-----------------------------------------------------------------------------

 Same rules for multilines apply for the "Else" block.

 Example:
 +-----------------------------------------------------------------------------
 |
 | If a=0 Then a=1 : Print "Hello!" : Else a=0 : Print "Blabla."
 |  
 | If a=0
 |   a=1
 |   Print "Hello!"
 | Else
 |   a=0
 |   Print "Blabla."
 | End If
 |
 +-----------------------------------------------------------------------------

2.1.5 While/Wend

 +-----------------------------------------------------------------------------
 |
 | While condition : ... : Wend
 |
 +-----------------------------------------------------------------------------

 This executes a block of expressions, while the condition evaluates
 to true. Same rules as for the "If" condition apply for numeric or string
 values.

 Example:
 +-----------------------------------------------------------------------------
 |
 | While a>0
 |   a=a-1
 |   Print "Hello!"
 | Wend
 |
 +-----------------------------------------------------------------------------

2.1.6 Repeat/Until

 +-----------------------------------------------------------------------------
 |
 | Repeat : ... : Until condition
 |
 +-----------------------------------------------------------------------------

 This is the same like a while loop, only that the condition is tested
 at the end of the block in contrast to the beginning of the block. Thus, the
 block is always executed at least once.

 Example:
 +-----------------------------------------------------------------------------
 |
 | Repeat
 |   a=a-1
 |   Print "Hello!"
 | Until a<=0
 |
 +-----------------------------------------------------------------------------

2.1.7 For/Next/Step

 +-----------------------------------------------------------------------------
 |
 | For var=a To b [Step increment] : ... : Next
 |
 +-----------------------------------------------------------------------------

 A "For" loop is a loop that sets a counter variable to an initial value a,
 executes a block of expressions and then de/increments the counter until it
 reaches the "To" value b.
 increment is the value added to the counter variable for each step,
 and is 1 if omitted. increment may also be negative for reverse loops.
 
 Examples:
 +-----------------------------------------------------------------------------
 |
 | For n=a To b : ... : Next        ; n is incremented by 1 for each cycle
 | For n=a To b Step c : ... : Next ; n is incremented by c for each cycle
 |
 +-----------------------------------------------------------------------------
 
 A real example (output the first 100 positive integer numbers):
 +-----------------------------------------------------------------------------
 |
 | For n.l=1 To 100
 |   NPrint n
 | Next
 |
 +-----------------------------------------------------------------------------

2.1.8 Select/Case

 "Select" is selecting a "Case" block for execution that matches a previously
 given value. If none of the "Case" blocks matches the value, the optional
 "Default" block is exectued.
 
 +-----------------------------------------------------------------------------
 |
 | Select value
 |   Case alternative1
 |     ...
 |   Case alternative2
 |     ...
 |   ...
 |   Default
 |     ...
 | End Select
 |
 +-----------------------------------------------------------------------------

 The Select/Case construct should be prefered over a cascade of "If" block, if
 a value is checked against more than one alternative.
 
 Example:
 +-----------------------------------------------------------------------------
 |
 | Select a.l
 |   Case 1   : NPrint "Value is 1"
 |   Case 2   : NPrint "Value is 2"
 |   Default  : NPrint "Value is something else..."
 | End Select
 |
 +-----------------------------------------------------------------------------
 Note: Unlike C "switch", no "break" is needed after each block.

2.1.9 End/initbasic

 +-----------------------------------------------------------------------------
 |
 | End
 |
 +-----------------------------------------------------------------------------

 "End" frees all resources (that AmiBlitz³ is aware of...) and terminates
 the program. All programs, including libraries, must have this function as the
 last instruction.

 +-----------------------------------------------------------------------------
 |
 | initbasic
 |
 +-----------------------------------------------------------------------------

 "initbasic" will move the initialization code of AmiBlitz³ to this line.
 It is not allowed to execute any AmiBlitz³ code before this function is called,
 *if* it is called.
 If there is no initbasic, this will be done before the first line of source code.
 "initbasic" should be called only once or never! This is for advanced
 programming only.

2.2 Variables

 Variables are "containers" that hold data (like numbers or strings) that can
 be addressed by the variables name. To specify the type of the data,
 a variable is usually "declared" before it is used. During the lifetime of the
 variable, it cannot change its type.
   
 The most formal way to declare a variable is explicitly by using the "DEFTYPE"
 compiler directive and always use the type extension when the variable
 is used.

 +-----------------------------------------------------------------------------
 |
 | DEFTYPE.t name, ...       ; declare variable name as type .t
 | name.t = expression       ; assign the result of the expression to name
 |
 +-----------------------------------------------------------------------------
 Note: See section 2.5 Primitive Types and 2.6 Newtypes for more information
       and possible types.
 Note: See section 2.8 Constants how to write constant expressions such as
       numbers or strings.

 Using the same variable name with different type extentions will lead to a
 type-missmatch compiler error.
 Variable names are case sensitive and can contain the character a-z, A-Z,
 0-9 and "_" (under score), but are not allowed to start with a number.
 Variables are always initialized to zero or empty string, depending on the
 type.
 There are three strictness settings that influence the declaration of
 variables. The compiler directive is called "Syntax n", were "n" can be
 0 (default), 1 or 2.
   
2.2.1 Syntax 0 (loose, default)

 Variables don't have to be explicitly declared. Their type can be specified
 during their first usage by mentioning the type extension. If they are used
 the first time without a type extension, they get the default type.
 The default type can be changed by using the compiler directive "DEFTYPE.t"
 without declaring a variable. Per default, the default type is Quick (.q).

 Example:
 +-----------------------------------------------------------------------------
 |
 | a = 5.5             ; a is now type Quick (.q) and has the value 5.5
 | DEFTYPE.l           ; set the default type to Long (.l)
 | b = 6               ; b is now of type Long and has the value 6
 | c.q = 1             ; c is now of type Quick and has the value 1
 |
 +-----------------------------------------------------------------------------
 Note: This syntax mode is traditionally used in BASIC dialects. However,
       this is very unsafe if you plan a medium or large project. You can
       easily introduce errors by typos that occure during runtime, and not
       already at compile time.
       
2.2.2 Syntax 1 (strict)

 All variables have to be declared and the type extension has always to be
 mentioned.
 Note: This syntax mode is similar to Pascal. It is very safe against
       typos, but creates significant overhead and can be anoying.

2.2.3 Syntax 2 (medium, recommended)

 Variables don't have to be explicitly declared, but their type has be specified
 at least by mentioning their type extension on first usage.
 On later usage, the extension is optional.
 
 Example:
 +-----------------------------------------------------------------------------
 |
 | Syntax 2
 | DEFTYPE.l a, b, c   ; declare a, b and c as type Long (and set to 0)
 | d.l = 1             ; declare d as type Long   and set it to 1
 | e.f = 1.0           ; declare e as type Float  and set it to 1
 | f.s = "test"        ; declare f as type String and set it to "test"
 | g   = 5             ; this will throw a compiler error, because g is not
 |                       explicitly declared and no type is mentioned.
 | a.f = 5             ; this will throw a compiler error, because a is
 |                       already declared as type Long (.l)
 +-----------------------------------------------------------------------------
 Note: Don't mix the "Syntax" directive up with the so called
 "new syntax mode", which is enabled by the optimize 4 directive.

2.2.4 Assignment Shortcut

 As a shortcut, the assign operator "=" can be ommited if the first operand is
 also the variable to assign the result to.

 Example:
 +-----------------------------------------------------------------------------
 |
 | a = a+1   ; normal writing
 | a + 1     ; this does the same, it's a short cut
 |
 | a = a/2+5 ; normal writing
 | a / 2+5   ; short cut
 |
 +-----------------------------------------------------------------------------
 Note: Unlike "a /= 2+5" in C/C++, "a / 2+5" would first devide though 2 and
       then add 5 (respecting common mathematical precedence).

2.2.5 Global vs. Local Variables
    
 Variables that are declared in the global context (outside of a
 Function/Statement) are global and have a lifetime that equals to the runtime
 of the program.
 Variables that are declared in a local context (inside a Function/Statement)
 are local and have a lifetime that starts and ends with the local context.

 By default, global variables are not reachable within local contexts. To
 "import" a global variable into a local context, the "SHARED" directive is
 used. If this is done inside a local context, the import is valid only for
 this specific context. If SHARED is used in global context, the variable is
 imported implicitly to every local context.

 Example:
 +-----------------------------------------------------------------------------
 |
 | DEFTYPE.l a  ; declare a global variable
 | SHARED b.l   ; declare a global variable that is reachable in all functions
 |
 | Function.l test{}
 | SHARED a     ; a needs to be "SHARED"
 | c.l = a + b
 | Function Return c
 | End Function
 |
 +-----------------------------------------------------------------------------
 Note: "a" and "b" are both global variables. "a" needs to be explicitly
       imported, while "b" is imported automatically. "c" is a local variable
       that is not available in global context and its lifetime ends when the
       function exits.
 Note: The global usage of SHARED needs new syntax mode (optimize 4) to
       be switched on.

2.3 Arrays

 Arrays of variables are declared by using the "Dim" instruction and
 stating the number of elements in round brackets:
 +-----------------------------------------------------------------------------
 |
 | Dim [KEEP] name.t(n)
 |
 +-----------------------------------------------------------------------------

 name is an array of n elements of type .t, starting from index 0
 to #elements-1.
 Same as single variables, all array elements are initialized to zero.
 The keyword "KEEP" is optional and used if the array already exists and the
 content should be kept (only new elements are initialized to zero).
 If the array is down-sized however, data might get lost.
 
 An element is indexed by:
 +-----------------------------------------------------------------------------
 |
 | name.t(index)
 |
 +-----------------------------------------------------------------------------
 Note: Negative indices are not allowed. The index must be smaller
       than #elements.

 Any array can be "re-dimmed" any time by calling "Dim KEEP name.t (n)".

 Example:
 +-----------------------------------------------------------------------------
 |
 | Dim Race.s(5)        ; declare an array of strings called "Race"
 |
 | Race(0) = "Human"    ; fill the elements of the array
 | Race(1) = "Elve"
 | Race(2) = "Dwarf"
 | Race(3) = "Ork"
 | Race(4) = "Halfling"
 |
 | For n.l=0 To 4
 |   NPrint Race(n)     ; print out all 5 race names
 | Next
 |
 +-----------------------------------------------------------------------------
 Note: The last element is 4, since we have 5 elements, from 0..4.
       Using 5 or higher as index would cause a runtime error!

 Arrays (with some restrictions) can be also part of a newtype. See 2.6 Newtypes
 for details.
2.3.1 Multi-Dimensional Arrays

 Arrays can be multi-dimensional. The dimensions are seperated by "," (comma).

 Example:
 +-----------------------------------------------------------------------------
 |
 | Dim Matrix.l(10,10)  ; define a 10x10 matrix of long intergers
 |
 | Matrix(0,0) = 1
 | Matrix(4,2) = 4
 |
 | For x.l=0 To 9
 |   For y.l=0 To 9
 |     NPrint Matrix(x,y)  ; print out all elements of the matrix
 |   Next
 | Next
 |
 +-----------------------------------------------------------------------------
 Note: Be careful with multi-dimensional arrays. They can quickly eat up
       a lot of memory. E.g. Dim x.l(100,100,100) would alread eat up 4MB!

2.4 Lists

 Lists contain items (elements) of a certain data type, similar to arrays. But
 in contrast to arrays, they are not addressed by indices. One of the items
 in the list is the current one that can be accessed at the moment. To access
 the other items, you can move forward or backwards in the list by the
 functions "NextItem" and "PrevItem". Once you seek over the boundaries, those
 functions return false and there is no valid current list item until you
 start from the beginning of the list or seek in the other direction again.
 
 The benefit of lists over arrays is that you can easily add or remove
 items with a minimum overhead and without bookkeeping which element is
 currently used. Lists are ideal for objects in a game, which often appear
 and disapear and all of them have to be processed every frame.

 Lists are declared by using "List" and the "Dim" instruction:
 +-----------------------------------------------------------------------------
 |
 | Dim List name.t(n)
 |
 +-----------------------------------------------------------------------------

 name is now an empty list of type .t, with maximum of n items.
 The list is referred by using the round brackets without index.
 Items are handled by the following functions:
 +-----------------------------------------------------------------------------
 |
 | AddItem(name())           ; add a new item at the current position and
 |                           ; make it the current item
 | KillItem name()           ; remove the current item from the list
 | NextItem(name())          ; seek to the next item
 | PrevItem(name())          ; seek to the previous item
 | ResetList name()          ; seek before the first item
 | FirstItem(name())         ; seek to the first item
 | LastItem(name())          ; seek to the last item
 | ClearList name()          ; remove all items from list
 | SortList(name()[,field])  ; sort the list according the field name,
 |                           ; if it is a newtype
 | PushItem name()           ; push the current position to stack
 | PopItem name()            ; pop the current position from stack
 |
 +-----------------------------------------------------------------------------

 Example:
 +-----------------------------------------------------------------------------
 |
 | Dim List Race.s(5)           ; declare a list of strings called Race
 |
 | If AddItem(Race()) Then Race() = "Human"
 | If AddItem(Race()) Then Race() = "Elve"
 | IF AddItem(Race()) Then Race() = "Dwarf"
 |
 | ResetList Race()             ; go before the first item
 | While NextItem(Race())       ; print out all items
 |   NPrint Race()
 | Wend
 |
 | ClearList Race()             ; remove all items
 |
 +-----------------------------------------------------------------------------

2.4.1 Dynamic Lists

 If a List is declared with a "maximum" of 0 elements, its size is dynamic and
 only limited by the memory of the machine.

2.4 Seek Recursively Through Lists
 
 Let us imagine you have the following situation:
 You seek through a list and process a certain item. Now you have to call a
 subroutine (function or gosub) that needs to seek through the same list too.
 After returning from the subroutine, the current list item would be probably
 not the one you were processing.
 To solve this problem, every list has a "stack". You can push your current
 item on this stack (well actually a pointer to it), and pop it from stack
 again once the subroutine returns. You can then continue processing this item
 or seeking through the list from that position.
 
2.5 Primitive Types

 AmiBlitz³ knows the following primitive types:

 Name          | Extension | Size   | Value Range
 --------------+-----------+--------+---------------------------------------
 Byte          |       .b  |  8 bit | -128...+127
 Word          |       .w  | 16 bit | -32768...+32767
 Long          |       .l  | 32 bit | -2^31...+2^31-1
 Quick         |       .q  | 32 bit | -32768...+32767 (16.16 bit fix point)
 Float         |       .f  | 32 bit | quite large
 Double Float  |       .d  | 64 bit | even larger
 String        |     .s/$  | 32 bit | character string from 0-2^31-1 length
               |           | +64+(n+1)*8 bit
 Pointer       | *         | 32 bit | 0...2^31-1

 The AmiBlitz³ compiler will throw an error if the types within an
 expression don't match and can't be casted easily.

2.5.1 Byte (.b)
 
 The type Byte is a signed 8 bit integer.

2.5.2 Word (.w)
 
 The type Word is a signed 16 bit integer.
 
2.5.3 Long (.l)
 
 The type Long is a signed 32 bit integer.
 
2.5.4 Quick (.q)
 
 The type Quick is a signed, 16.16 bit fix point. That means, the upper
 16bit are used for the (signed) integer value, and the lower 16 bit are
 used for the fractional part.
 This type is a relict from BlitzBasic for machines that have no floating point
 unit. It is called "Quick" because it is quicker than a software-emulated
 floating point. The accuracy and the value range is pretty low, but well
 enough for coordinates of objects on the screen.
 If you use hardware FPU support however (see optimize 2), floats are much
 faster than Quicks.
 
 Quick is the default type in Syntax 0 variable declaration strictness level.

2.5.5 Float (.f)
 
 The type Float is a signed 32 bit floating point. One bit for the sign, 23 bit
 for the mantissa and 8 bit for the exponent.
 
 Floats are calculated either by software emulation (slow) or by a
 hardware FPU. Which implementation is used will be defined during compile time
 using the optimize 2 directive.
 
 Note: If you compile your program with "optimize 2", it will require
       an FPU to run.  

 Note: If you switch between software/hardware floats within a program,
       the float variables are not compatible, since the softfloat emulation
       uses a different format to store the value. You need to pass their
       value through a string or write a converter routine.  

2.5.6 Double Float (.d)

 The type Double Float is a signed 64 bit floating point. One bit for the sign,
 52 bit for the mantissa and 11 bit for the exponent.

 This type has a very high accuracy and value range. It is only available if
 hardware FPU support is switched on using the "optimize 2" directive.
 There is no software emulation build in.

2.5.7 String (.s or $)

 The type String is a variable sized, 0-terminated byte array.
 A string can contain any byte value, including the 0-byte. The acutal
 length and the length of the buffer is seperately stored.
 
 Usually, the length of the buffer is increased/decreased automatically wihtout
 the programmers notice. But in certain situations, it is handy to set it
 explicitly via:
 +-----------------------------------------------------------------------------
 |
 | Maxlen string.s = n      ; the the strings buffer to n bytes.
 |
 +-----------------------------------------------------------------------------

 The length of a string is practially only limited by the global temporary
 string buffer that is used during string operations to compose a result
 string. The size of this buffer is set in the compiler settings of the IDE.
 
 The extention .s of a string can also be written in the traditional BASIC
 style using a $. In that case, the $ become also part of the variable name and
 must always be written.

2.5.8 Pointer (*)
 
 See 2.7 Pointers for more information.
 
2.6 Newtypes (Complex Types)

 Newtypes are compositions of primitive and/or other Newtypes. In
 other literatur you might find them as "structures" or "complex types".
 
 They are defined using the "NEWTYPE" keyword and listing the field with name
 and type:
 +-----------------------------------------------------------------------------
 |
 | NEWTYPE name
 |   varname.t
 |   ...
 | End NEWTYPE
 |
 +-----------------------------------------------------------------------------

 A field in the type is addressed by using "\" (back slash):
 +-----------------------------------------------------------------------------
 |
 | NEWTYPE myType
 |   x.f
 |   y.f
 | End NEWTYPE
 |
 | DEFTYPE.myType test
 | test\x = 1
 | test\y = 2
 | NPrint "x is ",test\x," and y is ",test\y
 |
 +-----------------------------------------------------------------------------

 If a field is written without type, it "inherits" the type from the previous
 field. The first field needs to have a type explicitly mentioned.
 
2.6.1 Multi Assignments

 When assigning values, multiple fields can be filled at once by starting with
 one field and give several values separated by commas. Be careful that the
 order you specify the values is exactly matching the order of the fields in
 the Newtype. This is a potential source for bugs, e.g. when the Newtype is
 reordered.

 Example:
 +-----------------------------------------------------------------------------
 |
 | NEWTYPE myType
 |   x.f : y
 | End NEWTYPE
 |
 | DEFTYPE.myType test
 | test\x = 1,2
 |
 +-----------------------------------------------------------------------------
 Note: "y" is of type float, because the previous field "x" is of type float.
 Note: Like expressions, the multiple fields can be in the same line,
       seperated by a ":" (colon).  
 
2.6.2 Arrays in Newtypes

 Newtypes can contain one-dimensional arrays. In contrast to normal arrays,
 they are written using square brackets.
 +-----------------------------------------------------------------------------
 |
 | NEWTYPE myType
 |   x.f[10]
 | End NEWTYPE
 |
 | DEFTYPE.myType test
 | test\x[0] = 1
 | test\x[1] = 2
 |  
 | NPrint test\x[0]
 |
 +-----------------------------------------------------------------------------
 
2.7 Pointers

 A pointer stores a memory address. Technically, on 32bit machines, this is a
 32bit value.
 To declare a pointer variable to a certain type instead of the type
 itself, the "*" (asterix) sign will be put in front and becomes part
 of the name, thus has always to be written.
 If the content of the pointer is addressed, it needs to be dereferred by
 accessing the fields in the Newtype the pointer is pointing to.
 Primitive types cannot access their values, only via the Peek.t() function.  

 Example:
 +-----------------------------------------------------------------------------
 |
 | *myPointer.l = 0     ; declare *myPointer and let it point to address 0
 |
 | *myPointer = 12345   ; this would change the pointer to point to 12345
 |                      ; (which is a bad idea, actually)
 |  
 +-----------------------------------------------------------------------------
 
2.7.1 Dereferencing a Pointer

 To get the content a pointer points to, the type must be a newtype. It is
 dereferenced by accessing the fields in the newtype, just as if it was a
 "real" newtype rather than a pointer.
 Pointers to primitve types cannot be dereferenced. You need the function
 "Peek.t" to access the content.
 
 Example:
 +-----------------------------------------------------------------------------
 |
 | NEWTYPE.t
 |   x.l
 | End NEWTYPE
 |
 | DEFTYPE.l dummy
 | *myNewtype.t = &dummy.l ; let *myNewtype point to the content of dummy
 | *myNewtype\x = 12345    ; this will set the content of *myNewtype\x to
 |                         ; 12345.
 |                         ; Note: because it points to the content of dummy,
 |                         ; dummy is changed too!
 |
 | *myLong.l = &dummy.l    ; let *myLong point to the content of dummy
 |                         ; there is actually no way to access the content.
 | y.l = Peek.l(*myLong)   ; ...unless you use Peek.t()
 | Poke.l *myLong,12345    ; ...and Poke.t
 |
 +-----------------------------------------------------------------------------  
 Note: See next subsection what the "&" is doing!
 
2.7.2 Referencing a Variable
 To get a pointer to a variable use "&" (ampersand) in front of its name.

 Example:
 +-----------------------------------------------------------------------------
 |
 | DEFTYPE.l dummy  
 | *myLong.l = &dummy.l  ; let *myLong point to the content of dummy
 |
 +-----------------------------------------------------------------------------

 Warning: Be careful with pointers. This is for advanced programming.
 Because AmigaOS has no memory protection, you can crash your machine easily
 if the pointer points to a wrong/orphaned place.
 
2.8 Constants

 Constants and literals exist only for primitive types. Depending on the type,
 they are written in different ways.
 If the type is ambiguous, e.g. Word, Long or Float, the type will be
 determined by choosing the best fitting type within the expression. If the
 type cannot be intuitively casted, the compiler will throw a type-missmatch
 error.
 
2.8.1 Boolean Literals

 Symbol             | Description
 -------------------+----------------------------------------------------------
 True               | logical true
 False              | logical false
 On                 | same like True
 Off                | same like False
 -1 or 0            | the above values written as numbers

 Note: AmiBlitz³ does not really know booleans, a boolean is an integer
       value of either -1 (true, all bits set) or 0 (false, all bits cleared).
 
2.8.2 Integer Literals (Byte, Word, Long)

 Symbol             | Description
 -------------------+----------------------------------------------------------
 65                 | decimal for "65"
 $41                | hexadecimal for "65"
 %10001             | binary for "65"
 @"A"               | ASCII for "65", newsyntax mode required
 
2.8.3 Float Literals (Quick, Float or Double Float)
 
 Float constants can be written as integers and will be casted.
 If the fractional part is needed, they are written as decimal numbers with a
 "." (full stop) to seperate the integer from fractional part.
 
 Symbol             | Description
 -------------------+----------------------------------------------------------
 65.0               | fractal number
 0.1                | fractal number with leading 0
 .1                 | fractal number without leading 0

2.8.4 String Literals

 Strings are written in double quotes. They use 8bit for each character.
 
 Symbol             | Description
 -------------------+----------------------------------------------------------
 "A"                | string of length 1
 "Hello World!"     | string of length 12

2.8.5 Pre-defined Constants

 Symbol             | Description
 -------------------+----------------------------------------------------------
 True               | logic true,  equals to -1
 False              | logic false, equals to  0
 On                 | logic true,  equals to -1
 Off                | logic false, equals to  0
 Pi                 | 3.1415926535
                    | require optimize 4:
 #__include         | 0 if main source, -1 if included
 #__autoconstantnum | value of the next auto-increment constant (read/write)
 #__debug           | -1 if debugger is on, 0 if debugger is off
 @#constant         | -1 if the user constant "constant" was defined earlier,
                    | 0 if undefined

2.8.6 User Defined Constants

 The user can define own constants. They are always of type long and must have
 a leading "#" (hash).

 Example:
 +-----------------------------------------------------------------------------
 |
 | #myConstant = 1234     ; define a user constant
 |
 | NPrint #myConstant + 1 ; this outputs 1235
 |
 +-----------------------------------------------------------------------------

2.8.7 Escape Sequences
 
 For use within string literals, the following escape sequences are defined:

 Symbol              | Description    
 --------------------+---------------------------------------------------------
 \\n                 | new line (ASCII #10)
 \\<hex>             | any character given by 2 digit hex value,
                     | e.g. \\40 for "@"
 \\r<nn><b>          | repeat the byte b for n times, while n is a two digit decimal number
                     |
 \\__CODELINE        | number of the current code line in sourc code
 \\__DATE__          | compile date in US format (mm/dd/yyyy)
 \\__DATE_GER__      | compile date in German format (dd.mm.yyy)
 \\__VER_MAJOR       | major verion number (from project settings)
 \\__VER_MINOR       | minor verion number (from project settings)
 \\__VER_PATCH       | patch number (from project settings)
 \\__VER_BUILD       | build number (auto-incremental)
 \\__THIS_FUNCTION   | name of the current function or "GLOBAL"
 \\__THIS_INCLUDE    | name of the current include file
 \\__THIS_POINTER    | hex pointer of the current function

2.8.8 Examples
 
 +-----------------------------------------------------------------------------
 |
 | #myConst    = 12345   
 |
 | myBool.b    = True
 | myFloat.f   = 2*Pi
 | myString.s  = "Hello World!"
 | myInt1.l    = 12345
 | myInt2.l    = $BEEF
 | myInt3.l    = %101110101011
 | myInt4.l    = @"ILBM"
 | myInt5.l    = #myConst
 |
 | version.s   = "$VER: MyProggy V\\__VER_MAJOR.\\__VER_MINOR (\\__DATE__)\\n"
 |
 +-----------------------------------------------------------------------------

2.9 Functions

 A function is defined as follows:
 +-----------------------------------------------------------------------------
 |
 | Function.t [FAST] name {param.t, ...}
 |   Function Return value
 | End Function
 |
 | Statement [FAST] name {param.t, ...}
 | End Statement
 |
 +-----------------------------------------------------------------------------
 
 Function/Statement: keyword to indicate we are defining a function
 FAST          : optional modifier
 name          : function's name
 .t                     : type extension
 value         : expression we want to return
 param.t, ...  : list of parameters, can be none up to 10

 Example:
 +-----------------------------------------------------------------------------
 |
 | Function.f AddTwoFloats{a.f, b.f}
 |   result.f = a + b
 |   Function Return result
 | End Function
 |
 | Statement PrintLine{text.s}
 |   Print text.s,"\\n"
 | End Statement
 |
 +-----------------------------------------------------------------------------

2.9.1 Statements

 If the function has no return value, the keyword "Statement" is used instead
 of "Function". There is no need for a "Statement Return", unless the function
 should be exited earlier than the "End Statement".

2.9.2 Optional Parameters

 A function can have optional parameters. The optional parameters
 are declared by using the "@" (at sign). Once a parameter is optional,
 all following parameters must be optional too.
 Optional parameters that are omitted will be filled with the default value -1
 if they are numeric (integers and floats), and the empty string if they are
 strings.

 Example:
 +-----------------------------------------------------------------------------
 |
 | Function.l AddLongs{a.l, @b.l, @c.l}
 |   Function Return a+b+c
 | End Function
 |
 | Function.l ConcatStrings{a.s, @b.s, @c.s}
 |   Function Return a+b+c
 | End Function
 |
 | Print AddLongs{3,2}                  ; this would output "4" (yes, "4")
 | Print ConcatStrings{"Hello","World"} ; this would output "HelloWorld"  
 |  
 +-----------------------------------------------------------------------------
 
 There is no possibility to overload a function.
 
2.9.3 FAST Modifier

 The FAST modifier directive removes the init code of variables from the
 function.
 The following restrictions apply:
 - All local variables must be initialized manually.
 - Strings and newtypes are not allowed anymore.
 Therefore, the calling overhead of the function is reduced to a minimum.
 This makes sense for short and high frequently called functions.

2.10 Macros

 A macro is a definition of text that is inserted during compilation time
 whenever the name of the macro is stated. In AmiBlitz³, they are defined
 by the "MACRO" Compiler directive and and referred by using a
 leading "!" (exclamation mark).
 A macro can have parameters, they are reference by `n (Back Quote + param#)
 within the macro.
 +-----------------------------------------------------------------------------
 |
 | MACRO myIntConst    :             5 : End MACRO
 | MACRO myFloatConst  :           5.4 : End MACRO
 | MACRO myStringConst :        "Test" : End MACRO
 | MACRO myFuncMacro   : ((`1) * (`2)) : End MACRO
 |
 | Print !myStringConst,!myFuncMacro{2,3}
 |  
 | ; The compiler would see: Print "Test",((2) * (3))
 |
 +-----------------------------------------------------------------------------
 Note: The Print would output "Test6".

 A disadvantage of Macros is, that they are typeless.
 Mismatching types are determined AFTER the macro is applied, which makes
 debugging harder.

 Useful macros found in all.res:
 
 Symbol         | Description
 ---------------+--------------------------------------------------------------
 !version       | version string

 Useful macros found in "useful.include.bb2"

 Symbol         | Description
 ---------------+--------------------------------------------------------------
 !_NULL         | 0, Null pointer to make source more readable  
 !_ASSERT{x}    | terminates the program with an error message if x is false/0
 
2.11 Compiler Directives

 A compiler directive is a keyword in the source code that influences the
 compiling process, rather than an expression that generates executable code.
 Compiler directives are all uppercased to identify them easily.

 Keyword          | Description
 -----------------+------------------------------------------------------------
 optimize n       | control the compiler optimizeation/syntaxmode
                  | "or" the follwing numbers:
                  | 1 : 68020 optimizer
                  | 2 : use FPU
                  | 4 : new syntax mode enabled
                  |
 Syntax n         | set the strictness:
                  | 0 : variables do not have to be declared (like BlitzBasic2)
                  | 1 : variables need to be defined via DEFTYPE
                  | 2 : vatiables need to be defined via DEFTYPE or first usage
                  |
 CNIF condition   | compile if condition evaluates to True
 CELSE            | alternative block to CNIF
 CEND             | end the conditional block
                  |
 RunErrsOff       | switch runtime debugger off
 RunErrsOn        | switch runtime debugger on
 LastRunErrsMode  | switch runtime debugger to last state
                  |
 INCLUDE          | include a source code file
 XINCLUDE         | include a source code file (only once!)
 IncBin           | include a binary file
 
 The search order (if not an absolute path in "file") is:
 1. the path set in IDE to the includes directory
 2. the path of the current source code file
 3. the path to the executable to create

3.1 Build-In Functions

3.1.1 Assign Operators

 Symbol         | Description
 ---------------+--------------------------------------------------------------
 x = y          | assign y to x (primitive types/pointers only)

3.1.2 Comparators

 Symbol         | Description
 ---------------+--------------------------------------------------------------
 x = y          | True if x is equal to y, False otherwise
 x >  y         | True if x is greater than y, False otherwise
 x >= y         | True if x is greater than or equal y, False otherwise
 x => y         | True if x is greater than or equal y, False otherwise
 x <  y         | True if x is smaller than y, False otherwise
 x <= y         | True if x is smaller than or equal y, False otherwise
 x =< y         | True if x is smaller than or equal y, False otherwise
 x >< y         | True if x is not equal to y, False otherwise
 x <> y         | True if x is not equal to y, False otherwise

3.1.3 Logic Operators

 Symbol         | Description
 ---------------+--------------------------------------------------------------
 NOT(x)         | logic NOT
 x AND y        | logic AND
 x OR y         | logic OR
 Xor(x,y)       | logic XOR, equals to (x AND NOT(y)) OR (NOT(x) AND y)

3.1.4 Bit Manipulating Operators

 Symbol         | Description
 ---------------+--------------------------------------------------------------
 NEG(x)         | bitwise negation of x (= XOR with all bits set)
 x & y          | bitwise AND (integer only)
 x | y          | bitwise OR  (integer only)
 Xor(x,y)       | bitwise XOR (integer only)
 x LSR y        | shift down x about y bits (unsigned)
 x ASR y        | shift down x about y bits (signed)
 x LSL y        | shift up x about y bits
 x ASL y        | shift up x about y bits

3.1.5 Math Operators

 Symbol         | Description
 ---------------+--------------------------------------------------------------
 -x             | negation of x
 x + y          | add x and y
 x - y          | subtract y from x
 x * y          | multiply x by y
 x / y          | divide x through y
 x MOD y        | x modulo y
 x ^ y          | x power y
 Log(x.f,y.f)   | logarithm of x to base y

3.1.6 Trigonometric Functions

 Symbol         | Description
 ---------------+--------------------------------------------------------------
 Sin(x.f)       | Sinus of x
 Cos(x.f)       | Cosinus of x
 Tan(x.f)       | Tangents of x
 ASin(x.f)      | inverse Sinus of x
 ACos(x.f)      | inverse Cosinus of x
 ATan(x.f)      | inverse Tangents of x

3.1.7 String Functions

 Symbol                    | Description
 --------------------------+---------------------------------------------------
 Mid$(str.s,pos.p,n.p)     | crop n characters starting from pos of str
 Len(str.s)                | string length of str

3.1.8 Program Flow Functions

 Symbol                    | Description
 --------------------------+---------------------------------------------------
 DEFTYPE.t a               | declare and initialized variable a of type t
 Dim [KEEP] a.t(n)         | dimension an array of type t with n indices
 Dim List a.t(n)           | create a linked list of name a of type t
 NEWTPYE name              | declare a data structure
 Function name {...}       | declare a function
 Goto label                | unconditional branch
 Function Return (r)       | return from a function with return value r
 For i=a to b Step c       | "For" loop
 While c : ... : Wend      | "While" loop
 Repeat : ... : Until c    | "Repeat" loop
 If c Then ...             | "If" block
 Else ...                  | "Else" block
 Select x                  | "Select" switch
 Case y                    | "Case" block
 End                       | end program
 initbasic                 | init the Basic context

3.1.9 Memory Functions

 Symbol               | Description
 ---------------------+--------------------------------------------------------
 Dc.t value           | declare a value directly in binary code
 SizeOf.t             | memory size of type t
 Peek.t(mem)          | (flat) copy the data from mem to the structure
 Poke.t(mem)          | (flat) copy the data from the structure to mem

3.1.10 Casting Function

 Symbol        | Description
 --------------+---------------------------------------------------------------
 Val(x)        | convert string to float
 Vallong(x)    | convert string to integer
 Str(x)        | convert integer/float to string
 Int(x)        | convert float to integer

4 68K Assembler Reference
 Amiblitz3 contains the full 68K instruction set (also 68020 and FPU) as inline assembler.
 You can simply write any time in your source code some lines of assembler
 and continue with Basic functions.
 
 The following registers are used across basic functions and must not be trashed:
 
 A4 is reserved for the local variable base within functions
 A5 is reserved for the global variable base
 A6 is reserved for library access
 D7 is reserved for intermediate results between Basic code

 ...and of course the Stack should not be trashed.
 
 A full reference of 68K Instuctions will not be described in this document.
 Check the Internet.

B Glossary

Variable      : A memory cell that can store value of the type the variable has.

Constant      : A value of a certain type that does not change over compile
               time. This is usually set by the compiler.

Type          : The kind of data that is in a memory cell, this can be an
               integer, float or string, or user defined "complex type".

Primitive Type: A primitive type is one of the types AmiBlitz³ knows build-in.

Complex Type  : A complex type is a composition of primitive types. They are
               defined by the user.
               
Function      : A block of expressions that has some input parameters and one
               output result.
               AmiBlitz³ has some build in functions, and the user can define own
               functions.

Macro         : Instruction how to replace the macro name in source code with
               its body.
               Note: AmiBlitz³ uses macros in form of constants defined by
               preceding # and "Macro"s, while C uses #define for both.
               AmiBlitz³ uses only the preceding #.

Bool(ean)     : a type that can hold only two values: true and false
               This is usually the result type of comparators.

Long/Word/Byte: Those are Integer values, which can contain only numbers
               without fractional part.
               Results are rounded downwards, e.g. 5/2 = 2 in integer space

Float/Double  : Float is a numeric value with fractional part, Double is the
               same with higher precision

String        : A string in AmiBlitz³ is a sequence of characters terminated
               by 0.

Array         : An Array is a sequence of variables of a certain type.
               The variables are accessed by their index.
               
List          : A List is a sequence of variables of a certain type.
               The variables are accessed by stepping forward and backwards in
               the list.

AmiBlitz³     : programming language, see http://AmiBlitz³.amiforce.de               

C             : programming language

Expression    : anything that can be evaluated. An expression is composed out
               of terminals and non-terminals.


D License/Disclaimer

License:

 AmiBlitz³ programming language obeys to the license defined at source forge
 (http://sourceforge.net/projects/amiblitz3/), where it is hosted for
 development.

DISCLAIMER:

 THE SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" WITHOUT WARRANTY
 OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED
 TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 PARTICULAR PURPOSE. YOU ARE ADVISED TO TEST THE SOFTWARE THOROUGHLY BEFORE
 RELYING ON IT. YOU AGREE TO ACCEPT THE ENTIRE RISK AS TO THE QUALITY AND
 PERFORMANCE OF THE SOFTWARE AND DOCUMENTATION.
 IN NO EVENT WILL THILO KOEHLER BE LIABLE FOR DIRECT, INDIRECT, INCIDENTAL,
 OR CONSEQUENTIAL DAMAGES RESULTING FROM ANY DEFECT IN THE PROGRAM OR
 DOCUMENTATION.

C Author

 Author if this documentation:
 
 Name:  Thilo Koehler
 Nick:  Der Wanderer
 Mail:  thilokoehler hd-rec de
 Web:   http://www.hd-rec.de
Zurück zum Seiteninhalt