Tree @master (Download .tar.gz)
Syntax-of-UampirNexol.md @master — view markup · raw · history · blame
Syntax of UampirNexol
This document defines the syntax of UampirNexol, a typed functional language for machine-language-level program construction.
The definition is illustrated with examples used as test cases.
These tests are written in Falderal format. Each indented code block
(generally preceded by a description) represents a test. All the lines of
the code block up until the ===>
line give the input to be tested; the
text after ===>
gives the expected output. ???>
gives an expected
error message, which is permitted to be a partial (substring) match.
Because the expected results are dumps of internal AST structures, these tests (or at least their expected outputs) are non-normative.
Parsing
-> Tests for functionality "Parse UampirNexol Expression"
-> Functionality "Parse UampirNexol Expression" is implemented by
-> shell command "bin/uampirnexol parse %(test-body-file)"
Demonstrating basic syntax, including line comments and hexadecimal literals.
LDA# 12;
INX; // this is a comment
LDA# 0x12 ;
INY
===> Seq (Apply LDA_i (IntLit 12)) (Seq INX (Seq (Apply LDA_i (IntLit 18)) INY))
Syntax of a conditional.
if C (LDA# 0; TAX) else TAY
===> If (IsSet C) (Seq (Apply LDA_i (IntLit 0)) TAX) TAY
Syntax of literal locations.
STA @0x0400
===> Apply STA_a (Loc (Address 1024))
Syntax of a repeat
..until
loop.
repeat (LDA# 0; TAX) until ~C
===> Repeat (Seq (Apply LDA_i (IntLit 0)) TAX) (IsUnset C)
Syntax of a while
..do
loop, which is just syntactic sugar.
while C do (LDA# 0; TAX)
===> If (IsSet C) (Repeat (Seq (Apply LDA_i (IntLit 0)) TAX) (IsUnset C)) Skip
Syntax of a let
..in
block.
let foo = 0 in LDA# foo
===> Bind "foo" (IntLit 0) (Apply LDA_i (VarRef "foo"))
A let
..in
block may have more than one binding.
let foo = 0, bar = 1 in LDA# foo
===> Bind "foo" (IntLit 0) (Bind "bar" (IntLit 1) (Apply LDA_i (VarRef "foo")))
Syntax of routine
and call
, including typical usage in let
, and precedence.
call routine (LDA# 0; TAX)
===> Call (Routine (Seq (Apply LDA_i (IntLit 0)) TAX))
call (routine LDA# 0); TAX
===> Call (Seq (Routine (Apply LDA_i (IntLit 0))) TAX)
let foo = routine (LDA# 0; TAX) in call foo
===> Bind "foo" (Routine (Seq (Apply LDA_i (IntLit 0)) TAX)) (Call (VarRef "foo"))
Syntax of extern
, including typical usage in let
.
let foo = extern @0xc018 : State[A/] -> State[A,X,Y/] in call foo
===> Bind "foo" (Extern (Loc (Address 49176)) Routine(State[A/] -> State[A,X,Y/])) (Call (VarRef "foo"))
Note the precedence of ;
is higher than that of while
.
while C do LDA# 0; TAX
===> If (IsSet C) (Repeat (Seq (Apply LDA_i (IntLit 0)) TAX) (IsUnset C)) Skip
while C do (LDA# 0); TAX
===> If (IsSet C) (Repeat (Seq (Apply LDA_i (IntLit 0)) TAX) (IsUnset C)) Skip
(while C do LDA# 0); TAX
===> Seq (If (IsSet C) (Repeat (Apply LDA_i (IntLit 0)) (IsUnset C)) Skip) TAX
These are syntactically valid, but will trip a type error in a later phase.
LDA#; TAX
===> Seq LDA_i TAX
STA; TAX
===> Seq STA_a TAX
STA C
===> Apply STA_a (Loc C)
repeat CLC until @0x0400
===> Repeat CLC (IsSet (Address 1024))