diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 0b577fedb1c..baddde3e04c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -1462,7 +1462,7 @@ public class ExpressionCodegen extends JetVisitor { return StackValue.onStack(Type.BOOLEAN_TYPE); } - private StackValue generateEqualsForExpressionsOnStack(IElementType opToken, Type leftType, Type rightType, boolean leftNullable, boolean rightNullable) { + public StackValue generateEqualsForExpressionsOnStack(IElementType opToken, Type leftType, Type rightType, boolean leftNullable, boolean rightNullable) { if (isNumberPrimitive(leftType) && leftType == rightType) { return compareExpressionsOnStack(opToken, leftType); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index 926b496e243..3d674335c81 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -39,6 +39,7 @@ public class JetTypeMapper { public static final Type JL_BOOLEAN_TYPE = Type.getObjectType("java/lang/Boolean"); public static final Type JL_NUMBER_TYPE = Type.getObjectType("java/lang/Number"); public static final Type JL_STRING_BUILDER = Type.getObjectType("java/lang/StringBuilder"); + public static final Type JL_STRING_TYPE = Type.getObjectType("java/lang/String"); public static final Type ARRAY_INT_TYPE = Type.getType(int[].class); public static final Type ARRAY_LONG_TYPE = Type.getType(long[].class); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/Equals.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/Equals.java new file mode 100644 index 00000000000..8a9280c0102 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/Equals.java @@ -0,0 +1,43 @@ +package org.jetbrains.jet.codegen.intrinsics; + +import com.intellij.psi.PsiElement; +import com.intellij.psi.tree.IElementType; +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 Equals implements IntrinsicMethod { + @Override + public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List arguments, StackValue receiver) { + receiver.put(JetTypeMapper.TYPE_OBJECT, v); + + boolean leftNullable = true; + if(element instanceof JetCallExpression) { + JetCallExpression jetCallExpression = (JetCallExpression) element; + JetExpression calleeExpression = jetCallExpression.getCalleeExpression(); + if(calleeExpression != null) { + JetType leftType = codegen.getBindingContext().get(BindingContext.EXPRESSION_TYPE, calleeExpression); + if(leftType != null) + leftNullable = leftType.isNullable(); + } + } + + JetExpression rightExpr = arguments.get(0); + JetType rightType = codegen.getBindingContext().get(BindingContext.EXPRESSION_TYPE, rightExpr); + codegen.gen(rightExpr).put(JetTypeMapper.TYPE_OBJECT, v); + + return codegen.generateEqualsForExpressionsOnStack(JetTokens.EQEQ, JetTypeMapper.TYPE_OBJECT, JetTypeMapper.TYPE_OBJECT, leftNullable, rightType.isNullable()); + } +} 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 b1efba96116..edda1e0f96b 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java @@ -73,6 +73,11 @@ public class IntrinsicMethods { declareIntrinsicFunction("String", "plus", 1, new Concat()); + declareOverload(myStdLib.getLibraryScope().getFunctions("toString"), 0, new ToString()); + declareOverload(myStdLib.getLibraryScope().getFunctions("equals"), 1, new Equals()); + +// declareIntrinsicFunction("Any", "equals", 1, new Equals()); +// declareIntrinsicStringMethods(); declareIntrinsicProperty("String", "length", new StringLength()); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ToString.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ToString.java new file mode 100644 index 00000000000..18e706a4b1f --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ToString.java @@ -0,0 +1,24 @@ +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.JetExpression; +import org.jetbrains.jet.lang.types.JetStandardClasses; +import org.objectweb.asm.Type; +import org.objectweb.asm.commons.InstructionAdapter; + +import java.util.List; + +/** + * @author alex.tkachman + */ +public class ToString implements IntrinsicMethod { + @Override + public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List arguments, StackValue receiver) { + receiver.put(JetTypeMapper.TYPE_OBJECT, v); + v.invokestatic("java/lang/String", "valueOf", "(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 9d943679e2b..67d88d00740 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java @@ -6,6 +6,7 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import org.jetbrains.jet.codegen.ClassFileFactory; @@ -28,12 +29,13 @@ import java.util.List; /** * @author yole + * @author alex.tkachman */ public class KotlinCompiler { public static void main(String[] args) { System.setProperty("java.awt.headless", "true"); if (args.length < 1) { - System.out.println("Usage: KotlinCompiler "); + System.out.println("Usage: KotlinCompiler or "); return; } @@ -44,61 +46,36 @@ public class KotlinCompiler { }; JavaCoreEnvironment environment = new JavaCoreEnvironment(root); - String javaHome = System.getenv("JAVA_HOME"); - File rtJar = null; - if (javaHome == null) { - ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); - if(systemClassLoader instanceof URLClassLoader) { - URLClassLoader loader = (URLClassLoader) systemClassLoader; - for(URL url: loader.getURLs()) { - if("file".equals(url.getProtocol())) { - if(url.getFile().endsWith("/lib/rt.jar")) { - rtJar = new File(url.getFile()); - break; - } - if(url.getFile().endsWith("/Classes/classes.jar")) { - rtJar = new File(url.getFile()).getAbsoluteFile(); - break; - } - } - } - } - - if(rtJar == null) { - System.out.println("JAVA_HOME environment variable needs to be defined"); - return; - } - } - else { - rtJar = findRtJar(javaHome); - } - - if (rtJar == null || !rtJar.exists()) { - System.out.print("No rt.jar found under JAVA_HOME=" + javaHome); - return; - } + 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(args [0]); if (vFile == null) { - System.out.print("File not found: " + args[0]); + System.out.print("File/directory not found: " + args[0]); return; } Project project = environment.getProject(); GenerationState generationState = new GenerationState(project, false); List namespaces = Lists.newArrayList(); - PsiFile psiFile = PsiManager.getInstance(project).findFile(vFile); - if (psiFile instanceof JetFile) { - namespaces.add(((JetFile) psiFile).getRootNamespace()); + if(vFile.isDirectory()) { + File dir = new File(vFile.getPath()); + addFiles(environment, project, namespaces, dir); } else { - System.out.print("Not a Kotlin file: " + vFile.getPath()); - return; + PsiFile psiFile = PsiManager.getInstance(project).findFile(vFile); + if (psiFile instanceof JetFile) { + namespaces.add(((JetFile) psiFile).getRootNamespace()); + } + else { + System.out.print("Not a Kotlin file: " + vFile.getPath()); + return; + } } BindingContext bindingContext = AnalyzingUtils.getInstance(JavaDefaultImports.JAVA_DEFAULT_IMPORTS).analyzeNamespaces(project, namespaces, JetControlFlowDataTraceFactory.EMPTY); @@ -137,6 +114,59 @@ public class KotlinCompiler { } + private static void addFiles(JavaCoreEnvironment environment, Project project, List namespaces, File dir) { + for(File file : dir.listFiles()) { + if(!file.isDirectory()) { + VirtualFile virtualFile = environment.getLocalFileSystem().findFileByPath(file.getAbsolutePath()); + PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile); + if (psiFile instanceof JetFile) { + namespaces.add(((JetFile) psiFile).getRootNamespace()); + System.out.println(file.getAbsolutePath()); + } + } + else { + addFiles(environment, project, namespaces, file); + } + } + } + + private static File initJdk() { + String javaHome = System.getenv("JAVA_HOME"); + File rtJar = null; + if (javaHome == null) { + ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); + if(systemClassLoader instanceof URLClassLoader) { + URLClassLoader loader = (URLClassLoader) systemClassLoader; + for(URL url: loader.getURLs()) { + if("file".equals(url.getProtocol())) { + if(url.getFile().endsWith("/lib/rt.jar")) { + rtJar = new File(url.getFile()); + break; + } + if(url.getFile().endsWith("/Classes/classes.jar")) { + rtJar = new File(url.getFile()).getAbsoluteFile(); + break; + } + } + } + } + + if(rtJar == null) { + System.out.println("JAVA_HOME environment variable needs to be defined"); + return null; + } + } + else { + rtJar = findRtJar(javaHome); + } + + if (rtJar == null || !rtJar.exists()) { + System.out.print("No rt.jar found under JAVA_HOME=" + javaHome); + return null; + } + return rtJar; + } + private static void report(Diagnostic diagnostic) { System.out.println(diagnostic.getMessage()); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/JetSemanticServices.java b/compiler/frontend/src/org/jetbrains/jet/lang/JetSemanticServices.java index 28b3b7b5c24..2aff00b8719 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/JetSemanticServices.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/JetSemanticServices.java @@ -21,18 +21,12 @@ public class JetSemanticServices { return new JetSemanticServices(JetStandardLibrary.getJetStandardLibrary(project), JetControlFlowDataTraceFactory.EMPTY); } - public static JetSemanticServices createSemanticServices(Project project, JetControlFlowDataTraceFactory flowDataTraceFactory) { - return new JetSemanticServices(JetStandardLibrary.getJetStandardLibrary(project), flowDataTraceFactory); - } - private final JetStandardLibrary standardLibrary; private final JetTypeChecker typeChecker; - private final JetControlFlowDataTraceFactory flowDataTraceFactory; private JetSemanticServices(JetStandardLibrary standardLibrary, JetControlFlowDataTraceFactory flowDataTraceFactory) { this.standardLibrary = standardLibrary; this.typeChecker = new JetTypeChecker(standardLibrary); - this.flowDataTraceFactory = flowDataTraceFactory; } @NotNull @@ -42,7 +36,7 @@ public class JetSemanticServices { @NotNull public ClassDescriptorResolver getClassDescriptorResolver(BindingTrace trace) { - return new ClassDescriptorResolver(this, trace, flowDataTraceFactory); + return new ClassDescriptorResolver(this, trace); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java index 4658d844a4f..72360b8b838 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java @@ -2,9 +2,9 @@ package org.jetbrains.jet.lang.cfg; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.psi.JetElement; -import org.jetbrains.jet.lang.psi.JetExpression; -import org.jetbrains.jet.lang.psi.JetThrowExpression; +import org.jetbrains.jet.lang.psi.*; + +import java.util.List; /** * @author abreslav @@ -24,6 +24,7 @@ public interface JetControlFlowBuilder { void jumpOnFalse(@NotNull Label label); void jumpOnTrue(@NotNull Label label); void nondeterministicJump(Label label); // Maybe, jump to label + void nondeterministicJump(List