diff --git a/build-tools/build.xml b/build-tools/build.xml
index 6b72edbf829..3c546ab1205 100644
--- a/build-tools/build.xml
+++ b/build-tools/build.xml
@@ -8,52 +8,29 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
@@ -74,21 +51,67 @@
-
-
-
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
diff --git a/build-tools/test/longer-examples/Bottles.kt b/build-tools/test/longer-examples/Bottles.kt
new file mode 100644
index 00000000000..3e67d77779a
--- /dev/null
+++ b/build-tools/test/longer-examples/Bottles.kt
@@ -0,0 +1,84 @@
+/**
+ * This example implements the famous "99 Bottles of Beer" program
+ * See http://99-bottles-of-beer.net/
+ *
+ * The point is to print out a song with the following lyrics:
+ *
+ * The "99 bottles of beer" song
+ *
+ * 99 bottles of beer on the wall, 99 bottles of beer.
+ * Take one down, pass it around, 98 bottles of beer on the wall.
+ *
+ * 98 bottles of beer on the wall, 98 bottles of beer.
+ * Take one down, pass it around, 97 bottles of beer on the wall.
+ *
+ * ...
+ *
+ * 2 bottles of beer on the wall, 2 bottles of beer.
+ * Take one down, pass it around, 1 bottle of beer on the wall.
+ *
+ * 1 bottle of beer on the wall, 1 bottle of beer.
+ * Take one down, pass it around, no more bottles of beer on the wall.
+ *
+ * No more bottles of beer on the wall, no more bottles of beer.
+ * Go to the store and buy some more, 99 bottles of beer on the wall.
+ *
+ * Additionally, you can pass the desired initial number of bottles to use (rather than 99)
+ * as a command-line argument
+ */
+package bottles
+
+fun main(args : Array) {
+ if (args.isEmpty) {
+ printBottles(99)
+ }
+ else {
+ try {
+ printBottles(Integer.parseInt(args[0]))
+ }
+ catch (e : NumberFormatException) {
+ System.err?.println("You have passed '${args[0]}' as a number of bottles, " +
+ "but it is not a valid integral number")
+ }
+ }
+}
+
+fun printBottles(bottleCount : Int) {
+ if (bottleCount <= 0) {
+ println("No bottles - no song")
+ return
+ }
+
+ println("The \"${bottlesOfBeer(bottleCount)}\" song\n")
+
+ var bottles = bottleCount
+ while (bottles > 0) {
+ val bottlesOfBeer = bottlesOfBeer(bottles)
+ print("$bottlesOfBeer on the wall, $bottlesOfBeer.\nTake one down, pass it around, ")
+ bottles--
+ println("${bottlesOfBeer(bottles)} on the wall.\n")
+ }
+ println("No more bottles of beer on the wall, no more bottles of beer.\n" +
+ "Go to the store and buy some more, ${bottlesOfBeer(bottleCount)} on the wall.")
+}
+
+fun bottlesOfBeer(count : Int) : String =
+ when (count) {
+ 0 -> "no more bottles"
+ 1 -> "1 bottle"
+ else -> "$count bottles"
+ } + " of beer"
+
+/*
+ * An excerpt from the Standard Library
+ */
+
+// From the std.io package
+// These are simple functions that wrap standard Java API calls
+fun print(message : String) { System.out?.print(message) }
+fun println(message : String) { System.out?.println(message) }
+
+// From the std package
+// This is an extension property, i.e. a property that is defined for the
+// type Array, but does not sit inside the class Array
+val Array.isEmpty : Boolean get() = size == 0
diff --git a/build-tools/test/longer-examples/HtmlBuilder.kt b/build-tools/test/longer-examples/HtmlBuilder.kt
new file mode 100644
index 00000000000..10b90890474
--- /dev/null
+++ b/build-tools/test/longer-examples/HtmlBuilder.kt
@@ -0,0 +1,154 @@
+/**
+ * This is an example of a Type-Safe Groovy-style Builder
+ *
+ * Builders are good for declaratively describing data in your code.
+ * In this example we show how to describe an HTML page in Kotlin.
+ *
+ * See this page for details:
+ * http://confluence.jetbrains.net/display/Kotlin/Type-safe+Groovy-style+builders
+ */
+package html
+
+import java.util.*
+
+fun main(args : Array) {
+ val result =
+ html {
+ head {
+ title {+"XML encoding with Kotlin"}
+ }
+ body {
+ h1 {+"XML encoding with Kotlin"}
+ p {+"this format can be used as an alternative markup to XML"}
+
+ // an element with attributes and text content
+ a(href = "http://jetbrains.com/kotlin") {+"Kotlin"}
+
+ // mixed content
+ p {
+ +"This is some"
+ b {+"mixed"}
+ +"text. For more see the"
+ a(href = "http://jetbrains.com/kotlin") {+"Kotlin"}
+ +"project"
+ }
+ p {+"some text"}
+
+ // content generated from command-line arguments
+ p {
+ +"Command line arguments were:"
+ ul {
+ for (arg in args)
+ li {+arg}
+ }
+ }
+ }
+ }
+ println(result)
+}
+
+trait Element {
+ fun render(builder : StringBuilder, indent : String)
+
+ fun toString() : String? {
+ val builder = StringBuilder()
+ render(builder, "")
+ return builder.toString()
+ }
+}
+
+class TextElement(val text : String) : Element {
+ override fun render(builder : StringBuilder, indent : String) {
+ builder.append("$indent$text\n")
+ }
+}
+
+abstract class Tag(val name : String) : Element {
+ val children = ArrayList()
+ val attributes = HashMap()
+
+ protected fun initTag(tag : T, init : T.() -> Unit) : T {
+ tag.init()
+ children.add(tag)
+ return tag
+ }
+
+ override fun render(builder : StringBuilder, indent : String) {
+ builder.append("$indent<$name${renderAttributes()}>\n")
+ for (c in children) {
+ c.render(builder, indent + " ")
+ }
+ builder.append("$indent$name>\n")
+ }
+
+ private fun renderAttributes() : String? {
+ val builder = StringBuilder()
+ for (a in attributes.keySet()) {
+ builder.append(" $a=\"${attributes[a]}\"")
+ }
+ return builder.toString()
+ }
+}
+
+abstract class TagWithText(name : String) : Tag(name) {
+ fun String.plus() {
+ children.add(TextElement(this))
+ }
+}
+
+class HTML() : TagWithText("html") {
+ fun head(init : Head.() -> Unit) = initTag(Head(), init)
+
+ fun body(init : Body.() -> Unit) = initTag(Body(), init)
+}
+
+class Head() : TagWithText("head") {
+ fun title(init : Title.() -> Unit) = initTag(Title(), init)
+}
+
+class Title() : TagWithText("title")
+
+abstract class BodyTag(name : String) : TagWithText(name) {
+ fun b(init : B.() -> Unit) = initTag(B(), init)
+ fun p(init : P.() -> Unit) = initTag(P(), init)
+ fun h1(init : H1.() -> Unit) = initTag(H1(), init)
+ fun ul(init : UL.() -> Unit) = initTag(UL(), init)
+ fun a(href : String, init : A.() -> Unit) {
+ val a = initTag(A(), init)
+ a.href = href
+ }
+}
+
+class Body() : BodyTag("body")
+class UL() : BodyTag("ul") {
+ fun li(init : LI.() -> Unit) = initTag(LI(), init)
+}
+
+class B() : BodyTag("b")
+class LI() : BodyTag("li")
+class P() : BodyTag("p")
+class H1() : BodyTag("h1")
+class A() : BodyTag("a") {
+ public var href : String
+ get() = attributes["href"]
+ set(value) {
+ attributes["href"] = value
+ }
+}
+
+fun html(init : HTML.() -> Unit) : HTML {
+ val html = HTML()
+ html.init()
+ return html
+}
+
+// An excerpt from the Standard Library
+fun Map.set(key : K, value : V) = this.put(key, value)
+
+fun println(message : Any?) {
+ System.out?.println(message)
+}
+
+fun print(message : Any?) {
+ System.out?.print(message)
+}
diff --git a/build-tools/test/longer-examples/Life.kt b/build-tools/test/longer-examples/Life.kt
new file mode 100644
index 00000000000..509331ebe25
--- /dev/null
+++ b/build-tools/test/longer-examples/Life.kt
@@ -0,0 +1,179 @@
+/**
+ * This is a straightforward implementation of The Game of Life
+ * See http://en.wikipedia.org/wiki/Conway's_Game_of_Life
+ */
+package life
+
+import java.util.Collections.*
+import java.util.*
+
+/*
+ * A field where cells live. Effectively immutable
+ */
+class Field(
+ val width : Int,
+ val height : Int,
+ // This function tells the constructor which cells are alive
+ // if init(i, j) is true, the cell (i, j) is alive
+ init : (Int, Int) -> Boolean
+) {
+ private val live : Array> = Array(height) {i -> Array(width) {j -> init(i, j)}}
+
+ private fun liveCount(i : Int, j : Int)
+ = if (i in 0..height-1 &&
+ j in 0..width-1 &&
+ live[i][j]) 1 else 0
+
+ // How many neighbors of (i, j) are alive?
+ fun liveNeighbors(i : Int, j : Int) =
+ liveCount(i - 1, j - 1) +
+ liveCount(i - 1, j) +
+ liveCount(i - 1, j + 1) +
+ liveCount(i, j - 1) +
+ liveCount(i, j + 1) +
+ liveCount(i + 1, j - 1) +
+ liveCount(i + 1, j) +
+ liveCount(i + 1, j + 1)
+
+ // You can say field[i, j], and this function gets called
+ fun get(i : Int, j : Int) = live[i][j]
+}
+
+/**
+ * This function takes the present state of the field
+ * and return a new field representing the next moment of time
+ */
+fun next(field : Field) : Field {
+ return Field(field.width, field.height) {i, j ->
+ val n = field.liveNeighbors(i, j)
+ if (field[i, j])
+ // (i, j) is alive
+ n in 2..3 // It remains alive iff it has 2 or 3 neighbors
+ else
+ // (i, j) is dead
+ n == 3 // A new cell is born if there are 3 neighbors alive
+ }
+}
+
+/** A few colony examples here */
+fun main(args : Array) {
+ // Simplistic demo
+ printField("***", 3)
+ // "Star burst"
+ printField("""
+ __*__
+ _***_
+ __*__
+ """, 10)
+ // Stable colony
+ printField("""
+ __*__
+ _*_*_
+ __*__
+ """, 3)
+ // Stable from the step 2
+ printField("""
+ __**__
+ __**__
+ __**__
+ """, 3)
+ // Oscillating colony
+ printField("""
+ __**__
+ __**__
+ __**__
+ __**__
+ """, 6)
+ // A fancier oscillating colony
+ printField("""
+ ---------------
+ ---***---***---
+ ---------------
+ -*----*-*----*-
+ -*----*-*----*-
+ -*----*-*----*-
+ ---***---***---
+ ---------------
+ ---***---***---
+ -*----*-*----*-
+ -*----*-*----*-
+ -*----*-*----*-
+ ---------------
+ ---***---***---
+ ---------------
+ """, 10)
+}
+
+// UTILITIES
+
+fun printField(s : String, steps : Int) {
+ var field = makeField(s)
+ for (step in 1..steps) {
+ println("Step: $step")
+ for (i in 0..field.height-1) {
+ for (j in 0..field.width-1) {
+ print(if (field[i, j]) "*" else " ")
+ }
+ println("")
+ }
+ field = next(field)
+ }
+}
+
+fun makeField(s : String) : Field {
+ val lines = s.split("\n").sure()
+ val w = max(lines.toList(), comparator {o1, o2 ->
+ val l1 : Int = o1?.size ?: 0
+ val l2 = o2?.size ?: 0
+ l1 - l2
+ }).sure()
+ val data = Array(lines.size) {Array(w.size) {false}}
+
+ // workaround
+ for (i in data.indices) {
+ data[i] = Array(w.size) {false}
+ for (j in data[i].indices)
+ data[i][j] = false
+ }
+
+ for (line in lines.indices) {
+ for (x in lines[line].indices) {
+ val c = lines[line].sure()[x]
+ data[line][x] = c == '*'
+ }
+ }
+
+ return Field(w.size, lines.size) {i, j -> data[i][j]}
+}
+
+// An excerpt from the Standard Library
+val String?.indices : IntRange get() = IntRange(0, this.sure().size)
+
+fun Map.set(k : K, v : V) { put(k, v) }
+
+fun comparator (f : (T, T) -> Int) : Comparator = object : Comparator {
+ override fun compare(o1 : T, o2 : T) : Int = f(o1, o2)
+}
+
+fun println(message : Any?) {
+ System.out?.println(message)
+}
+
+fun print(message : Any?) {
+ System.out?.print(message)
+}
+
+val Array.isEmpty : Boolean get() = size == 0
+
+fun String.split(s : String) = (this as java.lang.String).split(s)
+
+val String.size : Int
+ get() = length
+
+fun > Array.to(result: C) : C {
+ for (elem in this)
+ result.add(elem)
+ return result
+}
+
+fun Array.toList() : List = this.to(ArrayList())
diff --git a/build-tools/test/longer-examples/Maze.kt b/build-tools/test/longer-examples/Maze.kt
new file mode 100644
index 00000000000..f6dbb9eed3e
--- /dev/null
+++ b/build-tools/test/longer-examples/Maze.kt
@@ -0,0 +1,238 @@
+/**
+ * Let's Walk Through a Maze.
+ *
+ * Imagine there is a maze whose walls are the big 'O' letters.
+ * Now, I stand where a big 'I' stands and some cool prize lies
+ * somewhere marked with a '$' sign. Like this:
+ *
+ * OOOOOOOOOOOOOOOOO
+ * O O
+ * O$ O O
+ * OOOOO O
+ * O O
+ * O OOOOOOOOOOOOOO
+ * O O I O
+ * O O
+ * OOOOOOOOOOOOOOOOO
+ *
+ * I want to get the prize, and this program helps me do so as soon
+ * as I possibly can by finding a shortest path through the maze.
+ */
+package maze
+
+import java.util.Collections.*
+import java.util.*
+
+/**
+ * This function looks for a path from max.start to maze.end through
+ * free space (a path does not go through walls). One can move only
+ * straightly up, down, left or right, no diagonal moves allowed.
+ */
+fun findPath(maze : Maze) : List<#(Int, Int)>? {
+ val previous = HashMap<#(Int, Int), #(Int, Int)>
+
+ val queue = LinkedList<#(Int, Int)>
+ val visited = HashSet<#(Int, Int)>
+
+ queue.offer(maze.start)
+ visited.add(maze.start)
+ while (!queue.isEmpty()) {
+ val cell = queue.poll()
+ if (cell == maze.end) break
+
+ for (newCell in maze.neighbors(cell._1, cell._2)) {
+ if (newCell in visited) continue
+ previous[newCell] = cell
+ queue.offer(newCell)
+ visited.add(cell)
+ }
+ }
+
+ if (previous[maze.end] == null) return null
+
+ val path = ArrayList<#(Int, Int)>()
+ var current = previous[maze.end]
+ while (current != maze.start) {
+ path.add(0, current)
+ current = previous[current]
+ }
+ return path
+}
+
+/**
+ * Find neighbors of the (i, j) cell that are not walls
+ */
+fun Maze.neighbors(i : Int, j : Int) : List<#(Int, Int)> {
+ val result = ArrayList<#(Int, Int)>
+ addIfFree(i - 1, j, result)
+ addIfFree(i, j - 1, result)
+ addIfFree(i + 1, j, result)
+ addIfFree(i, j + 1, result)
+ return result
+}
+
+fun Maze.addIfFree(i : Int, j : Int, result : List<#(Int, Int)>) {
+ if (i !in 0..height-1) return
+ if (j !in 0..width-1) return
+ if (walls[i][j]) return
+
+ result.add(#(i, j))
+}
+
+/**
+ * A data class that represents a maze
+ */
+class Maze(
+ // Number or columns
+ val width : Int,
+ // Number of rows
+ val height : Int,
+ // true for a wall, false for free space
+ val walls : Array>,
+ // The starting point (must not be a wall)
+ val start : #(Int, Int),
+ // The target point (must not be a wall)
+ val end : #(Int, Int)
+) {
+}
+
+/** A few maze examples here */
+fun main(args : Array) {
+ printMaze("I $")
+ printMaze("I O $")
+ printMaze("""
+ O $
+ O
+ O
+ O
+ O I
+ """)
+ printMaze("""
+ OOOOOOOOOOO
+ O $ O
+ OOOOOOO OOO
+ O O
+ OOOOO OOOOO
+ O O
+ O OOOOOOOOO
+ O OO
+ OOOOOO IO
+ """)
+ printMaze("""
+ OOOOOOOOOOOOOOOOO
+ O O
+ O$ O O
+ OOOOO O
+ O O
+ O OOOOOOOOOOOOOO
+ O O I O
+ O O
+ OOOOOOOOOOOOOOOOO
+ """)
+}
+
+// UTILITIES
+
+fun printMaze(str : String) {
+ val maze = makeMaze(str)
+
+ println("Maze:")
+ val path = findPath(maze)
+ for (i in 0..maze.height - 1) {
+ for (j in 0..maze.width - 1) {
+ val cell = #(i, j)
+ print(
+ if (maze.walls[i][j]) "O"
+ else if (cell == maze.start) "I"
+ else if (cell == maze.end) "$"
+ else if (path != null && path.contains(cell)) "~"
+ else " "
+ )
+ }
+ println("")
+ }
+ println("Result: " + if (path == null) "No path" else "Path found")
+ println("")
+}
+
+/**
+ * A maze is encoded in the string s: the big 'O' letters are walls.
+ * I stand where a big 'I' stands and the prize is marked with
+ * a '$' sign.
+ *
+ * Example:
+ *
+ * OOOOOOOOOOOOOOOOO
+ * O O
+ * O$ O O
+ * OOOOO O
+ * O O
+ * O OOOOOOOOOOOOOO
+ * O O I O
+ * O O
+ * OOOOOOOOOOOOOOOOO
+ */
+fun makeMaze(s : String) : Maze {
+ val lines = s.split("\n").sure()
+ val w = max(lines.toList(), comparator {o1, o2 ->
+ val l1 : Int = o1?.size ?: 0
+ val l2 = o2?.size ?: 0
+ l1 - l2
+ }).sure()
+ val data = Array>(lines.size) {Array(w.size) {false}}
+
+ var start : #(Int, Int)? = null
+ var end : #(Int, Int)? = null
+
+ for (line in lines.indices) {
+ for (x in lines[line].indices) {
+ val c = lines[line].sure()[x]
+ data[line][x] = c == 'O'
+ when (c) {
+ 'I' -> start = #(line, x)
+ '$' -> end = #(line, x)
+ else -> {}
+ }
+ }
+ }
+
+ if (start == null) {
+ throw IllegalArgumentException("No starting point in the maze (should be indicated with 'I')")
+ }
+
+ if (end == null) {
+ throw IllegalArgumentException("No goal point in the maze (should be indicated with a '$' sign)")
+ }
+
+ return Maze(w.size, lines.size, data, start.sure(), end.sure())
+}
+
+// An excerpt from the Standard Library
+val String?.indices : IntRange get() = IntRange(0, this.sure().size)
+
+val String.size : Int
+ get() = length
+
+fun Map.set(k : K, v : V) { put(k, v) }
+
+fun comparator (f : (T, T) -> Int) : Comparator = object : Comparator {
+ override fun compare(o1 : T, o2 : T) : Int = f(o1, o2)
+}
+
+fun String.split(s : String) = (this as java.lang.String).split(s)
+
+fun println(message : Any?) {
+ System.out?.println(message)
+}
+
+fun print(message : Any?) {
+ System.out?.print(message)
+}
+
+fun > Array.to(result: C) : C {
+ for (elem in this)
+ result.add(elem)
+ return result
+}
+
+fun Array.toList() : List = this.to(ArrayList())