diff --git a/build-tools/ant/src/org/jetbrains/jet/buildtools/ant/KotlinBytecodeCompilerTask.java b/build-tools/ant/src/org/jetbrains/jet/buildtools/ant/KotlinBytecodeCompilerTask.java new file mode 100644 index 00000000000..6b7a3027942 --- /dev/null +++ b/build-tools/ant/src/org/jetbrains/jet/buildtools/ant/KotlinBytecodeCompilerTask.java @@ -0,0 +1,46 @@ +package org.jetbrains.jet.buildtools.ant; + +import static org.jetbrains.jet.buildtools.core.Util.*; +import org.apache.tools.ant.Task; +import org.jetbrains.jet.buildtools.core.KotlinBytecodeCompiler; + +import java.io.File; + + +/** + * Kotlin bytecode compiler Ant task. + * + * See + * http://evgeny-goldin.org/javadoc/ant/tutorial-writing-tasks.html + * http://evgeny-goldin.org/javadoc/ant/Tasks/javac.html - attribute names should be similar to {@code }. + */ +public class KotlinBytecodeCompilerTask extends Task { + + private File srcdir; + private File file; + private File destdir; + + public void setSrcdir ( File srcdir ) { this.srcdir = srcdir; } + public void setFile ( File file ) { this.file = file; } + public void setDestdir ( File destdir ) { this.destdir = destdir; } + + + @Override + public void execute() { + + if ( this.destdir == null ) { + throw new RuntimeException( "\"destdir\" attribute is not specified" ); + } + + if (( this.srcdir != null ) || ( this.file != null )) { + String src = getPath( this.srcdir != null ? this.srcdir : this.file ); + String dest = getPath( this.destdir ); + + log( String.format( "[%s] => [%s]", src, dest )); + KotlinBytecodeCompiler.compileSources( src, dest ); + } + else { + throw new RuntimeException( String.format( "Operation is not supported" )); + } + } +} diff --git a/build-tools/ant/src/org/jetbrains/jet/buildtools/ant/KotlinJavaScriptCompilerTask.java b/build-tools/ant/src/org/jetbrains/jet/buildtools/ant/KotlinJavaScriptCompilerTask.java new file mode 100644 index 00000000000..0d7eaa4cce7 --- /dev/null +++ b/build-tools/ant/src/org/jetbrains/jet/buildtools/ant/KotlinJavaScriptCompilerTask.java @@ -0,0 +1,16 @@ +package org.jetbrains.jet.buildtools.ant; + +import org.apache.tools.ant.Task; + + +/** + * Kotlin JavaScript compiler Ant task. + * http://evgeny-goldin.org/javadoc/ant/tutorial-writing-tasks.html + */ +public class KotlinJavaScriptCompilerTask extends Task { + + @Override + public void execute() { + log( "KotlinJavaScriptCompilerTask" ); + } +} diff --git a/build-tools/ant/src/org/jetbrains/jet/buildtools/ant/antlib.xml b/build-tools/ant/src/org/jetbrains/jet/buildtools/ant/antlib.xml new file mode 100644 index 00000000000..25a527811e6 --- /dev/null +++ b/build-tools/ant/src/org/jetbrains/jet/buildtools/ant/antlib.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/build-tools/build.xml b/build-tools/build.xml new file mode 100644 index 00000000000..8202b219f1d --- /dev/null +++ b/build-tools/build.xml @@ -0,0 +1,196 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${java-out} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build-tools/core/src/org/jetbrains/jet/buildtools/core/KotlinBytecodeCompiler.java b/build-tools/core/src/org/jetbrains/jet/buildtools/core/KotlinBytecodeCompiler.java new file mode 100644 index 00000000000..a5daafbed12 --- /dev/null +++ b/build-tools/core/src/org/jetbrains/jet/buildtools/core/KotlinBytecodeCompiler.java @@ -0,0 +1,36 @@ +package org.jetbrains.jet.buildtools.core; + +import org.jetbrains.jet.compiler.CompileEnvironment; + + +/** + * Wrapper class for Kotlin bytecode compiler. + */ +public class KotlinBytecodeCompiler { + + + private static CompileEnvironment environment() { + CompileEnvironment environment = new CompileEnvironment(); + environment.setJavaRuntime(CompileEnvironment.findRtJar( true )); + + if ( ! environment.initializeKotlinRuntime()) { + throw new RuntimeException( "No Kotlin runtime library found" ); + } + + return environment; + } + + + /** + * {@code CompileEnvironment#compileBunchOfSources} wrapper. + * + * @param source compilation source + * @param destination compilation destination + */ + public static void compileSources ( String source, String destination ) { + boolean success = environment().compileBunchOfSources( source, null, destination, true, false ); + if ( ! success ) { + throw new RuntimeException( String.format( "[%s] compilation failed, see \"ERROR:\" messages above for more details.", source )); + } + } +} diff --git a/build-tools/core/src/org/jetbrains/jet/buildtools/core/KotlinJavaScriptCompiler.java b/build-tools/core/src/org/jetbrains/jet/buildtools/core/KotlinJavaScriptCompiler.java new file mode 100644 index 00000000000..f4079188a08 --- /dev/null +++ b/build-tools/core/src/org/jetbrains/jet/buildtools/core/KotlinJavaScriptCompiler.java @@ -0,0 +1,8 @@ +package org.jetbrains.jet.buildtools.core; + + +/** + * Wrapper class for Kotlin JavaScript compiler. + */ +public class KotlinJavaScriptCompiler { +} diff --git a/build-tools/core/src/org/jetbrains/jet/buildtools/core/Util.java b/build-tools/core/src/org/jetbrains/jet/buildtools/core/Util.java new file mode 100644 index 00000000000..f1fb49b858c --- /dev/null +++ b/build-tools/core/src/org/jetbrains/jet/buildtools/core/Util.java @@ -0,0 +1,30 @@ +package org.jetbrains.jet.buildtools.core; + +import java.io.File; +import java.io.IOException; + + +/** + * General convenient utilities. + */ +public final class Util { + + private Util () { + } + + + /** + * {@code file.getCanonicalFile().getPath()} convenience wrapper. + * @param f file to get its canonical path. + * @return file's canonical path + */ + public static String getPath( File f ) { + try { + return f.getCanonicalFile().getPath(); + } + catch ( IOException e ) { + throw new RuntimeException( String.format( "Failed to resolve canonical file of [%s]: %s", f, e ), e ); + } + } + +} diff --git a/build-tools/lib/ant-contrib-1.0b3.jar b/build-tools/lib/ant-contrib-1.0b3.jar new file mode 100644 index 00000000000..062537661a5 Binary files /dev/null and b/build-tools/lib/ant-contrib-1.0b3.jar differ diff --git a/build-tools/test/compilation-fail/Bottles.kt b/build-tools/test/compilation-fail/Bottles.kt new file mode 100644 index 00000000000..7e2e0f02c99 --- /dev/null +++ b/build-tools/test/compilation-fail/Bottles.kt @@ -0,0 +1,59 @@ +/** + * "Bottles.kt" that doesn't compile, see line 6. + */ +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/hello/1/Hello.kt b/build-tools/test/hello/1/Hello.kt new file mode 100644 index 00000000000..699426924dd --- /dev/null +++ b/build-tools/test/hello/1/Hello.kt @@ -0,0 +1,3 @@ +fun main(args : Array) { + System.out?.println("Hello, world!") +} \ No newline at end of file diff --git a/build-tools/test/hello/2/Hello.kt b/build-tools/test/hello/2/Hello.kt new file mode 100644 index 00000000000..83ed78ab4c4 --- /dev/null +++ b/build-tools/test/hello/2/Hello.kt @@ -0,0 +1,7 @@ +fun main(args : Array) { + if (args.size == 0) { + System.out?.println("Please provide a name as a command-line argument") + return + } + System.out?.println("Hello, ${args[0]}!") +} diff --git a/build-tools/test/hello/3/Hello.kt b/build-tools/test/hello/3/Hello.kt new file mode 100644 index 00000000000..efc6503f75b --- /dev/null +++ b/build-tools/test/hello/3/Hello.kt @@ -0,0 +1,4 @@ +fun main(args : Array) { + for (name in args) + System.out?.println("Hello, $name!") +} diff --git a/build-tools/test/hello/4/Hello.kt b/build-tools/test/hello/4/Hello.kt new file mode 100644 index 00000000000..0038a5e12c0 --- /dev/null +++ b/build-tools/test/hello/4/Hello.kt @@ -0,0 +1,9 @@ +fun main(args : Array) { + val language = if (args.size == 0) "EN" else args[0] + System.out?.println(when (language) { + "EN" -> "Hello!" + "FR" -> "Salut!" + "IT" -> "Ciao!" + else -> "Sorry, I can't greet you in $language yet" + }) +} diff --git a/build-tools/test/hello/5/Hello.kt b/build-tools/test/hello/5/Hello.kt new file mode 100644 index 00000000000..96a210ce6cf --- /dev/null +++ b/build-tools/test/hello/5/Hello.kt @@ -0,0 +1,9 @@ +class Greeter(val name : String) { + fun greet() { + System.out?.println("Hello, ${name}!"); + } +} + +fun main(args : Array) { + Greeter(args[0]).greet() +} 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\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()) diff --git a/build.xml b/build.xml index 6b9761bf26b..32935e52248 100644 --- a/build.xml +++ b/build.xml @@ -1,9 +1,12 @@ + + + @@ -29,7 +32,7 @@ - + @@ -55,10 +58,10 @@ - + - + @@ -75,7 +78,7 @@ - + diff --git a/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java b/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java index 9b1d16180a8..2f43457dc3d 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java @@ -32,12 +32,12 @@ public class KotlinCompiler { @Argument(value = "help", alias = "h", description = "show help") public boolean help; } - + private static void usage(PrintStream target) { target.println("Usage: KotlinCompiler [-output |-jar ] [-src |-module ] [-includeRuntime] [-excludeStdlib]"); } - public static void main(String[] args) { + public static void main(String ... args) { System.setProperty("java.awt.headless", "true"); Arguments arguments = new Arguments(); try { @@ -53,7 +53,7 @@ public class KotlinCompiler { System.exit(1); return; } - + if (arguments.help) { usage(System.out); System.exit(0);