Built-In Definitions

/// Nat

dec Nat.Add   : [Nat, Nat] Nat
dec Nat.Sub   : [Nat, Int] Nat
dec Nat.Mul   : [Nat, Nat] Nat
dec Nat.Div   : [Nat, Nat] Nat
dec Nat.Mod   : [Nat, Nat] Nat
dec Nat.Min   : [Nat, Nat] Nat
dec Nat.Max   : [Nat, Int] Nat
dec Nat.Clamp : [Int] [Nat, Nat] Nat

dec Nat.Equals  : [Nat, Nat] Bool
dec Nat.Compare : [Nat, Nat] Ordering

dec Nat.Repeat : [Nat] recursive either {
  .end!,
  .step self,
}

dec Nat.RepeatLazy : [Nat] recursive either {
  .end!,
  .step box choice {
    .next => self,
  }
}

dec Nat.Range : [Nat, Nat] List<Nat>

dec Nat.ToString : [Nat] String

dec Nat.FromString : [String] either {
  .ok Nat,
  .err!,
}


/// Int

dec Int.Add   : [Int, Int] Int
dec Int.Sub   : [Int, Int] Int
dec Int.Mul   : [Int, Int] Int
dec Int.Div   : [Int, Int] Int
dec Int.Mod   : [Int, Nat] Nat
dec Int.Min   : [Int, Int] Int
dec Int.Max   : [Int, Int] Int
dec Int.Abs   : [Int] Nat
dec Int.Clamp : [Int] [Int, Int] Int

dec Int.Equals  : [Int, Int] Bool
dec Int.Compare : [Int, Int] Ordering

dec Int.Range : [Int, Int] List<Int>

dec Int.ToString : [Int] String

dec Int.FromString : [String] either {
  .ok Int,
  .err!,
}


/// Bool

type Bool = either {
  .false!,
  .true!,
}


/// Result

type Result<e, a> = either {
  .ok a,
  .err e,
}

dec Result.Always : <a>[Result<either {}, a>] a
def Result.Always = <a>[result] result.case {
  .ok value => value,
  .err impossible => impossible.case {},
}

type Option<a> = Result<!, a>


/// List

type List<a> = recursive either {
  .end!,
  .item(a) self,
}

type List.Builder<a> = iterative choice {
  .add(a) => self,
  .build => List<a>,
}

type List.Result<e, a> = recursive either {
  .end Result<e, !>,
  .item(a) self,
}

dec List.Builder : [type a] List.Builder<a>
def List.Builder = [type a]
  let append: [List<a>] List<a> = [xs] xs
  in begin case {
    .add(x) => let append = [xs: List<a>] append(.item(x) xs) in loop,
    .build => append(.end!),
  }

dec List.Find : <a>[List<box a>] [box [box a] Bool] Option<a>
def List.Find = <a>[list] [f] list.begin.case {
  .end! => .err!,
  .item(v) list => f(v).case {
    .true! => .ok v,
    .false! => list.loop,
  },
}

dec List.FindLast : <a>[List<box a>] [box [box a] Bool] Option<a>
def List.FindLast = <a>[list] [f]
  let result: Option<box a> = .err! in
  list.begin.case {
    .end! => result,
    .item(v) list => f(v).case {
      .true! => let result = .ok v in list.loop,
      .false! => list.loop,
    },
  }

dec List.Map : <a>[List<a>] [type b] [box [a] b] List<b>
def List.Map = <a>[list] [type b] [f] list.begin.case {
  .end! => .end!
  .item(v) list => .item(f(v)) list.loop,
}

dec List.FlatMap : <a>[List<a>] [type b] [box [a] List<b>] List<b>
def List.FlatMap = <a>[list] [type b] [f] list.begin.case {
  .end! => .end!,
  .item(v) list => f(v).begin@flat.case {
    .end! => list.loop,
    .item(v) flat => .item(v) flat.loop@flat,
  },
}

dec List.Filter : <a>[List<box a>] [box [box a] Bool] List<a>
def List.Filter = <a>[list] [f] list.begin.case {
  .end! => .end!,
  .item(v) list => f(v).case {
    .true! => .item(v) list.loop,
    .false! => list.loop,
  },
}

dec List.Fold : <a>[List<a>] <r>[r] [box [r, a] r] r
def List.Fold = <a>[list] <r>[result] [f] list.begin.case {
  .end! => result,
  .item(v) list => let result = f(result, v) in list.loop,
}

dec List.Reduce : <a>[List<a>] [box [a, a] a] Option<a>
def List.Reduce = <a>[list] [f] list.case {
  .end! => .err!,
  .item(result) list => .ok List.Fold(list, result, f),
}

dec List.Length : <a>[List<box a>] Nat
def List.Length = <a>[list]
  let len = 0 in
  list.begin.case {
    .end! => len,
    .item(_) list => do { len->Nat.Add(1) } in list.loop,
  }

dec List.Concat : <a>[List<List<a>>] List<a>
def List.Concat = <a>[lists] chan yield {
  lists.begin.case {
    .item(list) => {
      yield->List.Copy(list)
      lists.loop
    }
    .end! => {
      yield.end!
    }
  }
}

dec List.Copy : <a>[dual List<a>] [List<a>] dual List<a>
def List.Copy = <a>[dst] [src] do {
  src.begin.case {
    .end! => {},
    .item(v) src => {
      dst.item(v)
      src.loop
    },
  }
} in dst

dec List.MinMax : <a>[List<box a>] [box [box a, box a] Ordering] Option<(a) a>
def List.MinMax = <a>[list] [cmp]
  let result: Option<(box a) box a> = .err! in
  list.begin.case {
    .end! => result,
    .item(v) list => result.case {
      .err! =>
        let result = .ok(v) v in
        list.loop,
      .ok(min) max =>
        let result = cmp(v, min).case {
          .less! => .ok (v) max,
          else _ => cmp(v, max).case {
            .greater! => .ok (min) v,
            else _ => result,
          },
        } in list.loop,
    },
  }

dec List.Min : <a>[List<box a>] [box [box a, box a] Ordering] Option<a>
def List.Min = <a>[list] [cmp]
  List.MinMax(list, cmp).case {
    .err! => .err!,
    .ok(min) _ => .ok min,
  }

dec List.Max : <a>[List<box a>] [box [box a, box a] Ordering] Option<a>
def List.Max = <a>[list] [cmp]
  List.MinMax(list, cmp).case {
    .err! => .err!,
    .ok(_) max => .ok max,
  }

dec List.Zip : <a>[List<box a>] <b>[List<box b>] List<(a) b>
def List.Zip = <a>[list1] <b>[list2] chan yield {
  list1.begin.case {
    .end! => { yield.end! },
    .item(v1) list1 => {
      list2.case {
        .end! => { yield.end! },
        .item(v2) list2 => {
          yield.item((v1) v2)
          list1.loop
        },
      }
    },
  }
}

dec List.Unzip : <a, b>[List<(a) b>] (List<a>) List<b>
def List.Unzip = <a, b>[list] do {
  let list1 = List.Builder(type a)
  let list2 = List.Builder(type b)

  list.begin.case {
    .end! => {},
    .item((v1) v2) list => {
      list1.add(v1)
      list2.add(v2)
      list.loop
    },
  }
} in (list1.build) list2.build

dec List.All : <a>[List<box a>] [box [box a] Bool] Bool
def List.All = <a>[list] [f]
  list.begin.case {
    .end! => .true!,
    .item(v) list => f(v).case {
      .true! => list.loop,
      .false! => .false!,
    },
  }

dec List.Any : <a>[List<box a>] [box [box a] Bool] Bool
def List.Any = <a>[list] [f] List.All(list, box [v] f(v).case {
  .true! => .false!,
  .false! => .true!,
})

dec List.Dedup : <a>[List<box a>] [box [box a, box a] Bool] List<a>
def List.Dedup = <a>[list] [eq]
  list.case {
    .end! => .end!,
    .item(prev) list => .item(prev)
      list.begin.case {
        .end! => .end!,
        .item(v) list => eq(prev, v).case {
          .true! => list.loop,
          .false! =>
            let prev = v in
            .item(v) list.loop,
        }
      }
  }

dec List.Take : <a>[List<box a>] [Nat] List<a>
def List.Take = <a>[list] [n]
  Nat.Repeat(n).begin.case {
    .end! => .end!,
    .step next => list.case {
      .end! => .end!
      .item(v) list => .item(v) next.loop,
    }
  }

dec List.Drop : <a>[List<box a>] [Nat] List<a>
def List.Drop = <a>[list] [n]
  Nat.Repeat(n).begin.case {
    .end! => list,
    .step next => list.case {
      .end! => .end!,
      .item(_) list => next.loop,
    },
  }

dec List.Chunk : <a>[List<a>] [Nat] List<List<a>>
def List.Chunk = <a>[list] [n] chan outer {
  let inner: Option<List.Builder<a>> = .err!
  let i = 0

  list.begin.case {
    .end! => {
      inner.case {
        .err! => {},
        .ok builder => { outer.item(builder.build) },
      }
      outer.end!
    },
    .item(v) list => {
      inner.case {
        .err! => {
          let inner = .ok List.Builder(type a).add(v)
        },
        .ok builder => {
          let inner = .ok builder.add(v)
        },
      }
      i->Nat.Add(1)
      Nat.Equals(i, n).case {
        .true! => {
          inner.case {
            .ok builder => { outer.item(builder.build) },
          }
          let inner = .err!
          let i = 0
          list.loop
        },
        .false! => {
          list.loop
        },
      }
    },
  }
}


/// Ordering

type Ordering = either {
  .less!,
  .equal!,
  .greater!,
}


/// Char

type Char.Class = either {
  .any!,
  .char Char,
  .whitespace!,
  .ascii either {
    .any!,
    .alpha!,
    .alphanum!,
    .digit!,
  },
}

dec Char.Equals : [Char, Char] Bool
dec Char.Code   : [Char] Nat
dec Char.Is     : [Char, Char.Class] Bool


/// String

type String.Builder = iterative choice {
  .add(String) => self,
  .build => String,
}

type String.Parser<e> = recursive iterative@attempt choice {
  .close => Result<e, !>,
  .remainder => Result<e, String>,
  .char => either {
    .end Result<e, !>,
    .char(Char) self,
  },
  .match(String.Pattern, String.Pattern) => either {
    .end Result<e, !>,
    .fail self@attempt,
    .match(String, String) self,
  },
  .matchEnd(String.Pattern, String.Pattern) => either {
    .end Result<e, !>,
    .fail self@attempt,
    .match(String, String)!,
  },
}

type String.Pattern = recursive either {
  .empty!,
  .str String,
  .one Char.Class,
  .non Char.Class,
  .min Nat,
  .max Nat,
  .repeat self,
  .repeat1 self,
  .concat List<self>,
  .and List<self>,
  .or List<self>,
}

dec String.Quote     : [String] String
dec String.FromBytes : [Bytes] String

dec String.Equals    : [String, String] Bool
dec String.Compare   : [String, String] Ordering

dec String.Builder : String.Builder
dec String.Parser  : [String] String.Parser<either {}>

dec String.ParserFromReader : <e>[Bytes.Reader<e>] String.Parser<e>

dec String.Lines : <e>[String.Parser<e>] List.Result<e, String>
def String.Lines = <e>[parser]
  catch e => .end .err e in
  parser.begin.match(.repeat.one.any!, .str "\n").case {
    .end try ! => .end .ok!,
    .fail parser => let try r = parser.remainder in .item(r) .end .ok!,
    .match(line, _) parser => .item(line) parser.loop,
  }

dec String.Join : [List<String>, String] String
def String.Join = [list, sep]
  let builder = String.Builder in
  list.case {
    .end! => builder.build,
    .item(v) list => do {
      builder.add(v)
    } in list.begin.case {
      .end! => builder.build,
      .item(v) list => do {
        builder.add(sep).add(v)
      } in list.loop,
    },
  }

dec String.Concat : [List<String>] String
def String.Concat = [list]
  let builder = String.Builder in
  list.begin.case {
    .end! => builder.build,
    .item(v) list => do {
      builder.add(v)
    } in list.loop,
  }


/// Byte

type Byte.Class = either {
  .any!,
  .byte Byte,
  .range(Byte, Byte)!,
}

dec Byte.Equals : [Byte, Byte] Bool
dec Byte.Code   : [Byte] Nat
dec Byte.Is     : [Byte, Byte.Class] Bool


/// Bytes

type Bytes.Builder = iterative choice {
  .add(Bytes) => self,
  .build => Bytes,
}

type Bytes.Reader<e> = recursive choice {
  .close => Result<e, !>,
  .read => Result<e, either {
    .end!,
    .chunk(Bytes) self,
  }>,
}

type Bytes.Writer<e> = iterative choice {
  .close => Result<e, !>,
  .flush => Result<e, self>,
  .write(Bytes) => Result<e, self>,
}

type Bytes.Parser<e> = recursive iterative@attempt choice {
  .close => Result<e, !>,
  .remainder => Result<e, Bytes>,
  .byte => either {
    .end Result<e, !>,
    .byte(Byte) self,
  },
  .match(Bytes.Pattern, Bytes.Pattern) => either {
    .end Result<e, !>,
    .fail self@attempt,
    .match(Bytes, Bytes) self,
  },
  .matchEnd(Bytes.Pattern, Bytes.Pattern) => either {
    .end Result<e, !>,
    .fail self@attempt,
    .match(Bytes, Bytes)!,
  },
}

type Bytes.Pattern = recursive either {
  .empty!,
  .bytes Bytes,
  .one Byte.Class,
  .non Byte.Class,
  .min Nat,
  .max Nat,
  .repeat self,
  .repeat1 self,
  .concat List<self>,
  .and List<self>,
  .or List<self>,
}

dec Bytes.Equals  : [Bytes, Bytes] Bool
dec Bytes.Compare : [Bytes, Bytes] Ordering
dec Bytes.Length  : [Bytes] Nat
dec Bytes.Builder : Bytes.Builder
dec Bytes.Reader  : [Bytes] Bytes.Reader<either {}>
dec Bytes.Parser  : [Bytes] Bytes.Parser<either {}>

dec Bytes.EmptyReader      : Bytes.Reader<either {}>
dec Bytes.ParserFromReader : <e>[Bytes.Reader<e>] Bytes.Parser<e>

dec Bytes.PipeReader : [type e] [[Bytes.Writer<!>] Result<e, !>] Bytes.Reader<e>


/// Console

type Console = iterative choice {
  .close => !,
  .print(String) => self,
  .prompt(String) => (Option<String>) self,
}

dec Console.Open : Console


/// Os

type Os.Error  = String
type Os.Reader = Bytes.Reader<Os.Error>
type Os.Writer = Bytes.Writer<Os.Error>

type Os.Path = iterative@append recursive@parent box choice {
  .name => Bytes,
  .absolute => Bytes,
  .parts => List<Bytes>,

  .parent => Option<self@parent>,
  .append(Bytes) => self@append,
}

dec Os.Path : [Bytes] Os.Path

dec Os.Stdin  : Os.Reader
dec Os.Stdout : Os.Writer
dec Os.Stderr : Os.Writer

dec Os.OpenFile             : [Os.Path] Result<Os.Error, Os.Reader>
dec Os.CreateOrReplaceFile  : [Os.Path] Result<Os.Error, Os.Writer>
dec Os.CreateNewFile        : [Os.Path] Result<Os.Error, Os.Writer>
dec Os.AppendToFile         : [Os.Path] Result<Os.Error, Os.Writer>
dec Os.CreateOrAppendToFile : [Os.Path] Result<Os.Error, Os.Writer>

dec Os.CreateDir   : [Os.Path] Result<Os.Error, !>
dec Os.ListDir     : [Os.Path] Result<Os.Error, List<Os.Path>>
dec Os.TraverseDir : [Os.Path] Result<Os.Error, recursive either {
  .end!,
  .file(Os.Path) self,
  .dir(Os.Path, self) self,
}>

dec Os.Env : BoxMap.Readonly<Bytes, Bytes>

/// Url

type Url.Error = String

type Url = iterative box choice {
  .full => String,
  .protocol => String,
  .host => String,
  .path => String,
  .query => List<(String) String>,
  .appendPath(String) => self,
  .addQuery(String, String) => self,
}

dec Url.FromString : [String] Result<Url.Error, Url>


/// Http

type Http.Error  = String

type Http.Request =
  (String)
  (Url)
  (List<(String) Bytes>)
  Bytes.Reader<Http.Error>

type Http.Response =
  (Nat)
  (List<(String) Bytes>)
  Bytes.Reader<Http.Error>

dec Http.Fetch : [Http.Request] Result<Http.Error, Http.Response>

dec Http.Listen : [String] recursive either {
  .shutdown Result<Http.Error, !>,
  .incoming(Http.Request, [Http.Response] Result<Http.Error, !>) self,
}


/// Time

dec Time.Now : [!] Nat


/// Map

type Map<k, v> = iterative choice {
  .size => (Nat) self,
  .keys => (List<k>) self,
  .list => List<(k) v>,
  .entry(k) => (Option<v>) choice {
    .put(v) => self,
    .delete => self,
  },
}

dec Map.String : [type v] [List<(String) box v>] Map<String, v>
dec Map.Bytes  : [type v] [List<(Bytes) box v>]  Map<Bytes, v>
dec Map.Int    : [type v] [List<(Int) box v>]    Map<Int, v>
dec Map.Nat    : [type v] [List<(Nat) box v>]    Map<Nat, v>


/// BoxMap

type BoxMap<k, v> = iterative box choice {
  .size => Nat,
  .keys => List<k>,
  .list => List<(k) box v>,
  .get(k) => Option<box v>,
  .put(k, box v) => self,
  .delete(k) => self,
}

type BoxMap.Readonly<k, v> = box choice {
  .size => Nat,
  .keys => List<k>,
  .list => List<(k) box v>,
  .get(k) => Option<box v>,
}

dec BoxMap.String : [type v] [List<(String) box v>] BoxMap<String, v>
dec BoxMap.Bytes  : [type v] [List<(Bytes) box v>]  BoxMap<Bytes, v>
dec BoxMap.Int    : [type v] [List<(Int) box v>]    BoxMap<Int, v>
dec BoxMap.Nat    : [type v] [List<(Nat) box v>]    BoxMap<Nat, v>


/// Cell

type Cell<a> = iterative choice {
  .end => ?,
  .split(dual self) => self,
  .take => (a) choice {
    .put(a) => self,
  }
}

dec Cell.Share : <a>[a] [dual Cell<a>] a


/// Debug

dec Debug.Log : [String] !