asa 1.0.0

Advanced Subleq Assembler. Assembles 'sublang' to subleq
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
# Introduction to Sublang
Sublang is a bare bones assembly-like language consisting of four main elements:
* The **SUBLEQ** instruction
* **Labels** to refer to areas of memory easily
* **Macros** for code reuse
* **Syntax sugar** for common constructs


## Subleq
<!-- Clojure highlighting is used as an approximation for Sublang -->
```clojure
1 2 3 ; This is interpreted as standard subleq: mem[2] -= mem[1] jump to 3 if LEQ otherwise it goes to the next instruction. 
; This syntax is valid, but pointless.

; memory addresses and instructions may be labeled
a -> 1
b -> 2

c ->
    a -= b ; This syntax is used for the SUBLEQ instruction: Subtract b from a
    a -= b c ; Subtract b from a and jump to c if the result is less than or equal to zero

; If no `c` argument is given, the next instruction will always be executed, even if the result is LEQ to zero
; So these two are equivalent
a -= b
a -= b $1 ; `$1` gives a relative address with offset one

a -= b ; is equivalent to
b a $1 ; This syntax works but is not recommended, since it makes it harder for the assembler to give hints

; Other examples, literals and labels may freely be combined
a -= b 0x0000
'\0' -= 0 c

**
    Block comment.
    Important NOTE: Labeled values take up space in memory and will be
    executed if passed
**
a -> 2
4 10 5 ; will be executed as 2 4 10, NOT 4 10 5. To prevent this, jump over any
       ; label definitions, or use the assignment syntax
```

## Labels and Literals
```clojure
a -> 123 ; Decimal
b -> 0x4C6 ; Hex
c -> "Hello, World!" ; Strings are null-terminated by the assembler
d -> 'P' ; Character literals

.label ->
    a -= b .label   ; Repeats as long as (a -= b) <= 0
```


## IO
```clojure

char -> 'a'
input -> 0
W -> 0

-1 -= char ; Prints 'a' to the screen

input -= -1
-1 -= input ; Echoes back users input

W -= W -1 ; Halts execution

```

## Scopes
Scoping works like in most other languages. Note: Only labels are affected by scopes, macro definitions in scopes will still be globally accessible
```clojure
Z -> 123
X -> 456
Y -> 0
{
    Z -> -789
    {
        X -= Z  ; 456 - -789
    }
}
Y -= Z ; 0 - 123
```






## Macros
### Definition
```clojure
@Name {
    ...
}
@Name   ; This is allowed as well, but discouraged
{
    ...
}

; with parameters
@Name a? b? c? {
    ...
}

; It is also possible to define a macro that isn't scoped:
@Name a? [
    ...
]
; This, however, is dangerous when label definitions take place in the macro, so it is generally discouraged.

; Linebreaks are allowed between parameters

@Name a?
      b?
      c?
      d?
      e? {
    ...

}

```
### Expanding
```clojure
!Name
; With arguments
!Name2 a b c
; Linebreaks are NOT allowed between arguments
```

### Hygiene
Macros are hygienic. Variables won't be shadowed.
```clojure
; Macros
@MyMacro b {
    a -= b
    a -> 123
}

a -> 0
!MyMacro a
; Is completely fine, and will become the following:
{
    ?MyMacro?a -= a
    ?MyMacro?a -> 123
}
```

### Compound macro arguments
You may pass scopes as macro arguments

```clojure
@Mac s_my_scope? {
    s_my_scope?
}


!Mac { a -= b } 
; =>
{
    { a -= b }
}

; If a macro takes multiple scopes, they can be chained as follows:
!Mac {
    ...
} {
    ...
} {
    ...
}
```
If you don't want the argument to be surrounded by scopes, you can use braces

```clojure
@Mac b_my_braced? {
    b_my_braced?
}

!Mac ( a -= b )
; =>
{
    a -= b
}
```
This means that you can 'curry' macros (using that term loosely)
```clojure
@Mac b_some_macro? {
    b_some_macro? 10
    b_some_macro? 3
}

@CurriedMacro l_a? l_b? {
    l_a? -= l_b?
}
!Mac ( !CurriedMacro 5 ) 
; =>
{
    {
        5 -= 10
        5 -= 3
    }
}

```


### Types
The assembler has a simple type-checker for macro arguments, which can be disabled.

* `value` normal label
* `l_value` literal value
* `s_value` scoped value
* `b_value` a braced value
* `m_value` a macro call passed as argument, must be braced. In practice it's the same as `b_value`
* `a_value` anything, no type checking

## Pointers
### Referencing
To create a pointer to a value, the relative address syntax `$1` must be used to get the address of the next token
```clojure
ptr -> $1 0x1234 ; This takes up two words of memory, one for the pointer and one for the value

ptr -> $1 "String"
; or
ptr -> &'A'
ptr -> &"String"
ptr -> &123
; & is equivalent to $1
```

### Dereferencing
```clojure
; Generic sequence for dereferencing. The value that 'ptr' points to will be subtracted from 'a'
!Copy ptr b
a -= (b -> 0)
; If 'ptr' is constant the following is also legal. Note: ptr doesn't have to be constant but this syntax will give unexpected results if it isn't
a -= (b -> PTR)

; The '*' operator may also be used:
a -= *ptr
; This is effectively syntax sugar for
!Copy ptr b
a -= (b -> 0)


; (But in reality it is exactly equivalent to)
_ASM    _ASM    &1
*ID*ptr *ID*ptr &1
ptr     _ASM    &1
_ASM    *ID*ptr &1
a -= (*ID*ptr -> 0)
; *ID*ptr is a safe and automatically generated name

```
Remember that because of how Subleq works, what are called 'Labels' here, are also just pointers! But since Subleq dereferences them, we can think of them as values. But keep in mind that literals require indirection `a -= 10` doesn't subtract 10 from a


## Inclusions
The `#` symbol may be used to include another .sbl file anywhere
```Clojure
#MySblFile.sbl
; You may leave out the .sbl extension:
#MySblFile

; You can also do this:
...
Z -= Z
P -= Z
#IncludeMe
!Macro P
...
; But of course beware of the contents of the included file
```
If you want to create a module (a set of .sbl files in a folder) you must create a folder with the name of the module (for example 'sublib') and in that folder create a Lib.sbl file. Whenever the 'sublib' folder is imported, this is automatically resolved to 'sublib/Lib.sbl'. In this .sbl file you may include any other files you might need. Includes are initially resolved relative to the file being assembled, and otherwise they are searched for in the *LIBS* folder, defined using the `-l` command line argument.


```clojure
; ./subleq/MyFile.sbl
#math/FastSqrt
```
The order in which files are checked is as follows. The first one that exists will be included.
* `./subleq/math/FastSqrt/Lib.sbl`
* `./subleq/math/FastSqrt.sbl`
* `LIBS/math/FastSqrt/Lib.sbl`
* `LIBS/math/FastSqrt.sbl`


See subleq/libs/sublib for an example.

## Miscellaneous Syntax sugar
### Mult operator
When the '*' is placed before a literal `n`, the previous token is repeated `n` times.
```clojure
label * 3 ; =>
label label label

0x123 * 0x4 ; =>
0x123 0x123 0x123 0x123

; mind that 3 * label will dereference `label`!
```

### Assignments
The `=` operator can be used to both declare a label and assign it a value every time execution passes it. You can assign a label to another label or a literal.
```clojure

.loop ->
    a = 2 ; a will be set to 2 every iteration of the loop
    a -= a .loop

; Label to literal
a = 2 
; is equivalent to
_ASM -= _ASM
a -= a .assign
a -> 0 ; declaration
.assign -> {
    lit -> 2
    _ASM -= lit
    name? -= _ASM
}

; Label to zero (special optimised case)
b = 0
; is equivalent to
b -= b .fin
b -> 0 ; declaration
.fin ->

; Label to Label
b = a
_ASM -= _ASM .assign
b -> 0 ; declaration
.assign ->
b -= b
_ASM -= a
b -= _ASM

; Note that there is a small memory and performance cost to assignments
```




## Namespacing
The format `Namespace::Macro` or `Namespace::label` should be used. This is solely a naming convention and not enforced in any way. This means that module authors must decide what namespace their macros or labels should have. This is obviously bad design, but it is simple.

## Sublib
Sublib is the standard library. It has a range of very basic features (Prelude.sbl, IO.sbl and Symbols.sbl) to quite advanced ones like functions and control flow.

## Style guide
Adhere to the naming conventions and type system and make sure it looks good :), ideally you should follow the style of the Sublib

### Naming conventions
* `@MyMacro` macros in PascalCase
* `my_label` labels in snake_case, with the exception of single character 'registers', like `Z` or `W`
* `p_value` pointer (not type-checked)
* `p_p_value` pointer to pointer (not type-checked)
* `n_value` negated value (not type-checked)
* `value?` macro parameters
* `.value` a label to jump to
* `CONST_VALUE` constant, can be applied to all of the above and should be applied to macro arguments, but NOT to literals (l_name), since they are always constant by definition
* `Namespace::label` or `Namespace::Macro` for namespacing
* `Namespace::SubNamespace::label`
* `MyFile.sbl` files in PascalCase
* `module` modules (folders) in snake_case


## Assembler specific additions to Subleq
The assembler's runtimes will treat a jump to `-2` as a breakpoint and `-2 -= a` as printing `a` as a signed integer. Note that these features are non-canonical. They should be accessed using `ASM::Breakpoint` and `ASM::Debug` from the `ASM` library. When pedantic mode is turned on, the assembler will notify that these features wont work for other subleq interpreters.

## Runtimes
### Interpreter
The interpreter is the default runtime for subleq. When an error is encountered it exits and prints a trace. To halt the program when it running press CTRL-C but when it is prompting for input, press DELETE.
### Debugger
To run a program with the debugger, add the `-d` command line flag. Interactive debugging will only start when an error or breakpoint is encountered.

## Examples
### Basic
```clojure
; Very basic Sublang, without using the standard library Sublib
; Output: Hello, World!

!Print p_string ; Call the macro Print


Z -= Z -1 ; Jumping to -1 halts, equivalent to !Halt



p_string -> &"Hello, World!\n"
Z -> 0 ; Temp register
N_ONE -> -1 ; Store the literal negative one

**
    Pure no dependency implementation of print
**
@Print P_STRING? {


    ; Copy the pointer into the local variable ptr, because we don't want to
    ; modify the original pointer
    Z   -= Z ; clear Z
    Z   -= P_STRING? ; Z = -P_STRING?
    ptr -= Z ; ptr = -Z = --P_STRING? = P_STRING?

    Z -= Z
    .loop ->
        char -= char ; Clear char
        Z -= (ptr -> 0) ; Z -= *ptr, dereferences ptr to get the actual character

        char -= Z .fin ; Flip the character, since it is negative, and jump if
                       ; result is LEQ zero (i.e. finish if it is a ZERO/NULL)
        -1 -= char ; Writes the character to the screen. -1 is a special register used
                   ; for IO operations

        ptr -= N_ONE ; Increment the pointer to go to the next character
        Z -= Z .loop ; Infinite loop

    char -> 0 ; This point is never reached, so it is safe to define the
              ; label 'char' here. It is very important to keep in mind
              ; that, in this case the zero, will be put in memory in
              ; this exact place and, if execution crosses it, it will
              ; be interpreted as an instruction. To define values in between
              ; instructions, use the '=' operator

    .fin ->
}
```

### Sublib

```clojure
; This is how Sublang could should be written, making extensive use of macros
; Output: Hello, Sublang!

#sublib
#sublib/Control

p_string -> &"Hello, Sublang!\n"

**
   Print a string using macros from standard lib
**
@PrintStdLib P_STRING? {
    p_local = P_STRING?
    char = 0

    !Loop {
        !DerefAndCopy p_local char ; char = *p_local
        !IfFalse char {
            !Break
        }
        !IO -= char
        !Inc p_local
    }
}

; Executing starts here
.main -> {
    !PrintStdLib p_string
    !Halt
}
```
```clojure
; Or you can just use one of the Print macros from sublib/IO
#sublib

.main -> {
    IO::PrintLnLit "Hello, Sublib!"
    !Halt
}
```

### Conway's Game of Life
[./subleq/examples/GameOfLife.sbl](github.com/Kat9-123/asa/tree/master/subleq/examples/GameOfLife.sbl)




## Conclusion
For many more examples see Sublib or the end-to-end tests, though they are messy and not idiomatic