Fortob

From Esolang
Jump to navigation Jump to search
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

External resources