PRG

From Esolang
Jump to navigation Jump to search

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:

Data types
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:

Type conversions
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 BASEXP.
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 LFTRGT.
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.

Generic array functions
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