aboutsummaryrefslogtreecommitdiff
path: root/README.md
blob: fcbb5bde607a2ccaf90d19e2dce4bf315b4b2f78 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# Funco

This is a small functional programming language I wrote for fun inspired by [lispy](https://norvig.com/lispy.html) and [Atto](https://github.com/zesterer/atto/tree/master).

Still, it has a lexer and a parser, and some optimizations (like recursive tail calls, although they need to be tagged).

The only requirement is Python 3.

There are lots of limitations, but check [TODO](TODO.md) for some ideas to contribute.

## The language

An example:

```ruby
# example of a factorial function
def fact(n acc)
    if =(n 1)
        acc
    else
        # tagging a tail call with "@" so it can be optimized
        @fact(-(n 1) *(acc n))
    end
end

# main is the entry point of a program
def main()
    display("Running fact(50)...")
    display(fact(50. 1))
end

# output:
# Running fact(50)...
# 3.0414093201713376e+64
```

A program can have:

* line comments, with `#`
* function definitions
* expressions

A `main()` function is required and will be executed as entry point for the program.

Function definition:

```text
def ident([param1 [param2] [...]])
    [...]
end
```

Expressions can be:

* function calls
* conditionals with `if [elif [elif] [...]] [else]`
* literals

Literals include:

* numbers (int or float): `1`, `1.5`
* strings: `"this is a string"`
* booleans (`true` or `false`), as result of some logical functions; although 0 is false and non-zero is true
* lists
* functions
* none for "no value"

Operators are functions, that includes:

* `+`, `-`, `*`, `/`, `mod`
* `>`, `<`, `>=`, `<=`, `=`, `!=`
* `and`, `or`, `not`

For example, adding two numbers:

```ruby
+(1 1) # should be 2
```

Other built-in functions are:

* `int(value)`: convert a value into a integer
* `float(value)`: convert a value into a float
* `string(value)`: convert a value into a string
* `list(a b c d)`: convert its arguments into a list, for example `list(1 2 3 4)`
* `int?(value)`: returns true if a value is a integer
* `float?(value)`: returns true if a value is a float
* `string?(value)`: returns true if a value is a string
* `list?(value)`: returns true if a values is a list
* `none?(value)`: returns true if a value is none
* `boolean?(value)`: returns true if a value is a boolean
* `function?(value)`: returns true if a value is a function
* `head(list)`: returns the first element of a list
* `tail(list)`: returns the end of a list excluding the first element
* `empty?(list)`: returns true if a list is empty
* `size(list)`: returns the size of a list or a string
* `min(list)`: returns the smaller value in a list
* `max(list)`: returns the larger value in a list
* `contains(value list)`: returns true if a list contains a value
* `map(fn list)`: applies a list to a function
* `filter(fn list)`: applies a list to a function, excluding the items for which the function returns true
* `fold(initial fn list)`: folds using a function the receives the accumulator and the value, and returns the updated accumulator
* `take(n list)`: return the first n elements of a list
* `drop(n list)`: return the list dropping the n first elements
* `display(value)`: prints its arguments to the screen, for example `display("hello" "world")`
* `..(i j)`: generate a list of integers from i to j

See the examples in `./examples`.

## Licence

* This project is licensed [GPL 3.0](gpl-3.0.txt).