diff --git a/examples/.idea/ant.xml b/examples/.idea/ant.xml
new file mode 100644
index 00000000000..2581ca3fe84
--- /dev/null
+++ b/examples/.idea/ant.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/examples/.idea/compiler.xml b/examples/.idea/compiler.xml
new file mode 100644
index 00000000000..97c9ca5c8b0
--- /dev/null
+++ b/examples/.idea/compiler.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/.idea/copyright/profiles_settings.xml b/examples/.idea/copyright/profiles_settings.xml
new file mode 100644
index 00000000000..3572571ad83
--- /dev/null
+++ b/examples/.idea/copyright/profiles_settings.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/.idea/encodings.xml b/examples/.idea/encodings.xml
new file mode 100644
index 00000000000..e206d70d859
--- /dev/null
+++ b/examples/.idea/encodings.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/examples/.idea/misc.xml b/examples/.idea/misc.xml
new file mode 100644
index 00000000000..778bf31bc07
--- /dev/null
+++ b/examples/.idea/misc.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/.idea/modules.xml b/examples/.idea/modules.xml
new file mode 100644
index 00000000000..4b3b58ae48d
--- /dev/null
+++ b/examples/.idea/modules.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/examples/.idea/projectCodeStyle.xml b/examples/.idea/projectCodeStyle.xml
new file mode 100644
index 00000000000..8b60e241aaf
--- /dev/null
+++ b/examples/.idea/projectCodeStyle.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
diff --git a/examples/.idea/uiDesigner.xml b/examples/.idea/uiDesigner.xml
new file mode 100644
index 00000000000..3b000203088
--- /dev/null
+++ b/examples/.idea/uiDesigner.xml
@@ -0,0 +1,125 @@
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
+
diff --git a/examples/.idea/vcs.xml b/examples/.idea/vcs.xml
new file mode 100644
index 00000000000..275077f8255
--- /dev/null
+++ b/examples/.idea/vcs.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/examples/examples.iml b/examples/examples.iml
new file mode 100644
index 00000000000..26a958a9c8a
--- /dev/null
+++ b/examples/examples.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/src/BinaryTree.jetl b/examples/src/BinaryTree.jetl
new file mode 100644
index 00000000000..8327a968db0
--- /dev/null
+++ b/examples/src/BinaryTree.jetl
@@ -0,0 +1,195 @@
+class BinaryTree : IMutableSet {
+ private class TreeNode(
+ var value : T, var parent : TreeNode
+ ) {
+ var left : TreeNode
+ var right : TreeNode
+
+ }
+
+ private val compare : MatchableComparison
+ private var root : TreeNode
+ private var version = 0
+
+ override var size : Int { get; private set; }
+
+ this(compare : Comparison) {
+ this.compare = asMatchableComparison(comparison)
+ }
+
+ this() : this(naturalOrder) {
+ }
+
+ private extension [operator] fun T.compareTo(other : T) : Int = compare(this, other)
+
+ override fun contains(item : T) : Boolean {
+ return contains(root, item)
+
+ fun contains(node : TreeNode, item : T) : Boolean {
+ if (node == null) return false
+ compare(item, node.value) match {
+ case EQ => true
+ case LS => contains(node.left, item)
+ case GT => contains(node.right, item)
+ }
+ }
+ }
+
+ override fun add(item : T) : Boolean {
+ if (add(ref root, null)) {
+ size++
+ version++
+ return true
+ }
+ return false
+
+ // In principle, this has access to item anyway, but then it's unreachable code
+ // BAD: the naive implementation of ref will create H(T) ref objects, but can be optimized to create only one
+ fun add(ref node : TreeNode, parent : TreeNode) : Boolean {
+ if (node == null) {
+ node = TreeNode(item, parent)
+ return true
+ }
+ compare(item, node.value) match {
+ case EQ => false
+ case LS => add(ref node.left, node)
+ case GT => add(ref node.right, node)
+ }
+ }
+
+ // In principle, this has access to item anyway
+ fun addNoRef(node : TreeNode) : Boolean {
+ if (node == null) {
+ root = TreeNode(item, null)
+ return true
+ }
+ compare(item, node.value) match {
+ case EQ => return false
+ case LS =>
+ if (node.left == null) {
+ node.left = TreeNode(item, node)
+ return true
+ } else return add(node.left)
+ case GT =>
+ if (node.right == null) {
+ node.right = TreeNode(item, node)
+ return true
+ } else return add(node.right)
+ }
+ }
+ }
+
+ override fun remove(item : T) : Boolean {
+ val toRemove = find(root, item)
+ if (toRemove == null) return false
+ remove(toRemove)
+ size--
+ version++
+ return true
+
+ fun find(node : TreeNode) : TreeNode {
+ if (node == null) return null
+ compare(item, node.value) match {
+ case EQ => node
+ case LS => find(node.left)
+ case GT => find(node.right)
+ }
+ }
+ }
+
+ private fun remove(node : TreeNode) {
+ node match {
+ case TreeNode(null, null) => replace(node, null)
+ case TreeNode(null, right) => replace(node, right)
+ case TreeNode(left, null) => replace(node, left)
+ case TreeNode(left, right) => {
+ val min = min(node.right)
+ node.value = min.value
+ remove(min)
+ }
+ }
+
+ fun replace(node : TreeNode, replace : TreeNode) {
+ if (node == root) {
+ root = replace
+ return
+ }
+ if (node.parent.left == node) {
+ node.parent.left = replace
+ } else if (node.parent.right == node) {
+ node.parent.right = replace
+ } else Assert(false)
+ }
+ }
+
+ // Relies on tail-recursion optimization
+ private fun min(node : TreeNode) {
+ if (node.left == null) node else min(node.left)
+ }
+
+ override fun iterator() : IIterator = mutableIterator()
+
+ override fun mutableIterator() : IMutableIterator = new IMutableIterator() {
+ val version = BinaryTree.this.version
+ val down = Stack()
+ val up = Stack()
+ var lastNode : TreeNode
+
+ this() {
+ if (root != null)
+ down.push(root)
+ }
+
+ override fun next() : T {
+ if (!hasNext)
+ throw NoMoreElementsException()
+ checkVersion()
+
+ lastNode = nextNode()
+ return lastNode.value
+ }
+
+ private fun nextNode() : TreeNode {
+ while (true) {
+ if (!down.isEmpty) {
+ val curNode = down.pop()
+ if (curNode.left != null) {
+ up.push(curNode)
+ down.push(curNode.left)
+ } else {
+ if (curNode.right != null) {
+ down.push(curNode.right)
+ }
+ return curNode;
+ }
+ } else {
+ val curNode = up.pop()
+ if (curNode.right != null) {
+ down.push(curNode.right)
+ }
+ return curNode
+ }
+ }
+ }
+
+ override val hasNext : Boolean {
+ get() = !down.isEmpty || !up.isEmpty
+ }
+
+ override fun remove() {
+ checkVersion()
+ if (lastNode == null)
+ throw IterationException("Nothing to remove")
+ remove(lastNode)
+ version++
+ BinaryTree.this.version = version
+ }
+
+ private fun checkVersion() {
+ if (version != BinaryTree.this.version) {
+ throw ConcurrentModificationException()
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/examples/src/Color.jetl b/examples/src/Color.jetl
new file mode 100644
index 00000000000..2c2c4278ff1
--- /dev/null
+++ b/examples/src/Color.jetl
@@ -0,0 +1,5 @@
+enum class Color(val r, g, b : Int) {
+ RED : Color(255, 0, 0)
+ GREEN : Color(0, 255, 0)
+ BLUE : Color(0, 0, 255)
+}
\ No newline at end of file
diff --git a/examples/src/Graph.jetl b/examples/src/Graph.jetl
new file mode 100644
index 00000000000..4ed01564310
--- /dev/null
+++ b/examples/src/Graph.jetl
@@ -0,0 +1,60 @@
+sealed class Vertex(val data : V)
+
+sealed class Edge(val from : V, val data : E, val to : V)
+
+class Graph {
+
+ private val mutableEdges = new ArrayList>() // type is ArrayList, but I want IMutableList
+/* options:
+ private val edges : IMutableList> = new ArrayList>()
+ private val edges : IMutableList> = new ArrayList() // not an erasure, but a request to infer parameters
+*/
+
+ private val mutableVertices = new HashSet>()
+
+ val edges : IList> = mutableEdges;
+ val vertices : ISet> = mutableVertices;
+
+ fun addEdge(from : V, data : E, to : V) {
+ mutableEdges.add(new Edge(from, data, to)) // constructor parameters are inferred
+ }
+ fun addVertex(v : V) {
+ mutableEdges.add(new Edge(from, data, to)) // constructor parameters are inferred
+ }
+
+ fun neighbours(v : Vertex) = edges.filter{it.from == v}.map{it.to} // type is IIterable>
+
+ fun dfs(handler : {V => ()}) {
+ val visited = new HashSet>()
+ vertices.foreach{dfs(it, visited, handler)}
+
+ fun dfs(current : Vertex, visited : ISet>, handler : {V => ()}) {
+ if (!visited.add(current))
+ return
+ handler(current)
+ neighbours(current).foreach{dfs(it, visited, handler)}
+ }
+ }
+
+ public fun traverse(pending : IPushPop>, visited : ISet>, handler : {V => ()}) {
+ vertices.foreach {
+ if (!visited.add(it))
+ continue
+ pending.push(it)
+ while (!pending.isEmpty) {
+ val current = pending.pop()
+ handler(current);
+ neighbours(current).foreach { n =>
+ if (visited.add(n)) {
+ pending.push(n)
+ }
+ }
+ /* alternative
+ pending->push(neighbours(current).filter{n => !visited[n])})
+ // -> means that if push(x : T) and actual parameter y is IIterable, this compiles into
+ y.foreach{ n => push(n) }
+ */
+ }
+ }
+ }
+}
diff --git a/examples/src/IPushPop.jetl b/examples/src/IPushPop.jetl
new file mode 100644
index 00000000000..9065c1e0d10
--- /dev/null
+++ b/examples/src/IPushPop.jetl
@@ -0,0 +1,5 @@
+interface class IPushPop {
+ val isEmpty : Boolean
+ fun push(item : T)
+ fun pop() : T
+}
\ No newline at end of file
diff --git a/examples/src/Queue.jetl b/examples/src/Queue.jetl
new file mode 100644
index 00000000000..bbbbe1dc8c2
--- /dev/null
+++ b/examples/src/Queue.jetl
@@ -0,0 +1,33 @@
+sealed class Queue : IPushPop {
+ private class Item(val data : T, var next : Item)
+
+ private var head : Item = null
+ private var tail : Item = null
+
+ override fun push(item : T) {
+ val i = new Item(item)
+ if (tail == null) {
+ head = i
+ tail = head
+ } else {
+ tail.next = i
+ tail = i
+ }
+ }
+
+ override fun pop() =
+ if (head == null)
+ throw new UnderflowException()
+ else {
+ val result = head.data
+ head = head.next
+ if (head == null)
+ tail = null
+ result
+ }
+
+ override val isEmpty {
+ get() = head == null
+ }
+
+}
\ No newline at end of file
diff --git a/examples/src/Stack.jetl b/examples/src/Stack.jetl
new file mode 100644
index 00000000000..2e0803f543a
--- /dev/null
+++ b/examples/src/Stack.jetl
@@ -0,0 +1,13 @@
+sealed class Stack : IPushPop {
+ private val data = new ArrayList();
+
+ override fun push(item : T) {
+ data.add(item) // Problem: I would like to write push(...) = data.add(...), but the types do not match
+ }
+
+ override fun pop() = data.removeLast()
+
+ override val isEmpty { // TODO: This is UGLY :(
+ get() = data.isEmpty
+ }
+}
\ No newline at end of file
diff --git a/examples/src/UnionFind.jetl b/examples/src/UnionFind.jetl
new file mode 100644
index 00000000000..a817d3383fe
--- /dev/null
+++ b/examples/src/UnionFind.jetl
@@ -0,0 +1,34 @@
+class UnionFind {
+ private val data = IMutableList()
+
+ fun add() : Int {
+ val size = data.size
+ data.add(size)
+ size
+ }
+
+ private fun parent(x : Int) : Int {
+ val p = data[x];
+ if (p == x) {
+ return x;
+ }
+ val result = parent(p);
+ data[x] = result;
+ }
+
+ fun union(a : Int, b : Int) {
+ val pa = parent(a)
+ val pb = parent(b)
+ if (pa != pb) {
+ if (Random.nextInt().isOdd) {
+ data[pb] = pa
+ } else {
+ data[pa] = pb
+ }
+ }
+ }
+}
+
+extension val Int.isOdd : Boolean {
+ get() = this % 2 != 0
+}
\ No newline at end of file
diff --git a/examples/src/collections/ArrayList.jetl b/examples/src/collections/ArrayList.jetl
new file mode 100644
index 00000000000..ef3575ecba9
--- /dev/null
+++ b/examples/src/collections/ArrayList.jetl
@@ -0,0 +1,77 @@
+class ArrayList : IMutableList {
+ private var data = MutableArray(10)
+ private var used = 0
+ private var version = 0
+
+ override fun iterator() : IIterator = mutableIterator()
+
+ override fun mutableIterator() : IMutableIterator = new IMutableIterator() { // T is inferred
+ private val index = 0
+ private var myVersion = version
+
+ private fun checkVersion() {
+ if (version != myVersion)
+ throw new ConcurrentModificationException()
+ }
+
+ override fun next() {
+ checkVersion()
+ if (hasNext)
+ throw new NoMoreElementsException()
+ data[index++]
+ }
+
+ override val hasNext {
+ get() = index < used
+ }
+
+ override fun remove() {
+ checkVersion()
+ val result = ArrayList.this.remove(index - 1)
+ myVersion = version
+ result
+ }
+ }
+
+ override fun get(index : Int) {
+ checkIndex(index)
+ data[index]
+ }
+
+ private fun checkIndex(index : Int) {
+ if (index > used)
+ throw new IndexOutOfBoundsException(index)
+ }
+
+ override val isEmpty {
+ get() = used == 0
+ }
+
+ override val size {
+ get() = used
+ }
+
+ override fun set(index : Int, value : T) {
+ checkIndex(index)
+ var result = data[index]
+ data[index] = value
+ result
+ }
+
+ override fun add(index : Int, value : T) {
+ ensureSize(used + 1)
+ if (index == used) {
+ data[used++] = value
+ } else if (index < used) {
+ for (i in used-1..index) // backwards, special operator... Need to optimize this to be a real indexed loop
+ data[i + 1] = data[i]
+ data[index] = value
+ used++
+ } else throw IndexOutOfBoundsException(index)
+ }
+
+ override fun remove(index : Int) {
+ for (i in index..used-1)
+ data[i] = data[i + 1]
+ }
+}
\ No newline at end of file
diff --git a/examples/src/collections/IIterable.jetl b/examples/src/collections/IIterable.jetl
new file mode 100644
index 00000000000..2ef19c0caed
--- /dev/null
+++ b/examples/src/collections/IIterable.jetl
@@ -0,0 +1,3 @@
+interface class IIterable {
+ fun iterator() : IIterator
+}
diff --git a/examples/src/collections/IIterator.jetl b/examples/src/collections/IIterator.jetl
new file mode 100644
index 00000000000..7717e94062f
--- /dev/null
+++ b/examples/src/collections/IIterator.jetl
@@ -0,0 +1,4 @@
+interface class IIterator {
+ fun next() : T
+ val hasNext : Boolean
+}
diff --git a/examples/src/collections/IList.jetl b/examples/src/collections/IList.jetl
new file mode 100644
index 00000000000..9e03010ae58
--- /dev/null
+++ b/examples/src/collections/IList.jetl
@@ -0,0 +1,4 @@
+interface class IList : IIterable, ISizable {
+ [operator] fun get(index : Int) : T
+ val isEmpty : Boolean
+}
\ No newline at end of file
diff --git a/examples/src/collections/IMutableIterable.jetl b/examples/src/collections/IMutableIterable.jetl
new file mode 100644
index 00000000000..a60bf71c95c
--- /dev/null
+++ b/examples/src/collections/IMutableIterable.jetl
@@ -0,0 +1,3 @@
+interface class IMutableIterable : IIterable {
+ fun mutableIterator() : IMutableIterator
+}
\ No newline at end of file
diff --git a/examples/src/collections/IMutableIterator.jetl b/examples/src/collections/IMutableIterator.jetl
new file mode 100644
index 00000000000..c00e01c3eaa
--- /dev/null
+++ b/examples/src/collections/IMutableIterator.jetl
@@ -0,0 +1,3 @@
+interface class IMutableIterator : IIterator {
+ fun remove() : T
+}
\ No newline at end of file
diff --git a/examples/src/collections/IMutableList.jetl b/examples/src/collections/IMutableList.jetl
new file mode 100644
index 00000000000..2b308d8ca86
--- /dev/null
+++ b/examples/src/collections/IMutableList.jetl
@@ -0,0 +1,6 @@
+interface class IMutableList : IList, IMutableIterable {
+ fun set(index : Int, value : T) : T
+ fun add(index : Int, value : T)
+ fun remove(index : Int) : T
+ fun mutableIterator() : IMutableIterator
+}
\ No newline at end of file
diff --git a/examples/src/collections/IMutableSet.jetl b/examples/src/collections/IMutableSet.jetl
new file mode 100644
index 00000000000..aa4edbee412
--- /dev/null
+++ b/examples/src/collections/IMutableSet.jetl
@@ -0,0 +1,4 @@
+interface class IMutableSet : ISet, IMutableIterable {
+ fun add(item : T) : Boolean
+ fun remove(item : T) : Boolean
+}
\ No newline at end of file
diff --git a/examples/src/collections/ISet.jetl b/examples/src/collections/ISet.jetl
new file mode 100644
index 00000000000..8c32364dcf9
--- /dev/null
+++ b/examples/src/collections/ISet.jetl
@@ -0,0 +1,3 @@
+interface class ISet : IIterable, ISized {
+ fun contains(item : T) : Boolean
+}
diff --git a/examples/src/collections/ISized.jetl b/examples/src/collections/ISized.jetl
new file mode 100644
index 00000000000..0b724f702d5
--- /dev/null
+++ b/examples/src/collections/ISized.jetl
@@ -0,0 +1,3 @@
+interface class ISized {
+ val size : Int
+}
\ No newline at end of file
diff --git a/examples/src/collections/LinkedList.jetl b/examples/src/collections/LinkedList.jetl
new file mode 100644
index 00000000000..ca16db4d89a
--- /dev/null
+++ b/examples/src/collections/LinkedList.jetl
@@ -0,0 +1,73 @@
+class LinkedList : IMutableList {
+ private class Item(var value : Item) {
+ var next : Item
+ var previous : Item
+ }
+
+ private var head : Item = null
+ private var tail : Item = null
+ override var size { get; private set; }
+
+ override fun add(index : Int, value : T) {
+ size++
+ checkIndex(index)
+ val newItem = Item(value)
+ if (index == 0) {
+ newItem.next = head
+ head = newItem
+ if (tail == null) {
+ tail = head
+ }
+ } else {
+ var insertAfter = itemAt(index)
+ newItem.next = insertAfter.next
+ insertAfter.next = newItem
+ if (tail == insertAfter) {
+ tail = newItem
+ }
+ }
+ }
+
+ private fun checkIndex(index : Int) {
+ if (!index in [0..size-1]) {
+ throw IndexOutOfBoundsException(index)
+ }
+ }
+
+ override fun remove(index : Int) : T {
+ checkIndex(index)
+ val item = itemAt(index)
+ if (item == head) {
+ head = item.next
+ if (head == null)
+ tail= null
+ } else {
+ item.previous.next = item.next
+ if (item.next == null) {
+ item.next.previous = item.previous
+ } else {
+ tail = tail.previous
+ }
+ }
+ size--
+ return item.value
+ }
+
+ override fun set(index : Int, value : T) : T {
+ checkIndex(index)
+ val item = itemAt(index)
+ val result = item.value
+ item.value = value
+ return result
+ }
+
+ private fun itemAt(index : Int) {
+ var result = head
+ for (i in [1..index]) {
+ result = result.next
+ }
+ return result
+ }
+
+ override fun mutableIterator() : IMutableIterator
+}
\ No newline at end of file
diff --git a/examples/src/collections/List.jetl b/examples/src/collections/List.jetl
new file mode 100644
index 00000000000..14cd75594d3
--- /dev/null
+++ b/examples/src/collections/List.jetl
@@ -0,0 +1,27 @@
+enum class List(theSize : Int) : IList {
+ Nil : List(0)
+
+ Cons(val value : T, val tail : List) : List(1 + tail.size)
+
+ override val size : Int {
+ get() = theSize
+ }
+
+ override val isEmpty : Boolean {
+ get() = this == Nil
+ }
+
+ override fun iterator() = new IIterator() {
+ private var current = List.this
+
+ override val hasNext {
+ get() = current == Nil
+ }
+
+ override fun next() {
+ val result = current.value
+ current = current.tail
+ return result
+ }
+ }
+}
\ No newline at end of file
diff --git a/examples/src/map/IMap.jetl b/examples/src/map/IMap.jetl
new file mode 100644
index 00000000000..4f91bd5e996
--- /dev/null
+++ b/examples/src/map/IMap.jetl
@@ -0,0 +1,4 @@
+interface class IMap {
+
+
+}
\ No newline at end of file
diff --git a/examples/src/priorityqueues/BinaryHeap.jetl b/examples/src/priorityqueues/BinaryHeap.jetl
new file mode 100644
index 00000000000..1d54ca15cae
--- /dev/null
+++ b/examples/src/priorityqueues/BinaryHeap.jetl
@@ -0,0 +1,104 @@
+class BinaryHeap : IPriorityQueue {
+ private val data : IMutableList
+ private val compare : Comparison
+
+ fun this(data : IIterable, compare : Comparison = naturalOrder) {
+ this.compare = compare
+ this.data = ArrayList(data)
+ siftDown(* this.data.size / 2 .. 0)
+/*
+ for (val i in data.size / 2 .. 0) {
+ siftDown(i)
+ }
+*/
+ }
+
+ fun this(compare : Comparison) {
+ this.compare = compare
+ this.data = ArrayList()
+ }
+
+ fun this() {
+ this.data = ArrayList()
+ Assert(T is IComparable)
+ this.comparator = naturalOrder
+ }
+
+ override fun extract() : T {
+ if (this.isEmpty)
+ throw UnderflowException()
+ data.swap(0, data.lastIndex)
+ data.remove(data.lastIndex)
+ siftDown(0)
+ }
+
+ override fun add(item : T) {
+ data.add(item)
+ siftUp(data.lastItem)
+ }
+
+ private fun siftDown(index : Int) {
+ var current = index
+ while (current.left.exists) {
+ var min = current
+ if (current.left.value < min.value) {
+ min = current.left
+ }
+ if (current.right.exists && current.right.value < min.value) {
+ min = current.right
+ }
+ if (min == current) break
+ data.swap(min, current)
+ current = min
+ }
+ }
+
+ private fun siftUp(index : Int) {
+ if (!current.exists) return
+ var current = index
+ while (current.parent.exists) {
+ if (current.value < current.parent.value) {
+ data.swap(current, current.parent)
+ current = current.parent
+ }
+ }
+ }
+
+ private extension HeapIndex for Int {
+ val parent : Int {
+ get() = (this - 1) / 2
+ }
+
+ val left : Int {
+ get() = this * 2 + 1
+ }
+
+ val right : Int {
+ get() = this * 2 + 2
+ }
+
+ val value : T {
+ get() = data[this]
+ }
+
+ val exists : Boolean {
+ get() = (this < data.size) && (this >= 0)
+ }
+ }
+
+ private extension for T {
+ [operator] fun compareTo(other : T) : Int = compare(this, other)
+ }
+
+}
+
+extension fun IMutableList.swap(a : Int, b : Int) {
+ val t = this[a]
+ this[a] = this[b]
+ this[b] = t
+}
+
+extension val IList.lastIndex : Int {
+ get() = this.size - 1
+}
+
diff --git a/examples/src/priorityqueues/IPriorityQueue.jetl b/examples/src/priorityqueues/IPriorityQueue.jetl
new file mode 100644
index 00000000000..01e5f357eaf
--- /dev/null
+++ b/examples/src/priorityqueues/IPriorityQueue.jetl
@@ -0,0 +1,5 @@
+interface class IPriorityQueue {
+ fun extract() : T
+ fun add(item : T)
+ val isEmpty : Boolean
+}
diff --git a/examples/src/priorityqueues/PriorityQueueAsPushPop.jetl b/examples/src/priorityqueues/PriorityQueueAsPushPop.jetl
new file mode 100644
index 00000000000..0bbc006f7e1
--- /dev/null
+++ b/examples/src/priorityqueues/PriorityQueueAsPushPop.jetl
@@ -0,0 +1,7 @@
+class PriorityQueueAsPushPop wraps(wrapped : IPriorityQueue) : IPushPop {
+ override fun pop() = wrapped.extract()
+ override fun push(item : T) = wrapped.add(item)
+ override val isEmpty {
+ get() = wrapped.isEmpty
+ }
+}
\ No newline at end of file
diff --git a/examples/src/util/Comparison.jetl b/examples/src/util/Comparison.jetl
new file mode 100644
index 00000000000..1318b496d54
--- /dev/null
+++ b/examples/src/util/Comparison.jetl
@@ -0,0 +1,19 @@
+type Comparison = {T, T => Int}
+
+fun naturalOrder>(a : T, b : T) : Int = a.compareTo(b)
+
+fun castingNaturalOrder(a : Object, b : Object) : Int = a.as>.compareTo(b.as>)
+
+enum class ComparisonResult {
+ LS,EQ, GR
+}
+
+type MatchableComparison = {T, T, => ComparisonResult}
+
+fun asMatchableComparison(cmp : Comparison) : MatchableComparison = {a, b =>
+ val res = cmp(a, b)
+ if (res == 0) return ComparisonResult.EQ
+ if (res < 0) return ComparisonResult.LS
+ return ComparisonResult.GR
+}
+
diff --git a/examples/src/util/IComparable.jetl b/examples/src/util/IComparable.jetl
new file mode 100644
index 00000000000..79d19a364e6
--- /dev/null
+++ b/examples/src/util/IComparable.jetl
@@ -0,0 +1,3 @@
+interface class IComparable {
+ fun compareTo(other : T) : Int
+}
\ No newline at end of file