# dirac

Paradigm(s) | imperative |
---|---|

Designed by | Palaiologos |

Appeared in | 2022 |

Memory system | Cell-based Stack-based |

Dimensions | one-dimensional |

Computational class | Turing complete |

Major implementations | Reference Implementation |

Influenced by | FALSE |

File extension(s) | `.dir` |

dirac (Delightfully Intricate Reasonably Amazing Calculator) is a programming language inspired by FALSE created by Palaiologos in early 2022. The main goal of this esoteric language was creating an obfuscated, stack-based language which can express imperative algorithms in a concatenative fashion.

### Operations

Numeric literals push content to the stack. For example, `2 3+`

pushes 2 and 3 and adds them, so the number 5 ends up on the stack. It is possible to push the ASCII code of a character on the stack using a single quote, so that `'A`

will push 65 (the ASCII code of `A`

). String literals can be pushed on the stack using double quotes. Individual characters are pushed from the back, and the string is always terminated with a zero. Hexadecimal constants can be loaded using `H`

. For instance, `H3FF`

will load `0x3FF`

on the stack.

Reference to a variable (to be used with `:`

or `;`

) can be pushed using the variable's name. For instance, `var:`

will load the value of `var`

on the stack. dirac is lexically scoped, so variables defined in the inner scope don't affect the outer scope (if it exists). Lambda expressions are introduced using `[]`

and they push a reference to themselves on the stack.

The list of commands follows:

- `+`

- `a b -- a+b`

- addition

- `-`

- `a b -- a-b`

- subtraction

- `*`

- `a b -- a*b`

- multiplication

- `/`

- `a b -- a/b`

- division

- `%`

- `a b -- a%b`

- modulus

- `#`

- `a -- a a`

- duplicating the top of the stack

- `$`

- `a --`

- popping the top of the stack

- `I.`

- `-- c`

- character input

- `I:`

- `-- i`

- integer input

- `I,`

- `c --`

- character output

- `I;`

- `i --`

- integer output

- `I<`

- `-- i`

- hexadecimal integer input

- `I>`

- `i --`

- hexadecimal integer output

- `M<`

- `sz -- ptr`

- allocating a block of memory of size `sz`

and pushing a pointer to it

- `M>`

- `ptr --`

- freeing memory pointed by `ptr`

- `M.`

- `ptr a -- c`

- reading a byte of memory at address `a`

from `ptr`

(byte-aligned)

- `M:`

- `ptr a -- i`

- reading a qword of memory at address `a`

from `ptr`

(qword-aligned)

- `M,`

- `ptr a c --`

- writing byte `c`

at address `a`

in `ptr`

(byte-aligned)

- `M;`

- `ptr a i --`

- writing qword `i`

at address `a`

in `ptr`

(qword-aligned)

- `B|`

- `a b -- a|b`

- bit-wise OR

- `B&`

- `a b -- a&b`

- bit-wise AND

- `B^`

- `a b -- a^b`

- bit-wise XOR

- `B~`

- `a -- ~a`

- bit-wise NEG

- `B<`

- `a b -- a<<b`

- bit-wise SHL

- `B>`

- `a b -- a>>b`

- bit-wise SHR

- `C>`

- `a b -- a>b`

- greater-than check

- `C<`

- `a b -- a<b`

- lesser-than check

- `C>=`

- `a b -- a>=b`

- greater-or-equal check

- `C<=`

- `a b -- a<=b`

- lesser-or-equal check

- `C=`

- `a b -- a==b`

- equality check

- `C!`

- `a b -- a!=b`

- inequality check

- `@`

- `a_n a_n-1 ... a1 a0 i -- a_i`

- copy the `i`

-th element of the stack starting from the top

- `^`

- `x y -- y x`

- two-argument rotate

- ```

- `x y z -- z y x`

- three-argument rotate

- `!`

- `l --`

- execute lambda expression `l`

- `?`

- `c l --`

- execute lambda expression `l`

only if `c`

is truthy.

- `;`

- `v r --`

- set the value of variable `r`

to `v`

.

- `:`

- `r --`

- get the value of variable `r`

.

- `~;`

- `v r --`

- set the value of variable `r`

to `v`

in the outermost scope it's defined.

- `~:`

- `r --`

- get the value of variable `r`

in the outermost scope it's defined.

- `F#`

- `c i --`

- execute `i`

as long as executing `c`

yields true (an equivalent of `while`

loop in C).

- `F~`

- `c i --`

- execute `i`

at least once as long as executing `c`

yields true (an equivalent of `do .. while`

loop in C).

- `F$`

- `c t f --`

- if `c`

is true, execute `t`

and `f`

otherwise.

- `F``

- `--`

- exit the program.

- `F%`

- `s e t f --`

- a range loop from `s`

to `e`

. if `s < e`

, `t`

is added after every iteration. if `s > e`

, `t`

is subtracted after every iteration. on every iteration, pushes the current counter value and calls `f`

.

- `D,`

- `--`

- print debugging information.

- `&`

- `a1 a2 a3 ... an -- a_[b_1] a_[b_2] ... a_[b_m]`

- arbitrary stack reordering. For instance, `&210`

rotates three topmost stack elements, while `&111` overwrites the three topmost stack elements with the second to top stack element.

### Examples

Stack manipulation and basic arithmetics:

2 2 { Pushes two copies of 2 on the stack } + { Add them together } '0+ { Add ASCII(48) turning the result into a digit } H0F { Push 0xF } B| { Bit-wise OR } # { Duplicate } I; { Print as decimal } '=I, { Print "=" } I, { Print as character } { The code above prints "63=?", but it could also be written in a more compact way: } 2 2+'0+H0F B|#I;'=I,I,

A factorial function and it's invocation:

[1^1+1^1[*]F%I;]f;10f:! { Displays "3628800" }

A fibonacci function:

[#I;10I,]pf;[0pf:!1pf:!#3@1[$#`+pf:!]F%$$]fib;50fib:!

The following programs are sometimes used to test an implementation of dirac:

[[#0C!][I,]F#$]putstr;"Bitness: "putstr:!1 1[#0C>][1B<^1+^]F#$I;10I, "Allocating an array, got pointer: 0x"putstr:!256M<#I>10I, "Performing identity-fill..."putstr:!0 255 1[^#`#M,]F%10I, "Checking correctness..."putstr:!0 255 1[^#`#`^M.C!["Failed."putstr:!F`]?]F%10I, "Freeing the array"putstr:!M>10I,

[[#0C!][I,]F#10I,]puts; "Test 1: General operations"puts:! 2 2+'0+H0F B|#I;'=I,I,10I, "Test 2: Factorial"puts:! [1^1+1^1[*]F%I;]f;10f:!10I, "Test 3: Fibonacci"puts:! [#I;10I,]pf;[0pf:!1pf:!#3@1[$#`+pf:!]F%$$]fib;20fib:! "Test 4: Outer scope operations"puts:! [0a;[[1a~;]!]!a:["Ok"]["Failed"]F$]!puts:!