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)
  }
}
XXIIVV webring