package Sorting api;
import Carbon library "Printing";

fn Partition[T:! Comparable & Movable](s: Slice(T))
      -> i64 {
  var i: i64 = -1;
  let (x: i64, var y: auto) = (1, {.x = {.a = (1, {.k = 42}), .b = 13}, .y = "..."});

  for (e: T in s) {
    if (e <= s.Last()) {
      ++i;
      Swap(&s[i], &e);
    }
  }
  return i;
}

fn QuickSort[T:! Comparable & Movable](s: Slice(T)) {
  if (s.Size() <= 1) {
    return;
  }
  let p: i64 = Partition(s);
  QuickSort(s[:p - 1]));
  QuickSort(s[p + 1:]));
}

interface WidgetI {
}

constraint WidgetC {
}

abstract class Abstract {
  abstract fn DoSomething[self: Self]();
}

base class Widget {
  virtual fn Print[addr self: Self*](var i: i64, x: f32 = 4.2, _: bool);
}

fn Widget.Print[addr self: Self*](var i: i64, x: f32, _: bool, 47) {
  Carbon.Print("test" + "t\u{FFFF}his");
  Carbon.Print(
      """
      testing more
      with weird stuff \
      that does stuff
      """);
  Carbon.Print(
      """c++
      template <typename T> class C {};
      """);
}

class FancyWidget(T:! type) extends Widget {
  impl fn Print[self: Self]();

  impl as Add(T) {
    fn Op[self: Self]();
  }
}

fn FancyWidget(T:! type).Print[self: Self]() {
  Carbon.Print("more test");
}

impl forall [T:! type] FancyWidget(T) as Printable {
  alias Print = FancyWidget(T).Print;
}