Import text from the esowiki article, into the README.
Chris Pressey
2 years ago

1 | 1 | ======== |

2 | 2 | |

3 | 3 | This is the long-missing reference distribution for Carriage. |

4 | ||

5 | The following text was adapted from [the esowiki entry on Carriage](https://esolangs.org/wiki/Carriage), | |

6 | which is in the public domain. | |

7 | ||

8 | - - - - | |

9 | ||

10 | **Carriage** is a concatenative programming language designed by Chris Pressey | |

11 | in mid-November 2012. It is the result of trying to devise a "pure" | |

12 | concatenative language, i.e. one where the rule "concatenation = function | |

13 | composition" is taken to be strictly literal and universal (with no exceptions | |

14 | such as allowing nested quoted programs.) It falls short of | |

15 | that goal somewhat, but it has some mildly unusual properties, so it is presented | |

16 | here as an esoteric programming language. | |

17 | ||

18 | Note that this article describes Carriage version 0.1. It will not be version 1.0 | |

19 | until the author assures himself that there are no more instructions that are needed | |

20 | to write simple programs, and no fatal flaws. | |

21 | ||

22 | ### State | |

23 | ||

24 | The state of a Carriage program is a stack of unbounded size. Each element on | |

25 | the stack may be of one of three types: | |

26 | ||

27 | * an unbounded integer | |

28 | * a function which takes stacks to stacks | |

29 | * an instruction symbol | |

30 | ||

31 | ### Syntax | |

32 | ||

33 | Carriage defines nine instruction symbols. Each instruction symbol has an | |

34 | interpretation as a function which takes stacks to stacks. | |

35 | ||

36 | Any sequence of instructions (including an entire Carriage program) has two | |

37 | interpretations: | |

38 | ||

39 | * the *code interpretation*, which is the composition of the functions | |

40 | represented by each of the instruction symbols, in the manner of | |

41 | concatenative languages. For example, if the instruction symbol `A` | |

42 | has the interpretation f(s), and the instruction symbol `B` has the | |

43 | interpretation g(s), then the sequence `AB` has the interpretation | |

44 | g(f(s)). A sequence of length zero is taken to be the identity function. | |

45 | * the *data interpretation*, where the sequence of instruction symbols | |

46 | is taken to be a stack of instruction symbols, with the first symbol | |

47 | in the sequence at the bottom of the stack. A sequence of length | |

48 | zero is taken to be an empty stack. | |

49 | ||

50 | Whitespace has no meaning; the code interpretation of whitespace is the | |

51 | identity function, and the data interpretation does not introduce any | |

52 | instruction symbol onto the stack. However, attempting to take the code | |

53 | interpretation of any other symbol which is not defined by Carriage | |

54 | will cause the program to explode. | |

55 | ||

56 | ### Semantics | |

57 | ||

58 | Evaluation of a Carriage program can be summed up in one sentence: The | |

59 | function which the program represents under the code interpretation is | |

60 | applied to the stack which the program represents under the data interpretation. | |

61 | ||

62 | The result of executing a Carriage program is always either the stack to | |

63 | which the initial stack was mapped by the function, or an explosion. | |

64 | ||

65 | The instruction symbols defined by Carriage are listed below. The functions | |

66 | to which they are mapped by the interpretation function are described in | |

67 | operational terms for simplicity of explanation, but they are really | |

68 | functions which take stacks to stacks. | |

69 | ||

70 | * `1` ("one") pushes the integer 1 onto the stack. | |

71 | ||

72 | * `~` ("pick") pops an integer n off the stack, then copies the element which is n (zero-based) positions deep in the stack, and pushes that copy onto the stack. If n is negative or greater than the size of the stack or not an integer, the program explodes. If the element to be copied is an instruction symbol, the program explodes. | |

73 | ||

74 | * `\\` ("swap") pops an element a off the stack, then pops an element b off the stack, then pushes a back onto the stack, then pushes b back onto the stack. | |

75 | ||

76 | * `$` ("pop") pops an element off the stack and discards it. | |

77 | ||

78 | * `#` ("size") counts the number of elements into an integer k then pushes k onto the stack. | |

79 | ||

80 | * `+` ("add") pops an integer a off the stack, then pops an integer b off the stack, then pushes the sum (a + b) onto the stack. If either a or b is not an integer, the program explodes. | |

81 | ||

82 | * `-` ("sub") pops an integer a off the stack, then pops an integer b off the stack, then pushes the difference (b - a) onto the stack. If either a or b is not an integer, the program explodes. | |

83 | ||

84 | * `@` ("slice") pops an integer k off the stack, then pops an integer p off the stack. It then copies k instruction symbols from the stack into a sequence, starting at stack position p, zero-based, measured from the bottom of the stack. It then applies the code interpretation to this sequence to obtain a function. It then pushes this function onto the stack. If k or p is not an integer, or k is less than 0, or k is greater than 0 and either p or p+(k-1) refers to some position not inside the stack proper, or k is greater than 0 and any of the elements between p and p+(k-1) inclusive are not instruction symbols, the program explodes. | |

85 | ||

86 | * `!` ("apply") pops a function f off the stack and applies f to the stack to obtain a new stack. If f is not a function the program explodes. | |

87 | ||

88 | If the stack is empty any time an attempt is made to pop something off of it, the program explodes. | |

89 | ||

90 | ### Examples | |

91 | ||

92 | #### Basic Stack Manipulation | |

93 | ||

94 | As a simple example, the Carriage program | |

95 | ||

96 | 111-~+ | |

97 | ||

98 | will be turned into a function which we might spell out in, say, Erlang, as | |

99 | ||

100 | fun(S) -> add(pick(sub(one(one(one(S)))))) | |

101 | ||

102 | which will be applied to a stack | |

103 | ||

104 | (fun(S) -> add(pick(sub(one(one(one(S)))))))(["1","1","1","-","~","+"]) | |

105 | ||

106 | which could be stated more succinctly as | |

107 | ||

108 | add(pick(sub(one(one(one(["1","1","1","-","~","+"])))))) | |

109 | ||

110 | and whose evaluation could be depicted as | |

111 | ||

112 | add(pick(sub(one(one(["1","1","1","-","~","+",1]))))) | |

113 | add(pick(sub(one(["1","1","1","-","~","+",1,1])))) | |

114 | add(pick(sub(["1","1","1","-","~","+",1,1,1]))) | |

115 | add(pick(["1","1","1","-","~","+",1,0])) | |

116 | add(["1","1","1","-","~","+",1,1]) | |

117 | ||

118 | finally evaluating to the result stack | |

119 | ||

120 | ["1","1","1","-","~","+",2] | |

121 | ||

122 | (Note that stacks are being depicted bottom-to-top. I realize that's not how you'd typically | |

123 | implement them as lists in a functional language. Please just ignore that detail.) | |

124 | ||

125 | #### Function Creation and Application | |

126 | ||

127 | The previous example does not really demonstrate the power of the language. For that, | |

128 | we need to show how apply, and more importantly slice, work. Take the program | |

129 | ||

130 | 11+$11+111+@! | |

131 | ||

132 | The result stack of evaluating this program is | |

133 | ||

134 | ["1","1","+","$","1","1","+","1","1","1","+","@","!",3] | |

135 | ||

136 | The interpretation of the first four instruction symbols is just the | |

137 | identity function (create 2 then pop it, leaving the stack as it was.) | |

138 | ||

139 | The next seven instruction symbols leave [2,1,2] on the stack. | |

140 | ||

141 | The slice instruction then pops k = 2, p = 1, and retrieves a sequence of | |

142 | 2 instruction symbols from the stack starting from position 1 (that is, the element | |

143 | on top of the bottom element of the stack.) We can | |

144 | see that that sequence is `1+`. It then applies the code interpretation | |

145 | to that sequence to get a function (which pops a value off a stack and | |

146 | pushes the successor of that value back onto the stack) and it pushes | |

147 | this function onto the stack, which now looks like this: | |

148 | ||

149 | [...,"!",2,<fn>] | |

150 | ||

151 | Finally, the apply instruction pops the function, and applies it to the | |

152 | stack: the 2 is popped, 1 is added to it, and the result, 3, is pushed | |

153 | back on. | |

154 | ||

155 | ##### Note on "slice" | |

156 | ||

157 | We note that slice has the practical effect of ''delimiting'' some part | |

158 | of the program into a "subroutine" of sorts. However, there are some | |

159 | unusual consequences here. | |

160 | ||

161 | One is that these "subroutines" may overlap. | |

162 | ||

163 | Another is that these "subroutines" may be of variable size, as k need | |

164 | not be a constant. This may be used to affect a conditional of sorts. | |

165 | (k is allowed to be zero, in which case the slice is a zero-length | |

166 | sequence whose interpretation is the identity function.) | |

167 | ||

168 | Another is that, in a terminating and non-exploding program, every | |

169 | "subroutine" must be evaluated at least once -- because the entire | |

170 | program is turned into a single function (which is applied to the | |

171 | initial stack) and this single function contains all of its possible | |

172 | subroutines. | |

173 | ||

174 | In the above example, we anticipated this, and wrote our "subroutine" so that | |

175 | the first time it is evaluated, it has no effect. In fact, through | |

176 | lucky coincidence, if we remove it from the program, the second and | |

177 | third instruction symbols are still `1` and `+`, so we didn't need to | |

178 | go to such lengths. But this is in general not the case. | |

179 | ||

180 | Note also that the restriction on the pick instruction, that it not be | |

181 | able to pick instruction symbols from the stack, was introduced to | |

182 | prevent construction of new "subroutines" which did not exist in the | |

183 | original program. (Instruction symbols can still be popped and swapped, | |

184 | but these modifications to the "program on the stack" are quite minor.) | |

185 | ||

186 | Note also that, despite being a concatenative language, and thus supposedly | |

187 | mathematically pleasing, evaluating a "subfunction" with slice and apply | |

188 | has a distinctly machine-language feel to it (similar perhaps to [Aubergine][] | |

189 | and [Cfluviurrh][]), what with the absolute indexes into the stack and all. | |

190 | One small saving grace is that adding whitespace to the program does *not* | |

191 | change the indexes of the "subroutines". | |

192 | ||

193 | #### Infinite Loop | |

194 | ||

195 | 111-@11-~!$11111++++11-~@11-~! | |

196 | ||

197 | Explanation: | |

198 | ||

199 | 111-@ | |

200 | ||

201 | Push identity function (zero-length slice at position 1) onto the stack. | |

202 | ||

203 | 11-~! | |

204 | ||

205 | Duplicate object on the stack and apply it. (This is our subfunction.) | |

206 | ||

207 | $ | |

208 | ||

209 | Remove identity function from the stack. | |

210 | ||

211 | 11111++++11-~@ | |

212 | ||

213 | Push our subfunction (slice at position 5 with length 5) onto the stack. | |

214 | ||

215 | 11-~! | |

216 | ||

217 | Duplicate object on the stack and apply it. This applies our subfunction, with our subfunction already on the stack; so the subfunction will duplicate it, then apply its copy, ad infinitum. (A cleverer implementation might be able to use this last snippet of code ''as'' the subfunction.) | |

218 | ||

219 | ### See also | |

220 | ||

221 | * [the esowiki entry on Carriage](https://esolangs.org/wiki/Carriage) for more | |

222 | analysis and examples, including a Truth-machine, and open questions regarding | |

223 | the status of this language. | |

224 | * [Carriage.hs](https://esolangs.org/wiki/Carriage/Carriage.hs), a quick-and-dirty | |

225 | implementation in Haskell. (which is actually the reference implementation now, okay) | |

226 | * [Carriage.ml](https://esolangs.org/wiki/Carriage/Carriage.ml), an implementation in Ocaml. | |

227 | * [Equipage][], the "purely concatenative" language that | |

228 | Carriage might've been, had the author not been so concerned about quoting at the time. | |

229 | * [Wagon][], yet another "purely concatenative" language by the same author, trying to | |

230 | capture control flow in being "second-order concatenative", and not quite succeeding. | |

231 | ||

232 | [Aubergine]: https://catseye.tc/node/Aubergine | |

233 | [Cfluviurrh]: https://catseye.tc/node/Cfluviurrh | |

234 | [Equipage]: https://catseye.tc/node/Equipage | |

235 | [Wagon]: https://catseye.tc/node/Wagon |