<<

mulch

Code repository: https://codeberg.org/wr7/mulch

Mulch is a lazily evaluated declarative programming language. It was originally intended to replace the language used in vcat, but I now have grander visions for it.

Unlike the language in vcat, Mulch has its own custom garbage collector, it's lazily evaluated, has support for infinite-precision rational numbers, and it supports lambdas. Some of its syntax is borrowed from the "Nix" programming language, and some is borrowed from other languages.

🚧 Work in progress 🚧

Architecture

// The `#[derive(Parse)]` will automatically generate the parsing code based off of our struct
// definition. The `#[error_if_not_found]` attributes are to facilitate better parse error messages.
// The `#[parse_until_next]` attribute is required to resolve ambiguity in parse code generation.
// The code wouldn't compile if it was omitted.

#[derive(GCPtr, Parse, Clone, Copy)]
#[mulch_parse_error(<keyword!["let"]>::EXPECTED_ERROR_FUNCTION)]
pub struct LetIn {
    pub let_: keyword!["let"],

    #[parse_until_next]
    #[error_if_not_found]
    pub variables: SeparatedList<NamedValue, punct![";"]>,

    pub in_: keyword!["in"],

    #[error_if_not_found]
    pub val: OldGCBox<PartialSpanned<Expression>>,
}

Currently implemented features

Language features

Examples

let
    join3_regular = (a, b, c) -> [a, b, c];
    join3_attrs = {a, b, c = "default_c_value"} -> [a, b, c];
    join3_complex = {args: [a, b, c]} -> [a, b, c];
    nop = a -> a;
in
    [
        join3_regular(1, 2, 3),
        join3_attrs{a = "a"; b = "b"},
        join3_complex{args = [3, 1, 4]},
        nop([4, 5, 6]),
    ]

Output:

List [
    List [1, 2, 3],
    List ["a", "b", "default_c_value"],
    List [3, 1, 4],
    List [4, 5, 6],
]

Note that because this is a declarative language, the order in which variables are defined is not relevant, and we can define values that depend on eachother:

  let
      val0 = {
          next = val1;
          value = 42;
      };
      val1 = {
          next = val0;
          value = 72;
      };
  in
      [
          val0.next.next.next.value,
          val0.next.next.next.next.value,
      ]

Output:

List [
    72,
    42,
]

In this case, we're sort of describing a cyclic linked list with two nodes.

Miscellaneous features