mirror of
https://github.com/badvision/lawless-legends.git
synced 2024-12-26 19:29:27 +00:00
Update comment and multiple statements
New comment seperator and allow multiple statements per line
This commit is contained in:
parent
fb3f6722cf
commit
1740e93d11
@ -49,10 +49,10 @@ for the **make** program to build all the dependencies and run the module.
|
|||||||
All identifiers and reserved words are case insensitive. Case is only significant inside character constants and strings. Imported and exported symbols are always promoted to upper case when resolved. Because some Apple IIs only work easily with uppercase, the eases the chance of mismatched symbol names.
|
All identifiers and reserved words are case insensitive. Case is only significant inside character constants and strings. Imported and exported symbols are always promoted to upper case when resolved. Because some Apple IIs only work easily with uppercase, the eases the chance of mismatched symbol names.
|
||||||
|
|
||||||
### Comments
|
### Comments
|
||||||
Comments are allowed throughout a PLASMA source file. The format follows that of an assembler: they begin with a `;` and comment out the rest of the line:
|
Comments are allowed throughout a PLASMA source file. The format follows that of C like languages: they begin with a `//` and comment out the rest of the line:
|
||||||
|
|
||||||
```
|
```
|
||||||
; This is a comment, the rest of this line is ignored
|
// This is a comment, the rest of this line is ignored
|
||||||
```
|
```
|
||||||
|
|
||||||
### Declarations
|
### Declarations
|
||||||
@ -188,7 +188,7 @@ byte smallarray[4]
|
|||||||
byte initbarray[] = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
|
byte initbarray[] = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
|
||||||
byte string[64] = "Initialized string"
|
byte string[64] = "Initialized string"
|
||||||
word wlabel[]
|
word wlabel[]
|
||||||
word = 1000, 2000, 3000, 4000 ; Anonymous array
|
word = 1000, 2000, 3000, 4000 // Anonymous array
|
||||||
word funclist = @myfunc, $0000
|
word funclist = @myfunc, $0000
|
||||||
```
|
```
|
||||||
Arrays can be uninitialized and reserve a size, as in `smallarray` above. Initilized arrays without a size specifier in the definition will take up as much data as is present, as in `initbarray` above. Strings are special arrays that include a hidden length byte in the beginning (Pascal strings). When specified with a size, a minimum size is reserved for the string value. Labels can be defined as arrays without size or initializers; this can be useful when overlapping labels with other arrays or defining the actual array data as anonymous arrays in following lines as in `wlabel` and following lines. Addresses of other data (must be defined previously) or function definitions (pre-defined with predef), including imported references, can be initializers.
|
Arrays can be uninitialized and reserve a size, as in `smallarray` above. Initilized arrays without a size specifier in the definition will take up as much data as is present, as in `initbarray` above. Strings are special arrays that include a hidden length byte in the beginning (Pascal strings). When specified with a size, a minimum size is reserved for the string value. Labels can be defined as arrays without size or initializers; this can be useful when overlapping labels with other arrays or defining the actual array data as anonymous arrays in following lines as in `wlabel` and following lines. Addresses of other data (must be defined previously) or function definitions (pre-defined with predef), including imported references, can be initializers.
|
||||||
@ -210,9 +210,9 @@ The override operator becomes more useful when multi-dimenstional arrays are use
|
|||||||
##### Multi-Dimensional Arrays
|
##### Multi-Dimensional Arrays
|
||||||
Multi-dimensional arrays are implemented as arrays of arrays, not as a single block of memory. This allows constructs such as:
|
Multi-dimensional arrays are implemented as arrays of arrays, not as a single block of memory. This allows constructs such as:
|
||||||
```
|
```
|
||||||
;
|
//
|
||||||
; Hi-Res scanline addresses
|
// Hi-Res scanline addresses
|
||||||
;
|
//
|
||||||
word hgrscan[] = $2000,$2400,$2800,$2C00,$3000,$3400,$3800,$3C00
|
word hgrscan[] = $2000,$2400,$2800,$2C00,$3000,$3400,$3800,$3C00
|
||||||
word = $2080,$2480,$2880,$2C80,$3080,$3480,$3880,$3C80
|
word = $2080,$2480,$2880,$2C80,$3080,$3480,$3880,$3C80
|
||||||
```
|
```
|
||||||
@ -245,13 +245,13 @@ Notice how xscan goes to 39 instead of 19 in the byte accessed version.
|
|||||||
#### Offsets (Structure Elements)
|
#### Offsets (Structure Elements)
|
||||||
Structures are another fundamental construct when accessing in-common data. Using fixed element offsets from a given address means you only have to pass one address around to access the entire record. Offsets are specified with a constant expression following the type override specifier.
|
Structures are another fundamental construct when accessing in-common data. Using fixed element offsets from a given address means you only have to pass one address around to access the entire record. Offsets are specified with a constant expression following the type override specifier.
|
||||||
```
|
```
|
||||||
predef puti ; print an integer
|
predef puti // print an integer
|
||||||
byte myrec[]
|
byte myrec[]
|
||||||
word = 2
|
word = 2
|
||||||
byte = "PLASMA"
|
byte = "PLASMA"
|
||||||
|
|
||||||
puti(myrec:0) ; ID = 2
|
puti(myrec:0) // ID = 2
|
||||||
puti(myrec.2) ; Name length = 6 (Pascal string puts length byte first)
|
puti(myrec.2) // Name length = 6 (Pascal string puts length byte first)
|
||||||
```
|
```
|
||||||
This contrived example shows how one can access offsets from a variable as either `byte`s or `word`s regardless of how they were defined. This operator becomes more powerful when combined with pointers, defined next.
|
This contrived example shows how one can access offsets from a variable as either `byte`s or `word`s regardless of how they were defined. This operator becomes more powerful when combined with pointers, defined next.
|
||||||
|
|
||||||
@ -275,9 +275,9 @@ const elem_id = 0
|
|||||||
const elem_addr = 1
|
const elem_addr = 1
|
||||||
|
|
||||||
def addentry(entry, id, addr)
|
def addentry(entry, id, addr)
|
||||||
entry->elem_id = id ; set ID byte
|
entry->elem_id = id // set ID byte
|
||||||
entry=>elem_addr = addr ; set address
|
entry=>elem_addr = addr // set address
|
||||||
return entry + 3 ; return next enry address
|
return entry + 3 // return next enry address
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
The above is equivalent to:
|
The above is equivalent to:
|
||||||
@ -286,16 +286,16 @@ const elem_id = 0
|
|||||||
const elem_addr = 1
|
const elem_addr = 1
|
||||||
|
|
||||||
def addentry(entry, id, addr)
|
def addentry(entry, id, addr)
|
||||||
(entry).elem_id = id ; set ID byte
|
(entry).elem_id = id // set ID byte
|
||||||
(entry):elem_addr = addr ; set address
|
(entry):elem_addr = addr // set address
|
||||||
return entry + 3 ; return next enry address
|
return entry + 3 // return next enry address
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Addresses of Data/Code
|
##### Addresses of Data/Code
|
||||||
Along with dereferencing a pointer, there is the question of getting the address of a variable. The `@` operator prepended to a variable name or a function definition name, will return the address of the variable/definition. From the previous example, the call to `strlen` would look like:
|
Along with dereferencing a pointer, there is the question of getting the address of a variable. The `@` operator prepended to a variable name or a function definition name, will return the address of the variable/definition. From the previous example, the call to `strlen` would look like:
|
||||||
```
|
```
|
||||||
puti(strlen(@mystring)) ; would print 17 in this example
|
puti(strlen(@mystring)) // would print 17 in this example
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Function Pointers
|
##### Function Pointers
|
||||||
@ -311,16 +311,16 @@ def subvals(a, b)
|
|||||||
end
|
end
|
||||||
|
|
||||||
funcptr = @addvals
|
funcptr = @addvals
|
||||||
puti(funcptr(5, 2)) ; Outputs 7
|
puti(funcptr(5, 2)) // Outputs 7
|
||||||
funcptr = @subvals
|
funcptr = @subvals
|
||||||
puti(funcptr(5, 2)) ; Outputs 3
|
puti(funcptr(5, 2)) // Outputs 3
|
||||||
```
|
```
|
||||||
These concepts can be combined with the structure offsets to create a function table that can be easily changed on the fly. Virtual functions in object oriented languages are implemented this way.
|
These concepts can be combined with the structure offsets to create a function table that can be easily changed on the fly. Virtual functions in object oriented languages are implemented this way.
|
||||||
```
|
```
|
||||||
predef myinit, mynew, mydelete
|
predef myinit, mynew, mydelete
|
||||||
|
|
||||||
export word myobject_class = @myinit, @mynew, @mydelete
|
export word myobject_class = @myinit, @mynew, @mydelete
|
||||||
; Rest of class data/code follows...
|
// Rest of class data/code follows...
|
||||||
```
|
```
|
||||||
And an external module can call into this library (class) like:
|
And an external module can call into this library (class) like:
|
||||||
```
|
```
|
||||||
@ -390,7 +390,7 @@ Address operators can work on any value, i.e. anything can be an address. Parent
|
|||||||
| AND | logical AND
|
| AND | logical AND
|
||||||
|
|
||||||
### Statements
|
### Statements
|
||||||
PLASMA definitions are a list of statements the carry out the algorithm. Statements are generally assignment or control flow in nature.
|
PLASMA definitions are a list of statements the carry out the algorithm. Statements are generally assignment or control flow in nature. Multiple statements one a single line are seperated by a ';'. Note, this use the comment seperator in previous versions of PLASMA. It is generally considered bad form to have more than one statement per line unless they are very short.
|
||||||
|
|
||||||
#### Assignment
|
#### Assignment
|
||||||
Assignments evaluate an expression and save the result into memory. They can be very simple or quite complex. A simple example:
|
Assignments evaluate an expression and save the result into memory. They can be very simple or quite complex. A simple example:
|
||||||
@ -403,8 +403,8 @@ An assignment doesn't even have to save the expression into memory, although the
|
|||||||
```
|
```
|
||||||
byte keypress
|
byte keypress
|
||||||
|
|
||||||
keypress = ^$C000 ; read keyboard
|
keypress = ^$C000 // read keyboard
|
||||||
^$C010 ; read keyboard strobe, throw away value
|
^$C010 // read keyboard strobe, throw away value
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Control Flow
|
#### Control Flow
|
||||||
@ -424,19 +424,19 @@ The complex test case is handled with `when`. Basically a `if`, `elsifF`, `else`
|
|||||||
```
|
```
|
||||||
when key
|
when key
|
||||||
is 'A'
|
is 'A'
|
||||||
; handle A character
|
// handle A character
|
||||||
break
|
break
|
||||||
is 'B'
|
is 'B'
|
||||||
; handle B character
|
// handle B character
|
||||||
break
|
break
|
||||||
```
|
```
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
is 'Z'
|
is 'Z'
|
||||||
; handle Z character
|
// handle Z character
|
||||||
break
|
break
|
||||||
otherwise
|
otherwise
|
||||||
; Not a known key
|
// Not a known key
|
||||||
wend
|
wend
|
||||||
```
|
```
|
||||||
With a little "Yoda-Speak", some fairly complex test can be made:
|
With a little "Yoda-Speak", some fairly complex test can be made:
|
||||||
@ -448,13 +448,13 @@ byte a
|
|||||||
|
|
||||||
when TRUE
|
when TRUE
|
||||||
is (a <= 10)
|
is (a <= 10)
|
||||||
; 10 or less
|
// 10 or less
|
||||||
break
|
break
|
||||||
is (a > 10) AND (a < 20)
|
is (a > 10) AND (a < 20)
|
||||||
; between 10 and 20
|
// between 10 and 20
|
||||||
break
|
break
|
||||||
is (a >= 20)
|
is (a >= 20)
|
||||||
; 20 or greater
|
// 20 or greater
|
||||||
wend
|
wend
|
||||||
```
|
```
|
||||||
A `when` clause can fall-through to the following clause, just like C `switch` statements by leaving out the `break` at the end of a clause.
|
A `when` clause can fall-through to the following clause, just like C `switch` statements by leaving out the `break` at the end of a clause.
|
||||||
@ -463,11 +463,11 @@ A `when` clause can fall-through to the following clause, just like C `switch` s
|
|||||||
Iteration over a range is handled with the `for`/`next` loop. When iterating from a smaller to larger value, the `to` construct is used; when iterating from larger to smaller, the `downto` construct is used.
|
Iteration over a range is handled with the `for`/`next` loop. When iterating from a smaller to larger value, the `to` construct is used; when iterating from larger to smaller, the `downto` construct is used.
|
||||||
```
|
```
|
||||||
for a = 1 to 10
|
for a = 1 to 10
|
||||||
; do something with a
|
// do something with a
|
||||||
next
|
next
|
||||||
|
|
||||||
for a = 10 downto 1
|
for a = 10 downto 1
|
||||||
; do something else with a
|
// do something else with a
|
||||||
next
|
next
|
||||||
```
|
```
|
||||||
An optional stepping value can be used to change the default iteration step from 1 to something else. Always use a positive value; when iterating using `downto`, the step value will be subtracted from the current value.
|
An optional stepping value can be used to change the default iteration step from 1 to something else. Always use a positive value; when iterating using `downto`, the step value will be subtracted from the current value.
|
||||||
@ -475,10 +475,10 @@ An optional stepping value can be used to change the default iteration step from
|
|||||||
##### WHILE/LOOP
|
##### WHILE/LOOP
|
||||||
For loops that test at the top of the loop, use `while`. The loop will run zero or more times.
|
For loops that test at the top of the loop, use `while`. The loop will run zero or more times.
|
||||||
```
|
```
|
||||||
a = c ; Who knows what c could be
|
a = c // Who knows what c could be
|
||||||
while a < 10
|
while a < 10
|
||||||
; do something
|
// do something
|
||||||
a = b * 2 ; b is something special, I'm sure
|
a = b * 2 // b is something special, I'm sure
|
||||||
loop
|
loop
|
||||||
```
|
```
|
||||||
##### REPEAT/UNTIL
|
##### REPEAT/UNTIL
|
||||||
@ -512,14 +512,14 @@ end
|
|||||||
PLASMA always returns a value from a function, even if you don't supply one. Probably the easiest optimization to make in PLASMA is to cascade a return value if you don't care about the value you return. This only works if the last thing you do before returning from your routine is calling another definition. You would go from:
|
PLASMA always returns a value from a function, even if you don't supply one. Probably the easiest optimization to make in PLASMA is to cascade a return value if you don't care about the value you return. This only works if the last thing you do before returning from your routine is calling another definition. You would go from:
|
||||||
```
|
```
|
||||||
def mydef
|
def mydef
|
||||||
; do some stuff
|
// do some stuff
|
||||||
calldef(10) ; call some other def
|
calldef(10) // call some other def
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
PLASMA will effectively add a RETURN 0 to the end of your function, as well as add code to ignore the result of `calldef(10)`. As long as you don't care about the return value from `mydef` or want to use its return as the return value fromyour function (cascade the return), you can save some code bytes with:
|
PLASMA will effectively add a RETURN 0 to the end of your function, as well as add code to ignore the result of `calldef(10)`. As long as you don't care about the return value from `mydef` or want to use its return as the return value fromyour function (cascade the return), you can save some code bytes with:
|
||||||
```
|
```
|
||||||
def mydef
|
def mydef
|
||||||
; do some stuff
|
// do some stuff
|
||||||
return calldef(10) ; call some other def
|
return calldef(10) // call some other def
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
Loading…
Reference in New Issue
Block a user