Cremilda* is a minimalist functional educational programming language developed to teach a compilers course at University of Brasília/Brazil. That's why the rest of this readme is in Portuguese ;)
- provisional name.
Cremilda é uma linguagem de programação funcional com o foco em simplicidade e facilidade de implementação. O compilador e o runtime da linguagem são em Python. Muito provavelmente é simples portar o runtime para outras linguagens dinâmicas e no futuro talvez veremos Cremilda rodando no navegador em Javascript.
Apenas 2 tipos atômicos: strings, booleanos e números (floats). Estes tipos podem ser se compor para formar outros tipos algébricos: tuplas, records e tagged unions:
# Números podem ser expressos em vários formatos
x = 42
y = -3.14
z = 1.6e-19
# Strings são delimitadas por aspas duplas
a = "foo"
# Booleanos de "Javascript"
x = true
y = false
# Tuplas (em construção)
x = (1, 2)
# Listas (simplesmente encadeadas) (em construção)
x = [1, 2, 3, 4]
# Records/Structs/Objects (em construção)
x = {name: "John", age: 42}
# Tagged unions/Enums (em construção)
x = Nothing
y = Just 42
Cremilda é uma linguagem baseada em expressões (em oposição à declarações imperativas). As expressões mais básicas são variáveis, construção de objeto, chamadas de função e operadores arbitrários:
# Chamada de função + operadores x = sqrt(4) + 1 # Construindo uma instância de tagged union x = Ok "success" y = Err "bad request" # Note que nomes de variáveis são sempre minúsculos e nomes de tipos # aparecem em CamelCase
Números aceitam as operações básicas:
x = 2 + 1 y = 2 * 4 z = 3 ** 2 w = 4 / 2 k = 4 - 2
Comparações são feitas com >, <, ==, !=, >=, <=.
Um módulo deve declarar as variáveis e operadores na primeira linha:
export (Bool, name, age, +, -);
Em seguida, declara os imports utilizados:
# importa todos nomes import "module"; # qualificado: funções são acessadas como mod.func import "module" as mod; # especifica alguns nomes import (Foo, bar, baz) from "module"; # importa sob nome diferente import (Foo as Foobar, bar, baz) from "module";
Novos tipos:
type Vec = (Number, Number); # Enums e tagged unions type Bool = False | True; type Option = Null | Value x; type List = Nil | Cons (x, Cons);
Operadores:
# Precedência e associatividade explícitas left_op 3 (++) as concat; right_op 1 (::) as cons; # Precedência implícita left_op (.+) as try_add from (+);
Por último, declaramos as constantes e funções do módulo:
# Constantes pi = 3.1415; constants_list = Cons (pi, Nil); # Funções inc(n) = n + 1;
Cremilda não possui várias estruturas de controle esperadas em outras linguagens de programação. No entanto, as poucas oferecidas são mais que o suficiente para realizar qualquer tipo de computação.
Ifs:
# else é obrigatório!
fat(n) = if n < 2 then 1 else n * fat(n);
# Indentação é irrelevante
fib(n) =
if n < 2 then
1
else
fib(n - 1) + fib(n - 2);
# Com isso, podemos compor várias condições em um único bloco
quadrant(x, y) =
if x > 0 and y > 0 then
1
else if x < 0 and y < 0 then
2
else if x < 0 and y < 0 then
3
else if x > 0 and y < 0 then
4
else
0
Blocos de definições:
# Podemos definir valores intermediários dentro de um block let.
baskhara(a, b, c) =
let
delta = b^2 - 4 * a * c;
norm = 2 * a;
in ((-b + sqrt(delta)) / norm, (-b - sqrt(delta)) / norm);
Expressões case:
fmap(func, x) =
case x of
Ok value: Ok func(value);
Err e: x;
Funções anônimas:
doubles = fn (x) => x + x;