a couple of hacks to make life example work (still not working)

This commit is contained in:
Pavel Talanov
2012-02-05 15:16:09 +04:00
parent d46281822f
commit 1859ddf941
11 changed files with 231 additions and 193 deletions
@@ -12,161 +12,163 @@ import java.util.Map;
*/
public final class JsProgram extends JsNode {
private final JsStatement debuggerStmt;
private final JsEmpty emptyStmt;
private final JsBooleanLiteral falseLiteral;
private JsProgramFragment[] fragments;
private final Map<String, JsFunction> indexedFunctions = new HashMap<String, JsFunction>();
private final JsNullLiteral nullLiteral;
private final Map<Double, JsNumberLiteral> numberLiteralMap =
new HashMap<Double, JsNumberLiteral>();
private final JsScope objectScope;
private final JsRootScope rootScope;
private final Map<String, JsStringLiteral> stringLiteralMap =
new HashMap<String, JsStringLiteral>();
private final JsScope topScope;
private final JsBooleanLiteral trueLiteral;
private final JsStatement debuggerStmt;
private final JsEmpty emptyStmt;
private final JsBooleanLiteral falseLiteral;
private JsProgramFragment[] fragments;
private final Map<String, JsFunction> indexedFunctions = new HashMap<String, JsFunction>();
private final JsNullLiteral nullLiteral;
private final Map<Double, JsNumberLiteral> numberLiteralMap =
new HashMap<Double, JsNumberLiteral>();
private final JsScope objectScope;
private final JsRootScope rootScope;
private final Map<String, JsStringLiteral> stringLiteralMap =
new HashMap<String, JsStringLiteral>();
private final JsScope topScope;
private final JsBooleanLiteral trueLiteral;
/**
* Constructs a JavaScript program object.
*/
public JsProgram(String unitId) {
rootScope = new JsRootScope(this);
topScope = new JsScope(rootScope, "Global", unitId);
objectScope = new JsScope(rootScope, "Object");
setFragmentCount(1);
/**
* Constructs a JavaScript program object.
*/
public JsProgram(String unitId) {
rootScope = new JsRootScope(this);
topScope = new JsScope(rootScope, "Global", unitId);
objectScope = new JsScope(rootScope, "Object");
setFragmentCount(1);
debuggerStmt = new JsDebugger();
emptyStmt = new JsEmpty();
falseLiteral = new JsBooleanLiteral(false);
nullLiteral = new JsNullLiteral();
trueLiteral = new JsBooleanLiteral(true);
}
public JsBooleanLiteral getBooleanLiteral(boolean truth) {
if (truth) {
return getTrueLiteral();
}
return getFalseLiteral();
}
/**
* Gets the {@link JsStatement} to use whenever parsed source include a
* <code>debugger</code> statement.
*/
public JsStatement getDebuggerStmt() {
return debuggerStmt;
}
public JsEmpty getEmptyStmt() {
return emptyStmt;
}
public JsBooleanLiteral getFalseLiteral() {
return falseLiteral;
}
public JsBlock getFragmentBlock(int fragment) {
if (fragment < 0 || fragment >= fragments.length) {
throw new IllegalArgumentException("Invalid fragment: " + fragment);
}
return fragments[fragment].getGlobalBlock();
}
public int getFragmentCount() {
return this.fragments.length;
}
/**
* Gets the one and only global block.
*/
public JsBlock getGlobalBlock() {
return getFragmentBlock(0);
}
public JsFunction getIndexedFunction(String name) {
return indexedFunctions.get(name);
}
public JsNullLiteral getNullLiteral() {
return nullLiteral;
}
public JsNumberLiteral getNumberLiteral(double value) {
JsNumberLiteral lit = numberLiteralMap.get(value);
if (lit == null) {
lit = new JsNumberLiteral(value);
numberLiteralMap.put(value, lit);
debuggerStmt = new JsDebugger();
emptyStmt = new JsEmpty();
falseLiteral = new JsBooleanLiteral(false);
nullLiteral = new JsNullLiteral();
trueLiteral = new JsBooleanLiteral(true);
}
return lit;
}
public JsScope getObjectScope() {
return objectScope;
}
/**
* Gets the quasi-mythical root scope. This is not the same as the top scope;
* all unresolvable identifiers wind up here, because they are considered
* external to the program.
*/
public JsRootScope getRootScope() {
return rootScope;
}
/**
* Gets the top level scope. This is the scope of all the statements in the
* main program.
*/
public JsScope getScope() {
return topScope;
}
/**
* Creates or retrieves a JsStringLiteral from an interned object pool.
*/
public JsStringLiteral getStringLiteral(String value) {
JsStringLiteral lit = stringLiteralMap.get(value);
if (lit == null) {
lit = new JsStringLiteral(value);
stringLiteralMap.put(value, lit);
public JsBooleanLiteral getBooleanLiteral(boolean truth) {
if (truth) {
return getTrueLiteral();
}
return getFalseLiteral();
}
return lit;
}
public JsBooleanLiteral getTrueLiteral() {
return trueLiteral;
}
public JsNameRef getUndefinedLiteral() {
return new JsNameRef("$Dart$Null");
}
public void setFragmentCount(int fragments) {
this.fragments = new JsProgramFragment[fragments];
for (int i = 0; i < fragments; i++) {
this.fragments[i] = new JsProgramFragment();
/**
* Gets the {@link JsStatement} to use whenever parsed source include a
* <code>debugger</code> statement.
*/
public JsStatement getDebuggerStmt() {
return debuggerStmt;
}
}
public void setIndexedFunctions(Map<String, JsFunction> indexedFunctions) {
this.indexedFunctions.clear();
this.indexedFunctions.putAll(indexedFunctions);
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
for (JsProgramFragment fragment : fragments) {
v.accept(fragment);
}
public JsEmpty getEmptyStmt() {
return emptyStmt;
}
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.PROGRAM;
}
public JsBooleanLiteral getFalseLiteral() {
return falseLiteral;
}
public JsBlock getFragmentBlock(int fragment) {
if (fragment < 0 || fragment >= fragments.length) {
throw new IllegalArgumentException("Invalid fragment: " + fragment);
}
return fragments[fragment].getGlobalBlock();
}
public int getFragmentCount() {
return this.fragments.length;
}
/**
* Gets the one and only global block.
*/
public JsBlock getGlobalBlock() {
return getFragmentBlock(0);
}
public JsFunction getIndexedFunction(String name) {
return indexedFunctions.get(name);
}
public JsNullLiteral getNullLiteral() {
return nullLiteral;
}
public JsNumberLiteral getNumberLiteral(double value) {
JsNumberLiteral lit = numberLiteralMap.get(value);
if (lit == null) {
lit = new JsNumberLiteral(value);
numberLiteralMap.put(value, lit);
}
return lit;
}
public JsScope getObjectScope() {
return objectScope;
}
/**
* Gets the quasi-mythical root scope. This is not the same as the top scope;
* all unresolvable identifiers wind up here, because they are considered
* external to the program.
*/
public JsRootScope getRootScope() {
return rootScope;
}
/**
* Gets the top level scope. This is the scope of all the statements in the
* main program.
*/
public JsScope getScope() {
return topScope;
}
/**
* Creates or retrieves a JsStringLiteral from an interned object pool.
*/
public JsStringLiteral getStringLiteral(String value) {
JsStringLiteral lit = stringLiteralMap.get(value);
if (lit == null) {
lit = new JsStringLiteral(value);
stringLiteralMap.put(value, lit);
}
return lit;
}
public JsBooleanLiteral getTrueLiteral() {
return trueLiteral;
}
public JsNameRef getUndefinedLiteral() {
return new JsNameRef("$Dart$Null");
}
public void setFragmentCount(int fragments) {
this.fragments = new JsProgramFragment[fragments];
for (int i = 0; i < fragments; i++) {
this.fragments[i] = new JsProgramFragment();
}
}
public void setIndexedFunctions(Map<String, JsFunction> indexedFunctions) {
this.indexedFunctions.clear();
this.indexedFunctions.putAll(indexedFunctions);
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
for (JsProgramFragment fragment : fragments) {
v.accept(fragment);
}
}
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.PROGRAM;
}
}
+6 -1
View File
@@ -3,6 +3,7 @@ package js;
import js.annotations.library
import js.annotations.library
import js.annotations.native
import java.util.*;
library("println")
fun println() {}
@@ -23,4 +24,8 @@ fun setTimeout(callback : ()-> Unit) {}
native
fun setInterval(callback : ()-> Unit, ms : Int) {}
native
fun setInterval(callback : ()-> Unit) {}
fun setInterval(callback : ()-> Unit) {}
library("collectionsMax")
public fun max<T>(col : Collection<T>, comp : Comparator<T>) : T = f
+6 -1
View File
@@ -6,4 +6,9 @@ import js.annotations.library
library
trait Iterable<T> {
fun iterator() : java.util.Iterator<T> {}
}
}
library("splitString")
public fun String.split(regex : String) : Array<String> {
}
+11 -8
View File
@@ -17,6 +17,14 @@ public open class Iterator<T>() {
open fun hasNext() : Boolean {}
}
library
val Collections = object {
library("max")
public fun max<T>(col : Collection<T>, comp : Comparator<T>) : T = f
}
private val f : Nothing
library
public open class ArrayList<erased E>() : java.util.List<E> {
override public fun size() : Int {}
@@ -56,7 +64,7 @@ public trait Collection<erased E> : java.lang.Iterable<E> {
}
library
public trait List<erased E> : java.util.Collection<E> {
public trait List<erased E> : Collection<E> {
override fun size() : Int
override fun isEmpty() : Boolean
override fun contains(o : Any?) : Boolean
@@ -81,7 +89,7 @@ public trait List<erased E> : java.util.Collection<E> {
}
library
public trait Set<erased E> : java.util.Collection<E> {
public trait Set<erased E> : Collection<E> {
override fun size() : Int
override fun isEmpty() : Boolean
override fun contains(o : Any?) : Boolean
@@ -143,9 +151,4 @@ library
public class StringBuilder() {
public fun append(obj : Any) : StringBuilder
public fun toString() : String
}
library("splitString")
public fun String.split(regex : String) : Array<String> {
}
}
-8
View File
@@ -1,8 +0,0 @@
package java.util.Collections;
import js.annotations.library
import java.util.Collection
import java.util.Comparator
library("collectionsMax")
public fun max<T>(col : Collection<T>, comp : Comparator<T>) {}
@@ -31,8 +31,7 @@ public abstract class Config {
PATH_TO_JS_LIB_SRC + "\\core\\core.kt",
PATH_TO_JS_LIB_SRC + "\\raphael\\raphael.kt",
PATH_TO_JS_LIB_SRC + "\\core\\json.kt",
PATH_TO_JS_LIB_SRC + "\\html5\\core.kt",
PATH_TO_JS_LIB_SRC + "\\core\\javautilcollections.kt"
PATH_TO_JS_LIB_SRC + "\\html5\\core.kt"
);
@@ -86,7 +86,13 @@ public final class StandardClasses {
standardClasses.declare().forFQ("jet.IntRange").kotlinClass("NumberRange")
.methods("iterator", "contains").properties("start", "size", "end", "reversed");
standardClasses.declare().forFQ("jet.sure").kotlinFunction("sure");
standardClasses.declare().forFQ("jet.Any.toString").kotlinFunction("toString");
standardClasses.declare().forFQ("java.util.Collections.<no name provided>.max").kotlinFunction("collectionsMax");
standardClasses.declare().forFQ("jet.CharSequence.get").kotlinFunction("getChar");
}
@@ -64,6 +64,12 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
if (value instanceof Double) {
return context.program().getNumberLiteral((Double) value);
}
if (value instanceof String) {
return context.program().getStringLiteral((String) value);
}
if (value instanceof Character) {
return context.program().getStringLiteral(value.toString());
}
//TODO: all values
throw new AssertionError("Unsupported constant expression" + expression.toString());
}
@@ -130,6 +130,7 @@ public final class FunctionTranslator extends AbstractTranslator {
return (!functionDeclaration.hasBlockBody()) && (!JetStandardClasses.isUnit(functionReturnType));
}
//TODO: refactor
@NotNull
private JsBlock wrapWithReturnIfNeeded(@NotNull JsNode body, boolean needsReturn) {
if (!needsReturn) {
@@ -147,11 +148,16 @@ public final class FunctionTranslator extends AbstractTranslator {
}
private void addReturnToBlockStatement(@NotNull JsBlock bodyBlock) {
List<JsStatement> statements = bodyBlock.getStatements();
int lastIndex = statements.size() - 1;
JsStatement lastStatement = statements.get(lastIndex);
JsReturn returnStatement = new JsReturn(AstUtil.extractExpressionFromStatement(lastStatement));
statements.set(lastIndex, returnStatement);
AstUtil.mutateLastExpression(bodyBlock, new AstUtil.Mutator() {
@Override
@NotNull
public JsNode mutate(@NotNull JsNode node) {
if (!(node instanceof JsExpression)) {
return node;
}
return new JsReturn((JsExpression) node);
}
});
}
@NotNull
+15
View File
@@ -470,6 +470,17 @@
}
);
Kotlin.comparator = function(f) {
var result = new Kotlin.Comparator;
result.compare = function(el1, el2) {
return f(el1, el2);
};
};
Kotlin.getChar = function(str, index) {
return str.charAt(index);
};
Kotlin.collectionsMax = function (col, comp) {
var it = col.iterator();
if (col.isEmpty()) {
@@ -573,6 +584,10 @@
};
Kotlin.sure = function(obj) {
return obj;
};
/**
* Copyright 2010 Tim Down.
*
@@ -2,9 +2,10 @@
* 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.*
import java.lang.split;
import js.*;
/*
* A field where cells live. Effectively immutable
@@ -119,11 +120,24 @@ fun printField(s : String, steps : Int) {
}
}
fun <T> Array<T>.toList() : List<T> = this.to(ArrayList<T>())
val String?.size : Int
get() = if (this != null) this.length else 0;
fun <T, C: Collection<T>> Array<T>.to(result: C) : C {
for (elem in this)
result.add(elem)
return result
}
fun makeField(s : String) : Field {
val lines = s.split("\n").sure()
val w = max<String?>(lines.toList(), comparator<String?> {o1, o2 ->
val l1 : Int = o1?.size ?: 0
val l2 = o2?.size ?: 0
val lines : Array<String> = s.split("\n")
val w = max<String>(lines.toList(), comparator<String> {o1, o2 ->
val l1 : Int = o1.size
val l2 = o2.size
l1 - l2
}).sure()
val data = Array(lines.size) {Array(w.size) {false}}
@@ -137,7 +151,7 @@ fun makeField(s : String) : Field {
for (line in lines.indices) {
for (x in lines[line].indices) {
val c = lines[line].sure()[x]
val c = lines[line][x]
data[line][x] = c == '*'
}
}
@@ -150,19 +164,4 @@ val String?.indices : IntRange get() = IntRange(0, this.sure().size)
fun <K, V> Map<K, V>.set(k : K, v : V) { put(k, v) }
fun comparator<T> (f : (T, T) -> Int) : Comparator<T> = object : Comparator<T> {
override fun compare(o1 : T, o2 : T) : Int = f(o1, o2)
}
val <T> Array<T>.isEmpty : Boolean get() = size == 0
val String.size : Int
get() = length
fun <T, C: Collection<T>> Array<T>.to(result: C) : C {
for (elem in this)
result.add(elem)
return result
}
fun <T> Array<T>.toList() : List<T> = this.to(ArrayList<T>())