MesFunc
Yet another idea for a programming language
// Comments start with `//`
// Assignements
let pi = 3.1415;
let rd = 16;
// Method calling
pi * (rd * rd);
// Class definition
class Circle {
Float radius;
new Float r {
// only new is allowed to set members
this radius = r;
}
getArea Void -> Float {
// Last non `;` terminated expression is returned by method
pi * (this radius squared)
}
}
// Trait definition
trait Printable {
print Void -> String;
}
// Trait implementation
class Happy impl Printable {
print Void -> String {
":)"
}
}
class Sad impl Printable {
print Void -> String {
"):"
}
}
class Printer {
// Static method
// Side effects tracking via contexts
// Here we need the IO context as required by `stdout log`
@print Printable p ->[IO] Void {
Stdout log (p print ++ "\n");
}
}
class Stdout {
priv String out = "stdout";
// Builtins may access Context for side-effects
// User code will need to use wrappers
@log String s ->[IO] Void {
Context IO log (this out) s;
}
}
// Running
// # Code
// main.mf
class Main {
// Printer print requires IO
// Main main may expose any contexts
@main Array<String> args ->[IO] Void {
let happy = Happy new;
let sad = Sad new;
Printer print happy;
Printer print sad;
}
}
// # Shell
~: mesfunc build main.mf --with IO
Built ./main.mf at ./main.out
~: ./main.out
:)
:(
~:
// Multiple arguments
class StringUtils {
@replace String s, Char f, Char r -> String {
// \(...) is an anonymous function
// required here by map
// map type is `(T v -> T) -> Array<T>` on Array<T>
s toCharArray map \(c ->
c == f ifThenElse \(r) \(c)
) toString
}
}
// Generics
class Node<T> {
Ref<T> value;
Optional<Node<T>> next;
new T v, Optional<Node<T>> o -> Self {
this value = v !&;
this next = o;
}
setValue T v -> Self {
this value set v;
}
}
class List<T> {
Ref<Optional<Node<T>>> head;
new Optional<Node<T>> o -> Self {
this head = o &!;
}
peak Void -> Optional<T> {
this head get unwrap
\(Optional<T> none)
\(t -> Optional<T> new t)
}
push T v -> Self {
this head set (Node<T> new v (this head get));
}
pop Void -> Self {
this head set (this head get);
}
change Int idx, T v -> Self {
let i = 0 &!;
let hasSeenNoneNode = false &!;
let Ref<Optional<Node<T>>> node = this head get &!;
\(i get < idx and (hasSeeNoneNode not)) while
\(node set
(node get unwrap
\(hasSeenNoneNode set true;
Optional<Node<T>> none)
\(n -> Optional<Node<T>> new (n next))));
node get withValue \(n -> n setValue v);
}
}
// Builtins may use null
// User will use wrappers like Optional
class Optional<T> {
priv T v = null;
new T v -> Self {
$v = v;
}
@none Void -> Self {}
withValue (T -> R) f -> Optional<R> {
$v isNull ifThenElse
\(Optional<R> none)
// Safe access to $v cause its not null
\(Optional<R> new (f do $v))
}
unwrap (Void -> R) nf, (T -> R) vf -> R {
$v isNull ifThenElse
nf
// Safe access to $v cause its not null
\(vf do $v)
}
}