modified Config to implement multifile action
implemented optimisation of the for expression (quite dirty for now)
This commit is contained in:
@@ -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
|
||||
|
||||
+121
@@ -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);
|
||||
}
|
||||
}
|
||||
+11
-30
@@ -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) {
|
||||
+127
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user