GAXT

From Esolang
Jump to navigation Jump to search
GAXT
Designed by Fancryer
Appeared in 2022
Dimensions one-dimensional
Computational class Total
Reference implementation Interpreter
Influenced by Forth, Brainfuck
File extension(s) .gaxt


GAXT is an esoteric programming language created by Fancryer and uses two stacks: a stack for calculations (hereinafter - CalcStack) and a stack for variables (hereinafter - VarStack). Current GAXT version: v0.2-beta. There is an unfinished Java interpreter that will be publicly available after the stable release. All supported tokens, represented as a string: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-*/_`<=>?$:;~%{|}\^()@[].,#!.

Values

GAXT only has 64-bit signed integers. Accordingly, all mathematical operations result in integers, including division.

Variables

GAXT has a 26-element array for storing variable values, one for each letter from a to z. Initially, all variables are initialized to zero. To work with a variable, you need to put its name in varStack, you can do this regardless of which stack is currently in use. Only variable names are passed to VarStack, their values ​​are stored in an array and retrieved during operations.

Constants (DEPRECATED after GAXT 0.2-beta release)

There are 26 constants in GAXT, one for each Latin letter from A to Z. In GAXT v0.1-alpha all constants are predefined. Constants were provided to make it easier to print characters, but they can also be used as normal values. Below are the values ​​of all constants in alphabetical order.

  • A: 10
  • B: 20
  • C: 30
  • D: 40
  • E: 50
  • F: 60
  • G: 70
  • H: 80
  • I: 90
  • J: 100
  • K: 200
  • L: 300
  • M: 400
  • N: 500
  • O: 600
  • P: 700
  • Q: 800
  • R: 900
  • S: 1000
  • T: 2000
  • U: 3000
  • V: 4000
  • W: 5000
  • X: 6000
  • Y: 7000
  • Z: 8000

Operators

All operators are written in postfix form.

Each mathematical or logical operator performs the following actions depending on the current stack:

CalcStack VarStack
  1. Pops the value from the top of the stack and assigns it to the temporary variable β.
  2. Pops the value of a variable from the top of the stack and assigns it to the temporary variable α.
  1. Pops the value of a variable from the top of the stack and assigns it to the temporary variable β.
  2. Pops the value of a variable from the top of the stack and assigns it to the temporary variable α.
3. Creates a temporary variable ρ for the result of the operation.

4. Pushes ρ on the stack.

Math

Character Operator ρ
+ Add α + β
- Subtract α - β
* Multiply α * β
/ Divide α / β
_ Concat str(α)..(str(β))

The concatenation operation is performed differently depending on the sign of α and β (the '-' and '+' before α or β show their sign):

Concat 0
αβ β -αβ
0 α 0
-αβ αβ

Logical

The result of logical operations is always either 0 or 1.

Character Operator ρ
` Nor α ↓ β
< Less α < β
= Equal α = β
> Greater α > β

Print

Print operations do not affect the state of the stack, but it is not possible to remove printed characters from the output.

CalcStack VarStack

Peeks the value from the top of the stack and assigns it to the temporary variable β.

Peeks the value of a variable from the top of the stack and assigns it to the temporary variable β.


Character Operator Action
? PrintInt Prints β as int (including '-' sign if b is negative).
$ PrintChar Prints β as a character if it is in ASCII and can be printed.

Stack

Character Operator Action
: Assign Assigns the value of the top of the current stack to the top of another stack. This removes the top of the current stack. Also, the operation cannot be performed if the other or current stack is empty.
; Reverse Reverses current stack.
~ Shave Removes the top of the stack. The operation cannot be performed if the current stack is empty.
% Clear Erases the stack completely.

Flow

Character Operator Action
{ If Executes the code before the "then" statement if the top of the current stack is non-zero, otherwise execution jumps to the character after the "then" statement.
| Then Separates the code that is executed when the condition before the "if" is true, from the code that is executed otherwise.
} Else Closes if-then-else group.
\ Break Breaks one level of nesting: exits the current loop or macro.
^ Continue Jumps to the beginning of the current nesting level (loop or macro) regardless of the state of the stacks.

Macro

A macro in GAXT is similar to a procedure in conventional programming languages: it stores code that is executed immediately after the macro is called, and does not require a program finish statement. At the moment (GAXT v0.1-alpha) nested macros are not allowed.

Character Operator Action
( Read Starts macro recording, any characters before the "write" statement are not executed.
) Write Ends macro recording and stores it in the macro list.
@ Call Calls the macro written at the index at the top of the current stack. It is not possible to call a macro if it has not been recorded before. In this case, the operator is ignored.

Loop

Cycles in GAXT are only with a postcondition. Loops of any nesting are allowed up to level 263-1.

Character Operator Action
[ Repeat Increments the nesting level, executes all code up to the "Until" statement.
] Until Exits the loop if the top of the current stack is zero or empty, otherwise jumps to the character after the "Repeat" of this loop.

Label

Labels in GAXT are analogous to goto in C or jmp in assembly language. You can create or load any label at any time.

Character Operator Action
. Save Creates a new label and adds it to the list of labels. You can create up to 263-1 labels.
, Load Jumps to the label at the index at the top of the current stack. The label cannot be loaded if it has not been previously recorded. In this case, the operator is ignored.

Service

Character Operator Action
# Switch Changes the current stack: CalcStack -> VarStack or VarStack -> CalcStack.
! Finish Terminates the entire program even when called in a loop or procedure, regardless of the current nesting level.

String

Since version 0.2-beta, GAXT has added support for strings (interpolated too). A string is a sequence of numbers written upside down onto the stack. The length of the string is written next.

Character Operator Action
" String edge Toggles line-not-line mode (actually just represents a string boundary). On completion of a string, pushes it onto the stack (see above).
& Raw code Can only be inserted into a string, allowing almost any code to be executed while the string is being pushed onto the stack (a potentially dangerous operation).
' Formatter Escapes (replaces) the next character according to the table below.
Format character Name Action
whitespace Fmt_space Whitespace (ASCII) character.
\n Fmt_new_line Line feed character.
\t Fmt_tab Tabulation character.
! Fmt_finish Exclamation mark character.
a-z (any variable) Fmt_var The value of the variable as a number (as when using '?').

Undefined and comments

Any character that is not a digit, variable/constant name, or operator must be ignored in all implementations of GAXT or derived programming languages. All characters written after the "Finish" statement are also ignored.

Examples

Hello world

A typical "Hello, world!" print. This example uses delta encoding to reduce the length of the source code. GAXT 0.2-beta realization
72_$~
J1+$~
10_8_$~
10_8_$~
11_1_$~
44_$~
32_$~
11_9_$~
11_1_$~
11_4_$~
10_8_$~
J$~
33_$~!
G2+$
C+1-$
7+$$
3+$
G-3+$
A-2-$
JB+1-$
8-$
3+$
6-$
8-$
F-7-$~!
"Hello,' world'!"~[$~]!
78 characters 49 characters 23 characters (and code is also easier to read)

First 10 Fibonacci numbers

This example should work in theory, but has not been tested in practice. Translated from C (do-while loop).

An: 0x: 1y: 0z: 0i: #
[
  x? # C2+$
  1x: 1y: # +z: #
  1y: # x: # 1z: # y: #
  11i:+ #i: #
  in<
]!

Conditional branching

This program will print "A" if 2<3, and "B" otherwise.

23<
{
  I7+
  |
  I8+
}
$~~!

Macro test

Since GAXT ignores any characters that are not included in its set of tokens, and ASCII-Latin is included in it (set), the comments are in Russian.

(a0:b0:)            обнулить а и б
(#?~#)              напечатать значение вершины другого стека
(C2+$~)             напечатать пробел
($~ 2@ F1+$~ 2@)    напечатать символ и пробел  и равно и пробел


a3:                 а равно трём
I7+ 3@ a1@ 2@       напечатать а равно и его значение и пробел

b5:                 б равно пяти
I8+ 3@ b1@          напечатать б равно и его значение

0@                  очистить а и б
A$                  напечатать перевод строки

I7+ 3@ a1@ 2@       напечатать а равно и его значение и пробел
I8+ 3@ b1@          напечатать б равно и его значение
!                   финиш

99 bottles of beer

GAXT 0.1-alpha GAXT 0.2-beta
(
    9@
    H3+-$
    H1-+$ 9-$
    G-$
    F6++$ 3+$$ A3++$%
)

(
    C2+$
    G9++$ 1-$
    G8+-$
    H4++$ A2+-$ 3-$
    G1--$
    H7++$ B2+-$ A1++$$%
)

(
    H4+$ A3++$ A+$ 6-$
    F9+-$
    G9++$ 1-$ 9-$
    F9+-$
    F8++$ A1++$ 8+$ 9-$
    G8+-$
    F5++$ A3++$ A-$
    F8+-$
    H+$ A5+-$ A8++$$
    H3+-$
    G3++$ A1++$
    H4+-$
    F5++$ A7++$ 3-$ 6+$ 7-$ A-$
    E6+-$ A2+-$%
)

(
    I8+$ A3++$ 5+$$ 8-$ 7-$
    F9+-$
    G9++$ 9-$
    G-$
    F6++$ 3+$$ A3++$%
)

(0@1@)
(#ba+?ba-%#)
(D4+$ A2+-$%)
(D9+$ A7+-$%)
(D6+$C6+-$%)

(
    C2+$
    F6++$ A3++$ 5+$$ 8-$ 7-$ A4++$
)

(
    5@4@6@5@0@ 8@
    2@#b?#4@8@ #ba-#
)

(
    JA+$ 1+$
    G9+-$
    G7++$ 2+$ 3+$ A3+-$%
)

98_b: a1:
b#[#A@#]#

7@3@1@6@7@3@8@
2@A1+@4@!
(
    "'b' bottles' of' beer' on' the' wall,' 'b' bottles' of' beer.'\n"~[$~]
    "Take' one' down' and' pass' it' around,' &#ba-#&'b' bottles' of' beer' on' the' wall'\n"~[$~]
)
b99_: a1: #[%#0@#b]%!

Grammar

Below is the formal GAXT grammar in EBNF (ANTLR version).

grammar GAXT;

program: expression* FINISH EOF;

expression: loop
    | store_macro
    | stack_push
    | stack_op
    | print
    | direct_stack_op
    | service
    | flow
    | call_macro
    | label;

label: SAVE
    | LOAD;

string: STRING_EDGE string_chars=string_char* STRING_EDGE;

expr_in_string: loop
    | store_macro
    | VARIABLE
    | CONSTANT
    | DIGIT
    | stack_op
    | print
    | direct_stack_op
    | service
    | flow
    | call_macro
    | TOKEN;

string_char: expr_in_string
    | formatter;

formatter: Fmt_variable
    | Fmt_space
    | Fmt_tab
    | Fmt_new_line
    | Fmt_finish
    | fmt_expr;

Fmt_variable: FORMAT VARIABLE;
Fmt_space: FORMAT ' ';
Fmt_tab: FORMAT '\t';
Fmt_new_line: (FORMAT '\n') | '\'\\n';
Fmt_finish: FORMAT '!';
fmt_expr: AMPERSAND expression* AMPERSAND;
AMPERSAND: '&';

flow: full_branch
    | short_branch
    | BREAK
    | CONTINUE;

full_branch: IF true_branch=expression* THEN false_branch=expression* ELSE;
short_branch: IF true_branch=expression* ELSE;

service: SWITCH;

direct_stack_op: ASSIGN
    | CLEAR
    | REVERSE
    | SHAVE;

print: PRINT_INT
    | PRINT_CHAR;

stack_op: stack_math
    | stack_logical;

stack_logical: NOR
    | LESS
    | EQUAL
    | GREATER;

stack_math: ADD
    | SUB
    | MULT
    | DIV
    | CAT;

stack_push: string
    | VARIABLE
    | CONSTANT
    | DIGIT;


loop: REPEAT expression* UNTIL;

macro: store_macro
    | call_macro;

store_macro: READ expression* WRITE;

call_macro: CALL;

FINISH: '!';


SPACE: [\r\n\t\u0020] -> skip;

VARIABLE: [a-z];
CONSTANT: [A-Z];
DIGIT: [0-9];

ADD: '+';
SUB: '-';
MULT: '*';
DIV: '/';
CAT: '_';

NOR: '`';
LESS: '<';
EQUAL: '=';
GREATER: '>';

PRINT_INT: '?';
PRINT_CHAR: '$';

ASSIGN: ':';
REVERSE: ';';
SHAVE: '~';
CLEAR: '%';

IF: '{';
THEN: '|';
ELSE: '}';
BREAK: '\\';
CONTINUE: '^';

READ: '(';
WRITE: ')';
CALL: '@';

REPEAT: '[';
UNTIL: ']';

STRING_EDGE: '"';
FORMAT: '\;

SAVE: '.';
LOAD: ',';

SWITCH: '#';

PROGRAM_END: EOF;

COMMENT: ~
    ( 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm'//variables a-m
    | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z'//variables n-z
    | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M'//constants A-M
    | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z'//constants N-Z
    | '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'//digits
    | '+' | '-' | '*' | '/' | '_'//math
    | '`' | '<' | '=' | '>'//logical
    | '?' | '$'//print
    | ':' | ';' | '~' | '%'//direct_stack
    | '{' | '|' | '}' | '\\' | '^'//flow
    | '(' | ')' | '@'//macro
    | '[' | ']'//loop
    | '.' | ','//label
    | '#' | '!'//service
    | '"' | '\'' | '&'//string
    ) -> skip;