modified Config to implement multifile action

implemented optimisation of the for expression (quite dirty for now)
This commit is contained in:
Pavel Talanov
2012-02-22 20:55:08 +04:00
parent bbb84a9147
commit 4075070506
15 changed files with 453 additions and 123 deletions
@@ -17,18 +17,9 @@
package org.jetbrains.k2js.config;
import com.intellij.openapi.project.Project;
import core.Dummy;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.k2js.utils.JetFileUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
@@ -38,73 +29,10 @@ import java.util.List;
*/
public abstract class Config {
//TODO: provide some generic way to get the files of the project
@NotNull
private static final List<String> LIB_FILE_NAMES = Arrays.asList(
"/core/annotations.kt",
"/jquery/common.kt",
"/jquery/ui.kt",
"/core/javautil.kt",
"/core/javalang.kt",
"/core/core.kt",
"/core/math.kt",
"/core/json.kt",
"/raphael/raphael.kt",
"/html5/canvas.kt",
"/html5/files.kt",
"/html5/image.kt",
"/helper/ip.kt",
"/pixastic/pixastic.kt"
);
@NotNull
private static List<JetFile> initLibFiles(@NotNull Project project) {
List<JetFile> libFiles = new ArrayList<JetFile>();
for (String libFileName : LIB_FILE_NAMES) {
InputStream stream = Dummy.class.getResourceAsStream(libFileName);
//noinspection IOResourceOpenedButNotSafelyClosed
JetFile file = null;
try {
String text = readString(stream);
file = JetFileUtils.createPsiFile(libFileName, text, project);
} catch (IOException e) {
e.printStackTrace();
}
libFiles.add(file);
}
return libFiles;
}
@Nullable
private /*var*/ List<JetFile> jsLibFiles = null;
@NotNull
public abstract Project getProject();
@NotNull
public List<JetFile> getLibFiles() {
if (jsLibFiles == null) {
jsLibFiles = initLibFiles(getProject());
}
return jsLibFiles;
}
static String readString(InputStream is) throws IOException {
char[] buf = new char[2048];
Reader r = new InputStreamReader(is, "UTF-8");
StringBuilder s = new StringBuilder();
while (true) {
int n = r.read(buf);
if (n < 0)
break;
s.append(buf, 0, n);
}
return s.toString();
}
public abstract List<JetFile> getLibFiles();
}
@@ -18,6 +18,10 @@ package org.jetbrains.k2js.config;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetFile;
import java.util.Collections;
import java.util.List;
/**
* @author Pavel Talanov
@@ -36,4 +40,10 @@ public final class IDEAConfig extends Config {
public Project getProject() {
return project;
}
@NotNull
@Override
public List<JetFile> getLibFiles() {
return Collections.emptyList();
}
}
@@ -18,15 +18,46 @@ package org.jetbrains.k2js.config;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.project.Project;
import core.Dummy;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.compiler.JetCoreEnvironment;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.k2js.utils.JetFileUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author Pavel Talanov
*/
//TODO: review/refactor
public final class TestConfig extends Config {
//TODO: provide some generic way to get the files of the project
@NotNull
private static final List<String> LIB_FILE_NAMES = Arrays.asList(
"/core/annotations.kt",
"/jquery/common.kt",
"/jquery/ui.kt",
"/core/javautil.kt",
"/core/javalang.kt",
"/core/core.kt",
"/core/math.kt",
"/core/json.kt",
"/raphael/raphael.kt",
"/html5/canvas.kt",
"/html5/files.kt",
"/html5/image.kt",
"/helper/ip.kt",
"/pixastic/pixastic.kt"
);
@NotNull
private static JetCoreEnvironment getTestEnvironment() {
if (testOnlyEnvironment == null) {
@@ -42,6 +73,10 @@ public final class TestConfig extends Config {
@Nullable
private static /*var*/ JetCoreEnvironment testOnlyEnvironment = null;
@Nullable
private /*var*/ List<JetFile> jsLibFiles = null;
public TestConfig() {
}
@@ -50,4 +85,45 @@ public final class TestConfig extends Config {
public Project getProject() {
return getTestEnvironment().getProject();
}
@NotNull
private static List<JetFile> initLibFiles(@NotNull Project project) {
List<JetFile> libFiles = new ArrayList<JetFile>();
for (String libFileName : LIB_FILE_NAMES) {
InputStream stream = Dummy.class.getResourceAsStream(libFileName);
//noinspection IOResourceOpenedButNotSafelyClosed
JetFile file = null;
try {
String text = readString(stream);
file = JetFileUtils.createPsiFile(libFileName, text, project);
} catch (IOException e) {
e.printStackTrace();
}
libFiles.add(file);
}
return libFiles;
}
@NotNull
public List<JetFile> getLibFiles() {
if (jsLibFiles == null) {
jsLibFiles = initLibFiles(getProject());
}
return jsLibFiles;
}
@NotNull
private static String readString(@NotNull InputStream is) throws IOException {
char[] buf = new char[2048];
Reader r = new InputStreamReader(is, "UTF-8");
StringBuilder s = new StringBuilder();
while (true) {
int n = r.read(buf);
if (n < 0)
break;
s.append(buf, 0, n);
}
return s.toString();
}
}
@@ -22,6 +22,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.plugin.JetMainDetector;
import org.jetbrains.k2js.analyze.Analyzer;
import org.jetbrains.k2js.config.Config;
import org.jetbrains.k2js.config.IDEAConfig;
@@ -49,12 +50,16 @@ import static org.jetbrains.k2js.utils.JetFileUtils.createPsiFileList;
*/
public final class K2JSTranslator {
public static void translateWithCallToMainAndSaveToFile(@NotNull JetFile file,
public static void translateWithCallToMainAndSaveToFile(@NotNull List<JetFile> files,
@NotNull String outputPath,
@NotNull Project project) throws Exception {
K2JSTranslator translator = new K2JSTranslator(new IDEAConfig(project));
String programCode = translator.generateProgramCode(file) + "\n";
String callToMain = translator.generateCallToMain(file, "");
String programCode = translator.generateProgramCode(files) + "\n";
JetFile fileWithMain = JetMainDetector.getFileWithMain(files);
if (fileWithMain == null) {
throw new RuntimeException("No file with main detected.");
}
String callToMain = translator.generateCallToMain(fileWithMain, "");
FileWriter writer = new FileWriter(new File(outputPath));
writer.write(programCode + callToMain);
writer.close();
@@ -86,6 +91,7 @@ public final class K2JSTranslator {
this.config = config;
}
//TODO: refactor
@NotNull
public String translateStringWithCallToMain(@NotNull String programText, @NotNull String argumentsString) {
JetFile file = JetFileUtils.createPsiFile("test", programText, getProject());
@@ -103,6 +109,13 @@ public final class K2JSTranslator {
return generator.generateToString(program);
}
@NotNull
private String generateProgramCode(@NotNull List<JetFile> files) {
JsProgram program = generateProgram(files);
CodeGenerator generator = new CodeGenerator();
return generator.generateToString(program);
}
@NotNull
public BindingContext analyzeProgramCode(@NotNull String programText) {
JetFile file = JetFileUtils.createPsiFile("test", programText, getProject());
@@ -137,7 +150,6 @@ public final class K2JSTranslator {
return result;
}
@NotNull
private Project getProject() {
return config.getProject();
@@ -38,7 +38,7 @@ public final class TemporaryVariable {
}
@NotNull
public JsNameRef nameReference() {
public JsNameRef reference() {
return variableName.makeRef();
}
@@ -28,6 +28,7 @@ import org.jetbrains.jet.lang.resolve.constants.NullValue;
import org.jetbrains.k2js.translate.context.TemporaryVariable;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.declaration.ClassTranslator;
import org.jetbrains.k2js.translate.expression.foreach.ForTranslator;
import org.jetbrains.k2js.translate.general.Translation;
import org.jetbrains.k2js.translate.general.TranslatorVisitor;
import org.jetbrains.k2js.translate.operation.BinaryOperationTranslator;
@@ -160,12 +161,12 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
}
TemporaryVariable result = context.declareTemporary(context.program().getNullLiteral());
AstUtil.SaveLastExpressionMutator saveResultToTemporaryMutator =
new AstUtil.SaveLastExpressionMutator(result.nameReference());
new AstUtil.SaveLastExpressionMutator(result.reference());
JsNode mutatedIfStatement = AstUtil.mutateLastExpression(ifStatement,
saveResultToTemporaryMutator);
JsStatement resultingStatement = AstUtil.convertToStatement(mutatedIfStatement);
context.addStatementToCurrentBlock(resultingStatement);
return result.nameReference();
return result.reference();
}
@Override
@@ -65,7 +65,7 @@ public class WhenTranslator extends AbstractTranslator {
List<JsStatement> entries = translateEntries();
resultingFor.setBody(AstUtil.newBlock(entries));
context().addStatementToCurrentBlock(resultingFor);
return result.nameReference();
return result.reference();
}
@NotNull
@@ -80,7 +80,7 @@ public class WhenTranslator extends AbstractTranslator {
@NotNull
private JsStatement surroundWithDummyIf(@NotNull JsStatement entryStatement) {
JsExpression stepNumberEqualsCurrentEntryNumber = new JsBinaryOperation(JsBinaryOperator.EQ,
dummyCounter.nameReference(), context().program().getNumberLiteral(currentEntryNumber));
dummyCounter.reference(), context().program().getNumberLiteral(currentEntryNumber));
currentEntryNumber++;
return new JsIf(stepNumberEqualsCurrentEntryNumber, entryStatement, null);
}
@@ -97,12 +97,12 @@ public class WhenTranslator extends AbstractTranslator {
@NotNull
private JsBinaryOperation generateConditionStatement() {
JsNumberLiteral entriesNumber = program().getNumberLiteral(whenExpression.getEntries().size());
return new JsBinaryOperation(JsBinaryOperator.LT, dummyCounter.nameReference(), entriesNumber);
return new JsBinaryOperation(JsBinaryOperator.LT, dummyCounter.reference(), entriesNumber);
}
@NotNull
private JsPrefixOperation generateIncrementStatement() {
return new JsPrefixOperation(JsUnaryOperator.INC, dummyCounter.nameReference());
return new JsPrefixOperation(JsUnaryOperator.INC, dummyCounter.reference());
}
@NotNull
@@ -119,7 +119,7 @@ public class WhenTranslator extends AbstractTranslator {
JsStatement withReturnValueCaptured(@NotNull JsNode node) {
return AstUtil.convertToStatement(AstUtil.mutateLastExpression(node,
new AstUtil.SaveLastExpressionMutator(result.nameReference())));
new AstUtil.SaveLastExpressionMutator(result.reference())));
}
@NotNull
@@ -0,0 +1,121 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.k2js.translate.expression.foreach;
import com.google.common.collect.Lists;
import com.google.dart.compiler.backend.js.ast.*;
import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetForExpression;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.k2js.translate.context.TemporaryVariable;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.Translation;
import org.jetbrains.k2js.translate.intrinsic.string.LengthIntrinsic;
import org.jetbrains.k2js.translate.utils.BindingUtils;
import java.util.Collections;
import java.util.List;
import static org.jetbrains.k2js.translate.utils.DescriptorUtils.getClassDescriptorForType;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopBody;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopRange;
/**
* @author Pavel Talanov
*/
public final class ArrayForTranslator extends ForTranslator {
@NotNull
public static JsStatement translate(@NotNull JetForExpression expression,
@NotNull TranslationContext context) {
return (new ArrayForTranslator(expression, context).translate());
}
public static boolean isApplicable(@NotNull JetForExpression expression,
@NotNull TranslationContext context) {
JetExpression loopRange = getLoopRange(expression);
JetType rangeType = BindingUtils.getTypeForExpression(context.bindingContext(), loopRange);
//TODO: better check
//TODO: IMPORTANT!
return getClassDescriptorForType(rangeType).getName().equals("Array")
|| getClassDescriptorForType(rangeType).getName().equals("IntArray");
}
@NotNull
private final TemporaryVariable rangeExpression;
private ArrayForTranslator(@NotNull JetForExpression forExpression, @NotNull TranslationContext context) {
super(forExpression, context);
rangeExpression = context.declareTemporary(Translation.translateAsExpression(getLoopRange(expression), context));
}
@NotNull
private JsBlock translate() {
JsExpression length = LengthIntrinsic.INSTANCE.apply(rangeExpression.reference(), Collections.<JsExpression>emptyList(), context());
TemporaryVariable end = context().declareTemporary(length);
List<JsStatement> blockStatements = temporariesInitialization(rangeExpression, end);
blockStatements.add(generateForExpression(end));
return AstUtil.newBlock(blockStatements);
}
@NotNull
private JsFor generateForExpression(@NotNull TemporaryVariable end) {
JsFor result = new JsFor();
//TODO: make index instance variable
TemporaryVariable indexVar = context().declareTemporary(program().getNumberLiteral(0));
result.setInitVars(initExpression(indexVar));
result.setCondition(getCondition(end, indexVar));
result.setIncrExpr(getIncrExpression(indexVar));
result.setBody(getBody(indexVar));
return result;
}
@NotNull
private JsStatement getBody(@NotNull TemporaryVariable index) {
JsArrayAccess arrayAccess = new JsArrayAccess(rangeExpression.reference(), index.reference());
JsStatement currentVar = AstUtil.newVar(declareParameter(), arrayAccess);
JsStatement realBody = Translation.translateAsStatement(getLoopBody(expression), context());
return AstUtil.newBlock(currentVar, realBody);
}
@NotNull
private JsVars initExpression(TemporaryVariable start) {
return AstUtil.newVar(start.name(), program().getNumberLiteral(0));
}
@NotNull
private JsExpression getCondition(TemporaryVariable end, TemporaryVariable index) {
return AstUtil.notEqual(index.reference(), end.reference());
}
@NotNull
private JsExpression getIncrExpression(@NotNull TemporaryVariable index) {
return new JsPrefixOperation(JsUnaryOperator.INC, index.reference());
}
//TODO: move somewhere util
@NotNull
private List<JsStatement> temporariesInitialization(TemporaryVariable... temporaries) {
List<JsStatement> result = Lists.newArrayList();
for (TemporaryVariable temporary : temporaries) {
result.add(temporary.assignmentExpression().makeStmt());
}
return result;
}
}
@@ -0,0 +1,59 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.k2js.translate.expression.foreach;
import com.google.dart.compiler.backend.js.ast.JsName;
import com.google.dart.compiler.backend.js.ast.JsStatement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetForExpression;
import org.jetbrains.jet.lang.psi.JetParameter;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopParameter;
/**
* @author Pavel Talanov
*/
public abstract class ForTranslator extends AbstractTranslator {
@NotNull
public static JsStatement translate(@NotNull JetForExpression expression,
@NotNull TranslationContext context) {
if (ArrayForTranslator.isApplicable(expression, context)) {
return ArrayForTranslator.translate(expression, context);
}
if (RangeForTranslator.isApplicable(expression, context)) {
return RangeForTranslator.translate(expression, context);
}
return IteratorForTranslator.translate(expression, context);
}
@NotNull
protected final JetForExpression expression;
protected ForTranslator(@NotNull JetForExpression forExpression, @NotNull TranslationContext context) {
super(context);
this.expression = forExpression;
}
@NotNull
protected JsName declareParameter() {
JetParameter loopParameter = getLoopParameter(expression);
return context().getNameForElement(loopParameter);
}
}
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.k2js.translate.expression;
package org.jetbrains.k2js.translate.expression.foreach;
import com.google.dart.compiler.backend.js.ast.*;
import com.google.dart.compiler.util.AstUtil;
@@ -24,34 +24,28 @@ import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetForExpression;
import org.jetbrains.jet.lang.psi.JetParameter;
import org.jetbrains.k2js.translate.context.TemporaryVariable;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator;
import org.jetbrains.k2js.translate.general.Translation;
import org.jetbrains.k2js.translate.reference.CallBuilder;
import static org.jetbrains.k2js.translate.utils.BindingUtils.*;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopBody;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopParameter;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopRange;
/**
* @author Pavel Talanov
*/
public final class ForTranslator extends AbstractTranslator {
public final class IteratorForTranslator extends ForTranslator {
@NotNull
public static JsStatement translate(@NotNull JetForExpression expression,
@NotNull TranslationContext context) {
return (new ForTranslator(expression, context).translate());
return (new IteratorForTranslator(expression, context).translate());
}
@NotNull
private final JetForExpression expression;
private ForTranslator(@NotNull JetForExpression forExpression, @NotNull TranslationContext context) {
super(context);
this.expression = forExpression;
private IteratorForTranslator(@NotNull JetForExpression forExpression, @NotNull TranslationContext context) {
super(forExpression, context);
}
@NotNull
@@ -63,12 +57,6 @@ public final class ForTranslator extends AbstractTranslator {
return AstUtil.newBlock(iterator.assignmentExpression().makeStmt(), cycle);
}
@NotNull
private JsName declareParameter() {
JetParameter loopParameter = getLoopParameter(expression);
return context().getNameForElement(loopParameter);
}
@NotNull
private JsBlock generateCycleBody(@NotNull JsName parameterName, @NotNull TemporaryVariable iterator) {
JsBlock cycleBody = new JsBlock();
@@ -82,31 +70,24 @@ public final class ForTranslator extends AbstractTranslator {
@NotNull
private JsExpression nextMethodInvocation(@NotNull TemporaryVariable iterator) {
FunctionDescriptor nextFunction = getNextFunction(context().bindingContext(), getLoopRange());
return translateMethodInvocation(iterator.nameReference(), nextFunction);
FunctionDescriptor nextFunction = getNextFunction(context().bindingContext(), getLoopRange(expression));
return translateMethodInvocation(iterator.reference(), nextFunction);
}
@NotNull
private JsExpression hasNextMethodInvocation(@NotNull TemporaryVariable iterator) {
CallableDescriptor hasNextFunction = getHasNextCallable(context().bindingContext(), getLoopRange());
return translateMethodInvocation(iterator.nameReference(), hasNextFunction);
CallableDescriptor hasNextFunction = getHasNextCallable(context().bindingContext(), getLoopRange(expression));
return translateMethodInvocation(iterator.reference(), hasNextFunction);
}
@NotNull
private JsExpression iteratorMethodInvocation() {
JetExpression rangeExpression = getLoopRange();
JetExpression rangeExpression = getLoopRange(expression);
JsExpression range = Translation.translateAsExpression(rangeExpression, context());
FunctionDescriptor iteratorFunction = getIteratorFunction(context().bindingContext(), rangeExpression);
return translateMethodInvocation(range, iteratorFunction);
}
@NotNull
private JetExpression getLoopRange() {
JetExpression rangeExpression = expression.getLoopRange();
assert rangeExpression != null;
return rangeExpression;
}
@NotNull
private JsExpression translateMethodInvocation(@Nullable JsExpression receiver,
@NotNull CallableDescriptor descriptor) {
@@ -0,0 +1,127 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.k2js.translate.expression.foreach;
import com.google.common.collect.Lists;
import com.google.dart.compiler.backend.js.ast.*;
import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetForExpression;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.k2js.translate.context.TemporaryVariable;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.Translation;
import org.jetbrains.k2js.translate.utils.BindingUtils;
import java.util.List;
import static org.jetbrains.k2js.translate.utils.DescriptorUtils.getClassDescriptorForType;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopBody;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopRange;
/**
* @author Pavel Talanov
*/
public final class RangeForTranslator extends ForTranslator {
@NotNull
public static JsStatement translate(@NotNull JetForExpression expression,
@NotNull TranslationContext context) {
return (new RangeForTranslator(expression, context).translate());
}
public static boolean isApplicable(@NotNull JetForExpression expression,
@NotNull TranslationContext context) {
JetExpression loopRange = getLoopRange(expression);
JetType rangeType = BindingUtils.getTypeForExpression(context.bindingContext(), loopRange);
//TODO: better check
return getClassDescriptorForType(rangeType).getName().equals("IntRange");
}
@NotNull
private final TemporaryVariable rangeExpression;
private RangeForTranslator(@NotNull JetForExpression forExpression, @NotNull TranslationContext context) {
super(forExpression, context);
rangeExpression = context.declareTemporary(Translation.translateAsExpression(getLoopRange(expression), context));
}
@NotNull
private JsBlock translate() {
//TODO: make fields
JsExpression isReversed = callFunction("get_reversed");
JsConditional incrVarValue = new JsConditional(isReversed,
program().getNumberLiteral(-1),
program().getNumberLiteral(1));
TemporaryVariable incrVar = context().declareTemporary(incrVarValue);
TemporaryVariable start = context().declareTemporary(callFunction("get_start"));
TemporaryVariable end = context().declareTemporary(new JsBinaryOperation(JsBinaryOperator.ADD, callFunction("get_end"), incrVar.reference()));
List<JsStatement> blockStatements = temporariesInitialization(rangeExpression, incrVar, start, end);
blockStatements.add(generateForExpression(incrVar, start, end));
return AstUtil.newBlock(blockStatements);
}
@NotNull
private JsFor generateForExpression(@NotNull TemporaryVariable incrVar,
@NotNull TemporaryVariable start,
@NotNull TemporaryVariable end) {
JsFor result = new JsFor();
JsName parameterName = declareParameter();
result.setInitVars(initExpression(start, parameterName));
result.setCondition(getCondition(end, parameterName));
result.setIncrExpr(getIncrExpression(incrVar, parameterName));
result.setBody(Translation.translateAsStatement(getLoopBody(expression), context()));
return result;
}
@NotNull
private JsVars initExpression(TemporaryVariable start, JsName parameterName) {
return AstUtil.newVar(parameterName, start.reference());
}
@NotNull
private JsExpression getCondition(TemporaryVariable end, JsName parameterName) {
return AstUtil.notEqual(parameterName.makeRef(), end.reference());
}
@NotNull
private JsExpression getIncrExpression(@NotNull TemporaryVariable incrVar, @NotNull JsName parameterName) {
return new JsBinaryOperation(JsBinaryOperator.ASG_ADD, parameterName.makeRef(), incrVar.reference());
}
@NotNull
private JsExpression getField(@NotNull String fieldName) {
JsNameRef nameRef = AstUtil.newQualifiedNameRef(fieldName);
AstUtil.setQualifier(nameRef, rangeExpression.reference());
return nameRef;
}
@NotNull
private JsExpression callFunction(@NotNull String funName) {
return AstUtil.newInvocation(getField(funName));
}
@NotNull
private List<JsStatement> temporariesInitialization(TemporaryVariable... temporaries) {
List<JsStatement> result = Lists.newArrayList();
for (TemporaryVariable temporary : temporaries) {
result.add(temporary.assignmentExpression().makeStmt());
}
return result;
}
}
@@ -97,10 +97,10 @@ public abstract class IncrementTranslator extends AbstractTranslator {
// code fragment: expr(a++)
// generate: expr( (t1 = a, t2 = t1, a = t1.inc(), t2) )
TemporaryVariable t1 = context().declareTemporary(accessTranslator.translateAsGet());
TemporaryVariable t2 = context().declareTemporary(t1.nameReference());
JsExpression variableReassignment = variableReassignment(t1.nameReference());
TemporaryVariable t2 = context().declareTemporary(t1.reference());
JsExpression variableReassignment = variableReassignment(t1.reference());
return AstUtil.newSequence(t1.assignmentExpression(), t2.assignmentExpression(),
variableReassignment, t2.nameReference());
variableReassignment, t2.reference());
}
//TODO: TEST
@@ -109,9 +109,9 @@ public abstract class IncrementTranslator extends AbstractTranslator {
// code fragment: expr(a++)
// generate: expr( (t1 = a, t2 = t1, t2.inc(), t1) )
TemporaryVariable t1 = context().declareTemporary(accessTranslator.translateAsGet());
TemporaryVariable t2 = context().declareTemporary(t1.nameReference());
JsExpression methodCall = operationExpression(t2.nameReference());
JsExpression returnedValue = t1.nameReference();
TemporaryVariable t2 = context().declareTemporary(t1.reference());
JsExpression methodCall = operationExpression(t2.reference());
JsExpression returnedValue = t1.reference();
return AstUtil.newSequence(t1.assignmentExpression(), t2.assignmentExpression(), methodCall, returnedValue);
}
@@ -44,9 +44,9 @@ public enum CallType {
TemporaryVariable temporaryVariable = context.declareTemporary(receiver);
JsNullLiteral nullLiteral = context.program().getNullLiteral();
//TODO: find similar not null checks
JsBinaryOperation notNullCheck = AstUtil.notEqual(temporaryVariable.nameReference(), nullLiteral);
JsBinaryOperation notNullCheck = AstUtil.notEqual(temporaryVariable.reference(), nullLiteral);
JsConditional callMethodIfNotNullElseNull =
new JsConditional(notNullCheck, constructor.construct(temporaryVariable.nameReference()), nullLiteral);
new JsConditional(notNullCheck, constructor.construct(temporaryVariable.reference()), nullLiteral);
return newSequence(temporaryVariable.assignmentExpression(), callMethodIfNotNullElseNull);
}
},
@@ -330,4 +330,12 @@ public final class BindingUtils {
}
return descriptorSet;
}
@NotNull
public static JetType getTypeForExpression(@NotNull BindingContext context,
@NotNull JetExpression expression) {
JetType type = context.get(BindingContext.EXPRESSION_TYPE, expression);
assert type != null;
return type;
}
}
@@ -153,4 +153,11 @@ public final class PsiUtils {
}
return name;
}
@NotNull
public static JetExpression getLoopRange(@NotNull JetForExpression expression) {
JetExpression rangeExpression = expression.getLoopRange();
assert rangeExpression != null;
return rangeExpression;
}
}