ComeFrom2
Jump to navigation
Jump to search
ComeFrom 2 is a language that explores the implications of the only flow control in a program being 'come from x' and 'conditionally, come from x'. It is the successor to ComeFrom. The rest of the language is quite simple, consisting only of a handful of functions and two stacks. It features advanced debugging capabilities, actually telling you where the error was and what caused it.
ComeFrom is an esoteric programming language designed by David Roberts in 2012. He revisited it in 2015 using Javascript after Cube Trains, which housed with its original implementation, was found to be an esoteric game.
Running
A web IDE is available at the CFL2 github page. Be sure to check out the manual there!
Syntax
+, -, *, /, % |
Infix operators. Add, subtract, multiply, divide, or take the modulo of the next number to be pushed to the stack with the number currently on the stack. Only addition works with strings, concatenating them. |
<, =, > |
Infix operators. Compare the number currently on the stack with the next to be put on the stack, returning 1 if the assertion was true and 0 if not. |
^ |
Infix operator. Raise the number on the stack to the power of the next number to be put on the stack. |
calljs |
Call a javascript function. For example, take the stack ['Enter your password:', 1, 'prompt<window']. When calljs is executed it will prompt the user to enter their password and put the result on the stack. The newest value on the stack is the name of the function to call. eg; 'prompt<window' calls Javascript's window.prompt function. The number indicates the arity of the function, and then pops that many variables off the stack to feed to the function. A value which is not a number, boolean, or string is interpreted as nil. See also: readjs |
comefrom |
Come from a line number to this line. |
comefromif |
Comes from a line number to this line, IF the top value on the stack is truthy. The value is not removed from stack. Truthy values are anything other than #0, $, nul, or the empty stack. |
depth |
Puts the size of the stack prior to the instruction to the stack. |
drop |
Removes the first value on the stack. |
dup |
Takes the first value on the stack and adds it to the stack twice, duplicating it. |
log |
Pop a value to stack, and print it to the javascript console. See also: print, println |
nop |
Take no action. Very easy to implement! |
not |
Logically negate the first value on the stack. (In CFL, truthy values are anything other than #0, $, or nul.) |
num |
Cast the top value on the stack to a number. See also: str |
print |
Print and remove the top value of the stack. See also: log, println |
println |
Print and remove the top value of the stack. Advance the cursor to a new line. See also: log, print |
reach |
Reach back in the stack, read a value, and push the read value to the stack. Does not remove the read value. 10 #5, 20 #1, 30 reach is equivalent to 10 #5, 20 dup. |
readjs |
Read a javascript value as given by the js path string on top of the stack. For example, to read Math.PI, we'd push $PI<Math to the stack and then invoke readjs. See also: calljs |
str |
Cast the top value on the stack to a string. See also: num |
swap |
Reverse the position of the top two values on the stack. |
Counting to 10
With annotated source!
Line Number | Instruction | Annotation |
---|---|---|
10 |
#0 |
Push zero to the stack. This is the number we start counting from. |
20 |
comefrom 120 |
Come from line 120. This kicks off the next increment loop. |
30 |
+ |
|
40 |
#1 |
Increment by one. |
50 |
dup |
|
55 |
dup |
Duplicate the incremented number twice. There are now three versions of what we just incremented, instead of one. |
60 |
< |
|
70 |
#10 |
The first version is compared with 10, resulting in a boolean value on stack. Line 100 comes from here if the duplicated value is less than 10, continuing the loop. (Line 90 would have lead to line 130 otherwise, skipping the comefrom on line 20.) |
80 |
drop |
Drop the comparison, no longer important as we've exited the loop. |
100 |
comefromif 75 |
Jump over the line 130 comefrom and the line 80 drop to continue the loop. |
120 |
drop |
Drop the comparison, no longer important as we're continuing the loop. |
130 |
comefrom 90 |
Come from line 90 to skip the line 20 comefrom on line 120, if the line 100 comefromif didn't happen. |
145 |
drop |
Drop the second version of the number, which would otherwise have been incremented on the next loop. This leaves us with a clean stack listing #1 to #10. |
99 Bottles of Beer
0 !99 Bottles v1.0.0 10 #99 19 nul 20 comefromif 205 21 drop 30 dup 40 str 45 dup 50 + 60 $ bottles of beer on the wall,, 70 println 80 + 90 $ bottles of beer.\nTake one down,, pass it around,, 100 println 120 - 130 #1 140 dup 145 swap 150 str 155 + 160 $ bottles of beer on the wall.\n 170 println 180 dup 190 > 200 #2 215 $1 bottle of beer on the wall,,\n1 bottle of beer. 214 $Take one down,, pass it around,,\nno more bottles of beer on the wall.\n 213 $No more bottles of beer on the wall,,\nno more bottles of beer. 212 $Go to the store,, buy some more,, 211 $99 bottles of beer on the wall.\n 210 $... oh fine I'll stop now. 218 !loop until we've printed the entire stack we just filled 219 comefromif 220 220 println