// examples/length translated by mycpp

// BEGIN mycpp output

#include "mycpp/runtime.h"

GLOBAL_STR(str0, "foo");
GLOBAL_STR(str1, "bar");
GLOBAL_STR(str2, "foo");
GLOBAL_STR(str3, "a == b  ->  %d");
GLOBAL_STR(str4, "a != b  ->  %d");
GLOBAL_STR(str5, "a == y  ->  %d");
GLOBAL_STR(str6, "a != y  ->  %d");
GLOBAL_STR(str7, "a == n  ->  %d");
GLOBAL_STR(str8, "a != n  ->  %d");
GLOBAL_STR(str9, "abcd");
GLOBAL_STR(str10, "len(mystr) = %d");
GLOBAL_STR(str11, "mystr[1] = %s");
GLOBAL_STR(str12, "mystr[1:] = %s");
GLOBAL_STR(str13, "mystr[1:3] = %s");
GLOBAL_STR(str14, "mystr[:-2] = %s");
GLOBAL_STR(str15, "b");
GLOBAL_STR(str16, "c = %s");
GLOBAL_STR(str17, "c");
GLOBAL_STR(str18, "");
GLOBAL_STR(str19, "w");
GLOBAL_STR(str20, "x");
GLOBAL_STR(str21, "y");
GLOBAL_STR(str22, "z");
GLOBAL_STR(str23, "len(mylist) = %d");
GLOBAL_STR(str24, "mylist[1] = %s");
GLOBAL_STR(str25, "len(mylist[1:]) = %d");
GLOBAL_STR(str26, "x");
GLOBAL_STR(str27, "c = %s");
GLOBAL_STR(str28, "y");
GLOBAL_STR(str29, "a");
GLOBAL_STR(str30, "%s != a");
GLOBAL_STR(str31, "");
GLOBAL_STR(str32, "abcd");
GLOBAL_STR(str33, "w");
GLOBAL_STR(str34, "x");
GLOBAL_STR(str35, "y");
GLOBAL_STR(str36, "z");
GLOBAL_STR(str37, "result = %d");
GLOBAL_STR(str38, "iterations = %d");

namespace length {  // forward declare


}  // forward declare namespace length

namespace length {  // declare

void TestMaybeStrEquals();
void run_tests();
void run_benchmarks();

}  // declare namespace length

namespace length {  // define


void TestMaybeStrEquals() {
  BigStr* a = nullptr;
  BigStr* b = nullptr;
  BigStr* y = nullptr;
  BigStr* n = nullptr;
  a = str0;
  b = str1;
  y = str2;
  n = nullptr;
  mylib::print_stderr(StrFormat("a == b  ->  %d", str_equals(a, b)));
  mylib::print_stderr(StrFormat("a != b  ->  %d", !(str_equals(a, b))));
  mylib::print_stderr(StrFormat("a == y  ->  %d", maybe_str_equals(a, y)));
  mylib::print_stderr(StrFormat("a != y  ->  %d", !(maybe_str_equals(a, y))));
  mylib::print_stderr(StrFormat("a == n  ->  %d", maybe_str_equals(a, n)));
  mylib::print_stderr(StrFormat("a != n  ->  %d", !(maybe_str_equals(a, n))));
}

void run_tests() {
  BigStr* mystr = nullptr;
  List<BigStr*>* mylist = nullptr;
  BigStr* c2 = nullptr;
  mystr = str9;
  mylib::print_stderr(StrFormat("len(mystr) = %d", len(mystr)));
  mylib::print_stderr(StrFormat("mystr[1] = %s", mystr->at(1)));
  mylib::print_stderr(StrFormat("mystr[1:] = %s", mystr->slice(1)));
  mylib::print_stderr(StrFormat("mystr[1:3] = %s", mystr->slice(1, 3)));
  mylib::print_stderr(StrFormat("mystr[:-2] = %s", mystr->slice(0, -2)));
  for (StrIter it(mystr); !it.Done(); it.Next()) {
    BigStr* c = it.Value();
    StackRoot _for(&c  );
    if (str_equals(c, str15)) {
      continue;
    }
    mylib::print_stderr(StrFormat("c = %s", c));
    if (str_equals(c, str17)) {
      break;
    }
  }
  mylib::print_stderr(str18);
  mylist = NewList<BigStr*>(std::initializer_list<BigStr*>{str19, str20, str21, str22});
  mylib::print_stderr(StrFormat("len(mylist) = %d", len(mylist)));
  mylib::print_stderr(StrFormat("mylist[1] = %s", mylist->at(1)));
  mylib::print_stderr(StrFormat("len(mylist[1:]) = %d", len(mylist->slice(1))));
  for (ListIter<BigStr*> it(mylist); !it.Done(); it.Next()) {
    BigStr* c = it.Value();
    StackRoot _for(&c  );
    if (str_equals(c, str26)) {
      continue;
    }
    mylib::print_stderr(StrFormat("c = %s", c));
    if (str_equals(c, str28)) {
      break;
    }
  }
  c2 = nullptr;
  for (StrIter it(mystr); !it.Done(); it.Next()) {
    BigStr* c2 = it.Value();
    StackRoot _for(&c2  );
    if (!(str_equals(c2, str29))) {
      mylib::print_stderr(StrFormat("%s != a", c2));
    }
  }
  mylib::print_stderr(str31);
  TestMaybeStrEquals();
}

void run_benchmarks() {
  int n;
  BigStr* mystr = nullptr;
  List<BigStr*>* mylist = nullptr;
  int result;
  int i;
  StackRoot _root0(&mystr);
  StackRoot _root1(&mylist);

  n = 1000000;
  mystr = str32;
  mylist = NewList<BigStr*>(std::initializer_list<BigStr*>{str33, str34, str35, str36});
  result = 0;
  i = 0;
  while (i < n) {
    result += len(mystr->slice(1));
    result += len(mylist->slice(1));
    i += 1;
    mylib::MaybeCollect();
  }
  mylib::print_stderr(StrFormat("result = %d", result));
  mylib::print_stderr(StrFormat("iterations = %d", n));
}

}  // define namespace length

int main(int argc, char **argv) {
  gHeap.Init();

  char* b = getenv("BENCHMARK");
  if (b && strlen(b)) {  // match Python's logic
    fprintf(stderr, "Benchmarking...\n");
    length::run_benchmarks();
  } else {
    length::run_tests();
  }

  gHeap.CleanProcessExit();
}