Some checks failed
akbasic CI Build / coverage (push) Failing after 27s
akbasic CI Build / cmake_build (push) Failing after 33s
akbasic CI Build / akgl_build (push) Failing after 18s
akbasic CI Build / sanitizers (push) Failing after 1m7s
akbasic CI Build / mutation_test (push) Failing after 39s
372 lines
9.7 KiB
Markdown
372 lines
9.7 KiB
Markdown
# 16. Structures
|
|
|
|
A structure groups values that belong together. Commodore BASIC 7.0 has nothing like
|
|
it — this is entirely an addition, and Chapter 13 lists it with the other differences.
|
|
|
|
A structure variable's name ends in **`@`**, the fourth type suffix:
|
|
|
|
| Suffix | Type |
|
|
|---|---|
|
|
| `#` | integer |
|
|
| `%` | floating point |
|
|
| `$` | string |
|
|
| `@` | structure |
|
|
|
|
## Declaring a type
|
|
|
|
`TYPE` … `END TYPE` names a record and lists its fields, one per line. **Each field takes
|
|
its type from its own suffix**, the same rule every other name in this language follows,
|
|
so a field list needs no type column:
|
|
|
|
```basic
|
|
10 TYPE RECT
|
|
20 W#
|
|
30 H#
|
|
40 END TYPE
|
|
50 DIM R@ AS RECT
|
|
60 R@.W# = 3
|
|
70 R@.H# = 4
|
|
80 PRINT R@.W# * R@.H#
|
|
90 PRINT R@
|
|
```
|
|
|
|
```output
|
|
12
|
|
RECT(W#=3, H#=4)
|
|
```
|
|
|
|
`DIM name@ AS TYPE` is how a variable gets storage, and it is required — unlike an
|
|
ordinary variable, a structure cannot spring into existence on first use, because
|
|
nothing would say which type it is.
|
|
|
|
**A type name is a bare word, and so is every verb**, so the two share a namespace.
|
|
`TYPE POINT` is refused, because `POINT` is a verb:
|
|
|
|
```basic
|
|
10 TYPE POINT
|
|
20 X#
|
|
30 END TYPE
|
|
40 PRINT 1
|
|
```
|
|
|
|
```output
|
|
? 10 : PARSE ERROR TYPE POINT: POINT is a reserved word and cannot name a type
|
|
|
|
```
|
|
|
|
The same applies to field names, for the same reason a variable cannot be called `TO#`.
|
|
|
|
## Nesting
|
|
|
|
A field may be another structure, named with `AS`:
|
|
|
|
```basic
|
|
10 TYPE COORD
|
|
20 X#
|
|
30 Y#
|
|
40 END TYPE
|
|
50 TYPE SHAPE
|
|
60 NAME$
|
|
70 ORIGIN@ AS COORD
|
|
80 END TYPE
|
|
90 DIM S@ AS SHAPE
|
|
100 S@.NAME$ = "BOX"
|
|
110 S@.ORIGIN@.X# = 10
|
|
120 PRINT S@
|
|
```
|
|
|
|
```output
|
|
SHAPE(NAME$=BOX, ORIGIN@=COORD(X#=10, Y#=0))
|
|
```
|
|
|
|
`@` on its own says "a structure" but not *which*, which is why a structure field has to
|
|
name its type where `W#` does not. Three primitive types fit in three suffix characters;
|
|
ten declared types do not fit in one.
|
|
|
|
## Assignment copies
|
|
|
|
**This is the rule to remember.** A structure behaves like every other value here:
|
|
|
|
```basic
|
|
10 TYPE RECT
|
|
20 W#
|
|
30 END TYPE
|
|
40 DIM A@ AS RECT
|
|
50 DIM B@ AS RECT
|
|
60 A@.W# = 1
|
|
70 B@ = A@
|
|
80 A@.W# = 99
|
|
90 PRINT B@.W#
|
|
```
|
|
|
|
```output
|
|
1
|
|
```
|
|
|
|
`B@` is its own record from line 70 onward. Nesting copies too — a whole record, however
|
|
deep, moves as a unit.
|
|
|
|
## Pointers
|
|
|
|
When you want two names for *one* record, say so. A pointer is a distinct declared kind:
|
|
|
|
```basic
|
|
10 TYPE RECT
|
|
20 W#
|
|
30 END TYPE
|
|
40 DIM A@ AS RECT
|
|
50 DIM P@ AS PTR TO RECT
|
|
60 A@.W# = 1
|
|
70 POINT |