diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenStatementVisitor.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenStatementVisitor.java new file mode 100644 index 00000000000..52f865843bf --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenStatementVisitor.java @@ -0,0 +1,35 @@ +/* + * Copyright 2010-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.jet.codegen; + +import org.jetbrains.jet.lang.psi.JetElement; +import org.jetbrains.jet.lang.psi.JetIfExpression; +import org.jetbrains.jet.lang.psi.JetReturnExpression; +import org.jetbrains.jet.lang.psi.JetVisitor; + +public class CodegenStatementVisitor extends JetVisitor { + private final ExpressionCodegen codegen; + + public CodegenStatementVisitor(ExpressionCodegen codegen) { + this.codegen = codegen; + } + + @Override + public StackValue visitJetElement(JetElement element, StackValue receiver) { + return element.accept(codegen, receiver); + } +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index e04a27502b4..e2edc2f1698 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -94,6 +94,7 @@ public class ExpressionCodegen extends JetVisitor implem private final BindingContext bindingContext; final CodegenContext context; + private final CodegenStatementVisitor statementVisitor; private final Stack blockStackElements = new Stack(); private final Collection localVariableNames = new HashSet(); @@ -181,6 +182,7 @@ public class ExpressionCodegen extends JetVisitor implem }; this.bindingContext = state.getBindingContext(); this.context = context; + this.statementVisitor = new CodegenStatementVisitor(this); } public GenerationState getState() { @@ -217,6 +219,10 @@ public class ExpressionCodegen extends JetVisitor implem } public StackValue genQualified(StackValue receiver, JetElement selector) { + return genQualified(receiver, selector, this); + } + + private StackValue genQualified(StackValue receiver, JetElement selector, JetVisitor visitor) { if (tempVariables.containsKey(selector)) { throw new IllegalStateException("Inconsistent state: expression saved to a temporary variable is a selector"); } @@ -224,7 +230,7 @@ public class ExpressionCodegen extends JetVisitor implem markLineNumber(selector); } try { - return selector.accept(this, receiver); + return selector.accept(visitor, receiver); } catch (ProcessCanceledException e) { throw e; @@ -262,6 +268,10 @@ public class ExpressionCodegen extends JetVisitor implem gen(expr, expressionType(expr)); } + private StackValue genStatement(JetElement statement) { + return genQualified(StackValue.none(), statement, statementVisitor); + } + @Override public StackValue visitClass(JetClass klass, StackValue data) { return visitClassOrObject(klass); @@ -1186,11 +1196,15 @@ public class ExpressionCodegen extends JetVisitor implem generateLocalFunctionDeclaration((JetNamedFunction) statement, leaveTasks); } + boolean isStatement = iterator.hasNext() || !isInsideNonUnitFunction(); + + StackValue result = isStatement ? genStatement(statement) : gen(statement); + if (!iterator.hasNext()) { - answer = gen(statement); + answer = result; } else { - gen(statement, Type.VOID_TYPE); + result.put(Type.VOID_TYPE, v); } } @@ -1203,6 +1217,12 @@ public class ExpressionCodegen extends JetVisitor implem return answer; } + private boolean isInsideNonUnitFunction() { + DeclarationDescriptor descriptor = context.getContextDescriptor(); + JetType unit = KotlinBuiltIns.getInstance().getUnitType(); + return descriptor instanceof CallableDescriptor && !unit.equals(((CallableDescriptor) descriptor).getReturnType()); + } + private void generateLocalVariableDeclaration( @NotNull JetVariableDeclaration variableDeclaration, final @NotNull Label blockEnd, diff --git a/compiler/tests/org/jetbrains/jet/codegen/StatementGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/StatementGenTest.java new file mode 100644 index 00000000000..cb7b94f7d93 --- /dev/null +++ b/compiler/tests/org/jetbrains/jet/codegen/StatementGenTest.java @@ -0,0 +1,39 @@ +/* + * Copyright 2010-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.jet.codegen; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.ConfigurationKind; + +public class StatementGenTest extends CodegenTestCase { + @Override + protected void setUp() throws Exception { + super.setUp(); + createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); + } + + private void doTest() { + loadFile("statements/" + getTestName(true) + ".kt"); + String text = generateToText(); + // 'getstatic' means we refer to Unit.VALUE, which we shouldn't since these tests contain only statements + assertNoGetStatic(text); + } + + private void assertNoGetStatic(@NotNull String text) { + assertFalse(text, text.toLowerCase().contains("getstatic")); + } +}