Skip to content
/ uf Public

[Mirror] A traditional Forth system for the Uxn virtual computer by Felix Winkelmann.

Notifications You must be signed in to change notification settings

Ismael-VC/uf

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

97 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

                          
                    88        88 88888888888  
                    88        88 88           
                    88        88 88           
                    88        88 88aaaaa      
                    88        88 88"""""      
                    88        88 88           
                    Y8a.    .a8P 88           
                     `"Y8888Y"'  88           


Version: 9


I. Introduction

This is a traditional Forth system for the "uxn/varvara"[1] virtual
computer. "UF" is written in Tal[2] and Forth and provides an
interactive text interface and screen editor. The system is not
threaded, it compiles to native UXN code, but currently only minimal
optimizations are performed. The mapping of Forth source code to
VM instructions is nevertheless relatively direct, so performance
should be more than sufficient in all but the most speed-critical
situations. Cells are 16 bits, the full system uses around 25K of
memory, with another 4K needed for screen memory and buffers.


II. Building UF

To build the .rom files, you need to first assemble the kernel and
then use it to generate additional .rom files with more functionality:

    $ uxnasm kernel.tal kernel.rom
    ...
    $ uxncli kernel.rom <uf.f

This will produce the following files:

    kernel.rom

        The kernel, containing minimal functionality to define new
        words.

    uf0.rom

        The kernel and core words.

    uf.rom

        The functionality of "uf0.rom" together with words to access
        "varvara" device ports in a more convenient matter, and some
        basic tools (like `dump`).

    ufx.rom

        The full graphical Forth system, including the block editor.


III. Using UF

Run "uf0.rom" and "uf.rom" with "uxncli" as a normal terminal
application. "ufx.rom" should be executed with "uxnemu":

    uxnemu ufx.rom <arguments ...>

Additional command line arguments or console input will be redirected
to the graphical input prompt and can be used to perform initialization,
etc.

In the graphical interface the following key sequences have a special
meaning ("^" meaning the Control key, "Sh" the Shift key):

    ^a      Jump to beginning of line
    ^e      Jump to end of line
    ^c      Terminate Forth (unless a modified block is open in the 
            editor)
    ^d      Delete next char
    ^k      Kill to end of line or marked region (and write to 
            ".snarf" file)
    ^u      Kill to beginning of line or marked region (and snarf)
    ^x      Copy line or marked region to ".snarf" file
    ^v, ^y  Paste contents of ".snarf" file
    ^f      Find next occurrence of word below cursor
    ^s      Save changes in currently edited block
    ^l      Clear screen (unless in editor)
    ^g      Read digits and jump to indicated block on ENTER
            (abort on ESC)
    ^r      Read digits and copy current block to new one on ENTER
    ^m      Read digits and move current block to new one on ENTER
            (and delete the old block)
    ^ENTER  Toggle region mark on/off in editor

    Sh-Up   Recall the last entered line or jump to previous block
    Sh-Down Jump to next block
    Sh-Left/Right   Jump between code and documentation ("shadow")
            block

The arrow keys have the usual meaning. Pressing ENTER will execute
the current line (marked by the cursor). Pressing ^ENTER will
toggle "mark" mode, all lines between the start of the mark and
the current row are copied and written to a file named ".snarf"
in the current directory once you press ENTER or ^x. 

Pressing the first mouse button will reposition the cursor. Pressing
the third button will execute the word below the mouse pointer.
Moving the scroll wheel will jump to the previous or next block,
when currently editing an unmodified block.

File system access is provided by "block" files, where each block
is named by a natural number and contains 2496 bytes (39 lines with
64 columns). To edit a block, enter

    <blocknumber> edit

The ESC key will exit or enter editing (unless the current block
is modified). The bottom row contains counters indicating current
row, column, block number, the length of the most recently copied
text, the amount of dictionary space left and a marker indicating
whether the current block is modified. Blocks can be loaded using
`load` and `thru`. Note that block-loading is done by temporarily
changing the word for reading user-input (`query`) and takes effect
when the current input line has been fully processed. That implies
that loading words can not be invoked recursively.

You can also edit a block by clicking with button 3 on a string of
the form "#nnnn" where "nnnn" is a decimal integer.

If a 6 byte file named ".theme" is found in the current directory,
then it will be used to initialize the color scheme during startup.
The colors are used as follows: #0 background, #1 text, #2 status
line text, #3 selection.

The current state of the system can be conveniently stored as a
.rom file on disk by entering

    save <filename>

The saved rom has the exact same state (but with cleared stacks)
as when it was created. During startup, the deferred word `boot`
is invoked, you can redefine it to replace it with custom startup
code.

You are also heavily encouraged to consult the source code in "uf.f".


IV. Compatibility to other Forths

Consult the "GLOSSARY" file for a list of supported Forth words
and the extensively commented source files "kernel.tal" and "uf.f"
for more information. The dialect implemented in UF is mostly compatible 
to the Forth 2012 Standard[3]. Notable differences include:

- The system is case-sensitive (`Abc` and `abc` name two different
  words)

- `do` and `?do` treat the index and range as unsigned quantities.

- Numeric conversion in `<# ... #>` exclusively deals with single
  cell numbers.

- Double-word maths are currently not implemented.

- Words that produce boolean results may not always generate -1
  (`true`) but some other non-zero value.

- Multiple `while` forms in a `begin` ... `repeat` loop are not
  supported.

The dictionary can be inspected with the `words`, `order` and `.vocs` 
words. To decompile built-in or user words, use `see`.


V. The integrated Assembler

You can define words containing a simplifed form of Uxntal using the
`code` and `end-code` words. Inside such a definition, the following
words have a special meaning:

    BRK INC ...             assemble uxn op-instruction
    " k r                   add modifier bit to previous instruction
    $           ( u -- )    pad by number of bytes on stack
    #           ( c -- )    assemble byte literal
    #"          ( x -- )    assemble short literal
    &           ( u -- )    define label
    ,           ( u -- )    reference previously defined label as relative
                            branch distance
    `    ( | <word> -- )    Compile immediate call of Forth word
    !    ( | <word> -- )    Compile immediate jump to Forth word
    ?    ( | <word> -- )    Compile immediate conditional jump to Forth word

Currently only 16 labels can be defined. You can insert absolute
references to other Forth words using the sequence `' <word> #"`
or by using the syntax

    ` <word`

to encode an immediate (JSI) call to a Forth word.

Note that the stack is required to be aligned to shorts and that
code-words should perform the equivalent of a "JMP2r" to return to
the caller.

An example:

    code bitcount8 ( x^ -- n^ )
        0 # SWP ( n x )
        1 &
        DUP 0 # EQU ( n x x=0 )
        2 , JCN ( n x )
        1 # SFT ( n x>>1 )
        SWP INC SWP ( n+1 x>>1 )
        1 , JMP
        2 &
        POP ( n )
        JMP " r
    end-code


VI. Memory Map

   FFFF +----------------------------+
        |       Screen buffer        |
   F600 +----------------------------+
        |     Block load buffer      |
   ec40 +----------------------------+
        |                            |
        |        Unused space        |
        |                            |
        +----------------------------+ < `here`
        |     User defined words     |
        +----------------------------+
        |          Kernel            |
   0100 +----------------------------+
        |          Unused            |
   0000 +----------------------------+

Uf allows up to 4 vocabularies to be active at the same time. You
can see the currently available words by executing `words` and
inspect the vocabulary stack with `.vocs`. Predefined vocabularies
are `forth` (the default), `compiler` (words only available during
compilation of colon words), `assembler`, `decompiler` and `editor`.


VIII. Uxn VM implementation Issues

UF has been tested on SDL uxn[4] and uxn11[5].

In the graphical interface the controller, console and mouse device
vectors are modified to receive input events. During evaluation of
code the vectors are temporarily cleared and a BRK or machine halt
will abort with an error and return to the Forth prompt. If you
want to modify any of these vectors permanently, make sure your
code does not return to the interactive prompt or use `wait`, which
invokes the deferred word `tick`, which you can modify to perform
custom processing (the default implementation just blinks the
cursor).

The graphical system sets the screen size to the default 512x320
resolution which must be supported by the underlying uxn implementation.

A number of words are defined to access "varvara" devices, consult
the GLOSSARY for more details:

System:
    colors  reset  clear  depth  evector

Console:
    cin  cout  ctype  cvector

Screen:
    screensize@  screensize!  position  pixel  auto  spritedata
    sprite  svector

Audio:
    sample  play  adsr  volume  output  avector

Controller:
    jkey  jbutton  jvector

Mouse:
    mouse  mscroll  mstate  mvector

File:
    filename  filewrite  fileappend  fileread  filedelete

Datetime:
    year  month  day  hour  minute  second  dotw  doty  isdst

Note that the file words only use the first file device (a0).

Console input in the graphical interface is redirected to the 
screen, so the line-length limit of the screen applies here.
Input lines that exceed the screen width are silently cut off,
with the text preceding the exceeding part being ignored.

Due to limitations of the "varvara" file-system interface files
loaded with `include` (or `included`) may not exceed the
currently available dictionary space divided by two as the
file has to be loaded into memory completely before it can be
interpreted. Moreover, file-inclusion can not be nested.


IX. License

This software was written by Felix L. Winkelmann and has been
released into the public domain. Do with it whatever you want.


X. Contact Information

This software will have many bugs and shortcomings. In case you
need help, have suggestions or ideas, please do not hesitate to
contact the author at

    felix AT call-with-current-continuation DOT org

A git repository can be found at [6], if you want to follow the
development of the system more closely.


XI. References

[1] https://100r.co/site/uxn.html
[2] https://wiki.xxiivv.com/site/uxntal.html
[3] https://forth-standard.org/
[4] https://git.sr.ht/~rabbits/uxn
[5] https://git.sr.ht/~rabbits/uxn11
[6] https://gitlab.com/b2495/uf