Uxntal Notation
The Uxntal notation follows that of the Forth programming language, where each item on the left of the -- spacer is the state of the stack before, and to the right, the state of the stack after:
@routine ( a b -- a b c ) ADDk JMP2r
By default, single items are a byte long, and shorts are indicated with a * suffix, the order in which they appear is the order of the stack with the top item to the right:
@routine ( a b* -- b* a ) ROT JMP2r
The dot notation is used to indicate that stack effects to the right of the dot are happening on the return stack:
@routine ( a . b -- c ) STHr ADD JMP2r
If a routine is a vector, it uses the arrow notation.
@on-event ( -> ) BRK
Validation
Program validation is done at compile-time by comparing a routine's stack effect, against the resulting balance of all stack changes occurring in the routine's code. Words that do not pass the stack-checker are generating a warning, and so essentially this defines a very basic and permissive type system that nevertheless catches some invalid programs and enables compiler optimizations. For more details, see Uxnbal.
The simplest case is when a piece of code does not have any branches or recursion, and merely pushes literals and calls words. The stack effect routines is always known statically from the declaration.
@add-eight ( a -- a+8 ) #0008 ADD JMP2r
Working-stack imbalance of +1, in add-eight.
In the case of branching, each branch is evaluated and if an imbalance occurs inside one of the branches, the branch name is indicated:
@branching ( a* -- c ) LDAk #01 EQU ?&one LDAk #02 EQU ?&two POP2 #ff JMP2r &one ( a* -- c ) POP2 #12 JMP2r &two ( a* -- c d ) ADD JMP2r
Working-stack imbalance of -1, in branching/two.
In the case of a recursion, the validator will use the stack effect instead of repeatedly walking through the body of the routine.
@print-string ( str* -- ) LDAk DUP ?{ POP POP2 JMP2r } emit-letter INC2 !print-string
For loops that exits without affecting the stack depth, a > prefixed label is used as a shorthand to reduce the need for extraneous stack effect definitions in cases where it can be inferred:
@many-times ( a -- ) DUP &>l INC DUP ?&>l POP2 JMP2r
Routines that pull items from the stack beyond their allowed depth will also raise a warning, making the stack effect act a sort of boundary:
@shallow ( a -- ) POP2 JMP2r
Working-stack depth error of 1, in shallow.
Lastly, a runtime specific solution to validate the stack state at any one point during the execution of a program, is to read the System/wst port and compare it against a given stack pointer byte value.
@on-reset ( -> ) #abcd DUP2 .System/wst DEI #05 EQU ?{ #01 .System/debug DEO } BRK
Comments
A comment starts with any token beginning with opened parenthesis, and ends at its corresponding closed parenthesis. Comments may be nested, the enclosed comments parentheses must be whitespace separated on both sides.
( ( nested ) ) ( 1+2*(4/3) )
Outermost comments may be named, which means that sometimes the open parenthesis is immediately followed by a word used to indicates some meaning to external tools.
(doc This is a docstring. )
Brackets
The square brackets do nothing, they are there merely for readability and formatting, they are useful for making explicit certain things like grouping behaviors, joining literals or indicating lookup tables.
@routine ( -- ) [ LIT2 20 -Console/write ] DEO JMP2r %min ( a b -- r ) { GTHk [ JMP SWP ] POP } @sprite [ 00 66 ff ff ff 7e 3c 18 ]
incoming drifblim uxntal syntax uxntal reference uxnfor 2023