[
  {
    "path": ".gitattributes",
    "content": "text=auto\r\n"
  },
  {
    "path": ".gitignore",
    "content": "# Main\r\n*.log\r\n*~\r\n*.libs\r\n*.o\r\n*.la\r\n*.so*\r\n*.a\r\n*.lo\r\n*.dll\r\n*.exe\r\n*.gz\r\n*.class\r\n\r\n# Tests\r\ntest.bin\r\ntest.txt\r\ntest.exe\r\ntest\r\n\r\n# Benchmarking\r\nprofile.txt\r\n\r\n# Dist\r\nlibCello*\r\n\r\n# VIM related\r\n.clang_complete\r\n\r\n# benchmark programs\r\nbenchmarks/Dict/dict_c\r\nbenchmarks/Dict/dict_cello\r\nbenchmarks/Dict/dict_cpp\r\nbenchmarks/ext/genint\r\nbenchmarks/GC/gc_c\r\nbenchmarks/GC/gc_cello\r\nbenchmarks/GC/gc_cpp\r\nbenchmarks/List/list_c\r\nbenchmarks/List/list_cello\r\nbenchmarks/List/list_cpp\r\nbenchmarks/Map/map_c\r\nbenchmarks/Map/map_cello\r\nbenchmarks/Map/map_cpp\r\nbenchmarks/Matmul/matmul_c\r\nbenchmarks/Matmul/matmul_cello\r\nbenchmarks/Matmul/matmul_cpp\r\nbenchmarks/Nbodies/nbodies_c\r\nbenchmarks/Nbodies/nbodies_cello\r\nbenchmarks/Nbodies/nbodies_cpp\r\nbenchmarks/Sudoku/sudoku_c\r\nbenchmarks/Sudoku/sudoku_cello\r\nbenchmarks/Sudoku/sudoku_cpp\r\n"
  },
  {
    "path": "LICENSE.md",
    "content": "Licensed Under BSD\n\nCopyright (c) 2012, Daniel Holden\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met: \n\n1. Redistributions of source code must retain the above copyright notice, this\n   list of conditions and the following disclaimer. \n2. Redistributions in binary form must reproduce the above copyright notice,\n   this list of conditions and the following disclaimer in the documentation\n   and/or other materials provided with the distribution. \n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nThe views and conclusions contained in the software and documentation are those\nof the authors and should not be interpreted as representing official policies, \neither expressed or implied, of the FreeBSD Project."
  },
  {
    "path": "Makefile",
    "content": "CC ?= gcc\nAR ?= ar\n\nVERSION = 2.1.0\nPACKAGE = libCello-$(VERSION)\n\nBINDIR = ${PREFIX}/bin\nINCDIR = ${PREFIX}/include\nLIBDIR = ${PREFIX}/lib\n\nSRC := $(wildcard src/*.c)\nOBJ := $(addprefix obj/,$(notdir $(SRC:.c=.o)))\n\nTESTS := $(wildcard tests/*.c)\nTESTS_OBJ := $(addprefix obj/,$(notdir $(TESTS:.c=.o)))\n\nEXAMPLES := $(wildcard examples/*.c)\nEXAMPLES_OBJ := $(addprefix obj/,$(notdir $(EXAMPLES:.c=.o)))\nEXAMPLES_EXE := $(EXAMPLES:.c=)\n\nCFLAGS = -I ./include -std=gnu99 -Wall -Wno-unused -g -ggdb\n\nPLATFORM := $(shell uname)\nCOMPILER := $(shell $(CC) -v 2>&1 )\n\nifeq ($(findstring CYGWIN,$(PLATFORM)),CYGWIN)\n\tPREFIX ?= /usr/local\n\t\n\tDYNAMIC = libCello.so\n\tSTATIC = libCello.a\n\tLIBS = -lpthread -lm\n\t\n\tifneq (,$(wildcard ${LIBDIR}/libdbghelp.a))\n\t\tLIBS += -lDbgHelp\n\telse\n\t\tCFLAGS += -DCELLO_NSTRACE\n\tendif\n  \n\tINSTALL_LIB = mkdir -p ${LIBDIR} && cp -f ${STATIC} ${LIBDIR}/$(STATIC)\n\tINSTALL_INC = mkdir -p ${INCDIR} && cp -r include/Cello.h ${INCDIR}\n\tUNINSTALL_LIB = rm -f ${LIBDIR}/$(STATIC)\n\tUNINSTALL_INC = rm -f ${INCDIR}/Cello.h\nelse ifeq ($(findstring MINGW,$(PLATFORM)),MINGW)\n\t# MSYS2\n\tifeq ($(findstring MINGW32,$(MSYSTEM)),MINGW32)\n\t\tCC = i686-w64-mingw32-gcc\n\t\tPREFIX ?= /mingw32\n\telse ifeq ($(findstring MINGW64,$(MSYSTEM)),MINGW64)\n\t\tCC = x86_64-w64-mingw32-gcc\n\t\tPREFIX ?= /mingw64\n\telse ifeq ($(findstring MSYS,$(MSYSTEM)),MSYS)\n\t\tCC = gcc\n\t\tPREFIX ?= /usr\n\telse\n\t\t# MinGW64 mingw-builds\n\t\tprefix ?= c:/mingw64/x86_64-w64-mingw32\n\tendif\n\n\tDYNAMIC = libCello.dll\n\tSTATIC = libCello.a\n  \n\tifneq (,$(wildcard ${LIBDIR}/libdbghelp.a))\n\t\tLIBS += -lDbgHelp\n\telse\n\t\tCFLAGS += -DCELLO_NSTRACE\n\tendif\n\t\n\tINSTALL_LIB = cp $(STATIC) $(LIBDIR)/$(STATIC); cp $(DYNAMIC) $(BINDIR)/$(DYNAMIC)\n\tINSTALL_INC = cp -r include/Cello.h $(INCDIR)\n\tUNINSTALL_LIB = rm -f ${LIBDIR}/$(STATIC); rm -f ${BINDIR}/$(DYNAMIC)\n\tUNINSTALL_INC = rm -f ${INCDIR}/Cello.h\nelse ifeq ($(findstring FreeBSD,$(PLATFORM)),FreeBSD)\n\tPREFIX ?= /usr/local\n\n\tDYNAMIC = libCello.so\n\tSTATIC = libCello.a\n\tLIBS = -lpthread -lm\n\n\tCFLAGS += -fPIC\n\n\tifneq (,$(wildcard ${LIBDIR}/libexecinfo.a))\n\t\tLIBS += -lexecinfo\n\t\tLFLAGS += -rdynamic\n\telse\n\t\tCFLAGS += -DCELLO_NSTRACE\n\tendif\n  \n\tINSTALL_LIB = mkdir -p ${LIBDIR} && cp -f ${STATIC} ${LIBDIR}/$(STATIC)\n\tINSTALL_INC = mkdir -p ${INCDIR} && cp -r include/Cello.h ${INCDIR}\n\tUNINSTALL_LIB = rm -f ${LIBDIR}/$(STATIC)\n\tUNINSTALL_INC = rm -f ${INCDIR}/Cello.h\nelse\n\tPREFIX ?= /usr/local\n\n\tDYNAMIC = libCello.so\n\tSTATIC = libCello.a\n\tLIBS = -lpthread -lm\n\n\tCFLAGS += -fPIC\n  \n\tifneq (,$(wildcard ${LIBDIR}/libexecinfo.a))\n\t\tLIBS += -lexecinfo\n\t\tLFLAGS += -rdynamic\n\telse\n\t\tCFLAGS += -DCELLO_NSTRACE\n\tendif\n  \n\tINSTALL_LIB = mkdir -p ${LIBDIR} && cp -f ${STATIC} ${LIBDIR}/$(STATIC)\n\tINSTALL_INC = mkdir -p ${INCDIR} && cp -r include/Cello.h ${INCDIR}\n\tUNINSTALL_LIB = rm -f ${LIBDIR}/$(STATIC)\n\tUNINSTALL_INC = rm -f ${INCDIR}/Cello.h\nendif\n\n# Libraries\n\nall: $(DYNAMIC) $(STATIC)\n\n$(DYNAMIC): $(OBJ)\n\t$(CC) $(OBJ) -shared $(LFLAGS) $(LIBS) -o $@\n\n$(STATIC): $(OBJ)\n\t$(AR) rcs $@ $(OBJ)\n\nobj/%.o: src/%.c include/Cello.h | obj\n\t$(CC) $< -c $(CFLAGS) -o $@\n\nobj:\n\tmkdir -p obj\n\n# Tests\n\ncheck: CFLAGS += -Werror -g -ggdb\ncheck: $(TESTS_OBJ) $(STATIC)\n\t$(CC) $(TESTS_OBJ) $(STATIC) $(LIBS) $(LFLAGS) -o ./tests/test\n\t./tests/test\n\trm -f ./tests/test.bin ./tests/test.txt\n\nobj/%.o: tests/%.c | obj\n\t$(CC) $< -c $(CFLAGS) -o $@\n\n# Benchmarks\nifeq ($(findstring Darwin,$(PLATFORM)),Darwin)\nbench: CFLAGS += -DCELLO_NDEBUG -O3\nbench: clean $(STATIC)\n\tcd benchmarks; ./benchmark.sh; cd ../\nelse\nbench: CFLAGS += -DCELLO_NDEBUG -pg -O3\nbench: clean $(STATIC)\n\tcd benchmarks; ./benchmark; cd ../\nendif\n\n# Examples\n\nexamples: $(EXAMPLES_EXE)\n\nexamples/%: CFLAGS += -Werror\nexamples/%: examples/%.c $(STATIC) | obj\n\t$(CC) $< $(STATIC) $(CFLAGS) $(LIBS) $(LFLAGS) -o $@\n\n# Dist\n\ndist: all | $(PACKAGE)\n\tcp -R examples include src tests LICENSE.md Makefile README.md $(PACKAGE)\n\ttar -czf $(PACKAGE).tar.gz $(PACKAGE) --exclude='*.exe' --exclude='*.pdb'\n\n$(PACKAGE):\n\tmkdir -p $(PACKAGE)\n\n# Clean\n\nclean:\n\trm -f $(OBJ) $(TESTS_OBJ) $(EXAMPLES_OBJ) $(STATIC) $(DYNAMIC) tests/test\n\n# Install\n\ninstall: all\n\t$(INSTALL_LIB)\n\t$(INSTALL_INC)\n\t\n# Uninstall\n\nuninstall:\n\t$(UNINSTALL_LIB)\n\t$(UNINSTALL_INC)\n\n"
  },
  {
    "path": "README.md",
    "content": "Cello\n=====\n\n__Cello__ is a _library_ that brings higher level programming to C.\n\nBy acting as a _modern_, _powerful_ runtime system Cello makes many things easy \nthat were previously impractical or awkward in C such as:\n\n* __Generic Data Structures__\n* __Polymorphic Functions__\n* __Interfaces / Type Classes__\n* __Constructors / Destructors__\n* __Optional Garbage Collection__\n* __Exceptions__\n* __Reflection__\n\nAnd because Cello works seamlessly alongside standard C you get all the other \nbenefits such as great performance, powerful tooling, and extensive \nlibraries.\n\nExamples\n--------\n\n```c\n#include \"Cello.h\"\n\nint main(int argc, char** argv) {\n\n  /* Stack objects are created using \"$\" */\n  var i0 = $(Int, 5);\n  var i1 = $(Int, 3);\n  var i2 = $(Int, 4);\n\n  /* Heap objects are created using \"new\" */\n  var items = new(Array, Int, i0, i1, i2);\n  \n  /* Collections can be looped over */\n  foreach (item in items) {\n    print(\"Object %$ is of type %$\\n\",\n      item, type_of(item));\n  }\n  \n  /* Heap objects destructed via Garbage Collection */\n  return 0;\n}\n```\n\n```c\n#include \"Cello.h\"\n\nint main(int argc, char** argv) {\n  \n  /* Shorthand $ can be used for basic types */\n  var prices = new(Table, String, Int);\n  set(prices, $S(\"Apple\"),  $I(12)); \n  set(prices, $S(\"Banana\"), $I( 6)); \n  set(prices, $S(\"Pear\"),   $I(55)); \n\n  /* Tables also support iteration */\n  foreach (key in prices) {\n    var val = get(prices, key);\n    print(\"Price of %$ is %$\\n\", key, val);\n  }\n  \n  return 0;\n}\n```\n\nArticles\n--------\n\nLearning Resources:\n\n* [Installation](http://libcello.org/learn/installation)\n* [Cello World](http://libcello.org/learn/cello-world)\n* [Quickstart](http://libcello.org/learn/quickstart)\n* [Common Queries / Pitfalls](http://libcello.org/learn/queries-and-pitfalls)\n\nArticles about its creation and internal workings:\n\n* [Best Improvements of Cello 2.0](http://libcello.org/learn/best-improvements-of-cello-2.0)\n* [A Fat Pointer Library](http://libcello.org/learn/a-fat-pointer-library)\n* [Cello vs C++ vs ObjC](http://libcello.org/learn/cello-vs-cpp-vs-objc)\n* [Benchmarks](http://libcello.org/learn/benchmarks)\n* [Garbage Collection](http://libcello.org/learn/garbage-collection)\n\n\nMore Examples\n-------------\n\n```c\n#include \"Cello.h\"\n\nint main(int argc, char** argv) {\n\n  var items = new(Array, Int, \n    $I( 8), $I( 5), $I(20), \n    $I(15), $I(16), $I(98));\n\n  /* Iterate over indices using \"range\" */\n  foreach (i in range($I(len(items)))) {\n    print(\"Item Range %i is %i\\n\", i, get(items, i));\n  }\n\n  /* Iterate over every other item with \"slice\" */ \n  foreach (item in slice(items, _, _, $I(2))) {\n    print(\"Item Slice %i\\n\", item);\n  }\n  \n  return 0;\n}\n```\n    \n```c\n#include \"Cello.h\"\n\n/* Define a normal C structure */\nstruct Point {\n  float x, y;\n};\n\n/* Make it compatible with Cello */\nvar Point = Cello(Point);\n\nint main(int argc, char** argv) {\n  \n  /* Create on Stack or Heap */\n  var p0 = $(Point, 0.0, 1.0);\n  var p1 = new(Point, $(Point, 0.0, 2.0));\n  \n  /* It can be shown, compared, hashed, etc...\n  **\n  ** p0: <'Point' At 0x000000000022FC58>\n  ** p1: <'Point' At 0x00000000004C7CC8>\n  ** cmp: 1\n  ** hash: 2849275892l\n  */ \n  print(\"p0: %$\\np1: %$\\ncmp: %i\\nhash: %ul\\n\",\n    p0, p1, $I(cmp(p0, p1)), $I(hash(p0)));\n  \n  /* And collected by the GC when out of scope */\n  return 0;\n}\n```\n\nF.A.Q\n-----\n\n* __Why does this exist?__\n\nI made Cello as a fun experiment to see what C looks like hacked to its limits. \nAs well as being a powerful library and toolkit, it should be interesting to \nthose who want to explore what is possible in C.\n\n* __How does it work?__\n\nI recommend reading \n[A Fat Pointer Library](http://libcello.org/learn/a-fat-pointer-library) to get an \noverview of how Cello works. You can also peek at the source code, which I'm \ntold is fairly readable, or ask me any questions you like via e-mail.\n\n* __Can it be used in Production?__\n\nIt might be better to try Cello out on a hobby project first. Cello does aim to \nbe _production ready_, but because it is a hack it has its fair share of \noddities and pitfalls, and if you are working in a team, or to a deadline, \nthere is much better tooling, support and community for languages such as C++.\n\n* __Is anyone using Cello?__\n\nPeople have experimented with it, but there is no high profile project I know \nof that uses it. Cello is too big and scary a dependency for new C projects if \nthey want to be portable and easy to maintain.\n\n* __Can I get involved?__\n\nYes! That would be great. If you do anything with Cello I'd love to know, you \ncan e-mail me at `contact@theorangeduck.com`, or help with the development at \nthe [Cello github repo](https://github.com/orangeduck/libCello). Contributions \nare very welcome.\n\n* __Who are you?__\n\nHello! I'm Daniel Holden. You many know me from a \n[book I wrote](http://www.buildyourownlisp.com/) or my \n[personal website](http://theorangeduck.com/). I also have a rarely updated \n[twitter account](https://twitter.com/anorangeduck).\n"
  },
  {
    "path": "TODO.md",
    "content": "Cello 2.0\n=========\n\nCello REPL\n==========\n\n* REPL\n  - Python prototype\n  - Parse CPP and extract defines.\n  - Parse Syntax tree and extract type/variable declarations\n  - Record those in permanent storage which is added to every file\n"
  },
  {
    "path": "benchmarks/Dict/dict_c.c",
    "content": "#include <stdio.h>\n#include \"khash.h\"\nKHASH_MAP_INIT_STR(str, int)\n\n#define BUF_SIZE 0x10000\n#define BLOCK_SIZE 0x100000\n\nint main(int argc, char *argv[])\n{\n\tchar *buf, **mem = 0;\n\tint ret, max = 1, block_end = 0, curr = 0;\n\tkhint_t k;\n\tkhash_t(str) *h;\n\tbuf = malloc(BUF_SIZE); // string buffer\n\th = kh_init(str);\n\tmem = malloc(sizeof(void*));\n\tmem[0] = malloc(BLOCK_SIZE); // memory buffer to avoid memory fragments\n\tcurr = block_end = 0;\n\twhile (!feof(stdin)) {\n\t\tfgets(buf, BUF_SIZE, stdin);\n\t\tk = kh_put(str, h, buf, &ret);\n\t\tif (ret) { // absent\n\t\t\tint l = strlen(buf) + 1;\n\t\t\tif (block_end + l > BLOCK_SIZE) {\n\t\t\t\t++curr; block_end = 0;\n\t\t\t\tmem = realloc(mem, (curr + 1) * sizeof(void*));\n\t\t\t\tmem[curr] = malloc(BLOCK_SIZE);\n\t\t\t}\n\t\t\tmemcpy(mem[curr] + block_end, buf, l);\n\t\t\tkh_key(h, k) = mem[curr] + block_end;\n\t\t\tblock_end += l;\n\t\t\tkh_val(h, k) = 1;\n\t\t} else {\n\t\t\t++kh_val(h, k);\n\t\t\tif (kh_val(h, k) > max) max = kh_val(h, k);\n\t\t}\n\t}\n\t//printf(\"%u\\t%d\\n\", kh_size(h), max);\n\tfor (ret = 0; ret <= curr; ++ret) free(mem[ret]);\n\tfree(mem);\n\tkh_destroy(str, h);\n\tfree(buf);\n\treturn 0;\n}\n"
  },
  {
    "path": "benchmarks/Dict/dict_cello.c",
    "content": "#include \"Cello.h\"\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\nenum {\n  BUF_SIZE = 0x10000\n};\n\nint main(int argc, char *argv[]) {\n\tvar h = new(Table, String, Int);\n\tresize(h, 1500000);\n\tint max = 1;\n\tchar *buf = malloc(BUF_SIZE);\n\twhile (!feof(stdin)) {\n\t\tfgets(buf, BUF_SIZE, stdin);\n\t\tvar key = $S(buf);\n\t\tif (mem(h, key)) {\n\t\t\tstruct Int* v = get(h, key);\n\t\t\tv->val++;\n\t\t\tif (max < v->val) { max = v->val; }\n\t\t} else {\n\t\t\tset(h, key, $I(1));\n\t\t}\n\t}\n\tdel(h);\n\treturn 0;\n}\n"
  },
  {
    "path": "benchmarks/Dict/dict_cpp.cpp",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <utility>\n#include <unordered_map>\n\nusing namespace std;\n\nstruct eqstr {\n\tinline bool operator()(const char *s1, const char *s2) const {\n\t\treturn strcmp(s1, s2) == 0;\n    }\n};\n\nnamespace std {\n\ttemplate<>\n\tstruct hash<const char *> : public std::unary_function<const char *, size_t> {\n\t\tsize_t operator()(const char *s) const\n\t\t{ \n\t\t\tsize_t h = *s;\n\t\t\tif (h) for (++s ; *s; ++s) h = (h << 5) - h + *s;\n\t\treturn h;\n\t\t}\n\t};\n}\n\ntypedef unordered_map<const char*, int, hash<const char*>, eqstr> strhash;\n\n#define BUF_SIZE 0x10000\n#define BLOCK_SIZE 0x100000\n\nint main(int argc, char *argv[])\n{\n\tchar *buf;\n\tint ret, max = 1, block_end = 0, curr = 0;\n\tchar **mem;\n\tstrhash *h = new strhash;\n\tbuf = (char*)malloc(BUF_SIZE); // buffer size\n\tmem = (char**)malloc(sizeof(void*));\n\tmem[0] = (char*)malloc(BLOCK_SIZE); // memory buffer to avoid memory fragments\n\tcurr = block_end = 0;\n\twhile (!feof(stdin)) {\n\t\tfgets(buf, BUF_SIZE, stdin);\n\t\tstrhash::iterator p = h->find(buf);\n\t\tif (p == h->end()) {\n\t\t\tint l = strlen(buf) + 1;\n\t\t\tif (block_end + l > BLOCK_SIZE) {\n\t\t\t\t++curr; block_end = 0;\n\t\t\t\tmem = (char**)realloc(mem, (curr + 1) * sizeof(void*));\n\t\t\t\tmem[curr] = (char*)malloc(BLOCK_SIZE);\n\t\t\t}\n\t\t\tmemcpy(mem[curr] + block_end, buf, l);\n\t\t\th->insert(pair<const char*, int>(mem[curr] + block_end, 1));\n\t\t\tblock_end += l;\n\t\t} else {\n\t\t\t++p->second;\n\t\t\tif (max < p->second) max = p->second;\n\t\t}\n\t}\n\t//printf(\"%u\\t%d\\n\", h->size(), max);\n\tfor (int i = 0; i <= curr; ++i) free(mem[i]);\n\tfree(mem); free(buf);\n\tdelete h;\n\treturn 0;\n}\n"
  },
  {
    "path": "benchmarks/Dict/dict_cs.cs",
    "content": "using System;\nusing System.Collections.Generic;\n\nclass dict_v1 {\n\tstatic void Main() {\n\t\tstring l;\n\t\tDictionary<string, int> h = new Dictionary<string, int>();\n\t\tint max = 1;\n\t\twhile ((l = Console.ReadLine()) != null) {\n\t\t\tint v;\n\t\t\tif (h.TryGetValue(l, out v)) {\n\t\t\t\tif (v+1 > max) max = v+1;\n\t\t\t\th[l] = v+1;\n\t\t\t} else h[l] = 1;\n\t\t}\n\t\tConsole.WriteLine(h.Count);\n\t\tConsole.WriteLine(max);\n\t}\n}\n"
  },
  {
    "path": "benchmarks/Dict/dict_d.d",
    "content": "// This program segfaults at the end of the input file. I think this is a bug\n// of GDC. I can use std.stream or std.c.stdio instead, but those modules are\n// extremely slow. In the end, I decide to specify the number of lines at the\n// command line. Pretty nasty.\n\nimport std.stdio, std.string;\n\nvoid main(string[] args) {\n\tint N = 5000000;\n\tchar[] buf;\n\tint[char[]] h;\n\tint max = 1, n = 0;\n\tif (args.length >= 2) N = atoi(args[1]);\n\twhile (readln(stdin, buf)) {\n\t\tint current = ++h[buf];\n\t\tmax = (current > max)? current : max;\n\t\tif (++n == N) {\n\t\t\twritef(h.length); writef(\"\\t\"); writefln(max);\n\t\t}\n\t}\n\twritef(h.length); writef(\"\\t\"); writefln(max);\n}\n"
  },
  {
    "path": "benchmarks/Dict/dict_go.go",
    "content": "// Contributed by Pat\npackage main\n\nimport (\n\t\"fmt\"\n\t\"bufio\"\n\t\"os\"\n)\n\nfunc main() {\n\tr := bufio.NewReader(os.Stdin)\n\th := make(map[string]int, 1e6)\n\tmax := 1\n\tfor {\n\t\tb, e := r.ReadSlice('\\n')\n\t\tif e != nil {\n\t\t\tbreak\n\t\t}\n\t\tl := string(b)\n\t\tv := h[l] + 1\n\t\th[l] = v\n\t\tif v > max {\n\t\t\tmax = v\n\t\t}\n\t}\n\tfmt.Printf(\"%d\\t%d\\n\", len(h), max)\n}\n"
  },
  {
    "path": "benchmarks/Dict/dict_java.java",
    "content": "import java.util.HashMap;\nimport java.io.*;\n\nclass dict_java {\n\tpublic static void main(String[] args) {\n\t\tBufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));\n\t\tHashMap<String, Integer> h = new HashMap<String, Integer>();\n\t\tString l;\n\t\tint max = 0;\n\t\ttry {\n\t\t\twhile ((l = stdin.readLine()) != null) {\n\t\t\t\tint x = 1;\n\t\t\t\tif (h.containsKey(l)) {\n\t\t\t\t\tx = h.get(l) + 1;\n\t\t\t\t\th.put(l, x);\n\t\t\t\t\tif (x > max) max = x;\n\t\t\t\t} else h.put(l, 1);\n\t\t\t}\n\t\t} catch (IOException e) {\n\t\t}\n\t\t//System.out.println(h.size()+\"\\t\"+max);\n\t}\n}\n"
  },
  {
    "path": "benchmarks/Dict/dict_javascript.js",
    "content": "\n\nvar h = {}, n = 0, max = 0;\nfunction processLine (l) {\n\tif (h[l]) {\n\t\t++h[l];\n\t\tif (max < h[l]) max = h[l];\n\t} else h[l] = 1, ++n;\n}\n\nvar readline = require('readline');\nvar rl = readline.createInterface({\n  input: process.stdin,\n  output: process.stdout,\n  terminal: false\n});\n\nrl.on('line', function(line){\n    processLine(line);\n})\n\n//print(n, max)\n"
  },
  {
    "path": "benchmarks/Dict/dict_lua.lua",
    "content": "local h, max, n = {}, 0, 0\nfor l in io.lines() do\n\tif (h[l]) then h[l] = h[l] + 1\n\telse n, h[l] = n + 1, 1 end\n\tmax = max > h[l] and max or h[l]\nend\n-- print(n, max)\n"
  },
  {
    "path": "benchmarks/Dict/dict_perl.pl",
    "content": "my (%h, $max);\n\nwhile (<>) {\n    next if (++$h{$_} > $max);\n    $max = $h{$_};\n}\n\nprint scalar(keys(%h)), \"\\t$max\\n\";\n"
  },
  {
    "path": "benchmarks/Dict/dict_python.py",
    "content": "import sys\n\ndef count_duplicates(lines):\n    h, m = {}, 0\n    for l in lines:\n        if (l in h): h[l] += 1\n        else: h[l] = 1\n        if (m < h[l]): m = h[l]\n    return h, m\n\nh, m = count_duplicates(sys.stdin)\n# print(len(h), m)\n"
  },
  {
    "path": "benchmarks/Dict/dict_ruby.rb",
    "content": "h, max = {}, 0\nSTDIN.each do |l|\n\tif h[l] == nil\n\t\th[l] = 1\n\telse\n\t\th[l] = h[l] + 1\n\tend\n\tmax = h[l] if max < h[l]\nend\n# puts h.length, max\n"
  },
  {
    "path": "benchmarks/GC/gc_c.c",
    "content": "#include <stdlib.h>\n\nstatic void create_objects(int depth) {\n  \n  void\n  *i00=malloc(16), *i01=malloc(16), *i02=malloc(16), *i03=malloc(16), *i04=malloc(16),\n  *i05=malloc(16), *i06=malloc(16), *i07=malloc(16), *i08=malloc(16), *i09=malloc(16),\n  *i10=malloc(16), *i11=malloc(16), *i12=malloc(16), *i13=malloc(16), *i14=malloc(16),\n  *i15=malloc(16), *i16=malloc(16), *i17=malloc(16), *i18=malloc(16), *i19=malloc(16),\n  *i20=malloc(16), *i21=malloc(16), *i22=malloc(16), *i23=malloc(16), *i24=malloc(16),\n  *i25=malloc(16), *i26=malloc(16), *i27=malloc(16), *i28=malloc(16), *i29=malloc(16),\n  *i30=malloc(16), *i31=malloc(16), *i32=malloc(16), *i33=malloc(16), *i34=malloc(16);\n  \n  if (depth == 2) {\n    return;\n  }\n  \n  for (size_t i = 0; i < 10; i++) {\n    create_objects(depth+1);\n  }\n  \n  volatile int noinline = 1;\n  if (noinline) {\n    free(i00); free(i01); free(i02); free(i03); free(i04); free(i05); \n    free(i06); free(i07); free(i08); free(i09); free(i10); free(i11); \n    free(i12); free(i13); free(i14); free(i15); free(i16); free(i17); \n    free(i18); free(i19); free(i20); free(i21); free(i22); free(i23); \n    free(i24); free(i25); free(i26); free(i27); free(i28); free(i29); \n    free(i30); free(i31); free(i32); free(i34);\n  }\n  \n}\n\nint main(int argc, char** argv) {\n  \n  for (size_t i = 0; i < 100; i++) {\n    create_objects(0);\n  }\n  \n}\n"
  },
  {
    "path": "benchmarks/GC/gc_cello.c",
    "content": "#include \"Cello.h\"\n\nstatic void create_objects(int depth) {\n  \n  var\n  i00=new(Int), i01=new(Int), i02=new(Int), i03=new(Int), i04=new(Int),\n  i05=new(Int), i06=new(Int), i07=new(Int), i08=new(Int), i09=new(Int), \n  i10=new(Int), i11=new(Int), i12=new(Int), i13=new(Int), i14=new(Int),\n  i15=new(Int), i16=new(Int), i17=new(Int), i18=new(Int), i19=new(Int),\n  i20=new(Int), i21=new(Int), i22=new(Int), i23=new(Int), i24=new(Int), \n  i25=new(Int), i26=new(Int), i27=new(Int), i28=new(Int), i29=new(Int),\n  i30=new(Int), i31=new(Int), i32=new(Int), i33=new(Int), i34=new(Int);\n  \n  volatile int noinline = 0;\n  if (noinline) {\n    show(i00); show(i01); show(i02); show(i03); show(i04); show(i05); \n    show(i06); show(i07); show(i08); show(i09); show(i10); show(i11); \n    show(i12); show(i13); show(i14); show(i15); show(i16); show(i17); \n    show(i18); show(i19); show(i20); show(i21); show(i22); show(i23); \n    show(i24); show(i25); show(i26); show(i27); show(i28); show(i29); \n    show(i30); show(i31); show(i32); show(i34);\n  }\n  \n  if (depth == 2) {\n    return;\n  }\n  \n  for (size_t i = 0; i < 10; i++) {\n    create_objects(depth+1);\n  }\n  \n}\n\nint main(int argc, char** argv) {\n  \n  for (size_t i = 0; i < 100; i++) {\n    create_objects(0);\n  }\n  return 0;  \n}\n"
  },
  {
    "path": "benchmarks/GC/gc_cpp.cpp",
    "content": "#include <stdlib.h>\n\nclass Int {\n  int64_t i;\n  public:\n    Int() : i(0) {}\n};\n\nstatic void create_objects(int depth) {\n  \n  Int\n  *i00=new Int(), *i01=new Int(), *i02=new Int(), *i03=new Int(), *i04=new Int(),\n  *i05=new Int(), *i06=new Int(), *i07=new Int(), *i08=new Int(), *i09=new Int(),\n  *i10=new Int(), *i11=new Int(), *i12=new Int(), *i13=new Int(), *i14=new Int(),\n  *i15=new Int(), *i16=new Int(), *i17=new Int(), *i18=new Int(), *i19=new Int(),\n  *i20=new Int(), *i21=new Int(), *i22=new Int(), *i23=new Int(), *i24=new Int(), \n  *i25=new Int(), *i26=new Int(), *i27=new Int(), *i28=new Int(), *i29=new Int(),\n  *i30=new Int(), *i31=new Int(), *i32=new Int(), *i33=new Int(), *i34=new Int();\n  \n  if (depth == 2) {\n    return;\n  }\n  \n  for (size_t i = 0; i < 10; i++) {\n    create_objects(depth+1);\n  }\n  \n  volatile int noinline = 1;\n  if (noinline) {\n    delete(i00); delete(i01); delete(i02); delete(i03); delete(i04); delete(i05); \n    delete(i06); delete(i07); delete(i08); delete(i09); delete(i10); delete(i11);\n    delete(i12); delete(i13); delete(i14); delete(i15); delete(i16); delete(i17); \n    delete(i18); delete(i19); delete(i20); delete(i21); delete(i22); delete(i23); \n    delete(i24); delete(i25); delete(i26); delete(i27); delete(i28); delete(i29); \n    delete(i30); delete(i31); delete(i32); delete(i34);\n  }\n  \n}\n\nint main(int argc, char** argv) {\n  \n  for (size_t i = 0; i < 100; i++) {\n    create_objects(0);\n  }\n  \n}\n"
  },
  {
    "path": "benchmarks/GC/gc_java.java",
    "content": "public final class gc_java {\n\n    final public static class Int {\n      private int value;\n      Int(int x) {\n        value = x;\n      }\n    }\n\n    public static void create_objects(int depth) {\n      \n      Int i00=new Int(0); Int i01=new Int(0); \n      Int i02=new Int(0); Int i03=new Int(0); \n      Int i04=new Int(0); Int i05=new Int(0); \n      Int i06=new Int(0); Int i07=new Int(0); \n      Int i08=new Int(0); Int i09=new Int(0); \n      Int i10=new Int(0); Int i11=new Int(0); \n      Int i12=new Int(0); Int i13=new Int(0); \n      Int i14=new Int(0); Int i15=new Int(0); \n      Int i16=new Int(0); Int i17=new Int(0); \n      Int i18=new Int(0); Int i19=new Int(0);\n      Int i20=new Int(0); Int i21=new Int(0); \n      Int i22=new Int(0); Int i23=new Int(0); \n      Int i24=new Int(0); Int i25=new Int(0); \n      Int i26=new Int(0); Int i27=new Int(0); \n      Int i28=new Int(0); Int i29=new Int(0);\n      Int i30=new Int(0); Int i31=new Int(0); \n      Int i32=new Int(0); Int i33=new Int(0); \n      Int i34=new Int(0);\n      \n      if (depth == 2) {\n        return;\n      }\n      \n      for (int i = 0; i < 10; i++) {\n        create_objects(depth+1);\n      }\n      \n    }\n\n    public static void main(String[] args) {\n        for (int i=0; i<10000; ++i) {\n           create_objects(0);\n        }\n    }\n}\n\n"
  },
  {
    "path": "benchmarks/GC/gc_javascript.js",
    "content": "\nfunction Int() {\n  return {val:0}\n}\n\nfunction create_objects(depth) {\n  \n    var i00=Int(); var i01=Int(); var i02=Int(); var i03=Int(); var i04=Int();\n    var i05=Int(); var i06=Int(); var i07=Int(); var i08=Int(); var i09=Int(); \n    var i10=Int(); var i11=Int(); var i12=Int(); var i13=Int(); var i14=Int();\n    var i15=Int(); var i16=Int(); var i17=Int(); var i18=Int(); var i19=Int();\n    var i20=Int(); var i21=Int(); var i22=Int(); var i23=Int(); var i24=Int(); \n    var i25=Int(); var i26=Int(); var i27=Int(); var i28=Int(); var i29=Int();\n    var i30=Int(); var i31=Int(); var i32=Int(); var i33=Int(); var i34=Int();\n  \n    if (depth == 2) {\n        return;\n    }\n    \n    for (var i = 0; i < 10; i++) {\n        create_objects(depth+1);\n    }\n}\n\nfor (var i = 0; i < 10000; i++) {\n    create_objects(0);\n}\n    \n"
  },
  {
    "path": "benchmarks/GC/gc_lua.lua",
    "content": "\nfunction Int () \n  return {val=0}\nend\n\nfunction create_objects(depth)\n  \n    local i00=Int(); local i01=Int(); local i02=Int(); local i03=Int(); local i04=Int();\n    local i05=Int(); local i06=Int(); local i07=Int(); local i08=Int(); local i09=Int(); \n    local i10=Int(); local i11=Int(); local i12=Int(); local i13=Int(); local i14=Int();\n    local i15=Int(); local i16=Int(); local i17=Int(); local i18=Int(); local i19=Int();\n    local i20=Int(); local i21=Int(); local i22=Int(); local i23=Int(); local i24=Int(); \n    local i25=Int(); local i26=Int(); local i27=Int(); local i28=Int(); local i29=Int();\n    local i30=Int(); local i31=Int(); local i32=Int(); local i33=Int(); local i34=Int();\n  \n    if (depth == 2) then\n        return;\n    end\n  \n    for i=0,10 do\n      create_objects(depth+1)\n    end\nend\n\nfor i=0, 10000 do\n    create_objects(0)\nend\n\n"
  },
  {
    "path": "benchmarks/GC/gc_python.py",
    "content": "\nclass Int:\n    pass\n\ndef create_objects(depth):\n  \n    i00=Int(); i01=Int(); i02=Int(); i03=Int(); i04=Int();\n    i05=Int(); i06=Int(); i07=Int(); i08=Int(); i09=Int(); \n    i10=Int(); i11=Int(); i12=Int(); i13=Int(); i14=Int();\n    i15=Int(); i16=Int(); i17=Int(); i18=Int(); i19=Int();\n    i20=Int(); i21=Int(); i22=Int(); i23=Int(); i24=Int(); \n    i25=Int(); i26=Int(); i27=Int(); i28=Int(); i29=Int();\n    i30=Int(); i31=Int(); i32=Int(); i33=Int(); i34=Int();\n    \n    if depth == 2:\n        return\n    \n    for i in range(10):\n      create_objects(depth+1)\n\n\nfor i in range(10000):\n    create_objects(0)\n    \n"
  },
  {
    "path": "benchmarks/GC/gc_ruby.rb",
    "content": "\nclass Int\nend\n\ndef create_objects(depth)\n  \n    i00=Int.new; i01=Int.new; i02=Int.new; i03=Int.new; i04=Int.new;\n    i05=Int.new; i06=Int.new; i07=Int.new; i08=Int.new; i09=Int.new; \n    i10=Int.new; i11=Int.new; i12=Int.new; i13=Int.new; i14=Int.new;\n    i15=Int.new; i16=Int.new; i17=Int.new; i18=Int.new; i19=Int.new;\n    i20=Int.new; i21=Int.new; i22=Int.new; i23=Int.new; i24=Int.new; \n    i25=Int.new; i26=Int.new; i27=Int.new; i28=Int.new; i29=Int.new;\n    i30=Int.new; i31=Int.new; i32=Int.new; i33=Int.new; i34=Int.new;\n  \n    if depth == 2 then\n        return\n    end\n  \n    for i in 0..10\n        create_objects(depth+1)\n    end\nend\n\nfor i in 0..10000\n    create_objects(0)\nend\n"
  },
  {
    "path": "benchmarks/List/list_c.c",
    "content": "#include \"kvec.h\"\n#include <stdlib.h>\n#include <string.h>\n\nint main(int argc, char** argv) {\n  \n  kvec_t(int) x;\n  kv_init(x);\n  int n = 10000;\n  \n  for (int i = 0; i < n; i++) {\n    kv_push(int, x, rand());\n  }\n  \n  for (int i = 0; i < n; i++) {\n    kv_push(int, x, 0);\n    int index = rand() % n;\n    memmove(\n      &x.a[index+1], &x.a[index+0],\n      sizeof(int) * ((x.n-1) - index));\n    x.a[index] = rand();\n  }\n  \n  for (int i = 0; i < n; i++) {\n    int index = rand() % n;\n    memmove(\n      &x.a[index+0], &x.a[index+1],\n      sizeof(int) * ((x.n-1) - index));\n    kv_pop(x);\n  }\n  \n  kv_destroy(x);\n  \n  return 0;\n  \n}\n"
  },
  {
    "path": "benchmarks/List/list_cello.c",
    "content": "#include \"Cello.h\"\n\nint main(int argc, char** argv) {\n  \n  var x = new(Array, Int);\n  \n  int n = 10000;\n  \n  for (int i = 0; i < n; i++) {\n    push(x, $I(rand()));\n  }\n  \n  for (int i = 0; i < n; i++) {\n    push_at(x, $I(rand()), $I(rand() % n));\n  }\n  \n  for (int i = 0; i < n; i++) {\n    pop_at(x, $I(rand() % n));\n  }\n  \n  del(x);\n  \n  return 0;\n  \n}\n"
  },
  {
    "path": "benchmarks/List/list_cpp.cpp",
    "content": "#include <stdlib.h>\n#include <vector>\n\nint main(int argc, char** argv) {\n  \n  std::vector<int> x = std::vector<int>();\n  \n  int n = 10000;\n  \n  for (int i = 0; i < n; i++) {\n    x.push_back(rand());\n  }\n  \n  for (int i = 0; i < n; i++) {\n    x.insert(x.begin()+(rand() % n), rand());\n  }\n  \n  for (int i = 0; i < n; i++) {\n    x.erase(x.begin()+(rand() % n));\n  }\n  \n  return 0;\n  \n}\n"
  },
  {
    "path": "benchmarks/List/list_java.java",
    "content": "import java.util.ArrayList;\nimport java.util.Random;\nimport java.io.*;\n\nclass list_java {\n\tpublic static void main(String[] args) {\n\t\t\n\t\tArrayList<Integer> x = new ArrayList<Integer>();\n    Random rand = new Random();\n\t\t\n    int n = 10000;\n    \n    for (int i = 0; i < n; i++) {\n      x.add(rand.nextInt());\n    }\n    \n    for (int i = 0; i < n; i++) {\n      x.add(rand.nextInt(n), rand.nextInt());\n    }\n    \n    for (int i = 0; i < n; i++) {\n      x.remove(rand.nextInt(n));\n    }\n    \n\t}\n}\n"
  },
  {
    "path": "benchmarks/List/list_javascript.js",
    "content": "\nvar l = []\nvar n = 10000\n\nfor (var i = 0; i < n; i++) {\n  l.push(Math.floor((Math.random() * 32767) + 0))\n}\n\nfor (var i = 0; i < n; i++) {\n  l.splice(\n    Math.floor((Math.random() * n) + 0), 0,\n    Math.floor((Math.random() * 32767) + 0))\n}\n      \nfor (var i = 0; i < n; i++) {\n  l.pop(Math.floor((Math.random() * n) + 0))\n}\n"
  },
  {
    "path": "benchmarks/List/list_lua.lua",
    "content": "require \"math\"\n\nl = {}\nn = 10000\n\nfor i=1,n do\n    l[i] = math.random(0, 32767)\nend\n\nfor i=1,n do\n    table.insert(l, \n      math.random(1, n),\n      math.random(0, 32767))\nend\n      \nfor i=1,n do\n    table.remove(l, math.random(1, n))\nend\n\n"
  },
  {
    "path": "benchmarks/List/list_python.py",
    "content": "import random\n\nl = []\nn = 10000\n\nrandom.seed(123)\n\nfor i in xrange(n):\n    l.append(random.randint(0, 32767))\n    \nfor i in xrange(n):\n    l.insert(\n      random.randint(0, n),\n      random.randint(0, 32767))\n      \nfor i in xrange(n):\n    l.pop(random.randint(0, n))\n    \ndel l\n"
  },
  {
    "path": "benchmarks/List/list_ruby.rb",
    "content": "\nl = []\nn = 10000\n\nn.times {\n  l.push(rand())\n}\n\nn.times {\n  l.insert(rand(n), rand())\n}\n      \nn.times {\n  l.delete_at(rand(n))\n}\n"
  },
  {
    "path": "benchmarks/Map/dict.lua",
    "content": "\r\nlocal prv = {}\r\nlocal pub = {}\r\n\r\ndict = pub\r\n\r\nfunction prv.rot_less(node)\r\n\tlocal R = node.greater\r\n\tlocal M = R.less\r\n\tif R.weight == 0 then\r\n\t\tnode.weight, R.weight = 1, -1\r\n\telse\r\n\t\tnode.weight, R.weight = 0, 0\r\n\tend\r\n\tif M then M.parent = node end\r\n\tnode.greater, node.parent, R.less, R.parent =\r\n\t\tM, R, node, node.parent\r\n\treturn R\r\nend\r\n\r\nfunction prv.rot_greater(node)\r\n\tlocal L = node.less\r\n\tlocal M = L.greater\r\n\tif L.weight == 0 then\r\n\t\tnode.weight, L.weight = -1, 1\r\n\telse\r\n\t\tnode.weight, L.weight = 0, 0\r\n\tend\r\n\tif M then M.parent = node end\r\n\tnode.less, node.parent, L.greater, L.parent = M, L, node, node.parent\r\n\treturn L\r\nend\r\n\r\nfunction prv.rot2_less(node)\r\n\tlocal R = node.greater\r\n\tlocal M = R.less\r\n\tlocal ML, MR = M.less, M.greater\r\n\tif M.weight == 0 then\r\n\t\tnode.weight, R.weight = 0, 0\r\n\telseif M.weight == -1 then\r\n\t\tnode.weight, R.weight, M.weight = 0, 1, 0\r\n\telse\r\n\t\tnode.weight, R.weight, M.weight = -1, 0, 0\r\n\tend\r\n\tif ML then ML.parent = node end\r\n\tif MR then MR.parent = R end\r\n\tnode.greater, node.parent, M.less, M.greater, M.parent, R.less, R.parent = \r\n\t\tML, M, node, R, node.parent, MR, M\r\n\treturn M\r\nend\r\n\r\nfunction prv.rot2_greater(node)\r\n\tlocal L = node.less\r\n\tlocal M = L.greater\r\n\tlocal ML, MR = M.less, M.greater\r\n\tif M.weight == 0 then\r\n\t\tnode.weight, L.weight = 0, 0\r\n\telseif M.weight == -1 then\r\n\t\tnode.weight, L.weight, M.weight = 1, 0, 0\r\n\telse\r\n\t\tnode.weight, L.weight, M.weight = 0, -1, 0\r\n\tend\r\n\tif ML then ML.parent = L end\r\n\tif MR then MR.parent = node end\r\n\tnode.less, node.parent, M.greater, M.less, M.parent, L.greater, L.parent =\r\n\t\tMR, M, node, L, node.parent, ML, M\r\n\treturn M\r\nend\r\n\r\nfunction prv.rebalance(dict, node)\r\n\tlocal p, n, short = node.parent\r\n\tif node.weight == -2 then\r\n\t\tlocal w = node.less.weight\r\n\t\tif w == 1 then\r\n\t\t\tshort = 1\r\n\t\t\tn = %prv.rot2_greater(node)\r\n\t\telse\r\n\t\t\tshort = w == -1\r\n\t\t\tn = %prv.rot_greater(node)\r\n\t\tend\r\n\telseif node.weight == 2 then\r\n\t\tlocal w = node.greater.weight\r\n\t\tif w == -1 then\r\n\t\t\tshort = 1\r\n\t\t\tn = %prv.rot2_less(node)\r\n\t\telse\r\n\t\t\tshort = w == 1\r\n\t\t\tn = %prv.rot_less(node)\r\n\t\tend\r\n\telseif node.weight ~= 0 or not p then\r\n\t\treturn\r\n\telse\r\n\t\treturn p.less == node and 1 or -1\r\n\tend\r\n\r\n\tif not p then\r\n\t\tdict.root = n\r\n\telseif node == p.less then\r\n\t\tp.less = n\r\n\t\treturn short and 1\r\n\telse\r\n\t\tp.greater = n\r\n\t\treturn short and -1\r\n\tend\r\nend\r\n\r\nlocal node_tag = newtag()\r\n\r\nfunction prv.node(record, parent)\r\n\tlocal n = {\r\n\t\trecord = record,\r\n\t\tweight = 0,\r\n\t\tparent = parent,\r\n\t}\r\n\tsettag(n, %node_tag)\r\n\treturn n\r\nend\r\n\r\nlocal dict_tag = newtag()\r\nlocal dict_meta = {}\r\n\r\nsettagmethod(dict_tag, \"index\", function(_, index)\r\n\treturn %dict_meta[index]\r\nend)\r\n\r\nfunction dict_meta:insert(record)\r\n\tlocal n, node = self.root, %prv.node(record)\r\n\tif not n then\r\n\t\tself.root = node\r\n\telse\r\n\t\tlocal ro = self.record_order\r\n\t\tlocal p, t\r\n\t\trepeat\r\n\t\t\tif n.weight ~= 0 then t = n end\r\n\t\t\tp = n\r\n\t\t\tif ro(record, n.record) < 0 then\r\n\t\t\t\tn = n.less\r\n\t\t\t\tif not n then\r\n\t\t\t\t\tnode.parent = p\r\n\t\t\t\t\tn = node\r\n\t\t\t\t\tp.less = n\r\n\t\t\t\t\tbreak\r\n\t\t\t\tend\r\n\t\t\telse\r\n\t\t\t\tn = n.greater\r\n\t\t\t\tif not n then\r\n\t\t\t\t\tnode.parent = p\r\n\t\t\t\t\tn = node\r\n\t\t\t\t\tp.greater = n\r\n\t\t\t\t\tbreak\r\n\t\t\t\tend\r\n\t\t\tend\r\n\t\tuntil nil\r\n\t\twhile p ~= t do\r\n\t\t\tp.weight = n == p.less and -1 or 1\r\n\t\t\tp, n = p.parent, p\r\n\t\tend\r\n\t\tif t then\r\n\t\t\tif n == t.less then\r\n\t\t\t\tt.weight = t.weight - 1\r\n\t\t\telse\r\n\t\t\t\tt.weight = t.weight + 1\r\n\t\t\tend\r\n\t\t\t%prv.rebalance(self, t)\r\n\t\tend\r\n\tend\t\r\n\tself.n = self.n + 1\r\n\treturn node\r\nend\r\n\r\nfunction dict_meta:erase(node)\r\n\tassert(tag(node) == %node_tag, \"erase takes an iterator!\")\r\n\tlocal p, n, swap = node.parent\r\n\tif node.less then\r\n\t\tif node.greater then\r\n\t\t\t-- both children\r\n\t\t\tp, n = node, node.greater\r\n\t\t\twhile n.less do\r\n\t\t\t\tp, n = n, n.less\r\n\t\t\tend\r\n\t\t\tswap, node, n = node, n, n.greater\r\n\t\telse\r\n\t\t\t-- only less child\r\n\t\t\tn = node.less\r\n\t\tend\r\n\telseif node.greater then\r\n\t\t-- only greater child\r\n\t\tn = node.greater\r\n\telse\r\n\t\t-- no children\r\n\t\t-- n = nil\r\n\tend\r\n\t\r\n\tif n then n.parent = p end\r\n\t\r\n\tself.n = self.n - 1\r\n\t\r\n\tif not p then\r\n\t\tself.root = n\r\n\t\treturn\r\n\tend\r\n\t\r\n\tif p.greater == node then\r\n\t\tp.greater = n\r\n\t\tp.weight = p.weight - 1\r\n\telse\r\n\t\tp.less = n\r\n\t\tp.weight = p.weight + 1\r\n\tend\r\n\t\r\n\tif swap then\r\n\t\tlocal sl, sg, sp = swap.less, swap.greater, swap.parent\r\n\t\tnode.weight, node.parent, node.less, node.greater =\r\n\t\t\tswap.weight, sp, sl, sg\r\n\t\t\t\r\n\t\tif sl then sl.parent = node end\r\n\t\tif sg then sg.parent = node end\r\n\t\tif not sp then\r\n\t\t\tself.root = node\r\n\t\telseif sp.less == swap then\r\n\t\t\tsp.less = node\r\n\t\telse\r\n\t\t\tsp.greater = node\r\n\t\tend\r\n\t\t\r\n\t\tif p == swap then p = node end\r\n\tend\r\n\t\r\n\tlocal w\r\n\tp, w = p.parent, %prv.rebalance(self, p)\r\n\twhile w do\r\n\t\tp.weight = p.weight + w\r\n\t\tp, w = p.parent, %prv.rebalance(self, p)\r\n\tend\r\nend\r\n\r\nfunction dict_meta:find(key)\r\n\tlocal n, t = self.root\r\n\tlocal ko = self.key_order\r\n\twhile n do\r\n\t\tlocal ord = ko(key, n.record)\r\n\t\tif ord > 0 then\r\n\t\t\tn = n.greater\r\n\t\telseif ord < 0 then\r\n\t\t\tn = n.less\r\n\t\telse\r\n\t\t\tt, n = n, n.less\r\n\t\tend\r\n\tend\r\n\tif t then\r\n\t\treturn t.record, t\r\n\tend\r\nend\r\n\r\nfunction dict_meta:lwb(key)\r\n\tlocal n, t = self.root\r\n\tlocal ko = self.key_order\r\n\twhile n do\r\n\t\tif ko(key, n.record) > 0 then\r\n\t\t\tn = n.greater\r\n\t\telse\r\n\t\t\tt, n = n, n.less\r\n\t\tend\r\n\tend\r\n\tif t then\r\n\t\treturn t.record, t\r\n\tend\r\nend\r\n\r\nfunction dict_meta:upb(key)\r\n\tlocal n, t = self.root\r\n\tlocal ko = self.key_order\r\n\twhile n do\r\n\t\tif ko(key, n.record) < 0 then\r\n\t\t\tt, n = n, n.less\r\n\t\telse\r\n\t\t\tn = n.greater\r\n\t\tend\r\n\tend\r\n\tif t then\r\n\t\treturn t.record, t\r\n\tend\r\nend\r\n\r\nfunction dict_meta:next(node)\r\n\tlocal n\r\n\tif node then\r\n\t\tassert(tag(node) == %node_tag, \"next takes an iterator\")\r\n\t\tn = node.greater\r\n\telseif self.root then\r\n\t\tn = self.root\r\n\telse\r\n\t\treturn\r\n\tend\r\n\tif n then\r\n\t\trepeat\r\n\t\t\tnode, n = n, n.less\r\n\t\tuntil not n\r\n\t\treturn node.record, node\r\n\tend\r\n\t\r\n\trepeat\r\n\t\tn, node = node, node.parent\r\n\tuntil not node or node.less == n\r\n\t\r\n\tif node then\r\n\t\treturn node.record, node\r\n\tend\r\nend\r\n\r\nfunction dict_meta:prev(node)\r\n\tlocal n\r\n\tif node then\r\n\t\tassert(tag(node) == %node_tag, \"prev takes an iterator\")\r\n\t\tn = node.less\r\n\telseif self.root then\r\n\t\tn = self.root\r\n\telse\r\n\t\treturn\r\n\tend\r\n\tif n then\r\n\t\trepeat\r\n\t\t\tnode, n = n, n.greater\r\n\t\tuntil not n\r\n\t\treturn node.record, node\r\n\tend\r\n\t\r\n\trepeat\r\n\t\tn, node = node, node.parent\r\n\tuntil not node or node.greater == n\r\n\t\r\n\tif node then\r\n\t\treturn node.record, node\r\n\tend\r\nend\r\n\r\nfunction dict_meta:first()\r\n\treturn self:next()\r\nend\r\n\r\nfunction dict_meta:last()\r\n\treturn self:prev()\r\nend\r\n\r\nfunction pub.create(record_order, key_order)\r\n\tlocal d = {\r\n\t\trecord_order = record_order or %pub.cmp,\r\n\t\tkey_order = key_order or record_order or %pub.cmp,\r\n\t\tn = 0,\r\n\t}\r\n\tsettag(d, %dict_tag)\r\n\treturn d\r\nend\r\n\r\nfunction pub.record(node)\r\n\tassert(tag(node) == %node_tag, \"record takes an iterator\")\r\n\treturn node.record\r\nend\r\n\r\nfunction pub.cmp(a, b)\r\n\treturn a < b and -1 or (b < a and 1 or 0)\r\nend\r\n"
  },
  {
    "path": "benchmarks/Map/map_c.c",
    "content": "#include <stdio.h>\n#include \"kbtree.h\"\n\ntypedef struct {\n  char *key;\n  int count;\n} elem_t;\n\n#define elem_cmp(a, b) (strcmp((a).key, (b).key))\nKBTREE_INIT(str, elem_t, elem_cmp)\n\n#define BUF_SIZE 0x10000\n#define BLOCK_SIZE 0x100000\n\nint main(int argc, char *argv[])\n{\n\tchar *buf, **mem = 0;\n\tint ret, max = 1, block_end = 0, curr = 0;\n\tkbtree_t(str) *h;\n\th = kb_init(str, KB_DEFAULT_SIZE);\n\tbuf = malloc(BUF_SIZE); // string buffer\n\tmem = malloc(sizeof(void*));\n\tmem[0] = malloc(BLOCK_SIZE); // memory buffer to avoid memory fragments\n\tcurr = block_end = 0;\n\twhile (!feof(stdin)) {\n\t\tfgets(buf, BUF_SIZE, stdin);\n\t\telem_t t = { buf, 1 };\n\t\telem_t *p = kb_getp(str, h, &t);\n\t\tif (!p) {\n\t\t\n\t\t\tint l = strlen(buf) + 1;\n\t\t\tif (block_end + l > BLOCK_SIZE) {\n\t\t\t\t++curr; block_end = 0;\n\t\t\t\tmem = realloc(mem, (curr + 1) * sizeof(void*));\n\t\t\t\tmem[curr] = malloc(BLOCK_SIZE);\n\t\t\t}\n\t\t\tmemcpy(mem[curr] + block_end, buf, l);\n\t\t\t\n\t\t\tt.key = mem[curr] + block_end;\n\t\t\tt.count = 1;\n\t\t\tkb_putp(str, h, &t);\n\t\t\tblock_end += l;\n\t\t\n\t\t} else {\n\t\t  p->count++;\n\t\t\tif (p->count > max) max = p->count;\n    }\n\n\t}\n\t//printf(\"%u\\t%d\\n\", kh_size(h), max);\n\tfor (ret = 0; ret <= curr; ++ret) free(mem[ret]);\n\tfree(mem);\n\tkb_destroy(str, h);\n\tfree(buf);\n\treturn 0;\n}\n"
  },
  {
    "path": "benchmarks/Map/map_cello.c",
    "content": "#include \"Cello.h\"\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\nenum {\n  BUF_SIZE = 0x10000\n};\n\nint main(int argc, char *argv[]) {\n\tvar m = new(Tree, String, Int);\n\tint max = 1;\n\tchar *buf = malloc(BUF_SIZE);\n\twhile (!feof(stdin)) {\n\t\tfgets(buf, BUF_SIZE, stdin);\n\t\tvar key = $S(buf);\n\t\tif (mem(m, key)) {\n\t\t\tstruct Int* v = get(m, key);\n\t\t\tv->val++;\n\t\t\tif (max < v->val) { max = v->val; }\n\t\t} else {\n\t\t\tset(m, key, $I(1));\n\t\t}\n\t}\n\tdel(m);\n\treturn 0;\n}\n"
  },
  {
    "path": "benchmarks/Map/map_cpp.cpp",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <utility>\n#include <map>\n\nusing namespace std;\n\nstruct eqstr {\n\tinline bool operator()(const char *s1, const char *s2) const {\n\t\treturn strcmp(s1, s2) == 0;\n    }\n};\n\ntypedef map<const char*, int, eqstr> strmap;\n\n#define BUF_SIZE 0x10000\n#define BLOCK_SIZE 0x100000\n\nint main(int argc, char *argv[])\n{\n\tchar *buf;\n\tint ret, max = 1, block_end = 0, curr = 0;\n\tchar **mem;\n\tstrmap *m = new strmap;\n\tbuf = (char*)malloc(BUF_SIZE); // buffer size\n\tmem = (char**)malloc(sizeof(void*));\n\tmem[0] = (char*)malloc(BLOCK_SIZE); // memory buffer to avoid memory fragments\n\tcurr = block_end = 0;\n\twhile (!feof(stdin)) {\n\t\tfgets(buf, BUF_SIZE, stdin);\n\t\tstrmap::iterator p = m->find(buf);\n\t\tif (p == m->end()) {\n\t\t\tint l = strlen(buf) + 1;\n\t\t\tif (block_end + l > BLOCK_SIZE) {\n\t\t\t\t++curr; block_end = 0;\n\t\t\t\tmem = (char**)realloc(mem, (curr + 1) * sizeof(void*));\n\t\t\t\tmem[curr] = (char*)malloc(BLOCK_SIZE);\n\t\t\t}\n\t\t\tmemcpy(mem[curr] + block_end, buf, l);\n\t\t\tm->insert(pair<const char*, int>(mem[curr] + block_end, 1));\n\t\t\tblock_end += l;\n\t\t} else {\n\t\t\t++p->second;\n\t\t\tif (max < p->second) max = p->second;\n\t\t}\n\t}\n\t//printf(\"%u\\t%d\\n\", h->size(), max);\n\tfor (int i = 0; i <= curr; ++i) free(mem[i]);\n\tfree(mem); free(buf);\n\tdelete m;\n\treturn 0;\n}\n"
  },
  {
    "path": "benchmarks/Map/map_cs.cs",
    "content": "using System;\nusing System.Collections.Generic;\n\nclass dict_v1 {\n\tstatic void Main() {\n\t\tstring l;\n\t\tSortedSet<string, int> m = new SortedSet<string, int>();\n\t\tint max = 1;\n\t\twhile ((l = Console.ReadLine()) != null) {\n\t\t\tint v;\n\t\t\tif (m.TryGetValue(l, out v)) {\n\t\t\t\tif (v+1 > max) max = v+1;\n\t\t\t\tm[l] = v+1;\n\t\t\t} else m[l] = 1;\n\t\t}\n\t\tConsole.WriteLine(m.Count);\n\t\tConsole.WriteLine(max);\n\t}\n}\n"
  },
  {
    "path": "benchmarks/Map/map_d.d",
    "content": "// This program segfaults at the end of the input file. I think this is a bug\n// of GDC. I can use std.stream or std.c.stdio instead, but those modules are\n// extremely slow. In the end, I decide to specify the number of lines at the\n// command line. Pretty nasty.\n\nimport std.stdio, std.string;\n\nvoid main(string[] args) {\n\tint N = 5000000;\n\tchar[] buf;\n\tint[char[]] h;\n\tint max = 1, n = 0;\n\tif (args.length >= 2) N = atoi(args[1]);\n\twhile (readln(stdin, buf)) {\n\t\tint current = ++h[buf];\n\t\tmax = (current > max)? current : max;\n\t\tif (++n == N) {\n\t\t\twritef(h.length); writef(\"\\t\"); writefln(max);\n\t\t}\n\t}\n\twritef(h.length); writef(\"\\t\"); writefln(max);\n}\n"
  },
  {
    "path": "benchmarks/Map/map_go.go",
    "content": "// Contributed by Pat\npackage main\n\nimport (\n\t\"fmt\"\n\t\"bufio\"\n\t\"os\"\n)\n\nfunc main() {\n\tr := bufio.NewReader(os.Stdin)\n\th := make(map[string]int, 1e6)\n\tmax := 1\n\tfor {\n\t\tb, e := r.ReadSlice('\\n')\n\t\tif e != nil {\n\t\t\tbreak\n\t\t}\n\t\tl := string(b)\n\t\tv := h[l] + 1\n\t\th[l] = v\n\t\tif v > max {\n\t\t\tmax = v\n\t\t}\n\t}\n\tfmt.Printf(\"%d\\t%d\\n\", len(h), max)\n}\n"
  },
  {
    "path": "benchmarks/Map/map_java.java",
    "content": "import java.util.TreeMap;\nimport java.io.*;\n\nclass map_java {\n\tpublic static void main(String[] args) {\n\t\tBufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));\n\t\tTreeMap<String, Integer> h = new TreeMap<String, Integer>();\n\t\tString l;\n\t\tint max = 0;\n\t\ttry {\n\t\t\twhile ((l = stdin.readLine()) != null) {\n\t\t\t\tint x = 1;\n\t\t\t\tif (h.containsKey(l)) {\n\t\t\t\t\tx = h.get(l) + 1;\n\t\t\t\t\th.put(l, x);\n\t\t\t\t\tif (x > max) max = x;\n\t\t\t\t} else h.put(l, 1);\n\t\t\t}\n\t\t} catch (IOException e) {\n\t\t}\n\t\t//System.out.println(h.size()+\"\\t\"+max);\n\t}\n}\n"
  },
  {
    "path": "benchmarks/Map/map_javascript.js",
    "content": "var RBTree = require('bintrees').RBTree;\n\nvar strcmp = function (a, b) { return a.localeCompare(b); };\n\nvar h = new RBTree(strcmp), n = 0, max = 0;\n\nfunction processLine (l) {\n\tvar val = h.find(l)\n    if (val) {\n\t\th.insert(val+1);\n\t\tif (max < val+1) max = val+1;\n\t} else h.insert(l, 1), ++n;\n}\n\nvar readline = require('readline');\nvar rl = readline.createInterface({\n  input: process.stdin,\n  output: process.stdout,\n  terminal: false\n});\n\nrl.on('line', function(line){\n    processLine(line);\n})\n\n//print(n, max)\n"
  },
  {
    "path": "benchmarks/Map/map_lua.lua",
    "content": "require 'Map/redblack'\n\nlocal h = redblack.newTree()\nlocal max = 0\nfor l in io.lines() do\n\tlocal c = redblack.find(h, l)\n\tif (c) then\n\t  -- This Red black doesn't support value types so whatever\n\t  redblack.insert(h, l)\n\t  -- max = max > c and max or c\n\telse\n\t  redblack.insert(h, l)\n  end\nend\n\n-- print(n, max)\n"
  },
  {
    "path": "benchmarks/Map/map_perl.pl",
    "content": "my (%h, $max);\n\nwhile (<>) {\n    next if (++$h{$_} > $max);\n    $max = $h{$_};\n}\n\nprint scalar(keys(%h)), \"\\t$max\\n\";\n"
  },
  {
    "path": "benchmarks/Map/map_python.py",
    "content": "import sys\nfrom bintrees import RBTree\n\ndef count_duplicates(lines):\n    h, m = RBTree(), 0\n    for l in lines:\n        if (l in h): h[l] += 1\n        else: h[l] = 1\n        if (m < h[l]): m = h[l]\n    return h, m\n\nh, m = count_duplicates(sys.stdin)\n# print(len(h), m)\n"
  },
  {
    "path": "benchmarks/Map/map_ruby.rb",
    "content": "require 'rbtree'\n\nh, max = RBTree[], 0\nSTDIN.each do |l|\n\tif h[l] == nil\n\t\th[l] = 1\n\telse\n\t\th[l] = h[l] + 1\n\tend\n\tmax = h[l] if max < h[l]\nend\n# puts h.length, max\n"
  },
  {
    "path": "benchmarks/Map/rb.lua",
    "content": "---------------------------------------\n--\n--  rb.lua \n--  20110212\n--\n--  from cormen 2nd edition\n--\n---------------------------------------\n\n--[[\nnode = {\n  k;    -- key\n  red;  -- true or false\n  l;    -- left subtree\n  r;    -- right subtree\n  p;    -- parent\n  data; -- for the client\n}\n\ntree = {\n  root;\n  NIL;  -- sentinel node: parent of root / leaves\n}\n--]]\n\n-- used for the simetric operations\n-- d is either 'left'/'right' or true/false (or error !)\n-- returns 'l','r' or 'r','l'\nlocal function direction(d)\n  if d == 'left' or d == true then\n    return 'l','r','left','right'\n  elseif d == 'right' or d == false then\n    return 'r','l','right','left'\n  else\n    error(\"bad argument to 'direction' : either 'left' or 'right'\")\n  end\nend\n\nlocal function new()\n  local NIL = {}\n  NIL.p = NIL\n  NIL.l = NIL\n  NIL.r = NIL\n  return {root = NIL, NIL=NIL}\nend\n\n-- names of variables are consistent with minimum\nlocal function edge(x, NIL, d)\n  local L = direction(d)\n  while x[L] ~= NIL do\n    x = x[L]\n  end\n  return x\nend\n\n-- names of variables are consistent with successor (!)\nlocal function next(x, NIL, d)\n  local _, R = direction(d)\n  if x[R] ~= NIL then\n    return edge(x[R], NIL, d)\n  end\n  local y = x.p\n  while y ~= NIL and x == y[R] do\n    x = y\n    y = y.p\n  end\n  return y\nend\n\nlocal function search(x, k, NIL)\n  while x ~= NIL and x.k ~= k do\n    if k < x.k then\n      x = x.l\n    else\n      x = x.r\n    end\n  end\n  return x\nend\n\n-- names of variables are consistent with left rotation\nlocal function rotate (t,x,d)\n  local L,R = direction(d)\n  local y = x[R]\n  x[R] = y[L]\n  if y[L] ~= t.NIL\n    then y[L].p = x end\n  y.p = x.p\n  if x.p == t.NIL \n    then t.root = y\n    else if x == x.p[L] \n            then x.p[L] = y\n            else x.p[R] = y end end\n  y[L] = x\n  x.p = y\nend\n\nlocal function fixinsert(t,z)\n  local n = z\n  while z.p.red do  \n    local L,R,LEFT,RIGHT = direction(z.p == z.p.p.l)\n    local y = z.p.p[R]\n    if y.red then \n      z.p.red = nil\n      y.red = nil\n      z.p.p.red = true\n      z = z.p.p\n    else \n      if z == z.p[R] then \n        z = z.p\n        rotate(t,z,LEFT)\n      end\n      z.p.red = nil\n      z.p.p.red = true\n      rotate(t,z.p.p,RIGHT)\n    end\n  end\n  t.root.red = nil\n  return n\nend\n\nlocal function insert(t,k,data)\n  local NIL = t.NIL\n  local y = NIL\n  local x = t.root\n  \n  while x ~= NIL \n    do y = x\n    if k == x.k then return x end\n    if k < x.k \n      then x = x.l\n      else x = x.r end end\n  local z = {k=k,data=data}\n  z.p = y\n  if y == NIL \n    then t.root = z\n    else \n      if k == y.k then return y end\n      if k < y.k \n         then y.l = z\n         else y.r = z end end\n  z.l = NIL\n  z.r = NIL\n  z.red = true\n  z.data = data\n  return fixinsert(t,z)\nend\n\nlocal function fixdelete(t, x)\n  local y,z,w\n  while x ~= t.root and not x.red do\n    local L,R,LEFT,RIGHT = direction(x == x.p.l)\n    w = x.p[R]\n    if w.red then\n      w.red = nil\n      x.p.red = true\n      rotate(t, x.p, LEFT)\n      w = x.p[R]\n    end\n    if not w[L].red and not w[R].red then \n      w.red = true\n      x = x.p\n    else\n      if not w[R].red then\n        w[L].red = nil\n        w.red = true\n        rotate(t, w, RIGHT)\n        w = x.p[R]\n      end\n      w.red = x.p.red\n      x.p.red = nil\n      w[R].red = nil\n      rotate(t, x.p, LEFT)\n      x = t.root\n    end\n  end\n  x.red = nil\nend\n\nlocal function delete(t, z)\n  local NIL = t.NIL\n  local x,y\n  if z.l == NIL or z.r == NIL \n     then y = z \n     else y = next(z, NIL, 'left') end\n  if y.l ~= NIL \n     then x = y.l \n     else x = y.r end\n  x.p = y.p \n  if y.p == NIL \n     then t.root = x \n     else if y == y.p.l \n             then y.p.l = x\n             else y.p.r = x end end\n  if y ~= z \n     then z.k = y.k\n          z.data = y.data end\n  if not y.red\n     then fixdelete(t, x) end\n  return y\nend\n\nreturn {\n  new         = new;\n  minimum     = function(x,NIL) return edge(x,NIL,'left') end;\n  maximum     = function(x,NIL) return edge(x,NIL,'right') end;\n  predecessor = function(x,NIL) return next(x,NIL,'right') end;\n  successor   = function(x,NIL) return next(x,NIL,'left') end;\n  search      = search;\n  insert      = insert;\n  delete      = delete;\n}\n"
  },
  {
    "path": "benchmarks/Map/redblack.lua",
    "content": "--------------------------------------------------------------------------------\n-- Copyright (C) 2014, Greg Johnson.\n-- Released under the terms of the GNU GPL v2.0.\n--------------------------------------------------------------------------------\n--[[\nThis is a lua implementation of red black trees.\n\nHere are the provided operations:\n - create a new tree\n - insert a data element\n - delete a data element\n - find a data element\n - iterate over the data elements\n \nA red black tree is a binary search tree in which each node is marked\nas a red node or a black node.  The tree satisfies the following two\nproperties, which together guarantee that insert, delete, and find\noperations are all O(logN):\n\n    Red property:    Red nodes do not have red parents.\n\n    Black property:  Siblings have the same maximum black height.\n\n(The maximum black height of a node is the maximum number of black nodes\non any simple path starting at the node and descending into its subtree.)\n\nData values are any lua values that support comparison via \"<\", including\ntables with metatables containing the \"__lt\" method.\n\nUsage:\n    require 'redblack'\n    local tree = redblack.newTree()\n\n    redblack.insert(tree, 10)\n    redblack.insert(tree, 20)\n\n    for value in redblack.iterate(tree) do\n        print(value)\n    end\n\n    print(redblack.find(tree, 10))        -- expect 10\n\n    redblack.delete(tree, 10)\n    redblack.delete(tree, 20)\n\n    print(redblack.find(tree, 10) ~= nil) -- expect false\n--]]\n\nlocal delete, deleteNode, farNephew, findNode, first, grandparent, insert\nlocal insertIntoSortedPosition, insideChild, isBlackNode, isInsideChild\nlocal isLeftChild, isRedNode, isRightChild, isRootNode, iterate\nlocal leftChild, ensureFarNephewIsRed, ensureOutsideChild, makeRootNode\nlocal ensureSiblingIsBlack, nearNephew, newNode, newTree, outsideChild\nlocal parent, restoreBlackProperty, restoreRedProperty, rightChild\nlocal rotateUp, rotateUpBlackNode, setChild, sibling, successor, swapColors\nlocal swapWithSuccessor, uncle, violatesBlackProperty, violatesRedProperty\nlocal getChildOrNil, getOnlyChild, find, ensureLeafOrParentOfOneLeaf\n\n------------------------------- public functions -------------------------------\nfunction newTree()\n    return { childList = {} }\nend\n\n-- insert a node into the tree; data values must be comparable using \"<\".\n--\nfunction insert(tree, data)\n    local insertedNode = insertIntoSortedPosition(tree, tree.root, data)\n\n    if violatesRedProperty(insertedNode) then\n        restoreRedProperty(tree, insertedNode)\n    end\nend\n\n-- delete a node from the tree; data values must be comparable using \"<\".\n--\nfunction delete(tree, data)\n    local deleteMe = findNode(tree.root, data)\n\n    if deleteMe == nil then return end\n\n    deleteMe = ensureLeafOrParentOfOneLeaf(deleteMe)\n\n    if not isRootNode(deleteMe) and not isRedNode(deleteMe) then\n        deleteMe.color = 'white'  -- to satisfy pre-condition of restoreBlackProperty()\n        restoreBlackProperty(tree, deleteMe)\n    end\n\n    deleteNode(tree, deleteMe)\nend\n\nfunction find(tree, data)\n    local node = findNode(tree.root, data)\n    return node and node.data\nend\n\nfunction iterate(xTree)\n    local f = function(s, var)\n                 local result = s.returnMe\n                 s.returnMe = successor(s.returnMe)\n                 return result and result.data\n              end\n\n    return f, { returnMe = first(xTree.root) }, nil\nend\n----------------------------- end public functions -----------------------------\n\n-- Node \"fixMe\" is red and has a red parent, violating the red property.\n-- Other than that, all nodes in the tree satisfy the red and black properties.\n--\n-- Upon return, the red property is restored for all nodes in the tree.  \n--\nfunction restoreRedProperty(tree, fixMe)\n    -- base case 1:\n        if isRootNode(parent(fixMe)) then\n            parent(fixMe).color = 'black'\n\n    -- base case 2:\n        elseif not isRedNode(uncle(fixMe)) then\n            -- rotateUp changes color of outside child's parent.\n            -- So, if fixMe is outside child, then rotateUp(parent of fixMe) will fix red violation.\n            --\n            -- (rotateUp requires a red node with black sibling as input)\n\n            fixMe = ensureOutsideChild(tree, fixMe)\n\n            rotateUp(tree, parent(fixMe))\n\n    -- inductive case:\n        else\n            parent(fixMe).color      = 'black'\n            uncle(fixMe).color       = 'black'\n            grandparent(fixMe).color = 'red'\n\n            if violatesRedProperty(grandparent(fixMe)) then\n                restoreRedProperty(tree, grandparent(fixMe))\n            end\n        end\nend\n\n-- Node fixMe has max black height one less than its sibling, violating the black property.\n-- Other than that, all nodes in the tree satisfy the red and black properties.\n-- (This algorithm also requires that fixMe not be a red node.)\n--\n-- Upon return, the black property is restored for all nodes in the tree.  \n--\n-- (Also, upon return the parent of fixMe (if it exists) is black;\n-- this fact is used to slightly simplify the delete algorithm.)\n--\nfunction restoreBlackProperty(tree, fixMe)\n    ensureSiblingIsBlack(tree, fixMe)\n\n    -- base case 1:\n        if isRedNode(nearNephew(fixMe)) or isRedNode(farNephew(fixMe)) then\n            -- In this case we can treat parent(fixMe) as root of a tree; no recursion will be necessary.\n            -- rotateUpBlackNode(sibling) will swap max black heights of root's two subtrees.\n\n            -- rotate operation will make far nephew a child of root and uncle of fixMe.\n            -- If we ensure that far nephew is red, we will be able to increase its max\n            -- black height by simply changing its color to black.\n\n            ensureFarNephewIsRed(fixMe)\n\n            rotateUpBlackNode(tree, sibling(fixMe))\n\n            uncle(fixMe).color = 'black'\n        else\n            -- Fix black property violation by reducing sibling's max black height.  (This also\n            -- reduces max black height of parent, potentially giving parent a black violation.)\n\n            sibling(fixMe).color = 'red'\n\n    -- base case 2:\n            if isRedNode(parent(fixMe)) then\n                parent(fixMe).color = 'black'\n\n    -- inductive case:\n            elseif not isRootNode(parent(fixMe)) then\n                restoreBlackProperty(tree, parent(fixMe))\n            end\n        end\nend\n\n----------------------------- rotateUp operations ------------------------------\n-- pre-condition:  redNode must be red and must not have a red sibling.\n-- This operation preserves the red and black properties of the tree and the\n-- in-order traversal of the tree.\n--\n--     orig_parent (b)              node (b)\n--          |                        |         \n--     +----+----+     ===>     +----+----+    \n--     |         |              |         |    \n--    node (r)   t3             t1   orig_parent (r)\n--     |                                  |    \n--  +--+--+                            +--+--+ \n--  |     |                            |     | \n--  t1    t2                           t2    t3\n--\nfunction rotateUp(tree, redNode)\n    assert(parent(redNode))\n\n    swapColors(redNode, parent(redNode))\n\n    local leftChild = isLeftChild(redNode)\n    local p  = parent(redNode)\n    local gp = grandparent(redNode)\n\n    setChild(tree, p,         insideChild(redNode), leftChild)\n    setChild(tree, gp,        redNode,              isLeftChild(p))\n    setChild(tree, redNode,   p,                    not leftChild)\nend\n\n-- pre-condition:  blackNode must be black and must not have a red outside child.\n-- This function preserves the red property and the in-order traversal of the tree,\n-- but it violates the black property:\n--\n-- if we consider parent(blackNode) to be the root of a subtree,\n-- rotateUpBlackNode(node) swaps max black heights of root's two subtrees.\n--\n-- (This function is identical to rotateUp(), except for the pre-conditions)\n--\nfunction rotateUpBlackNode(tree, blackNode)\n    rotateUp(tree, blackNode)\nend\n--------------------------- end rotateUp operations ----------------------------\n\n------------------------------- iterator support -------------------------------\nfunction first(xNode)\n    while leftChild(xNode) do\n        xNode = leftChild(xNode)\n    end\n    return xNode\nend\n\nfunction successor(xNode)\n    local result = first(rightChild(xNode))\n    if result == nil then\n        while isRightChild(xNode) do\n            xNode = parent(xNode)\n        end\n        result = parent(xNode)\n    end\n    return result\nend\n----------------------------- end iterator support -----------------------------\n\n------------------------------ familial relations ------------------------------\nfunction parent(node)\n    return node and node.parent\nend\n\nfunction sibling(node)\n    if     isLeftChild(node)  then return rightChild(parent(node))\n    elseif isRightChild(node) then return leftChild(parent(node))\n    else                           return nil\n    end\nend\n\nfunction insideChild(node)\n    if     isLeftChild(node)  then return node.childList[2]\n    elseif isRightChild(node) then return node.childList[1]\n    else                           return nil\n    end\nend\n\nfunction outsideChild(node)\n    if     isLeftChild(node)  then return node.childList[1]\n    elseif isRightChild(node) then return node.childList[2]\n    else                           return nil\n    end\nend\n\nfunction grandparent(node)\n    return parent(parent(node))\nend\n\nfunction uncle(node)\n    return sibling(parent(node))\nend\n\nfunction nearNephew(node)\n    return insideChild(sibling(node))\nend\n\nfunction farNephew(node)\n    return outsideChild(sibling(node))\nend\n\nfunction getOnlyChild(node)\n     return (node.childList[1] or node.childList[2])\nend\n\nfunction isInsideChild(node)\n    return    isLeftChild(parent(node))  and isRightChild(node)\n           or isRightChild(parent(node)) and isLeftChild(node)\nend\n\nfunction ensureOutsideChild(tree, node)\n    if isInsideChild(node) then\n        rotateUp(tree, node)\n        node = outsideChild(node)\n    end\n    return node\nend\n\nfunction leftChild(node)\n    return node and node.childList[1]\nend\n\nfunction rightChild(node)\n    return node and node.childList[2]\nend\n\nfunction isLeftChild(child)\n    return child and child == leftChild(parent(child))\nend\n\nfunction isRightChild(child)\n    return child and child == rightChild(parent(child))\nend\n\nfunction setChild(tree, parentNode, childNode, makeLeftChild)\n    if parentNode == nil then\n        tree.root = childNode\n\n    elseif makeLeftChild then\n        parentNode.childList[1] = childNode\n\n    else\n        parentNode.childList[2] = childNode\n    end\n\n    if childNode ~= nil then\n        childNode.parent = parentNode\n    end\n\n    return childNode\nend\n\nfunction isRootNode(node)\n    return node and node.parent == nil\nend\n\nfunction makeRootNode(tree, node)\n    tree.root = node\n    return node\nend\n---------------------------- end familial relations ----------------------------\n\n------------------------------ support functions -------------------------------\nfunction violatesRedProperty(node)\n    return isRedNode(node) and isRedNode(parent(node))\nend\n\nfunction findNode(subtreeRoot, data)\n    if subtreeRoot == nil then\n        return nil\n\n    elseif data < subtreeRoot.data then\n        return findNode(subtreeRoot.childList[1], data)\n\n    elseif subtreeRoot.data < data then\n        return findNode(subtreeRoot.childList[2], data)\n\n    else\n        return subtreeRoot\n    end\nend\n\nfunction insertIntoSortedPosition(tree, subtreeRoot, xData)\n    if subtreeRoot == nil then \n        return makeRootNode(tree, newNode(xData))\n\n    else\n        local childIndex = (xData < subtreeRoot.data and 1 or 2)\n\n        if subtreeRoot.childList[childIndex] == nil then \n            return setChild(tree,\n                            subtreeRoot,\n                            newNode(xData),\n                            childIndex == 1)\n        else\n            return insertIntoSortedPosition(tree,\n                                            subtreeRoot.childList[childIndex],\n                                            xData)\n        end\n    end\nend\n\nfunction newNode(xData)\n    local node = { data = xData, color = 'red', childList = {} }\n    return node\nend\n\nfunction isBlackNode(node)\n    return node and node.color == 'black'\nend\n\nfunction isRedNode(node)\n    return node and node.color == 'red'\nend\n\nfunction ensureLeafOrParentOfOneLeaf(deleteMe)\n    if deleteMe.childList[1] ~= nil and deleteMe.childList[2] ~= nil then\n        deleteMe = swapWithSuccessor(deleteMe)\n    end\n    return deleteMe\nend\n\nfunction swapColors(node1, node2)\n      node1.color, node2.color = node2.color, node1.color\nend\n\nfunction ensureSiblingIsBlack(tree, node)\n    if isRedNode(sibling(node)) then\n        rotateUp(tree, sibling(node))\n    end\nend\n\nfunction ensureFarNephewIsRed(tree, node)\n    if isBlackNode(farNephew(node)) then\n        rotateUp(tree, nearNephew(node))\n    end\nend\n\nfunction swapWithSuccessor(deleteMe)\n    local succ = successor(deleteMe)\n    deleteMe.data, succ.data = succ.data, deleteMe.data\n    return succ\nend\n\nfunction getChildOrNil(node)\n     return (node and (node.childList[1] or node.childList[2]))\nend\n\nfunction deleteNode(tree, deleteMe)\n    assert(deleteMe ~= nil\n           and (deleteMe.childList[1] == nil or deleteMe.childList[2] == nil))\n\n    setChild(tree,\n             parent(deleteMe),\n             getChildOrNil(deleteMe),\n             isLeftChild(deleteMe))\nend\n---------------------------- end support functions -----------------------------\n\n------------------------- support for testing redblack -------------------------\nlocal function printNode(node)\n    io.write(tostring(node))\n    io.write('<c1:  ', tostring(node.childList[1]), '>')\n    io.write(' <c2:  ', tostring(node.childList[2]), '>')\n    io.write(' <color:  ', tostring(node.color), '>')\n    io.write(' <data:  ', tostring(node.data), '>')\n    --for k,v in pairs(node) do\n    --    io.write(' <' .. tostring(k) .. ': ' .. tostring(v) .. '>')\n    --end\n    print()\nend\n\nlocal function printTree(tree, depth)\n    if tree == nil then return end\n    if tree.root ~= nil then tree = tree.root end\n    if depth == nil then depth = 0 end\n\n    if depth == 0 then print() end\n\n    printTree(tree.childList[1], depth+1)\n\n    for i = 1, depth do io.write(\"    \") end\n    printNode(tree)\n\n    printTree(tree.childList[2], depth+1)\n\n    if depth == 0 then print() end\nend\n\ntestredblack = {\n    insertIntoSortedPosition = insertIntoSortedPosition,\n    printNode = printNode,\n    printTree = printTree,\n}\n----------------------- end support for testing redblack -----------------------\n\nredblack = {\n    newTree = newTree,\n    insert  = insert,\n    delete  = delete,\n    iterate = iterate,\n    find    = find,\n}\n\n"
  },
  {
    "path": "benchmarks/Matmul/matmul_c.c",
    "content": "// Writen by Attractive Chaos; distributed under the MIT license\n\n#include <stdlib.h>\n#include <stdio.h>\n\ndouble **mm_init(int n)\n{\n\tdouble **m;\n\tint i;\n\tm = (double**)malloc(n * sizeof(void*));\n\tfor (i = 0; i < n; ++i)\n\t\tm[i] = calloc(n, sizeof(double));\n\treturn m;\n}\nvoid mm_destroy(int n, double **m)\n{\n\tint i;\n\tfor (i = 0; i < n; ++i) free(m[i]);\n\tfree(m);\n}\ndouble **mm_gen(int n)\n{\n\tdouble **m, tmp = 1. / n / n;\n\tint i, j;\n\tm = mm_init(n);\n\tfor (i = 0; i < n; ++i)\n\t\tfor (j = 0; j < n; ++j)\n\t\t\tm[i][j] = tmp * (i - j) * (i + j);\n\treturn m;\n}\n// better cache performance by transposing the second matrix\ndouble **mm_mul(int n, double *const *a, double *const *b)\n{\n\tint i, j, k;\n\tdouble **m, **c;\n\tm = mm_init(n); c = mm_init(n);\n\tfor (i = 0; i < n; ++i) // transpose\n\t\tfor (j = 0; j < n; ++j)\n\t\t\tc[i][j] = b[j][i];\n\tfor (i = 0; i < n; ++i) {\n\t\tdouble *p = a[i], *q = m[i];\n\t\tfor (j = 0; j < n; ++j) {\n\t\t\tdouble t = 0.0, *r = c[j];\n\t\t\tfor (k = 0; k < n; ++k)\n\t\t\t\tt += p[k] * r[k];\n\t\t\tq[j] = t;\n\t\t}\n\t}\n\tmm_destroy(n, c);\n\treturn m;\n}\nint main(int argc, char *argv[])\n{\n\tint n = 300;\n\tdouble **a, **b, **m;\n\tn = (n/2) * 2;\n\ta = mm_gen(n); b = mm_gen(n);\n\tm = mm_mul(n, a, b);\n\t//fprintf(stderr, \"%lf\\n\", m[n/2][n/2]);\n\tmm_destroy(n, a); mm_destroy(n, b); mm_destroy(n, m);\n\treturn 0;\n}\n\n"
  },
  {
    "path": "benchmarks/Matmul/matmul_cello.c",
    "content": "#include \"Cello.h\"\n\nstruct Matrix {\n  size_t n;\n  double** d;\n};\n\nstatic void Matrix_New(var self, var args) {\n  struct Matrix* m = self;\n  m->n = c_int(get(args, $I(0)));\n\tm->d = malloc(m->n * sizeof(double*));\n\tfor (int i = 0; i < m->n; ++i) {\n\t\tm->d[i] = calloc(m->n, sizeof(double));\n\t}\n}\n\nstatic void Matrix_Del(var self) {\n\tstruct Matrix* m = self;\n\tfor (int i = 0; i < m->n; ++i) free(m->d[i]);\n\tfree(m->d);\n}\n\nstatic var Matrix = Cello(Matrix, Instance(New, Matrix_New, Matrix_Del));\n\nstatic struct Matrix* Matrix_Gen(int n) {\n\tstruct Matrix* m = new(Matrix, $I(n));\n\tdouble tmp = 1.0 / n / n;\n\tfor (int i = 0; i < m->n; ++i) {\n\t\tfor (int j = 0; j < m->n; ++j) {\n\t\t\tm->d[i][j] = tmp * (i - j) * (i + j);\n\t\t}\n\t}\n\treturn m;\n}\n\nstatic var Matrix_Mul(var m0, var m1) {\n  struct Matrix* a = m0;\n  struct Matrix* b = m1;\n\tstruct Matrix* m = new(Matrix, $I(a->n));\n\tstruct Matrix* c = new(Matrix, $I(a->n));\n\tfor (int i = 0; i < m->n; ++i) {\n\t\tfor (int j = 0; j < m->n; ++j) {\n\t\t\tc->d[i][j] = b->d[j][i];\n\t\t}\n\t}\n\tfor (int i = 0; i < m->n; ++i) {\n\t\tdouble *p = a->d[i], *q = m->d[i];\n\t\tfor (int j = 0; j < m->n; ++j) {\n\t\t\tdouble t = 0.0, *r = c->d[j];\n\t\t\tfor (int k = 0; k < m->n; ++k) {\n\t\t\t\tt += p[k] * r[k];\n\t\t\t}\n\t\t\tq[j] = t;\n\t\t}\n\t}\n\tdel(c);\n\treturn m;\n}\n\nint main(int argc, char *argv[]) {\n\tint n = 300;\n\tn = (n/2) * 2;\n\tvar a = Matrix_Gen(n);\n\tvar b = Matrix_Gen(n);\n\tvar m = Matrix_Mul(a, b);\n\tdel(a); del(b); del(m);\n\treturn 0;\n}\n\n"
  },
  {
    "path": "benchmarks/Matmul/matmul_cpp.cpp",
    "content": "#include <stdlib.h>\n\nclass Matrix {\n\n  public:\n  size_t n;\n  double** d;  \n\n  Matrix(int n);\n  ~Matrix();\n  \n};\n\nMatrix::Matrix(int n) {\n  n = n;\n\td = (double**)malloc(n * sizeof(double*));\n\tfor (int i = 0; i < n; ++i) {\n\t\td[i] = (double*)calloc(n, sizeof(double));\n\t}\n}\n\nMatrix::~Matrix() {\n\tfor (int i = 0; i < n; ++i) free(d[i]);\n\tfree(d);\n}\n\nstatic Matrix* Matrix_Gen(int n) {\n\tMatrix* m = new Matrix(n);\n\tdouble tmp = 1.0 / n / n;\n\tfor (int i = 0; i < m->n; ++i) {\n\t\tfor (int j = 0; j < m->n; ++j) {\n\t\t\tm->d[i][j] = tmp * (i - j) * (i + j);\n\t\t}\n\t}\n\treturn m;\n}\n\nstatic Matrix* Matrix_Mul(Matrix* m0, Matrix* m1) {\n  Matrix* a = m0;\n  Matrix* b = m1;\n\tMatrix* m = new Matrix(a->n);\n\tMatrix* c = new Matrix(a->n);\n\tfor (int i = 0; i < m->n; ++i) {\n\t\tfor (int j = 0; j < m->n; ++j) {\n\t\t\tc->d[i][j] = b->d[j][i];\n\t\t}\n\t}\n\tfor (int i = 0; i < m->n; ++i) {\n\t\tdouble *p = a->d[i], *q = m->d[i];\n\t\tfor (int j = 0; j < m->n; ++j) {\n\t\t\tdouble t = 0.0, *r = c->d[j];\n\t\t\tfor (int k = 0; k < m->n; ++k) {\n\t\t\t\tt += p[k] * r[k];\n\t\t\t}\n\t\t\tq[j] = t;\n\t\t}\n\t}\n\tdelete c;\n\treturn m;\n}\n\nint main(int argc, char *argv[]) {\n\tint n = 300;\n\tn = (n/2) * 2;\n\tMatrix* a = Matrix_Gen(n);\n\tMatrix* b = Matrix_Gen(n);\n\tMatrix* m = Matrix_Mul(a, b);\n\tdelete a; delete b; delete m;\n\treturn 0;\n}\n\n"
  },
  {
    "path": "benchmarks/Matmul/matmul_cs.cs",
    "content": "// Written by Attractive Chaos; distributed under the MIT license\n\n// To compile: mcs -optimize+ -out:matmul_v1.run matmul_v1.cs\n// Translated from Java with reference to: http://code.wikia.com/wiki/Matrix_multiplication\n\nusing System;\n\nclass matmul_v1 {\n\tpublic double[,] matgen(int n) {\n\t\tdouble[,] a = new double[n,n];\n\t\tdouble tmp = 1.0 / n / n;\n\t\tfor (int i = 0; i < n; ++i)\n\t\t\tfor (int j = 0; j < n; ++j)\n\t\t\t\ta[i,j] = tmp * (i - j) * (i + j);\n\t\treturn a;\n\t}\n\tpublic double[,] matmul(double[,] a, double[,] b) {\n\t\tint m = a.GetLength(0), n = a.GetLength(1), p = b.GetLength(0);\n\t\tdouble[,] x = new double[m,p];\n\t\tdouble[,] c = new double[p,n];\n\t\tfor (int i = 0; i < n; ++i) // transpose\n\t\t\tfor (int j = 0; j < p; ++j)\n\t\t\t\tc[j,i] = b[i,j];\n\t\tfor (int i = 0; i < m; ++i)\n\t\t\tfor (int j = 0; j < p; ++j) {\n\t\t\t\tdouble s = 0.0;\n\t\t\t\tfor (int k = 0; k < n; ++k)\n\t\t\t\t\ts += a[i,k] * c[j,k];\n\t\t\t\tx[i,j] = s;\n\t\t\t}\n\t\treturn x;\n\t}\n\tpublic static void Main(String[] args) {\n\t\tint n = 100;\n\t\tif (args.GetLength(0) >= 1) n = int.Parse(args[0]);\n\t\tn = n / 2 * 2;\n\t\tmatmul_v1 m = new matmul_v1();\n\t\tdouble[,] a, b, x;\n\t\ta = m.matgen(n);\n\t\tb = m.matgen(n);\n\t\tx = m.matmul(a, b);\n\t\tConsole.WriteLine(x[n/2,n/2]);\n\t}\n}\n"
  },
  {
    "path": "benchmarks/Matmul/matmul_d.d",
    "content": "// Originally written by Attractive Chaos; distributed under the MIT license (D V.2 code)\n// Contributed by leonardo and then modified by Attractive Chaos to remove D 2.0 features\n\nimport std.stdio, std.string;\n\ndouble[][] matGen(in int n) {\n\tdouble tmp = 1.0 / n / n;\n\tauto a = new double[][](n, n);\n\tforeach (int i, row; a)\n\t\tforeach (int j, ref x; row)\n\t\t\tx = tmp * (i - j) * (i + j);\n\treturn a;\n}\n\ndouble[][] matMul(in double[][] a, in double[][] b) {\n\tint m = a.length, n = a[0].length, p = b[0].length;\n\n\t// transpose\n\tauto c = new double[][](p, n);\n\tforeach (i, brow; b)\n\t\tforeach (j, bx; brow)\n\t\t\tc[j][i] = bx;\n\n\tauto x = new double[][](m, p);\n\n\tforeach (i, arow; a)\n\t\tforeach (j, crow; c) {\n\t\t\t// x[i][j] = std.numeric.dotProduct(arow, crow); // right way\n\t\t\tdouble s = 0.0;\n\t\t\tforeach (k, arowk; arow)\n\t\t\t\ts += arowk * crow[k];\n\t\t\tx[i][j] = s;\n\t\t}\n\n\treturn x;\n}\n\nvoid main(in string[] args) {\n\tint n = 100;\n\tif (args.length >= 2) n = atoi(args[1]) / 2 * 2;\n\tauto a = matGen(n);\n\tauto b = matGen(n);\n\tauto x = matMul(a, b);\n\twritefln(x[n / 2][n / 2]);\n}\n"
  },
  {
    "path": "benchmarks/Matmul/matmul_dart.dart",
    "content": "import 'dart:scalarlist';\n\nmat_transpose(a)\n{\n\tint m = a.length, n = a[0].length; // m rows and n cols\n\tvar b = new List(n);\n\tfor (int j = 0; j < n; ++j) b[j] = new Float64List(m);\n\tfor (int i = 0; i < m; ++i)\n\t\tfor (int j = 0; j < n; ++j)\n\t\t\tb[j][i] = a[i][j];\n\treturn b;\n}\n\nmat_mul(a, b)\n{\n\tinner_loop(t, n, ai, c)\n\t{\n\t\tvar xi = new Float64List(t);\n\t\tfor (int j = 0; j < t; ++j) {\n\t\t\tdouble sum = 0.0;\n\t\t\tfor (int k = 0; k < n; ++k) sum += ai[k] * c[j][k];\n\t\t\txi[j] = sum;\n\t\t}\n\t\treturn xi;\n\t}\n\n\tint m = a.length, n = a[0].length, s = b.length, t = b[0].length;\n\tif (n != s) return null;\n\tvar x = new List(m), c = mat_transpose(b);\n\tfor (int i = 0; i < m; ++i)\n\t\tx[i] = inner_loop(t, n, a[i], c);\n\treturn x;\n}\n\nmat_gen(int n)\n{\n\tvar a = new List(n);\n\tdouble t = 1.0 / n / n;\n\tfor (int i = 0; i < n; ++i) {\n\t\ta[i] = new Float64List(n);\n\t\tfor (int j = 0; j < n; ++j)\n\t\t\ta[i][j] = t * (i - j) * (i + j);\n\t}\n\treturn a;\n}\n\nmain()\n{\n\tList<String> argv = new Options().arguments;\n\tint n = argv.length != 0? int.parse(argv[0]) : 1000;\n\tvar a = mat_gen(n), b = mat_gen(n);\n\tvar c = mat_mul(a, b);\n\tprint(c[n~/2][n~/2]);\n}\n"
  },
  {
    "path": "benchmarks/Matmul/matmul_go.go",
    "content": "// Written by Attractive Chaos; distributed under the MIT license\n\npackage main\n\nimport \"fmt\"\nimport \"flag\"\nimport \"strconv\"\n\nfunc matgen(n int) [][]float64 {\n\ta := make([][]float64, n)\n\ttmp := float64(1.0) / float64(n) / float64(n) // pretty silly...\n\tfor i := 0; i < n; i++ {\n\t\ta[i] = make([]float64, n)\n\t\tfor j := 0; j < n; j++ {\n\t\t\ta[i][j] = tmp * float64(i-j) * float64(i+j)\n\t\t}\n\t}\n\treturn a\n}\n\nfunc matmul(a [][]float64, b [][]float64) [][]float64 {\n\tm := len(a)\n\tn := len(a[0])\n\tp := len(b[0])\n\tx := make([][]float64, m)\n\tc := make([][]float64, p)\n\tfor i := 0; i < p; i++ {\n\t\tc[i] = make([]float64, n)\n\t\tfor j := 0; j < n; j++ {\n\t\t\tc[i][j] = b[j][i]\n\t\t}\n\t}\n\tfor i, am := range a {\n\t\tx[i] = make([]float64, p)\n\t\tfor j, cm := range c {\n\t\t\ts := float64(0)\n\t\t\tfor k, m := range am {\n\t\t\t\ts += m*cm[k]\n\t\t\t}\n\t\t\tx[i][j] = s\n\t\t}\n\t}\n\treturn x\n}\n\nfunc main() {\n\tn := int(100)\n\tflag.Parse()\n\tif flag.NArg() > 0 { n,_ = strconv.Atoi(flag.Arg(0)) }\n\ta := matgen(n)\n\tb := matgen(n)\n\tx := matmul(a, b)\n\tfmt.Printf(\"%f\\n\", x[n/2][n/2])\n}\n"
  },
  {
    "path": "benchmarks/Matmul/matmul_java.java",
    "content": "// Written by Attractive Chaos; distributed under the MIT license\n\nclass matmul_java {\n\tpublic double[][] matgen(int n) {\n\t\tdouble[][] a = new double[n][n];\n\t\tdouble tmp = 1. / n / n;\n\t\tfor (int i = 0; i < n; ++i)\n\t\t\tfor (int j = 0; j < n; ++j)\n\t\t\t\ta[i][j] = tmp * (i - j) * (i + j);\n\t\treturn a;\n\t}\n\tpublic double[][] matmul(double[][] a, double[][] b) {\n\t\tint m = a.length, n = a[0].length, p = b[0].length;\n\t\tdouble[][] x = new double[m][p];\n\t\tdouble[][] c = new double[p][n];\n\t\tfor (int i = 0; i < n; ++i) // transpose\n\t\t\tfor (int j = 0; j < p; ++j)\n\t\t\t\tc[j][i] = b[i][j];\n\t\tfor (int i = 0; i < m; ++i)\n\t\t\tfor (int j = 0; j < p; ++j) {\n\t\t\t\tdouble s = 0.0;\n\t\t\t\tfor (int k = 0; k < n; ++k)\n\t\t\t\t\ts += a[i][k] * c[j][k];\n\t\t\t\tx[i][j] = s;\n\t\t\t}\n\t\treturn x;\n\t}\n\tpublic static void main(String[] args) {\n\t\tint n = 300;\n\t\tn = n / 2 * 2;\n\t\tmatmul_java m = new matmul_java();\n\t\tdouble[][] a, b, x;\n\t\ta = m.matgen(n);\n\t\tb = m.matgen(n);\n\t\tx = m.matmul(a, b);\n\t\t//System.out.println(x[n/2][n/2]);\n\t}\n}\n"
  },
  {
    "path": "benchmarks/Matmul/matmul_javascript.js",
    "content": "// Writen by Attractive Chaos; distributed under the MIT license\n\nMath.m = {};\n\nMath.m.T = function(a) { // matrix transpose\n\tvar b = [], m = a.length, n = a[0].length; // m rows and n cols\n\tfor (var j = 0; j < n; ++j) b[j] = [];\n\tfor (var i = 0; i < m; ++i)\n\t\tfor (var j = 0; j < n; ++j)\n\t\t\tb[j].push(a[i][j]);\n\treturn b;\n}\n\nMath.m.mul = function(a, b) { // matrix mul\n\tvar m = a.length, n = a[0].length, s = b.length, t = b[0].length;\n\tif (n != s) return null;\n\tvar x = [], c = Math.m.T(b);\n\tfor (var i = 0; i < m; ++i) {\n\t\tx[i] = [];\n\t\tfor (var j = 0; j < t; ++j) {\n\t\t\tvar sum = 0;\n\t\t\tvar ai = a[i], cj = c[j];\n\t\t\tfor (var k = 0; k < n; ++k) sum += ai[k] * cj[k];\n\t\t\tx[i].push(sum);\n\t\t}\n\t}\n\treturn x;\n}\n\nfunction matgen(n) {\n\tvar a = [], tmp = 1. / n / n;\n\tfor (i = 0; i < n; ++i) {\n\t\ta[i] = []\n\t\tfor (j = 0; j < n; ++j)\n\t\t\ta[i][j] = tmp * (i - j) * (i + j);\n\t}\n\treturn a;\n}\n\nvar n = 300;\nvar a = matgen(n);\nvar b = matgen(n);\nvar c = Math.m.mul(a, b);\n//print(c[n/2][n/2]);\n\n"
  },
  {
    "path": "benchmarks/Matmul/matmul_lua.lua",
    "content": "-- Writen by Attractive Chaos; distributed under the MIT license\n\nmatrix = {}\n\nfunction matrix.T(a)\n\tlocal m, n, x = #a, #a[1], {};\n\tfor i = 1, n do\n\t\tx[i] = {};\n\t\tfor j = 1, m do x[i][j] = a[j][i] end\n\tend\n\treturn x;\nend\n\nfunction matrix.mul(a, b)\n\tassert(#a[1] == #b);\n\tlocal m, n, p, x = #a, #a[1], #b[1], {};\n\tlocal c = matrix.T(b); -- transpose for efficiency\n\tfor i = 1, m do\n\t\tx[i] = {}\n\t\tlocal xi = x[i];\n\t\tfor j = 1, p do\n\t\t\tlocal sum, ai, cj = 0, a[i], c[j];\n\t\t\t-- for luajit, caching c[j] or not makes no difference; lua is not so clever\n\t\t\tfor k = 1, n do sum = sum + ai[k] * cj[k] end\n\t\t\txi[j] = sum;\n\t\tend\n\tend\n\treturn x;\nend\n\nfunction matgen(n)\n\tlocal a, tmp = {}, 1. / n / n;\n\tfor i = 1, n do\n\t\ta[i] = {}\n\t\tfor j = 1, n do\n\t\t\ta[i][j] = tmp * (i - j) * (i + j - 2) \n\t\tend\n\tend\n\treturn a;\nend\n\nlocal n = 300;\nn = math.floor(n/2) * 2;\nlocal a = matrix.mul(matgen(n), matgen(n));\n--print(a[n/2+1][n/2+1]);\n"
  },
  {
    "path": "benchmarks/Matmul/matmul_perl.pl",
    "content": "#!/usr/bin/perl -w\n\n# Writen by Attractive Chaos; distributed under the MIT license\n\nuse strict;\nuse warnings;\n\n&main;\n\nsub main {\n\tmy $n = $ARGV[0] || 100;\n\t$n = int($n/2) * 2;\n\tmy (@a, @b, @x);\n\t&matgen($n, \\@a); &matgen($n, \\@b);\n\t&mul(\\@a, \\@b, \\@x);\n\tprint $x[$n/2][$n/2], \"\\n\";\n}\n\nsub transpose {\n\tmy ($a, $b) = @_;\n\tmy $m = @$a;\n\tmy $n = @{$a->[0]};\n\t@$b = ();\n\tfor my $i (0 .. $n - 1) {\n\t\t@{$b->[$i]} = ();\n\t\tfor my $j (0 .. $m - 1) {\n\t\t\tpush(@{$b->[$i]}, $a->[$j][$i]);\n\t\t}\n\t}\n}\nsub mul {\n\tmy ($a, $b, $x) = @_;\n\tmy $m = @$a;\n\tmy $n = @{$a->[0]};\n\tmy $p = @{$b->[0]};\n\tmy @c;\n\t&transpose($b, \\@c);\n\tfor my $i (0 .. $m - 1) {\n\t\t@{$x->[$i]} = ();\n\t\tfor my $j (0 .. $p - 1) {\n\t\t\tmy $sum = 0;\n\t\t\tmy ($ai, $cj) = ($a->[$i], $c[$j]);\n\t\t\tfor my $k (0 .. $n - 1) {\n\t\t\t\t$sum += $ai->[$k] * $cj->[$k];\n\t\t\t}\n\t\t\tpush(@{$x->[$i]}, $sum);\n\t\t}\n\t}\n}\nsub matgen {\n\tmy ($n, $a) = @_;\n\t@$a = ();\n\tmy $tmp = 1. / $n / $n;\n\tfor my $i (0 .. $n - 1) {\n\t\tfor my $j (0 .. $n - 1) {\n\t\t\t$a->[$i][$j] = $tmp * ($i - $j) * ($i + $j);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "benchmarks/Matmul/matmul_python.py",
    "content": "import sys\n\n# Writen by Attractive Chaos; distributed under the MIT license\n\n# reference: http://www.syntagmatic.net/matrix-multiplication-in-python/\n\ndef matmul(a, b): # FIXME: no error checking\n\tc = [[b[j][i] for j in range(len(b))] for i in range(len(b[0]))]\n\td = [[0 for j in range(len(b[0]))] for i in range(len(a))] # transpose\n\tfor i in range(len(a)):\n\t\tfor j in range(len(b[0])):\n\t\t\ts = 0\n\t\t\tai = a[i]\n\t\t\tcj = c[j]\n\t\t\tfor k in range(len(a[0])):\n\t\t\t\ts += ai[k] * cj[k]\n\t\t\td[i][j] = s\n\treturn d\n\t\ndef main():\n\tn = 300\n\tn = int(float(n)/2) * 2 # FIXME: I am sure there are better ways to do this...\n\ttmp = 1. / n / n\n\ta = [[tmp * (i - j) * (i + j) for j in range(n)] for i in range(n)]\n\tb = [[tmp * (i - j) * (i + j) for j in range(n)] for i in range(n)]\n\td = matmul(a, b)\n\t#print(d[int(n/2)][int(n/2)])\n\nif __name__ == '__main__': main()\n"
  },
  {
    "path": "benchmarks/Matmul/matmul_r.R",
    "content": "matgen <- function(n) {\n\ty0 <- matrix(rep(seq(0, n-1), n), n)\n\ty1 <- t(y0)\n\tz <- 1 / n / n\n\t(y0 - y1) * (y0 + y1) * z\n}\n\nmatmul <- function(a, b) {\n\t# transposing or not seems to make no difference\n\tm <- dim(a)[1]\n\tn <- dim(a)[2]\n\tp <- dim(b)[2]\n\tx <- matrix(rep(0, m * p), m)\n\tfor (i in seq(1, m)) {\n\t\tfor (j in seq(1, p)) {\n\t\t\t#x[i,j] <- sum(a[i,], b[,j]) # using this line: 43.3 sec, 64.6 MB\n\t\t\ts <- 0; ai <- a[i,]; bj <- b[,j]; for (k in seq(1, n)) s <- s + ai[k] * bj[k]; x[i,j] <- s\n\t\t}\n\t}\n\tx\n}\n\nn <- as.integer(commandArgs(trailingOnly = T)[1])\nif (is.na(n)) n <- 100\n\n# x <- matgen(n) %*% matgen(n) # using this line: 2.7 sec, 53.0 MB\nx <- matmul(matgen(n), matgen(n))\nx[n/2+1,n/2+1]\n"
  },
  {
    "path": "benchmarks/Matmul/matmul_ruby.rb",
    "content": "# Writen by Attractive Chaos; distributed under the MIT license\n\n# This version does not use the built-in Matrix object\n# reference: http://vikhyat.net/articles/matrix_multiplication_ruby/\n\ndef matmul(a, b)\n\tm = a.length\n\tn = a[0].length\n\tp = b[0].length\n\t# transpose\n\tb2 = Array.new(n) { Array.new(p) { 0 } }\n\tfor i in 0 .. n-1\n\t\tfor j in 0 .. p-1\n\t\t\tb2[j][i] = b[i][j]\n\t\tend\n\tend\n\t# multiplication\n  \tc = Array.new(m) { Array.new(p) { 0 } }\n\tfor i in 0 .. m-1\n\t\tfor j in 0 .. p-1\n\t\t\ts = 0\n\t\t\tai, b2j = a[i], b2[j]\n\t\t\tfor k in 0 .. n-1\n\t\t\t\ts += ai[k] * b2j[k]\n\t\t\tend\n\t\t\tc[i][j] = s\n\t\tend\n\tend\n\treturn c\nend\n\ndef matgen(n)\n\ttmp = 1.0 / n / n\n  \ta = Array.new(n) { Array.new(n) { 0 } }\n\tfor i in 0 .. n-1\n\t\tfor j in 0 .. n-1\n\t\t\ta[i][j] = tmp * (i - j) * (i + j)\n\t\tend\n\tend\n\treturn a\nend\n\t\t\t\nn = 300\nn = n / 2 * 2\na = matgen(n)\nb = matgen(n)\nc = matmul(a, b)\n#puts c[n/2][n/2]\n"
  },
  {
    "path": "benchmarks/Nbodies/nbodies_c.c",
    "content": "#include <math.h>\n#include <stdlib.h>\n\n#undef M_PI\n#define M_PI 3.14159265359\n\nstatic const double solar_mass = 4 * M_PI * M_PI;\nstatic const double days_per_year = 365.24;\n\nstruct Body {\n  double  x,  y,  z;\n  double vx, vy, vz;\n  double mass;\n};\n\nstatic void Body_Offset_Momentum(struct Body* b, double px, double py, double pz) {\n  b->vx = -px / solar_mass;\n  b->vy = -py / solar_mass;\n  b->vz = -pz / solar_mass;\n}\n\nstatic void Bodies_Advance(struct Body* bodies, size_t nbodies, double dt) {\n\n  for(size_t i = 0; i < nbodies; i++) {\n\n    struct Body* body0 = &bodies[i];\n\n    for(size_t j = i+1; j < nbodies; j++) {\n\n      struct Body* body1 = &bodies[j];\n\n      double dx = body0->x - body1->x;\n      double dy = body0->y - body1->y;\n      double dz = body0->z - body1->z;\n\n      double dsquared = dx * dx + dy * dy + dz * dz;\n      double distance = sqrt(dsquared);\n      double mag = dt / (dsquared * distance);\n\n      body0->vx -= dx * body1->mass * mag;\n      body0->vy -= dy * body1->mass * mag;\n      body0->vz -= dz * body1->mass * mag;\n\n      body1->vx += dx * body0->mass * mag;\n      body1->vy += dy * body0->mass * mag;\n      body1->vz += dz * body0->mass * mag;\n    }\n  }\n\n  for(size_t i = 0; i < nbodies; i++) {\n    struct Body* b = &bodies[i];\n    b->x += dt * b->vx;\n    b->y += dt * b->vy;\n    b->z += dt * b->vz;\n  }\n}\n        \nstatic double Bodies_Energy(struct Body* bodies, size_t nbodies) {\n\n  double dx = 0.0;\n  double dy = 0.0;\n  double dz = 0.0;\n  double distance = 0.0;\n  double e = 0.0;\n  \n  for(size_t i = 0; i < nbodies; i++) {\n  \n    struct Body* body0 = &bodies[i];\n\n    e += (0.5 * body0->mass * (\n        body0->vx * body0->vx +\n        body0->vy * body0->vy +\n        body0->vz * body0->vz));\n\n    for(size_t j = i+1; j < nbodies; j++) {\n      \n      struct Body* body1 = &bodies[j];\n\n      dx = body0->x - body1->x;\n      dy = body0->y - body1->y;\n      dz = body0->z - body1->z;\n\n      distance = sqrt(dx * dx + dy * dy + dz * dz);\n      e -= (body0->mass * body1->mass) / distance;\n    }\n  }\n  \n  return e;\n}\n\nint main(int argc, char** argv) {\n  \n  struct Body jupiter = (struct Body){\n    4.84143144246472090e+00,\n    -1.16032004402742839e+00,\n    -1.03622044471123109e-00,\n    days_per_year * 1.66007664274403694e-03,\n    days_per_year * 7.69901118419740425e-03,\n    days_per_year * -6.90460016972063023e-05,\n    solar_mass * 9.54791938424326609e-04};\n  \n  struct Body saturn = (struct Body){\n    8.34336671824457987e+00,\n    4.12479856412430479e+00,\n    -4.03523417114321381e-01,\n    days_per_year * -2.76742510726862411e-03,\n    days_per_year * 4.99852801234917238e-03,\n    days_per_year * 2.30417297573763929e-05,\n    solar_mass * 2.85885980666130812e-04};\n\n  struct Body uranus = (struct Body){\n    1.28943695621391310e+01,\n    -1.51111514016986312e+01,\n    -2.23307578892655734e-01,\n    days_per_year * 2.96460137564761618e-03,\n    days_per_year * 2.37847173959480950e-03,\n    days_per_year * -2.96589568540237556e-05,\n    solar_mass * 4.36624404335156298e-05};\n\n  struct Body neptune = (struct Body){\n    1.53796971148509165e+01,\n    -2.59193146099879641e+01,\n    1.79258772950371181e-01,\n    days_per_year * 2.68067772490389322e-03,\n    days_per_year * 1.62824170038242295e-03,\n    days_per_year * -9.51592254519715870e-05,\n    solar_mass * 5.15138902046611451e-05};\n\n  struct Body sun = (struct Body){\n    0.0, 0.0, 0.0,\n    0.0, 0.0, 0.0,\n    solar_mass};\n  \n  size_t nbodies = 5;\n  struct Body* bodies = (struct Body[5]){ \n    jupiter, saturn, uranus, neptune, sun};\n  \n  double px = 0.0;\n  double py = 0.0;\n  double pz = 0.0;\n\n  for(size_t i = 0; i < nbodies; i++) {\n    struct Body* b = &bodies[i];\n    px += b->vx * b->mass;\n    py += b->vy * b->mass;\n    pz += b->vz * b->mass;\n  }\n  \n  Body_Offset_Momentum(&bodies[0], px, py, pz);\n  \n  for(size_t i = 0; i < 100000; i++) {\n    Bodies_Advance(bodies, nbodies, 1e-5);\n  }\n  \n}\n\n\n\n\n"
  },
  {
    "path": "benchmarks/Nbodies/nbodies_cello.c",
    "content": "#include \"Cello.h\"\n\nstatic const double solar_mass = 4 * M_PI * M_PI;\nstatic const double days_per_year = 365.24;\n\nstruct Body {\n  double  x,  y,  z;\n  double vx, vy, vz;\n  double mass;\n};\n\nstatic void Body_Offset_Momentum(struct Body* self, double px, double py, double pz) {\n  self->vx = -px / solar_mass;\n  self->vy = -py / solar_mass;\n  self->vz = -pz / solar_mass;\n}\n\nvar Body = Cello(Body);\n\nstatic void Bodies_Advance(var bodies, double dt) {\n  \n  \n  size_t nbodies = len(bodies);\n  \n  foreach(i in range($I(nbodies))) {\n\n    struct Body* body0 = get(bodies, i);\n\n    foreach(j in range($I(c_int(i)+1), $I(nbodies))) {\n\n      struct Body* body1 = get(bodies, j);\n\n      double dx = body0->x - body1->x;\n      double dy = body0->y - body1->y;\n      double dz = body0->z - body1->z;\n\n      double dsquared = dx * dx + dy * dy + dz * dz;\n      double mag = dt / (dsquared * sqrt(dsquared));\n\n      body0->vx -= dx * body1->mass * mag;\n      body0->vy -= dy * body1->mass * mag;\n      body0->vz -= dz * body1->mass * mag;\n\n      body1->vx += dx * body0->mass * mag;\n      body1->vy += dy * body0->mass * mag;\n      body1->vz += dz * body0->mass * mag;\n    }\n  }\n\n  foreach (body in bodies) {\n    struct Body* b = body;\n    b->x += dt * b->vx;\n    b->y += dt * b->vy;\n    b->z += dt * b->vz;\n  }\n}\n        \nstatic double Bodies_Energy(var bodies) {\n\n  double dx = 0.0;\n  double dy = 0.0;\n  double dz = 0.0;\n  double distance = 0.0;\n  double e = 0.0;\n  size_t nbodies = len(bodies);\n  \n  foreach(i in range($I(nbodies))) {\n  \n    struct Body* body0 = get(bodies, i);\n\n    e += (0.5 * body0->mass * (\n        body0->vx * body0->vx +\n        body0->vy * body0->vy +\n        body0->vz * body0->vz));\n\n    foreach(j in range($I(c_int(i)+1), $I(nbodies))) {\n      \n      struct Body* body1 = get(bodies, j);\n\n      dx = body0->x - body1->x;\n      dy = body0->y - body1->y;\n      dz = body0->z - body1->z;\n\n      distance = sqrt(dx * dx + dy * dy + dz * dz);\n      e -= (body0->mass * body1->mass) / distance;\n    }\n  }\n  \n  return e;\n}\n\nint main(int argc, char** argv) {\n  \n  var jupiter = $(Body,\n    4.84143144246472090e+00,\n    -1.16032004402742839e+00,\n    -1.03622044471123109e-00,\n    days_per_year * 1.66007664274403694e-03,\n    days_per_year * 7.69901118419740425e-03,\n    days_per_year * -6.90460016972063023e-05,\n    solar_mass * 9.54791938424326609e-04);\n  \n  var saturn = $(Body,\n    8.34336671824457987e+00,\n    4.12479856412430479e+00,\n    -4.03523417114321381e-01,\n    days_per_year * -2.76742510726862411e-03,\n    days_per_year * 4.99852801234917238e-03,\n    days_per_year * 2.30417297573763929e-05,\n    solar_mass * 2.85885980666130812e-04);\n\n  var uranus = $(Body,\n    1.28943695621391310e+01,\n    -1.51111514016986312e+01,\n    -2.23307578892655734e-01,\n    days_per_year * 2.96460137564761618e-03,\n    days_per_year * 2.37847173959480950e-03,\n    days_per_year * -2.96589568540237556e-05,\n    solar_mass * 4.36624404335156298e-05);\n\n  var neptune = $(Body,\n    1.53796971148509165e+01,\n    -2.59193146099879641e+01,\n    1.79258772950371181e-01,\n    days_per_year * 2.68067772490389322e-03,\n    days_per_year * 1.62824170038242295e-03,\n    days_per_year * -9.51592254519715870e-05,\n    solar_mass * 5.15138902046611451e-05);\n\n  var sun = $(Body,\n    0.0, 0.0, 0.0,\n    0.0, 0.0, 0.0,\n    solar_mass);\n  \n  var bodies = new(Array, Body, \n    jupiter, saturn, uranus, neptune, sun);\n  \n  double px = 0.0;\n  double py = 0.0;\n  double pz = 0.0;\n\n  foreach(body in bodies) {\n    struct Body* b = body;\n    px += b->vx * b->mass;\n    py += b->vy * b->mass;\n    pz += b->vz * b->mass;\n  }\n  \n  Body_Offset_Momentum(get(bodies, $I(0)), px, py, pz);\n  \n  foreach(i in range($I(100000))) {\n    Bodies_Advance(bodies, 1e-5);\n  }\n  \n  del(bodies);\n    \n  return 0;\n}\n\n\n\n\n"
  },
  {
    "path": "benchmarks/Nbodies/nbodies_cpp.cpp",
    "content": "#include <vector>\n#include <cmath>\n\n#undef M_PI\n#define M_PI 3.14159265358979323846\n\nstatic const double solar_mass = 4 * M_PI * M_PI;\nstatic const double days_per_year = 365.24;\n\nclass Body {\n  \n  public:\n  \n  Body(double  x, double  y, double  z, \n       double vx, double vy, double vz, double mass)\n   : x(x), y(y), z(z), vx(vx), vy(vy), vz(vz), mass(mass) {}\n  \n  double  x,  y,  z;\n  double vx, vy, vz;\n  double mass;\n\n  void Offset_Momentum(double px, double py, double pz) {\n    vx = -px / solar_mass;\n    vy = -py / solar_mass;\n    vz = -pz / solar_mass;\n  }\n  \n};\n\nstatic void Bodies_Advance(std::vector<Body*> bodies, double dt) {\n\n  for(int i = 0; i < bodies.size(); i++) {\n\n    Body* body0 = bodies[i];\n\n    for(int j = i+1; j < bodies.size(); j++) {\n\n      Body* body1 = bodies[j];\n\n      double dx = body0->x - body1->x;\n      double dy = body0->y - body1->y;\n      double dz = body0->z - body1->z;\n\n      double dsquared = dx * dx + dy * dy + dz * dz;\n      double distance = sqrt(dsquared);\n      double mag = dt / (dsquared * distance);\n\n      body0->vx -= dx * body1->mass * mag;\n      body0->vy -= dy * body1->mass * mag;\n      body0->vz -= dz * body1->mass * mag;\n\n      body1->vx += dx * body0->mass * mag;\n      body1->vy += dy * body0->mass * mag;\n      body1->vz += dz * body0->mass * mag;\n    }\n  }\n\n  for (auto &b : bodies) {\n    b->x += dt * b->vx;\n    b->y += dt * b->vy;\n    b->z += dt * b->vz;\n  }\n}\n        \nstatic double Bodies_Energy(std::vector<Body*> bodies) {\n\n  double dx = 0.0;\n  double dy = 0.0;\n  double dz = 0.0;\n  double distance = 0.0;\n  double e = 0.0;\n  \n  for(int i = 0; i < bodies.size(); i++) {\n  \n    Body* body0 = bodies[i];\n\n    e += (0.5 * body0->mass * (\n        body0->vx * body0->vx +\n        body0->vy * body0->vy +\n        body0->vz * body0->vz));\n\n    for(int j = i+1; j < bodies.size(); j++) {\n      \n      Body* body1 = bodies[j];\n\n      dx = body0->x - body1->x;\n      dy = body0->y - body1->y;\n      dz = body0->z - body1->z;\n\n      distance = sqrt(dx * dx + dy * dy + dz * dz);\n      e -= (body0->mass * body1->mass) / distance;\n    }\n  }\n  \n  return e;\n}\n\nint main(int argc, char** argv) {\n  \n  Body jupiter = Body(\n    4.84143144246472090e+00,\n    -1.16032004402742839e+00,\n    -1.03622044471123109e-00,\n    days_per_year * 1.66007664274403694e-03,\n    days_per_year * 7.69901118419740425e-03,\n    days_per_year * -6.90460016972063023e-05,\n    solar_mass * 9.54791938424326609e-04);\n  \n  Body saturn = Body(\n    8.34336671824457987e+00,\n    4.12479856412430479e+00,\n    -4.03523417114321381e-01,\n    days_per_year * -2.76742510726862411e-03,\n    days_per_year * 4.99852801234917238e-03,\n    days_per_year * 2.30417297573763929e-05,\n    solar_mass * 2.85885980666130812e-04);\n\n  Body uranus = Body(\n    1.28943695621391310e+01,\n    -1.51111514016986312e+01,\n    -2.23307578892655734e-01,\n    days_per_year * 2.96460137564761618e-03,\n    days_per_year * 2.37847173959480950e-03,\n    days_per_year * -2.96589568540237556e-05,\n    solar_mass * 4.36624404335156298e-05);\n\n  Body neptune = Body(\n    1.53796971148509165e+01,\n    -2.59193146099879641e+01,\n    1.79258772950371181e-01,\n    days_per_year * 2.68067772490389322e-03,\n    days_per_year * 1.62824170038242295e-03,\n    days_per_year * -9.51592254519715870e-05,\n    solar_mass * 5.15138902046611451e-05);\n\n  Body sun = Body(\n    0.0, 0.0, 0.0,\n    0.0, 0.0, 0.0,\n    solar_mass);\n  \n  auto bodies = std::vector<Body*>();\n  bodies.push_back(&jupiter);\n  bodies.push_back(&saturn);\n  bodies.push_back(&uranus);\n  bodies.push_back(&neptune);\n  bodies.push_back(&sun);\n  \n  double px = 0.0;\n  double py = 0.0;\n  double pz = 0.0;\n\n  for(auto &b : bodies) {\n    px += b->vx * b->mass;\n    py += b->vy * b->mass;\n    pz += b->vz * b->mass;\n  }\n  \n  bodies[0]->Offset_Momentum(px, py, pz);\n  \n  for(int i = 0; i < 100000; i++) {\n    Bodies_Advance(bodies, 1e-5);\n  }\n  \n}\n\n\n\n\n"
  },
  {
    "path": "benchmarks/Nbodies/nbodies_java.java",
    "content": "public final class nbodies_java {\n    public static void main(String[] args) {\n\n        NBodySystem bodies = new NBodySystem();\n        for (int i=0; i<100000; ++i) {\n           bodies.advance(1e-5);\n        }\n    }\n}\n\nfinal class NBodySystem {\n   private Body[] bodies;\n\n   public NBodySystem(){\n      bodies = new Body[]{\n            Body.sun(),\n            Body.jupiter(),\n            Body.saturn(),\n            Body.uranus(),\n            Body.neptune()\n         };\n\n      double px = 0.0;\n      double py = 0.0;\n      double pz = 0.0;\n      for(int i=0; i < bodies.length; ++i) {\n         px += bodies[i].vx * bodies[i].mass;\n         py += bodies[i].vy * bodies[i].mass;\n         pz += bodies[i].vz * bodies[i].mass;\n      }\n      bodies[0].offsetMomentum(px,py,pz);\n   }\n\n   public void advance(double dt) {\n\n      for(int i=0; i < bodies.length; ++i) {\n            Body iBody = bodies[i];\n         for(int j=i+1; j < bodies.length; ++j) {\n                double dx = iBody.x - bodies[j].x;\n            double dy = iBody.y - bodies[j].y;\n            double dz = iBody.z - bodies[j].z;\n\n                double dSquared = dx * dx + dy * dy + dz * dz;\n                double distance = Math.sqrt(dSquared);\n                double mag = dt / (dSquared * distance);\n\n            iBody.vx -= dx * bodies[j].mass * mag;\n            iBody.vy -= dy * bodies[j].mass * mag;\n            iBody.vz -= dz * bodies[j].mass * mag;\n\n            bodies[j].vx += dx * iBody.mass * mag;\n            bodies[j].vy += dy * iBody.mass * mag;\n            bodies[j].vz += dz * iBody.mass * mag;\n         }\n      }\n\n        for ( Body body : bodies) {\n         body.x += dt * body.vx;\n         body.y += dt * body.vy;\n         body.z += dt * body.vz;\n      }\n   }\n\n   public double energy(){\n      double dx, dy, dz, distance;\n      double e = 0.0;\n\n      for (int i=0; i < bodies.length; ++i) {\n            Body iBody = bodies[i];\n            e += 0.5 * iBody.mass *\n                 ( iBody.vx * iBody.vx\n                   + iBody.vy * iBody.vy\n                   + iBody.vz * iBody.vz );\n\n         for (int j=i+1; j < bodies.length; ++j) {\n                Body jBody = bodies[j];\n                dx = iBody.x - jBody.x;\n            dy = iBody.y - jBody.y;\n            dz = iBody.z - jBody.z;\n\n            distance = Math.sqrt(dx*dx + dy*dy + dz*dz);\n            e -= (iBody.mass * jBody.mass) / distance;\n         }\n      }\n      return e;\n   }\n}\n\n\nfinal class Body {\n   static final double PI = 3.141592653589793;\n   static final double SOLAR_MASS = 4 * PI * PI;\n   static final double DAYS_PER_YEAR = 365.24;\n\n   public double x, y, z, vx, vy, vz, mass;\n\n   public Body(){}\n\n   static Body jupiter(){\n      Body p = new Body();\n      p.x = 4.84143144246472090e+00;\n      p.y = -1.16032004402742839e+00;\n      p.z = -1.03622044471123109e-01;\n      p.vx = 1.66007664274403694e-03 * DAYS_PER_YEAR;\n      p.vy = 7.69901118419740425e-03 * DAYS_PER_YEAR;\n      p.vz = -6.90460016972063023e-05 * DAYS_PER_YEAR;\n      p.mass = 9.54791938424326609e-04 * SOLAR_MASS;\n      return p;\n   }\n\n   static Body saturn(){\n      Body p = new Body();\n      p.x = 8.34336671824457987e+00;\n      p.y = 4.12479856412430479e+00;\n      p.z = -4.03523417114321381e-01;\n      p.vx = -2.76742510726862411e-03 * DAYS_PER_YEAR;\n      p.vy = 4.99852801234917238e-03 * DAYS_PER_YEAR;\n      p.vz = 2.30417297573763929e-05 * DAYS_PER_YEAR;\n      p.mass = 2.85885980666130812e-04 * SOLAR_MASS;\n      return p;\n   }\n\n   static Body uranus(){\n      Body p = new Body();\n      p.x = 1.28943695621391310e+01;\n      p.y = -1.51111514016986312e+01;\n      p.z = -2.23307578892655734e-01;\n      p.vx = 2.96460137564761618e-03 * DAYS_PER_YEAR;\n      p.vy = 2.37847173959480950e-03 * DAYS_PER_YEAR;\n      p.vz = -2.96589568540237556e-05 * DAYS_PER_YEAR;\n      p.mass = 4.36624404335156298e-05 * SOLAR_MASS;\n      return p;\n   }\n\n   static Body neptune(){\n      Body p = new Body();\n      p.x = 1.53796971148509165e+01;\n      p.y = -2.59193146099879641e+01;\n      p.z = 1.79258772950371181e-01;\n      p.vx = 2.68067772490389322e-03 * DAYS_PER_YEAR;\n      p.vy = 1.62824170038242295e-03 * DAYS_PER_YEAR;\n      p.vz = -9.51592254519715870e-05 * DAYS_PER_YEAR;\n      p.mass = 5.15138902046611451e-05 * SOLAR_MASS;\n      return p;\n   }\n\n   static Body sun(){\n      Body p = new Body();\n      p.mass = SOLAR_MASS;\n      return p;\n   }\n\n   Body offsetMomentum(double px, double py, double pz){\n      vx = -px / SOLAR_MASS;\n      vy = -py / SOLAR_MASS;\n      vz = -pz / SOLAR_MASS;\n      return this;\n   }\n}\n"
  },
  {
    "path": "benchmarks/Nbodies/nbodies_javascript.js",
    "content": "\nvar pi = 3.141592653589793\nvar solar_mass = 4 * pi * pi\nvar days_per_year = 365.24\n\nvar jupiter = {\n    x: 4.84143144246472090e+00,\n    y: -1.16032004402742839e+00,\n    z: -1.03622044471123109e-01,\n    vx: days_per_year * 1.66007664274403694e-03,\n    vy: days_per_year * 7.69901118419740425e-03,\n    vz: days_per_year * -6.90460016972063023e-05,\n    mass: solar_mass * 9.54791938424326609e-04}\n\nvar saturn = {\n  x: 8.34336671824457987e+00,\n  y: 4.12479856412430479e+00,\n  z: -4.03523417114321381e-01,\n  vx: days_per_year * -2.76742510726862411e-03,\n  vy: days_per_year * 4.99852801234917238e-03,\n  vz: days_per_year * 2.30417297573763929e-05,\n  mass: solar_mass * 2.85885980666130812e-04}\n\nvar uranus = {\n  x: 1.28943695621391310e+01,\n  y: -1.51111514016986312e+01,\n  z: -2.23307578892655734e-01,\n  vx: days_per_year * 2.96460137564761618e-03,\n  vy: days_per_year * 2.37847173959480950e-03,\n  vz: days_per_year * -2.96589568540237556e-05,\n  mass: solar_mass * 4.36624404335156298e-05}\n\nvar neptune = {\n  x: 1.53796971148509165e+01,\n  y: -2.59193146099879641e+01,\n  z: 1.79258772950371181e-01,\n  vx: days_per_year * 2.68067772490389322e-03,\n  vy: days_per_year * 1.62824170038242295e-03,\n  vz: days_per_year * -9.51592254519715870e-05,\n  mass: solar_mass * 5.15138902046611451e-05}\n\nvar sun = {\n   x: 0.0,  y: 0.0,  z: 0.0,\n  vx: 0.0, vy: 0.0, vz: 0.0,\n  mass: solar_mass}\n\nfunction body_offset_momentum(b, px, py, pz) {\n    b.vx = -px / solar_mass\n    b.vy = -py / solar_mass\n    b.vz = -pz / solar_mass\n}\n\n\nfunction bodies_new() {\n\n    bodies = [jupiter, saturn, uranus, neptune, sun];\n\n    px = 0.0;\n    py = 0.0;\n    pz = 0.0;\n\n    for (var i = 0; i < bodies.length; i++) {\n        body = bodies[i];\n        px += body.vx * body.mass;\n        py += body.vy * body.mass;\n        pz += body.vz * body.mass;\n    }\n\n    body_offset_momentum(bodies[0], px, py, pz);\n\n    return bodies;\n}\n\nfunction bodies_advance(bodies, dt) {\n\n    for (var i = 0; i < bodies.length; i++) {\n\n        var body0 = bodies[i]\n\n        for (var j = i+1; j < bodies.length; j++) {\n\n            var body1 = bodies[j];\n\n            var dx = body0.x - body1.x;\n            var dy = body0.y - body1.y;\n            var dz = body0.z - body1.z;\n\n            var dsquared = dx * dx + dy * dy + dz * dz;\n            var distance = Math.sqrt(dsquared);\n            var mag = dt / (dsquared * distance);\n\n            body0.vx -= dx * body1.mass * mag;\n            body0.vy -= dy * body1.mass * mag;\n            body0.vz -= dz * body1.mass * mag;\n\n            body1.vx += dx * body0.mass * mag;\n            body1.vy += dy * body0.mass * mag;\n            body1.vz += dz * body0.mass * mag;\n        }\n    }\n\n    for (var i = 0; i < bodies.length; i++) {\n        body = bodies[i];\n        body.x += dt * body.vx;\n        body.y += dt * body.vy;\n        body.z += dt * body.vz;\n    }\n        \n}\n        \nfunction bodies_energy(bodies) {\n\n    var dx = 0.0;\n    var dy = 0.0;\n    var dz = 0.0;\n    var distance = 0.0;\n    var e = 0.0;\n\n    for (var i = 0; i < bodies.length; i++) {\n\n        var body0 = bodies[i];\n\n        e += (0.5 * body0.mass * (\n            body0.vx * body0.vx +\n            body0.vy * body0.vy +\n            body0.vz * body0.vz));\n\n        for (var j = i+1; j < bodies.length; j++) {\n\n            var body1 = bodies[j];\n\n            dx = body0.x - body1.x;\n            dy = body0.y - body1.y;\n            dz = body0.z - body1.z;\n\n            distance = Math.sqrt(dx * dx + dy * dy + dz * dz);\n            e -= (body0.mass * body1.mass) / distance;\n        }\n\n    }\n\n    return e;\n}\n\nvar bodies = bodies_new()\nfor (var i = 0; i < 100000; i++) {\n    bodies_advance(bodies, 1e-5)\n}\n\n\n\n"
  },
  {
    "path": "benchmarks/Nbodies/nbodies_lua.lua",
    "content": "\nlocal pi = 3.141592653589793\nlocal solar_mass = 4 * pi * pi\nlocal days_per_year = 365.24\n\nlocal jupiter = {\n    x=4.84143144246472090e+00,\n    y=-1.16032004402742839e+00,\n    z=-1.03622044471123109e-01,\n    vx=days_per_year * 1.66007664274403694e-03,\n    vy=days_per_year * 7.69901118419740425e-03,\n    vz=days_per_year * -6.90460016972063023e-05,\n    mass=solar_mass * 9.54791938424326609e-04}\n\nlocal saturn = {\n  x=8.34336671824457987e+00,\n  y=4.12479856412430479e+00,\n  z=-4.03523417114321381e-01,\n  vx=days_per_year * -2.76742510726862411e-03,\n  vy=days_per_year * 4.99852801234917238e-03,\n  vz=days_per_year * 2.30417297573763929e-05,\n  mass=solar_mass * 2.85885980666130812e-04}\n\nlocal uranus = {\n  x=1.28943695621391310e+01,\n  y=-1.51111514016986312e+01,\n  z=-2.23307578892655734e-01,\n  vx=days_per_year * 2.96460137564761618e-03,\n  vy=days_per_year * 2.37847173959480950e-03,\n  vz=days_per_year * -2.96589568540237556e-05,\n  mass=solar_mass * 4.36624404335156298e-05}\n\nlocal neptune = {\n  x=1.53796971148509165e+01,\n  y=-2.59193146099879641e+01,\n  z=1.79258772950371181e-01,\n  vx=days_per_year * 2.68067772490389322e-03,\n  vy=days_per_year * 1.62824170038242295e-03,\n  vz=days_per_year * -9.51592254519715870e-05,\n  mass=solar_mass * 5.15138902046611451e-05}\n\nlocal sun = {\n   x=0.0,  y=0.0,  z=0.0,\n  vx=0.0, vy=0.0, vz=0.0,\n  mass=solar_mass}\n\nfunction body_offset_momentum (b, px, py, pz)\n    b.vx = -px / solar_mass\n    b.vy = -py / solar_mass\n    b.vz = -pz / solar_mass\nend\n\nfunction bodies_advance(bodies, dt)\n\n    for i = 1, #bodies do\n\n        local body0 = bodies[i]\n\n        for j = i+1, #bodies do\n\n            local body1 = bodies[j];\n\n            local dx = body0.x - body1.x;\n            local dy = body0.y - body1.y;\n            local dz = body0.z - body1.z;\n\n            local dsquared = dx * dx + dy * dy + dz * dz;\n            local distance = math.sqrt(dsquared);\n            local mag = dt / (dsquared * distance);\n\n            body0.vx = body0.vx - dx * body1.mass * mag;\n            body0.vy = body0.vy -dy * body1.mass * mag;\n            body0.vz = body0.vz -dz * body1.mass * mag;\n\n            body1.vx = body1.vx + dx * body0.mass * mag;\n            body1.vy = body1.vy + dy * body0.mass * mag;\n            body1.vz = body1.vz + dz * body0.mass * mag;\n        end\n    end\n\n    for i = 1, #bodies do\n        body = bodies[i];\n        body.x = body.x + dt * body.vx;\n        body.y = body.y + dt * body.vy;\n        body.z = body.z + dt * body.vz;\n    end\n        \nend\n        \nfunction bodies_energy(bodies)\n\n    local dx = 0.0;\n    local dy = 0.0;\n    local dz = 0.0;\n    local distance = 0.0;\n    local e = 0.0;\n\n    for i = 1, #bodies.length do\n\n        local body0 = bodies[i];\n\n        e = e + (0.5 * body0.mass * (\n            body0.vx * body0.vx +\n            body0.vy * body0.vy +\n            body0.vz * body0.vz));\n\n        for j = i+1, #bodies do\n\n            local body1 = bodies[j];\n\n            dx = body0.x - body1.x;\n            dy = body0.y - body1.y;\n            dz = body0.z - body1.z;\n\n            distance = sqrt(dx * dx + dy * dy + dz * dz);\n            e = e - (body0.mass * body1.mass) / distance;\n        end\n\n    end\n\n    return e;\nend\n\n\n\nlocal bodies = {jupiter, saturn, uranus, neptune, sun};\n\nlocal px = 0.0;\nlocal py = 0.0;\nlocal pz = 0.0;\n\nfor i = 1, #bodies do\n    local body = bodies[i];\n    px = px + body.vx * body.mass;\n    py = py + body.vy * body.mass;\n    pz = pz + body.vz * body.mass;\nend\n\nbody_offset_momentum(bodies[1], px, py, pz);\n\nfor i = 1, 100000 do\n    bodies_advance(bodies, 1e-5)\nend\n\n\n\n"
  },
  {
    "path": "benchmarks/Nbodies/nbodies_python.py",
    "content": "import math\nimport sys\n\n# Constants\n\npi = 3.141592653589793\nsolar_mass = 4 * pi * pi\ndays_per_year = 365.24\n\n# Bodies\n\nclass Body:\n    \n    def __init__(self, x, y, z, vx, vy, vz, mass):\n        \n        self.x = x\n        self.y = y\n        self.z = z\n        \n        self.vx = vx\n        self.vy = vy\n        self.vz = vz\n        \n        self.mass = mass\n\njupiter = Body(\n    4.84143144246472090e+00,\n    -1.16032004402742839e+00,\n    -1.03622044471123109e-01,\n    days_per_year * 1.66007664274403694e-03,\n    days_per_year * 7.69901118419740425e-03,\n    days_per_year * -6.90460016972063023e-05,\n    solar_mass * 9.54791938424326609e-04\n)\n\nsaturn = Body(\n  8.34336671824457987e+00,\n  4.12479856412430479e+00,\n  -4.03523417114321381e-01,\n  days_per_year * -2.76742510726862411e-03,\n  days_per_year * 4.99852801234917238e-03,\n  days_per_year * 2.30417297573763929e-05,\n  solar_mass * 2.85885980666130812e-04\n)\n\nuranus = Body(\n  1.28943695621391310e+01,\n  -1.51111514016986312e+01,\n  -2.23307578892655734e-01,\n  days_per_year * 2.96460137564761618e-03,\n  days_per_year * 2.37847173959480950e-03,\n  days_per_year * -2.96589568540237556e-05,\n  solar_mass * 4.36624404335156298e-05\n)\n\nneptune = Body(\n  1.53796971148509165e+01,\n  -2.59193146099879641e+01,\n  1.79258772950371181e-01,\n  days_per_year * 2.68067772490389322e-03,\n  days_per_year * 1.62824170038242295e-03,\n  days_per_year * -9.51592254519715870e-05,\n  solar_mass * 5.15138902046611451e-05\n)\n\nsun = Body(\n  0.0, 0.0, 0.0,\n  0.0, 0.0, 0.0,\n  solar_mass\n)\n\ndef body_offset_momentum(b, px, py, pz):\n    b.vx = -px / solar_mass\n    b.vy = -py / solar_mass\n    b.vz = -pz / solar_mass\n\n\ndef bodies_new():\n\n    bodies = [jupiter, saturn, uranus, neptune, sun]\n\n    px = 0.0\n    py = 0.0\n    pz = 0.0\n\n    for body in bodies:\n        px += body.vx * body.mass\n        py += body.vy * body.mass\n        pz += body.vz * body.mass\n\n    body_offset_momentum(bodies[0], px, py, pz)\n\n    return bodies\n\n\n# Simulation\n\ndef bodies_advance(bodies, dt):\n\n    for i in xrange(len(bodies)):\n\n        body0 = bodies[i]\n\n        for j in xrange(i+1, len(bodies)):\n\n            body1 = bodies[j]\n\n            dx = body0.x - body1.x\n            dy = body0.y - body1.y\n            dz = body0.z - body1.z\n\n            dsquared = dx * dx + dy * dy + dz * dz\n            distance = math.sqrt(dsquared)\n            mag = dt / (dsquared * distance)\n\n            body0.vx -= dx * body1.mass * mag\n            body0.vy -= dy * body1.mass * mag\n            body0.vz -= dz * body1.mass * mag\n\n            body1.vx += dx * body0.mass * mag\n            body1.vy += dy * body0.mass * mag\n            body1.vz += dz * body0.mass * mag\n\n\n    for body in bodies:\n        body.x += dt * body.vx\n        body.y += dt * body.vy\n        body.z += dt * body.vz\n        \ndef bodies_energy(bodies):\n\n    dx = 0.0\n    dy = 0.0\n    dz = 0.0\n    distance = 0.0\n    e = 0.0\n\n    for i in xrange(len(bodies)):\n\n        body0 = bodies[i]\n\n        e += (0.5 * body0.mass * (\n            body0.vx * body0.vx +\n            body0.vy * body0.vy +\n            body0.vz * body0.vz))\n\n        for j in xrange(i+1, len(bodies)):\n\n            body1 = bodies[j]\n\n            dx = body0.x - body1.x\n            dy = body0.y - body1.y\n            dz = body0.z - body1.z\n\n            distance = math.sqrt(dx * dx + dy * dy + dz * dz)\n            e -= (body0.mass * body1.mass) / distance\n\n    return e\n\n# Run\n\nbodies = bodies_new()\nfor i in xrange(100000):\n    bodies_advance(bodies, 1e-5)\n\n\n\n"
  },
  {
    "path": "benchmarks/Nbodies/nbodies_ruby.rb",
    "content": "SOLAR_MASS = 4 * Math::PI**2\nDAYS_PER_YEAR = 365.24\n\nclass Planet\n attr_accessor :x, :y, :z, :vx, :vy, :vz, :mass\n\n def initialize(x, y, z, vx, vy, vz, mass)\n  @x, @y, @z = x, y, z\n  @vx, @vy, @vz = vx * DAYS_PER_YEAR, vy * DAYS_PER_YEAR, vz * DAYS_PER_YEAR \n  @mass = mass * SOLAR_MASS\n end\n\n def move_from_i(bodies, nbodies, dt, i)\n  while i < nbodies\n   b2 = bodies[i]\n   dx = @x - b2.x\n   dy = @y - b2.y\n   dz = @z - b2.z\n\n   distance = Math.sqrt(dx * dx + dy * dy + dz * dz)\n   mag = dt / (distance * distance * distance)\n   b_mass_mag, b2_mass_mag = @mass * mag, b2.mass * mag\n\n   @vx -= dx * b2_mass_mag\n   @vy -= dy * b2_mass_mag\n   @vz -= dz * b2_mass_mag\n   b2.vx += dx * b_mass_mag\n   b2.vy += dy * b_mass_mag\n   b2.vz += dz * b_mass_mag\n   i += 1 \n  end\n\n  @x += dt * @vx\n  @y += dt * @vy\n  @z += dt * @vz\n end\nend\n\ndef energy(bodies)\n  e = 0.0\n  nbodies = bodies.size\n \n  for i in 0 ... nbodies \n    b = bodies[i]\n    e += 0.5 * b.mass * (b.vx * b.vx + b.vy * b.vy + b.vz * b.vz)\n    for j in (i + 1) ... nbodies\n      b2 = bodies[j]\n      dx = b.x - b2.x\n      dy = b.y - b2.y\n      dz = b.z - b2.z\n      distance = Math.sqrt(dx * dx + dy * dy + dz * dz)\n      e -= (b.mass * b2.mass) / distance\n    end\n  end\n  e\nend\n\ndef offset_momentum(bodies)\n  px, py, pz = 0.0, 0.0, 0.0\n\n  for b in bodies\n    m = b.mass\n    px += b.vx * m\n    py += b.vy * m\n    pz += b.vz * m\n  end\n\n  b = bodies[0]\n  b.vx = - px / SOLAR_MASS\n  b.vy = - py / SOLAR_MASS\n  b.vz = - pz / SOLAR_MASS\nend\n\nBODIES = [\n  # sun\n  Planet.new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0),\n\n  # jupiter\n  Planet.new(\n    4.84143144246472090e+00,\n    -1.16032004402742839e+00,\n    -1.03622044471123109e-01,\n    1.66007664274403694e-03,\n    7.69901118419740425e-03,\n    -6.90460016972063023e-05,\n    9.54791938424326609e-04),\n\n  # saturn\n  Planet.new(\n    8.34336671824457987e+00,\n    4.12479856412430479e+00,\n    -4.03523417114321381e-01,\n    -2.76742510726862411e-03,\n    4.99852801234917238e-03,\n    2.30417297573763929e-05,\n    2.85885980666130812e-04),\n\n  # uranus\n  Planet.new(\n    1.28943695621391310e+01,\n    -1.51111514016986312e+01,\n    -2.23307578892655734e-01,\n    2.96460137564761618e-03,\n    2.37847173959480950e-03,\n    -2.96589568540237556e-05,\n    4.36624404335156298e-05),\n\n  # neptune\n  Planet.new(\n    1.53796971148509165e+01,\n    -2.59193146099879641e+01,\n    1.79258772950371181e-01,\n    2.68067772490389322e-03,\n    1.62824170038242295e-03,\n    -9.51592254519715870e-05,\n    5.15138902046611451e-05)\n]\n\noffset_momentum(BODIES)\n\n100000.times do\n  i = 0\n  while i < BODIES.size\n    b = BODIES[i]\n    b.move_from_i(BODIES, BODIES.size, 1e-5, i + 1)\n    i += 1\n  end\nend\n\n"
  },
  {
    "path": "benchmarks/Sudoku/sudoku_c.c",
    "content": "/* The MIT License\n\n   Copyright (c) 2011 by Attractive Chaos <attractor@live.co.uk>\n\n   Permission is hereby granted, free of charge, to any person obtaining\n   a copy of this software and associated documentation files (the\n   \"Software\"), to deal in the Software without restriction, including\n   without limitation the rights to use, copy, modify, merge, publish,\n   distribute, sublicense, and/or sell copies of the Software, and to\n   permit persons to whom the Software is furnished to do so, subject to\n   the following conditions:\n\n   The above copyright notice and this permission notice shall be\n   included in all copies or substantial portions of the Software.\n\n   THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n   BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n   ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n   SOFTWARE.\n*/\n\n// This file implements an improved algorithm of Guenter Stertenbrink's suexco.c\n// (http://magictour.free.fr/suexco.txt).\n\n#include <stdlib.h>\n#include <stdint.h>\n#include <string.h>\n#include <stdio.h>\n\n/* For Sudoku, there are 9x9x9=729 possible choices (9 numbers to choose for\n   each cell in a 9x9 grid), and 4x9x9=324 constraints with each constraint\n   representing a set of choices that are mutually conflictive with each other.\n   The 324 constraints are classified into 4 categories:\n\n   1. row-column where each cell contains only one number\n   2. box-number where each number appears only once in one 3x3 box\n   3. row-number where each number appears only once in one row\n   4. col-number where each number appears only once in one column\n\n   Each category consists of 81 constraints. We number these constraints from 0\n   to 323. In this program, for example, constraint 0 requires that the (0,0)\n   cell contains only one number; constraint 81 requires that number 1 appears\n   only once in the upper-left 3x3 box; constraint 162 requires that number 1\n   appears only once in row 1; constraint 243 requires that number 1 appears\n   only once in column 1.\n   \n   Noting that a constraint is a subset of choices, we may represent a\n   constraint with a binary vector of 729 elements. Thus we have a 729x324\n   binary matrix M with M(r,c)=1 indicating the constraint c involves choice r.\n   Solving a Sudoku is reduced to finding a subset of choices such that no\n   choices are present in the same constaint. This is equivalent to finding the\n   minimal subset of choices intersecting all constraints, a minimum hitting\n   set problem or a eqivalence of the exact cover problem.\n\n   The 729x324 binary matrix is a sparse matrix, with each row containing 4\n   non-zero elements and each column 9 non-zero elements. In practical\n   implementation, we store the coordinate of non-zero elements instead of\n   the binary matrix itself. We use a binary row vector to indicate the\n   constraints that have not been used and use a column vector to keep the\n   number of times a choice has been forbidden. When we set a choice, we will\n   use up 4 constraints and forbid other choices in the 4 constraints. When we\n   make wrong choices, we will find an unused constraint with all choices\n   forbidden, in which case, we have to backtrack to make new choices. Once we\n   understand what the 729x324 matrix represents, the backtracking algorithm\n   itself is easy.\n\n   A major difference between the algorithm implemented here and Guenter\n   Stertenbrink's suexco.c lies in how to count the number of the available\n   choices for each constraint. Suexco.c computes the count with a loop, while\n   the algorithm here keeps the count in an array. The latter is a little more\n   complex to implement as we have to keep the counts synchronized all the time,\n   but it is 50-100% faster, depending on the input.\n */\n\n// the sparse representation of the binary matrix\ntypedef struct {\n\tuint16_t r[324][9]; // M(r[c][i], c) is a non-zero element\n\tuint16_t c[729][4]; // M(r, c[r][j]) is a non-zero element\n} sdaux_t;\n\n// generate the sparse representation of the binary matrix\nsdaux_t *sd_genmat()\n{\n\tsdaux_t *a;\n\tint i, j, k, r, c, c2, r2;\n\tint8_t nr[324];\n\ta = calloc(1, sizeof(sdaux_t));\n\tfor (i = r = 0; i < 9; ++i) // generate c[729][4]\n\t\tfor (j = 0; j < 9; ++j)\n\t\t\tfor (k = 0; k < 9; ++k) // this \"9\" means each cell has 9 possible numbers\n\t\t\t\ta->c[r][0] = 9 * i + j,                  // row-column constraint\n\t\t\t\ta->c[r][1] = (i/3*3 + j/3) * 9 + k + 81, // box-number constraint\n\t\t\t\ta->c[r][2] = 9 * i + k + 162,            // row-number constraint\n\t\t\t\ta->c[r][3] = 9 * j + k + 243,            // col-number constraint\n\t\t\t\t++r;\n\tfor (c = 0; c < 324; ++c) nr[c] = 0;\n\tfor (r = 0; r < 729; ++r) // generate r[][] from c[][]\n\t\tfor (c2 = 0; c2 < 4; ++c2)\n\t\t\tk = a->c[r][c2], a->r[k][nr[k]++] = r;\n\treturn a;\n}\n// update the state vectors when we pick up choice r; v=1 for setting choice; v=-1 for reverting\nstatic inline int sd_update(const sdaux_t *aux, int8_t sr[729], uint8_t sc[324], int r, int v)\n{\n\tint c2, min = 10, min_c = 0;\n\tfor (c2 = 0; c2 < 4; ++c2) sc[aux->c[r][c2]] += v<<7;\n\tfor (c2 = 0; c2 < 4; ++c2) { // update # available choices\n\t\tint r2, rr, cc2, c = aux->c[r][c2];\n\t\tif (v > 0) { // move forward\n\t\t\tfor (r2 = 0; r2 < 9; ++r2) {\n\t\t\t\tif (sr[rr = aux->r[c][r2]]++ != 0) continue; // update the row status\n\t\t\t\tfor (cc2 = 0; cc2 < 4; ++cc2) {\n\t\t\t\t\tint cc = aux->c[rr][cc2];\n\t\t\t\t\tif (--sc[cc] < min) // update # allowed choices\n\t\t\t\t\t\tmin = sc[cc], min_c = cc; // register the minimum number\n\t\t\t\t}\n\t\t\t}\n\t\t} else { // revert\n\t\t\tconst uint16_t *p;\n\t\t\tfor (r2 = 0; r2 < 9; ++r2) {\n\t\t\t\tif (--sr[rr = aux->r[c][r2]] != 0) continue; // update the row status\n\t\t\t\tp = aux->c[rr]; ++sc[p[0]]; ++sc[p[1]]; ++sc[p[2]]; ++sc[p[3]]; // update the count array\n\t\t\t}\n\t\t}\n\t}\n\treturn min<<16 | min_c; // return the col that has been modified and with the minimal available choices\n}\n// solve a Sudoku; _s is the standard dot/number representation\nint sd_solve(const sdaux_t *aux, const char *_s)\n{\n\tint i, j, r, c, r2, dir, cand, n = 0, min, hints = 0; // dir=1: forward; dir=-1: backtrack\n\tint8_t sr[729], cr[81]; // sr[r]: # times the row is forbidden by others; cr[i]: row chosen at step i\n\tuint8_t sc[324]; // bit 1-7: # allowed choices; bit 8: the constraint has been used or not\n\tint16_t cc[81]; // cc[i]: col chosen at step i\n\tchar out[82];\n\tfor (r = 0; r < 729; ++r) sr[r] = 0; // no row is forbidden\n\tfor (c = 0; c < 324; ++c) sc[c] = 0<<7|9; // 9 allowed choices; no constraint has been used\n\tfor (i = 0; i < 81; ++i) {\n\t\tint a = _s[i] >= '1' && _s[i] <= '9'? _s[i] - '1' : -1; // number from -1 to 8\n\t\tif (a >= 0) sd_update(aux, sr, sc, i * 9 + a, 1); // set the choice\n\t\tif (a >= 0) ++hints; // count the number of hints\n\t\tcr[i] = cc[i] = -1, out[i] = _s[i];\n\t}\n\tfor (i = 0, dir = 1, cand = 10<<16|0, out[81] = 0;;) {\n\t\twhile (i >= 0 && i < 81 - hints) { // maximum 81-hints steps\n\t\t\tif (dir == 1) {\n\t\t\t\tmin = cand>>16, cc[i] = cand&0xffff;\n\t\t\t\tif (min > 1) {\n\t\t\t\t\tfor (c = 0; c < 324; ++c) {\n\t\t\t\t\t\tif (sc[c] < min) {\n\t\t\t\t\t\t\tmin = sc[c], cc[i] = c; // choose the top constraint\n\t\t\t\t\t\t\tif (min <= 1) break; // this is for acceleration; slower without this line\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (min == 0 || min == 10) cr[i--] = dir = -1; // backtrack\n\t\t\t}\n\t\t\tc = cc[i];\n\t\t\tif (dir == -1 && cr[i] >= 0) sd_update(aux, sr, sc, aux->r[c][cr[i]], -1); // revert the choice\n\t\t\tfor (r2 = cr[i] + 1; r2 < 9; ++r2) // search for the choice to make\n\t\t\t\tif (sr[aux->r[c][r2]] == 0) break; // found if the state equals 0\n\t\t\tif (r2 < 9) {\n\t\t\t\tcand = sd_update(aux, sr, sc, aux->r[c][r2], 1); // set the choice\n\t\t\t\tcr[i++] = r2; dir = 1; // moving forward\n\t\t\t} else cr[i--] = dir = -1; // backtrack\n\t\t}\n\t\tif (i < 0) break;\n\t\tfor (j = 0; j < i; ++j) r = aux->r[cc[j]][cr[j]], out[r/9] = r%9 + '1'; // print\n\t\t//puts(out);\n\t\t++n; --i; dir = -1; // backtrack\n\t}\n\treturn n; // return the number of solutions\n}\n\nint main()\n{\n\tsdaux_t *a = sd_genmat();\n\tchar buf[1024];\n\twhile (fgets(buf, 1024, stdin) != 0) {\n\t\tif (strlen(buf) < 81) continue;\n\t\tsd_solve(a, buf);\n\t\t//putchar('\\n');\n\t}\n\tfree(a);\n\treturn 0;\n}\n"
  },
  {
    "path": "benchmarks/Sudoku/sudoku_cello.c",
    "content": "#include \"Cello.h\"\n\nstruct Sudoku {\n  uint16_t r[324][9];\n  uint16_t c[729][4];\n};\n\nstatic void Sudoku_New(var self, var args) {\n\n\tstruct Sudoku* a = self;\n\tint i, j, k, r, c, c2;\n\tint8_t nr[324];\n\tfor (i = r = 0; i < 9; ++i) // generate c[729][4]\n\t\tfor (j = 0; j < 9; ++j)\n\t\t\tfor (k = 0; k < 9; ++k) // this \"9\" means each cell has 9 possible numbers\n\t\t\t\ta->c[r][0] = 9 * i + j,                  // row-column constraint\n\t\t\t\ta->c[r][1] = (i/3*3 + j/3) * 9 + k + 81, // box-number constraint\n\t\t\t\ta->c[r][2] = 9 * i + k + 162,            // row-number constraint\n\t\t\t\ta->c[r][3] = 9 * j + k + 243,            // col-number constraint\n\t\t\t\t++r;\n\tfor (c = 0; c < 324; ++c) nr[c] = 0;\n\tfor (r = 0; r < 729; ++r) // generate r[][] from c[][]\n\t\tfor (c2 = 0; c2 < 4; ++c2)\n\t\t\tk = a->c[r][c2], a->r[k][nr[k]++] = r;\n\n}\n\nstatic var Sudoku = Cello(Sudoku, Instance(New, Sudoku_New, NULL));\n\nstatic int Sudoku_Update(\n  struct Sudoku* aux, int8_t sr[729], uint8_t sc[324], int r, int v) {\n\t\n\tint c2, min = 10, min_c = 0;\n\tfor (c2 = 0; c2 < 4; ++c2) sc[aux->c[r][c2]] += v<<7;\n\tfor (c2 = 0; c2 < 4; ++c2) { // update # available choices\n\t\tint r2, rr, cc2, c = aux->c[r][c2];\n\t\tif (v > 0) { // move forward\n\t\t\tfor (r2 = 0; r2 < 9; ++r2) {\n\t\t\t\tif (sr[rr = aux->r[c][r2]]++ != 0) continue; // update the row status\n\t\t\t\tfor (cc2 = 0; cc2 < 4; ++cc2) {\n\t\t\t\t\tint cc = aux->c[rr][cc2];\n\t\t\t\t\tif (--sc[cc] < min) // update # allowed choices\n\t\t\t\t\t\tmin = sc[cc], min_c = cc; // register the minimum number\n\t\t\t\t}\n\t\t\t}\n\t\t} else { // revert\n\t\t\tconst uint16_t *p;\n\t\t\tfor (r2 = 0; r2 < 9; ++r2) {\n\t\t\t\tif (--sr[rr = aux->r[c][r2]] != 0) continue; // update the row status\n\t\t\t\tp = aux->c[rr]; ++sc[p[0]]; ++sc[p[1]]; ++sc[p[2]]; ++sc[p[3]]; // update the count array\n\t\t\t}\n\t\t}\n\t}\n\treturn min<<16 | min_c; // return the col that has been modified and with the minimal available choices\n}\n\n// solve a Sudoku; _s is the standard dot/number representation\nstatic int Sudoku_Solve(struct Sudoku* aux, const char *_s) {\n\tint i, j, r, c, r2, dir, cand, n = 0, min, hints = 0; // dir=1: forward; dir=-1: backtrack\n\tint8_t sr[729], cr[81]; // sr[r]: # times the row is forbidden by others; cr[i]: row chosen at step i\n\tuint8_t sc[324]; // bit 1-7: # allowed choices; bit 8: the constraint has been used or not\n\tint16_t cc[81]; // cc[i]: col chosen at step i\n\tchar out[82];\n\tfor (r = 0; r < 729; ++r) sr[r] = 0; // no row is forbidden\n\tfor (c = 0; c < 324; ++c) sc[c] = 0<<7|9; // 9 allowed choices; no constraint has been used\n\tfor (i = 0; i < 81; ++i) {\n\t\tint a = _s[i] >= '1' && _s[i] <= '9'? _s[i] - '1' : -1; // number from -1 to 8\n\t\tif (a >= 0) Sudoku_Update(aux, sr, sc, i * 9 + a, 1); // set the choice\n\t\tif (a >= 0) ++hints; // count the number of hints\n\t\tcr[i] = cc[i] = -1, out[i] = _s[i];\n\t}\n\tfor (i = 0, dir = 1, cand = 10<<16|0, out[81] = 0;;) {\n\t\twhile (i >= 0 && i < 81 - hints) { // maximum 81-hints steps\n\t\t\tif (dir == 1) {\n\t\t\t\tmin = cand>>16, cc[i] = cand&0xffff;\n\t\t\t\tif (min > 1) {\n\t\t\t\t\tfor (c = 0; c < 324; ++c) {\n\t\t\t\t\t\tif (sc[c] < min) {\n\t\t\t\t\t\t\tmin = sc[c], cc[i] = c; // choose the top constraint\n\t\t\t\t\t\t\tif (min <= 1) break; // this is for acceleration; slower without this line\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (min == 0 || min == 10) cr[i--] = dir = -1; // backtrack\n\t\t\t}\n\t\t\tc = cc[i];\n\t\t\tif (dir == -1 && cr[i] >= 0) Sudoku_Update(aux, sr, sc, aux->r[c][cr[i]], -1); // revert the choice\n\t\t\tfor (r2 = cr[i] + 1; r2 < 9; ++r2) // search for the choice to make\n\t\t\t\tif (sr[aux->r[c][r2]] == 0) break; // found if the state equals 0\n\t\t\tif (r2 < 9) {\n\t\t\t\tcand = Sudoku_Update(aux, sr, sc, aux->r[c][r2], 1); // set the choice\n\t\t\t\tcr[i++] = r2; dir = 1; // moving forward\n\t\t\t} else cr[i--] = dir = -1; // backtrack\n\t\t}\n\t\tif (i < 0) break;\n\t\tfor (j = 0; j < i; ++j) r = aux->r[cc[j]][cr[j]], out[r/9] = r%9 + '1'; // print\n\t\t//puts(out);\n\t\t++n; --i; dir = -1; // backtrack\n\t}\n\treturn n; // return the number of solutions\n}\n\nint main(int argc, char** argv) {\n\tstruct Sudoku* a = new(Sudoku);\n\tchar buf[1024];\n\twhile (fgets(buf, 1024, stdin) != 0) {\n\t\tif (strlen(buf) < 81) continue;\n\t\tSudoku_Solve(a, buf);\n\t\t//putchar('\\n');\n\t}\n\tdel(a);\n\treturn 0;\n}\n"
  },
  {
    "path": "benchmarks/Sudoku/sudoku_cpp.cpp",
    "content": "/* The MIT License\n\n   Copyright (c) 2011 by Attractive Chaos <attractor@live.co.uk>\n\n   Permission is hereby granted, free of charge, to any person obtaining\n   a copy of this software and associated documentation files (the\n   \"Software\"), to deal in the Software without restriction, including\n   without limitation the rights to use, copy, modify, merge, publish,\n   distribute, sublicense, and/or sell copies of the Software, and to\n   permit persons to whom the Software is furnished to do so, subject to\n   the following conditions:\n\n   The above copyright notice and this permission notice shall be\n   included in all copies or substantial portions of the Software.\n\n   THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n   BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n   ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n   SOFTWARE.\n*/\n\n// This file implements an improved algorithm of Guenter Stertenbrink's suexco.c\n// (http://magictour.free.fr/suexco.txt).\n\n#include <stdlib.h>\n#include <stdint.h>\n#include <string.h>\n#include <stdio.h>\n\n/* For Sudoku, there are 9x9x9=729 possible choices (9 numbers to choose for\n   each cell in a 9x9 grid), and 4x9x9=324 constraints with each constraint\n   representing a set of choices that are mutually conflictive with each other.\n   The 324 constraints are classified into 4 categories:\n\n   1. row-column where each cell contains only one number\n   2. box-number where each number appears only once in one 3x3 box\n   3. row-number where each number appears only once in one row\n   4. col-number where each number appears only once in one column\n\n   Each category consists of 81 constraints. We number these constraints from 0\n   to 323. In this program, for example, constraint 0 requires that the (0,0)\n   cell contains only one number; constraint 81 requires that number 1 appears\n   only once in the upper-left 3x3 box; constraint 162 requires that number 1\n   appears only once in row 1; constraint 243 requires that number 1 appears\n   only once in column 1.\n   \n   Noting that a constraint is a subset of choices, we may represent a\n   constraint with a binary vector of 729 elements. Thus we have a 729x324\n   binary matrix M with M(r,c)=1 indicating the constraint c involves choice r.\n   Solving a Sudoku is reduced to finding a subset of choices such that no\n   choices are present in the same constaint. This is equivalent to finding the\n   minimal subset of choices intersecting all constraints, a minimum hitting\n   set problem or a eqivalence of the exact cover problem.\n\n   The 729x324 binary matrix is a sparse matrix, with each row containing 4\n   non-zero elements and each column 9 non-zero elements. In practical\n   implementation, we store the coordinate of non-zero elements instead of\n   the binary matrix itself. We use a binary row vector to indicate the\n   constraints that have not been used and use a column vector to keep the\n   number of times a choice has been forbidden. When we set a choice, we will\n   use up 4 constraints and forbid other choices in the 4 constraints. When we\n   make wrong choices, we will find an unused constraint with all choices\n   forbidden, in which case, we have to backtrack to make new choices. Once we\n   understand what the 729x324 matrix represents, the backtracking algorithm\n   itself is easy.\n\n   A major difference between the algorithm implemented here and Guenter\n   Stertenbrink's suexco.c lies in how to count the number of the available\n   choices for each constraint. Suexco.c computes the count with a loop, while\n   the algorithm here keeps the count in an array. The latter is a little more\n   complex to implement as we have to keep the counts synchronized all the time,\n   but it is 50-100% faster, depending on the input.\n */\n\n// the sparse representation of the binary matrix\nclass sdaux_t {\n\tuint16_t r[324][9]; // M(r[c][i], c) is a non-zero element\n\tuint16_t c[729][4]; // M(r, c[r][j]) is a non-zero element\n\t\n\tpublic:\n\tsdaux_t();\n\tint update(int8_t sr[729], uint8_t sc[324], int r, int v);\n\tint solve(const char *_s);\n\t\n};\n\n// generate the sparse representation of the binary matrix\nsdaux_t::sdaux_t() {\n\tint i, j, k, r, c, c2, r2;\n\tint8_t nr[324];\n\tfor (i = r = 0; i < 9; ++i) // generate c[729][4]\n\t\tfor (j = 0; j < 9; ++j)\n\t\t\tfor (k = 0; k < 9; ++k) // this \"9\" means each cell has 9 possible numbers\n\t\t\t\tthis->c[r][0] = 9 * i + j,                  // row-column constraint\n\t\t\t\tthis->c[r][1] = (i/3*3 + j/3) * 9 + k + 81, // box-number constraint\n\t\t\t\tthis->c[r][2] = 9 * i + k + 162,            // row-number constraint\n\t\t\t\tthis->c[r][3] = 9 * j + k + 243,            // col-number constraint\n\t\t\t\t++r;\n\tfor (c = 0; c < 324; ++c) nr[c] = 0;\n\tfor (r = 0; r < 729; ++r) // generate r[][] from c[][]\n\t\tfor (c2 = 0; c2 < 4; ++c2)\n\t\t\tk = this->c[r][c2], this->r[k][nr[k]++] = r;\n}\n// update the state vectors when we pick up choice r; v=1 for setting choice; v=-1 for reverting\nint sdaux_t::update(int8_t sr[729], uint8_t sc[324], int r, int v)\n{\n\tint c2, min = 10, min_c = 0;\n\tfor (c2 = 0; c2 < 4; ++c2) sc[this->c[r][c2]] += v<<7;\n\tfor (c2 = 0; c2 < 4; ++c2) { // update # available choices\n\t\tint r2, rr, cc2, c = this->c[r][c2];\n\t\tif (v > 0) { // move forward\n\t\t\tfor (r2 = 0; r2 < 9; ++r2) {\n\t\t\t\tif (sr[rr = this->r[c][r2]]++ != 0) continue; // update the row status\n\t\t\t\tfor (cc2 = 0; cc2 < 4; ++cc2) {\n\t\t\t\t\tint cc = this->c[rr][cc2];\n\t\t\t\t\tif (--sc[cc] < min) // update # allowed choices\n\t\t\t\t\t\tmin = sc[cc], min_c = cc; // register the minimum number\n\t\t\t\t}\n\t\t\t}\n\t\t} else { // revert\n\t\t\tconst uint16_t *p;\n\t\t\tfor (r2 = 0; r2 < 9; ++r2) {\n\t\t\t\tif (--sr[rr = this->r[c][r2]] != 0) continue; // update the row status\n\t\t\t\tp = this->c[rr]; ++sc[p[0]]; ++sc[p[1]]; ++sc[p[2]]; ++sc[p[3]]; // update the count array\n\t\t\t}\n\t\t}\n\t}\n\treturn min<<16 | min_c; // return the col that has been modified and with the minimal available choices\n}\n// solve a Sudoku; _s is the standard dot/number representation\nint sdaux_t::solve(const char *_s)\n{\n\tint i, j, r, c, r2, dir, cand, n = 0, min, hints = 0; // dir=1: forward; dir=-1: backtrack\n\tint8_t sr[729], cr[81]; // sr[r]: # times the row is forbidden by others; cr[i]: row chosen at step i\n\tuint8_t sc[324]; // bit 1-7: # allowed choices; bit 8: the constraint has been used or not\n\tint16_t cc[81]; // cc[i]: col chosen at step i\n\tchar out[82];\n\tfor (r = 0; r < 729; ++r) sr[r] = 0; // no row is forbidden\n\tfor (c = 0; c < 324; ++c) sc[c] = 0<<7|9; // 9 allowed choices; no constraint has been used\n\tfor (i = 0; i < 81; ++i) {\n\t\tint a = _s[i] >= '1' && _s[i] <= '9'? _s[i] - '1' : -1; // number from -1 to 8\n\t\tif (a >= 0) this->update(sr, sc, i * 9 + a, 1); // set the choice\n\t\tif (a >= 0) ++hints; // count the number of hints\n\t\tcr[i] = cc[i] = -1, out[i] = _s[i];\n\t}\n\tfor (i = 0, dir = 1, cand = 10<<16|0, out[81] = 0;;) {\n\t\twhile (i >= 0 && i < 81 - hints) { // maximum 81-hints steps\n\t\t\tif (dir == 1) {\n\t\t\t\tmin = cand>>16, cc[i] = cand&0xffff;\n\t\t\t\tif (min > 1) {\n\t\t\t\t\tfor (c = 0; c < 324; ++c) {\n\t\t\t\t\t\tif (sc[c] < min) {\n\t\t\t\t\t\t\tmin = sc[c], cc[i] = c; // choose the top constraint\n\t\t\t\t\t\t\tif (min <= 1) break; // this is for acceleration; slower without this line\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (min == 0 || min == 10) cr[i--] = dir = -1; // backtrack\n\t\t\t}\n\t\t\tc = cc[i];\n\t\t\tif (dir == -1 && cr[i] >= 0) this->update(sr, sc, this->r[c][cr[i]], -1); // revert the choice\n\t\t\tfor (r2 = cr[i] + 1; r2 < 9; ++r2) // search for the choice to make\n\t\t\t\tif (sr[this->r[c][r2]] == 0) break; // found if the state equals 0\n\t\t\tif (r2 < 9) {\n\t\t\t\tcand = this->update(sr, sc, this->r[c][r2], 1); // set the choice\n\t\t\t\tcr[i++] = r2; dir = 1; // moving forward\n\t\t\t} else cr[i--] = dir = -1; // backtrack\n\t\t}\n\t\tif (i < 0) break;\n\t\tfor (j = 0; j < i; ++j) r = this->r[cc[j]][cr[j]], out[r/9] = r%9 + '1'; // print\n\t\t//puts(out);\n\t\t++n; --i; dir = -1; // backtrack\n\t}\n\treturn n; // return the number of solutions\n}\n\nint main()\n{\n\tsdaux_t *a = new sdaux_t();\n\tchar buf[1024];\n\twhile (fgets(buf, 1024, stdin) != 0) {\n\t\tif (strlen(buf) < 81) continue;\n\t\ta->solve(buf);\n\t\t//putchar('\\n');\n\t}\n  delete a;\n\treturn 0;\n}\n"
  },
  {
    "path": "benchmarks/Sudoku/sudoku_cs.cs",
    "content": "using System;\n\nclass sudoku_v1 {\n\tint[,] R, C;\n\tpublic void genmat() {\n\t\tR = new int[324,9];\n\t\tC = new int[729,4];\n\t\tint[] nr = new int[324];\n\t\tint i, j, k, r, c, c2;\n\t\tfor (i = r = 0; i < 9; ++i) // generate c[729][4]\n\t\t\tfor (j = 0; j < 9; ++j)\n\t\t\t\tfor (k = 0; k < 9; ++k) { // this \"9\" means each cell has 9 possible numbers\n\t\t\t\t\tC[r,0] = 9 * i + j;                  // row-column constraint\n\t\t\t\t\tC[r,1] = (i/3*3 + j/3) * 9 + k + 81; // box-number constraint\n\t\t\t\t\tC[r,2] = 9 * i + k + 162;            // row-number constraint\n\t\t\t\t\tC[r,3] = 9 * j + k + 243;            // col-number constraint\n\t\t\t\t\t++r;\n\t\t\t\t}\n\t\tfor (c = 0; c < 324; ++c) nr[c] = 0;\n\t\tfor (r = 0; r < 729; ++r) // generate r[][] from c[][]\n\t\t\tfor (c2 = 0; c2 < 4; ++c2) {\n\t\t\t\tk = C[r,c2]; R[k,nr[k]] = r; nr[k]++;\n\t\t\t}\n\t}\n\tprivate int sd_update(int[] sr, int[] sc, int r, int v) {\n\t\tint c2, min = 10, min_c = 0;\n\t\tfor (c2 = 0; c2 < 4; ++c2) sc[C[r,c2]] += v<<7;\n\t\tfor (c2 = 0; c2 < 4; ++c2) { // update # available choices\n\t\t\tint r2, rr, cc2, c = C[r,c2];\n\t\t\tif (v > 0) { // move forward\n\t\t\t\tfor (r2 = 0; r2 < 9; ++r2) {\n\t\t\t\t\tif (sr[rr = R[c,r2]]++ != 0) continue; // update the row status\n\t\t\t\t\tfor (cc2 = 0; cc2 < 4; ++cc2) {\n\t\t\t\t\t\tint cc = C[rr,cc2];\n\t\t\t\t\t\tif (--sc[cc] < min) { // update # allowed choices\n\t\t\t\t\t\t\tmin = sc[cc]; min_c = cc; // register the minimum number\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else { // revert\n\t\t\t\tfor (r2 = 0; r2 < 9; ++r2) {\n\t\t\t\t\tif (--sr[rr = R[c,r2]] != 0) continue; // update the row status\n\t\t\t\t\t++sc[C[rr,0]]; ++sc[C[rr,1]]; ++sc[C[rr,2]]; ++sc[C[rr,3]]; // update the count array\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn min<<16 | min_c; // return the col that has been modified and with the minimal available choices\n\t}\n\t// solve a Sudoku; _s is the standard dot/number representation\n\tpublic int solve(String _s) {\n\t\tint i, j, r, c, r2, dir, cand, n = 0, min, hints = 0; // dir=1: forward; dir=-1: backtrack\n\t\tint[] sr = new int[729];\n\t\tint[] cr = new int[81];\n\t\tint[] sc = new int[324];\n\t\tint[] cc = new int[81];\n\t\tint[] o = new int[81];\n\t\tfor (r = 0; r < 729; ++r) sr[r] = 0; // no row is forbidden\n\t\tfor (c = 0; c < 324; ++c) sc[c] = 0<<7|9; // 9 allowed choices; no constraint has been used\n\t\tfor (i = 0; i < 81; ++i) {\n\t\t\tint a = _s[i] >= '1' && _s[i] <= '9'? _s[i] - '1' : -1; // number from -1 to 8\n\t\t\tif (a >= 0) sd_update(sr, sc, i * 9 + a, 1); // set the choice\n\t\t\tif (a >= 0) ++hints; // count the number of hints\n\t\t\tcr[i] = cc[i] = -1; o[i] = a;\n\t\t}\n\t\ti = 0; dir = 1; cand = 10<<16|0;\n\t\tfor (;;) {\n\t\t\twhile (i >= 0 && i < 81 - hints) { // maximum 81-hints steps\n\t\t\t\tif (dir == 1) {\n\t\t\t\t\tmin = cand>>16; cc[i] = cand&0xffff;\n\t\t\t\t\tif (min > 1) {\n\t\t\t\t\t\tfor (c = 0; c < 324; ++c) {\n\t\t\t\t\t\t\tif (sc[c] < min) {\n\t\t\t\t\t\t\t\tmin = sc[c]; cc[i] = c; // choose the top constraint\n\t\t\t\t\t\t\t\tif (min <= 1) break; // this is for acceleration; slower without this line\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (min == 0 || min == 10) cr[i--] = dir = -1; // backtrack\n\t\t\t\t}\n\t\t\t\tc = cc[i];\n\t\t\t\tif (dir == -1 && cr[i] >= 0) sd_update(sr, sc, R[c,cr[i]], -1); // revert the choice\n\t\t\t\tfor (r2 = cr[i] + 1; r2 < 9; ++r2) // search for the choice to make\n\t\t\t\t\tif (sr[R[c,r2]] == 0) break; // found if the state equals 0\n\t\t\t\tif (r2 < 9) {\n\t\t\t\t\tcand = sd_update(sr, sc, R[c,r2], 1); // set the choice\n\t\t\t\t\tcr[i++] = r2; dir = 1; // moving forward\n\t\t\t\t} else cr[i--] = dir = -1; // backtrack\n\t\t\t}\n\t\t\tif (i < 0) break;\n\t\t\tchar[] y = new char[81];\n\t\t\tfor (j = 0; j < 81; ++j) y[i] = (char)(o[i] + '1');\n\t\t\tfor (j = 0; j < i; ++j) { r = R[cc[j],cr[j]]; y[r/9] = (char)(r%9 + '1'); }\n\t\t\tConsole.WriteLine(new String(y));\n\t\t\t++n; --i; dir = -1; // backtrack\n\t\t}\n\t\treturn n;\n\t}\n\tpublic static void Main(String[] args) {\n\t\tsudoku_v1 a = new sudoku_v1();\n\t\tString l;\n\t\ta.genmat();\n\t\twhile ((l = Console.ReadLine()) != null)\n\t\t\tif (l.Length >= 81) {\n\t\t\t\ta.solve(l);\n\t\t\t\tConsole.WriteLine();\n\t\t\t}\n\t}\n}\n"
  },
  {
    "path": "benchmarks/Sudoku/sudoku_d.d",
    "content": "// Works with LDC1\n// Compile with: ldc -O3 -release -inline\n// Contributed by leonardo\n\n/*\nThe MIT License\n\nCopyright (c) 2011 by Attractive Chaos <attractor@live.co.uk>\n                      leonardo\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\nBE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\nACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n*/\n\n// This implements an improved algorithm of Guenter Stertenbrink's suexco.c\n// (http://magictour.free.fr/suexco.txt).\n\nimport tango.stdc.stdio: puts, fgets, stdin, putchar;\nimport tango.stdc.string: strlen;\n\n\n/// the sparse representation of the binary matrix\nstruct Sdaux {\n    int[9][324] r; // M(r[c][i], c) is a non-zero element\n    int[4][729] c; // M(r, c[r][j]) is a non-zero element\n\n    /// generate the sparse representation of the binary matrix\n    void initialize() { // static this() is slower\n        // generate this.c\n        {\n            int r1 = 0;\n            for (int i = 0; i < 9; i++)\n                for (int j = 0; j < 9; j++)\n                    for (int k = 0; k < 9; k++) { // this \"9\" means each cell has 9 possible numbers\n                        c[r1][] = [9 * i + j, (i/3*3 + j/3) * 9 + k + 81, 9 * i + k + 162, 9 * j + k + 243];\n                        r1++;\n                    }\n        }\n\n        // generate this.r from this.c\n        byte[r.length] nr;\n        foreach (ushort r2, ref rowc; this.c)\n            foreach (c2, int k; rowc) {\n                this.r[k][nr[k]] = r2;\n                nr[k]++;\n            }\n    }\n}\n\n\n/// update the state vectors when we pick up choice r; v=1 for setting choice; v=-1 for reverting\nint sdUpdate(in Sdaux* aux, byte[Sdaux.c.length] sr,\n             ubyte[Sdaux.r.length] sc, in int r, in int v) {\n    int min = 10, min_c;\n\n    for (size_t c2 = 0; c2 < aux.c[0].length; c2++)\n        sc[aux.c[r][c2]] += v << 7;\n\n    for (size_t c2 = 0; c2 < aux.c[0].length; c2++) { // update # available choices\n        int c = aux.c[r][c2];\n        int rr;\n\n        if (v > 0) { // move forward\n            for (size_t r2 = 0; r2 < 9; r2++) {\n                if (sr[rr = aux.r[c][r2]]++ != 0)\n                    continue; // update the row status\n                for (size_t cc2 = 0; cc2 < aux.c[0].length; cc2++) {\n                    int cc = aux.c[rr][cc2];\n                    sc[cc]--;\n                    if (sc[cc] < min) { // update # allowed choices\n                        min = sc[cc]; // register the minimum number\n                        min_c = cc;\n                    }\n                }\n            }\n        } else { // revert\n            for (size_t r2 = 0; r2 < 9; r2++) {\n                if (--sr[rr = aux.r[c][r2]] != 0)\n                    continue; // update the row status\n                auto p = aux.c[rr].ptr;\n                sc[p[0]]++; // update the count array\n                sc[p[1]]++;\n                sc[p[2]]++;\n                sc[p[3]]++;\n            }\n        }\n    }\n\n    return (min << 16) | min_c; // return the col that has been modified and\n                                // with the minimal available choices\n}\n\n\n/// solve a Sudoku; _s is the standard dot/number representation\nint sdSolve(in Sdaux* aux, in char* _s) {\n    int hints;\n    byte[Sdaux.c.length] sr; // sr[r]: # times the row is forbidden by others\n    byte[81] cr = -1; // cr[i]: row chosen at step i\n    ubyte[Sdaux.r.length] sc = 9; // bit 1-7: # allowed choices;\n                                  // bit 8: the constraint has been used or not\n                                  // 9 allowed choices; no constraint has been used\n    short[cr.length] cc = -1; // cc[i]: col chosen at step i\n    char[82] outs;\n\n    for (int i = 0; i < cr.length; i++) {\n        int a = (_s[i] >= '1' && _s[i] <= '9') ? (_s[i] - '1') : -1; // number from -1 to 8\n        if (a >= 0)\n            sdUpdate(aux, sr, sc, i * 9 + a, 1); // set the choice\n        if (a >= 0)\n            hints++; // count the number of hints\n        outs[i] = _s[i];\n    }\n\n    int dir; // dir=1: forward; dir=-1: backtrack\n    int i, r, cand, n, min;\n\n    for (i = 0, dir = 1, cand = (10 << 16) | 0, outs[81] = 0; ; ) {\n        while (i >= 0 && i < 81 - hints) { // maximum 81-hints steps\n            if (dir == 1) {\n                min = cand >> 16;\n                cc[i] = cand & 0xFFFF;\n\n                if (min > 1) {\n                    for (size_t c = 0; c < sc.length; c++) { // performance-critical loop\n                        if (sc[c] < min) {\n                            min = sc[c]; // choose the top constraint\n                            cc[i] = cast(short)c;\n                            if (min <= 1)\n                                break; // this is for acceleration; slower without this line\n                        }\n                    }\n                }\n\n                if (min == 0 || min == 10) {\n                    dir = cr[i] = -1; // backtrack\n                    i--;\n                }\n            }\n\n            int c = cc[i];\n            if (dir == -1 && cr[i] >= 0)\n                sdUpdate(aux, sr, sc, aux.r[c][cr[i]], -1); // revert the choice\n\n            int r2;\n            for (r2 = cr[i] + 1; r2 < 9; r2++) // search for the choice to make\n                if (sr[aux.r[c][r2]] == 0)\n                    break; // found if the state equals 0\n\n            if (r2 < 9) {\n                cand = sdUpdate(aux, sr, sc, aux.r[c][r2], 1); // set the choice\n                cr[i] = cast(byte)r2; // moving forward. r2 < 9\n                i++;\n                dir = 1;\n            } else {\n                dir = cr[i] = -1; // backtrack\n                i--;\n            }\n        }\n\n        if (i < 0)\n            break;\n\n        for (size_t j = 0; j < i; j++) {\n            r = aux.r[cc[j]][cr[j]];\n            outs[r / 9] = cast(char)(r % 9 + '1'); // print\n        }\n\n        puts(outs.ptr);\n        n++; // backtrack\n        i--;\n        dir = -1;\n    }\n\n    return n; // return the number of solutions\n}\n\n\nvoid main() {\n    Sdaux a;\n    a.initialize();\n    char[1024] buf;\n\n    while (fgets(buf.ptr, buf.length, stdin) != null) {\n        if (strlen(buf.ptr) < 81)\n            continue;\n        sdSolve(&a, buf.ptr);\n        putchar('\\n');\n    }\n}\n"
  },
  {
    "path": "benchmarks/Sudoku/sudoku_dart.dart",
    "content": "import 'dart:core';\nimport 'dart:io';\nimport 'dart:typeddata';\n\nclass Sudoku {\n  final _R = new List<Uint16List>(324);\n  final _C = new List<List<int>>(729);\n  \n  Sudoku() {\n    final Uint8List nr = new Uint8List(324);\n    for (int i = 0, r = 0; i < 9; ++i)\n      for (int j = 0; j < 9; ++j)\n        for (int k = 0; k < 9; ++k)\n          _C[r++] = <int>[ 9 * i + j, (i~/3*3 + j~/3) * 9 + k + 81, 9 * i + k + 162, 9 * j + k + 243 ];\n    for (int c = 0; c < 324; ++c) {\n      _R[c] = new Uint16List(9);\n      nr[c] = 0;\n    }\n    for (int r = 0; r < 729; ++r)\n      for (int c2 = 0; c2 < 4; ++c2) {\n        int k = _C[r][c2];\n        _R[k][nr[k]++] = r;\n      }\n  }\n  _update(sr, sc, r, v) {\n    int min = 10, min_c = 0;\n    for (int c2 = 0; c2 < 4; ++c2) sc[_C[r][c2]] += v<<7;\n    for (int c2 = 0; c2 < 4; ++c2) {\n      int r2, rr, cc2, c = _C[r][c2];\n      if (v > 0) {\n        for (r2 = 0; r2 < 9; ++r2) {\n          if (sr[rr = _R[c][r2]]++ != 0) continue;\n          for (cc2 = 0; cc2 < 4; ++cc2) {\n            var cc = _C[rr][cc2];\n            if (--sc[cc] < min) { min = sc[cc]; min_c = cc; }\n          }\n        }\n      } else { // revert\n        for (r2 = 0; r2 < 9; ++r2) {\n          if (--sr[rr = _R[c][r2]] != 0) continue;\n          var p = _C[rr];\n          ++sc[p[0]]; ++sc[p[1]]; ++sc[p[2]]; ++sc[p[3]];\n        }\n      }\n    }\n    return min<<16 | min_c; // return the col that has been modified and with the minimal available choices\n  }\n  solve(s_) {\n    int j, r, c, r2, min, hints = 0;\n    var sr = new Int16List(729), sc = new Int16List(324);\n    var cr = new Int16List(81), cc = new Int16List(81), out = new Int16List(81);\n    List<String> ret = [];\n    for (r = 0; r < 729; ++r) sr[r] = 0;\n    for (c = 0; c < 324; ++c) sc[c] = 9;\n    for (int i = 0; i < 81; ++i) {\n      int a = s_.codeUnitAt(i) >= 49 && s_.codeUnitAt(i) <= 57? s_.codeUnitAt(i) - 49 : -1;\n      if (a >= 0) _update(sr, sc, i * 9 + a, 1);\n      if (a >= 0) ++hints;\n      cr[i] = cc[i] = -1; out[i] = a + 1;\n    }\n\n    for (int i = 0, dir = 1, cand = 10<<16|0;;) {\n      while (i >= 0 && i < 81 - hints) {\n        if (dir == 1) {\n          min = cand>>16; cc[i] = cand&0xffff;\n          if (min > 1) {\n            for (c = 0; c < 324; ++c) {\n              if (sc[c] < min) {\n                min = sc[c]; cc[i] = c;\n                if (min <= 1) break;\n              }\n            }\n          }\n          if (min == 0 || min == 10) cr[i--] = dir = -1;\n        }\n        c = cc[i];\n        if (dir == -1 && cr[i] >= 0) _update(sr, sc, _R[c][cr[i]], -1);\n        for (r2 = cr[i] + 1; r2 < 9; ++r2)\n          if (sr[_R[c][r2]] == 0) break;\n        if (r2 < 9) {\n          cand = _update(sr, sc, _R[c][r2], 1);\n          cr[i++] = r2; dir = 1;\n        } else cr[i--] = dir = -1;\n      }\n  \n      if (i < 0) break;\n\n      Uint8List y = new Uint8List(81);\n      for (j = 0; j < 81; ++j) y[j] = out[j];\n      for (j = 0; j < i; ++j) { r = _R[cc[j]][cr[j]]; y[r~/9] = r%9 + 1; }\n      ret.add(y.join());\n      --i; dir = -1;\n    }\n    return ret;\n  }\n}\n\nmain()\n{\n  final List<String> argv = new Options().arguments;\n  final fp = new File(argv[0]);\n  final lines = fp.readAsLinesSync(encoding: Encoding.ASCII);\n  final Sudoku s = new Sudoku();\n  for (int i = 0; i < lines.length; ++i) {\n    var rst = s.solve(lines[i]);\n    for (final x in rst) print(x);\n    print(\"\");\n  }\n}\n"
  },
  {
    "path": "benchmarks/Sudoku/sudoku_go.go",
    "content": "package main\n\nimport (\n\t\"bufio\"\n\t\"fmt\"\n\t\"os\"\n)\n\ntype sdaux_t struct {\n\tr [324][9]uint16\n\tc [729][4]uint16\n}\n\nfunc sd_genmat() *sdaux_t {\n\ta := new(sdaux_t)\n\tnr := make([]int8, 324)\n\tr := 0\n\tfor i := 0; i < 9; i++ {\n\t\tfor j := 0; j < 9; j++ {\n\t\t\tfor k := 0; k < 9; k++ {\n\t\t\t\ta.c[r][0] = uint16(9*i + j)\n\t\t\t\ta.c[r][1] = uint16((i/3*3+j/3)*9 + k + 81)\n\t\t\t\ta.c[r][2] = uint16(9*i + k + 162)\n\t\t\t\ta.c[r][3] = uint16(9*j + k + 243)\n\t\t\t\tr++\n\t\t\t}\n\t\t}\n\t}\n\tfor c := 0; c < 324; c++ {\n\t\tnr[c] = 0\n\t}\n\tfor r := 0; r < 729; r++ {\n\t\tfor c2 := 0; c2 < 4; c2++ {\n\t\t\tk := a.c[r][c2]\n\t\t\ta.r[k][nr[k]] = uint16(r)\n\t\t\tnr[k]++\n\t\t}\n\t}\n\treturn a\n}\n\nfunc sd_update_forward(aux *sdaux_t, sr []int8, sc []uint8, r uint16) int {\n\tmin, min_c := uint8(10), uint16(0)\n\trows := &aux.c[r]\n\tfor _, c := range rows {\n\t\tsc[c] |= 0x80\n\t}\n\tfor _, c := range rows {\n\t\tfor _, rr := range &aux.r[c] {\n\t\t\tsr[rr]++\n\t\t\tif sr[rr] != 1 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfor _, cc := range &aux.c[rr] {\n\t\t\t\tv := sc[cc] - 1\n\t\t\t\tsc[cc] = v\n\t\t\t\tif v < min {\n\t\t\t\t\tmin, min_c = v, cc\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn int(min)<<16 | int(min_c)\n}\n\nfunc sd_update_revert(aux *sdaux_t, sr []int8, sc []uint8, r uint16) {\n\trows := &aux.c[r]\n\tfor _, c := range rows {\n\t\tsc[c] &= 0x7f\n\t}\n\tfor _, c := range rows {\n\t\tfor _, rr := range &aux.r[c] {\n\t\t\tsr[rr]--\n\t\t\tif sr[rr] != 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfor _, cc := range &aux.c[rr] {\n\t\t\t\tsc[cc]++\n\t\t\t} // unroll this loop makes no difference\n\t\t}\n\t}\n}\n\nfunc sd_solve(aux *sdaux_t, _s []byte) int {\n\tsr := make([]int8, 729)\n\tcr := make([]int8, 81)\n\tsc := make([]uint8, 324)\n\tcc := make([]int16, 81)\n\tout := make([]byte, 81)\n\tn, hints := 0, 0\n\tfor c := 0; c < 324; c++ {\n\t\tsc[c] = 9\n\t}\n\tfor i := 0; i < 81; i++ {\n\t\ta := -1\n\t\tif _s[i] >= '1' && _s[i] <= '9' {\n\t\t\ta = int(_s[i] - '1')\n\t\t}\n\t\tif a >= 0 {\n\t\t\tsd_update_forward(aux, sr, sc, uint16(i*9+a))\n\t\t\thints++\n\t\t}\n\t\tcr[i], cc[i], out[i] = -1, -1, _s[i]\n\t}\n\ti, dir, cand := 0, 1, 10<<16\n\tfor {\n\t\tfor i >= 0 && i < 81-hints {\n\t\t\tif dir == 1 {\n\t\t\t\tmin := uint8(cand >> 16)\n\t\t\t\tcc[i] = int16(cand & 0xffff)\n\t\t\t\tif min > 1 {\n\t\t\t\t\tfor c, scc := range sc {\n\t\t\t\t\t\tif scc < min {\n\t\t\t\t\t\t\tmin, cc[i] = scc, int16(c)\n\t\t\t\t\t\t\tif min <= 1 {\n\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif min == 0 || min == 10 {\n\t\t\t\t\tcr[i], dir = -1, -1\n\t\t\t\t\ti--\n\t\t\t\t}\n\t\t\t}\n\t\t\tc := cc[i]\n\t\t\tif dir == -1 && cr[i] >= 0 {\n\t\t\t\tsd_update_revert(aux, sr, sc, aux.r[c][cr[i]])\n\t\t\t}\n\t\t\tr2_ := 9\n\t\t\tfor r2 := cr[i] + 1; r2 < 9; r2++ {\n\t\t\t\tif sr[aux.r[c][r2]] == 0 {\n\t\t\t\t\tr2_ = int(r2)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif r2_ < 9 {\n\t\t\t\tcand = sd_update_forward(aux, sr, sc, aux.r[c][r2_])\n\t\t\t\tcr[i], dir = int8(r2_), 1\n\t\t\t\ti++\n\t\t\t} else {\n\t\t\t\tcr[i], dir = -1, -1\n\t\t\t\ti--\n\t\t\t}\n\t\t}\n\t\tif i < 0 {\n\t\t\tbreak\n\t\t}\n\t\tfor j := 0; j < i; j++ {\n\t\t\tr := aux.r[cc[j]][cr[j]]\n\t\t\tout[r/9] = byte(r%9) + '1'\n\t\t}\n\t\tfmt.Println(string(out))\n\t\tn++\n\t\ti--\n\t\tdir = -1\n\t}\n\treturn n\n}\n\nfunc main() {\n\ta := sd_genmat()\n\tr := bufio.NewReader(os.Stdin)\n\tfor {\n\t\tl, e := r.ReadSlice('\\n')\n\t\tif e != nil {\n\t\t\tbreak\n\t\t}\n\t\tif len(l) > 81 {\n\t\t\tsd_solve(a, l)\n\t\t\tfmt.Println(\"\")\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "benchmarks/Sudoku/sudoku_java.java",
    "content": "import java.io.*;\n\nclass sudoku_java {\n\tint[][] R, C;\n\tpublic void genmat() {\n\t\tR = new int[324][9];\n\t\tC = new int[729][4];\n\t\tint[] nr = new int[324];\n\t\tint i, j, k, r, c, c2, r2;\n\t\tfor (i = r = 0; i < 9; ++i) // generate c[729][4]\n\t\t\tfor (j = 0; j < 9; ++j)\n\t\t\t\tfor (k = 0; k < 9; ++k) { // this \"9\" means each cell has 9 possible numbers\n\t\t\t\t\tC[r][0] = 9 * i + j;                  // row-column constraint\n\t\t\t\t\tC[r][1] = (i/3*3 + j/3) * 9 + k + 81; // box-number constraint\n\t\t\t\t\tC[r][2] = 9 * i + k + 162;            // row-number constraint\n\t\t\t\t\tC[r][3] = 9 * j + k + 243;            // col-number constraint\n\t\t\t\t\t++r;\n\t\t\t\t}\n\t\tfor (c = 0; c < 324; ++c) nr[c] = 0;\n\t\tfor (r = 0; r < 729; ++r) // generate r[][] from c[][]\n\t\t\tfor (c2 = 0; c2 < 4; ++c2) {\n\t\t\t\tk = C[r][c2]; R[k][nr[k]++] = r;\n\t\t\t}\n\t}\n\tprivate int sd_update(int[] sr, int[] sc, int r, int v) {\n\t\tint c2, min = 10, min_c = 0;\n\t\tfor (c2 = 0; c2 < 4; ++c2) sc[C[r][c2]] += v<<7;\n\t\tfor (c2 = 0; c2 < 4; ++c2) { // update # available choices\n\t\t\tint r2, rr, cc2, c = C[r][c2];\n\t\t\tif (v > 0) { // move forward\n\t\t\t\tfor (r2 = 0; r2 < 9; ++r2) {\n\t\t\t\t\tif (sr[rr = R[c][r2]]++ != 0) continue; // update the row status\n\t\t\t\t\tfor (cc2 = 0; cc2 < 4; ++cc2) {\n\t\t\t\t\t\tint cc = C[rr][cc2];\n\t\t\t\t\t\tif (--sc[cc] < min) { // update # allowed choices\n\t\t\t\t\t\t\tmin = sc[cc]; min_c = cc; // register the minimum number\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else { // revert\n\t\t\t\tint[] p;\n\t\t\t\tfor (r2 = 0; r2 < 9; ++r2) {\n\t\t\t\t\tif (--sr[rr = R[c][r2]] != 0) continue; // update the row status\n\t\t\t\t\tp = C[rr]; ++sc[p[0]]; ++sc[p[1]]; ++sc[p[2]]; ++sc[p[3]]; // update the count array\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn min<<16 | min_c; // return the col that has been modified and with the minimal available choices\n\t}\n\t// solve a Sudoku; _s is the standard dot/number representation\n\tpublic int solve(String _s) {\n\t\tint i, j, r, c, r2, dir, cand, n = 0, min, hints = 0; // dir=1: forward; dir=-1: backtrack\n\t\tint[] sr = new int[729];\n\t\tint[] cr = new int[81];\n\t\tint[] sc = new int[324];\n\t\tint[] cc = new int[81];\n\t\tint[] out = new int[81];\n\t\tfor (r = 0; r < 729; ++r) sr[r] = 0; // no row is forbidden\n\t\tfor (c = 0; c < 324; ++c) sc[c] = 0<<7|9; // 9 allowed choices; no constraint has been used\n\t\tfor (i = 0; i < 81; ++i) {\n\t\t\tint a = _s.charAt(i) >= '1' && _s.charAt(i) <= '9'? _s.codePointAt(i) - '1' : -1; // number from -1 to 8\n\t\t\tif (a >= 0) sd_update(sr, sc, i * 9 + a, 1); // set the choice\n\t\t\tif (a >= 0) ++hints; // count the number of hints\n\t\t\tcr[i] = cc[i] = -1; out[i] = a;\n\t\t}\n\t\ti = 0; dir = 1; cand = 10<<16|0;\n\t\tfor (;;) {\n\t\t\twhile (i >= 0 && i < 81 - hints) { // maximum 81-hints steps\n\t\t\t\tif (dir == 1) {\n\t\t\t\t\tmin = cand>>16; cc[i] = cand&0xffff;\n\t\t\t\t\tif (min > 1) {\n\t\t\t\t\t\tfor (c = 0; c < 324; ++c) {\n\t\t\t\t\t\t\tif (sc[c] < min) {\n\t\t\t\t\t\t\t\tmin = sc[c]; cc[i] = c; // choose the top constraint\n\t\t\t\t\t\t\t\tif (min <= 1) break; // this is for acceleration; slower without this line\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (min == 0 || min == 10) cr[i--] = dir = -1; // backtrack\n\t\t\t\t}\n\t\t\t\tc = cc[i];\n\t\t\t\tif (dir == -1 && cr[i] >= 0) sd_update(sr, sc, R[c][cr[i]], -1); // revert the choice\n\t\t\t\tfor (r2 = cr[i] + 1; r2 < 9; ++r2) // search for the choice to make\n\t\t\t\t\tif (sr[R[c][r2]] == 0) break; // found if the state equals 0\n\t\t\t\tif (r2 < 9) {\n\t\t\t\t\tcand = sd_update(sr, sc, R[c][r2], 1); // set the choice\n\t\t\t\t\tcr[i++] = r2; dir = 1; // moving forward\n\t\t\t\t} else cr[i--] = dir = -1; // backtrack\n\t\t\t}\n\t\t\tif (i < 0) break;\n\t\t\tchar[] y = new char[81];\n\t\t\tfor (j = 0; j < 81; ++j) y[j] = (char)(out[j] + '1');\n\t\t\tfor (j = 0; j < i; ++j) { r = R[cc[j]][cr[j]]; y[r/9] = (char)(r%9 + '1'); }\n\t\t\t//System.out.println(new String(y));\n\t\t\t++n; --i; dir = -1; // backtrack\n\t\t}\n\t\treturn n;\n\t}\n\tpublic static void main(String[] args) throws Exception {\n\t\tBufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));\n\t\tsudoku_java a = new sudoku_java();\n\t\tString l;\n\t\ta.genmat();\n\t\twhile ((l = stdin.readLine()) != null)\n\t\t\tif (l.length() >= 81) {\n\t\t\t\ta.solve(l);\n\t\t\t\t//System.out.println();\n\t\t\t}\n\t}\n}\n"
  },
  {
    "path": "benchmarks/Sudoku/sudoku_javascript.js",
    "content": "function Sudoku() {\n\tvar C = [], R = [];\n\t\n\tfunction sd_genmat() { // precompute matrix\n\t\tvar i, j, r, c, c2;\n\t\tfor (i = r = 0; i < 9; ++i)\n\t\t\tfor (j = 0; j < 9; ++j)\n\t\t\t\tfor (k = 0; k < 9; ++k)\n\t\t\t\t\tC[r++] = [ 9 * i + j, (Math.floor(i/3)*3 + Math.floor(j/3)) * 9 + k + 81, 9 * i + k + 162, 9 * j + k + 243 ]\n\t\tfor (c = 0; c < 324; ++c) R[c] = []\n\t\tfor (r = 0; r < 729; ++r)\n\t\t\tfor (c2 = 0; c2 < 4; ++c2)\n\t\t\t\tR[C[r][c2]].push(r)\n\t}\n\n\tfunction sd_update(sr, sc, r, v) { // update\n\t\tvar min = 10, min_c = 0;\n\t\tfor (var c2 = 0; c2 < 4; ++c2) sc[C[r][c2]] += v<<7;\n\t\tfor (var c2 = 0; c2 < 4; ++c2) {\n\t\t\tvar r2, rr, cc2, c = C[r][c2];\n\t\t\tif (v > 0) {\n\t\t\t\tfor (r2 = 0; r2 < 9; ++r2) {\n\t\t\t\t\tif (sr[rr = R[c][r2]]++ != 0) continue;\n\t\t\t\t\tfor (cc2 = 0; cc2 < 4; ++cc2) {\n\t\t\t\t\t\tvar cc = C[rr][cc2];\n\t\t\t\t\t\tif (--sc[cc] < min)\n\t\t\t\t\t\t\tmin = sc[cc], min_c = cc;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else { // revert\n\t\t\t\tfor (r2 = 0; r2 < 9; ++r2) {\n\t\t\t\t\tif (--sr[rr = R[c][r2]] != 0) continue;\n\t\t\t\t\tvar p = C[rr]\n\t\t\t\t\t\t++sc[p[0]]; ++sc[p[1]]; ++sc[p[2]]; ++sc[p[3]];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn min<<16 | min_c; // return the col that has been modified and with the minimal available choices\n\t}\n\n\tsd_genmat();\n\n\treturn function(_s) { // closure, the actual solver\n\t\tvar i, j, r, c, r2, min, cand, dir, hints = 0;\n\t\tvar sr = [], sc = [], cr = [], cc = [], out = [], ret = [];\n\t\tfor (r = 0; r < 729; ++r) sr[r] = 0;\n\t\tfor (c = 0; c < 324; ++c) sc[c] = 9;\n\t\tfor (i = 0; i < 81; ++i) {\n\t\t\tvar a = _s.charAt(i) >= '1' && _s.charAt(i) <= '9'? _s.charCodeAt(i) - 49 : -1;\n\t\t\tif (a >= 0) sd_update(sr, sc, i * 9 + a, 1);\n\t\t\tif (a >= 0) ++hints;\n\t\t\tcr[i] = cc[i] = -1, out[i] = a + 1;\n\t\t}\n\t\tfor (i = 0, dir = 1, cand = 10<<16|0;;) {\n\t\t\twhile (i >= 0 && i < 81 - hints) {\n\t\t\t\tif (dir == 1) {\n\t\t\t\t\tmin = cand>>16, cc[i] = cand&0xffff;\n\t\t\t\t\tif (min > 1) {\n\t\t\t\t\t\tfor (c = 0; c < 324; ++c) {\n\t\t\t\t\t\t\tif (sc[c] < min) {\n\t\t\t\t\t\t\t\tmin = sc[c], cc[i] = c;\n\t\t\t\t\t\t\t\tif (min <= 1) break;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (min == 0 || min == 10) cr[i--] = dir = -1;\n\t\t\t\t}\n\t\t\t\tc = cc[i];\n\t\t\t\tif (dir == -1 && cr[i] >= 0) sd_update(sr, sc, R[c][cr[i]], -1);\n\t\t\t\tfor (r2 = cr[i] + 1; r2 < 9; ++r2)\n\t\t\t\t\tif (sr[R[c][r2]] == 0) break;\n\t\t\t\tif (r2 < 9) {\n\t\t\t\t\tcand = sd_update(sr, sc, R[c][r2], 1);\n\t\t\t\t\tcr[i++] = r2; dir = 1;\n\t\t\t\t} else cr[i--] = dir = -1;\n\t\t\t}\n\t\t\tif (i < 0) break;\n\t\t\tvar y = [];\n\t\t\tfor (j = 0; j < 81; ++j) y[j] = out[j];\n\t\t\tfor (j = 0; j < i; ++j) r = R[cc[j]][cr[j]], y[Math.floor(r/9)] = r%9 + 1;\n\t\t\tret.push(y);\n\t\t\t--i; dir = -1;\n\t\t}\n\t\treturn ret;\n\t}\n}\n\nvar solver = Sudoku();\n\nfunction processLine (l) {\n\tif (l.length >= 81) {\n\t\tvar r = solver(l)\n\t\t//for (var i = 0; i < r.length; ++i) print(r[i].join('')+'\\n')\n\t}\n}\n\nvar readline = require('readline');\nvar rl = readline.createInterface({\n  input: process.stdin,\n  output: process.stdout,\n  terminal: false\n});\n\nrl.on('line', function(line){\n    processLine(line);\n})\n\n"
  },
  {
    "path": "benchmarks/Sudoku/sudoku_lua.lua",
    "content": "function sd_genmat()\n\tlocal R, C, r = {}, {}, 0\n\tfor i = 0, 8 do\n\t\tfor j = 0, 8 do\n\t\t\tfor k = 0, 8 do\n\t\t\t\tC[r], r = { 9 * i + j, math.floor(i/3)*27 + math.floor(j/3)*9 + k + 81,\n\t\t\t\t\t\t\t9 * i + k + 162, 9 * j + k + 243 }, r + 1\n\t\t\tend\n\t\tend\n\tend\n\tfor c = 0, 323 do R[c] = {} end\n\tfor r = 0, 728 do\n\t\tfor c2 = 1, 4 do table.insert(R[C[r][c2]], r) end\n\tend\n\treturn R, C\nend\n\nfunction sd_update(R, C, sr, sc, r, v)\n\tlocal min, min_c = 10, 0\n\tfor c2 = 1, 4 do\n\t\tif v > 0 then sc[C[r][c2]] = sc[C[r][c2]] + 128\n\t\telse sc[C[r][c2]] = sc[C[r][c2]] - 128 end\n\tend\n\tfor c2 = 1, 4 do\n\t\tlocal c = C[r][c2]\n\t\tif v > 0 then\n\t\t\tfor r2 = 1, 9 do\n\t\t\t\tlocal rr = R[c][r2]\n\t\t\t\tsr[rr] = sr[rr] + 1\n\t\t\t\tif sr[rr] == 1 then\n\t\t\t\t\tfor cc2 = 1, 4 do\n\t\t\t\t\t\tlocal cc = C[rr][cc2]\n\t\t\t\t\t\tsc[cc] = sc[cc] - 1\n\t\t\t\t\t\tif sc[cc] < min then min, min_c = sc[cc], cc end\n\t\t\t\t\tend\n\t\t\t\tend\n\t\t\tend\n\t\telse\n\t\t\tfor r2 = 1, 9 do\n\t\t\t\tlocal rr = R[c][r2]\n\t\t\t\tsr[rr] = sr[rr] - 1\n\t\t\t\tif sr[rr] == 0 then\n\t\t\t\t\tlocal p = C[rr]\n\t\t\t\t\tsc[p[1]], sc[p[2]], sc[p[3]], sc[p[4]] = sc[p[1]]+1, sc[p[2]]+1, sc[p[3]]+1, sc[p[4]]+1\n\t\t\t\tend\n\t\t\tend\n\t\tend\n\tend\n\treturn min, min_c\nend\n\nfunction sd_solve(R, C, s)\n\tlocal sr, sc, cr, cc, hints = {}, {}, {}, {}, 0\n\tfor r = 0, 728 do sr[r] = 0 end\n\tfor c = 0, 323 do sc[c] = 9 end\n\tfor i = 0, 80 do\n\t\tlocal t = s:byte(i+1)\n\t\tlocal a = t >= 49 and t <= 57 and t - 49 or -1\n\t\tif a >= 0 then sd_update(R, C, sr, sc, i * 9 + a, 1); hints = hints + 1 end\n\t\tcr[i], cc[i] = 0, 0\n\tend\n\tlocal i, min, dir, ret = 0, 10, 1, {}\n\twhile true do\n\t\twhile i >= 0 and i < 81 - hints do\n\t\t\tif dir == 1 then\n\t\t\t\tif min > 1 then\n\t\t\t\t\tfor c = 0, 323 do\n\t\t\t\t\t\tif sc[c] < min then\n\t\t\t\t\t\t\tmin, cc[i] = sc[c], c\n\t\t\t\t\t\t\tif min < 2 then break end\n\t\t\t\t\t\tend\n\t\t\t\t\tend\n\t\t\t\tend\n\t\t\t\tif min == 0 or min == 10 then cr[i], dir, i = 0, -1, i - 1 end\n\t\t\tend\n\t\t\tlocal c, r2_ = cc[i], 10\n\t\t\tif dir == -1 and cr[i] > 0 then sd_update(R, C, sr, sc, R[c][cr[i]], -1) end\n\t\t\tfor r2 = cr[i] + 1, 9 do\n\t\t\t\tif sr[R[c][r2]] == 0 then r2_ = r2; break end\n\t\t\tend\n\t\t\tif r2_ < 10 then\n\t\t\t\tmin, cc[i+1] = sd_update(R, C, sr, sc, R[c][r2_], 1)\n\t\t\t\tcr[i], dir, i = r2_, 1, i + 1\n\t\t\telse cr[i], dir, i = 0, -1, i - 1 end\n\t\tend\n\t\tif i < 0 then break end\n\t\tlocal y = {}\n\t\tfor j = 1, 81 do y[j] = s:byte(j) - 48 end\n\t\tfor j = 0, i - 1 do\n\t\t\tr = R[cc[j]][cr[j]]\n\t\t\ty[math.floor(r/9)+1] = math.fmod(r, 9) + 1\n\t\tend\n\t\tret[#ret+1] = y\n\t\tdir, i = -1, i - 1\n\tend\n\treturn ret\nend\n\nlocal R, C = sd_genmat()\nfor l in io.lines() do\n\tif #l >= 81 then\n\t\tlocal ret = sd_solve(R, C, l)\n\t\t--for _, v in ipairs(ret) do print(table.concat(v)) end\n\t\t--print()\n\tend\nend\n"
  },
  {
    "path": "benchmarks/Sudoku/sudoku_perl.pl",
    "content": "use strict;\nuse warnings;\n\nmy @aux = &sd_genmat();\nwhile (<>) {\n\tchomp;\n\tif (length($_) >= 81) {\n\t\tmy $ret = &sd_solve($aux[0], $aux[1], $_);\n\t\tprint($_, \"\\n\") for (@$ret);\n\t\tprint(\"\\n\");\n\t}\n}\n\nsub sd_genmat() {\n\tmy (@C, @R);\n\tfor my $i (0..8) {\n\t\tfor my $j (0..8) {\n\t\t\tfor my $k (0..8) {\n\t\t\t\tpush(@C, [9*$i+$j, int($i/3)*27+int($j/3)*9+$k+81, 9*$i+$k+162, 9*$j+$k+243])\n\t\t\t}\n\t\t}\n\t}\n\tfor my $r (0..728) {\n\t\tfor my $k (@{$C[$r]}) {\n\t\t\tpush(@{$R[$k]}, $r);\n\t\t}\n\t}\n\treturn (\\@R, \\@C);\n}\n\nsub sd_update() {\n\tmy ($R, $C, $sr, $sc, $r, $v) = @_;\n\tmy ($min, $min_c) = (10, 0);\n\tfor my $c (@{$C->[$r]})  {\n\t\tif ($v > 0) { $sc->[$c] += 128; }\n\t\telse { $sc->[$c] -= 128; }\n\t}\n\tfor my $c (@{$C->[$r]}) {\n\t\tif ($v > 0) {\n\t\t\tfor my $rr (@{$R->[$c]}) {\n\t\t\t\t++$sr->[$rr];\n\t\t\t\tnext if ($sr->[$rr] != 1);\n\t\t\t\tfor my $cc (@{$C->[$rr]}) {\n\t\t\t\t\tif (--$sc->[$cc] < $min) {\n\t\t\t\t\t\t$min = $sc->[$cc];\n\t\t\t\t\t\t$min_c = $cc;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfor my $rr (@{$R->[$c]}) {\n\t\t\t\t--$sr->[$rr];\n\t\t\t\tnext if ($sr->[$rr] != 0);\n\t\t\t\tmy $p = $C->[$rr];\n\t\t\t\t++$sc->[$p->[0]]; ++$sc->[$p->[1]]; ++$sc->[$p->[2]]; ++$sc->[$p->[3]];\n\t\t\t}\n\t\t}\n\t}\n\treturn $min<<16 | $min_c;\n}\n\nsub sd_solve() {\n\tmy ($R, $C, $s) = @_;\n\tmy (@sr, @sc, @cr, @cc, @ret);\n\tmy $hints = 0;\n\tfor my $r (0..728) { $sr[$r] = 0; }\n\tfor my $c (0..323) { $sc[$c] = 9; }\n\tfor my $i (0..80) {\n\t\tmy $a = substr($s, $i, 1) =~ /[1-9]/? ord(substr($s, $i, 1)) - 49 : -1;\n\t\tif ($a >= 0) {\n\t\t\t&sd_update($R, $C, \\@sr, \\@sc, $i*9+$a, 1);\n\t\t\t++$hints;\n\t\t}\n\t\t$cr[$i] = $cc[$i] = -1;\n\t}\n\t#for my $i (0..323) {print(\"$i\\t$sc[$i]\\n\")}\n\tmy ($i, $dir, $cand) = (0, 1, 10<<16);\n\tfor (;;) {\n\t\twhile ($i >= 0 && $i < 81 - $hints) {\n\t\t\tif ($dir == 1) {\n\t\t\t\tmy $min = $cand>>16;\n\t\t\t\t$cc[$i] = $cand&0xffff;\n\t\t\t\tif ($min > 1) {\n\t\t\t\t\tfor my $c (0..323) {\n\t\t\t\t\t\tif ($sc[$c] < $min) {\n\t\t\t\t\t\t\t$min = $sc[$c];\n\t\t\t\t\t\t\t$cc[$i] = $c;\n\t\t\t\t\t\t\tlast if ($min <= 1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ($min == 0 || $min == 10) {\n\t\t\t\t\t$cr[$i--] = $dir = -1;\n\t\t\t\t}\n\t\t\t}\n\t\t\tmy $c = $cc[$i];\n\t\t\t&sd_update($R, $C, \\@sr, \\@sc, $R->[$c][$cr[$i]], -1) if ($dir == -1 && $cr[$i] >= 0);\n\t\t\tmy $r2;\n\t\t\tfor ($r2 = $cr[$i] + 1; $r2 < 9; ++$r2) {\n\t\t\t\tlast if ($sr[$R->[$c][$r2]] == 0);\n\t\t\t}\n\t\t\tif ($r2 < 9) {\n\t\t\t\t$cand = &sd_update($R, $C, \\@sr, \\@sc, $R->[$c][$r2], 1);\n\t\t\t\t$cr[$i++] = $r2; $dir = 1;\n\t\t\t} else {\n\t\t\t\t$cr[$i--] = $dir = -1;\n\t\t\t}\n\t\t}\n\t\tlast if ($i < 0);\n\t\tfor my $j (0..$i-1) {\n\t\t\tmy $r = $R->[$cc[$j]][$cr[$j]];\n\t\t\tsubstr($s, int($r/9), 1) = $r%9 + 1;\n\t\t}\n\t\tpush(@ret, $s);\n\t\t--$i; $dir = -1;\n\t}\n\treturn \\@ret;\n}\n"
  },
  {
    "path": "benchmarks/Sudoku/sudoku_python.py",
    "content": "import sys, string\n\ntry:\n\txrange(1)\nexcept NameError:\n\txrange = range\n\ndef sd_genmat():\n\tC = [[n/9, n/81*9 + n%9 + 81, n%81 + 162, n%9*9 + n/243*3 + n/27%3 + 243] for n in range(729)]\n\tR = [[] for c in xrange(324)]\n\tfor r in xrange(729):\n\t\tfor c2 in xrange(4):\n\t\t\tR[C[r][c2]].append(r)\n\treturn R, C\n\ndef sd_update(R, C, sr, sc, r, v):\n\tm = 10\n\tm_c = 0\n\tfor c in C[r]: sc[c] += v<<7\n\tfor c in C[r]:\n\t\tif v > 0:\n\t\t\tfor rr in R[c]:\n\t\t\t\tsr[rr] += 1\n\t\t\t\tif sr[rr] == 1:\n\t\t\t\t\tfor cc in C[rr]:\n\t\t\t\t\t\tsc[cc] -= 1\n\t\t\t\t\t\tif sc[cc] < m:\n\t\t\t\t\t\t\tm, m_c = sc[cc], cc\n\t\telse:\n\t\t\tfor rr in R[c]:\n\t\t\t\tsr[rr] -= 1\n\t\t\t\tif sr[rr] == 0:\n\t\t\t\t\tp = C[rr]\n\t\t\t\t\tsc[p[0]] += 1; sc[p[1]] += 1; sc[p[2]] += 1; sc[p[3]] += 1;\n\treturn m, m_c\n\ndef sd_solve(R, C, s):\n\tret, out, hints = [], [], 0\n\tsr = [0] * 729\n\tsc = [9] * 324\n\tcr = [-1] * 81\n\tcc = [-1] * 81\n\tfor i in xrange(81):\n\t\tif ord(s[i]) >= 49 and ord(s[i]) <= 57: a = ord(s[i]) - 49\n\t\telse: a = -1\n\t\tif a >= 0:\n\t\t\tsd_update(R, C, sr, sc, i * 9 + a, 1)\n\t\t\thints += 1\n\t\tout.append(a + 1)\n\ti, m, d = 0, 10, 1\n\twhile True:\n\t\twhile i >= 0 and i < 81 - hints:\n\t\t\tif d == 1:\n\t\t\t\tif m > 1:\n\t\t\t\t\tfor c in xrange(324): # using enumerate() here is slower\n\t\t\t\t\t\tif sc[c] < m:\n\t\t\t\t\t\t\tm, cc[i] = sc[c], c\n\t\t\t\t\t\t\tif m < 2: break\n\t\t\t\tif m == 0 or m == 10:\n\t\t\t\t\tcr[i], d = -1, -1\n\t\t\t\t\ti -= 1\n\t\t\tc = cc[i]\n\t\t\tif d == -1 and cr[i] >= 0: sd_update(R, C, sr, sc, R[c][cr[i]], -1)\n\t\t\tr2_ = 9\n\t\t\tfor r2 in xrange(cr[i] + 1, 9):\n\t\t\t\tif sr[R[c][r2]] == 0: r2_ = r2; break\n\t\t\tif r2_ < 9:\n\t\t\t\tm, cc[i+1] = sd_update(R, C, sr, sc, R[c][r2], 1)\n\t\t\t\tcr[i], d = r2, 1\n\t\t\t\ti += 1\n\t\t\telse:\n\t\t\t\tcr[i], d = -1, -1\n\t\t\t\ti -= 1\n\t\tif i < 0: break\n\t\ty = out[:81]\n\t\tfor j in xrange(i):\n\t\t\tr = R[cc[j]][cr[j]]\n\t\t\ty[r//9] = r%9 + 1\n\t\tret.append(y)\n\t\ti -= 1\n\t\td = -1\n\treturn ret\n\nR, C = sd_genmat()\nfor line in sys.stdin:\n\tif len(line) >= 81:\n\t\tret = sd_solve(R, C, line)\n\t\t#for j in ret:\n\t\t#\tprint(''.join(map(str, j)))\n\t\t#print('')\n"
  },
  {
    "path": "benchmarks/Sudoku/sudoku_ruby.rb",
    "content": "def sd_genmat()\n\tmr = Array.new(324) { [] }\n\tmc = Array.new(729) { [] }\n\tr = 0\n\t(0...9).each do |i|\n\t\t(0...9).each do |j|\n\t\t\t(0...9).each do |k|\n\t\t\t\tmc[r] = [ 9 * i + j, (i/3*3 + j/3) * 9 + k + 81, 9 * i + k + 162, 9 * j + k + 243 ]\n\t\t\t\tr += 1\n\t\t\tend\n\t\tend\n\tend\n\t(0...729).each do |r|\n\t\t(0...4).each do |c2|\n\t\t\tmr[mc[r][c2]].push(r)\n\t\tend\n\tend\n\treturn mr, mc\nend\n\ndef sd_update(mr, mc, sr, sc, r, v)\n\tmin, min_c = 10, 0\n\t(0...4).each do |c2|\n\t\tif v > 0 then sc[mc[r][c2]] += 128\n\t\telse sc[mc[r][c2]] -= 128 end\n\tend\n\t(0...4).each do |c2|\n\t\tc = mc[r][c2]\n\t\tif v > 0 then\n\t\t\t(0...9).each do |r2|\n\t\t\t\trr = mr[c][r2]\n\t\t\t\tsr[rr] += + 1\n\t\t\t\tif sr[rr] == 1 then\n\t\t\t\t\tp = mc[rr]\n\t\t\t\t\tsc[p[0]] -= 1; sc[p[1]] -= 1; sc[p[2]] -= 1; sc[p[3]] -= 1\n\t\t\t\t\tif sc[p[0]] < min then min, min_c = sc[p[0]], p[0] end\n\t\t\t\t\tif sc[p[1]] < min then min, min_c = sc[p[1]], p[1] end\n\t\t\t\t\tif sc[p[2]] < min then min, min_c = sc[p[2]], p[2] end\n\t\t\t\t\tif sc[p[3]] < min then min, min_c = sc[p[3]], p[3] end\n\t\t\t\tend\n\t\t\tend\n\t\telse\n\t\t\t(0...9).each do |r2|\n\t\t\t\trr = mr[c][r2]\n\t\t\t\tsr[rr] -= 1\n\t\t\t\tif sr[rr] == 0 then\n\t\t\t\t\tp = mc[rr]\n\t\t\t\t\tsc[p[0]] += 1; sc[p[1]] += 1; sc[p[2]] += 1; sc[p[3]] += 1\n\t\t\t\tend\n\t\t\tend\n\t\tend\n\tend\n\treturn min, min_c\nend\n\ndef sd_solve(mr, mc, s)\n\tret, sr, sc, hints = [], Array.new(729) { 0 }, Array.new(324) { 9 }, 0\n\t(0...81).each do |i|\n\t\ta = (s[i].chr >= '1' and s[i].chr <= '9')? s[i].ord - 49 : -1\n\t\tif a >= 0 then sd_update(mr, mc, sr, sc, i * 9 + a, 1); hints += 1 end\n\tend\n\tcr, cc = Array.new(81) { -1 }, Array.new(81) { 0 }\n\ti, min, dir = 0, 10, 1\n\tloop do\n\t\twhile i >= 0 and i < 81 - hints do\n\t\t\tif dir == 1 then\n\t\t\t\tif min > 1 then\n\t\t\t\t\t(0...324).each do |c|\n\t\t\t\t\t\tif sc[c] < min then\n\t\t\t\t\t\t\tmin, cc[i] = sc[c], c\n\t\t\t\t\t\t\tif min < 2 then break end\n\t\t\t\t\t\tend\n\t\t\t\t\tend\n\t\t\t\tend\n\t\t\t\tif min == 0 or min == 10 then cr[i], dir, i = -1, -1, i - 1 end\n\t\t\tend\n\t\t\tc = cc[i]\n\t\t\tif dir == -1 and cr[i] >= 0 then sd_update(mr, mc, sr, sc, mr[c][cr[i]], -1) end\n\t\t\tr2_ = 9\n\t\t\t(cr[i]+1...9).each do |r2|\n\t\t\t\tif sr[mr[c][r2]] == 0 then r2_ = r2; break end\n\t\t\tend\n\t\t\tif r2_ < 9 then\n\t\t\t\tmin, cc[i+1] = sd_update(mr, mc, sr, sc, mr[c][r2_], 1)\n\t\t\t\tcr[i], dir, i = r2_, 1, i + 1\n\t\t\telse cr[i], dir, i = -1, -1, i - 1 end\n\t\tend\n\t\tif i < 0 then break end\n\t\to = []\n\t\t(0...81).each do |j| o.push(s[j].ord - 49) end\n\t\t(0...i).each do |j|\n\t\t\tr = mr[cc[j]][cr[j]]\n\t\t\to[r/9] = r % 9 + 1\n\t\tend\n\t\tret.push(o)\n\t\ti, dir = i - 1, -1\n\tend\n\treturn ret\nend\n\nmr, mc = sd_genmat()\nSTDIN.each do |line|\n\tif line.length >= 81 then\n\t\tret = sd_solve(mr, mc, line)\n\t\t#ret.each do |s| puts s.join end\n\t\t#puts\n\tend\nend\n"
  },
  {
    "path": "benchmarks/benchmark",
    "content": "gcc ./ext/genint.c -o ./ext/genint\n\ngcc Nbodies/nbodies_c.c -std=c99 -O3 -lm -o Nbodies/nbodies_c\ng++ Nbodies/nbodies_cpp.cpp -std=c++11 -O3 -lm -o Nbodies/nbodies_cpp\ngcc Nbodies/nbodies_cello.c -DCELLO_NDEBUG ../libCello.a -I../include -std=gnu99 -pg -O3 -lm -lpthread -o Nbodies/nbodies_cello\njavac Nbodies/nbodies_java.java\n\ngcc List/list_c.c -Wno-unused-result -I./ext -std=c99 -O3 -lm -o List/list_c\ng++ List/list_cpp.cpp -Wno-unused-result -std=c++11 -O3 -lm -o List/list_cpp\ngcc List/list_cello.c -DCELLO_NDEBUG ../libCello.a -I../include -Wno-unused-result -std=gnu99 -pg -O3 -lm -lpthread -o List/list_cello\njavac List/list_java.java\n\ngcc Dict/dict_c.c -Wno-unused-result -I./ext -std=c99 -O3 -lm -o Dict/dict_c\ng++ Dict/dict_cpp.cpp -Wno-unused-result -std=c++11 -O3 -lm -o Dict/dict_cpp\ngcc Dict/dict_cello.c -DCELLO_NDEBUG ../libCello.a -I../include -Wno-unused-result -std=gnu99 -pg -O3 -lm -lpthread -o Dict/dict_cello\njavac Dict/dict_java.java\n\ngcc Map/map_c.c -Wno-unused-result -I./ext -std=c99 -O3 -lm -o Map/map_c\ng++ Map/map_cpp.cpp -Wno-unused-result -std=c++11 -O3 -lm -o Map/map_cpp\ngcc Map/map_cello.c -DCELLO_NDEBUG ../libCello.a -I../include -Wno-unused-result -std=gnu99 -pg -O3 -lm -lpthread -o Map/map_cello\njavac Map/map_java.java\n\ngcc Sudoku/sudoku_c.c -Wno-unused-result -I./ext -std=c99 -O3 -lm -o Sudoku/sudoku_c\ng++ Sudoku/sudoku_cpp.cpp -Wno-unused-result -std=c++11 -O3 -lm -o Sudoku/sudoku_cpp\ngcc Sudoku/sudoku_cello.c -DCELLO_NDEBUG ../libCello.a -I../include -Wno-unused-result -std=gnu99 -pg -O3 -lm -lpthread -o Sudoku/sudoku_cello\njavac Sudoku/sudoku_java.java\n\ngcc Matmul/matmul_c.c -Wno-unused-result -I./ext -std=c99 -O3 -lm -o Matmul/matmul_c\ng++ Matmul/matmul_cpp.cpp -Wno-unused-result -std=c++11 -O3 -lm -o Matmul/matmul_cpp\ngcc Matmul/matmul_cello.c -DCELLO_NDEBUG ../libCello.a -I../include -Wno-unused-result -std=gnu99 -pg -O3 -lm -lpthread -o Matmul/matmul_cello\njavac Matmul/matmul_java.java\n\ngcc GC/gc_c.c -Wno-unused-result -I./ext -std=c99 -O3 -lm -o GC/gc_c\ng++ GC/gc_cpp.cpp -Wno-unused-result -std=c++11 -O3 -lm -o GC/gc_cpp\ngcc GC/gc_cello.c -DCELLO_NDEBUG ../libCello.a -I../include -std=gnu99 -O3 -lm -lpthread -o GC/gc_cello\njavac GC/gc_java.java\n\necho \necho \"## Garbage Collection\"\necho\necho -n \"* C: \"\ntime -f \"%e\" ./GC/gc_c\necho -n \"* C++: \"\ntime -f \"%e\" ./GC/gc_cpp\necho -n \"* Cello: \"\ntime -f \"%e\" ./GC/gc_cello\necho -n \"* Java: \"\ntime -f \"%e\" java -cp ./GC gc_java\necho -n \"* Javascript: \"\ntime -f \"%e\" nodejs GC/gc_javascript.js\necho -n \"* Python: \"\ntime -f \"%e\" python GC/gc_python.py\necho -n \"* Ruby: \"\ntime -f \"%e\" ruby GC/gc_ruby.rb\necho -n \"* Lua: \"\ntime -f \"%e\" lua GC/gc_lua.lua\necho -n \"* Lua JIT: \"\ntime -f \"%e\" luajit GC/gc_lua.lua\n\ngprof GC/gc_cello > GC/profile.txt\nrm gmon.out\n\n\necho \necho \"## List\"\necho\necho -n \"* C: \"\ntime -f \"%e\" ./List/list_c\necho -n \"* C++: \"\ntime -f \"%e\" ./List/list_cpp\necho -n \"* Cello: \"\ntime -f \"%e\" ./List/list_cello\necho -n \"* Java: \"\ntime -f \"%e\" java -cp ./List list_java\necho -n \"* Javascript: \"\ntime -f \"%e\" nodejs List/list_javascript.js\necho -n \"* Python: \"\ntime -f \"%e\" python List/list_python.py\necho -n \"* Ruby: \"\ntime -f \"%e\" ruby List/list_ruby.rb\necho -n \"* Lua: \"\ntime -f \"%e\" lua List/list_lua.lua\necho -n \"* Lua JIT: \"\ntime -f \"%e\" luajit List/list_lua.lua\n\ngprof List/list_cello > List/profile.txt\nrm gmon.out\n\necho \necho \"## Map\"\necho\necho -n \"* C: \"\ntime -f \"%e\" sh -c './ext/genint | ./Map/map_c'\necho -n \"* C++: \"\ntime -f \"%e\" sh -c './ext/genint | ./Map/map_cpp'\necho -n \"* Cello: \"\ntime -f \"%e\" sh -c './ext/genint | ./Map/map_cello'\necho -n \"* Java: \"\ntime -f \"%e\" sh -c './ext/genint | java -cp ./Map map_java'\necho -n \"* Javascript: \"\ntime -f \"%e\" sh -c './ext/genint | nodejs Map/map_javascript.js'\necho -n \"* Python: \"\ntime -f \"%e\" sh -c './ext/genint | python Map/map_python.py'\necho -n \"* Ruby: \"\ntime -f \"%e\" sh -c './ext/genint | ruby Map/map_ruby.rb'\necho -n \"* Lua: \"\ntime -f \"%e\" sh -c './ext/genint | lua Map/map_lua.lua'\necho -n \"* Lua JIT: \"\ntime -f \"%e\" sh -c './ext/genint | luajit Map/map_lua.lua'\n\ngprof Map/map_cello > Map/profile.txt\nrm gmon.out\n\necho \necho \"## NBodies\"\necho\necho -n \"* C: \"\ntime -f \"%e\" ./Nbodies/nbodies_c \necho -n \"* C++: \"\ntime -f \"%e\" ./Nbodies/nbodies_cpp\necho -n \"* Cello: \"\ntime -f \"%e\" ./Nbodies/nbodies_cello\necho -n \"* Java: \"\ntime -f \"%e\" java -cp ./Nbodies nbodies_java\necho -n \"* Javascript: \"\ntime -f \"%e\" nodejs Nbodies/nbodies_javascript.js\necho -n \"* Python: \"\ntime -f \"%e\" python Nbodies/nbodies_python.py\necho -n \"* Ruby: \"\ntime -f \"%e\" ruby Nbodies/nbodies_ruby.rb\necho -n \"* Lua: \"\ntime -f \"%e\" lua Nbodies/nbodies_lua.lua\necho -n \"* Lua JIT: \"\ntime -f \"%e\" luajit Nbodies/nbodies_lua.lua\n\ngprof Nbodies/nbodies_cello > Nbodies/profile.txt\nrm gmon.out\n\necho \necho \"## Dict\"\necho\necho -n \"* C: \"\ntime -f \"%e\" sh -c './ext/genint | ./Dict/dict_c'\necho -n \"* C++: \"\ntime -f \"%e\" sh -c './ext/genint | ./Dict/dict_cpp'\necho -n \"* Cello: \"\ntime -f \"%e\" sh -c './ext/genint | ./Dict/dict_cello'\necho -n \"* Java: \"\ntime -f \"%e\" sh -c './ext/genint | java -cp ./Dict dict_java'\necho -n \"* Javascript: \"\ntime -f \"%e\" sh -c './ext/genint | nodejs Dict/dict_javascript.js'\necho -n \"* Python: \"\ntime -f \"%e\" sh -c './ext/genint | python Dict/dict_python.py'\necho -n \"* Ruby: \"\ntime -f \"%e\" sh -c './ext/genint | ruby Dict/dict_ruby.rb'\necho -n \"* Lua: \"\ntime -f \"%e\" sh -c './ext/genint | lua Dict/dict_lua.lua'\necho -n \"* Lua JIT: \"\ntime -f \"%e\" sh -c './ext/genint | luajit Dict/dict_lua.lua'\n\ngprof Dict/dict_cello > Dict/profile.txt\nrm gmon.out\n\necho \necho \"## Sudoku\"\necho\necho -n \"* C: \"\ntime -f \"%e\" sh -c './ext/sudoku | ./Sudoku/sudoku_c'\necho -n \"* C++: \"\ntime -f \"%e\" sh -c './ext/sudoku | ./Sudoku/sudoku_cpp'\necho -n \"* Cello: \"\ntime -f \"%e\" sh -c './ext/sudoku | ./Sudoku/sudoku_cello'\necho -n \"* Java: \"\ntime -f \"%e\" sh -c './ext/sudoku | java -cp ./Sudoku sudoku_java'\necho -n \"* Javascript: \"\ntime -f \"%e\" sh -c './ext/sudoku | nodejs Sudoku/sudoku_javascript.js'\necho -n \"* Python: \"\ntime -f \"%e\" sh -c './ext/sudoku | python Sudoku/sudoku_python.py'\necho -n \"* Ruby: \"\ntime -f \"%e\" sh -c './ext/sudoku | ruby Sudoku/sudoku_ruby.rb'\necho -n \"* Lua: \"\ntime -f \"%e\" sh -c './ext/sudoku | lua Sudoku/sudoku_lua.lua'\necho -n \"* Lua JIT: \"\ntime -f \"%e\" sh -c './ext/sudoku | luajit Sudoku/sudoku_lua.lua'\n\ngprof Sudoku/sudoku_cello > Sudoku/profile.txt\nrm gmon.out\n\necho \necho \"## Matmul\"\necho\necho -n \"* C: \"\ntime -f \"%e\" ./Matmul/matmul_c\necho -n \"* C++: \"\ntime -f \"%e\" ./Matmul/matmul_cpp\necho -n \"* Cello: \"\ntime -f \"%e\" ./Matmul/matmul_cello\necho -n \"* Java: \"\ntime -f \"%e\" java -cp ./Matmul matmul_java\necho -n \"* Javascript: \"\ntime -f \"%e\" nodejs Matmul/matmul_javascript.js\necho -n \"* Python: \"\ntime -f \"%e\" python Matmul/matmul_python.py\necho -n \"* Ruby: \"\ntime -f \"%e\" ruby Matmul/matmul_ruby.rb\necho -n \"* Lua: \"\ntime -f \"%e\" lua Matmul/matmul_lua.lua\necho -n \"* Lua JIT: \"\ntime -f \"%e\" luajit Matmul/matmul_lua.lua\n\ngprof Matmul/matmul_cello > Matmul/profile.txt\nrm gmon.out\n\n"
  },
  {
    "path": "benchmarks/benchmark.sh",
    "content": "#!/bin/sh\ngcc ./ext/genint.c -o ./ext/genint\n\ngcc Nbodies/nbodies_c.c -std=c99 -O3 -lm -o Nbodies/nbodies_c\ng++ Nbodies/nbodies_cpp.cpp -std=c++11 -O3 -lm -o Nbodies/nbodies_cpp\ncc Nbodies/nbodies_cello.c -DCELLO_NDEBUG ../libCello.a -I../include -std=gnu99  -O3 -lm -lpthread -o Nbodies/nbodies_cello\njavac Nbodies/nbodies_java.java\n\ngcc List/list_c.c -Wno-unused-result -I./ext -std=c99 -O3 -lm -o List/list_c\ng++ List/list_cpp.cpp -Wno-unused-result -std=c++11 -O3 -lm -o List/list_cpp\ncc List/list_cello.c -DCELLO_NDEBUG ../libCello.a -I../include -Wno-unused-result -std=gnu99  -O3 -lm -lpthread -o List/list_cello\njavac List/list_java.java\n\ngcc Dict/dict_c.c -Wno-unused-result -I./ext -std=c99 -O3 -lm -o Dict/dict_c\ng++ Dict/dict_cpp.cpp -Wno-unused-result -std=c++11 -O3 -lm -o Dict/dict_cpp\ncc Dict/dict_cello.c -DCELLO_NDEBUG ../libCello.a -I../include -Wno-unused-result -std=gnu99  -O3 -lm -lpthread -o Dict/dict_cello\njavac Dict/dict_java.java\n\ngcc Map/map_c.c -Wno-unused-result -I./ext -std=c99 -O3 -lm -o Map/map_c\ng++ Map/map_cpp.cpp -Wno-unused-result -std=c++11 -O3 -lm -o Map/map_cpp\ncc Map/map_cello.c -DCELLO_NDEBUG ../libCello.a -I../include -Wno-unused-result -std=gnu99  -O3 -lm -lpthread -o Map/map_cello\njavac Map/map_java.java\n\ngcc Sudoku/sudoku_c.c -Wno-unused-result -I./ext -std=c99 -O3 -lm -o Sudoku/sudoku_c\ng++ Sudoku/sudoku_cpp.cpp -Wno-unused-result -std=c++11 -O3 -lm -o Sudoku/sudoku_cpp\ncc Sudoku/sudoku_cello.c -DCELLO_NDEBUG ../libCello.a -I../include -Wno-unused-result -std=gnu99  -O3 -lm -lpthread -o Sudoku/sudoku_cello\njavac Sudoku/sudoku_java.java\n\ngcc Matmul/matmul_c.c -Wno-unused-result -I./ext -std=c99 -O3 -lm -o Matmul/matmul_c\ng++ Matmul/matmul_cpp.cpp -Wno-unused-result -std=c++11 -O3 -lm -o Matmul/matmul_cpp\ncc Matmul/matmul_cello.c -DCELLO_NDEBUG ../libCello.a -I../include -Wno-unused-result -std=gnu99  -O3 -lm -lpthread -o Matmul/matmul_cello\njavac Matmul/matmul_java.java\n\ngcc GC/gc_c.c -Wno-unused-result -I./ext -std=c99 -O3 -lm -o GC/gc_c\ng++ GC/gc_cpp.cpp -Wno-unused-result -std=c++11 -O3 -lm -o GC/gc_cpp\ncc GC/gc_cello.c -DCELLO_NDEBUG ../libCello.a -I../include -std=gnu99 -O3 -lm -lpthread -o GC/gc_cello\njavac GC/gc_java.java\n\necho \necho \"## Garbage Collection\"\necho\nprintf \"* C: \"\ngtime -f \"%e\" -f \"%e\" ./GC/gc_c\nprintf \"* C++: \"\ngtime -f \"%e\" -f \"%e\" ./GC/gc_cpp\nprintf \"* Cello: \"\ngtime -f \"%e\" -f \"%e\" ./GC/gc_cello\nprintf \"* Java: \"\ngtime -f \"%e\" -f \"%e\" java -cp ./GC gc_java\nprintf \"* Javascript: \"\ngtime -f \"%e\" -f \"%e\" node GC/gc_javascript.js\nprintf \"* Python: \"\ngtime -f \"%e\" -f \"%e\" python GC/gc_python.py\nprintf \"* Ruby: \"\ngtime -f \"%e\" -f \"%e\" ruby GC/gc_ruby.rb\nprintf \"* Lua: \"\ngtime -f \"%e\" -f \"%e\" lua GC/gc_lua.lua\n# printf \"* Lua JIT: \"\n# gtime -f \"%e\" -f \"%e\" luajit GC/gc_lua.lua\n\n# gprof GC/gc_cello > GC/profile.txt\n# rm gmon.out\n\n\necho \necho \"## List\"\necho\nprintf \"* C: \"\ngtime -f \"%e\" -f \"%e\" ./List/list_c\nprintf \"* C++: \"\ngtime -f \"%e\" -f \"%e\" ./List/list_cpp\nprintf \"* Cello: \"\ngtime -f \"%e\" -f \"%e\" ./List/list_cello\nprintf \"* Java: \"\ngtime -f \"%e\" -f \"%e\" java -cp ./List list_java\nprintf \"* Javascript: \"\ngtime -f \"%e\" -f \"%e\" node List/list_javascript.js\nprintf \"* Python: \"\ngtime -f \"%e\" -f \"%e\" python List/list_python.py\nprintf \"* Ruby: \"\ngtime -f \"%e\" -f \"%e\" ruby List/list_ruby.rb\nprintf \"* Lua: \"\ngtime -f \"%e\" -f \"%e\" lua List/list_lua.lua\n# printf \"* Lua JIT: \"\n# gtime -f \"%e\" -f \"%e\" luajit List/list_lua.lua\n\n# gprof List/list_cello > List/profile.txt\n# rm gmon.out\n\necho \necho \"## Map\"\necho\nprintf \"* C: \"\ngtime -f \"%e\" -f \"%e\" sh -c './ext/genint | ./Map/map_c'\nprintf \"* C++: \"\ngtime -f \"%e\" -f \"%e\" sh -c './ext/genint | ./Map/map_cpp'\nprintf \"* Cello: \"\ngtime -f \"%e\" -f \"%e\" sh -c './ext/genint | ./Map/map_cello'\nprintf \"* Java: \"\ngtime -f \"%e\" -f \"%e\" sh -c './ext/genint | java -cp ./Map map_java'\nprintf \"* Javascript: \"\ngtime -f \"%e\" -f \"%e\" sh -c './ext/genint | node Map/map_javascript.js'\nprintf \"* Python: \"\ngtime -f \"%e\" -f \"%e\" sh -c './ext/genint | python Map/map_python.py'\nprintf \"* Ruby: \"\ngtime -f \"%e\" -f \"%e\" sh -c './ext/genint | ruby Map/map_ruby.rb'\nprintf \"* Lua: \"\ngtime -f \"%e\" -f \"%e\" sh -c './ext/genint | lua Map/map_lua.lua'\n# printf \"* Lua JIT: \"\n# gtime -f \"%e\" -f \"%e\" sh -c './ext/genint | luajit Map/map_lua.lua'\n\n# gprof Map/map_cello > Map/profile.txt\n# rm gmon.out\n\necho \necho \"## NBodies\"\necho\nprintf \"* C: \"\ngtime -f \"%e\" -f \"%e\" ./Nbodies/nbodies_c \nprintf \"* C++: \"\ngtime -f \"%e\" -f \"%e\" ./Nbodies/nbodies_cpp\nprintf \"* Cello: \"\ngtime -f \"%e\" -f \"%e\" ./Nbodies/nbodies_cello\nprintf \"* Java: \"\ngtime -f \"%e\" -f \"%e\" java -cp ./Nbodies nbodies_java\nprintf \"* Javascript: \"\ngtime -f \"%e\" -f \"%e\" node Nbodies/nbodies_javascript.js\nprintf \"* Python: \"\ngtime -f \"%e\" -f \"%e\" python Nbodies/nbodies_python.py\nprintf \"* Ruby: \"\ngtime -f \"%e\" -f \"%e\" ruby Nbodies/nbodies_ruby.rb\nprintf \"* Lua: \"\ngtime -f \"%e\" -f \"%e\" lua Nbodies/nbodies_lua.lua\n# printf \"* Lua JIT: \"\n# gtime -f \"%e\" -f \"%e\" luajit Nbodies/nbodies_lua.lua\n\n# gprof Nbodies/nbodies_cello > Nbodies/profile.txt\n# rm gmon.out\n\necho \necho \"## Dict\"\necho\nprintf \"* C: \"\ngtime -f \"%e\" -f \"%e\" sh -c './ext/genint | ./Dict/dict_c'\nprintf \"* C++: \"\ngtime -f \"%e\" -f \"%e\" sh -c './ext/genint | ./Dict/dict_cpp'\nprintf \"* Cello: \"\ngtime -f \"%e\" -f \"%e\" sh -c './ext/genint | ./Dict/dict_cello'\nprintf \"* Java: \"\ngtime -f \"%e\" -f \"%e\" sh -c './ext/genint | java -cp ./Dict dict_java'\nprintf \"* Javascript: \"\ngtime -f \"%e\" -f \"%e\" sh -c './ext/genint | node Dict/dict_javascript.js'\nprintf \"* Python: \"\ngtime -f \"%e\" -f \"%e\" sh -c './ext/genint | python Dict/dict_python.py'\nprintf \"* Ruby: \"\ngtime -f \"%e\" -f \"%e\" sh -c './ext/genint | ruby Dict/dict_ruby.rb'\nprintf \"* Lua: \"\ngtime -f \"%e\" -f \"%e\" sh -c './ext/genint | lua Dict/dict_lua.lua'\n# printf \"* Lua JIT: \"\n# gtime -f \"%e\" -f \"%e\" sh -c './ext/genint | luajit Dict/dict_lua.lua'\n\n# gprof Dict/dict_cello > Dict/profile.txt\n# rm gmon.out\n\necho \necho \"## Sudoku\"\necho\nprintf \"* C: \"\ngtime -f \"%e\" -f \"%e\" sh -c './ext/sudoku | ./Sudoku/sudoku_c'\nprintf \"* C++: \"\ngtime -f \"%e\" -f \"%e\" sh -c './ext/sudoku | ./Sudoku/sudoku_cpp'\nprintf \"* Cello: \"\ngtime -f \"%e\" -f \"%e\" sh -c './ext/sudoku | ./Sudoku/sudoku_cello'\nprintf \"* Java: \"\ngtime -f \"%e\" -f \"%e\" sh -c './ext/sudoku | java -cp ./Sudoku sudoku_java'\nprintf \"* Javascript: \"\ngtime -f \"%e\" -f \"%e\" sh -c './ext/sudoku | node Sudoku/sudoku_javascript.js'\nprintf \"* Python: \"\ngtime -f \"%e\" -f \"%e\" sh -c './ext/sudoku | python Sudoku/sudoku_python.py'\nprintf \"* Ruby: \"\ngtime -f \"%e\" -f \"%e\" sh -c './ext/sudoku | ruby Sudoku/sudoku_ruby.rb'\nprintf \"* Lua: \"\ngtime -f \"%e\" -f \"%e\" sh -c './ext/sudoku | lua Sudoku/sudoku_lua.lua'\n# printf \"* Lua JIT: \"\n# gtime -f \"%e\" -f \"%e\" sh -c './ext/sudoku | luajit Sudoku/sudoku_lua.lua'\n\n# gprof Sudoku/sudoku_cello > Sudoku/profile.txt\n# rm gmon.out\n\necho \necho \"## Matmul\"\necho\nprintf \"* C: \"\ngtime -f \"%e\" -f \"%e\" ./Matmul/matmul_c\nprintf \"* C++: \"\ngtime -f \"%e\" -f \"%e\" ./Matmul/matmul_cpp\nprintf \"* Cello: \"\ngtime -f \"%e\" -f \"%e\" ./Matmul/matmul_cello\nprintf \"* Java: \"\ngtime -f \"%e\" -f \"%e\" java -cp ./Matmul matmul_java\nprintf \"* Javascript: \"\ngtime -f \"%e\" -f \"%e\" node Matmul/matmul_javascript.js\nprintf \"* Python: \"\ngtime -f \"%e\" -f \"%e\" python Matmul/matmul_python.py\nprintf \"* Ruby: \"\ngtime -f \"%e\" -f \"%e\" ruby Matmul/matmul_ruby.rb\nprintf \"* Lua: \"\ngtime -f \"%e\" -f \"%e\" lua Matmul/matmul_lua.lua\n# printf \"* Lua JIT: \"\n# gtime -f \"%e\" -f \"%e\" luajit Matmul/matmul_lua.lua\n\n# gprof Matmul/matmul_cello > Matmul/profile.txt\n# rm gmon.out\n\n"
  },
  {
    "path": "benchmarks/ext/cleantxt.c",
    "content": "#include <stdio.h>\n#include <string.h>\n#include <ctype.h>\n\nint main(int argc, char *argv[])\n{\n\tFILE *fp;\n\tint c = EOF;\n\tif (argc == 1) {\n\t\tfprintf(stderr, \"Usage: cleantxt <file>\\n\");\n\t\treturn 1;\n\t}\n\tfp = strcmp(argv[1], \"-\")? fopen(argv[1], \"rb\") : stdin;\n\tif (fp == 0) {\n\t\tfprintf(stderr, \"ERROR: fail to open the input file.\\n\");\n\t\treturn 1;\n\t}\n\twhile (!feof(fp)) {\n\t\tc = fgetc(fp);\n\t\tif (isgraph(c) || c == '\\t' || c == '\\n' || c == ' ')\n\t\t\tfputc(c, stdout);\n\t}\n\tif (c != '\\n') fputc('\\n', stdout);\n\tfclose(fp);\n\treturn 0;\n}\n"
  },
  {
    "path": "benchmarks/ext/genint.c",
    "content": "/* This program generates 5 million recurrent integers. Each distinct integer\n * occurs 4 times in average.\n */\n#include <stdio.h>\n#include <stdlib.h>\n\nint main(int argc, char *argv[])\n{\n\tint i, n = 500000; // by default, output 5 million integers\n\tif (argc > 1) n = atoi(argv[1]);\n\tsrand(11);\n\tfor (i = 0; i < n; ++i)\n\t\tprintf(\"%u\\n\", (unsigned)((rand() % (n/4))  * 271828183u)); // 4 times in average\n\treturn 0;\n}\n"
  },
  {
    "path": "benchmarks/ext/kbtree.h",
    "content": "/*-\n * Copyright 1997-1999, 2001, John-Mark Gurney.\n *           2008-2009, Attractive Chaos <attractor@live.co.uk>\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n */\n\n#ifndef __AC_KBTREE_H\n#define __AC_KBTREE_H\n\n#include <stdlib.h>\n#include <string.h>\n#include <stdint.h>\n\ntypedef struct {\n\tint32_t is_internal:1, n:31;\n} kbnode_t;\n\n#define\t__KB_KEY(type, x)\t((type*)((char*)x + 4))\n#define __KB_PTR(btr, x)\t((kbnode_t**)((char*)x + btr->off_ptr))\n\n#define __KB_TREE_T(name)\t\t\t\t\t\t\\\n\ttypedef struct {\t\t\t\t\t\t\t\\\n\t\tkbnode_t *root;\t\t\t\t\t\t\t\\\n\t\tint\toff_key, off_ptr, ilen, elen;\t\t\\\n\t\tint\tn, t;\t\t\t\t\t\t\t\t\\\n\t\tint\tn_keys, n_nodes;\t\t\t\t\t\\\n\t} kbtree_##name##_t;\n\n#define __KB_INIT(name, key_t)\t\t\t\t\t\t\t\t\t\t\t\\\n\tkbtree_##name##_t *kb_init_##name(int size)\t\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tkbtree_##name##_t *b;\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tb = (kbtree_##name##_t*)calloc(1, sizeof(kbtree_##name##_t));\t\\\n\t\tb->t = ((size - 4 - sizeof(void*)) / (sizeof(void*) + sizeof(key_t)) + 1) >> 1; \\\n\t\tif (b->t < 2) {\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tfree(b); return 0;\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tb->n = 2 * b->t - 1;\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tb->off_ptr = 4 + b->n * sizeof(key_t);\t\t\t\t\t\t\t\\\n\t\tb->ilen = (4 + sizeof(void*) + b->n * (sizeof(void*) + sizeof(key_t)) + 3) >> 2 << 2; \\\n\t\tb->elen = (b->off_ptr + 3) >> 2 << 2;\t\t\t\t\t\t\t\\\n\t\tb->root = (kbnode_t*)calloc(1, b->ilen);\t\t\t\t\t\t\\\n\t\t++b->n_nodes;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\treturn b;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t}\n\n#define __kb_destroy(b) do {\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tint i, max = 8;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tkbnode_t *x, **top, **stack = 0;\t\t\t\t\t\t\t\t\\\n\t\tif (b) {\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\ttop = stack = (kbnode_t**)calloc(max, sizeof(kbnode_t*));\t\\\n\t\t\t*top++ = (b)->root;\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\twhile (top != stack) {\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tx = *--top;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tif (x->is_internal == 0) { free(x); continue; }\t\t\t\\\n\t\t\t\tfor (i = 0; i <= x->n; ++i)\t\t\t\t\t\t\t\t\\\n\t\t\t\t\tif (__KB_PTR(b, x)[i]) {\t\t\t\t\t\t\t\\\n\t\t\t\t\t\tif (top - stack == max) {\t\t\t\t\t\t\\\n\t\t\t\t\t\t\tmax <<= 1;\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\tstack = (kbnode_t**)realloc(stack, max * sizeof(kbnode_t*)); \\\n\t\t\t\t\t\t\ttop = stack + (max>>1);\t\t\t\t\t\t\\\n\t\t\t\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t*top++ = __KB_PTR(b, x)[i];\t\t\t\t\t\t\\\n\t\t\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tfree(x);\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tfree(b); free(stack);\t\t\t\t\t\t\t\t\t\t\t\\\n\t} while (0)\n\n#define __kb_get_first(key_t, b, ret) do {\t\\\n\t\tkbnode_t *__x = (b)->root;\t\t\t\\\n\t\twhile (__KB_PTR(b, __x)[0] != 0)\t\\\n\t\t\t__x = __KB_PTR(b, __x)[0];\t\t\\\n\t\t(ret) = __KB_KEY(key_t, __x)[0];\t\\\n\t} while (0)\n\n#define __KB_GET_AUX0(name, key_t, __cmp)\t\t\t\t\t\t\t\t\\\n\tstatic inline int __kb_get_aux_##name(const kbnode_t * __restrict x, const key_t * __restrict k, int *r) \\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tint tr, *rr, begin, end, n = x->n >> 1;\t\t\t\t\t\t\t\\\n\t\tif (x->n == 0) return -1;\t\t\t\t\t\t\t\t\t\t\\\n\t\tif (__cmp(*k, __KB_KEY(key_t, x)[n]) < 0) {\t\t\t\t\t\t\\\n\t\t\tbegin = 0; end = n;\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t} else { begin = n; end = x->n - 1; }\t\t\t\t\t\t\t\\\n\t\trr = r? r : &tr;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tn = end;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\twhile (n >= begin && (*rr = __cmp(*k, __KB_KEY(key_t, x)[n])) < 0) --n; \\\n\t\treturn n;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t}\n\n#define __KB_GET_AUX1(name, key_t, __cmp)\t\t\t\t\t\t\t\t\\\n\tstatic inline int __kb_getp_aux_##name(const kbnode_t * __restrict x, const key_t * __restrict k, int *r) \\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tint tr, *rr, begin = 0, end = x->n;\t\t\t\t\t\t\t\t\\\n\t\tif (x->n == 0) return -1;\t\t\t\t\t\t\t\t\t\t\\\n\t\trr = r? r : &tr;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\twhile (begin < end) {\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tint mid = (begin + end) >> 1;\t\t\t\t\t\t\t\t\\\n\t\t\tif (__cmp(__KB_KEY(key_t, x)[mid], *k) < 0) begin = mid + 1; \\\n\t\t\telse end = mid;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif (begin == x->n) { *rr = 1; return x->n - 1; }\t\t\t\t\\\n\t\tif ((*rr = __cmp(*k, __KB_KEY(key_t, x)[begin])) < 0) --begin;\t\\\n\t\treturn begin;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t}\n\n#define __KB_GET(name, key_t)\t\t\t\t\t\t\t\t\t\t\t\\\n\tstatic key_t *kb_getp_##name(kbtree_##name##_t *b, const key_t * __restrict k) \\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tint i, r = 0;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tkbnode_t *x = b->root;\t\t\t\t\t\t\t\t\t\t\t\\\n\t\twhile (x) {\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\ti = __kb_getp_aux_##name(x, k, &r);\t\t\t\t\t\t\t\\\n\t\t\tif (i >= 0 && r == 0) return &__KB_KEY(key_t, x)[i];\t\t\\\n\t\t\tif (x->is_internal == 0) return 0;\t\t\t\t\t\t\t\\\n\t\t\tx = __KB_PTR(b, x)[i + 1];\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\treturn 0;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tstatic inline key_t *kb_get_##name(kbtree_##name##_t *b, const key_t k) \\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\treturn kb_getp_##name(b, &k);\t\t\t\t\t\t\t\t\t\\\n\t}\n\n#define __KB_INTERVAL(name, key_t)\t\t\t\t\t\t\t\t\t\t\\\n\tstatic void kb_intervalp_##name(kbtree_##name##_t *b, const key_t * __restrict k, key_t **lower, key_t **upper)\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tint i, r = 0;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tkbnode_t *x = b->root;\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t*lower = *upper = 0;\t\t\t\t\t\t\t\t\t\t\t\\\n\t\twhile (x) {\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\ti = __kb_getp_aux_##name(x, k, &r);\t\t\t\t\t\t\t\\\n\t\t\tif (i >= 0 && r == 0) {\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t*lower = *upper = &__KB_KEY(key_t, x)[i];\t\t\t\t\\\n\t\t\t\treturn;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tif (i >= 0) *lower = &__KB_KEY(key_t, x)[i];\t\t\t\t\\\n\t\t\tif (i < x->n - 1) *upper = &__KB_KEY(key_t, x)[i + 1];\t\t\\\n\t\t\tif (x->is_internal == 0) return;\t\t\t\t\t\t\t\\\n\t\t\tx = __KB_PTR(b, x)[i + 1];\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tstatic inline void kb_interval_##name(kbtree_##name##_t *b, const key_t k, key_t **lower, key_t **upper) \\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tkb_intervalp_##name(b, &k, lower, upper);\t\t\t\t\t\t\\\n\t}\n\n#define __KB_PUT(name, key_t, __cmp)\t\t\t\t\t\t\t\t\t\\\n\t/* x must be an internal node */\t\t\t\t\t\t\t\t\t\\\n\tstatic void __kb_split_##name(kbtree_##name##_t *b, kbnode_t *x, int i, kbnode_t *y) \\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tkbnode_t *z;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tz = (kbnode_t*)calloc(1, y->is_internal? b->ilen : b->elen);\t\\\n\t\t++b->n_nodes;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tz->is_internal = y->is_internal;\t\t\t\t\t\t\t\t\\\n\t\tz->n = b->t - 1;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tmemcpy(__KB_KEY(key_t, z), __KB_KEY(key_t, y) + b->t, sizeof(key_t) * (b->t - 1)); \\\n\t\tif (y->is_internal) memcpy(__KB_PTR(b, z), __KB_PTR(b, y) + b->t, sizeof(void*) * b->t); \\\n\t\ty->n = b->t - 1;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tmemmove(__KB_PTR(b, x) + i + 2, __KB_PTR(b, x) + i + 1, sizeof(void*) * (x->n - i)); \\\n\t\t__KB_PTR(b, x)[i + 1] = z;\t\t\t\t\t\t\t\t\t\t\\\n\t\tmemmove(__KB_KEY(key_t, x) + i + 1, __KB_KEY(key_t, x) + i, sizeof(key_t) * (x->n - i)); \\\n\t\t__KB_KEY(key_t, x)[i] = __KB_KEY(key_t, y)[b->t - 1];\t\t\t\\\n\t\t++x->n;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tstatic void __kb_putp_aux_##name(kbtree_##name##_t *b, kbnode_t *x, const key_t * __restrict k) \\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tint i = x->n - 1;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif (x->is_internal == 0) {\t\t\t\t\t\t\t\t\t\t\\\n\t\t\ti = __kb_getp_aux_##name(x, k, 0);\t\t\t\t\t\t\t\\\n\t\t\tif (i != x->n - 1)\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tmemmove(__KB_KEY(key_t, x) + i + 2, __KB_KEY(key_t, x) + i + 1, (x->n - i - 1) * sizeof(key_t)); \\\n\t\t\t__KB_KEY(key_t, x)[i + 1] = *k;\t\t\t\t\t\t\t\t\\\n\t\t\t++x->n;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\ti = __kb_getp_aux_##name(x, k, 0) + 1;\t\t\t\t\t\t\\\n\t\t\tif (__KB_PTR(b, x)[i]->n == 2 * b->t - 1) {\t\t\t\t\t\\\n\t\t\t\t__kb_split_##name(b, x, i, __KB_PTR(b, x)[i]);\t\t\t\\\n\t\t\t\tif (__cmp(*k, __KB_KEY(key_t, x)[i]) > 0) ++i;\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t__kb_putp_aux_##name(b, __KB_PTR(b, x)[i], k);\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tstatic void kb_putp_##name(kbtree_##name##_t *b, const key_t * __restrict k) \\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tkbnode_t *r, *s;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t++b->n_keys;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tr = b->root;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif (r->n == 2 * b->t - 1) {\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t++b->n_nodes;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\ts = (kbnode_t*)calloc(1, b->ilen);\t\t\t\t\t\t\t\\\n\t\t\tb->root = s; s->is_internal = 1; s->n = 0;\t\t\t\t\t\\\n\t\t\t__KB_PTR(b, s)[0] = r;\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t__kb_split_##name(b, s, 0, r);\t\t\t\t\t\t\t\t\\\n\t\t\tr = s;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t__kb_putp_aux_##name(b, r, k);\t\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tstatic inline void kb_put_##name(kbtree_##name##_t *b, const key_t k) \\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tkb_putp_##name(b, &k);\t\t\t\t\t\t\t\t\t\t\t\\\n\t}\n\n\n#define __KB_DEL(name, key_t)\t\t\t\t\t\t\t\t\t\t\t\\\n\tstatic key_t __kb_delp_aux_##name(kbtree_##name##_t *b, kbnode_t *x, const key_t * __restrict k, int s) \\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tint yn, zn, i, r = 0;\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tkbnode_t *xp, *y, *z;\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tkey_t kp;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif (x == 0) return *k;\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif (s) { /* s can only be 0, 1 or 2 */\t\t\t\t\t\t\t\\\n\t\t\tr = x->is_internal == 0? 0 : s == 1? 1 : -1;\t\t\t\t\\\n\t\t\ti = s == 1? x->n - 1 : -1;\t\t\t\t\t\t\t\t\t\\\n\t\t} else i = __kb_getp_aux_##name(x, k, &r);\t\t\t\t\t\t\\\n\t\tif (x->is_internal == 0) {\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tif (s == 2) ++i;\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tkp = __KB_KEY(key_t, x)[i];\t\t\t\t\t\t\t\t\t\\\n\t\t\tmemmove(__KB_KEY(key_t, x) + i, __KB_KEY(key_t, x) + i + 1, (x->n - i - 1) * sizeof(key_t)); \\\n\t\t\t--x->n;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\treturn kp;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif (r == 0) {\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tif ((yn = __KB_PTR(b, x)[i]->n) >= b->t) {\t\t\t\t\t\\\n\t\t\t\txp = __KB_PTR(b, x)[i];\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tkp = __KB_KEY(key_t, x)[i];\t\t\t\t\t\t\t\t\\\n\t\t\t\t__KB_KEY(key_t, x)[i] = __kb_delp_aux_##name(b, xp, 0, 1); \\\n\t\t\t\treturn kp;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t} else if ((zn = __KB_PTR(b, x)[i + 1]->n) >= b->t) {\t\t\\\n\t\t\t\txp = __KB_PTR(b, x)[i + 1];\t\t\t\t\t\t\t\t\\\n\t\t\t\tkp = __KB_KEY(key_t, x)[i];\t\t\t\t\t\t\t\t\\\n\t\t\t\t__KB_KEY(key_t, x)[i] = __kb_delp_aux_##name(b, xp, 0, 2); \\\n\t\t\t\treturn kp;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t} else if (yn == b->t - 1 && zn == b->t - 1) {\t\t\t\t\\\n\t\t\t\ty = __KB_PTR(b, x)[i]; z = __KB_PTR(b, x)[i + 1];\t\t\\\n\t\t\t\t__KB_KEY(key_t, y)[y->n++] = *k;\t\t\t\t\t\t\\\n\t\t\t\tmemmove(__KB_KEY(key_t, y) + y->n, __KB_KEY(key_t, z), z->n * sizeof(key_t)); \\\n\t\t\t\tif (y->is_internal) memmove(__KB_PTR(b, y) + y->n, __KB_PTR(b, z), (z->n + 1) * sizeof(void*)); \\\n\t\t\t\ty->n += z->n;\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tmemmove(__KB_KEY(key_t, x) + i, __KB_KEY(key_t, x) + i + 1, (x->n - i - 1) * sizeof(key_t)); \\\n\t\t\t\tmemmove(__KB_PTR(b, x) + i + 1, __KB_PTR(b, x) + i + 2, (x->n - i - 1) * sizeof(void*)); \\\n\t\t\t\t--x->n;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tfree(z);\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\treturn __kb_delp_aux_##name(b, y, k, s);\t\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t++i;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif ((xp = __KB_PTR(b, x)[i])->n == b->t - 1) {\t\t\t\t\t\\\n\t\t\tif (i > 0 && (y = __KB_PTR(b, x)[i - 1])->n >= b->t) {\t\t\\\n\t\t\t\tmemmove(__KB_KEY(key_t, xp) + 1, __KB_KEY(key_t, xp), xp->n * sizeof(key_t)); \\\n\t\t\t\tif (xp->is_internal) memmove(__KB_PTR(b, xp) + 1, __KB_PTR(b, xp), (xp->n + 1) * sizeof(void*)); \\\n\t\t\t\t__KB_KEY(key_t, xp)[0] = __KB_KEY(key_t, x)[i - 1];\t\t\\\n\t\t\t\t__KB_KEY(key_t, x)[i - 1] = __KB_KEY(key_t, y)[y->n - 1]; \\\n\t\t\t\tif (xp->is_internal) __KB_PTR(b, xp)[0] = __KB_PTR(b, y)[y->n]; \\\n\t\t\t\t--y->n; ++xp->n;\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t} else if (i < x->n && (y = __KB_PTR(b, x)[i + 1])->n >= b->t) { \\\n\t\t\t\t__KB_KEY(key_t, xp)[xp->n++] = __KB_KEY(key_t, x)[i];\t\\\n\t\t\t\t__KB_KEY(key_t, x)[i] = __KB_KEY(key_t, y)[0];\t\t\t\\\n\t\t\t\tif (xp->is_internal) __KB_PTR(b, xp)[xp->n] = __KB_PTR(b, y)[0]; \\\n\t\t\t\t--y->n;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tmemmove(__KB_KEY(key_t, y), __KB_KEY(key_t, y) + 1, y->n * sizeof(key_t)); \\\n\t\t\t\tif (y->is_internal) memmove(__KB_PTR(b, y), __KB_PTR(b, y) + 1, (y->n + 1) * sizeof(void*)); \\\n\t\t\t} else if (i > 0 && (y = __KB_PTR(b, x)[i - 1])->n == b->t - 1) { \\\n\t\t\t\t__KB_KEY(key_t, y)[y->n++] = __KB_KEY(key_t, x)[i - 1];\t\\\n\t\t\t\tmemmove(__KB_KEY(key_t, y) + y->n, __KB_KEY(key_t, xp), xp->n * sizeof(key_t));\t\\\n\t\t\t\tif (y->is_internal) memmove(__KB_PTR(b, y) + y->n, __KB_PTR(b, xp), (xp->n + 1) * sizeof(void*)); \\\n\t\t\t\ty->n += xp->n;\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tmemmove(__KB_KEY(key_t, x) + i - 1, __KB_KEY(key_t, x) + i, (x->n - i) * sizeof(key_t)); \\\n\t\t\t\tmemmove(__KB_PTR(b, x) + i, __KB_PTR(b, x) + i + 1, (x->n - i) * sizeof(void*)); \\\n\t\t\t\t--x->n;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tfree(xp);\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\txp = y;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t} else if (i < x->n && (y = __KB_PTR(b, x)[i + 1])->n == b->t - 1) { \\\n\t\t\t\t__KB_KEY(key_t, xp)[xp->n++] = __KB_KEY(key_t, x)[i];\t\\\n\t\t\t\tmemmove(__KB_KEY(key_t, xp) + xp->n, __KB_KEY(key_t, y), y->n * sizeof(key_t));\t\\\n\t\t\t\tif (xp->is_internal) memmove(__KB_PTR(b, xp) + xp->n, __KB_PTR(b, y), (y->n + 1) * sizeof(void*)); \\\n\t\t\t\txp->n += y->n;\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tmemmove(__KB_KEY(key_t, x) + i, __KB_KEY(key_t, x) + i + 1, (x->n - i - 1) * sizeof(key_t)); \\\n\t\t\t\tmemmove(__KB_PTR(b, x) + i + 1, __KB_PTR(b, x) + i + 2, (x->n - i - 1) * sizeof(void*)); \\\n\t\t\t\t--x->n;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tfree(y);\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\treturn __kb_delp_aux_##name(b, xp, k, s);\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tstatic key_t kb_delp_##name(kbtree_##name##_t *b, const key_t * __restrict k) \\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tkbnode_t *x;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tkey_t ret;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tret = __kb_delp_aux_##name(b, b->root, k, 0);\t\t\t\t\t\\\n\t\t--b->n_keys;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif (b->root->n == 0 && b->root->is_internal) {\t\t\t\t\t\\\n\t\t\t--b->n_nodes;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tx = b->root;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tb->root = __KB_PTR(b, x)[0];\t\t\t\t\t\t\t\t\\\n\t\t\tfree(x);\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\treturn ret;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tstatic inline key_t kb_del_##name(kbtree_##name##_t *b, const key_t k) \\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\treturn kb_delp_##name(b, &k);\t\t\t\t\t\t\t\t\t\\\n\t}\n\ntypedef struct {\n\tkbnode_t *x;\n\tint i;\n} __kbstack_t;\n\n#define __kb_traverse(key_t, b, __func) do {\t\t\t\t\t\t\t\\\n\t\tint __kmax = 8;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t__kbstack_t *__kstack, *__kp;\t\t\t\t\t\t\t\t\t\\\n\t\t__kp = __kstack = (__kbstack_t*)calloc(__kmax, sizeof(__kbstack_t)); \\\n\t\t__kp->x = (b)->root; __kp->i = 0;\t\t\t\t\t\t\t\t\\\n\t\tfor (;;) {\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\twhile (__kp->x && __kp->i <= __kp->x->n) {\t\t\t\t\t\\\n\t\t\t\tif (__kp - __kstack == __kmax - 1) {\t\t\t\t\t\\\n\t\t\t\t\t__kmax <<= 1;\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t__kstack = (__kbstack_t*)realloc(__kstack, __kmax * sizeof(__kbstack_t)); \\\n\t\t\t\t\t__kp = __kstack + (__kmax>>1) - 1;\t\t\t\t\t\\\n\t\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t(__kp+1)->i = 0; (__kp+1)->x = __kp->x->is_internal? __KB_PTR(b, __kp->x)[__kp->i] : 0; \\\n\t\t\t\t++__kp;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t--__kp;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tif (__kp >= __kstack) {\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tif (__kp->x && __kp->i < __kp->x->n) __func(&__KB_KEY(key_t, __kp->x)[__kp->i]); \\\n\t\t\t\t++__kp->i;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t} else break;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tfree(__kstack);\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t} while (0)\n\n#define KBTREE_INIT(name, key_t, __cmp)\t\t\t\\\n\t__KB_TREE_T(name)\t\t\t\t\t\t\t\\\n\t__KB_INIT(name, key_t)\t\t\t\t\t\t\\\n\t__KB_GET_AUX1(name, key_t, __cmp)\t\t\t\\\n\t__KB_GET(name, key_t)\t\t\t\t\t\t\\\n\t__KB_INTERVAL(name, key_t)\t\t\t\t\t\\\n\t__KB_PUT(name, key_t, __cmp)\t\t\t\t\\\n\t__KB_DEL(name, key_t)\n\n#define KB_DEFAULT_SIZE 512\n\n#define kbtree_t(name) kbtree_##name##_t\n#define kb_init(name, s) kb_init_##name(s)\n#define kb_destroy(name, b) __kb_destroy(b)\n#define kb_get(name, b, k) kb_get_##name(b, k)\n#define kb_put(name, b, k) kb_put_##name(b, k)\n#define kb_del(name, b, k) kb_del_##name(b, k)\n#define kb_interval(name, b, k, l, u) kb_interval_##name(b, k, l, u)\n#define kb_getp(name, b, k) kb_getp_##name(b, k)\n#define kb_putp(name, b, k) kb_putp_##name(b, k)\n#define kb_delp(name, b, k) kb_delp_##name(b, k)\n#define kb_intervalp(name, b, k, l, u) kb_intervalp_##name(b, k, l, u)\n\n#define kb_size(b) ((b)->n_keys)\n\n#define kb_generic_cmp(a, b) (((b) < (a)) - ((a) < (b)))\n#define kb_str_cmp(a, b) strcmp(a, b)\n\n#endif\n"
  },
  {
    "path": "benchmarks/ext/khash.h",
    "content": "/* The MIT License\n\n   Copyright (c) 2008, 2009, 2011 by Attractive Chaos <attractor@live.co.uk>\n\n   Permission is hereby granted, free of charge, to any person obtaining\n   a copy of this software and associated documentation files (the\n   \"Software\"), to deal in the Software without restriction, including\n   without limitation the rights to use, copy, modify, merge, publish,\n   distribute, sublicense, and/or sell copies of the Software, and to\n   permit persons to whom the Software is furnished to do so, subject to\n   the following conditions:\n\n   The above copyright notice and this permission notice shall be\n   included in all copies or substantial portions of the Software.\n\n   THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n   BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n   ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n   SOFTWARE.\n*/\n\n/*\n  An example:\n\n#include \"khash.h\"\nKHASH_MAP_INIT_INT(32, char)\nint main() {\n\tint ret, is_missing;\n\tkhiter_t k;\n\tkhash_t(32) *h = kh_init(32);\n\tk = kh_put(32, h, 5, &ret);\n\tif (!ret) kh_del(32, h, k);\n\tkh_value(h, k) = 10;\n\tk = kh_get(32, h, 10);\n\tis_missing = (k == kh_end(h));\n\tk = kh_get(32, h, 5);\n\tkh_del(32, h, k);\n\tfor (k = kh_begin(h); k != kh_end(h); ++k)\n\t\tif (kh_exist(h, k)) kh_value(h, k) = 1;\n\tkh_destroy(32, h);\n\treturn 0;\n}\n*/\n\n/*\n  2011-02-14 (0.2.5):\n\n    * Allow to declare global functions.\n\n  2009-09-26 (0.2.4):\n\n    * Improve portability\n\n  2008-09-19 (0.2.3):\n\n\t* Corrected the example\n\t* Improved interfaces\n\n  2008-09-11 (0.2.2):\n\n\t* Improved speed a little in kh_put()\n\n  2008-09-10 (0.2.1):\n\n\t* Added kh_clear()\n\t* Fixed a compiling error\n\n  2008-09-02 (0.2.0):\n\n\t* Changed to token concatenation which increases flexibility.\n\n  2008-08-31 (0.1.2):\n\n\t* Fixed a bug in kh_get(), which has not been tested previously.\n\n  2008-08-31 (0.1.1):\n\n\t* Added destructor\n*/\n\n\n#ifndef __AC_KHASH_H\n#define __AC_KHASH_H\n\n/*!\n  @header\n\n  Generic hash table library.\n\n  @copyright Heng Li\n */\n\n#define AC_VERSION_KHASH_H \"0.2.5\"\n\n#include <stdlib.h>\n#include <string.h>\n#include <limits.h>\n\n/* compipler specific configuration */\n\n#if UINT_MAX == 0xffffffffu\ntypedef unsigned int khint32_t;\n#elif ULONG_MAX == 0xffffffffu\ntypedef unsigned long khint32_t;\n#endif\n\n#if ULONG_MAX == ULLONG_MAX\ntypedef unsigned long khint64_t;\n#else\ntypedef unsigned long long khint64_t;\n#endif\n\n#ifdef _MSC_VER\n#define inline __inline\n#endif\n\ntypedef khint32_t khint_t;\ntypedef khint_t khiter_t;\n\n#define __ac_HASH_PRIME_SIZE 32\nstatic const khint32_t __ac_prime_list[__ac_HASH_PRIME_SIZE] =\n{\n  0ul,          3ul,          11ul,         23ul,         53ul,\n  97ul,         193ul,        389ul,        769ul,        1543ul,\n  3079ul,       6151ul,       12289ul,      24593ul,      49157ul,\n  98317ul,      196613ul,     393241ul,     786433ul,     1572869ul,\n  3145739ul,    6291469ul,    12582917ul,   25165843ul,   50331653ul,\n  100663319ul,  201326611ul,  402653189ul,  805306457ul,  1610612741ul,\n  3221225473ul, 4294967291ul\n};\n\n#define __ac_isempty(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&2)\n#define __ac_isdel(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&1)\n#define __ac_iseither(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&3)\n#define __ac_set_isdel_false(flag, i) (flag[i>>4]&=~(1ul<<((i&0xfU)<<1)))\n#define __ac_set_isempty_false(flag, i) (flag[i>>4]&=~(2ul<<((i&0xfU)<<1)))\n#define __ac_set_isboth_false(flag, i) (flag[i>>4]&=~(3ul<<((i&0xfU)<<1)))\n#define __ac_set_isdel_true(flag, i) (flag[i>>4]|=1ul<<((i&0xfU)<<1))\n\nstatic const double __ac_HASH_UPPER = 0.77;\n\n#define KHASH_DECLARE(name, khkey_t, khval_t)\t\t \t\t\t\t\t\\\n\ttypedef struct {\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tkhint_t n_buckets, size, n_occupied, upper_bound;\t\t\t\t\\\n\t\tkhint32_t *flags;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tkhkey_t *keys;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tkhval_t *vals;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t} kh_##name##_t;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\textern kh_##name##_t *kh_init_##name();\t\t\t\t\t\t\t\t\\\n\textern void kh_destroy_##name(kh_##name##_t *h);\t\t\t\t\t\\\n\textern void kh_clear_##name(kh_##name##_t *h);\t\t\t\t\t\t\\\n\textern khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key); \t\\\n\textern void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets); \\\n\textern khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret); \\\n\textern void kh_del_##name(kh_##name##_t *h, khint_t x);\n\n#define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \\\n\ttypedef struct {\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tkhint_t n_buckets, size, n_occupied, upper_bound;\t\t\t\t\\\n\t\tkhint32_t *flags;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tkhkey_t *keys;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tkhval_t *vals;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t} kh_##name##_t;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tSCOPE kh_##name##_t *kh_init_##name() {\t\t\t\t\t\t\t\t\\\n\t\treturn (kh_##name##_t*)calloc(1, sizeof(kh_##name##_t));\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tSCOPE void kh_destroy_##name(kh_##name##_t *h)\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif (h) {\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tfree(h->keys); free(h->flags);\t\t\t\t\t\t\t\t\\\n\t\t\tfree(h->vals);\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tfree(h);\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tSCOPE void kh_clear_##name(kh_##name##_t *h)\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif (h && h->flags) {\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tmemset(h->flags, 0xaa, ((h->n_buckets>>4) + 1) * sizeof(khint32_t)); \\\n\t\t\th->size = h->n_occupied = 0;\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tSCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) \t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif (h->n_buckets) {\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tkhint_t inc, k, i, last;\t\t\t\t\t\t\t\t\t\\\n\t\t\tk = __hash_func(key); i = k % h->n_buckets;\t\t\t\t\t\\\n\t\t\tinc = 1 + k % (h->n_buckets - 1); last = i;\t\t\t\t\t\\\n\t\t\twhile (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \\\n\t\t\t\tif (i + inc >= h->n_buckets) i = i + inc - h->n_buckets; \\\n\t\t\t\telse i += inc;\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tif (i == last) return h->n_buckets;\t\t\t\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\treturn __ac_iseither(h->flags, i)? h->n_buckets : i;\t\t\\\n\t\t} else return 0;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tSCOPE void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tkhint32_t *new_flags = 0;\t\t\t\t\t\t\t\t\t\t\\\n\t\tkhint_t j = 1;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tkhint_t t = __ac_HASH_PRIME_SIZE - 1;\t\t\t\t\t\t\\\n\t\t\twhile (__ac_prime_list[t] > new_n_buckets) --t;\t\t\t\t\\\n\t\t\tnew_n_buckets = __ac_prime_list[t+1];\t\t\t\t\t\t\\\n\t\t\tif (h->size >= (khint_t)(new_n_buckets * __ac_HASH_UPPER + 0.5)) j = 0;\t\\\n\t\t\telse {\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tnew_flags = (khint32_t*)malloc(((new_n_buckets>>4) + 1) * sizeof(khint32_t));\t\\\n\t\t\t\tmemset(new_flags, 0xaa, ((new_n_buckets>>4) + 1) * sizeof(khint32_t)); \\\n\t\t\t\tif (h->n_buckets < new_n_buckets) {\t\t\t\t\t\t\\\n\t\t\t\t\th->keys = (khkey_t*)realloc(h->keys, new_n_buckets * sizeof(khkey_t)); \\\n\t\t\t\t\tif (kh_is_map)\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\th->vals = (khval_t*)realloc(h->vals, new_n_buckets * sizeof(khval_t)); \\\n\t\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif (j) {\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tfor (j = 0; j != h->n_buckets; ++j) {\t\t\t\t\t\t\\\n\t\t\t\tif (__ac_iseither(h->flags, j) == 0) {\t\t\t\t\t\\\n\t\t\t\t\tkhkey_t key = h->keys[j];\t\t\t\t\t\t\t\\\n\t\t\t\t\tkhval_t val;\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\tif (kh_is_map) val = h->vals[j];\t\t\t\t\t\\\n\t\t\t\t\t__ac_set_isdel_true(h->flags, j);\t\t\t\t\t\\\n\t\t\t\t\twhile (1) {\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\tkhint_t inc, k, i;\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\tk = __hash_func(key);\t\t\t\t\t\t\t\\\n\t\t\t\t\t\ti = k % new_n_buckets;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\tinc = 1 + k % (new_n_buckets - 1);\t\t\t\t\\\n\t\t\t\t\t\twhile (!__ac_isempty(new_flags, i)) {\t\t\t\\\n\t\t\t\t\t\t\tif (i + inc >= new_n_buckets) i = i + inc - new_n_buckets; \\\n\t\t\t\t\t\t\telse i += inc;\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t__ac_set_isempty_false(new_flags, i);\t\t\t\\\n\t\t\t\t\t\tif (i < h->n_buckets && __ac_iseither(h->flags, i) == 0) { \\\n\t\t\t\t\t\t\t{ khkey_t tmp = h->keys[i]; h->keys[i] = key; key = tmp; } \\\n\t\t\t\t\t\t\tif (kh_is_map) { khval_t tmp = h->vals[i]; h->vals[i] = val; val = tmp; } \\\n\t\t\t\t\t\t\t__ac_set_isdel_true(h->flags, i);\t\t\t\\\n\t\t\t\t\t\t} else {\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\th->keys[i] = key;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\tif (kh_is_map) h->vals[i] = val;\t\t\t\\\n\t\t\t\t\t\t\tbreak;\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tif (h->n_buckets > new_n_buckets) {\t\t\t\t\t\t\t\\\n\t\t\t\th->keys = (khkey_t*)realloc(h->keys, new_n_buckets * sizeof(khkey_t)); \\\n\t\t\t\tif (kh_is_map)\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\th->vals = (khval_t*)realloc(h->vals, new_n_buckets * sizeof(khval_t)); \\\n\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tfree(h->flags);\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\th->flags = new_flags;\t\t\t\t\t\t\t\t\t\t\\\n\t\t\th->n_buckets = new_n_buckets;\t\t\t\t\t\t\t\t\\\n\t\t\th->n_occupied = h->size;\t\t\t\t\t\t\t\t\t\\\n\t\t\th->upper_bound = (khint_t)(h->n_buckets * __ac_HASH_UPPER + 0.5); \\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tSCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) \\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tkhint_t x;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif (h->n_occupied >= h->upper_bound) {\t\t\t\t\t\t\t\\\n\t\t\tif (h->n_buckets > (h->size<<1)) kh_resize_##name(h, h->n_buckets - 1); \\\n\t\t\telse kh_resize_##name(h, h->n_buckets + 1);\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tkhint_t inc, k, i, site, last;\t\t\t\t\t\t\t\t\\\n\t\t\tx = site = h->n_buckets; k = __hash_func(key); i = k % h->n_buckets; \\\n\t\t\tif (__ac_isempty(h->flags, i)) x = i;\t\t\t\t\t\t\\\n\t\t\telse {\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tinc = 1 + k % (h->n_buckets - 1); last = i;\t\t\t\t\\\n\t\t\t\twhile (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \\\n\t\t\t\t\tif (__ac_isdel(h->flags, i)) site = i;\t\t\t\t\\\n\t\t\t\t\tif (i + inc >= h->n_buckets) i = i + inc - h->n_buckets; \\\n\t\t\t\t\telse i += inc;\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\tif (i == last) { x = site; break; }\t\t\t\t\t\\\n\t\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tif (x == h->n_buckets) {\t\t\t\t\t\t\t\t\\\n\t\t\t\t\tif (__ac_isempty(h->flags, i) && site != h->n_buckets) x = site; \\\n\t\t\t\t\telse x = i;\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif (__ac_isempty(h->flags, x)) {\t\t\t\t\t\t\t\t\\\n\t\t\th->keys[x] = key;\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t__ac_set_isboth_false(h->flags, x);\t\t\t\t\t\t\t\\\n\t\t\t++h->size; ++h->n_occupied;\t\t\t\t\t\t\t\t\t\\\n\t\t\t*ret = 1;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t} else if (__ac_isdel(h->flags, x)) {\t\t\t\t\t\t\t\\\n\t\t\th->keys[x] = key;\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t__ac_set_isboth_false(h->flags, x);\t\t\t\t\t\t\t\\\n\t\t\t++h->size;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t*ret = 2;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t} else *ret = 0;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\treturn x;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tSCOPE void kh_del_##name(kh_##name##_t *h, khint_t x)\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif (x != h->n_buckets && !__ac_iseither(h->flags, x)) {\t\t\t\\\n\t\t\t__ac_set_isdel_true(h->flags, x);\t\t\t\t\t\t\t\\\n\t\t\t--h->size;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t}\n\n#define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \\\n\tKHASH_INIT2(name, static inline, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal)\n\n/* --- BEGIN OF HASH FUNCTIONS --- */\n\n/*! @function\n  @abstract     Integer hash function\n  @param  key   The integer [khint32_t]\n  @return       The hash value [khint_t]\n */\n#define kh_int_hash_func(key) (khint32_t)(key)\n/*! @function\n  @abstract     Integer comparison function\n */\n#define kh_int_hash_equal(a, b) ((a) == (b))\n/*! @function\n  @abstract     64-bit integer hash function\n  @param  key   The integer [khint64_t]\n  @return       The hash value [khint_t]\n */\n#define kh_int64_hash_func(key) (khint32_t)((key)>>33^(key)^(key)<<11)\n/*! @function\n  @abstract     64-bit integer comparison function\n */\n#define kh_int64_hash_equal(a, b) ((a) == (b))\n/*! @function\n  @abstract     const char* hash function\n  @param  s     Pointer to a null terminated string\n  @return       The hash value\n */\nstatic inline khint_t __ac_X31_hash_string(const char *s)\n{\n\tkhint_t h = *s;\n\tif (h) for (++s ; *s; ++s) h = (h << 5) - h + *s;\n\treturn h;\n}\n/*! @function\n  @abstract     Another interface to const char* hash function\n  @param  key   Pointer to a null terminated string [const char*]\n  @return       The hash value [khint_t]\n */\n#define kh_str_hash_func(key) __ac_X31_hash_string(key)\n/*! @function\n  @abstract     Const char* comparison function\n */\n#define kh_str_hash_equal(a, b) (strcmp(a, b) == 0)\n\n/* --- END OF HASH FUNCTIONS --- */\n\n/* Other necessary macros... */\n\n/*!\n  @abstract Type of the hash table.\n  @param  name  Name of the hash table [symbol]\n */\n#define khash_t(name) kh_##name##_t\n\n/*! @function\n  @abstract     Initiate a hash table.\n  @param  name  Name of the hash table [symbol]\n  @return       Pointer to the hash table [khash_t(name)*]\n */\n#define kh_init(name) kh_init_##name()\n\n/*! @function\n  @abstract     Destroy a hash table.\n  @param  name  Name of the hash table [symbol]\n  @param  h     Pointer to the hash table [khash_t(name)*]\n */\n#define kh_destroy(name, h) kh_destroy_##name(h)\n\n/*! @function\n  @abstract     Reset a hash table without deallocating memory.\n  @param  name  Name of the hash table [symbol]\n  @param  h     Pointer to the hash table [khash_t(name)*]\n */\n#define kh_clear(name, h) kh_clear_##name(h)\n\n/*! @function\n  @abstract     Resize a hash table.\n  @param  name  Name of the hash table [symbol]\n  @param  h     Pointer to the hash table [khash_t(name)*]\n  @param  s     New size [khint_t]\n */\n#define kh_resize(name, h, s) kh_resize_##name(h, s)\n\n/*! @function\n  @abstract     Insert a key to the hash table.\n  @param  name  Name of the hash table [symbol]\n  @param  h     Pointer to the hash table [khash_t(name)*]\n  @param  k     Key [type of keys]\n  @param  r     Extra return code: 0 if the key is present in the hash table;\n                1 if the bucket is empty (never used); 2 if the element in\n\t\t\t\tthe bucket has been deleted [int*]\n  @return       Iterator to the inserted element [khint_t]\n */\n#define kh_put(name, h, k, r) kh_put_##name(h, k, r)\n\n/*! @function\n  @abstract     Retrieve a key from the hash table.\n  @param  name  Name of the hash table [symbol]\n  @param  h     Pointer to the hash table [khash_t(name)*]\n  @param  k     Key [type of keys]\n  @return       Iterator to the found element, or kh_end(h) is the element is absent [khint_t]\n */\n#define kh_get(name, h, k) kh_get_##name(h, k)\n\n/*! @function\n  @abstract     Remove a key from the hash table.\n  @param  name  Name of the hash table [symbol]\n  @param  h     Pointer to the hash table [khash_t(name)*]\n  @param  k     Iterator to the element to be deleted [khint_t]\n */\n#define kh_del(name, h, k) kh_del_##name(h, k)\n\n\n/*! @function\n  @abstract     Test whether a bucket contains data.\n  @param  h     Pointer to the hash table [khash_t(name)*]\n  @param  x     Iterator to the bucket [khint_t]\n  @return       1 if containing data; 0 otherwise [int]\n */\n#define kh_exist(h, x) (!__ac_iseither((h)->flags, (x)))\n\n/*! @function\n  @abstract     Get key given an iterator\n  @param  h     Pointer to the hash table [khash_t(name)*]\n  @param  x     Iterator to the bucket [khint_t]\n  @return       Key [type of keys]\n */\n#define kh_key(h, x) ((h)->keys[x])\n\n/*! @function\n  @abstract     Get value given an iterator\n  @param  h     Pointer to the hash table [khash_t(name)*]\n  @param  x     Iterator to the bucket [khint_t]\n  @return       Value [type of values]\n  @discussion   For hash sets, calling this results in segfault.\n */\n#define kh_val(h, x) ((h)->vals[x])\n\n/*! @function\n  @abstract     Alias of kh_val()\n */\n#define kh_value(h, x) ((h)->vals[x])\n\n/*! @function\n  @abstract     Get the start iterator\n  @param  h     Pointer to the hash table [khash_t(name)*]\n  @return       The start iterator [khint_t]\n */\n#define kh_begin(h) (khint_t)(0)\n\n/*! @function\n  @abstract     Get the end iterator\n  @param  h     Pointer to the hash table [khash_t(name)*]\n  @return       The end iterator [khint_t]\n */\n#define kh_end(h) ((h)->n_buckets)\n\n/*! @function\n  @abstract     Get the number of elements in the hash table\n  @param  h     Pointer to the hash table [khash_t(name)*]\n  @return       Number of elements in the hash table [khint_t]\n */\n#define kh_size(h) ((h)->size)\n\n/*! @function\n  @abstract     Get the number of buckets in the hash table\n  @param  h     Pointer to the hash table [khash_t(name)*]\n  @return       Number of buckets in the hash table [khint_t]\n */\n#define kh_n_buckets(h) ((h)->n_buckets)\n\n/* More conenient interfaces */\n\n/*! @function\n  @abstract     Instantiate a hash set containing integer keys\n  @param  name  Name of the hash table [symbol]\n */\n#define KHASH_SET_INIT_INT(name)\t\t\t\t\t\t\t\t\t\t\\\n\tKHASH_INIT(name, khint32_t, char, 0, kh_int_hash_func, kh_int_hash_equal)\n\n/*! @function\n  @abstract     Instantiate a hash map containing integer keys\n  @param  name  Name of the hash table [symbol]\n  @param  khval_t  Type of values [type]\n */\n#define KHASH_MAP_INIT_INT(name, khval_t)\t\t\t\t\t\t\t\t\\\n\tKHASH_INIT(name, khint32_t, khval_t, 1, kh_int_hash_func, kh_int_hash_equal)\n\n/*! @function\n  @abstract     Instantiate a hash map containing 64-bit integer keys\n  @param  name  Name of the hash table [symbol]\n */\n#define KHASH_SET_INIT_INT64(name)\t\t\t\t\t\t\t\t\t\t\\\n\tKHASH_INIT(name, khint64_t, char, 0, kh_int64_hash_func, kh_int64_hash_equal)\n\n/*! @function\n  @abstract     Instantiate a hash map containing 64-bit integer keys\n  @param  name  Name of the hash table [symbol]\n  @param  khval_t  Type of values [type]\n */\n#define KHASH_MAP_INIT_INT64(name, khval_t)\t\t\t\t\t\t\t\t\\\n\tKHASH_INIT(name, khint64_t, khval_t, 1, kh_int64_hash_func, kh_int64_hash_equal)\n\ntypedef const char *kh_cstr_t;\n/*! @function\n  @abstract     Instantiate a hash map containing const char* keys\n  @param  name  Name of the hash table [symbol]\n */\n#define KHASH_SET_INIT_STR(name)\t\t\t\t\t\t\t\t\t\t\\\n\tKHASH_INIT(name, kh_cstr_t, char, 0, kh_str_hash_func, kh_str_hash_equal)\n\n/*! @function\n  @abstract     Instantiate a hash map containing const char* keys\n  @param  name  Name of the hash table [symbol]\n  @param  khval_t  Type of values [type]\n */\n#define KHASH_MAP_INIT_STR(name, khval_t)\t\t\t\t\t\t\t\t\\\n\tKHASH_INIT(name, kh_cstr_t, khval_t, 1, kh_str_hash_func, kh_str_hash_equal)\n\n#endif /* __AC_KHASH_H */\n"
  },
  {
    "path": "benchmarks/ext/kvec.h",
    "content": "/* The MIT License\n\n   Copyright (c) 2008, by Attractive Chaos <attractor@live.co.uk>\n\n   Permission is hereby granted, free of charge, to any person obtaining\n   a copy of this software and associated documentation files (the\n   \"Software\"), to deal in the Software without restriction, including\n   without limitation the rights to use, copy, modify, merge, publish,\n   distribute, sublicense, and/or sell copies of the Software, and to\n   permit persons to whom the Software is furnished to do so, subject to\n   the following conditions:\n\n   The above copyright notice and this permission notice shall be\n   included in all copies or substantial portions of the Software.\n\n   THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n   BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n   ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n   SOFTWARE.\n*/\n\n/*\n  An example:\n\n#include \"kvec.h\"\nint main() {\n\tkvec_t(int) array;\n\tkv_init(array);\n\tkv_push(int, array, 10); // append\n\tkv_a(int, array, 20) = 5; // dynamic\n\tkv_A(array, 20) = 4; // static\n\tkv_destroy(array);\n\treturn 0;\n}\n*/\n\n/*\n  2008-09-22 (0.1.0):\n\n\t* The initial version.\n\n*/\n\n#ifndef AC_KVEC_H\n#define AC_KVEC_H\n\n#include <stdlib.h>\n\n#define kv_roundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))\n\n#define kvec_t(type) struct { size_t n, m; type *a; }\n#define kv_init(v) ((v).n = (v).m = 0, (v).a = 0)\n#define kv_destroy(v) free((v).a)\n#define kv_A(v, i) ((v).a[(i)])\n#define kv_pop(v) ((v).a[--(v).n])\n#define kv_size(v) ((v).n)\n#define kv_max(v) ((v).m)\n\n#define kv_resize(type, v, s)  ((v).m = (s), (v).a = (type*)realloc((v).a, sizeof(type) * (v).m))\n\n#define kv_copy(type, v1, v0) do {\t\t\t\t\t\t\t\\\n\t\tif ((v1).m < (v0).n) kv_resize(type, v1, (v0).n);\t\\\n\t\t(v1).n = (v0).n;\t\t\t\t\t\t\t\t\t\\\n\t\tmemcpy((v1).a, (v0).a, sizeof(type) * (v0).n);\t\t\\\n\t} while (0)\t\t\t\t\t\t\t\t\t\t\t\t\\\n\n#define kv_push(type, v, x) do {\t\t\t\t\t\t\t\t\t\\\n\t\tif ((v).n == (v).m) {\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t(v).m = (v).m? (v).m<<1 : 2;\t\t\t\t\t\t\t\\\n\t\t\t(v).a = (type*)realloc((v).a, sizeof(type) * (v).m);\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t(v).a[(v).n++] = (x);\t\t\t\t\t\t\t\t\t\t\\\n\t} while (0)\n\n#define kv_pushp(type, v) (((v).n == (v).m)?\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t   ((v).m = ((v).m? (v).m<<1 : 2),\t\t\t\t\\\n\t\t\t\t\t\t\t(v).a = (type*)realloc((v).a, sizeof(type) * (v).m), 0)\t\\\n\t\t\t\t\t\t   : 0), ((v).a + ((v).n++))\n\n#define kv_a(type, v, i) (((v).m <= (size_t)(i)? \\\n\t\t\t\t\t\t  ((v).m = (v).n = (i) + 1, kv_roundup32((v).m), \\\n\t\t\t\t\t\t   (v).a = (type*)realloc((v).a, sizeof(type) * (v).m), 0) \\\n\t\t\t\t\t\t  : (v).n <= (size_t)(i)? (v).n = (i) + 1 \\\n\t\t\t\t\t\t  : 0), (v).a[(i)])\n\n#endif\n\n"
  },
  {
    "path": "benchmarks/ext/regexp9.c",
    "content": "/*\n  Copyright information from the original package:\n*/\n/*\n  The authors of this software is Rob Pike.\n\t\tCopyright (c) 2002 by Lucent Technologies.\n  Permission to use, copy, modify, and distribute this software for any\n  purpose without fee is hereby granted, provided that this entire notice\n  is included in all copies of any software which is or includes a copy\n  or modification of this software and in all copies of the supporting\n  documentation for such software.\n  THIS SOFTWARE IS BEING PROVIDED \"AS IS\", WITHOUT ANY EXPRESS OR IMPLIED\n  WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY\n  REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY\n  OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.\n\n\n  This is a Unix port of the Plan 9 regular expression library.\n\n  Please send comments about the packaging\n  to Russ Cox <rsc@swtch.com>.\n\n  ----\n\n  This software is also made available under the Lucent Public License\n  version 1.02; see http://plan9.bell-labs.com/plan9dist/license.html\n*/\n/*\n  This software was packaged for Unix by Russ Cox.\n  Please send comments to rsc@swtch.com.\n\n  http://swtch.com/plan9port/unix\n*/\n\n#include <stdlib.h>\n#include <setjmp.h>\n#include <unistd.h>\n#include \"regexp9.h\"\n\n#define nil 0\n#define exits(x) exit(x && *x ? 1 : 0)\n\n/****************************************************\n * Routines from rune.c, runestrchr.c and utfrune.c *\n ****************************************************/\n\n#include <stdarg.h>\n#include <string.h>\n\nenum\n{\n\tBit1\t= 7,\n\tBitx\t= 6,\n\tBit2\t= 5,\n\tBit3\t= 4,\n\tBit4\t= 3,\n\n\tT1\t= ((1<<(Bit1+1))-1) ^ 0xFF,\t/* 0000 0000 */\n\tTx\t= ((1<<(Bitx+1))-1) ^ 0xFF,\t/* 1000 0000 */\n\tT2\t= ((1<<(Bit2+1))-1) ^ 0xFF,\t/* 1100 0000 */\n\tT3\t= ((1<<(Bit3+1))-1) ^ 0xFF,\t/* 1110 0000 */\n\tT4\t= ((1<<(Bit4+1))-1) ^ 0xFF,\t/* 1111 0000 */\n\n\tRune1\t= (1<<(Bit1+0*Bitx))-1,\t\t/* 0000 0000 0111 1111 */\n\tRune2\t= (1<<(Bit2+1*Bitx))-1,\t\t/* 0000 0111 1111 1111 */\n\tRune3\t= (1<<(Bit3+2*Bitx))-1,\t\t/* 1111 1111 1111 1111 */\n\n\tMaskx\t= (1<<Bitx)-1,\t\t\t/* 0011 1111 */\n\tTestx\t= Maskx ^ 0xFF,\t\t\t/* 1100 0000 */\n\n\tBad\t= Runeerror\n};\n\nint\nchartorune(Rune *rune, const char *str)\n{\n\tint c, c1, c2;\n\tlong l;\n\n\t/*\n\t * one character sequence\n\t *\t00000-0007F => T1\n\t */\n\tc = *(uchar*)str;\n\tif(c < Tx) {\n\t\t*rune = c;\n\t\treturn 1;\n\t}\n\n\t/*\n\t * two character sequence\n\t *\t0080-07FF => T2 Tx\n\t */\n\tc1 = *(uchar*)(str+1) ^ Tx;\n\tif(c1 & Testx)\n\t\tgoto bad;\n\tif(c < T3) {\n\t\tif(c < T2)\n\t\t\tgoto bad;\n\t\tl = ((c << Bitx) | c1) & Rune2;\n\t\tif(l <= Rune1)\n\t\t\tgoto bad;\n\t\t*rune = l;\n\t\treturn 2;\n\t}\n\n\t/*\n\t * three character sequence\n\t *\t0800-FFFF => T3 Tx Tx\n\t */\n\tc2 = *(uchar*)(str+2) ^ Tx;\n\tif(c2 & Testx)\n\t\tgoto bad;\n\tif(c < T4) {\n\t\tl = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3;\n\t\tif(l <= Rune2)\n\t\t\tgoto bad;\n\t\t*rune = l;\n\t\treturn 3;\n\t}\n\n\t/*\n\t * bad decoding\n\t */\nbad:\n\t*rune = Bad;\n\treturn 1;\n}\n\nRune*\nrunestrchr(const Rune *s, Rune c)\n{\n\tRune c0 = c;\n\tRune c1;\n\n\tif(c == 0) {\n\t\twhile(*s++)\n\t\t\t;\n\t\treturn (Rune*)s-1;\n\t}\n\n\twhile((c1 = *s++))\n\t\tif(c1 == c0)\n\t\t\treturn (Rune*)s-1;\n\treturn 0;\n}\n\nchar*\nutfrune(char *s, long c)\n{\n\tlong c1;\n\tRune r;\n\tint n;\n\n\tif(c < Runesync)\t\t/* not part of utf sequence */\n\t\treturn strchr(s, c);\n\n\tfor(;;) {\n\t\tc1 = *(uchar*)s;\n\t\tif(c1 < Runeself) {\t/* one byte rune */\n\t\t\tif(c1 == 0)\n\t\t\t\treturn 0;\n\t\t\tif(c1 == c)\n\t\t\t\treturn s;\n\t\t\ts++;\n\t\t\tcontinue;\n\t\t}\n\t\tn = chartorune(&r, s);\n\t\tif(r == c)\n\t\t\treturn s;\n\t\ts += n;\n\t}\n}\n\n/************\n * regaux.c *\n ************/\n\n/*\n *  save a new match in mp\n */\nstatic void\n_renewmatch(Resub *mp, int ms, Resublist *sp)\n{\n\tint i;\n\n\tif(mp==0 || ms<=0)\n\t\treturn;\n\tif(mp[0].s.sp==0 || sp->m[0].s.sp<mp[0].s.sp ||\n\t   (sp->m[0].s.sp==mp[0].s.sp && sp->m[0].e.ep>mp[0].e.ep)){\n\t\tfor(i=0; i<ms && i<NSUBEXP; i++)\n\t\t\tmp[i] = sp->m[i];\n\t\tfor(; i<ms; i++)\n\t\t\tmp[i].s.sp = mp[i].e.ep = 0;\n\t}\n}\n\n/*\n * Note optimization in _renewthread:\n * \t*lp must be pending when _renewthread called; if *l has been looked\n *\t\tat already, the optimization is a bug.\n */\nstatic Relist*\n_renewthread(Relist *lp,\t/* _relist to add to */\n\tReinst *ip,\t\t/* instruction to add */\n\tint ms,\n\tResublist *sep)\t\t/* pointers to subexpressions */\n{\n\tRelist *p;\n\n\tfor(p=lp; p->inst; p++){\n\t\tif(p->inst == ip){\n\t\t\tif(sep->m[0].s.sp < p->se.m[0].s.sp){\n\t\t\t\tif(ms > 1)\n\t\t\t\t\tp->se = *sep;\n\t\t\t\telse\n\t\t\t\t\tp->se.m[0] = sep->m[0];\n\t\t\t}\n\t\t\treturn 0;\n\t\t}\n\t}\n\tp->inst = ip;\n\tif(ms > 1)\n\t\tp->se = *sep;\n\telse\n\t\tp->se.m[0] = sep->m[0];\n\t(++p)->inst = 0;\n\treturn p;\n}\n\n/*\n * same as renewthread, but called with\n * initial empty start pointer.\n */\nstatic Relist*\n_renewemptythread(Relist *lp,\t/* _relist to add to */\n\tReinst *ip,\t\t/* instruction to add */\n\tint ms,\n\tchar *sp)\t\t/* pointers to subexpressions */\n{\n\tRelist *p;\n\n\tfor(p=lp; p->inst; p++){\n\t\tif(p->inst == ip){\n\t\t\tif(sp < p->se.m[0].s.sp) {\n\t\t\t\tif(ms > 1)\n\t\t\t\t\tmemset(&p->se, 0, sizeof(p->se));\n\t\t\t\tp->se.m[0].s.sp = sp;\n\t\t\t}\n\t\t\treturn 0;\n\t\t}\n\t}\n\tp->inst = ip;\n\tif(ms > 1)\n\t\tmemset(&p->se, 0, sizeof(p->se));\n\tp->se.m[0].s.sp = sp;\n\t(++p)->inst = 0;\n\treturn p;\n}\n\nstatic Relist*\n_rrenewemptythread(Relist *lp,\t/* _relist to add to */\n\tReinst *ip,\t\t/* instruction to add */\n\tint ms,\n\tRune *rsp)\t\t/* pointers to subexpressions */\n{\n\tRelist *p;\n\n\tfor(p=lp; p->inst; p++){\n\t\tif(p->inst == ip){\n\t\t\tif(rsp < p->se.m[0].s.rsp) {\n\t\t\t\tif(ms > 1)\n\t\t\t\t\tmemset(&p->se, 0, sizeof(p->se));\n\t\t\t\tp->se.m[0].s.rsp = rsp;\n\t\t\t}\n\t\t\treturn 0;\n\t\t}\n\t}\n\tp->inst = ip;\n\tif(ms > 1)\n\t\tmemset(&p->se, 0, sizeof(p->se));\n\tp->se.m[0].s.rsp = rsp;\n\t(++p)->inst = 0;\n\treturn p;\n}\n\n/*************\n * regcomp.c *\n *************/\n\n#define\tTRUE\t1\n#define\tFALSE\t0\n\n/*\n * Parser Information\n */\ntypedef\nstruct Node\n{\n\tReinst*\tfirst;\n\tReinst*\tlast;\n}Node;\n\n#define\tNSTACK\t20\nstatic\tNode\tandstack[NSTACK];\nstatic\tNode\t*andp;\nstatic\tint\tatorstack[NSTACK];\nstatic\tint*\tatorp;\nstatic\tint\tcursubid;\t\t/* id of current subexpression */\nstatic\tint\tsubidstack[NSTACK];\t/* parallel to atorstack */\nstatic\tint*\tsubidp;\nstatic\tint\tlastwasand;\t/* Last token was operand */\nstatic\tint\tnbra;\nstatic\tchar*\texprp;\t\t/* pointer to next character in source expression */\nstatic\tint\tlexdone;\nstatic\tint\tnclass;\nstatic\tReclass*classp;\nstatic\tReinst*\tfreep;\nstatic\tint\terrors;\nstatic\tRune\tyyrune;\t\t/* last lex'd rune */\nstatic\tReclass*yyclassp;\t/* last lex'd class */\n\n/* predeclared crap */\nstatic\tvoid\toperator(int);\nstatic\tvoid\tpushand(Reinst*, Reinst*);\nstatic\tvoid\tpushator(int);\nstatic\tvoid\tevaluntil(int);\nstatic\tint\tbldcclass(void);\n\nstatic jmp_buf regkaboom;\n\nstatic\tvoid\nrcerror(char *s)\n{\n\terrors++;\n\tregerror9(s);\n\tlongjmp(regkaboom, 1);\n}\n\nstatic\tReinst*\nnewinst(int t)\n{\n\tfreep->type = t;\n\tfreep->u2.left = 0;\n\tfreep->u1.right = 0;\n\treturn freep++;\n}\n\nstatic\tvoid\noperand(int t)\n{\n\tReinst *i;\n\n\tif(lastwasand)\n\t\toperator(CAT);\t/* catenate is implicit */\n\ti = newinst(t);\n\n\tif(t == CCLASS || t == NCCLASS)\n\t\ti->u1.cp = yyclassp;\n\tif(t == RUNE)\n\t\ti->u1.r = yyrune;\n\n\tpushand(i, i);\n\tlastwasand = TRUE;\n}\n\nstatic\tvoid\noperator(int t)\n{\n\tif(t==RBRA && --nbra<0)\n\t\trcerror(\"unmatched right paren\");\n\tif(t==LBRA){\n\t\tif(++cursubid >= NSUBEXP)\n\t\t\trcerror (\"too many subexpressions\");\n\t\tnbra++;\n\t\tif(lastwasand)\n\t\t\toperator(CAT);\n\t} else\n\t\tevaluntil(t);\n\tif(t != RBRA)\n\t\tpushator(t);\n\tlastwasand = FALSE;\n\tif(t==STAR || t==QUEST || t==PLUS || t==RBRA)\n\t\tlastwasand = TRUE;\t/* these look like operands */\n}\n\nstatic\tvoid\nregerr2(char *s, int c)\n{\n\tchar buf[100];\n\tchar *cp = buf;\n\twhile(*s)\n\t\t*cp++ = *s++;\n\t*cp++ = c;\n\t*cp = '\\0'; \n\trcerror(buf);\n}\n\nstatic\tvoid\ncant(char *s)\n{\n\tchar buf[100];\n\tstrcpy(buf, \"can't happen: \");\n\tstrcat(buf, s);\n\trcerror(buf);\n}\n\nstatic\tvoid\npushand(Reinst *f, Reinst *l)\n{\n\tif(andp >= &andstack[NSTACK])\n\t\tcant(\"operand stack overflow\");\n\tandp->first = f;\n\tandp->last = l;\n\tandp++;\n}\n\nstatic\tvoid\npushator(int t)\n{\n\tif(atorp >= &atorstack[NSTACK])\n\t\tcant(\"operator stack overflow\");\n\t*atorp++ = t;\n\t*subidp++ = cursubid;\n}\n\nstatic\tNode*\npopand(int op)\n{\n\tReinst *inst;\n\n\tif(andp <= &andstack[0]){\n\t\tregerr2(\"missing operand for \", op);\n\t\tinst = newinst(NOP);\n\t\tpushand(inst,inst);\n\t}\n\treturn --andp;\n}\n\nstatic\tint\npopator(void)\n{\n\tif(atorp <= &atorstack[0])\n\t\tcant(\"operator stack underflow\");\n\t--subidp;\n\treturn *--atorp;\n}\n\nstatic\tvoid\nevaluntil(int pri)\n{\n\tNode *op1, *op2;\n\tReinst *inst1, *inst2;\n\n\twhile(pri==RBRA || atorp[-1]>=pri){\n\t\tswitch(popator()){\n\t\tdefault:\n\t\t\trcerror(\"unknown operator in evaluntil\");\n\t\t\tbreak;\n\t\tcase LBRA:\t\t/* must have been RBRA */\n\t\t\top1 = popand('(');\n\t\t\tinst2 = newinst(RBRA);\n\t\t\tinst2->u1.subid = *subidp;\n\t\t\top1->last->u2.next = inst2;\n\t\t\tinst1 = newinst(LBRA);\n\t\t\tinst1->u1.subid = *subidp;\n\t\t\tinst1->u2.next = op1->first;\n\t\t\tpushand(inst1, inst2);\n\t\t\treturn;\n\t\tcase OR:\n\t\t\top2 = popand('|');\n\t\t\top1 = popand('|');\n\t\t\tinst2 = newinst(NOP);\n\t\t\top2->last->u2.next = inst2;\n\t\t\top1->last->u2.next = inst2;\n\t\t\tinst1 = newinst(OR);\n\t\t\tinst1->u1.right = op1->first;\n\t\t\tinst1->u2.left = op2->first;\n\t\t\tpushand(inst1, inst2);\n\t\t\tbreak;\n\t\tcase CAT:\n\t\t\top2 = popand(0);\n\t\t\top1 = popand(0);\n\t\t\top1->last->u2.next = op2->first;\n\t\t\tpushand(op1->first, op2->last);\n\t\t\tbreak;\n\t\tcase STAR:\n\t\t\top2 = popand('*');\n\t\t\tinst1 = newinst(OR);\n\t\t\top2->last->u2.next = inst1;\n\t\t\tinst1->u1.right = op2->first;\n\t\t\tpushand(inst1, inst1);\n\t\t\tbreak;\n\t\tcase PLUS:\n\t\t\top2 = popand('+');\n\t\t\tinst1 = newinst(OR);\n\t\t\top2->last->u2.next = inst1;\n\t\t\tinst1->u1.right = op2->first;\n\t\t\tpushand(op2->first, inst1);\n\t\t\tbreak;\n\t\tcase QUEST:\n\t\t\top2 = popand('?');\n\t\t\tinst1 = newinst(OR);\n\t\t\tinst2 = newinst(NOP);\n\t\t\tinst1->u2.left = inst2;\n\t\t\tinst1->u1.right = op2->first;\n\t\t\top2->last->u2.next = inst2;\n\t\t\tpushand(inst1, inst2);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nstatic\tReprog*\noptimize(Reprog *pp)\n{\n\tReinst *inst, *target;\n\tint size;\n\tReprog *npp;\n\tReclass *cl;\n\tint diff;\n\n\t/*\n\t *  get rid of NOOP chains\n\t */\n\tfor(inst=pp->firstinst; inst->type!=END; inst++){\n\t\ttarget = inst->u2.next;\n\t\twhile(target->type == NOP)\n\t\t\ttarget = target->u2.next;\n\t\tinst->u2.next = target;\n\t}\n\n\t/*\n\t *  The original allocation is for an area larger than\n\t *  necessary.  Reallocate to the actual space used\n\t *  and then relocate the code.\n\t */\n\tsize = sizeof(Reprog) + (freep - pp->firstinst)*sizeof(Reinst);\n\tnpp = realloc(pp, size);\n\tif(npp==0 || npp==pp)\n\t\treturn pp;\n\tdiff = (char *)npp - (char *)pp;\n\tfreep = (Reinst *)((char *)freep + diff);\n\tfor(inst=npp->firstinst; inst<freep; inst++){\n\t\tswitch(inst->type){\n\t\tcase OR:\n\t\tcase STAR:\n\t\tcase PLUS:\n\t\tcase QUEST:\n\t\t\tinst->u1.right = (void*)((char*)inst->u1.right + diff);\n\t\t\tbreak;\n\t\tcase CCLASS:\n\t\tcase NCCLASS:\n\t\t\tinst->u1.right = (void*)((char*)inst->u1.right + diff);\n\t\t\tcl = inst->u1.cp;\n\t\t\tcl->end = (void*)((char*)cl->end + diff);\n\t\t\tbreak;\n\t\t}\n\t\tinst->u2.left = (void*)((char*)inst->u2.left + diff);\n\t}\n\tnpp->startinst = (void*)((char*)npp->startinst + diff);\n\treturn npp;\n}\n\n#ifdef\tDEBUG\nstatic\tvoid\ndumpstack(void){\n\tNode *stk;\n\tint *ip;\n\n\tprint(\"operators\\n\");\n\tfor(ip=atorstack; ip<atorp; ip++)\n\t\tprint(\"0%o\\n\", *ip);\n\tprint(\"operands\\n\");\n\tfor(stk=andstack; stk<andp; stk++)\n\t\tprint(\"0%o\\t0%o\\n\", stk->first->type, stk->last->type);\n}\n\nstatic\tvoid\ndump(Reprog *pp)\n{\n\tReinst *l;\n\tRune *p;\n\n\tl = pp->firstinst;\n\tdo{\n\t\tprint(\"%d:\\t0%o\\t%d\\t%d\", l-pp->firstinst, l->type,\n\t\t\tl->u2.left-pp->firstinst, l->u1.right-pp->firstinst);\n\t\tif(l->type == RUNE)\n\t\t\tprint(\"\\t%C\\n\", l->u1.r);\n\t\telse if(l->type == CCLASS || l->type == NCCLASS){\n\t\t\tprint(\"\\t[\");\n\t\t\tif(l->type == NCCLASS)\n\t\t\t\tprint(\"^\");\n\t\t\tfor(p = l->u1.cp->spans; p < l->u1.cp->end; p += 2)\n\t\t\t\tif(p[0] == p[1])\n\t\t\t\t\tprint(\"%C\", p[0]);\n\t\t\t\telse\n\t\t\t\t\tprint(\"%C-%C\", p[0], p[1]);\n\t\t\tprint(\"]\\n\");\n\t\t} else\n\t\t\tprint(\"\\n\");\n\t}while(l++->type);\n}\n#endif\n\nstatic\tReclass*\nnewclass(void)\n{\n\tif(nclass >= NCLASS)\n\t\tregerr2(\"too many character classes; limit\", NCLASS+'0');\n\treturn &(classp[nclass++]);\n}\n\nstatic\tint\nnextc(Rune *rp)\n{\n\tif(lexdone){\n\t\t*rp = 0;\n\t\treturn 1;\n\t}\n\texprp += chartorune(rp, exprp);\n\tif(*rp == '\\\\'){\n\t\texprp += chartorune(rp, exprp);\n\t\treturn 1;\n\t}\n\tif(*rp == 0)\n\t\tlexdone = 1;\n\treturn 0;\n}\n\nstatic\tint\nlex(int literal, int dot_type)\n{\n\tint quoted;\n\n\tquoted = nextc(&yyrune);\n\tif(literal || quoted){\n\t\tif(yyrune == 0)\n\t\t\treturn END;\n\t\treturn RUNE;\n\t}\n\n\tswitch(yyrune){\n\tcase 0:\n\t\treturn END;\n\tcase '*':\n\t\treturn STAR;\n\tcase '?':\n\t\treturn QUEST;\n\tcase '+':\n\t\treturn PLUS;\n\tcase '|':\n\t\treturn OR;\n\tcase '.':\n\t\treturn dot_type;\n\tcase '(':\n\t\treturn LBRA;\n\tcase ')':\n\t\treturn RBRA;\n\tcase '^':\n\t\treturn BOL;\n\tcase '$':\n\t\treturn EOL;\n\tcase '[':\n\t\treturn bldcclass();\n\t}\n\treturn RUNE;\n}\n\nstatic int\nbldcclass(void)\n{\n\tint type;\n\tRune r[NCCRUNE];\n\tRune *p, *ep, *np;\n\tRune rune;\n\tint quoted;\n\n\t/* we have already seen the '[' */\n\ttype = CCLASS;\n\tyyclassp = newclass();\n\n\t/* look ahead for negation */\n\t/* SPECIAL CASE!!! negated classes don't match \\n */\n\tep = r;\n\tquoted = nextc(&rune);\n\tif(!quoted && rune == '^'){\n\t\ttype = NCCLASS;\n\t\tquoted = nextc(&rune);\n\t\t*ep++ = '\\n';\n\t\t*ep++ = '\\n';\n\t}\n\n\t/* parse class into a set of spans */\n\tfor(; ep<&r[NCCRUNE];){\n\t\tif(rune == 0){\n\t\t\trcerror(\"malformed '[]'\");\n\t\t\treturn 0;\n\t\t}\n\t\tif(!quoted && rune == ']')\n\t\t\tbreak;\n\t\tif(!quoted && rune == '-'){\n\t\t\tif(ep == r){\n\t\t\t\trcerror(\"malformed '[]'\");\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tquoted = nextc(&rune);\n\t\t\tif((!quoted && rune == ']') || rune == 0){\n\t\t\t\trcerror(\"malformed '[]'\");\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\t*(ep-1) = rune;\n\t\t} else {\n\t\t\t*ep++ = rune;\n\t\t\t*ep++ = rune;\n\t\t}\n\t\tquoted = nextc(&rune);\n\t}\n\n\t/* sort on span start */\n\tfor(p = r; p < ep; p += 2){\n\t\tfor(np = p; np < ep; np += 2)\n\t\t\tif(*np < *p){\n\t\t\t\trune = np[0];\n\t\t\t\tnp[0] = p[0];\n\t\t\t\tp[0] = rune;\n\t\t\t\trune = np[1];\n\t\t\t\tnp[1] = p[1];\n\t\t\t\tp[1] = rune;\n\t\t\t}\n\t}\n\n\t/* merge spans */\n\tnp = yyclassp->spans;\n\tp = r;\n\tif(r == ep)\n\t\tyyclassp->end = np;\n\telse {\n\t\tnp[0] = *p++;\n\t\tnp[1] = *p++;\n\t\tfor(; p < ep; p += 2)\n\t\t\tif(p[0] <= np[1]){\n\t\t\t\tif(p[1] > np[1])\n\t\t\t\t\tnp[1] = p[1];\n\t\t\t} else {\n\t\t\t\tnp += 2;\n\t\t\t\tnp[0] = p[0];\n\t\t\t\tnp[1] = p[1];\n\t\t\t}\n\t\tyyclassp->end = np+2;\n\t}\n\n\treturn type;\n}\n\nstatic\tReprog*\nregcomp1(char *s, int literal, int dot_type)\n{\n\tint token;\n\tReprog *volatile pp;\n\n\t/* get memory for the program */\n\tpp = malloc(sizeof(Reprog) + 6*sizeof(Reinst)*strlen(s));\n\tif(pp == 0){\n\t\tregerror9(\"out of memory\");\n\t\treturn 0;\n\t}\n\tfreep = pp->firstinst;\n\tclassp = pp->class;\n\terrors = 0;\n\n\tif(setjmp(regkaboom))\n\t\tgoto out;\n\n\t/* go compile the sucker */\n\tlexdone = 0;\n\texprp = s;\n\tnclass = 0;\n\tnbra = 0;\n\tatorp = atorstack;\n\tandp = andstack;\n\tsubidp = subidstack;\n\tlastwasand = FALSE;\n\tcursubid = 0;\n\n\t/* Start with a low priority operator to prime parser */\n\tpushator(START-1);\n\twhile((token = lex(literal, dot_type)) != END){\n\t\tif((token&0300) == OPERATOR)\n\t\t\toperator(token);\n\t\telse\n\t\t\toperand(token);\n\t}\n\n\t/* Close with a low priority operator */\n\tevaluntil(START);\n\n\t/* Force END */\n\toperand(END);\n\tevaluntil(START);\n#ifdef DEBUG\n\tdumpstack();\n#endif\n\tif(nbra)\n\t\trcerror(\"unmatched left paren\");\n\t--andp;\t/* points to first and only operand */\n\tpp->startinst = andp->first;\n#ifdef DEBUG\n\tdump(pp);\n#endif\n\tpp = optimize(pp);\n#ifdef DEBUG\n\tprint(\"start: %d\\n\", andp->first-pp->firstinst);\n\tdump(pp);\n#endif\nout:\n\tif(errors){\n\t\tfree(pp);\n\t\tpp = 0;\n\t}\n\treturn pp;\n}\n\nextern\tReprog*\nregcomp9(char *s)\n{\n\treturn regcomp1(s, 0, ANY);\n}\n\nextern\tReprog*\nregcomplit9(char *s)\n{\n\treturn regcomp1(s, 1, ANY);\n}\n\nextern\tReprog*\nregcompnl9(char *s)\n{\n\treturn regcomp1(s, 0, ANYNL);\n}\n\n/*************\n * regexec.c *\n *************/\n\n/*\n *  return\t0 if no match\n *\t\t>0 if a match\n *\t\t<0 if we ran out of _relist space\n */\nstatic int\nregexec1(const Reprog *progp,\t/* program to run */\n\tchar *bol,\t/* string to run machine on */\n\tResub *mp,\t/* subexpression elements */\n\tint ms,\t\t/* number of elements at mp */\n\tReljunk *j\n)\n{\n\tint flag=0;\n\tReinst *inst;\n\tRelist *tlp;\n\tchar *s;\n\tint i, checkstart;\n\tRune r, *rp, *ep;\n\tint n;\n\tRelist* tl;\t\t/* This list, next list */\n\tRelist* nl;\n\tRelist* tle;\t\t/* ends of this and next list */\n\tRelist* nle;\n\tint match;\n\tchar *p;\n\n\tmatch = 0;\n\tcheckstart = j->starttype;\n\tif(mp)\n\t\tfor(i=0; i<ms; i++) {\n\t\t\tmp[i].s.sp = 0;\n\t\t\tmp[i].e.ep = 0;\n\t\t}\n\tj->relist[0][0].inst = 0;\n\tj->relist[1][0].inst = 0;\n\n\t/* Execute machine once for each character, including terminal NUL */\n\ts = j->starts;\n\tdo{\n\t\t/* fast check for first char */\n\t\tif(checkstart) {\n\t\t\tswitch(j->starttype) {\n\t\t\tcase RUNE:\n\t\t\t\tp = utfrune(s, j->startchar);\n\t\t\t\tif(p == 0 || s == j->eol)\n\t\t\t\t\treturn match;\n\t\t\t\ts = p;\n\t\t\t\tbreak;\n\t\t\tcase BOL:\n\t\t\t\tif(s == bol)\n\t\t\t\t\tbreak;\n\t\t\t\tp = utfrune(s, '\\n');\n\t\t\t\tif(p == 0 || s == j->eol)\n\t\t\t\t\treturn match;\n\t\t\t\ts = p+1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tr = *(uchar*)s;\n\t\tif(r < Runeself)\n\t\t\tn = 1;\n\t\telse\n\t\t\tn = chartorune(&r, s);\n\n\t\t/* switch run lists */\n\t\ttl = j->relist[flag];\n\t\ttle = j->reliste[flag];\n\t\tnl = j->relist[flag^=1];\n\t\tnle = j->reliste[flag];\n\t\tnl->inst = 0;\n\n\t\t/* Add first instruction to current list */\n\t\tif(match == 0)\n\t\t\t_renewemptythread(tl, progp->startinst, ms, s);\n\n\t\t/* Execute machine until current list is empty */\n\t\tfor(tlp=tl; tlp->inst; tlp++){\t/* assignment = */\n\t\t\tfor(inst = tlp->inst; ; inst = inst->u2.next){\n\t\t\t\tswitch(inst->type){\n\t\t\t\tcase RUNE:\t/* regular character */\n\t\t\t\t\tif(inst->u1.r == r){\n\t\t\t\t\t\tif(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle)\n\t\t\t\t\t\t\treturn -1;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase LBRA:\n\t\t\t\t\ttlp->se.m[inst->u1.subid].s.sp = s;\n\t\t\t\t\tcontinue;\n\t\t\t\tcase RBRA:\n\t\t\t\t\ttlp->se.m[inst->u1.subid].e.ep = s;\n\t\t\t\t\tcontinue;\n\t\t\t\tcase ANY:\n\t\t\t\t\tif(r != '\\n')\n\t\t\t\t\t\tif(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle)\n\t\t\t\t\t\t\treturn -1;\n\t\t\t\t\tbreak;\n\t\t\t\tcase ANYNL:\n\t\t\t\t\tif(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle)\n\t\t\t\t\t\t\treturn -1;\n\t\t\t\t\tbreak;\n\t\t\t\tcase BOL:\n\t\t\t\t\tif(s == bol || *(s-1) == '\\n')\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tbreak;\n\t\t\t\tcase EOL:\n\t\t\t\t\tif(s == j->eol || r == 0 || r == '\\n')\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tbreak;\n\t\t\t\tcase CCLASS:\n\t\t\t\t\tep = inst->u1.cp->end;\n\t\t\t\t\tfor(rp = inst->u1.cp->spans; rp < ep; rp += 2)\n\t\t\t\t\t\tif(r >= rp[0] && r <= rp[1]){\n\t\t\t\t\t\t\tif(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle)\n\t\t\t\t\t\t\t\treturn -1;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase NCCLASS:\n\t\t\t\t\tep = inst->u1.cp->end;\n\t\t\t\t\tfor(rp = inst->u1.cp->spans; rp < ep; rp += 2)\n\t\t\t\t\t\tif(r >= rp[0] && r <= rp[1])\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\tif(rp == ep)\n\t\t\t\t\t\tif(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle)\n\t\t\t\t\t\t\treturn -1;\n\t\t\t\t\tbreak;\n\t\t\t\tcase OR:\n\t\t\t\t\t/* evaluate right choice later */\n\t\t\t\t\tif(_renewthread(tlp, inst->u1.right, ms, &tlp->se) == tle)\n\t\t\t\t\t\treturn -1;\n\t\t\t\t\t/* efficiency: advance and re-evaluate */\n\t\t\t\t\tcontinue;\n\t\t\t\tcase END:\t/* Match! */\n\t\t\t\t\tmatch = 1;\n\t\t\t\t\ttlp->se.m[0].e.ep = s;\n\t\t\t\t\tif(mp != 0)\n\t\t\t\t\t\t_renewmatch(mp, ms, &tlp->se);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif(s == j->eol)\n\t\t\tbreak;\n\t\tcheckstart = j->starttype && nl->inst==0;\n\t\ts += n;\n\t}while(r);\n\treturn match;\n}\n\nstatic int\nregexec2(const Reprog *progp,\t/* program to run */\n\tchar *bol,\t/* string to run machine on */\n\tResub *mp,\t/* subexpression elements */\n\tint ms,\t\t/* number of elements at mp */\n\tReljunk *j\n)\n{\n\tint rv;\n\tRelist *relist0, *relist1;\n\n\t/* mark space */\n\trelist0 = malloc(BIGLISTSIZE*sizeof(Relist));\n\tif(relist0 == nil)\n\t\treturn -1;\n\trelist1 = malloc(BIGLISTSIZE*sizeof(Relist));\n\tif(relist1 == nil){\n\t\tfree(relist1);\n\t\treturn -1;\n\t}\n\tj->relist[0] = relist0;\n\tj->relist[1] = relist1;\n\tj->reliste[0] = relist0 + BIGLISTSIZE - 2;\n\tj->reliste[1] = relist1 + BIGLISTSIZE - 2;\n\n\trv = regexec1(progp, bol, mp, ms, j);\n\tfree(relist0);\n\tfree(relist1);\n\treturn rv;\n}\n\nextern int\nregexec9(const Reprog *progp,\t/* program to run */\n\tchar *bol,\t/* string to run machine on */\n\tResub *mp,\t/* subexpression elements */\n\tint ms)\t\t/* number of elements at mp */\n{\n\tReljunk j;\n\tRelist relist0[LISTSIZE], relist1[LISTSIZE];\n\tint rv;\n\n\t/*\n \t *  use user-specified starting/ending location if specified\n\t */\n\tj.starts = bol;\n\tj.eol = 0;\n\tif(mp && ms>0){\n\t\tif(mp->s.sp)\n\t\t\tj.starts = mp->s.sp;\n\t\tif(mp->e.ep)\n\t\t\tj.eol = mp->e.ep;\n\t}\n\tj.starttype = 0;\n\tj.startchar = 0;\n\tif(progp->startinst->type == RUNE && progp->startinst->u1.r < Runeself) {\n\t\tj.starttype = RUNE;\n\t\tj.startchar = progp->startinst->u1.r;\n\t}\n\tif(progp->startinst->type == BOL)\n\t\tj.starttype = BOL;\n\n\t/* mark space */\n\tj.relist[0] = relist0;\n\tj.relist[1] = relist1;\n\tj.reliste[0] = relist0 + nelem(relist0) - 2;\n\tj.reliste[1] = relist1 + nelem(relist1) - 2;\n\n\trv = regexec1(progp, bol, mp, ms, &j);\n\tif(rv >= 0)\n\t\treturn rv;\n\trv = regexec2(progp, bol, mp, ms, &j);\n\tif(rv >= 0)\n\t\treturn rv;\n\treturn -1;\n}\n\n/************\n * regsub.c *\n ************/\n\n/* substitute into one string using the matches from the last regexec() */\nextern\tvoid\nregsub9(char *sp,\t/* source string */\n\tchar *dp,\t/* destination string */\n\tint dlen,\n\tResub *mp,\t/* subexpression elements */\n\tint ms)\t\t/* number of elements pointed to by mp */\n{\n\tchar *ssp, *ep;\n\tint i;\n\n\tep = dp+dlen-1;\n\twhile(*sp != '\\0'){\n\t\tif(*sp == '\\\\'){\n\t\t\tswitch(*++sp){\n\t\t\tcase '0':\n\t\t\tcase '1':\n\t\t\tcase '2':\n\t\t\tcase '3':\n\t\t\tcase '4':\n\t\t\tcase '5':\n\t\t\tcase '6':\n\t\t\tcase '7':\n\t\t\tcase '8':\n\t\t\tcase '9':\n\t\t\t\ti = *sp-'0';\n\t\t\t\tif(mp[i].s.sp != 0 && mp!=0 && ms>i)\n\t\t\t\t\tfor(ssp = mp[i].s.sp;\n\t\t\t\t\t     ssp < mp[i].e.ep;\n\t\t\t\t\t     ssp++)\n\t\t\t\t\t\tif(dp < ep)\n\t\t\t\t\t\t\t*dp++ = *ssp;\n\t\t\t\tbreak;\n\t\t\tcase '\\\\':\n\t\t\t\tif(dp < ep)\n\t\t\t\t\t*dp++ = '\\\\';\n\t\t\t\tbreak;\n\t\t\tcase '\\0':\n\t\t\t\tsp--;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tif(dp < ep)\n\t\t\t\t\t*dp++ = *sp;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}else if(*sp == '&'){\t\t\t\t\n\t\t\tif(mp[0].s.sp != 0 && mp!=0 && ms>0)\n\t\t\tif(mp[0].s.sp != 0)\n\t\t\t\tfor(ssp = mp[0].s.sp;\n\t\t\t\t     ssp < mp[0].e.ep; ssp++)\n\t\t\t\t\tif(dp < ep)\n\t\t\t\t\t\t*dp++ = *ssp;\n\t\t}else{\n\t\t\tif(dp < ep)\n\t\t\t\t*dp++ = *sp;\n\t\t}\n\t\tsp++;\n\t}\n\t*dp = '\\0';\n}\n\n/**************\n * regerror.c *\n **************/\n\nvoid\nregerror9(char *s)\n{\n\tchar buf[132];\n\n\tstrcpy(buf, \"regerror: \");\n\tstrcat(buf, s);\n\tstrcat(buf, \"\\n\");\n\twrite(2, buf, strlen(buf));\n\texits(\"regerr\");\n}\n\n/**************\n * rregexec.c *\n **************/\n\n/*\n *  return\t0 if no match\n *\t\t>0 if a match\n *\t\t<0 if we ran out of _relist space\n */\nstatic int\nrregexec1(const Reprog *progp,\t/* program to run */\n\tRune *bol,\t\t/* string to run machine on */\n\tResub *mp,\t\t/* subexpression elements */\n\tint ms,\t\t\t/* number of elements at mp */\n\tReljunk *j)\n{\n\tint flag=0;\n\tReinst *inst;\n\tRelist *tlp;\n\tRune *s;\n\tint i, checkstart;\n\tRune r, *rp, *ep;\n\tRelist* tl;\t\t/* This list, next list */\n\tRelist* nl;\n\tRelist* tle;\t\t/* ends of this and next list */\n\tRelist* nle;\n\tint match;\n\tRune *p;\n\n\tmatch = 0;\n\tcheckstart = j->startchar;\n\tif(mp)\n\t\tfor(i=0; i<ms; i++) {\n\t\t\tmp[i].s.rsp = 0;\n\t\t\tmp[i].e.rep = 0;\n\t\t}\n\tj->relist[0][0].inst = 0;\n\tj->relist[1][0].inst = 0;\n\n\t/* Execute machine once for each character, including terminal NUL */\n\ts = j->rstarts;\n\tdo{\n\n\t\t/* fast check for first char */\n\t\tif(checkstart) {\n\t\t\tswitch(j->starttype) {\n\t\t\tcase RUNE:\n\t\t\t\tp = runestrchr(s, j->startchar);\n\t\t\t\tif(p == 0 || p == j->reol)\n\t\t\t\t\treturn match;\n\t\t\t\ts = p;\n\t\t\t\tbreak;\n\t\t\tcase BOL:\n\t\t\t\tif(s == bol)\n\t\t\t\t\tbreak;\n\t\t\t\tp = runestrchr(s, '\\n');\n\t\t\t\tif(p == 0 || s == j->reol)\n\t\t\t\t\treturn match;\n\t\t\t\ts = p+1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tr = *s;\n\n\t\t/* switch run lists */\n\t\ttl = j->relist[flag];\n\t\ttle = j->reliste[flag];\n\t\tnl = j->relist[flag^=1];\n\t\tnle = j->reliste[flag];\n\t\tnl->inst = 0;\n\n\t\t/* Add first instruction to current list */\n\t\t_rrenewemptythread(tl, progp->startinst, ms, s);\n\n\t\t/* Execute machine until current list is empty */\n\t\tfor(tlp=tl; tlp->inst; tlp++){\n\t\t\tfor(inst=tlp->inst; ; inst = inst->u2.next){\n\t\t\t\tswitch(inst->type){\n\t\t\t\tcase RUNE:\t/* regular character */\n\t\t\t\t\tif(inst->u1.r == r)\n\t\t\t\t\t\tif(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle)\n\t\t\t\t\t\t\treturn -1;\n\t\t\t\t\tbreak;\n\t\t\t\tcase LBRA:\n\t\t\t\t\ttlp->se.m[inst->u1.subid].s.rsp = s;\n\t\t\t\t\tcontinue;\n\t\t\t\tcase RBRA:\n\t\t\t\t\ttlp->se.m[inst->u1.subid].e.rep = s;\n\t\t\t\t\tcontinue;\n\t\t\t\tcase ANY:\n\t\t\t\t\tif(r != '\\n')\n\t\t\t\t\t\tif(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle)\n\t\t\t\t\t\t\treturn -1;\n\t\t\t\t\tbreak;\n\t\t\t\tcase ANYNL:\n\t\t\t\t\tif(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle)\n\t\t\t\t\t\t\treturn -1;\n\t\t\t\t\tbreak;\n\t\t\t\tcase BOL:\n\t\t\t\t\tif(s == bol || *(s-1) == '\\n')\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tbreak;\n\t\t\t\tcase EOL:\n\t\t\t\t\tif(s == j->reol || r == 0 || r == '\\n')\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tbreak;\n\t\t\t\tcase CCLASS:\n\t\t\t\t\tep = inst->u1.cp->end;\n\t\t\t\t\tfor(rp = inst->u1.cp->spans; rp < ep; rp += 2)\n\t\t\t\t\t\tif(r >= rp[0] && r <= rp[1]){\n\t\t\t\t\t\t\tif(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle)\n\t\t\t\t\t\t\t\treturn -1;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase NCCLASS:\n\t\t\t\t\tep = inst->u1.cp->end;\n\t\t\t\t\tfor(rp = inst->u1.cp->spans; rp < ep; rp += 2)\n\t\t\t\t\t\tif(r >= rp[0] && r <= rp[1])\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\tif(rp == ep)\n\t\t\t\t\t\tif(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle)\n\t\t\t\t\t\t\treturn -1;\n\t\t\t\t\tbreak;\n\t\t\t\tcase OR:\n\t\t\t\t\t/* evaluate right choice later */\n\t\t\t\t\tif(_renewthread(tlp, inst->u1.right, ms, &tlp->se) == tle)\n\t\t\t\t\t\treturn -1;\n\t\t\t\t\t/* efficiency: advance and re-evaluate */\n\t\t\t\t\tcontinue;\n\t\t\t\tcase END:\t/* Match! */\n\t\t\t\t\tmatch = 1;\n\t\t\t\t\ttlp->se.m[0].e.rep = s;\n\t\t\t\t\tif(mp != 0)\n\t\t\t\t\t\t_renewmatch(mp, ms, &tlp->se);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif(s == j->reol)\n\t\t\tbreak;\n\t\tcheckstart = j->startchar && nl->inst==0;\n\t\ts++;\n\t}while(r);\n\treturn match;\n}\n\nstatic int\nrregexec2(const Reprog *progp,\t/* program to run */\n\tRune *bol,\t/* string to run machine on */\n\tResub *mp,\t/* subexpression elements */\n\tint ms,\t\t/* number of elements at mp */\n\tReljunk *j\n)\n{\n\tRelist relist0[5*LISTSIZE], relist1[5*LISTSIZE];\n\n\t/* mark space */\n\tj->relist[0] = relist0;\n\tj->relist[1] = relist1;\n\tj->reliste[0] = relist0 + nelem(relist0) - 2;\n\tj->reliste[1] = relist1 + nelem(relist1) - 2;\n\n\treturn rregexec1(progp, bol, mp, ms, j);\n}\n\nextern int\nrregexec9(const Reprog *progp,\t/* program to run */\n\tRune *bol,\t/* string to run machine on */\n\tResub *mp,\t/* subexpression elements */\n\tint ms)\t\t/* number of elements at mp */\n{\n\tReljunk j;\n\tRelist relist0[LISTSIZE], relist1[LISTSIZE];\n\tint rv;\n\n\t/*\n \t *  use user-specified starting/ending location if specified\n\t */\n\tj.rstarts = bol;\n\tj.reol = 0;\n\tif(mp && ms>0){\n\t\tif(mp->s.sp)\n\t\t\tj.rstarts = mp->s.rsp;\n\t\tif(mp->e.ep)\n\t\t\tj.reol = mp->e.rep;\n\t}\n\tj.starttype = 0;\n\tj.startchar = 0;\n\tif(progp->startinst->type == RUNE && progp->startinst->u1.r < Runeself) {\n\t\tj.starttype = RUNE;\n\t\tj.startchar = progp->startinst->u1.r;\n\t}\n\tif(progp->startinst->type == BOL)\n\t\tj.starttype = BOL;\n\n\t/* mark space */\n\tj.relist[0] = relist0;\n\tj.relist[1] = relist1;\n\tj.reliste[0] = relist0 + nelem(relist0) - 2;\n\tj.reliste[1] = relist1 + nelem(relist1) - 2;\n\n\trv = rregexec1(progp, bol, mp, ms, &j);\n\tif(rv >= 0)\n\t\treturn rv;\n\trv = rregexec2(progp, bol, mp, ms, &j);\n\tif(rv >= 0)\n\t\treturn rv;\n\treturn -1;\n}\n\n/*************\n * rregsub.c *\n *************/\n\n/* substitute into one string using the matches from the last regexec() */\nextern\tvoid\nrregsub9(Rune *sp,\t/* source string */\n\tRune *dp,\t/* destination string */\n\tint dlen,\n\tResub *mp,\t/* subexpression elements */\n\tint ms)\t\t/* number of elements pointed to by mp */\n{\n\tRune *ssp, *ep;\n\tint i;\n\n\tep = dp+(dlen/sizeof(Rune))-1;\n\twhile(*sp != '\\0'){\n\t\tif(*sp == '\\\\'){\n\t\t\tswitch(*++sp){\n\t\t\tcase '0':\n\t\t\tcase '1':\n\t\t\tcase '2':\n\t\t\tcase '3':\n\t\t\tcase '4':\n\t\t\tcase '5':\n\t\t\tcase '6':\n\t\t\tcase '7':\n\t\t\tcase '8':\n\t\t\tcase '9':\n\t\t\t\ti = *sp-'0';\n\t\t\t\tif(mp[i].s.rsp != 0 && mp!=0 && ms>i)\n\t\t\t\t\tfor(ssp = mp[i].s.rsp;\n\t\t\t\t\t     ssp < mp[i].e.rep;\n\t\t\t\t\t     ssp++)\n\t\t\t\t\t\tif(dp < ep)\n\t\t\t\t\t\t\t*dp++ = *ssp;\n\t\t\t\tbreak;\n\t\t\tcase '\\\\':\n\t\t\t\tif(dp < ep)\n\t\t\t\t\t*dp++ = '\\\\';\n\t\t\t\tbreak;\n\t\t\tcase '\\0':\n\t\t\t\tsp--;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tif(dp < ep)\n\t\t\t\t\t*dp++ = *sp;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}else if(*sp == '&'){\t\t\t\t\n\t\t\tif(mp[0].s.rsp != 0 && mp!=0 && ms>0)\n\t\t\tif(mp[0].s.rsp != 0)\n\t\t\t\tfor(ssp = mp[0].s.rsp;\n\t\t\t\t     ssp < mp[0].e.rep; ssp++)\n\t\t\t\t\tif(dp < ep)\n\t\t\t\t\t\t*dp++ = *ssp;\n\t\t}else{\n\t\t\tif(dp < ep)\n\t\t\t\t*dp++ = *sp;\n\t\t}\n\t\tsp++;\n\t}\n\t*dp = '\\0';\n}\n\n"
  },
  {
    "path": "benchmarks/ext/regexp9.h",
    "content": "#ifndef _REGEXP9_H_\n#define _REGEXP9_H_ 1\n\n/*********\n * utf.h *\n *********/\n\ntypedef unsigned short Rune;\n\ntypedef struct Resub\t\tResub;\ntypedef struct Reclass\t\tReclass;\ntypedef struct Reinst\t\tReinst;\ntypedef struct Reprog\t\tReprog;\n\nenum\n{\n    UTFmax      = 3,        /* maximum bytes per rune */\n    Runesync    = 0x80,     /* cannot represent part of a UTF sequence (<) */\n    Runeself    = 0x80,     /* rune and UTF sequences are the same (<) */\n    Runeerror   = 0xFFFD        /* decoding error in UTF */\n};\n\n/*************\n * regexp9.h *\n *************/\n\n#if defined(__cplusplus)\nextern \"C\" { \n#endif\n\n#ifdef AUTOLIB\nAUTOLIB(regexp9)\n#endif\n\n/*\n *\tSub expression matches\n */\nstruct Resub{\n\tunion\n\t{\n\t\tchar *sp;\n\t\tRune *rsp;\n\t}s;\n\tunion\n\t{\n\t\tchar *ep;\n\t\tRune *rep;\n\t}e;\n};\n\n/*\n *\tcharacter class, each pair of rune's defines a range\n */\nstruct Reclass{\n\tRune\t*end;\n\tRune\tspans[64];\n};\n\n/*\n *\tMachine instructions\n */\nstruct Reinst{\n\tint\ttype;\n\tunion\t{\n\t\tReclass\t*cp;\t\t/* class pointer */\n\t\tRune\tr;\t\t/* character */\n\t\tint\tsubid;\t\t/* sub-expression id for RBRA and LBRA */\n\t\tReinst\t*right;\t\t/* right child of OR */\n\t}u1;\n\tunion {\t/* regexp relies on these two being in the same union */\n\t\tReinst *left;\t\t/* left child of OR */\n\t\tReinst *next;\t\t/* next instruction for CAT & LBRA */\n\t}u2;\n};\n\n/*\n *\tReprogram definition\n */\nstruct Reprog{\n\tReinst\t*startinst;\t/* start pc */\n\tReclass\tclass[16];\t/* .data */\n\tReinst\tfirstinst[5];\t/* .text */\n};\n\nextern Reprog\t*regcomp9(char*);\nextern Reprog\t*regcomplit9(char*);\nextern Reprog\t*regcompnl9(char*);\nextern void\tregerror9(char*);\nextern int\tregexec9(const Reprog*, char*, Resub*, int);\nextern void\tregsub9(char*, char*, int, Resub*, int);\n\nextern int\trregexec9(const Reprog*, Rune*, Resub*, int);\nextern void\trregsub9(Rune*, Rune*, int, Resub*, int);\n\nextern int chartorune(Rune *rune, const char *str);\nextern Rune* runestrchr(const Rune *s, Rune c);\nextern char* utfrune(char *s, long c);\n\n#if defined(__cplusplus)\n}\n#endif\n\n/*************\n * regcomp.h *\n *************/\n\n/*\n *  substitution list\n */\n#define uchar __reuchar\ntypedef unsigned char uchar;\n#define nelem(x) (sizeof(x)/sizeof((x)[0]))\n\n#define NSUBEXP 32\ntypedef struct Resublist\tResublist;\nstruct\tResublist\n{\n\tResub\tm[NSUBEXP];\n};\n\n/* max character classes per program */\nextern Reprog\tRePrOg;\n#define\tNCLASS\t(sizeof(RePrOg.class)/sizeof(Reclass))\n\n/* max rune ranges per character class */\n#define NCCRUNE\t(sizeof(Reclass)/sizeof(Rune))\n\n/*\n * Actions and Tokens (Reinst types)\n *\n *\t02xx are operators, value == precedence\n *\t03xx are tokens, i.e. operands for operators\n */\n#define RUNE\t\t0177\n#define\tOPERATOR\t0200\t/* Bitmask of all operators */\n#define\tSTART\t\t0200\t/* Start, used for marker on stack */\n#define\tRBRA\t\t0201\t/* Right bracket, ) */\n#define\tLBRA\t\t0202\t/* Left bracket, ( */\n#define\tOR\t\t0203\t/* Alternation, | */\n#define\tCAT\t\t0204\t/* Concatentation, implicit operator */\n#define\tSTAR\t\t0205\t/* Closure, * */\n#define\tPLUS\t\t0206\t/* a+ == aa* */\n#define\tQUEST\t\t0207\t/* a? == a|nothing, i.e. 0 or 1 a's */\n#define\tANY\t\t0300\t/* Any character except newline, . */\n#define\tANYNL\t\t0301\t/* Any character including newline, . */\n#define\tNOP\t\t0302\t/* No operation, internal use only */\n#define\tBOL\t\t0303\t/* Beginning of line, ^ */\n#define\tEOL\t\t0304\t/* End of line, $ */\n#define\tCCLASS\t\t0305\t/* Character class, [] */\n#define\tNCCLASS\t\t0306\t/* Negated character class, [] */\n#define\tEND\t\t0377\t/* Terminate: match found */\n\n/*\n *  regexec execution lists\n */\n#define LISTSIZE\t10\n#define BIGLISTSIZE\t(10*LISTSIZE)\ntypedef struct Relist\tRelist;\nstruct Relist\n{\n\tReinst*\t\tinst;\t\t/* Reinstruction of the thread */\n\tResublist\tse;\t\t/* matched subexpressions in this thread */\n};\ntypedef struct Reljunk\tReljunk;\nstruct\tReljunk\n{\n\tRelist*\trelist[2];\n\tRelist*\treliste[2];\n\tint\tstarttype;\n\tRune\tstartchar;\n\tchar*\tstarts;\n\tchar*\teol;\n\tRune*\trstarts;\n\tRune*\treol;\n};\n\n#endif\n"
  },
  {
    "path": "benchmarks/ext/sudoku",
    "content": "cat ./ext/sudoku.txt\n"
  },
  {
    "path": "benchmarks/ext/sudoku.txt",
    "content": "..............3.85..1.2.......5.7.....4...1...9.......5......73..2.1........4...9\tnear worst case for brute-force solver (wiki)\n.......12........3..23..4....18....5.6..7.8.......9.....85.....9...4.5..47...6...\tgsf's sudoku q1 (Platinum Blonde)\n.2..5.7..4..1....68....3...2....8..3.4..2.5.....6...1...2.9.....9......57.4...9..\t(Cheese)\n........3..1..56...9..4..7......9.5.7.......8.5.4.2....8..2..9...35..1..6........\t(Fata Morgana)\n12.3....435....1....4........54..2..6...7.........8.9...31..5.......9.7.....6...8\t(Red Dwarf)\n1.......2.9.4...5...6...7...5.9.3.......7.......85..4.7.....6...3...9.8...2.....1\t(Easter Monster)\n.......39.....1..5..3.5.8....8.9...6.7...2...1..4.......9.8..5..2....6..4..7.....\tNicolas Juillerat's Sudoku explainer 1.2.1 (top 5)\n12.3.....4.....3....3.5......42..5......8...9.6...5.7...15..2......9..6......7..8\n..3..6.8....1..2......7...4..9..8.6..3..4...1.7.2.....3....5.....5...6..98.....5.\n1.......9..67...2..8....4......75.3...5..2....6.3......9....8..6...4...1..25...6.\n..9...4...7.3...2.8...6...71..8....6....1..7.....56...3....5..1.4.....9...2...7..\n....9..5..1.....3...23..7....45...7.8.....2.......64...9..1.....8..6......54....7\tdukuso's suexrat9 (top 1)\n4...3.......6..8..........1....5..9..8....6...7.2........1.27..5.3....4.9........\tfrom http://magictour.free.fr/topn87 (top 3)\n7.8...3.....2.1...5.........4.....263...8.......1...9..9.6....4....7.5...........\n3.7.4...........918........4.....7.....16.......25..........38..9....5...2.6.....\n........8..3...4...9..2..6.....79.......612...6.5.2.7...8...5...1.....2.4.5.....3\tdukuso's suexratt (top 1)\n.......1.4.........2...........5.4.7..8...3....1.9....3..4..2...5.1........8.6...\tfirst 2 from sudoku17\n.......12....35......6...7.7.....3.....4..8..1...........12.....8.....4..5....6..\n1.......2.9.4...5...6...7...5.3.4.......6........58.4...2...6...3...9.8.7.......1\t2 from http://www.setbb.com/phpbb/viewtopic.php?p=10478\n.....1.2.3...4.5.....6....7..2.....1.8..9..3.4.....8..5....2....9..3.4....67.....\n..............3.85..1.2.......5.7.....4...1...9.......5......73..2.1........4...9\tnear worst case for brute-force solver (wiki)\n.......12........3..23..4....18....5.6..7.8.......9.....85.....9...4.5..47...6...\tgsf's sudoku q1 (Platinum Blonde)\n.2..5.7..4..1....68....3...2....8..3.4..2.5.....6...1...2.9.....9......57.4...9..\t(Cheese)\n........3..1..56...9..4..7......9.5.7.......8.5.4.2....8..2..9...35..1..6........\t(Fata Morgana)\n12.3....435....1....4........54..2..6...7.........8.9...31..5.......9.7.....6...8\t(Red Dwarf)\n1.......2.9.4...5...6...7...5.9.3.......7.......85..4.7.....6...3...9.8...2.....1\t(Easter Monster)\n.......39.....1..5..3.5.8....8.9...6.7...2...1..4.......9.8..5..2....6..4..7.....\tNicolas Juillerat's Sudoku explainer 1.2.1 (top 5)\n12.3.....4.....3....3.5......42..5......8...9.6...5.7...15..2......9..6......7..8\n..3..6.8....1..2......7...4..9..8.6..3..4...1.7.2.....3....5.....5...6..98.....5.\n1.......9..67...2..8....4......75.3...5..2....6.3......9....8..6...4...1..25...6.\n..9...4...7.3...2.8...6...71..8....6....1..7.....56...3....5..1.4.....9...2...7..\n....9..5..1.....3...23..7....45...7.8.....2.......64...9..1.....8..6......54....7\tdukuso's suexrat9 (top 1)\n4...3.......6..8..........1....5..9..8....6...7.2........1.27..5.3....4.9........\tfrom http://magictour.free.fr/topn87 (top 3)\n7.8...3.....2.1...5.........4.....263...8.......1...9..9.6....4....7.5...........\n3.7.4...........918........4.....7.....16.......25..........38..9....5...2.6.....\n........8..3...4...9..2..6.....79.......612...6.5.2.7...8...5...1.....2.4.5.....3\tdukuso's suexratt (top 1)\n.......1.4.........2...........5.4.7..8...3....1.9....3..4..2...5.1........8.6...\tfirst 2 from sudoku17\n.......12....35......6...7.7.....3.....4..8..1...........12.....8.....4..5....6..\n1.......2.9.4...5...6...7...5.3.4.......6........58.4...2...6...3...9.8.7.......1\t2 from http://www.setbb.com/phpbb/viewtopic.php?p=10478\n.....1.2.3...4.5.....6....7..2.....1.8..9..3.4.....8..5....2....9..3.4....67.....\n..............3.85..1.2.......5.7.....4...1...9.......5......73..2.1........4...9\tnear worst case for brute-force solver (wiki)\n.......12........3..23..4....18....5.6..7.8.......9.....85.....9...4.5..47...6...\tgsf's sudoku q1 (Platinum Blonde)\n.2..5.7..4..1....68....3...2....8..3.4..2.5.....6...1...2.9.....9......57.4...9..\t(Cheese)\n........3..1..56...9..4..7......9.5.7.......8.5.4.2....8..2..9...35..1..6........\t(Fata Morgana)\n12.3....435....1....4........54..2..6...7.........8.9...31..5.......9.7.....6...8\t(Red Dwarf)\n1.......2.9.4...5...6...7...5.9.3.......7.......85..4.7.....6...3...9.8...2.....1\t(Easter Monster)\n.......39.....1..5..3.5.8....8.9...6.7...2...1..4.......9.8..5..2....6..4..7.....\tNicolas Juillerat's Sudoku explainer 1.2.1 (top 5)\n12.3.....4.....3....3.5......42..5......8...9.6...5.7...15..2......9..6......7..8\n..3..6.8....1..2......7...4..9..8.6..3..4...1.7.2.....3....5.....5...6..98.....5.\n1.......9..67...2..8....4......75.3...5..2....6.3......9....8..6...4...1..25...6.\n..9...4...7.3...2.8...6...71..8....6....1..7.....56...3....5..1.4.....9...2...7..\n....9..5..1.....3...23..7....45...7.8.....2.......64...9..1.....8..6......54....7\tdukuso's suexrat9 (top 1)\n4...3.......6..8..........1....5..9..8....6...7.2........1.27..5.3....4.9........\tfrom http://magictour.free.fr/topn87 (top 3)\n7.8...3.....2.1...5.........4.....263...8.......1...9..9.6....4....7.5...........\n3.7.4...........918........4.....7.....16.......25..........38..9....5...2.6.....\n........8..3...4...9..2..6.....79.......612...6.5.2.7...8...5...1.....2.4.5.....3\tdukuso's suexratt (top 1)\n.......1.4.........2...........5.4.7..8...3....1.9....3..4..2...5.1........8.6...\tfirst 2 from sudoku17\n.......12....35......6...7.7.....3.....4..8..1...........12.....8.....4..5....6..\n1.......2.9.4...5...6...7...5.3.4.......6........58.4...2...6...3...9.8.7.......1\t2 from http://www.setbb.com/phpbb/viewtopic.php?p=10478\n.....1.2.3...4.5.....6....7..2.....1.8..9..3.4.....8..5....2....9..3.4....67.....\n..............3.85..1.2.......5.7.....4...1...9.......5......73..2.1........4...9\tnear worst case for brute-force solver (wiki)\n.......12........3..23..4....18....5.6..7.8.......9.....85.....9...4.5..47...6...\tgsf's sudoku q1 (Platinum Blonde)\n.2..5.7..4..1....68....3...2....8..3.4..2.5.....6...1...2.9.....9......57.4...9..\t(Cheese)\n........3..1..56...9..4..7......9.5.7.......8.5.4.2....8..2..9...35..1..6........\t(Fata Morgana)\n12.3....435....1....4........54..2..6...7.........8.9...31..5.......9.7.....6...8\t(Red Dwarf)\n1.......2.9.4...5...6...7...5.9.3.......7.......85..4.7.....6...3...9.8...2.....1\t(Easter Monster)\n.......39.....1..5..3.5.8....8.9...6.7...2...1..4.......9.8..5..2....6..4..7.....\tNicolas Juillerat's Sudoku explainer 1.2.1 (top 5)\n12.3.....4.....3....3.5......42..5......8...9.6...5.7...15..2......9..6......7..8\n..3..6.8....1..2......7...4..9..8.6..3..4...1.7.2.....3....5.....5...6..98.....5.\n1.......9..67...2..8....4......75.3...5..2....6.3......9....8..6...4...1..25...6.\n..9...4...7.3...2.8...6...71..8....6....1..7.....56...3....5..1.4.....9...2...7..\n....9..5..1.....3...23..7....45...7.8.....2.......64...9..1.....8..6......54....7\tdukuso's suexrat9 (top 1)\n4...3.......6..8..........1....5..9..8....6...7.2........1.27..5.3....4.9........\tfrom http://magictour.free.fr/topn87 (top 3)\n7.8...3.....2.1...5.........4.....263...8.......1...9..9.6....4....7.5...........\n3.7.4...........918........4.....7.....16.......25..........38..9....5...2.6.....\n........8..3...4...9..2..6.....79.......612...6.5.2.7...8...5...1.....2.4.5.....3\tdukuso's suexratt (top 1)\n.......1.4.........2...........5.4.7..8...3....1.9....3..4..2...5.1........8.6...\tfirst 2 from sudoku17\n.......12....35......6...7.7.....3.....4..8..1...........12.....8.....4..5....6..\n1.......2.9.4...5...6...7...5.3.4.......6........58.4...2...6...3...9.8.7.......1\t2 from http://www.setbb.com/phpbb/viewtopic.php?p=10478\n.....1.2.3...4.5.....6....7..2.....1.8..9..3.4.....8..5....2....9..3.4....67.....\n..............3.85..1.2.......5.7.....4...1...9.......5......73..2.1........4...9\tnear worst case for brute-force solver (wiki)\n.......12........3..23..4....18....5.6..7.8.......9.....85.....9...4.5..47...6...\tgsf's sudoku q1 (Platinum Blonde)\n.2..5.7..4..1....68....3...2....8..3.4..2.5.....6...1...2.9.....9......57.4...9..\t(Cheese)\n........3..1..56...9..4..7......9.5.7.......8.5.4.2....8..2..9...35..1..6........\t(Fata Morgana)\n12.3....435....1....4........54..2..6...7.........8.9...31..5.......9.7.....6...8\t(Red Dwarf)\n1.......2.9.4...5...6...7...5.9.3.......7.......85..4.7.....6...3...9.8...2.....1\t(Easter Monster)\n.......39.....1..5..3.5.8....8.9...6.7...2...1..4.......9.8..5..2....6..4..7.....\tNicolas Juillerat's Sudoku explainer 1.2.1 (top 5)\n12.3.....4.....3....3.5......42..5......8...9.6...5.7...15..2......9..6......7..8\n..3..6.8....1..2......7...4..9..8.6..3..4...1.7.2.....3....5.....5...6..98.....5.\n1.......9..67...2..8....4......75.3...5..2....6.3......9....8..6...4...1..25...6.\n..9...4...7.3...2.8...6...71..8....6....1..7.....56...3....5..1.4.....9...2...7..\n....9..5..1.....3...23..7....45...7.8.....2.......64...9..1.....8..6......54....7\tdukuso's suexrat9 (top 1)\n4...3.......6..8..........1....5..9..8....6...7.2........1.27..5.3....4.9........\tfrom http://magictour.free.fr/topn87 (top 3)\n7.8...3.....2.1...5.........4.....263...8.......1...9..9.6....4....7.5...........\n3.7.4...........918........4.....7.....16.......25..........38..9....5...2.6.....\n........8..3...4...9..2..6.....79.......612...6.5.2.7...8...5...1.....2.4.5.....3\tdukuso's suexratt (top 1)\n.......1.4.........2...........5.4.7..8...3....1.9....3..4..2...5.1........8.6...\tfirst 2 from sudoku17\n.......12....35......6...7.7.....3.....4..8..1...........12.....8.....4..5....6..\n1.......2.9.4...5...6...7...5.3.4.......6........58.4...2...6...3...9.8.7.......1\t2 from http://www.setbb.com/phpbb/viewtopic.php?p=10478\n.....1.2.3...4.5.....6....7..2.....1.8..9..3.4.....8..5....2....9..3.4....67.....\n..............3.85..1.2.......5.7.....4...1...9.......5......73..2.1........4...9\tnear worst case for brute-force solver (wiki)\n.......12........3..23..4....18....5.6..7.8.......9.....85.....9...4.5..47...6...\tgsf's sudoku q1 (Platinum Blonde)\n.2..5.7..4..1....68....3...2....8..3.4..2.5.....6...1...2.9.....9......57.4...9..\t(Cheese)\n........3..1..56...9..4..7......9.5.7.......8.5.4.2....8..2..9...35..1..6........\t(Fata Morgana)\n12.3....435....1....4........54..2..6...7.........8.9...31..5.......9.7.....6...8\t(Red Dwarf)\n1.......2.9.4...5...6...7...5.9.3.......7.......85..4.7.....6...3...9.8...2.....1\t(Easter Monster)\n.......39.....1..5..3.5.8....8.9...6.7...2...1..4.......9.8..5..2....6..4..7.....\tNicolas Juillerat's Sudoku explainer 1.2.1 (top 5)\n12.3.....4.....3....3.5......42..5......8...9.6...5.7...15..2......9..6......7..8\n..3..6.8....1..2......7...4..9..8.6..3..4...1.7.2.....3....5.....5...6..98.....5.\n1.......9..67...2..8....4......75.3...5..2....6.3......9....8..6...4...1..25...6.\n..9...4...7.3...2.8...6...71..8....6....1..7.....56...3....5..1.4.....9...2...7..\n....9..5..1.....3...23..7....45...7.8.....2.......64...9..1.....8..6......54....7\tdukuso's suexrat9 (top 1)\n4...3.......6..8..........1....5..9..8....6...7.2........1.27..5.3....4.9........\tfrom http://magictour.free.fr/topn87 (top 3)\n7.8...3.....2.1...5.........4.....263...8.......1...9..9.6....4....7.5...........\n3.7.4...........918........4.....7.....16.......25..........38..9....5...2.6.....\n........8..3...4...9..2..6.....79.......612...6.5.2.7...8...5...1.....2.4.5.....3\tdukuso's suexratt (top 1)\n.......1.4.........2...........5.4.7..8...3....1.9....3..4..2...5.1........8.6...\tfirst 2 from sudoku17\n.......12....35......6...7.7.....3.....4..8..1...........12.....8.....4..5....6..\n1.......2.9.4...5...6...7...5.3.4.......6........58.4...2...6...3...9.8.7.......1\t2 from http://www.setbb.com/phpbb/viewtopic.php?p=10478\n.....1.2.3...4.5.....6....7..2.....1.8..9..3.4.....8..5....2....9..3.4....67.....\n..............3.85..1.2.......5.7.....4...1...9.......5......73..2.1........4...9\tnear worst case for brute-force solver (wiki)\n.......12........3..23..4....18....5.6..7.8.......9.....85.....9...4.5..47...6...\tgsf's sudoku q1 (Platinum Blonde)\n.2..5.7..4..1....68....3...2....8..3.4..2.5.....6...1...2.9.....9......57.4...9..\t(Cheese)\n........3..1..56...9..4..7......9.5.7.......8.5.4.2....8..2..9...35..1..6........\t(Fata Morgana)\n12.3....435....1....4........54..2..6...7.........8.9...31..5.......9.7.....6...8\t(Red Dwarf)\n1.......2.9.4...5...6...7...5.9.3.......7.......85..4.7.....6...3...9.8...2.....1\t(Easter Monster)\n.......39.....1..5..3.5.8....8.9...6.7...2...1..4.......9.8..5..2....6..4..7.....\tNicolas Juillerat's Sudoku explainer 1.2.1 (top 5)\n12.3.....4.....3....3.5......42..5......8...9.6...5.7...15..2......9..6......7..8\n..3..6.8....1..2......7...4..9..8.6..3..4...1.7.2.....3....5.....5...6..98.....5.\n1.......9..67...2..8....4......75.3...5..2....6.3......9....8..6...4...1..25...6.\n..9...4...7.3...2.8...6...71..8....6....1..7.....56...3....5..1.4.....9...2...7..\n....9..5..1.....3...23..7....45...7.8.....2.......64...9..1.....8..6......54....7\tdukuso's suexrat9 (top 1)\n4...3.......6..8..........1....5..9..8....6...7.2........1.27..5.3....4.9........\tfrom http://magictour.free.fr/topn87 (top 3)\n7.8...3.....2.1...5.........4.....263...8.......1...9..9.6....4....7.5...........\n3.7.4...........918........4.....7.....16.......25..........38..9....5...2.6.....\n........8..3...4...9..2..6.....79.......612...6.5.2.7...8...5...1.....2.4.5.....3\tdukuso's suexratt (top 1)\n.......1.4.........2...........5.4.7..8...3....1.9....3..4..2...5.1........8.6...\tfirst 2 from sudoku17\n.......12....35......6...7.7.....3.....4..8..1...........12.....8.....4..5....6..\n1.......2.9.4...5...6...7...5.3.4.......6........58.4...2...6...3...9.8.7.......1\t2 from http://www.setbb.com/phpbb/viewtopic.php?p=10478\n.....1.2.3...4.5.....6....7..2.....1.8..9..3.4.....8..5....2....9..3.4....67.....\n..............3.85..1.2.......5.7.....4...1...9.......5......73..2.1........4...9\tnear worst case for brute-force solver (wiki)\n.......12........3..23..4....18....5.6..7.8.......9.....85.....9...4.5..47...6...\tgsf's sudoku q1 (Platinum Blonde)\n.2..5.7..4..1....68....3...2....8..3.4..2.5.....6...1...2.9.....9......57.4...9..\t(Cheese)\n........3..1..56...9..4..7......9.5.7.......8.5.4.2....8..2..9...35..1..6........\t(Fata Morgana)\n12.3....435....1....4........54..2..6...7.........8.9...31..5.......9.7.....6...8\t(Red Dwarf)\n1.......2.9.4...5...6...7...5.9.3.......7.......85..4.7.....6...3...9.8...2.....1\t(Easter Monster)\n.......39.....1..5..3.5.8....8.9...6.7...2...1..4.......9.8..5..2....6..4..7.....\tNicolas Juillerat's Sudoku explainer 1.2.1 (top 5)\n12.3.....4.....3....3.5......42..5......8...9.6...5.7...15..2......9..6......7..8\n..3..6.8....1..2......7...4..9..8.6..3..4...1.7.2.....3....5.....5...6..98.....5.\n1.......9..67...2..8....4......75.3...5..2....6.3......9....8..6...4...1..25...6.\n..9...4...7.3...2.8...6...71..8....6....1..7.....56...3....5..1.4.....9...2...7..\n....9..5..1.....3...23..7....45...7.8.....2.......64...9..1.....8..6......54....7\tdukuso's suexrat9 (top 1)\n4...3.......6..8..........1....5..9..8....6...7.2........1.27..5.3....4.9........\tfrom http://magictour.free.fr/topn87 (top 3)\n7.8...3.....2.1...5.........4.....263...8.......1...9..9.6....4....7.5...........\n3.7.4...........918........4.....7.....16.......25..........38..9....5...2.6.....\n........8..3...4...9..2..6.....79.......612...6.5.2.7...8...5...1.....2.4.5.....3\tdukuso's suexratt (top 1)\n.......1.4.........2...........5.4.7..8...3....1.9....3..4..2...5.1........8.6...\tfirst 2 from sudoku17\n.......12....35......6...7.7.....3.....4..8..1...........12.....8.....4..5....6..\n1.......2.9.4...5...6...7...5.3.4.......6........58.4...2...6...3...9.8.7.......1\t2 from http://www.setbb.com/phpbb/viewtopic.php?p=10478\n.....1.2.3...4.5.....6....7..2.....1.8..9..3.4.....8..5....2....9..3.4....67.....\n..............3.85..1.2.......5.7.....4...1...9.......5......73..2.1........4...9\tnear worst case for brute-force solver (wiki)\n.......12........3..23..4....18....5.6..7.8.......9.....85.....9...4.5..47...6...\tgsf's sudoku q1 (Platinum Blonde)\n.2..5.7..4..1....68....3...2....8..3.4..2.5.....6...1...2.9.....9......57.4...9..\t(Cheese)\n........3..1..56...9..4..7......9.5.7.......8.5.4.2....8..2..9...35..1..6........\t(Fata Morgana)\n12.3....435....1....4........54..2..6...7.........8.9...31..5.......9.7.....6...8\t(Red Dwarf)\n1.......2.9.4...5...6...7...5.9.3.......7.......85..4.7.....6...3...9.8...2.....1\t(Easter Monster)\n.......39.....1..5..3.5.8....8.9...6.7...2...1..4.......9.8..5..2....6..4..7.....\tNicolas Juillerat's Sudoku explainer 1.2.1 (top 5)\n12.3.....4.....3....3.5......42..5......8...9.6...5.7...15..2......9..6......7..8\n..3..6.8....1..2......7...4..9..8.6..3..4...1.7.2.....3....5.....5...6..98.....5.\n1.......9..67...2..8....4......75.3...5..2....6.3......9....8..6...4...1..25...6.\n..9...4...7.3...2.8...6...71..8....6....1..7.....56...3....5..1.4.....9...2...7..\n....9..5..1.....3...23..7....45...7.8.....2.......64...9..1.....8..6......54....7\tdukuso's suexrat9 (top 1)\n4...3.......6..8..........1....5..9..8....6...7.2........1.27..5.3....4.9........\tfrom http://magictour.free.fr/topn87 (top 3)\n7.8...3.....2.1...5.........4.....263...8.......1...9..9.6....4....7.5...........\n3.7.4...........918........4.....7.....16.......25..........38..9....5...2.6.....\n........8..3...4...9..2..6.....79.......612...6.5.2.7...8...5...1.....2.4.5.....3\tdukuso's suexratt (top 1)\n.......1.4.........2...........5.4.7..8...3....1.9....3..4..2...5.1........8.6...\tfirst 2 from sudoku17\n.......12....35......6...7.7.....3.....4..8..1...........12.....8.....4..5....6..\n1.......2.9.4...5...6...7...5.3.4.......6........58.4...2...6...3...9.8.7.......1\t2 from http://www.setbb.com/phpbb/viewtopic.php?p=10478\n.....1.2.3...4.5.....6....7..2.....1.8..9..3.4.....8..5....2....9..3.4....67.....\n..............3.85..1.2.......5.7.....4...1...9.......5......73..2.1........4...9\tnear worst case for brute-force solver (wiki)\n.......12........3..23..4....18....5.6..7.8.......9.....85.....9...4.5..47...6...\tgsf's sudoku q1 (Platinum Blonde)\n.2..5.7..4..1....68....3...2....8..3.4..2.5.....6...1...2.9.....9......57.4...9..\t(Cheese)\n........3..1..56...9..4..7......9.5.7.......8.5.4.2....8..2..9...35..1..6........\t(Fata Morgana)\n12.3....435....1....4........54..2..6...7.........8.9...31..5.......9.7.....6...8\t(Red Dwarf)\n1.......2.9.4...5...6...7...5.9.3.......7.......85..4.7.....6...3...9.8...2.....1\t(Easter Monster)\n.......39.....1..5..3.5.8....8.9...6.7...2...1..4.......9.8..5..2....6..4..7.....\tNicolas Juillerat's Sudoku explainer 1.2.1 (top 5)\n12.3.....4.....3....3.5......42..5......8...9.6...5.7...15..2......9..6......7..8\n..3..6.8....1..2......7...4..9..8.6..3..4...1.7.2.....3....5.....5...6..98.....5.\n1.......9..67...2..8....4......75.3...5..2....6.3......9....8..6...4...1..25...6.\n..9...4...7.3...2.8...6...71..8....6....1..7.....56...3....5..1.4.....9...2...7..\n....9..5..1.....3...23..7....45...7.8.....2.......64...9..1.....8..6......54....7\tdukuso's suexrat9 (top 1)\n4...3.......6..8..........1....5..9..8....6...7.2........1.27..5.3....4.9........\tfrom http://magictour.free.fr/topn87 (top 3)\n7.8...3.....2.1...5.........4.....263...8.......1...9..9.6....4....7.5...........\n3.7.4...........918........4.....7.....16.......25..........38..9....5...2.6.....\n........8..3...4...9..2..6.....79.......612...6.5.2.7...8...5...1.....2.4.5.....3\tdukuso's suexratt (top 1)\n.......1.4.........2...........5.4.7..8...3....1.9....3..4..2...5.1........8.6...\tfirst 2 from sudoku17\n.......12....35......6...7.7.....3.....4..8..1...........12.....8.....4..5....6..\n1.......2.9.4...5...6...7...5.3.4.......6........58.4...2...6...3...9.8.7.......1\t2 from http://www.setbb.com/phpbb/viewtopic.php?p=10478\n.....1.2.3...4.5.....6....7..2.....1.8..9..3.4.....8..5....2....9..3.4....67.....\n"
  },
  {
    "path": "benchmarks/graphs.py",
    "content": "import numpy as np\nfrom matplotlib import pyplot as plt\n\nlanguages = np.array([\n    'C', 'C++', 'Cello', \n    'Java', 'Javascript', 'Python', \n    'Ruby', 'Lua', 'Lua JIT'])\n\nexperiments = [\n  'Array', 'Map', 'N-Bodies', \n  'Dictionary', 'Sudoku', 'Matrix', \n  'Garbage Collection']\n    \nresults_array = np.array([\n    0.02, 0.02, 0.10,\n    0.14, 0.07, 0.11, \n    0.07, 2.34, 0.24])\n    \nresults_map = np.array([\n    0.24, 0.05, 0.54,\n    0.60, 1.92, 9.73,\n    1.24, 5.46, 2.01])\n\nresults_nbodies = np.array([\n    0.01, 0.01, 0.07,\n    0.07, 0.09, 1.52,\n    1.45, 0.66, 0.02])\n\nresults_dict = np.array([\n    0.09, 0.13, 0.25,\n    0.24, 0.46, 0.18,\n    0.44, 0.23, 0.18])\n\nresults_sudoku = np.array([\n    0.14, 0.14, 0.15,\n    0.29, 0.44, 5.30,\n    9.64, 6.34, 0.49])\n\nresults_matrix = np.array([\n    0.03,  0.01,  0.02,\n    0.11,  0.23,  2.33,\n    7.62,  0.94,  0.03])\n\nresults_gc = np.array([\n    0.01,  0.01,  0.26,\n    0.06,  0.25,  3.34,\n    5.37,  8.02,  0.31])\n\nresults = [\n    results_array, results_map,    results_nbodies,\n    results_dict,  results_sudoku, results_matrix,\n    results_gc]\n    \n#cols = [\n#    '#006666', '#FF6600', '#991F00',\n#    '#339933', '#009999', '#006666',\n#    '#FF6600', '#991F00', '#339933']\n    \ncols = [\n    '#006666', '#FF6600', '#991F00',\n    '#006666', '#FF6600', '#991F00',\n    '#006666', '#FF6600', '#991F00']\n    \nylims = [\n    3.25, 13.5, 2.2,\n    0.65, 13.5, 11, 11\n]\n    \nfor exp, result, ylim in zip(experiments, results, ylims):\n    \n    fig = plt.figure(figsize=(3, 2.5))\n    ax = fig.add_subplot(1, 1, 1, axisbg='#FCFCFC')\n    \n    bars = ax.bar(np.arange(len(result)), result)\n    \n    for bar, col in zip(bars, cols):\n        bar.set_color(col)\n        bar.set_edgecolor('#555555')\n        height = bar.get_height()\n        ax.text(\n          bar.get_x()+bar.get_width()/1.5, \n          height + (ylim/20), '%0.2f' % height, \n          ha='center', va='bottom', rotation='vertical', \n          color='#555555')\n            \n    plt.xticks(np.arange(len(result)) + 0.75 / 2, languages, rotation='vertical')\n    \n    plt.gca().xaxis.grid(False)\n    plt.gca().yaxis.grid(False)\n    plt.ylim((0, ylim))\n    plt.tight_layout()\n    plt.show()\n        \n    \n"
  },
  {
    "path": "examples/cello_world.c",
    "content": "#include \"Cello.h\"\n\nint main(int argc, char** argv) {\n  println(\"Cello World!\");\n  return 0;\n}\n"
  },
  {
    "path": "examples/help.c",
    "content": "#include \"Cello.h\"\n\nint main(int argc, char** argv) {\n  \n  help(Range);\n  \n  return 0;\n}\n\n"
  },
  {
    "path": "examples/iteration.c",
    "content": "#include \"Cello.h\"\n\nint main(int argc, char** argv) {\n\n  /* Stack objects are created using \"$\" */\n  var i0 = $(Int, 5);\n  var i1 = $(Int, 3);\n  var i2 = $(Int, 4);\n\n  /* Heap objects are created using \"new\" */\n  var items = new(Array, Int, i0, i1, i2);\n\n  /* Collections can be looped over */\n  foreach (item in items) {\n    print(\"Object %$ is of type %$\\n\",\n      item, type_of(item));\n  }\n  \n  return 0;\n}\n\n"
  },
  {
    "path": "examples/newtype.c",
    "content": "#include \"Cello.h\"\n\n/* Type Variable */\nstatic var ExampleType;\n\n/* Type Struct */\nstruct ExampleType {\n  int value;\n};\n\n/* Constructor Function */\nstatic void ExampleType_New(var self, var args) {\n  struct ExampleType* h = self;\n  h->value = c_int(get(args, $I(0)));\n}\n\n/* Comparison Function */\nstatic int ExampleType_Cmp(var self, var obj) {\n  struct ExampleType* lhs = self;\n  struct ExampleType* rhs = cast(obj, ExampleType);\n  return lhs->value - rhs->value;\n}\n\nint main(int argc, char** argv) {\n  \n  /* Construct `ExampleType` type dynamically */\n  ExampleType = new_root(Type,\n    $S(\"ExampleType\"),              /* Type Name */ \n    $I(sizeof(struct ExampleType)), /* Type Size */ \n    $(New, ExampleType_New, NULL),  /* Type Interfaces */\n    $(Cmp, ExampleType_Cmp));       /* ... */\n  \n  print(\"%$ is a %$!\\n\", ExampleType, type_of(ExampleType));\n\n  /* We can now make `ExampleType` objects */\n  var obj0 = new(ExampleType, $I(1));\n  var obj1 = new(ExampleType, $I(2));\n  \n  /* Test for comparison etc... */\n  print(\"Is %$ less Than %$? %s\\n\", \n    obj0, obj1, lt(obj0, obj1) ? $S(\"Yes\") : $S(\"No\"));\n  \n  /* Type objects must remain around longer than their instances */\n  del(obj0); del(obj1);\n  \n  del_root(ExampleType);\n  \n  return 0;\n  \n}\n\n"
  },
  {
    "path": "examples/object.c",
    "content": "#include \"Cello.h\"\n\n/* Define a normal C structure */\nstruct Point {\n  float x, y;\n};\n\n/* Make it compatible with Cello */\nvar Point = Cello(Point);\n\nint main(int argc, char** argv) {\n  \n  /* Create on Stack or Heap */\n  var p0 = $(Point, 0.0, 1.0);\n  var p1 = new(Point, $(Point, 0.0, 2.0));\n  \n  /* It can be shown, compared, hashed, etc...\n  **\n  ** p0: <'Point' At 0x000000000022FC58>\n  ** p1: <'Point' At 0x00000000004C7CC8>\n  ** cmp: 1\n  ** hash: 2849275892l\n  */ \n  print(\"p0: %$\\np1: %$\\ncmp: %i\\nhash: %ul\\n\",\n    p0, p1, $I(cmp(p0, p1)), $I(hash(p0)));\n  \n  /* And collected by the GC when out of scope */\n  return 0;\n}"
  },
  {
    "path": "examples/ranges.c",
    "content": "#include \"Cello.h\"\n\nint main(int argc, char** argv) {\n\n  var items = new(Array, Int, \n    $I( 8), $I( 5), $I(20), \n    $I(15), $I(16), $I(98));\n\n  /* Iterate over indices using \"range\" */\n  foreach (i in range($I(len(items)))) {\n    print(\"Item Range %i is %i\\n\", i, get(items, i));\n  }\n\n  /* Iterate over every other item with \"slice\" */ \n  foreach (item in slice(items, _, _, $I(2))) {\n    print(\"Item Slice %i\\n\", item);\n  }\n  \n  return 0;\n}\n\n"
  },
  {
    "path": "examples/table.c",
    "content": "#include \"Cello.h\"\n\nint main(int argc, char** argv) {\n\n  /* Shorthand $ can be used for basic types */\n  var prices = new(Table, String, Int);\n  set(prices, $S(\"Apple\"),  $I(12)); \n  set(prices, $S(\"Banana\"), $I( 6)); \n  set(prices, $S(\"Pear\"),   $I(55));\n\n  /* Tables also support iteration */\n  foreach (key in prices) {\n    var val = get(prices, key);\n    print(\"Price of %$ is %$\\n\", key, val);\n  }\n\n  return 0;\n}\n\n"
  },
  {
    "path": "examples/threads.c",
    "content": "#include \"Cello.h\"\n\n/* Threaded Callback */\nvar say_hello(var args) {\n  with (mutex in get(args, $I(0))) {\n    println(\"Hello from %$!\", current(Thread));\n  }\n  return NULL;\n}\n\nint main(int argc, char** argv) {\n\n  /* Create a Mutex */\n  var mutex = new(Mutex);\n  \n  /* Create Several Threads */\n  var threads = new(Array, Thread,\n    new(Thread, $(Function, say_hello)),\n    new(Thread, $(Function, say_hello)),\n    new(Thread, $(Function, say_hello)),\n    new(Thread, $(Function, say_hello)));\n  \n  /* Call each Thread */\n  foreach (t in threads) { call(t, mutex); }\n  \n  /* Wait for each Thread to finish */\n  foreach (t in threads) { join(t); }\n  \n  return 0;\n}\n"
  },
  {
    "path": "include/Cello.h",
    "content": "/*\n**         $$===================================================$$\n**         ||                                                   ||\n**         ||          ,;,                ___     _ _           ||\n**         ||         +($)+              / __|___| | |___       ||\n**         ||         +($)+             | (__/ -_) | / _ \\      ||\n**         ||          |||           lib \\___\\___|_|_\\___/      ||\n**         ||          |||                                      ||\n**         ||          |||    /#           High Level           ||\n**         ||         _|||_  /'         Programming in C        ||\n**         ||       .' ||| '/                                   ||\n**         ||      /   ||| / \\        http://libcello.org/      ||\n**         ||      |   |||/  |                                  ||\n**         ||      )_  ||/  _(         Licensed under BSD       ||\n**         ||       _) |/| (_                                   ||\n**         ||      )   /||   (                                  ||\n**         ||     /  }/+++ {  \\                                 ||\n**         ||    |  {/ |||  }  |                                ||\n**         ||    |  /  ~~~     |                                ||\n**         ||     \\/   \\ /    /                                 ||\n**         ||     /`-.__Y__.-`                                  ||\n**         ||    '-     |              Daniel Holden            ||\n**         ||           |                                       ||\n**         ||           !      contact@theorangeduck.com        ||\n**         ||                                                   ||\n**         ||       https://github.com/orangeduck/libCello      ||\n**         ||                                                   ||\n**         $$===================================================$$\n*/\n\n#ifndef CELLO_H\n#define CELLO_H\n\n/* Settings */\n\n#ifdef  CELLO_NDEBUG\n#define CELLO_BOUND_CHECK  0\n#define CELLO_MAGIC_CHECK  0\n#define CELLO_ALLOC_CHECK  0\n#define CELLO_NULL_CHECK   0\n#define CELLO_METHOD_CHECK 0\n#define CELLO_MEMORY_CHECK 0\n#else\n#define CELLO_BOUND_CHECK  1\n#define CELLO_MAGIC_CHECK  1\n#define CELLO_ALLOC_CHECK  1\n#define CELLO_NULL_CHECK   1\n#define CELLO_METHOD_CHECK 1\n#define CELLO_MEMORY_CHECK 1\n#endif\n\n#if CELLO_ALLOC_CHECK == 1\n#define CELLO_ALLOC_HEADER (var)AllocStatic,\n#else\n#define CELLO_ALLOC_HEADER\n#endif\n\n#if CELLO_MAGIC_CHECK == 1\n#define CELLO_MAGIC_NUM 0xCe110\n#define CELLO_MAGIC_HEADER ((var)CELLO_MAGIC_NUM),\n#else\n#define CELLO_MAGIC_HEADER\n#endif\n\n#ifndef CELLO_CACHE\n#define CELLO_CACHE 1\n#define CELLO_CACHE_HEADER \\\n  NULL, NULL, NULL, NULL, NULL, NULL, \\\n  NULL, NULL, NULL, NULL, NULL, NULL, \\\n  NULL, NULL, NULL, NULL, NULL, NULL,\n#define CELLO_CACHE_NUM 18\n#else\n#define CELLO_CACHE 0\n#define CELLO_CACHE_HEADER\n#define CELLO_CACHE_NUM 0\n#endif\n\n#ifdef _WIN32\n#define CELLO_WINDOWS\n#endif\n\n#ifdef __unix__\n#define CELLO_UNIX\n#define CELLO_LINUX\n#endif\n\n#ifdef __APPLE__\n#define CELLO_UNIX\n#define CELLO_MAC\n#endif\n\n#ifdef _MSC_VER\n#define CELLO_MSC\n#define popen _popen\n#define pclose _pclose\n#define __func__ __FUNCTION__\n#ifndef CELLO_NSTRACE \n#pragma comment(lib, \"DbgHelp.lib\")\n#endif\n#endif\n\n#if defined __has_feature\n# if __has_feature(address_sanitizer)\n#   if defined __clang__ \n#     define CELLO_NASAN __attribute__((no_sanitize(\"address\")))\n#   else\n#     define CELLO_NASAN\n#   endif\n# else\n#     define CELLO_NASAN\n# endif\n#else\n# define CELLO_NASAN\n#endif\n\n/* Includes */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <stdarg.h>\n#include <stddef.h>\n#include <stdbool.h>\n#include <setjmp.h>\n#include <signal.h>\n#include <string.h>\n#include <errno.h>\n#include <math.h>\n#include <time.h>\n\n#ifdef CELLO_WINDOWS\n#include <windows.h>\n#ifndef CELLO_NSTRACE\n#include <DbgHelp.h>\n#endif\n#endif\n\n#ifdef CELLO_UNIX\n#include <pthread.h>\n#ifndef CELLO_NSTRACE\n#include <execinfo.h>\n#endif\n#endif\n\n/* Syntax */\n\ntypedef void* var;\n\n#define is ==\n#define isnt !=\n#define not !\n#define and &&\n#define or ||\n#define in ,\n\n/* Declaration */\n\n#define Cello(T, ...) CelloStruct(T, ##__VA_ARGS__)\n#define CelloStruct(T, ...) CelloObject(T, sizeof(struct T), ##__VA_ARGS__)\n#define CelloEmpty(T, ...) CelloObject(T, 0, ##__VA_ARGS__)\n#define CelloObject(T, S, ...) (var)((char*)((var[]){ NULL, \\\n  CELLO_ALLOC_HEADER       \\\n  CELLO_MAGIC_HEADER       \\\n  CELLO_CACHE_HEADER       \\\n  NULL, \"__Name\",     #T,  \\\n  NULL, \"__Size\", (var)S,  \\\n  ##__VA_ARGS__,           \\\n  NULL, NULL, NULL}) +     \\\n  sizeof(struct Header))\n\n#define Instance(I, ...) NULL, #I, &((struct I){__VA_ARGS__})\n\n/* Types */\n\nextern var Type;\nextern var Tuple;\n\nextern var Ref;\nextern var Box;\nextern var Int;\nextern var Float;\nextern var String;\n\nextern var Tree;\nextern var List;\nextern var Array;\nextern var Table;\nextern var Range;\nextern var Slice;\nextern var Zip;\nextern var Filter;\nextern var Map;\nextern var Terminal;\nextern var _;\n\nextern var File;\nextern var Mutex;\nextern var Thread;\nextern var Process;\nextern var Function;\n\nextern var Exception;\nextern var IOError;\nextern var KeyError;\nextern var BusyError;\nextern var TypeError;\nextern var ValueError;\nextern var ClassError;\nextern var FormatError;\nextern var ResourceError;\nextern var OutOfMemoryError;\nextern var IndexOutOfBoundsError;\nextern var SegmentationError;\nextern var ProgramAbortedError;\nextern var DivisionByZeroError;\nextern var IllegalInstructionError;\nextern var ProgramInterruptedError;\nextern var ProgramTerminationError;\n\n\n/* Data */\n\nenum {\n  AllocStatic = 0x01, AllocStack = 0x02,\n  AllocHeap   = 0x03, AllocData  = 0x04\n};\n\nstruct Header {\n  var type;\n#if CELLO_ALLOC_CHECK == 1\n  var alloc;\n#endif\n#if CELLO_MAGIC_CHECK == 1\n  var magic;\n#endif\n};\n\nstruct Type {\n  var cls;\n  var name;\n  var inst;\n};\n\nstruct Ref {\n  var val;\n};\n\nstruct Box {\n  var val;\n};\n\nstruct Int {\n  int64_t val;\n};\n\nstruct Float {\n  double val;\n};\n\nstruct String {\n  char* val;\n};\n\nstruct Tuple {\n  var* items;\n};\n\nstruct Range {\n  var value;\n  int64_t start;\n  int64_t stop;\n  int64_t step;\n};\n\nstruct Slice {\n  var iter;\n  var range;\n};\n\nstruct Zip {\n  var iters;\n  var values;\n};\n\nstruct Filter {\n  var iter;\n  var func;\n};\n\nstruct Map {\n  var iter;\n  var curr;\n  var func;\n};\n\nstruct File {\n  FILE* file;\n};\n\nstruct Process {\n  FILE* proc;\n};\n\nstruct Function {\n  var (*func)(var);\n};\n\n/* Classes */\n\nextern var Doc;\nextern var Help;\nextern var Cast;\nextern var Size;\nextern var Alloc;\nextern var New;\nextern var Copy;\nextern var Assign;\nextern var Swap;\nextern var Cmp;\nextern var Hash;\nextern var Len;\nextern var Iter;\nextern var Push;\nextern var Concat;\nextern var Get;\nextern var Sort;\nextern var Resize;\nextern var C_Str;\nextern var C_Int;\nextern var C_Float;\nextern var Stream;\nextern var Pointer;\nextern var Call;\nextern var Format;\nextern var Show;\nextern var Current;\nextern var Start;\nextern var Lock;\nextern var Mark;\n\n/* Signatures */\n\nstruct Example {\n  const char* name;\n  const char* body;\n};\n\nstruct Method {\n  const char* name;\n  const char* definition;\n  const char* description;\n};\n\nstruct Doc {\n  const char* (*name)(void);\n  const char* (*brief)(void);\n  const char* (*description)(void);\n  const char* (*definition)(void);\n  struct Example* (*examples)(void);\n  struct Method* (*methods)(void);\n};\n\nstruct Help {\n  int (*help_to)(var, var, int);\n};\n\nstruct Cast {\n  var (*cast)(var, var);\n};\n\nstruct Size {\n  size_t (*size)(void);\n};\n\nstruct Alloc {\n  var (*alloc)(void);\n  void (*dealloc)(var);\n};\n\nstruct New {\n  void (*construct_with)(var, var);\n  void (*destruct)(var);\n};\n\nstruct Copy {\n  var (*copy)(var);\n};\n\nstruct Assign {\n  void (*assign)(var, var);\n};\n\nstruct Swap {\n  void (*swap)(var, var);\n};\n\nstruct Cmp {\n  int (*cmp)(var, var);\n};\n\nstruct Hash {\n  uint64_t (*hash)(var);\n};\n\nstruct Len {\n  size_t (*len)(var);\n};\n\nstruct Push {\n  void (*push)(var, var);\n  void (*pop)(var);\n  void (*push_at)(var, var, var);\n  void (*pop_at)(var, var);\n};\n\nstruct Concat {\n  void (*concat)(var, var);\n  void (*append)(var, var);\n};\n\nstruct Get {\n  var  (*get)(var, var);\n  void (*set)(var, var, var);\n  bool (*mem)(var, var);\n  void (*rem)(var, var);\n  var (*key_type)(var);\n  var (*val_type)(var);\n};\n\nstruct Iter {\n  var (*iter_init)(var);\n  var (*iter_next)(var, var);\n  var (*iter_last)(var);\n  var (*iter_prev)(var, var);\n  var (*iter_type)(var);  \n};\n\nstruct Sort {\n  void (*sort_by)(var,bool(*f)(var,var));\n};\n\nstruct Resize {\n  void (*resize)(var, size_t);\n};\n\nstruct C_Str {\n  char* (*c_str)(var);\n};\n\nstruct C_Int {\n  int64_t (*c_int)(var);\n};\n\nstruct C_Float {\n  double (*c_float)(var);\n};\n\nstruct Stream {\n  var  (*sopen)(var,var,var);\n  void (*sclose)(var);\n  void (*sseek)(var,int64_t,int);\n  int64_t (*stell)(var);\n  void (*sflush)(var);\n  bool (*seof)(var);\n  size_t (*sread)(var,void*,size_t);\n  size_t (*swrite)(var,void*,size_t);\n};\n\nstruct Pointer {\n  void (*ref)(var, var);\n  var (*deref)(var);\n};\n\nstruct Call {\n  var (*call_with)(var, var);\n};\n\nstruct Format {\n  int (*format_to)(var,int,const char*,va_list);\n  int (*format_from)(var,int,const char*,va_list);\n};\n\nstruct Show {\n  int (*show)(var, var, int);\n  int (*look)(var, var, int);\n};\n\nstruct Current {\n  var (*current)(void);\n};\n\nstruct Start {\n  void (*start)(var);\n  void (*stop)(var);\n  void (*join)(var);\n  bool (*running)(var);\n};\n\nstruct Lock {\n  void (*lock)(var);\n  void (*unlock)(var);\n  bool (*trylock)(var);\n};\n\nstruct Mark {\n  void (*mark)(var, var, void(*)(var,void*));\n};\n\n/* Functions */\n\nconst char* name(var type);\nconst char* brief(var type);\nconst char* description(var type);\nconst char* definition(var type);\n\nvoid help(var self);\nint help_to(var out, int pos, var self);\n\nvar type_of(var self);\nvar cast(var self, var type);\nvar instance(var self, var cls);\nbool implements(var self, var cls);\nvar type_instance(var type, var cls);\nbool type_implements(var type, var cls);\n\n#define method(X, C, M, ...) \\\n  ((struct C*)method_at_offset(X, C, \\\n  offsetof(struct C, M), #M))->M(X, ##__VA_ARGS__)\n\n#define implements_method(X, C, M) \\\n  implements_method_at_offset(X, C, offsetof(struct C, M))\n  \n#define type_method(T, C, M, ...) \\\n  ((struct C*)type_method_at_offset(T, C, \\\n  offsetof(struct C, M), #M))->M(__VA_ARGS__)\n  \n#define type_implements_method(T, C, M) \\\n  type_implements_method_at_offset(T, C, offsetof(struct C, M))\n  \nvar method_at_offset(var self, var cls, size_t offset, const char* method);\nbool implements_method_at_offset(var self, var cls, size_t offset);\n\nvar type_method_at_offset(var self, var cls, size_t offset, const char* method);\nbool type_implements_method_at_offset(var self, var cls, size_t offset);\n\nstruct Header* header(var self);\nvar header_init(var head, var type, int alloc);\n\nsize_t size(var type);\n\nvar alloc(var type);\nvar alloc_raw(var type);\nvar alloc_root(var type);\n\n#define alloc_stack(T) ((struct T*)header_init( \\\n  (char[sizeof(struct Header) + sizeof(struct T)]){0}, T, AllocStack))\n\nvoid dealloc(var self);\nvoid dealloc_raw(var self);\nvoid dealloc_root(var self);\n\n#define $(T, ...) ((struct T*)memcpy( \\\n  alloc_stack(T), &((struct T){__VA_ARGS__}), sizeof(struct T)))\n\n#define $I(X) $(Int, X)\n#define $F(X) $(Float, X)\n#define $S(X) $(String, X)\n#define $R(X) $(Ref, X)\n#define $B(X) $(Box, X)\n\n#define tuple(...) tuple_xp(tuple_in, (_, ##__VA_ARGS__, Terminal))\n#define tuple_xp(X, A) X A\n#define tuple_in(_, ...) $(Tuple, (var[]){ __VA_ARGS__ })\n\n#define construct(self, ...) construct_with(self, tuple(__VA_ARGS__))\nvar construct_with(var self, var args);\nvar destruct(var self);\n\n#define new(T, ...) ((struct T*)new_with(T, tuple(__VA_ARGS__)))\n#define new_raw(T, ...) ((struct T*)new_raw_with(T, tuple(__VA_ARGS__)))\n#define new_root(T, ...) ((struct T*)new_root_with(T, tuple(__VA_ARGS__)))\n\nvar new_with(var type, var args);\nvar new_raw_with(var type, var args);\nvar new_root_with(var type, var args);\n\nvoid del(var self);\nvoid del_raw(var self);\nvoid del_root(var self);\n\nvar assign(var self, var obj);\nvar copy(var self);\nvoid swap(var self, var obj);\n\nint cmp(var self, var obj);\nbool eq(var self, var obj);\nbool neq(var self, var obj);\nbool gt(var self, var obj);\nbool lt(var self, var obj);\nbool ge(var self, var obj);\nbool le(var self, var obj);\n\nuint64_t hash(var self);\nuint64_t hash_data(const void* data, size_t num);\n\nvar iter_init(var self);\nvar iter_next(var self, var curr);\nvar iter_prev(var self, var curr);\nvar iter_last(var self);\nvar iter_type(var self);\n\n#define foreach(...) foreach_xp(foreach_in, (__VA_ARGS__))\n#define foreach_xp(X, A) X A\n#define foreach_in(X, S) for(var \\\n  __##X = (S), \\\n  __Iter##X = instance(__##X, Iter), \\\n  X = ((struct Iter*)(__Iter##X))->iter_init(__##X); \\\n  X isnt Terminal; \\\n  X = ((struct Iter*)(__Iter##X))->iter_next(__##X, X))\n\nvoid push(var self, var obj);\nvoid pop(var self);\nvoid push_at(var self, var obj, var key);\nvoid pop_at(var self, var key);\n\nvoid sort(var self);\nvoid sort_by(var self, bool(*f)(var,var));\n\nvoid append(var self, var obj);\nvoid concat(var self, var obj);\n\nvar  get(var self, var key);\nvoid set(var self, var key, var val);\nbool mem(var self, var key);\nvoid rem(var self, var key);\nvar key_type(var self);\nvar val_type(var self);\n\nvoid resize(var self, size_t n);\nsize_t len(var self);\nbool empty(var self);\n\nchar* c_str(var self);\nint64_t c_int(var self);\ndouble c_float(var self);\n\n#define range(...) range_stack($(Range, $I(0), 0, 0, 0), tuple(__VA_ARGS__))\n\n#define slice(I, ...) slice_xp(slice_in, (I, ##__VA_ARGS__))\n#define slice_xp(X, A) X A\n#define slice_in(...) slice_stack( \\\n  $(Slice, NULL, $(Range, $I(0), 0, 0, 0)), tuple(__VA_ARGS__))\n\n#define reverse(I) slice(I, _, _, $I(-1))\n#define filter(I, F) $(Filter, I, F)\n#define map(I, F) $(Map, I, NULL, F)\n\n#define zip(...) zip_stack( \\\n  $(Zip, tuple(__VA_ARGS__), \\\n  $(Tuple, (var[(sizeof((var[]){__VA_ARGS__})/sizeof(var))+1]){0})))\n\n#define enumerate(I) enumerate_stack(zip(range(), I))\n\nvar range_stack(var self, var args);\nvar slice_stack(var self, var args);\nvar zip_stack(var self);\nvar enumerate_stack(var self);\n\nvar sopen(var self, var resource, var options);\nvoid sclose(var self);\nvoid sseek(var self, int64_t pos, int origin);\nint64_t stell(var self);\nvoid sflush(var self);\nbool seof(var self);\nsize_t sread(var self, void* output, size_t size);\nsize_t swrite(var self, void* input, size_t size);\n\nvoid ref(var self, var item);\nvar deref(var self);\n\n#define call(self, ...) call_with(self, tuple(__VA_ARGS__))\nvar call_with(var self, var args);\n\nint format_to_va(var self, int pos, const char* fmt, va_list va);\nint format_from_va(var self, int pos, const char* fmt, va_list va);\n\nint format_to(var self, int pos, const char* fmt, ...);\nint format_from(var self, int pos, const char* fmt, ...);\n\nint show(var self);\nint show_to(var self, var out, int pos);\n\n#define print(fmt, ...) print_with(fmt, tuple(__VA_ARGS__))\n#define println(fmt, ...) println_with(fmt, tuple(__VA_ARGS__))\n#define print_to(out, pos, fmt, ...) \\\n  print_to_with(out, pos, fmt, tuple(__VA_ARGS__))\n\nint print_with(const char* fmt, var args);\nint println_with(const char* fmt, var args);\nint print_to_with(var out, int pos, const char* fmt, var args);\n\nint look(var self);\nint look_from(var self, var input, int pos);\n\n#define scan(fmt, ...) scan_with(fmt, tuple(__VA_ARGS__))\n#define scanln(fmt, ...) scanln_with(fmt, tuple(__VA_ARGS__))\n#define scan_from(input, pos, fmt, ...) \\\n  scan_from_with(input, pos, fmt, tuple(__VA_ARGS__))\n\nint scan_with(const char* fmt, var args);\nint scanln_with(const char* fmt, var args);\nint scan_from_with(var input, int pos, const char* fmt, var args);\n\nvar current(var type);\n\nvoid start(var self);\nvoid stop(var self);\nvoid join(var self);\nbool running(var self);\n\nvar start_in(var self);\nvar stop_in(var self);\n\n#define with(...) with_xp(with_in, (__VA_ARGS__))\n#define with_xp(X, A) X A\n#define with_in(X, S) for(var X = start_in(S); X isnt NULL; X = stop_in(X))\n\nvoid lock(var self);\nbool trylock(var self);\nvoid unlock(var self);\n\n#define try { jmp_buf __env; exception_try(&__env); if (!setjmp(__env))\n\n#define catch(...) catch_xp(catch_in, (__VA_ARGS__))\n#define catch_xp(X, A) X A\n#define catch_in(X, ...) else { exception_try_fail(); } exception_try_end(); } \\\n  for (var X = exception_catch(tuple(__VA_ARGS__)); \\\n    X isnt NULL; X = NULL)\n\n#define throw(E, F, ...) exception_throw(E, F, tuple(__VA_ARGS__))\n\nvoid exception_try(jmp_buf* env);\nvoid exception_try_end(void);\nvoid exception_try_fail(void);\nvar exception_throw(var obj, const char* fmt, var args);\nvar exception_catch(var args);\n\nvoid exception_signals(void);\n\nvar exception_object(void);\nvar exception_message(void);\n\nvoid mark(var self, var gc, void(*f)(var,void*));\n\n#ifndef CELLO_NGC\n\nextern var GC;\n\nint Cello_Main(int argc, char** argv);\nvoid Cello_Exit(void);\n\n#define main(...) \\\n  main(int argc, char** argv) { \\\n    var bottom = NULL; \\\n    new_raw(GC, $R(&bottom)); \\\n    atexit(Cello_Exit); \\\n    return Cello_Main(argc, argv); \\\n  }; \\\n  int Cello_Main(__VA_ARGS__)\n\n#endif\n  \n#endif\n"
  },
  {
    "path": "src/Alloc.c",
    "content": "#include \"Cello.h\"\n\nstruct Header* header(var self) {\n  return (struct Header*)((char*)self - sizeof(struct Header));\n}\n\nvar header_init(var head, var type, int alloc) {\n  \n  struct Header* self = head;\n  \n  self->type = type;\n  \n#if CELLO_ALLOC_CHECK == 1\n  self->alloc = (var)(intptr_t)alloc;\n#endif\n  \n#if CELLO_MAGIC_CHECK == 1\n  self->magic = (var)CELLO_MAGIC_NUM;\n#endif\n\n  return ((char*)self) + sizeof(struct Header);\n}\n\nstatic const char* Alloc_Name(void) {\n  return \"Alloc\";\n}\n\nstatic const char* Alloc_Brief(void) {\n  return \"Memory Allocation\";\n}\n\nstatic const char* Alloc_Description(void) {\n  return\n    \"The `Alloc` class can be used to override how memory is allocated for a \"\n    \"given data type. By default memory is allocated using `calloc` along with \"\n    \"the `Size` class to determine the amount of memory to allocate.\"\n    \"\\n\\n\"\n    \"A custom allocator should be careful to also initialise the header for \"\n    \"the allocated memory using the function `header_init`. Cello objects \"\n    \"without a header wont be recognised as such as so will throw errors when \"\n    \"used with Cello functions.\"\n    \"\\n\\n\"\n    \"Allocated memory is automatically registered with the garbage collector \"\n    \"unless the functions `alloc_raw` and `dealloc_raw` are used.\"\n  ;\n}\n\nstatic const char* Alloc_Definition(void) {\n  return\n    \"struct Alloc {\\n\"\n    \"  var (*alloc)(void);\\n\"\n    \"  void (*dealloc)(var);\\n\"\n    \"};\";\n}\n\nstatic struct Example* Alloc_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n     \"Usage\",\n     \"/* Allocation deallocated by Garbage Collector */\\n\"\n     \"var x = alloc(Int);\\n\"\n     \"construct(x, $I(10));\\n\",\n    }, {\n     \"Avoid Garbage Collection\",\n     \"/* Allocation must be manually deallocated */\\n\"\n     \"var x = alloc_raw(Int);\\n\"\n     \"construct(x, $I(10));\\n\"\n     \"destruct(x);\\n\"\n     \"dealloc_raw(x);\\n\",\n    }, {NULL, NULL}\n  };\n  \n  return examples;\n}\n\nstatic struct Method* Alloc_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"$\",\n      \"#define $(T, ...)\\n\"\n      \"#define $I(X)\\n\"\n      \"#define $F(X)\\n\"\n      \"#define $S(X)\\n\"\n      \"#define $R(X)\\n\"\n      \"#define $B(X)\",\n      \"Allocate memory for the given type `T` on the stack and copy in the \"\n      \"given arguments `...` as struct members. Shorthand constructors exist \"\n      \"for native types:\\n\\n* `$I -> Int` `$F -> Float` `$S -> String`\\n*\"\n      \" `$R -> Ref` `$B -> Box`\\n\\n\"\n    }, {\n      \"alloc\", \n      \"#define alloc_stack(T)\\n\"\n      \"var alloc(var type);\\n\"\n      \"var alloc_raw(var type);\\n\"\n      \"var alloc_root(var type);\",\n      \"Allocate memory for a given `type`. To avoid the Garbage Collector \"\n      \"completely use `alloc_raw`, to register the allocation as a root use \"\n      \"`alloc_root`. In the case of raw or root allocations the corresponding \"\n      \"`dealloc` function should be used when done. Memory allocated with \"\n      \"`alloc_stack` is not managed by the Garbage Collector.\"\n    }, {\n      \"dealloc\",\n      \"void dealloc(var self);\\n\"\n      \"void dealloc_raw(var self);\\n\"\n      \"void dealloc_root(var self);\",\n      \"Deallocate memory for object `self` manually. If registered with the \"\n      \"Garbage Collector then entry will be removed. If the `raw` variation is \"\n      \"used memory will be deallocated without going via the Garbage Collector.\" \n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nvar Alloc = Cello(Alloc, Instance(Doc, \n  Alloc_Name,       Alloc_Brief,    Alloc_Description, \n  Alloc_Definition, Alloc_Examples, Alloc_Methods));\n\nenum {\n  ALLOC_STANDARD,\n  ALLOC_RAW,\n  ALLOC_ROOT\n};\n  \nstatic var alloc_by(var type, int method) {\n  \n  struct Alloc* a = type_instance(type, Alloc);\n  var self;\n  if (a and a->alloc) {\n    self = a->alloc();\n  } else {\n    struct Header* head = calloc(1, sizeof(struct Header) + size(type));  \n\n#if CELLO_MEMORY_CHECK == 1\n    if (head is NULL) {\n      throw(OutOfMemoryError, \"Cannot create new '%s', out of memory!\", type);\n    }\n#endif\n    \n    self = header_init(head, type, AllocHeap);\n  }\n\n  switch (method) {\n    case ALLOC_STANDARD:\n#ifndef CELLO_NGC\n    set(current(GC), self, $I(0));\n#endif\n    break;\n    case ALLOC_RAW: break;\n    case ALLOC_ROOT:\n#ifndef CELLO_NGC\n    set(current(GC), self, $I(1));\n#endif\n    break;\n  }\n  \n  return self;\n}\n\nvar alloc(var type)      { return alloc_by(type, ALLOC_STANDARD); }\nvar alloc_raw(var type)  { return alloc_by(type, ALLOC_RAW); }\nvar alloc_root(var type) { return alloc_by(type, ALLOC_ROOT); }\n\nvoid dealloc(var self) {\n\n  struct Alloc* a = instance(self, Alloc);\n  if (a and a->dealloc) {\n    a->dealloc(self);\n    return;\n  }\n\n#if CELLO_ALLOC_CHECK == 1\n  if (self is NULL) {\n    throw(ResourceError, \"Attempt to deallocate NULL!\"); \n  }\n\n  if (header(self)->alloc is (var)AllocStatic) {\n    throw(ResourceError,\n      \"Attempt to deallocate %$ \"\n      \"which was allocated statically!\", self); \n  }\n  \n  if (header(self)->alloc is (var)AllocStack) {\n    throw(ResourceError,\n      \"Attempt to deallocate %$ \"\n      \"which was allocated on the stack!\", self); \n  }\n  \n  if (header(self)->alloc is (var)AllocData) {\n    throw(ResourceError,\n      \"Attempt to deallocate %$ \"\n      \"which was allocated inside a data structure!\", self); \n  }\n#endif\n  \n#if CELLO_ALLOC_CHECK == 1\n  size_t s = size(type_of(self));\n  for (size_t i = 0; i < (sizeof(struct Header) + s) / sizeof(var); i++) {\n    ((var*)header(self))[i] = (var)0xDeadCe110;\n  }\n#endif\n  \n  free(((char*)self) - sizeof(struct Header));\n  \n}\n\nvoid dealloc_raw(var self)  { dealloc(self); }\nvoid dealloc_root(var self) { dealloc(self); }\n\nstatic const char* New_Name(void) {\n  return \"New\";\n}\n\nstatic const char* New_Brief(void) {\n  return \"Construction and Destruction\";\n}\n\nstatic const char* New_Description(void) {\n  return\n    \"The `New` class allows the user to define constructors and destructors \"\n    \"for a type, accessible via `new` and `del`. Objects allocated with `new` \"\n    \"are allocated on the heap and also registered with the Garbage Collector \"\n    \"this means technically it isn't required to call `del` on them as they \"\n    \"will be cleaned up at a later date.\"\n    \"\\n\\n\"\n    \"The `new_root` function can be called to register a variable with the \"\n    \"Garbage Collector but to indicate that it will be manually destructed \"\n    \"with `del_root` by the user. This should be used for variables that wont \"\n    \"be reachable by the Garbage Collector such as those in the data segment \"\n    \"or only accessible via vanilla C structures.\"\n    \"\\n\\n\"\n    \"The `new_raw` and `del_raw` functions can be called to construct and \"\n    \"destruct objects without going via the Garbage Collector.\"\n    \"\\n\\n\"\n    \"It is also possible to simply call the `construct` and `destruct` \"\n    \"functions if you wish to construct an already allocated object.\"\n    \"\\n\\n\"\n    \"Constructors should assume that memory is zero'd for an object but \"\n    \"nothing else.\"\n  ;\n}\n\nstatic const char* New_Definition(void) {\n  return\n    \"struct New {\\n\"\n    \"  void (*construct_with)(var, var);\\n\"\n    \"  void (*destruct)(var);\\n\"\n    \"};\\n\";\n}\n\n\nstatic struct Example* New_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var x = new(Int, $I(1));\\n\"\n      \"show(x); /* 1 */\\n\"\n      \"show(type_of(x)); /* Int */\\n\"\n      \"\\n\"\n      \"var y = alloc(Float);\\n\"\n      \"construct(y, $F(1.0));\\n\"\n      \"show(y); /* 1.0 */\\n\"\n      \"destruct(y);\\n\"\n    }, {NULL, NULL}\n  };\n  \n  return examples;\n}\n\nstatic struct Method* New_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"new\", \n      \"#define new(T, ...)\\n\"\n      \"#define new_raw(T, ...)\\n\"\n      \"#define new_root(T, ...)\\n\"\n      \"var new_with(var type, var args);\\n\"\n      \"var new_raw_with(var type, var args);\\n\"\n      \"var new_root_with(var type, var args);\",\n      \"Construct a new object of a given `type`. Use `new_raw` to avoid the \"\n      \"Garbage Collector completely, and `new_root` to register the allocation \"\n      \"as a Garbage Collection root. In the case of raw and root allocations \"\n      \"they must be destructed with the corresponding deletion functions.\"\n    }, {\n      \"del\",\n      \"void del(var self);\\n\"\n      \"void del_raw(var self);\\n\"\n      \"void del_root(var self);\",\n      \"Destruct the object `self` manually. If registered with the \"\n      \"Garbage Collector then entry will be removed. If `del_raw` is used then\"\n      \"the destruction will be done without going via the Garbage Collector.\"\n    }, {\n      \"construct\",\n      \"#define construct(self, ...)\\n\"\n      \"var construct_with(var self, var args);\",\n      \"Call the constructor on object `self` which has already been allocated.\"\n    }, {\n      \"destruct\",\n      \"var destruct(var self);\",\n      \"Call the destructor on object `self` without deallocating the memory \"\n      \"for it.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nvar New = Cello(New,\n  Instance(Doc,\n    New_Name,       New_Brief,    New_Description, \n    New_Definition, New_Examples, New_Methods));\n\nvar construct_with(var self, var args) {\n  struct New* n = instance(self, New);\n  if (n and n->construct_with) {\n    n->construct_with(self, args);\n  } else if (len(args) == 1) {\n    assign(self, get(args, $I(0)));\n  }\n  return self;\n}\n\nvar destruct(var self) {\n  struct New* n = instance(self, New);\n  if (n and n->destruct) {\n    n->destruct(self);\n  }\n  return self;\n}\n\nvar new_with(var type, var args) {\n  return construct_with(alloc(type), args);\n}\n\nvar new_raw_with(var type, var args) { \n  return construct_with(alloc_raw(type), args);\n}\n\nvar new_root_with(var type, var args) { \n  return construct_with(alloc_root(type), args);\n}\n\nstatic void del_by(var self, int method) {\n  \n  switch (method) {\n    case ALLOC_STANDARD:\n    case ALLOC_ROOT:\n#ifndef CELLO_NGC\n    rem(current(GC), self);\n    return;\n#endif\n    break;\n    case ALLOC_RAW: break;\n  }\n  \n  dealloc(destruct(self));\n  \n}\n\nvoid del(var self) { del_by(self, ALLOC_STANDARD); }\nvoid del_raw(var self) { del_by(self, ALLOC_RAW); }\nvoid del_root(var self) { del_by(self, ALLOC_ROOT); }\n\nstatic const char* Copy_Name(void) {\n  return \"Copy\";\n}\n\nstatic const char* Copy_Brief(void) {\n  return \"Copyable\";\n}\n\nstatic const char* Copy_Description(void) {\n  return\n    \"The `Copy` class can be used to override the behaviour of an object when \"\n    \"a copy is made of it. By default the `Copy` class allocates a new empty \"\n    \"object of the same type and uses the `Assign` class to set the \"\n    \"contents. The copy is then registered with the Garbage Collector as if it \"\n    \"had been constructed with `new`. This means when using manual memory \"\n    \"management a copy must be deleted manually.\"\n    \"\\n\\n\"\n    \"If the `copy` class is overridden then the implementer may manually have \"\n    \"to register the object with the Garbage Collector if they wish for it to \"\n    \"be tracked.\"\n    \"\\n\\n\"\n    \"By convention `copy` follows the semantics of `Assign`, which typically \"\n    \"means a _deep copy_ should be made, and that an object will create a \"\n    \"copy of all of the sub-objects it references or contains - although this \"\n    \"could vary depending on the type's overridden behaviours.\";\n}\n\nstatic const char* Copy_Definition(void) {\n  return\n    \"struct Copy {\\n\"\n    \"  var (*copy)(var);\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* Copy_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var x = new(String, $S(\\\"Hello\\\"));\\n\"\n      \"var y = copy(x);\\n\"\n      \"show(x); /* Hello */\\n\"\n      \"show(y); /* Hello */\\n\"\n      \"show($I(eq(x, y))); /* 1 */\\n\"\n      \"show($I(x is y)); /* 0 */\\n\"\n    }, {NULL, NULL}\n  };\n  \n  return examples;\n}\n\nstatic struct Method* Copy_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"copy\", \n      \"var copy(var self);\",\n      \"Make a copy of the object `self`.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nvar Copy = Cello(Copy,\n  Instance(Doc,\n    Copy_Name,       Copy_Brief,    Copy_Description, \n    Copy_Definition, Copy_Examples, Copy_Methods));\n\nvar copy(var self) {\n  \n  struct Copy* c = instance(self, Copy);\n  if (c and c->copy) {\n    return c->copy(self); \n  }\n  \n  return assign(alloc(type_of(self)), self);\n  \n}\n"
  },
  {
    "path": "src/Array.c",
    "content": "#include \"Cello.h\"\n\nstatic const char* Array_Name(void) {\n  return \"Array\";\n}\n\nstatic const char* Array_Brief(void) {\n  return \"Sequential Container\";\n}\n\nstatic const char* Array_Description(void) {\n  return \"\"\n    \"The `Array` type is data structure containing a sequence of a single type \"\n    \"of object. It can dynamically grow and shrink in size depending on how \"\n    \"many elements it contains. It allocates storage for the type specified. \"\n    \"It also deallocates and destroys the objects inside upon destruction.\"\n    \"\\n\\n\"\n    \"Elements are copied into an Array using `assign` and will initially have \"\n    \"zero'd memory.\"\n    \"\\n\\n\"\n    \"Elements are ordered linearly. Elements are accessed by their position in \"\n    \"this sequence directly. Addition and removal of elements at the end of \"\n    \"the sequence is fast, with memory movement required for elements in the \"\n    \"middle of the sequence.\" \n    \"\\n\\n\"\n    \"This is largely equivalent to the C++ construct \"\n    \"[std::vector](http://www.cplusplus.com/reference/vector/vector/)\";\n}\n\nstatic struct Example* Array_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Construction & Deletion\",\n      \"var x = new(Array, Int);\\n\"\n      \"push(x, $I(32));\\n\"\n      \"push(x, $I(6));\\n\"\n      \"\\n\"\n      \"/* <'Array' At 0x0000000000414603 [32, 6]> */\\n\"\n      \"show(x);\\n\",\n    }, {\n      \"Element Access\",\n      \"var x = new(Array, Float, $F(0.01), $F(5.12));\\n\"\n      \"\\n\"\n      \"show(get(x, $I(0))); /* 0.01 */\\n\"\n      \"show(get(x, $I(1))); /* 5.12 */\\n\"\n      \"\\n\"\n      \"set(x, $I(0), $F(500.1));\\n\"\n      \"show(get(x, $I(0))); /* 500.1 */\\n\",\n    }, {\n      \"Membership\",\n      \"var x = new(Array, Int, $I(1), $I(2), $I(3), $I(4));\\n\"\n      \"\\n\"\n      \"show($I(mem(x, $I(1)))); /* 1 */\\n\"\n      \"show($I(len(x)));        /* 4 */\\n\"\n      \"\\n\"\n      \"rem(x, $I(3));\\n\"\n      \"\\n\"\n      \"show($I(mem(x, $I(3)))); /* 0 */\\n\"\n      \"show($I(len(x)));        /* 3 */\\n\"\n      \"show($I(empty(x)));      /* 0 */\\n\"\n      \"\\n\"\n      \"resize(x, 0);\\n\"\n      \"\\n\"\n      \"show($I(empty(x)));      /* 1 */\\n\",\n    }, {\n      \"Iteration\",\n      \"var greetings = new(Array, String, \\n\"\n      \"  $S(\\\"Hello\\\"), $S(\\\"Bonjour\\\"), $S(\\\"Hej\\\"));\\n\"\n      \"\\n\"\n      \"foreach(greet in greetings) {\\n\"\n      \"  show(greet);\\n\"\n      \"}\\n\",\n    }, {NULL, NULL}\n  };\n  \n  return examples;\n}\n\nstruct Array {\n  var type;\n  var data;\n  size_t tsize;\n  size_t nitems;\n  size_t nslots;\n};\n\nstatic size_t Array_Step(struct Array* a) {\n  return a->tsize + sizeof(struct Header);\n}\n\nstatic var Array_Item(struct Array* a, size_t i) {\n  return (char*)a->data + Array_Step(a) * i + sizeof(struct Header);\n}\n\nstatic void Array_Alloc(struct Array* a, size_t i) {\n  memset((char*)a->data + Array_Step(a) * i, 0, Array_Step(a));\n  struct Header* head = (struct Header*)((char*)a->data + Array_Step(a) * i);\n  header_init(head, a->type, AllocData);\n}\n\nstatic size_t Array_Size_Round(size_t s) {\n  return ((s + sizeof(var) - 1) / sizeof(var)) * sizeof(var);\n}\n\nstatic void Array_New(var self, var args) {\n  \n  struct Array* a = self;\n  a->type   = cast(get(args, $I(0)), Type);\n  a->tsize  = Array_Size_Round(size(a->type));\n  a->nitems = len(args)-1;\n  a->nslots = a->nitems;\n  \n  if (a->nslots is 0) {\n    a->data = NULL;\n    return;\n  }\n  \n  a->data = malloc(a->nslots * Array_Step(a));\n  \n#if CELLO_MEMORY_CHECK == 1\n  if (a->data is NULL) {\n    throw(OutOfMemoryError, \"Cannot allocate Array, out of memory!\");\n  }\n#endif\n  \n  for(size_t i = 0; i < a->nitems; i++) {\n    Array_Alloc(a, i);\n    assign(Array_Item(a, i), get(args, $I(i+1)));  \n  }\n  \n}\n\nstatic void Array_Del(var self) {\n  \n  struct Array* a = self;\n  \n  for(size_t i = 0; i < a->nitems; i++) {\n    destruct(Array_Item(a, i));\n  }\n  \n  free(a->data);\n  \n}\n\nstatic void Array_Clear(var self) {\n  struct Array* a = self;\n  \n  for(size_t i = 0; i < a->nitems; i++) {\n    destruct(Array_Item(a, i));\n  }\n  \n  free(a->data);\n  a->data  = NULL;\n  a->nitems = 0;\n  a->nslots = 0;\n}\n\nstatic void Array_Push(var self, var obj);\n\nstatic void Array_Assign(var self, var obj) {\n  struct Array* a = self;\n\n  Array_Clear(self);\n  \n  a->type = implements_method(obj, Iter, iter_type) ? iter_type(obj) : Ref;\n  a->tsize = Array_Size_Round(size(a->type));\n  a->nitems = 0;\n  a->nslots = 0;\n  \n  if (implements_method(obj, Len, len)\n  and implements_method(obj, Get, get)) {\n  \n    a->nitems = len(obj);\n    a->nslots = a->nitems;\n    \n    if (a->nslots is 0) {\n      a->data = NULL;\n      return;\n    }\n    \n    a->data = malloc(a->nslots * Array_Step(a));\n    \n  #if CELLO_MEMORY_CHECK == 1\n    if (a->data is NULL) {\n      throw(OutOfMemoryError, \"Cannot allocate Array, out of memory!\");\n    }\n  #endif\n    \n    for(size_t i = 0; i < a->nitems; i++) {\n      Array_Alloc(a, i);\n      assign(Array_Item(a, i), get(obj, $I(i)));  \n    }\n  \n  } else {\n    \n    foreach (item in obj) {\n      Array_Push(self, item);\n    }\n    \n  }\n  \n}\n\nstatic void Array_Reserve_More(struct Array* a) {\n  \n  if (a->nitems > a->nslots) {\n    a->nslots = a->nitems + a->nitems / 2;\n    a->data = realloc(a->data, Array_Step(a) * a->nslots);\n#if CELLO_MEMORY_CHECK == 1\n    if (a->data is NULL) {\n      throw(OutOfMemoryError, \"Cannot grow Array, out of memory!\");\n    }\n#endif\n  }\n\n}\n\nstatic void Array_Concat(var self, var obj) {\n  \n  struct Array* a = self;\n  \n  size_t i = 0;\n  size_t olen = len(obj);\n  \n  a->nitems += olen;\n  Array_Reserve_More(a);\n  \n  foreach (item in obj) {\n    Array_Alloc(a, a->nitems-olen+i);\n    assign(Array_Item(a, a->nitems-olen+i), item);\n    i++;\n  }\n  \n}\n\nstatic var Array_Iter_Init(var self);\nstatic var Array_Iter_Next(var self, var curr);\n\nstatic int Array_Cmp(var self, var obj) {\n  \n  var item0 = Array_Iter_Init(self);\n  var item1 = iter_init(obj);\n  \n  while (true) {\n    if (item0 is Terminal and item1 is Terminal) { return 0; }\n    if (item0 is Terminal) { return -1; }\n    if (item1 is Terminal) { return  1; }\n    int c = cmp(item0, item1);\n    if (c < 0) { return -1; }\n    if (c > 0) { return  1; }\n    item0 = Array_Iter_Next(self, item0);\n    item1 = iter_next(obj, item1);\n  }\n  \n  return 0;\n}\n\nstatic uint64_t Array_Hash(var self) {\n  struct Array* a = self;\n  uint64_t h = 0;\n  \n  for (size_t i = 0; i < a->nitems; i++) {\n    h ^= hash(Array_Item(a, i));\n  }\n  \n  return h;\n}\n\nstatic size_t Array_Len(var self) {\n  struct Array* a = self;\n  return a->nitems;\n}\n\nstatic bool Array_Mem(var self, var obj) {\n  struct Array* a = self;\n  for(size_t i = 0; i < a->nitems; i++) {\n    if (eq(Array_Item(a, i), obj)) {\n      return true;\n    }\n  }\n  return false;\n}\n\nstatic void Array_Reserve_Less(struct Array* a) {\n  if (a->nslots > a->nitems + a->nitems / 2) {\n    a->nslots = a->nitems;\n    a->data = realloc(a->data, Array_Step(a) * a->nslots);\n  }\n}\n\nstatic void Array_Pop_At(var self, var key) {\n\n  struct Array* a = self;\n  int64_t i = c_int(key);\n  i = i < 0 ? a->nitems+i : i;\n  \n#if CELLO_BOUND_CHECK == 1\n  if (i < 0 or i >= (int64_t)a->nitems) {\n    throw(IndexOutOfBoundsError,\n      \"Index '%i' out of bounds for Array of size %i.\", key, $I(a->nitems));\n    return;\n  }\n#endif\n  \n  destruct(Array_Item(a, i));\n  \n  memmove((char*)a->data + Array_Step(a) * (i+0), \n          (char*)a->data + Array_Step(a) * (i+1), \n          Array_Step(a) * ((a->nitems-1) - i));\n  \n  a->nitems--;\n  Array_Reserve_Less(a);\n}\n\nstatic void Array_Rem(var self, var obj) {\n  struct Array* a = self;\n  for(size_t i = 0; i < a->nitems; i++) {\n    if (eq(Array_Item(a, i), obj)) {\n      Array_Pop_At(a, $I(i));\n      return;\n    }\n  }\n  throw(ValueError, \"Object %$ not in Array!\", obj);\n}\n\nstatic void Array_Push(var self, var obj) {\n  struct Array* a = self;\n  a->nitems++;\n  Array_Reserve_More(a);\n  Array_Alloc(a, a->nitems-1);\n  assign(Array_Item(a, a->nitems-1), obj);\n}\n\nstatic void Array_Push_At(var self, var obj, var key) {\n  struct Array* a = self;\n  a->nitems++;\n  Array_Reserve_More(a);\n  \n  int64_t i = c_int(key);\n  i = i < 0 ? a->nitems+i : i;\n  \n#if CELLO_BOUND_CHECK == 1\n  if (i < 0 or i >= (int64_t)a->nitems) {\n    throw(IndexOutOfBoundsError,\n      \"Index '%i' out of bounds for Array of size %i.\", key, $I(a->nitems));\n    return;\n  }\n#endif\n  \n  memmove((char*)a->data + Array_Step(a) * (i+1),\n          (char*)a->data + Array_Step(a) * (i+0), \n          Array_Step(a) * ((a->nitems-1) - i));\n  \n  Array_Alloc(self, i);\n  assign(Array_Item(a, i), obj);\n}\n\nstatic void Array_Pop(var self) {\n\n  struct Array* a = self;\n  \n#if CELLO_BOUND_CHECK == 1\n  if (a->nitems is 0) {\n    throw(IndexOutOfBoundsError, \"Cannot pop. Array is empty!\");\n    return;\n  }\n#endif\n  \n  destruct(Array_Item(a, a->nitems-1));\n  \n  a->nitems--;\n  Array_Reserve_Less(a);\n}\n\nstatic var Array_Get(var self, var key) {\n\n  struct Array* a = self;\n  int64_t i = c_int(key);\n  i = i < 0 ? a->nitems+i : i;\n  \n#if CELLO_BOUND_CHECK == 1\n  if (i < 0 or i >= (int64_t)a->nitems) {\n    return throw(IndexOutOfBoundsError,\n      \"Index '%i' out of bounds for Array of size %i.\", key, $I(a->nitems));\n  }\n#endif\n  \n  return Array_Item(a, i);\n}\n\nstatic void Array_Set(var self, var key, var val) {\n\n  struct Array* a = self;\n  int64_t i = c_int(key);\n  i = i < 0 ? a->nitems+i : i;\n  \n#if CELLO_BOUND_CHECK == 1\n  if (i < 0 or i >= (int64_t)a->nitems) {\n    throw(IndexOutOfBoundsError, \n      \"Index '%i' out of bounds for Array of size %i.\", key, $I(a->nitems));\n    return;\n  }\n#endif\n  \n  assign(Array_Item(a, i), val);\n}\n\nstatic var Array_Iter_Init(var self) {\n  struct Array* a = self;\n  if (a->nitems is 0) { return Terminal; }\n  return Array_Item(a, 0);\n}\n\nstatic var Array_Iter_Next(var self, var curr) {\n  struct Array* a = self;\n  if (curr >= Array_Item(a, a->nitems-1)) {\n    return Terminal;\n  } else {\n    return (char*)curr + Array_Step(a);\n  }\n}\n\nstatic var Array_Iter_Last(var self) {\n  struct Array* a = self;\n  if (a->nitems is 0) { return Terminal; }\n  return Array_Item(a, a->nitems-1);\n}\n\nstatic var Array_Iter_Prev(var self, var curr) {\n  struct Array* a = self;\n  if (curr < Array_Item(a, 0)) {\n    return Terminal;\n  } else {\n    return (char*)curr - Array_Step(a);\n  }\n}\n\nstatic var Array_Iter_Type(var self) {\n  struct Array* a = self;\n  return a->type;\n}\n\nstatic size_t Array_Sort_Partition(\n  struct Array* a, int64_t l, int64_t r, bool(*f)(var,var)) {\n  \n  int64_t p = l + (r - l) / 2;\n  swap(Array_Item(a, p), Array_Item(a, r));\n  \n  int64_t s = l;\n  for (int64_t i = l; i < r; i++) {\n    if (f(Array_Get(a, $I(i)), Array_Item(a, r))) {\n      swap(Array_Item(a, i), Array_Item(a, s));\n      s++;\n    }\n  }\n  \n  swap(Array_Item(a, s), Array_Item(a, r));\n  \n  return s;\n}\n\nstatic void Array_Sort_Part(struct Array* a, int64_t l, int64_t r, bool(*f)(var,var)) {\n  if (l < r) {\n    int64_t s = Array_Sort_Partition(a, l, r, f);\n    Array_Sort_Part(a, l, s-1, f);\n    Array_Sort_Part(a, s+1, r, f);\n  }\n}\n\nstatic void Array_Sort_By(var self, bool(*f)(var,var)) {\n  Array_Sort_Part(self, 0, Array_Len(self)-1, f);\n}\n\nstatic int Array_Show(var self, var output, int pos) {\n  struct Array* a = self;\n  pos = print_to(output, pos, \"<'Array' At 0x%p [\", self);\n  for (size_t i = 0; i < a->nitems; i++) {\n    pos = print_to(output, pos, \"%$\", Array_Item(a, i));\n    if (i < a->nitems-1) { pos = print_to(output, pos, \", \"); }\n  }\n  return print_to(output, pos, \"]>\");\n}\n\nstatic void Array_Resize(var self, size_t n) {\n  struct Array* a = self;\n  \n  if (n is 0) {\n    Array_Clear(self);\n    return;\n  }\n  \n  while (n < a->nitems) {\n    destruct(Array_Item(a, a->nitems-1));\n    a->nitems--;\n  }\n  \n  a->nslots = n;\n  a->data = realloc(a->data, Array_Step(a) * a->nslots);\n\n#if CELLO_MEMORY_CHECK == 1\n  if (a->data is NULL) {\n    throw(OutOfMemoryError, \"Cannot grow Array, out of memory!\");\n  }\n#endif\n\n}\n\nstatic void Array_Mark(var self, var gc, void(*f)(var,void*)) {\n  struct Array* a = self;\n  for (size_t i = 0; i < a->nitems; i++) {\n    f(gc, Array_Item(a, i));\n  }\n}\n\nvar Array = Cello(Array,\n  Instance(Doc,\n    Array_Name, Array_Brief,    Array_Description, \n    NULL,       Array_Examples, NULL),\n  Instance(New,     Array_New, Array_Del),\n  Instance(Assign,  Array_Assign),\n  Instance(Mark,    Array_Mark),\n  Instance(Cmp,     Array_Cmp),\n  Instance(Hash,    Array_Hash),\n  Instance(Push,\n    Array_Push,     Array_Pop,\n    Array_Push_At,  Array_Pop_At),\n  Instance(Concat,  Array_Concat, Array_Push),\n  Instance(Len,     Array_Len),\n  Instance(Get,     Array_Get, Array_Set, Array_Mem, Array_Rem),\n  Instance(Iter,   \n    Array_Iter_Init, Array_Iter_Next, \n    Array_Iter_Last, Array_Iter_Prev, Array_Iter_Type),\n  Instance(Sort,    Array_Sort_By),\n  Instance(Show,    Array_Show, NULL),\n  Instance(Resize,  Array_Resize));\n\n  \n"
  },
  {
    "path": "src/Assign.c",
    "content": "#include \"Cello.h\"\n\nstatic const char* Assign_Name(void) {\n  return \"Assign\";\n}\n\nstatic const char* Assign_Brief(void) {\n  return \"Assignment\";\n}\n\nstatic const char* Assign_Description(void) {\n  return\n    \"`Assign` is potentially the most important class in Cello. It is used \"\n    \"throughout Cello to initialise objects using other objects. In C++ this is \"\n    \"called the _copy constructor_ and it is used to assign the value of one \"\n    \"object to another.\"\n    \"\\n\\n\"\n    \"By default the `Assign` class uses the `Size` class to copy the memory \"\n    \"from one object to another. But for more complex objects which maintain \"\n    \"their own behaviours and state this may need to be overridden.\"\n    \"\\n\\n\"\n    \"The most important thing about the `Assign` class is that it must work on \"\n    \"the assumption that the target object may not have had it's constructor \"\n    \"called and could be uninitialised with just zero'd memory. This is often \"\n    \"the case when copying contents into containers.\";\n}\n\nstatic const char* Assign_Definition(void) {\n  return\n    \"struct Assign {\\n\"\n    \"  void (*assign)(var, var);\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* Assign_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var x = new(Int, $I(10));\\n\"\n      \"var y = new(Int, $I(20));\\n\"\n      \"\\n\"\n      \"show(x); /* 10 */\\n\"\n      \"show(y); /* 20 */\\n\"\n      \"\\n\"\n      \"assign(x, y);\\n\"\n      \"\\n\"\n      \"show(x); /* 20 */\\n\"\n      \"show(y); /* 20 */\\n\"\n    }, {NULL, NULL}\n  };\n  \n  return examples;\n}\n\nstatic struct Method* Assign_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"assign\", \n      \"var assign(var self, var obj);\",\n      \"Assign the object `obj` to the object `self`. The assigned object \"\n      \"`self` is returned.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nvar Assign = Cello(Assign,\n  Instance(Doc,\n    Assign_Name,       Assign_Brief,    Assign_Description,\n    Assign_Definition, Assign_Examples, Assign_Methods));\n\nvar assign(var self, var obj) {\n  \n  struct Assign* a = instance(self, Assign);\n  \n  if (a and a->assign) {\n    a->assign(self, obj);\n    return self;\n  }\n  \n  size_t s = size(type_of(self));\n  if (type_of(self) is type_of(obj) and s) {\n    return memcpy(self, obj, s);\n  }\n  \n  return throw(TypeError,\n    \"Cannot assign type %s to type %s\", type_of(obj), type_of(self));\n  \n}\n\nstatic const char* Swap_Name(void) {\n  return \"Swap\";\n}\n\nstatic const char* Swap_Brief(void) {\n  return \"Swapable\";\n}\n\nstatic const char* Swap_Description(void) {\n  return\n    \"The `Swap` class can be used to override the behaviour of swapping two \"\n    \"objects. By default the `Swap` class simply swaps the memory of the \"\n    \"two objects passed in as parameters making use of the `Size` class. \"\n    \"In almost all cases this default behaviour should be fine, even if the \"\n    \"objects have custom assignment functions.\"\n    \"\\n\\n\"\n    \"Swapping can be used internally by various collections and algorithms.\";\n}\n\nstatic const char* Swap_Definition(void) {\n  return\n    \"struct Swap {\\n\"\n    \"  void (*swap)(var, var);\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* Swap_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var x = $S(\\\"Hello\\\");\\n\"\n      \"var y = $S(\\\"World\\\");\\n\"\n      \"show(x); /* Hello */\\n\"\n      \"show(y); /* World */\\n\"\n      \"swap(x, y);\\n\"\n      \"show(x); /* World */\\n\"\n      \"show(y); /* Hello */\\n\"\n    }, {NULL, NULL}\n  };\n  \n  return examples;\n}\n\nstatic struct Method* Swap_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"swap\", \n      \"void swap(var self, var obj);\",\n      \"Swap the object `self` for the object `obj`.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nvar Swap = Cello(Swap,\n  Instance(Doc,\n    Swap_Name,       Swap_Brief,    Swap_Description, \n    Swap_Definition, Swap_Examples, Swap_Methods));\n\nstatic void memswap(void* p0, void* p1, size_t s) {\n  if (p0 == p1) { return; }\n  for (size_t i = 0; i < s; i++) {\n    char t = ((char*)p0)[i];\n    ((char*)p0)[i] = ((char*)p1)[i];\n    ((char*)p1)[i] = t;\n  }\n}\n    \nvoid swap(var self, var obj) {\n  \n  struct Swap* s = instance(self, Swap);\n  if (s and s->swap) {\n    s->swap(self, obj);\n    return;\n  }\n  \n  size_t n = size(type_of(self));\n  if (type_of(self) is type_of(obj) and n) {\n    memswap(self, obj, n);\n    return;\n  }\n  \n  throw(TypeError,\n    \"Cannot swap type %s and type %s\", type_of(obj), type_of(self));\n  \n}\n"
  },
  {
    "path": "src/Cmp.c",
    "content": "#include \"Cello.h\"\n\nstatic const char* Cmp_Name(void) {\n  return \"Cmp\";\n}\n\nstatic const char* Cmp_Brief(void) {\n  return \"Comparison\";\n}\n\nstatic const char* Cmp_Description(void) {\n  return\n    \"The `Cmp` class is used to define comparison between two object values. \"\n    \"This class is important as it is used by many data structures to test \"\n    \"equality or ordering of objects.\"\n    \"\\n\\n\"\n    \"By default, if passed two objects of the same type, the `Cmp` class will \"\n    \"simply compare the raw memory of both objects, using the `Size` \"\n    \"class.\"\n    \"\\n\\n\"\n    \"To implement this class a `cmp` function must be provided which returns \"\n    \"`< 0` if the first object is _less than_ the second, `> 0` if the first \"\n    \"object is _greater than_ the second, and `0` if they are _equal_. \"\n    \"\\n\\n\"\n    \"For objects that manage their own data this class may need to be \"\n    \"overridden to ensure that objects of the same _value_ are still treated \"\n    \"as equal. E.G. for string types.\"\n    \"\\n\\n\"\n    \"This class to used to test for _value_ equality between objects, I.E. if \"\n    \"they represent the same thing. For _object_ equality the `is` keyword can \"\n    \"be used, which will return `true` only if two variables are pointing to \"\n    \"the same object in memory.\";\n}\n\nstatic const char* Cmp_Definition(void) {\n  return\n    \"struct Cmp {\\n\"\n    \"  int (*cmp)(var, var);\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* Cmp_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage 1\",\n      \"show($I( eq($I(1), $I( 1)))); /* 1 */\\n\"\n      \"show($I(neq($I(2), $I(20)))); /* 1 */\\n\"\n      \"show($I(neq($S(\\\"Hello\\\"), $S(\\\"Hello\\\")))); /* 0 */\\n\"\n      \"show($I( eq($S(\\\"Hello\\\"), $S(\\\"There\\\")))); /* 0 */\\n\"\n      \"\\n\"\n      \"var a = $I(1); var b = $I(1);\\n\"\n      \"\\n\"\n      \"show($I(eq(a, b))); /* 1 */\\n\"\n      \"show($I(a is b));   /* 0 */\\n\"\n      \"show($I(a isnt b)); /* 1 */\\n\"\n    }, {\n      \"Usage 2\",\n      \"show($I(gt($I(15), $I(3 )))); /* 1 */\\n\"\n      \"show($I(lt($I(70), $I(81)))); /* 1 */\\n\"\n      \"show($I(lt($I(71), $I(71)))); /* 0 */\\n\"\n      \"show($I(ge($I(78), $I(71)))); /* 1 */\\n\"\n      \"show($I(gt($I(32), $I(32)))); /* 0 */\\n\"\n      \"show($I(le($I(21), $I(32)))); /* 1 */\\n\"\n      \"\\n\"\n      \"show($I(cmp($I(20), $I(20)))); /*  0 */\\n\"\n      \"show($I(cmp($I(21), $I(20)))); /*  1 */\\n\"\n      \"show($I(cmp($I(20), $I(21)))); /* -1 */\\n\"\n    }, {NULL, NULL}\n  };\n  \n  return examples;\n}\n\nstatic struct Method* Cmp_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"cmp\", \n      \"int cmp(var self, var obj);\",\n      \"The return value of `cmp` is `< 0` if `self` is less than `obj`, `> 0` \"\n      \"if `self` is greater than `obj` and `0` if they are equal.\"\n    }, {\n      \"eq\", \n      \"bool eq(var self, var obj);\",\n      \"Returns true if the object `self` is equal to the object `obj`.\"\n    }, {\n      \"neq\", \n      \"bool neq(var self, var obj);\",\n      \"Returns false if the object `self` is equal to the object `obj`.\"\n    }, {\n      \"gt\", \n      \"bool gt(var self, var obj);\",\n      \"Returns true if the object `self` is greater than the object `obj`.\"\n    }, {\n      \"lt\", \n      \"bool lt(var self, var obj);\",\n      \"Returns false if the object `self` is less than the object `obj`.\"\n    }, {\n      \"ge\", \n      \"bool ge(var self, var obj);\",\n      \"Returns false if the object `self` is greater than or equal to the \"\n      \"object `obj`.\"\n    }, {\n      \"le\", \n      \"bool le(var self, var obj);\",\n      \"Returns false if the object `self` is less than or equal to the \"\n      \"object `obj`.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nvar Cmp = Cello(Cmp,\n  Instance(Doc,\n    Cmp_Name,       Cmp_Brief,    Cmp_Description, \n    Cmp_Definition, Cmp_Examples, Cmp_Methods));\n\nint cmp(var self, var obj) {\n  \n  struct Cmp* c = instance(self, Cmp);\n  if (c and c->cmp) { return c->cmp(self, obj); }\n  \n  size_t s = size(type_of(self));\n  if (type_of(self) is type_of(obj) and s) { return memcmp(self, obj, s); }\n  \n  throw(TypeError,\n    \"Cannot compare type %s to type %s\", type_of(obj), type_of(self));\n  \n  return 0;\n}\n    \nbool  eq(var self, var obj) { return cmp(self, obj) is 0; }\nbool neq(var self, var obj) { return not eq(self, obj); }\nbool  gt(var self, var obj) { return cmp(self, obj) > 0; }\nbool  lt(var self, var obj) { return cmp(self, obj) < 0; }\nbool  ge(var self, var obj) { return not lt(self, obj); }\nbool  le(var self, var obj) { return not gt(self, obj); }\n\nstatic const char* Sort_Name(void) {\n  return \"Sort\";\n}\n\nstatic const char* Sort_Brief(void) {\n  return \"Sortable\";\n}\n\nstatic const char* Sort_Description(void) {\n  return\n    \"The `Sort` class can be implemented by types which can be sorted in some \"\n    \"way such as `Array`. By default the sorting function uses the `lt` method \"\n    \"to compare elements, but a custom function can also be provided.\";\n}\n\nstatic const char* Sort_Definition(void) {\n  return\n    \"struct Sort {\\n\"\n    \"  void (*sort_by)(var,bool(*f)(var,var));\\n\"\n    \"};\";\n}\n\nstatic struct Example* Sort_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var x = new(Array, Float, \\n\"\n      \"  $F(5.2), $F(7.1), $F(2.2));\\n\"\n      \"\\n\"\n      \"show(x); /* <'Array' At 0x00414603 [5.2, 7.1, 2.2]> */\\n\"\n      \"sort(x);\\n\"\n      \"show(x); /* <'Array' At 0x00414603 [2.2, 5.2, 7.1]> */\\n\"\n    }, {NULL, NULL}\n  };\n  \n  return examples;\n}\n\nstatic struct Method* Sort_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"sort\", \n      \"void sort(var self);\",\n      \"Sorts the object `self`.\"\n    }, {\n      \"sort_by\", \n      \"void sort_by(var self, bool(*f)(var,var));\",\n      \"Sorts the object `self` using the function `f`.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nvar Sort = Cello(Sort, \n  Instance(Doc,\n    Sort_Name,       Sort_Brief,    Sort_Description, \n    Sort_Definition, Sort_Examples, Sort_Methods));\n  \nvoid sort(var self) {\n  method(self, Sort, sort_by, lt);\n}\n\nvoid sort_by(var self, bool(*f)(var,var)) {\n  method(self, Sort, sort_by, f);\n}\n"
  },
  {
    "path": "src/Concat.c",
    "content": "#include \"Cello.h\"\n\nstatic const char* Concat_Name(void) {\n  return \"Concat\";\n}\n\nstatic const char* Concat_Brief(void) {\n  return \"Concatenate Objects\";\n}\n\nstatic const char* Concat_Description(void) {\n  return\n    \"The `Concat` class is implemented by objects that can have other objects \"\n    \"either _appended_ to their, on _concatenated_ to them. For example \"\n    \"collections or strings.\";\n}\n\nstatic const char* Concat_Definition(void) {\n  return\n    \"struct Concat {\\n\"\n    \"  void (*concat)(var, var);\\n\"\n    \"  void (*append)(var, var);\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* Concat_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var x = new(Array, Float, $F(9.9), $F(2.8));\\n\"\n      \"var y = new(Array, Float, $F(1.1), $F(6.5));\\n\"\n      \"\\n\"\n      \"show(x); /* <'Array' At 0x00414603 [9.9, 2.8]> */\\n\"\n      \"show(y); /* <'Array' At 0x00414603 [1.1, 6.5]> */\\n\"\n      \"append(x, $F(2.5));\\n\"\n      \"show(x); /* <'Array' At 0x00414603 [9.9, 2.8, 2.5]> */\\n\"\n      \"concat(x, y);\\n\"\n      \"show(x); /* <'Array' At 0x00414603 [9.9, 2.8, 2.5, 1.1, 6.5]> */\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic struct Method* Concat_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"append\", \n      \"void append(var self, var obj);\",\n      \"Append the object `obj` to the object `self`.\"\n    }, {\n      \"concat\", \n      \"void concat(var self, var obj);\",\n      \"Concatenate the object `obj` to the object `self`.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nvar Concat = Cello(Concat,\n  Instance(Doc,\n    Concat_Name,       Concat_Brief,    Concat_Description,\n    Concat_Definition, Concat_Examples, Concat_Methods));\n\nvoid append(var self, var obj) {\n  method(self, Concat, append, obj);\n}\n\nvoid concat(var self, var obj) {\n  method(self, Concat, concat, obj);\n}\n"
  },
  {
    "path": "src/Doc.c",
    "content": "#include \"Cello.h\"\n\nstatic const char* Doc_Name(void) {\n  return \"Doc\";\n}\n\nstatic const char* Doc_Brief(void) {\n  return \"Provides Documentation\";\n}\n\nstatic const char* Doc_Description(void) {\n  return\n    \"The `Doc` class can be used to give documentation to a certain class or \"\n    \"type. This documentation can then be accessed using the `help` function \"\n    \"or by other tools used to generate documentation such as for the Cello \"\n    \"website. Documentation can be written in Markdown.\"\n    \"\\n\\n\"\n    \"The `examples` and `methods` entries should be provided as `NULL` \"\n    \"terminated arrays allocated statically.\" ;\n}\n\nstatic const char* Doc_Definition(void) {\n  return\n    \"struct Example {\\n\"\n    \"  const char* name;\\n\"\n    \"  const char* body;\\n\"\n    \"};\\n\"\n    \"\\n\"\n    \"struct Method {\\n\"\n    \"  const char* name;\\n\"\n    \"  const char* definition;\\n\"\n    \"  const char* description;\\n\"\n    \"};\\n\"\n    \"\\n\"\n    \"struct Doc {\\n\"\n    \"  const char* (*name)(void);\\n\"\n    \"  const char* (*brief)(void);\\n\"\n    \"  const char* (*description)(void);\\n\"\n    \"  const char* (*definition)(void);\\n\"\n    \"  struct Example* (*examples)(void);\\n\"\n    \"  struct Method* (*methods)(void);\\n\"\n    \"};\\n\";\n}\n\nstatic struct Method* Doc_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"name\", \n      \"const char* name(var type);\",\n      \"Return the name of a given `type`.\"\n    }, {\n      \"brief\", \n      \"const char* brief(var type);\",\n      \"Return a brief description of a given `type`.\"\n    }, {\n      \"description\", \n      \"const char* description(var type);\",\n      \"Return a longer description of a given `type`.\"\n    }, {\n      \"definition\", \n      \"const char* definition(var type);\",\n      \"Return the C definition of a given `type`.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nstatic struct Example* Doc_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"show($S(name(Int))); /* Int */\\n\"\n      \"show($S(brief(Int))); /* Integer Object */\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nvar Doc = Cello(Doc,\n  Instance(Doc,\n    Doc_Name,       Doc_Brief,    Doc_Description,\n    Doc_Definition, Doc_Examples, Doc_Methods));\n    \nconst char* name(var type) {\n  struct Doc* doc = type_instance(type, Doc);\n  if (doc and doc->name) { return doc->name(); }\n  return c_str(type);\n}\n  \nconst char* brief(var type) {\n  return type_method(type, Doc, brief);\n}\n\nconst char* description(var type) {\n  return type_method(type, Doc, description);\n}\n\nconst char* definition(var type) {\n  return type_method(type, Doc, definition);\n}\n    \nstatic const char* Help_Name(void) {\n  return \"Help\";\n}\n\nstatic const char* Help_Brief(void) {\n  return \"Usage information\";\n}\n\nstatic const char* Help_Description(void) {\n  return\n    \"The `Help` class can be implemented to let an object provide helpful \"\n    \"information about itself. In the standard library this class is \"\n    \"implemented by `Type` and it prints out the documentation provided \"\n    \"by the `Doc` class in a friendly way.\";\n}\n\nstatic const char* Help_Definition(void) {\n  return\n    \"struct Help {\\n\"\n    \"  int (*help_to)(var, int);\\n\"\n    \"};\\n\";\n}\n\nstatic struct Method* Help_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"help\", \n      \"void help(var self);\\n\"\n      \"int help_to(var out, int pos, var self);\",\n      \"Print help information about the object `self` either to `stdout` or \"\n      \"to the object `out` at some position `pos`.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nstatic struct Example* Help_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"help(Int);\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nvar Help = Cello(Help,\n  Instance(Doc,\n    Help_Name,       Help_Brief,    Help_Description,\n    Help_Definition, Help_Examples, Help_Methods));\n\nint help_to(var out, int pos, var self) {\n  return method(self, Help, help_to, out, pos);\n}\n\nvoid help(var self) {\n  help_to($(File, stdout), 0, self);\n}\n    \n"
  },
  {
    "path": "src/Exception.c",
    "content": "#include \"Cello.h\"\n\n#define EXCEPTION_TLS_KEY \"__Exception\"\n\nenum {\n  EXCEPTION_MAX_DEPTH  = 2048,\n  EXCEPTION_MAX_STRACE = 25\n};\n\nvar TypeError = CelloEmpty(TypeError);\nvar ValueError = CelloEmpty(ValueError);\nvar ClassError = CelloEmpty(ClassError);\nvar IndexOutOfBoundsError = CelloEmpty(IndexOutOfBoundsError);\nvar KeyError = CelloEmpty(KeyError);\nvar OutOfMemoryError = CelloEmpty(OutOfMemoryError);\nvar IOError = CelloEmpty(IOError);\nvar FormatError = CelloEmpty(FormatError);\nvar BusyError = CelloEmpty(BusyError);\nvar ResourceError = CelloEmpty(ResourceError);\n\nvar ProgramAbortedError = CelloEmpty(ProgramAbortedError);\nvar DivisionByZeroError = CelloEmpty(DivisionByZeroError);\nvar IllegalInstructionError = CelloEmpty(IllegalInstructionError);\nvar ProgramInterruptedError = CelloEmpty(ProgramInterruptedError);\nvar SegmentationError = CelloEmpty(SegmentationError);\nvar ProgramTerminationError = CelloEmpty(ProgramTerminationError);\n\nstruct Exception {\n  var      obj;\n  var      msg;\n  size_t   depth;\n  bool     active;\n  jmp_buf* buffers[EXCEPTION_MAX_DEPTH];  \n};\n\nstatic const char* Exception_Name(void) {\n  return \"Exception\";\n}\n\nstatic const char* Exception_Brief(void) {\n  return \"Exception Object\";\n}\n\nstatic const char* Exception_Description(void) {\n  return\n    \"The `Exception` type provides an interface to the Cello Exception System. \"\n    \"One instance of this type is created for each `Thread` and stores the \"\n    \"various bits of data required for the exception system. It can be \"\n    \"retrieved using the `current` function, although not much can be done \"\n    \"with it.\"\n    \"\\n\\n\"\n    \"Exceptions are available via the `try`, `catch` and `throw` macros. It is \"\n    \"important that the `catch` part of the exception block is always \"\n    \"evaluated otherwise the internal state of the exception system can go out \"\n    \"of sync. For this reason please never use `return` inside a `try` block. \"\n    \"\\n\\n\"\n    \"The `exception_signals` method can be used to register some exception to \"\n    \"be thrown for any of the \"\n    \"[standard C signals](https://en.wikipedia.org/wiki/C_signal_handling).\"\n    \"\\n\\n\"\n    \"To get the current exception object or message use the \"\n    \"`exception_message` or `exception_object` methods.\";\n}\n\nstatic struct Method* Exception_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"try\", \n      \"#define try\",\n      \"Start an exception `try` block.\"\n    }, {\n      \"catch\", \n      \"#define catch(...)\",\n      \"Start an exception `catch` block, catching any objects listed in `...` \"\n      \"as the first name given. To catch any exception object leave argument \"\n      \"list empty other than caught variable name.\"\n    }, {\n      \"#define throw\",\n      \"throw(E, F, ...)\",\n      \"Throw exception object `E` with format string `F` and arguments `...`.\"\n    }, {\n      \"exception_signals\",\n      \"void exception_signals(void);\",\n      \"Register the standard C signals to throw corresponding exceptions.\"\n    }, {\n      \"exception_object\",\n      \"void exception_object(void);\\n\",\n      \"Retrieve the current exception object.\"\n    }, {\n      \"exception_message\",\n      \"void exception_message(void);\\n\",\n      \"Retrieve the current exception message.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nstatic struct Example* Exception_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var x = new(Table, String, Int);\\n\"\n      \"set(x, $S(\\\"Hello\\\"), $I(1));\\n\"\n      \"set(x, $S(\\\"World\\\"), $I(2));\\n\"\n      \"\\n\"\n      \"try {\\n\"\n      \"  get(x, $S(\\\"Missing\\\"));\\n\"\n      \"} catch (e in KeyError) {\\n\"\n      \"  println(\\\"Got Exception: %$\\\", e);\\n\"\n      \"}\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic void Exception_New(var self, var args) {\n  struct Exception* e = self;\n  e->active = false;\n  e->depth = 0;\n  e->obj = NULL;\n  e->msg = new_raw(String);\n  memset(e->buffers, 0, sizeof(jmp_buf*) * EXCEPTION_MAX_DEPTH);\n  set(current(Thread), $S(EXCEPTION_TLS_KEY), self);\n}\n\nstatic void Exception_Del(var self) {\n  struct Exception* e = self;\n  del_raw(e->msg);\n  rem(current(Thread), $S(EXCEPTION_TLS_KEY));\n}\n\nstatic void Exception_Assign(var self, var obj) {\n  struct Exception* e = self;\n  struct Exception* o = cast(obj, Exception);\n  e->obj = o->obj;\n  assign(e->msg, o->msg);\n  e->depth = o->depth;\n  e->active = o->active;\n  memcpy(e->buffers, o->buffers, sizeof(jmp_buf*) * EXCEPTION_MAX_DEPTH);\n}\n\nstatic var Exception_Current(void) {\n  return get(current(Thread), $S(EXCEPTION_TLS_KEY));\n}\n\nstatic void Exception_Signal(int sig) {\n  switch(sig) {\n    case SIGABRT: throw(ProgramAbortedError, \"Program Aborted\");\n    case SIGFPE:  throw(DivisionByZeroError, \"Division by Zero\");\n    case SIGILL:  throw(IllegalInstructionError, \"Illegal Instruction\");\n    case SIGINT:  throw(ProgramInterruptedError, \"Program Interrupted\");\n    case SIGSEGV: throw(SegmentationError, \"Segmentation fault\");\n    case SIGTERM: throw(ProgramTerminationError, \"Program Terminated\");\n  }\n}\n\nstatic jmp_buf* Exception_Buffer(struct Exception* e) {\n  if (e->depth == 0) {\n    fprintf(stderr, \"Cello Fatal Error: Exception Buffer Out of Bounds!\\n\");\n    abort();\n  }\n  return e->buffers[e->depth-1];\n}\n\nstatic size_t Exception_Len(var self) {\n  struct Exception* e = self;\n  return e->depth;\n}\n\nstatic bool Exception_Running(var self) {\n  struct Exception* e = self;\n  return e->active;\n}\n\n#ifndef CELLO_NSTRACE\n#if defined(CELLO_UNIX)\n\nstatic void Exception_Backtrace(void) {\n  \n  var trace[EXCEPTION_MAX_STRACE];\n  size_t trace_count = backtrace(trace, EXCEPTION_MAX_STRACE);\n  char** symbols = backtrace_symbols(trace, trace_count);  \n  \n  print_to($(File, stderr), 0, \"!!\\tStack Trace: \\n\");\n  print_to($(File, stderr), 0, \"!!\\t\\n\");\n\n  for (size_t i = 0; i < trace_count; i++) {\n    print_to($(File, stderr), 0, \"!!\\t\\t[%i] %s\\n\", \n      $(Int, i), $(String, symbols[i]));\n  }\n  print_to($(File, stderr), 0, \"!!\\t\\n\");\n  \n  free(symbols);\n  \n}\n\n#elif defined(CELLO_WINDOWS)\n\nstatic void Exception_Backtrace(void) {\n  \n  HANDLE process = GetCurrentProcess();\n  HANDLE thread = GetCurrentThread();\n  \n  CONTEXT context;\n  memset(&context, 0, sizeof(CONTEXT));\n  context.ContextFlags = CONTEXT_FULL;\n  RtlCaptureContext(&context);\n  \n  SymSetOptions(SYMOPT_UNDNAME|SYMOPT_LOAD_LINES);\n  SymInitialize(process, NULL, TRUE);\n  \n  DWORD image;\n  STACKFRAME64 stackframe;\n  ZeroMemory(&stackframe, sizeof(STACKFRAME64));\n  \n#ifdef _M_IX86\n  image = IMAGE_FILE_MACHINE_I386;\n  stackframe.AddrPC.Offset = context.Eip;\n  stackframe.AddrPC.Mode = AddrModeFlat;\n  stackframe.AddrFrame.Offset = context.Ebp;\n  stackframe.AddrFrame.Mode = AddrModeFlat;\n  stackframe.AddrStack.Offset = context.Esp;\n  stackframe.AddrStack.Mode = AddrModeFlat;\n#elif _M_X64\n  image = IMAGE_FILE_MACHINE_AMD64;\n  stackframe.AddrPC.Offset = context.Rip;\n  stackframe.AddrPC.Mode = AddrModeFlat;\n  stackframe.AddrFrame.Offset = context.Rsp;\n  stackframe.AddrFrame.Mode = AddrModeFlat;\n  stackframe.AddrStack.Offset = context.Rsp;\n  stackframe.AddrStack.Mode = AddrModeFlat;\n#elif _M_IA64\n  image = IMAGE_FILE_MACHINE_IA64;\n  stackframe.AddrPC.Offset = context.StIIP;\n  stackframe.AddrPC.Mode = AddrModeFlat;\n  stackframe.AddrFrame.Offset = context.IntSp;\n  stackframe.AddrFrame.Mode = AddrModeFlat;\n  stackframe.AddrBStore.Offset = context.RsBSP;\n  stackframe.AddrBStore.Mode = AddrModeFlat;\n  stackframe.AddrStack.Offset = context.IntSp;\n  stackframe.AddrStack.Mode = AddrModeFlat;\n#endif\n\n  print_to($(File, stderr), 0, \"!!\\tStack Trace: \\n\");\n  print_to($(File, stderr), 0, \"!!\\t\\n\");\n\n  for (size_t i = 0; i < EXCEPTION_MAX_STRACE; i++) {\n    \n    BOOL result = StackWalk64(\n      image, process, thread,\n      &stackframe, &context, NULL, \n      SymFunctionTableAccess64, SymGetModuleBase64, NULL);\n    \n    if (!result) { break; }\n    \n    char* filename = \"\";\n    char* symbolname = \"???\";\n    int lineno = 0;\n    \n    char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];\n    PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer;\n    symbol->SizeOfStruct = sizeof(SYMBOL_INFO);\n    symbol->MaxNameLen = MAX_SYM_NAME;\n    \n    DWORD64 displacement = 0;\n    if (SymFromAddr(process, stackframe.AddrPC.Offset, &displacement, symbol)) {\n      symbolname = symbol->Name;\n    } else {\n      symbolname = \"???\";\n    }\n      \n    IMAGEHLP_LINE64 line;\n    line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);\n    \n    DWORD displacementline = 0;\n    if (SymGetLineFromAddr64(process, \n      stackframe.AddrPC.Offset, &displacementline, &line)) {\n      lineno = line.LineNumber;\n      filename = line.FileName;\n    } else {\n      lineno = 0;\n      filename = \"\";\n    }\n    \n    if (strcmp(filename, \"\") == 0) {\n      print_to($(File, stderr), 0, \"!!\\t\\t[%i] %s\\n\",\n        $I(i), $S(symbolname));      \n    } else {\n      print_to($(File, stderr), 0, \"!!\\t\\t[%i] %s:%i %s\\n\",\n        $I(i), $S(filename), $I(lineno), $S(symbolname));\n    }\n    \n  }\n  \n  print_to($(File, stderr), 0, \"!!\\t\\n\");\n  \n  SymCleanup(process);\n  \n}\n\n#else\n\nstatic void Exception_Backtrace(void) {}\n\n#endif\n\n#else\n\nstatic void Exception_Backtrace(void) {}\n  \n#endif\n\nstatic void Exception_Error(struct Exception* e)  {\n  \n  print_to($(File, stderr), 0, \"\\n\");\n  print_to($(File, stderr), 0, \"!!\\t\\n\");\n  print_to($(File, stderr), 0, \"!!\\tUncaught %$\\n\", e->obj);\n  print_to($(File, stderr), 0, \"!!\\t\\n\");\n  print_to($(File, stderr), 0, \"!!\\t\\t %s\\n\", e->msg);\n  print_to($(File, stderr), 0, \"!!\\t\\n\");\n  \n  Exception_Backtrace();\n  \n  exit(EXIT_FAILURE);\n  \n}\n\nstatic int Exception_Show(var self, var out, int pos) {\n  struct Exception* e = self;\n  return print_to(out, pos, \n    \"<'Exception' At 0x%p %$ - %$>\", self, e->obj, e->msg);\n}\n\nvar Exception = Cello(Exception,\n  Instance(Doc,\n    Exception_Name, Exception_Brief,    Exception_Description, \n    NULL,           Exception_Examples, Exception_Methods),\n  Instance(New,     Exception_New, Exception_Del),\n  Instance(Assign,  Exception_Assign),\n  Instance(Len,     Exception_Len),\n  Instance(Current, Exception_Current),\n  Instance(Start,   NULL, NULL, NULL, Exception_Running),\n  Instance(Show,    Exception_Show, NULL));\n\nvoid exception_signals(void) {\n  signal(SIGABRT, Exception_Signal);\n  signal(SIGFPE,  Exception_Signal);\n  signal(SIGILL,  Exception_Signal);\n  signal(SIGINT,  Exception_Signal);\n  signal(SIGSEGV, Exception_Signal);\n  signal(SIGTERM, Exception_Signal);\n}\n\nvoid exception_try(jmp_buf* env) {\n  struct Exception* e = current(Exception);\n  if (e->depth is EXCEPTION_MAX_DEPTH) {\n    fprintf(stderr, \"Cello Fatal Error: Exception Buffer Overflow!\\n\");\n    abort();\n  }\n  e->depth++;\n  e->active = false; \n  e->buffers[e->depth-1] = env;\n}\n\nvar exception_throw(var obj, const char* fmt, var args) {\n\n  struct Exception* e = current(Exception);\n  \n  e->obj = obj;\n  print_to_with(e->msg, 0, fmt, args);\n  \n  if (Exception_Len(e) >= 1) {\n    longjmp(*Exception_Buffer(e), 1);\n  } else {\n    Exception_Error(e);\n  }\n  \n  return NULL;\n  \n}\n\nvar exception_catch(var args) {\n  \n  struct Exception* e = current(Exception);\n  \n  if (not e->active) { return NULL; }\n  \n  /* If no Arguments catch all */\n  if (len(args) is 0) {\n    return e->obj;\n  }\n  \n  /* Check Exception against Arguments */\n  foreach(arg in args) {\n    if (eq(arg, e->obj)) {\n      return e->obj;\n    }\n  }\n  \n  /* No matches found. Propagate to outward block */\n  if (e->depth >= 1) {\n    longjmp(*Exception_Buffer(e), 1);\n  } else {\n    Exception_Error(e);\n  }\n  \n  return NULL;\n  \n}\n\nvoid exception_try_end(void) {\n  struct Exception* e = current(Exception);\n  if (e->depth == 0) {\n    fprintf(stderr, \"Cello Fatal Error: Exception Buffer Underflow!\\n\");\n    abort();\n  }\n  e->depth--;\n}\n\nvoid exception_try_fail(void) {\n  struct Exception* e = current(Exception);\n  e->active = true;\n}\n"
  },
  {
    "path": "src/File.c",
    "content": "#include \"Cello.h\"\n\nstatic const char* Stream_Name(void) {\n  return \"Stream\";\n}\n\nstatic const char* Stream_Brief(void) {\n  return \"File-like\";\n}\n\nstatic const char* Stream_Description(void) {\n  return \n    \"The `Stream` class represents an abstract set of operations that can be \"\n    \"performed on File-like objects.\";\n}\n\nstatic const char* Stream_Definition(void) {\n  return\n    \"struct Stream {\\n\"\n    \"  var  (*sopen)(var,var,var);\\n\"\n    \"  void (*sclose)(var);\\n\"\n    \"  void (*sseek)(var,int64_t,int);\\n\"\n    \"  int64_t (*stell)(var);\\n\"\n    \"  void (*sflush)(var);\\n\"\n    \"  bool (*seof)(var);\\n\"\n    \"  size_t (*sread)(var,void*,size_t);\\n\"\n    \"  size_t (*swrite)(var,void*,size_t);\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* Stream_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var f = sopen($(File, NULL), $S(\\\"test.bin\\\"), $S(\\\"r\\\"));\\n\"\n      \"\\n\"\n      \"char c;\\n\"\n      \"while (!seof(f)) {\\n\"\n      \"  sread(f, &c, 1);\\n\"\n      \"  putc(c, stdout);\\n\"\n      \"}\\n\"\n      \"\\n\"\n      \"sclose(f);\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic struct Method* Stream_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"sopen\", \n      \"var sopen(var self, var resource, var options);\",\n      \"Open the stream `self` with a given `resource` and `options`.\"\n    }, {\n      \"sclose\", \n      \"void sclose(var self);\",\n      \"Close the stream `self`.\"\n    }, {\n      \"sseek\", \n      \"void sseek(var self, int64_t pos, int origin);\",\n      \"Seek to the position `pos` from some `origin` in the stream `self`.\"\n    }, {\n      \"stell\", \n      \"int64_t stell(var self);\",\n      \"Return the current position of the stream `stell`.\"\n    }, {\n      \"sflush\", \n      \"void sflush(var self);\",\n      \"Flush the buffered contents of stream `self`.\"\n    }, {\n      \"seof\", \n      \"bool seof(var self);\",\n      \"Returns true if there is no more information in the stream.\"\n    }, {\n      \"sread\", \n      \"size_t sread(var self, void* output, size_t size);\",\n      \"Read `size` bytes from the stream `self` and write them to `output`.\"\n    }, {\n      \"swrite\", \n      \"size_t swrite(var self, void* input, size_t size);\",\n      \"Write `size` bytes to the stream `self` and read them from `input`.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nvar Stream = Cello(Stream,\n  Instance(Doc, \n    Stream_Name,       Stream_Brief,    Stream_Description,\n    Stream_Definition, Stream_Examples, Stream_Methods));\n\nvar sopen(var self, var resource, var options) {\n  return method(self, Stream, sopen, resource, options);\n}\n\nvoid sclose(var self) {\n  method(self, Stream, sclose);\n}\n\nvoid sseek(var self, int64_t pos, int origin) {\n  method(self, Stream, sseek, pos, origin);\n}\n\nint64_t stell(var self) {\n  return method(self, Stream, stell);\n}\n\nvoid sflush(var self) {\n  method(self, Stream, sflush);\n}\n\nbool seof(var self) {\n  return method(self, Stream, seof);\n}\n\nsize_t sread(var self, void* output, size_t size) {\n  return method(self, Stream, sread, output, size);\n}\n\nsize_t swrite(var self, void* input, size_t size) {\n  return method(self, Stream, swrite, input, size);\n}\n\nstatic const char* File_Name(void) {\n  return \"File\";\n}\n\nstatic const char* File_Brief(void) {\n  return \"Operating System File\";\n}\n\nstatic const char* File_Description(void) {\n  return\n    \"The `File` type is a wrapper of the native C `FILE` type representing a \"\n    \"file in the operating system.\";\n}\n\nstatic const char* File_Definition(void) {\n  return\n    \"struct File {\\n\"\n    \"  FILE* file;\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* File_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var x = new(File, $S(\\\"test.bin\\\"), $S(\\\"wb\\\"));\\n\"\n      \"char* data = \\\"hello\\\";\\n\"\n      \"swrite(x, data, strlen(data));\\n\"\n      \"sclose(x);\\n\"\n    }, {\n      \"Formatted Printing\",\n      \"var x = $(File, NULL);\\n\"\n      \"sopen(x, $S(\\\"test.txt\\\"), $S(\\\"w\\\"));\\n\"\n      \"print_to(x, 0, \\\"%$ is %$ \\\", $S(\\\"Dan\\\"), $I(23));\\n\"\n      \"print_to(x, 0, \\\"%$ is %$ \\\", $S(\\\"Chess\\\"), $I(24));\\n\"\n      \"sclose(x);\\n\"\n    }, {\n      \"Automatic Closing\",\n      \"with(f in new(File, $S(\\\"test.txt\\\"), $S(\\\"r\\\"))) {\\n\"\n      \"  var k = new(String); resize(k, 100);\\n\"\n      \"  var v = new(Int, $I(0));\\n\"\n      \"  foreach (i in range($I(2))) {\\n\"\n      \"    scan_from(f, 0, \\\"%$ is %$ \\\", k, v);\\n\"\n      \"    show(k); show(v);\\n\"\n      \"  }\\n\"\n      \"}\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic var File_Open(var self, var filename, var access);\nstatic void File_Close(var self);\n\nstatic void File_New(var self, var args) {\n  struct File* f = self;\n  if (len(args) > 0) {\n    File_Open(self, get(args, $I(0)), get(args, $I(1)));\n  }\n}\n\nstatic void File_Del(var self) {\n  struct File* f = self;\n  if (f->file isnt NULL) { File_Close(self); }\n}\n\nstatic var File_Open(var self, var filename, var access) {\n  struct File* f = self;\n  \n  if (f->file isnt NULL) { File_Close(self); }\n  \n  f->file = fopen(c_str(filename), c_str(access));\n  \n  if (f->file is NULL) {\n    throw(IOError, \"Could not open file: %s\", filename);\n  }\n  \n  return self;\n}\n\nstatic void File_Close(var self) {\n  struct File* f = self;\n  \n  int err = fclose(f->file);\n  if (err != 0) {\n    throw(IOError, \"Failed to close file: %i\", $I(err));\n  }\n  \n  f->file = NULL;\n}\n\nstatic void File_Seek(var self, int64_t pos, int origin) {\n  struct File* f = self;\n  \n  if (f->file is NULL) {\n    throw(IOError, \"Cannot seek file - no file open.\");\n  }\n  \n  int err = fseek(f->file, pos, origin);\n  if (err != 0) {\n    throw(IOError, \"Failed to seek in file: %i\", $I(err));\n  }\n  \n}\n\nstatic int64_t File_Tell(var self) {\n  struct File* f = self;\n  \n  if (f->file is NULL) {\n    throw(IOError, \"Cannot tell file - no file open.\");\n  }\n  \n  int64_t i = ftell(f->file);\n  if (i == -1) {\n    throw(IOError, \"Failed to tell file: %i\", $I(i));\n  }\n  \n  return i;\n}\n\nstatic void File_Flush(var self) {\n  struct File* f = self;\n  \n  if (f->file is NULL) {\n    throw(IOError, \"Cannot flush file - no file open.\");\n  }\n  \n  int err = fflush(f->file);\n  if (err != 0) {\n    throw(IOError, \"Failed to flush file: %i\", $I(err));\n  }\n  \n}\n\nstatic bool File_EOF(var self) {\n  struct File* f = self;\n  \n  if (f->file is NULL) {\n    throw(IOError, \"Cannot eof file - no file open.\");\n  }\n  \n  return feof(f->file);\n}\n\nstatic size_t File_Read(var self, void* output, size_t size) {\n  struct File* f = self;\n  \n  if (f->file is NULL) {\n    throw(IOError, \"Cannot read file - no file open.\");\n  }\n  \n  size_t num = fread(output, size, 1, f->file);\n  if (num isnt 1 and size isnt 0 and not feof(f->file)) {\n    throw(IOError, \"Failed to read from file: %i\", $I(num));\n    return num;\n  }\n  \n  return num;\n}\n\nstatic size_t File_Write(var self, void* input, size_t size) {\n  struct File* f = self;\n  \n  if (f->file is NULL) {\n    throw(IOError, \"Cannot write file - no file open.\");\n  }\n  \n  size_t num = fwrite(input, size, 1, f->file);\n  if (num isnt 1 and size isnt 0) {\n    throw(IOError, \"Failed to write to file: %i\", $I(num));\n  }\n  \n  return num;\n}\n\nstatic int File_Format_To(var self, int pos, const char* fmt, va_list va) {\n  struct File* f = self;\n  \n  if (f->file is NULL) {\n    throw(IOError, \"Cannot format to file - no file open.\");\n  }\n  \n  return vfprintf(f->file, fmt, va);\n}\n\nstatic int File_Format_From(var self, int pos, const char* fmt, va_list va) {\n  struct File* f = self;\n  \n  if (f->file is NULL) {\n    throw(IOError, \"Cannot format from file - no file open.\");\n  }\n  \n  return vfscanf(f->file, fmt, va);\n}\n\nvar File = Cello(File,\n  Instance(Doc,\n    File_Name,       File_Brief,    File_Description, \n    File_Definition, File_Examples, NULL),\n  Instance(New, File_New, File_Del),\n  Instance(Start, NULL, File_Close, NULL),\n  Instance(Stream,\n    File_Open, File_Close, File_Seek, File_Tell,\n    File_Flush, File_EOF, File_Read, File_Write),\n  Instance(Format, File_Format_To, File_Format_From));\n\n\nstatic const char* Process_Name(void) {\n  return \"Process\";\n}\n\nstatic const char* Process_Brief(void) {\n  return \"Operating System Process\";\n}\n\nstatic const char* Process_Description(void) {\n  return \n    \"The `Process` type is a wrapper for an operating system process as \"\n    \"constructed by the unix-like call `popen`. In this sense it is much like \"\n    \"a standard file in the operating system but that instead of writing data \"\n    \"to a location you are writing it as input to a process.\";\n}\n\nstatic const char* Process_Definition(void) {\n  return\n    \"struct Process {\\n\"\n    \"  FILE* proc;\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* Process_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var x = new(Process, $S(\\\"ls\\\"), $S(\\\"r\\\"));\\n\"\n      \"char c;\\n\"\n      \"while (not seof(x)) {\\n\"\n      \"  sread(x, &c, 1);\\n\"\n      \"  print(\\\"%c\\\", $I(c));\\n\"\n      \"}\\n\"\n      \"sclose(x);\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic var Process_Open(var self, var filename, var access);\nstatic void Process_Close(var self);\n\nstatic void Process_New(var self, var args) {\n  struct Process* p = self;\n  p->proc = NULL;\n  Process_Open(self, get(args, $I(0)), get(args, $I(1)));\n}\n\nstatic void Process_Del(var self) {\n  struct Process* p = self;\n  if (p->proc isnt NULL) { Process_Close(self); }\n}\n\nstatic var Process_Open(var self, var filename, var access) {\n  struct Process* p = self;\n  \n  if (p->proc isnt NULL) { Process_Close(self); }\n  \n  p->proc = popen(c_str(filename), c_str(access));\n  \n  if (p->proc is NULL) {\n    throw(IOError, \"Could not open process: %s\", filename);\n  }\n  \n  return self;\n}\n\nstatic void Process_Close(var self) {\n  struct Process* p = self;\n  \n  int err = pclose(p->proc);\n  if (err != 0) {\n    throw(IOError, \"Failed to close process: %i\", $I(err));\n  }\n  \n  p->proc = NULL;\n}\n\nstatic void Process_Seek(var self, int64_t pos, int origin) {\n  struct Process* p = self;\n  \n  if (p->proc is NULL) {\n    throw(IOError, \"Cannot seek process - no process open.\");\n  }\n  \n  int err = fseek(p->proc, pos, origin);\n  if (err != 0) {\n    throw(IOError, \"Failed to seek in process: %i\", $I(err));\n  }\n  \n}\n\nstatic int64_t Process_Tell(var self) {\n  struct Process* p = self;\n  \n  if (p->proc is NULL) {\n    throw(IOError, \"Cannot tell process - no process open.\");\n  }\n  \n  int64_t i = ftell(p->proc);\n  if (i == -1) {\n    throw(IOError, \"Failed to tell process: %i\", $I(i));\n  }\n  \n  return i;\n}\n\nstatic void Process_Flush(var self) {\n  struct Process* p = self;\n  \n  if (p->proc is NULL) {\n    throw(IOError, \"Cannot flush process - no process open.\");\n  }\n  \n  int err = fflush(p->proc);\n  if (err != 0) {\n    throw(IOError, \"Failed to flush process: %i\", $I(err));\n  }\n  \n}\n\nstatic bool Process_EOF(var self) {\n  struct Process* p = self;\n  \n  if (p->proc is NULL) {\n    throw(IOError, \"Cannot eof process - no process open.\");\n  }\n  \n  return feof(p->proc);\n}\n\nstatic size_t Process_Read(var self, void* output, size_t size) {\n  struct Process* p = self;\n  \n  if (p->proc is NULL) {\n    throw(IOError, \"Cannot read process - no process open.\");\n  }\n  \n  size_t num = fread(output, size, 1, p->proc);\n  if (num isnt 1 and size isnt 0 and not feof(p->proc)) {\n    throw(IOError, \"Failed to read from process: %i\", $I(num));\n    return num;\n  }\n  \n  return num;\n}\n\nstatic size_t Process_Write(var self, void* input, size_t size) {\n  struct Process* p = self;\n  \n  if (p->proc is NULL) {\n    throw(IOError, \"Cannot write process - no process open.\");\n  }\n  \n  size_t num = fwrite(input, size, 1, p->proc);\n  if (num isnt 1 and size isnt 0) {\n    throw(IOError, \"Failed to write to process: %i\", $I(num));\n  }\n  \n  return num;\n}\n\nstatic int Process_Format_To(var self, int pos, const char* fmt, va_list va) {\n  struct Process* p = self;\n  \n  if (p->proc is NULL) {\n    throw(IOError, \"Cannot format to process - no process open.\");\n  }\n  \n  return vfprintf(p->proc, fmt, va);\n}\n\nstatic int Process_Format_From(var self, int pos, const char* fmt, va_list va) {\n  struct Process* p = self;\n  \n  if (p->proc is NULL) {\n    throw(IOError, \"Cannot format from process - no process open.\");\n  }\n  \n  return vfscanf(p->proc, fmt, va);\n}\n\nvar Process = Cello(Process,\n  Instance(Doc,\n    Process_Name,       Process_Brief,    Process_Description, \n    Process_Definition, Process_Examples, NULL),\n  Instance(New,  Process_New, Process_Del),\n  Instance(Start, NULL, Process_Close, NULL),\n  Instance(Stream,\n    Process_Open,  Process_Close, Process_Seek, Process_Tell,\n    Process_Flush, Process_EOF,   Process_Read, Process_Write),\n  Instance(Format, Process_Format_To, Process_Format_From));\n\n"
  },
  {
    "path": "src/Function.c",
    "content": "#include \"Cello.h\"\n\nstatic const char* Call_Name(void) {\n  return \"Call\";\n}\n\nstatic const char* Call_Brief(void) {\n  return \"Callable\";\n}\n\nstatic const char* Call_Description(void) {\n  return\n    \"The `Call` class is used by types which can be called as functions.\";\n}\n\nstatic const char* Call_Definition(void) {\n  return\n    \"struct Call {\\n\"\n    \"  var (*call_with)(var, var);\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* Call_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var increment(var args) {\\n\"\n      \"  struct Int* i = get(args, $I(0));\\n\"\n      \"  i->val++;\\n\"\n      \"  return NULL;\\n\"\n      \"}\\n\"\n      \"\\n\"\n      \"var x = $I(0);\\n\"\n      \"show(x); /* 0 */\\n\"\n      \"call($(Function, increment), x);\\n\"\n      \"show(x); /* 1 */\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic struct Method* Call_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"call\", \n      \"#define call(self, ...)\\n\"\n      \"var call_with(var self, var args);\",\n      \"Call the object `self` with arguments `args`.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nvar Call = Cello(Call,\n  Instance(Doc,\n    Call_Name,       Call_Brief,    Call_Description, \n    Call_Definition, Call_Examples, Call_Methods));\n\nvar call_with(var self, var args) {\n  return method(self, Call, call_with, args);\n}\n\nstatic const char* Function_Name(void) {\n  return \"Function\";\n}\n\nstatic const char* Function_Brief(void) {\n  return \"Function Object\";\n}\n\nstatic const char* Function_Description(void) {\n  return\n    \"The `Function` type allows C function pointers to be treated as \"\n    \"Cello objects. They can be passed around, stored, and manipulated. Only C \"\n    \"functions of the type `var(*)(var)` can be stored as a `Function` type \"\n    \"and when called the arguments will be wrapped into an iterable and passed \"\n    \"as the first argument, typically in the form of a `tuple`.\";\n}\n\nstatic struct Example* Function_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var increment(var args) {\\n\"\n      \"  struct Int* i = get(args, $I(0));\\n\"\n      \"  i->val++;\\n\"\n      \"  return NULL;\\n\"\n      \"}\\n\"\n      \"\\n\"\n      \"var x = $I(0);\\n\"\n      \"show(x); /* 0 */\\n\"\n      \"call($(Function, increment), x);\\n\"\n      \"show(x); /* 1 */\\n\"\n    }, {\n      \"Usage 2\",\n      \"var hello_person(var args) {\\n\"\n      \"  print(\\\"Hello %$!\\\", get(args, $I(0)));\\n\"\n      \"  return NULL;\\n\"\n      \"}\\n\"\n      \"\\n\"\n      \"call($(Function, hello_person), $S(\\\"Dan\\\"));\\n\"\n    }, {\n      \"Usage 3\",\n      \"var add_print(var args) {\\n\"\n      \"  int64_t fst = c_int(get(args, $I(0)));\\n\"\n      \"  int64_t snd = c_int(get(args, $I(1)));\\n\"\n      \"  println(\\\"%i + %i = %i\\\", $I(fst), $I(snd), $I(fst+snd));\\n\"\n      \"  return NULL;\\n\"\n      \"}\\n\"\n      \"\\n\"\n      \"call($(Function, add_print), $I(10), $I(21));\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic const char* Function_Definition(void) {\n  return\n    \"struct Function {\\n\"\n    \"  var (*func)(var);\\n\"\n    \"};\\n\";\n}\n\nstatic var Function_Call(var self, var args) {\n  struct Function* f = self;\n  return f->func(args);\n}\n\nvar Function = Cello(Function,\n  Instance(Doc,\n    Function_Name,       Function_Brief,    Function_Description,\n    Function_Definition, Function_Examples, NULL),\n  Instance(Call, Function_Call));\n\n\n"
  },
  {
    "path": "src/GC.c",
    "content": "#include \"Cello.h\"\n\nstatic const char* Mark_Name(void) {\n  return \"Mark\";\n}\n\nstatic const char* Mark_Brief(void) {\n  return \"Markable by GC\";\n}\n\nstatic const char* Mark_Description(void) {\n  return\n    \"The `Mark` class can be overridden to customize the behaviour of the \"\n    \"Cello Garbage Collector on encountering a given type. By default the \"\n    \"allocated memory for a structure is scanned for pointers to other Cello \"\n    \"objects, but if a type does its own memory allocation it may store \"\n    \"pointers to Cello objects in other locations.\"\n    \"\\n\\n\"\n    \"If this is the case the `Mark` class can be overridden and the callback \"\n    \"function `f` must be called on all pointers which might be Cello objects \"\n    \"which are managed by the class. Alternately the `mark` function can be \"\n    \"called on any sub object to start a chain of recursive marking.\";\n}\n\nstatic const char* Mark_Definition(void) {\n  return\n    \"struct Mark {\\n\"\n    \"  void (*mark)(var, var, void(*)(var,void*));\\n\"\n    \"};\\n\";\n}\n\nstatic struct Method* Mark_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"mark\", \n      \"void mark(var self, var gc, void(*f)(var,void*));\",\n      \"Mark the object `self` with the Garbage Collector `gc` and the callback \"\n      \"function `f`.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nvar Mark = Cello(Mark, Instance(Doc, \n  Mark_Name,       Mark_Brief, Mark_Description, \n  Mark_Definition, NULL,       Mark_Methods));\n  \nvoid mark(var self, var gc, void(*f)(var,void*)) {\n  if (self is NULL) { return; }\n  struct Mark* m = instance(self, Mark);\n  if (m and m->mark) { m->mark(self, gc, f); }\n}\n\n#ifndef CELLO_NGC\n  \n#define GC_TLS_KEY \"__GC\"\n\nenum {\n  GC_PRIMES_COUNT = 24\n};\n\nstatic const size_t GC_Primes[GC_PRIMES_COUNT] = {\n  0,       1,       5,       11,\n  23,      53,      101,     197,\n  389,     683,     1259,    2417,\n  4733,    9371,    18617,   37097,\n  74093,   148073,  296099,  592019,\n  1100009, 2200013, 4400021, 8800019\n};\n\nstatic const char* GC_Name(void) {\n  return \"GC\";\n}\n\nstatic const char* GC_Brief(void) {\n  return \"Garbage Collector\";\n}\n\nstatic const char* GC_Description(void) {\n  return\n    \"The `GC` type provides an interface to the Cello Garbage Collector. One \"\n    \"instance of this type is created for each thread and can be retrieved \"\n    \"using the `current` function. The Garbage Collector can be stopped and \"\n    \"started using `start` and `stop` and objects can be added or removed from \"\n    \"the Garbage Collector using `set` and `rem`.\";\n}\n\nstatic struct Example* GC_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Starting & Stopping\",\n      \"var gc = current(GC);\\n\"\n      \"stop(gc);\\n\"\n      \"var x = new(Int, $I(10)); /* Not added to GC */\\n\"\n      \"show($I(running(gc))); /* 0 */\\n\"\n      \"del(x); /* Must be deleted when done */\\n\"\n      \"start(gc);\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstruct GCEntry {\n  var ptr;\n  uint64_t hash;\n  bool root;\n  bool marked;\n};\n\nstruct GC {\n  struct GCEntry* entries;\n  size_t nslots;\n  size_t nitems;\n  size_t mitems;\n  uintptr_t maxptr;\n  uintptr_t minptr;\n  var bottom;\n  bool running;\n  uintptr_t freenum;\n  var* freelist;\n};\n\nstatic uint64_t GC_Probe(struct GC* gc, uint64_t i, uint64_t h) {\n  int64_t v = i - (h-1);\n  if (v < 0) {\n    v = gc->nslots + v;\n  }\n  return v;\n}\n\nstatic const double GC_Load_Factor = 0.9;\n\nstatic size_t GC_Ideal_Size(size_t size) {\n  size = (size_t)((double)(size+1) / GC_Load_Factor);\n  for (size_t i = 0; i < GC_PRIMES_COUNT; i++) {\n    if (GC_Primes[i] >= size) { return GC_Primes[i]; }\n  }\n  size_t last = GC_Primes[GC_PRIMES_COUNT-1];\n  for (size_t i = 0;; i++) {\n    if (last * i >= size) { return last * i; }\n  }\n}\n\nstatic void GC_Set_Ptr(struct GC* gc, var ptr, bool root);\n\nstatic void GC_Rehash(struct GC* gc, size_t new_size) {\n\n  struct GCEntry* old_entries = gc->entries;\n  size_t old_size = gc->nslots;\n  \n  gc->nslots = new_size;\n  gc->entries = calloc(gc->nslots, sizeof(struct GCEntry));\n  \n#if CELLO_MEMORY_CHECK == 1\n  if (gc->entries is NULL) {\n    throw(OutOfMemoryError, \"Cannot allocate GC Pointer Table, out of memory!\");\n    return;\n  }\n#endif\n  \n  for (size_t i = 0; i < old_size; i++) {\n    if (old_entries[i].hash isnt 0) {\n      GC_Set_Ptr(gc, old_entries[i].ptr, old_entries[i].root);\n    }\n  }\n  \n  free(old_entries);\n\n}\n\nstatic void GC_Resize_More(struct GC* gc) {\n  size_t new_size = GC_Ideal_Size(gc->nitems);  \n  size_t old_size = gc->nslots;\n  if (new_size > old_size) { GC_Rehash(gc, new_size); }\n}\n\nstatic void GC_Resize_Less(struct GC* gc) {\n  size_t new_size = GC_Ideal_Size(gc->nitems);  \n  size_t old_size = gc->nslots;\n  if (new_size < old_size) { GC_Rehash(gc, new_size); }\n}\n\nstatic uint64_t GC_Hash(var ptr) {\n  return ((uintptr_t)ptr) >> 3;\n}\n\nstatic void GC_Set_Ptr(struct GC* gc, var ptr, bool root) {\n  \n  uint64_t i = GC_Hash(ptr) % gc->nslots;\n  uint64_t j = 0;\n  uint64_t ihash = i+1;\n  struct GCEntry entry = { ptr, ihash, root, 0 };\n  \n  while (true) {\n    \n    uint64_t h = gc->entries[i].hash;\n    if (h is 0) { gc->entries[i] = entry; return; }\n    if (gc->entries[i].ptr == entry.ptr) { return; }\n    \n    uint64_t p = GC_Probe(gc, i, h);\n    if (j >= p) {\n      struct GCEntry tmp = gc->entries[i];\n      gc->entries[i] = entry;\n      entry = tmp;\n      j = p;\n    }\n    \n    i = (i+1) % gc->nslots;\n    j++;\n  }\n  \n}\n\nstatic bool GC_Mem_Ptr(struct GC* gc, var ptr) {\n\n  if (gc->nslots is 0) { return false; }\n  \n  uint64_t i = GC_Hash(ptr) % gc->nslots;\n  uint64_t j = 0;\n  \n  while (true) {\n    uint64_t h = gc->entries[i].hash;\n    if (h is 0 or j > GC_Probe(gc, i, h)) { return false; }\n    if (gc->entries[i].ptr == ptr) { return true; }\n    i = (i+1) % gc->nslots; j++;\n  }\n\n}\n\nstatic void GC_Rem_Ptr(struct GC* gc, var ptr) {\n  \n  if (gc->nslots is 0) { return; }\n  \n  for (size_t i = 0; i < gc->freenum; i++) {\n    if (gc->freelist[i] is ptr) { gc->freelist[i] = NULL; }\n  }\n  \n  uint64_t i = GC_Hash(ptr) % gc->nslots;\n  uint64_t j = 0;\n  \n  while (true) {\n    \n    uint64_t h = gc->entries[i].hash;\n    if (h is 0 or j > GC_Probe(gc, i, h)) { return; }\n    if (gc->entries[i].ptr is ptr) {\n      \n      var freeitem = gc->entries[i].ptr;\n      memset(&gc->entries[i], 0, sizeof(struct GCEntry));\n      \n      j = i;\n      while (true) { \n        uint64_t nj = (j+1) % gc->nslots;\n        uint64_t nh = gc->entries[nj].hash;\n        if (nh isnt 0 and GC_Probe(gc, nj, nh) > 0) {\n          memcpy(&gc->entries[j], &gc->entries[nj], sizeof(struct GCEntry));\n          memset(&gc->entries[nj], 0, sizeof(struct GCEntry));\n          j = nj;\n        } else {\n          break;\n        }  \n      }\n      \n      gc->nitems--;\n      \n      dealloc(destruct(freeitem));\n      return;\n    }\n    \n    i = (i+1) % gc->nslots; j++;\n  }\n  \n}\n\nstatic void GC_Mark_Item(void* _gc, void* ptr);\nstatic void GC_Recurse(struct GC* gc, var ptr);\n\nstatic void GC_Mark_And_Recurse(void* _gc, void* ptr) {\n  struct GC* gc = _gc;\n  GC_Mark_Item(gc, ptr);\n  GC_Recurse(gc, ptr);\n}\n\nstatic void GC_Recurse(struct GC* gc, var ptr) {\n  \n  var type = type_of(ptr);\n  \n  if (type is Int    or  type is Float   \n  or  type is String or  type is Type\n  or  type is File   or  type is Process\n  or  type is Function) { return; }\n    \n  struct Mark* m = type_instance(type, Mark);\n  if (m and m->mark) {\n    m->mark(ptr, gc, (void(*)(var,void*))GC_Mark_And_Recurse);\n    return;\n  }\n    \n  for (size_t i = 0; i+sizeof(var) <= size(type); i += sizeof(var)) {\n    var p = ((char*)ptr) + i;\n    GC_Mark_Item(gc, *((var*)p));\n  }\n  \n}\n\nstatic void GC_Print(struct GC* gc);\n\nstatic void GC_Mark_Item(void* _gc, void* ptr) {\n  struct GC* gc = _gc;\n  uintptr_t pval = (uintptr_t)ptr;\n  if (pval % sizeof(var) isnt 0\n  or  pval < gc->minptr\n  or  pval > gc->maxptr) { return; }\n  \n  uint64_t i = GC_Hash(ptr) % gc->nslots;\n  uint64_t j = 0;\n  \n  while (true) {\n    \n    uint64_t h = gc->entries[i].hash;\n    \n    if (h is 0 or j > GC_Probe(gc, i, h)) { return; }\n    \n    if (gc->entries[i].ptr is ptr and not gc->entries[i].marked) {\n      gc->entries[i].marked = true;\n      GC_Recurse(gc, gc->entries[i].ptr);\n      return;\n    }\n    \n    i = (i+1) % gc->nslots; j++;\n  }\n  \n}\n\nstatic void CELLO_NASAN GC_Mark_Stack(struct GC* gc) {\n  \n  var stk = NULL;\n  var bot = gc->bottom;\n  var top = &stk;\n  \n  if (bot == top) { return; }\n  \n  if (bot < top) {\n    for (var p = top; p >= bot; p = ((char*)p) - sizeof(var)) {\n      GC_Mark_Item(gc, *((var*)p));\n    }\n  }\n  \n  if (bot > top) {\n    for (var p = top; p <= bot; p = ((char*)p) + sizeof(var)) {\n      GC_Mark_Item(gc, *((var*)p));\n    }\n  }\n  \n}\n\nstatic void GC_Mark_Stack_Fake(struct GC* gc) { }\n\nvoid GC_Mark(struct GC* gc) {\n  \n  if (gc is NULL or gc->nitems is 0) { return; }\n  \n  /* Mark Thread Local Storage */\n  mark(current(Thread), gc, (void(*)(var,void*))GC_Mark_Item);\n  \n  /* Mark Roots */\n  for (size_t i = 0; i < gc->nslots; i++) {\n    if (gc->entries[i].hash is 0) { continue; }\n    if (gc->entries[i].marked) { continue; }\n    if (gc->entries[i].root) {\n      gc->entries[i].marked = true;\n      GC_Recurse(gc, gc->entries[i].ptr);\n    }\n  }\n  \n  volatile int noinline = 1;\n  \n  /* Flush Registers to Stack */\n  if (noinline) {\n    jmp_buf env;\n    memset(&env, 0, sizeof(jmp_buf));\n    setjmp(env);\n  }\n  \n  /* Avoid Inlining function call */\n  void (*mark_stack)(struct GC* gc) = noinline\n    ? GC_Mark_Stack\n    : (void(*)(struct GC* gc))(NULL);\n  \n  /* Mark Stack */\n  mark_stack(gc);\n  \n}\n\nstatic int GC_Show(var self, var out, int pos) {\n  struct GC* gc = self;\n \n  pos = print_to(out, pos, \"<'GC' At 0x%p\\n\", self);\n  for (size_t i = 0; i < gc->nslots; i++) {\n    if (gc->entries[i].hash is 0) {\n      pos = print_to(out, pos, \"| %i : \\n\", $I(i));\n      continue;\n    }\n    pos = print_to(out, pos, \"| %i : %15s %p %s %s\\n\", \n      $I(i), type_of(gc->entries[i].ptr), \n      gc->entries[i].ptr, \n      gc->entries[i].root ? $S(\"root\") : $S(\"auto\"),\n      gc->entries[i].marked ? $S(\"*\") : $S(\" \"));\n  }\n  \n  return print_to(out, pos, \"+------------------->\\n\");\n}\n\nvoid GC_Sweep(struct GC* gc) {\n   \n  gc->freelist = realloc(gc->freelist, sizeof(var) * gc->nitems);\n  gc->freenum = 0;\n  \n  size_t i = 0;\n  while (i < gc->nslots) {\n    \n    if (gc->entries[i].hash is 0) { i++; continue; }\n    if (gc->entries[i].marked) { i++; continue; }\n    \n    if (not gc->entries[i].root and not gc->entries[i].marked) {\n      \n      gc->freelist[gc->freenum] = gc->entries[i].ptr;\n      gc->freenum++;\n      memset(&gc->entries[i], 0, sizeof(struct GCEntry));\n      \n      uint64_t j = i;\n      while (true) { \n        uint64_t nj = (j+1) % gc->nslots;\n        uint64_t nh = gc->entries[nj].hash;\n        if (nh isnt 0 and GC_Probe(gc, nj, nh) > 0) {\n          memcpy(&gc->entries[j], &gc->entries[nj], sizeof(struct GCEntry));\n          memset(&gc->entries[nj], 0, sizeof(struct GCEntry));\n          j = nj;\n        } else {\n          break;\n        }  \n      }\n      \n      gc->nitems--;\n      continue;\n    }\n    \n    i++;\n  }\n  \n  for (size_t i = 0; i < gc->nslots; i++) {\n    if (gc->entries[i].hash is 0) { continue; }\n    if (gc->entries[i].marked) {\n      gc->entries[i].marked = false;\n      continue;\n    }\n  }\n  \n  GC_Resize_Less(gc);\n  gc->mitems = gc->nitems + gc->nitems / 2 + 1;\n  \n  for (size_t i = 0; i < gc->freenum; i++) {\n    if (gc->freelist[i]) {\n      dealloc(destruct(gc->freelist[i]));\n    }\n  }\n  \n  free(gc->freelist);\n  gc->freelist = NULL;\n  gc->freenum = 0;\n  \n}\n\nstatic var GC_Current(void) {\n  return get(current(Thread), $S(GC_TLS_KEY));\n}\n\nstatic void GC_New(var self, var args) {\n  struct GC* gc = self;\n  struct Ref* bt = cast(get(args, $I(0)), Ref);\n  gc->bottom = bt->val;\n  gc->maxptr = 0;\n  gc->minptr = UINTPTR_MAX;\n  gc->running = true;\n  gc->freelist = NULL;\n  gc->freenum = 0;\n  set(current(Thread), $S(GC_TLS_KEY), gc);\n}\n\nstatic void GC_Del(var self) {\n  struct GC* gc = self;\n  GC_Sweep(gc);\n  free(gc->entries);\n  free(gc->freelist);\n  rem(current(Thread), $S(GC_TLS_KEY));\n}\n\nstatic void GC_Set(var self, var key, var val) {\n  struct GC* gc = self;\n  if (not gc->running) { return; }\n  gc->nitems++;\n  gc->maxptr = (uintptr_t)key > gc->maxptr ? (uintptr_t)key : gc->maxptr;\n  gc->minptr = (uintptr_t)key < gc->minptr ? (uintptr_t)key : gc->minptr;\n  GC_Resize_More(gc);\n  GC_Set_Ptr(gc, key, (bool)c_int(val));\n  if (gc->nitems > gc->mitems) {\n    GC_Mark(gc);\n    GC_Sweep(gc);\n  }\n}\n\nstatic void GC_Rem(var self, var key) {\n  struct GC* gc = self;\n  if (not gc->running) { return; }\n  GC_Rem_Ptr(gc, key);\n  GC_Resize_Less(gc);\n  gc->mitems = gc->nitems + gc->nitems / 2 + 1;\n}\n\nstatic bool GC_Mem(var self, var key) {\n  return GC_Mem_Ptr(self, key);\n}\n\nstatic void GC_Start(var self) {\n  struct GC* gc = self;\n  gc->running = true;\n}\n\nstatic void GC_Stop(var self) {\n  struct GC* gc = self;\n  gc->running = false;\n}\n\nstatic bool GC_Running(var self) {\n  struct GC* gc = self;\n  return gc->running;\n}\n\nvar GC = Cello(GC,\n  Instance(Doc,\n    GC_Name, GC_Brief,    GC_Description, \n    NULL,    GC_Examples, NULL),\n  Instance(New,     GC_New, GC_Del),\n  Instance(Get,     NULL, GC_Set, GC_Mem, GC_Rem),\n  Instance(Start,   GC_Start, GC_Stop, NULL, GC_Running),\n  Instance(Show,    GC_Show, NULL),\n  Instance(Current, GC_Current));\n\nvoid Cello_Exit(void) {\n  del_raw(current(GC));\n}\n\n#endif\n"
  },
  {
    "path": "src/Get.c",
    "content": "#include \"Cello.h\"\n\nstatic const char* Get_Name(void) {\n  return \"Get\";\n}\n\nstatic const char* Get_Brief(void) {\n  return \"Gettable or Settable\";\n}\n\nstatic const char* Get_Description(void) {\n  return\n    \"The `Get` class provides a method to _get_ or _set_ certain properties \"\n    \"of an object using keys and value. Typically it is implemented by \"\n    \"data lookup structures such as `Table` or `Map` but it is also used \"\n    \"more generally such as using indices to look up items in `Array`, or \"\n    \"as thread local storage for the `Thread` object.\";\n}\n\nstatic const char* Get_Definition(void) {\n  return\n    \"struct Get {\\n\"\n    \"  var  (*get)(var, var);\\n\"\n    \"  void (*set)(var, var, var);\\n\"\n    \"  bool (*mem)(var, var);\\n\"\n    \"  void (*rem)(var, var);\\n\"\n    \"  var (*key_type)(var);\\n\"\n    \"  var (*val_type)(var);\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* Get_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage 1\",\n      \"var x = new(Array, String, \\n\"\n      \"  $S(\\\"Hello\\\"), $S(\\\"There\\\"));\\n\"\n      \"\\n\"\n      \"show(get(x, $I(0))); /* Hello */\\n\"\n      \"show(get(x, $I(1))); /* There */\\n\"\n      \"set(x, $I(1), $S(\\\"Blah\\\"));\\n\"\n      \"show(get(x, $I(1))); /* Blah */\\n\"\n    }, {\n      \"Usage 2\",\n      \"var prices = new(Table, String, Int, \\n\"\n      \"  $S(\\\"Apple\\\"),  $I(12),\\n\"\n      \"  $S(\\\"Banana\\\"), $I( 6),\\n\"\n      \"  $S(\\\"Pear\\\"),   $I(55));\\n\"\n      \"\\n\"\n      \"var pear_price   = get(prices, $S(\\\"Pear\\\"));\\n\"\n      \"var banana_price = get(prices, $S(\\\"Banana\\\"));\\n\"\n      \"var apple_price  = get(prices, $S(\\\"Apple\\\"));\\n\"\n      \"\\n\"\n      \"show(pear_price);   /* 55 */\\n\"\n      \"show(banana_price); /*  6 */\\n\"\n      \"show(apple_price);  /* 12 */\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic struct Method* Get_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"get\", \n      \"var get(var self, var key);\",\n      \"Get the value at a given `key` for object `self`.\"\n    }, {\n      \"set\", \n      \"void set(var self, var key, var val);\",\n      \"Set the value at a given `key` for object `self`.\"\n    }, {\n      \"mem\", \n      \"bool mem(var self, var key);\",\n      \"Returns true if `key` is a member of the object `self`.\"\n    }, {\n      \"rem\", \n      \"void rem(var self, var key);\",\n      \"Removes the `key` from object `self`.\"\n    }, {\n      \"key_type\", \n      \"var key_type(var self);\",\n      \"Returns the key type for the object `self`.\"\n    }, {\n      \"val_type\", \n      \"var val_type(var self);\",\n      \"Returns the value type for the object `self`.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nvar Get = Cello(Get,\n  Instance(Doc,\n    Get_Name,       Get_Brief,    Get_Description, \n    Get_Definition, Get_Examples, Get_Methods));\n\nvar get(var self, var key) {\n  return method(self, Get, get, key);\n}\n\nvoid set(var self, var key, var val) {\n  method(self, Get, set, key, val);\n}\n\nbool mem(var self, var key) {\n  return method(self, Get, mem, key);\n}\n\nvoid rem(var self, var key) {\n  method(self, Get, rem, key);\n}\n\nvar key_type(var self) {\n  return method(self, Get, key_type);\n}\n\nvar val_type(var self) {\n  return method(self, Get, val_type);  \n}\n"
  },
  {
    "path": "src/Hash.c",
    "content": "#include \"Cello.h\"\n\nstatic const char* Hash_Name(void) {\n  return \"Hash\";\n}\n\nstatic const char* Hash_Brief(void) {\n  return \"Hashable\";\n}\n\nstatic const char* Hash_Description(void) {\n  return\n    \"The `Hash` class provides a mechanism for hashing an object. This hash \"\n    \"value should remain the same across objects that are also considered \"\n    \"equal by the `Cmp` class. For objects that are not considered equal this \"\n    \"value should aim to be evenly distributed across integers.\"\n    \"\\n\\n\"\n    \"This is not a cryptographic hash. It is used for various objects or \"\n    \"data structures that require fast hashing such as the `Table` type. Due \"\n    \"to this it should not be used for cryptography or security.\"\n    \"\\n\\n\"\n    \"By default an object is hashed by using its raw memory with the \"\n    \"[Murmurhash](http://en.wikipedia.org/wiki/MurmurHash) algorithm. Due to \"\n    \"the link between them it is recommended to only override `Hash` and \"\n    \"`Cmp` in conjunction.\";\n}\n\nstatic const char* Hash_Definition(void) {\n  return\n    \"struct Hash {\\n\"\n    \"  uint64_t (*hash)(var);\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* Hash_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"println(\\\"%li\\\", $I(hash($I(  1)))); /*   1 */\\n\"\n      \"println(\\\"%li\\\", $I(hash($I(123)))); /* 123 */\\n\"\n      \"\\n\"\n      \"/* 866003103 */\\n\"\n      \"println(\\\"%li\\\", $I(hash_data($I(123), size(Int))));\\n\"\n      \"\\n\"\n      \"println(\\\"%li\\\", $I(hash($S(\\\"Hello\\\"))));  /* -1838682532 */\\n\"\n      \"println(\\\"%li\\\", $I(hash($S(\\\"There\\\"))));  /*   961387266 */\\n\"\n      \"println(\\\"%li\\\", $I(hash($S(\\\"People\\\")))); /*   697467069 */\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic struct Method* Hash_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"hash\", \n      \"uint64_t hash(var self);\",\n      \"Get the hash value for the object `self`.\"\n    }, {\n      \"hash_data\", \n      \"uint64_t hash_data(void* data, size_t num);\",\n      \"Hash `num` bytes pointed to by `data` using \"\n      \"[Murmurhash](http://en.wikipedia.org/wiki/MurmurHash).\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nvar Hash = Cello(Hash,\n  Instance(Doc,\n    Hash_Name,       Hash_Brief,    Hash_Description, \n    Hash_Definition, Hash_Examples, Hash_Methods));\n    \nuint64_t hash_data(const void* data, size_t size) {\n  \n  const uint64_t m = 0xc6a4a7935bd1e995;\n\tconst int r = 47;\n\tconst uint8_t * d = (const uint8_t*)data;\n\tconst uint8_t * end = d + (size & ~7ULL);\n  \n\tuint64_t h = 0xCe110 ^ (size * m);\n\n\twhile (d != end) {\n\t\tuint64_t k;\n\t\tmemcpy(&k, d, sizeof(uint64_t));\n\t\td += sizeof(uint64_t);\n\t\tk *= m; \n\t\tk ^= k >> r; \n\t\tk *= m; \n\t\th ^= k;\n\t\th *= m; \n\t}\n\n\tswitch (size & 7) {\n    case 7: h ^= (uint64_t)(d[6]) << 48;\n    case 6: h ^= (uint64_t)(d[5]) << 40;\n    case 5: h ^= (uint64_t)(d[4]) << 32;\n    case 4: h ^= (uint64_t)(d[3]) << 24;\n    case 3: h ^= (uint64_t)(d[2]) << 16;\n    case 2: h ^= (uint64_t)(d[1]) << 8;\n    case 1: h ^= (uint64_t)(d[0]);\n            h *= m;\n\t};\n  \n\th ^= h >> r;\n\th *= m;\n\th ^= h >> r;\n\n\treturn h;\n\n}\n    \nuint64_t hash(var self) {\n  \n  struct Hash* h = instance(self, Hash);\n  if (h and h->hash) {\n    return h->hash(self);\n  }\n  \n  return hash_data(self, size(type_of(self)));\n  \n}\n\n"
  },
  {
    "path": "src/Iter.c",
    "content": "#include \"Cello.h\"\n\nvar _ = CelloEmpty(_);\nvar Terminal = CelloEmpty(Terminal);\n\nstatic const char* Iter_Name(void) {\n  return \"Iter\";\n}\n\nstatic const char* Iter_Brief(void) {\n  return \"Iterable\";\n}\n\nstatic const char* Iter_Description(void) {\n  return\n    \"The `Iter` class is implemented by types which can be looped over. This \"\n    \"allows them to be used in conjunction with the `foreach` macro as well \"\n    \"as various other components of Cello.\"\n    \"\\n\\n\"\n    \"To signal that an interation has finished an iteration should return the \"\n    \"Cello object `Terminal`. Due to this - the `Terminal` object cannot be \"\n    \"placed inside of Tuples because it artificially shortens their length.\";\n}\n\nstatic const char* Iter_Definition(void) {\n  return\n    \"struct Iter {\\n\"\n    \"  var (*iter_init)(var);\\n\"\n    \"  var (*iter_next)(var, var);\\n\"\n    \"  var (*iter_prev)(var, var);\\n\"\n    \"  var (*iter_last)(var);\\n\"\n    \"  var (*iter_type)(var);\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* Iter_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var x = new(Array, Int, $I(1), $I(2), $I(5));\\n\"\n      \"\\n\"\n      \"foreach(o in x) {\\n\"\n      \"  show(o); /* 1, 2, 5 */\\n\"\n      \"}\\n\"\n    }, {\n      \"Table\",\n      \"var prices = new(Table, String, Int);\\n\"\n      \"set(prices, $S(\\\"Apple\\\"),  $I(12));\\n\"\n      \"set(prices, $S(\\\"Banana\\\"), $I( 6));\\n\"\n      \"set(prices, $S(\\\"Pear\\\"),   $I(55));\\n\"\n      \"\\n\"\n      \"foreach(key in prices) {\\n\"\n      \"  var price = get(prices, key);\\n\"\n      \"  print(\\\"Price of %$ is %$\\\\n\\\", key, price);\\n\"\n      \"}\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic struct Method* Iter_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"foreach\", \n      \"#define foreach(...)\\n\",\n      \"Iterate over elements in a loop.\"\n    }, {\n      \"iter_init\", \n      \"var iter_init(var self);\\n\"\n      \"var iter_last(var self);\",\n      \"Return the initial item (or final item) in the iteration over `self`.\"\n    }, {\n      \"iter_next\", \n      \"var iter_next(var self, var curr);\\n\"\n      \"var iter_prev(var self, var curr);\",\n      \"Given the current item `curr`, return the next (or previous) item in \"\n      \"the iteration over `self`.\"\n    }, {\n      \"iter_type\", \n      \"var iter_type(var self);\",\n      \"Returns the type of item that can be expected to be returned by the \"\n      \"iterable.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nvar Iter = Cello(Iter,\n  Instance(Doc,\n    Iter_Name,       Iter_Brief,    Iter_Description, \n    Iter_Definition, Iter_Examples, Iter_Methods));\n\nvar iter_init(var self) {\n  return method(self, Iter, iter_init);\n}\n\nvar iter_next(var self, var curr) {\n  return method(self, Iter, iter_next, curr);\n}\n\nvar iter_last(var self) {\n  return method(self, Iter, iter_last);\n}\n\nvar iter_prev(var self, var curr) {\n  return method(self, Iter, iter_prev, curr);\n}\n\nvar iter_type(var self) {\n  return method(self, Iter, iter_type);  \n}\n\nstatic const char* Range_Name(void) {\n  return \"Range\";\n}\n\nstatic const char* Range_Brief(void) {\n  return \"Integer Sequence\";\n}\n\nstatic const char* Range_Description(void) {\n  return\n    \"The `Range` type is a basic iterable which acts as a virtual \"\n    \"sequence of integers, starting from some value, stopping at some value \"\n    \"and incrementing by some step.\"\n    \"\\n\\n\"\n    \"This can be a useful replacement for the standard C `for` loop with \"\n    \"decent performance but returning a Cello `Int`. It is constructable on \"\n    \"the stack with the `range` macro which makes it practical and easy to \"\n    \"use.\";\n}\n\nstatic const char* Range_Definition(void) {\n  return\n    \"struct Range {\\n\"\n    \"  var value;\\n\"\n    \"  int64_t start;\\n\"\n    \"  int64_t stop;\\n\"\n    \"  int64_t step;\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* Range_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"/* Iterate 0 to 10 */\\n\"\n      \"foreach (i in range($I(10))) {\\n\"\n      \"  print(\\\"%i\\\\n\\\", i);\\n\"\n      \"}\\n\"\n      \"\\n\"\n      \"/* Iterate 10 to 20 */\\n\"\n      \"foreach (i in range($I(10), $I(20))) {\\n\"\n      \"  print(\\\"%i\\\\n\\\", i);\\n\"\n      \"}\\n\"\n      \"\\n\"\n      \"/* Iterate 10 to 20 with a step of 5 */\\n\"\n      \"foreach (i in range($I(10), $I(20), $I(5))) {\\n\"\n      \"  print(\\\"%i\\\\n\\\", i);\\n\"\n      \"}\\n\"\n      \"\\n\"\n      \"/* Iterate 20 to 10 */\\n\"\n      \"foreach (i in range($I(10), $I(20), $I(-1))) {\\n\"\n      \"  print(\\\"%i\\\\n\\\", i);\\n\"\n      \"}\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic struct Method* Range_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"range\", \n      \"#define range(...)\",\n      \"Construct a `Range` object on the stack.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nvar range_stack(var self, var args) {\n  \n  struct Range* r = self;\n  size_t nargs = len(args);\n  \n  if (nargs > 3) {\n    throw(FormatError, \"Received too many arguments to Range constructor\");\n  }\n  \n  switch (nargs) {\n    case 0:\n      r->start = 0;\n      r->stop  = 0;\n      r->step  = 1;\n    break;\n    case 1:\n      r->start = 0;\n      r->stop  = c_int(get(args, $I(0)));\n      r->step  = 1;\n    break;\n    case 2:\n      r->start = get(args, $I(0)) is _ ? 0 : c_int(get(args, $I(0)));\n      r->stop  = c_int(get(args, $I(1)));\n      r->step  = 1;\n    break;\n    case 3:\n      r->start = get(args, $I(0)) is _ ? 0 : c_int(get(args, $I(0)));\n      r->stop  = c_int(get(args, $I(1)));\n      r->step  = get(args, $I(2)) is _ ? 1 : c_int(get(args, $I(2)));\n    break;\n  }\n  \n  return self;\n  \n}\n\nstatic void Range_New(var self, var args) {\n  struct Range* r = self;\n  r->value = new(Int);  \n  range_stack(self, args);\n}\n\nstatic void Range_Del(var self) {\n  struct Range* r = self;\n  del(r->value);\n}\n\nstatic void Range_Assign(var self, var obj) {\n  struct Range* r = self;\n  struct Range* o = cast(obj, Range);\n  assign(r->value, o->value);\n  r->start = o->start;\n  r->stop = o->stop;\n  r->step = o->step;\n}\n\nstatic int Range_Cmp(var self, var obj) {\n  struct Range* r = self;\n  struct Range* o = cast(obj, Range);\n  return memcmp(&r->start, &o->start, sizeof(int64_t) * 3);\n}\n\nstatic var Range_Iter_Init(var self) {\n  struct Range* r = self;\n  struct Int* i = r->value;\n  if (r->step == 0) { return Terminal; }\n  if (r->step  > 0) { i->val = r->start; }\n  if (r->step  < 0) { i->val = r->stop-1; }\n  if (r->step  > 0 and i->val >= r->stop) { return Terminal; }\n  if (r->step  < 0 and i->val < r->start) { return Terminal; }\n  return i;\n}\n\nstatic var Range_Iter_Last(var self) {\n  struct Range* r = self;\n  struct Int* i = r->value;\n  if (r->step == 0) { return Terminal; }\n  if (r->step  > 0) { i->val = r->stop-1; }\n  if (r->step  < 0) { i->val = r->start; }\n  if (r->step  > 0 and i->val < r->start) { return Terminal; }\n  if (r->step  < 0 and i->val >= r->stop) { return Terminal; }\n  return i;\n}\n\nstatic var Range_Iter_Next(var self, var curr) {\n  struct Range* r = self;\n  struct Int* i = r->value;\n  i->val += r->step;\n  if (r->step == 0) { return Terminal; }\n  if (r->step  > 0 and i->val >= r->stop) { return Terminal; }\n  if (r->step  < 0 and i->val < r->start) { return Terminal; }\n  return i;\n}\n\nstatic var Range_Iter_Prev(var self, var curr) {\n  struct Range* r = self;\n  struct Int* i = r->value;\n  i->val -= r->step;\n  if (r->step == 0) { return Terminal; }\n  if (r->step  > 0 and i->val < r->start) { return Terminal; }\n  if (r->step  < 0 and i->val >= r->stop) { return Terminal; }\n  return i;\n}\n\nstatic var Range_Iter_Type(var self) {\n  return Int;\n}\n\nstatic size_t Range_Len(var self) {\n  struct Range* r = self;\n  if (r->step == 0) { return 0; }\n  if (r->step  > 0) { return ((r->stop-1) - r->start) /  r->step + 1; }\n  if (r->step  < 0) { return ((r->stop-1) - r->start) / -r->step + 1; }\n  return 0;\n}\n\nstatic var Range_Get(var self, var key) {\n  struct Range* r = self;\n  struct Int* x = r->value;\n  \n  int64_t i = c_int(key);\n  i = i < 0 ? Range_Len(r)+i : i;\n  \n  if (r->step == 0) {\n    x->val = 0;\n    return x;\n  }\n  \n  if (r->step  > 0 and (r->start + r->step * i) < r->stop) {\n    x->val = r->start  + r->step * i;\n    return x;\n  }\n  \n  if (r->step  < 0 and (r->stop-1 + r->step * i) >= r->start) {\n    x->val = r->stop-1 + r->step * i;\n    return x;\n  }\n  \n  return throw(IndexOutOfBoundsError, \n      \"Index '%i' out of bounds for Range of start %i, stop %i and step %i.\", \n      key, $I(r->start), $I(r->stop), $I(r->step));\n}\n\nstatic bool Range_Mem(var self, var key) {\n  struct Range* r = self;\n  int64_t i = c_int(key);\n  i = i < 0 ? Range_Len(r)+i : i;\n  if (r->step == 0) { return false; }\n  if (r->step  > 0) {\n    return i >= r->start and i < r->stop and (i - r->start) % r->step is 0;\n  }\n  if (r->step  < 0) {\n    return i >= r->start and i < r->stop and (i - (r->stop-1)) % -r->step is 0;\n  }\n  return false;\n}\n\nstatic int Range_Show(var self, var output, int pos) {\n  struct Range* r = self;\n  pos = print_to(output, pos, \"<'Range' At 0x%p [\", self);\n  var curr = Range_Iter_Init(self);\n  while (curr isnt Terminal) {\n    pos = print_to(output, pos, \"%i\", curr);\n    curr = Range_Iter_Next(self, curr);\n    if (curr isnt Terminal) { pos = print_to(output, pos, \", \"); }\n  }\n  return print_to(output, pos, \"]>\");\n}\n\nvar Range = Cello(Range,\n  Instance(Doc,\n    Range_Name,       Range_Brief,    Range_Description, \n    Range_Definition, Range_Examples, Range_Methods),\n  Instance(New,       Range_New, Range_Del),\n  Instance(Assign,    Range_Assign),\n  Instance(Cmp,       Range_Cmp),\n  Instance(Len,       Range_Len),\n  Instance(Get,       Range_Get, NULL, Range_Mem, NULL),\n  Instance(Show,      Range_Show, NULL),\n  Instance(Iter, \n    Range_Iter_Init,  Range_Iter_Next, \n    Range_Iter_Last,  Range_Iter_Prev, Range_Iter_Type));\n\nstatic const char* Slice_Name(void) {\n  return \"Slice\";\n}\n\nstatic const char* Slice_Brief(void) {\n  return \"Partial Iterable\";\n}\n\nstatic const char* Slice_Description(void) {\n  return\n    \"The `Slice` type is an iterable that allows one to only iterate over \"\n    \"part of another iterable. Given some start, stop and step, only \"\n    \"those entries described by the `Slice` are returned in the iteration.\"\n    \"\\n\\n\"\n    \"Under the hood the `Slice` object still iterates over the whole iterable \"\n    \"but it only returns those values in the range given.\";\n}\n\nstatic const char* Slice_Definition(void) {\n  return\n    \"struct Slice {\\n\"\n    \"  var iter;\\n\"\n    \"  var range;\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* Slice_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var x = tuple(\\n\"\n      \"  $S(\\\"Hello\\\"), $S(\\\"There\\\"), $S(\\\"World\\\"), $S(\\\"!\\\"));\\n\"\n      \"\\n\"\n      \"/* Iterate over elements 0 to 2 */\\n\"\n      \"foreach (s in slice(x, $I(2))) {\\n\"\n      \"  print(\\\"%s\\\\n\\\", s);\\n\"\n      \"}\\n\"\n      \"\\n\"\n      \"/* Iterate over elements 1 to 2 */\\n\"\n      \"foreach (s in slice(x, $I(1), $I(2))) {\\n\"\n      \"  print(\\\"%s\\\\n\\\", s);\\n\"\n      \"}\\n\"\n      \"\\n\"\n      \"/* Iterate over every other element */\\n\"\n      \"foreach (s in slice(x, _, _, $I(2))) {\\n\"\n      \"  print(\\\"%s\\\\n\\\", s);\\n\"\n      \"}\\n\"\n      \"\\n\"\n      \"/* Iterate backwards, starting from element 3 */\\n\"\n      \"foreach (s in slice(x, _, $I(2), $I(-1))) {\\n\"\n      \"  print(\\\"%s\\\\n\\\", s);\\n\"\n      \"}\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic struct Method* Slice_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"slice\", \n      \"#define slice(I, ...)\",\n      \"Construct a `Slice` object on the stack over iterable `I`.\"\n    }, {\n      \"reverse\",\n      \"#define reverse(I)\",\n      \"Construct a `Slice` object that iterates over iterable `I` in reverse \"\n      \"order.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nstatic int64_t Slice_Arg(int part, size_t n, var arg) {\n  \n  if (arg is _) {\n    if (part is 0) { return 0; }\n    if (part is 1) { return n; }\n    if (part is 2) { return 1; }\n  }\n  \n  int64_t a = c_int(arg);\n  \n  if (part isnt 2) {\n    a = a < 0 ? n+a : a;\n    a = a > n ? n   : a;\n    a = a < 0 ? 0   : a;\n  }\n  \n  return a;\n}\n\nvar slice_stack(var self, var args) {\n  \n  size_t nargs = len(args);\n\n  if (nargs > 4) {\n    throw(FormatError, \"Received too many arguments to Slice constructor\");\n  }\n  \n  if (nargs < 1) {\n    throw(FormatError, \"Received too few arguments to Slice constructor\");\n  }\n  \n  struct Slice* s = self;\n  s->iter  = get(args, $I(0));\n  \n  struct Range* r = s->range;\n  size_t n = len(s->iter);\n  \n  switch (nargs) {\n    case 1:\n      r->start = 0;\n      r->stop  = n;\n      r->step  = 1;\n    break;\n    case 2:\n      r->start = 0;\n      r->stop  = Slice_Arg(1, n, get(args, $I(1)));\n      r->step  = 1;\n    break;\n    case 3:\n      r->start = Slice_Arg(0, n, get(args, $I(1)));\n      r->stop  = Slice_Arg(1, n, get(args, $I(2)));\n      r->step  = 1;\n    break;\n    case 4:\n      r->start = Slice_Arg(0, n, get(args, $I(1)));\n      r->stop  = Slice_Arg(1, n, get(args, $I(2)));\n      r->step  = Slice_Arg(2, n, get(args, $I(3)));\n    break;\n  }\n  \n  return self;\n  \n}\n\nstatic void Slice_New(var self, var args) {\n  struct Slice* s = self;\n  s->range = new(Range);\n  slice_stack(self, args);\n}\n\nstatic void Slice_Del(var self) {\n  struct Slice* s = self;\n  del(s->range);\n}\n\nstatic void Slice_Assign(var self, var obj) {\n  struct Slice* s = self;\n  struct Slice* o = cast(obj, Slice);\n  s->iter = o->iter;\n  assign(s->range, o->range);\n}\n\nstatic int Slice_Cmp(var self, var obj) {\n  struct Slice* s = self;\n  struct Slice* o = cast(obj, Slice);\n  if (s->iter > o->iter) { return  1; }\n  if (s->iter < o->iter) { return -1; }\n  return cmp(s->range, o->range);\n}\n\nstatic var Slice_Iter_Init(var self) {\n  struct Slice* s = self;\n  struct Range* r = s->range;\n  \n  if (r->step > 0) {\n    var curr = iter_init(s->iter);\n    for(int64_t i = 0; i < r->start; i++) {\n      curr = iter_next(s->iter, curr);\n    }\n    return curr;\n  }\n  \n  if (r->step < 0) {\n    var curr = iter_last(s->iter);\n    for (int64_t i = 0; i < (int64_t)len(s->iter)-r->stop; i++) {\n      curr = iter_prev(s->iter, curr);\n    }\n    return curr;\n  }\n\n  return Terminal;\n}\n\nstatic var Slice_Iter_Next(var self, var curr) {\n  struct Slice* s = self;\n  struct Range* r = s->range;\n  \n  if (r->step > 0) {\n    for (int64_t i = 0; i < r->step; i++) {\n      curr = iter_next(s->iter, curr);\n    }\n  }\n  \n  if (r->step < 0) {\n    for (int64_t i = 0; i < -r->step; i++) {\n      curr = iter_prev(s->iter, curr);\n    }\n  }\n  \n  return curr;\n}\n\nstatic var Slice_Iter_Type(var self) {\n  struct Slice* s = self;\n  return iter_type(s->iter);\n}\n\nstatic var Slice_Iter_Last(var self) {\n  struct Slice* s = self;\n  struct Range* r = s->range;\n  \n  if (r->step > 0) {\n    var curr = iter_last(s->iter);\n    for(int64_t i = 0; i < (int64_t)len(s->iter)-r->stop; i++) {\n      curr = iter_prev(s->iter, curr);\n    }\n    return curr;\n  }\n  \n  if (r->step < 0) {\n    var curr = iter_init(s->iter);\n    for(int64_t i = 0; i < r->start; i++) {\n      curr = iter_next(s->iter, curr);\n    }\n    return curr;\n  }\n\n  return Terminal;\n}\n\nstatic var Slice_Iter_Prev(var self, var curr) {\n  struct Slice* s = self;\n  struct Range* r = s->range;\n  \n  if (r->step > 0) {\n    for (int64_t i = 0; i < r->step; i++) {\n      curr = iter_prev(s->iter, curr);\n    }\n  }\n  \n  if (r->step < 0) {\n    for (int64_t i = 0; i < -r->step; i++) {\n      curr = iter_next(s->iter, curr);\n    }\n  }\n  \n  return curr;\n}\n\nstatic size_t Slice_Len(var self) {\n  struct Slice* s = self;\n  return Range_Len(s->range);\n}\n\nstatic var Slice_Get(var self, var key) {\n  struct Slice* s = self;\n  return get(s->iter, Range_Get(s->range, key));\n}\n\nstatic bool Slice_Mem(var self, var key) {\n  var curr = Slice_Iter_Init(self);\n  while (curr) {\n    if (eq(curr, key)) { return true; }\n    curr = Slice_Iter_Next(self, curr);\n  }\n  return false;\n}\n\nstatic int Slice_Show(var self, var output, int pos) {\n  struct Slice* s = self;\n  pos = print_to(output, pos, \"<'Slice' At 0x%p [\", self);\n  var curr = Slice_Iter_Init(self);\n  while (curr isnt Terminal) {\n    pos = print_to(output, pos, \"%$\", curr);\n    curr = Slice_Iter_Next(self, curr);\n    if (curr isnt Terminal) { pos = print_to(output, pos, \", \"); }\n  }\n  return print_to(output, pos, \"]>\");\n}\n\nvar Slice = Cello(Slice,\n  Instance(Doc,\n    Slice_Name,       Slice_Brief,    Slice_Description, \n    Slice_Definition, Slice_Examples, Slice_Methods),\n  Instance(New,      Slice_New, Slice_Del),\n  Instance(Assign,   Slice_Assign),\n  Instance(Cmp,      Slice_Cmp),\n  Instance(Len,      Slice_Len),\n  Instance(Get,      Slice_Get, NULL, Slice_Mem, NULL),\n  Instance(Iter, \n    Slice_Iter_Init, Slice_Iter_Next, \n    Slice_Iter_Last, Slice_Iter_Prev, Slice_Iter_Type),\n  Instance(Show,     Slice_Show, NULL));\n  \n  \nstatic const char* Zip_Name(void) {\n  return \"Zip\";\n}\n\nstatic const char* Zip_Brief(void) {\n  return \"Multiple Iterator\";\n}\n\nstatic const char* Zip_Description(void) {\n  return\n    \"The `Zip` type can be used to combine multiple iterables into one which \"\n    \"is then iterated over all at once and returned as a Tuple. The Zip object \"\n    \"only iterates when all of it's sub iterators have valid items. More \"\n    \"specifically the Zip iteration will terminate if _any_ of the sub \"\n    \"iterators terminate.\";\n}\n\nstatic const char* Zip_Definition(void) {\n  return\n    \"struct Zip {\\n\"\n    \"  var iters;\\n\"\n    \"  var values;\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* Zip_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"/* Iterate over two iterables at once */\\n\"\n      \"var x = new(Array, Int, $I(100), $I(200), $I(130));\\n\"\n      \"var y = new(Array, Float, $F(0.1), $F(0.2), $F(1.3));\\n\"\n      \"foreach (pair in zip(x, y)) {\\n\"\n      \"  print(\\\"x: %$\\\\n\\\", get(pair, $I(0)));\\n\"\n      \"  print(\\\"y: %$\\\\n\\\", get(pair, $I(1)));\\n\"\n      \"}\\n\"\n      \"\\n\"\n      \"/* Iterate over iterable with count */\\n\"\n      \"foreach (pair in enumerate(x)) {\\n\"\n      \"  print(\\\"%i: %$\\\\n\\\", get(pair, $I(0)), get(pair, $I(1)));\\n\"\n      \"}\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic struct Method* Zip_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"zip\", \n      \"#define zip(...)\",\n      \"Construct a `Zip` object on the stack.\"\n    }, {\n      \"enumerate\", \n      \"#define enumerate(I)\",\n      \"Zip the iterable `I` with a `Range` object of the same length.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nvar zip_stack(var self) {\n  struct Zip* z = self;\n  size_t nargs = len(z->iters);\n  struct Tuple* t = z->values;\n  for (size_t i = 0; i < nargs; i++) {\n    t->items[i] = _;\n  }\n  t->items[nargs] = Terminal;\n  return z;\n}\n\nstatic void Zip_New(var self, var args) {\n  struct Zip* z = self;\n  z->iters = new(Tuple);\n  z->values = new(Tuple);\n  assign(z->iters, args);\n  for (size_t i = 0; i < len(args); i++) {\n    push(z->values, _);\n  }\n}\n\nstatic void Zip_Del(var self) {\n  struct Zip* z = self;\n  del(z->iters);\n  del(z->values);\n}\n\nstatic void Zip_Assign(var self, var obj) {\n  struct Zip* z = self;\n  struct Zip* o = cast(obj, Zip);\n  assign(z->iters, o->iters);\n  assign(z->values, o->values);\n}\n\nstatic var Zip_Iter_Init(var self) {\n  struct Zip* z = self;\n  struct Tuple* values = z->values;\n  struct Tuple* iters = z->iters;\n  size_t num = len(iters);\n  if (num is 0) { return Terminal; }\n  for (size_t i = 0; i < num; i++) {\n    var init = iter_init(iters->items[i]);\n    if (init is Terminal) { return Terminal; }\n    values->items[i] = init;\n  }\n  return values;\n}\n\nstatic var Zip_Iter_Last(var self) {\n  struct Zip* z = self;\n  struct Tuple* values = z->values;\n  struct Tuple* iters = z->iters;\n  size_t num = len(iters);\n  if (num is 0) { return Terminal; }\n  for (size_t i = 0; i < num; i++) {\n    var last = iter_last(iters->items[i]);\n    if (last is Terminal) { return Terminal; }\n    values->items[i] = last;\n  }\n  return values;\n}\n\nstatic var Zip_Iter_Next(var self, var curr) {\n  struct Zip* z = self;\n  struct Tuple* values = z->values;\n  struct Tuple* iters = z->iters;\n  size_t num = len(iters);\n  if (num is 0) { return Terminal; }\n  for (size_t i = 0; i < num; i++) {\n    var next = iter_next(iters->items[i], get(curr, $I(i)));\n    if (next is Terminal) { return Terminal; }\n    values->items[i] = next;\n  }\n  return values;\n}\n\nstatic var Zip_Iter_Prev(var self, var curr) {\n  struct Zip* z = self;\n  struct Tuple* values = z->values;\n  struct Tuple* iters = z->iters;\n  size_t num = len(iters);\n  if (num is 0) { return Terminal; }\n  for (size_t i = 0; i < num; i++) {\n    var prev = iter_prev(iters->items[i], get(curr, $I(i)));\n    if (prev is Terminal) { return Terminal; }\n    values->items[i] = prev;\n  }\n  return values;\n}\n\nstatic var Zip_Iter_Type(var self) {\n  return Tuple;\n}\n\nstatic size_t Zip_Len(var self) {\n  struct Zip* z = self;\n  struct Tuple* values = z->values;\n  struct Tuple* iters = z->iters;\n  size_t num = len(iters);\n  if (num is 0) { return 0; }\n  size_t mlen = len(iters->items[0]);\n  for (size_t i = 1; i < num; i++) {\n    size_t num = len(iters->items[i]);\n    mlen = num < mlen ? num : mlen;\n  }\n  return mlen;\n}\n\nstatic var Zip_Get(var self, var key) {\n  struct Zip* z = self;\n  struct Tuple* values = z->values;\n  struct Tuple* iters = z->iters;\n  size_t num = len(iters);\n  \n  for (size_t i = 0; i < num; i++) {\n    values->items[i] = get(iters->items[i], key);\n  }\n  \n  return values;\n}\n\nstatic bool Zip_Mem(var self, var key) {\n  foreach (item in self) {\n    if (eq(item, key)) { return true; }\n  }\n  return false;\n}\n\nvar Zip = Cello(Zip,\n  Instance(Doc,\n    Zip_Name,         Zip_Brief,    Zip_Description, \n    Zip_Definition,   Zip_Examples, Zip_Methods),\n  Instance(New,       Zip_New, Zip_Del),\n  Instance(Assign,    Zip_Assign),\n  Instance(Len,       Zip_Len),\n  Instance(Get,       Zip_Get, NULL, Zip_Mem, NULL),\n  Instance(Iter, \n    Zip_Iter_Init,  Zip_Iter_Next, \n    Zip_Iter_Last,  Zip_Iter_Prev, Zip_Iter_Type));\n\nvar enumerate_stack(var self) {\n  struct Zip* z = self;\n  struct Range* r = get(z->iters, $I(0));\n  r->stop = len(get(z->iters, $I(1)));\n  return self;\n}\n\nstatic const char* Filter_Name(void) {\n  return \"Filter\";\n}\n\nstatic const char* Filter_Brief(void) {\n  return \"Filtered Iterable\";\n}\n\nstatic const char* Filter_Description(void) {\n  return\n    \"The `Filter` type can be used to filter the results of some iterable. \"\n    \"Given a callable object `Filter` iterable returns only those items in \"\n    \"the original iterable for where calling the function returns a \"\n    \"non-`NULL` value.\";\n}\n\nstatic const char* Filter_Definition(void) {\n  return\n    \"struct Filter {\\n\"\n    \"  var iter;\\n\"\n    \"  var func;\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* Filter_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var greater_than_two(var x) {\\n\"\n      \"  return c_int(x) > 2 ? x : NULL;\\n\"\n      \"}\\n\"\n      \"\\n\"\n      \"var x = new(Array, Int, $I(0), $I(5), $I(2), $I(9));\\n\"\n      \"\\n\"\n      \"foreach (n in filter(x, $(Function, greater_than_two))) {\\n\"\n      \"  show(n); /* 5, 9 */\\n\"\n      \"}\\n\"\n    }, {\n      \"Usage 2\",\n      \"var mem_hello(var x) {\\n\"\n      \"  return mem(x, $S(\\\"Hello\\\")) ? x : NULL;\\n\"\n      \"}\\n\"\n      \"\\n\"\n      \"var x = new(Tuple, \\n\"\n      \"  $S(\\\"Hello World\\\"), $S(\\\"Hello Dan\\\"), \\n\"\n      \"  $S(\\\"Bonjour\\\"));\\n\"\n      \"\\n\"\n      \"var y = new(Tuple);\\n\"\n      \"assign(y, filter(x, $(Function, mem_hello)));\\n\"\n      \"show(y); /* tuple(\\\"Hello World\\\", \\\"Hello Dan\\\") */\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic struct Method* Filter_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"filter\", \n      \"#define filter(I, F)\",\n      \"Construct a `Filter` object on the stack over iterable `I` with \"\n      \"filter function `F`.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nstatic void Filter_New(var self, var args) {\n  struct Filter* f = self;\n  f->iter = get(args, $I(0));\n  f->func = get(args, $I(1));\n}\n\nstatic var Filter_Iter_Init(var self) {\n  struct Filter* f = self;\n  var curr = iter_init(f->iter);\n  while (true) {\n    if (curr is Terminal or call_with(f->func, curr)) {\n      return curr;\n    } else {\n      curr = iter_next(f->iter, curr);\n    }\n  }\n  return Terminal;\n}\n\nstatic var Filter_Iter_Last(var self) {\n  struct Filter* f = self;\n  var curr = iter_last(f->iter);\n  while (true) {\n    if (curr is Terminal or call_with(f->func, curr)) {\n      return curr;\n    } else {\n      curr = iter_prev(f->iter, curr);\n    }\n  }\n  return Terminal;\n}\n\nstatic var Filter_Iter_Next(var self, var curr) {\n  struct Filter* f = self;\n  curr = iter_next(f->iter, curr);\n  while (true) {\n    if (curr is Terminal or call_with(f->func, curr)) {\n      return curr;\n    } else {\n      curr = iter_next(f->iter, curr);\n    }\n  }\n  return Terminal;\n}\n\nstatic var Filter_Iter_Prev(var self, var curr) {\n  struct Filter* f = self;\n  curr = iter_prev(f->iter, curr);\n  while (true) {\n    if (curr is Terminal or call_with(f->func, curr)) {\n      return curr;\n    } else {\n      curr = iter_prev(f->iter, curr);\n    }\n  }\n  return Terminal;\n}\n\nstatic var Filter_Iter_Type(var self) {\n  struct Filter* f = self;\n  return iter_type(f->iter);\n}\n\nstatic bool Filter_Mem(var self, var key) {\n  foreach (item in self) {\n    if (eq(item, key)) { return true; }\n  }\n  return false;\n}\n\nvar Filter = Cello(Filter,\n  Instance(Doc,\n    Filter_Name,       Filter_Brief,    Filter_Description, \n    Filter_Definition, Filter_Examples, Filter_Methods),\n  Instance(New,        Filter_New, NULL),\n  Instance(Get,        NULL, NULL, Filter_Mem, NULL),\n  Instance(Iter, \n    Filter_Iter_Init, Filter_Iter_Next, \n    Filter_Iter_Last, Filter_Iter_Prev, Filter_Iter_Type));\n    \n    \nstatic const char* Map_Name(void) {\n  return \"Map\";\n}\n\nstatic const char* Map_Brief(void) {\n  return \"Apply Function to Iterable\";\n}\n\nstatic const char* Map_Description(void) {\n  return\n    \"The `Map` type is an iterable that applies some callable to to each \"\n    \"item in another iterable and returns the result. This can be useful to \"\n    \"make more concise iteration when there are callback functions available.\"\n    \"\\n\\n\"\n    \"If the mapping callable is a purely side-effect callable it is possible \"\n    \"to use the `call` function on the `Map` object directly for a quick way \"\n    \"to perform the iteration.\"\n    \"\\n\\n\"\n    \"One downside of `Map` is that the `iter_type` becomes unknown (there is \"\n    \"no way to know what type the callable will return so some objects such \"\n    \"as `Array`s may revert to using `Ref` as the object type when assigned a \"\n    \"`Map`.\";\n}\n\nstatic const char* Map_Definition(void) {\n  return\n    \"struct Map {\\n\"\n    \"  var iter;\\n\"\n    \"  var curr;\\n\"\n    \"  var func;\\n\"\n    \"};\\n\";\n}\n\nstatic struct Method* Map_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"map\", \n      \"#define map(I, F)\",\n      \"Construct a `Map` object on the stack over iterable `I` applying \"\n      \"function `F`.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nstatic struct Example* Map_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var convert_to_int(var x) {\\n\"\n      \"  var y = new(Int);\\n\"\n      \"  look_from(y, x, 0);\\n\"\n      \"  return y;\\n\"\n      \"}\\n\"\n      \"\\n\"\n      \"var x = tuple($S(\\\"1\\\"), $S(\\\"2\\\"), $S(\\\"3\\\"));\\n\"\n      \"\\n\"\n      \"foreach (y in map(x, $(Function, convert_to_int))) {\\n\"\n      \"  show(y); /* 1, 2, 3 */\\n\"\n      \"};\\n\"\n    }, {\n      \"Usage 2\",\n      \"var print_object(var x) {\\n\"\n      \"  println(\\\"Object %$ is of type %$\\\", x, type_of(x));\\n\"\n      \"  return NULL;\\n\"\n      \"}\\n\"\n      \"\\n\"\n      \"var x = tuple($I(0), $S(\\\"Hello!\\\"), $F(2.4));\\n\"\n      \"\\n\"\n      \"call(map(x, $(Function, print_object)));\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic void Map_New(var self, var args) {\n  struct Map* m = self;\n  m->iter = get(args, $I(0));\n  m->func = get(args, $I(1));\n}\n\nstatic var Map_Iter_Init(var self) {\n  struct Map* m = self;\n  m->curr = iter_init(m->iter);\n  if (m->curr is Terminal) {\n    return m->curr;\n  } else {\n    return call_with(m->func, m->curr);\n  }\n}\n\nstatic var Map_Iter_Last(var self) {\n  struct Map* m = self;\n  m->curr = iter_last(m->iter);\n  if (m->curr is Terminal) {\n    return m->curr;\n  } else {\n    return call_with(m->func, m->curr);\n  }\n}\n\nstatic var Map_Iter_Next(var self, var curr) {\n  struct Map* m = self;\n  m->curr = iter_next(m->iter, m->curr);\n  if (m->curr is Terminal) {\n    return m->curr;\n  } else {\n    return call_with(m->func, m->curr);\n  }\n}\n\nstatic var Map_Iter_Prev(var self, var curr) {\n  struct Map* m = self;\n  m->curr = iter_prev(m->iter, m->curr);\n  if (m->curr is Terminal) {\n    return m->curr;\n  } else {\n    return call_with(m->func, m->curr);\n  }\n}\n\nstatic size_t Map_Len(var self) {\n  struct Map* m = self;\n  return len(m->iter);\n}\n\nstatic var Map_Get(var self, var key) {\n  struct Map* m = self;\n  m->curr = get(m->iter, key);\n  if (m->curr is Terminal) {\n    return m->curr;\n  } else {\n    return call_with(m->func, m->curr);\n  }\n}\n\nstatic bool Map_Mem(var self, var key) {\n  foreach (item in self) {\n    if (eq(item, key)) { return true; }\n  }\n  return false;\n}\n\nstatic var Map_Call(var self, var args) {\n  foreach (item in self);\n  return Terminal;\n}\n\nvar Map = Cello(Map,\n  Instance(Doc,\n    Map_Name,       Map_Brief,    Map_Description, \n    Map_Definition, Map_Examples, Map_Methods),\n  Instance(New,     Map_New, NULL),\n  Instance(Len,     Map_Len),\n  Instance(Get,     Map_Get, NULL, Map_Mem, NULL),\n  Instance(Call,    Map_Call),\n  Instance(Iter, \n    Map_Iter_Init, Map_Iter_Next, \n    Map_Iter_Last, Map_Iter_Prev, NULL));\n"
  },
  {
    "path": "src/Len.c",
    "content": "#include \"Cello.h\"\n\nstatic const char* Len_Name(void) {\n  return \"Len\";\n}\n\nstatic const char* Len_Brief(void) {\n  return \"Has a length\";\n}\n\nstatic const char* Len_Description(void) {\n  return\n    \"The `Len` class can be implemented by any type that has a length \"\n    \"associated with it. It is typically implemented by collections \"\n    \"and is often used in conjunction with `Iter` or `Get`.\";\n}\n\nstatic const char* Len_Definition(void) {\n  return\n    \"struct Len {\\n\"\n    \"  size_t (*len)(var);\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* Len_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var x = new(Array, Int, $I(1), $I(2), $I(5));\\n\"\n      \"show($I(len(x))); /* 3 */\\n\"\n      \"var y = $S(\\\"Test\\\");\\n\"\n      \"show($I(len(y))); /* 4 */\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic struct Method* Len_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"len\", \n      \"size_t len(var self);\",\n      \"Returns the length of object `self`.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nvar Len = Cello(Len,\n  Instance(Doc,\n    Len_Name,       Len_Brief,    Len_Description, \n    Len_Definition, Len_Examples, Len_Methods));\n\nsize_t len(var self) {\n  return method(self, Len, len);\n}\n\nbool empty(var self) {\n  return len(self) is 0;\n}\n"
  },
  {
    "path": "src/List.c",
    "content": "#include \"Cello.h\"\n\nstatic const char* List_Name(void) {\n  return \"List\";\n}\n\nstatic const char* List_Brief(void) {\n  return \"Linked List\";\n}\n\nstatic const char* List_Description(void) {\n  return\n    \"The `List` type is a linked list data structure. Elements can be added \"\n    \"and removed from the list and their memory is allocated and deallocated \"\n    \"by the structure. Additionally destructors will be called on objects \"\n    \"once removed.\"\n    \"\\n\\n\"\n    \"Elements are copied into the List using `assign` and will initially have \"\n    \"zero'd memory.\"\n    \"\\n\\n\"\n    \"Lists can provide fast insertion and removal at arbitrary locations \"\n    \"although most other operations will be slow due to having to traverse \"\n    \"the linked list data structure.\"\n    \"\\n\\n\"\n    \"This is largely equivalent to the C++ construct \"\n    \"[std::list](http://www.cplusplus.com/reference/list/list/)\";\n}\n\nstatic struct Example* List_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Construction & Deletion\",\n      \"var x = new(List, Int);\\n\"\n      \"push(x, $I(32));\\n\"\n      \"push(x, $I(6));\\n\"\n      \"\\n\"\n      \"/* <'List' At 0x0000000000414603 [32, 6]> */\\n\"\n      \"show(x);\\n\",\n    }, {\n      \"Element Access\",\n      \"var x = new(List, Float, $F(0.01), $F(5.12));\\n\"\n      \"\\n\"\n      \"show(get(x, $I(0))); /* 0.01 */\\n\"\n      \"show(get(x, $I(1))); /* 5.12 */\\n\"\n      \"\\n\"\n      \"set(x, $I(0), $F(500.1));\\n\"\n      \"show(get(x, $I(0))); /* 500.1 */\\n\",\n    }, {\n      \"Membership\",\n      \"var x = new(List, Int, $I(1), $I(2), $I(3), $I(4));\\n\"\n      \"\\n\"\n      \"show($I(mem(x, $I(1)))); /* 1 */\\n\"\n      \"show($I(len(x)));        /* 4 */\\n\"\n      \"\\n\"\n      \"rem(x, $I(3));\\n\"\n      \"\\n\"\n      \"show($I(mem(x, $I(3)))); /* 0 */\\n\"\n      \"show($I(len(x)));        /* 3 */\\n\"\n      \"show($I(empty(x)));      /* 0 */\\n\"\n      \"\\n\"\n      \"resize(x, 0);\\n\"\n      \"\\n\"\n      \"show($I(empty(x)));      /* 1 */\\n\",\n    }, {\n      \"Iteration\",\n      \"var greetings = new(List, String, \\n\"\n      \"  $S(\\\"Hello\\\"), $S(\\\"Bonjour\\\"), $S(\\\"Hej\\\"));\\n\"\n      \"\\n\"\n      \"foreach(greet in greetings) {\\n\"\n      \"  show(greet);\\n\"\n      \"}\\n\",\n    }, {NULL, NULL}\n  };\n  \n  return examples;\n}\n\n\nstruct List {\n  var type;\n  var head;\n  var tail;\n  size_t tsize;\n  size_t nitems;\n};\n\nstatic var List_Alloc(struct List* l) {\n  var item = calloc(1, 2 * sizeof(var) + sizeof(struct Header) + l->tsize);\n  \n#if CELLO_MEMORY_CHECK == 1\n  if (item is NULL) {\n    throw(OutOfMemoryError, \"Cannot allocate List entry, out of memory!\");\n  }\n#endif\n  \n  return header_init((struct Header*)(\n    (char*)item + 2 * sizeof(var)), l->type, AllocData);\n}\n\nstatic void List_Free(struct List* l, var self) {\n  free((char*)self - sizeof(struct Header) - 2 * sizeof(var));\n}\n\nstatic var* List_Next(struct List* l, var self) {\n  return (var*)((char*)self - sizeof(struct Header) - 1 * sizeof(var));\n}\n\nstatic var* List_Prev(struct List* l, var self) {\n  return (var*)((char*)self - sizeof(struct Header) - 2 * sizeof(var));\n}\n\nstatic var List_At(struct List* l, int64_t i) {\n\n  i = i < 0 ? l->nitems+i : i;\n\n#if CELLO_BOUND_CHECK == 1\n  if (i < 0 or i >= (int64_t)l->nitems) {\n    return throw(IndexOutOfBoundsError,\n      \"Index '%i' out of bounds for List of size %i.\", \n       $(Int, i), $(Int, l->nitems));\n  }\n#endif\n  \n  var item;\n  \n  if (i <= (int64_t)(l->nitems / 2)) {\n    item = l->head;\n    while (i) { item = *List_Next(l, item); i--; }\n  } else {\n    i = l->nitems-i-1;\n    item = l->tail;\n    while (i) { item = *List_Prev(l, item); i--; }\n  }\n  \n  return item;\n}\n\nstatic void List_Push(var self, var obj);\nstatic void List_Rem(var self, var obj);\n\nstatic void List_New(var self, var args) {\n  \n  struct List* l = self;\n  l->type   = cast(get(args, $I(0)), Type);\n  l->tsize  = size(l->type);\n  l->nitems = 0;\n  l->head = NULL;\n  l->tail = NULL;\n  \n  size_t nargs = len(args);\n  for(size_t i = 0; i < nargs-1; i++) {\n    List_Push(self, get(args, $I(i+1)));\n  }\n  \n}\n\nstatic void List_Clear(var self) {\n  struct List* l = self;\n  var item = l->head;\n  while (item) {\n    var next = *List_Next(l, item);\n\t  destruct(item);\n    List_Free(l, item);\n    item = next;\n  }\n  l->tail = NULL;\n  l->head = NULL;\n  l->nitems = 0;\n}\n\nstatic void List_Del(var self) {\n  struct List* l = self;\n  List_Clear(self);\n}\n\nstatic void List_Assign(var self, var obj) {\n  struct List* l = self;\n  \n  List_Clear(self);\n  \n  l->type = implements_method(obj, Iter, iter_type) ? iter_type(obj) : Ref;\n  l->tsize = size(l->type);\n  \n  size_t nargs = len(obj);\n  for (size_t i = 0; i < nargs; i++) {\n    List_Push(self, get(obj, $I(i)));\n  }\n  \n}\n\nstatic void List_Concat(var self, var obj) {\n  foreach (item in obj) {\n    List_Push(self, item);\n  }\n}\n\nstatic var List_Iter_Init(var self);\nstatic var List_Iter_Next(var self, var curr);\n\nstatic int List_Cmp(var self, var obj) {\n  \n  var item0 = List_Iter_Init(self);\n  var item1 = iter_init(obj);\n  \n  while (true) {\n    if (item0 is Terminal and item1 is Terminal) { return 0; }\n    if (item0 is Terminal) { return -1; }\n    if (item1 is Terminal) { return  1; }\n    int c = cmp(item0, item1);\n    if (c < 0) { return -1; }\n    if (c > 0) { return  1; }\n    item0 = List_Iter_Next(self, item0);\n    item1 = iter_next(obj, item1);\n  }\n  \n  return 0;\n}\n\nstatic uint64_t List_Hash(var self) {\n  struct List* l = self;\n  uint64_t h = 0;\n  \n  var item = l->head;\n  for (size_t i = 0; i < l->nitems; i++) {\n    h ^= hash(item);\n    item = *List_Next(l, item);\n  }\n  \n  return h;\n}\n\nstatic size_t List_Len(var self) {\n  struct List* l = self;\n  return l->nitems;\n}\n\nstatic bool List_Mem(var self, var obj) {\n  struct List* l = self;\n  var item = l->head;\n  while (item) {\n    if (eq(item, obj)) { return true; }\n    item = *List_Next(l, item);\n  }\n  return false;\n}\n\nstatic void List_Unlink(struct List* l, var item) {\n  \n  var next = *List_Next(l, item);\n  var prev = *List_Prev(l, item);\n\n  if (item is l->head and item is l->tail) {\n    l->head = NULL; l->tail = NULL;\n  } else if (item is l->head) {\n    l->head = next;\n    *List_Prev(l, next) = NULL;\n  } else if (item is l->tail) {\n    l->tail = prev;\n    *List_Next(l, prev) = NULL;\n  } else {\n    *List_Next(l, prev) = next;\n    *List_Prev(l, next) = prev;\n  }\n  \n}\n\nstatic void List_Link(struct List* l, var item, var prev, var next) {\n  if (prev is NULL) { l->head = item; } else { *List_Next(l, prev) = item; }\n  if (next is NULL) { l->tail = item; } else { *List_Prev(l, next) = item; }\n  *List_Next(l, item) = next;\n  *List_Prev(l, item) = prev;\n}\n\nstatic void List_Pop_At(var self, var key) {\n\n  struct List* l = self;\n  int64_t i = c_int(key);\n  \n  var item = List_At(l, i);\n  List_Unlink(l, item);\n  destruct(item);\n  List_Free(l, item);\n  l->nitems--;\n}\n\nstatic void List_Rem(var self, var obj) {\n  struct List* l = self;\n  var item = l->head;\n  while (item) {\n    if (eq(item, obj)) {\n      List_Unlink(l, item);\n      destruct(item);\n      List_Free(l, item);\n      l->nitems--;\n      return;\n    }\n    item = *List_Next(l, item);\n  }\n  \n  throw(ValueError, \"Object %$ not in List!\", obj);\n}\n\nstatic void List_Push(var self, var obj) {\n  struct List* l = self;\n  var item = List_Alloc(l);\n  assign(item, obj);\n  List_Link(l, item, l->tail, NULL);\n  l->nitems++;\n}\n\nstatic void List_Push_At(var self, var obj, var key) {\n  struct List* l = self;\n  \n  var item = List_Alloc(l);\n  assign(item, obj);\n  \n  int64_t i = c_int(key);\n  if (i is 0) {\n    List_Link(l, item, NULL, l->head);\n  } else {\n    var curr = List_At(l, i);\n    List_Link(l, item, *List_Prev(l, curr), curr);\n  }\n  l->nitems++;\n}\n\nstatic void List_Pop(var self) {\n\n  struct List* l = self;\n  \n#if CELLO_BOUND_CHECK == 1\n  if (l->nitems is 0) {\n    throw(IndexOutOfBoundsError, \"Cannot pop. List is empty!\");\n    return;\n  }\n#endif\n  \n  var item = l->tail;\n  List_Unlink(l, item);\n  destruct(item);\n  List_Free(l, item);\n  l->nitems--;\n}\n\nstatic var List_Get(var self, var key) {\n  struct List* l = self;\n  return List_At(l, c_int(key));\n}\n\nstatic void List_Set(var self, var key, var val) {\n  struct List* l = self;\n  assign(List_At(l, c_int(key)), val);\n}\n\nstatic var List_Iter_Init(var self) {\n  struct List* l = self;\n  if (l->nitems is 0) { return Terminal; }\n  return l->head;\n}\n\nstatic var List_Iter_Next(var self, var curr) {\n  struct List* l = self;\n  curr = *List_Next(l, curr);\n  return curr ? curr : Terminal;\n}\n\nstatic var List_Iter_Last(var self) {\n  struct List* l = self;\n  if (l->nitems is 0) { return Terminal; }\n  return l->tail;\n}\n\nstatic var List_Iter_Prev(var self, var curr) {\n  struct List* l = self;\n  curr = *List_Prev(l, curr);\n  return curr ? curr : Terminal;\n}\n\nstatic var List_Iter_Type(var self) {\n  struct List* l = self;\n  return l->type;\n}\n\nstatic int List_Show(var self, var output, int pos) {\n  struct List* l = self;\n  pos = print_to(output, pos, \"<'List' At 0x%p [\", self);\n  var item = l->head;\n  while (item) {\n    pos = print_to(output, pos, \"%$\", item);\n    item = *List_Next(l, item);\n    if (item) { pos = print_to(output, pos, \", \"); }\n  }\n  return print_to(output, pos, \"]>\");\n}\n\nstatic void List_Resize(var self, size_t n) {\n  struct List* l = self;\n\n  if (n is 0) {\n    List_Clear(self);\n    return;\n  }\n  \n  while (n < l->nitems) {\n    var item = l->tail;\n    List_Unlink(l, item);\n    destruct(item);\n    List_Free(l, item);\n    l->nitems--;\n  }\n  \n  while (n > l->nitems) {\n    var item = List_Alloc(l);\n    List_Link(l, item, l->tail, NULL);\n    l->nitems++;\n  }\n  \n}\n\nstatic void List_Mark(var self, var gc, void(*f)(var,void*)) {\n  struct List* l = self;\n  var item = l->head;\n  while (item) {\n    f(gc, item);\n    item = *List_Next(l, item);\n  }\n}\n\nvar List = Cello(List,\n  Instance(Doc,\n    List_Name, List_Brief,    List_Description, \n    NULL,      List_Examples, NULL),\n  Instance(New,     List_New, List_Del),\n  Instance(Assign,  List_Assign),\n  Instance(Mark,    List_Mark),\n  Instance(Cmp,     List_Cmp),\n  Instance(Hash,    List_Hash),\n  Instance(Push,\n    List_Push,      List_Pop,\n    List_Push_At,   List_Pop_At),\n  Instance(Concat,  List_Concat, List_Push),\n  Instance(Len,     List_Len),\n  Instance(Get,     List_Get, List_Set, List_Mem, List_Rem),\n  Instance(Iter,\n    List_Iter_Init, List_Iter_Next,\n    List_Iter_Last, List_Iter_Prev, List_Iter_Type),\n  Instance(Show,    List_Show, NULL),\n  Instance(Resize,  List_Resize));\n  \n"
  },
  {
    "path": "src/Num.c",
    "content": "#include \"Cello.h\"\n\nstatic const char* C_Int_Name(void) {\n  return \"C_Int\";\n}\n\nstatic const char* C_Int_Brief(void) {\n  return \"Interpret as C Integer\";\n}\n\nstatic const char* C_Int_Description(void) {\n  return\n    \"The `C_Int` class should be overridden by types which are representable \"\n    \"as a C style Integer of the type `int64_t`.\";\n}\n\nstatic const char* C_Int_Definition(void) {\n  return\n    \"struct C_Int {\\n\"\n    \"  int64_t (*c_int)(var);\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* C_Int_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"printf(\\\"%li\\\", c_int($I(5))); /* 5 */\\n\"\n      \"printf(\\\"%li\\\", c_int($I(6))); /* 6 */\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic struct Method* C_Int_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"c_int\", \n      \"int64_t c_int(var self);\",\n      \"Returns the object `self` represented as a `int64_t`.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nvar C_Int = Cello(C_Int,\n  Instance(Doc,\n    C_Int_Name,       C_Int_Brief,    C_Int_Description, \n    C_Int_Definition, C_Int_Examples, C_Int_Methods));\n    \nstatic const char* C_Float_Name(void) {\n  return \"C_Float\";\n}\n\nstatic const char* C_Float_Brief(void) {\n  return \"Interpret as C Float\";\n}\n\nstatic const char* C_Float_Description(void) {\n  return\n    \"The `C_Float` class should be overridden by types which are representable \"\n    \"as a C style Float of the type `double`.\";\n}\n\nstatic const char* C_Float_Definition(void) {\n  return\n    \"struct C_Float {\\n\"\n    \"  double (*c_float)(var);\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* C_Float_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"printf(\\\"%f\\\", c_float($F(5.1))); /* 5.1 */\\n\"\n      \"printf(\\\"%f\\\", c_float($F(6.2))); /* 6.2 */\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic struct Method* C_Float_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"c_float\", \n      \"double c_float(var self);\",\n      \"Returns the object `self` represented as a `double`.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nvar C_Float = Cello(C_Float,\n  Instance(Doc,\n    C_Float_Name,       C_Float_Brief,    C_Float_Description, \n    C_Float_Definition, C_Float_Examples, C_Float_Methods));\n\nint64_t c_int(var self) {\n  \n  if (type_of(self) is Int) {\n    return ((struct Int*)self)->val;\n  }\n  \n  return method(self, C_Int, c_int);\n}\n\ndouble c_float(var self) {\n  \n  if (type_of(self) is Float) {\n    return ((struct Float*)self)->val;\n  }\n  \n  return method(self, C_Float, c_float);\n}\n\nstatic const char* Int_Name(void) {\n  return \"Int\";\n}\n\nstatic const char* Int_Brief(void) {\n  return \"Integer Object\";\n}\n\nstatic const char* Int_Description(void) {\n  return \"64-bit signed integer Object.\";\n}\n\nstatic const char* Int_Definition(void) {\n  return\n    \"struct Int {\\n\"\n    \"  int64_t val;\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* Int_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var i0 = $(Int, 1);\\n\"\n      \"var i1 = new(Int, $I(24313));\\n\"\n      \"var i2 = copy(i0);\\n\"\n      \"\\n\"\n      \"show(i0); /*     1 */\\n\"\n      \"show(i1); /* 24313 */\\n\"\n      \"show(i2); /*     1 */\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic void Int_Assign(var self, var obj) {\n  struct Int* i = self;\n  i->val = c_int(obj);\n}\n\nstatic int64_t Int_C_Int(var self) {\n  struct Int* i = self;\n  return i->val;\n}\n\nstatic int Int_Cmp(var self, var obj) {\n  return (int)(Int_C_Int(self) - c_int(obj));\n}\n\nstatic uint64_t Int_Hash(var self) {\n  return (uint64_t)c_int(self);\n}\n\nstatic int Int_Show(var self, var output, int pos) {\n  return print_to(output, pos, \"%li\", self);\n}\n\nstatic int Int_Look(var self, var input, int pos) {\n  return scan_from(input, pos, \"%li\", self);\n}\n\nvar Int = Cello(Int,\n  Instance(Doc,\n    Int_Name, Int_Brief, Int_Description, Int_Definition, Int_Examples, NULL),\n  Instance(Assign,  Int_Assign),\n  Instance(Cmp,     Int_Cmp),\n  Instance(Hash,    Int_Hash),\n  Instance(C_Int,   Int_C_Int),\n  Instance(Show,    Int_Show, Int_Look));\n\nstatic const char* Float_Name(void) {\n  return \"Float\";\n}\n\nstatic const char* Float_Brief(void) {\n  return \"Floating Point Object\";\n}\n\nstatic const char* Float_Description(void) {\n  return \"64-bit double precision float point Object.\";\n}\n\nstatic const char* Float_Definition(void) {\n  return\n    \"struct Float {\\n\"\n    \"  double val;\\n\"\n    \"};\\n\";  \n}\n\nstatic struct Example* Float_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var f0 = $(Float, 1.0);\\n\"\n      \"var f1 = new(Float, $F(24.313));\\n\"\n      \"var f2 = copy(f0);\\n\"\n      \"\\n\"\n      \"show(f0); /*  1.000 */\\n\"\n      \"show(f1); /* 24.313 */\\n\"\n      \"show(f2); /*  1.000 */\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic void Float_Assign(var self, var obj) {\n  struct Float* f = self;\n  f->val = c_float(obj);\n}\n\nstatic double Float_C_Float(var self) {\n  struct Float* f = self;\n  return f->val;\n}\n\nstatic int Float_Cmp(var self, var obj) {\n  double c = Float_C_Float(self) - c_float(obj);\n  return c > 0 ? 1 : c < 0 ? -1 : 0;\n}\n\nunion interp_cast {\n  double   as_flt;\n  uint64_t as_int;\n};\n\nstatic uint64_t Float_Hash(var self) {\n  union interp_cast ic;\n  ic.as_flt = c_float(self);\n  return ic.as_int;\n}\n\nint Float_Show(var self, var output, int pos) {\n  return print_to(output, pos, \"%f\", self);\n}\n\nint Float_Look(var self, var input, int pos) {\n  return scan_from(input, pos, \"%f\", self);\n}\n\nvar Float = Cello(Float,\n  Instance(Doc,\n    Float_Name,       Float_Brief,    Float_Description, \n    Float_Definition, Float_Examples, NULL),\n  Instance(Assign,  Float_Assign),\n  Instance(Cmp,     Float_Cmp),\n  Instance(Hash,    Float_Hash),\n  Instance(C_Float, Float_C_Float),\n  Instance(Show,    Float_Show, Float_Look));\n"
  },
  {
    "path": "src/Pointer.c",
    "content": "#include \"Cello.h\"\n\nstatic const char* Pointer_Name(void) {\n  return \"Pointer\";\n}\n\nstatic const char* Pointer_Brief(void) {\n  return \"Reference to other object\";\n}\n\nstatic const char* Pointer_Description(void) {\n  return\n    \"The `Pointer` class is implemented by types which act as references to \"\n    \"other objects. Primarily this class is implemented by `Ref` and `Box` \"\n    \"which provide the two main pointer types in Cello.\";\n}\n\nstatic const char* Pointer_Definition(void) {\n  return\n    \"struct Pointer {\\n\"\n    \"  void (*ref)(var, var);\\n\"\n    \"  var (*deref)(var);\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* Pointer_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var obj0 = $F(1.0), obj1 = $F(2.0);\\n\"\n      \"var r = $(Ref, obj0);\\n\"\n      \"show(r);\\n\"\n      \"show(deref(r)); /* 1.0 */\\n\"\n      \"ref(r, obj1);\\n\"\n      \"show(deref(r)); /* 2.0 */\\n\"\n      \"assign(r, obj0);\\n\"\n      \"show(deref(r)); /* 1.0 */\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic struct Method* Pointer_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"ref\", \n      \"void ref(var self, var item);\",\n      \"Set the object `self` to reference the object `item`.\"\n    }, {\n      \"deref\", \n      \"var deref(var self);\",\n      \"Get the object referenced by `self`.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nvar Pointer = Cello(Pointer,\n  Instance(Doc,\n    Pointer_Name,       Pointer_Brief,    Pointer_Description, \n    Pointer_Definition, Pointer_Examples, Pointer_Methods));\n\nvoid ref(var self, var item) {\n  method(self, Pointer, ref, item);\n}\n\nvar deref(var self) {\n  return method(self, Pointer, deref);\n}\n\nstatic const char* Ref_Name(void) {\n  return \"Ref\";\n}\n\nstatic const char* Ref_Brief(void) {\n  return \"Shared Pointer\";\n}\n\nstatic const char* Ref_Description(void) {\n  return\n    \"The `Ref` type is a basic wrapper around a C pointer. It can be used \"\n    \"as a type argument to collections to allow them to store generic types. \"\n    \"It may also be useful in various circumstances where another level of \"\n    \"indirection or mutability is required.\";\n}\n\nstatic const char* Ref_Definition(void) {\n  return\n    \"struct Ref {\\n\"\n    \"  var val;\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* Ref_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var obj0 = $F(1.0), obj1 = $F(2.0);\\n\"\n      \"var r = $(Ref, obj0);\\n\"\n      \"show(r);\\n\"\n      \"show(deref(r)); /* 1.0 */\\n\"\n      \"ref(r, obj1);\\n\"\n      \"show(deref(r)); /* 2.0 */\\n\"\n      \"assign(r, obj0);\\n\"\n      \"show(deref(r)); /* 1.0 */\\n\"\n    }, {\n      \"Collections\",\n      \"var i0 = new(Int, $I(100));\\n\"\n      \"var i1 = new(Int, $I(200));\\n\"\n      \"var x = new(Array, Ref, i0, i1);\\n\"\n      \"\\n\"\n      \"print(deref(get(x, $I(0)))); /* 100 */\"\n      \"\\n\"\n      \"del(x); /* Contents of `x` still alive */\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic void Ref_Ref(var self, var val);\nstatic var Ref_Deref(var self);\nstatic void Ref_Assign(var self, var obj);\n\nstatic void Ref_Assign(var self, var obj) {\n  struct Pointer* p = instance(obj, Pointer);\n  if (p and p->deref) {\n    Ref_Ref(self, p->deref(obj));\n  } else {\n    Ref_Ref(self, obj);\n  }\n}\n\nstatic void Ref_Ref(var self, var val) {\n  struct Ref* r = self;\n  r->val = val;\n}\n\nstatic var Ref_Deref(var self) {\n  struct Ref* r = self;\n  return r->val;\n}\n\nvar Ref = Cello(Ref,\n  Instance(Doc,\n    Ref_Name, Ref_Brief, Ref_Description, Ref_Definition, Ref_Examples, NULL),\n  Instance(Assign,   Ref_Assign),\n  Instance(Pointer,  Ref_Ref, Ref_Deref));\n\n  \nstatic const char* Box_Name(void) {\n  return \"Box\";\n}\n\nstatic const char* Box_Brief(void) {\n  return \"Unique Pointer\";\n}\n\nstatic const char* Box_Description(void) {\n  return\n    \"The `Box` type is another wrapper around a C pointer with one additional \"\n    \"behaviour as compared to `Ref`. When a `Box` object is deleted it will \"\n    \"also call `del` on the object it points to. The means a `Box` is \"\n    \"considered a pointer type that _owns_ the object it points to, and so is \"\n    \"responsible for it's destruction. Due to this `Box`s must point to valid \"\n    \"Cello objects and so can't be initalised with `NULL` or anything else \"\n    \"invalid. \"\n    \"\\n\\n\"\n    \"While this might not seem that useful when there is Garbage Collection \"\n    \"this can be very useful when Garbage Collection is turned off, and when \"\n    \"used in conjunction with collections.\";\n}\n\nstatic const char* Box_Definition(void) {\n  return\n    \"struct Box {\\n\"\n    \"  var val;\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* Box_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var obj0 = $F(1.0), obj1 = $F(2.0);\\n\"\n      \"var r = $(Box, obj0);\\n\"\n      \"show(r);\\n\"\n      \"show(deref(r)); /* 1.0 */\\n\"\n      \"ref(r, obj1);\\n\"\n      \"show(deref(r)); /* 2.0 */\\n\"\n      \"assign(r, obj0);\\n\"\n      \"show(deref(r)); /* 1.0 */\\n\"\n    }, {\n      \"Lifetimes\",\n      \"var quote = $S(\\\"Life is long\\\");\\n\"\n      \"\\n\"\n      \"with (r in $B(new(String, quote))) {\\n\"\n      \"  println(\\\"This reference is: %$\\\", r);\\n\"\n      \"  println(\\\"This string is alive: '%s'\\\", deref(r));\\n\"\n      \"}\\n\"\n      \"\\n\"\n      \"print(\\\"Now it has been cleared up!\\\\n\\\");\\n\"\n    }, {\n      \"Collection\",\n      \"/* Multiple Types in one Collection */\\n\"\n      \"var x = new(Array, Box, \\n\"\n      \"  new(String, $S(\\\"Hello\\\")), \\n\"\n      \"  new(String, $S(\\\"There\\\")), \\n\"\n      \"  new(Int, $I(10)));\\n\"\n      \"\\n\"\n      \"print(deref(get(x, $I(0)))); /* Hello */ \\n\"\n      \"\\n\"\n      \"del(x); /* Contents of `x` deleted with it */\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic void Box_Ref(var self, var val);\nstatic var Box_Deref(var self);\nstatic void Box_Assign(var self, var obj);\n\nstatic void Box_New(var self, var args) {\n  Box_Assign(self, get(args, $I(0)));\n}\n\nstatic void Box_Del(var self) {\n  var obj = Box_Deref(self);\n  if (obj) { del(obj); }\n  Box_Ref(self, NULL);\n}\n\nstatic void Box_Assign(var self, var obj) {\n  struct Pointer* p = instance(obj, Pointer);\n  if (p and p->deref) {\n    Box_Ref(self, p->deref(obj));\n  } else {\n    Box_Ref(self, obj);\n  }\n}\n\nstatic int Box_Show(var self, var output, int pos) {\n  return print_to(output, pos, \"<'Box' at 0x%p (%$)>\", self, Box_Deref(self));\n}\n\nstatic void Box_Ref(var self, var val) {\n  struct Box* b = self;\n  b->val = val;\n}\n\nstatic var Box_Deref(var self) {\n  struct Box* b = self;\n  return b->val;\n}\n\nvar Box = Cello(Box,\n  Instance(Doc,\n    Box_Name, Box_Brief, Box_Description, Box_Definition, Box_Examples, NULL),\n  Instance(New,      Box_New, Box_Del),\n  Instance(Assign,   Box_Assign),\n  Instance(Show,     Box_Show, NULL),\n  Instance(Pointer,  Box_Ref, Box_Deref));\n  \n"
  },
  {
    "path": "src/Push.c",
    "content": "#include \"Cello.h\"\n\nstatic const char* Push_Name(void) {\n  return \"Push\";\n}\n\nstatic const char* Push_Brief(void) {\n  return \"Pushable and Popable object\";\n}\n\nstatic const char* Push_Description(void) {\n  return \"\"\n    \"The `Push` class provides an interface for the addition and removal of \"\n    \"objects from another in a positional sense.\"\n    \"\\n\\n\"\n    \"`push` can be used to add new objects to a collection and `pop` to remove \"\n    \"them. Usage of `push` can require `assign` to be defined on the argument.\";\n}\n\nstatic const char* Push_Definition(void) {\n  return\n    \"struct Push {\\n\"\n    \"  void (*push)(var, var);\\n\"\n    \"  void (*pop)(var);\\n\"\n    \"  void (*push_at)(var, var, var);\\n\"\n    \"  void (*pop_at)(var, var);\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* Push_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var x = new(Array, Int);\\n\"\n      \"\\n\"\n      \"push(x, $I( 0));\\n\"\n      \"push(x, $I( 5));\\n\"\n      \"push(x, $I(10));\\n\"\n      \"\\n\"\n      \"show(get(x, $I(0))); /*  0 */\\n\"\n      \"show(get(x, $I(1))); /*  5 */\\n\"\n      \"show(get(x, $I(2))); /* 10 */\\n\"\n      \"\\n\"\n      \"pop_at(x, $I(1));\\n\"\n      \"\\n\"\n      \"show(get(x, $I(0))); /*  0 */\\n\"\n      \"show(get(x, $I(1))); /* 10 */\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic struct Method* Push_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"push\", \n      \"void push(var self, var obj);\",\n      \"Push the object `obj` onto the top of object `self`.\"\n    }, {\n      \"pop\", \n      \"void pop(var self);\",\n      \"Pop the top item from the object `self`.\"\n    }, {\n      \"push_at\", \n      \"void push_at(var self, var obj, var key);\",\n      \"Push the object `obj` onto the object `self` at a given `key`.\"\n    }, {\n      \"pop_at\", \n      \"void pop_at(var self, var key);\",\n      \"Pop the object from the object `self` at a given `key`.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nvar Push = Cello(Push,\n  Instance(Doc,\n    Push_Name,       Push_Brief,    Push_Description, \n    Push_Definition, Push_Examples, Push_Methods));\n\nvoid push(var self, var val) { method(self, Push, push, val); }\nvoid push_at(var self, var val, var i) { method(self, Push, push_at, val, i); }\nvoid pop(var self) { method(self, Push, pop); }\nvoid pop_at(var self, var i) { method(self, Push, pop_at, i); }\n"
  },
  {
    "path": "src/Resize.c",
    "content": "#include \"Cello.h\" \n\nstatic const char* Resize_Name(void) {\n  return \"Reserve\";\n}\n\nstatic const char* Resize_Brief(void) {\n  return \"Object can be resized\";\n}\n\nstatic const char* Resize_Description(void) {\n  return\n    \"The `Resize` class can be implemented by objects which can be resized in \"\n    \"some way. Resizing to a larger size than the current may allow for some \"\n    \"resource or other to be preallocated or reserved. For example this class \"\n    \"is implemented by `Array` and `Table` to either remove a number of items \"\n    \"quickly or to preallocate memory space if it is known that many items are \"\n    \"going to be added at a later date.\";\n}\n\nstatic const char* Resize_Definition(void) {\n  return\n    \"struct Resize {\\n\"\n    \"  void (*resize)(var, size_t);\\n\"\n    \"};\\n\";\n}\n\nstatic struct Method* Resize_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"resize\", \n      \"void resize(var self, size_t n);\",\n      \"Resize to some size `n`, perhaps reserving some resource for object \"\n      \"`self`.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nstatic struct Example* Resize_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var x = new(Array, Int);\\n\"\n      \"resize(x, 10000); /* Reserve space in Array */ \\n\"\n      \"for (size_t i = 0; i < 10000; i++) {\\n\"\n      \"  push(x, $I(i));\\n\"\n      \"}\\n\"\n    }, {\n      \"Usage 2\",\n      \"var x = new(Array, Int, $I(0), $I(1), $I(2));\\n\"\n      \"resize(x, 0); /* Clear Array of items */\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nvar Resize = Cello(Resize, \n  Instance(Doc,\n    Resize_Name,       Resize_Brief,    Resize_Description, \n    Resize_Definition, Resize_Examples, Resize_Methods));\n  \nvoid resize(var self, size_t n) {\n  method(self, Resize, resize, n);\n}\n\n"
  },
  {
    "path": "src/Show.c",
    "content": "#include \"Cello.h\"\n\nstatic const char* Format_Name(void) {\n  return \"Format\";\n}\n\nstatic const char* Format_Brief(void) {\n  return \"Read or Write with Format String\";\n}\n\nstatic const char* Format_Description(void) {\n  return\n    \"Format abstracts the class of operations such as `scanf`, `sprintf` and \"\n    \"`fprintf` with matching semantics. It provides general `printf` and \"\n    \"`scanf` functionality for several different types objects in a \"\n    \"uniform way. This class is essentially an in-between class, used by the \"\n    \"`Show` class to read and write output.\"\n    \"\\n\\n\"\n    \"It is important to note that the semantics of these operations match \"\n    \"`printf` and not the newly defined `Show` class. For example it is \"\n    \"perfectly valid to pass a C `int` to these functions, while the `println` \"\n    \"function from `Show` must be passed only `var` objects.\";\n}\n\nstatic const char* Format_Definition(void) {\n  return \n    \"struct Format {\\n\"\n    \"  int (*format_to)(var,int,const char*,va_list);\\n\"\n    \"  int (*format_from)(var,int,const char*,va_list);\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* Format_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"/* printf(\\\"Hello my name is %s, I'm %i\\\\n\\\", \\\"Dan\\\", 23); */\\n\"\n      \"format_to($(File, stdout), 0, \\n\"\n      \"  \\\"Hello my name is %s, I'm %i\\\\n\\\", \\\"Dan\\\", 23);\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic struct Method* Format_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"format_to\", \n      \"int format_to(var self, int pos, const char* fmt, ...);\\n\"\n      \"int format_to_va(var self, int pos, const char* fmt, va_list va);\",\n      \"Write a formatted string `fmt` to the object `self` at position `pos`.\"\n    }, {\n      \"format_from\", \n      \"int format_from(var self, int pos, const char* fmt, ...);\\n\"\n      \"int format_from_va(var self, int pos, const char* fmt, va_list va);\",\n      \"Read a formatted string `fmt` from the object `self` at position `pos`.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nvar Format = Cello(Format,\n  Instance(Doc, \n    Format_Name,       Format_Brief,    Format_Description,\n    Format_Definition, Format_Examples, Format_Methods));\n\nint format_to_va(var self, int pos, const char* fmt, va_list va) {\n  return method(self, Format, format_to, pos, fmt, va);\n}\n\nint format_from_va(var self, int pos, const char* fmt, va_list va) {\n  return method(self, Format, format_from, pos, fmt, va);\n}\n\nint format_to(var self, int pos, const char* fmt, ...) {\n  va_list va;\n  va_start(va, fmt);\n  int ret = format_to_va(self, pos, fmt, va);\n  va_end(va);\n  return ret;\n}\n\nint format_from(var self, int pos, const char* fmt, ...) {\n  va_list va;\n  va_start(va, fmt);\n  int ret = format_from_va(self, pos, fmt, va);\n  va_end(va);\n  return ret;\n}\n\nstatic const char* Show_Name(void) {\n  return \"Show\";\n}\n\nstatic const char* Show_Brief(void) {\n  return \"Convert To or From String\";\n}\n\nstatic const char* Show_Description(void) {\n  return\n    \"The `Show` class is used to convert objects to, and from, a `String` \"\n    \"representation. Objects which implement `Show` should expect the \"\n    \"input/output object to be one that support the `Format` class, such as \"\n    \"`File` or `String`.\"\n    \"\\n\\n\"\n    \"The `print`, `println` and `print_to` functions provide a mechanism for \"\n    \"writing formatted strings with Cello objects. To do this they provide a \"\n    \"new format specifier `%$` which uses an object's `Show` functionality to \"\n    \"write that part of the string. All objects which don't support `Show` can \"\n    \"still be shown via a default implementation.\"\n    \"\\n\\n\"\n    \"All the Show methods which are variable arguments only take `var` objects \"\n    \"as input. To print native C types wrap them in Cello types using `$`.\"\n    \"\\n\\n\"\n    \"Standard format specifiers such as `%f` and `%d` will call functions such \"\n    \"as `c_float` and `c_int` on their passed arguments to convert objects to \"\n    \"C types before performing the standard C formatting behaviour.\"\n    \"\\n\\n\"\n    \"See [printf](http://www.cplusplus.com/reference/cstdio/printf/) for more \"\n    \"information on format specifiers.\";\n}\n\nstatic const char* Show_Definition(void) {\n  return\n    \"struct Show {\\n\"\n    \"  int (*show)(var, var, int);\\n\"\n    \"  int (*look)(var, var, int);\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* Show_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Hello World\",\n      \"println(\\\"Hello %s!\\\", $S(\\\"World\\\"));\\n\"\n    }, {\n      \"File Writing\",\n      \"with (f in new(File, $S(\\\"prices.txt\\\"), $S(\\\"wb\\\"))) {\\n\"\n      \"  print_to(f, 0, \\\"%$ :: %$\\\\n\\\", $S(\\\"Banana\\\"), $I(57));\\n\"\n      \"  print_to(f, 0, \\\"%$ :: %$\\\\n\\\", $S(\\\"Apple\\\"),  $I(22));\\n\"\n      \"  print_to(f, 0, \\\"%$ :: %$\\\\n\\\", $S(\\\"Pear\\\"),   $I(16));\\n\"\n      \"}\\n\"\n    }, {\n      \"String Scanning\",\n      \"var input = $S(\\\"1 and 52 then 78\\\");\\n\"\n      \"\\n\"\n      \"var i0 = $I(0), i1 = $I(0), i2 = $I(0);\\n\"\n      \"scan_from(input, 0, \\\"%i and %i then %i\\\", i0, i1, i2);\\n\"\n      \"\\n\"\n      \"/* i0: 1, i1: 52, i2: 78 */\\n\"\n      \"println(\\\"i0: %$, i1: %$, i2: %$\\\", i0, i1, i2);\\n\"\n    }, {\n      \"String Printing\",\n      \"var greeting = new(String);\\n\"\n      \"print_to(greeting, 0, \\\"Hello %s %s, %s?\\\", \\n\"\n      \"  $S(\\\"Mr\\\"), $S(\\\"Johnson\\\"), $S(\\\"how are you?\\\"));\\n\"\n      \"\\n\"\n      \"/* Hello Mr Johnson, how are you? */\\n\"\n      \"show(greeting);\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic struct Method* Show_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"show\", \n      \"int show(var self);\\n\"\n      \"int show_to(var self, var out, int pos);\",\n      \"Show the object `self` either to `stdout` or to the object `output`.\"\n    }, {\n      \"look\", \n      \"int look(var self);\\n\"\n      \"int look_from(var self, var input, int pos);\",\n      \"Read the object `self` either from `stdout` or from the object `input`.\"\n    }, {\n      \"print\", \n      \"#define print(fmt, ...)\\n\"\n      \"#define println(fmt, ...)\\n\"\n      \"#define print_to(out, pos, fmt, ...)\\n\"\n      \"int print_with(const char* fmt, var args);\\n\"\n      \"int println_with(const char* fmt, var args);\\n\"\n      \"int print_to_with(var out, int pos, const char* fmt, var args);\",\n      \"Print the format string `fmt` either to `stdout` or to the object `out` \"\n      \"at positions `pos`. Returns new position in output.\"\n    }, {\n      \"scan\", \n      \"#define scan(fmt, ...)\\n\"\n      \"#define scanln(fmt, ...)\\n\"\n      \"#define scan_from(input, pos, fmt, ...)\\n\"\n      \"int scan_with(const char* fmt, var args);\\n\"\n      \"int scanln_with(const char* fmt, var args);\\n\"\n      \"int scan_from_with(var input, int pos, const char* fmt, var args);\",\n      \"Scan the format string `fmt` either from `stdin` or from the object \"\n      \"`input` at position `pos`. Returns new position in output.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nvar Show = Cello(Show,\n  Instance(Doc, \n    Show_Name,       Show_Brief,    Show_Description,\n    Show_Definition, Show_Examples, Show_Methods));\n\nint show(var self) {\n  return show_to(self, $(File, stdout), 0);\n}\n\nint show_to(var self, var out, int pos) {\n\n  if (self is NULL) {\n    return print_to(out, pos, \"<NULL>\");\n  }\n  struct Show* s = instance(self, Show);\n  if (s and s->show) {\n    return s->show(self, out, pos);\n  }\n  \n  return print_to(out, pos, \"<'%s' At 0x%p>\", type_of(self), self);\n  \n}\n\nint print_with(const char* fmt, var args) {\n  return print_to_with($(File, stdout), 0, fmt, args);\n}\n\nint println_with(const char* fmt, var args) {\n  int pos = 0;\n  pos = print_to_with($(File, stdout), pos, fmt, args);\n  pos = print_to($(File, stdout), pos, \"\\n\");\n  return pos;\n}\n\nint print_to_with(var out, int pos, const char* fmt, var args) {\n  \n  char* fmt_buf = malloc(strlen(fmt)+1); \n  size_t index = 0;\n  \n  while (true) {\n    \n    if (*fmt is '\\0') { break; }\n    \n    const char* start = fmt;\n    \n    /* Match String */\n    while(*fmt isnt '\\0' and *fmt isnt '%') { fmt++; }\n    \n    if (start isnt fmt) {\n      memcpy(fmt_buf, start, fmt - start);\n      fmt_buf[fmt - start] = '\\0';\n      int off = format_to(out, pos, fmt_buf);\n      if (off < 0) { throw(FormatError, \"Unable to output format!\"); }\n      pos += off;\n      continue;\n    }\n    \n    /* Match %% */\n    if (*fmt is '%' && *(fmt+1) is '%') {\n      int off = format_to(out, pos, \"%%\");\n      if (off < 0) { throw(FormatError, \"Unable to output '%%%%'!\"); }\n      pos += off;\n      fmt += 2;\n      continue;\n    }\n    \n    /* Match Format Specifier */\n    while(not strchr(\"diuoxXfFeEgGaAxcsp$\", *fmt)) { fmt++; }\n    \n    if (start isnt fmt) {\n    \n      memcpy(fmt_buf, start, fmt - start + 1);\n      fmt_buf[fmt - start + 1] = '\\0';\n      \n      if (index >= len(args)) {\n        throw(FormatError, \"Not enough arguments to Format String!\");\n      }\n      \n      var a = get(args, $I(index)); index++;\n      \n      if (*fmt is '$') { pos = show_to(a, out, pos); }\n      \n      if (*fmt is 's') {      \n        int off = format_to(out, pos, fmt_buf, c_str(a));\n        if (off < 0) { throw(FormatError, \"Unable to output String!\"); }\n        pos += off;\n      }\n      \n      if (strchr(\"diouxX\", *fmt)) {\n        int off = format_to(out, pos, fmt_buf, c_int(a));\n        if (off < 0) { throw(FormatError, \"Unable to output Int!\"); }\n        pos += off;\n      }\n      \n      if (strchr(\"fFeEgGaA\", *fmt)) { \n        int off = format_to(out, pos, fmt_buf, c_float(a));\n        if (off < 0) { throw(FormatError, \"Unable to output Real!\"); }\n        pos += off;\n      }\n      \n      if (*fmt is 'c') {\n        int off = format_to(out, pos, fmt_buf, c_int(a));\n        if (off < 0) { throw(FormatError, \"Unable to output Char!\"); }\n        pos += off;\n      }\n      \n      if (*fmt is 'p') {\n        int off = format_to(out, pos, fmt_buf, a);\n        if (off < 0) { throw(FormatError, \"Unable to output Object!\"); }\n        pos += off;\n      }\n\n      fmt++;\n      continue;\n    }\n    \n    throw(FormatError, \"Invalid Format String!\");\n  }\n\n  free(fmt_buf);\n  \n  return pos;\n  \n}\n\nint look(var self) {\n  return look_from(self, $(File, stdin), 0);\n}\n\nint look_from(var self, var input, int pos) {\n  return method(self, Show, look, input, pos);\n}\n\nint scan_with(const char* fmt, var args) {\n  return scan_from_with($(File, stdin), 0, fmt, args);\n}\n\nint scanln_with(const char* fmt, var args) {\n  int pos = 0;\n  pos = scan_from_with($(File, stdin), pos, fmt, args);\n  pos = scan_from($(File, stdin), pos, \"\\n\");\n  return pos;\n}\n\nint scan_from_with(var input, int pos, const char* fmt, var args) {\n  \n  char* fmt_buf = malloc(strlen(fmt)+4);\n  size_t index = 0;\n  \n  while (true) {\n    \n    if (*fmt is '\\0') { break; }\n    \n    const char* start = fmt;\n    \n    /* Match String */\n    while (*fmt isnt '\\0' and *fmt isnt '%') { fmt++; }\n    \n    if (start isnt fmt) {  \n      memcpy(fmt_buf, start, fmt - start);\n      fmt_buf[fmt - start] = '\\0';\n      format_from(input, pos, fmt_buf);\n      pos += (int)(fmt - start);\n      continue;\n    }\n    \n    /* Match %% */\n    if (*fmt is '%' and *(fmt+1) is '%') {\n      int err = format_from(input, pos, \"%%\");\n      if (err < 0) { throw(FormatError, \"Unable to input '%%%%'!\"); }\n      pos += 2;\n      fmt += 2;\n      continue;\n    }\n    \n    /* Match Format Specifier */\n    while (not strchr(\"diuoxXfFeEgGaAxcsp$[^]\", *fmt)) { fmt++; }\n    \n    if (start isnt fmt) {\n      \n      int off = 0;\n      memcpy(fmt_buf, start, fmt - start + 1);\n      fmt_buf[fmt - start + 1] = '\\0';\n      strcat(fmt_buf, \"%n\");\n\n      if (index >= len(args)) {\n        throw(FormatError, \"Not enough arguments to Format String!\");\n      }\n      \n      var a = get(args, $I(index)); index++;\n      \n      if (*fmt is '$') { pos = look_from(a, input, pos); }\n      \n      else if (*fmt is 's') {\n        int err = format_from(input, pos, fmt_buf, c_str(a), &off);\n        if (err < 1) { throw(FormatError, \"Unable to input String!\"); }\n        pos += off;\n      }\n      \n      /* TODO: Test */\n      else if (*fmt is ']') {\n        int err = format_from(input, pos, fmt_buf, c_str(a), &off);\n        if (err < 1) { throw(FormatError, \"Unable to input Scanset!\"); }\n        pos += off;\n      }\n      \n      else if (strchr(\"diouxX\", *fmt)) {\n        long tmp = 0;\n        int err = format_from(input, pos, fmt_buf, &tmp, &off);\n        if (err < 1) { throw(FormatError, \"Unable to input Int!\"); }\n        pos += off;\n        assign(a, $I(tmp));\n      }\n      \n      else if (strchr(\"fFeEgGaA\", *fmt)) {\n        if (strchr(fmt_buf, 'l')) {\n          double tmp = 0;\n          int err = format_from(input, pos, fmt_buf, &tmp, &off);\n          if (err < 1) { throw(FormatError, \"Unable to input Float!\"); }\n          pos += off;\n          assign(a, $F(tmp));\n        } else {\n          float tmp = 0;\n          int err = format_from(input, pos, fmt_buf, &tmp, &off);\n          if (err < 1) { throw(FormatError, \"Unable to input Float!\"); }\n          pos += off;\n          assign(a, $F(tmp));\n        }\n      }\n      \n      else if (*fmt is 'c') {\n        char tmp = '\\0';\n        int err = format_from(input, pos, fmt_buf, &tmp, &off);\n        if (err < 1) { throw(FormatError, \"Unable to input Char!\"); }\n        pos += off;\n        assign(a, $I(tmp));\n      }\n      \n      else if (*fmt is 'p') {\n        void* tmp = NULL;\n        int err = format_from(input, pos, fmt_buf, &tmp, &off);\n        if (err < 1) { throw(FormatError, \"Unable to input Ref!\"); }\n        pos += off;\n        assign(a, $R(tmp));\n      }\n      \n      else {\n        /* TODO: Report Better */\n        throw(FormatError, \"Invalid Format Specifier!\");\n      }\n\n      fmt++;\n      continue;\n    }\n  }\n\n  free(fmt_buf);\n  \n  return pos;\n\n}\n\n"
  },
  {
    "path": "src/Start.c",
    "content": "#include \"Cello.h\"\n\nstatic const char* Start_Name(void) {\n  return \"Start\";\n}\n\nstatic const char* Start_Brief(void) {\n  return \"Can be started or stopped\";\n}\n\nstatic const char* Start_Description(void) {\n  return\n    \"The `Start` class can be implemented by types which provide an abstract \"\n    \"notion of a started and stopped state. This can be real processes such \"\n    \"as `Thread`, or something like `File` where the on/off correspond to \"\n    \"if the file is open or not.\"\n    \"\\n\\n\"\n    \"The main nicety of the `Start` class is that it allows use of the `with` \"\n    \"macro which performs the `start` function at the opening of a scope block \"\n    \"and the `stop` function at the end.\";\n}\n\nstatic const char* Start_Definition(void) {\n  return\n    \"struct Start {\\n\"\n    \"  void (*start)(var);\\n\"\n    \"  void (*stop)(var);\\n\"\n    \"  void (*join)(var);\\n\"\n    \"  bool (*running)(var);\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* Start_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var x = new(Mutex);\\n\"\n      \"start(x); /* Lock Mutex */ \\n\"\n      \"print(\\\"Inside Mutex!\\\\n\\\");\\n\"\n      \"stop(x); /* unlock Mutex */\"\n    }, {\n      \"Scoped\",\n      \"var x = new(Mutex);\\n\"\n      \"with (mut in x) { /* Lock Mutex */ \\n\"\n      \"  print(\\\"Inside Mutex!\\\\n\\\");\\n\"\n      \"} /* unlock Mutex */\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic struct Method* Start_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"with\", \n      \"#define with(...)\",\n      \"Perform operations in between `start` and `stop`.\"\n    }, {\n      \"start\", \n      \"void start(var self);\",\n      \"Start the object `self`.\"\n    }, {\n      \"stop\", \n      \"void stop(var self);\",\n      \"Stop the object `self`.\"\n    }, {\n      \"join\", \n      \"void join(var self);\",\n      \"Block and wait for the object `self` to stop.\"\n    }, {\n      \"running\", \n      \"bool running(var self);\",\n      \"Check if the object `self` is running.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nvar Start = Cello(Start, Instance(Doc, \n  Start_Name,       Start_Brief,    Start_Description, \n  Start_Definition, Start_Examples, Start_Methods));\n\nvoid start(var self) {\n  method(self, Start, start);\n}\n\nvoid stop(var self) {\n  method(self, Start, stop);\n}\n\nvoid join(var self) {\n  method(self, Start, join);\n}\n\nbool running(var self) {\n  return method(self, Start, running);\n}\n\nvar start_in(var self) {\n  struct Start* s = instance(self, Start);\n  if (s and s->start) {\n    s->start(self);\n  }\n  return self;\n}\n\nvar stop_in(var self) {\n  struct Start* s = instance(self, Start);\n  if (s and s->stop) {\n    s->stop(self);\n  }\n  return NULL;\n}\n"
  },
  {
    "path": "src/String.c",
    "content": "#include \"Cello.h\"\n\nstatic const char* C_Str_Name(void) {\n  return \"C_Str\";\n}\n\nstatic const char* C_Str_Brief(void) {\n  return \"Interpret as C String\";\n}\n\nstatic const char* C_Str_Description(void) {\n  return\n    \"The `C_Str` class should be overridden by types which are representable \"\n    \"as a C style String.\";\n}\n\nstatic const char* C_Str_Definition(void) {\n  return\n    \"struct C_Str {\\n\"\n    \"  char* (*c_str)(var);\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* C_Str_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"puts(c_str($S(\\\"Hello\\\"))); /* Hello */\\n\"\n      \"puts(c_str($S(\\\"There\\\"))); /* There */\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic struct Method* C_Str_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"c_str\", \n      \"char* c_str(var self);\",\n      \"Returns the object `self` represented as a `char*`.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nvar C_Str = Cello(C_Str,\n  Instance(Doc,\n    C_Str_Name,       C_Str_Brief,    C_Str_Description, \n    C_Str_Definition, C_Str_Examples, C_Str_Methods));\n\nchar* c_str(var self) {\n  \n  if (type_of(self) is String) {\n    return ((struct String*)self)->val;\n  }\n  \n  return method(self, C_Str, c_str);\n}\n    \nstatic const char* String_Name(void) {\n  return \"String\";\n}\n\nstatic const char* String_Brief(void) {\n  return \"String Object\";\n}\n\nstatic const char* String_Description(void) {\n  return\n    \"The `String` type is a wrapper around the native C string type. This \"\n    \"includes strings that are allocated on either the Stack or the Heap.\"\n    \"\\n\\n\"\n    \"For strings allocated on the heap a number of extra operations are \"\n    \"provided overs standard C strings such as concatenation.\";\n}\n\nstatic const char* String_Definition(void) {\n  return\n    \"struct String {\\n\"\n    \"  char* val;\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* String_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var s0 = $(String, \\\"Hello\\\");\\n\"\n      \"var s1 = new(String, $S(\\\"Hello\\\"));\\n\"\n      \"append(s1, $S(\\\" There\\\"));\\n\"\n      \"show(s0); /* Hello */\\n\"\n      \"show(s1); /* Hello There */\\n\"\n    }, {\n      \"Manipulation\",\n      \"var s0 = new(String, $S(\\\"Balloons\\\"));\\n\"\n      \"\\n\"\n      \"show($I(len(s0))); /* 8 */\\n\"\n      \"show($I(mem(s0, $S(\\\"Ball\\\"))));     /* 1 */\\n\"\n      \"show($I(mem(s0, $S(\\\"oon\\\"))));      /* 1 */\\n\"\n      \"show($I(mem(s0, $S(\\\"Balloons\\\")))); /* 1 */\\n\"\n      \"show($I(mem(s0, $S(\\\"l\\\"))));        /* 1 */\\n\"\n      \"\\n\"\n      \"rem(s0, $S(\\\"oons\\\"));\\n\"\n      \"\\n\"\n      \"show($I(eq(s0, $S(\\\"Ball\\\")))); /* 1 */\\n\"\n      \"\\n\"\n      \"resize(s0, 0);\\n\"\n      \"\\n\"\n      \"show($I(len(s0))); /* 0 */\\n\"\n      \"show($I(eq(s0, $S(\\\"\\\")))); /* 1 */\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic void String_Assign(var self, var obj);\n\nstatic void String_New(var self, var args) {\n  struct String* s = self;\n  if (len(args) > 0) {\n    String_Assign(self, get(args, $I(0)));\n  } else {\n    s->val = calloc(1, 1);\n  }\n  \n#if CELLO_MEMORY_CHECK == 1\n  if (s->val is NULL) {\n    throw(OutOfMemoryError, \"Cannot allocate String, out of memory!\");\n  }\n#endif\n}\n\nstatic void String_Del(var self) {\n  struct String* s = self;\n\n#if CELLO_ALLOC_CHECK == 1\n  if (header(self)->alloc is (var)AllocStack\n  or  header(self)->alloc is (var)AllocStatic) {\n    throw(ValueError, \"Cannot destruct String, not on heap!\");\n  }\n#endif\n\n  free(s->val);\n}\n\nstatic void String_Assign(var self, var obj) {\n  struct String* s = self;\n  char* val = c_str(obj);\n  \n#if CELLO_ALLOC_CHECK == 1\n  if (header(self)->alloc is (var)AllocStack\n  or  header(self)->alloc is (var)AllocStatic) {\n    throw(ValueError, \"Cannot reallocate String, not on heap!\");\n  }\n#endif\n  \n  s->val = realloc(s->val, strlen(val) + 1);\n  \n#if CELLO_MEMORY_CHECK == 1\n  if (s->val is NULL) {\n    throw(OutOfMemoryError, \"Cannot allocate String, out of memory!\");\n  }\n#endif\n\n  strcpy(s->val, val);\n}\n\nstatic char* String_C_Str(var self) {\n  struct String* s = self;\n  return s->val;\n}\n\nstatic int String_Cmp(var self, var obj) {\n  return strcmp(String_C_Str(self), c_str(obj));\n}\n\nstatic size_t String_Len(var self) {\n  struct String* s = self;\n  return strlen(s->val);\n}\n\nstatic void String_Clear(var self) {\n  struct String* s = self;\n  \n#if CELLO_ALLOC_CHECK == 1\n  if (header(self)->alloc is (var)AllocStack\n  or  header(self)->alloc is (var)AllocStatic) {\n    throw(ValueError, \"Cannot reallocate String, not on heap!\");\n  }\n#endif\n  \n  s->val = realloc(s->val, 1);\n  \n#if CELLO_MEMORY_CHECK == 1\n  if (s->val is NULL) {\n    throw(OutOfMemoryError, \"Cannot allocate String, out of memory!\");\n  }\n#endif\n\n  s->val[0] = '\\0';\n}\n\nstatic bool String_Mem(var self, var obj) {\n  \n  struct C_Str* c = instance(obj, C_Str);\n  if (c and c->c_str) {\n    return strstr(String_C_Str(self), c->c_str(obj));\n  }\n  \n  return false;\n}\n\nstatic void String_Rem(var self, var obj) {\n  \n  struct C_Str* c = instance(obj, C_Str);\n  if (c and c->c_str) {\n    char* pos = strstr(String_C_Str(self), c->c_str(obj));\n    size_t count = strlen(String_C_Str(self)) - strlen(pos) - \n      strlen(c->c_str(obj)) + 1;\n    memmove((char*)pos, pos + strlen(c->c_str(obj)), count);\n  }\n  \n}\n\nstatic uint64_t String_Hash(var self) {\n  struct String* s = self;\n  return hash_data(s->val, strlen(s->val));\n}\n\nstatic void String_Concat(var self, var obj) {\n  struct String* s = self;\n  \n#if CELLO_ALLOC_CHECK == 1\n  if (header(self)->alloc is (var)AllocStack\n  or  header(self)->alloc is (var)AllocStatic) {\n    throw(ValueError, \"Cannot reallocate String, not on heap!\");\n  }\n#endif\n  \n  s->val = realloc(s->val, strlen(s->val) + strlen(c_str(obj)) + 1);\n  \n#if CELLO_MEMORY_CHECK == 1\n  if (s->val is NULL) {\n    throw(OutOfMemoryError, \"Cannot allocate String, out of memory!\");\n  }\n#endif\n  \n  strcat(s->val, c_str(obj));\n}\n\nstatic void String_Resize(var self, size_t n) {\n  struct String* s = self;\n  \n#if CELLO_ALLOC_CHECK == 1\n  if (header(self)->alloc is (var)AllocStack\n  or  header(self)->alloc is (var)AllocStatic) {\n    throw(ValueError, \"Cannot reallocate String, not on heap!\");\n  }\n#endif\n  \n  size_t m = String_Len(self);\n  s->val = realloc(s->val, n+1);\n  \n  if (n > m) {\n    memset(&s->val[m], 0, n - m);\n  } else {\n    s->val[n] = '\\0';\n  }\n  \n#if CELLO_MEMORY_CHECK == 1\n  if (s->val is NULL) {\n    throw(OutOfMemoryError, \"Cannot allocate String, out of memory!\");\n  }\n#endif\n  \n}\n\nstatic int String_Format_To(var self, int pos, const char* fmt, va_list va) {\n\n  struct String* s = self;\n  \n#ifdef CELLO_WINDOWS\n  \n  va_list va_tmp;\n  va_copy(va_tmp, va);\n  int size = _vscprintf(fmt, va_tmp);\n  va_end(va_tmp);\n  \n#if CELLO_ALLOC_CHECK == 1\n  if (header(self)->alloc is (var)AllocStack\n  or  header(self)->alloc is (var)AllocStatic) {\n    throw(ValueError, \"Cannot reallocate String, not on heap!\");\n  }\n#endif\n  \n  s->val = realloc(s->val, pos + size + 1);\n\n#if CELLO_MEMORY_CHECK == 1\n  if (s->val is NULL) {\n    throw(OutOfMemoryError, \"Cannot allocate String, out of memory!\");  \n  }\n#endif\n  \n  return vsprintf(s->val + pos, fmt, va); \n  \n#elif defined(CELLO_MAC)\n  \n  va_list va_tmp;\n  va_copy(va_tmp, va);\n  char* tmp = NULL;\n  int size = vasprintf(&tmp, fmt, va_tmp);\n  va_end(va_tmp);\n  \n#if CELLO_ALLOC_CHECK == 1\n  if (header(self)->alloc is (var)AllocStack\n  or  header(self)->alloc is (var)AllocStatic) {\n    throw(ValueError, \"Cannot reallocate String, not on heap!\");\n  }\n#endif\n  \n  s->val = realloc(s->val, pos + size + 1);\n  \n#if CELLO_MEMORY_CHECK == 1\n  if (s->val is NULL) {\n    throw(OutOfMemoryError, \"Cannot allocate String, out of memory!\");\n  }\n#endif\n  \n  s->val[pos] = '\\0';\n  strcat(s->val, tmp);\n  free(tmp);\n  \n  return size;\n  \n#else\n\n  va_list va_tmp;\n  va_copy(va_tmp, va);\n  int size = vsnprintf(NULL, 0, fmt, va_tmp);\n  va_end(va_tmp);\n  \n#if CELLO_ALLOC_CHECK == 1\n  if (header(self)->alloc is (var)AllocStack\n  or  header(self)->alloc is (var)AllocStatic) {\n    throw(ValueError, \"Cannot reallocate String, not on heap!\");\n  }\n#endif\n  \n  s->val = realloc(s->val, pos + size + 1);\n  \n#if CELLO_MEMORY_CHECK == 1\n  if (s->val is NULL) {\n    throw(OutOfMemoryError, \"Cannot allocate String, out of memory!\");\n  }\n#endif\n  \n  return vsprintf(s->val + pos, fmt, va); \n  \n#endif\n\n}\n\nstatic int String_Format_From(var self, int pos, const char* fmt, va_list va) {\n  struct String* s = self;\n  return vsscanf(s->val + pos, fmt, va);\n}\n\nstatic int String_Show(var self, var out, int pos) {\n  struct String* s = self;\n  pos = print_to(out, pos, \"\\\"\", self);\n  char* v = s->val;\n  while (*v) {\n    switch (*v) {\n      case '\\a': pos = print_to(out, pos, \"\\\\a\"); break;\n      case '\\b': pos = print_to(out, pos, \"\\\\b\"); break;\n      case '\\f': pos = print_to(out, pos, \"\\\\f\"); break;\n      case '\\n': pos = print_to(out, pos, \"\\\\n\"); break;\n      case '\\r': pos = print_to(out, pos, \"\\\\r\"); break;\n      case '\\t': pos = print_to(out, pos, \"\\\\t\"); break;\n      case '\\v': pos = print_to(out, pos, \"\\\\v\"); break;\n      case '\\\\': pos = print_to(out, pos, \"\\\\\\\\\"); break;\n      case '\\'': pos = print_to(out, pos, \"\\\\'\"); break;\n      case '\\\"': pos = print_to(out, pos, \"\\\\\\\"\"); break;\n      case '\\?': pos = print_to(out, pos, \"\\\\?\"); break;\n      default:   pos = print_to(out, pos, \"%c\", $I(*v));\n    }\n    v++;\n  }\n  return print_to(out, pos, \"\\\"\", self);\n}\n\nstatic int String_Look(var self, var input, int pos) {\n  \n  String_Clear(self);\n  \n  var chr = $I(0);\n  pos = scan_from(input, pos, \"%c\", chr);\n  \n  if (c_int(chr) isnt '\\\"') {\n    throw(FormatError, \n      \"String literal does not start with quotation marks!\");\n  }\n  \n  while (true) {\n    \n    pos = scan_from(input, pos, \"%c\", chr);\n    \n    if (c_int(chr) == '\"') { break; }\n    \n    if (c_int(chr) == '\\\\') {\n      pos = scan_from(input, pos, \"%c\", chr);\n      switch (c_int(chr)) {\n        case 'a':  String_Concat(self, $S(\"\\a\")); break;\n        case 'b':  String_Concat(self, $S(\"\\b\")); break;\n        case 'f':  String_Concat(self, $S(\"\\f\")); break;\n        case 'n':  String_Concat(self, $S(\"\\n\")); break;\n        case 'r':  String_Concat(self, $S(\"\\r\")); break;\n        case 't':  String_Concat(self, $S(\"\\t\")); break;\n        case 'v':  String_Concat(self, $S(\"\\v\")); break;\n        case '\\\\': String_Concat(self, $S(\"\\\\\")); break;\n        case '\\'': String_Concat(self, $S(\"\\'\")); break;\n        case '\"':  String_Concat(self, $S(\"\\\"\")); break;\n        case '?':  String_Concat(self, $S(\"\\?\")); break;\n        default: throw(FormatError, \"Unknown Escape Sequence '\\\\%c'!\", chr);\n      }\n    }\n    \n    char buffer[2];\n    buffer[0] = (char)c_int(chr);\n    buffer[1] = '\\0';\n    \n    String_Concat(self, $S(buffer));\n  }\n  \n  return pos;\n}\n\nvar String = Cello(String,\n  Instance(Doc,\n    String_Name,       String_Brief,    String_Description,\n    String_Definition, String_Examples, NULL),\n  Instance(New,     String_New, String_Del),\n  Instance(Assign,  String_Assign),\n  Instance(Cmp,     String_Cmp),\n  Instance(Hash,    String_Hash),\n  Instance(Len,     String_Len),\n  Instance(Get,     NULL, NULL, String_Mem, String_Rem),\n  Instance(Resize,  String_Resize),\n  Instance(Concat,  String_Concat, String_Concat),\n  Instance(C_Str,   String_C_Str),\n  Instance(Format,  String_Format_To, String_Format_From),\n  Instance(Show,    String_Show, String_Look));\n\n"
  },
  {
    "path": "src/Table.c",
    "content": "#include \"Cello.h\"\n\nstatic const char* Table_Name(void) {\n  return \"Table\";\n}\n\nstatic const char* Table_Brief(void) {\n  return \"Hash table\";\n}\n\nstatic const char* Table_Description(void) {\n  return\n    \"The `Table` type is a hash table data structure that maps keys to values. \"\n    \"It uses an open-addressing robin-hood hashing scheme which requires \"\n    \"`Hash` and `Cmp` to be defined on the key type. Keys and values are \"\n    \"copied into the collection using the `Assign` class and intially have \"\n    \"zero'd memory.\"\n    \"\\n\\n\"\n    \"Hash tables provide `O(1)` lookup, insertion and removal can but require \"\n    \"long pauses when the table must be _rehashed_ and all entries processed.\"\n    \"\\n\\n\"\n    \"This is largely equivalent to the C++ construct \"\n    \"[std::unordered_map](http://www.cplusplus.com/reference/unordered_map/unordered_map/)\";\n}\n\nstatic struct Example* Table_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var prices = new(Table, String, Int);\\n\"\n      \"set(prices, $S(\\\"Apple\\\"),  $I(12));\\n\"\n      \"set(prices, $S(\\\"Banana\\\"), $I( 6));\\n\"\n      \"set(prices, $S(\\\"Pear\\\"),   $I(55));\\n\"\n      \"\\n\"\n      \"foreach (key in prices) {\\n\"\n      \"  var price = get(prices, key);\\n\"\n      \"  println(\\\"Price of %$ is %$\\\", key, price);\\n\"\n      \"}\\n\"\n    }, {\n      \"Manipulation\",\n      \"var t = new(Table, String, Int);\\n\"\n      \"set(t, $S(\\\"Hello\\\"), $I(2));\\n\"\n      \"set(t, $S(\\\"There\\\"), $I(5));\\n\"\n      \"\\n\"\n      \"show($I(len(t))); /* 2 */\\n\"\n      \"show($I(mem(t, $S(\\\"Hello\\\")))); /* 1 */\\n\"\n      \"\\n\"\n      \"rem(t, $S(\\\"Hello\\\"));\\n\"\n      \"\\n\"\n      \"show($I(len(t))); /* 1 */\\n\"\n      \"show($I(mem(t, $S(\\\"Hello\\\")))); /* 0 */\\n\"\n      \"show($I(mem(t, $S(\\\"There\\\")))); /* 1 */\\n\"\n      \"\\n\"\n      \"resize(t, 0);\\n\"\n      \"\\n\"\n      \"show($I(len(t))); /* 0 */\\n\"\n      \"show($I(mem(t, $S(\\\"Hello\\\")))); /* 0 */\\n\"\n      \"show($I(mem(t, $S(\\\"There\\\")))); /* 0 */\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstruct Table {\n  var data;\n  var ktype;\n  var vtype;\n  size_t ksize;\n  size_t vsize;\n  size_t nslots;\n  size_t nitems;\n  var sspace0;\n  var sspace1;\n};\n\nenum {\n  TABLE_PRIMES_COUNT = 24\n};\n\nstatic const size_t Table_Primes[TABLE_PRIMES_COUNT] = {\n  0,       1,       5,       11,\n  23,      53,      101,     197,\n  389,     683,     1259,    2417,\n  4733,    9371,    18617,   37097,\n  74093,   148073,  296099,  592019,\n  1100009, 2200013, 4400021, 8800019\n};\n\nstatic const double Table_Load_Factor = 0.9;\n\nstatic size_t Table_Ideal_Size(size_t size) {\n  size = (size_t)((double)(size+1) / Table_Load_Factor);\n  for (size_t i = 0; i < TABLE_PRIMES_COUNT; i++) {\n    if (Table_Primes[i] >= size) { return Table_Primes[i]; }\n  }\n  size_t last = Table_Primes[TABLE_PRIMES_COUNT-1];\n  for (size_t i = 0;; i++) {\n    if (last * i >= size) { return last * i; }\n  }\n}\n\nstatic size_t Table_Step(struct Table* t) {\n  return\n    sizeof(uint64_t) + \n    sizeof(struct Header) + t->ksize + \n    sizeof(struct Header) + t->vsize;\n}\n\nstatic uint64_t Table_Key_Hash(struct Table* t, uint64_t i) {\n  return *(uint64_t*)((char*)t->data + i * Table_Step(t));\n}\n\nstatic var Table_Key(struct Table* t, uint64_t i) {\n  return (char*)t->data + i * Table_Step(t) +\n    sizeof(uint64_t) + \n    sizeof(struct Header);  \n}\n\nstatic var Table_Val(struct Table* t, uint64_t i) {\n  return (char*)t->data + i * Table_Step(t) +\n    sizeof(uint64_t) + \n    sizeof(struct Header) + \n    t->ksize + \n    sizeof(struct Header);  \n}\n\nstatic uint64_t Table_Probe(struct Table* t, uint64_t i, uint64_t h) {\n  int64_t v = i - (h-1);\n  if (v < 0) {\n    v = t->nslots + v;\n  }\n  return v;\n}\n\nstatic void Table_Set(var self, var key, var val);\nstatic void Table_Set_Move(var self, var key, var val, bool move);\n\nstatic size_t Table_Size_Round(size_t s) {\n  return ((s + sizeof(var) - 1) / sizeof(var)) * sizeof(var);\n}\n\nstatic void Table_New(var self, var args) {\n  \n  struct Table* t = self;\n  t->ktype = cast(get(args, $(Int, 0)), Type);\n  t->vtype = cast(get(args, $(Int, 1)), Type);\n  t->ksize = Table_Size_Round(size(t->ktype));\n  t->vsize = Table_Size_Round(size(t->vtype));\n  \n  size_t nargs = len(args);\n  if (nargs % 2 isnt 0) {\n    throw(FormatError, \n      \"Received non multiple of two argument count to Table constructor.\");\n  }\n  \n  t->nslots = Table_Ideal_Size((nargs-2)/2);\n  t->nitems = 0;\n  \n  if (t->nslots is 0) {\n    t->data = NULL;\n    return;\n  }\n  \n  t->data = calloc(t->nslots, Table_Step(t));\n  t->sspace0 = calloc(1, Table_Step(t));\n  t->sspace1 = calloc(1, Table_Step(t));\n  \n#if CELLO_MEMORY_CHECK == 1\n  if (t->data is NULL or t->sspace0 is NULL or t->sspace1 is NULL) {\n    throw(OutOfMemoryError, \"Cannot allocate Table, out of memory!\");\n  }\n#endif\n  \n  for(size_t i = 0; i < (nargs-2)/2; i++) {\n    var key = get(args, $(Int, 2+(i*2)+0));\n    var val = get(args, $(Int, 2+(i*2)+1));\n    Table_Set_Move(t, key, val, false);\n  }\n  \n}\n\nstatic void Table_Del(var self) {\n  struct Table* t = self;  \n  \n  for (size_t i = 0; i < t->nslots; i++) {\n    if (Table_Key_Hash(t, i) isnt 0) {\n      destruct(Table_Key(t, i));\n      destruct(Table_Val(t, i));\n    }\n  }\n  \n  free(t->data);\n  free(t->sspace0);\n  free(t->sspace1);\n  \n}\n\nstatic var Table_Key_Type(var self) {\n  struct Table* t = self;  \n  return t->ktype;\n}\n\nstatic var Table_Val_Type(var self) {\n  struct Table* t = self;  \n  return t->vtype;\n}\n\nstatic void Table_Clear(var self) {\n  struct Table* t = self;\n  \n  for (size_t i = 0; i < t->nslots; i++) {\n    if (Table_Key_Hash(t, i) isnt 0) {\n      destruct(Table_Key(t, i));\n      destruct(Table_Val(t, i));\n    }\n  }\n  \n  free(t->data);\n  \n  t->nslots = 0;\n  t->nitems = 0;\n  t->data = NULL;\n  \n}\n\nstatic void Table_Assign(var self, var obj) {\n  struct Table* t = self;  \n  Table_Clear(t);\n  \n  t->ktype = implements_method(obj, Get, key_type) ? key_type(obj) : Ref;\n  t->vtype = implements_method(obj, Get, val_type) ? val_type(obj) : Ref;\n  t->ksize = Table_Size_Round(size(t->ktype));\n  t->vsize = Table_Size_Round(size(t->vtype));\n  t->nitems = 0;\n  t->nslots = Table_Ideal_Size(len(obj));\n  \n  if (t->nslots is 0) {\n    t->data = NULL;\n    return;\n  }\n  \n  t->data = calloc(t->nslots, Table_Step(t));\n  t->sspace0 = realloc(t->sspace0, Table_Step(t));\n  t->sspace1 = realloc(t->sspace1, Table_Step(t));\n  \n#if CELLO_MEMORY_CHECK == 1\n  if (t->data is NULL or t->sspace0 is NULL or t->sspace1 is NULL) {\n    throw(OutOfMemoryError, \"Cannot allocate Table, out of memory!\");\n  }\n#endif\n\n  memset(t->sspace0, 0, Table_Step(t));\n  memset(t->sspace1, 0, Table_Step(t));\n  \n  foreach(key in obj) {\n    Table_Set_Move(t, key, get(obj, key), false);\n  }\n  \n}\n\nstatic var Table_Iter_Init(var self);\nstatic var Table_Iter_Next(var self, var curr);\n\nstatic bool Table_Mem(var self, var key);\nstatic var Table_Get(var self, var key);\n\nstatic int Table_Cmp(var self, var obj) {\n  \n  int c;\n  var item0 = Table_Iter_Init(self);\n  var item1 = iter_init(obj);\n  \n  while (true) {\n    if (item0 is Terminal and item1 is Terminal) { return 0; }\n    if (item0 is Terminal) { return -1; }\n    if (item1 is Terminal) { return  1; }\n    c = cmp(item0, item1);\n    if (c < 0) { return -1; }\n    if (c > 0) { return  1; }\n    c = cmp(Table_Get(self, item0), get(obj, item1));\n    if (c < 0) { return -1; }\n    if (c > 0) { return  1; }\n    item0 = Table_Iter_Next(self, item0);\n    item1 = iter_next(obj, item1);\n  }\n  \n  return 0;\n  \n}\n\nstatic uint64_t Table_Hash(var self) {\n  struct Table* t = self;\n  uint64_t h = 0;\n  \n  var curr = Table_Iter_Init(self);\n  while (curr isnt Terminal) {\n    var vurr = (char*)curr + t->ksize + sizeof(struct Header);\n    h = h ^ hash(curr) ^ hash(vurr);\n    curr = Table_Iter_Next(self, curr);\n  }\n  \n  return h;\n}\n\nstatic size_t Table_Len(var self) {\n  struct Table* t = self;\n  return t->nitems;\n}\n\nstatic uint64_t Table_Swapspace_Hash(struct Table* t, var space) {\n  return *((uint64_t*)space);\n}\n\nstatic var Table_Swapspace_Key(struct Table* t, var space) {\n  return (char*)space + sizeof(uint64_t) + sizeof(struct Header);\n}\n\nstatic var Table_Swapspace_Val(struct Table* t, var space) {\n  return (char*)space + sizeof(uint64_t) + sizeof(struct Header) +\n    t->ksize + sizeof(struct Header); \n}\n\nstatic void Table_Set_Move(var self, var key, var val, bool move) {\n  \n  struct Table* t = self;\n  key = cast(key, t->ktype);\n  val = cast(val, t->vtype);\n  \n  uint64_t i = hash(key) % t->nslots;\n  uint64_t j = 0;\n  \n  memset(t->sspace0, 0, Table_Step(t));\n  memset(t->sspace1, 0, Table_Step(t));\n  \n  if (move) {\n      \n    uint64_t ihash = i+1;\n    memcpy((char*)t->sspace0, &ihash, sizeof(uint64_t));\n    memcpy((char*)t->sspace0 + sizeof(uint64_t),\n      (char*)key - sizeof(struct Header),\n      t->ksize + sizeof(struct Header));\n    memcpy((char*)t->sspace0 + sizeof(uint64_t) +\n      sizeof(struct Header) + t->ksize, \n      (char*)val - sizeof(struct Header),\n      t->vsize + sizeof(struct Header));\n  \n  } else {\n        \n    struct Header* khead = (struct Header*)\n      ((char*)t->sspace0 + sizeof(uint64_t));\n    struct Header* vhead = (struct Header*)\n      ((char*)t->sspace0 + sizeof(uint64_t) \n      + sizeof(struct Header) + t->ksize);\n    \n    header_init(khead, t->ktype, AllocData);\n    header_init(vhead, t->vtype, AllocData);\n    \n    uint64_t ihash = i+1;\n    memcpy((char*)t->sspace0, &ihash, sizeof(uint64_t)); \n    assign((char*)t->sspace0 + sizeof(uint64_t) + sizeof(struct Header), key);\n    assign((char*)t->sspace0 + sizeof(uint64_t) + sizeof(struct Header)\n      + t->ksize + sizeof(struct Header), val);\n  }\n  \n  while (true) {\n    \n    uint64_t h = Table_Key_Hash(t, i);\n    if (h is 0) {\n      memcpy((char*)t->data + i * Table_Step(t), t->sspace0, Table_Step(t));\n      t->nitems++;\n      return;\n    }\n    \n    if (eq(Table_Key(t, i), Table_Swapspace_Key(t, t->sspace0))) {\n      destruct(Table_Key(t, i));\n      destruct(Table_Val(t, i));\n      memcpy((char*)t->data + i * Table_Step(t), t->sspace0, Table_Step(t));\n      return;\n    }\n    \n    uint64_t p = Table_Probe(t, i, h);\n    if (j >= p) {\n      memcpy((char*)t->sspace1, (char*)t->data + i * Table_Step(t), Table_Step(t));\n      memcpy((char*)t->data + i * Table_Step(t), (char*)t->sspace0, Table_Step(t));\n      memcpy((char*)t->sspace0, (char*)t->sspace1, Table_Step(t));\n      j = p;\n    }\n    \n    i = (i+1) % t->nslots;\n    j++;\n  }\n  \n}\n\nstatic void Table_Rehash(struct Table* t, size_t new_size) {\n  \n  var old_data = t->data;\n  size_t old_size = t->nslots;\n  \n  t->nslots = new_size;\n  t->nitems = 0;\n  t->data = calloc(t->nslots, Table_Step(t));\n  \n#if CELLO_MEMORY_CHECK == 1\n  if (t->data is NULL) {\n    throw(OutOfMemoryError, \"Cannot allocate Table, out of memory!\");\n  }\n#endif\n  \n  for (size_t i = 0; i < old_size; i++) {\n    \n    uint64_t h = *(uint64_t*)((char*)old_data + i * Table_Step(t));\n    \n    if (h isnt 0) {\n      var key = (char*)old_data + i * Table_Step(t) +\n        sizeof(uint64_t) + sizeof(struct Header);\n      var val = (char*)old_data + i * Table_Step(t) +\n        sizeof(uint64_t) + sizeof(struct Header) + \n        t->ksize + sizeof(struct Header);\n      Table_Set_Move(t, key, val, true);\n    }\n    \n  }\n  \n  free(old_data);\n}\n\nstatic void Table_Resize_More(struct Table* t) {\n  size_t new_size = Table_Ideal_Size(t->nitems);  \n  size_t old_size = t->nslots;\n  if (new_size > old_size) { Table_Rehash(t, new_size); }\n}\n\nstatic void Table_Resize_Less(struct Table* t) {\n  size_t new_size = Table_Ideal_Size(t->nitems);  \n  size_t old_size = t->nslots;\n  if (new_size < old_size) { Table_Rehash(t, new_size); }\n}\n\nstatic bool Table_Mem(var self, var key) {\n  struct Table* t = self;\n  key = cast(key, t->ktype);\n  \n  if (t->nslots is 0) { return false; }\n  \n  uint64_t i = hash(key) % t->nslots;\n  uint64_t j = 0;\n  \n  while (true) {\n    \n    uint64_t h = Table_Key_Hash(t, i);\n    if (h is 0 or j > Table_Probe(t, i, h)) {\n      return false;\n    }\n    \n    if (eq(Table_Key(t, i), key)) {\n      return true;\n    }\n    \n    i = (i+1) % t->nslots; j++;\n  }\n  \n  return false;\n}\n\nstatic void Table_Rem(var self, var key) {\n  struct Table* t = self;\n  key = cast(key, t->ktype);\n  \n  if (t->nslots is 0) {\n    throw(KeyError, \"Key %$ not in Table!\", key);\n  }\n  \n  uint64_t i = hash(key) % t->nslots;\n  uint64_t j = 0;\n  \n  while (true) {\n    \n    uint64_t h = Table_Key_Hash(t, i);\n    if (h is 0 or j > Table_Probe(t, i, h)) {\n      throw(KeyError, \"Key %$ not in Table!\", key);\n    }\n    \n    if (eq(Table_Key(t, i), key)) {\n      \n      destruct(Table_Key(t, i));\n      destruct(Table_Val(t, i));\n      memset((char*)t->data + i * Table_Step(t), 0, Table_Step(t));\n      \n      while (true) {\n        \n        uint64_t ni = (i+1) % t->nslots;\n        uint64_t nh = Table_Key_Hash(t, ni);\n        if (nh isnt 0 and Table_Probe(t, ni, nh) > 0) {\n          memcpy(\n            (char*)t->data + i * Table_Step(t),\n            (char*)t->data + ni * Table_Step(t),\n            Table_Step(t));\n          memset((char*)t->data + ni * Table_Step(t), 0, Table_Step(t));\n          i = ni;\n        } else {\n          break;\n        }\n        \n      }\n      \n      t->nitems--;\n      Table_Resize_Less(t);\n      return;\n    }\n    \n    i = (i+1) % t->nslots; j++;\n  }\n  \n}\n\nstatic var Table_Get(var self, var key) {\n  struct Table* t = self;\n  \n  if (key >= t->data and ((char*)key) < ((char*)t->data) + t->nslots * Table_Step(self)) {\n    return Table_Val(self, (((char*)key) - ((char*)t->data)) / Table_Step(self));\n  }\n  \n  key = cast(key, t->ktype);\n  \n  if (t->nslots is 0) {\n    throw(KeyError, \"Key %$ not in Table!\", key);\n  }\n  \n  uint64_t i = hash(key) % t->nslots;\n  uint64_t j = 0;\n  \n  while (true) {\n\n    uint64_t h = Table_Key_Hash(t, i);\n    if (h is 0 or j > Table_Probe(t, i, h)) {\n      throw(KeyError, \"Key %$ not in Table!\", key);\n    }\n    \n    if (eq(Table_Key(t, i), key)) {\n      return Table_Val(t, i);\n    }\n    \n    i = (i+1) % t->nslots; j++;\n  }\n  \n  return NULL;\n}\n\nstatic void Table_Set(var self, var key, var val) {\n  Table_Set_Move(self, key, val, false);\n  Table_Resize_More(self);\n}\n\nstatic var Table_Iter_Init(var self) {\n  struct Table* t = self;\n  if (t->nitems is 0) { return Terminal; }\n  \n  for (size_t i = 0; i < t->nslots; i++) {\n    if (Table_Key_Hash(t, i) isnt 0) {\n      return Table_Key(t, i);\n    }\n  }\n  \n  return Terminal;\n}\n\nstatic var Table_Iter_Next(var self, var curr) {\n  struct Table* t = self;\n  \n  curr = (char*)curr + Table_Step(t);\n  \n  while (true) {\n\n    if (curr > Table_Key(t, t->nslots-1)) { return Terminal;}\n    uint64_t h = *(uint64_t*)((char*)curr - \n      sizeof(struct Header) - sizeof(uint64_t));\n    if (h isnt 0) { return curr; }\n    curr = (char*)curr + Table_Step(t);\n  }\n  \n  return Terminal;\n}\n\nstatic var Table_Iter_Last(var self) {\n  \n  struct Table* t = self;\n  if (t->nitems is 0) { return Terminal; }\n  \n  size_t i = t->nslots-1;\n  while (true) {\n    if (Table_Key_Hash(t, i) isnt 0) {\n      return Table_Key(t, i);\n    }\n    if (i == 0) { break; }\n    i--;\n  }\n  \n  return Terminal;\n  \n}\n\nstatic var Table_Iter_Prev(var self, var curr) {\n  struct Table* t = self;\n  \n  curr = (char*)curr - Table_Step(t);\n  \n  while (true) {\n\n    if (curr < Table_Key(t, 0)) { return Terminal; }\n    uint64_t h = *(uint64_t*)((char*)curr - \n      sizeof(struct Header) - sizeof(uint64_t));\n    if (h isnt 0) { return curr; }\n    curr = (char*)curr - Table_Step(t);\n  }\n  \n  return Terminal;\n}\n\nstatic var Table_Iter_Type(var self) {\n  struct Table* t = self;  \n  return t->ktype;\n}\n\nstatic int Table_Show(var self, var output, int pos) {\n  struct Table* t = self;\n  \n  pos = print_to(output, pos, \"<'Table' At 0x%p {\", self);\n  \n  size_t j =0;\n  for(size_t i = 0; i < t->nslots; i++) {\n    if (Table_Key_Hash(t, i) isnt 0) {\n      pos = print_to(output, pos, \"%$:%$\",\n        Table_Key(t, i), Table_Val(t, i));\n      if (j < Table_Len(t)-1) { pos = print_to(output, pos, \", \"); }\n      j++;\n    }\n  }\n  \n  return print_to(output, pos, \"}>\");\n}\n\nstatic void Table_Resize(var self, size_t n) {\n  struct Table* t = self;\n  \n  if (n is 0) {\n    Table_Clear(t);\n    return;\n  }\n  \n#if CELLO_BOUND_CHECK == 1\n  if (n < t->nitems) {\n    throw(FormatError, \n      \"Cannot resize Table to make it smaller than %li items\", \n      $I(t->nitems));\n  }\n#endif\n  \n  Table_Rehash(t, Table_Ideal_Size(n));\n}\n\nstatic void Table_Mark(var self, var gc, void(*f)(var,void*)) {\n  struct Table* t = self;\n  for(size_t i = 0; i < t->nslots; i++) {\n    if (Table_Key_Hash(t, i) isnt 0) {\n      f(gc, Table_Key(t, i));\n      f(gc, Table_Val(t, i));\n    }\n  }\n}\n\nvar Table = Cello(Table,\n  Instance(Doc,\n    Table_Name, Table_Brief,    Table_Description,\n    NULL,       Table_Examples, NULL),\n  Instance(New,      Table_New, Table_Del),\n  Instance(Assign,   Table_Assign),\n  Instance(Mark,     Table_Mark),\n  Instance(Cmp,      Table_Cmp),\n  Instance(Hash,     Table_Hash),\n  Instance(Len,      Table_Len),\n  Instance(Get,\n    Table_Get, Table_Set, Table_Mem, Table_Rem, \n    Table_Key_Type, Table_Val_Type),\n  Instance(Iter, \n    Table_Iter_Init, Table_Iter_Next, \n    Table_Iter_Last, Table_Iter_Prev, Table_Iter_Type),\n  Instance(Show,     Table_Show, NULL),\n  Instance(Resize,   Table_Resize));\n\n"
  },
  {
    "path": "src/Thread.c",
    "content": "#include \"Cello.h\"\n\nstatic const char* Current_Name(void) {\n  return \"Current\";\n}\n\nstatic const char* Current_Brief(void) {\n  return \"Implicit Object\";\n}\n\nstatic const char* Current_Description(void) {\n  return\n    \"The `Current` class can be implemented by types which have implicit \"\n    \"instances associated with them. For example it can be used to retrieve \"\n    \"the _current_ `Thread`, or it could be used to get the _current_ Garbage \"\n    \"Collector.\"\n    \"\\n\\n\"\n    \"This class may be implemented by types which express the [Singleton \"\n    \"Design Pattern](http://en.wikipedia.org/wiki/Singleton_pattern)\";\n}\n\nstatic const char* Current_Definition(void) {\n  return\n    \"struct Current {\\n\"\n    \"  var (*current)(void);\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* Current_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var gc = current(GC);\\n\"\n      \"show(gc);\\n\"\n      \"var thread = current(Thread);\\n\"\n      \"show(thread);\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic struct Method* Current_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"current\", \n      \"var current(var type);\",\n      \"Returns the current active object of the given `type`.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nvar Current = Cello(Current,\n  Instance(Doc,\n    Current_Name,       Current_Brief,    Current_Description,\n    Current_Definition, Current_Examples, Current_Methods));\n\nvar current(var type) {\n  return type_method(type, Current, current);\n}\n\nstruct Thread {\n  \n  var func;\n  var args;\n  var tls;\n  \n  bool is_main;\n  bool is_running;\n  \n#if defined(CELLO_UNIX)\n  pthread_t thread;\n#elif defined(CELLO_WINDOWS)\n  DWORD id;\n  HANDLE thread;\n#endif  \n  \n};\n\nstatic const char* Thread_Name(void) {\n  return \"Thread\";\n}\n\nstatic const char* Thread_Brief(void) {\n  return \"Concurrent Execution\";\n}\n\nstatic const char* Thread_Description(void) {\n  return\n    \"The `Thread` type provides a basic primitive for concurrent \"\n    \"execution. It acts as a basic wrapper around operating system threads, \"\n    \"using WinThreads on Windows and pthreads otherwise.\";\n}\n\nstatic struct Example* Thread_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var set_value(var args) {\\n\"\n      \"  assign(get(args, $I(0)), $I(1));\\n\"\n      \"  return NULL;\\n\"\n      \"}\\n\"\n      \"\\n\"\n      \"var i = $I(0);\\n\"\n      \"\\n\"\n      \"var x = new(Thread, $(Function, set_value));\\n\"\n      \"call(x, i);\\n\"\n      \"join(x);\\n\"\n      \"\\n\"\n      \"show(i); /* 1 */\\n\"\n    }, {\n      \"Exclusive Resource\",\n      \"var increment(var args) {\\n\"\n      \"  var mut = get(args, $I(0));\\n\"\n      \"  var tot = get(args, $I(1));\\n\"\n      \"  lock(mut);\\n\"\n      \"  assign(tot, $I(c_int(tot)+1));\\n\"\n      \"  unlock(mut);\\n\"\n      \"  return NULL;\\n\"\n      \"}\\n\"\n      \"\\n\"\n      \"var mutex = new(Mutex);\\n\"\n      \"var total = $I(0);\\n\"\n      \"\\n\"\n      \"var threads = new(Array, Box,\\n\"\n      \"  new(Thread, $(Function, increment)),\\n\"\n      \"  new(Thread, $(Function, increment)),\\n\"\n      \"  new(Thread, $(Function, increment)));\\n\"\n      \"\\n\"\n      \"show(total); /* 0 */\\n\"\n      \"\\n\"\n      \"foreach (t in threads) {\\n\"\n      \"  call(deref(t), mutex, total);\\n\"\n      \"}\\n\"\n      \"\\n\"\n      \"foreach (t in threads) {\\n\"\n      \"  join(deref(t));\\n\"\n      \"}\\n\"\n      \"\\n\"\n      \"show(total); /* 3 */\\n\"\n    }, {NULL, NULL}\n  };\n  \n  return examples;\n}\n\nstatic void Thread_New(var self, var args) {\n  struct Thread* t = self;\n  t->func = empty(args) ? NULL : get(args, $I(0));\n  t->args = NULL;\n  t->is_main = false;\n  t->is_running = false;\n  t->tls = new_raw(Table, String, Ref);\n}\n\nstatic void Thread_Del(var self) {\n  struct Thread* t = self;\n\n#ifdef CELLO_WINDOWS\n  CloseHandle(t->thread);\n#endif\n  \n  if (t->args isnt NULL) { del_raw(t->args); }\n  del_raw(t->tls);\n}\n\nstatic int64_t Thread_C_Int(var self) {\n  struct Thread* t = self;\n  \n  if (not t->is_running) {\n    throw(ValueError, \"Cannot get thread ID, thread not running!\");\n  }\n  \n#if defined(CELLO_UNIX)\n  return (int64_t)t->thread;\n#elif defined(CELLO_WINDOWS)\n  return (int64_t)t->id;\n#else\n  return 0;\n#endif\n  \n}\n\nstatic void Thread_Assign(var self, var obj) {\n  struct Thread* t = self;\n  struct Thread* o = cast(obj, Thread);\n  t->func = o->func;\n  t->tls = t->tls ? t->tls : alloc_raw(Table);\n  assign(t->tls, o->tls);\n}\n\nstatic int Thread_Cmp(var self, var obj) {\n  return (int)(Thread_C_Int(self) - c_int(obj));\n}\n\nstatic uint64_t Thread_Hash(var self) {\n  return Thread_C_Int(self);\n}\n\nstatic bool Thread_TLS_Key_Created = false;\n\n#if defined(CELLO_UNIX)\n\nstatic pthread_key_t Thread_Key_Wrapper;\n\nstatic void Thread_TLS_Key_Create(void) {\n  pthread_key_create(&Thread_Key_Wrapper, NULL);\n}\nstatic void Thread_TLS_Key_Delete(void) {\n  pthread_key_delete(Thread_Key_Wrapper);\n}\n\nstatic var Thread_Init_Run(var self) {\n\n  struct Thread* t = self;  \n  pthread_setspecific(Thread_Key_Wrapper, t);\n  t->is_running = true;\n  \n#ifndef CELLO_NGC\n  var bottom = NULL;\n  var gc = new_raw(GC, $R(&bottom));\n#endif\n\n  var exc = new_raw(Exception);\n  \n  var x = call_with(t->func, t->args);\n  del_raw(t->args);\n  t->args = NULL;\n  \n  del_raw(exc);\n  \n#ifndef CELLO_NGC\n  del_raw(gc);\n#endif\n  \n  return x;\n}\n\n#elif defined(CELLO_WINDOWS)\n\nstatic DWORD Thread_Key_Wrapper;\n\nstatic void Thread_TLS_Key_Create(void) {\n  Thread_Key_Wrapper = TlsAlloc();\n}\nstatic void Thread_TLS_Key_Delete(void) {\n  TlsFree(Thread_Key_Wrapper);\n}\n\nstatic DWORD Thread_Init_Run(var self) {\n  \n  struct Thread* t = self;\n  TlsSetValue(Thread_Key_Wrapper, t);\n  t->is_running = true;\n  \n  var ex = new_raw(Exception);\n\n#ifndef CELLO_NGC\n  var bottom = NULL;\n  var gc = new_raw(GC, $R(&bottom));\n#endif\n  \n  call_with(t->func, t->args);\n  del_raw(t->args);\n  t->args = NULL;\n  \n#ifndef CELLO_NGC\n  del_raw(gc);\n#endif\n  \n  del_raw(ex);\n  \n  return 0;\n}\n\n#endif\n\nstatic var Thread_Call(var self, var args) {\n  \n  struct Thread* t = self;\n  \n  t->args = assign(alloc_raw(type_of(args)), args);  \n  \n  /* Call Init Thread & Run */\n  \n#if defined(CELLO_UNIX)\n  \n  /* Setup Thread Local Storage */\n  \n  if (not Thread_TLS_Key_Created) {\n    Thread_TLS_Key_Create();\n    Thread_TLS_Key_Created = true;\n    atexit(Thread_TLS_Key_Delete);\n  }\n  \n  int err = pthread_create(&t->thread, NULL, Thread_Init_Run, t);\n  \n  if (err is EINVAL) {\n    throw(ValueError, \"Invalid Argument to Thread Creation\");\n  }\n  \n  if (err is EAGAIN) {\n    throw(OutOfMemoryError, \"Not enough resources to create another Thread\");\n  }\n  \n  if (err is EBUSY)  {\n    throw(BusyError, \"System is too busy to create thread\");\n  }\n  \n#elif defined(CELLO_WINDOWS)\n  \n  /* Setup Thread Local Storage */\n  \n  if (not Thread_TLS_Key_Created) {\n    Thread_TLS_Key_Create();\n    Thread_TLS_Key_Created = true;\n    atexit(Thread_TLS_Key_Delete);\n  }\n  \n  t->thread = CreateThread(NULL, 0,\n    (LPTHREAD_START_ROUTINE)Thread_Init_Run, t, 0, &t->id);\n  \n  if (t->thread is NULL) {\n    throw(ValueError, \"Unable to Create WinThread\");\n  }\n  \n#else\n  \n  throw(ResourceError, \"Unsupported Threading Environment\");\n  \n#endif\n  \n  return self;\n  \n}\n\nstatic var Thread_Main = NULL;\nstatic var Exception_Main = NULL;\n\nstatic void Thread_Main_Del(void) {\n  del_raw(Exception_Main);\n  del_raw(Thread_Main);\n}\n\nstatic var Thread_Current(void) {\n  \n  if (not Thread_TLS_Key_Created) {\n    Thread_TLS_Key_Create();\n    Thread_TLS_Key_Created = true;\n    atexit(Thread_TLS_Key_Delete);\n  }\n  \n#if defined(CELLO_UNIX)\n  var wrapper = pthread_getspecific(Thread_Key_Wrapper);\n#elif defined(CELLO_WINDOWS)\n  var wrapper = TlsGetValue(Thread_Key_Wrapper);\n#else\n  var wrapper = NULL;\n#endif\n  \n  /*\n  ** Here is a nasty one. On OSX instead of\n  ** returning NULL for an unset key it\n  ** decides to return uninitialized rubbish\n  ** (even though the spec says otherwise).\n  **\n  ** Luckily we can test directly for the main\n  ** thread on OSX using this non-portable method\n  */\n#ifdef CELLO_MAC\n  if (pthread_main_np()) { wrapper = NULL; }\n#endif\n  \n  if (wrapper is NULL) {\n  \n    if (Thread_Main is NULL) {\n      Thread_Main = new_raw(Thread);\n      Exception_Main = new_raw(Exception);\n      atexit(Thread_Main_Del);\n    }\n    \n    struct Thread* t = Thread_Main;\n    t->is_main = true;\n    t->is_running = true;\n    \n#if defined(CELLO_UNIX)\n    t->thread = pthread_self();\n#elif defined(CELLO_WINDOWS)\n    t->thread = GetCurrentThread();\n#endif\n\n    return Thread_Main;\n  }\n  \n  return wrapper;\n  \n}\n\nstatic void Thread_Start(var self) {\n  call(self);\n}\n\nstatic void Thread_Stop(var self) {\n  struct Thread* t = self;\n  \n#if defined(CELLO_UNIX)\n  if (not t->thread) { return; }\n  int err = pthread_kill(t->thread, SIGINT);\n  if (err is EINVAL) { throw(ValueError, \"Invalid Argument to Thread Stop\"); }\n  if (err is ESRCH)  { throw(ValueError, \"Invalid Thread\"); }\n#elif defined(CELLO_WINDOWS)\n  if (not t->thread) { return; }\n  TerminateThread(t->thread, FALSE);\n#endif  \n  \n}\n\nstatic void Thread_Join(var self) {\n  struct Thread* t = self;\n  \n#if defined(CELLO_UNIX)\n  if (not t->thread) { return; }\n  int err = pthread_join(t->thread, NULL);\n  if (err is EINVAL) { throw(ValueError, \"Invalid Argument to Thread Join\"); }\n  if (err is ESRCH)  { throw(ValueError, \"Invalid Thread\"); }\n#elif defined(CELLO_WINDOWS)\n  if (not t->thread) { return; }\n  WaitForSingleObject(t->thread, INFINITE);\n#endif\n  \n}\n\nstatic bool Thread_Running(var self) {\n  struct Thread* t = self;\n  return t->is_running;\n}\n\nstatic var Thread_Get(var self, var key) {\n  struct Thread* t = self;\n  return deref(get(t->tls, key));\n}\n\nstatic void Thread_Set(var self, var key, var val) {\n  struct Thread* t = self;\n  set(t->tls, key, $R(val));\n}\n\nstatic bool Thread_Mem(var self, var key) {\n  struct Thread* t = self;\n  return mem(t->tls, key);\n}\n\nstatic void Thread_Rem(var self, var key) {\n  struct Thread* t = self;\n  rem(t->tls, key);\n}\n\nstatic var Thread_Key_Type(var self) {\n  struct Thread* t = self;\n  return key_type(t->tls);\n}\n\nstatic var Thread_Val_Type(var self) {\n  struct Thread* t = self;\n  return val_type(t->tls);\n}\n\nstatic void Thread_Mark(var self, var gc, void(*f)(var,void*)) {\n  struct Thread* t = self;\n  mark(t->tls, gc, f);\n}\n\nvar Thread = Cello(Thread,\n  Instance(Doc,\n    Thread_Name, Thread_Brief, Thread_Description, \n    NULL, Thread_Examples, NULL),\n  Instance(New,     Thread_New, Thread_Del),\n  Instance(Assign,  Thread_Assign),\n  Instance(Cmp,     Thread_Cmp),\n  Instance(Hash,    Thread_Hash),\n  Instance(Call,    Thread_Call),\n  Instance(Current, Thread_Current),\n  Instance(Mark,    Thread_Mark),\n  Instance(Start,   Thread_Start, Thread_Stop, Thread_Join, Thread_Running),\n  Instance(C_Int,   Thread_C_Int),\n  Instance(Get,     Thread_Get, Thread_Set, Thread_Mem, Thread_Rem));\n\nstatic const char* Lock_Name(void) {\n  return \"Lock\";\n}\n\nstatic const char* Lock_Brief(void) {\n  return \"Exclusive Resource\";\n}\n\nstatic const char* Lock_Description(void) {\n  return\n    \"The `Lock` class can be implemented by types to limit the access to them. \"\n    \"For example this class is implemented by the `Mutex` type to provide \"\n    \"mutual exclusion across Threads.\";\n}\n\nstatic const char* Lock_Definition(void) {\n  return\n    \"struct Lock {\\n\"\n    \"  void (*lock)(var);\\n\"\n    \"  void (*unlock)(var);\\n\"\n    \"  bool (*trylock)(var);\\n\"\n    \"};\\n\";\n}\n\nstatic struct Method* Lock_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"lock\", \n      \"void lock(var self);\",\n      \"Wait until a lock can be aquired on object `self`.\"\n    }, {\n      \"trylock\", \n      \"bool trylock(var self);\",\n      \"Try to acquire a lock on object `self`. Returns `true` on success and \"\n      \"`false` if the resource is busy.\"\n    }, {\n      \"unlock\", \n      \"void unlock(var self);\",\n      \"Release lock on object `self`.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nstatic struct Example* Lock_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var x = new(Mutex);\\n\"\n      \"lock(x);   /* Lock Mutex */ \\n\"\n      \"print(\\\"Inside Mutex!\\\\n\\\");\\n\"\n      \"unlock(x); /* Unlock Mutex */\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nvar Lock = Cello(Lock,\n  Instance(Doc,\n    Lock_Name,       Lock_Brief,    Lock_Description,\n    Lock_Definition, Lock_Examples, Lock_Methods));\n\nvoid lock(var self) {\n  method(self, Lock, lock);\n}\n\nvoid unlock(var self) {\n  method(self, Lock, unlock);\n}\n\nbool trylock(var self) {\n  return method(self, Lock, trylock);\n}\n\nstruct Mutex {\n#if defined(CELLO_UNIX)\n  pthread_mutex_t mutex;\n#elif defined(CELLO_WINDOWS)\n  HANDLE mutex;\n#endif\n};\n\nstatic const char* Mutex_Name(void) {\n  return \"Mutex\";\n}\n\nstatic const char* Mutex_Brief(void) {\n  return \"Mutual Exclusion Lock\";\n}\n\nstatic const char* Mutex_Description(void) {\n  return\n    \"The `Mutex` type can be used to gain mutual exclusion across Threads for \"\n    \"access to some resource.\";\n}\n\nstatic struct Example* Mutex_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var x = new(Mutex);\\n\"\n      \"with (mut in x) { /* Lock Mutex */ \\n\"\n      \"  print(\\\"Inside Mutex!\\\\n\\\");\\n\"\n      \"} /* Unlock Mutex */\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic void Mutex_New(var self, var args) {\n  struct Mutex* m = self;\n#if defined(CELLO_UNIX)\n  pthread_mutex_init(&m->mutex, NULL);\n#elif defined(CELLO_WINDOWS)\n  m->mutex = CreateMutex(NULL, false, NULL);\n#endif\n}\n\nstatic void Mutex_Del(var self) {\n  struct Mutex* m = self;\n#if defined(CELLO_UNIX)\n  pthread_mutex_destroy(&m->mutex);\n#elif defined(CELLO_WINDOWS)\n  CloseHandle(m->mutex);\n#endif\n}\n\nstatic void Mutex_Lock(var self) {\n  struct Mutex* m = self;\n#if defined(CELLO_UNIX)\n  int err = pthread_mutex_lock(&m->mutex);\n  \n  if (err is EINVAL)  {\n    throw(ValueError, \"Invalid Argument to Mutex Lock\");\n  }\n  \n  if (err is EDEADLK) {\n    throw(ResourceError, \"Attempt to relock already held mutex\");\n  }\n#elif defined(CELLO_WINDOWS)\n  WaitForSingleObject(m->mutex, INFINITE);\n#endif\n  \n}\n\nstatic bool Mutex_Trylock(var self) {\n  struct Mutex* m = self;\n#if defined(CELLO_UNIX)\n  int err = pthread_mutex_trylock(&m->mutex);\n  if (err == EBUSY) { return false; }\n  if (err is EINVAL) {\n    throw(ValueError, \"Invalid Argument to Mutex Lock Try\");\n  }\n  return true;\n#elif defined(CELLO_WINDOWS)\n  return not (WaitForSingleObject(m->mutex, 0) is WAIT_TIMEOUT);\n#else\n  return true;\n#endif\n  \n}\n\nstatic void Mutex_Unlock(var self) {\n  struct Mutex* m = cast(self, Mutex);\n#if defined(CELLO_UNIX)\n  int err = pthread_mutex_unlock(&m->mutex);\n  if (err is EINVAL) { throw(ValueError, \"Invalid Argument to Mutex Unlock\"); }\n  if (err is EPERM)  { throw(ResourceError, \"Mutex cannot be held by caller\"); }\n#elif defined(CELLO_WINDOWS)\n  ReleaseMutex(m->mutex);\n#endif\n  \n}\n\nvar Mutex = Cello(Mutex,\n  Instance(Doc, \n    Mutex_Name, Mutex_Brief, Mutex_Description, NULL, Mutex_Examples, NULL),\n  Instance(New,    Mutex_New, Mutex_Del),\n  Instance(Lock,   Mutex_Lock, Mutex_Unlock, Mutex_Trylock),\n  Instance(Start,  Mutex_Lock, Mutex_Unlock, NULL));\n\n"
  },
  {
    "path": "src/Tree.c",
    "content": "#include \"Cello.h\"\n\nstatic const char* Tree_Name(void) {\n  return \"Tree\";\n}\n\nstatic const char* Tree_Brief(void) {\n  return \"Balanced Binary Tree\";\n}\n\nstatic const char* Tree_Description(void) {\n  return\n    \"The `Tree` type is a self balancing binary tree implemented as a red-black \"\n    \"tree. It provides key-value access and requires the `Cmp` class to be \"\n    \"defined on the key type.\"\n    \"\\n\\n\"\n    \"Element lookup and insertion are provided as an `O(log(n))` operation. \"\n    \"This means in general a `Tree` is slower than a `Table` but it has several \"\n    \"other nice properties such as being able to iterate over the items in \"\n    \"order and not having large pauses for rehashing on some insertions.\"\n    \"\\n\\n\"\n    \"This is largely equivalent to the C++ construct \"\n    \"[std::map](http://www.cplusplus.com/reference/map/map/)\";\n}\n\nstatic struct Example* Tree_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var prices = new(Tree, String, Int);\\n\"\n      \"set(prices, $S(\\\"Apple\\\"),  $I(12));\\n\"\n      \"set(prices, $S(\\\"Banana\\\"), $I( 6));\\n\"\n      \"set(prices, $S(\\\"Pear\\\"),   $I(55));\\n\"\n      \"\\n\"\n      \"foreach (key in prices) {\\n\"\n      \"  var price = get(prices, key);\\n\"\n      \"  println(\\\"Price of %$ is %$\\\", key, price);\\n\"\n      \"}\\n\"\n    }, {\n      \"Manipulation\",\n      \"var t = new(Tree, String, Int);\\n\"\n      \"set(t, $S(\\\"Hello\\\"), $I(2));\\n\"\n      \"set(t, $S(\\\"There\\\"), $I(5));\\n\"\n      \"\\n\"\n      \"show($I(len(t))); /* 2 */\\n\"\n      \"show($I(mem(t, $S(\\\"Hello\\\")))); /* 1 */\\n\"\n      \"\\n\"\n      \"rem(t, $S(\\\"Hello\\\"));\\n\"\n      \"\\n\"\n      \"show($I(len(t))); /* 1 */\\n\"\n      \"show($I(mem(t, $S(\\\"Hello\\\")))); /* 0 */\\n\"\n      \"show($I(mem(t, $S(\\\"There\\\")))); /* 1 */\\n\"\n      \"\\n\"\n      \"resize(t, 0);\\n\"\n      \"\\n\"\n      \"show($I(len(t))); /* 0 */\\n\"\n      \"show($I(mem(t, $S(\\\"Hello\\\")))); /* 0 */\\n\"\n      \"show($I(mem(t, $S(\\\"There\\\")))); /* 0 */\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstruct Tree {\n  var root;\n  var ktype;\n  var vtype;\n  size_t ksize;\n  size_t vsize;\n  size_t nitems;\n};\n\nstatic bool Tree_Is_Red(struct Tree* m, var node);\n\nstatic var* Tree_Left(struct Tree* m, var node) {\n  return (var*)((char*)node + 0 * sizeof(var));\n}\n\nstatic var* Tree_Right(struct Tree* m, var node) {\n  return (var*)((char*)node + 1 * sizeof(var));\n}\n\nstatic var Tree_Get_Parent(struct Tree* m, var node) {\n  var ptr = *(var*)((char*)node + 2 * sizeof(var));\n  return (var)(((uintptr_t)ptr) & (~1));\n}\n\nstatic void Tree_Set_Parent(struct Tree* m, var node, var ptr) {\n  if (Tree_Is_Red(m, node)) {\n    *(var*)((char*)node + 2 * sizeof(var)) = (var)(((uintptr_t)ptr) | 1);\n  } else {\n    *(var*)((char*)node + 2 * sizeof(var)) = ptr;\n  }\n}\n\nstatic var Tree_Key(struct Tree* m, var node) {\n  return (char*)node + 3 * sizeof(var) + sizeof(struct Header);\n}\n\nstatic var Tree_Val(struct Tree* m, var node) {\n  return (char*)node + 3 * sizeof(var) +\n    sizeof(struct Header) + m->ksize +\n    sizeof(struct Header);\n}\n\nstatic void Tree_Set_Color(struct Tree* m, var node, bool col) {\n  var ptr = Tree_Get_Parent(m, node);\n  if (col) {\n    *(var*)((char*)node + 2 * sizeof(var)) = (var)(((uintptr_t)ptr) | 1);\n  } else {\n    *(var*)((char*)node + 2 * sizeof(var)) = ptr;\n  }\n}\n\nstatic bool Tree_Get_Color(struct Tree* m, var node) {\n  if (node is NULL) { return 0; }\n  var ptr = *(var*)((char*)node + 2 * sizeof(var));\n  return ((uintptr_t)ptr) & 1;\n}\n\nstatic void Tree_Set_Black(struct Tree* m, var node) {\n  Tree_Set_Color(m, node, false);\n}\n\nstatic void Tree_Set_Red(struct Tree* m, var node) {\n  Tree_Set_Color(m, node, true);\n}\n\nstatic bool Tree_Is_Red(struct Tree* m, var node) {\n  return Tree_Get_Color(m, node);\n}\n\nstatic bool Tree_Is_Black(struct Tree* m, var node) {\n  return not Tree_Get_Color(m, node);\n}\n\nstatic var Tree_Alloc(struct Tree* m) {\n  var node = calloc(1, 3 * sizeof(var) + \n    sizeof(struct Header) + m->ksize + \n    sizeof(struct Header) + m->vsize);\n  \n#if CELLO_MEMORY_CHECK == 1\n  if (node is NULL) {\n    throw(OutOfMemoryError, \"Cannot allocate Tree entry, out of memory!\");\n  }\n#endif\n  \n  var key = header_init((struct Header*)(\n    (char*)node + 3 * sizeof(var)), m->ktype, AllocData);\n  var val = header_init((struct Header*)(\n    (char*)node + 3 * sizeof(var) +\n    sizeof(struct Header) + m->ksize), m->vtype, AllocData);\n  \n  *Tree_Left(m, node) = NULL;\n  *Tree_Right(m, node) = NULL;\n  Tree_Set_Parent(m, node, NULL);\n  Tree_Set_Red(m, node);\n  \n  return node;\n}\n\nstatic void Tree_Set(var self, var key, var val);\n\nstatic void Tree_New(var self, var args) {\n  struct Tree* m = self;\n  m->ktype = get(args, $I(0));\n  m->vtype = get(args, $I(1));\n  m->ksize = size(m->ktype);\n  m->vsize = size(m->vtype);\n  m->nitems = 0;\n  m->root = NULL;\n\n  size_t nargs = len(args);\n  if (nargs % 2 isnt 0) {\n    throw(FormatError, \n      \"Received non multiple of two argument count to Tree constructor.\");\n  }\n  \n  for(size_t i = 0; i < (nargs-2)/2; i++) {\n    var key = get(args, $I(2+(i*2)+0));\n    var val = get(args, $I(2+(i*2)+1));\n    Tree_Set(m, key, val);\n  }\n  \n}\n\nstatic void Tree_Clear_Entry(struct Tree* m, var node) {\n  if (node isnt NULL) {\n    Tree_Clear_Entry(m, *Tree_Left(m, node));\n    Tree_Clear_Entry(m, *Tree_Right(m, node));\n    destruct(Tree_Key(m, node));\n    destruct(Tree_Val(m, node));\n    free(node);\n  }\n}\n\nstatic void Tree_Clear(var self) {\n  struct Tree* m = self;\n  Tree_Clear_Entry(m, m->root);\n  m->nitems = 0;\n  m->root = NULL;\n}\n\nstatic void Tree_Del(var self) {\n  struct Tree* m = self;\n  Tree_Clear(self);\n}\n\nstatic void Tree_Assign(var self, var obj) {\n  struct Tree* m = self;\n  Tree_Clear(self);\n  m->ktype = implements_method(obj, Get, key_type) ? key_type(obj) : Ref;\n  m->vtype = implements_method(obj, Get, val_type) ? val_type(obj) : Ref;\n  m->ksize = size(m->ktype);\n  m->vsize = size(m->vtype);\n  foreach (key in obj) {\n    Tree_Set(self, key, get(obj, key));\n  }\n}\n\nstatic var Tree_Iter_Init(var self);\nstatic var Tree_Iter_Next(var self, var curr);\n\nstatic bool Tree_Mem(var self, var key);\nstatic var Tree_Get(var self, var key);\n\nstatic int Tree_Cmp(var self, var obj) {\n  \n  int c;\n  var item0 = Tree_Iter_Init(self);\n  var item1 = iter_init(obj);\n  \n  while (true) {\n    if (item0 is Terminal and item1 is Terminal) { return 0; }\n    if (item0 is Terminal) { return -1; }\n    if (item1 is Terminal) { return  1; }\n    c = cmp(item0, item1);\n    if (c < 0) { return -1; }\n    if (c > 0) { return  1; }\n    c = cmp(Tree_Get(self, item0), get(obj, item1));\n    if (c < 0) { return -1; }\n    if (c > 0) { return  1; }\n    item0 = Tree_Iter_Next(self, item0);\n    item1 = iter_next(obj, item1);\n  }\n  \n  return 0;\n  \n}\n\nstatic uint64_t Tree_Hash(var self) {\n  struct Tree* m = self;\n  uint64_t h = 0;\n  \n  var curr = Tree_Iter_Init(self);\n  while (curr isnt Terminal) {\n    var node = (char*)curr - sizeof(struct Header) - 3 * sizeof(var);\n    h = h ^ hash(Tree_Key(m, node)) ^ hash(Tree_Val(m, node));\n    curr = Tree_Iter_Next(self, curr);\n  }\n  \n  return h;\n}\n\nstatic size_t Tree_Len(var self) {\n  struct Tree* m = self;\n  return m->nitems;\n}\n\nstatic bool Tree_Mem(var self, var key) {\n  struct Tree* m = self;\n  key = cast(key, m->ktype);\n  \n  var node = m->root;\n  while (node isnt NULL) { \n    int c = cmp(Tree_Key(m, node), key);\n    if (c is 0) { return true; }\n    node = c < 0 ? *Tree_Left(m, node) : *Tree_Right(m, node);\n  }\n  \n  return false;\n}\n\nstatic var Tree_Get(var self, var key) {\n  struct Tree* m = self;\n  key = cast(key, m->ktype);\n  \n  var node = m->root;\n  while (node isnt NULL) {\n    int c = cmp(Tree_Key(m, node), key);\n    if (c is 0) { return Tree_Val(m, node); }\n    node = c < 0 ? *Tree_Left(m, node) : *Tree_Right(m, node);\n  }\n  \n  return throw(KeyError, \"Key %$ not in Tree!\", key);\n}\n\nstatic var Tree_Key_Type(var self) {\n  struct Tree* m = self;  \n  return m->ktype;\n}\n\nstatic var Tree_Val_Type(var self) {\n  struct Tree* m = self;  \n  return m->vtype;\n}\n\nstatic var Tree_Maximum(struct Tree* m, var node) {\n  while (*Tree_Right(m, node) isnt NULL) {\n    node = *Tree_Right(m, node);\n  }\n  return node;\n}\n\nstatic var Tree_Sibling(struct Tree* m, var node) {\n  \n  if (node is NULL or Tree_Get_Parent(m, node) is NULL) {\n    return NULL;\n  }\n  \n  if (node is *Tree_Left(m, Tree_Get_Parent(m, node))) {\n    return *Tree_Right(m, Tree_Get_Parent(m, node));\n  } else {\n    return *Tree_Left(m, Tree_Get_Parent(m, node));\n  }\n}\n\nstatic var Tree_Grandparent(struct Tree* m, var node) {\n  if ((node isnt NULL) and (Tree_Get_Parent(m, node) isnt NULL)) {\n    return Tree_Get_Parent(m, Tree_Get_Parent(m, node));\n  } else {\n    return NULL;\n  }\n}\n\nstatic var Tree_Uncle(struct Tree* m, var node) {\n  var gpar = Tree_Grandparent(m, node);\n  if (gpar is NULL) { return NULL; }\n  if (Tree_Get_Parent(m, node) is *Tree_Left(m, gpar)) {\n    return *Tree_Right(m, gpar);\n  } else {\n    return *Tree_Left(m, gpar);\n  }\n}\n\nvoid Tree_Replace(struct Tree* m, var oldn, var newn) {\n  if (Tree_Get_Parent(m, oldn) is NULL) {\n    m->root = newn;\n  } else {\n    if (oldn is *Tree_Left(m, Tree_Get_Parent(m, oldn))) {\n      *Tree_Left(m, Tree_Get_Parent(m, oldn)) = newn;\n    } else {\n      *Tree_Right(m, Tree_Get_Parent(m, oldn)) = newn;\n    }\n  }\n  if (newn isnt NULL) {\n    Tree_Set_Parent(m, newn, Tree_Get_Parent(m, oldn));\n  }\n}\n\nstatic void Tree_Rotate_Left(struct Tree* m, var node) {\n  var r = *Tree_Right(m, node);\n  Tree_Replace(m, node, r);\n  *Tree_Right(m, node) = *Tree_Left(m, r);\n  if (*Tree_Left(m, r) isnt NULL) {\n      Tree_Set_Parent(m, *Tree_Left(m, r), node);\n  }\n  *Tree_Left(m, r) = node;\n  Tree_Set_Parent(m, node, r);\n}\n\nstatic void Tree_Rotate_Right(struct Tree* m, var node) {\n  var l = *Tree_Left(m, node);\n  Tree_Replace(m, node, l);\n  *Tree_Left(m, node) = *Tree_Right(m, l);\n  if (*Tree_Right(m, l) isnt NULL) {\n    Tree_Set_Parent(m, *Tree_Right(m, l), node);\n  }\n  *Tree_Right(m, l) = node;\n  Tree_Set_Parent(m, node, l);\n}\n\nstatic void Tree_Set_Fix(struct Tree* m, var node) {\n  \n  while (true) {\n  \n    if (Tree_Get_Parent(m, node) is NULL) {\n      Tree_Set_Black(m, node);\n      return;\n    }\n    \n    if (Tree_Is_Black(m, Tree_Get_Parent(m, node))) { return; }\n    \n    if ((Tree_Uncle(m, node) isnt NULL)\n    and (Tree_Is_Red(m, Tree_Uncle(m, node)))) {\n      Tree_Set_Black(m, Tree_Get_Parent(m, node));\n      Tree_Set_Black(m, Tree_Uncle(m, node));\n      Tree_Set_Red(m, Tree_Grandparent(m, node));\n      node = Tree_Grandparent(m, node);\n      continue;\n    }\n    \n    if ((node is *Tree_Right(m, Tree_Get_Parent(m, node))) \n    and (Tree_Get_Parent(m, node) is *Tree_Left(m, Tree_Grandparent(m, node)))) {\n      Tree_Rotate_Left(m, Tree_Get_Parent(m, node));\n      node = *Tree_Left(m, node);\n    }\n    \n    else\n    \n    if ((node is *Tree_Left(m, Tree_Get_Parent(m, node))) \n    and (Tree_Get_Parent(m, node) is *Tree_Right(m, Tree_Grandparent(m, node)))) {\n      Tree_Rotate_Right(m, Tree_Get_Parent(m, node));\n      node = *Tree_Right(m, node);\n    }\n    \n    Tree_Set_Black(m, Tree_Get_Parent(m, node));\n    Tree_Set_Red(m, Tree_Grandparent(m, node));\n    \n    if (node is *Tree_Left(m, Tree_Get_Parent(m, node))) {\n      Tree_Rotate_Right(m, Tree_Grandparent(m, node));\n    } else {\n      Tree_Rotate_Left(m, Tree_Grandparent(m, node));\n    }\n    \n    return;\n  \n  }\n  \n}\n\nstatic void Tree_Set(var self, var key, var val) {\n  struct Tree* m = self;\n  key = cast(key, m->ktype);\n  val = cast(val, m->vtype);\n  \n  var node = m->root;\n  \n  if (node is NULL) {\n    var node = Tree_Alloc(m);\n    assign(Tree_Key(m, node), key);\n    assign(Tree_Val(m, node), val);\n    m->root = node;\n    m->nitems++;\n    Tree_Set_Fix(m, node);\n    return;\n  }\n  \n  while (true) {\n    \n    int c = cmp(Tree_Key(m, node), key);\n    \n    if (c is 0) {\n      assign(Tree_Key(m, node), key);\n      assign(Tree_Val(m, node), val);\n      return;\n    }\n    \n    if (c < 0) {\n    \n      if (*Tree_Left(m, node) is NULL) {\n        var newn = Tree_Alloc(m);\n        assign(Tree_Key(m, newn), key);\n        assign(Tree_Val(m, newn), val);\n        *Tree_Left(m, node) = newn;\n        Tree_Set_Parent(m, newn, node);\n        Tree_Set_Fix(m, newn);\n        m->nitems++;\n        return;\n      }\n      \n      node = *Tree_Left(m, node);\n    }\n      \n    if (c > 0) {\n    \n      if (*Tree_Right(m, node) is NULL) {\n        var newn = Tree_Alloc(m);\n        assign(Tree_Key(m, newn), key);\n        assign(Tree_Val(m, newn), val);\n        *Tree_Right(m, node) = newn;\n        Tree_Set_Parent(m, newn, node);\n        Tree_Set_Fix(m, newn);\n        m->nitems++;\n        return;\n      }\n      \n      node = *Tree_Right(m, node);\n    }\n    \n  }\n  \n}\n\nstatic void Tree_Rem_Fix(struct Tree* m, var node) {\n \n  while (true) {\n  \n    if (Tree_Get_Parent(m, node) is NULL) { return; }\n    \n    if (Tree_Is_Red(m, Tree_Sibling(m, node))) {\n      Tree_Set_Red(m, Tree_Get_Parent(m, node));\n      Tree_Set_Black(m, Tree_Sibling(m, node));\n      if (node is *Tree_Left(m, Tree_Get_Parent(m, node))) {\n          Tree_Rotate_Left(m, Tree_Get_Parent(m, node));\n      } else {\n          Tree_Rotate_Right(m, Tree_Get_Parent(m, node));\n      }\n    }\n    \n    if (Tree_Is_Black(m, Tree_Get_Parent(m, node))\n    and Tree_Is_Black(m, Tree_Sibling(m, node))\n    and Tree_Is_Black(m, *Tree_Left(m, Tree_Sibling(m, node)))\n    and Tree_Is_Black(m, *Tree_Right(m, Tree_Sibling(m, node)))) {\n      Tree_Set_Red(m, Tree_Sibling(m, node));\n      node = Tree_Get_Parent(m, node);\n      continue;\n    }\n    \n    if (Tree_Is_Red(m, Tree_Get_Parent(m, node))\n    and Tree_Is_Black(m, Tree_Sibling(m, node))\n    and Tree_Is_Black(m, *Tree_Left(m, Tree_Sibling(m, node)))\n    and Tree_Is_Black(m, *Tree_Right(m, Tree_Sibling(m, node)))) {\n      Tree_Set_Red(m, Tree_Sibling(m, node));\n      Tree_Set_Black(m, Tree_Get_Parent(m, node));\n      return;\n    }\n    \n    if (Tree_Is_Black(m, Tree_Sibling(m, node))) {\n    \n      if (node is *Tree_Left(m, Tree_Get_Parent(m, node))\n      and Tree_Is_Red(m, *Tree_Left(m, Tree_Sibling(m, node)))\n      and Tree_Is_Black(m, *Tree_Right(m, Tree_Sibling(m, node)))) {\n        Tree_Set_Red(m, Tree_Sibling(m, node));\n        Tree_Set_Black(m, *Tree_Left(m, Tree_Sibling(m, node)));\n        Tree_Rotate_Right(m, Tree_Sibling(m, node));\n      }\n      \n      else \n      \n      if (node is *Tree_Right(m, Tree_Get_Parent(m, node))\n      and Tree_Is_Red(m, *Tree_Right(m, Tree_Sibling(m, node)))\n      and Tree_Is_Black(m, *Tree_Left(m, Tree_Sibling(m, node)))) {\n        Tree_Set_Red(m, Tree_Sibling(m, node));\n        Tree_Set_Black(m, *Tree_Right(m, Tree_Sibling(m, node)));\n        Tree_Rotate_Left(m, Tree_Sibling(m, node));\n      }\n    \n    }\n    \n    Tree_Set_Color(m, \n      Tree_Sibling(m, node),  \n      Tree_Get_Color(m, Tree_Get_Parent(m, node)));\n    \n    Tree_Set_Black(m, Tree_Get_Parent(m, node));\n    \n    if (node is *Tree_Left(m, Tree_Get_Parent(m, node))) {\n        Tree_Set_Black(m, *Tree_Right(m, Tree_Sibling(m, node)));\n        Tree_Rotate_Left(m, Tree_Get_Parent(m, node));\n    } else {\n        Tree_Set_Black(m, *Tree_Left(m, Tree_Sibling(m, node)));\n        Tree_Rotate_Right(m, Tree_Get_Parent(m, node));\n    }\n    \n    return;\n  }\n\n}\n\nstatic void Tree_Rem(var self, var key) {\n  struct Tree* m = self;\n  \n  key = cast(key, m->ktype);\n  \n  bool found = false;\n  var node = m->root;\n  while (node isnt NULL) {\n    int c = cmp(Tree_Key(m, node), key);\n    if (c is 0) { found = true; break; }\n    node = c < 0 ? *Tree_Left(m, node) : *Tree_Right(m, node);\n  }\n  \n  if (not found) {\n    throw(KeyError, \"Key %$ not in Tree!\", key);\n    return;\n  }\n  \n  destruct(Tree_Key(m, node));\n  destruct(Tree_Val(m, node));\n  \n  if ((*Tree_Left(m, node) isnt NULL) \n  and (*Tree_Right(m, node) isnt NULL)) {\n    var pred = Tree_Maximum(m, *Tree_Left(m, node));\n    bool ncol = Tree_Get_Color(m, node);\n    memcpy((char*)node + 3 * sizeof(var), (char*)pred + 3 * sizeof(var),\n      sizeof(struct Header) + m->ksize +\n      sizeof(struct Header) + m->vsize);\n    Tree_Set_Color(m, node, ncol);\n    node = pred;\n  }\n\n  var chld = *Tree_Right(m, node) is NULL \n    ? *Tree_Left(m, node) \n    : *Tree_Right(m, node);\n    \n  if (Tree_Is_Black(m, node)) {\n    Tree_Set_Color(m, node, Tree_Get_Color(m, chld));\n    Tree_Rem_Fix(m, node);\n  }\n    \n  Tree_Replace(m, node, chld);\n  \n  if ((Tree_Get_Parent(m, node) is NULL) and (chld isnt NULL)) {\n    Tree_Set_Black(m, chld);\n  }\n  \n  m->nitems--;\n  free(node);\n  \n}\n\nstatic var Tree_Iter_Init(var self) {\n  struct Tree* m = self;\n  if (m->nitems is 0) { return Terminal; }\n  var node = m->root;\n  while (*Tree_Left(m, node) isnt NULL) {\n    node = *Tree_Left(m, node);\n  }\n  return Tree_Key(m, node);\n}\n\nstatic var Tree_Iter_Next(var self, var curr) {\n  struct Tree* m = self;\n  \n  var node = (char*)curr - sizeof(struct Header) - 3 * sizeof(var);\n  var prnt = Tree_Get_Parent(m, node);\n  \n  if (*Tree_Right(m, node) isnt NULL) {\n    node = *Tree_Right(m, node);\n    while (*Tree_Left(m, node) isnt NULL) {\n      node = *Tree_Left(m, node);\n    }\n    return Tree_Key(m, node);\n  }\n  \n  while (true) {\n    if (prnt is NULL) { return Terminal; }\n    if (node is *Tree_Left(m, prnt)) { return Tree_Key(m, prnt); }\n    if (node is *Tree_Right(m, prnt)) {\n      prnt = Tree_Get_Parent(m, prnt);\n      node = Tree_Get_Parent(m, node);\n    }\n  }\n  \n  return Terminal;\n}\n\nstatic var Tree_Iter_Last(var self) {\n  struct Tree* m = self;\n  if (m->nitems is 0) { return Terminal; }\n  var node = m->root;\n  while (*Tree_Right(m, node) isnt NULL) {\n    node = *Tree_Right(m, node);\n  }\n  return Tree_Key(m, node);\n}\n\nstatic var Tree_Iter_Prev(var self, var curr) {\n  struct Tree* m = self;\n  \n  var node = (char*)curr - sizeof(struct Header) - 3 * sizeof(var);\n  var prnt = Tree_Get_Parent(m, node);\n  \n  if (*Tree_Left(m, node) isnt NULL) {\n    node = *Tree_Left(m, node);\n    while (*Tree_Right(m, node) isnt NULL) {\n      node = *Tree_Right(m, node);\n    }\n    return Tree_Key(m, node);\n  }\n  \n  while (true) {\n    if (prnt is NULL) { return Terminal; }\n    if (node is *Tree_Right(m, prnt)) { return Tree_Key(m, prnt); }\n    if (node is *Tree_Left(m, prnt)) {\n      prnt = Tree_Get_Parent(m, prnt);\n      node = Tree_Get_Parent(m, node);\n    }\n  }\n  \n  return Terminal;\n}\n\nstatic var Tree_Iter_Type(var self) {\n  struct Tree* m = self;\n  return m->ktype;\n}\n\nstatic int Tree_Show(var self, var output, int pos) {\n  struct Tree* m = self;  \n  \n  pos = print_to(output, pos, \"<'Tree' At 0x%p {\", self);\n  \n  var curr = Tree_Iter_Init(self);\n  \n  while (curr isnt Terminal) {\n    var node = (char*)curr - sizeof(struct Header) - 3 * sizeof(var);\n    pos = print_to(output, pos, \"%$:%$\",\n      Tree_Key(m, node), Tree_Val(m, node));\n    curr = Tree_Iter_Next(self, curr);\n    if (curr isnt Terminal) { pos = print_to(output, pos, \", \"); }\n  }\n  \n  return print_to(output, pos, \"}>\");\n}\n\nstatic void Tree_Mark(var self, var gc, void(*f)(var,void*)) {  \n  struct Tree* m = self;\n\n  var curr = Tree_Iter_Init(self);\n  \n  while (curr isnt Terminal) {\n    var node = (char*)curr - sizeof(struct Header) - 3 * sizeof(var);\n    f(gc, Tree_Key(m, node));\n    f(gc, Tree_Val(m, node));\n    curr = Tree_Iter_Next(self, curr);\n  }\n  \n}\n\nstatic void Tree_Resize(var self, size_t n) {\n  \n  if (n is 0) {\n    Tree_Clear(self);\n  } else {\n    throw(FormatError, \n      \"Cannot resize Tree to %li items. Trees can only be resized to 0 items.\", \n      $I(n));\n  }\n  \n}\n\nvar Tree = Cello(Tree,\n  Instance(Doc,\n    Tree_Name, Tree_Brief,    Tree_Description,\n    NULL,      Tree_Examples, NULL),\n  Instance(New,     Tree_New, Tree_Del),\n  Instance(Assign,  Tree_Assign),\n  Instance(Mark,    Tree_Mark),\n  Instance(Cmp,     Tree_Cmp),\n  Instance(Hash,    Tree_Hash),\n  Instance(Len,     Tree_Len),\n  Instance(Get, \n    Tree_Get, Tree_Set, Tree_Mem, Tree_Rem, \n    Tree_Key_Type,  Tree_Val_Type),\n  Instance(Resize,  Tree_Resize),\n  Instance(Iter, \n    Tree_Iter_Init, Tree_Iter_Next, \n    Tree_Iter_Last, Tree_Iter_Prev, Tree_Iter_Type),\n  Instance(Show,    Tree_Show, NULL));\n\n\n"
  },
  {
    "path": "src/Tuple.c",
    "content": "#include \"Cello.h\"\n\nstatic const char* Tuple_Name(void) {\n  return \"Tuple\";\n}\n\nstatic const char* Tuple_Brief(void) {\n  return \"Basic Collection\";\n}\n\nstatic const char* Tuple_Description(void) {\n  return\n    \"The `Tuple` type provides a basic way to create a simple collection of \"\n    \"objects. Its main use is the fact that it can be constructed on the \"\n    \"stack using the `tuple` macro. This makes it suitable for a number of \"\n    \"purposes such as use in functions that take a variable number of \"\n    \"arguments.\"\n    \"\\n\\n\"\n    \"Tuples can also be constructed on the heap and stored in collections. \"\n    \"This makes them also useful as a simple _untyped_ list of objects.\"\n    \"\\n\\n\"\n    \"Internally Tuples are just an array of pointers terminated with a pointer \"\n    \"to the Cello `Terminal` object. This makes positional access fast, but \"\n    \"many other operations slow including iteration and counting the number of \"\n    \"elements. Due to this it is only recommended Tuples are used for small \"\n    \"collections. \"\n    \"\\n\\n\"\n    \"Because Tuples are terminated with the Cello `Terminal` object this can't \"\n    \"naturally be included within them. This object should therefore only be \"\n    \"returned from iteration functions.\";\n}\n\nstatic const char* Tuple_Definition(void) {\n  return\n    \"struct Tuple {\\n\"\n    \"  var* items;\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* Tuple_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var x = tuple($I(100), $I(200), $S(\\\"Hello\\\"));\\n\"\n      \"show(x);\\n\"\n      \"var y = tuple(Int, $I(10), $I(20));\\n\"\n      \"var z = new_with(Array, y);\\n\"\n      \"show(z);\\n\"\n      \"\\n\"\n      \"foreach (item in x) {\\n\"\n      \"  println(\\\"%$\\\", item);\\n\"\n      \"}\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic struct Method* Tuple_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"tuple\", \n      \"#define tuple(...)\",\n      \"Construct a `Tuple` object on the stack.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nstatic void Tuple_New(var self, var args) {\n  struct Tuple* t = self;\n  size_t nargs = len(args);\n  \n  t->items = malloc(sizeof(var) * (nargs+1));\n  \n#if CELLO_MEMORY_CHECK == 1\n  if (t->items is NULL) {\n    throw(OutOfMemoryError, \"Cannot create Tuple, out of memory!\");\n  }\n#endif\n  \n  for (size_t i = 0; i < nargs; i++) {\n    t->items[i] = get(args, $I(i));\n  }\n  \n  t->items[nargs] = Terminal;\n}\n\nstatic void Tuple_Del(var self) {\n  struct Tuple* t = self;\n  \n#if CELLO_ALLOC_CHECK == 1\n  if (header(self)->alloc is (var)AllocStack\n  or  header(self)->alloc is (var)AllocStatic) {\n    throw(ValueError, \"Cannot destruct Tuple, not on heap!\");\n  }\n#endif\n  \n  free(t->items);\n}\n\nstatic void Tuple_Push(var self, var obj);\n\nstatic void Tuple_Assign(var self, var obj) {\n  struct Tuple* t = self;\n  \n  if (implements_method(obj, Len, len)\n  and implements_method(obj, Get, get)) {\n  \n    size_t nargs = len(obj);\n    \n#if CELLO_ALLOC_CHECK == 1\n    if (header(self)->alloc is (var)AllocStack\n    or  header(self)->alloc is (var)AllocStatic) {\n      throw(ValueError, \"Cannot reallocate Tuple, not on heap!\");\n    }\n#endif\n    \n    t->items = realloc(t->items, sizeof(var) * (nargs+1));\n    \n#if CELLO_MEMORY_CHECK == 1\n    if (t->items is NULL) {\n      throw(OutOfMemoryError, \"Cannot allocate Tuple, out of memory!\");\n    }\n#endif\n    \n    for (size_t i = 0; i < nargs; i++) {\n      t->items[i] = get(obj, $I(i));\n    }\n    \n    t->items[nargs] = Terminal;\n  \n  } else {\n    \n    foreach (item in obj) {\n      Tuple_Push(self, item);\n    }\n    \n  }\n}\n\nstatic size_t Tuple_Len(var self) {\n  struct Tuple* t = self;\n  size_t i = 0;\n  while (t->items and t->items[i] isnt Terminal) { i++; }\n  return i;\n}\n\nstatic var Tuple_Iter_Init(var self) {\n  struct Tuple* t = self;\n  return t->items[0];\n}\n\nstatic var Tuple_Iter_Next(var self, var curr) {\n  struct Tuple* t = self;\n  size_t i = 0;\n  while (t->items[i] isnt Terminal) {\n    if (t->items[i] is curr) { return t->items[i+1]; }\n    i++;\n  }\n  return Terminal;\n}\n\nstatic var Tuple_Iter_Last(var self) {\n  struct Tuple* t = self;\n  return t->items[Tuple_Len(t)-1];\n}\n\nstatic var Tuple_Iter_Prev(var self, var curr) {\n  struct Tuple* t = self;\n  if (curr is t->items[0]) { return Terminal; }\n  size_t i = 0;\n  while (t->items[i] isnt Terminal) {\n    if (t->items[i] is curr) { return t->items[i-1]; }\n    i++;\n  }\n  return Terminal;\n}\n\nstatic var Tuple_Get(var self, var key) {\n  struct Tuple* t = self;\n  size_t nitems = Tuple_Len(t);\n  \n  int64_t i = c_int(key);\n  i = i < 0 ? nitems+i : i;\n\n#if CELLO_BOUND_CHECK == 1\n  if (i < 0 or i >= (int64_t)nitems) {\n    return throw(IndexOutOfBoundsError, \n      \"Index '%i' out of bounds for Tuple of size %i.\", \n      key, $I(Tuple_Len(t)));\n  }\n#endif\n  \n  return t->items[i];\n}\n\nstatic void Tuple_Set(var self, var key, var val) {\n  struct Tuple* t = self;\n  size_t nitems = Tuple_Len(t);\n\n  int64_t i = c_int(key);\n  i = i < 0 ? nitems+i : i;\n\n#if CELLO_BOUND_CHECK == 1\n  if (i < 0 or i >= (int64_t)nitems) {\n    throw(IndexOutOfBoundsError, \n      \"Index '%i' out of bounds for Tuple of size %i.\", \n      key, $I(Tuple_Len(t)));\n    return;\n  }\n#endif\n\n  t->items[i] = val;\n}\n\nstatic bool Tuple_Mem(var self, var item) {\n  foreach (obj in self) {\n    if (eq(obj, item)) { return true; }\n  }\n  return false;  \n}\n\nstatic void Tuple_Pop_At(var self, var key);\n\nstatic void Tuple_Rem(var self, var item) {\n  struct Tuple* t = self;\n  size_t i = 0;\n  while (t->items[i] isnt Terminal) {\n    if (eq(item, t->items[i])) {\n      Tuple_Pop_At(self, $I(i));\n      return;\n    }\n    i++;\n  }\n}\n\nstatic int Tuple_Show(var self, var output, int pos) {\n  struct Tuple* t = self;\n  pos = print_to(output, pos, \"tuple(\", self);\n  size_t i = 0;\n  while (t->items[i] isnt Terminal) {\n    pos = print_to(output, pos, \"%$\", t->items[i]);\n    if (t->items[i+1] isnt Terminal) { pos = print_to(output, pos, \", \"); }\n    i++;\n  }\n  return print_to(output, pos, \")\");\n}\n\nstatic void Tuple_Push(var self, var obj) {\n  \n  struct Tuple* t = self;\n  size_t nitems = Tuple_Len(t);\n  \n#if CELLO_ALLOC_CHECK == 1\n  if (header(self)->alloc is (var)AllocStack\n  or  header(self)->alloc is (var)AllocStatic) {\n    throw(ValueError, \"Cannot reallocate Tuple, not on heap!\");\n  }\n#endif\n  \n  t->items = realloc(t->items, sizeof(var) * (nitems+2));\n  \n#if CELLO_MEMORY_CHECK == 1\n  if (t->items is NULL) {\n    throw(OutOfMemoryError, \"Cannot grow Tuple, out of memory!\");\n  }\n#endif\n  \n  t->items[nitems+0] = obj;\n  t->items[nitems+1] = Terminal;\n  \n}\n\nstatic void Tuple_Pop(var self) {\n  \n  struct Tuple* t = self;\n  size_t nitems = Tuple_Len(t);\n  \n#if CELLO_BOUND_CHECK == 1\n  if (nitems is 0) {\n    throw(IndexOutOfBoundsError, \"Cannot pop. Tuple is empty!\");\n    return;\n  }\n#endif\n  \n#if CELLO_ALLOC_CHECK == 1\n  if (header(self)->alloc is (var)AllocStack\n  or  header(self)->alloc is (var)AllocStatic) {\n    throw(ValueError, \"Cannot reallocate Tuple, not on heap!\");\n  }\n#endif\n  \n  t->items = realloc(t->items, sizeof(var) * nitems);\n  t->items[nitems-1] = Terminal;\n  \n}\n\nstatic void Tuple_Push_At(var self, var obj, var key) {\n  \n  struct Tuple* t = self;\n  size_t nitems = Tuple_Len(t);\n\n  int64_t i = c_int(key);\n  i = i < 0 ? nitems+i : i;\n\n#if CELLO_BOUND_CHECK == 1\n  if (i < 0 or i >= (int64_t)nitems) {\n    throw(IndexOutOfBoundsError,\n      \"Index '%i' out of bounds for Tuple of size %i.\", key, $I(nitems));\n  }\n#endif  \n  \n#if CELLO_ALLOC_CHECK == 1\n  if (header(self)->alloc is (var)AllocStack\n  or  header(self)->alloc is (var)AllocStatic) {\n    throw(ValueError, \"Cannot reallocate Tuple, not on heap!\");\n  }\n#endif\n  \n  t->items = realloc(t->items, sizeof(var) * (nitems+2));\n  \n#if CELLO_MEMORY_CHECK == 1\n  if (t->items is NULL) {\n    throw(OutOfMemoryError, \"Cannot grow Tuple, out of memory!\");\n  }\n#endif\n\n  memmove(&t->items[i+1], &t->items[i+0], \n    sizeof(var) * (nitems - (size_t)i + 1));\n    \n  t->items[i] = obj;\n  \n}\n\nstatic void Tuple_Pop_At(var self, var key) {\n\n  struct Tuple* t = self;\n  size_t nitems = Tuple_Len(t);\n\n  int64_t i = c_int(key);\n  i = i < 0 ? nitems+i : i;\n  \n#if CELLO_BOUND_CHECK == 1\n  if (i < 0 or i >= (int64_t)nitems) {\n    throw(IndexOutOfBoundsError,\n      \"Index '%i' out of bounds for Tuple of size %i.\", key, $I(nitems));\n  }\n#endif\n  \n  memmove(&t->items[i+0], &t->items[i+1], sizeof(var) * (nitems - (size_t)i));\n\n#if CELLO_ALLOC_CHECK == 1\n  if (header(self)->alloc is (var)AllocStack\n  or  header(self)->alloc is (var)AllocStatic) {\n    throw(ValueError, \"Cannot reallocate Tuple, not on heap!\");\n  }\n#endif\n  \n  t->items = realloc(t->items, sizeof(var) * nitems);\n  \n}\n\nstatic void Tuple_Concat(var self, var obj) {\n\n  struct Tuple* t = self;\n  size_t nitems = Tuple_Len(t);\n  size_t objlen = len(obj);\n  \n#if CELLO_ALLOC_CHECK == 1\n  if (header(self)->alloc is (var)AllocStack\n  or  header(self)->alloc is (var)AllocStatic) {\n    throw(ValueError, \"Cannot reallocate Tuple, not on heap!\");\n  }\n#endif\n  \n  t->items = realloc(t->items, sizeof(var) * (nitems+1+objlen));\n  \n#if CELLO_MEMORY_CHECK == 1\n  if (t->items is NULL) {\n    throw(OutOfMemoryError, \"Cannot grow Tuple, out of memory!\");\n  }\n#endif\n  \n  size_t i = nitems;\n  foreach (item in obj) {\n    t->items[i] = item;\n    i++;\n  }\n  \n  t->items[nitems+objlen] = Terminal;\n  \n}\n\nstatic void Tuple_Resize(var self, size_t n) {\n  struct Tuple* t = self;\n  \n#if CELLO_ALLOC_CHECK == 1\n  if (header(self)->alloc is (var)AllocStack\n  or  header(self)->alloc is (var)AllocStatic) {\n    throw(ValueError, \"Cannot reallocate Tuple, not on heap!\");\n  }\n#endif\n  \n  size_t m = Tuple_Len(self);\n  \n  if (n < m) {\n    t->items = realloc(t->items, sizeof(var) * (n+1));\n    t->items[n] = Terminal;\n  } else {\n    throw(FormatError, \n      \"Cannot resize Tuple to %li as it only contains %li items\", \n      $I(n), $I(m));\n  }\n  \n}\n\nstatic void Tuple_Mark(var self, var gc, void(*f)(var,void*)) {\n  struct Tuple* t = self;\n  size_t i = 0;\n  if (t->items is NULL) { return; }\n  while (t->items[i] isnt Terminal) {\n    f(gc, t->items[i]); i++;\n  }\n}\n\nstatic void Tuple_Swap(struct Tuple* t, size_t i, size_t j) {\n  var tmp = t->items[i];\n  t->items[i] = t->items[j];\n  t->items[j] = tmp;\n}\n\nstatic size_t Tuple_Sort_Partition(\n  struct Tuple* t, int64_t l, int64_t r, bool(*f)(var,var)) {\n  \n  int64_t p = l + (r - l) / 2;\n  Tuple_Swap(t, p, r);\n  \n  int64_t s = l;\n  for (int64_t i = l; i < r; i++) {\n    if (f(t->items[i], t->items[r])) {\n      Tuple_Swap(t, i, s);\n      s++;\n    }\n  }\n  \n  Tuple_Swap(t, s, r);\n  return s;\n}\n\nstatic void Tuple_Sort_Part(\n  struct Tuple* t, int64_t l, int64_t r, bool(*f)(var,var)) {\n  if (l < r) {\n    int64_t s = Tuple_Sort_Partition(t, l, r, f);\n    Tuple_Sort_Part(t, l, s-1, f);\n    Tuple_Sort_Part(t, s+1, r, f);\n  }\n}\n\nstatic void Tuple_Sort_By(var self, bool(*f)(var,var)) {\n  Tuple_Sort_Part(self, 0, Tuple_Len(self)-1, f);\n}\n\nstatic int Tuple_Cmp(var self, var obj) {\n  struct Tuple* t = self;\n  \n  size_t i = 0;\n  var item0 = t->items[i];\n  var item1 = iter_init(obj);\n  \n  while (true) {\n    if (item0 is Terminal and item1 is Terminal) { return 0; }\n    if (item0 is Terminal) { return -1; }\n    if (item1 is Terminal) { return  1; }\n    int c = cmp(item0, item1);\n    if (c < 0) { return -1; }\n    if (c > 0) { return  1; }\n    i++;\n    item0 = t->items[i];\n    item1 = iter_next(obj, item1);\n  }\n  \n  return 0;\n}\n\nstatic uint64_t Tuple_Hash(var self) {\n  struct Tuple* t = self;\n  uint64_t h = 0;\n  \n  size_t n = Tuple_Len(self);\n  for (size_t i = 0; i < n; i++) {\n    h ^= hash(t->items[i]);\n  }\n  \n  return h;\n}\n\nvar Tuple = Cello(Tuple,\n  Instance(Doc,\n    Tuple_Name,       Tuple_Brief,    Tuple_Description, \n    Tuple_Definition, Tuple_Examples, Tuple_Methods),\n  Instance(New,      Tuple_New, Tuple_Del),\n  Instance(Assign,   Tuple_Assign),\n  Instance(Cmp,      Tuple_Cmp),\n  Instance(Hash,     Tuple_Hash),\n  Instance(Len,      Tuple_Len),\n  Instance(Get,      Tuple_Get, Tuple_Set, Tuple_Mem, Tuple_Rem),\n  Instance(Push,     Tuple_Push, Tuple_Pop, Tuple_Push_At, Tuple_Pop_At),\n  Instance(Concat,   Tuple_Concat, Tuple_Push),\n  Instance(Resize,   Tuple_Resize),\n  Instance(Iter, \n    Tuple_Iter_Init, Tuple_Iter_Next, \n    Tuple_Iter_Last, Tuple_Iter_Prev, NULL),\n  Instance(Mark,     Tuple_Mark),\n  Instance(Sort,     Tuple_Sort_By),\n  Instance(Show,     Tuple_Show, NULL));\n\n"
  },
  {
    "path": "src/Type.c",
    "content": "#include \"Cello.h\"\n\nstatic const char* Cast_Name(void) {\n  return \"Cast\";\n}\n\nstatic const char* Cast_Brief(void) {\n  return \"Runtime Type Checking\";\n}\n\nstatic const char* Cast_Description(void) {\n  return\n    \"The `Cast` class provides a rudimentary run-time type checking. By \"\n    \"default it simply checks that the passed in object is of a given type \"\n    \"but it can be overridden by types which have to do more complex checking \"\n    \"to ensure the types are correct.\";\n}\n\nstatic const char* Cast_Definition(void) {\n  return\n    \"struct Cast {\\n\"\n    \"  var (*cast)(var, var);\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* Cast_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var x = $I(100);\\n\"\n      \"struct Int* y = cast(x, Int);\\n\"\n      \"show(y);\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic struct Method* Cast_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"cast\", \n      \"var cast(var self, var type);\",\n      \"Ensures the object `self` is of the given `type` and returns it if it \"\n      \"is.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nvar Cast = Cello(Cast, Instance(Doc, \n  Cast_Name,       Cast_Brief,    Cast_Description, \n  Cast_Definition, Cast_Examples, Cast_Methods));\n\nvar cast(var self, var type) {\n  \n  struct Cast* c = instance(self, Cast);\n  if (c and c->cast) {\n    return c->cast(self, type);\n  }\n  \n  if (type_of(self) is type) {\n    return self;\n  } else {\n    return throw(ValueError,\n      \"cast expected type %s, got type %s\", type_of(self), type);\n  }\n  \n}\n\nstatic const char* Type_Name(void) {\n  return \"Type\";\n}\n\nstatic const char* Type_Brief(void) {\n  return \"Metadata Object\";\n}\n\nstatic const char* Type_Description(void) {\n  return \n    \"The `Type` type is one of the most important types in Cello. It is the \"\n    \"object which specifies the meta-data associated with a particular object. \"\n    \"Most importantly this says what classes an object implements and what \"\n    \"their instances are.\"\n    \"\\n\\n\"\n    \"One can get the type of an object using the `type_of` function.\"\n    \"\\n\\n\"\n    \"To see if an object implements a class `implements` can be used. To \"\n    \"call a member of a class with an object `method` can be used.\"\n    \"\\n\\n\"\n    \"To see if a type implements a class `type_implements` can be used. To \"\n    \"call a member of a class, implemented `type_method` can be used.\";\n}\n\nstatic struct Example* Type_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"var t = type_of($I(5));\\n\"\n      \"show(t); /* Int */\\n\"\n      \"\\n\"\n      \"show($I(type_implements(t, New)));  /* 1 */\\n\"\n      \"show($I(type_implements(t, Cmp)));  /* 1 */\\n\"\n      \"show($I(type_implements(t, Hash))); /* 1 */\\n\"\n      \"\\n\"\n      \"show($I(type_method(t, Cmp, cmp, $I(5), $I(6))));\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic struct Method* Type_Methods(void) {\n\n  static struct Method methods[] = {\n    {\n      \"type_of\", \n      \"var type_of(var self);\",\n      \"Returns the `Type` of an object `self`.\"\n    }, {\n      \"instance\", \n      \"var instance(var self, var cls);\\n\"\n      \"var type_instance(var type, var cls);\",\n      \"Returns the instance of class `cls` implemented by object `self` or \"\n      \"type `type`. If class is not implemented then returns `NULL`.\"\n    }, {\n      \"implements\", \n      \"bool implements(var self, var cls);\\n\"\n      \"bool type_implements(var type, var cls);\",\n      \"Returns if the object `self` or type `type` implements the class `cls`.\"\n    }, {\n      \"method\", \n      \"#define method(X, C, M, ...)\\n\"\n      \"#define type_method(T, C, M, ...)\",\n      \"Returns the result of the call to method `M` of class `C` for object `X`\"\n      \"or type `T`. If class is not implemented then an error is thrown.\"\n    }, {\n      \"implements_method\", \n      \"#define implements_method(X, C, M)\\n\"\n      \"#define type_implements_method(T, C, M)\",\n      \"Returns if the type `T` or object `X` implements the method `M` of \"\n      \"class C.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n  \n}\n\nenum {\n  CELLO_NBUILTINS = 2 + (CELLO_CACHE_NUM / 3),\n  CELLO_MAX_INSTANCES = 256\n};\n\nstatic var Type_Alloc(void) {\n\n  struct Header* head = calloc(1, \n    sizeof(struct Header) +\n    sizeof(struct Type) * \n    (CELLO_NBUILTINS + \n     CELLO_MAX_INSTANCES + 1));\n  \n#if CELLO_MEMORY_CHECK == 1\n  if (head is NULL) {\n    throw(OutOfMemoryError, \"Cannot create new 'Type', out of memory!\");\n  }\n#endif\n  \n  return header_init(head, Type, AllocHeap);\n}\n\nstatic void Type_New(var self, var args) {\n  \n  struct Type* t = self;\n\n  var name = get(args, $I(0));\n  var size = get(args, $I(1));\n  \n#if CELLO_MEMORY_CHECK == 1\n  if (len(args) - 2 > CELLO_MAX_INSTANCES) {\n    throw(OutOfMemoryError,\n      \"Cannot construct 'Type' with %i instances, maximum is %i.\",\n      $I(len(args)), $I(CELLO_MAX_INSTANCES));\n  }\n#endif  \n  \n  size_t cache_entries = CELLO_CACHE_NUM / 3;\n  for (size_t i = 0; i < cache_entries; i++) {\n    t[i] = (struct Type){ NULL, NULL, NULL };\n  }\n  \n  t[cache_entries+0] = (struct Type){ NULL, \"__Name\", (var)c_str(name) };\n  t[cache_entries+1] = (struct Type){ NULL, \"__Size\", (var)(uintptr_t)c_int(size) };\n  \n  for(size_t i = 2; i < len(args); i++) {\n    var ins = get(args, $I(i));\n    t[CELLO_NBUILTINS-2+i] = (struct Type){\n      NULL, (var)c_str(type_of(ins)), ins };\n  }\n  \n  t[CELLO_NBUILTINS+len(args)-2] = (struct Type){ NULL, NULL, NULL };\n}\n\nstatic char* Type_Builtin_Name(struct Type* t) {\n  return t[(CELLO_CACHE_NUM / 3)+0].inst;\n}\n\nstatic size_t Type_Builtin_Size(struct Type* t) {\n  return (size_t)t[(CELLO_CACHE_NUM / 3)+1].inst;\n}\n\nstatic int Type_Show(var self, var output, int pos) {\n  return format_to(output, pos, \"%s\", Type_Builtin_Name(self));\n}\n\nstatic int Type_Cmp(var self, var obj) {\n  struct Type* objt = cast(obj, Type);\n  return strcmp(Type_Builtin_Name(self), Type_Builtin_Name(objt));\n}\n\nstatic uint64_t Type_Hash(var self) {\n  const char* name = Type_Builtin_Name(self);\n  return hash_data(name, strlen(name));\n}\n\nstatic char* Type_C_Str(var self) {\n  return Type_Builtin_Name(self);\n}\n\nstatic void Type_Assign(var self, var obj) {\n  throw(ValueError, \"Type objects cannot be assigned.\");\n}\n\nstatic var Type_Copy(var self) {\n  return throw(ValueError, \"Type objects cannot be copied.\");\n}\n\nstatic int print_indent(var out, int pos, const char* str) {\n  pos = print_to(out, pos, \"    \");\n  while (*str) {\n    if (*str is '\\n') { pos = print_to(out, pos, \"\\n    \"); }\n    else { pos = print_to(out, pos, \"%c\", $I(*str)); }\n    str++;\n  }\n  return pos;\n}\n\nstatic int Type_Help_To(var self, var out, int pos) {\n  \n  struct Doc* doc = type_instance(self, Doc);\n  \n  if (doc is NULL) {\n    return print_to(out, pos, \"\\nNo Documentation Found for Type %s\\n\", self);\n  }\n  \n  pos = print_to(out, pos, \"\\n\");\n  pos = print_to(out, pos, \"# %s \", self);\n  \n  if (doc->brief) {\n    pos = print_to(out, pos, \" - %s\\n\\n\", $S((char*)doc->brief()));\n  }\n\n  if (doc->description) {\n    pos = print_to(out, pos, \"%s\\n\\n\", $S((char*)doc->description()));\n  }\n  \n  if (doc->definition) {\n    pos = print_to(out, pos, \"\\n### Definition\\n\\n\");\n    pos = print_indent(out, pos, doc->definition());\n    pos = print_to(out, pos, \"\\n\\n\");\n  }\n\n  if (doc->methods) {\n    pos = print_to(out, pos, \"\\n### Methods\\n\\n\");\n    struct Method* methods = doc->methods();\n    while (methods[0].name) {\n      pos = print_to(out, pos, \"__%s__\\n\\n\", $S((char*)methods[0].name));\n      pos = print_indent(out, pos, methods[0].definition);\n      pos = print_to(out, pos, \"\\n\\n%s\\n\\n\", $S((char*)methods[0].description));\n      methods++;\n    }\n  }\n    \n  if (doc->examples) {\n    pos = print_to(out, pos, \"\\n### Examples\\n\\n\");\n    struct Example* examples = doc->examples();\n    while (examples[0].name) {\n      pos = print_to(out, pos, \"__%s__\\n\\n\", $S((char*)examples[0].name));\n      pos = print_indent(out, pos, examples[0].body);\n      pos = print_to(out, pos, \"\\n\\n\");\n      examples++;\n    }\n    pos = print_to(out, pos, \"\\n\\n\");\n  }\n  \n  return pos;\n  \n}\n\nvar Type = CelloEmpty(Type,\n  Instance(Doc,\n    Type_Name, Type_Brief, Type_Description, NULL, Type_Examples, Type_Methods),\n  Instance(Assign,   Type_Assign),\n  Instance(Copy,     Type_Copy),\n  Instance(Alloc,    Type_Alloc, NULL),\n  Instance(New,      Type_New, NULL),\n  Instance(Cmp,      Type_Cmp),\n  Instance(Hash,     Type_Hash),\n  Instance(Show,     Type_Show, NULL),\n  Instance(C_Str,    Type_C_Str),\n  Instance(Help,     Type_Help_To));\n\nstatic var Type_Scan(var self, var cls) {\n \n #if CELLO_METHOD_CHECK == 1\n  if (type_of(self) isnt Type) {\n    return throw(TypeError, \"Method call got non type '%s'\", type_of(self));\n  }\n#endif\n  \n  struct Type* t;\n  \n  t = (struct Type*)self + CELLO_NBUILTINS; \n  while (t->name) { if (t->cls is cls) { return t->inst; } t++; }\n\n  t = (struct Type*)self + CELLO_NBUILTINS; \n  while (t->name) {\n    if (strcmp(t->name, Type_Builtin_Name(cls)) is 0) {\n      t->cls = cls;\n      return t->inst;\n    }\n    t++;\n  }\n  \n  return NULL;\n  \n}\n\nstatic bool Type_Implements(var self, var cls) {\n  return Type_Scan(self, cls) isnt NULL;\n}\n\nbool type_implements(var self, var cls) {\n  return Type_Implements(self, cls);\n}\n\nstatic var Type_Instance(var self, var cls);\n\nstatic var Type_Method_At_Offset(\n  var self, var cls, size_t offset, const char* method_name) {\n\n  var inst = Type_Instance(self, cls);\n  \n#if CELLO_METHOD_CHECK == 1\n  if (inst is NULL) {\n    return throw(ClassError,\n      \"Type '%s' does not implement class '%s'\",\n      self,  cls);\n  }\n#endif\n  \n#if CELLO_METHOD_CHECK == 1  \n  var meth = *((var*)(((char*)inst) + offset));\n\n  if (meth is NULL) {\n    return throw(ClassError,\n      \"Type '%s' implements class '%s' but not the method '%s' required\",\n      self,  cls, $(String, (char*)method_name));  \n  }\n#endif\n  \n  return inst;\n  \n}\n\nvar type_method_at_offset(\n  var self, var cls, size_t offset, const char* method_name) {\n  return Type_Method_At_Offset(self, cls, offset, method_name);  \n}\n\nstatic bool Type_Implements_Method_At_Offset(var self, var cls, size_t offset) {\n  var inst = Type_Scan(self, cls);\n  if (inst is NULL) { return false; }\n  var meth = *((var*)(((char*)inst) + offset));\n  if (meth is NULL) { return false; }\n  return true;\n}\n\nbool type_implements_method_at_offset(var self, var cls, size_t offset) {\n  return Type_Implements_Method_At_Offset(self, cls, offset);\n}\n\n/*\n**  Doing the lookup of a class instances is fairly fast\n**  but still too slow to be done inside a tight inner loop.\n**  This is because there could be any number of instances \n**  and they could be in any order, so each time a linear \n**  search must be done to find the correct instance.\n**\n**  We can remove the need for a linear search by placing\n**  some common class instances at known locations. These \n**  are the _Type Cache Entries_ and are located at some\n**  preallocated space at the beginning of every type object.\n**\n**  The only problem is that these instances are not filled \n**  at compile type, so we must dynamically fill them if they\n**  are empty. But this can be done with a standard call to \n**  `Type_Scan` the first time.\n**\n**  The main advantage of this method is that it gives the compiler\n**  a better chance of inlining the code up to the call of the \n**  instance function pointer, and removes the overhead \n**  associated with setting up the call to `Type_Scan` which is \n**  too complex a call to be effectively inlined.\n**\n*/\n\n#define Type_Cache_Entry(i, lit) \\\n  if (cls is lit) { \\\n    var inst = ((var*)self)[i]; \\\n    if (inst is NULL) { \\\n      inst = Type_Scan(self, lit); \\\n      ((var*)self)[i] = inst; \\\n    } \\\n    return inst; \\\n  }\n\nstatic var Type_Instance(var self, var cls) {\n\n#if CELLO_CACHE == 1\n  Type_Cache_Entry( 0, Size);    Type_Cache_Entry( 1, Alloc);\n  Type_Cache_Entry( 2, New);     Type_Cache_Entry( 3, Assign);\n  Type_Cache_Entry( 4, Cmp);     Type_Cache_Entry( 5, Mark);\n  Type_Cache_Entry( 6, Hash);    Type_Cache_Entry( 7, Len);\n  Type_Cache_Entry( 8, Iter);    Type_Cache_Entry( 9, Push);\n  Type_Cache_Entry(10, Concat);  Type_Cache_Entry(11, Get);\n  Type_Cache_Entry(12, C_Str);   Type_Cache_Entry(13, C_Int);\n  Type_Cache_Entry(14, C_Float); Type_Cache_Entry(15, Current);\n  Type_Cache_Entry(16, Cast);    Type_Cache_Entry(17, Pointer);\n#endif\n  \n  return Type_Scan(self, cls);\n}\n\n#undef Type_Cache_Entry\n\nvar type_instance(var self, var cls) {\n  return Type_Instance(self, cls);\n}\n  \nstatic var Type_Of(var self) {\n\n  /*\n  **  The type of a Type object is just `Type` again. But because `Type` is \n  **  extern it isn't a constant expression. This means it cannot be set at \n  **  compile time.\n  **\n  **  But we really want to be able to construct types statically. So by \n  **  convention at compile time the type of a Type object is set to `NULL`.\n  **  So if we access a statically allocated object and it tells us `NULL` \n  **  is the type, we assume the type is `Type`.\n  */\n\n#if CELLO_NULL_CHECK == 1  \n    if (self is NULL) {\n      return throw(ValueError, \"Received NULL as value to 'type_of'\");\n    }\n#endif\n  \n  struct Header* head = \n    (struct Header*)((char*)self - sizeof(struct Header));\n\n#if CELLO_MAGIC_CHECK == 1\n  if (head->magic is (var)0xDeadCe110) {\n    throw(ValueError, \"Pointer '%p' passed to 'type_of' \"\n      \"has bad magic number, it looks like it was already deallocated.\", self);    \n  }\n\n  if (head->magic isnt ((var)CELLO_MAGIC_NUM)) {\n    throw(ValueError, \"Pointer '%p' passed to 'type_of' \"\n      \"has bad magic number, perhaps it wasn't allocated by Cello.\", self);\n  }\n#endif\n  \n  if (head->type is NULL) { head->type = Type; }\n  \n  return head->type;\n\n}\n  \nvar type_of(var self) {\n  return Type_Of(self);\n}\n\nvar instance(var self, var cls) {\n  return Type_Instance(Type_Of(self), cls);\n}\n\nbool implements(var self, var cls) {  \n  return Type_Implements(Type_Of(self), cls);\n}\n\nvar method_at_offset(\n  var self, var cls, size_t offset, const char* method_name) { \n  return Type_Method_At_Offset(Type_Of(self), cls, offset, method_name);\n}\n\nbool implements_method_at_offset(var self, var cls, size_t offset) {\n  return Type_Implements_Method_At_Offset(Type_Of(self), cls, offset);\n}\n\nstatic const char* Size_Name(void) {\n  return \"Size\";\n}\n\nstatic const char* Size_Brief(void) {\n  return \"Type Size\";\n}\n\nstatic const char* Size_Description(void) {\n  return\n    \"The `Size` class is a very important class in Cello because it gives the \"\n    \"size in bytes you can expect an object of a given type to be. This is \"\n    \"used by many methods to allocate, assign, or compare various objects.\"\n    \"\\n\\n\"\n    \"By default this size is automatically found and recorded by the `Cello` \"\n    \"macro, but if the type does it's own allocation, or the size cannot be \"\n    \"found naturally then it may be necessary to override this method.\";\n}\n\nstatic const char* Size_Definition(void) {\n  return\n    \"struct Size {\\n\"\n    \"  size_t (*size)(void);\\n\"\n    \"};\\n\";\n}\n\nstatic struct Example* Size_Examples(void) {\n  \n  static struct Example examples[] = {\n    {\n      \"Usage\",\n      \"show($I(size(Int)));\\n\"\n      \"show($I(size(Float)));\\n\"\n      \"show($I(size(Array)));\\n\"\n    }, {NULL, NULL}\n  };\n\n  return examples;\n  \n}\n\nstatic struct Method* Size_Methods(void) {\n  \n  static struct Method methods[] = {\n    {\n      \"size\", \n      \"size_t size(var type);\",\n      \"Returns the associated size of a given `type` in bytes.\"\n    }, {NULL, NULL, NULL}\n  };\n  \n  return methods;\n}\n\nvar Size = Cello(Size, Instance(Doc, \n  Size_Name,       Size_Brief,    Size_Description, \n  Size_Definition, Size_Examples, Size_Methods));\n\nsize_t size(var type) {\n\n  struct Size* s = type_instance(type, Size);\n  if (s and s->size) {\n    return s->size();\n  }\n  \n  return Type_Builtin_Size(type);\n}\n  \n"
  },
  {
    "path": "tests/ptest.c",
    "content": "#include \"ptest.h\"\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <signal.h>\n#include <time.h>\n#if defined(CELLO_UNIX)\n# include <unistd.h>\n#endif\n\n/* Globals */\n\nenum {\n  MAX_NAME = 512\n};\n\nenum {\n  MAX_ERROR = 2048\n};\n\nenum {\n  MAX_TESTS = 2048\n};\n\nstatic int test_passing = 0;\nstatic int suite_passing = 0;\n\n/* Colors */\n\nenum {\n  BLACK   = 0,\n  BLUE    = 1,\n  GREEN   = 2,\n  AQUA    = 3,\n  RED     = 4,\n  PURPLE  = 5,\n  YELLOW  = 6,\n  WHITE   = 7,\n  GRAY    = 8,\n  \n  LIGHT_BLUE   = 9,\n  LIGHT_GREEN  = 10,\n  LIGHT_AQUA   = 11,\n  LIGHT_RED    = 12,\n  LIGHT_PURPLE = 13,\n  LIGHT_YELLOW = 14,\n  LIGHT_WHITE  = 15,\n  \n  DEFAULT      = 16,\n};\n\n#ifdef _WIN32\n\n#include <windows.h>\n\nstatic WORD defaults;\nstatic int defaults_loaded = 0;\n\nstatic void pt_color(int color) {\n  \n  HANDLE cnsl = GetStdHandle(STD_OUTPUT_HANDLE);\n  \n  if (!defaults_loaded) {\n    CONSOLE_SCREEN_BUFFER_INFO info;\n    GetConsoleScreenBufferInfo(cnsl, &info);\n    defaults = info.wAttributes;\n    defaults_loaded = 1;\n  }\n  \n  SetConsoleTextAttribute(cnsl, color == DEFAULT ? defaults : color);\n}\n\n#else\n\nstatic const char* colors[] = {\n  \"\\x1B[0m\",\n  \"\\x1B[34m\",\n  \"\\x1B[32m\",\n  \"\\x1B[36m\",\n  \"\\x1B[31m\",\n  \"\\x1B[35m\",\n  \"\\x1B[33m\",\n  \"\\x1B[37m\",\n  \"\",\n  \"\\x1B[34m\",\n  \"\\x1B[32m\",\n  \"\\x1B[36m\",\n  \"\\x1B[31m\",\n  \"\\x1B[35m\",\n  \"\\x1B[33m\",\n  \"\\x1B[37m\",\n  \"\\x1B[39m\",\n};\n\nstatic void pt_color(int color) {  \n  printf(\"%s\", colors[color]);\n}\n\n#endif\n\n/* Asserts */\n\nstatic int num_asserts = 0;\nstatic int num_assert_passes = 0;\nstatic int num_assert_fails  = 0;\n\nstatic char assert_err[MAX_ERROR];\nstatic char assert_err_buff[MAX_ERROR];\nstatic int assert_err_num = 0;\n\nvoid pt_assert_run(\n  int result, const char* expr, const char* func, const char* file, int line) {\n  \n  num_asserts++;\n  test_passing = test_passing && result;\n  \n  if (result) {\n    num_assert_passes++;\n  } else {\n    sprintf(assert_err_buff, \n      \"        %i. Assert [ %s ] (%s:%i)\\n\", \n      assert_err_num+1, expr, file, line );\n    strcat(assert_err, assert_err_buff);\n    assert_err_num++;\n    num_assert_fails++;\n  }\n  \n}\n\nstatic void ptest_signal(int sig) {\n\n  test_passing = 0;\n  \n  switch( sig ) {\n    case SIGFPE:  sprintf(assert_err_buff,\n      \"        %i. Division by Zero\\n\", assert_err_num+1);\n    break;\n    case SIGILL:  sprintf(assert_err_buff,\n      \"        %i. Illegal Instruction\\n\", assert_err_num+1);\n    break;\n    case SIGSEGV: sprintf(assert_err_buff,\n      \"        %i. Segmentation Fault\\n\", assert_err_num+1);\n    break;\n  }\n  \n  assert_err_num++;\n  strcat(assert_err, assert_err_buff);\n  \n  pt_color(RED); \n  printf(\"Failed! \\n\\n%s\\n\", assert_err);\n  pt_color(DEFAULT);\n  \n  puts(\"    | Stopping Execution.\");\n  fflush(stdout);\n  exit(0);\n  \n}\n\n/* Tests */\n\nstatic void pt_title_case(char* output, const char* input) {\n\n  int space = 1;\n  unsigned int i;\n  \n  strcpy(output, input);\n  \n  for(i = 0; i < strlen(output); i++) {\n\n    if (output[i] == '_' || output[i] == ' ') {\n      space = 1;\n      output[i] = ' ';\n      continue;\n    } \n    \n    if (space && output[i] >= 'a' && output[i] <= 'z') {\n      space = 0;\n      output[i] = output[i] - 32;\n      continue;\n    }\n    \n    space = 0;\n    \n  }\n  \n}\n\ntypedef struct {\n  void (*func)(void);\n  char name[MAX_NAME];\n  char suite[MAX_NAME];\n} test_t;\n\nstatic test_t tests[MAX_TESTS];\n\nstatic int num_tests = 0;\nstatic int num_tests_passes = 0;\nstatic int num_tests_fails  = 0;\n\nvoid pt_add_test(void (*func)(void), const char* name, const char* suite) {\n\n  test_t test;\n\n  if (num_tests == MAX_TESTS) {\n    printf(\"ERROR: Exceeded maximum test count of %i!\\n\", \n      MAX_TESTS); abort();\n  }\n  \n  if (strlen(name) >= MAX_NAME) {\n    printf(\"ERROR: Test name '%s' too long (Maximum is %i characters)\\n\", \n      name, MAX_NAME); abort();\n  }\n  \n  if (strlen(suite) >= MAX_NAME) {\n    printf(\"ERROR: Test suite '%s' too long (Maximum is %i characters)\\n\", \n      suite, MAX_NAME); abort();\n  }\n  \n  test.func = func;\n  pt_title_case(test.name, name);\n  pt_title_case(test.suite, suite);\n  \n  tests[num_tests] = test;\n  num_tests++;\n}\n\n/* Suites */\n\nstatic int num_suites = 0;\nstatic int num_suites_passes = 0;\nstatic int num_suites_fails  = 0;\n\nvoid pt_add_suite(void (*func)(void)) {\n  num_suites++;\n  func();\n}\n\n/* Running */\n\nstatic clock_t start, end;\nstatic char current_suite[MAX_NAME];\n\nint pt_run(void) {\n  \n  unsigned int i;\n  double total;\n  test_t test;\n\n  puts(\"\");\n  puts(\"    +-------------------------------------------+\");\n  puts(\"    | ptest          MicroTesting Magic for C   |\");\n  puts(\"    |                                           |\");\n  puts(\"    | http://github.com/orangeduck/ptest        |\");\n  puts(\"    |                                           |\");\n  puts(\"    | Daniel Holden (contact@theorangeduck.com) |\");\n  puts(\"    +-------------------------------------------+\");\n  \n  signal(SIGFPE,  ptest_signal);\n  signal(SIGILL,  ptest_signal);\n  signal(SIGSEGV, ptest_signal);\n  \n  start = clock();\n  strcpy(current_suite, \"\");\n  \n  for(i = 0; i < num_tests; i++) {\n\n    test = tests[i];\n    \n    /* Check for transition to a new suite */\n    if (strcmp(test.suite, current_suite)) {\n\n      /* Don't increment any counter for first entrance */\n      if (strcmp(current_suite, \"\")) {\n        if (suite_passing) {\n          num_suites_passes++;\n        } else {\n          num_suites_fails++;\n        }\n      }\n    \n      suite_passing = 1;\n      strcpy(current_suite, test.suite);\n      printf(\"\\n\\n  ===== %s =====\\n\\n\", current_suite);\n    }\n    \n    /* Run Test */\n    \n    test_passing = 1;\n    strcpy(assert_err, \"\");\n    strcpy(assert_err_buff, \"\");\n    assert_err_num = 0;\n    printf(\"    | %s ... \", test.name);\n    fflush(stdout);\n    \n    test.func();\n    \n    suite_passing = suite_passing && test_passing;\n    \n    if (test_passing) {\n      num_tests_passes++;\n      pt_color(GREEN);\n      puts(\"Passed!\");\n      pt_color(DEFAULT);\n    } else {\n      num_tests_fails++;\n      pt_color(RED); \n      printf(\"Failed! \\n\\n%s\\n\", assert_err);\n      pt_color(DEFAULT);\n    }\n    \n  }\n  \n  if (suite_passing) {\n    num_suites_passes++;\n  } else {\n    num_suites_fails++;\n  }\n  \n  end = clock();\n  \n  puts(\"\");\n  puts(\"  +---------------------------------------------------+\");\n  puts(\"  |                      Summary                      |\");\n  puts(\"  +---------++------------+-------------+-------------+\");\n  \n  printf(\"  | Suites  ||\");\n  pt_color(YELLOW);  printf(\" Total %4d \",  num_suites);        \n  pt_color(DEFAULT); putchar('|');\n  pt_color(GREEN);   printf(\" Passed %4d \", num_suites_passes); \n  pt_color(DEFAULT); putchar('|');\n  pt_color(RED);     printf(\" Failed %4d \", num_suites_fails);  \n  pt_color(DEFAULT); puts(\"|\");\n  \n  printf(\"  | Tests   ||\");\n  pt_color(YELLOW);  printf(\" Total %4d \",  num_tests);         \n  pt_color(DEFAULT); putchar('|');\n  pt_color(GREEN);   printf(\" Passed %4d \", num_tests_passes);  \n  pt_color(DEFAULT); putchar('|');\n  pt_color(RED);     printf(\" Failed %4d \", num_tests_fails);   \n  pt_color(DEFAULT); puts(\"|\");\n  \n  printf(\"  | Asserts ||\");\n  pt_color(YELLOW);  printf(\" Total %4d \",  num_asserts);       \n  pt_color(DEFAULT); putchar('|');\n  pt_color(GREEN);   printf(\" Passed %4d \", num_assert_passes); \n  pt_color(DEFAULT); putchar('|');\n  pt_color(RED);     printf(\" Failed %4d \", num_assert_fails);  \n  pt_color(DEFAULT); puts(\"|\");\n  \n  puts(\"  +---------++------------+-------------+-------------+\");\n  puts(\"\");\n  \n  total = (double)(end - start) / CLOCKS_PER_SEC;\n  \n  printf(\"      Total Running Time: %0.3fs\\n\\n\", total);\n  \n  if (num_suites_fails > 0) { return 1; } else { return 0; }\n}\n"
  },
  {
    "path": "tests/ptest.h",
    "content": "#ifndef ptest_h\n#define ptest_h\n\n#include <string.h>\n\n#define PT_SUITE(name) void name(void)\n\n#define PT_FUNC(name) static void name(void)\n#define PT_REG(name) pt_add_test(name, #name, __func__)\n#define PT_TEST(name) auto void name(void); PT_REG(name); void name(void)\n\n#define PT_ASSERT(expr) pt_assert_run((int)((expr) != 0), #expr, __func__, __FILE__, __LINE__)\n#define PT_ASSERT_STR_EQ(fst, snd) pt_assert_run(strcmp(fst, snd) == 0, \"strcmp( \" #fst \", \" #snd \" ) == 0\", __func__, __FILE__, __LINE__)\n\nvoid pt_assert_run(int result, const char* expr, const char* func, const char* file, int line);\n\nvoid pt_add_test(void (*func)(void), const char* name, const char* suite);\nvoid pt_add_suite(void (*func)(void));\nint pt_run(void);\n\n#endif"
  },
  {
    "path": "tests/test.c",
    "content": "#include \"../include/Cello.h\"\n#include \"ptest.h\"\n\n/* Array */\n\nPT_FUNC(test_array_new) {\n  \n  var a0 = new(Array, Int, $I(1), $I(5), $I(10));\n  var a1 = new(Array, Float, $F(1.1), $F(2.2));\n  var a2 = copy(a0);\n  \n  PT_ASSERT(a0);\n  PT_ASSERT(a1);\n  PT_ASSERT(a2);\n  \n  PT_ASSERT(a0 isnt a1);\n  PT_ASSERT(a0 isnt a2);\n  PT_ASSERT(a1 isnt a2);\n\n  PT_ASSERT( eq(get(a0, $I(0)), $I(1)) );\n  PT_ASSERT( eq(get(a1, $I(0)), $F(1.1)) );\n  PT_ASSERT( eq(get(a2, $I(0)), $I(1)) );\n \n  del(a0);\n  del(a1);\n  del(a2);\n  \n}\n\nPT_FUNC(test_array_assign) {\n  \n  var a0 = new(Array, Int, $I(1), $I(2), $I(3));\n  var l0 = new(List, Int, $I(4), $I(5), $I(6), $I(7));\n  \n  PT_ASSERT(eq(get(a0, $I(0)), $I(1)));\n  PT_ASSERT(eq(get(a0, $I(1)), $I(2)));\n  PT_ASSERT(eq(get(a0, $I(2)), $I(3)));\n  \n  assign(a0, l0);\n  \n  PT_ASSERT(eq(get(a0, $I(0)), $I(4)));\n  PT_ASSERT(eq(get(a0, $I(1)), $I(5)));\n  PT_ASSERT(eq(get(a0, $I(2)), $I(6)));\n  PT_ASSERT(eq(get(a0, $I(3)), $I(7)));\n  \n  assign(a0, range($I(5)));\n  \n  PT_ASSERT(eq(get(a0, $I(0)), $I(0)));\n  PT_ASSERT(eq(get(a0, $I(1)), $I(1)));\n  PT_ASSERT(eq(get(a0, $I(2)), $I(2)));\n  PT_ASSERT(eq(get(a0, $I(3)), $I(3)));\n  PT_ASSERT(eq(get(a0, $I(4)), $I(4)));\n  \n  del(a0);\n  del(l0);\n  \n}\n\nPT_FUNC(test_array_concat) {\n  \n  var a0 = new(Array, Int, $I(1), $I(2), $I(3));\n  var a1 = new(Array, Int, $I(4), $I(5), $I(6));\n  \n  concat(a0, a1);\n  \n  PT_ASSERT(eq(get(a0, $I(0)), $I(1)));\n  PT_ASSERT(eq(get(a0, $I(1)), $I(2)));\n  PT_ASSERT(eq(get(a0, $I(2)), $I(3)));\n  PT_ASSERT(eq(get(a0, $I(3)), $I(4)));\n  PT_ASSERT(eq(get(a0, $I(4)), $I(5)));\n  PT_ASSERT(eq(get(a0, $I(5)), $I(6)));\n  \n  append(a0, $I(10));\n  \n  PT_ASSERT(eq(get(a0, $I(6)), $I(10)));\n  \n  del(a0); del(a1);\n  \n}\n\nPT_FUNC(test_array_cmp) {\n  \n  var a0 = new(Array, Int, $I(1), $I(5), $I(10));\n  var a1 = new(Array, Int, $I(1), $I(5), $I(10));\n  var a2 = new(Array, Int, $I(2), $I(5), $I(10));\n  \n  PT_ASSERT(eq(a0, a1));\n  PT_ASSERT(neq(a0, a2));\n  PT_ASSERT(gt(a2, a1));\n  PT_ASSERT(lt(a1, a2));\n  \n  del(a0); del(a1); del(a2);\n  \n}\n\nPT_FUNC(test_array_get) {\n  \n  var a0 = new(Array, Int, $I(1), $I(5), $I(10));\n  \n  PT_ASSERT(len(a0) is 3);\n  PT_ASSERT(mem(a0, $I(1)));\n  PT_ASSERT(mem(a0, $I(5)));\n  \n  rem(a0, $I(5));\n  \n  PT_ASSERT(len(a0) is 2);\n  PT_ASSERT(mem(a0, $I(1)));\n  PT_ASSERT(not mem(a0, $I(5)));\n  \n  resize(a0, 0);\n  \n  PT_ASSERT(len(a0) is 0);\n  PT_ASSERT(not mem(a0, $I(1)));\n  \n  del(a0);\n\n  var a1 = new(Array, String, \n    $S(\"Hello\"), $S(\"There\"), $S(\"People\"));\n  \n  PT_ASSERT( eq(get(a1, $I(0)), $S(\"Hello\")) );\n  PT_ASSERT( eq(get(a1, $I(1)), $S(\"There\")) );\n  PT_ASSERT( eq(get(a1, $I(2)), $S(\"People\")) );\n  \n  PT_ASSERT( eq(get(a1, $I(-1)), $S(\"People\")) );\n  PT_ASSERT( eq(get(a1, $I(-2)), $S(\"There\")) );\n  PT_ASSERT( eq(get(a1, $I(-3)), $S(\"Hello\")) );\n  \n  set(a1, $I(1), $S(\"Blah\"));\n  \n  PT_ASSERT( eq(get(a1, $I(0)), $S(\"Hello\")) );\n  PT_ASSERT( eq(get(a1, $I(1)), $S(\"Blah\")) );\n  PT_ASSERT( eq(get(a1, $I(2)), $S(\"People\")) );\n  \n  set(a1, $I(0), $S(\"Foo\"));\n  set(a1, $I(2), $S(\"Bar\"));\n  \n  PT_ASSERT( eq(get(a1, $I(0)), $S(\"Foo\")) );\n  PT_ASSERT( eq(get(a1, $I(1)), $S(\"Blah\")) );\n  PT_ASSERT( eq(get(a1, $I(2)), $S(\"Bar\")) );\n  \n  del(a1);\n  \n}\n\nPT_FUNC(test_array_hash) {\n  \n  var a0 = new(Array, String, $S(\"Hello\"), $S(\"World\"));\n  \n  PT_ASSERT(hash(a0) is (hash($S(\"Hello\")) ^ hash($S(\"World\"))));\n  \n  del(a0);\n  \n}\n\nPT_FUNC(test_array_iter) {\n  \n  var a0 = new(Array, Int);\n  var a1 = new(Array, Float);\n  \n  PT_ASSERT(iter_type(a0) is Int);\n  PT_ASSERT(iter_type(a1) is Float);\n  \n  del(a0); del(a1);\n  \n  a0 = new(Array, String, \n    $S(\"Hello\"), $S(\"There\"), $S(\"People\"));\n  \n  int counter = 0;\n  \n  foreach(item in a0) {\n    \n    switch(counter) {\n      case 0: PT_ASSERT( eq(item, $S(\"Hello\")) ); break;\n      case 1: PT_ASSERT( eq(item, $S(\"There\")) ); break;\n      case 2: PT_ASSERT( eq(item, $S(\"People\")) ); break;\n    }\n    \n    counter++;\n  }\n  \n  PT_ASSERT(counter is 3);\n  \n  counter = 0;\n  \n  foreach(item0 in a0) {\n    foreach(item1 in a0) {\n      counter++;\n    }\n  }\n  \n  PT_ASSERT(counter is 9);\n  del(a0);\n  \n}\n\nPT_FUNC(test_array_len) {\n  \n  var a0 = new(Array, String, $S(\"Hello\"), $S(\"World\"));\n  \n  PT_ASSERT(len(a0) is 2);\n  \n  append(a0, $S(\"!\"));\n  \n  PT_ASSERT(len(a0) is 3);\n  \n  resize(a0, 0);\n  \n  PT_ASSERT(len(a0) is 0);\n  \n  del(a0);\n  \n}\n\nPT_FUNC(test_array_push) {\n  \n  var a0 = new(Array, Int);\n  \n  PT_ASSERT(len(a0) is 0);\n  \n  push(a0, $I(1));\n  \n  PT_ASSERT(len(a0) is 1);\n  PT_ASSERT( eq(get(a0, $I(0)), $I(1)) );\n  \n  push(a0, $I(3));\n  \n  PT_ASSERT(len(a0) is 2);\n  PT_ASSERT( eq(get(a0, $I(0)), $I(1)) );\n  PT_ASSERT( eq(get(a0, $I(1)), $I(3)) );\n  \n  push_at(a0, $I(10), $I(0));\n  \n  PT_ASSERT(len(a0) is 3);\n  PT_ASSERT( eq(get(a0, $I(0)), $I(10)) );\n  PT_ASSERT( eq(get(a0, $I(1)), $I(1)) );\n  PT_ASSERT( eq(get(a0, $I(2)), $I(3)) );\n  \n  push_at(a0, $I(20), $I(1));\n  \n  PT_ASSERT(len(a0) is 4);\n  PT_ASSERT( eq(get(a0, $I(0)), $I(10)) );\n  PT_ASSERT( eq(get(a0, $I(1)), $I(20)) );\n  PT_ASSERT( eq(get(a0, $I(2)), $I(1)) );\n  PT_ASSERT( eq(get(a0, $I(3)), $I(3)) );\n  \n  pop_at(a0, $I(2));\n  \n  PT_ASSERT(len(a0) is 3);\n  PT_ASSERT( eq(get(a0, $I(0)), $I(10)) );\n  PT_ASSERT( eq(get(a0, $I(1)), $I(20)) );\n  PT_ASSERT( eq(get(a0, $I(2)), $I(3)) );\n  \n  pop_at(a0, $I(0));\n  \n  PT_ASSERT(len(a0) is 2);\n  PT_ASSERT( eq(get(a0, $I(0)), $I(20)) );\n  PT_ASSERT( eq(get(a0, $I(1)), $I(3)) );\n  \n  pop(a0);\n  \n  PT_ASSERT(len(a0) is 1);\n  PT_ASSERT( eq(get(a0, $I(0)), $I(20)) );\n  \n  pop(a0);\n  \n  PT_ASSERT(len(a0) is 0);\n  \n  del(a0);\n  \n}\n\nPT_FUNC(test_array_resize) {\n  \n  var a0 = new(Array, Int);\n  resize(a0, 1000);\n  del(a0);\n  \n  a0 = new(Array, Int, $I(1), $I(2), $I(3));\n  \n  PT_ASSERT(len(a0) is 3);\n  \n  resize(a0, 0);\n  \n  PT_ASSERT(len(a0) is 0);\n  PT_ASSERT(empty(a0));\n  \n  del(a0);\n  \n}\n\nPT_FUNC(test_array_show) {\n  \n  var a0 = new(Array, Int, $I(1), $I(5), $I(9));\n  var s0 = new(String);\n  \n  show_to(a0, s0, 0);\n  \n  del(a0); del(s0);\n}\n\nPT_FUNC(test_array_sort) {\n  \n  var a0 = new(Array, Int, $I(100), $I(1233), $I(1), $I(2312), $I(21));\n  var a1 = new(Array, Int, $I(1), $I(21), $I(100), $I(1233), $I(2312));\n  var a2 = new(Array, Int, $I(2312), $I(1233), $I(100), $I(21), $I(1));\n  \n  var a3 = copy(a0);\n  var a4 = copy(a0);\n  \n  sort(a3);\n  sort_by(a4, gt);\n  PT_ASSERT(eq(a3, a1));\n  PT_ASSERT(eq(a4, a2));\n  \n  del(a0); del(a1); del(a2); del(a3); del(a4);\n  \n  var a5 = new(Array, String, $S(\"a\"), $S(\"b\"), $S(\"c\"), $S(\"d\"), $S(\"e\"));\n  var a6 = new(Array, String, $S(\"c\"), $S(\"b\"), $S(\"e\"), $S(\"a\"), $S(\"d\"));\n  \n  PT_ASSERT(neq(a5, a6));\n  sort(a6);\n  PT_ASSERT(eq(a5, a6));\n  \n  del(a5); del(a6);\n  \n}\n\nPT_SUITE(suite_array) {\n  PT_REG(test_array_new);\n  PT_REG(test_array_assign);\n  PT_REG(test_array_concat);\n  PT_REG(test_array_cmp);\n  PT_REG(test_array_get);\n  PT_REG(test_array_hash);\n  PT_REG(test_array_iter);\n  PT_REG(test_array_len);\n  PT_REG(test_array_push);\n  PT_REG(test_array_resize);\n  PT_REG(test_array_show);\n  PT_REG(test_array_sort);\n}\n\n/* Box */\n\nPT_FUNC(test_box_new) {\n  \n  var s0 = new(String, $S(\"Hello World!\"));\n  \n  var b1 = new(Box, s0);\n  \n  PT_ASSERT(b1);\n  PT_ASSERT(deref(b1) is s0);\n  \n  del(b1);\n  \n}\n\nPT_FUNC(test_box_assign) {\n  \n  var s0 = new(String, $S(\"Hello World!\"));\n  var b0 = assign($(Box, NULL), s0);\n  \n  PT_ASSERT(b0);\n  PT_ASSERT(deref(b0) is s0);\n  \n  destruct(b0);\n  \n}\n\nPT_FUNC(test_box_pointer) {\n  \n  var s0 = new(String, $S(\"Hello World 1!\"));\n  var s1 = new(String, $S(\"Hello World 2!\"));\n\n  var b0 = $(Box, s0);\n  var b1 = $(Box, s1);\n  \n  PT_ASSERT(deref(b0) is s0);\n  PT_ASSERT(deref(b1) is s1);\n  \n  del(s0); del(s1);\n  \n}\n\nPT_FUNC(test_box_show) {\n  \n  var b0 = new(Box, new(Int, $I(1)));\n  var s0 = new(String);\n  \n  show_to(b0, s0, 0);\n  \n  del(b0); del(s0);\n  \n}\n\nPT_SUITE(suite_box) {\n  PT_REG(test_box_new);\n  PT_REG(test_box_assign);\n  PT_REG(test_box_pointer);\n  PT_REG(test_box_show);\n}\n\n/* File */\n\nPT_FUNC(test_file_format) {\n  \n  var f0 = $(File, NULL);\n  \n  sopen(f0, $S(\"./tests/test.txt\"), $S(\"w\"));\n  format_to(f0, 0, \"%s\", \"Hello World!\");\n  sclose(f0);  \n  \n}\n\nPT_FUNC(test_file_new) {\n  \n  var f0 = new(File, $S(\"./tests/test.bin\"), $S(\"w\")); \n  var f1 = $(File, NULL);\n  \n  PT_ASSERT(f0);\n  PT_ASSERT(f1);\n  \n  PT_ASSERT(f0 isnt f1);\n  \n  del(f0);\n  \n}\n\nPT_FUNC(test_file_start) {\n  \n  struct File* file = new(File, $S(\"./tests/test.bin\"), $S(\"w\"));\n  with (f0 in file) {\n    PT_ASSERT(f0);\n  }; \n     \n  PT_ASSERT(file->file is NULL);\n  \n  del(file);\n  \n}\n\nPT_FUNC(test_file_stream) {\n  \n  static char testoutput1[] = \"This is a test\\n\";\n  static char testoutput2[] = \"This is a sample\\n\";\n  static char testinput[512];\n  \n  var f0 = $(File, NULL);\n  \n  sopen(f0, $S(\"./tests/test.txt\"), $S(\"w\"));\n  swrite(f0, testoutput1, sizeof(testoutput1));\n  sclose(f0);  \n  \n  sopen(f0, $S(\"./tests/test.txt\"), $S(\"r\"));\n  sread(f0, testinput, sizeof(testoutput1));\n  sclose(f0);\n  \n  PT_ASSERT_STR_EQ(testinput, testoutput1);\n  \n}\n\nPT_SUITE(suite_file) {\n  PT_REG(test_file_format);\n  PT_REG(test_file_new);\n  PT_REG(test_file_start);\n  PT_REG(test_file_stream);\n}\n\n/* Float */\n\nPT_FUNC(test_float_assign) {\n  \n  var float0 = $F(1.0);\n  var float1 = new(Float, $F(24.313));\n  var float2 = copy(float0);\n  \n  PT_ASSERT(float0);\n  PT_ASSERT(float1);\n  PT_ASSERT(float2);\n  \n  PT_ASSERT(c_float(float0) is 1.0);\n  PT_ASSERT(c_float(float1) is 24.313);\n  PT_ASSERT(c_float(float2) is 1.0);\n  \n  assign(float2, float1);\n  \n  PT_ASSERT( not(float2 is float1) );\n  PT_ASSERT(c_float(float2) is 24.313);\n  \n  del(float1);\n  del(float2);\n  \n}\n\nPT_FUNC(test_float_c_float) {\n  \n  PT_ASSERT(c_float($F(      10.0)) is       10.0);\n  PT_ASSERT(c_float($F(  531.1231)) is   531.1231);\n  PT_ASSERT(c_float($F(21312.4535)) is 21312.4535);\n  PT_ASSERT(c_float($F(   1352.21)) is    1352.21);\n  PT_ASSERT(c_float($F(   676.342)) is    676.342);\n  \n}\n\nPT_FUNC(test_float_cmp) {\n  \n  PT_ASSERT( gt($F(5.0),    $F(0.0)) );\n  PT_ASSERT( gt($F(51.33), $F(2.32)) );\n  PT_ASSERT( lt($F(23.32), $F(99.92)) );\n  PT_ASSERT( lt($F(31.0),   $F(32.3)) );\n  PT_ASSERT( eq($F(1.11),  $F(1.11)) );\n  PT_ASSERT( eq($F(23.55),   $F(23.55)) );\n  PT_ASSERT( ge($F(2.89),  $F(2.89)) );\n  PT_ASSERT( ge($F(87.34), $F(2.89)) );\n  PT_ASSERT( le($F(16.6),  $F(16.6)) );\n  PT_ASSERT( le($F(1.1),   $F(88.8)) );\n  PT_ASSERT( neq($F(3.24), $F(6.85)) );\n  PT_ASSERT( neq($F(3.4),  $F(5.4)) );\n  \n}\n\nunion type_interp {\n  double c_float;\n  int64_t c_int;\n};\n\nPT_FUNC(test_float_hash) {\n  \n  union type_interp r0 = { 34.0 };\n  union type_interp r1 = { 11.0 };\n  union type_interp r2 = { 0.6 };\n  union type_interp r3 = { 82.13 };\n  \n  PT_ASSERT( hash($F(34.0)) is r0.c_int );\n  PT_ASSERT( hash($F(11.0)) is r1.c_int );\n  PT_ASSERT( hash($F(0.6)) is r2.c_int );\n  PT_ASSERT( hash($F(82.13)) is r3.c_int );\n  \n}\n\nPT_FUNC(test_float_show) {\n  \n  var s0 = new(String);\n  \n  show_to($F(213.12), s0, 0);\n  PT_ASSERT_STR_EQ(c_str(s0),  \"213.120000\");\n  \n  show_to($F(3532.11), s0, 0);\n  PT_ASSERT_STR_EQ(c_str(s0), \"3532.110000\");\n  \n  show_to($F(1023.1), s0, 0);\n  PT_ASSERT_STR_EQ(c_str(s0), \"1023.100000\");\n  \n  del(s0);\n  \n}\n\nPT_SUITE(suite_float) {\n  PT_REG(test_float_assign);\n  PT_REG(test_float_c_float);\n  PT_REG(test_float_cmp);\n  PT_REG(test_float_hash);\n  PT_REG(test_float_show);\n}\n\n/* Filter */\n\nvar greater_than_two(var x) {\n  return c_int(x) > 2 ? x : NULL;\n}\n\nvar mem_hello(var x) {\n  return mem(x, $S(\"Hello\")) ? x : NULL;\n}\n\nPT_FUNC(test_filter_get) {\n  \n  var x = new(Array, Int, $I(0), $I(5), $I(2), $I(9));\n  var f = filter(x, $(Function, greater_than_two));\n  \n  PT_ASSERT(mem(f, $I(5)));\n  PT_ASSERT(mem(f, $I(9)));\n  PT_ASSERT(not mem(f, $I(0)));\n  PT_ASSERT(not mem(f, $I(1)));\n  \n  del(x);\n  \n}\n\nPT_FUNC(test_filter_iter) {\n  \n  var x = new(Tuple, $S(\"Hello World\"), $S(\"Hello Dan\"), $S(\"Bonjour\"));\n\n  var y = new(Tuple);\n  foreach (item in filter(x, $(Function, mem_hello))) {\n    push(y, item);\n  }\n  \n  PT_ASSERT(eq(get(y, $I(0)), $S(\"Hello World\")));\n  PT_ASSERT(eq(get(y, $I(1)), $S(\"Hello Dan\")));\n  \n  del(x); del(y);\n  \n}\n\nPT_FUNC(test_filter_new) {\n  \n  var x = new(Array, Int, $I(0), $I(5), $I(2), $I(9));\n  var f = new(Filter, x, $(Function, greater_than_two));\n  \n  PT_ASSERT(mem(f, $I(5)));\n  PT_ASSERT(mem(f, $I(9)));\n  PT_ASSERT(not mem(f, $I(0)));\n  PT_ASSERT(not mem(f, $I(1)));\n  \n  del(x);\n  del(f);\n  \n}\n\nPT_SUITE(suite_filter) {\n  PT_REG(test_filter_get);\n  PT_REG(test_filter_iter);\n  PT_REG(test_filter_new);\n}\n\n/* Function */\n\nvar return_fst(var args) {\n  return get(args, $I(0));\n}\n\nvar return_snd(var args) {\n  return get(args, $I(1));\n}\n\n\nPT_FUNC(test_function_call) {\n  \n  PT_ASSERT(eq(call($(Function, return_fst), $I(100), $I(200)), $I(100)));\n  PT_ASSERT(eq(call($(Function, return_snd), $I(100), $I(200)), $I(200)));\n  \n}\n\nPT_SUITE(suite_function) {\n  PT_REG(test_function_call);\n}\n\n/* Int */\n\nPT_FUNC(test_int_assign) {\n  \n  var int0 = $I(1);\n  var int1 = new(Int, $I(24313));\n  var int2 = copy(int0);\n  \n  PT_ASSERT(int0);\n  PT_ASSERT(int1);\n  PT_ASSERT(int2);\n  \n  PT_ASSERT(c_int(int0) is 1);\n  PT_ASSERT(c_int(int1) is 24313);\n  PT_ASSERT(c_int(int2) is 1);\n  \n  assign(int2, int1);\n  \n  PT_ASSERT( not(int2 is int1) );\n  PT_ASSERT(c_int(int2) is 24313);\n  \n  del(int1);\n  del(int2);\n  \n}\n\nPT_FUNC(test_int_c_int) {\n  \n  PT_ASSERT( c_int($I(34)) is 34 );\n  PT_ASSERT( c_int($I(11)) is 11 );\n  PT_ASSERT( c_int($I(06)) is 06 );\n  PT_ASSERT( c_int($I(8213)) is 8213 );\n  \n}\n\nPT_FUNC(test_int_cmp) {\n  \n  PT_ASSERT( gt($I(5),    $I(0)) );\n  PT_ASSERT( gt($I(5133), $I(232)) );\n  PT_ASSERT( lt($I(2332), $I(9992)) );\n  PT_ASSERT( lt($I(34),   $I(323)) );\n  PT_ASSERT( eq($I(111),  $I(111)) );\n  PT_ASSERT( eq($I(23),   $I(23)) );\n  PT_ASSERT( ge($I(289),  $I(289)) );\n  PT_ASSERT( ge($I(8734), $I(289)) );\n  PT_ASSERT( le($I(166),  $I(166)) );\n  PT_ASSERT( le($I(11),   $I(888)) );\n  PT_ASSERT( neq($I(324), $I(685)) );\n  PT_ASSERT( neq($I(34),  $I(54)) );\n  \n}\n\nPT_FUNC(test_int_hash) {\n  \n  PT_ASSERT( hash($I(34)) is 34 );\n  PT_ASSERT( hash($I(11)) is 11 );\n  PT_ASSERT( hash($I(06)) is 06 );\n  PT_ASSERT( hash($I(8213)) is 8213 );\n  \n}\n\nPT_FUNC(test_int_show) {\n  \n  var s0 = new(String);\n  \n  show_to($I(34), s0, 0);\n  PT_ASSERT_STR_EQ(c_str(s0), \"34\");\n  \n  show_to($I(06), s0, 0);\n  PT_ASSERT_STR_EQ(c_str(s0), \"6\");\n  \n  show_to($I(8213), s0, 0);\n  PT_ASSERT_STR_EQ(c_str(s0), \"8213\");\n  \n  del(s0);\n  \n}\n\nPT_SUITE(suite_int) {\n  PT_REG(test_int_assign);\n  PT_REG(test_int_c_int);\n  PT_REG(test_int_cmp);\n  PT_REG(test_int_hash);\n  PT_REG(test_int_show);\n}\n\n/* List */\n\nPT_FUNC(test_list_new) {\n  \n  var l0 = new(List, Int, $I(1), $I(5), $I(10));\n  var l1 = new(List, Float, $F(1.1), $F(2.2));\n  var l2 = copy(l0);\n  \n  PT_ASSERT(l0);\n  PT_ASSERT(l1);\n  PT_ASSERT(l2);\n  \n  PT_ASSERT(l0 isnt l1);\n  PT_ASSERT(l0 isnt l2);\n  PT_ASSERT(l1 isnt l2);\n\n  PT_ASSERT( eq(get(l0, $I(0)), $I(1)) );\n  PT_ASSERT( eq(get(l1, $I(0)), $F(1.1)) );\n  PT_ASSERT( eq(get(l2, $I(0)), $I(1)) );\n \n  del(l0);\n  del(l1);\n  del(l2);\n  \n}\n\nPT_FUNC(test_list_assign) {\n  \n  var l0 = new(List, Int, $I(1), $I(2), $I(3));\n  var a0 = new(Array, Int, $I(4), $I(5), $I(6), $I(7));\n  \n  PT_ASSERT(eq(get(l0, $I(0)), $I(1)));\n  PT_ASSERT(eq(get(l0, $I(1)), $I(2)));\n  PT_ASSERT(eq(get(l0, $I(2)), $I(3)));\n  \n  assign(l0, a0);\n  \n  PT_ASSERT(eq(get(l0, $I(0)), $I(4)));\n  PT_ASSERT(eq(get(l0, $I(1)), $I(5)));\n  PT_ASSERT(eq(get(l0, $I(2)), $I(6)));\n  PT_ASSERT(eq(get(l0, $I(3)), $I(7)));\n  \n  assign(l0, range($I(5)));\n  \n  PT_ASSERT(eq(get(l0, $I(0)), $I(0)));\n  PT_ASSERT(eq(get(l0, $I(1)), $I(1)));\n  PT_ASSERT(eq(get(l0, $I(2)), $I(2)));\n  PT_ASSERT(eq(get(l0, $I(3)), $I(3)));\n  PT_ASSERT(eq(get(l0, $I(4)), $I(4)));\n  \n  del(l0);\n  del(a0);\n  \n}\n\nPT_FUNC(test_list_concat) {\n  \n  var l0 = new(List, Int, $I(1), $I(2), $I(3));\n  var l1 = new(List, Int, $I(4), $I(5), $I(6));\n  \n  concat(l0, l1);\n  \n  PT_ASSERT(eq(get(l0, $I(0)), $I(1)));\n  PT_ASSERT(eq(get(l0, $I(1)), $I(2)));\n  PT_ASSERT(eq(get(l0, $I(2)), $I(3)));\n  PT_ASSERT(eq(get(l0, $I(3)), $I(4)));\n  PT_ASSERT(eq(get(l0, $I(4)), $I(5)));\n  PT_ASSERT(eq(get(l0, $I(5)), $I(6)));\n  \n  append(l0, $I(10));\n  \n  PT_ASSERT(eq(get(l0, $I(6)), $I(10)));\n  \n  del(l0); del(l1);\n  \n}\n\nPT_FUNC(test_list_cmp) {\n    \n  var a0 = new(Array, Int, $I(1), $I(5), $I(10));\n  var a1 = new(Array, Int, $I(1), $I(5), $I(10));\n  var a2 = new(Array, Int, $I(2), $I(5), $I(10));\n  \n  PT_ASSERT(eq(a0, a1));\n  PT_ASSERT(neq(a0, a2));\n  PT_ASSERT(gt(a2, a1));\n  PT_ASSERT(lt(a1, a2));\n  \n  del(a0); del(a1); del(a2);\n  \n}\n\nPT_FUNC(test_list_get) {\n  \n  var l0 = new(List, Int, $I(1), $I(5), $I(10));\n  \n  PT_ASSERT(len(l0) is 3);\n  PT_ASSERT(mem(l0, $I(1)));\n  PT_ASSERT(mem(l0, $I(5)));\n  \n  rem(l0, $I(5));\n  \n  PT_ASSERT(len(l0) is 2);\n  PT_ASSERT(mem(l0, $I(1)));\n  PT_ASSERT(not mem(l0, $I(5)));\n  \n  resize(l0, 0);\n  \n  PT_ASSERT(len(l0) is 0);\n  PT_ASSERT(not mem(l0, $I(1)));\n  \n  del(l0);\n\n  var l1 = new(List, String, \n    $S(\"Hello\"), $S(\"There\"), $S(\"People\"));\n  \n  PT_ASSERT( eq(get(l1, $I(0)), $S(\"Hello\")) );\n  PT_ASSERT( eq(get(l1, $I(1)), $S(\"There\")) );\n  PT_ASSERT( eq(get(l1, $I(2)), $S(\"People\")) );\n  \n  PT_ASSERT( eq(get(l1, $I(-1)), $S(\"People\")) );\n  PT_ASSERT( eq(get(l1, $I(-2)), $S(\"There\")) );\n  PT_ASSERT( eq(get(l1, $I(-3)), $S(\"Hello\")) );\n  \n  set(l1, $I(1), $S(\"Blah\"));\n  \n  PT_ASSERT( eq(get(l1, $I(0)), $S(\"Hello\")) );\n  PT_ASSERT( eq(get(l1, $I(1)), $S(\"Blah\")) );\n  PT_ASSERT( eq(get(l1, $I(2)), $S(\"People\")) );\n  \n  set(l1, $I(0), $S(\"Foo\"));\n  set(l1, $I(2), $S(\"Bar\"));\n  \n  PT_ASSERT( eq(get(l1, $I(0)), $S(\"Foo\")) );\n  PT_ASSERT( eq(get(l1, $I(1)), $S(\"Blah\")) );\n  PT_ASSERT( eq(get(l1, $I(2)), $S(\"Bar\")) );\n  \n  del(l1);\n  \n}\n\nPT_FUNC(test_list_hash) {\n  \n  var l0 = new(List, String, $S(\"Hello\"), $S(\"World\"));\n  \n  PT_ASSERT(hash(l0) is (hash($S(\"Hello\")) ^ hash($S(\"World\"))));\n  \n  del(l0);\n  \n}\n\nPT_FUNC(test_list_iter) {\n  \n  var l0 = new(List, Int);\n  var l1 = new(List, Float);\n  \n  PT_ASSERT(iter_type(l0) is Int);\n  PT_ASSERT(iter_type(l1) is Float);\n  \n  del(l0); del(l1);\n  \n  l0 = new(List, String, \n    $S(\"Hello\"), $S(\"There\"), $S(\"People\"));\n  \n  int counter = 0;\n  \n  foreach(item in l0) {\n    \n    switch(counter) {\n      case 0: PT_ASSERT( eq(item, $S(\"Hello\")) ); break;\n      case 1: PT_ASSERT( eq(item, $S(\"There\")) ); break;\n      case 2: PT_ASSERT( eq(item, $S(\"People\")) ); break;\n    }\n    \n    counter++;\n  }\n  \n  PT_ASSERT(counter is 3);\n  \n  counter = 0;\n  \n  foreach(item0 in l0) {\n    foreach(item1 in l0) {\n      counter++;\n    }\n  }\n  \n  PT_ASSERT(counter is 9);\n  del(l0);\n  \n}\n\nPT_FUNC(test_list_len) {\n  \n  var l0 = new(List, String, $S(\"Hello\"), $S(\"World\"));\n  \n  PT_ASSERT(len(l0) is 2);\n  \n  append(l0, $S(\"!\"));\n  \n  PT_ASSERT(len(l0) is 3);\n  \n  resize(l0, 0);\n  \n  PT_ASSERT(len(l0) is 0);\n  \n  del(l0);\n  \n}\n\nPT_FUNC(test_list_push) {\n  \n  var l0 = new(List, Int);\n  \n  PT_ASSERT(len(l0) is 0);\n  \n  push(l0, $I(1));\n  \n  PT_ASSERT(len(l0) is 1);\n  PT_ASSERT( eq(get(l0, $I(0)), $I(1)) );\n  \n  push(l0, $I(3));\n  \n  PT_ASSERT(len(l0) is 2);\n  PT_ASSERT( eq(get(l0, $I(0)), $I(1)) );\n  PT_ASSERT( eq(get(l0, $I(1)), $I(3)) );\n  \n  push_at(l0, $I(10), $I(0));\n  \n  PT_ASSERT(len(l0) is 3);\n  PT_ASSERT( eq(get(l0, $I(0)), $I(10)) );\n  PT_ASSERT( eq(get(l0, $I(1)), $I(1)) );\n  PT_ASSERT( eq(get(l0, $I(2)), $I(3)) );\n  \n  push_at(l0, $I(20), $I(1));\n  \n  PT_ASSERT(len(l0) is 4);\n  PT_ASSERT( eq(get(l0, $I(0)), $I(10)) );\n  PT_ASSERT( eq(get(l0, $I(1)), $I(20)) );\n  PT_ASSERT( eq(get(l0, $I(2)), $I(1)) );\n  PT_ASSERT( eq(get(l0, $I(3)), $I(3)) );\n  \n  pop_at(l0, $I(2));\n  \n  PT_ASSERT(len(l0) is 3);\n  PT_ASSERT( eq(get(l0, $I(0)), $I(10)) );\n  PT_ASSERT( eq(get(l0, $I(1)), $I(20)) );\n  PT_ASSERT( eq(get(l0, $I(2)), $I(3)) );\n  \n  pop_at(l0, $I(0));\n  \n  PT_ASSERT(len(l0) is 2);\n  PT_ASSERT( eq(get(l0, $I(0)), $I(20)) );\n  PT_ASSERT( eq(get(l0, $I(1)), $I(3)) );\n  \n  pop(l0);\n  \n  PT_ASSERT(len(l0) is 1);\n  PT_ASSERT( eq(get(l0, $I(0)), $I(20)) );\n  \n  pop(l0);\n  \n  PT_ASSERT(len(l0) is 0);\n  \n  del(l0);\n  \n}\n\nPT_FUNC(test_list_resize) {\n  \n  var l0 = new(List, Int);\n  resize(l0, 1000);\n  del(l0);\n  \n  l0 = new(List, Int, $I(1), $I(2), $I(3));\n  \n  PT_ASSERT(len(l0) is 3);\n  \n  resize(l0, 0);\n  \n  PT_ASSERT(len(l0) is 0);\n  PT_ASSERT(empty(l0));\n  \n  del(l0);\n  \n}\n\nPT_FUNC(test_list_show) {\n\n  var l0 = new(List, Int, $I(1), $I(5), $I(9));\n  var s0 = new(String);\n  \n  show_to(l0, s0, 0);\n  \n  del(l0); del(s0);\n\n}\n\nPT_SUITE(suite_list) {\n  PT_REG(test_list_new);\n  PT_REG(test_list_assign);\n  PT_REG(test_list_concat);\n  PT_REG(test_list_cmp);\n  PT_REG(test_list_get);\n  PT_REG(test_list_hash);\n  PT_REG(test_list_iter);\n  PT_REG(test_list_len);\n  PT_REG(test_list_push);\n  PT_REG(test_list_resize);\n  PT_REG(test_list_show);\n}\n\n/* Map */\n\nvar convert_to_int(var x) {\n  var y = new(Int);\n  look_from(y, x, 0);\n  return y;\n}\n\nvar assert_value(var x) {\n  PT_ASSERT(x);\n  return NULL;\n}\n\nPT_FUNC(test_map_call) {\n\n  var x = tuple($I(0), $S(\"Hello!\"), $F(2.4));\n  call(map(x, $(Function, assert_value)));\n\n}\n\nPT_FUNC(test_map_get) {\n\n  var x = tuple($S(\"1\"), $S(\"2\"), $S(\"3\"));\n  var m = map(x, $(Function, convert_to_int));\n  \n  var i0 = get(m, $I(0));\n  var i1 = get(m, $I(1));\n  var i2 = get(m, $I(2));\n  \n  PT_ASSERT(eq(i0, $I(1)));\n  PT_ASSERT(eq(i1, $I(2)));\n  PT_ASSERT(eq(i2, $I(3)));\n  \n  del(i0); del(i1); del(i2);\n  \n}\n\nPT_FUNC(test_map_iter) {\n\n  var x = tuple($I(0), $S(\"Hello!\"), $F(2.4));\n  foreach (_ in map(x, $(Function, assert_value)));\n  \n}\n\nPT_FUNC(test_map_len) {\n\n  var x = tuple($S(\"1\"), $S(\"2\"), $S(\"3\"));\n  var y = tuple($S(\"1\"), $S(\"2\"), $S(\"3\"), $S(\"4\"));\n  var m = map(x, $(Function, convert_to_int));\n  var n = map(y, $(Function, convert_to_int));\n  \n  PT_ASSERT(len(m) is len(x));\n  PT_ASSERT(len(n) is len(y));\n  \n}\n\nPT_FUNC(test_map_new) {\n\n  var x = tuple($S(\"1\"), $S(\"2\"), $S(\"3\"));\n  var m = new(Map, x, $(Function, convert_to_int));\n  \n  var i0 = get(m, $I(0));\n  var i1 = get(m, $I(1));\n  var i2 = get(m, $I(2));\n  \n  PT_ASSERT(eq(i0, $I(1)));\n  PT_ASSERT(eq(i1, $I(2)));\n  PT_ASSERT(eq(i2, $I(3)));\n  \n  del(i0); del(i1); del(i2);\n  del(m);\n  \n}\n\nPT_SUITE(suite_map) {\n  PT_REG(test_map_call);\n  PT_REG(test_map_get);\n  PT_REG(test_map_iter);\n  PT_REG(test_map_len);\n  PT_REG(test_map_new);\n}\n\n/* Mutex */\n\nstatic var increment(var args) {\n  var mut = get(args, $I(0));\n  var tot = get(args, $I(1));\n  lock(mut);\n  assign(tot, $I(c_int(tot)+1));\n  unlock(mut);\n  return NULL;\n}\n\nstatic var increment2(var args) {\n  var mut = get(args, $I(0));\n  var tot = get(args, $I(1));\n  with (m in mut) {\n    assign(tot, $I(c_int(tot)+1));\n  }\n  return NULL;\n}\n\nPT_FUNC(test_mutex_lock) {\n  \n  var mutex = new(Mutex);\n  var total = $I(0);\n  \n  var threads = new(Array, Box,\n    new(Thread, $(Function, increment)), new(Thread, $(Function, increment)),\n    new(Thread, $(Function, increment)), new(Thread, $(Function, increment)),\n    new(Thread, $(Function, increment)));\n  \n  PT_ASSERT(eq(total, $I(0)));\n  \n  foreach (t in threads) {\n    call(deref(t), mutex, total);\n  }\n  \n  foreach (t in threads) {\n    join(deref(t));\n  }\n  \n  PT_ASSERT(eq(total, $I(5)));\n  \n  del(threads);\n  del(mutex);\n  \n}\n\nPT_FUNC(test_mutex_new) {\n  \n  var mutex = new(Mutex);\n  \n  start(mutex);\n  \n  del(mutex);\n  \n}\n\nPT_FUNC(test_mutex_start) {\n  \n  var mutex = new(Mutex);\n  var total = $I(0);\n  \n  var threads = new(Array, Box,\n    new(Thread, $(Function, increment2)), new(Thread, $(Function, increment2)),\n    new(Thread, $(Function, increment2)), new(Thread, $(Function, increment2)),\n    new(Thread, $(Function, increment2)));\n  \n  PT_ASSERT(eq(total, $I(0)));\n  \n  foreach (t in threads) {\n    call(deref(t), mutex, total);\n  }\n  \n  foreach (t in threads) {\n    join(deref(t));\n  }\n  \n  PT_ASSERT(eq(total, $I(5)));\n  \n  del(threads);\n  del(mutex);\n  \n}\n\nPT_SUITE(suite_mutex) {\n  PT_REG(test_mutex_lock);\n  PT_REG(test_mutex_new);\n  PT_REG(test_mutex_start);\n}\n\n/* Range */\n\nPT_FUNC(test_range_assign) {\n  var x = new(Range, $I(1), $I(5), $I(2));\n  var y = assign(new(Range), x);\n  \n  PT_ASSERT(eq(x, y));\n  PT_ASSERT(c_int(get(y, $I(0))) is 1);\n  PT_ASSERT(c_int(get(y, $I(1))) is 3);\n  PT_ASSERT(len(y) is 2);\n  \n  del(x); del(y);\n}\n\nPT_FUNC(test_range_cmp) {\n  \n  var x = range($I(100));\n  var y = range($I(0), $I(100));\n  var z = range($I(0), $I(100), $I(1));\n  \n  PT_ASSERT(eq(x, y));\n  PT_ASSERT(eq(y, z));\n  PT_ASSERT(eq(x, z));\n  \n  var a = new(Range, $I(100));\n  \n  PT_ASSERT(eq(x, a));\n  PT_ASSERT(eq(y, a));\n  PT_ASSERT(eq(z, a));\n  \n  del(a);\n  \n}\n\nPT_FUNC(test_range_get) {\n  \n  var x = range($I(1000));\n  var y = range($I(1), $I(20));\n  var z = range($I(3), $I(21), $I(2));\n\n  PT_ASSERT(c_int(get(x, $I(100))) is 100);\n  PT_ASSERT(c_int(get(x, $I(10))) is 10);\n  PT_ASSERT(c_int(get(x, $I(5))) is 5);\n  \n  PT_ASSERT(c_int(get(x, $I(-1))) is 999);\n  PT_ASSERT(c_int(get(x, $I(-2))) is 998);\n  PT_ASSERT(c_int(get(x, $I(-3))) is 997);\n  \n  PT_ASSERT(c_int(get(y, $I(15))) is 16);\n  PT_ASSERT(c_int(get(y, $I(10))) is 11);\n  PT_ASSERT(c_int(get(y, $I(5))) is 6);\n  \n  PT_ASSERT(c_int(get(z, $I(0))) is 3);\n  PT_ASSERT(c_int(get(z, $I(1))) is 5);\n  PT_ASSERT(c_int(get(z, $I(3))) is 9);\n  \n}\n\nPT_FUNC(test_range_iter) {\n  \n  PT_ASSERT(iter_type(range($I(10))) is Int);\n  \n  size_t j;\n  var x = range($I(1000));\n  var y = range($I(1), $I(20));\n  var z = range($I(3), $I(21), $I(2));\n  \n  j = 0;\n  foreach (i in x) {\n    PT_ASSERT(c_int(i) is j);\n    j++;\n  }\n  \n  j = 1;\n  foreach (i in y) {\n    PT_ASSERT(c_int(i) is j);\n    j++;\n  }\n  \n  j = 3;\n  foreach (i in z) {\n    PT_ASSERT(c_int(i) is j);\n    j+=2;\n  }\n  \n}\n\nPT_FUNC(test_range_len) {\n  \n  var x = range($I(1000));\n  var y = range($I(1), $I(20));\n  var z = range($I(3), $I(21), $I(2));\n  \n  PT_ASSERT(len(x) is 1000);\n  PT_ASSERT(len(y) is 19);\n  PT_ASSERT(len(z) is 9);\n  \n}\n\nPT_FUNC(test_range_new) {\n  var x = new(Range, $I(1), $I(5), $I(2));\n  del(x);\n}\n\nPT_FUNC(test_range_show) {\n  \n  var r0 = new(Range, $I(1), $I(5), $I(2));\n  var s0 = new(String);\n  \n  show_to(r0, s0, 0);\n  \n  del(r0); del(s0);\n}\n\n\nPT_SUITE(suite_range) {\n  PT_REG(test_range_assign);\n  PT_REG(test_range_cmp);\n  PT_REG(test_range_get);\n  PT_REG(test_range_iter);\n  PT_REG(test_range_len);\n  PT_REG(test_range_new);\n  PT_REG(test_range_show);\n}\n\n/* Ref */\n\nPT_FUNC(test_ref_assign) {\n  \n  var s0 = new(String, $S(\"Hello World!\"));\n  var r0 = assign($(Ref, NULL), s0);\n  \n  PT_ASSERT(r0);\n  PT_ASSERT(deref(r0) is s0);\n  \n  del(s0);\n  \n}\n\nPT_FUNC(test_ref_pointer) {\n  \n  var s0 = new(String, $S(\"Hello World 1!\"));\n  var s1 = NULL;\n\n  var r0 = $(Ref, s0);\n  var r1 = $(Ref, s1);\n  \n  PT_ASSERT(deref(r0) is s0);\n  PT_ASSERT(deref(r1) is NULL);\n  \n  del(s0);\n  \n}\n\nPT_SUITE(suite_ref) {\n  PT_REG(test_ref_assign);\n  PT_REG(test_ref_pointer);\n}\n\n/* Slice */\n\nPT_FUNC(test_slice_assign) {\n  \n  var x = tuple($I(100), $I(10), $I(30), $I(50), $I(6), $I(1));\n  var s0 = new(Slice, x, _, _, _);\n  var s1 = assign(new(Slice, x), s0);\n  \n  PT_ASSERT(eq(s0, s1));\n  PT_ASSERT(c_int(get(s1, $I(0))) is 100);\n  PT_ASSERT(c_int(get(s1, $I(1))) is 10);\n  PT_ASSERT(c_int(get(s1, $I(2))) is 30);\n  \n  del(s0); del(s1);\n  \n}\n\nPT_FUNC(test_slice_cmp) {\n  \n  \n  var x = tuple($I(100), $I(10), $I(30), $I(50), $I(6), $I(1));\n  var s0 = slice(x, $I(4));\n  var s1 = slice(x, $I(0), $I(4));\n  var s2 = slice(x, $I(0), $I(4), $I(1));\n  var s3 = slice(x, _, $I(4));\n  \n  PT_ASSERT(eq(s0, s1));\n  PT_ASSERT(eq(s0, s2));\n  PT_ASSERT(eq(s0, s3));\n  \n}\n\nPT_FUNC(test_slice_get) {\n  \n  var x = tuple($I(100), $I(10), $I(30), $I(50), $I(6), $I(1));\n  var s0 = slice(x, $I(4));\n  var s1 = slice(x, $I(1), $I(4));\n  var s2 = slice(x, $I(0), $I(4), $I(2));\n  var s3 = slice(x, _, _, $I(2));\n  \n  PT_ASSERT(c_int(get(s0, $I(0))) is 100);\n  PT_ASSERT(c_int(get(s0, $I(1))) is 10);\n  \n  PT_ASSERT(c_int(get(s1, $I(0))) is 10);\n  PT_ASSERT(c_int(get(s1, $I(1))) is 30);\n  \n  PT_ASSERT(c_int(get(s2, $I(0))) is 100);\n  PT_ASSERT(c_int(get(s2, $I(1))) is 30);\n  \n  PT_ASSERT(c_int(get(s3, $I(0))) is 100);\n  PT_ASSERT(c_int(get(s3, $I(1))) is 30);\n  \n  var s4 = slice(x, $I(-2));\n  var s5 = slice(x, $I(-3), $I(-2));\n  var s6 = slice(x, _, _, $I(-1));\n  var s7 = slice(x, $I(-4), _, $I(1));\n  \n  PT_ASSERT(c_int(get(s4, $I(-1))) is 50);\n  PT_ASSERT(c_int(get(s4, $I(-2))) is 30);\n  \n  PT_ASSERT(c_int(get(s5, $I(0))) is 50);\n\n  PT_ASSERT(c_int(get(s6, $I(0))) is 1);\n  PT_ASSERT(c_int(get(s6, $I(1))) is 6);\n  PT_ASSERT(c_int(get(s6, $I(2))) is 50);\n  PT_ASSERT(c_int(get(s6, $I(3))) is 30);\n  PT_ASSERT(c_int(get(s6, $I(4))) is 10);\n  PT_ASSERT(c_int(get(s6, $I(5))) is 100);\n\n  PT_ASSERT(c_int(get(s7, $I(0))) is 30);\n  PT_ASSERT(c_int(get(s7, $I(1))) is 50);\n  PT_ASSERT(c_int(get(s7, $I(2))) is 6);\n  \n  PT_ASSERT(c_int(get(s0, $I(-1))) is 50);\n  PT_ASSERT(c_int(get(s1, $I(-1))) is 50);\n  PT_ASSERT(c_int(get(s6, $I(-1))) is 100);\n  \n}\n\nPT_FUNC(test_slice_iter) {\n  \n  var x = tuple($I(100), $I(10), $I(30), $I(50), $I(6), $I(1));\n  var s0 = slice(x, $I(4));\n  var s1 = slice(x, $I(1), $I(4));\n  var s2 = slice(x, $I(0), $I(4), $I(2));\n  var s3 = slice(x, _, _, $I(2));\n  \n  /* TODO: Improve */\n  foreach (i in s0) {}\n  foreach (i in s1) {}\n  foreach (i in s2) {}\n  foreach (i in s3) {}\n  \n  x = new(Array, Int);\n  var y = slice(x);\n  \n  PT_ASSERT(iter_type(y) is iter_type(x));\n  \n  del(x);\n  \n}\n\nPT_FUNC(test_slice_len) {\n  \n  var x = tuple($I(100), $I(10), $I(30), $I(50), $I(6), $I(1));\n  var s0 = slice(x, $I(4));\n  var s1 = slice(x, $I(1), $I(4));\n  var s2 = slice(x, $I(0), $I(4), $I(2));\n  var s3 = slice(x, _, _, $I(2));\n  \n  PT_ASSERT(len(s0) is 4);\n  PT_ASSERT(len(s1) is 3);\n  PT_ASSERT(len(s2) is 2);\n  PT_ASSERT(len(s3) is 3);\n  \n}\n\nPT_FUNC(test_slice_new) {\n  \n  var x = tuple($I(100), $I(10), $I(30), $I(50), $I(6), $I(1));\n  var s0 = new(Slice, x, _, _, _);\n  var s1 = new(Slice, x, $I(1), _);\n  \n  del(s0);\n  del(s1);\n  \n}\n\nPT_SUITE(suite_slice) {\n  PT_REG(test_slice_assign);\n  PT_REG(test_slice_cmp);\n  PT_REG(test_slice_get);\n  PT_REG(test_slice_iter);\n  PT_REG(test_slice_len);\n  PT_REG(test_slice_new);\n}\n\n/* String */\n\nPT_FUNC(test_string_assign) {\n  \n  var s0 = new(String, $S(\"Hello\"));\n  \n  PT_ASSERT_STR_EQ(c_str(s0), \"Hello\");\n  \n  assign(s0, $S(\"There\"));\n\n  PT_ASSERT_STR_EQ(c_str(s0), \"There\");\n\n  del(s0);\n  \n}\n\nPT_FUNC(test_string_c_str) {\n  \n  PT_ASSERT_STR_EQ(c_str($S(\"Ball\")),    \"Ball\");\n  PT_ASSERT_STR_EQ(c_str($S(\"dog\")),     \"dog\");\n  PT_ASSERT_STR_EQ(c_str($S(\"great\")),   \"great\");\n  PT_ASSERT_STR_EQ(c_str($S(\"Yellow\")),  \"Yellow\");\n  PT_ASSERT_STR_EQ(c_str($S(\"Hello\")),   \"Hello\");\n  \n}\n\nPT_FUNC(test_string_cmp) {\n  \n  PT_ASSERT( gt($S(\"Ball\"),    $S(\"Apple\")) );\n  PT_ASSERT( gt($S(\"dog\"),     $S(\"cat\")) );\n  PT_ASSERT( lt($S(\"great\"),   $S(\"hello\")) );\n  PT_ASSERT( lt($S(\"Yellow\"),  $S(\"Zoo\")) );\n  PT_ASSERT( eq($S(\"Hello\"),   $S(\"Hello\")) );\n  PT_ASSERT( eq($S(\"there\"),   $S(\"there\")) );\n  PT_ASSERT( ge($S(\"Hello\"),   $S(\"Hello\")) );\n  PT_ASSERT( ge($S(\"tooting\"), $S(\"red\")) );\n  PT_ASSERT( le($S(\"guard\"),   $S(\"guardian\")) );\n  PT_ASSERT( le($S(\"keep\"),    $S(\"keep\")) );\n  PT_ASSERT(neq($S(\"Hello\"),   $S(\"hello\")) );\n  PT_ASSERT(neq($S(\"group\"),   $S(\"GROUP\")) );\n  \n}\n\nPT_FUNC(test_string_concat) {\n  \n  var s0 = new(String, $S(\"Hello\"));\n  PT_ASSERT_STR_EQ(c_str(s0), \"Hello\");\n    \n  concat(s0, $S(\" \"));\n  PT_ASSERT_STR_EQ(c_str(s0), \"Hello \");\n  \n  concat(s0, $S(\"World\"));\n  PT_ASSERT_STR_EQ(c_str(s0), \"Hello World\");\n\n  append(s0, $S(\"!\"));\n  PT_ASSERT_STR_EQ(c_str(s0), \"Hello World!\");\n  \n  del(s0);\n  \n}\n\nPT_FUNC(test_string_format) {\n  \n  var s0 = new(String);\n  resize(s0, 1000);\n  \n  format_to(s0, 0, \"%s\", \"Hello\");  \n  PT_ASSERT_STR_EQ(c_str(s0), \"Hello\");\n\n  format_to(s0, 0, \"\");  \n  PT_ASSERT_STR_EQ(c_str(s0), \"\");\n  \n  print_to(s0, 0, \"\");\n  PT_ASSERT_STR_EQ(c_str(s0), \"\");\n  \n  del(s0);\n  \n}\n\nPT_FUNC(test_string_get) {\n  \n  var s0 = new(String, $S(\"Balloons\"));\n  \n  PT_ASSERT(len(s0) is 8);\n  PT_ASSERT(mem(s0, $S(\"Ball\")));\n  PT_ASSERT(mem(s0, $S(\"oon\")));\n  PT_ASSERT(mem(s0, $S(\"Balloons\")));\n  \n  rem(s0, $S(\"oons\"));\n  \n  PT_ASSERT_STR_EQ(c_str(s0), \"Ball\");\n  \n  resize(s0, 0);\n  \n  PT_ASSERT(len(s0) is 0);\n  PT_ASSERT_STR_EQ(c_str(s0), \"\");\n  \n  \n  del(s0);\n  \n}\n\nPT_FUNC(test_string_hash) {\n  \n  uint64_t v0 = 4771441285123272284ULL;\n  uint64_t v1 = 17415363727859751682ULL;\n  uint64_t v2 = 11867268813077774525ULL;\n  \n  PT_ASSERT(hash($S(\"Hello\")) is v0);\n  PT_ASSERT(hash($S(\"There\")) is v1);\n  PT_ASSERT(hash($S(\"People\")) is v2);\n  \n}\n\nPT_FUNC(test_string_len) {\n  \n  PT_ASSERT(len($S(\"tooting\")) is 7);\n  PT_ASSERT(len($S(\"guard\")) is 5);\n  PT_ASSERT(len($S(\"keep\")) is 4);\n  PT_ASSERT(len($S(\"Hello\")) is 5);\n  PT_ASSERT(len($S(\"group\")) is 5);\n  \n}\n\nPT_FUNC(test_string_new) {\n  \n  var s0 = $S(\"Hello\");\n  var s1 = new(String, $S(\"There\"));\n  var s2 = copy(s0);\n  \n  PT_ASSERT(s0);\n  PT_ASSERT(s1);\n  PT_ASSERT(s2);\n  \n  PT_ASSERT_STR_EQ(c_str(s0), \"Hello\");\n  PT_ASSERT_STR_EQ(c_str(s1), \"There\");\n  PT_ASSERT_STR_EQ(c_str(s2), \"Hello\");\n  \n  assign(s2, s1);\n  \n  PT_ASSERT( not(s1 is s2) );\n  PT_ASSERT_STR_EQ( c_str(s2), \"There\" );\n  \n  del(s1);\n  del(s2);\n  \n}\n\nPT_FUNC(test_string_resize) {\n  \n  var s0 = new(String, $S(\"Hello\"));\n  resize(s0, 1000);\n  del(s0);\n  \n  s0 = new(String, $S(\"Hello\"));\n  \n  PT_ASSERT_STR_EQ(c_str(s0), \"Hello\");\n  \n  resize(s0, 0);\n\n  PT_ASSERT_STR_EQ(c_str(s0), \"\");\n  PT_ASSERT(len(s0) is 0);\n  PT_ASSERT(empty(s0));\n\n  del(s0);\n  \n}\n\nPT_FUNC(test_string_show) {\n  \n  var s0 = new(String);\n  \n  show_to($S(\"Hello\"), s0, 0);\n  PT_ASSERT_STR_EQ(c_str(s0), \"\\\"Hello\\\"\");\n  \n  show_to($S(\"Hello\\n\"), s0, 0);\n  PT_ASSERT_STR_EQ(c_str(s0), \"\\\"Hello\\\\n\\\"\");\n  \n  show_to($S(\"Hel\\\"lo\\n\"), s0, 0);\n  PT_ASSERT_STR_EQ(c_str(s0), \"\\\"Hel\\\\\\\"lo\\\\n\\\"\");\n  \n  show_to($S(\"Hel\\\"'lo\\n\"), s0, 0);\n  PT_ASSERT_STR_EQ(c_str(s0), \"\\\"Hel\\\\\\\"\\\\'lo\\\\n\\\"\");\n  \n  del(s0);\n  \n}\n\nPT_SUITE(suite_string) {\n  PT_REG(test_string_assign);\n  PT_REG(test_string_c_str);\n  PT_REG(test_string_cmp);\n  PT_REG(test_string_concat);\n  PT_REG(test_string_format);\n  PT_REG(test_string_get);\n  PT_REG(test_string_hash);\n  PT_REG(test_string_len);\n  PT_REG(test_string_new);\n  PT_REG(test_string_resize);\n  PT_REG(test_string_show);\n}\n\n/* Table */\n\nPT_FUNC(test_table_assign) {\n  \n  var t0 = new(Table, String, Int);\n  var t1 = new(Table, String, Int,\n    $S(\"asfa\"), $I(0), $S(\"gasg\"), $I(2),\n    $S(\"asda\"), $I(1), $S(\"dqga\"), $I(0),\n    $S(\"jaja\"), $I(7), $S(\"sdfa\"), $I(2),\n    $S(\"jads\"), $I(7), $S(\"kyad\"), $I(2),\n    $S(\"kyas\"), $I(7), $S(\"hwdw\"), $I(2),\n    $S(\"awaa\"), $I(7), $S(\"lkil\"), $I(2)); \n  \n  PT_ASSERT(len(t0) is 0);\n  \n  assign(t0, t1);\n  \n  PT_ASSERT(len(t0) is 12);\n  PT_ASSERT(eq(get(t0, $S(\"asfa\")), $I(0)));\n  PT_ASSERT(eq(get(t0, $S(\"kyad\")), $I(2)));\n  PT_ASSERT(eq(get(t0, $S(\"lkil\")), $I(2)));\n  PT_ASSERT(eq(get(t0, $S(\"jads\")), $I(7)));\n  \n  del(t0); del(t1);\n  \n}\n\nPT_FUNC(test_table_cmp) {\n  \n  var t0 = new(Table, String, Int,\n    $S(\"Hello\"), $I(2),\n    $S(\"There\"), $I(5));\n  \n  var t1 = new(Table, String, Int,\n    $S(\"Hello\"), $I(2),\n    $S(\"There\"), $I(5));\n  \n  var t2 = new(Table, String, Int,\n    $S(\"Bello\"), $I(2),\n    $S(\"There\"), $I(5));\n  \n  var t3 = new(Table, String, Int,\n    $S(\"Hello\"), $I(2),\n    $S(\"There\"), $I(5),\n    $S(\"World\"), $I(6));\n  \n  PT_ASSERT(eq(t0, t1));\n  PT_ASSERT(neq(t0, t2));\n  PT_ASSERT(lt(t2, t0));\n  PT_ASSERT(gt(t0, t2));\n  PT_ASSERT(gt(t3, t1));\n  PT_ASSERT(gt(t3, t0));\n  \n  del(t0); del(t1); del(t2); del(t3);\n  \n}\n\nPT_FUNC(test_table_get) {\n  \n  var t0 = new(Table, String, Int);\n  set(t0, $S(\"Hello\"), $I(2));\n  set(t0, $S(\"There\"), $I(5));\n  \n  PT_ASSERT(len(t0) is 2);\n  PT_ASSERT(mem(t0, $S(\"Hello\")));\n  \n  rem(t0, $S(\"Hello\"));\n  \n  PT_ASSERT(len(t0) is 1);\n  PT_ASSERT(not mem(t0, $S(\"Hello\")));\n  PT_ASSERT(mem(t0, $S(\"There\")));\n  \n  resize(t0, 0);\n  \n  PT_ASSERT(len(t0) is 0);\n  PT_ASSERT(not mem(t0, $S(\"Hello\")));\n  PT_ASSERT(not mem(t0, $S(\"There\")));\n  \n  del(t0);\n\n\n  var t1 = new(Table, String, Int);\n  set(t1, $S(\"Hello\"), $I(2));\n  set(t1, $S(\"There\"), $I(5));\n  \n  var i0 = get(t1, $S(\"Hello\"));\n  var i1 = get(t1, $S(\"There\"));\n  \n  PT_ASSERT( eq(i0, $I(2)) );\n  PT_ASSERT( eq(i1, $I(5)) );\n  \n  set(t1, $S(\"Hello\"), $I(6));\n  \n  var i2 = get(t1, $S(\"Hello\"));\n  PT_ASSERT( eq(i2, $I(6)) );\n  \n  del(t1);\n  \n  var t3 = new(Table, String, Int,\n    $S(\"asfa\"), $I(0), $S(\"gasg\"), $I(2),\n    $S(\"asda\"), $I(1), $S(\"dqga\"), $I(0),\n    $S(\"jaja\"), $I(7), $S(\"sdfa\"), $I(2),\n    $S(\"jads\"), $I(7), $S(\"kyad\"), $I(2),\n    $S(\"kyas\"), $I(7), $S(\"hwdw\"), $I(2),\n    $S(\"oaqv\"), $I(7), $S(\"fgds\"), $I(2),\n    $S(\"awaa\"), $I(7), $S(\"lkil\"), $I(2));\n  \n  rem(t3, $S(\"gasg\"));\n  rem(t3, $S(\"oaqv\"));\n  rem(t3, $S(\"fgds\"));\n  rem(t3, $S(\"awaa\"));\n  rem(t3, $S(\"kyad\"));\n  rem(t3, $S(\"dqga\"));\n  rem(t3, $S(\"jaja\"));\n    \n  del(t3);\n  \n}\n\nPT_FUNC(test_table_hash) {\n  \n  var t0 = new(Table, String, Int);\n  set(t0, $S(\"Hello\"), $I(2));\n  set(t0, $S(\"There\"), $I(5));\n  \n  PT_ASSERT(hash(t0) is (\n    hash($S(\"Hello\")) ^ hash($I(2)) ^\n    hash($S(\"There\")) ^ hash($I(5))));\n  \n  del(t0);\n  \n}\n\nPT_FUNC(test_table_iter) {\n  \n  var t0 = new(Table, String, Int);\n  set(t0, $S(\"Hello\"), $I(2));\n  set(t0, $S(\"There\"), $I(5));\n  \n  foreach(key in t0) {\n    \n    var val = get(t0, key);\n    \n    PT_ASSERT(\n       (eq(key, $S(\"Hello\")) and eq(val, $I(2)))\n    or (eq(key, $S(\"There\")) and eq(val, $I(5))));\n    \n  }\n  \n  del(t0);\n  \n}\n\nPT_FUNC(test_table_len) {\n  \n  var t0 = new(Table, String, Int);\n  set(t0, $S(\"Hello\"), $I(2));\n  set(t0, $S(\"There\"), $I(5));\n  \n  PT_ASSERT(len(t0) is 2);\n  \n  del(t0);\n  \n}\n\nPT_FUNC(test_table_new) {\n  \n  var t0 = new(Table, String, Int);\n  set(t0, $S(\"Hello\"), $I(2));\n  set(t0, $S(\"There\"), $I(5));\n  \n  var t1 = new(Table, String, Int);\n  set(t1, $S(\"Bonjour\"), $I(9));\n  set(t1, $S(\"Where\"), $I(5));\n  \n  var t2 = copy(t0);\n  \n  PT_ASSERT(t0);\n  PT_ASSERT(t1);\n  PT_ASSERT(t2);\n  \n  PT_ASSERT(t0 isnt t2);\n  PT_ASSERT(t0 isnt t1);\n  \n  PT_ASSERT(mem(t0, $S(\"Hello\")));\n  PT_ASSERT(mem(t1, $S(\"Bonjour\")));\n  PT_ASSERT(mem(t2, $S(\"There\")));\n  \n  assign(t2, t1);\n  \n  PT_ASSERT(mem(t2, $S(\"Where\")));\n  PT_ASSERT(mem(t2, $S(\"Bonjour\")));\n  PT_ASSERT(not mem(t2, $S(\"Hello\")));\n  PT_ASSERT(not mem(t2, $S(\"There\")));\n  \n  del(t0);\n  del(t1);\n  del(t2);\n  \n  var t3 = new(Table, String, Int,\n    $S(\"asfa\"), $I(0), $S(\"gasg\"), $I(2),\n    $S(\"asda\"), $I(1), $S(\"dqga\"), $I(0),\n    $S(\"jaja\"), $I(7), $S(\"sdfa\"), $I(2),\n    $S(\"jads\"), $I(7), $S(\"kyad\"), $I(2),\n    $S(\"kyas\"), $I(7), $S(\"hwdw\"), $I(2),\n    $S(\"awaa\"), $I(7), $S(\"lkil\"), $I(2));\n  \n  del(t3);\n  \n  t0 = new(Table, Int, Float);\n  t1 = new(Table, String, Int);\n  \n  PT_ASSERT(key_type(t0) is Int);\n  PT_ASSERT(val_type(t0) is Float);\n  PT_ASSERT(key_type(t1) is String);\n  PT_ASSERT(val_type(t1) is Int);\n  \n  del(t0); del(t1);\n  \n}\n\nPT_FUNC(test_table_resize) {\n  \n  var t0 = new(Table, String, Int);\n  resize(t0, 1000);\n  del(t0);\n  \n  t0 = new(Table, String, Int);\n  set(t0, $S(\"Hello\"), $I(2));\n  set(t0, $S(\"There\"), $I(5));\n  \n  PT_ASSERT(len(t0) is 2);\n  \n  resize(t0, 0);\n  \n  PT_ASSERT(len(t0) is 0);\n  PT_ASSERT(empty(t0));\n  \n  del(t0);\n  \n}\n\nPT_FUNC(test_table_show) {\n  \n  var t0 = new(Table, String, Int);\n  set(t0, $S(\"Bonjour\"), $I(9));\n  set(t0, $S(\"Where\"), $I(5));\n  \n  var s0 = new(String);\n  \n  show_to(t0, s0, 0);\n  \n  del(t0); del(s0);\n  \n}\n\nPT_FUNC(test_table_rehash) {\n  \n  var t0 = new(Table, Int, Int);\n  var value = $I(23);\n  var test_key = NULL;\n\n  size_t max = 1000;\n  int64_t r = rand() % max;\n\n  for (size_t i = 0; i < max; i++) {\n    var key = $I(i);\n    if (i == r) {\n      test_key = key;\n    }\n    set(t0, key, value);\n  }\n\n  PT_ASSERT(test_key isnt NULL);\n  PT_ASSERT(eq(get(t0, test_key), value));\n  PT_ASSERT(len(t0) is max);\n\n  del(t0);\n}\n\nPT_SUITE(suite_table) {\n  PT_REG(test_table_assign);\n  PT_REG(test_table_cmp);\n  PT_REG(test_table_get);\n  PT_REG(test_table_hash);\n  PT_REG(test_table_iter);\n  PT_REG(test_table_len);\n  PT_REG(test_table_new);\n  PT_REG(test_table_resize);\n  PT_REG(test_table_show);\n  PT_REG(test_table_rehash);\n}\n\n/* Thread */\n\nPT_FUNC(test_thread_c_int) {\n  \n  var x = new(Thread);\n  int64_t cid = c_int(current(Thread));  \n  del(x);\n  \n}\n\nstatic var set_value(var args) {\n  assign(get(args, $I(0)), $I(1));\n  return NULL;\n}\n\nPT_FUNC(test_thread_call) {\n  \n  var i = $I(0);\n  \n  var x = new(Thread, $(Function, set_value));\n  call(x, i);\n  join(x);\n  \n  PT_ASSERT(c_int(i) is 1);\n  \n  del(x);\n  \n}\n\nPT_FUNC(test_thread_cmp) {\n  \n  PT_ASSERT(eq(current(Thread), current(Thread)));\n  \n}\n\nPT_FUNC(test_thread_current) {\n  var x = current(Thread);\n  PT_ASSERT(x);\n}\n\nPT_FUNC(test_thread_get) {\n  \n  set(current(Thread), $S(\"Hello\"), $I(1));\n  PT_ASSERT(mem(current(Thread), $S(\"Hello\")));\n  PT_ASSERT(c_int(get(current(Thread), $S(\"Hello\"))) is 1);\n  rem(current(Thread), $S(\"Hello\"));\n  PT_ASSERT(not mem(current(Thread), $S(\"Hello\")));\n  \n}\n\nPT_FUNC(test_thread_hash) {\n  var x = new(Thread);\n  int64_t h0 = hash(current(Thread));\n  int64_t h1 = hash(current(Thread));\n  PT_ASSERT(h0 is h1);\n  del(x);\n}\n\nPT_FUNC(test_thread_new) {\n  var x = new(Thread);\n  del(x);\n}\n\nPT_FUNC(test_thread_start) {\n  \n  \n  /*\n  ** TODO: Separate out Enter/Exit to Start/Stop.\n  ** For Threads With should do `join` on stop\n  */\n  \n}\n\n#ifdef CELLO_UNIX\n#include <unistd.h>\n#endif\n\nvoid cello_sleep(int ms) {\n#if defined(CELLO_UNIX)\n  usleep(ms * 1000);\n#elif defined(CELLO_WINDOWS)\n  Sleep(ms);\n#endif\n}\n\nstatic var exception_sleep(var args) {\n  try {\n    cello_sleep(20);\n    PT_ASSERT(len(current(Exception)) is 1);\n  } catch(e) { }\n  return NULL;\n}\n\nPT_FUNC(test_thread_exception) {\n  \n  var t = new(Thread, $(Function, exception_sleep));\n  \n  call(t);\n  cello_sleep(10);\n  PT_ASSERT(len(current(Exception)) is 0);\n  join(t);\n  \n  del(t);\n  \n}\n\nPT_SUITE(suite_thread) {\n  PT_REG(test_thread_c_int);\n  PT_REG(test_thread_call);\n  PT_REG(test_thread_cmp);\n  PT_REG(test_thread_current);\n  PT_REG(test_thread_get);\n  PT_REG(test_thread_hash);\n  PT_REG(test_thread_new);\n  PT_REG(test_thread_start);\n  PT_REG(test_thread_exception);\n}\n\n/* Tree */\n\nPT_FUNC(test_tree_assign) {\n  \n  var m0 = new(Tree, String, Int);\n  var m1 = new(Tree, String, Int,\n    $S(\"asfa\"), $I(0), $S(\"gasg\"), $I(2),\n    $S(\"asda\"), $I(1), $S(\"dqga\"), $I(0),\n    $S(\"jaja\"), $I(7), $S(\"sdfa\"), $I(2),\n    $S(\"jads\"), $I(7), $S(\"kyad\"), $I(2),\n    $S(\"kyas\"), $I(7), $S(\"hwdw\"), $I(2),\n    $S(\"awaa\"), $I(7), $S(\"lkil\"), $I(2)); \n  \n  PT_ASSERT(len(m0) is 0);\n  \n  assign(m0, m1);\n  \n  PT_ASSERT(len(m0) is 12);\n  PT_ASSERT(eq(get(m0, $S(\"asfa\")), $I(0)));\n  PT_ASSERT(eq(get(m0, $S(\"kyad\")), $I(2)));\n  PT_ASSERT(eq(get(m0, $S(\"lkil\")), $I(2)));\n  PT_ASSERT(eq(get(m0, $S(\"jads\")), $I(7)));\n  \n  del(m0); del(m1);\n  \n}\n\nPT_FUNC(test_tree_resize) {\n  \n  var m0 = new(Tree, String, Int);\n  set(m0, $S(\"Hello\"), $I(2));\n  set(m0, $S(\"There\"), $I(5));\n  \n  PT_ASSERT(len(m0) is 2);\n  \n  resize(m0, 0);\n  \n  PT_ASSERT(len(m0) is 0);\n  PT_ASSERT(empty(m0));\n  \n  del(m0);\n  \n}\n\nPT_FUNC(test_tree_cmp) {\n  \n  var m0 = new(Tree, String, Int,\n    $S(\"Hello\"), $I(2),\n    $S(\"There\"), $I(5));\n  \n  var m1 = new(Tree, String, Int,\n    $S(\"Hello\"), $I(2),\n    $S(\"There\"), $I(5));\n  \n  var m2 = new(Tree, String, Int,\n    $S(\"Bello\"), $I(2),\n    $S(\"There\"), $I(5));\n  \n  var m3 = new(Table, String, Int,\n    $S(\"Hello\"), $I(2),\n    $S(\"There\"), $I(5),\n    $S(\"World\"), $I(6));\n  \n  PT_ASSERT(eq(m0, m1));\n  PT_ASSERT(neq(m0, m2));\n  PT_ASSERT(lt(m2, m0));\n  PT_ASSERT(gt(m0, m2));\n  PT_ASSERT(gt(m3, m1));\n  PT_ASSERT(gt(m3, m0));\n  \n  del(m0); del(m1); del(m2); del(m3);\n  \n}\n\nPT_FUNC(test_tree_get) {\n  \n  var m0 = new(Tree, String, Int);\n  set(m0, $S(\"Hello\"), $I(2));\n  set(m0, $S(\"There\"), $I(5));\n  \n  PT_ASSERT(len(m0) is 2);\n  PT_ASSERT(mem(m0, $S(\"Hello\")));\n  \n  rem(m0, $S(\"Hello\"));\n  \n  PT_ASSERT(len(m0) is 1);\n  PT_ASSERT(not mem(m0, $S(\"Hello\")));\n  PT_ASSERT(mem(m0, $S(\"There\")));\n  \n  resize(m0, 0);\n  \n  PT_ASSERT(len(m0) is 0);\n  PT_ASSERT(not mem(m0, $S(\"Hello\")));\n  PT_ASSERT(not mem(m0, $S(\"There\")));\n  \n  del(m0);\n\n\n  var m1 = new(Tree, String, Int);\n  set(m1, $S(\"Hello\"), $I(2));\n  set(m1, $S(\"There\"), $I(5));\n  \n  var i0 = get(m1, $S(\"Hello\"));\n  var i1 = get(m1, $S(\"There\"));\n  \n  PT_ASSERT( eq(i0, $I(2)) );\n  PT_ASSERT( eq(i1, $I(5)) );\n  \n  set(m1, $S(\"Hello\"), $I(6));\n  \n  var i2 = get(m1, $S(\"Hello\"));\n  PT_ASSERT( eq(i2, $I(6)) );\n  \n  del(m1);\n  \n  var m3 = new(Tree, String, Int,\n    $S(\"asfa\"), $I(0), $S(\"gasg\"), $I(2),\n    $S(\"asda\"), $I(1), $S(\"dqga\"), $I(0),\n    $S(\"jaja\"), $I(7), $S(\"sdfa\"), $I(2),\n    $S(\"jads\"), $I(7), $S(\"kyad\"), $I(2),\n    $S(\"kyas\"), $I(7), $S(\"hwdw\"), $I(2),\n    $S(\"oaqv\"), $I(7), $S(\"fgds\"), $I(2),\n    $S(\"awaa\"), $I(7), $S(\"lkil\"), $I(2));\n  \n  rem(m3, $S(\"gasg\"));\n  rem(m3, $S(\"oaqv\"));\n  rem(m3, $S(\"fgds\"));\n  rem(m3, $S(\"awaa\"));\n  rem(m3, $S(\"kyad\"));\n  rem(m3, $S(\"dqga\"));\n  rem(m3, $S(\"jaja\"));\n    \n  del(m3);\n  \n  m0 = new(Tree, Int, Float);\n  m1 = new(Tree, String, Int);\n  \n  PT_ASSERT(key_type(m0) is Int);\n  PT_ASSERT(val_type(m0) is Float);\n  PT_ASSERT(key_type(m1) is String);\n  PT_ASSERT(val_type(m1) is Int);\n  \n  del(m0); del(m1);\n  \n}\n\nPT_FUNC(test_tree_hash) {\n  \n  var m0 = new(Tree, String, Int);\n  set(m0, $S(\"Hello\"), $I(2));\n  set(m0, $S(\"There\"), $I(5));\n  \n  PT_ASSERT(hash(m0) is (\n    hash($S(\"Hello\")) ^ hash($I(2)) ^\n    hash($S(\"There\")) ^ hash($I(5))));\n  \n  del(m0);\n  \n}\n\nPT_FUNC(test_tree_iter) {\n  \n  var m0 = new(Tree, String, Int);\n  set(m0, $S(\"Hello\"), $I(2));\n  set(m0, $S(\"There\"), $I(5));\n  \n  foreach(key in m0) {\n    \n    var val = get(m0, key);\n    \n    PT_ASSERT(\n       (eq(key, $S(\"Hello\")) and eq(val, $I(2)))\n    or (eq(key, $S(\"There\")) and eq(val, $I(5))));\n    \n  }\n  \n  del(m0);\n  \n}\n\nPT_FUNC(test_tree_len) {\n  \n  var m0 = new(Tree, String, Int);\n  set(m0, $S(\"Hello\"), $I(2));\n  set(m0, $S(\"There\"), $I(5));\n  \n  PT_ASSERT(len(m0) is 2);\n  \n  del(m0);\n  \n}\n\nPT_FUNC(test_tree_new) {\n  \n  var m0 = new(Tree, String, Int);\n  set(m0, $S(\"Hello\"), $I(2));\n  set(m0, $S(\"There\"), $I(5));\n  \n  var m1 = new(Tree, String, Int);\n  set(m1, $S(\"Bonjour\"), $I(9));\n  set(m1, $S(\"Where\"), $I(5));\n  \n  var m2 = copy(m0);\n  \n  PT_ASSERT(m0);\n  PT_ASSERT(m1);\n  PT_ASSERT(m2);\n  \n  PT_ASSERT(m0 isnt m2);\n  PT_ASSERT(m0 isnt m1);\n  \n  PT_ASSERT(mem(m0, $S(\"Hello\")));\n  PT_ASSERT(mem(m1, $S(\"Bonjour\")));\n  PT_ASSERT(mem(m2, $S(\"There\")));\n  \n  assign(m2, m1);\n  \n  PT_ASSERT(mem(m2, $S(\"Where\")));\n  PT_ASSERT(mem(m2, $S(\"Bonjour\")));\n  PT_ASSERT(not mem(m2, $S(\"Hello\")));\n  PT_ASSERT(not mem(m2, $S(\"There\")));\n  \n  del(m0);\n  del(m1);\n  del(m2);\n  \n  var m3 = new(Tree, String, Int,\n    $S(\"asfa\"), $I(0), $S(\"gasg\"), $I(2),\n    $S(\"asda\"), $I(1), $S(\"dqga\"), $I(0),\n    $S(\"jaja\"), $I(7), $S(\"sdfa\"), $I(2),\n    $S(\"jads\"), $I(7), $S(\"kyad\"), $I(2),\n    $S(\"kyas\"), $I(7), $S(\"hwdw\"), $I(2),\n    $S(\"awaa\"), $I(7), $S(\"lkil\"), $I(2));\n  \n  del(m3);\n  \n}\n\nPT_FUNC(test_tree_show) {\n  \n  var m0 = new(Tree, String, Int);\n  set(m0, $S(\"Bonjour\"), $I(9));\n  set(m0, $S(\"Where\"), $I(5));\n  \n  var s0 = new(String);\n  \n  show_to(m0, s0, 0);\n  \n  del(m0); del(s0);\n  \n}\n\nPT_SUITE(suite_tree) {\n  PT_REG(test_tree_assign);\n  PT_REG(test_tree_resize);\n  PT_REG(test_tree_cmp);\n  PT_REG(test_tree_get);\n  PT_REG(test_tree_hash);\n  PT_REG(test_tree_iter);\n  PT_REG(test_tree_len);\n  PT_REG(test_tree_new);\n  PT_REG(test_tree_show);\n}\n\n/* Tuple */\n\nPT_FUNC(test_tuple_assign) {\n  \n  var x = new(Tuple);\n  var y = tuple($I(100), $I(200), $I(300));\n  assign(x, y);\n  \n  PT_ASSERT(c_int(get(x, $I(0))) is 100);\n  PT_ASSERT(c_int(get(x, $I(1))) is 200);\n  PT_ASSERT(c_int(get(x, $I(2))) is 300);\n  PT_ASSERT(len(y) is 3);\n  \n  var z = new(Array, Ref);\n  assign(z, x);\n  \n  PT_ASSERT(c_int(deref(get(z, $I(0)))) is 100);\n  PT_ASSERT(c_int(deref(get(z, $I(1)))) is 200);\n  PT_ASSERT(c_int(deref(get(z, $I(2)))) is 300);\n  PT_ASSERT(len(z) is 3);\n  \n  del(z);\n  del(x);\n  \n  \n}\n\nPT_FUNC(test_tuple_resize) {\n  \n  var x = new(Tuple, $I(100), $I(200), $I(300));\n  \n  PT_ASSERT(len(x) is 3);\n  resize(x, 0);\n  PT_ASSERT(len(x) is 0);\n  \n  del(x);\n  \n}\n\nPT_FUNC(test_tuple_cmp) {\n  \n  var x = tuple($I(100), $I(200), $I(300));\n  var y = tuple($I(100), $I(200), $I(300));\n  PT_ASSERT(eq(x, y));\n  \n  set(y, $I(0), $I(0));\n  PT_ASSERT(neq(x, y));\n  \n}\n\nPT_FUNC(test_tuple_concat) {\n  \n  var x = new(Tuple, $I(100), $I(200), $I(300));\n  concat(x, tuple($I(10), $I(20)));\n  \n  PT_ASSERT(c_int(get(x, $I(0))) is 100);\n  PT_ASSERT(c_int(get(x, $I(1))) is 200);\n  PT_ASSERT(c_int(get(x, $I(2))) is 300);\n  PT_ASSERT(c_int(get(x, $I(3))) is 10);\n  PT_ASSERT(c_int(get(x, $I(4))) is 20);\n  \n  del(x);\n  \n}\n\nPT_FUNC(test_tuple_get) {\n  \n  var x = new(Tuple, $I(100), $I(200), $I(300));\n  \n  PT_ASSERT(c_int(get(x, $I(0))) is 100);\n  PT_ASSERT(c_int(get(x, $I(1))) is 200);\n  PT_ASSERT(c_int(get(x, $I(2))) is 300);\n  \n  PT_ASSERT(c_int(get(x, $I(-1))) is 300);\n  PT_ASSERT(c_int(get(x, $I(-2))) is 200);\n  PT_ASSERT(c_int(get(x, $I(-3))) is 100);\n  \n  set(x, $I(1), $I(10));\n  \n  PT_ASSERT(c_int(get(x, $I(1))) is 10);\n\n  PT_ASSERT(mem(x, $I(10)));\n  PT_ASSERT(mem(x, $I(100)));\n  PT_ASSERT(mem(x, $I(300)));\n\n  rem(x, $I(10));\n  \n  PT_ASSERT(c_int(get(x, $I(0))) is 100);\n  PT_ASSERT(c_int(get(x, $I(1))) is 300);\n\n  del(x);\n  \n}\n\nPT_FUNC(test_tuple_hash) {\n  \n  var x = tuple($S(\"Hello\"), $S(\"World\"), $S(\"!\"));\n  \n  PT_ASSERT(hash(x) is (\n    hash($S(\"Hello\")) ^ hash($S(\"World\")) ^ hash($S(\"!\"))));\n  \n}\n\nPT_FUNC(test_tuple_iter) {\n  \n  size_t i = 0;\n  foreach (x in tuple($I(10), $I(20), $I(30))) {\n    if (i is 0) { PT_ASSERT(eq(x, $I(10))); }\n    if (i is 1) { PT_ASSERT(eq(x, $I(20))); }\n    if (i is 2) { PT_ASSERT(eq(x, $I(30))); }\n    i++;\n  }\n  \n}\n\nPT_FUNC(test_tuple_len) {\n  \n  var x = tuple($I(1), $I(2));\n  var y = tuple($I(1), $I(2), $I(3));\n  var z = tuple($I(1), $I(2), $I(3), $I(10));\n  \n  PT_ASSERT(len(x) is 2);\n  PT_ASSERT(len(y) is 3);\n  PT_ASSERT(len(z) is 4);\n  \n}\n\nPT_FUNC(test_tuple_new) {\n  \n  var x = new(Tuple, $I(100), $S(\"Test\"));\n  PT_ASSERT(x);\n  del(x);\n  \n}\n\nPT_FUNC(test_tuple_push) {\n  \n  var x = new(Tuple);\n  \n  push(x, $S(\"Hello\"));\n  PT_ASSERT(eq(get(x, $I(0)), $S(\"Hello\")));\n  \n  push(x, $S(\"World\"));\n  PT_ASSERT(eq(get(x, $I(0)), $S(\"Hello\")));\n  PT_ASSERT(eq(get(x, $I(1)), $S(\"World\")));\n  \n  pop_at(x, $I(0));\n  PT_ASSERT(eq(get(x, $I(0)), $S(\"World\")));\n  \n  push_at(x, $S(\"Hello\"), $I(0));\n  PT_ASSERT(eq(get(x, $I(0)), $S(\"Hello\")));\n  PT_ASSERT(eq(get(x, $I(1)), $S(\"World\")));\n  \n  del(x);\n  \n}\n\nPT_FUNC(test_tuple_show) {\n  \n  var a0 = tuple($I(1), $I(5), $I(9));\n  var s0 = new(String);\n  \n  show_to(a0, s0, 0);\n  \n  del(s0);\n  \n}\n\nPT_FUNC(test_tuple_sort) {\n  \n  var a0 = tuple($I(100), $I(1233), $I(1), $I(2312), $I(21));\n  var a1 = tuple($I(1), $I(21), $I(100), $I(1233), $I(2312));\n  var a2 = tuple($I(2312), $I(1233), $I(100), $I(21), $I(1));\n  \n  var a3 = copy(a0);\n  var a4 = copy(a0);\n  \n  sort(a3);\n  sort_by(a4, gt);\n  PT_ASSERT(eq(a3, a1));\n  PT_ASSERT(eq(a4, a2));\n  \n  del(a3); del(a4);\n  \n}\n\nPT_SUITE(suite_tuple) {\n  PT_REG(test_tuple_assign);\n  PT_REG(test_tuple_resize);\n  PT_REG(test_tuple_cmp);\n  PT_REG(test_tuple_concat);\n  PT_REG(test_tuple_get);\n  PT_REG(test_tuple_hash);\n  PT_REG(test_tuple_iter);\n  PT_REG(test_tuple_len);\n  PT_REG(test_tuple_new);\n  PT_REG(test_tuple_push);\n  PT_REG(test_tuple_show);\n  PT_REG(test_tuple_sort);\n}\n\n/* Type */\n\nstatic var TestType;\n\nstruct TestType {\n  int64_t test_data;\n};\n\nstatic void TestType_New(var self, var args) {\n  struct TestType* tt = self;\n  tt->test_data = c_int(get(args, $I(0)));\n}\n\nstatic int TestType_Cmp(var self, var obj) {\n  struct TestType* lhs = cast(self, TestType);\n  struct TestType* rhs = cast(obj, TestType);\n  return (int)(lhs->test_data - rhs->test_data);\n}\n\nPT_FUNC(test_type_new) {\n  \n  TestType = new_root(Type, \n    $S(\"TestType\"), \n    $I(sizeof(struct TestType)),\n    $(New, TestType_New, NULL),\n    $(Cmp, TestType_Cmp));\n  \n  PT_ASSERT(TestType);\n  PT_ASSERT_STR_EQ(c_str(TestType), \"TestType\");\n\n  var test_obj1 = new(TestType, $I(1));\n  var test_obj2 = new(TestType, $I(1));\n  var test_obj3 = new(TestType, $I(4));\n\n  PT_ASSERT(test_obj1);\n  PT_ASSERT(test_obj2);\n  PT_ASSERT(test_obj3);\n  \n  PT_ASSERT(eq(test_obj1, test_obj2));\n  PT_ASSERT(neq(test_obj1, test_obj3));\n  \n  del(test_obj1);\n  del(test_obj2);\n  del(test_obj3);\n  \n  del_root(TestType);\n  \n}\n\nPT_FUNC(test_type_c_str) {\n  PT_ASSERT_STR_EQ(c_str(Type),  \"Type\");\n  PT_ASSERT_STR_EQ(c_str(Int),   \"Int\");\n  PT_ASSERT_STR_EQ(c_str(Float), \"Float\");\n  PT_ASSERT_STR_EQ(c_str(Array), \"Array\");\n}\n\nPT_FUNC(test_type_cmp) {\n  PT_ASSERT(gt(Type, Int));\n  PT_ASSERT(lt(Array, Float));\n}\n\nPT_FUNC(test_type_hash) {\n  PT_ASSERT(hash(Type) is hash($S(\"Type\")));\n  PT_ASSERT(hash(Int) is hash($S(\"Int\")));\n  PT_ASSERT(hash(Array) is hash($S(\"Array\")));\n}\n\nPT_FUNC(test_type_help) {\n  /* TODO: improve test cases, but for now just verify that\n    they can be called without crashing\n   */\n  try{ name(_);        } catch(e) { }\n  try{ brief(_);       } catch(e) { }\n  try{ description(_); } catch(e) { }\n  try{ definition(_);  } catch(e) { }\n  try{ help(_);        } catch(e) { }\n  try{ help_to(_, 0,_);} catch(e) { }\n  PT_ASSERT(1);\n}\n\nPT_FUNC(test_type_show) {\n  var s = new(String);\n  show_to(Int, s, 0);\n  PT_ASSERT_STR_EQ(c_str(s), \"Int\");\n  show_to(Type, s, 0);\n  PT_ASSERT_STR_EQ(c_str(s), \"Type\");\n  show_to(Array, s, 0);\n  PT_ASSERT_STR_EQ(c_str(s), \"Array\");\n  del(s);\n}\n\nPT_SUITE(suite_type) {\n  PT_REG(test_type_new);\n  PT_REG(test_type_c_str);\n  PT_REG(test_type_cmp);\n  PT_REG(test_type_hash);\n  PT_REG(test_type_help);\n  PT_REG(test_type_show);\n}\n\n/* Zip */\n\nPT_FUNC(test_zip_get) {\n  \n  var x = tuple($I(100), $I(10), $I(30), $I(50), $I(6), $I(1));\n  var y = tuple($I(10), $I(213), $I(12), $I(88), $I(99));\n  var z = zip(x, y);\n  \n  PT_ASSERT(eq(get(z, $I(0)), tuple($I(100), $I( 10))));\n  PT_ASSERT(eq(get(z, $I(1)), tuple($I( 10), $I(213))));\n  PT_ASSERT(eq(get(z, $I(2)), tuple($I( 30), $I( 12))));\n  PT_ASSERT(eq(get(z, $I(3)), tuple($I( 50), $I( 88))));\n  PT_ASSERT(eq(get(z, $I(4)), tuple($I(  6), $I( 99))));\n  \n}\n\nPT_FUNC(test_zip_iter) {\n  \n  var x = tuple($I(100), $I(10), $I(30), $I(50), $I(6), $I(1));\n  var y = tuple($I(10), $I(213), $I(12), $I(88), $I(99));\n  var z = tuple($I(10), $I(213));\n  \n  /* TODO: Improve */\n  foreach (i in zip(x)) {}\n  foreach (i in zip(x, y)) {}\n  foreach (i in zip(x, y, z)) {}\n  foreach (i in zip(y, z)) {}\n  \n  PT_ASSERT(iter_type(zip(x, y, z)) is Tuple);\n  \n  x = new(Array, Int, $I(100), $I(200), $I(130));\n  y = new(Array, Float, $F(0.1), $F(0.2), $F(1.3));\n\n  foreach (pair in zip(x, y)) {}\n  foreach (pair in enumerate(x)) {}\n  \n  del(x);\n  del(y);\n  \n}\n\nPT_FUNC(test_zip_len) {\n  \n  var x = tuple($I(100), $I(10), $I(30), $I(50), $I(6), $I(1));\n  var y = tuple($I(10), $I(213), $I(12), $I(88), $I(99));\n  var z = tuple($I(10), $I(213));\n  \n  PT_ASSERT(len(zip(z)) is 2);\n  PT_ASSERT(len(zip(z, y)) is 2);\n  PT_ASSERT(len(zip(x, y, z)) is 2);\n  PT_ASSERT(len(zip(x, y)) is 5);\n  PT_ASSERT(len(zip(x)) is 6);\n  \n}\n\nPT_FUNC(test_zip_new) {\n  \n  var x = tuple($I(100), $I(10), $I(30), $I(50), $I(6), $I(1));\n  var y = tuple($I(10), $I(213), $I(12), $I(88), $I(99));\n  var z = new(Zip, x, y);\n  \n  PT_ASSERT(eq(get(z, $I(0)), tuple($I(100), $I( 10))));\n  PT_ASSERT(eq(get(z, $I(1)), tuple($I( 10), $I(213))));\n  PT_ASSERT(eq(get(z, $I(2)), tuple($I( 30), $I( 12))));\n  \n  del(z);\n  \n}\n\nPT_SUITE(suite_zip) {\n  PT_REG(test_zip_get);\n  PT_REG(test_zip_iter);\n  PT_REG(test_zip_len);\n  PT_REG(test_zip_new);\n}\n\n\n/* Exception */\n\nstatic var DivideByZeroError = CelloEmpty(DivideByZeroError);\nstatic var OtherError = CelloEmpty(OtherError);\n\nstatic int exception_divide(int x, int y) {\n  if (y == 0) {\n    throw(DivideByZeroError, \"%i / %i\", $I(x), $I(y));\n    return 0;\n  } else {\n    return x / y;\n  }\n}\n\nPT_FUNC(test_exception_throw) {\n  \n  int r0 = exception_divide(2, 1);\n  int r1 = exception_divide(4, 2);\n  int r2 = exception_divide(9, 3);\n  \n  PT_ASSERT(r0 == 2);\n  PT_ASSERT(r1 == 2);\n  PT_ASSERT(r2 == 3);\n  \n  PT_ASSERT(len(current(Exception)) is 0);\n  \n}\n\nPT_FUNC(test_exception_catch) {\n  \n  volatile bool reached0 = false;\n  volatile bool reached1 = false;\n  volatile bool reached2 = false;\n  \n  try {\n    int r3 = exception_divide(2, 0);\n  } catch (e in DivideByZeroError) {\n    reached0 = true;\n  }\n  \n  try {\n    int r3 = exception_divide(2, 1);\n  } catch (e in DivideByZeroError) {\n    reached1 = true;\n  }\n  \n  try {\n    int r3 = exception_divide(2, 1);\n  } catch (e) {\n    reached2 = true;\n  }\n  \n  PT_ASSERT(reached0);\n  PT_ASSERT(not reached1);\n  PT_ASSERT(not reached2);\n  \n  PT_ASSERT(len(current(Exception)) is 0);\n  \n}\n\nPT_FUNC(test_exception_catch_all) {\n  \n  volatile bool reached0 = false;\n  volatile bool reached1 = false;\n\n  try {\n    exception_divide(2, 0);\n  } catch (e) {\n    reached0 = true;\n  }\n  \n  try {\n    throw(OtherError, \"Something else went wrong\");\n  } catch (e) {\n    reached1 = true;\n  }\n  \n  PT_ASSERT(reached0);\n  PT_ASSERT(reached1);\n  PT_ASSERT(len(current(Exception)) is 0);\n  \n}\n\nPT_FUNC(test_exception_catch_outer) {\n\n  volatile bool reached0 = false;\n  volatile bool reached1 = false;\n  \n  try {\n\n  PT_ASSERT(len(current(Exception)) is 1);\n\n    try {\n      PT_ASSERT(len(current(Exception)) is 2);\n      exception_divide(2, 0);\n    } catch (e in TypeError) {\n      reached0 = true;\n    }    \n\n    PT_ASSERT(len(current(Exception)) is 1);\n  \n  } catch (e) {\n    reached1  = true;\n  }\n  \n  PT_ASSERT(not reached0);\n  PT_ASSERT(reached1);\n  \n  PT_ASSERT(len(current(Exception)) is 0);\n  \n}\n\nPT_SUITE(suite_exception) {\n  \n  PT_REG(test_exception_throw);\n  PT_REG(test_exception_catch);\n  PT_REG(test_exception_catch_all);\n  PT_REG(test_exception_catch_outer);\n\n}\n\nint main(int argc, char** argv) {\n  \n  pt_add_suite(suite_array);\n  pt_add_suite(suite_box);\n  pt_add_suite(suite_file);\n  pt_add_suite(suite_float);\n  pt_add_suite(suite_filter);\n  pt_add_suite(suite_function);\n  pt_add_suite(suite_int);\n  pt_add_suite(suite_list);\n  pt_add_suite(suite_map);\n#if defined(CELLO_WINDOWS) || defined(CELLO_UNIX)\n  pt_add_suite(suite_mutex);\n#endif\n  pt_add_suite(suite_range);\n  pt_add_suite(suite_ref);\n  pt_add_suite(suite_slice);\n  pt_add_suite(suite_string);\n  pt_add_suite(suite_table);\n#if defined(CELLO_WINDOWS) || defined(CELLO_UNIX)\n  pt_add_suite(suite_thread);\n#endif\n  pt_add_suite(suite_tree);\n  pt_add_suite(suite_tuple);\n  pt_add_suite(suite_type);\n  pt_add_suite(suite_zip);\n  pt_add_suite(suite_exception);\n  \n  pt_run();\n  \n  return 0;\n  \n}\n"
  }
]