(** Some example programs in the Matzo language
 *
 * It is important to note that, in the Matzo language, the value of a
 * variable is generally not a single value, but one of a set of values.
 * Every time a variable is used, an element is drawn from this set;
 * so the following program can print 1, 2, 3, 10, 20, or 30. *)

x := 1 | 2 | 3;
f := { n => x } 
   | { n => n * 10 };
puts f(x);


(** The Aquan language program *)

(* The ::= operator is for the common case that we want to select from a
 * whole bunch of literal characters or words. It is referred to as the
 * 'literal assignment operator'. *)
vowel ::= a e i o u;
consonant ::= p t k w h m n l;

(* Normally, each alternative has equal weight, but explicit weights can be
 * given; weights which are not given are considered to be 1. *)
syll := 4: vowel | 4: consonant vowel
      | vowel "'" | consonant vowel "'";

(* The `n @ value` syntax represents 1 to n possible repetitions of value.
 * e.g. 3 @ ("a" | "b") is the same as
 * ( ("a" | "b")
 * | ("a" | "b") ("a" | "b")
 * | ("a" | "b") ("a" | "b") ("a" | "b") )
 * and is given special syntax because it is a common case in word generation.
 * Below, it means that every word will have at least three and at most eight
 * syllables. *)
word := syll syll (6 @ syll);
puts word;


(** Fixing a value *)

(* The built-in pseudo-function `choose` allows you to force a value
 * to stay the same. *)

n := 1 | 2;
m := choose(n);
(* The following could print either "1,2", "2,1" "1,1" or "2,2" *)
puts "{n},{n}"
(* The following can only print "1,1" or "2,2" *)
puts "{m},{m}"


(** A random person description *)

(* Identifiers that begin with capitals are symbols. Symbols can be
 * compared and matched against. It is not allowed to use an identifier
 * that begins with a capital as a variable. *)

pronoun := 
  { Male => "he"
  | Female => "she"
  };
person :=
  { Male => "man"
  | Female => "woman"
  };

gender := choose(Male | Female);
hair ::= long short;
hair_color ::= brown black blonde red white;
eye_color ::= blue black brown green;
mood ::= happy sad angry;

puts "This {person(gender)} has {hair}, {hair_color} hair and "
     "{eye_color} eyes; {pronoun(gender)} appears to be "
     "quite {mood}.";