Powerlist

From Esolang
Jump to navigation Jump to search

Powerlist is an esoteric programming language created by User:CodingBat in April 2014. Designed to compute high level arithmetic operations (such as powers or logs) while keeping the syntax minimalistic. It uses a single data structure type, but provides an extensive number of overridable operators.

Header

Any Powerlist program must have a header which defines the structure of the only variable type allowed. Each header line is a characteristic of the variable, and is enclosed in dollar ($) symbols.

Bit structure line

The first line of the header defines the use of each bit of the type, if the total of bits defined is not a multiple of 8, the computer will assign the minimum byte number needed, making no use of the undefined bits.

Bit usage syntax

The line is made but contatenating the following characters:

Character Meaning Explanation
S Signum bit A type which lacks this bit will be unsigned, if more than one is present, they will all have the same value.
e exponent bit Define a bit in the exponent part of a floating-point type. The type will be fixed-point if none is present.
E exponent half-byte Syntaxic sugar for eeee
d decimal bit Define a bit in the decimal part of a fixed-point type. The type will be integer if none is present.
D decimal half-byte Syntaxic sugar for dddd
m mantissa bit If floating-point type, will define the mantissa part. If fixed-point type, will define the integer part.
M mantissa half-byte Syntaxic sugar for mmmm

Character encoding syntax

The last character of the line defines the character encoding format the program will use. It is also the format the source file will be interpreted as using.

Character Character encoding
A 7-bit ASCII
E 8-bit extended ASCII
3 UTF-8
4 UTF-16
5 UTF-32
J JIS

Example: Possible implementation of an ASCII type

$SmmmMA$

Example: Possible implementation of classical single-precision floating-point type

$SEEMmMmMmMM3$

Special behaviours lines

The other lines of the header override the default behaviour of a give type. This allows things like NaN, INF, -INF values.

Value selection syntax

Each line needs one or more values to be selected, here's the syntax to select a value:

Character(s) Meaning
0 Bit of value zero
1 Bit of value one
? Bit of either value
: Equivalant to the preceding character, repeated for the rest of the bits
*x* Equivalent to the preceding character, repeated x times (x being a integer litteral in base 10)
- Whatever value the bit used to have before an arithmetic operation (only for the third value selection in operatop, definition lines (see below))

Example: Value with all bit at 1

1:

Example: Value with the first bit being either 1 or 0, the ten next bits at 1 then all others at 0

?1*10*0:

String redefinition syntax

String redefinition lines will affect a special displaying behaviour for the given value that isn't the default. They are written by typing a value then an operator, then a string of characters between quotation marks. The operators are:

Operator Effect
P Rededines the way the "Print" operation will print the value on the screen (see Print for more information)
D Rededines the way the "Display" operation will print the value on the screen (see Display for more information)
S Rededines the way the "Scan" operation will parse the value inputted (see Scan for more information)
T Rededines the way the "Type" operation will parse the value inputted (see Type for more information)
s Rededines the way the "ScanNumber" operation will parse the value inputted (see ScanNumber for more information)

Example: A value with all bits at 1 but the first will be printed as "+INF", and a value with all bits at 1 will be printe as "-INF"

$01:P"+INF"$
$1:P"-INF"$

Operation redefinition syntax

Operation definition lines will change the effect a given value will result once affected to an arithmetic operation. They take three value selections, the two first separated by the arithmetic operator, the second and the third separated by the equality symbol (=). Operators availables for redefinition are:

Operator Name
* Power (a*n = nth power of a)
/ Root (a/n = nth root of a)
\ Logarithm (a\n = logarithm base n of a)

Example: Sets "zero to the power of zero" to return zero (default behaviour returns 1)

$0:*0:=0:$

Example: Sets the logarithm of a negative number to return -0 (assuming the variable type's first bit being a signum, and not being floating-point)

$1?:\?:=10:$

Comments

Any text between parenthesis (()) is interpreted as comments and thus ignored.

Lists

The defined variable type is only used internally by the Powerlist program. The programmer must use another data structure: the list. A list contains values, but unlike a C array, you can't access an arbitrary element of it. You can only access the first and the last item. Lists are the only kind of data structure provided by Powerlist. Lists names can be any characters allowed by the defined character encoding (including digits), with the exeption of $, ~, >, <, ?, :, +, !, {, }, _, @, ^, [, ], =, ;, ( and ) It is also not allowed to name a list "..." (three full stops).

Operators

Here are the operators available to manipulate lists (applied on a example list named List):

Operation syntax Name Overridable? Description Notes
~ List ~ Creation No Instanciates an empty list named List Using a non-created list or applying the Creation operator on an already created list causes the program to end
> List Head Push Yes Inserts a value in front of the list
List < Tail Push Yes Inserts a value in end of the list
List ? Length Yes Returns the length of the list
: List Head Clone Yes Head-pushes a copy of the first value of the list No effect if the list is empty
List : Tail Clone Yes Tail-pushes a copy of the last value of the list No effect if the list is empty
< List Head Pop Yes Removes and returns the first value of the list Returns an empty list if the list is empty
List > Tail Pop Yes Removes and returns the last value of the list Returns an empty list if the list is empty
<+ List Global Head Pop Yes Head-pops all values of the list Default implementation makes use of the Head Pop and the Length operators
List +> Global Tail Pop Yes Tail-pops all values of the list Default implementation makes use of the Tail Pop and the Length operators
< Rep ! List Repeated Head Pop Yes Head-pops Rep times Default implementation makes use of the Head Pop operator
List ! Rep > Repeated Tail Pop Yes Tail-pops Rep times Default implementation makes use of the Tail Pop operator
List { code } Length Loop Yes Executes the Powerlist code between brackets until the list's length is 0 Default implementation makes use of the Length operator
_ List _ Deletion No Free the variable name Variable names take up memory until freed
~ Child @ List ~ Metacopy No Instanciates an new list (named Child in this example) with the same operator overrides as the parent list Does not copy the values stored in the parent list
List ^ Default Form No List with all operators at default implementation (before any override). Useful for override
List @ Parent Form No List with all operators at parent implementation (just after the Metacopy). Useful for override, comparable to super in Java. For lists instanciated with the Creation operator, same effect as List^

Pop operators that feed into another list will automaticly push in it from the fitting side.

Anonymous lists

For faster creation of lists, Powerlist provides a syntax to create anonymous lists. Anonymous lists are deleted once the program stops using it. An anonymous list is created by enclosing it's content between square brackets ([]), and separating each element with a semicolon (;).

Example: This code creates a list named List and adds to it the values 1, 2, 3, 4, in that order.

~List~
List <+ [1 ; 2 ; 3 ; 4]

For anonymous lists the Head Pop and Tail Pop operators behave like the Global Head Pop and the Global Tail Pop respectively, as a syntaxic sugar. So List<[1, 2] does the same as List<+[1, 2]

String lists

A special kind of anonymous list allows to create string literals. String lists a created by enclosing the desired string of characters in quotation marks ("")

Example: This code creates a list named List and adds to it the numeric values for each character of the string "List".

~List~
List < "List"

This code has the same effect as

~List~
List < [ 76 ; 105 ; 115 ; 116 ]

Literal lists

Powerlist provides built-in lists which provide a single value. These lists have valid names according to the list naming specifications of the language, so they can be freely Created, Deleted, Metacopied and have their operators overriden, though it is frown upon to do so as they provide basic values needed by most programs. The Push and Clone operations has no effect on them, their Length is 0, the Pop and Global Pop operations both return a single instance of their value (though the Repeated Pop operations do provide the requested number of instances), and they are automaticly deleted when the program ends (no need to apply Delete on them). As a syntaxic sugar, the literal list name without any operator is interpreted as a Pop operation in anonymous lists declaration (see above).

Any number literal is interpreted by the program as a litteral list that returns that number. Litteral list are just the number in base 10, with the comma (,) and full stop (.) both valid as decimal mark.

Example: This code push 42 in a list named List.

List < 42

Other literal lists are *, /, \, ', &, |, ` and # (See arithmetic operations for more information)

Operators override

Most Powerlist list operators are overridable to alter the functionnalities of a given list. There is no "class" in Powerlist, each list overrides its operators independantly.

To override an operator, the syntax is to type the operator call, followed by the equal symbol (=), then the new code for the operator, then close with another equal symbol. Inside the override's scope, a few named lists are provided to access some value otherwise unreachable.

Name Operators Description
Self All The calling list, anything done to this list is also done to the list the operator is called on
In Push and Repeated Pop operators For Push operators: The input list, all the values the operator is trying to input are in this list

For Repeated Pop operators: A list with only one value: the number of times to repeat

Out Pop and Length operators The output list, everything the operator will output have be be in it. For the Length operator, only the first element will be actually outputted.

Example: This code overrides the Tail Push operator to push the given value twice.

List< = 
       Self<:In
       Self<In
      =

The Length Loop operator override requieres a special syntax:

List{} =
        (Code executed before the length check and first loop)
        {...
            (Code executed on loop start, before the code in the brackets at operator call is executed)
            ...
            (Code executed on loop start, after the code in the brackets at operator call is executed and just before the next length check)
        ...}
        (Code executed after the last loop, when the list's length is 0)
       =

Arithmetic operations

Arithmetic operations in Powerlist are not part of the syntax, instead a built-in list named "Computer" is provided for that purpose. Like other built-in functions, it can be overriden by any way, but this is frown upon because their behaviour is internal and no way is provided to copy their original behaviour.

The Computer list only compute one binary arithmetic operation at a time. When prompted with the Pop operator, the Computer list will take the 3 first values (or the 3 last, depending on which side the Pop operator is on) it holds and process the first and the third through on operation specified by the second. The value for each operation available is not set in the specification, and may change depending on implementation. Powerlist provides literal lists for the operations (*, /, \, ', &, |, ` and #). The # is the only unary operation, the Computer list only processed 2 elements instead of 3 for the others.

The operations available are:

Literal list Operation Description
* Power <Computer<[ a ; * ; n ] Returns a raised to its nth power
/ Root <Computer<[ a ; / ; n ] Returns the nth root of a
\ Logarithm <Computer<[ a ; \ ; b ] Returns the logarithm base a of b
' Equality <Computer<[ a ; ' ; b ] Returns ' if a equals b, 0 if not
& Bitwise And <Computer<[ a ; & ; b ] Returns a AND b
| Bitwise Or <Computer<[ a ; | ; b ] Returns a OR b
` Bitwise Xor <Computer<[ a ; ` ; b ] Returns a XOR b
# Signum <Computer<[ a ; ` ] Return the signum of a (1 if negative, 0 if positive)

As you can see, Powerlist doesn't implement First level (addition, subtraction) and Second level (multiplication, division) arithmetic operations. Those have been internalized to reduce the language's complexity. Plus, high-level programmers using this language obviously don't need such mundane operations anyway, and even in the rare event of any of those operations being needed, it is well known that the superior operations are able to implement inferior ones. The rest of this chapter will be dedicated to prove that claim.

Addition implementation

$SeeeEEEMMMMMMMMMMMMMMMMMMMMMMMMMMMM$
~Add~
<Add =
      Out<Computer<[2 ; * ; <Self^]
      Out<Computer<[2 ; * ; <Out]
      Out<Computer<[2 ; * ; <Self^]
      Out<Computer<[<Out ; * ; <Out]
      Out<+Computer<[2 ; \ ; <:Out ; 2 ; \ ; <Out]
     =
Add> =
      [Self^> ; * ; 2]>Computer>Out
      [Out> ; * ; 2]>Computer>Out
      [Self^> ; * ; 2]>Computer>Out
      [Out> ; * ; Out>]>Computer>Out
      [Out:> ; \ ; 2 ; Out> ; \ ; 2]>Computer+>Out
     =
Display<Add<[3 ; 2] (Print "5" on the screen)

Subtraction implementation

$SeeeEEEMMMMMMMMMMMMMMMMMMMMMMMMMMMM$
~Sub~
<Sub =
      Out<Computer<[2 ; * ; <Self^]
      Out<Computer<[2 ; * ; <Out]
      Out<Computer<[2 ; * ; <Self^]
      Out<Computer<[Out> ; * ; -1]
      Out<Computer<[2 ; \ ; Out>]
      Out<Computer<[2 ; * ; Out>]
      Out<Computer<[<Out ; * ; <Out]
      Out<+Computer<[2 ; \ ; <:Out ; 2 ; \ ; <Out]
     =
Sub> =
      [Self^> ; * ; 2]>Computer>Out
      [Out> ; * ; 2]>Computer>Out
      [Self^> ; * ; 2]>Computer>Out
      [-1 ; * ; <Out]>Computer>Out
      [<Out ; \ ; 2]>Computer>Out 
      [<Out ; * ; 2]>Computer>Out
      [Out> ; * ; Out>]>Computer>Out
      [Out:> ; \ ; 2 ; Out> ; \ ; 2]>Computer+>Out
     =
Display<Sub<[3 ; 2] (Print "1" on the screen)

Multiplication implementation

$SeeeEEEMMMMMMMMMMMMMMMMMMMMMMMMMMMM$
~Mul~
<Mul =
      Out<Computer<[2 ; * ; <Self^]
      Out<Computer<[<Out ; * ; <Self^]
      Out<Computer<[2 ; \ ; <Out]
     =
Mul> =
      [Self^> ; * ; 2]>Computer>Out
      [Self^> ; * ; Out>]>Computer>Out
      [Out> ; \ ; 2]>Computer>Out
     =
Display<Mul<[3 ; 2] (Print "6" on the screen)

Division implementation

$SeeeEEEMMMMMMMMMMMMMMMMMMMMMMMMMMMM$
~Div~
<Div =
      Out<Computer<[2 ; * ; <Self^]
      Out<Computer<[<Self^ ; * ; -1]
      Out<Computer<[<Out ; * ; <Out]
      Out<Computer<[2 ; \ ; <Out]
     =
Div> =
      [Self^> ; * ; 2]>Computer>Out
      [-1 ; * ; Self^>]>Computer>Out
      [Out> ; * ; Out>]>Computer>Out
      [Out> ; \ ; 2]>Computer>Out
     =
Display<Mul<[3 ; 2] (Print "1.5" on the screen)

Other built-in lists

Name Description Notes
Bin Safely delete any value pushed in it Clone operators do nothing, Pop operators return an empty list, Length is always 0
Error Print any string pushed in it to the standard error output Clone operators do nothing, Pop operators return an empty list, Length is always 0
Print Print any string pushed in it to the screen Clone operators do nothing, Pop operators return an empty list, Length is always 0
Display Print any value pushed in it as a number base 10 on the screen Clone operators do nothing, Pop operators return an empty list, Length is always 0
Scan Retrieve a single character from the standard input when popped, more recent character being at the front of the list Push operators do nothing
Type When popped etrieve all character from the standard input until a line break is encountered, more recent character being at the front of the list If end is reached an no line break is found, wait until it gets one Push operators do nothing
ScanNumber Retrieve a number base 10 from the standard input when popped, more recent character being at the front of the list. If the input stream doesn't start with a number, returns an empty list Push operators do nothing
Format Pops a character list fitting the pushed in value Clone operators affect the pushed in value
Number Pops a value fitting the pushed in character string Clone operators affect the pushed in value
Kill Any operator force-closes the program
ENV Contains a list of environment values Clone and Push operators do nothing, Pop operators clones values before return them

Turing-compleness proof

The following program emulates the Brainfuck program +[-<,.>]:

$MMA$
~Memory~
Memory<<1024!0 (creates a 1024-cell memory tape)
(start of program)

(+)
[<Memory ; * ; 2]>Computer>Memory
[<Memory ; * ; 4]>Computer>Memory
[<Memory ; \ ; 2]>Computer>Memory
[<Memory ; \ ; 2]>Computer>Memory

([)
~Loop1~
    (Create an empty list, each brainfuck bracket pair needs its own list)
Bin< <:Loop1 !Loop1<Computer<[<:Memory ; ' ; 0]
    (If the memory cell is 0, the loop will have 1 element, if not, the loop will be empty)
Loop1{
    (If the list is not empty, enters the brackets, if not, skip the brackets) 

(-)
[<Memory ; * ; 2]>Computer>Memory
[2 ; / ; 2]>Computer>Memory
[<Memory ; * ; <Memory]>Computer>Memory
[<Memory ; \ ; 2]>Computer>Memory
[<Memory ; \ ; 2]>Computer>Memory

(<)
Memory>Memory

(,)
Bin<Memory
Scan>Memory

(.)
Print<:Memory

(>)
Memory<Memory

(])
Bin<+Loop1
    (Empty the list)
Bin< <:Loop1 !Loop1<Computer<[<:Memory ; ' ; 0]
    (If the memory cell is 0, the loop will have 1 element, if not, the loop will be empty)
} _Loop1_
(If the list is not empty, restart at the fitting bracket, if not, free the Loop1 list and go on)

(end of program)
_Memory_ (free the memory list)

Example programs

Hello world!

$MMA$
Print<"Hello world!"

cat

$MMA$
Scan { Print<[Scan>] }

Truth machine

$MMA$
~Out~
Bin < <:Out ! Out < Computer < [0 ; ' ; Scan>]
Out { Display<1 }
Display<0
_Out_