PRG
PRG is a weirdlang created by User:DigitalDetective47 where the entire program is made of three‐letter tokens.
Program structure
The entire program is made of a sequence of tokens, each of which is a series of three capital letters. Each token must be separated from its neighbors by exactly one space. Trailing spaces are not allowed. Newlines between tokens are allowed, and any multiple of four spaces at the beginning of a line are ignored.
Compiler errors
The term “compiler error” in this context is used to mean that a syntactical error is detected in the program. For a compiler, a successful compilation should give an exit code of 0 (if applicable). A compiler error should cause SRC ERR
to be printed to standard error, and give an exit code of 1 (if applicable). An interpreter must check for compiler errors throughout the entirety of the source before beginning execution, and raise any error it may find. For an interpreter, a valid program should run without errors. A compiler error should result in SRC ERR
to be printed to standard error, and the program should not attempt to run. Below is a list of causes for a compiler error:
- Token of incorrect length
- Token containing invalid characters
- Line contains trailing spaces
- Tokens have multiple spaces between them
- Line starts with a number of spaces that is not a multiple of four
- A naming conflict is found.
- An undefined syntax is detected.
Data model
Basic types
There are six basic data types in PRG, which are documented in the table below:
Token | Description | Default value |
---|---|---|
BIN |
Raw binary data. 64 bits in length. | 0x0000000000000000 |
BOL |
Boolean value. | False |
CHR |
Character. Can represent any Unicode character. Line feed is the canonical newline character. | Null character |
DEC |
64‐bit floating‐point number. Uses wikipedia:IEEE 754 binary64. | 0.0 |
INT |
64‐bit signed integer. Uses wikipedia:Two's complement | 0 |
NUL |
Null value. Mainly used for functions that have no return value. | Null |
Type conversions are supported between all possible pairs of types; these behaviors are documented below:
To | |||||||
---|---|---|---|---|---|---|---|
BIN |
BOL |
CHR |
DEC |
INT |
NUL
| ||
From | BIN
|
Copy unchanged | 0x0000000000000000 → False Everything else → True |
Unicode character of value as integer modulo 1114111 | Decode binary data as float (big endian) | Decode binary data as integer (big endian) | Null |
BOL
|
False → 0x0000000000000000 True → 0x0000000000000001 |
Copy unchanged | False → Null character True → Start of Heading |
False → 0.0 True → 1.0 |
False → 0 True → 1 |
Null | |
CHR
|
Character's Unicode value in big endian | Null character → False Everything else → True |
Copy unchanged | Character's Unicode value as a float | Character's Unicode value | Null | |
DEC
|
Binary representation (big endian) | 0.0 → False Everything else → True |
Unicode character of value modulo 1114111 | Copy unchanged | Convert to an integer with the same numeric value. If the double is not an integer, it is truncated to be an integer. If the double is greater than 263−1, it is converted to 263−1. If it is less than −263, it is converted to −263. NaN is converted to 0. | Null | |
INT
|
Binary representation (big endian) | 0 → False Everything else → True |
Unicode character of value modulo 1114111 | Convert to a float of the same numeric value, using whatever rounding is default. | Copy unchanged | Null | |
NUL
|
0x0000000000000000 | False | Null character | 0.0 | 0 | Null |
If a function is passed a value of an incorrect type, it is automatically converted to the correct type.
Arrays
An array is denoted by the token ARR
. It is an immutable sequence of values of a single type. Arrays can be nested by specifying an array as the element type. When used as a type, it should be followed by the type of its elements. It can also be used to construct array literals, which happens automatically when the ARR
token is encountered when a value is expected. In this case, it reads off a sequence of values until an END
token is found outside of a value. An array literal's elements are automatically converted to the appropriate type for where it is used. It is worth noting that ARR END
is a valid expression that returns an empty array. Arrays cannot be longer than 263−1; attempting to insert a value into an array containing the maximum number of elements will cause the final element to be removed. Array literals with more than 263−1 will raise a compiler error. An array is empty by default. If an array is passed into a function where a single value is expected, or if a single value is passed where an array is expected, a compiler error occurs. Type conversions on arrays act on their elements.
Functions
Computations are performed using functions, which are called by writing the function's name followed by its parameters.
User‐defined functions
A function can be defined using the DEF
token. This is then followed by the return type, the function's name, a sequence of arguments, an END
token, the function's code, and another END
token. Each argument is specified by its type followed by its name. Functions cannot be defined within other functions. Within a function, the RET
token can be used to return a value. It is followed by the value to return, and is automatically converted to the return type of the function. If a function reaches the end of its execution without reaching a RET
, it will return the default value for its type. All function declarations must occur immediately after global variable declarations.
Built‐in functions
Signature | Description |
---|---|
DEC ADD DEC LFT DEC RGT |
Return LFT + RGT .
|
BIN AND BIN LFT BIN RGT |
Return a bitwise AND of LFT and RGT .
|
BIN BOR BIN LFT BIN RGT |
Return a bitwise OR of LFT and RGT .
|
DEC COS DEC VAL |
Return cos(val ) in radians.
|
DEC DIV DEC LFT DEC RGT |
Return LFT ÷ RGT .
|
NUL ERR ARR CHR TXT |
Print TXT to standard error.
|
BOL FLS |
Boolean constant False. |
ARR CHR GET |
Get a line of text from the user, and return it as an array of characters. |
DEC INF |
Float constant ∞. |
INT LEN ARR NUL INA |
Return the length of INA .
|
DEC LOG DEC BAS DEC VAL |
Return logBAS (VAL ).
|
DEC MAX DEC LFT DEC RGT |
Return whichever of LFT and RGT is larger.
|
DEC MIN DEC LFT DEC RGT |
Return whichever of LFT and RGT is smaller.
|
DEC MOD DEC LFT DEC RGT |
Return LFT mod RGT . Takes the sign of the second argument.
|
DEC MUL DEC LFT DEC RGT |
Return LFT × RGT .
|
DEC NAN |
Float constant NaN. |
INT ONE |
Integer constant 1. |
ARR DEC PIE |
Two‐element array containing float approximations of π and e. |
DEC POW DEC BAS DEC EXP |
Return BAS EXP .
|
NUL PUT ARR CHR TXT |
Print TXT to standard output.
|
INT RNG |
Return a random integer. |
BIN ROT BIN VAL INT BTS |
wikipedia:Circular shift VAL BTS bits to the left.
|
BIN SFT BIN VAL INT BTS |
wikipedia:Logical shift VAL BTS bits to the left.
|
DEC SIN DEC VAL |
Return sin(val ) in radians.
|
INT SIX |
Integer constant 6. |
DEC SUB DEC LFT DEC RGT |
Return LFT − RGT .
|
DEC TAN DEC VAL |
Return tan(val ) in radians.
|
INT TEN |
Integer constant 10. |
BOL TRU |
Boolean constant True. |
INT TWO |
Integer constant 2. |
BIN XOR BIN LFT BIN RGT |
Return a bitwise XOR of LFT and RGT .
|
Generic array functions
The following functions act on arrays with any type, inheriting the type of their elements. The element type is referenced here as ELM
. Note that ELM
can be an array type. Array indices are automatically wrapped to fit within the bounds of the list, and these functions have special behavior when applied to the empty array.
Signature | Description | Behavior on empty array |
---|---|---|
ELM ACC ARR ELM AIN INT IDX |
Return the element of AIN at index IDX . |
Return Null. |
ARR ELM INS ARR ELM AIN ELM VAL INT IDX |
Return a copy of AIN with VAL inserted at index IDX . |
Return a one element array containing VAL .
|
ARR ELM DEL ARR ELM AIN INT IDX |
Return a copy of AIN without the element at index IDX . |
Return an empty array. |
Variables
Data is stored in variables, which are also tokens. A variable is defined using the VAR
token, followed by the variable's type, followed by its name. All variable declarations must be at the top of the program, or at the top of their function. A variable can be accessed by its token. To set a variable's value, use the SET
token, followed by the variable name and then the value to assign.
Control flow
There are three primary control flow structures available. The simplest of the three is IFT
. It functions as an if block, taking a boolean parameter. The block extends to the matching END
token. This can also be augmented with an ELS
, which defines the else clause. If‐else blocks should only have a single END
. The next simplest is WHL
, which is a while loop. Its parameter is defined identically to IFT
, and is also terminated by an END
token. The most complex is FOR
, which takes two parameters. The first parameter is an array, and the second parameter is a variable name. The for loop iterates over the elements of the array, setting the loop variable to the current element. The loop variable must be defined, and array elements are converted to the loop variable's type. After the for loop completes, the loop variable retains the final element of the array.
List of reserved tokens
ACC
ADD
AND
ARR
BIN
BOL
BOR
CHR
COS
DEC
DEF
DEL
DIV
ELS
END
ERR
FLS
FOR
GET
IFT
INF
INS
INT
LEN
LOG
MAX
MIN
MOD
MUL
NAN
NUL
ONE
PIE
POW
PUT
RET
RNG
ROT
SET
SFT
SIN
SIX
SUB
TAN
TEN
TRU
TWO
VAR
WHL
XOR
Examples
Hello, world!
VAR CHR CHL VAR CHR CHO SET CHL SUB POW TEN TWO TEN SET CHO SUB POW ADD TEN ONE TWO TEN PUT ARR MUL ADD TEN TWO SIX ADD POW TEN TWO ONE CHL CHL CHO ADD MUL ADD SIX ONE SIX TWO POW TWO SUB SIX ONE ADD ADD CHL TEN ONE CHO SUB MUL ADD TEN TWO TEN SIX CHL POW TEN TWO ADD POW TWO SUB SIX ONE ONE END
Truth-machine
VAR ARR CHR UIN SET UIN GET IFT XOR ACC UIN FLS INT POW ADD SIX ONE TWO PUT UIN ELS WHL TRU PUT UIN END END
Cat program
WHL TRU PUT INS GET TEN SUB ONE TWO END
String to integer function
Doesn't work for numbers with a magnitude greater than 253.
DEF INT CTI ARR CHR VAL END VAR ARR CHR REM VAR DEC SUM VAR DEC SGN VAR DEC NEO SET SUM FAL SET NEO SUB ONE TWO IFT XOR ACC VAL FAL SUB SUB POW ADD SIX ONE TWO TWO TWO SET SGN ONE SET REM VAL ELS SET SGN NEO SET REM DEL VAL FAL END WHL LEN REM SET SUM ADD MUL SUM TEN ACC REM NEO SET REM DEL REM NEO END RET MUL SUM SGN END
Integer to string function
Doesn't work for numbers with a magnitude greater than 253.
DEF ARR CHR ITC INT VAL END VAR ARR CHR OUT VAR INT REM VAR BOL NEG VAR DEC CHZ SET CHZ SUB POW ADD SIX ONE TWO ONE IFT VAL IFT AND VAL POW TWO SUB POW TWO SIX ONE SET NEG TRU SET REM MUL VAL SUB ONE TWO ELS SET NEG FLS SET REM VAL END WHL REM SET OUT INS OUT ADD MOD REM TEN CHZ FAL SET REM DIV REM TEN END IFT NEG RET INS OUT SUB SUB POW ADD SIX ONE TWO TWO TWO FAL ELS RET OUT END ELS RET ARR CHZ END END END
Fibonacci sequence
VAR ARR DEC FIB VAR DEC CHZ VAR CHR SPC DEF ARR CHR ITC INT VAL END VAR ARR CHR OUT VAR INT REM VAR BOL NEG IFT VAL IFT AND VAL POW TWO SUB POW TWO SIX ONE SET NEG TRU SET REM MUL VAL SUB ONE TWO ELS SET NEG FLS SET REM VAL END WHL REM SET OUT INS OUT ADD MOD REM TEN CHZ FAL SET REM DIV REM TEN END IFT NEG RET INS OUT SUB SUB POW ADD SIX ONE TWO TWO TWO FAL ELS RET OUT END ELS RET ARR CHZ END END END SET CHZ SUB POW ADD SIX ONE TWO ONE SET SPC POW TWO SUB SIX ONE PUT ARR CHZ SPC ADD CHZ ONE END SET FIB ARR FAL ONE END WHL TRU SET FIB DEL INS FIB ADD ACC FIB FAL ACC FIB ONE TWO FAL PUT INS ITC ACC FIB ONE SPC FAL END
Ackermann function
DEF INT CTI ARR CHR VAL END VAR ARR CHR REM VAR DEC SUM VAR DEC SGN VAR DEC NEO SET SUM FAL SET NEO SUB ONE TWO IFT XOR ACC VAL FAL SUB SUB POW ADD SIX ONE TWO TWO TWO SET SGN ONE SET REM VAL ELS SET SGN NEO SET REM DEL VAL FAL END WHL LEN REM SET SUM ADD MUL SUM TEN ACC REM NEO SET REM DEL REM NEO END RET MUL SUM SGN END DEF ARR CHR ITC INT VAL END VAR ARR CHR OUT VAR INT REM VAR BOL NEG VAR DEC CHZ SET CHZ SUB POW ADD SIX ONE TWO ONE IFT VAL IFT AND VAL POW TWO SUB POW TWO SIX ONE SET NEG TRU SET REM MUL VAL SUB ONE TWO ELS SET NEG FLS SET REM VAL END WHL REM SET OUT INS OUT ADD MOD REM TEN CHZ FAL SET REM DIV REM TEN END IFT NEG RET INS OUT SUB SUB POW ADD SIX ONE TWO TWO TWO FAL ELS RET OUT END ELS RET ARR CHZ END END END DEF INT ACK INT MMM INT NNN END IFT MMM IFT NNN RET ACK SUB MMM ONE ACK MMM SUB NNN ONE ELS RET ACK SUB MMM ONE ONE END ELS RET ADD NNN ONE END END PUT ITC ACK CTI GET CTI GET
Factorial
VAR DEC IDX VAR DEC PRD DEF INT CTI ARR CHR VAL END VAR ARR CHR REM VAR DEC SUM VAR DEC SGN VAR DEC NEO SET SUM FAL SET NEO SUB ONE TWO IFT XOR ACC VAL FAL SUB SUB POW ADD SIX ONE TWO TWO TWO SET SGN ONE SET REM VAL ELS SET SGN NEO SET REM DEL VAL FAL END WHL LEN REM SET SUM ADD MUL SUM TEN ACC REM NEO SET REM DEL REM NEO END RET MUL SUM SGN END DEF ARR CHR ITC INT VAL END VAR ARR CHR OUT VAR INT REM VAR BOL NEG VAR DEC CHZ SET CHZ SUB POW ADD SIX ONE TWO ONE IFT VAL IFT AND VAL POW TWO SUB POW TWO SIX ONE SET NEG TRU SET REM MUL VAL SUB ONE TWO ELS SET NEG FLS SET REM VAL END WHL REM SET OUT INS OUT ADD MOD REM TEN CHZ FAL SET REM DIV REM TEN END IFT NEG RET INS OUT SUB SUB POW ADD SIX ONE TWO TWO TWO FAL ELS RET OUT END ELS RET ARR CHZ END END END SET IDX CTI GET SET PRD ONE WHL IDX SET PRD MUL PRD IDX SET IDX SUB IDX ONE END PUT ITC PRD