PolyStack

PolyStack is an esoteric programming language and Domain-Specific Language designed to serve as the Type System for other programming languages, particularly stack-based ones. It aims to be a powerful type system for stack- and deque- based languages, itself being deque-based. It aims to be so powerful, in fact, that it is hoped to be Turing-complete in its final form.

Syntax
PolyStack is similar to any other concatenative programming language, having an RPN format for its instructions. In order to thoroughly integrate with W'', the language for which it was primarily defined, it does some fiddling with the logical syntax; however, an alternative standalone syntax is also available.

As a stack-based language, the commands are a series of instructions separated by spaces. In the default version, quotes delimit a quoted string, which can be pushed onto a secondary stack, whereas in the alternative version, there are no quotes. All other instructions are commands; either types (which just push their type onto the stack) or manipulation commands (which actually do stuff).

The primary stack can hold three things: Scalar Types, Type Classes, and Compound Types. Scalar Types are the types of scalar data; for example,  or   or. Type classes represent sets of types, such as. Compound types are full type expressions; the type of a function in Haskell. A Compound Type might be  or. Unlike Haskell types, which return exactly one value (which may be a collection, but is one value nonetheless) from a single list of inputs, PolyStack types accept two lists of inputs and two lists of outputs, representing the values POPed and the values PUSHed. This means that PolyStack types can return multiple values, though this can be constrained in implementations.

An example of a PolyStack program is: "x" pmt Ord <-> constrain <| ?<

Which always returns True through a convoluted process.

Type Expressions
Type Expressions in PolyStack are based off of Forth's type expressions. They are of the following form: (Tc1 x, Tc2 y, Tc3 z) => (a b..c d -- e f..g h)

This tells the computer the following:
 * The polymorphic variables x, y, and z must belong to the typeclass Tc1, Tc2, and Tc3, respectively
 * The arguments of types a and b are POPed from the front of the deque (first b, then a)
 * The arguments of types c and d are POPed from the back of the deque (first d, then c)
 * The results of types e and f are PUSHed onto the front of the deque
 * The results of types g and h are PUSHed onto the back of the deque

Argument types can be either polymorphic (lowercase) or static (capitalized). When padded in square brackets, they form a list; in curly brackets forms a set, and a comma-separated list in parenthesis forms a tuple. A type of the form  is a dict mapping elements of type a to type b, and if the curlies are replaced with square brackets it forms an ordered dict of the same type. Finally, an argument can be another type expression padded in parenthesis.

Builtin Types, Type Classes, etc.
A list of the Builtin Type Classes is:

The builtin types, and the classes they belong to, are:

Commands
This section covers the commands available to the user in PolyStack.