work on safe acess

implement callType
better KotlinPropertyAccessTranslator
This commit is contained in:
Pavel Talanov
2012-02-10 17:12:21 +04:00
parent dce8a6de21
commit 893d983861
10 changed files with 109 additions and 114 deletions
@@ -114,7 +114,6 @@
this.$dragOff = new creatures.Vector_0(0, 0);
this.$interval = 1000 / 30;
{
var tmp$5;
var tmp$4;
var tmp$3;
var tmp$2;
@@ -170,15 +169,9 @@
}
}
));
$(this.get_canvas()).resize((tmp$4 = this , function () {
setInterval((tmp$4 = this , function () {
{
tmp$4.updateSize();
}
}
));
setInterval((tmp$5 = this , function () {
{
tmp$5.draw();
tmp$4.draw();
}
}
), this.get_interval());
@@ -217,11 +210,6 @@
this.$dragOff = tmp$0;
}, get_interval:function () {
return this.$interval;
}, updateSize:function () {
{
this.set_width(this.get_canvas().width);
this.set_height(this.get_canvas().height);
}
}, mousePos_0:function (e) {
{
var offset = new creatures.Vector_0(0, 0);
@@ -19,6 +19,7 @@ import org.jetbrains.k2js.translate.operation.IncrementTranslator;
import org.jetbrains.k2js.translate.operation.UnaryOperationTranslator;
import org.jetbrains.k2js.translate.reference.AccessTranslator;
import org.jetbrains.k2js.translate.reference.CallTranslator;
import org.jetbrains.k2js.translate.reference.QualifiedExpressionTranslator;
import org.jetbrains.k2js.translate.reference.ReferenceTranslator;
import org.jetbrains.k2js.translate.utils.BindingUtils;
import org.jetbrains.k2js.translate.utils.TranslationUtils;
@@ -4,7 +4,6 @@ import com.google.dart.compiler.backend.js.ast.JsExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.expression.QualifiedExpressionTranslator;
import org.jetbrains.k2js.translate.general.AbstractTranslator;
/**
@@ -0,0 +1,77 @@
package org.jetbrains.k2js.translate.reference;
import com.google.dart.compiler.backend.js.ast.JsBinaryOperation;
import com.google.dart.compiler.backend.js.ast.JsConditional;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.backend.js.ast.JsNullLiteral;
import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression;
import org.jetbrains.jet.lang.psi.JetQualifiedExpression;
import org.jetbrains.jet.lang.psi.JetSafeQualifiedExpression;
import org.jetbrains.k2js.translate.context.TemporaryVariable;
import org.jetbrains.k2js.translate.context.TranslationContext;
import static com.google.dart.compiler.util.AstUtil.newSequence;
/**
* @author Pavel Talanov
*/
public enum CallType {
SAFE {
@NotNull
@Override
JsExpression mutateSelector(@NotNull JsExpression selector, @NotNull TranslationContext context) {
TemporaryVariable temporaryVariable = context.declareTemporary(selector);
return newSequence(temporaryVariable.assignmentExpression(), temporaryVariable.nameReference());
}
@NotNull
@Override
JsExpression mutateExpression(@NotNull JsExpression mutatedSelector,
@NotNull JsExpression expressionWithMutatedSelector,
@NotNull TranslationContext context) {
JsNullLiteral nullLiteral = context.program().getNullLiteral();
//TODO: find similar not null checks
JsBinaryOperation notNullCheck = AstUtil.notEqual(expressionWithMutatedSelector, nullLiteral);
return new JsConditional(notNullCheck, expressionWithMutatedSelector, nullLiteral);
}
},
//TODO: bang qualifier is not implemented in frontend for now
// BANG,
NORMAL {
@NotNull
@Override
JsExpression mutateSelector(@NotNull JsExpression selector, @NotNull TranslationContext context) {
// do not mutate
return selector;
}
@NotNull
@Override
JsExpression mutateExpression(@NotNull JsExpression mutatedSelector,
@NotNull JsExpression expression,
@NotNull TranslationContext context) {
// do not mutate
return expression;
}
};
@NotNull
abstract JsExpression mutateSelector(@NotNull JsExpression selector, @NotNull TranslationContext context);
@NotNull
abstract JsExpression mutateExpression(@NotNull JsExpression mutatedSelector,
@NotNull JsExpression expression,
@NotNull TranslationContext context);
@NotNull
public static CallType getCallTypeForQualifierExpression(@NotNull JetQualifiedExpression expression) {
if (expression instanceof JetSafeQualifiedExpression) {
return SAFE;
}
assert expression instanceof JetDotQualifiedExpression;
return NORMAL;
}
}
@@ -1,8 +1,6 @@
package org.jetbrains.k2js.translate.reference;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.backend.js.ast.JsNameRef;
import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
@@ -11,8 +9,6 @@ import org.jetbrains.k2js.translate.context.TranslationContext;
import java.util.Arrays;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.backingFieldReference;
/**
* @author Pavel Talanov
* <p/>
@@ -24,36 +20,24 @@ public final class KotlinPropertyAccessTranslator extends PropertyAccessTranslat
private final JsExpression qualifier;
@NotNull
private final PropertyDescriptor propertyDescriptor;
private final boolean isBackingFieldAccess;
@NotNull
ResolvedCall<?> resolvedCall;
//TODO: too many params in constructor
/*package*/ KotlinPropertyAccessTranslator(@NotNull PropertyDescriptor descriptor,
@Nullable JsExpression qualifier,
boolean isBackingFieldAccess,
@NotNull ResolvedCall<?> resolvedCall,
@NotNull TranslationContext context) {
super(context);
this.qualifier = qualifier;
this.propertyDescriptor = descriptor.getOriginal();
this.isBackingFieldAccess = isBackingFieldAccess;
this.resolvedCall = resolvedCall;
}
@Override
@NotNull
public JsExpression translateAsGet() {
if (isBackingFieldAccess) {
return backingFieldGet();
} else {
return getterCall();
}
}
@NotNull
private JsExpression backingFieldGet() {
return backingFieldReference(context(), propertyDescriptor);
return getterCall();
}
@NotNull
@@ -64,11 +48,8 @@ public final class KotlinPropertyAccessTranslator extends PropertyAccessTranslat
@Override
@NotNull
public JsExpression translateAsSet(@NotNull JsExpression toSetTo) {
if (isBackingFieldAccess) {
return backingFieldAssignment(toSetTo);
} else {
return setterCall(toSetTo);
}
return setterCall(toSetTo);
}
@NotNull
@@ -76,10 +57,4 @@ public final class KotlinPropertyAccessTranslator extends PropertyAccessTranslat
return CallTranslator.translate(qualifier, Arrays.asList(toSetTo),
resolvedCall, propertyDescriptor.getSetter(), context());
}
@NotNull
private JsExpression backingFieldAssignment(@NotNull JsExpression toSetTo) {
JsNameRef backingFieldReference = backingFieldReference(context(), propertyDescriptor);
return AstUtil.newAssignment(backingFieldReference, toSetTo);
}
}
@@ -29,8 +29,7 @@ public abstract class PropertyAccessTranslator extends AccessTranslator {
if (isNativeObject(descriptor)) {
return new NativePropertyAccessTranslator(descriptor, /*qualifier = */ null, context);
} else {
return new KotlinPropertyAccessTranslator(descriptor, /*qualifier = */ null, /*backingFieldAccess = */ false,
resolvedCall, context);
return new KotlinPropertyAccessTranslator(descriptor, /*qualifier = */ null, resolvedCall, context);
}
}
@@ -39,13 +38,11 @@ public abstract class PropertyAccessTranslator extends AccessTranslator {
@Nullable JsExpression qualifier,
@NotNull TranslationContext context) {
PropertyDescriptor propertyDescriptor = getPropertyDescriptor(expression, context);
if (isNativeObject(propertyDescriptor)) {
if (isNativeObject(propertyDescriptor) || isBackingFieldReference(expression)) {
return new NativePropertyAccessTranslator(propertyDescriptor, qualifier, context);
}
ResolvedCall<?> resolvedCall = getResolvedCall(context.bindingContext(), expression);
boolean backingFieldAccess = isBackingFieldReference(expression);
return new KotlinPropertyAccessTranslator(propertyDescriptor, qualifier,
backingFieldAccess, resolvedCall, context);
return new KotlinPropertyAccessTranslator(propertyDescriptor, qualifier, resolvedCall, context);
}
@NotNull
@@ -105,13 +102,6 @@ public abstract class PropertyAccessTranslator extends AccessTranslator {
return canBePropertyGetterCall(expression, context);
}
public enum CallType {
SAFE,
//TODO: bang qualifier is not implemented in frontend for now
BANG,
NORMAL
}
//TODO: we use normal by default but may cause bugs
private /*var*/ CallType callType = CallType.NORMAL;
@@ -1,4 +1,4 @@
package org.jetbrains.k2js.translate.expression;
package org.jetbrains.k2js.translate.reference;
import com.google.dart.compiler.backend.js.ast.JsConditional;
import com.google.dart.compiler.backend.js.ast.JsExpression;
@@ -8,9 +8,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.k2js.translate.context.TemporaryVariable;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.reference.AccessTranslator;
import org.jetbrains.k2js.translate.reference.CallTranslator;
import org.jetbrains.k2js.translate.reference.PropertyAccessTranslator;
import static org.jetbrains.k2js.translate.general.Translation.translateAsExpression;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getNotNullSimpleNameSelector;
@@ -32,13 +29,7 @@ public final class QualifiedExpressionTranslator {
JsExpression receiver = translateReceiver(expression, context);
PropertyAccessTranslator result =
PropertyAccessTranslator.newInstance(getNotNullSimpleNameSelector(expression), receiver, context);
//TODO: util if this code duplicates
if (expression instanceof JetSafeQualifiedExpression) {
result.setCallType(PropertyAccessTranslator.CallType.SAFE);
}
if (expression instanceof JetDotQualifiedExpression) {
result.setCallType(PropertyAccessTranslator.CallType.NORMAL);
}
result.setCallType(CallType.getCallTypeForQualifierExpression(expression));
return result;
}
@@ -0,0 +1,15 @@
package foo
class A() {
var c = 3
}
fun box() {
var a1 : A? = A()
var a2 : A? = null
a1?.c++
a2?.c++
a2 = a1
a2?.c++
return (a2?.c == 5)
}
@@ -1,46 +0,0 @@
package org.jetbrains.k2js.test;
import org.jetbrains.k2js.facade.K2JSTranslatorApplet;
import org.junit.Assert;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
/**
* @author Pavel Talanov
*/
public final class AppletTest extends TranslationTest {
final private static String MAIN = "applet/";
@Override
protected String mainDirectory() {
return MAIN;
}
public void testSimple() throws Exception {
evaluateCodeWithParameters("fun main(args : Array<String>) {}", " a 3 1 2134", "");
}
public void testSystemOutTest() throws Exception {
evaluateCodeWithParameters("class A() {} fun main(args : Array<String>) { var a = A();}", "", "");
}
private void evaluateCodeWithParameters(String kotlinCode, String paramString, String expectedResult)
throws Exception {
String programCode = (new K2JSTranslatorApplet())
.translateToJS(kotlinCode, paramString);
Assert.assertEquals(evaluateStringWithRhino(programCode), expectedResult);
}
private String evaluateStringWithRhino(String programCode) throws Exception {
Context context = Context.enter();
Scriptable scope = context.initStandardObjects();
runFileWithRhino(kotlinLibraryPath(), context, scope);
Object result = context.evaluateString(scope, programCode, "program code", 1, null);
Context.exit();
assert result instanceof String : "Must evaluate to string! Evaluated to: " + result;
return (String) result;
}
}
@@ -62,8 +62,13 @@ public final class PropertyAccessTest extends TranslationTest {
}
public void classUsesNamespaceProperties() throws Exception {
public void testClassUsesNamespaceProperties() throws Exception {
testFooBoxIsTrue("classUsesNamespaceProperties.kt");
}
public void testSafeAccess() throws Exception {
testFooBoxIsTrue("safeAccess.kt");
}
}