Functional Struct Language

From Esolang
Jump to navigation Jump to search

The Functional Struct Language (FSL for short) is an functional esoteric programming language designed to lift the burden of predefined types and predefined functions and undefined behaviour, since this language does not contain any of these and everything you want to achieve must be programmed by hand (even types like integers and operations like addition). This makes it no longer necessary to look through the documentation of the language so often and also makes it so that there are no undefined edge cases in the language similar to division by zero in other programming languages.

Syntax

An FSL program can contain two different things: Types and functions.

Types

A type in FSL is defined with the following syntax:

type <name> {
    <name>(<type1> <name1>, <type2> <name2>, ...);
    ...
}

Types in FSL store either of the type combinations (states) inside of the type. It is also possible to have one or no types inside of a state.

Example:

type Example {
    hello();
    another_example(CrazyType abc, Example recursion);
    simple_recursion(Example myself);
}

Each instance of the type Example will be in one of the states:

  • "hello". Contains no additional data.
  • "another_example". Contains an instance of the type "CrazyType" under the name "abc" and an instance of itself under the name "recursion".
  • "simple_recursion". Only contains an instance of itself.

Functions

A function in FSL is defined with the following syntax:

function <name>(<type1> <name1>, <type2> <name2>, ...) -> <type> {
    <expression>
}

A function can have any amount of parameters and one return value. A function with no parameters is also called a constant function as no function can have side-effects and all functions will always return the same thing when given the same parameters. A function gets executed by evaluating the expression and returning its result.

Expressions

Match expression

Syntax:

match <variable> {
    <state_name>: <expression>;
    ...
}

The match expression chooses one of the expressions depending on the state of the object. The match expression needs to contain all of the different states of the type of the variable. For example, when using a match expression on the Example type above, you would need to make entries for "hello", "another_example" and "simple_recursion".

With expression

Syntax:

with <expression> as <name> <expression2>

The with expression is used to introduce a new variable <name> with the value <expression> and then evaluate <expression2> with the new variable. This is useful when using an expression multiple times.

Match as expression

Syntax:

match <expression> as <name> {
    <state_name>: <expression>;
    ...
}

The match as expression is a combination of the match expression and the with expression and could be instead written like this:

with <expression> as <name> match <name> {
    ...
}

Child expression

Syntax:

<variable>.<name>

Retrieves the value from the child with the given name of the variable. This can only be done when the variable could only be in one state or has been matched using a match expression.

Variable expression

Syntax:

<variable>

Retrieves the value from the variable. Yep, that's it.

Call expression

Syntax:

<function_name>(<expression1>,<expression2>,...)

Calls the function with the given parameters.

Instance expression

Syntax:

<type>.<state>(<expression1>,<expression2>,...)

Creates a new instance of the type in the given state with the given values.

Examples

Due to the lack of input and output functions, these examples are just functions that manipulate data.

Boolean manipulation

type Bool {
    true();
    false();
}
function and(Bool a, Bool b) -> Bool {
    match a {
        true: b;
        false: Bool.false();
    }
}
function or(Bool a, Bool b) -> Bool {
    match a {
        true: Bool.true();
        false: b;
    }
}
function not(Bool x) -> Bool {
    match x {
        true: Bool.false();
        false: Bool.true();
    }
}
function xor(Bool a, Bool b) -> Bool {
    match a {
        true: not(b);
        false: b;
    }
}

In this example, the boolean type is defined alongside some basic boolean manipulation functions.