FunctionsFTW
Paradigm(s) | procedural, imperative |
---|---|
Designed by | User:NutronStar45 |
Appeared in | 2022 |
Type system | strict |
Memory system | variable-based |
Computational class | Unknown |
Reference implementation | Unimplemented |
File extension(s) | .fftw |
FunctionsFTW (FFTW for short) is an esoteric programming language created by User:NutronStar45 where you should use functions for everything.
FFTW programs automatically terminate when the end of the program in reached.
Every statement should end with a semicolon (;
).
There are no "reserved words" due to the string-based variable name system.
Syntax
Types
There's 5 types of value in FFTW: num
, str
, bool
, func
and obj
.
Numbers
Numbers are integers, floats or NaN
described in
- one or more decimal digits
- none or one dot (
.
) - or just
NaN
Strings
Strings are text enclosed with a pair of single ('
) or double ("
) quotes.
The quotes enclosing a string must be consistent. For example
'single quotes'
and
"double quotes"
are both allowed, but
'inconsistent quotes"
are not allowed and will raise a SyntaxError
if there isn't a closing quote.
To access the length of a string, use len(strToObj(string))
, for example
len(strToObj("Hello, world!"))
returns 13
.
Booleans
Booleans are either true (T
) or false (F
).
Functions
Functions are some codes condensed into one line.
Enclose parameters with a pair of parentheses (()
), enclose some codes with a pair of braces ({}
) and combine them together to define an anonymous function, or define a custom function by assigning an anonymous function to a variable.
To return a number, use the returnNum(num val)
function.
To return a string, use the returnStr(str val)
function.
To return a boolean, use the returnBool(bool val)
function.
To return a function, use the returnFunc(func val)
function.
To return an object, use the returnObj(obj val)
function.
For example
(bool "b1", bool "b2") { returnBool(and(or(b1, b2), not(and(b1, b2)))); }
defines an XOR function.
Note that the value is returned to the current function, so the following function
(bool "input") { if(input, () { returnNum(10); }, () {}); }
won't return anything because the returnNum(10);
is returning to the function inside the if
. Do this instead:
(bool "input") { if(input, () { setNum("ret", 10); }, () { setNum("ret", NaN); }); returnNum(getNum("ret")); }
The function will always return a number even if input
was F
due to "technical limitations".
Objects
Objects are made of keys and values, each value is assigned to its key, similar to objects in JavaScript or dictionaries in Python.
All keys should be strings, even if the key is 0
.
To define an object, enclose pairs of key and value with a pair of brackets ([]
), for example
[ "firstName" "John" "lastName" "Doe" "age" 26 "isAdult" T "children" [ "0" [ "firstName" "Jane" "lastName" "Doe" "age" 6 "isAdult" F "children" [] ] ] ]
Objects can also be used for arrays, just use the indices as the keys.
To access a number in an object, use the numInObj(obj object, str key) => num
function.
To access a string in an object, use the strInObj(obj object, str key) => str
function.
To access a boolean in an object, use the boolInObj(obj object, str key) => bool
function.
To access a function in an object, use the funcInObj(obj object, str key) => func
function.
To access an object in an object, use the objInObj(obj object, str key) => obj
function.
To access a list of keys in an object, use the keys(obj object) => obj
function, for example
keys([ "name" "John Doe" "age" 26 ])
returns [ "0" "name" "1" "age" ]
.
To access the number of keys in an object, use the len(obj object) => num
function, for example
len([ "name" "John Doe" "age" 26 ])
returns 2
.
Type conversions
Original \ Target | num | str | bool | func | obj |
---|---|---|---|---|---|
num | numToStr() |
numToBool() |
|||
str | strToNum() |
strToBool() |
strToObj()
| ||
bool | boolToNum() |
||||
func | |||||
obj |
Type conversions are very important in an FFTW program as all the function parameters are type-strict, including type conversions.
To convert a number to a string, use the numToStr(num val) => str
function, for example
numToStr(12.34)
returns "12.34"
.
To convert a number to a boolean, use the numToBool(num val) => bool
function. 0
will be converted to F
or otherwise T
. For example
numToBool(123)
returns T
, and
numToBool(0)
returns F
.
To convert a string to a number, use the strToNum(str val) => num
function, for example
strToNum("12.34")
returns 12.34
.
To convert a string to a boolean, use the strToBool(str val) => bool
function. Empty strings will be converted to F
or otherwise T
. For example
strToBool("Hello, world!")
returns T
, and
strToBool("")
returns F
.
To convert a string to an object (parse the characters to an array), use the strToObj(str val) => obj
function, for example
strToObj("Hello, world!")
returns
[ "0" "H" "1" "e" "2" "l" "3" "l" "4" "o" "5" "," "6" " " "7" "w" "8" "o" "9" "r" "10" "l" "11" "d" "12" "!" ]
To convert a boolean to a number, use the boolToNum(bool val) => num
function. F
will be converted to 0
and T
will be converted to 1
. For example
boolToNum(T)
returns 1
, and
boolToNum(F)
returns 0
.
To print something to the console (without newline), use the print(str content)
function, for example
print("Hello, world!");
prints Hello, world!
to the console.
Note that the print()
function can only accept strings, so you need to manually convert the input to string, for example
print(str(100));
prints 100
to the console.
Input
To get one line of text from the input stream, use the input() => str
function, for example
num(input())
Will get one line of text from the input stream, convert it to a number and return it.
Negation
Negative
To get the negative of a number, use the neg(num number) => num
function, for example
neg(5)
returns -5
Reciprocal
To get the reciprocal of a number, use the recip(num number) => num
function, for example
recip(20)
returns 0.05
.
Calculation
Addition
To add two numbers together, use the add(num n1, num n2) => num
function, for example
add(123, 456)
returns 579
.
Subtraction
To subtract a number from another, use add(n1, neg(n2))
, for example
add(50, neg(30))
returns 20
.
Multiplication
To multiply two numbers together, use the mult(num n1, num n2) => num
function, for example
mult(4, 8)
returns 32
.
Division
To divide a number by another, use mult(n1, recip(n2))
, for example
mult(35, recip(7))
returns 5
.
Remainder
To get the remainder of dividing a number by another, use rem(num n1, num n2) => num
, for example
rem(10, 3)
returns 1
.
Exponentiation
To raise a number to the power of another, use the pow(num base, num exponent) => num
function, for example
pow(5, 4)
returns 625
.
Root
To get the root of a number, use pow(radicand, recip(degree))
, for example
pow(256, recip(4))
returns 4
.
Logarithm
To get the logarithm of a number, use the log(num antiLog, num base) => num
function, for example
log(128, 2)
returns 7
.
Comparisons
Equality
To check if two numbers are the same, use the eqNum(num n1, num n2) => bool
function, for example
eqNum(add(0.1, 0.2), 0.3)
returns F
. ('cause binary inconsistency LOL why not)
To check if two strings are the same, use the eqStr(str s1, str s2) => bool
function, for example
eqStr("Hello, world!", "Bye, world!")
returns F
.
Greater than
To check if a number is greater than another, use the gt(num n1, num n2) => bool
function, for example
gt(123, 234)
returns F
.
Less than
To check if a number is less than another, use gt(n2, n1)
, for example
gt(234, 123)
returns T
.
Greater than or equal to
To check if a number is greater than or equal to another, use not(gt(n2, n1))
.
Less than or equal to
To check if a number is less than or equal to another, use not(gt(n1, n2))
.
Inequality
To check if two numbers are not the same, use not(eqNum(n1, n2))
.
Boolean algebra
And
b1 \ b2 | T | F |
---|---|---|
T | T | F |
F | F | F |
To perform an AND function, use the and(bool b1, bool b2) => bool
function, for example
and(T, F)
returns F
.
Or
b1 \ b2 | T | F |
---|---|---|
T | T | T |
F | T | F |
To perform an OR function, use the or(bool b1, bool b2) => bool
function, for example
or(T, F)
returns T
.
Not
val | not(val) |
---|---|
T | F |
F | T |
To perform a NOT function, use the not(bool val) => bool
function, for example
not(T)
returns F
.
Xor
b1 \ b2 | T | F |
---|---|---|
T | F | T |
F | T | F |
To perform an XOR function, use and(or(b1, b2), not(and(b1, b2)))
, for example
and(or(T, F), not(and(T, F)))
returns T
.
Concatenation
Strings
To concatenate two strings together, use the concatStr(str s1, str s2) => str
function, for example
concatStr(concatStr("Hello, ", "world"), "!")
returns "Hello, world!"
.
Objects
To concatenate two objects together, use the concatObj(obj o1, obj o2) => obj
function, for example
concatObj([ "name" "John Doe" "age" 20 ], [ "age" 26 ])
returns [ "name" "John Doe" "age" 26 ]
.
Note that the latter object overwrites the former one.
Conditions
if
To execute a function if a value is T
, use the if(bool condition, func ifT, func ifF)
, for example
if(gt(2, 1), () { print("2 is greater than 1"); }, () {});
checks if 2
is greater than 1
(which always evaluates to T
), print 2 is greater than 1
to the console.
if
... else
To execute a function if a value is T
, or execute another function otherwise, use the if()
function, for example
if(gt(1, 2), () { print("1 is greater than 2"); }, () { print("1 isn't greater than 2"); });
checks if 1
is greater than 2
(which always evaluates to F
), print 1 is greater than 2
to the console, or print 1 isn't greater than 2
to the console otherwise.
if
... else if
... else
To execute a function if a value is T
, or execute another function if the value is F
and another value is T
, or execute another function if both values are F
, use nested if
, for example
setNum("secret", 20); setNum("guess", num(input())); if(gt(getNum("secret"), setNum("guess")), () { print("Too small"); }, () { if(gt(getNum("guess"), getNum("secret")), () { print("Too big"); }, () { print("Correct"); }); });
does the following:
Setsecret
to 20 Take a number from the input stream and store it toguess
Ifsecret
is bigger thanguess
: PrintToo small
to the console Else: Ifguess
is bigger thansecret
: PrintToo big
to the console Else: PrintCorrent
to the console
Labels & gotos
To create a label, use the label(str labelName)
function.
To goto a label, use the goto(str labelName)
function.
For example
setNum("i", 0); label("l1"); if(gt(10, i), () { print(numToStr(getNum("i"))); setNum("i", add(getNum("i"), 1)); goto("l1"); }, () {});
prints 0123456789
to the console.
Note that you can overwrite labels by using the same string as the labelName
.
Variables
A variable stores some values and can be accessed anytime if the variable is available.
All variables are global.
There can be spaces and symbols in a variable name (which is illegal in most modern languages) due to variable name being a string, but I'm not gonna use these because I don't like them.
Assignment
To assign a number to a variable (declared on first assignment), use the setNum(str varName, num value)
function, for example
setNum("myNumber", 123);
declares and sets myNumber
to 123
.
To assign a string to a variable (declared on first assignment), use the setStr(str varName, str value)
function, for example
setStr("myString", "Hello, world!");
declares and sets myString
to "Hello, world!"
.
To assign a boolean to a variable (declared on first assignment), use the setBool(str varName, bool value)
function, for example
setBool("myBoolean", T);
declares and sets myBoolean
to T
.
To assign an object to a variable (declared on first assignment), use the setObj(str varName, obj value)
function, for example
setObj("myObject", [ "name" "John Doe" "age" 26 ]);
declares and sets myObject
to [ "name" "John Doe" "age" 26 ]
.
Access
To access a numeral variable, use the getNum(str varName) => num
function, for example
getNum("myNumber");
returns the value of myNumber
.
To access a string variable, use the getStr(str varName) => str
function, for example
getStr("myString");
returns the value of myString
.
To access a boolean variable, use the getBool(str varName) => bool
function, for example
getBool("myBoolean");
returns the value of myBoolean
.
To access an object variable, use the getObj(str varName) => obj
function, for example
getObj("myObject");
returns the value of myObject
.
Type
To get the type of a variable, use the type(str varName) => str
function, for example
setNum("myNumber", 123); print(type("myNumber"));
prints num
to the console,
setStr("myString", "Hello, world!"); print(type("myString"));
prints str
to the console,
setBool("myBoolean", T); print(type("myBoolean"));
prints bool
to the console,
def("myFunction", { print("Hello, world!"); }); print(type("myFunction"));
prints func
to the console, and
setObj("myObject", [ "name" "John Doe" "age" 26 ]); print(type("myObject"));
prints obj
to the console.
Availability
To check if a variable exists, use the ex(str varName) => bool
function.
Comments
To write a comment, use a statement containing only a string, for example
"This is a comment";
For multi-line comments:
"This is a multi-line comment";
Note that comments are also statements, so the following code wouldn't work:
setNum("i", "Some comment"; 10);
Custom functions
Definition
To define a custom function, use the def(str funcName, func val)
function, for example
def("myFunction", (str "name") { print(concatStr(concatStr("Hello, ", getStr("name")), "!")); });
Defines a function that accepts a name
argument and prints Hello, {name}!
to the console.
Call
To call a custom function with no returning value, use the call(str funcName, obj params)
function, for example
def("myFunction", (str "name") { print(concatStr(concatStr("Hello, ", getStr("name")), "!")); }); call("myFunction", [ "name" "Mr. John" ]);
prints Hello, Mr. John!
to the console.
To call a custom function that returns a number, use the callNum(str funcName, obj params) => num
function.
To call a custom function that returns a string, use the callStr(str funcName, obj params) => str
function.
To call a custom function that returns a boolean, use the callBool(str funcName, obj params) => bool
function.
To call a custom function that returns a function, use the callFunc(str funcName, obj params) => func
function.
To call a custom function that returns an object, use the callObj(str funcName, obj params) => obj
function.
If the function don't accept any parameters, use an empty object ([]
) for params
.
Exceptions
SyntaxError
There's an error in the syntax.
TypeError
Caused by feeding an argument with a wrong type to a function.
Examples
Hello world
print("Hello, world!");
Cat
print(input());
Truth-machine
setStr("input", input()); "Get input"; if(eqStr(getStr("input"), "0")), () { "If input is 0"; print("0"); "Print 0"; }, () { if(eqStr(getStr("input"), "1"), () { "If input is 1"; label("l"); print("1\n"); "Print 1"; goto("l"); "Repeat"; }, () {}); });
Minimized (140 bytes)
setStr("i",input());if(eqStr(getStr("i"),"0")),(){print("0");},(){if(eqStr(getStr("i"),"1"),(){label("l");print("1\n");goto("l");},(){});});
FizzBuzz
setNum("i", 1); "Initialize i"; label("l"); if(not(gt(getNum("i"), 100)), () { "If i isn't greater than 100"; if(eqNum(rem(getNum("i"), 15), 0), () { "If i is divisable by 15"; print("FizzBuzz"); "Print FizzBuzz"; }, () { if(eqNum(rem(getNum("i"), 3), 0), () { "Else if i is divisable by 3"; print("Fizz"); "Print Fizz"; }, () { if(eqNum(rem(getNum("i"), 5), 0), () { "Else if i is divisable by 5"; print("Buzz"); "Print Buzz"; }, () { "If all checks above failed"; print(numToStr(getNum("i"))); "Print i"; }); }); }); print("\n"); "Return"; setNum("i", add(getNum("i"), 1)); "Increment i by 1"; goto("l"); "Repeat"; }, () {});
Minimized (319 bytes)
setNum("i",1);label("l");if(not(gt(getNum("i"),100)),(){if(eqNum(rem(getNum("i"),15),0),(){print("FizzBuzz");},(){if(eqNum(rem(getNum("i"),3),0),(){print("Fizz");},(){if(eqNum(rem(getNum("i"),5),0),(){print("Buzz");},(){print(numToStr(getNum("i")));});});});print("\n");setNum("i",add(getNum("i"),1));goto("l");},(){});
Fibonacci
setNum("stl", 1); "Set stl(second to last) to 1"; setNum("last", 0); "Set last to 0"; label("l"); print(numToStr(add(getNum("stl"), getNum("last")))); "Print stl + last"; setNum("last", add(getNum("stl"), getNum("last"))); "last = stl + last"; setNum("stl", add(getNum("last"), neg(getNum("stl")))); "stl = (stl + last) - stl = last"; goto("l"); "Repeat";
Minimized (182 bytes)
setNum("s",1);setNum("l",0);label("L");print(numToStr(add(getNum("s"),getNum("l"))));setNum("l",add(getNum("s"),getNum("l")));setNum("s",add(getNum("l"),neg(getNum("s"))));goto("L");
Fibonacci (Recursive)
def("fib", (num "index") { if(eqNum(getNum("index"), 0), () { "F(0)"; returnNum(0); }, () { if(eqNum(getNum("index"), 0), () { "F(1)"; returnNum(1); }, () { "F(i-2) + F(i-1)"; returnNum(add(callNum("fib", [ "index" add(getNum("index"), neg(2)) ]), callNum("fib", [ "index" add(getNum("index"), neg(1)) ]))); }); }); }); setNum("x", 1); label("l"); print(callNum("fib", [ "index" getNum("x") ])); setNum("x", add(getNum("x"), 1)); goto("l");
Minimized (323 bytes)
def("f",(num "i"){if(eqNum(getNum("i"),0),(){returnNum(0);},(){if(eqNum(getNum("i"),0),(){returnNum(1);},(){returnNum(add(callNum("f",["i" add(getNum("i"),neg(2))]),callNum("f",["i" add(getNum("i"),neg(1))])));});});});setNum("x",1);label("l");print(callNum("f",["i" getNum("x")]));setNum("x",add(getNum("x"),1));goto("l");
Factorial
setNum("input", strtoNum(input())); "Get number"; setNum("result", 1); "The result"; label("l"); if(gt(getNum("input"), 1), () { "If input > 1"; setNum("result", mult(getNum("result"), getNum("input"))); "result = result * input"; setNum("input", add(getNum("input"), neg(1))); "input--"; goto("l"); "Repeat"; }, () {}); print(numToStr(getNumber("result"))); "Print result";
Minimized (207 bytes)
setNum("i",strtoNum(input()));setNum("r",1);label("l");if(gt(getNum("i"),1),(){setNum("r",mult(getNum("r"),getNum("i")));setNum("i",add(getNum("i"),neg(1)));goto("l");},(){});print(numToStr(getNumber("r")));
99 bottles of beer
setNum("bottles", 99); "Set X (bottles) to 99"; setStr("form", " bottles"); "Plural"; label("l"); if(gt(getNum("bottles"), 0), () { "If X > 0"; print(numToStr(getNum("bottles"))); "X bottle(s) of beer on the wall,"; print(getStr("form")); print(" of beer on the wall,\n"); print(numToStr(getNum("bottles"))); "X bottle(s) of beer."; print(getStr("form")); "Take one down, pass it around,"; print(" of beer.\nTake one down, pass it around,\n"); setNum("bottles", add(getNum("bottles"), neg(1))); "X--"; if(eqNum(getNum("bottles"), 1), () { "If X = 1"; setStr("form", " bottle"); "Singular"; }, () { "Else"; setStr("form", " bottles"); "Plural"; }); if(gt(getNum("bottles"), 0), () { "If X > 0"; print(numToStr(getNum("bottles"))); "Use X"; }, () { "Else"; print("No"); "Use No"; }); print(getStr("form")); "X/No bottle(s) of beer on the wall."; print(" of beer on the wall.\n\n"); goto("l"); "Repeat"; }, () {});
Minimized (522 bytes)
setNum("b",99);setStr("f"," bottles");label("l");if(gt(getNum("b"),0),(){print(numToStr(getNum("b")));print(getStr("f"));print(" of beer on the wall,\n");print(numToStr(getNum("b")));print(getStr("f"));print(" of beer.\nTake one down, pass it around,\n");setNum("bottles",add(getNum("b"),neg(1)));if(eqNum(getNum("b"),1),(){setStr("f"," bottle");},(){setStr("f"," bottles");});if(gt(getNum("b"),0),(){print(numToStr(getNum("b")));},(){print("No");});print(getStr("f"));print(" of beer on the wall.\n\n");goto("l");},(){});
List of functions
This list is alphanumerically sorted.
add(num n1, num n2) => num and(bool b1, bool b2) => bool boolInObj(obj object, str key) => bool boolToNum(bool val) => num call(str funcName, obj params) callBool(str funcName, obj params) => bool callFunc(str funcName, obj params) => func callNum(str funcName, obj params) => num callObj(str funcName, obj params) => obj callStr(str funcName, obj params) => str concatObj(obj o1, obj o2) => obj concatStr(str s1, str s2) => str def(str funcName, func val) eqNum(num n1, num n2) => bool eqStr(str s1, str s2) => bool ex(str varName) => bool funcInObj(obj object, str key) => func getBool(str varName) => bool getNum(str varName) => num getObj(str varName) => obj getStr(str varName) => str goto(str labelName) gt(num n1, num n2) => bool if(bool condition, func ifT func ifF) input() => str keys(obj object) => obj label(str labelName) len(obj object) => num log(num antiLog, num base) => num mult(num n1, num n2) => num neg(num number) => num not(bool val) => bool numInObj(obj object, str key) => num numToBool(num val) => bool numToStr(num val) => str objInObj(obj object, str key) => obj or(bool b1, bool b2) => bool pow(num base, num exponent) => num print(str content) recip(num number) => num rem(num n1, num n2) => num returnBool(bool val) returnFunc(func val) returnNum(num val) returnObj(obj val) returnStr(str val) setBool(str varName, bool value) setNum(str varName, num value) setObj(str varName, obj value) setStr(str varName, str value) strInObj(obj object, str key) => str strToBool(str val) => bool strToNum(str val) => num strToObj(str val) => obj type(str varName) => str
Implementation
Unimplemented, please someone writes an interpreter here