ComeFrom is a language made by David Roberts. It is also known as the ComeFrom Language, or CFL for short. Its notable feature is that the only flow-control constructs are comefroms and conditional comefroms. (A comefrom is the opposite of a goto.) In addition, the only storage it has is a variable stack which doubles as returned output. However, you may print variables while the program is running. In event of catastrophic failure, the language only tells why it has crashed, not why your program has crashed. It has one error message to help, but due to implementation details this is impossible to trigger.
This language has been obsoleted by ComeFrom2, which introduces some breaking changes and a nicer syntax. ComeFrom 2 is available through a web-based IDE, at http://ddr0.github.io/side%20projects/cfl/.
ComeFrom was developed in late 2012 in about a day using the scripting language of the game Cube Trains (from the Wayback Machine; retrieved on 14 December 2012), which was made for Frogatto. The interpreter is downloadable from GitHub. To run, compile the project from GitHub, launch the game with
--module=cube_trains, press ctrl-d for the interactive debug console, and then you can paste in the examples below.
All operators work on one stack. Operators themselves may be stacked. Numbers are denoted by a
# in front of them, and everything else is a string if it's not an operator listed below. Each element of the code must be preceeded by a line-number, and all elements and line-numbers must be separated by one or more spaces. (Tabs and hard-returns get removed on running, not replaced with spaces.) The program is run in order of line-number, not in order of appearance.
||Add the previous datum and the next datum.|
||Interpret the next two results, and anything they might interpret.|
|Prints the next datum.|
||Comparison between the previous and next data.|
||Duplicate the first value in the stack.|
||Drop the first value in the stack.|
||Come from a line number, the line number being the number supplied on the next line.|
||Come from a line number, if the most recent value in the stack is 'true'.|
Sum up three numbers (version 1).
This first executes line 10, which adds five to the variable stack (the stack). Then, on line 20, it adds a plus operator to the operator stack (the opstack), which waits for one more variable to be added to the variable stack. Note that it executes line 20 before line 30, which adds a three to the stack. Then the plus operator is popped off the opstack, the 3 and 5 are popped off the stack, and an 8 is put back on the stack. Next, we find another plus operator, wait for the 4 to be added to the stack, and then sum that. At this point, the program exits and returns .
cfl(' 10 #5 30 #3 20 + 40 + 50 #4 ')
Sum up three numbers (version 2).
This version works like the first version, except that we add the 5 and the 3 to the stack, then we add two plusses to the opstack, and when the 4 is read into the stack the second plus adds 4 and 3, then the first plus is popped and adds 7 and 5. I'm not sure what this notation is called.
cfl(' 10 #5 20 #3 30 + 40 + 50 #4 ')
Since order is supplied by line numbers, it is only customary to order the lines by number. An equivalent way of writing the previous example would be:
cfl('30 + 40 + 10 #5 50 #4 20 #3')
Prints "Hello world.". On line 10, we invoke the
( operator, now satisfied, pops itself off the stack while leaving the variable 'Hello world.' there.
10 print 20 Hello world. would separate on the spaces, and then 'world.' would not have a line number.
cfl(' 10 print 11 ( 20 Hello 30 + 40 world. ')
Print a list of numbers from 1 to 10.
Due to the extreme difficulty involved in concatenating words, this entry replaces the usual '99 bottles of beer' problem.
cfl(' 10 #0 20 comefrom 25 #120 30 + 40 #1 50 dup 55 dup 60 < 70 #10 80 drop 100 comefromif 110 #75 120 drop 130 comefrom 140 #90 145 drop ')
It would be easy to add an
addcome and an
addcomeif statement, which would let you set new comefroms. A
delete operator would complement it nicely, too.
reach operator, for accessing history in the variable stack, would be useful. eg;
10 #1 20 #2 30 #3 40 reach 50 #3 60# reach 70 #2 would, when executed, return [1,2,3,1,3].