Skip to content

mobarski/fabris

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

46 Commits
 
 
 
 
 
 
 
 

Repository files navigation

FABRIS PROGRAMMING LANGUAGE

Introduction

Fabris is a stack-oriented, concatenative language designed to be simple, friendly and efficient.

Fabris is inspired by Forth, Python, Joy, DSSP, Factor, COBOL and Unix.

Current Fabris version is unstable and is intended only for experimental use.

The name comes from first leters of main components of Fabris VM: (F)ixed point base, (A)uxiliary pointers, (B)ase pointer, (R)eturn stack, (I)nstruction pointer, (S)tack.

Similarity with the name of Italian fencing master Salvator Fabris is not a coincidence.

Basic Syntax

Basic expressions:

"the answer is " print 40 2 add dot

Line comment:

"hello world" print -- the rest of line is ignored
-- this line is also ignored

Stream comment:

4 10 mul (this is a comment) 1 1 add add ( this also )

Conditional statement:

if 10 equal then "equals ten" print end

Conditional statement with alternative:

if 10 or-more then "ten or more" else "nine or less" end

Conditional statement with multiple branches:

10 or-more then "ten or more"   else
 8 or-less then "eight or less" else
                "exactly nine"  end

Counted loop:

3 times
    "Hastur! " print
loop

Universal loop:

do
    scan-for-enemies
    if enemy then
        break end
    patrol-area
loop
exterminate exterminate exterminate

New function definition:

def square dup mul ret

New function definition with named parameters:

def energy in h m v out 1 (e)
    m v v mul mul 2 div -- kinetic energy
    h m g mul mul -- potential energy
    add (e) ret

Testing:

test 40 2 add 42 ok
test 10 dup inc 11 ok 10 ok

Lambda expressions:

[ " world" print ] [ "hello" print ] call call -- prints "hello world"

Recurrency:

def print-stack
    if depth then dot drop print-stack end ret

List reduction:

[ 1 3 5 7 9 ] list [ add ] fold -- sum all elements

Include module:

use string
do each-word
    print
loop

Top-down programming:

def c b ret
def b a ret
def a 42 ret

c dot -- prints 42

Fixed point arithmetics:

1000 tof
3.14159    2  mul fdot -- prints 6.282
3.14159  2.0 fmul fdot -- prints 6.282
   3141    2  mul fdot -- prints 6.282
   3141 2000 fmul fdot -- prints 6.282

Functions

Stack Manipulation

name effect comments core
swap (ab--ba) swap the two top stack items yes
dup (a--aa) duplicate the top stack item yes
drop (a--) discard the top item yes
depth (--n) push number of items on stack yes
tor (a--)(=a) move the top item to the return stack yes
r (--x)(a=) move the top item of return stack to stack yes
tof (a--) move the top item to the fixed point base yes

Basic Arithmetic

name effect comments core
add (ab--x) add two top items (a+b) yes
sub (ab--x) subtract top item from second item (a-b)  
mul (ab--x) multiply two top items (a*b)  
div (ab--x) divide second item by top item (a/b)  
mod (ab--x) reminder of dividing second item by top item (a%b)  
inc (a--x) increment the top item (a+1)  
dec (a--x) decrement the top item (a-1)  
abs (a--x) return absolute value (abs(a))  
neg (a--x) change the sign (-a) yes
fmul (ab--x) fixed point - multiply two top items (a*b) opt.
fdiv (ab--x) fixed point - divide of second item by top item (a/b) opt.

Comparators

name effect comments core
zero (a--ax) check if a == 0 yes
negative (a--ax) check if a < 0 yes
positive (a--ax) check if a > 0  
less (ab--ax) check if a < b  
or-less (ab--ax) check if a <= b  
more (ab--ax) check if a > b  
or-more (ab--ax) check if a >= b  
equal (ab--ax) check if a == b  
within (nab--nx) check if a <= n <= b  

Logic

name effect comments core
and (ab--x) and two top items (a&b) yes
or (ab--x) or two top items (a|b) yes
xor (ab--x) xor two top items (a^b) yes
not (a--x) logical negation (!a) yes

Input/Output

name effect comments core
emit (c--) write single character to standard output yes
take (--c) read single character from standard input opt.
untake (c--) unread single character from standard input opt.
print (an--) prints n characters at address a  
argc (--x) returns number of program arguments opt.
argv (a--xn) returns address and length of argument number a opt.
dot (a--a) prints top item as number followed by space  
fdot (a--a) prints top item as fixed point number followed by space  
udot (a--a) prints top item as unsigned number followed by space  
xdot (a--a) prints top item as hexadecimal number followed by a space  
write (anf--) write n characters at address a to file with descriptor f  

Control/Flow

name effect comments core
def X (--) define new word X yes
ret (--) return from definition yes
macro X (--) define new macro X opt.
mend (--) end macro definition opt.
then (x--) execute following code if x is not zero yes
else (--) branch for the then word (optional) yes
end (--) finish then/else sequence yes
do (=x) start of unconditioned loop yes
break (x=) break out of the current loop yes
loop (--) repeat loop yes
times (x--)(=i) start of counted loop yes
"X" (--an) start/end of a string, places addres and length on the stack yes
[ (--) start of anonymous code block yes
] (--r) end of anonymous code block, put reference to it on the stack yes
_ (x--) capture stack item into code block, right to left yes
call (r--) call code block referenced by r yes
yield (--r) return and push reference to next instruction yes
'X' (--c) start/end of a char yes
X (--x) place integer X in the stack yes
use X (--) use module X yes
dyn X (--) declare word X as dynamic, that can change at the runtime yes
ref X (--r) put reference to word X on the stack yes
as X (r--) redefine dynamic word X as code reference r yes
in X... (--) define names of input parameters, set input register yes
out X (--) define number of output parameters yes

Other

name effect comments core
nop (--) do nothig  
clock (--x) returns number of microseconds since the program was launched opt.
halt (--) stops program execution yes
peek (a--c) get character (unsigned) from address a opt.
poke (ca--) set character at addres a to c opt.
ok (ab--) halt and print error if two top items are not equal  
trace (--) prints information about VM state - stack, ip, ...  
sprint (--) prints stack  

More Logic

name effect comments core
shl (ab--x) shift a left by b bits (a<<b)  
shr (ab--x) shift a right by b bits (a>>b)  
ushr (ab--x) shift unsigned a right by b bits (a>>b)  
inv (a--x) invert all bits (~a)  

More Stack Manipulation

name effect comments core
over (ab--aba) push the second item on top  
nip (ab--b) discard the second item  
tuck (ab--bab) insert copy of top item before second item  
rot (abc--bca) rotate the third item to the top  
unrot (abc--cab) unrotate the top to the third item  
yank (--a)(ab=b) remove second item from return stack and place it on stack  
mark (--)(=n) mark stack location (push stack depth to return stack)  
count (--x)(n=) push number of items after the mark, unmark stack  
cut (?--)(n=) drop items after marked stack location  
chars (n--x) calculate number of items for storing n characters  
bytes (n--x) calculate number of items for storing n bytes  
ndrop (?n--) discard n top items (not counting n)  
dup2 (ab--abab) duplicate top pair  
swap2 (abxy--xyab) swap two pairs  
drop2 (ab--) drop pair  
pick (n--x) pick nth stack item from top (not counting n)  
reverse (?n--?n) reverse order of n top stack items  
reverse2 (?n--?n) reverse order of n top stack pairs  

String Manipulation

name effect comments core
hash (an--x) return hash value for given string (x65599 algorithm)  
split (an--rxfy) return first word from a string and the rest of the string  
strip (an--bx) return string without leading and trailing whitespaces  
lstrip (an--bx) return string without leading whitespaces  
rstrip (an--bx) return string without trailing whitespaces  
substr (ankc--anbc) return substring of c characters starting at b  
index (anbm--anx) return index of bm string within an string, or -1  
char (ani--anx) return character at index i in given string yes?
upper (an--an) destructive change to lowercase  
lower (an--an) destructive change to uppercase  

String Comparators

name effect comments
begins (anbm--anx) return true if an string begins with bm string
ends (anbm--anx) return true if an string ends with bm string
contains (anbm--anx) return true if an string contains bm string
arein (anbm--anx) return true if an string contains any character from bm string
haschar (anc--anx) return true if an string contains character c

More Arithmetic

name effect comments
min (ab--x) return lower value
max (ab--x) return greater value
limit (xab--y) limit value of x (aka clamp), if x<a then a, if x>b then b
divmul (abc--x) ... (a/b*c)
muldiv (abc--x) ... (a*b/c)
muldivmod (abc--xr) ... (a*b/c, a*b%c)
divmod (ab--xr) ... (a/b, a%b)

Performance

Different dispatching techniques results in different efficiency depending on the CPU architecture [1].

Fabris offers multiple dispatching strategies in the single VM.

benchmark N goto switch call direct repl.sw c.call c.inl python ENV VM cfg
nested-loops 16 508 862 990 391 518 489 464 11671 E.1 C.0
nested-loops 16 398 882 934 287 546 400 369 7142 E.1 C.1
fibonacci 32 867 1043 1183 665 904 520 485 6037 E.1 C.0
fibonacci 32 620 1017 1001 501 787 506 401 4524 E.1 C.2

Programs are based on Benchmark Tests from http://dada.perl.it/shootout/.

Times are given in milliseconds for best of 5 runs. More benchmarks and results coming soon.

Environment:
  • E.1 - Intel Atom N570 1.66 @ 1.0 GHz, gcc 4.8.4, -O3 -fomit-frame-pointer
VM config:
  • C.0 - Default Fabris config. Python 3.5
  • C.1 - Fabris registers: sp on ESI, ip on EDI. Python 2.7
  • C.2 - Fabris registers: sp on ESI, ip on EDI, rp on EBX. Python 2.7

Related articles:

[1]http://www.complang.tuwien.ac.at/forth/threading/
[2]http://www.complang.tuwien.ac.at/forth/threaded-code.html
[3]http://realityforge.org/code/virtual-machines/2011/05/19/interpreters.html
[4]https://en.wikipedia.org/wiki/Threaded_code

Simplicity

Friendly Language

About

Fabris Programming Language

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published