1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2024-06-07 06:29:32 +00:00

Update docs.

This commit is contained in:
Chris Pressey 2019-04-10 09:29:45 +01:00
parent 8d6e5e090d
commit 21a187a105
3 changed files with 99 additions and 50 deletions

View File

@ -16,7 +16,7 @@ History of SixtyPical
can also be given.
* Accessing a `table` through a `pointer` must be done in
the context of a `point ... into` block. This allows the
analyzer to check *which* table is being modified.
analyzer to check *which* table is being accessed.
* Added `--dump-exit-contexts` option to `sixtypical`.
0.18

139
README.md
View File

@ -1,60 +1,25 @@
SixtyPical
==========
_Version 0.18. Work-in-progress, everything is subject to change._
_Version 0.19. Work-in-progress, everything is subject to change._
**SixtyPical** is a low-level programming language with advanced
static analysis. Many of its primitive instructions resemble
those of the 6502 CPU — in fact it is intended to be compiled to
6502 machine code — but along with these instructions are
constructs which ease structuring and analyzing the code. The
language aims to fill this niche:
**SixtyPical** is a [very low-level](#very-low-level) programming language
supporting a [sophisticated static analysis](#sophisticated-static-analysis).
* You'd use assembly, but you don't want to spend hours
debugging (say) a memory overrun that happened because of a
ridiculous silly error.
* You'd use C or some other "high-level" language, but you don't
want the extra overhead added by the compiler to manage the
stack and registers.
SixtyPical gives the programmer a coding regimen on par with assembly
language in terms of size and hands-on-ness, but also able to catch
many ridiculous silly errors at compile time, such as
* you forgot to clear carry before adding something to the accumulator
* a subroutine that you called trashes a register you thought it preserved
* you tried to read or write a byte beyond the end of a byte array
* you tried to write the address of something that was not a routine, to
a jump vector
Many of these checks are done with _abstract interpretation_, where we
go through the program step by step, tracking not just the changes that
happen during a _specific_ execution of the program, but _sets_ of changes
that could _possibly_ happen in any run of the program.
SixtyPical also provides some convenient operations based on
machine-language programming idioms, such as
* copying values from one register to another (via a third register when
there are no underlying instructions that directly support it); this
includes 16-bit values, which are copied in two steps
* explicit tail calls
* indirect subroutine calls
SixtyPical is defined by a specification document, a set of test cases,
and a reference implementation written in Python 2. The reference
implementation can analyze and compile SixtyPical programs to 6502 machine
code, which can be run on several 6502-based 8-bit architectures:
* Commodore 64
* Commodore VIC-20
* Atari 2600 VCS
* Apple II
Its reference compiler can generate [efficient code](#efficient-code) for
[several 6502-based platforms](#target-platforms) while catching many
common mistakes at compile-time, reducing the time spent in debugging.
Quick Start
-----------
If you have the [VICE][] emulator installed, from this directory, you can run
Make sure you have Python (2.7 or 3.5+) installed. Then
clone this repository and put its `bin` directory on your
executable search path. Then run:
sixtypical
If you have the [VICE][] emulator installed, you can run
./loadngo.sh c64 eg/c64/hearts.60p
@ -67,11 +32,80 @@ You can try the `loadngo.sh` script on other sources in the `eg` directory
tree, which contains more extensive examples, including an entire
game(-like program); see [eg/README.md](eg/README.md) for a listing.
[VICE]: http://vice-emu.sourceforge.net/
Features
--------
SixtyPical aims to fill this niche:
* You'd use assembly, but you don't want to spend hours
debugging (say) a memory overrun that happened because of a
ridiculous silly error.
* You'd use C or some other "high-level" language, but you don't
want the extra overhead added by the compiler to manage the
stack and registers.
SixtyPical gives the programmer a coding regimen on par with assembly
language in terms of size and hands-on-ness, but also able to catch
many ridiculous silly errors at compile time.
### Very low level
Many of SixtyPical's primitive instructions resemble
those of the 6502 CPU — in fact it is intended to be compiled to
6502 machine code — but along with these instructions are
constructs which ease structuring and analyzing the code.
However, SixtyPical also does provide some "higher-level" operations
based on common 8-bit machine-language programming idioms, including
* copying values from one register to another (via a third register when
there are no underlying instructions that directly support it)
* copying, adding, and comparing 16-bit values (done in two steps)
* explicit tail calls
* indirect subroutine calls
While a programmer will find these constructs convenient, their
inclusion in the language is primarily to make programs easier to analyze.
### Sophisticated static analysis
The language defines an [effect system][], and the reference
compiler [abstractly interprets][] the input program to check that
it conforms to it. It can detect common mistakes such as
* you forgot to clear carry before adding something to the accumulator
* a subroutine that you called trashes a register you thought it preserved
* you tried to read or write a byte beyond the end of a byte array
* you tried to write the address of something that was not a routine, to
a jump vector
### Efficient code
Unlike most languages, in SixtyPical the programmer must manage memory very
explicitly, selecting the registers and memory locations to store all data in.
So, unlike a C compiler such as [cc65][], a SixtyPical compiler doesn't need
to generate code to handle stack management or register spilling. This results
in smaller (and thus faster) programs.
The flagship demo, a minigame for the Commodore 64, compiles to
a **930**-byte `.PRG` file.
### Target platforms
The reference implementation can analyze and compile SixtyPical programs to
6502 machine code formats which can run on several 6502-based 8-bit architectures:
* [Commodore 64][] -- examples in [eg/c64/](eg/c64/)
* [Commodore VIC-20][] -- examples in [eg/vic20/](eg/vic20/)
* [Atari 2600][] -- examples in [eg/atari2600/](eg/atari2600/)
* [Apple II series][] -- examples in [eg/apple2/](eg/apple2/)
Documentation
-------------
SixtyPical is defined by a specification document, a set of test cases,
and a reference implementation written in Python.
* [Design Goals](doc/Design%20Goals.md)
* [SixtyPical specification](doc/SixtyPical.md)
* [SixtyPical revision history](HISTORY.md)
@ -82,3 +116,10 @@ Documentation
* [6502 Opcodes used/not used in SixtyPical](doc/6502%20Opcodes.md)
* [Output formats supported by `sixtypical`](doc/Output%20Formats.md)
* [TODO](TODO.md)
[VICE]: http://vice-emu.sourceforge.net/
[cc65]: https://cc65.github.io/
[Commodore 64]: https://en.wikipedia.org/wiki/Commodore_64
[Commodore VIC-20]: https://en.wikipedia.org/wiki/Commodore_VIC-20
[Atari 2600]: https://en.wikipedia.org/wiki/Atari_2600
[Apple II series]: https://en.wikipedia.org/wiki/Apple_II_series

View File

@ -29,6 +29,14 @@ inner block has finished -- even if there is no `call`.)
These holes need to be plugged.
### Reset pointer in `point into` blocks
We have `point into` blocks, but maybe the action when entering such a
block shouldn't always be to set the given pointer to the start of the given table.
That is, sometimes we would like to start at some fixed offset. And
sometimes we want to (re)set the pointer, without closing and starting a new block.
### Pointers associated globally with a table
We have `point into` blocks, but we would also like to sometimes pass a pointer