a couple of hacks to make life example work (still not working)
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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,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> {
|
||||
}
|
||||
|
||||
|
||||
@@ -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> {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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>())
|
||||
|
||||
Reference in New Issue
Block a user