Fortob
Paradigm(s) | imperative, self-modifying |
---|---|
Designed by | User:Fergusq |
Appeared in | 2014 |
Memory system | stack-based, variable-based |
Dimensions | one-dimensional |
Computational class | Unknown |
Reference implementation | [1] |
Influenced by | Forobj, Perl |
File extension(s) | .fortob |
Fortob is the second language of the For series, first being Forobj. It shares many aspects of its predecessor. The main difference is its lexical structure, as it is based on tokens and not characters. The name is a play of "forobj" and "token".
Overview
Readcom
The language is based on a thing called readcom. Readcom is a processor that reads tokens from the input stream and interprets them. Unlike in Forobj Interpreter, readcom can be called from the program itself, making recursive command parsing possible.
For example, the +
command calls readcom to parse the right operand. As readcom parses imperative code, the operand may be empty, in which case the value will be taken from the stack.
Operators
All operators are infix. There is no operator precedence. All operators are right-associative.
Command reference
Name | Syntax | Stack before | Stack after | Description |
---|---|---|---|---|
Values | ||||
'
|
0 | Inserts a zero to the stack | ||
0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 (n)
|
x | x × 10 + n | Shifts the top number of the stack and adds n to it. | |
"
|
c*" | the new string | Inserts a string to the stack | |
[
|
t*] | the new string | Inserts a string to the stack | |
Stack manipulation | ||||
;
|
x | Drops the top value of the stack | ||
Variable and command manipulation | ||||
$
|
name | value of $name | Inserts the value of the variable to the stack | |
$
|
name = readcom | value of $name | Sets the value of the variable | |
%
|
name = readcom | value of $name | Forces creation of a new variable | |
@
|
name readcom | value of readcom | Sets a command and pushes the value of the readcom to the stack | |
Method invokation | ||||
.
|
name [ : readcom {, readcom} ] | o | return value of o.name() | Invokates a method and pushes its return value to the stack |
+ , - , * , / , < , > , =
|
readcom | o | return value of o.op(r) | Invokates an operator method |
Readcom built-ins | ||||
\ | Tells readcom to stop reading tokens |
Method reference
Return type | Name and args | Description |
---|---|---|
Number | ||
Number | +(Number) | Addition |
Number | -(Number) | Subtraction |
Number | *(Number) | Multiplication |
Number | /(Number) | Division |
Boolean | =(Number) | Equals |
Boolean | <(Number) | Less than |
Boolean | >(Number) | Greater than |
Boolean | ||
Boolean or Any | if(String) | If true converts the argument to a function and calls it, returning its return value, otherwise return false |
Any | if(String, String) | Calls the first string if true, otherwise the second |
String | ||
String | +(String) | Concatenation |
Boolean | =(String) | Equals |
Boolean | while(String) | Converts itself to a function and calls it as long as it returns true, calling the argument string at the same time. Returns true if the argument string was called once or more, otherwise false. |
Any | apply(...) | Converts itself to a function and calls it with given arguments. Returns the appropriate return value. |
Boolean | proceed(...) | Converts itself to a function and calls it with given arguments. Returns true. |
Environment | ||
Environment | push(Any) | Pushes a value to the stack and returns itself |
Environment | dup() | Duplicates the top value of the stack and returns itself |
Any | pop() | Pops and returns the top value of the stack |
Environment | drop() | Pops and discards the top value of the stack and returns itself |
Environment | put(String, Any) | Puts a value to the map |
Environment | putLocal(String, Any) | Forces creation of a new entry |
Any | get(String) | Gets a value from the map |
InputQueue | ||
String | nextString() | Returns the next string from the queue |
Number | nextNumber() | Parses the next string as a number |
String | seekString() | Returns the next string from the queue (lookahead) |
Number | seekNumber() | Parses the next string as a number (lookahead) |
Any | readcom() | Uses readcom to parse an expression from the queue |
Example code
Hello world
"Hello world!".println;
Print numbers from 0 to 9
$i = '0\; [$i < '1 0].while: [ $i = $i + '1\\; $i p; ]\;
Print statement
@print[$!.readcom.println;$\.push:'\;]\; print "Hello world!"\;
Custom variable manipulation command
@£[ $name=$!.nextString\; $!.seekString="="\.if: [ $!.accept:"="\; $\.put:$name,$val=$!.readcom\\; $\.push:$val\;' ], [ $\.push:$\.get:$name\\;' ]\; ]\;
Example usage:
£var='4\; ""+£var\.println;
Infix expression parser
Supports precedence and parentheses.
@expr[ $expr=[ $!=\; %a=$!$term.apply:\\; [$!.seekString="+"\.if:['='],[$!.seekString="-"\.if:['=']]].while: [ $a=$!.nextString="+"\.if:[ $a+$!$term.apply: ], [ $a-$!$term.apply: ]\\; ]\; $a ]\; $term=[ $!=\; %b=$!$prim.apply:\\; [$!.seekString="*"\.if:['='],[$!.seekString="/"\.if:['=']]].while: [ $b=$!.nextString="*"\.if:[ $b*$!$prim.apply: ], [ $b/$!$prim.apply: ]\\; ]\; $b ]\; $prim=[ $!=\; $!.seekString="("\.if: [ $!.accept:"("\; $expr.apply:$!\ $!.accept:")"\; ], [ $!.nextNumber ] ]\; $\.push:$expr.apply:$!\\; ]\;
Example usage:
""+expr 2*(3+4)\.println;
99 bottles of beer
$f=[ %i=\; ['=$i].if: [ "No more bottles of beer on the wall".println; "no more bottles of beer".println; "take one down, pass it around".println; "99 bottles of beer".println;' ], [ ""+$i\+_\+"bottle"\+['1=$i].if:[""],["s"]\\+_\+"of beer on the wall"\.println; ""+$i\+_\+"bottle"\+['1=$i].if:[""],["s"]\\+_\+" of beer"\.println; "take one down, pass it around".println; ""+$i-'1\\+_\+"bottle"\+['1=$i-'1].if:[""],["s"]\\+_\+" of beer"\.println; "".println; $f.proceed:$i-'1\\;' ]\;' ]\; $f.proceed:'9 9\;
See also
- Forobj, the predecessor of Fortob