It's a fun language-side-project (not that I have a real project to work on tho).
type NamedColor
  | :Red
  | :Green
  | :Blue
  | :Cyan
  | :Magenta
  | :Yellow
  | :Black
  | :White
end
type Color
  | :Rgb Int, Int, Int
  | :Hsb Int, Int, Int
  | NamedColor
end
def main[] do
  let green = { :Green } as NamedColor;
  let color = { :Rgb 50, 100, 200 } as Color;
  color = green; # Note: allowed because NamedColor <: Color.
  match color
    | { :Red } => intr.puts["I love red!"]
    | { :Rgb r, g, b } =>
        intr.puts["The red component is"];   intr.dbg_int[r];
        intr.puts["The green component is"]; intr.dbg_int[g];
        intr.puts["The blue component is"];  intr.dbg_int[b];
    | other => intr.puts["I don't know that color!"];
  end
endtype rec Expr
  | :Num Int
  | :Bool Bool
  | :Add rec, rec
  | :Mul rec, rec
  | :If rec, rec, rec
  | :Var Text
  | :Let Text, rec, rec
end
# Note: `Val` and `Expr` are allowed to have overlapping constructor names!
type Val
  | :Num Int
  | :Bool Bool
end
type rec Ctx
  | :Empty
  | :Bind Text, Val, rec
end
def eval[ctx: Ctx, expr: Expr] -> Tuple[Ctx, Val] do
  match expr
    | { :Num x } => { ctx, { :Num x } }
    | { :Bool x } => { ctx, { :Bool x } }
    | { :Add x, y } =>
        let { ctx, x } = eval[ctx, x];
        let { ctx, y } = eval[ctx, y];
        let { :Num x } = x else
          type_error["The `+` operator requires numbers!"];
        end
        let { :Num y } = y else
          type_error["The `+` operator requires numbers!"];
        end
        { ctx, { :Num x + y } }
    | { :Mul x, y } =>
        let { ctx, x } = eval[ctx, x];
        let { ctx, y } = eval[ctx, y];
        let { :Num x } = x else
          type_error["The `*` operator requires numbers!"];
        end
        let { :Num y } = y else
          type_error["The `*` operator requires numbers!"];
        end
        { ctx, { :Num x * y } }
    | { :If cond, yes, no } =>
        let { ctx, cond } = eval[ctx, cond];
        let { :Bool cond } = cond else
          type_error["An `if` expression requires a boolean in it's conditional!"];
        end
        if cond then
          eval[ctx, yes]
        else
          eval[ctx, no]
        end
    | { :Var x } => { ctx, ctx_lookup[ctx, x] }
    | { :Let x, expr, body } =>
        let { ctx, val } = eval[ctx, expr];
        let ctx = { :Bind x, val, ctx };
        eval[ctx, body]
  end
end
def ctx_lookup[ctx: Ctx, x: Text] -> Val do
  match ctx
    | { :Empty } =>
        intr.puts["Unbound variable " ++ x];
        intr.exit[];
    | { :Bind y, val, ctx } =>
        if intr.eq_text[y, x] then
          val
        else 
          ctx_lookup[ctx, x]
        end
  end
end
def type_error[msg: Text] -> Never do
  intr.puts["Type Error: " ++ msg];
  intr.exit[];
end
def print_val[val: Val] do
  match val
    | { :Num x } => intr.dbg_int[x]
    | { :Bool x } => intr.dbg_bool[x]
    end
end
def main[] do
  let ctx = { :Empty };
  let expr =
    { :Let "x", { :Num 123 },
      { :Add { :Mul { :Num 2 }, { :Num 3 } }, { :Var "x" } } };
  let { ctx, result } = eval[ctx, expr];
  print_val[result];
end- You need 
stackinstalled. I'm using version2.9.3just FYI. Stackshould be usingghc-8.10.4for the haskell compiler.- You need 
cargoto run the Rust bytecode interpreter. 
$ stack run -- path/to/my/source-file.funlang-  Compile a (somewhat) high-level language down to bytecode that can be run on a virtual machine
- Impl basic operations, and control flow statements
 - Impl function calls
 - Impl lexical scoping for blocks
 - Impl closures
 
 -  Add a bidirectional type-checking algorithm
- Implement non-polymorphic type checking
 - Implement polymorphic type checking
 
 -  Add algebraic data types
- Impl basic variant types
 - Impl tuple types
 -  Impl record types (currently called Mod types)
- Call them records instead
 
 - Allow recursive types
 -  Impl 
matchexpressions- Support basic pattern matching
 -  Allow irrefutable patterns in 
matchexpressions - Impl literal patterns
 - Impl pattern guards
 
 -  Impl 
let-elseexpressions