diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java index b062a56f417..3aa68b5b5ed 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -1,5 +1,6 @@ /* * @author max + * @author alex.tkachman */ package org.jetbrains.jet.codegen; @@ -16,9 +17,7 @@ import org.objectweb.asm.commons.Method; import org.objectweb.asm.signature.SignatureWriter; import java.util.Arrays; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; import static org.objectweb.asm.Opcodes.*; @@ -152,6 +151,9 @@ public class ClosureCodegen extends FunctionOrClosureCodegen { final Method bridge = erasedInvokeSignature(funDescriptor); final Method delegate = invokeSignature(funDescriptor); + if(bridge.getDescriptor().equals(delegate.getDescriptor())) + return; + final MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "invoke", bridge.getDescriptor(), state.getTypeMapper().genericSignature(funDescriptor), new String[0]); mv.visitCode(); @@ -212,7 +214,8 @@ public class ClosureCodegen extends FunctionOrClosureCodegen { ExpressionCodegen expressionCodegen = new ExpressionCodegen(mv, null, Type.VOID_TYPE, context, state); iv.load(0, Type.getObjectType(funClass)); - expressionCodegen.generateTypeInfo(new ProjectionErasingJetType(returnType)); +// expressionCodegen.generateTypeInfo(new ProjectionErasingJetType(returnType)); + iv.aconst(null); // @todo iv.invokespecial(funClass, "", "(Ljet/typeinfo/TypeInfo;)V"); i = 1; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index e9483184889..a76f5e3d782 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -313,10 +313,6 @@ public class ExpressionCodegen extends JetVisitor { myContinueTargets.pop(); } - private DeclarationDescriptor contextType() { - return context.getContextClass(); - } - private OwnerKind contextKind() { return context.getContextKind(); } @@ -874,7 +870,7 @@ public class ExpressionCodegen extends JetVisitor { String owner; boolean isInterface; - boolean isInsideClass = containingDeclaration == contextType(); + boolean isInsideClass = containingDeclaration == context.getContextClass(); if (isInsideClass || isStatic) { owner = typeMapper.getOwner(functionDescriptor, contextKind()); isInterface = false; @@ -904,7 +900,7 @@ public class ExpressionCodegen extends JetVisitor { DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); boolean isStatic = containingDeclaration instanceof NamespaceDescriptorImpl; propertyDescriptor = propertyDescriptor.getOriginal(); - boolean isInsideClass = !forceInterface && containingDeclaration == contextType(); + boolean isInsideClass = !forceInterface && containingDeclaration == context.getContextClass(); Method getter; Method setter; if (forceField) { @@ -1024,10 +1020,6 @@ public class ExpressionCodegen extends JetVisitor { return funDescriptor; } - public void invokeMethodWithArguments(CallableMethod callableMethod, JetCallElement expression) { - invokeMethodWithArguments(callableMethod, expression, StackValue.none()); - } - public void invokeMethodWithArguments(CallableMethod callableMethod, JetCallElement expression, StackValue receiver) { final Type calleeType = callableMethod.getGenerateCalleeType(); if (calleeType != null && expression instanceof JetCallExpression) { @@ -1053,7 +1045,11 @@ public class ExpressionCodegen extends JetVisitor { } else { if (callableMethod.isNeedsReceiver()) { - receiver.put(JetTypeMapper.TYPE_OBJECT, v); + if (receiver == StackValue.none()) { + v.load(0, JetTypeMapper.TYPE_OBJECT); + } + else + receiver.put(JetTypeMapper.TYPE_OBJECT, v); } } @@ -1812,7 +1808,7 @@ public class ExpressionCodegen extends JetVisitor { } CallableMethod method = typeMapper.mapToCallableMethod((ConstructorDescriptor) constructorDescriptor, OwnerKind.IMPLEMENTATION); - invokeMethodWithArguments(method, expression); + invokeMethodWithArguments(method, expression, StackValue.none()); } } else { @@ -1849,7 +1845,7 @@ public class ExpressionCodegen extends JetVisitor { v.anew(type); v.dup(); final CallableMethod callableMethod = typeMapper.mapToCallableMethod(constructor); - invokeMethodWithArguments(callableMethod, expression); + invokeMethodWithArguments(callableMethod, expression, StackValue.none()); return type; } @@ -1867,20 +1863,22 @@ public class ExpressionCodegen extends JetVisitor { throw new CompilationException("primitive array constructor requires one argument"); } } - gen(args.get(0).getArgumentExpression(), Type.INT_TYPE); if(isArray) { JetType elementType = typeMapper.getGenericsElementType(arrayType); if(elementType != null) { generateTypeInfo(elementType); - v.invokestatic("jet/typeinfo/TypeInfo", "newArray", "(ILjet/typeinfo/TypeInfo;)[Ljava/lang/Object;"); + gen(args.get(0).getArgumentExpression(), Type.INT_TYPE); + v.invokevirtual("jet/typeinfo/TypeInfo", "newArray", "(I)[Ljava/lang/Object;"); } else { + gen(args.get(0).getArgumentExpression(), Type.INT_TYPE); v.newarray(JetTypeMapper.boxType(typeMapper.mapType(arrayType.getArguments().get(0).getType()))); } } else { Type type = typeMapper.mapType(arrayType, OwnerKind.IMPLEMENTATION); + gen(args.get(0).getArgumentExpression(), Type.INT_TYPE); v.newarray(type.getElementType()); } @@ -2311,12 +2309,12 @@ public class ExpressionCodegen extends JetVisitor { return; } DeclarationDescriptor containingDeclaration = typeParameterDescriptor.getContainingDeclaration(); - if (contextType() instanceof ClassDescriptor) { - ClassDescriptor descriptor = (ClassDescriptor) contextType(); + if (context.getContextClass() instanceof ClassDescriptor) { + ClassDescriptor descriptor = (ClassDescriptor) context.getContextClass(); JetType defaultType = ((ClassDescriptor)containingDeclaration).getDefaultType(); Type ownerType = typeMapper.mapType(defaultType); ownerType = JetTypeMapper.boxType(ownerType); - if (containingDeclaration == contextType()) { + if (containingDeclaration == context.getContextClass()) { if(!CodegenUtil.isInterface(descriptor)) { if (CodegenUtil.hasTypeInfoField(defaultType)) { v.load(0, JetTypeMapper.TYPE_OBJECT); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 97ea22a1428..69df0081b91 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -461,7 +461,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } CallableMethod method = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, kind); - codegen.invokeMethodWithArguments(method, constructorCall); + codegen.invokeMethodWithArguments(method, constructorCall, StackValue.none()); } @Override @@ -513,7 +513,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { final JetDelegatorToSuperCall superCall = (JetDelegatorToSuperCall) specifier; ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) state.getBindingContext().get(BindingContext.REFERENCE_TARGET, superCall.getCalleeExpression().getConstructorReferenceExpression()); CallableMethod method = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION); - codegen.invokeMethodWithArguments(method, superCall); + codegen.invokeMethodWithArguments(method, superCall, StackValue.none()); } else { throw new UnsupportedOperationException("unsupported type of enum constant initializer: " + specifier); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java index edda1e0f96b..1d58a515884 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java @@ -75,6 +75,7 @@ public class IntrinsicMethods { declareOverload(myStdLib.getLibraryScope().getFunctions("toString"), 0, new ToString()); declareOverload(myStdLib.getLibraryScope().getFunctions("equals"), 1, new Equals()); + declareOverload(myStdLib.getLibraryScope().getFunctions("plus"), 1, new StringPlus()); // declareIntrinsicFunction("Any", "equals", 1, new Equals()); // diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/StringPlus.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/StringPlus.java new file mode 100644 index 00000000000..79995fe4abb --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/StringPlus.java @@ -0,0 +1,28 @@ +package org.jetbrains.jet.codegen.intrinsics; + +import com.intellij.psi.PsiElement; +import org.jetbrains.jet.codegen.ExpressionCodegen; +import org.jetbrains.jet.codegen.JetTypeMapper; +import org.jetbrains.jet.codegen.StackValue; +import org.jetbrains.jet.lang.psi.JetCallExpression; +import org.jetbrains.jet.lang.psi.JetExpression; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lexer.JetTokens; +import org.objectweb.asm.Type; +import org.objectweb.asm.commons.InstructionAdapter; + +import java.util.List; + +/** + * @author alex.tkachman + */ +public class StringPlus implements IntrinsicMethod { + @Override + public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List arguments, StackValue receiver) { + codegen.gen(arguments.get(0)).put(JetTypeMapper.JL_STRING_TYPE, v); + codegen.gen(arguments.get(1)).put(JetTypeMapper.TYPE_OBJECT, v); + v.invokestatic("jet/runtime/Intrinsics", "stringPlus", "(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;"); + return StackValue.onStack(JetTypeMapper.JL_STRING_TYPE); + } +} diff --git a/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java b/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java index 105351a6f4f..68f4809ee36 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java @@ -1,6 +1,8 @@ package org.jetbrains.jet.cli; -import com.google.common.collect.*; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Lists; +import com.google.common.collect.Multimap; import com.intellij.core.JavaCoreEnvironment; import com.intellij.openapi.Disposable; import com.intellij.openapi.project.Project; @@ -10,6 +12,7 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import com.sampullara.cli.Args; import com.sampullara.cli.Argument; +import org.jetbrains.jet.JetCoreEnvironment; import org.jetbrains.jet.codegen.ClassFileFactory; import org.jetbrains.jet.codegen.GenerationState; import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; @@ -17,13 +20,11 @@ import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; import org.jetbrains.jet.lang.diagnostics.DiagnosticWithTextRange; import org.jetbrains.jet.lang.diagnostics.Severity; -import org.jetbrains.jet.lang.parsing.JetParserDefinition; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetNamespace; import org.jetbrains.jet.lang.resolve.AnalyzingUtils; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.java.JavaDefaultImports; -import org.jetbrains.jet.plugin.JetFileType; import java.io.File; import java.io.IOException; @@ -61,17 +62,13 @@ public class KotlinCompiler { public void dispose() { } }; - JavaCoreEnvironment environment = new JavaCoreEnvironment(root); + JetCoreEnvironment environment = new JetCoreEnvironment(root); File rtJar = initJdk(); if (rtJar == null) return; environment.addToClasspath(rtJar); - environment.registerFileType(JetFileType.INSTANCE, "kt"); - environment.registerFileType(JetFileType.INSTANCE, "jet"); - environment.registerParserDefinition(new JetParserDefinition()); - VirtualFile vFile = environment.getLocalFileSystem().findFileByPath(arguments.src); if (vFile == null) { System.out.print("File/directory not found: " + arguments.src); diff --git a/compiler/frontend/src/jet/Library.jet b/compiler/frontend/src/jet/Library.jet index 296cd1038e6..b88e5eb0287 100644 --- a/compiler/frontend/src/jet/Library.jet +++ b/compiler/frontend/src/jet/Library.jet @@ -40,6 +40,8 @@ fun Any?.equals(other : Any?) : Boolean// = this === other // Returns "null" for null fun Any?.toString() : String// = this === other +fun String?.plus(other: Any?) : String + trait Iterator { fun next() : T val hasNext : Boolean diff --git a/compiler/frontend/src/org/jetbrains/jet/JetCoreEnvironment.java b/compiler/frontend/src/org/jetbrains/jet/JetCoreEnvironment.java index 2e95dde30b3..eac28f341d6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/JetCoreEnvironment.java +++ b/compiler/frontend/src/org/jetbrains/jet/JetCoreEnvironment.java @@ -12,6 +12,8 @@ public class JetCoreEnvironment extends JavaCoreEnvironment { public JetCoreEnvironment(Disposable parentDisposable) { super(parentDisposable); registerFileType(JetFileType.INSTANCE, "kt"); + registerFileType(JetFileType.INSTANCE, "kts"); + registerFileType(JetFileType.INSTANCE, "ktm"); registerFileType(JetFileType.INSTANCE, "jet"); registerParserDefinition(new JetParserDefinition()); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java new file mode 100644 index 00000000000..4ac299453dd --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java @@ -0,0 +1,116 @@ +package org.jetbrains.jet.lang.cfg; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import org.jetbrains.jet.lang.cfg.pseudocode.Instruction; +import org.jetbrains.jet.lang.cfg.pseudocode.LocalDeclarationInstruction; +import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode; +import org.jetbrains.jet.lang.cfg.pseudocode.SubroutineEnterInstruction; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * @author svtk + */ +public class JetControlFlowGraphTraverser { + public static Map traverseInstructionGraphUntilFactsStabilization( + Pseudocode pseudocode, + InstructionsMergeStrategy instructionsMergeStrategy, + D initialDataValue, + D initialDataValueForEnterInstruction, + boolean straightDirection) { + Map dataMap = Maps.newHashMap(); + initializeDataMap(dataMap, pseudocode, initialDataValue); + dataMap.put(pseudocode.getEnterInstruction(), initialDataValueForEnterInstruction); + + boolean[] changed = new boolean[1]; + changed[0] = true; + while (changed[0]) { + changed[0] = false; + traverseSubGraph(pseudocode, instructionsMergeStrategy, Collections.emptyList(), straightDirection, dataMap, changed, false); + } + return dataMap; + } + + private static void initializeDataMap( + Map dataMap, + Pseudocode pseudocode, + D initialDataValue) { + List instructions = pseudocode.getInstructions(); + for (Instruction instruction : instructions) { + dataMap.put(instruction, initialDataValue); + if (instruction instanceof LocalDeclarationInstruction) { + initializeDataMap(dataMap, ((LocalDeclarationInstruction) instruction).getBody(), initialDataValue); + } + } + } + + private static void traverseSubGraph( + Pseudocode pseudocode, + InstructionsMergeStrategy instructionsMergeStrategy, + Collection previousSubGraphInstructions, + boolean straightDirection, + Map dataMap, + boolean[] changed, + boolean isLocal) { + List instructions = pseudocode.getInstructions(); + SubroutineEnterInstruction enterInstruction = pseudocode.getEnterInstruction(); + for (Instruction instruction : instructions) { + if (!isLocal && instruction instanceof SubroutineEnterInstruction) continue; + + Collection allPreviousInstructions; + Collection previousInstructions = straightDirection + ? instruction.getPreviousInstructions() + : instruction.getNextInstructions(); + + if (instruction == enterInstruction && !previousSubGraphInstructions.isEmpty()) { + allPreviousInstructions = Lists.newArrayList(previousInstructions); + allPreviousInstructions.addAll(previousSubGraphInstructions); + } + else { + allPreviousInstructions = previousInstructions; + } + + if (instruction instanceof LocalDeclarationInstruction) { + Pseudocode subroutinePseudocode = ((LocalDeclarationInstruction) instruction).getBody(); + traverseSubGraph(subroutinePseudocode, instructionsMergeStrategy, previousInstructions, straightDirection, dataMap, changed, true); + } + D previousDataValue = dataMap.get(instruction); + + Collection incomingEdgesData = Sets.newHashSet(); + + for (Instruction previousInstruction : allPreviousInstructions) { + incomingEdgesData.add(dataMap.get(previousInstruction)); + } + D mergedData = instructionsMergeStrategy.execute(instruction, incomingEdgesData); + if (!mergedData.equals(previousDataValue)) { + changed[0] = true; + dataMap.put(instruction, mergedData); + } + } + } + + public static void traverseAndAnalyzeInstructionGraph( + Pseudocode pseudocode, + InstructionDataAnalyzeStrategy instructionDataAnalyzeStrategy) { + List instructions = pseudocode.getInstructions(); + for (Instruction instruction : instructions) { + if (instruction instanceof LocalDeclarationInstruction) { + traverseAndAnalyzeInstructionGraph(((LocalDeclarationInstruction) instruction).getBody(), instructionDataAnalyzeStrategy); + } + instructionDataAnalyzeStrategy.execute(instruction); + } + } + + interface InstructionsMergeStrategy { + D execute(Instruction instruction, Collection incomingEdgesData); + } + + interface InstructionDataAnalyzeStrategy { + void execute(Instruction instruction); + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java index 15d55b7f5de..b2f14f97964 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java @@ -5,10 +5,12 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.calls.ResolvedCall; import org.jetbrains.jet.lang.types.JetStandardClasses; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.expressions.OperatorConventions; @@ -590,6 +592,17 @@ public class JetControlFlowProcessor { @Override public void visitCallExpression(JetCallExpression expression) { + //inline functions after M1 +// ResolvedCall resolvedCall = trace.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression()); +// assert resolvedCall != null; +// CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor(); +// PsiElement element = trace.get(BindingContext.DESCRIPTOR_TO_DECLARATION, resultingDescriptor); +// if (element instanceof JetNamedFunction) { +// JetNamedFunction namedFunction = (JetNamedFunction) element; +// if (namedFunction.hasModifier(JetTokens.INLINE_KEYWORD)) { +// } +// } + for (JetTypeProjection typeArgument : expression.getTypeArguments()) { value(typeArgument, false); } @@ -726,6 +739,9 @@ public class JetControlFlowProcessor { @Override public void visitObjectDeclaration(JetObjectDeclaration declaration) { +// for (JetDelegationSpecifier delegationSpecifier : declaration.getDelegationSpecifiers()) { +// value(delegationSpecifier, inCondition); +// } Queue