Captive
Paradigm(s) | imperative |
---|---|
Designed by | Daniel Temkin |
Appeared in | 2024 |
Memory system | stack-based |
Computational class | Turing complete |
Reference implementation | Captive |
File extension(s) | .txt |
Captive is a stack-based language inspired by the Oulipian constraint set "Prisoner's Constraint." While it can be programmed intentionally, it is designed for accidental programs. Any text will run as a Captive program.
Concept
The Prisoner's Constraint is a lipogram where letters with ascenders or descenders are avoided, as if to squeeze text into lines as short as possible (perhaps as if one were a prisoner with limited paper). In Captive, only letters with ascenders or descenders (e.g. 'l' or 'q') have programmatic meaning. Once a bare Captive program is written, it can be enhanced with "short" letters to create a coherent text, a similar lipogrammatic writing exercise to the original Prisoner's Constraint.
Language Overview
Captive is a stack-based language. These letters correspond to commands. All other characters are ignored.
Captive is designed to be very forgiving. Unterminated loops are legal, as are unterminated ints -- both close at end of program. If an end
command (which indicates the end of a block) is hit with no block to close, it is ignored. Trivial infinite loops are escaped. However, currently only the most trivial infinite loops are detected: those where the program state (the stack) is exactly the same as in its previous iteration.
Command List
1st | 2nd | cmd | followed by | note |
---|---|---|---|---|
l
|
push | int to push to the stack | ||
p
|
k
|
pop | index of item to pop | |
p
|
h
|
not | 0 and 1 are interchanged, for all other values, sign is flipped | |
p
|
t
|
if | ||
p
|
d
|
end | indicates end of block | |
t
|
t
|
emit | ||
t
|
h
|
rot | int for how many to rotate | |
f
|
sub | |||
b
|
mul | |||
d
|
d
|
add | ||
d
|
g
|
> | replaces top two items in stack with 1 or 0 for true/false | |
k
|
div | |||
q
|
mod | |||
g
|
while | |||
j
|
== | replaces top two items in stack with 1 or 0 for true/false | ||
h
|
dup | |||
y
|
end | indicates end of block |
Constants
Following any of the three commands that require a constant, the next characters are read according to the list below. Consts are terminated with a y
, or end of file. Each letter adds a value, unless followed by a "subtract next value" indicator. Redundant subtracts have no effect.
ltr | |
---|---|
q
|
subtract next value |
k
|
subtract next value |
f
|
subtract next value |
b
|
subtract next value |
d
|
64 |
g
|
32 |
j
|
24 |
h
|
16 |
p
|
8 |
l
|
4 |
t
|
1 |
y
|
end of const |
Example Programs
In Captive, every text, regardless of its content, is a program. If it has zero letters corresponding to commands (i.e. if it is written in Prisoner’s Constraint), then it is an empty program, producing nothing. Most texts over a line or two will do something. If they don't produce output, they at least have internal activity: loading data and manipulating it in some way.
Hi
This program outputs "Hi":
I emailed again, open to yield payment on that tax.
As does this one:
Including crew, part owners, many inland reapers, we see systematic visits too.
Here they are stripped of non-significant characters:
ldgptyldpytttt
Moby Dick
The first sentence of Moby Dick is Call me Ishmael.
of which llhl
is a Captive program. This program has no output but loads 24 to the stack.
Here is the first paragraph of Moby Dick:
Call me Ishmael. Some years ago—never mind how long precisely—having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world. It is a way I have of driving off the spleen and regulating the circulation. Whenever I find myself growing grim about the mouth; whenever it is a damp, drizzly November in my soul; whenever I find myself involuntarily pausing before coffin warehouses, and bringing up the rear of every funeral I meet; and especially whenever my hypos get such an upper hand of me, that it requires a strong moral principle to prevent me from deliberately stepping into the street, and methodically knocking people's hats off—then, I account it high time to get to sea as soon as I can. This is my substitute for pistol and ball. With a philosophical flourish Cato throws himself upon his sword; I quietly take to the ship. There is nothing surprising in this. If they but knew it, almost all men in their degree, some time or other, cherish very nearly the same feelings towards the ocean with me.
Stripped to the significant characters:
llhlgdhlgplhglttlpdthgptlttththghtldlbtlttldthtptthldthdgthpldgltgthlthdlgggbtththhtdpdlblhdlltlpgbhdbg gpthltdpllhhpgthpphdthttqtglppltptdlbtltppgtthttdthdllkkgpplhtthtthghttgtthbtttptldbllthphlphllhtthhlphd qtltktthhphthgpgththbtktltllthdgtthhhlthlgtdthth
When run as Captive, it has this output:
QQQ,Q,ᦡ�ᦡ,ᦡㄨQQ
Alternatives
While Captive has a set lexicon, other lexicons can be created that will similarly result in unintentional programs.
EULA Captive
Here is a variation that replaces each of the letters of Captive with a word used commonly in EULAs, thus turning these agreements into working programs.
keyword | cmd |
---|---|
content /property
|
push |
permission
|
pop |
rights
|
not |
intellectual / conduct
|
if |
limit / limitation
|
end |
liable / liability
|
emit |
license / appreciate
|
rot |
conduct / suggestion
|
sub |
breach / breached
|
mul |
product / products
|
add |
terms / dispute
|
> |
portion / warrenty
|
div |
amendment
|
mod |
grant / granted
|
while |
expressly / disclaim
|
== |
policy / policies
|
dup |
recommend
|
end |
To Do
- There is no reason this need work for Latin characters only. Expand to include lower-case letters in other character sets
- Add detection for other types of trivial infinite loops (e.g. repeatedly adding the same value to the stack)
- What would a quine (other than the null-quine) look like in this language?