A compiler for a functional low-level language, targeting tiny computers.
- C 70.5%
- Assembly 18.3%
- GLSL 9.4%
- Shell 1.4%
- Makefile 0.3%
| doc | update docs | |
| examples | ext | |
| include | handle slow servers | |
| tests | obsolete | |
| tools | remove linking tools and use of -l option in checks | |
| 6502.h | drop sign-of and numerical identity | |
| chk | test for grade | |
| cpmchk | remove linking tools and use of -l option in checks | |
| labels.awk | resident r/t option for PDP-1 | |
| macro1.c | initial PDP-1 support | |
| Makefile | version header | |
| pdp1.h | proper char/text handling on PDP1 | |
| pdpchk | typo | |
| README | formatting | |
| shell.nix | drop all 6502 assemblers but xa | |
| superfly.c | win32 fixes | |
| uxn.h | bugfix | |
| uxnasm.c | drop diagnostics, stats from output | |
| uxnmin.c | make behaviour the same as uxncli | |
| VERSION | version header | |
| z80.h | z80 assembly fixes (stricter syntax) | |
_____ __ __ ____ ___ ____ _____ _ __ __
/ ___/| T T| \ / _]| \ | || T | T T
( \_ | | || o )/ [_ | D )| __j| | | | |
\__ T| | || _/Y _]| / | l_ | l___ | ~ |
/ \ || : || | | [_ | \ | _] | Tl___, |
\ |l || | | T| . Y| T | || !
\___j \__,_jl__j l_____jl__j\_jl__j l_____jl____/
"SUPERFLY" is a compiler for a non-pure functional low-level
programming language targeting tiny computers. The language derives
from John Backus' "FP" and is heavily influenced by the "K" array
language.
The compiler performs some minor optimizations but relies mostly
on the user to ensure the generated code is compact and efficient.
Even though the programming model uses dynamically allocated
sequences, a simple translation model and the ability to keep short
arrays in registers allows to produce relatively good code assuming
the programmer keeps the code simple and has a sufficient understanding
on how the compiler operates. Currently, SUPERFLY can produce for
for the Commodore 64, the Atari VCS game console, Z80 machines
running CP/M, the neo6502 retro computer, the ZX Spectrum,
the ZX81, the PDP-1 and the Uxn[1] virtual machine.
Values are statically but weakly typed with operators that allow full
control of how values are to interpreted. Dynamic memory allocation
uses manually managed "regions", which is simple and flexible with
minimal runtime overhead.
Here some example programs that give an impression on how FP code
looks, all examples but the last are targeting the Uxn VM.
Hello world:
[u] main:"hello, world!"pl
"FizzBuzz", for the numbers 1 to 100:
[u] fizzbuzz:'c,<101->((%.15=0->"FizzBuzz";
%.3=0->"Fizz";%.5=0->"Buzz";n2d)pl;!R+1^.)
main:1 fizzbuzz
Computing "proquints", readable names from short integers:
[u] c:'s2>.&0xf["bdfghjklmnprstvz",]#
v:'s2>.&3["aiou",]#
proquint:'s[c.12,v.10,c.6,v.4,c.0]
w:'c2[x's<.8,y]|
main:[127 0 w, 0 1 w]/.(proquint ps ws)nl
John Conway's Game of Life:
[varvara] 1000!:T old:.C new:.C
<_1 _1,0 _1,1 _1,1_ 0,1_ 1_,0 1_,_1 1,_1 0>:around
width:64_
height:40_
~$fefefefefefefe00$:sdata
cls:0_ 0_xy 0b10000000 pixel sdata saddr
colors:0x0f7f 0x0fd6 0x0fb2 rgb
buf:[width%8,height]*
setup:colors cls[buf,0'c],=.:old;=.:new
swap:[old,new],x:new;y:old
plot:'Sb,[x#1*8,x#2*8]xy;y sprite
at:'s2[[y,width%8]*,x%8]++1
get:'s2[[old,at]#,x][x,y%.8]>.&1'b
put:'Sb[x at,x#1%.8,y][new,x,[[[new,x]#,[1,y]<.^]&,[z,y]<.]|]#
next:'SS[[[x#1,y#1]+,width]%.,[[x#2,y#2]+,height]%.]get
count:'s2::here[0_,around]*/('sS[x,[here,y]next]+)
choose:'Sbs,[x,y,z=3->1;[y=1,z=2]&]
update:'Sbb,[x,z](put;plot)
cell:'s2[,get,count]choose update
cols:'s[width,-1]^{x>0->[x-1,y](cell;!T^.)}
rows:height/cols
1_:gen 0_:pos
run:gen+1:gen rows swap brk
row:'B!.([[[width%2,x]+,pos],y](put;plot)) pos+1:pos
r_pentomino:height%2:pos~<0 1 1,1 1 0,0 1 0>/.row
main:setup r_pentomino swap{run}onrefresh T brk
A simple animated "rainbow" effect for the Atari 2600/VCS:
/ assuming NTSC output
[vcs] BGColor:.c col:.c
top:2:VBLANK:VSYNC :WSYNC:WSYNC:WSYNC 0:VSYNC ~
36/:WSYNC :WSYNC 0:VBLANK
bottom:2:VBLANK 30/:WSYNC
main:top BGColor:col 192/(:WSYNC col:COLUBK 1:+col) ~
:WSYNC bottom 1:-BGColor^.
Drawing a circle on the type PDP-1 CRT:
[u] 020000:xp 0:yp
main:xp->._4[,yp]+:yp>._4[,xp]+:xp yp:`IO xp dpy^.
FP has a relatively simple evaluation model that, with some care,
can be mapped quite well to low level operations. This dialect puts
an emphasis on conciseness and supports a rich set of sequence
transformations. It takes a bit of effort to learn the syntax and
the available operators, but allows to write rather compact and
elegant programs.
The compiler is written in C, has been tested on various UNIX like
systems and should be portable to a wide range of operating systems.
The only external dependencies are a C compiler. If you don't have
Uxn installed, a minimal version of the VM included in the distribution
files is used for testing.
This is not necessarily an easy language and especially on the 6502
targets, some experience with the target system is required to write
efficient code. Nevertheless it may be an interesting approach to
write programs for minimalistic machines in a quasi functional
manner.
The compiler is written in C and should be quite portable, it
has been tested on OpenBSD, Linux and Mac OS.
To build the compiler, enter
$ make
Running
$ make check
will run a number of tests to ensure the compiler works. Note that
one of the example programs ("6502.fp") produces more labels than
the default "uxnasm" program can handle, so a slightly modified
version of it has been included in the distribution and will be
used for the tests.
See "doc/MANUAL" for a reference of the supported language, a
description of how to use the compiler and links to more information.
The "examples" directory contains various example programs to get you
started. The "include" directory has some support libraries with more
or less useful additional functions and include some basic
documentation.
Status of the backends:
Uxn: complete
Atari VCS, PDP1: complete, with many restrictions
C64, neo6502, CP/M, ZX81, ZX Spectrum: complete, with some restrictions
Note that the 6502 targets (C64, Atari VCS and neo6502) generate
output compatible to the xa[2] assembler.
You can obtain the source code here:
https://codeberg.org/Bunny351/superfly
Porting the compiler to other 6502 or Z80 based systems should be
quite easy, contact me if you need any help with such an effort.
The code is released in the public domain, do with it whatever you
like.
The files "uxnmin.c" and "uxnasm.c" included in the distribution
are Copyright (c) 2021-2024 Devine Lu Linvega, Andrew Alderwick
The "macro1" assembler for the PDP-1 was taken from [3], and
is Copyright by Gary A. Messenbrink, originally based on the pal
assember by Douglas Jones and Rich Coon.
If you want to report bugs, have suggestions or questions, please
don't hesitate to contact the author at
felix (at) call-with-current-continuation (dot) org
[1] https://wiki.xxiivv.com/site/uxn.html
[2] https://www.floodgap.com/retrotech/xa/
[3] https://github.com/obsolescence/pidp1/