"compiler" folder created

This commit is contained in:
Andrey Breslav
2011-09-09 21:47:21 +04:00
parent 443c342725
commit 116f35c650
375 changed files with 3 additions and 11 deletions
+43
View File
@@ -0,0 +1,43 @@
<project name="Lexer" default="lexer">
<property name="home" value="${basedir}"/>
<property file="${home}/idea.properties"/>
<property name="flex.base" value="${idea.home}/tools/lexer/jflex-1.4"/>
<property name="out.dir" value="${basedir}/tmpout"/>
<macrodef name="flex">
<attribute name="flexfile"/>
<attribute name="destdir"/>
<attribute name="skeleton" default="${idea.home}/tools/lexer/idea-flex.skeleton"/>
<sequential>
<delete dir="${out.dir}"/>
<mkdir dir="${out.dir}"/>
<java classname="JFlex.Main"
jvmargs="-Xmx512M"
fork="true"
failonerror="true">
<arg value="-sliceandcharat"/>
<arg value="-skel"/>
<arg value="@{skeleton}"/>
<arg value="-d"/>
<arg value="${out.dir}"/>
<arg value="@{flexfile}"/>
<classpath>
<pathelement location="${flex.base}/lib/JFlex.jar"/>
</classpath>
</java>
<move todir="@{destdir}">
<fileset dir="${out.dir}">
<include name="*.java"/>
</fileset>
</move>
<delete dir="${out.dir}"/>
</sequential>
</macrodef>
<target name="lexer">
<echo message="${flex.base}"/>
<flex flexfile="${home}/src/org/jetbrains/jet/lexer/Jet.flex"
destdir="${home}//src/org/jetbrains/jet/lexer/"/>
</target>
</project>
+12
View File
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="jdk" jdkName="IDEA 10.x" jdkType="IDEA JDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
+574
View File
@@ -0,0 +1,574 @@
namespace jet
namespace typeinfo {
class TypeInfo<T> {
fun isSubtypeOf(other : TypeInfo<*>) : Boolean
fun isInstance(obj : Any?) : Boolean
}
fun typeinfo<T>() : TypeInfo<T>
fun typeinfo<T>(expression : T) : TypeInfo<out T>
}
namespace io {
fun print(message : Any?)
fun print(message : Int)
fun print(message : Long)
fun print(message : Byte)
fun print(message : Short)
fun print(message : Char)
fun print(message : Boolean)
fun print(message : Float)
fun print(message : Double)
fun println(message : Any?)
fun println(message : Int)
fun println(message : Long)
fun println(message : Byte)
fun println(message : Short)
fun println(message : Char)
fun println(message : Boolean)
fun println(message : Float)
fun println(message : Double)
fun readLine() : String?
}
// Can't write a body due to a bootstrapping problem (see JET-74)
fun Any?.equals(other : Any?) : Boolean// = this === other
// Returns "null" for null
fun Any?.toString() : String// = this === other
trait Iterator<out T> {
fun next() : T
abstract fun hasNext() : Boolean
}
trait Iterable<out T> {
fun iterator() : Iterator<T>
}
class Array<T>(val size : Int) {
fun get(index : Int) : T
fun set(index : Int, value : T) : Unit
fun iterator() : Iterator<T>
}
trait Comparable<in T> {
fun compareTo(other : T) : Int
}
trait Hashable {
fun hashCode() : Int
fun equals(other : Any?) : Boolean
}
class Boolean : Comparable<Boolean> {
fun not() : Boolean
fun xor(other : Boolean) : Boolean
fun equals(other : Any?) : Boolean
}
class String() : Comparable<String> {
fun get(index : Int) : Char
val length : Int
fun plus(other : Any?) : String
fun equals(other : Any?) : Boolean
fun equalsIgnoreCase(other: String?) : Boolean
fun substring(start: Int): String
fun substring(start: Int, end: Int): String
fun startsWith(prefix: String, toffset: Int): Boolean
fun startsWith(prefix: String): Boolean
fun endsWith(suffix: String): Boolean
fun trim(): String
}
trait Range<in T : Comparable<T>> {
fun contains(item : T) : Boolean
}
class IntRange<T : Comparable<T>> : Range<T>, Iterable<T> {
}
abstract class Number : Hashable {
abstract val dbl : Double
abstract val flt : Float
abstract val lng : Long
abstract val int : Int
abstract val chr : Char
abstract val sht : Short
abstract val byt : Byte
// fun equals(other : Double) : Boolean
// fun equals(other : Float) : Boolean
// fun equals(other : Long) : Boolean
// fun equals(other : Byte) : Boolean
// fun equals(other : Int) : Boolean
// fun equals(other : Short) : Boolean
// fun equals(other : Char) : Boolean
}
class Double : Number, Comparable<Double> {
override fun compareTo(other : Double) : Int
fun compareTo(other : Float) : Int
fun compareTo(other : Long) : Int
fun compareTo(other : Int) : Int
fun compareTo(other : Short) : Int
fun compareTo(other : Byte) : Int
fun compareTo(other : Char) : Int
fun plus(other : Double) : Double
fun plus(other : Float) : Double
fun plus(other : Long) : Double
fun plus(other : Int) : Double
fun plus(other : Short) : Double
fun plus(other : Byte) : Double
fun plus(other : Char) : Double
fun minus(other : Double) : Double
fun minus(other : Float) : Double
fun minus(other : Long) : Double
fun minus(other : Int) : Double
fun minus(other : Short) : Double
fun minus(other : Byte) : Double
fun minus(other : Char) : Double
fun times(other : Double) : Double
fun times(other : Float) : Double
fun times(other : Long) : Double
fun times(other : Int) : Double
fun times(other : Short) : Double
fun times(other : Byte) : Double
fun times(other : Char) : Double
fun div(other : Double) : Double
fun div(other : Float) : Double
fun div(other : Long) : Double
fun div(other : Int) : Double
fun div(other : Short) : Double
fun div(other : Byte) : Double
fun div(other : Char) : Double
fun mod(other : Double) : Double
fun mod(other : Float) : Double
fun mod(other : Long) : Double
fun mod(other : Int) : Double
fun mod(other : Short) : Double
fun mod(other : Byte) : Double
fun rangeTo(other : Double) : Range<Double>
fun rangeTo(other : Float) : Range<Double>
fun rangeTo(other : Long) : Range<Double>
fun rangeTo(other : Int) : Range<Double>
fun rangeTo(other : Short) : Range<Double>
fun rangeTo(other : Byte) : Range<Double>
fun rangeTo(other : Char) : Range<Double>
fun inc() : Double
fun dec() : Double
fun plus() : Double
fun minus() : Double
}
class Float : Number, Comparable<Float> {
fun compareTo(other : Double) : Int
override fun compareTo(other : Float) : Int
fun compareTo(other : Long) : Int
fun compareTo(other : Int) : Int
fun compareTo(other : Short) : Int
fun compareTo(other : Byte) : Int
fun compareTo(other : Char) : Int
fun plus(other : Double) : Double
fun plus(other : Float) : Float
fun plus(other : Long) : Float
fun plus(other : Int) : Float
fun plus(other : Short) : Float
fun plus(other : Byte) : Float
fun plus(other : Char) : Float
fun minus(other : Double) : Double
fun minus(other : Float) : Float
fun minus(other : Long) : Float
fun minus(other : Int) : Float
fun minus(other : Short) : Float
fun minus(other : Byte) : Float
fun minus(other : Char) : Float
fun times(other : Double) : Double
fun times(other : Float) : Float
fun times(other : Long) : Float
fun times(other : Int) : Float
fun times(other : Short) : Float
fun times(other : Byte) : Float
fun times(other : Char) : Float
fun div(other : Double) : Double
fun div(other : Float) : Float
fun div(other : Long) : Float
fun div(other : Int) : Float
fun div(other : Short) : Float
fun div(other : Byte) : Float
fun div(other : Char) : Float
fun mod(other : Double) : Double
fun mod(other : Float) : Float
fun mod(other : Long) : Float
fun mod(other : Int) : Float
fun mod(other : Short) : Float
fun mod(other : Byte) : Float
fun mod(other : Char) : Float
fun rangeTo(other : Double) : Range<Double>
fun rangeTo(other : Float) : Range<Float>
fun rangeTo(other : Long) : Range<Double>
fun rangeTo(other : Int) : Range<Double>
fun rangeTo(other : Short) : Range<Float>
fun rangeTo(other : Byte) : Range<Float>
fun rangeTo(other : Char) : Range<Float>
fun inc() : Float
fun dec() : Float
fun plus() : Float
fun minus() : Float
}
class Long : Number, Comparable<Long> {
fun compareTo(other : Double) : Int
fun compareTo(other : Float) : Int
override fun compareTo(other : Long) : Int
fun compareTo(other : Int) : Int
fun compareTo(other : Short) : Int
fun compareTo(other : Byte) : Int
fun compareTo(other : Char) : Int
fun plus(other : Double) : Double
fun plus(other : Float) : Float
fun plus(other : Long) : Long
fun plus(other : Int) : Long
fun plus(other : Short) : Long
fun plus(other : Byte) : Long
fun plus(other : Char) : Long
fun minus(other : Double) : Double
fun minus(other : Float) : Float
fun minus(other : Long) : Long
fun minus(other : Int) : Long
fun minus(other : Short) : Long
fun minus(other : Byte) : Long
fun minus(other : Char) : Long
fun times(other : Double) : Double
fun times(other : Float) : Float
fun times(other : Long) : Long
fun times(other : Int) : Long
fun times(other : Short) : Long
fun times(other : Byte) : Long
fun times(other : Char) : Long
fun div(other : Double) : Double
fun div(other : Float) : Float
fun div(other : Long) : Long
fun div(other : Int) : Long
fun div(other : Short) : Long
fun div(other : Byte) : Long
fun div(other : Char) : Long
fun mod(other : Double) : Double
fun mod(other : Float) : Float
fun mod(other : Long) : Long
fun mod(other : Int) : Long
fun mod(other : Short) : Long
fun mod(other : Byte) : Long
fun mod(other : Char) : Long
fun rangeTo(other : Double) : Range<Double>
fun rangeTo(other : Float) : Range<Double>
fun rangeTo(other : Long) : IntRange<Long>
fun rangeTo(other : Int) : IntRange<Long>
fun rangeTo(other : Short) : IntRange<Long>
fun rangeTo(other : Byte) : IntRange<Long>
fun rangeTo(other : Char) : IntRange<Long>
fun inc() : Long
fun dec() : Long
fun plus() : Long
fun minus() : Long
fun shl(bits : Int) : Long
fun shr(bits : Int) : Long
fun ushr(bits : Int) : Long
fun and(other : Long) : Long
fun or(other : Long) : Long
fun xor(other : Long) : Long
fun inv() : Long
}
class Int : Number, Comparable<Int> {
fun compareTo(other : Double) : Int
fun compareTo(other : Float) : Int
fun compareTo(other : Long) : Int
override fun compareTo(other : Int) : Int
fun compareTo(other : Short) : Int
fun compareTo(other : Byte) : Int
fun compareTo(other : Char) : Int
fun plus(other : Double) : Double
fun plus(other : Float) : Float
fun plus(other : Long) : Long
fun plus(other : Int) : Int
fun plus(other : Short) : Int
fun plus(other : Byte) : Int
fun plus(other : Char) : Int
fun minus(other : Double) : Double
fun minus(other : Float) : Float
fun minus(other : Long) : Long
fun minus(other : Int) : Int
fun minus(other : Short) : Int
fun minus(other : Byte) : Int
fun minus(other : Char) : Int
fun times(other : Double) : Double
fun times(other : Float) : Float
fun times(other : Long) : Long
fun times(other : Int) : Int
fun times(other : Short) : Int
fun times(other : Byte) : Int
fun times(other : Char) : Int
fun div(other : Double) : Double
fun div(other : Float) : Float
fun div(other : Long) : Long
fun div(other : Int) : Int
fun div(other : Short) : Int
fun div(other : Byte) : Int
fun div(other : Char) : Int
fun mod(other : Double) : Double
fun mod(other : Float) : Float
fun mod(other : Long) : Long
fun mod(other : Int) : Int
fun mod(other : Short) : Int
fun mod(other : Byte) : Int
fun mod(other : Char) : Int
fun rangeTo(other : Double) : Range<Double>
fun rangeTo(other : Float) : Range<Double>
fun rangeTo(other : Long) : IntRange<Long>
fun rangeTo(other : Int) : IntRange<Int>
fun rangeTo(other : Short) : IntRange<Int>
fun rangeTo(other : Byte) : IntRange<Int>
fun rangeTo(other : Char) : IntRange<Int>
fun inc() : Int
fun dec() : Int
fun plus() : Int
fun minus() : Int
fun shl(bits : Int) : Int
fun shr(bits : Int) : Int
fun ushr(bits : Int) : Int
fun and(other : Int) : Int
fun or(other : Int) : Int
fun xor(other : Int) : Int
fun inv() : Int
}
class Char : Number, Comparable<Char> {
fun compareTo(other : Double) : Int
fun compareTo(other : Float) : Int
fun compareTo(other : Long) : Int
fun compareTo(other : Int) : Int
fun compareTo(other : Short) : Int
override fun compareTo(other : Char) : Int
fun compareTo(other : Byte) : Int
fun plus(other : Double) : Double
fun plus(other : Float) : Float
fun plus(other : Long) : Long
fun plus(other : Int) : Int
fun plus(other : Short) : Int
fun plus(other : Byte) : Int
fun plus(other : Char) : Int
fun minus(other : Double) : Double
fun minus(other : Float) : Float
fun minus(other : Long) : Long
fun minus(other : Int) : Int
fun minus(other : Short) : Int
fun minus(other : Byte) : Int
fun minus(other : Char) : Int
fun times(other : Double) : Double
fun times(other : Float) : Float
fun times(other : Long) : Long
fun times(other : Int) : Int
fun times(other : Short) : Int
fun times(other : Byte) : Int
fun times(other : Char) : Int
fun div(other : Double) : Double
fun div(other : Float) : Float
fun div(other : Long) : Long
fun div(other : Int) : Int
fun div(other : Short) : Int
fun div(other : Byte) : Int
fun div(other : Char) : Int
fun mod(other : Double) : Double
fun mod(other : Float) : Float
fun mod(other : Long) : Long
fun mod(other : Int) : Int
fun mod(other : Short) : Int
fun mod(other : Byte) : Int
fun mod(other : Char) : Int
fun rangeTo(other : Double) : Range<Double>
fun rangeTo(other : Float) : Range<Float>
fun rangeTo(other : Long) : IntRange<Long>
fun rangeTo(other : Int) : IntRange<Int>
fun rangeTo(other : Short) : IntRange<Short>
fun rangeTo(other : Byte) : IntRange<Byte>
fun rangeTo(other : Char) : IntRange<Char>
fun inc() : Char
fun dec() : Char
fun plus() : Int
fun minus() : Int
}
class Short : Number, Comparable<Short> {
fun compareTo(other : Double) : Int
fun compareTo(other : Float) : Int
fun compareTo(other : Long) : Int
fun compareTo(other : Int) : Int
override fun compareTo(other : Short) : Int
fun compareTo(other : Byte) : Int
fun compareTo(other : Char) : Int
fun plus(other : Double) : Double
fun plus(other : Float) : Float
fun plus(other : Long) : Long
fun plus(other : Int) : Int
fun plus(other : Short) : Int
fun plus(other : Byte) : Int
fun plus(other : Char) : Int
fun minus(other : Double) : Double
fun minus(other : Float) : Float
fun minus(other : Long) : Long
fun minus(other : Int) : Int
fun minus(other : Short) : Int
fun minus(other : Byte) : Int
fun minus(other : Char) : Int
fun times(other : Double) : Double
fun times(other : Float) : Float
fun times(other : Long) : Long
fun times(other : Int) : Int
fun times(other : Short) : Int
fun times(other : Byte) : Int
fun times(other : Char) : Int
fun div(other : Double) : Double
fun div(other : Float) : Float
fun div(other : Long) : Long
fun div(other : Int) : Int
fun div(other : Short) : Int
fun div(other : Byte) : Int
fun div(other : Char) : Int
fun mod(other : Double) : Double
fun mod(other : Float) : Float
fun mod(other : Long) : Long
fun mod(other : Int) : Int
fun mod(other : Short) : Int
fun mod(other : Byte) : Int
fun mod(other : Char) : Int
fun rangeTo(other : Double) : Range<Double>
fun rangeTo(other : Float) : Range<Float>
fun rangeTo(other : Long) : IntRange<Long>
fun rangeTo(other : Int) : IntRange<Int>
fun rangeTo(other : Short) : IntRange<Short>
fun rangeTo(other : Byte) : IntRange<Short>
fun rangeTo(other : Char) : IntRange<Int>
fun inc() : Short
fun dec() : Short
fun plus() : Int
fun minus() : Int
}
class Byte : Number, Comparable<Byte> {
fun compareTo(other : Double) : Int
fun compareTo(other : Float) : Int
fun compareTo(other : Long) : Int
fun compareTo(other : Int) : Int
fun compareTo(other : Short) : Int
fun compareTo(other : Char) : Int
override fun compareTo(other : Byte) : Int
fun plus(other : Double) : Double
fun plus(other : Float) : Float
fun plus(other : Long) : Long
fun plus(other : Int) : Int
fun plus(other : Short) : Int
fun plus(other : Byte) : Int
fun plus(other : Char) : Int
fun minus(other : Double) : Double
fun minus(other : Float) : Float
fun minus(other : Long) : Long
fun minus(other : Int) : Int
fun minus(other : Short) : Int
fun minus(other : Byte) : Int
fun minus(other : Char) : Int
fun times(other : Double) : Double
fun times(other : Float) : Float
fun times(other : Long) : Long
fun times(other : Int) : Int
fun times(other : Short) : Int
fun times(other : Byte) : Int
fun times(other : Char) : Int
fun div(other : Double) : Double
fun div(other : Float) : Float
fun div(other : Long) : Long
fun div(other : Int) : Int
fun div(other : Short) : Int
fun div(other : Byte) : Int
fun div(other : Char) : Int
fun mod(other : Double) : Double
fun mod(other : Float) : Float
fun mod(other : Long) : Long
fun mod(other : Int) : Int
fun mod(other : Short) : Int
fun mod(other : Byte) : Int
fun mod(other : Char) : Int
fun rangeTo(other : Double) : Range<Double>
fun rangeTo(other : Float) : Range<Float>
fun rangeTo(other : Long) : IntRange<Long>
fun rangeTo(other : Int) : IntRange<Int>
fun rangeTo(other : Short) : IntRange<Short>
fun rangeTo(other : Byte) : IntRange<Byte>
fun rangeTo(other : Char) : IntRange<Int>
fun inc() : Byte
fun dec() : Byte
fun plus() : Int
fun minus() : Int
}
@@ -0,0 +1,43 @@
/*
* @author max
*/
package org.jetbrains.jet;
import com.intellij.lang.ASTNode;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.plugin.JetLanguage;
import org.jetbrains.jet.lang.psi.JetElement;
import java.lang.reflect.Constructor;
public class JetNodeType extends IElementType {
private Constructor<? extends JetElement> myPsiFactory;
public JetNodeType(@NotNull @NonNls String debugName) {
this(debugName, null);
}
public JetNodeType(@NotNull @NonNls String debugName, Class<? extends JetElement> psiClass) {
super(debugName, JetLanguage.INSTANCE);
try {
myPsiFactory = psiClass != null ? psiClass.getConstructor(ASTNode.class) : null;
} catch (NoSuchMethodException e) {
throw new RuntimeException("Must have a constructor with ASTNode");
}
}
public JetElement createPsi(ASTNode node) {
assert node.getElementType() == this;
try {
if (myPsiFactory == null) {
return new JetElement(node);
}
return myPsiFactory.newInstance(node);
} catch (Exception e) {
throw new RuntimeException("Error creating psi element for node", e);
}
}
}
@@ -0,0 +1,146 @@
/*
* @author max
*/
package org.jetbrains.jet;
import com.intellij.psi.tree.IFileElementType;
import org.jetbrains.jet.plugin.JetLanguage;
import org.jetbrains.jet.lang.psi.*;
public interface JetNodeTypes {
IFileElementType JET_FILE = new IFileElementType(JetLanguage.INSTANCE);
JetNodeType NAMESPACE = new JetNodeType("NAMESPACE", JetNamespace.class);
JetNodeType CLASS = new JetNodeType("CLASS", JetClass.class);
JetNodeType PROPERTY = new JetNodeType("PROPERTY", JetProperty.class);
JetNodeType FUN = new JetNodeType("FUN", JetNamedFunction.class);
JetNodeType TYPEDEF = new JetNodeType("TYPEDEF", JetTypedef.class);
JetNodeType OBJECT_DECLARATION = new JetNodeType("OBJECT_DECLARATION", JetObjectDeclaration.class);
JetNodeType OBJECT_DECLARATION_NAME = new JetNodeType("OBJECT_DECLARATION_NAME", JetObjectDeclarationName.class);
JetNodeType CLASS_OBJECT = new JetNodeType("CLASS_OBJECT", JetClassObject.class);
JetNodeType CONSTRUCTOR = new JetNodeType("CONSTRUCTOR", JetConstructor.class);
JetNodeType ENUM_ENTRY = new JetNodeType("ENUM_ENTRY", JetEnumEntry.class);
JetNodeType ANONYMOUS_INITIALIZER = new JetNodeType("ANONYMOUS_INITIALIZER", JetClassInitializer.class);
JetNodeType TYPE_PARAMETER_LIST = new JetNodeType("TYPE_PARAMETER_LIST", JetTypeParameterList.class);
JetNodeType TYPE_PARAMETER = new JetNodeType("TYPE_PARAMETER", JetTypeParameter.class);
JetNodeType DELEGATION_SPECIFIER_LIST = new JetNodeType("DELEGATION_SPECIFIER_LIST", JetDelegationSpecifierList.class);
JetNodeType DELEGATOR_BY = new JetNodeType("DELEGATOR_BY", JetDelegatorByExpressionSpecifier.class);
JetNodeType DELEGATOR_SUPER_CALL = new JetNodeType("DELEGATOR_SUPER_CALL", JetDelegatorToSuperCall.class);
JetNodeType DELEGATOR_SUPER_CLASS = new JetNodeType("DELEGATOR_SUPER_CLASS", JetDelegatorToSuperClass.class);
JetNodeType CONSTRUCTOR_CALLEE = new JetNodeType("CONSTRUCTOR_CALLEE", JetConstructorCalleeExpression.class);
JetNodeType VALUE_PARAMETER_LIST = new JetNodeType("VALUE_PARAMETER_LIST", JetParameterList.class);
JetNodeType VALUE_PARAMETER = new JetNodeType("VALUE_PARAMETER", JetParameter.class);
JetNodeType CLASS_BODY = new JetNodeType("CLASS_BODY", JetClassBody.class);
JetNodeType IMPORT_DIRECTIVE = new JetNodeType("IMPORT_DIRECTIVE", JetImportDirective.class);
JetNodeType NAMESPACE_BODY = new JetNodeType("NAMESPACE_BODY", JetNamespaceBody.class);
JetNodeType MODIFIER_LIST = new JetNodeType("MODIFIER_LIST", JetModifierList.class);
JetNodeType PRIMARY_CONSTRUCTOR_MODIFIER_LIST = new JetNodeType("PRIMARY_CONSTRUCTOR_MODIFIER_LIST", JetModifierList.class);
JetNodeType ANNOTATION = new JetNodeType("ANNOTATION", JetAnnotation.class);
JetNodeType ANNOTATION_ENTRY = new JetNodeType("ANNOTATION_ENTRY", JetAnnotationEntry.class);
JetNodeType TYPE_ARGUMENT_LIST = new JetNodeType("TYPE_ARGUMENT_LIST", JetTypeArgumentList.class);
JetNodeType VALUE_ARGUMENT_LIST = new JetNodeType("VALUE_ARGUMENT_LIST", JetValueArgumentList.class);
JetNodeType VALUE_ARGUMENT = new JetNodeType("VALUE_ARGUMENT", JetValueArgument.class);
JetNodeType VALUE_ARGUMENT_NAME = new JetNodeType("VALUE_ARGUMENT_NAME", JetValueArgumentName.class);
JetNodeType TYPE_REFERENCE = new JetNodeType("TYPE_REFERENCE", JetTypeReference.class);
JetNodeType LABELED_TUPLE_ENTRY = new JetNodeType("LABELED_TUPLE_ENTRY");
JetNodeType LABELED_TUPLE_TYPE_ENTRY = new JetNodeType("LABELED_TUPLE_TYPE_ENTRY");
JetNodeType USER_TYPE = new JetNodeType("USER_TYPE", JetUserType.class);
JetNodeType TUPLE_TYPE = new JetNodeType("TUPLE_TYPE", JetTupleType.class);
JetNodeType FUNCTION_TYPE = new JetNodeType("FUNCTION_TYPE", JetFunctionType.class);
JetNodeType SELF_TYPE = new JetNodeType("SELF_TYPE", JetSelfType.class);
JetNodeType NULLABLE_TYPE = new JetNodeType("NULLABLE_TYPE", JetNullableType.class);
JetNodeType TYPE_PROJECTION = new JetNodeType("TYPE_PROJECTION", JetTypeProjection.class);
// TODO: review
JetNodeType PROPERTY_ACCESSOR = new JetNodeType("PROPERTY_ACCESSOR", JetPropertyAccessor.class);
JetNodeType INITIALIZER_LIST = new JetNodeType("INITIALIZER_LIST", JetInitializerList.class);
JetNodeType THIS_CALL = new JetNodeType("THIS_CALL", JetDelegatorToThisCall.class);
JetNodeType THIS_CONSTRUCTOR_REFERENCE = new JetNodeType("THIS_CONSTRUCTOR_REFERENCE", JetThisReferenceExpression.class);
JetNodeType TYPE_CONSTRAINT_LIST = new JetNodeType("TYPE_CONSTRAINT_LIST", JetTypeConstraintList.class);
JetNodeType TYPE_CONSTRAINT = new JetNodeType("TYPE_CONSTRAINT", JetTypeConstraint.class);
// TODO: Not sure if we need separate NT for each kind of constants
JetNodeType NULL = new JetNodeType("NULL", JetConstantExpression.class);
JetNodeType BOOLEAN_CONSTANT = new JetNodeType("BOOLEAN_CONSTANT", JetConstantExpression.class);
JetNodeType FLOAT_CONSTANT = new JetNodeType("FLOAT_CONSTANT", JetConstantExpression.class);
JetNodeType CHARACTER_CONSTANT = new JetNodeType("CHARACTER_CONSTANT", JetConstantExpression.class);
JetNodeType RAW_STRING_CONSTANT = new JetNodeType("STRING_CONSTANT", JetConstantExpression.class);
JetNodeType INTEGER_CONSTANT = new JetNodeType("INTEGER_CONSTANT", JetConstantExpression.class);
JetNodeType STRING_TEMPLATE = new JetNodeType("STRING_TEMPLATE", JetStringTemplateExpression.class);
JetNodeType LONG_STRING_TEMPLATE_ENTRY = new JetNodeType("LONG_STRING_TEMPLATE_ENTRY", JetBlockStringTemplateEntry.class);
JetNodeType SHORT_STRING_TEMPLATE_ENTRY = new JetNodeType("SHORT_STRING_TEMPLATE_ENTRY", JetSimpleNameStringTemplateEntry.class);
JetNodeType LITERAL_STRING_TEMPLATE_ENTRY = new JetNodeType("LITERAL_STRING_TEMPLATE_ENTRY", JetLiteralStringTemplateEntry.class);
JetNodeType ESCAPE_STRING_TEMPLATE_ENTRY = new JetNodeType("ESCAPE_STRING_TEMPLATE_ENTRY", JetEscapeStringTemplateEntry.class);
JetNodeType TUPLE = new JetNodeType("TUPLE", JetTupleExpression.class);
JetNodeType PARENTHESIZED = new JetNodeType("PARENTHESIZED", JetParenthesizedExpression.class);
JetNodeType RETURN = new JetNodeType("RETURN", JetReturnExpression.class);
JetNodeType THROW = new JetNodeType("THROW", JetThrowExpression.class);
JetNodeType CONTINUE = new JetNodeType("CONTINUE", JetContinueExpression.class);
JetNodeType BREAK = new JetNodeType("BREAK", JetBreakExpression.class);
JetNodeType IF = new JetNodeType("IF", JetIfExpression.class);
JetNodeType CONDITION = new JetNodeType("CONDITION", JetContainerNode.class);
JetNodeType THEN = new JetNodeType("THEN", JetContainerNode.class);
JetNodeType ELSE = new JetNodeType("ELSE", JetContainerNode.class);
JetNodeType TRY = new JetNodeType("TRY", JetTryExpression.class);
JetNodeType CATCH = new JetNodeType("CATCH", JetCatchClause.class);
JetNodeType FINALLY = new JetNodeType("FINALLY", JetFinallySection.class);
JetNodeType FOR = new JetNodeType("FOR", JetForExpression.class);
JetNodeType WHILE = new JetNodeType("WHILE", JetWhileExpression.class);
JetNodeType DO_WHILE = new JetNodeType("DO_WHILE", JetDoWhileExpression.class);
JetNodeType LOOP_PARAMETER = new JetNodeType("LOOP_PARAMETER", JetParameter.class); // TODO: Do we need separate type?
JetNodeType LOOP_RANGE = new JetNodeType("LOOP_RANGE", JetContainerNode.class);
JetNodeType BODY = new JetNodeType("BODY", JetContainerNode.class);
JetNodeType BLOCK = new JetNodeType("BLOCK", JetBlockExpression.class);
JetNodeType FUNCTION_LITERAL_EXPRESSION = new JetNodeType("FUNCTION_LITERAL_EXPRESSION", JetFunctionLiteralExpression.class);
JetNodeType FUNCTION_LITERAL = new JetNodeType("FUNCTION_LITERAL", JetFunctionLiteral.class);
JetNodeType ANNOTATED_EXPRESSION = new JetNodeType("ANNOTATED_EXPRESSION", JetAnnotatedExpression.class);
JetNodeType REFERENCE_EXPRESSION = new JetNodeType("REFERENCE_EXPRESSION", JetSimpleNameExpression.class);
JetNodeType OPERATION_REFERENCE = new JetNodeType("OPERATION_REFERENCE", JetSimpleNameExpression.class);
JetNodeType LABEL_REFERENCE = new JetNodeType("LABEL_REFERENCE", JetSimpleNameExpression.class);
JetNodeType LABEL_QUALIFIER = new JetNodeType("LABEL_QUALIFIER", JetContainerNode.class);
JetNodeType THIS_EXPRESSION = new JetNodeType("THIS_EXPRESSION", JetThisExpression.class);
JetNodeType BINARY_EXPRESSION = new JetNodeType("BINARY_EXPRESSION", JetBinaryExpression.class);
JetNodeType BINARY_WITH_TYPE = new JetNodeType("BINARY_WITH_TYPE", JetBinaryExpressionWithTypeRHS.class);
JetNodeType BINARY_WITH_PATTERN = new JetNodeType("BINARY_WITH_PATTERN", JetIsExpression.class); // TODO:
JetNodeType PREFIX_EXPRESSION = new JetNodeType("PREFIX_EXPRESSION", JetPrefixExpression.class);
JetNodeType POSTFIX_EXPRESSION = new JetNodeType("POSTFIX_EXPRESSION", JetPostfixExpression.class);
JetNodeType CALL_EXPRESSION = new JetNodeType("CALL_EXPRESSION", JetCallExpression.class);
JetNodeType ARRAY_ACCESS_EXPRESSION = new JetNodeType("ARRAY_ACCESS_EXPRESSION", JetArrayAccessExpression.class);
JetNodeType INDICES = new JetNodeType("INDICES", JetContainerNode.class);
JetNodeType DOT_QUALIFIED_EXPRESSION = new JetNodeType("DOT_QUALIFIED_EXPRESSION", JetDotQualifiedExpression.class);
JetNodeType HASH_QUALIFIED_EXPRESSION = new JetNodeType("HASH_QUALIFIED_EXPRESSION", JetHashQualifiedExpression.class);
JetNodeType SAFE_ACCESS_EXPRESSION = new JetNodeType("SAFE_ACCESS_EXPRESSION", JetSafeQualifiedExpression.class);
JetNodeType PREDICATE_EXPRESSION = new JetNodeType("PREDICATE_EXPRESSION", JetPredicateExpression.class);
JetNodeType OBJECT_LITERAL = new JetNodeType("OBJECT_LITERAL", JetObjectLiteralExpression.class);
JetNodeType ROOT_NAMESPACE = new JetNodeType("ROOT_NAMESPACE", JetRootNamespaceExpression.class);
JetNodeType EXPRESSION_PATTERN = new JetNodeType("EXPRESSION_PATTERN", JetExpressionPattern.class);
JetNodeType TYPE_PATTERN = new JetNodeType("TYPE_PATTERN", JetTypePattern.class);
JetNodeType WILDCARD_PATTERN = new JetNodeType("WILDCARD_PATTERN", JetWildcardPattern.class);
JetNodeType BINDING_PATTERN = new JetNodeType("BINDING_PATTERN", JetBindingPattern.class);
JetNodeType TUPLE_PATTERN = new JetNodeType("TUPLE_PATTERN", JetTuplePattern.class);
JetNodeType TUPLE_PATTERN_ENTRY = new JetNodeType("TUPLE_PATTERN_ENTRY", JetTuplePatternEntry.class);
JetNodeType DECOMPOSER_PATTERN = new JetNodeType("DECOMPOSER_PATTERN", JetDecomposerPattern.class);
JetNodeType DECOMPOSER_ARGUMENT_LIST = new JetNodeType("DECOMPOSER_ARGUMENT_LIST", JetTuplePattern.class);
JetNodeType DECOMPOSER_ARGUMENT = TUPLE_PATTERN_ENTRY;
JetNodeType WHEN = new JetNodeType("WHEN", JetWhenExpression.class);
JetNodeType WHEN_ENTRY = new JetNodeType("WHEN_ENTRY", JetWhenEntry.class);
JetNodeType WHEN_CONDITION_IN_RANGE = new JetNodeType("WHEN_CONDITION_IN_RANGE", JetWhenConditionInRange.class);
JetNodeType WHEN_CONDITION_IS_PATTERN = new JetNodeType("WHEN_CONDITION_IS_PATTERN", JetWhenConditionIsPattern.class);
JetNodeType WHEN_CONDITION_CALL = new JetNodeType("WHEN_CONDITION_CALL", JetWhenConditionCall.class);
JetNodeType NAMESPACE_NAME = new JetNodeType("NAMESPACE_NAME", JetContainerNode.class);
}
@@ -0,0 +1,55 @@
package org.jetbrains.jet.lang;
import com.google.common.collect.Lists;
import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
import org.jetbrains.jet.lang.types.JetType;
import java.util.List;
/**
* @author abreslav
*/
public class CollectingErrorHandler extends ErrorHandler {
private final List<JetDiagnostic> diagnostics;
public CollectingErrorHandler() {
this(Lists.<JetDiagnostic>newArrayList());
}
public CollectingErrorHandler(List<JetDiagnostic> diagnostics) {
this.diagnostics = diagnostics;
}
public List<JetDiagnostic> getDiagnostics() {
return diagnostics;
}
@Override
public void unresolvedReference(@NotNull JetReferenceExpression referenceExpression) {
diagnostics.add(new JetDiagnostic.UnresolvedReferenceError(referenceExpression));
}
@Override
public void typeMismatch(@NotNull JetExpression expression, @NotNull JetType expectedType, @NotNull JetType actualType) {
diagnostics.add(new JetDiagnostic.TypeMismatchError(expression, expectedType, actualType));
}
@Override
public void redeclaration(@NotNull DeclarationDescriptor existingDescriptor, @NotNull DeclarationDescriptor redeclaredDescriptor) {
diagnostics.add(new JetDiagnostic.RedeclarationError(existingDescriptor, redeclaredDescriptor));
}
@Override
public void genericError(@NotNull ASTNode node, @NotNull String errorMessage) {
diagnostics.add(new JetDiagnostic.GenericError(node, errorMessage));
}
@Override
public void genericWarning(@NotNull ASTNode node, @NotNull String message) {
diagnostics.add(new JetDiagnostic.GenericWarning(node, message));
}
}
@@ -0,0 +1,54 @@
package org.jetbrains.jet.lang;
import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
import org.jetbrains.jet.lang.types.JetType;
/**
* @author abreslav
*/
public class CompositeErrorHandler extends ErrorHandler {
private final ErrorHandler[] handlers;
public CompositeErrorHandler(ErrorHandler... handlers) {
this.handlers = handlers;
}
@Override
public void unresolvedReference(@NotNull JetReferenceExpression referenceExpression) {
for (ErrorHandler handler : handlers) {
handler.unresolvedReference(referenceExpression);
}
}
@Override
public void typeMismatch(@NotNull JetExpression expression, @NotNull JetType expectedType, @NotNull JetType actualType) {
for (ErrorHandler handler : handlers) {
handler.typeMismatch(expression, expectedType, actualType);
}
}
@Override
public void redeclaration(@NotNull DeclarationDescriptor existingDescriptor, @NotNull DeclarationDescriptor redeclaredDescriptor) {
for (ErrorHandler handler : handlers) {
handler.redeclaration(existingDescriptor, redeclaredDescriptor);
}
}
@Override
public void genericError(@NotNull ASTNode node, @NotNull String errorMessage) {
for (ErrorHandler handler : handlers) {
handler.genericError(node, errorMessage);
}
}
@Override
public void genericWarning(@NotNull ASTNode node, @NotNull String message) {
for (ErrorHandler handler : handlers) {
handler.genericWarning(node, message);
}
}
}
@@ -0,0 +1,94 @@
package org.jetbrains.jet.lang;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.editor.Document;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Collection;
/**
* @author abreslav
*/
public class ErrorHandler {
public static final ErrorHandler DO_NOTHING = new ErrorHandler();
public static final ErrorHandler THROW_EXCEPTION = new ErrorHandler() {
@Override
public void unresolvedReference(@NotNull JetReferenceExpression referenceExpression) {
throw new IllegalStateException("Unresolved reference: " + referenceExpression.getText() +
atLocation(referenceExpression));
}
@Override
public void genericError(@NotNull ASTNode node, @NotNull String errorMessage) {
throw new IllegalStateException(errorMessage + " at " + node.getText() + atLocation(node));
}
@Override
public void typeMismatch(@NotNull JetExpression expression, @NotNull JetType expectedType, @NotNull JetType actualType) {
throw new IllegalStateException("Type mismatch " + atLocation(expression) + ": inferred type is " + actualType + " but " + expectedType + " was expected");
}
@Override
public void redeclaration(@NotNull DeclarationDescriptor existingDescriptor, @NotNull DeclarationDescriptor redeclaredDescriptor) {
throw new IllegalStateException("Redeclaration: " + existingDescriptor.getName());
}
};
public static String atLocation(@NotNull PsiElement element) {
return atLocation(element.getNode());
}
public static String atLocation(@NotNull ASTNode node) {
while (node.getPsi() == null) {
node = node.getTreeParent();
}
PsiElement element = node.getPsi();
Document document = PsiDocumentManager.getInstance(element.getProject()).getDocument(element.getContainingFile());
int offset = element.getTextRange().getStartOffset();
if (document != null) {
int lineNumber = document.getLineNumber(offset);
int lineStartOffset = document.getLineStartOffset(lineNumber);
int column = offset - lineStartOffset;
return "' at line " + (lineNumber+1) + ":" + column;
}
else {
return "' at offset " + offset + " (line unknown)";
}
}
public static void applyHandler(@NotNull ErrorHandler errorHandler, @NotNull BindingContext bindingContext) {
Collection<JetDiagnostic> diagnostics = bindingContext.getDiagnostics();
applyHandler(errorHandler, diagnostics);
}
public static void applyHandler(@NotNull ErrorHandler errorHandler, @NotNull Collection<JetDiagnostic> diagnostics) {
for (JetDiagnostic jetDiagnostic : diagnostics) {
jetDiagnostic.acceptHandler(errorHandler);
}
}
public void unresolvedReference(@NotNull JetReferenceExpression referenceExpression) {
}
public void typeMismatch(@NotNull JetExpression expression, @NotNull JetType expectedType, @NotNull JetType actualType) {
}
public void redeclaration(@NotNull DeclarationDescriptor existingDescriptor, @NotNull DeclarationDescriptor redeclaredDescriptor) {
}
public void genericError(@NotNull ASTNode node, @NotNull String errorMessage) {
}
public void genericWarning(@NotNull ASTNode node, @NotNull String message) {
}
}
@@ -0,0 +1,44 @@
package org.jetbrains.jet.lang;
import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
import org.jetbrains.jet.lang.types.JetType;
/**
* @author abreslav
*/
public class ErrorHandlerAdapter extends ErrorHandler {
protected ErrorHandler worker;
public ErrorHandlerAdapter(ErrorHandler worker) {
this.worker = worker;
}
@Override
public void unresolvedReference(@NotNull JetReferenceExpression referenceExpression) {
worker.unresolvedReference(referenceExpression);
}
@Override
public void typeMismatch(@NotNull JetExpression expression, @NotNull JetType expectedType, @NotNull JetType actualType) {
worker.typeMismatch(expression, expectedType, actualType);
}
@Override
public void redeclaration(@NotNull DeclarationDescriptor existingDescriptor, @NotNull DeclarationDescriptor redeclaredDescriptor) {
worker.redeclaration(existingDescriptor, redeclaredDescriptor);
}
@Override
public void genericError(@NotNull ASTNode node, @NotNull String errorMessage) {
worker.genericError(node, errorMessage);
}
@Override
public void genericWarning(@NotNull ASTNode node, @NotNull String message) {
worker.genericWarning(node, message);
}
}
@@ -0,0 +1,111 @@
package org.jetbrains.jet.lang;
import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
import org.jetbrains.jet.lang.types.JetType;
/**
* @author abreslav
*/
public abstract class JetDiagnostic {
public static class UnresolvedReferenceError extends JetDiagnostic {
private final JetReferenceExpression referenceExpression;
public UnresolvedReferenceError(@NotNull JetReferenceExpression referenceExpression) {
this.referenceExpression = referenceExpression;
}
@Override
public void acceptHandler(@NotNull ErrorHandler handler) {
handler.unresolvedReference(referenceExpression);
}
@NotNull
public JetReferenceExpression getReferenceExpression() {
return referenceExpression;
}
}
public static class GenericError extends JetDiagnostic {
private final ASTNode node;
private final String message;
public GenericError(@NotNull ASTNode node, @NotNull String message) {
this.node = node;
this.message = message;
}
@Override
public void acceptHandler(@NotNull ErrorHandler handler) {
handler.genericError(node, message);
}
}
public static class TypeMismatchError extends JetDiagnostic {
private final JetExpression expression;
private final JetType expectedType;
private final JetType actualType;
public TypeMismatchError(@NotNull JetExpression expression, @NotNull JetType expectedType, @NotNull JetType actualType) {
this.expression = expression;
this.expectedType = expectedType;
this.actualType = actualType;
}
@Override
public void acceptHandler(@NotNull ErrorHandler handler) {
handler.typeMismatch(expression, expectedType, actualType);
}
}
public static class RedeclarationError extends JetDiagnostic {
private final DeclarationDescriptor existingDescriptor;
private final DeclarationDescriptor redeclaredDescriptor;
public RedeclarationError(@NotNull DeclarationDescriptor existingDescriptor, @NotNull DeclarationDescriptor redeclaredDescriptor) {
this.existingDescriptor = existingDescriptor;
this.redeclaredDescriptor = redeclaredDescriptor;
}
@Override
public void acceptHandler(@NotNull ErrorHandler handler) {
handler.redeclaration(existingDescriptor, redeclaredDescriptor);
}
}
public static class GenericWarning extends JetDiagnostic {
private final ASTNode node;
private final String message;
public GenericWarning(@NotNull ASTNode node, @NotNull String message) {
this.message = message;
this.node = node;
}
@Override
public void acceptHandler(@NotNull ErrorHandler handler) {
handler.genericWarning(node, message);
}
}
// private final StackTraceElement[] stackTrace;
//
// protected JetDiagnostic() {
// stackTrace = Thread.currentThread().getStackTrace();
// }
//
// public StackTraceElement[] getStackTrace() {
// return stackTrace;
// }
public abstract void acceptHandler(@NotNull ErrorHandler handler);
}
@@ -0,0 +1,56 @@
package org.jetbrains.jet.lang;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.types.*;
/**
* @author abreslav
*/
public class JetSemanticServices {
public static JetSemanticServices createSemanticServices(JetStandardLibrary standardLibrary) {
return new JetSemanticServices(standardLibrary, JetControlFlowDataTraceFactory.EMPTY);
}
public static JetSemanticServices createSemanticServices(Project project) {
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
public JetStandardLibrary getStandardLibrary() {
return standardLibrary;
}
@NotNull
public ClassDescriptorResolver getClassDescriptorResolver(BindingTrace trace) {
return new ClassDescriptorResolver(this, trace, flowDataTraceFactory);
}
@NotNull
public JetTypeInferrer.Services getTypeInferrerServices(@NotNull BindingTrace trace, @NotNull JetFlowInformationProvider flowInformationProvider) {
return new JetTypeInferrer(flowInformationProvider, this).getServices(trace);
}
@NotNull
public JetTypeChecker getTypeChecker() {
return typeChecker;
}
}
@@ -0,0 +1,6 @@
package org.jetbrains.jet.lang.cfg;
/**
* @author abreslav
*/
public abstract class BlockInfo {}
@@ -0,0 +1,30 @@
package org.jetbrains.jet.lang.cfg;
import org.jetbrains.jet.lang.psi.JetElement;
/**
* @author abreslav
*/
public class BreakableBlockInfo extends BlockInfo {
private final JetElement element;
private final Label entryPoint;
private final Label exitPoint;
public BreakableBlockInfo(JetElement element, Label entryPoint, Label exitPoint) {
this.element = element;
this.entryPoint = entryPoint;
this.exitPoint = exitPoint;
}
public JetElement getElement() {
return element;
}
public Label getEntryPoint() {
return entryPoint;
}
public Label getExitPoint() {
return exitPoint;
}
}
@@ -0,0 +1,8 @@
package org.jetbrains.jet.lang.cfg;
/**
* @author abreslav
*/
public interface GenerationTrigger {
void generate();
}
@@ -0,0 +1,59 @@
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;
/**
* @author abreslav
*/
public interface JetControlFlowBuilder {
void read(@NotNull JetExpression expression);
void readUnit(@NotNull JetExpression expression);
// General label management
@NotNull
Label createUnboundLabel();
void bindLabel(@NotNull Label label);
// Jumps
void jump(@NotNull Label label);
void jumpOnFalse(@NotNull Label label);
void jumpOnTrue(@NotNull Label label);
void nondeterministicJump(Label label); // Maybe, jump to label
void jumpToError(JetThrowExpression expression);
// Entry/exit points
Label getEntryPoint(@NotNull JetElement labelElement);
Label getExitPoint(@NotNull JetElement labelElement);
// Loops
LoopInfo enterLoop(@NotNull JetExpression expression, @Nullable Label loopExitPoint, @Nullable Label conditionEntryPoint);
void exitLoop(@NotNull JetExpression expression);
@Nullable
JetElement getCurrentLoop();
// Finally
void enterTryFinally(@NotNull GenerationTrigger trigger);
void exitTryFinally();
// Subroutines
void enterSubroutine(@NotNull JetElement subroutine, boolean isFunctionLiteral);
void exitSubroutine(@NotNull JetElement subroutine, boolean functionLiteral);
@Nullable
JetElement getCurrentSubroutine();
void returnValue(@NotNull JetExpression returnExpression, @NotNull JetElement subroutine);
void returnNoValue(@NotNull JetElement returnExpression, @NotNull JetElement subroutine);
void write(@NotNull JetElement assignment, @NotNull JetElement lValue);
// Other
void unsupported(JetElement element);
}
@@ -0,0 +1,136 @@
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;
/**
* @author abreslav
*/
public class JetControlFlowBuilderAdapter implements JetControlFlowBuilder {
protected JetControlFlowBuilder builder;
public JetControlFlowBuilderAdapter(JetControlFlowBuilder builder) {
this.builder = builder;
}
@Override
public void read(@NotNull JetExpression expression) {
builder.read(expression);
}
@Override
public void readUnit(@NotNull JetExpression expression) {
builder.readUnit(expression);
}
@Override
@NotNull
public Label createUnboundLabel() {
return builder.createUnboundLabel();
}
@Override
public void bindLabel(@NotNull Label label) {
builder.bindLabel(label);
}
@Override
public void jump(@NotNull Label label) {
builder.jump(label);
}
@Override
public void jumpOnFalse(@NotNull Label label) {
builder.jumpOnFalse(label);
}
@Override
public void jumpOnTrue(@NotNull Label label) {
builder.jumpOnTrue(label);
}
@Override
public void nondeterministicJump(Label label) {
builder.nondeterministicJump(label);
}
@Override
public void jumpToError(JetThrowExpression expression) {
builder.jumpToError(expression);
}
@Override
public Label getEntryPoint(@NotNull JetElement labelElement) {
return builder.getEntryPoint(labelElement);
}
@Override
public Label getExitPoint(@NotNull JetElement labelElement) {
return builder.getExitPoint(labelElement);
}
@Override
public LoopInfo enterLoop(@NotNull JetExpression expression, Label loopExitPoint, Label conditionEntryPoint) {
return builder.enterLoop(expression, loopExitPoint, conditionEntryPoint);
}
@Override
public void exitLoop(@NotNull JetExpression expression) {
builder.exitLoop(expression);
}
@Override
@Nullable
public JetElement getCurrentLoop() {
return builder.getCurrentLoop();
}
@Override
public void enterTryFinally(@NotNull GenerationTrigger trigger) {
builder.enterTryFinally(trigger);
}
@Override
public void exitTryFinally() {
builder.exitTryFinally();
}
@Override
public void enterSubroutine(@NotNull JetElement subroutine, boolean isFunctionLiteral) {
builder.enterSubroutine(subroutine, isFunctionLiteral);
}
@Override
public void exitSubroutine(@NotNull JetElement subroutine, boolean functionLiteral) {
builder.exitSubroutine(subroutine, functionLiteral);
}
@Override
@Nullable
public JetElement getCurrentSubroutine() {
return builder.getCurrentSubroutine();
}
@Override
public void returnValue(@NotNull JetExpression returnExpression, @NotNull JetElement subroutine) {
builder.returnValue(returnExpression, subroutine);
}
@Override
public void returnNoValue(@NotNull JetElement returnExpression, @NotNull JetElement subroutine) {
builder.returnNoValue(returnExpression, subroutine);
}
@Override
public void unsupported(JetElement element) {
builder.unsupported(element);
}
@Override
public void write(@NotNull JetElement assignment, @NotNull JetElement lValue) {
builder.write(assignment, lValue);
}
}
@@ -0,0 +1,778 @@
package org.jetbrains.jet.lang.cfg;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.types.JetTypeInferrer;
import org.jetbrains.jet.lexer.JetTokens;
import java.util.*;
/**
* @author abreslav
*/
public class JetControlFlowProcessor {
private final Map<String, Stack<JetElement>> labeledElements = new HashMap<String, Stack<JetElement>>();
private final JetControlFlowBuilder builder;
private final BindingTrace trace;
public JetControlFlowProcessor(BindingTrace trace, JetControlFlowBuilder builder) {
this.builder = builder;
this.trace = trace;
}
public void generate(@NotNull JetElement subroutineElement, @NotNull JetExpression body) {
generateSubroutineControlFlow(subroutineElement, Collections.singletonList(body));
}
public void generateSubroutineControlFlow(@NotNull JetElement subroutineElement, @NotNull List<? extends JetElement> body) {
if (subroutineElement instanceof JetNamedDeclaration) {
JetNamedDeclaration namedDeclaration = (JetNamedDeclaration) subroutineElement;
enterLabeledElement(JetPsiUtil.safeName(namedDeclaration.getName()), namedDeclaration);
}
boolean functionLiteral = subroutineElement instanceof JetFunctionLiteralExpression;
builder.enterSubroutine(subroutineElement, functionLiteral);
for (JetElement statement : body) {
statement.accept(new CFPVisitor(false));
}
builder.exitSubroutine(subroutineElement, functionLiteral);
}
private void enterLabeledElement(@NotNull String labelName, @NotNull JetElement labeledElement) {
Stack<JetElement> stack = labeledElements.get(labelName);
if (stack == null) {
stack = new Stack<JetElement>();
labeledElements.put(labelName, stack);
}
stack.push(labeledElement);
}
private void exitElement(JetElement element) {
// TODO : really suboptimal
for (Iterator<Map.Entry<String, Stack<JetElement>>> mapIter = labeledElements.entrySet().iterator(); mapIter.hasNext(); ) {
Map.Entry<String, Stack<JetElement>> entry = mapIter.next();
Stack<JetElement> stack = entry.getValue();
for (Iterator<JetElement> stackIter = stack.iterator(); stackIter.hasNext(); ) {
JetElement recorded = stackIter.next();
if (recorded == element) {
stackIter.remove();
}
}
if (stack.isEmpty()) {
mapIter.remove();
}
}
}
@Nullable
private JetElement resolveLabel(@NotNull String labelName, @NotNull JetSimpleNameExpression labelExpression, boolean reportUnresolved) {
Stack<JetElement> stack = labeledElements.get(labelName);
if (stack == null || stack.isEmpty()) {
if (reportUnresolved) {
trace.getErrorHandler().unresolvedReference(labelExpression);
}
return null;
}
else if (stack.size() > 1) {
trace.getErrorHandler().genericWarning(labelExpression.getNode(), "There is more than one label with such a name in this scope");
}
JetElement result = stack.peek();
trace.record(BindingContext.LABEL_TARGET, labelExpression, result);
return result;
}
private class CFPVisitor extends JetVisitorVoid {
// private final boolean preferBlock;
private final boolean inCondition;
private CFPVisitor(boolean inCondition) {
// this.preferBlock = preferBlock;
this.inCondition = inCondition;
}
private void value(@Nullable JetElement element, boolean inCondition) {
if (element == null) return;
CFPVisitor visitor;
if (this.inCondition == inCondition) {
visitor = this;
}
else {
visitor = new CFPVisitor(inCondition);
}
element.accept(visitor);
exitElement(element);
}
@Override
public void visitParenthesizedExpression(JetParenthesizedExpression expression) {
JetExpression innerExpression = expression.getExpression();
if (innerExpression != null) {
value(innerExpression, inCondition);
}
}
@Override
public void visitThisExpression(JetThisExpression expression) {
JetSimpleNameExpression targetLabel = expression.getTargetLabel();
if (targetLabel != null) {
String labelName = expression.getLabelName();
assert labelName != null;
resolveLabel(labelName, targetLabel, false);
}
builder.read(expression);
}
@Override
public void visitConstantExpression(JetConstantExpression expression) {
builder.read(expression);
}
@Override
public void visitSimpleNameExpression(JetSimpleNameExpression expression) {
builder.read(expression);
}
@Override
public void visitLabelQualifiedExpression(JetLabelQualifiedExpression expression) {
String labelName = expression.getLabelName();
JetExpression labeledExpression = expression.getLabeledExpression();
if (labelName != null && labeledExpression != null) {
visitLabeledExpression(labelName, labeledExpression);
}
}
private void visitLabeledExpression(@NotNull String labelName, @NotNull JetExpression labeledExpression) {
JetExpression deparenthesized = JetPsiUtil.deparenthesize(labeledExpression);
if (deparenthesized != null) {
enterLabeledElement(labelName, deparenthesized);
value(labeledExpression, inCondition);
}
}
@Override
public void visitBinaryExpression(JetBinaryExpression expression) {
IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
JetExpression right = expression.getRight();
if (operationType == JetTokens.ANDAND) {
value(expression.getLeft(), true);
Label resultLabel = builder.createUnboundLabel();
builder.jumpOnFalse(resultLabel);
if (right != null) {
value(right, true);
}
builder.bindLabel(resultLabel);
if (!inCondition) {
builder.read(expression);
}
}
else if (operationType == JetTokens.OROR) {
value(expression.getLeft(), true);
Label resultLabel = builder.createUnboundLabel();
builder.jumpOnTrue(resultLabel);
if (right != null) {
value(right, true);
}
builder.bindLabel(resultLabel);
if (!inCondition) {
builder.read(expression);
}
}
else if (operationType == JetTokens.EQ) {
JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
if (right != null) {
value(right, false);
}
if (left instanceof JetSimpleNameExpression) {
builder.write(expression, left);
}
else if (left instanceof JetArrayAccessExpression) {
JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) left;
visitAssignToArrayAccess(expression, arrayAccessExpression);
} else if (left instanceof JetQualifiedExpression) {
assert !(left instanceof JetPredicateExpression) : left; // TODO
assert !(left instanceof JetHashQualifiedExpression) : left; // TODO
JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression) left;
value(qualifiedExpression.getReceiverExpression(), false);
value(expression.getOperationReference(), false);
builder.write(expression, left);
} else {
builder.unsupported(expression); // TODO
}
}
else if (JetTypeInferrer.assignmentOperationNames.containsKey(operationType)) {
JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
if (left != null) {
value(left, false);
}
if (right != null) {
value(right, false);
}
if (left instanceof JetSimpleNameExpression || left instanceof JetArrayAccessExpression) {
value(expression.getOperationReference(), false);
builder.write(expression, left);
}
else if (left != null) {
builder.unsupported(expression); // TODO
}
}
else {
value(expression.getLeft(), false);
if (right != null) {
value(right, false);
}
value(expression.getOperationReference(), false);
builder.read(expression);
}
}
private void visitAssignToArrayAccess(JetBinaryExpression expression, JetArrayAccessExpression arrayAccessExpression) {
for (JetExpression index : arrayAccessExpression.getIndexExpressions()) {
value(index, false);
}
value(arrayAccessExpression.getArrayExpression(), false);
value(expression.getOperationReference(), false);
builder.write(expression, arrayAccessExpression); // TODO : ???
}
@Override
public void visitUnaryExpression(JetUnaryExpression expression) {
JetSimpleNameExpression operationSign = expression.getOperationSign();
IElementType operationType = operationSign.getReferencedNameElementType();
JetExpression baseExpression = expression.getBaseExpression();
if (JetTokens.LABELS.contains(operationType)) {
String referencedName = operationSign.getReferencedName();
referencedName = referencedName == null ? " <?>" : referencedName;
visitLabeledExpression(referencedName.substring(1), baseExpression);
}
else {
value(baseExpression, false);
value(operationSign, false);
boolean incrementOrDecrement = isIncrementOrDecrement(operationType);
if (incrementOrDecrement) {
builder.write(expression, baseExpression);
}
builder.read(expression);
}
}
private boolean isIncrementOrDecrement(IElementType operationType) {
return operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS;
}
@Override
public void visitIfExpression(JetIfExpression expression) {
JetExpression condition = expression.getCondition();
if (condition != null) {
value(condition, true);
}
Label elseLabel = builder.createUnboundLabel();
builder.jumpOnFalse(elseLabel);
JetExpression thenBranch = expression.getThen();
if (thenBranch != null) {
value(thenBranch, inCondition);
}
else {
builder.readUnit(expression);
}
Label resultLabel = builder.createUnboundLabel();
builder.jump(resultLabel);
builder.bindLabel(elseLabel);
JetExpression elseBranch = expression.getElse();
if (elseBranch != null) {
value(elseBranch, inCondition);
}
else {
builder.readUnit(expression);
}
builder.bindLabel(resultLabel);
}
@Override
public void visitTryExpression(JetTryExpression expression) {
final JetFinallySection finallyBlock = expression.getFinallyBlock();
if (finallyBlock != null) {
builder.enterTryFinally(new GenerationTrigger() {
private boolean working = false;
@Override
public void generate() {
// This checks are needed for the case of having e.g. return inside finally: 'try {return} finally{return}'
if (working) return;
working = true;
value(finallyBlock.getFinalExpression(), inCondition);
working = false;
}
});
}
Label onException = builder.createUnboundLabel();
builder.nondeterministicJump(onException);
value(expression.getTryBlock(), inCondition);
List<JetCatchClause> catchClauses = expression.getCatchClauses();
if (!catchClauses.isEmpty()) {
Label afterCatches = builder.createUnboundLabel();
builder.jump(afterCatches);
builder.bindLabel(onException);
for (Iterator<JetCatchClause> iterator = catchClauses.iterator(); iterator.hasNext(); ) {
JetCatchClause catchClause = iterator.next();
JetExpression catchBody = catchClause.getCatchBody();
if (catchBody != null) {
value(catchBody, false);
}
if (iterator.hasNext()) {
builder.nondeterministicJump(afterCatches);
}
}
builder.bindLabel(afterCatches);
} else {
builder.bindLabel(onException);
}
if (finallyBlock != null) {
builder.exitTryFinally();
value(finallyBlock.getFinalExpression(), inCondition);
}
}
@Override
public void visitWhileExpression(JetWhileExpression expression) {
LoopInfo loopInfo = builder.enterLoop(expression, null, null);
builder.bindLabel(loopInfo.getConditionEntryPoint());
JetExpression condition = expression.getCondition();
if (condition != null) {
value(condition, true);
}
builder.jumpOnFalse(loopInfo.getExitPoint());
builder.bindLabel(loopInfo.getBodyEntryPoint());
JetExpression body = expression.getBody();
if (body != null) {
value(body, false);
}
builder.jump(loopInfo.getEntryPoint());
builder.exitLoop(expression);
builder.readUnit(expression);
}
@Override
public void visitDoWhileExpression(JetDoWhileExpression expression) {
LoopInfo loopInfo = builder.enterLoop(expression, null, null);
builder.bindLabel(loopInfo.getBodyEntryPoint());
JetExpression body = expression.getBody();
if (body != null) {
value(body, false);
}
builder.bindLabel(loopInfo.getConditionEntryPoint());
JetExpression condition = expression.getCondition();
if (condition != null) {
value(condition, true);
}
builder.jumpOnTrue(loopInfo.getEntryPoint());
builder.exitLoop(expression);
builder.readUnit(expression);
}
@Override
public void visitForExpression(JetForExpression expression) {
JetExpression loopRange = expression.getLoopRange();
if (loopRange != null) {
value(loopRange, false);
}
// TODO : primitive cases
Label loopExitPoint = builder.createUnboundLabel();
Label conditionEntryPoint = builder.createUnboundLabel();
builder.bindLabel(conditionEntryPoint);
builder.nondeterministicJump(loopExitPoint);
LoopInfo loopInfo = builder.enterLoop(expression, loopExitPoint, conditionEntryPoint);
builder.bindLabel(loopInfo.getBodyEntryPoint());
JetExpression body = expression.getBody();
if (body != null) {
value(body, false);
}
builder.nondeterministicJump(loopInfo.getEntryPoint());
builder.exitLoop(expression);
builder.readUnit(expression);
}
@Override
public void visitBreakExpression(JetBreakExpression expression) {
JetElement loop = getCorrespondingLoop(expression);
if (loop != null) {
builder.jump(builder.getExitPoint(loop));
}
}
@Override
public void visitContinueExpression(JetContinueExpression expression) {
JetElement loop = getCorrespondingLoop(expression);
if (loop != null) {
builder.jump(builder.getEntryPoint(loop));
}
}
private JetElement getCorrespondingLoop(JetLabelQualifiedExpression expression) {
String labelName = expression.getLabelName();
JetElement loop;
if (labelName != null) {
JetSimpleNameExpression targetLabel = expression.getTargetLabel();
assert targetLabel != null;
loop = resolveLabel(labelName, targetLabel, true);
if (!isLoop(loop)) {
trace.getErrorHandler().genericError(expression.getNode(), "The label '" + targetLabel.getText() + "' does not denote a loop");
loop = null;
}
}
else {
loop = builder.getCurrentLoop();
if (loop == null) {
trace.getErrorHandler().genericError(expression.getNode(), "'break' and 'continue' are only allowed inside a loop");
}
}
return loop;
}
private boolean isLoop(JetElement loop) {
return loop instanceof JetWhileExpression ||
loop instanceof JetDoWhileExpression ||
loop instanceof JetForExpression;
}
@Override
public void visitReturnExpression(JetReturnExpression expression) {
JetExpression returnedExpression = expression.getReturnedExpression();
if (returnedExpression != null) {
value(returnedExpression, false);
}
JetSimpleNameExpression labelElement = expression.getTargetLabel();
JetElement subroutine;
if (labelElement != null) {
String labelName = expression.getLabelName();
assert labelName != null;
subroutine = resolveLabel(labelName, labelElement, true);
}
else {
subroutine = builder.getCurrentSubroutine();
// TODO : a context check
}
if (subroutine != null) {
if (returnedExpression == null) {
builder.returnNoValue(expression, subroutine);
}
else {
builder.returnValue(expression, subroutine);
}
}
}
@Override
public void visitBlockExpression(JetBlockExpression expression) {
List<JetElement> statements = expression.getStatements();
for (JetElement statement : statements) {
value(statement, false);
}
if (statements.isEmpty()) {
builder.readUnit(expression);
}
}
@Override
public void visitNamedFunction(JetNamedFunction function) {
JetExpression bodyExpression = function.getBodyExpression();
if (bodyExpression != null) {
generate(function, bodyExpression);
}
}
@Override
public void visitFunctionLiteralExpression(JetFunctionLiteralExpression expression) {
JetFunctionLiteral functionLiteral = expression.getFunctionLiteral();
JetBlockExpression bodyExpression = expression.getFunctionLiteral().getBodyExpression();
if (bodyExpression != null) {
List<JetElement> statements = bodyExpression.getStatements();
generateSubroutineControlFlow(expression, statements);
}
}
@Override
public void visitQualifiedExpression(JetQualifiedExpression expression) {
value(expression.getReceiverExpression(), false);
JetExpression selectorExpression = expression.getSelectorExpression();
if (selectorExpression != null) {
value(selectorExpression, false);
}
builder.read(expression);
}
private void visitCall(JetCallElement call) {
for (ValueArgument argument : call.getValueArguments()) {
JetExpression argumentExpression = argument.getArgumentExpression();
if (argumentExpression != null) {
value(argumentExpression, false);
}
}
for (JetExpression functionLiteral : call.getFunctionLiteralArguments()) {
value(functionLiteral, false);
}
}
@Override
public void visitCallExpression(JetCallExpression expression) {
for (JetTypeProjection typeArgument : expression.getTypeArguments()) {
value(typeArgument, false);
}
visitCall(expression);
value(expression.getCalleeExpression(), false);
builder.read(expression);
}
// @Override
// public void visitNewExpression(JetNewExpression expression) {
// // TODO : Instantiated class is loaded
// // TODO : type arguments?
// visitCall(expression);
// builder.read(expression);
// }
@Override
public void visitProperty(JetProperty property) {
JetExpression initializer = property.getInitializer();
if (initializer != null) {
value(initializer, false);
builder.write(property, property);
}
}
@Override
public void visitTupleExpression(JetTupleExpression expression) {
for (JetExpression entry : expression.getEntries()) {
value(entry, false);
}
builder.read(expression);
}
@Override
public void visitBinaryWithTypeRHSExpression(JetBinaryExpressionWithTypeRHS expression) {
IElementType operationType = expression.getOperationSign().getReferencedNameElementType();
if (operationType == JetTokens.COLON || operationType == JetTokens.AS_KEYWORD || operationType == JetTokens.AS_SAFE) {
value(expression.getLeft(), false);
builder.read(expression);
}
else {
visitJetElement(expression);
}
}
@Override
public void visitThrowExpression(JetThrowExpression expression) {
JetExpression thrownExpression = expression.getThrownExpression();
if (thrownExpression != null) {
value(thrownExpression, false);
}
builder.jumpToError(expression);
}
@Override
public void visitArrayAccessExpression(JetArrayAccessExpression expression) {
for (JetExpression index : expression.getIndexExpressions()) {
value(index, false);
}
value(expression.getArrayExpression(), false);
// TODO : read 'get' or 'set' function
builder.read(expression);
}
@Override
public void visitIsExpression(JetIsExpression expression) {
value(expression.getLeftHandSide(), inCondition);
// TODO : builder.read(expression.getPattern());
builder.read(expression);
}
@Override
public void visitWhenExpression(JetWhenExpression expression) {
// TODO : no more than one else
// TODO : else must be the last
JetExpression subjectExpression = expression.getSubjectExpression();
if (subjectExpression != null) {
value(subjectExpression, inCondition);
}
Label doneLabel = builder.createUnboundLabel();
Label nextLabel = builder.createUnboundLabel();
for (Iterator<JetWhenEntry> iterator = expression.getEntries().iterator(); iterator.hasNext(); ) {
JetWhenEntry whenEntry = iterator.next();
if (whenEntry.isElse()) {
if (iterator.hasNext()) {
trace.getErrorHandler().genericError(whenEntry.getNode(), "'else' entry must be the last one in a when-expression");
}
}
Label bodyLabel = builder.createUnboundLabel();
JetWhenCondition[] conditions = whenEntry.getConditions();
for (int i = 0; i < conditions.length; i++) {
JetWhenCondition condition = conditions[i];
condition.accept(new JetVisitorVoid() {
private final JetVisitorVoid conditionVisitor = this;
@Override
public void visitWhenConditionCall(JetWhenConditionCall condition) {
value(condition.getCallSuffixExpression(), inCondition); // TODO : inCondition?
}
@Override
public void visitWhenConditionInRange(JetWhenConditionInRange condition) {
value(condition.getRangeExpression(), inCondition); // TODO : inCondition?
value(condition.getOperationReference(), inCondition); // TODO : inCondition?
// TODO : read the call to contains()...
}
@Override
public void visitWhenConditionIsPattern(JetWhenConditionIsPattern condition) {
JetPattern pattern = condition.getPattern();
if (pattern != null) {
pattern.accept(new JetVisitorVoid() {
@Override
public void visitTypePattern(JetTypePattern typePattern) {
// TODO
}
@Override
public void visitWildcardPattern(JetWildcardPattern pattern) {
// TODO
}
@Override
public void visitExpressionPattern(JetExpressionPattern pattern) {
value(pattern.getExpression(), inCondition);
}
@Override
public void visitTuplePattern(JetTuplePattern pattern) {
// TODO
}
@Override
public void visitDecomposerPattern(JetDecomposerPattern pattern) {
value(pattern.getDecomposerExpression(), inCondition);
pattern.getArgumentList().accept(this);
}
@Override
public void visitBindingPattern(JetBindingPattern pattern) {
JetWhenCondition condition = pattern.getCondition();
if (condition != null) {
condition.accept(conditionVisitor);
}
}
@Override
public void visitJetElement(JetElement element) {
throw new UnsupportedOperationException("[JetControlFlowProcessor] " + element.toString());
}
});
}
}
@Override
public void visitJetElement(JetElement element) {
throw new UnsupportedOperationException("[JetControlFlowProcessor] " + element.toString());
}
});
if (i + 1 < conditions.length) {
builder.nondeterministicJump(bodyLabel);
}
}
builder.nondeterministicJump(nextLabel);
builder.bindLabel(bodyLabel);
value(whenEntry.getExpression(), inCondition);
builder.jump(doneLabel);
builder.bindLabel(nextLabel);
nextLabel = builder.createUnboundLabel();
}
// TODO : if there's else, no error can happen
builder.jumpToError(null);
builder.bindLabel(doneLabel);
}
@Override
public void visitObjectLiteralExpression(JetObjectLiteralExpression expression) {
// List<JetDelegationSpecifier> delegationSpecifiers = expression.getObjectDeclaration().getDelegationSpecifiers();
// for (JetDelegationSpecifier delegationSpecifier : delegationSpecifiers) {
// if (delegationSpecifier instanceof JetDelegatorByExpressionSpecifier) {
// JetDelegatorByExpressionSpecifier specifier = (JetDelegatorByExpressionSpecifier) delegationSpecifier;
// JetExpression delegateExpression = specifier.getDelegateExpression();
// if (delegateExpression != null) {
// value(delegateExpression, false, false);
// }
// }
// }
value(expression.getObjectDeclaration(), inCondition);
builder.read(expression);
}
@Override
public void visitObjectDeclaration(JetObjectDeclaration declaration) {
for (JetDelegationSpecifier delegationSpecifier : declaration.getDelegationSpecifiers()) {
value(delegationSpecifier, inCondition);
}
for (JetDeclaration jetDeclaration : declaration.getDeclarations()) {
FOR_LOCAL_CLASSES.value(jetDeclaration, false);
}
}
@Override
public void visitStringTemplateExpression(JetStringTemplateExpression expression) {
for (JetStringTemplateEntry entry : expression.getEntries()) {
if (entry instanceof JetStringTemplateEntryWithExpression) {
JetStringTemplateEntryWithExpression entryWithExpression = (JetStringTemplateEntryWithExpression) entry;
value(entryWithExpression.getExpression(), false);
}
}
builder.read(expression);
}
@Override
public void visitTypeProjection(JetTypeProjection typeProjection) {
// TODO : Support Type Arguments. Class object may be initialized at this point");
}
@Override
public void visitJetElement(JetElement element) {
builder.unsupported(element);
}
}
private final CFPVisitor FOR_LOCAL_CLASSES = new CFPVisitor(false) {
@Override
public void visitNamedFunction(JetNamedFunction function) {
// Nothing
}
};
}
@@ -0,0 +1,92 @@
package org.jetbrains.jet.lang.cfg;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetLoopExpression;
import java.util.Collection;
/**
* @author abreslav
*/
public interface JetFlowInformationProvider {
JetFlowInformationProvider THROW_EXCEPTION = new JetFlowInformationProvider() {
@Override
public void collectReturnedInformation(@NotNull JetElement subroutine, @NotNull Collection<JetExpression> returnedExpressions, @NotNull Collection<JetElement> elementsReturningUnit) {
throw new UnsupportedOperationException();
}
@Override
public void collectReturnExpressions(@NotNull JetElement subroutine, @NotNull Collection<JetExpression> returnedExpressions) {
throw new UnsupportedOperationException();
}
@Override
public void collectUnreachableExpressions(@NotNull JetElement subroutine, @NotNull Collection<JetElement> unreachableElements) {
throw new UnsupportedOperationException();
}
@Override
public void collectDominatedExpressions(@NotNull JetExpression dominator, @NotNull Collection<JetElement> dominated) {
throw new UnsupportedOperationException();
}
@Override
public boolean isBreakable(JetLoopExpression loop) {
throw new UnsupportedOperationException();
}
};
JetFlowInformationProvider NONE = new JetFlowInformationProvider() {
@Override
public void collectReturnedInformation(@NotNull JetElement subroutine, @NotNull Collection<JetExpression> returnedExpressions, @NotNull Collection<JetElement> elementsReturningUnit) {
}
@Override
public void collectReturnExpressions(@NotNull JetElement subroutine, @NotNull Collection<JetExpression> returnedExpressions) {
}
@Override
public void collectUnreachableExpressions(@NotNull JetElement subroutine, @NotNull Collection<JetElement> unreachableElements) {
}
@Override
public void collectDominatedExpressions(@NotNull JetExpression dominator, @NotNull Collection<JetElement> dominated) {
}
@Override
public boolean isBreakable(JetLoopExpression loop) {
return false;
}
};
/**
* Collects expressions returned from the given subroutine and 'return;' expressions
*/
void collectReturnedInformation(
@NotNull JetElement subroutine,
@NotNull Collection<JetExpression> returnedExpressions,
@NotNull Collection<JetElement> elementsReturningUnit);
/**
* Collects all 'return ...' expressions that return from the given subroutine and all the expressions that precede the exit point
*/
void collectReturnExpressions(@NotNull JetElement subroutine, @NotNull Collection<JetExpression> returnedExpressions);
void collectUnreachableExpressions(
@NotNull JetElement subroutine,
@NotNull Collection<JetElement> unreachableElements);
void collectDominatedExpressions(
@NotNull JetExpression dominator,
@NotNull Collection<JetElement> dominated);
boolean isBreakable(JetLoopExpression loop);
}
@@ -0,0 +1,8 @@
package org.jetbrains.jet.lang.cfg;
/**
* @author abreslav
*/
public interface Label {
String getName();
}
@@ -0,0 +1,25 @@
package org.jetbrains.jet.lang.cfg;
import org.jetbrains.jet.lang.psi.JetElement;
/**
* @author abreslav
*/
public class LoopInfo extends BreakableBlockInfo {
private final Label bodyEntryPoint;
private final Label conditionEntryPoint;
public LoopInfo(JetElement element, Label entryPoint, Label exitPoint, Label bodyEntryPoint, Label conditionEntryPoint) {
super(element, entryPoint, exitPoint);
this.bodyEntryPoint = bodyEntryPoint;
this.conditionEntryPoint = conditionEntryPoint;
}
public Label getBodyEntryPoint() {
return bodyEntryPoint;
}
public Label getConditionEntryPoint() {
return conditionEntryPoint;
}
}
@@ -0,0 +1,37 @@
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.cfg.Label;
import java.util.Collection;
import java.util.Collections;
/**
* @author abreslav
*/
public abstract class AbstractJumpInstruction extends InstructionImpl {
private final Label targetLabel;
private Instruction resolvedTarget;
public AbstractJumpInstruction(Label targetLabel) {
this.targetLabel = targetLabel;
}
public Label getTargetLabel() {
return targetLabel;
}
public Instruction getResolvedTarget() {
return resolvedTarget;
}
@NotNull
@Override
public Collection<Instruction> getNextInstructions() {
return Collections.singleton(getResolvedTarget());
}
public void setResolvedTarget(Instruction resolvedTarget) {
this.resolvedTarget = outgoingEdgeTo(resolvedTarget);
}
}
@@ -0,0 +1,58 @@
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.cfg.Label;
import java.util.Arrays;
import java.util.Collection;
/**
* @author abreslav
*/
public class ConditionalJumpInstruction extends AbstractJumpInstruction {
private final boolean onTrue;
private Instruction nextOnTrue;
private Instruction nextOnFalse;
public ConditionalJumpInstruction(boolean onTrue, Label targetLabel) {
super(targetLabel);
this.onTrue = onTrue;
}
public boolean onTrue() {
return onTrue;
}
public Instruction getNextOnTrue() {
return nextOnTrue;
}
public void setNextOnTrue(Instruction nextOnTrue) {
this.nextOnTrue = outgoingEdgeTo(nextOnTrue);
}
public Instruction getNextOnFalse() {
return nextOnFalse;
}
public void setNextOnFalse(Instruction nextOnFalse) {
this.nextOnFalse = outgoingEdgeTo(nextOnFalse);
}
@NotNull
@Override
public Collection<Instruction> getNextInstructions() {
return Arrays.asList(getNextOnFalse(), getNextOnTrue());
}
@Override
public void accept(InstructionVisitor visitor) {
visitor.visitConditionalJump(this);
}
@Override
public String toString() {
String instr = onTrue ? "jt" : "jf";
return instr + "(" + getTargetLabel().getName() + ")";
}
}
@@ -0,0 +1,34 @@
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression;
/**
* @author abreslav
*/
public class FunctionLiteralValueInstruction extends ReadValueInstruction {
private Pseudocode body;
public FunctionLiteralValueInstruction(@NotNull JetFunctionLiteralExpression expression) {
super(expression);
}
public Pseudocode getBody() {
return body;
}
public void setBody(Pseudocode body) {
this.body = body;
}
@Override
public void accept(InstructionVisitor visitor) {
visitor.visitFunctionLiteralValue(this);
}
@Override
public String toString() {
return "rf(" + element.getText() + ")";
}
}
@@ -0,0 +1,22 @@
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
/**
* @author abreslav
*/
public interface Instruction {
@NotNull
Pseudocode getOwner();
void setOwner(@NotNull Pseudocode owner);
Collection<Instruction> getPreviousInstructions();
@NotNull
Collection<Instruction> getNextInstructions();
void accept(InstructionVisitor visitor);
}
@@ -0,0 +1,44 @@
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.LinkedHashSet;
/**
* @author abreslav
*/
public abstract class InstructionImpl implements Instruction {
private Pseudocode owner;
private final Collection<Instruction> previousInstructions = new LinkedHashSet<Instruction>();
protected InstructionImpl() {
}
@Override
@NotNull
public Pseudocode getOwner() {
return owner;
}
@Override
public void setOwner(@NotNull Pseudocode owner) {
assert this.owner == null || this.owner == owner;
this.owner = owner;
}
@Override
public Collection<Instruction> getPreviousInstructions() {
return previousInstructions;
}
@Nullable
protected Instruction outgoingEdgeTo(@Nullable Instruction target) {
if (target != null) {
target.getPreviousInstructions().add(this);
}
return target;
}
}
@@ -0,0 +1,65 @@
package org.jetbrains.jet.lang.cfg.pseudocode;
/**
* @author abreslav
*/
public class InstructionVisitor {
public void visitReadValue(ReadValueInstruction instruction) {
visitInstructionWithNext(instruction);
}
public void visitFunctionLiteralValue(FunctionLiteralValueInstruction instruction) {
visitReadValue(instruction);
}
public void visitUnconditionalJump(UnconditionalJumpInstruction instruction) {
visitJump(instruction);
}
public void visitConditionalJump(ConditionalJumpInstruction instruction) {
visitJump(instruction);
}
public void visitReturnValue(ReturnValueInstruction instruction) {
visitJump(instruction);
}
public void visitReturnNoValue(ReturnNoValueInstruction instruction) {
visitJump(instruction);
}
public void visitNondeterministicJump(NondeterministicJumpInstruction instruction) {
visitJump(instruction);
}
public void visitUnsupportedElementInstruction(UnsupportedElementInstruction instruction) {
visitInstructionWithNext(instruction);
}
public void visitSubroutineExit(SubroutineExitInstruction instruction) {
visitInstruction(instruction);
}
public void visitJump(AbstractJumpInstruction instruction) {
visitInstruction(instruction);
}
public void visitInstructionWithNext(InstructionWithNext instruction) {
visitInstruction(instruction);
}
public void visitInstruction(Instruction instruction) {
}
public void visitSubroutineEnter(SubroutineEnterInstruction instruction) {
visitInstructionWithNext(instruction);
}
public void visitWriteValue(WriteValueInstruction writeValueInstruction) {
visitInstructionWithNext(writeValueInstruction);
}
public void visitReadUnitValue(ReadUnitValueInstruction instruction) {
visitInstructionWithNext(instruction);
}
}
@@ -0,0 +1,32 @@
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetElement;
import java.util.Collection;
import java.util.Collections;
/**
* @author abreslav
*/
public abstract class InstructionWithNext extends JetElementInstructionImpl {
private Instruction next;
protected InstructionWithNext(@NotNull JetElement element) {
super(element);
}
public Instruction getNext() {
return next;
}
@NotNull
@Override
public Collection<Instruction> getNextInstructions() {
return Collections.singleton(next);
}
public void setNext(Instruction next) {
this.next = outgoingEdgeTo(next);
}
}
@@ -0,0 +1,20 @@
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetElement;
/**
* @author abreslav
*/
public interface JetControlFlowDataTraceFactory {
JetControlFlowDataTraceFactory EMPTY = new JetControlFlowDataTraceFactory() {
@NotNull
@Override
public JetPseudocodeTrace createTrace(JetElement element) {
return JetPseudocodeTrace.EMPTY;
}
};
@NotNull
JetPseudocodeTrace createTrace(JetElement element);
}
@@ -0,0 +1,283 @@
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.cfg.*;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression;
import org.jetbrains.jet.lang.psi.JetThrowExpression;
import java.util.*;
/**
* @author abreslav
*/
public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAdapter {
private final Stack<BreakableBlockInfo> loopInfo = new Stack<BreakableBlockInfo>();
private final Map<JetElement, BreakableBlockInfo> elementToBlockInfo = new HashMap<JetElement, BreakableBlockInfo>();
private int labelCount = 0;
private final Stack<JetControlFlowInstructionsGeneratorWorker> builders = new Stack<JetControlFlowInstructionsGeneratorWorker>();
private final Stack<BlockInfo> allBlocks = new Stack<BlockInfo>();
private final JetPseudocodeTrace trace;
public JetControlFlowInstructionsGenerator(JetPseudocodeTrace trace) {
super(null);
this.trace = trace;
}
private void pushBuilder(JetElement scopingElement, JetElement subroutine) {
JetControlFlowInstructionsGeneratorWorker worker = new JetControlFlowInstructionsGeneratorWorker(scopingElement, subroutine);
builders.push(worker);
builder = worker;
}
private JetControlFlowInstructionsGeneratorWorker popBuilder(@NotNull JetElement element) {
JetControlFlowInstructionsGeneratorWorker worker = builders.pop();
trace.recordControlFlowData(element, worker.getPseudocode());
if (!builders.isEmpty()) {
builder = builders.peek();
}
return worker;
}
@Override
public void enterSubroutine(@NotNull JetElement subroutine, boolean isFunctionLiteral) {
if (isFunctionLiteral) {
pushBuilder(subroutine, builder.getCurrentSubroutine());
}
else {
pushBuilder(subroutine, subroutine);
}
builder.enterSubroutine(subroutine, false);
}
@Override
public void exitSubroutine(@NotNull JetElement subroutine, boolean functionLiteral) {
super.exitSubroutine(subroutine, functionLiteral);
JetControlFlowInstructionsGeneratorWorker worker = popBuilder(subroutine);
if (functionLiteral) {
JetControlFlowInstructionsGeneratorWorker builder = builders.peek();
FunctionLiteralValueInstruction instruction = new FunctionLiteralValueInstruction((JetFunctionLiteralExpression) subroutine);
instruction.setBody(worker.getPseudocode());
builder.add(instruction);
}
}
private class JetControlFlowInstructionsGeneratorWorker implements JetControlFlowBuilder {
private final Pseudocode pseudocode;
private final Label error;
private final JetElement currentSubroutine;
private JetControlFlowInstructionsGeneratorWorker(@NotNull JetElement scopingElement, @NotNull JetElement currentSubroutine) {
this.pseudocode = new Pseudocode(scopingElement);
this.error = pseudocode.createLabel("error");
this.currentSubroutine = currentSubroutine;
}
public Pseudocode getPseudocode() {
return pseudocode;
}
private void add(@NotNull Instruction instruction) {
pseudocode.addInstruction(instruction);
if (instruction instanceof JetElementInstruction) {
JetElementInstruction elementInstruction = (JetElementInstruction) instruction;
trace.recordRepresentativeInstruction(elementInstruction.getElement(), instruction);
}
}
@NotNull
@Override
public final Label createUnboundLabel() {
return pseudocode.createLabel("l" + labelCount++);
}
@Override
public final LoopInfo enterLoop(@NotNull JetExpression expression, Label loopExitPoint, Label conditionEntryPoint) {
Label label = createUnboundLabel();
bindLabel(label);
LoopInfo blockInfo = new LoopInfo(
expression,
label,
loopExitPoint != null ? loopExitPoint : createUnboundLabel(),
createUnboundLabel(),
conditionEntryPoint != null ? conditionEntryPoint : createUnboundLabel());
loopInfo.push(blockInfo);
elementToBlockInfo.put(expression, blockInfo);
allBlocks.push(blockInfo);
trace.recordLoopInfo(expression, blockInfo);
return blockInfo;
}
@Override
public final void exitLoop(@NotNull JetExpression expression) {
BreakableBlockInfo info = loopInfo.pop();
elementToBlockInfo.remove(expression);
allBlocks.pop();
bindLabel(info.getExitPoint());
}
@Override
public JetElement getCurrentLoop() {
return loopInfo.empty() ? null : loopInfo.peek().getElement();
}
@Override
public void enterSubroutine(@NotNull JetElement subroutine, boolean isFunctionLiteral) {
Label entryPoint = createUnboundLabel();
BreakableBlockInfo blockInfo = new BreakableBlockInfo(subroutine, entryPoint, createUnboundLabel());
// subroutineInfo.push(blockInfo);
elementToBlockInfo.put(subroutine, blockInfo);
allBlocks.push(blockInfo);
bindLabel(entryPoint);
add(new SubroutineEnterInstruction(subroutine));
}
@Override
public JetElement getCurrentSubroutine() {
return currentSubroutine;// subroutineInfo.empty() ? null : subroutineInfo.peek().getElement();
}
@Override
public Label getEntryPoint(@NotNull JetElement labelElement) {
return elementToBlockInfo.get(labelElement).getEntryPoint();
}
@Override
public Label getExitPoint(@NotNull JetElement labelElement) {
BreakableBlockInfo blockInfo = elementToBlockInfo.get(labelElement);
assert blockInfo != null : labelElement.getText();
return blockInfo.getExitPoint();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void handleJumpInsideTryFinally(Label jumpTarget) {
List<TryFinallyBlockInfo> finallyBlocks = new ArrayList<TryFinallyBlockInfo>();
for (int i = allBlocks.size() - 1; i >= 0; i--) {
BlockInfo blockInfo = allBlocks.get(i);
if (blockInfo instanceof BreakableBlockInfo) {
BreakableBlockInfo breakableBlockInfo = (BreakableBlockInfo) blockInfo;
if (jumpTarget == breakableBlockInfo.getExitPoint() || jumpTarget == breakableBlockInfo.getEntryPoint()) {
for (int j = finallyBlocks.size() - 1; j >= 0; j--) {
finallyBlocks.get(j).generateFinallyBlock();
}
break;
}
}
else if (blockInfo instanceof TryFinallyBlockInfo) {
TryFinallyBlockInfo tryFinallyBlockInfo = (TryFinallyBlockInfo) blockInfo;
finallyBlocks.add(tryFinallyBlockInfo);
}
}
}
@Override
public void exitSubroutine(@NotNull JetElement subroutine, boolean functionLiteral) {
bindLabel(getExitPoint(subroutine));
pseudocode.addExitInstruction(new SubroutineExitInstruction(subroutine, "<END>"));
bindLabel(error);
add(new SubroutineExitInstruction(subroutine, "<ERROR>"));
elementToBlockInfo.remove(subroutine);
allBlocks.pop();
}
@Override
public void returnValue(@NotNull JetExpression returnExpression, @NotNull JetElement subroutine) {
Label exitPoint = getExitPoint(subroutine);
handleJumpInsideTryFinally(exitPoint);
add(new ReturnValueInstruction(returnExpression, exitPoint));
}
@Override
public void returnNoValue(@NotNull JetElement returnExpression, @NotNull JetElement subroutine) {
Label exitPoint = getExitPoint(subroutine);
handleJumpInsideTryFinally(exitPoint);
add(new ReturnNoValueInstruction(returnExpression, exitPoint));
}
@Override
public void write(@NotNull JetElement assignment, @NotNull JetElement lValue) {
add(new WriteValueInstruction(assignment, lValue));
}
@Override
public void read(@NotNull JetExpression expression) {
add(new ReadValueInstruction(expression));
}
@Override
public void readUnit(@NotNull JetExpression expression) {
add(new ReadUnitValueInstruction(expression));
}
@Override
public void jump(@NotNull Label label) {
handleJumpInsideTryFinally(label);
add(new UnconditionalJumpInstruction(label));
}
@Override
public void jumpOnFalse(@NotNull Label label) {
handleJumpInsideTryFinally(label);
add(new ConditionalJumpInstruction(false, label));
}
@Override
public void jumpOnTrue(@NotNull Label label) {
handleJumpInsideTryFinally(label);
add(new ConditionalJumpInstruction(true, label));
}
@Override
public void bindLabel(@NotNull Label label) {
pseudocode.bindLabel(label);
}
@Override
public void nondeterministicJump(Label label) {
handleJumpInsideTryFinally(label);
add(new NondeterministicJumpInstruction(label));
}
@Override
public void jumpToError(JetThrowExpression expression) {
add(new UnconditionalJumpInstruction(error));
}
@Override
public void enterTryFinally(@NotNull GenerationTrigger generationTrigger) {
allBlocks.push(new TryFinallyBlockInfo(generationTrigger));
}
@Override
public void exitTryFinally() {
BlockInfo pop = allBlocks.pop();
assert pop instanceof TryFinallyBlockInfo;
}
@Override
public void unsupported(JetElement element) {
add(new UnsupportedElementInstruction(element));
}
}
public static class TryFinallyBlockInfo extends BlockInfo {
private final GenerationTrigger finallyBlock;
private TryFinallyBlockInfo(GenerationTrigger finallyBlock) {
this.finallyBlock = finallyBlock;
}
public void generateFinallyBlock() {
finallyBlock.generate();
}
}
}
@@ -0,0 +1,12 @@
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetElement;
/**
* @author abreslav
*/
public interface JetElementInstruction extends Instruction {
@NotNull
JetElement getElement();
}
@@ -0,0 +1,21 @@
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetElement;
/**
* @author abreslav
*/
public abstract class JetElementInstructionImpl extends InstructionImpl implements JetElementInstruction {
protected final JetElement element;
public JetElementInstructionImpl(@NotNull JetElement element) {
this.element = element;
}
@NotNull
@Override
public JetElement getElement() {
return element;
}
}
@@ -0,0 +1,38 @@
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.cfg.LoopInfo;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetExpression;
/**
* @author abreslav
*/
public interface JetPseudocodeTrace {
JetPseudocodeTrace EMPTY = new JetPseudocodeTrace() {
@Override
public void recordControlFlowData(@NotNull JetElement element, @NotNull Pseudocode pseudocode) {
}
@Override
public void recordRepresentativeInstruction(@NotNull JetElement element, @NotNull Instruction instruction) {
}
@Override
public void close() {
}
@Override
public void recordLoopInfo(JetExpression expression, LoopInfo blockInfo) {
}
};
void recordControlFlowData(@NotNull JetElement element, @NotNull Pseudocode pseudocode);
void recordRepresentativeInstruction(@NotNull JetElement element, @NotNull Instruction instruction);
void close();
void recordLoopInfo(JetExpression expression, LoopInfo blockInfo);
}
@@ -0,0 +1,43 @@
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.cfg.Label;
import java.util.Arrays;
import java.util.Collection;
/**
* @author abreslav
*/
public class NondeterministicJumpInstruction extends AbstractJumpInstruction {
private Instruction next;
public NondeterministicJumpInstruction(Label targetLabel) {
super(targetLabel);
}
@Override
public void accept(InstructionVisitor visitor) {
visitor.visitNondeterministicJump(this);
}
public Instruction getNext() {
return next;
}
public void setNext(Instruction next) {
this.next = next;
}
@NotNull
@Override
public Collection<Instruction> getNextInstructions() {
return Arrays.asList(getResolvedTarget(), getNext());
}
@Override
public String toString() {
return "jmp?(" + getTargetLabel().getName() + ")";
}
}
@@ -0,0 +1,332 @@
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.Label;
import org.jetbrains.jet.lang.psi.JetElement;
import java.io.PrintStream;
import java.util.*;
/**
* @author abreslav
*/
public class Pseudocode {
public class PseudocodeLabel implements Label {
private final String name;
private Integer targetInstructionIndex;
private PseudocodeLabel(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
@Override
public String toString() {
return name;
}
public int getTargetInstructionIndex() {
return targetInstructionIndex;
}
public void setTargetInstructionIndex(int targetInstructionIndex) {
this.targetInstructionIndex = targetInstructionIndex;
}
@Nullable
private List<Instruction> resolve() {
assert targetInstructionIndex != null;
return instructions.subList(getTargetInstructionIndex(), instructions.size());
}
public Instruction resolveToInstruction() {
assert targetInstructionIndex != null;
return instructions.get(targetInstructionIndex);
}
}
private final List<Instruction> instructions = new ArrayList<Instruction>();
private final List<PseudocodeLabel> labels = new ArrayList<PseudocodeLabel>();
private final JetElement correspondingElement;
private SubroutineExitInstruction exitInstruction;
private boolean postPrecessed = false;
public Pseudocode(JetElement correspondingElement) {
this.correspondingElement = correspondingElement;
}
public JetElement getCorrespondingElement() {
return correspondingElement;
}
public PseudocodeLabel createLabel(String name) {
PseudocodeLabel label = new PseudocodeLabel(name);
labels.add(label);
return label;
}
@NotNull
public Collection<Instruction> getInstructions() {
return instructions;
}
public void addExitInstruction(SubroutineExitInstruction exitInstruction) {
addInstruction(exitInstruction);
assert this.exitInstruction == null;
this.exitInstruction = exitInstruction;
}
public void addInstruction(Instruction instruction) {
instructions.add(instruction);
instruction.setOwner(this);
}
@NotNull
public SubroutineExitInstruction getExitInstruction() {
return exitInstruction;
}
@NotNull
public SubroutineEnterInstruction getEnterInstruction() {
return (SubroutineEnterInstruction) instructions.get(0);
}
public void bindLabel(Label label) {
((PseudocodeLabel) label).setTargetInstructionIndex(instructions.size());
}
public void postProcess() {
if (postPrecessed) return;
postPrecessed = true;
for (int i = 0, instructionsSize = instructions.size(); i < instructionsSize; i++) {
Instruction instruction = instructions.get(i);
final int currentPosition = i;
instruction.accept(new InstructionVisitor() {
@Override
public void visitInstructionWithNext(InstructionWithNext instruction) {
instruction.setNext(getNextPosition(currentPosition));
}
@Override
public void visitJump(AbstractJumpInstruction instruction) {
instruction.setResolvedTarget(getJumpTarget(instruction.getTargetLabel()));
}
@Override
public void visitNondeterministicJump(NondeterministicJumpInstruction instruction) {
instruction.setNext(getNextPosition(currentPosition));
visitJump(instruction);
}
@Override
public void visitConditionalJump(ConditionalJumpInstruction instruction) {
Instruction nextInstruction = getNextPosition(currentPosition);
Instruction jumpTarget = getJumpTarget(instruction.getTargetLabel());
if (instruction.onTrue()) {
instruction.setNextOnFalse(nextInstruction);
instruction.setNextOnTrue(jumpTarget);
}
else {
instruction.setNextOnFalse(jumpTarget);
instruction.setNextOnTrue(nextInstruction);
}
visitJump(instruction);
}
@Override
public void visitFunctionLiteralValue(FunctionLiteralValueInstruction instruction) {
instruction.getBody().postProcess();
super.visitFunctionLiteralValue(instruction);
}
@Override
public void visitSubroutineExit(SubroutineExitInstruction instruction) {
// Nothing
}
@Override
public void visitInstruction(Instruction instruction) {
throw new UnsupportedOperationException(instruction.toString());
}
});
}
}
@NotNull
private Instruction getJumpTarget(@NotNull Label targetLabel) {
return getTargetInstruction(((PseudocodeLabel) targetLabel).resolve());
}
@NotNull
private Instruction getTargetInstruction(@NotNull List<Instruction> instructions) {
while (true) {
assert instructions != null;
Instruction targetInstruction = instructions.get(0);
if (false == targetInstruction instanceof UnconditionalJumpInstruction) {
return targetInstruction;
}
Label label = ((UnconditionalJumpInstruction) targetInstruction).getTargetLabel();
instructions = ((PseudocodeLabel)label).resolve();
}
}
@NotNull
private Instruction getNextPosition(int currentPosition) {
int targetPosition = currentPosition + 1;
assert targetPosition < instructions.size() : currentPosition;
return getTargetInstruction(instructions.subList(targetPosition, instructions.size()));
}
public void dfsDump(StringBuilder nodes, StringBuilder edges, Map<Instruction, String> nodeNames) {
dfsDump(nodes, edges, instructions.get(0), nodeNames);
}
private void dfsDump(StringBuilder nodes, StringBuilder edges, Instruction instruction, Map<Instruction, String> nodeNames) {
if (nodeNames.containsKey(instruction)) return;
String name = "n" + nodeNames.size();
nodeNames.put(instruction, name);
nodes.append(name).append(" := ").append(renderName(instruction));
}
private String renderName(Instruction instruction) {
throw new UnsupportedOperationException(); // TODO
}
public void dumpInstructions(@NotNull StringBuilder out) {
List<Pseudocode> locals = new ArrayList<Pseudocode>();
for (int i = 0, instructionsSize = instructions.size(); i < instructionsSize; i++) {
Instruction instruction = instructions.get(i);
if (instruction instanceof FunctionLiteralValueInstruction) {
FunctionLiteralValueInstruction functionLiteralValueInstruction = (FunctionLiteralValueInstruction) instruction;
locals.add(functionLiteralValueInstruction.getBody());
}
for (PseudocodeLabel label: labels) {
if (label.getTargetInstructionIndex() == i) {
out.append(label.getName()).append(":\n");
}
}
out.append(" ").append(instruction).append("\n");
}
for (Pseudocode local : locals) {
local.dumpInstructions(out);
}
}
public void dumpEdges(final PrintStream out, final int[] count, final Map<Instruction, String> nodeToName) {
for (final Instruction fromInst : instructions) {
fromInst.accept(new InstructionVisitor() {
@Override
public void visitFunctionLiteralValue(FunctionLiteralValueInstruction instruction) {
int index = count[0];
// instruction.getBody().dumpSubgraph(out, "subgraph cluster_" + index, count, "color=blue;\nlabel = \"f" + index + "\";", nodeToName);
printEdge(out, nodeToName.get(instruction), nodeToName.get(instruction.getBody().instructions.get(0)), null);
visitInstructionWithNext(instruction);
}
@Override
public void visitUnconditionalJump(UnconditionalJumpInstruction instruction) {
// Nothing
}
@Override
public void visitJump(AbstractJumpInstruction instruction) {
printEdge(out, nodeToName.get(instruction), nodeToName.get(instruction.getResolvedTarget()), null);
}
@Override
public void visitNondeterministicJump(NondeterministicJumpInstruction instruction) {
visitJump(instruction);
printEdge(out, nodeToName.get(instruction), nodeToName.get(instruction.getNext()), null);
}
@Override
public void visitReturnValue(ReturnValueInstruction instruction) {
super.visitReturnValue(instruction);
}
@Override
public void visitReturnNoValue(ReturnNoValueInstruction instruction) {
super.visitReturnNoValue(instruction);
}
@Override
public void visitConditionalJump(ConditionalJumpInstruction instruction) {
String from = nodeToName.get(instruction);
printEdge(out, from, nodeToName.get(instruction.getNextOnFalse()), "no");
printEdge(out, from, nodeToName.get(instruction.getNextOnTrue()), "yes");
}
@Override
public void visitInstructionWithNext(InstructionWithNext instruction) {
printEdge(out, nodeToName.get(instruction), nodeToName.get(instruction.getNext()), null);
}
@Override
public void visitSubroutineExit(SubroutineExitInstruction instruction) {
// Nothing
}
@Override
public void visitInstruction(Instruction instruction) {
throw new UnsupportedOperationException(instruction.toString());
}
});
}
}
public void dumpNodes(PrintStream out, int[] count, Map<Instruction, String> nodeToName) {
for (Instruction node : instructions) {
if (node instanceof UnconditionalJumpInstruction) {
continue;
}
String name = "n" + count[0]++;
nodeToName.put(node, name);
String text = node.toString();
int newline = text.indexOf("\n");
if (newline >= 0) {
text = text.substring(0, newline);
}
String shape = "box";
if (node instanceof ConditionalJumpInstruction) {
shape = "diamond";
}
else if (node instanceof NondeterministicJumpInstruction) {
shape = "Mdiamond";
}
else if (node instanceof UnsupportedElementInstruction) {
shape = "box, fillcolor=red, style=filled";
}
else if (node instanceof FunctionLiteralValueInstruction) {
shape = "Mcircle";
}
else if (node instanceof SubroutineEnterInstruction || node instanceof SubroutineExitInstruction) {
shape = "roundrect, style=rounded";
}
out.println(name + "[label=\"" + text + "\", shape=" + shape + "];");
}
}
private void printEdge(PrintStream out, String from, String to, String label) {
if (label != null) {
label = "[label=\"" + label + "\"]";
}
else {
label = "";
}
out.println(from + " -> " + to + label + ";");
}
}
@@ -0,0 +1,24 @@
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetExpression;
/**
* @author abreslav
*/
public class ReadUnitValueInstruction extends InstructionWithNext {
public ReadUnitValueInstruction(@NotNull JetExpression expression) {
super(expression);
}
@Override
public void accept(InstructionVisitor visitor) {
visitor.visitReadUnitValue(this);
}
@Override
public String toString() {
return "read (Unit)";
}
}
@@ -0,0 +1,24 @@
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetExpression;
/**
* @author abreslav
*/
public class ReadValueInstruction extends InstructionWithNext {
public ReadValueInstruction(@NotNull JetExpression expression) {
super(expression);
}
@Override
public void accept(InstructionVisitor visitor) {
visitor.visitReadValue(this);
}
@Override
public String toString() {
return "r(" + element.getText() + ")";
}
}
@@ -0,0 +1,34 @@
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.cfg.Label;
import org.jetbrains.jet.lang.psi.JetElement;
/**
* @author abreslav
*/
public class ReturnNoValueInstruction extends AbstractJumpInstruction implements JetElementInstruction {
private final JetElement element;
public ReturnNoValueInstruction(@NotNull JetElement element, Label targetLabel) {
super(targetLabel);
this.element = element;
}
@NotNull
@Override
public JetElement getElement() {
return element;
}
@Override
public void accept(InstructionVisitor visitor) {
visitor.visitReturnNoValue(this);
}
@Override
public String toString() {
return "ret " + getTargetLabel();
}
}
@@ -0,0 +1,35 @@
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.cfg.Label;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetExpression;
/**
* @author abreslav
*/
public class ReturnValueInstruction extends AbstractJumpInstruction implements JetElementInstruction {
private final JetElement element;
public ReturnValueInstruction(@NotNull JetExpression returnExpression, @NotNull Label targetLabel) {
super(targetLabel);
this.element = returnExpression;
}
@Override
public void accept(InstructionVisitor visitor) {
visitor.visitReturnValue(this);
}
@Override
public String toString() {
return "ret(*) " + getTargetLabel();
}
@NotNull
@Override
public JetElement getElement() {
return element;
}
}
@@ -0,0 +1,30 @@
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetElement;
/**
* @author abreslav
*/
public class SubroutineEnterInstruction extends InstructionWithNext {
private final JetElement subroutine;
public SubroutineEnterInstruction(@NotNull JetElement subroutine) {
super(subroutine);
this.subroutine = subroutine;
}
public JetElement getSubroutine() {
return subroutine;
}
@Override
public void accept(InstructionVisitor visitor) {
visitor.visitSubroutineEnter(this);
}
@Override
public String toString() {
return "<START>";
}
}
@@ -0,0 +1,40 @@
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetElement;
import java.util.Collection;
import java.util.Collections;
/**
* @author abreslav
*/
public class SubroutineExitInstruction extends InstructionImpl {
private final JetElement subroutine;
private final String debugLabel;
public SubroutineExitInstruction(@NotNull JetElement subroutine, @NotNull String debugLabel) {
this.subroutine = subroutine;
this.debugLabel = debugLabel;
}
public JetElement getSubroutine() {
return subroutine;
}
@NotNull
@Override
public Collection<Instruction> getNextInstructions() {
return Collections.emptyList();
}
@Override
public void accept(InstructionVisitor visitor) {
visitor.visitSubroutineExit(this);
}
@Override
public String toString() {
return debugLabel;
}
}
@@ -0,0 +1,25 @@
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.jet.lang.cfg.Label;
/**
* @author abreslav
*/
public class UnconditionalJumpInstruction extends AbstractJumpInstruction {
public UnconditionalJumpInstruction(Label targetLabel) {
super(targetLabel);
}
@Override
public void accept(InstructionVisitor visitor) {
visitor.visitUnconditionalJump(this);
}
@Override
public String toString() {
return "jmp(" + getTargetLabel().getName() + ")";
}
}
@@ -0,0 +1,24 @@
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetElement;
/**
* @author abreslav
*/
public class UnsupportedElementInstruction extends InstructionWithNext {
protected UnsupportedElementInstruction(@NotNull JetElement element) {
super(element);
}
@Override
public void accept(InstructionVisitor visitor) {
visitor.visitUnsupportedElementInstruction(this);
}
@Override
public String toString() {
return "unsupported(" + element + " : " + element.getText() + ")";
}
}
@@ -0,0 +1,32 @@
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetNamedDeclaration;
/**
* @author abreslav
*/
public class WriteValueInstruction extends InstructionWithNext {
@NotNull
private final JetElement lValue;
public WriteValueInstruction(@NotNull JetElement assignment, @NotNull JetElement lValue) {
super(assignment);
this.lValue = lValue;
}
@Override
public void accept(InstructionVisitor visitor) {
visitor.visitWriteValue(this);
}
@Override
public String toString() {
if (lValue instanceof JetNamedDeclaration) {
JetNamedDeclaration value = (JetNamedDeclaration) lValue;
return "w(" + value.getName() + ")";
}
return "w(" + lValue.getText() + ")";
}
}
@@ -0,0 +1,39 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.types.NamespaceType;
import org.jetbrains.jet.lang.types.TypeSubstitutor;
import java.util.List;
/**
* @author abreslav
*/
public abstract class AbstractNamespaceDescriptorImpl extends DeclarationDescriptorImpl implements NamespaceDescriptor {
private NamespaceType namespaceType;
public AbstractNamespaceDescriptorImpl(DeclarationDescriptor containingDeclaration, List<AnnotationDescriptor> annotations, String name) {
super(containingDeclaration, annotations, name);
}
@Override
@NotNull
public NamespaceType getNamespaceType() {
if (namespaceType == null) {
namespaceType = new NamespaceType(getName(), getMemberScope());
}
return namespaceType;
}
@NotNull
@Override
public NamespaceDescriptor substitute(TypeSubstitutor substitutor) {
throw new UnsupportedOperationException("This operation does not make sense for a namespace");
}
@Override
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitNamespaceDescriptor(this, data);
}
}
@@ -0,0 +1,7 @@
package org.jetbrains.jet.lang.descriptors;
/**
* @author abreslav
*/
public interface Annotation {
}
@@ -0,0 +1,36 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeSubstitutor;
import java.util.List;
import java.util.Set;
/**
* @author abreslav
*/
public interface CallableDescriptor extends DeclarationDescriptor {
@Nullable
JetType getReceiverType();
@NotNull
List<TypeParameterDescriptor> getTypeParameters();
@NotNull
JetType getReturnType();
@NotNull
@Override
CallableDescriptor getOriginal();
@Override
CallableDescriptor substitute(TypeSubstitutor substitutor);
@NotNull
List<ValueParameterDescriptor> getValueParameters();
@NotNull
Set<? extends CallableDescriptor> getOverriddenDescriptors();
}
@@ -0,0 +1,56 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.JetScope;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeProjection;
import org.jetbrains.jet.lang.types.TypeSubstitutor;
import java.util.List;
/**
* @author abreslav
*/
public interface ClassDescriptor extends ClassifierDescriptor {
@NotNull
JetScope getMemberScope(List<TypeProjection> typeArguments);
/**
* @return the superclass for a class descriptor, and the required class fro a trait descriptor
*/
@NotNull
JetType getSuperclassType();
@NotNull
FunctionGroup getConstructors();
@Nullable
ConstructorDescriptor getUnsubstitutedPrimaryConstructor();
boolean hasConstructors();
@Override
@NotNull
DeclarationDescriptor getContainingDeclaration();
/**
* @return type A&lt;T&gt; for the class A&lt;T&gt;
*/
@NotNull
JetType getDefaultType();
@NotNull
@Override
ClassDescriptor substitute(TypeSubstitutor substitutor);
@Nullable
JetType getClassObjectType();
@NotNull
ClassKind getKind();
@NotNull
Modality getModality();
}
@@ -0,0 +1,154 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.JetScope;
import org.jetbrains.jet.lang.resolve.SubstitutingScope;
import org.jetbrains.jet.lang.types.*;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* @author abreslav
*/
public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements ClassDescriptor {
private TypeConstructor typeConstructor;
private JetScope memberDeclarations;
private FunctionGroup constructors;
private ConstructorDescriptor primaryConstructor;
private JetType superclassType;
public ClassDescriptorImpl(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull List<AnnotationDescriptor> annotations,
@NotNull String name) {
super(containingDeclaration, annotations, name);
}
public final ClassDescriptorImpl initialize(boolean sealed,
@NotNull List<TypeParameterDescriptor> typeParameters,
@NotNull Collection<JetType> supertypes,
@NotNull JetScope memberDeclarations,
@NotNull FunctionGroup constructors,
@Nullable ConstructorDescriptor primaryConstructor) {
return initialize(sealed, typeParameters, supertypes, memberDeclarations, constructors, primaryConstructor, getClassType(supertypes));
}
public final ClassDescriptorImpl initialize(boolean sealed,
@NotNull List<TypeParameterDescriptor> typeParameters,
@NotNull Collection<JetType> supertypes,
@NotNull JetScope memberDeclarations,
@NotNull FunctionGroup constructors,
@Nullable ConstructorDescriptor primaryConstructor,
@Nullable JetType superclassType) {
this.typeConstructor = new TypeConstructorImpl(this, getAnnotations(), sealed, getName(), typeParameters, supertypes);
this.memberDeclarations = memberDeclarations;
this.constructors = constructors;
this.primaryConstructor = primaryConstructor;
this.superclassType = superclassType;
// assert !constructors.isEmpty() || primaryConstructor == null;
return this;
}
@NotNull
private JetType getClassType(@NotNull Collection<JetType> types) {
for (JetType type : types) {
ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(type);
if (classDescriptor != null) {
return type;
}
}
return JetStandardClasses.getAnyType();
}
public void setPrimaryConstructor(@NotNull ConstructorDescriptor primaryConstructor) {
this.primaryConstructor = primaryConstructor;
}
@Override
@NotNull
public TypeConstructor getTypeConstructor() {
return typeConstructor;
}
@Override
@NotNull
public JetScope getMemberScope(List<TypeProjection> typeArguments) {
assert typeArguments.size() == typeConstructor.getParameters().size() : typeArguments;
if (typeConstructor.getParameters().isEmpty()) {
return memberDeclarations;
}
Map<TypeConstructor, TypeProjection> substitutionContext = TypeUtils.buildSubstitutionContext(typeConstructor.getParameters(), typeArguments);
return new SubstitutingScope(memberDeclarations, TypeSubstitutor.create(substitutionContext));
}
@NotNull
@Override
public JetType getSuperclassType() {
return superclassType;
}
@NotNull
@Override
public JetType getDefaultType() {
return TypeUtils.makeUnsubstitutedType(this, memberDeclarations);
}
@NotNull
@Override
public FunctionGroup getConstructors() {
// assert typeArguments.size() == getTypeConstructor().getParameters().size() : "Argument list length mismatch for " + getName();
// if (typeArguments.size() == 0) {
// return constructors;
// }
// Map<TypeConstructor, TypeProjection> substitutionContext = TypeUtils.buildSubstitutionContext(getTypeConstructor().getParameters(), typeArguments);
return constructors;// LazySubstitutingFunctionGroup(TypeSubstitutor.create(substitutionContext), constructors);
}
@NotNull
@Override
public ClassDescriptor substitute(TypeSubstitutor substitutor) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public JetType getClassObjectType() {
return null;
}
@NotNull
@Override
public ClassKind getKind() {
return ClassKind.CLASS;
}
@Override
public boolean isClassObjectAValue() {
return true;
}
@Override
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitClassDescriptor(this, data);
}
@Override
public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
return primaryConstructor;
}
@Override
public boolean hasConstructors() {
return !constructors.isEmpty();
}
@Override
@NotNull
public Modality getModality() {
return Modality.FINAL;
}
}
@@ -0,0 +1,12 @@
package org.jetbrains.jet.lang.descriptors;
/**
* @author abreslav
*/
public enum ClassKind {
CLASS,
TRAIT,
ENUM_CLASS,
ANNOTATION_CLASS,
OBJECT
}
@@ -0,0 +1,22 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeConstructor;
/**
* @author abreslav
*/
public interface ClassifierDescriptor extends DeclarationDescriptor {
@NotNull
TypeConstructor getTypeConstructor();
@NotNull
JetType getDefaultType();
@Nullable
JetType getClassObjectType();
boolean isClassObjectAValue();
}
@@ -0,0 +1,38 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.types.JetType;
import java.util.List;
/**
* @author abreslav
*/
public interface ConstructorDescriptor extends FunctionDescriptor {
/**
* @throws UnsupportedOperationException -- no type parameters supported for constructors
*/
@NotNull
@Override
List<TypeParameterDescriptor> getTypeParameters();
/**
* @throws UnsupportedOperationException -- return type is not stored for constructors
*/
@NotNull
@Override
JetType getReturnType();
@NotNull
@Override
ClassDescriptor getContainingDeclaration();
/**
* @return "&lt;init&gt;" -- name is not stored for constructors
*/
@NotNull
@Override
String getName();
boolean isPrimary();
}
@@ -0,0 +1,81 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Collections;
import java.util.List;
import java.util.Set;
/**
* @author abreslav
*/
public class ConstructorDescriptorImpl extends FunctionDescriptorImpl implements ConstructorDescriptor {
private final boolean isPrimary;
public ConstructorDescriptorImpl(@NotNull ClassDescriptor containingDeclaration, @NotNull List<AnnotationDescriptor> annotations, boolean isPrimary) {
super(containingDeclaration, annotations, "<init>");
this.isPrimary = isPrimary;
}
public ConstructorDescriptorImpl(@NotNull ConstructorDescriptor original, @NotNull List<AnnotationDescriptor> annotations, boolean isPrimary) {
super(original, annotations, "<init>");
this.isPrimary = isPrimary;
}
@Override
@Deprecated
public FunctionDescriptorImpl initialize(@Nullable JetType receiverType, @NotNull List<TypeParameterDescriptor> typeParameters, @NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters, @Nullable JetType unsubstitutedReturnType, Modality modality) {
assert receiverType == null;
return super.initialize(null, typeParameters, unsubstitutedValueParameters, unsubstitutedReturnType, modality);
}
public ConstructorDescriptorImpl initialize(@NotNull List<TypeParameterDescriptor> typeParameters, @NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters, Modality modality) {
super.initialize(null, typeParameters, unsubstitutedValueParameters, null, modality);
return this;
}
@NotNull
@Override
public ClassDescriptor getContainingDeclaration() {
return (ClassDescriptor) super.getContainingDeclaration();
}
@NotNull
@Override
public ConstructorDescriptor getOriginal() {
return (ConstructorDescriptor) super.getOriginal();
}
@Override
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitConstructorDescriptor(this, data);
}
@Override
public boolean isPrimary() {
return isPrimary;
}
@NotNull
@Override
public Set<? extends FunctionDescriptor> getOverriddenDescriptors() {
return Collections.emptySet();
}
@Override
public void addOverriddenFunction(@NotNull FunctionDescriptor overriddenFunction) {
throw new UnsupportedOperationException("Constructors cannot override anything");
}
@Override
protected FunctionDescriptorImpl createSubstitutedCopy() {
return new ConstructorDescriptorImpl(
this,
Collections.<AnnotationDescriptor>emptyList(), // TODO
isPrimary);
}
}
@@ -0,0 +1,28 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.annotations.Annotated;
import org.jetbrains.jet.lang.types.TypeSubstitutor;
/**
* @author abreslav
*/
public interface DeclarationDescriptor extends Annotated, Named {
/**
* @return The descriptor that corresponds to the original declaration of this element.
* A descriptor can be obtained from its original by substituting type arguments (of the declaring class
* or of the element itself).
* returns <code>this</code> object if the current descriptor is original itself
*/
@NotNull
DeclarationDescriptor getOriginal();
@Nullable
DeclarationDescriptor getContainingDeclaration();
DeclarationDescriptor substitute(TypeSubstitutor substitutor);
<R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data);
void acceptVoid(DeclarationDescriptorVisitor<Void, Void> visitor);
}
@@ -0,0 +1,51 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotatedImpl;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.resolve.DescriptorRenderer;
import java.util.List;
/**
* @author abreslav
*/
public abstract class DeclarationDescriptorImpl extends AnnotatedImpl implements Named, DeclarationDescriptor {
private final String name;
private final DeclarationDescriptor containingDeclaration;
public DeclarationDescriptorImpl(@Nullable DeclarationDescriptor containingDeclaration, List<AnnotationDescriptor> annotations, String name) {
super(annotations);
this.name = name;
this.containingDeclaration = containingDeclaration;
}
@NotNull
@Override
public String getName() {
return name;
}
@NotNull
@Override
public DeclarationDescriptor getOriginal() {
return this;
}
@Override
public DeclarationDescriptor getContainingDeclaration() {
return containingDeclaration;
}
@Override
public void acceptVoid(DeclarationDescriptorVisitor<Void, Void> visitor) {
accept(visitor, null);
}
@Override
public String toString() {
return DescriptorRenderer.TEXT.render(this) + "[" + getClass().getSimpleName() + "@" + Integer.toHexString(System.identityHashCode(this)) + "]";
}
}
@@ -0,0 +1,62 @@
package org.jetbrains.jet.lang.descriptors;
/**
* @author abreslav
*/
public class DeclarationDescriptorVisitor<R, D> {
public R visitDeclarationDescriptor(DeclarationDescriptor descriptor, D data) {
return null;
}
public R visitVariableDescriptor(VariableDescriptor descriptor, D data) {
return visitDeclarationDescriptor(descriptor, data);
}
public R visitFunctionDescriptor(FunctionDescriptor descriptor, D data) {
return visitDeclarationDescriptor(descriptor, data);
}
public R visitTypeParameterDescriptor(TypeParameterDescriptor descriptor, D data) {
return visitDeclarationDescriptor(descriptor, data);
}
public R visitNamespaceDescriptor(NamespaceDescriptor descriptor, D data) {
return visitDeclarationDescriptor(descriptor, data);
}
public R visitClassDescriptor(ClassDescriptor descriptor, D data) {
return visitDeclarationDescriptor(descriptor, data);
}
public R visitModuleDeclaration(ModuleDescriptor descriptor, D data) {
return visitDeclarationDescriptor(descriptor, data);
}
public R visitConstructorDescriptor(ConstructorDescriptor constructorDescriptor, D data) {
return visitFunctionDescriptor(constructorDescriptor, data);
}
public R visitLocalVariableDescriptor(LocalVariableDescriptor descriptor, D data) {
return visitVariableDescriptor(descriptor, data);
}
public R visitPropertyDescriptor(PropertyDescriptor descriptor, D data) {
return visitVariableDescriptor(descriptor, data);
}
public R visitValueParameterDescriptor(ValueParameterDescriptor descriptor, D data) {
return visitVariableDescriptor(descriptor, data);
}
public R visitPropertyGetterDescriptor(PropertyGetterDescriptor descriptor, D data) {
return visitPropertyAccessorDescriptor(descriptor, data);
}
private R visitPropertyAccessorDescriptor(PropertyAccessorDescriptor descriptor, D data) {
return visitFunctionDescriptor(descriptor, data);
}
public R visitPropertySetterDescriptor(PropertySetterDescriptor descriptor, D data) {
return visitPropertyAccessorDescriptor(descriptor, data);
}
}
@@ -0,0 +1,7 @@
package org.jetbrains.jet.lang.descriptors;
/**
* @author abreslav
*/
public class ExtensionDescriptor {
}
@@ -0,0 +1,26 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.types.TypeSubstitutor;
import java.util.Set;
/**
* @author abreslav
*/
public interface FunctionDescriptor extends CallableDescriptor, MemberDescriptor {
@Override
@NotNull
DeclarationDescriptor getContainingDeclaration();
@NotNull
@Override
FunctionDescriptor getOriginal();
@Override
FunctionDescriptor substitute(TypeSubstitutor substitutor);
@Override
@NotNull
Set<? extends FunctionDescriptor> getOverriddenDescriptors();
}
@@ -0,0 +1,161 @@
package org.jetbrains.jet.lang.descriptors;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.types.DescriptorSubstitutor;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeSubstitutor;
import org.jetbrains.jet.lang.types.Variance;
import java.util.List;
import java.util.Set;
/**
* @author abreslav
*/
public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements FunctionDescriptor {
private List<TypeParameterDescriptor> typeParameters;
private List<ValueParameterDescriptor> unsubstitutedValueParameters;
private JetType unsubstitutedReturnType;
private JetType receiverType;
private Modality modality;
private final Set<FunctionDescriptor> overriddenFunctions = Sets.newLinkedHashSet();
private final FunctionDescriptor original;
public FunctionDescriptorImpl(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull List<AnnotationDescriptor> annotations,
@NotNull String name) {
super(containingDeclaration, annotations, name);
this.original = this;
}
public FunctionDescriptorImpl(
@NotNull FunctionDescriptor original,
@NotNull List<AnnotationDescriptor> annotations,
@NotNull String name) {
super(original.getContainingDeclaration(), annotations, name);
this.original = original;
}
public FunctionDescriptorImpl initialize(
@Nullable JetType receiverType,
@NotNull List<TypeParameterDescriptor> typeParameters,
@NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters,
@Nullable JetType unsubstitutedReturnType,
@Nullable Modality modality) {
this.receiverType = receiverType;
this.typeParameters = typeParameters;
this.unsubstitutedValueParameters = unsubstitutedValueParameters;
this.unsubstitutedReturnType = unsubstitutedReturnType;
this.modality = modality;
return this;
}
public void setReturnType(@NotNull JetType unsubstitutedReturnType) {
this.unsubstitutedReturnType = unsubstitutedReturnType;
}
@Override
public JetType getReceiverType() {
return receiverType;
}
@NotNull
@Override
public Set<? extends FunctionDescriptor> getOverriddenDescriptors() {
return overriddenFunctions;
}
@NotNull
@Override
public Modality getModality() {
return modality;
}
public void addOverriddenFunction(@NotNull FunctionDescriptor overriddenFunction) {
overriddenFunctions.add(overriddenFunction);
}
@Override
@NotNull
public List<TypeParameterDescriptor> getTypeParameters() {
return typeParameters;
}
@Override
@NotNull
public List<ValueParameterDescriptor> getValueParameters() {
return unsubstitutedValueParameters;
}
@Override
@NotNull
public JetType getReturnType() {
return unsubstitutedReturnType;
}
@NotNull
@Override
public FunctionDescriptor getOriginal() {
return original == this ? this : original.getOriginal();
}
@Override
public final FunctionDescriptor substitute(TypeSubstitutor originalSubstitutor) {
if (originalSubstitutor.isEmpty()) {
return this;
}
FunctionDescriptorImpl substitutedDescriptor = createSubstitutedCopy();
List<TypeParameterDescriptor> substitutedTypeParameters = Lists.newArrayList();
TypeSubstitutor substitutor = DescriptorSubstitutor.substituteTypeParameters(getTypeParameters(), originalSubstitutor, substitutedDescriptor, substitutedTypeParameters);
JetType receiverType = getReceiverType();
JetType substitutedReceiverType = null;
if (receiverType != null) {
substitutedReceiverType = substitutor.substitute(receiverType, Variance.IN_VARIANCE);
if (substitutedReceiverType == null) {
return null;
}
}
List<ValueParameterDescriptor> substitutedValueParameters = FunctionDescriptorUtil.getSubstitutedValueParameters(substitutedDescriptor, this, substitutor);
if (substitutedValueParameters == null) {
return null;
}
JetType substitutedReturnType = FunctionDescriptorUtil.getSubstitutedReturnType(this, substitutor);
if (substitutedReturnType == null) {
return null;
}
substitutedDescriptor.initialize(
substitutedReceiverType,
substitutedTypeParameters,
substitutedValueParameters,
substitutedReturnType,
modality
);
return substitutedDescriptor;
}
protected FunctionDescriptorImpl createSubstitutedCopy() {
return new FunctionDescriptorImpl(
this,
// TODO : safeSubstitute
getAnnotations(),
getName());
}
@Override
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitFunctionDescriptor(this, data);
}
}
@@ -0,0 +1,236 @@
package org.jetbrains.jet.lang.descriptors;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.Maps;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.JetScope;
import org.jetbrains.jet.lang.resolve.WritableScope;
import org.jetbrains.jet.lang.resolve.WritableScopeImpl;
import org.jetbrains.jet.lang.types.*;
import java.util.*;
import static org.jetbrains.jet.lang.types.TypeSubstitutor.TypeSubstitution;
/**
* @author abreslav
*/
public class FunctionDescriptorUtil {
/** @return Minimal number of arguments to be passed */
public static int getMinimumArity(@NotNull FunctionDescriptor functionDescriptor) {
int result = 0;
for (ValueParameterDescriptor valueParameter : functionDescriptor.getValueParameters()) {
if (valueParameter.hasDefaultValue()) {
break;
}
result++;
}
return result;
}
/**
* @return Maximum number of arguments that can be passed. -1 if unbound (vararg)
*/
public static int getMaximumArity(@NotNull FunctionDescriptor functionDescriptor) {
List<ValueParameterDescriptor> unsubstitutedValueParameters = functionDescriptor.getValueParameters();
if (unsubstitutedValueParameters.isEmpty()) {
return 0;
}
// TODO : check somewhere that vararg is only the last one, and that varargs do not have default values
ValueParameterDescriptor lastParameter = unsubstitutedValueParameters.get(unsubstitutedValueParameters.size() - 1);
if (lastParameter.isVararg()) {
return -1;
}
return unsubstitutedValueParameters.size();
}
public static Map<TypeConstructor, TypeProjection> createSubstitutionContext(@NotNull FunctionDescriptor functionDescriptor, List<JetType> typeArguments) {
if (functionDescriptor.getTypeParameters().isEmpty()) return Collections.emptyMap();
Map<TypeConstructor, TypeProjection> result = new HashMap<TypeConstructor, TypeProjection>();
int typeArgumentsSize = typeArguments.size();
List<TypeParameterDescriptor> typeParameters = functionDescriptor.getTypeParameters();
assert typeArgumentsSize == typeParameters.size();
for (int i = 0; i < typeArgumentsSize; i++) {
TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i);
JetType typeArgument = typeArguments.get(i);
result.put(typeParameterDescriptor.getTypeConstructor(), new TypeProjection(typeArgument));
}
return result;
}
@Nullable
public static List<ValueParameterDescriptor> getSubstitutedValueParameters(FunctionDescriptor substitutedDescriptor, @NotNull FunctionDescriptor functionDescriptor, TypeSubstitutor substitutor) {
List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>();
List<ValueParameterDescriptor> unsubstitutedValueParameters = functionDescriptor.getValueParameters();
for (int i = 0, unsubstitutedValueParametersSize = unsubstitutedValueParameters.size(); i < unsubstitutedValueParametersSize; i++) {
ValueParameterDescriptor unsubstitutedValueParameter = unsubstitutedValueParameters.get(i);
// TODO : Lazy?
JetType substitutedType = substitutor.substitute(unsubstitutedValueParameter.getOutType(), Variance.IN_VARIANCE);
if (substitutedType == null) return null;
result.add(new ValueParameterDescriptorImpl(
substitutedDescriptor,
unsubstitutedValueParameter,
unsubstitutedValueParameter.getAnnotations(),
unsubstitutedValueParameter.getInType() == null ? null : substitutedType,
substitutedType
));
}
return result;
}
@Nullable
public static JetType getSubstitutedReturnType(@NotNull FunctionDescriptor functionDescriptor, TypeSubstitutor substitutor) {
return substitutor.substitute(functionDescriptor.getReturnType(), Variance.OUT_VARIANCE);
}
@Nullable
public static FunctionDescriptor substituteFunctionDescriptor(@NotNull List<JetType> typeArguments, @NotNull FunctionDescriptor functionDescriptor) {
Map<TypeConstructor, TypeProjection> substitutionContext = createSubstitutionContext(functionDescriptor, typeArguments);
return functionDescriptor.substitute(TypeSubstitutor.create(substitutionContext));
}
@NotNull
public static JetScope getFunctionInnerScope(@NotNull JetScope outerScope, @NotNull FunctionDescriptor descriptor, @NotNull BindingTrace trace) {
WritableScope parameterScope = new WritableScopeImpl(outerScope, descriptor, trace.getErrorHandler()).setDebugName("Function inner scope");
JetType receiverType = descriptor.getReceiverType();
if (receiverType != null) {
parameterScope.setThisType(receiverType);
}
for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) {
parameterScope.addTypeParameterDescriptor(typeParameter);
}
for (ValueParameterDescriptor valueParameterDescriptor : descriptor.getValueParameters()) {
parameterScope.addVariableDescriptor(valueParameterDescriptor);
}
parameterScope.addLabeledDeclaration(descriptor);
return parameterScope;
}
public static class OverrideCompatibilityInfo {
private static final OverrideCompatibilityInfo SUCCESS = new OverrideCompatibilityInfo(false, "SUCCESS");
@NotNull
public static OverrideCompatibilityInfo nameMismatch() {
return new OverrideCompatibilityInfo(true, "nameMismatch"); // TODO
}
@NotNull
public static OverrideCompatibilityInfo typeParameterNumberMismatch() {
return new OverrideCompatibilityInfo(true, "typeParameterNumberMismatch"); // TODO
}
@NotNull
public static OverrideCompatibilityInfo valueParameterNumberMismatch() {
return new OverrideCompatibilityInfo(true, "valueParameterNumberMismatch"); // TODO
}
@NotNull
public static OverrideCompatibilityInfo boundsMismatch(TypeParameterDescriptor superTypeParameter, TypeParameterDescriptor subTypeParameter) {
return new OverrideCompatibilityInfo(true, "boundsMismatch"); // TODO
}
@NotNull
public static OverrideCompatibilityInfo valueParameterTypeMismatch(ValueParameterDescriptor superValueParameter, ValueParameterDescriptor subValueParameter) {
return new OverrideCompatibilityInfo(true, "valueParameterTypeMismatch"); // TODO
}
@NotNull
public static OverrideCompatibilityInfo returnTypeMismatch(JetType substitutedSuperReturnType, JetType unsubstitutedSubReturnType) {
return new OverrideCompatibilityInfo(true, "returnTypeMismatch: " + unsubstitutedSubReturnType + " >< " + substitutedSuperReturnType); // TODO
}
@NotNull
public static OverrideCompatibilityInfo success() {
return SUCCESS;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private final boolean isError;
private final String message;
public OverrideCompatibilityInfo(boolean error, String message) {
isError = error;
this.message = message;
}
public boolean isSuccess() {
return !isError;
}
public String getMessage() {
return message;
}
}
@NotNull
public static OverrideCompatibilityInfo isOverridableBy(@NotNull JetTypeChecker typeChecker, @NotNull FunctionDescriptor superFunction, @NotNull FunctionDescriptor subFunction) {
if (!superFunction.getName().equals(subFunction.getName())) {
return OverrideCompatibilityInfo.nameMismatch();
}
// TODO : Visibility
if (superFunction.getTypeParameters().size() != subFunction.getTypeParameters().size()) {
return OverrideCompatibilityInfo.typeParameterNumberMismatch();
}
if (superFunction.getValueParameters().size() != subFunction.getValueParameters().size()) {
return OverrideCompatibilityInfo.valueParameterNumberMismatch();
}
List<TypeParameterDescriptor> superTypeParameters = superFunction.getTypeParameters();
List<TypeParameterDescriptor> subTypeParameters = subFunction.getTypeParameters();
Map<TypeConstructor, TypeProjection> substitutionContext = Maps.newHashMap();
BiMap<TypeConstructor, TypeConstructor> axioms = HashBiMap.create();
for (int i = 0, typeParametersSize = superTypeParameters.size(); i < typeParametersSize; i++) {
TypeParameterDescriptor superTypeParameter = superTypeParameters.get(i);
TypeParameterDescriptor subTypeParameter = subTypeParameters.get(i);
substitutionContext.put(
superTypeParameter.getTypeConstructor(),
new TypeProjection(subTypeParameter.getDefaultType()));
axioms.put(superTypeParameter.getTypeConstructor(), subTypeParameter.getTypeConstructor());
}
for (int i = 0, typeParametersSize = superTypeParameters.size(); i < typeParametersSize; i++) {
TypeParameterDescriptor superTypeParameter = superTypeParameters.get(i);
TypeParameterDescriptor subTypeParameter = subTypeParameters.get(i);
if (!JetTypeImpl.equalTypes(superTypeParameter.getBoundsAsType(), subTypeParameter.getBoundsAsType(), axioms)) {
return OverrideCompatibilityInfo.boundsMismatch(superTypeParameter, subTypeParameter);
}
}
List<ValueParameterDescriptor> superValueParameters = superFunction.getValueParameters();
List<ValueParameterDescriptor> subValueParameters = subFunction.getValueParameters();
for (int i = 0, unsubstitutedValueParametersSize = superValueParameters.size(); i < unsubstitutedValueParametersSize; i++) {
ValueParameterDescriptor superValueParameter = superValueParameters.get(i);
ValueParameterDescriptor subValueParameter = subValueParameters.get(i);
if (!JetTypeImpl.equalTypes(superValueParameter.getOutType(), subValueParameter.getOutType(), axioms)) {
return OverrideCompatibilityInfo.valueParameterTypeMismatch(superValueParameter, subValueParameter);
}
}
// TODO : Default values, varargs etc
TypeSubstitutor typeSubstitutor = TypeSubstitutor.create(substitutionContext);
JetType substitutedSuperReturnType = typeSubstitutor.substitute(superFunction.getReturnType(), Variance.OUT_VARIANCE);
assert substitutedSuperReturnType != null;
if (!typeChecker.isSubtypeOf(subFunction.getReturnType(), substitutedSuperReturnType)) {
return OverrideCompatibilityInfo.returnTypeMismatch(substitutedSuperReturnType, subFunction.getReturnType());
}
return OverrideCompatibilityInfo.success();
}
}
@@ -0,0 +1,40 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.Set;
/**
* @author abreslav
*/
public interface FunctionGroup extends Named {
FunctionGroup EMPTY = new FunctionGroup() {
@NotNull
@Override
public String getName() {
return "<empty>";
}
@Override
public boolean isEmpty() {
return true;
}
@NotNull
@Override
public Set<FunctionDescriptor> getFunctionDescriptors() {
return Collections.emptySet();
}
};
@NotNull
@Override
String getName();
boolean isEmpty();
@NotNull
Set<FunctionDescriptor> getFunctionDescriptors();
}
@@ -0,0 +1,173 @@
package org.jetbrains.jet.lang.descriptors;
import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.JetScope;
import org.jetbrains.jet.lang.resolve.SubstitutingScope;
import org.jetbrains.jet.lang.types.*;
import java.util.Collection;
import java.util.List;
/**
* @author abreslav
*/
public class LazySubstitutingClassDescriptor implements ClassDescriptor {
private final ClassDescriptor original;
private final TypeSubstitutor originalSubstitutor;
private TypeSubstitutor newSubstitutor;
private List<TypeParameterDescriptor> typeParameters;
private TypeConstructor typeConstructor;
private JetType superclassType;
public LazySubstitutingClassDescriptor(ClassDescriptor descriptor, TypeSubstitutor substitutor) {
this.original = descriptor;
this.originalSubstitutor = substitutor;
}
private TypeSubstitutor getSubstitutor() {
if (newSubstitutor == null) {
if (originalSubstitutor.isEmpty()) {
newSubstitutor = originalSubstitutor;
}
else {
typeParameters = Lists.newArrayList();
newSubstitutor = DescriptorSubstitutor.substituteTypeParameters(original.getTypeConstructor().getParameters(), originalSubstitutor, this, typeParameters);
}
}
return newSubstitutor;
}
@NotNull
@Override
public TypeConstructor getTypeConstructor() {
TypeConstructor originalTypeConstructor = original.getTypeConstructor();
if (originalSubstitutor.isEmpty()) {
return originalTypeConstructor;
}
if (typeConstructor == null) {
TypeSubstitutor substitutor = getSubstitutor();
Collection<JetType> supertypes = Lists.newArrayList();
for (JetType supertype : originalTypeConstructor.getSupertypes()) {
supertypes.add(substitutor.substitute(supertype, Variance.INVARIANT));
}
typeConstructor = new TypeConstructorImpl(
this,
originalTypeConstructor.getAnnotations(),
originalTypeConstructor.isSealed(),
originalTypeConstructor.toString(),
typeParameters,
supertypes
);
}
return typeConstructor;
}
@NotNull
@Override
public JetScope getMemberScope(List<TypeProjection> typeArguments) {
JetScope memberScope = original.getMemberScope(typeArguments);
if (originalSubstitutor.isEmpty()) {
return memberScope;
}
return new SubstitutingScope(memberScope, getSubstitutor());
}
@NotNull
@Override
public JetType getSuperclassType() {
if (superclassType == null) {
superclassType = getSubstitutor().substitute(original.getSuperclassType(), Variance.INVARIANT);
}
return superclassType;
}
@NotNull
@Override
public JetType getDefaultType() {
throw new UnsupportedOperationException(); // TODO
}
@NotNull
@Override
public FunctionGroup getConstructors() {
throw new UnsupportedOperationException(); // TODO
}
@Override
public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
return original.getUnsubstitutedPrimaryConstructor();
}
@Override
public boolean hasConstructors() {
return original.hasConstructors();
}
@Override
public List<AnnotationDescriptor> getAnnotations() {
throw new UnsupportedOperationException(); // TODO
}
@NotNull
@Override
public String getName() {
return original.getName();
}
@NotNull
@Override
public DeclarationDescriptor getOriginal() {
return original.getOriginal();
}
@NotNull
@Override
public DeclarationDescriptor getContainingDeclaration() {
return original.getContainingDeclaration();
}
@NotNull
@Override
public ClassDescriptor substitute(TypeSubstitutor substitutor) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public JetType getClassObjectType() {
return original.getClassObjectType();
}
@NotNull
@Override
public ClassKind getKind() {
return original.getKind();
}
@Override
@NotNull
public Modality getModality() {
return original.getModality();
}
@Override
public boolean isClassObjectAValue() {
return original.isClassObjectAValue();
}
@Override
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitClassDescriptor(this, data);
}
@Override
public void acceptVoid(DeclarationDescriptorVisitor<Void, Void> visitor) {
throw new UnsupportedOperationException(); // TODO
}
}
@@ -0,0 +1,54 @@
package org.jetbrains.jet.lang.descriptors;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.types.TypeSubstitutor;
import java.util.Collections;
import java.util.Set;
/**
* @author abreslav
*/
public class LazySubstitutingFunctionGroup implements FunctionGroup {
private final TypeSubstitutor substitutor;
private final FunctionGroup functionGroup;
private Set<FunctionDescriptor> functionDescriptors;
public LazySubstitutingFunctionGroup(TypeSubstitutor substitutor, FunctionGroup functionGroup) {
this.substitutor = substitutor;
this.functionGroup = functionGroup;
}
@NotNull
@Override
public String getName() {
return functionGroup.getName();
}
@Override
public boolean isEmpty() {
return functionGroup.isEmpty();
}
@NotNull
@Override
public Set<FunctionDescriptor> getFunctionDescriptors() {
if (functionDescriptors == null) {
if (substitutor.isEmpty()) {
functionDescriptors = functionGroup.getFunctionDescriptors();
}
else {
Set<FunctionDescriptor> functionDescriptorSet = Sets.newLinkedHashSet();
for (FunctionDescriptor descriptor : functionGroup.getFunctionDescriptors()) {
FunctionDescriptor substitute = descriptor.substitute(substitutor);
if (substitute != null) {
functionDescriptorSet.add(substitute);
}
}
functionDescriptors = Collections.unmodifiableSet(functionDescriptorSet);
}
}
return functionDescriptors;
}
}
@@ -0,0 +1,41 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeSubstitutor;
import java.util.List;
/**
* @author abreslav
*/
public class LocalVariableDescriptor extends VariableDescriptorImpl {
private boolean isVar;
public LocalVariableDescriptor(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull List<AnnotationDescriptor> annotations,
@NotNull String name,
@Nullable JetType type,
boolean mutable) {
super(containingDeclaration, annotations, name, mutable ? type : null, type);
isVar = mutable;
}
@NotNull
@Override
public LocalVariableDescriptor substitute(TypeSubstitutor substitutor) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitLocalVariableDescriptor(this, data);
}
@Override
public boolean isVar() {
return isVar;
}
}
@@ -0,0 +1,11 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
/**
* @author abreslav
*/
public interface MemberDescriptor {
@NotNull
Modality getModality();
}
@@ -0,0 +1,26 @@
package org.jetbrains.jet.lang.descriptors;
/**
* @author abreslav
*/
public enum Modality {
FINAL(false),
OPEN(true),
ABSTRACT(true);
private final boolean open;
private Modality(boolean open) {
this.open = open;
}
public boolean isOpen() {
return open;
}
public static Modality convertFromFlags(boolean _abstract, boolean open) {
if (_abstract) return ABSTRACT;
if (open) return OPEN;
return FINAL;
}
}
@@ -0,0 +1,27 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.types.TypeSubstitutor;
import java.util.Collections;
/**
* @author abreslav
*/
public class ModuleDescriptor extends DeclarationDescriptorImpl {
public ModuleDescriptor(String name) {
super(null, Collections.<AnnotationDescriptor>emptyList(), name);
}
@NotNull
@Override
public ModuleDescriptor substitute(TypeSubstitutor substitutor) {
return this;
}
@Override
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitModuleDeclaration(this, data);
}
}
@@ -0,0 +1,278 @@
package org.jetbrains.jet.lang.descriptors;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.resolve.DescriptorRenderer;
import java.util.*;
/**
* @author abreslav
*/
public class MutableClassDescriptor extends MutableDeclarationDescriptor implements ClassDescriptor, NamespaceLike {
private ConstructorDescriptor primaryConstructor;
private final WritableFunctionGroup constructors = new WritableFunctionGroup("<init>");
private final Set<FunctionDescriptor> functions = Sets.newHashSet();
private final Set<PropertyDescriptor> properties = Sets.newHashSet();
private List<TypeParameterDescriptor> typeParameters = Lists.newArrayList();
private Collection<JetType> supertypes = Lists.newArrayList();
private Modality modality;
private TypeConstructor typeConstructor;
private final WritableScope scopeForMemberResolution;
private final WritableScope scopeForMemberLookup;
// This scope contains type parameters but does not contain inner classes
private final WritableScope scopeForSupertypeResolution;
private MutableClassDescriptor classObjectDescriptor;
private JetType classObjectType;
private JetType defaultType;
private final ClassKind kind;
private JetType superclassType;
// public MutableClassDescriptor(@NotNull BindingTrace trace, @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope outerScope) {
// this(trace, containingDeclaration, outerScope, ClassKind.CLASS);
// }
public MutableClassDescriptor(@NotNull BindingTrace trace, @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope outerScope, ClassKind kind) {
super(containingDeclaration);
this.scopeForMemberLookup = new WritableScopeImpl(JetScope.EMPTY, this, trace.getErrorHandler()).setDebugName("MemberLookup");
this.scopeForSupertypeResolution = new WritableScopeImpl(outerScope, this, trace.getErrorHandler()).setDebugName("SupertypeResolution");
this.scopeForMemberResolution = new WritableScopeImpl(new ChainedScope(this, scopeForMemberLookup, scopeForSupertypeResolution), this, trace.getErrorHandler()).setDebugName("MemberResolution");
this.kind = kind;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@Override
public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) {
if (this.classObjectDescriptor != null) return ClassObjectStatus.DUPLICATE;
assert classObjectDescriptor.getKind() == ClassKind.OBJECT;
this.classObjectDescriptor = classObjectDescriptor;
return ClassObjectStatus.OK;
}
@Nullable
public MutableClassDescriptor getClassObjectDescriptor() {
return classObjectDescriptor;
}
public void setPrimaryConstructor(@NotNull ConstructorDescriptor constructorDescriptor) {
assert this.primaryConstructor == null : "Primary constructor assigned twice " + this;
this.primaryConstructor = constructorDescriptor;
addConstructor(constructorDescriptor);
}
@Override
@Nullable
public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
return primaryConstructor;
}
public void addConstructor(@NotNull ConstructorDescriptor constructorDescriptor) {
assert constructorDescriptor.getContainingDeclaration() == this;
// assert constructorDescriptor.getTypeParameters().size() == getTypeConstructor().getParameters().size();
constructors.addFunction(constructorDescriptor);
if (defaultType != null) {
// constructorDescriptor.getTypeParameters().addAll(typeParameters);
((ConstructorDescriptorImpl) constructorDescriptor).setReturnType(getDefaultType());
}
}
@Override
public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) {
properties.add(propertyDescriptor);
scopeForMemberLookup.addVariableDescriptor(propertyDescriptor);
}
@NotNull
public Set<PropertyDescriptor> getProperties() {
return properties;
}
@Override
public void addFunctionDescriptor(@NotNull FunctionDescriptor functionDescriptor) {
functions.add(functionDescriptor);
scopeForMemberLookup.addFunctionDescriptor(functionDescriptor);
}
@NotNull
public Set<FunctionDescriptor> getFunctions() {
return functions;
}
@Override
public NamespaceDescriptorImpl getNamespace(String name) {
throw new UnsupportedOperationException("Classes do not define namespaces");
}
@Override
public void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) {
throw new UnsupportedOperationException("Classes do not define namespaces");
}
@Override
public void addClassifierDescriptor(@NotNull MutableClassDescriptor classDescriptor) {
scopeForMemberLookup.addClassifierDescriptor(classDescriptor);
}
public void addSupertype(@NotNull JetType supertype) {
if (!ErrorUtils.isErrorType(supertype)) {
scopeForMemberLookup.importScope(supertype.getMemberScope());
}
supertypes.add(supertype);
}
public void setTypeParameterDescriptors(List<TypeParameterDescriptor> typeParameters) {
for (TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
this.typeParameters.add(typeParameterDescriptor);
scopeForSupertypeResolution.addTypeParameterDescriptor(typeParameterDescriptor);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@Override
public void setName(@NotNull String name) {
super.setName(name);
scopeForMemberResolution.addLabeledDeclaration(this);
}
@NotNull
@Override
public TypeConstructor getTypeConstructor() {
return typeConstructor;
}
public void createTypeConstructor() {
assert typeConstructor == null : typeConstructor;
this.typeConstructor = new TypeConstructorImpl(
this,
Collections.<AnnotationDescriptor>emptyList(), // TODO : pass annotations from the class?
!modality.isOpen(),
getName(),
typeParameters,
supertypes);
scopeForMemberResolution.setThisType(getDefaultType());
for (FunctionDescriptor functionDescriptor : constructors.getFunctionDescriptors()) {
((ConstructorDescriptorImpl) functionDescriptor).setReturnType(getDefaultType());
}
}
@NotNull
@Override
public JetScope getMemberScope(List<TypeProjection> typeArguments) {
assert typeArguments.size() == typeConstructor.getParameters().size();
if (typeArguments.isEmpty()) return scopeForMemberLookup;
List<TypeParameterDescriptor> typeParameters = getTypeConstructor().getParameters();
Map<TypeConstructor, TypeProjection> substitutionContext = TypeUtils.buildSubstitutionContext(typeParameters, typeArguments);
return new SubstitutingScope(scopeForMemberLookup, TypeSubstitutor.create(substitutionContext));
}
@NotNull
@Override
public JetType getDefaultType() {
if (defaultType == null) {
defaultType = TypeUtils.makeUnsubstitutedType(this, scopeForMemberLookup);
}
return defaultType;
}
@NotNull
@Override
public FunctionGroup getConstructors() {
// TODO : Duplicates ClassDescriptorImpl
// assert typeArguments.size() == getTypeConstructor().getParameters().size();
// if (typeArguments.size() == 0) {
// return constructors;
// }
// Map<TypeConstructor, TypeProjection> substitutionContext = TypeUtils.buildSubstitutionContext(getTypeConstructor().getParameters(), typeArguments);
// return new LazySubstitutingFunctionGroup(TypeSubstitutor.create(substitutionContext), constructors);
return constructors;
}
@NotNull
public JetScope getScopeForSupertypeResolution() {
return scopeForSupertypeResolution;
}
@NotNull
public JetScope getScopeForMemberLookup() {
return scopeForMemberLookup;
}
@NotNull
public JetScope getScopeForMemberResolution() {
return scopeForMemberResolution;
}
@NotNull
@Override
public ClassDescriptor substitute(TypeSubstitutor substitutor) {
if (substitutor.isEmpty()) {
return this;
}
return new LazySubstitutingClassDescriptor(this, substitutor);
}
@Override
public JetType getClassObjectType() {
if (classObjectType == null && classObjectDescriptor != null) {
classObjectType = classObjectDescriptor.getDefaultType();
}
return classObjectType;
}
@Override
public boolean isClassObjectAValue() {
return true;
}
@Override
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitClassDescriptor(this, data);
}
@Override
public boolean hasConstructors() {
return !constructors.isEmpty();
}
@NotNull
@Override
public ClassKind getKind() {
return kind;
}
@NotNull
@Override
public JetType getSuperclassType() {
return superclassType;
}
public void setSuperclassType(@NotNull JetType superclassType) {
this.superclassType = superclassType;
}
public void setModality(Modality modality) {
this.modality = modality;
}
@Override
@NotNull
public Modality getModality() {
return modality;
}
@Override
public String toString() {
return DescriptorRenderer.TEXT.render(this) + "[" + getClass().getCanonicalName() + "@" + System.identityHashCode(this) + "]";
}
}
@@ -0,0 +1,51 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import java.util.List;
/**
* @author abreslav
*/
public abstract class MutableDeclarationDescriptor implements DeclarationDescriptor {
private String name;
private final DeclarationDescriptor containingDeclaration;
public MutableDeclarationDescriptor(DeclarationDescriptor containingDeclaration) {
this.containingDeclaration = containingDeclaration;
}
@Override
public List<AnnotationDescriptor> getAnnotations() {
throw new UnsupportedOperationException(); // TODO
}
@NotNull
@Override
public String getName() {
return name;
}
public void setName(@NotNull String name) {
assert this.name == null : this.name;
this.name = name;
}
@NotNull
@Override
public DeclarationDescriptor getOriginal() {
return this;
}
@NotNull
@Override
public DeclarationDescriptor getContainingDeclaration() {
return containingDeclaration;
}
@Override
public void acceptVoid(DeclarationDescriptorVisitor<Void, Void> visitor) {
accept(visitor, null);
}
}
@@ -0,0 +1,11 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.types.JetType;
/**
* @author abreslav
*/
public interface MutableValueParameterDescriptor extends ValueParameterDescriptor {
void setType(@NotNull JetType type);
}
@@ -0,0 +1,11 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
/**
* @author abreslav
*/
public interface Named {
@NotNull
String getName();
}
@@ -0,0 +1,17 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.annotations.Annotated;
import org.jetbrains.jet.lang.resolve.JetScope;
import org.jetbrains.jet.lang.types.NamespaceType;
/**
* @author abreslav
*/
public interface NamespaceDescriptor extends Annotated, Named, DeclarationDescriptor {
@NotNull
JetScope getMemberScope();
@NotNull
NamespaceType getNamespaceType();
}
@@ -0,0 +1,60 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.WritableScope;
import java.util.List;
/**
* @author abreslav
*/
public class NamespaceDescriptorImpl extends AbstractNamespaceDescriptorImpl implements NamespaceLike {
private WritableScope memberScope;
public NamespaceDescriptorImpl(@Nullable DeclarationDescriptor containingDeclaration, @NotNull List<AnnotationDescriptor> annotations, @NotNull String name) {
super(containingDeclaration, annotations, name);
}
public void initialize(@NotNull WritableScope memberScope) {
this.memberScope = memberScope;
}
@Override
@NotNull
public WritableScope getMemberScope() {
return memberScope;
}
@Override
public NamespaceDescriptorImpl getNamespace(String name) {
return (NamespaceDescriptorImpl) memberScope.getDeclaredNamespace(name);
}
@Override
public void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) {
memberScope.addNamespace(namespaceDescriptor);
}
@Override
public void addClassifierDescriptor(@NotNull MutableClassDescriptor classDescriptor) {
memberScope.addClassifierDescriptor(classDescriptor);
}
@Override
public void addFunctionDescriptor(@NotNull FunctionDescriptor functionDescriptor) {
memberScope.addFunctionDescriptor(functionDescriptor);
}
@Override
public void addPropertyDescriptor(@NotNull PropertyDescriptor variableDescriptor) {
memberScope.addVariableDescriptor(variableDescriptor);
}
@Override
public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) {
throw new IllegalStateException("Must be guaranteed not to happen by the parser");
}
}
@@ -0,0 +1,79 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.types.TypeSubstitutor;
import java.util.List;
/**
* @author abreslav
*/
public interface NamespaceLike extends DeclarationDescriptor {
abstract class Adapter implements NamespaceLike {
private final DeclarationDescriptor descriptor;
public Adapter(DeclarationDescriptor descriptor) {
this.descriptor = descriptor;
}
@Override
@NotNull
public DeclarationDescriptor getOriginal() {
return descriptor.getOriginal();
}
@Override
@Nullable
public DeclarationDescriptor getContainingDeclaration() {
return descriptor.getContainingDeclaration();
}
@Override
public DeclarationDescriptor substitute(TypeSubstitutor substitutor) {
return descriptor.substitute(substitutor);
}
@Override
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
return descriptor.accept(visitor, data);
}
@Override
public void acceptVoid(DeclarationDescriptorVisitor<Void, Void> visitor) {
descriptor.acceptVoid(visitor);
}
@Override
public List<AnnotationDescriptor> getAnnotations() {
return descriptor.getAnnotations();
}
@Override
@NotNull
public String getName() {
return descriptor.getName();
}
}
@Nullable
NamespaceDescriptorImpl getNamespace(String name);
void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor);
void addClassifierDescriptor(@NotNull MutableClassDescriptor classDescriptor);
void addFunctionDescriptor(@NotNull FunctionDescriptor functionDescriptor);
void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor);
enum ClassObjectStatus {
OK,
DUPLICATE,
NOT_ALLOWED
}
ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor);
}
@@ -0,0 +1,63 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.types.TypeSubstitutor;
import java.util.Collections;
import java.util.List;
/**
* @author abreslav
*/
public abstract class PropertyAccessorDescriptor extends DeclarationDescriptorImpl implements FunctionDescriptor, MemberDescriptor {
private final boolean hasBody;
private final boolean isDefault;
private final Modality modality;
protected PropertyAccessorDescriptor(
@NotNull Modality modality,
@NotNull PropertyDescriptor correspondingProperty,
@NotNull List<AnnotationDescriptor> annotations,
@NotNull String name,
boolean hasBody,
boolean isDefault) {
super(correspondingProperty.getContainingDeclaration(), annotations, name);
this.modality = modality;
this.hasBody = hasBody;
this.isDefault = isDefault;
}
public boolean hasBody() {
return hasBody;
}
public boolean isDefault() {
return isDefault;
}
@NotNull
@Override
public PropertyAccessorDescriptor getOriginal() {
return (PropertyAccessorDescriptor) super.getOriginal();
}
@NotNull
@Override
public FunctionDescriptor substitute(TypeSubstitutor substitutor) {
throw new UnsupportedOperationException(); // TODO
}
@NotNull
@Override
public List<TypeParameterDescriptor> getTypeParameters() {
return Collections.emptyList();
}
@NotNull
@Override
public Modality getModality() {
return modality;
}
}
@@ -0,0 +1,147 @@
package org.jetbrains.jet.lang.descriptors;
import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeSubstitutor;
import org.jetbrains.jet.lang.types.Variance;
import java.util.List;
/**
* @author abreslav
*/
public class PropertyDescriptor extends VariableDescriptorImpl implements MemberDescriptor {
private final Modality modality;
private final boolean isVar;
private final JetType receiverType;
private final List<TypeParameterDescriptor> typeParemeters = Lists.newArrayListWithCapacity(0);
private final PropertyDescriptor original;
private PropertyGetterDescriptor getter;
private PropertySetterDescriptor setter;
private PropertyDescriptor(
@Nullable PropertyDescriptor original,
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull List<AnnotationDescriptor> annotations,
@NotNull Modality modality,
boolean isVar,
@Nullable JetType receiverType,
@NotNull String name,
@Nullable JetType inType,
@NotNull JetType outType) {
super(containingDeclaration, annotations, name, inType, outType);
assert !isVar || inType != null;
// assert outType != null;
this.isVar = isVar;
this.modality = modality;
this.receiverType = receiverType;
this.original = original == null ? this : original.getOriginal();
}
public PropertyDescriptor(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull List<AnnotationDescriptor> annotations,
@NotNull Modality modality,
boolean isVar,
@Nullable JetType receiverType,
@NotNull String name,
@Nullable JetType inType,
@NotNull JetType outType) {
this(null, containingDeclaration, annotations, modality, isVar, receiverType, name, inType, outType);
}
private PropertyDescriptor(
@NotNull PropertyDescriptor original,
@Nullable JetType receiverType,
@Nullable JetType inType,
@NotNull JetType outType) {
this(
original,
original.getContainingDeclaration(),
original.getAnnotations(), // TODO : substitute?
original.getModality(),
original.isVar,
receiverType,
original.getName(),
inType,
outType);
}
public void initialize(@NotNull List<TypeParameterDescriptor> typeParameters, @Nullable PropertyGetterDescriptor getter, @Nullable PropertySetterDescriptor setter) {
this.typeParemeters.addAll(typeParameters);
this.getter = getter;
this.setter = setter;
}
@NotNull
@Override
public List<TypeParameterDescriptor> getTypeParameters() {
return typeParemeters;
}
@Nullable
public JetType getReceiverType() {
return receiverType;
}
@NotNull
@Override
public JetType getReturnType() {
return getOutType();
}
public boolean isVar() {
return isVar;
}
@NotNull
@Override
public Modality getModality() {
return modality;
}
@Nullable
public PropertyGetterDescriptor getGetter() {
return getter;
}
@Nullable
public PropertySetterDescriptor getSetter() {
return setter;
}
@NotNull
@Override
public PropertyDescriptor substitute(TypeSubstitutor substitutor) {
JetType originalInType = getInType();
JetType inType = originalInType == null ? null : substitutor.substitute(originalInType, Variance.IN_VARIANCE);
JetType originalOutType = getOutType();
JetType outType = substitutor.substitute(originalOutType, Variance.OUT_VARIANCE);
if (inType == null && outType == null) {
return null; // TODO : tell the user that the property was projected out
}
JetType receiverType = getReceiverType();
return new PropertyDescriptor(
this,
receiverType == null ? null : substitutor.substitute(receiverType, Variance.IN_VARIANCE),
inType,
outType
);
}
@Override
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitPropertyDescriptor(this, data);
}
@NotNull
@Override
public PropertyDescriptor getOriginal() {
return original;
}
}
@@ -0,0 +1,56 @@
package org.jetbrains.jet.lang.descriptors;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Collections;
import java.util.List;
import java.util.Set;
/**
* @author abreslav
*/
public class PropertyGetterDescriptor extends PropertyAccessorDescriptor {
private final Set<PropertyGetterDescriptor> overriddenGetters = Sets.newHashSet();
private JetType returnType;
public PropertyGetterDescriptor(@NotNull Modality modality, @NotNull PropertyDescriptor correspondingProperty, @NotNull List<AnnotationDescriptor> annotations, @Nullable JetType returnType, boolean hasBody, boolean isDefault) {
super(modality, correspondingProperty, annotations, "get-" + correspondingProperty.getName(), hasBody, isDefault);
this.returnType = returnType == null ? correspondingProperty.getOutType() : returnType;
}
@NotNull
@Override
public Set<? extends FunctionDescriptor> getOverriddenDescriptors() {
return overriddenGetters;
}
public void addOverriddenFunction(@NotNull PropertyGetterDescriptor overriddenGetter) {
overriddenGetters.add(overriddenGetter);
}
@Override
public JetType getReceiverType() {
return null; // TODO
}
@NotNull
@Override
public List<ValueParameterDescriptor> getValueParameters() {
return Collections.emptyList();
}
@NotNull
@Override
public JetType getReturnType() {
return returnType;
}
@Override
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitPropertyGetterDescriptor(this, data);
}
}
@@ -0,0 +1,66 @@
package org.jetbrains.jet.lang.descriptors;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Collections;
import java.util.List;
import java.util.Set;
/**
* @author abreslav
*/
public class PropertySetterDescriptor extends PropertyAccessorDescriptor {
private MutableValueParameterDescriptor parameter;
private final Set<PropertySetterDescriptor> overriddenSetters = Sets.newHashSet();
public PropertySetterDescriptor(@NotNull Modality modality, @NotNull PropertyDescriptor correspondingProperty, @NotNull List<AnnotationDescriptor> annotations, boolean hasBody, boolean isDefault) {
super(modality, correspondingProperty, annotations, "set-" + correspondingProperty.getName(), hasBody, isDefault);
}
public void initialize(@NotNull MutableValueParameterDescriptor parameter) {
assert this.parameter == null;
this.parameter = parameter;
}
public void setParameterType(@NotNull JetType type) {
parameter.setType(type);
}
@NotNull
@Override
public Set<? extends FunctionDescriptor> getOverriddenDescriptors() {
return overriddenSetters;
}
public void setOverriddenFunction(@NotNull PropertySetterDescriptor overriddenSetter) {
overriddenSetters.add(overriddenSetter);
}
@Override
public JetType getReceiverType() {
return null; // TODO
}
@NotNull
@Override
public List<ValueParameterDescriptor> getValueParameters() {
return Collections.<ValueParameterDescriptor>singletonList(parameter);
}
@NotNull
@Override
public JetType getReturnType() {
return JetStandardClasses.getUnitType();
}
@Override
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitPropertySetterDescriptor(this, data);
}
}
@@ -0,0 +1,160 @@
package org.jetbrains.jet.lang.descriptors;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.JetScope;
import org.jetbrains.jet.lang.resolve.LazyScopeAdapter;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.resolve.DescriptorRenderer;
import java.util.Collections;
import java.util.List;
import java.util.Set;
/**
* @author abreslav
*/
public class TypeParameterDescriptor extends DeclarationDescriptorImpl implements ClassifierDescriptor {
public static TypeParameterDescriptor createWithDefaultBound(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull List<AnnotationDescriptor> annotations,
@NotNull Variance variance,
@NotNull String name,
int index) {
TypeParameterDescriptor typeParameterDescriptor = createForFurtherModification(containingDeclaration, annotations, variance, name, index);
typeParameterDescriptor.addUpperBound(JetStandardClasses.getDefaultBound());
return typeParameterDescriptor;
}
public static TypeParameterDescriptor createForFurtherModification(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull List<AnnotationDescriptor> annotations,
@NotNull Variance variance,
@NotNull String name,
int index) {
return new TypeParameterDescriptor(containingDeclaration, annotations, variance, name, index);
}
private final int index;
private final Variance variance;
private final Set<JetType> upperBounds;
private JetType boundsAsType;
private final TypeConstructor typeConstructor;
private JetType defaultType;
private final Set<JetType> classObjectUpperBounds = Sets.newLinkedHashSet();
private JetType classObjectBoundsAsType;
private TypeParameterDescriptor(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull List<AnnotationDescriptor> annotations,
@NotNull Variance variance,
@NotNull String name,
int index) {
super(containingDeclaration, annotations, name);
this.index = index;
this.variance = variance;
this.upperBounds = Sets.newLinkedHashSet();
// TODO: Should we actually pass the annotations on to the type constructor?
this.typeConstructor = new TypeConstructorImpl(
this,
annotations,
false,
"&" + name,
Collections.<TypeParameterDescriptor>emptyList(),
upperBounds);
}
public Variance getVariance() {
return variance;
}
public void addUpperBound(@NotNull JetType bound) {
upperBounds.add(bound); // TODO : Duplicates?
}
public Set<JetType> getUpperBounds() {
return upperBounds;
}
@NotNull
@Override
public TypeConstructor getTypeConstructor() {
return typeConstructor;
}
@Override
public String toString() {
return DescriptorRenderer.TEXT.render(this);
}
@NotNull
public JetType getBoundsAsType() {
if (boundsAsType == null) {
assert upperBounds != null : "Upper bound list is null in " + getName();
assert upperBounds.size() > 0 : "Upper bound list is empty in " + getName();
boundsAsType = TypeUtils.intersect(JetTypeChecker.INSTANCE, upperBounds);
if (boundsAsType == null) {
boundsAsType = JetStandardClasses.getNothingType();
}
}
return boundsAsType;
}
@NotNull
@Override
@Deprecated // Use the static method TypeParameterDescriptor.substitute()
public TypeParameterDescriptor substitute(TypeSubstitutor substitutor) {
throw new UnsupportedOperationException();
}
@Override
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitTypeParameterDescriptor(this, data);
}
@NotNull
@Override
public JetType getDefaultType() {
if (defaultType == null) {
defaultType = new JetTypeImpl(
Collections.<AnnotationDescriptor>emptyList(),
getTypeConstructor(),
TypeUtils.hasNullableBound(this),
Collections.<TypeProjection>emptyList(),
new LazyScopeAdapter(new LazyValue<JetScope>() {
@Override
protected JetScope compute() {
return getBoundsAsType().getMemberScope();
}
}));
}
return defaultType;
}
@Override
public JetType getClassObjectType() {
if (classObjectUpperBounds.isEmpty()) return null;
if (classObjectBoundsAsType == null) {
classObjectBoundsAsType = TypeUtils.intersect(JetTypeChecker.INSTANCE, classObjectUpperBounds);
if (classObjectBoundsAsType == null) {
classObjectBoundsAsType = JetStandardClasses.getNothingType();
}
}
return classObjectBoundsAsType;
}
@Override
public boolean isClassObjectAValue() {
return true;
}
public void addClassObjectBound(@NotNull JetType bound) {
classObjectUpperBounds.add(bound); // TODO : Duplicates?
}
public int getIndex() {
return index;
}
}
@@ -0,0 +1,26 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.types.JetType;
/**
* @author abreslav
*/
public interface ValueParameterDescriptor extends VariableDescriptor {
/**
* Returns the 0-based index of the value parameter in the parameter list of its containing function.
*
* @return the parameter index
*/
int getIndex();
boolean hasDefaultValue();
boolean isRef();
boolean isVararg();
@Override
@NotNull
JetType getOutType();
@Override
ValueParameterDescriptor getOriginal();
}
@@ -0,0 +1,104 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeSubstitutor;
import java.util.List;
/**
* @author abreslav
*/
public class ValueParameterDescriptorImpl extends VariableDescriptorImpl implements MutableValueParameterDescriptor {
private final boolean hasDefaultValue;
private final boolean isVararg;
private final boolean isVar;
private final int index;
private final ValueParameterDescriptor original;
public ValueParameterDescriptorImpl(
@NotNull DeclarationDescriptor containingDeclaration,
int index,
@NotNull List<AnnotationDescriptor> annotations,
@NotNull String name,
@Nullable JetType inType,
@NotNull JetType outType,
boolean hasDefaultValue,
boolean isVararg) {
super(containingDeclaration, annotations, name, inType, outType);
this.original = this;
this.index = index;
this.hasDefaultValue = hasDefaultValue;
this.isVararg = isVararg;
this.isVar = inType != null;
}
public ValueParameterDescriptorImpl(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull ValueParameterDescriptor original,
@NotNull List<AnnotationDescriptor> annotations,
@Nullable JetType inType,
@NotNull JetType outType
) {
super(containingDeclaration, annotations, original.getName(), inType, outType);
this.original = original;
this.index = original.getIndex();
this.hasDefaultValue = original.hasDefaultValue();
this.isVararg = original.isVararg();
this.isVar = inType != null;
}
@Override
public void setType(@NotNull JetType type) {
assert getOutType() == null;
setOutType(type);
if (isVar) {
assert getInType() == null;
setInType(type);
}
}
@Override
public int getIndex() {
return index;
}
@Override
public boolean hasDefaultValue() {
return hasDefaultValue;
}
@Override
public boolean isRef() {
throw new UnsupportedOperationException(); // TODO
}
@Override
public boolean isVararg() {
return isVararg;
}
@NotNull
@Override
public ValueParameterDescriptor getOriginal() {
return original == this ? this : original.getOriginal();
}
@NotNull
@Override
public ValueParameterDescriptor substitute(TypeSubstitutor substitutor) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitValueParameterDescriptor(this, data);
}
@Override
public boolean isVar() {
return isVar;
}
}
@@ -0,0 +1,34 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Collections;
/**
* @author abreslav
*/
public class VariableAsFunctionDescriptor extends FunctionDescriptorImpl {
public static VariableAsFunctionDescriptor create(@NotNull VariableDescriptor variableDescriptor) {
JetType outType = variableDescriptor.getOutType();
assert outType != null;
assert JetStandardClasses.isFunctionType(outType);
VariableAsFunctionDescriptor result = new VariableAsFunctionDescriptor(variableDescriptor);
result.initialize(JetStandardClasses.getReceiverType(outType), Collections.<TypeParameterDescriptor>emptyList(), JetStandardClasses.getValueParameters(result, outType), JetStandardClasses.getReturnType(outType), Modality.FINAL);
return result;
}
private final VariableDescriptor variableDescriptor;
private VariableAsFunctionDescriptor(VariableDescriptor variableDescriptor) {
super(variableDescriptor.getContainingDeclaration(), Collections.<AnnotationDescriptor>emptyList(), variableDescriptor.getName());
// super(variableDescriptor.getContainingDeclaration(), Collections.<AnnotationDescriptor>emptyList(), variableDescriptor.getName());
this.variableDescriptor = variableDescriptor;
}
public VariableDescriptor getVariableDescriptor() {
return variableDescriptor;
}
}
@@ -0,0 +1,34 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeSubstitutor;
/**
* @author abreslav
*/
public interface VariableDescriptor extends CallableDescriptor {
/**
* @return <code>null</code> for write-only variables (i.e. properties), variable value type otherwise
*/
@Nullable
JetType getOutType();
/**
* @return <code>null</code> for read-only variables (i.e. val's etc), or the type expected on assignment type otherwise
*/
@Nullable
JetType getInType();
@Override
@SuppressWarnings({"NullableProblems"})
@NotNull
DeclarationDescriptor getContainingDeclaration();
@NotNull
@Override
VariableDescriptor substitute(TypeSubstitutor substitutor);
boolean isVar();
}
@@ -0,0 +1,84 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Collections;
import java.util.List;
import java.util.Set;
/**
* @author abreslav
*/
public abstract class VariableDescriptorImpl extends DeclarationDescriptorImpl implements VariableDescriptor {
private JetType inType;
private JetType outType;
public VariableDescriptorImpl(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull List<AnnotationDescriptor> annotations,
@NotNull String name,
@Nullable JetType inType,
@Nullable JetType outType) {
super(containingDeclaration, annotations, name);
assert (inType != null) || (outType != null);
this.inType = inType;
this.outType = outType;
}
@Override
public JetType getOutType() {
return outType;
}
@Override
public JetType getInType() {
return inType;
}
protected void setInType(JetType inType) {
this.inType = inType;
}
protected void setOutType(JetType outType) {
this.outType = outType;
}
@Override
@NotNull
public VariableDescriptor getOriginal() {
return (VariableDescriptor) super.getOriginal();
}
@NotNull
@Override
public List<ValueParameterDescriptor> getValueParameters() {
return Collections.emptyList();
}
@NotNull
@Override
public Set<? extends CallableDescriptor> getOverriddenDescriptors() {
return Collections.emptySet();
}
@NotNull
@Override
public List<TypeParameterDescriptor> getTypeParameters() {
return Collections.emptyList();
}
@Override
public JetType getReceiverType() {
return null;
}
@NotNull
@Override
public JetType getReturnType() {
return getOutType();
}
}
@@ -0,0 +1,63 @@
package org.jetbrains.jet.lang.descriptors;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.Set;
/**
* @author abreslav
*/
public class WritableFunctionGroup implements FunctionGroup {
private final String name;
private Set<FunctionDescriptor> functionDescriptors;
private Set<FunctionDescriptor> unmodifiableFunctionDescriptors;
public WritableFunctionGroup(String name) {
this.name = name;
}
@NotNull
@Override
public String getName() {
return name;
}
@Override
public String toString() {
return "FunctionGroup{" +
"name='" + name + '\'' +
'}';
}
public void addFunction(@NotNull FunctionDescriptor functionDescriptor) {
getWritableFunctionDescriptors().add(functionDescriptor);
}
@Override
@NotNull
public Set<FunctionDescriptor> getFunctionDescriptors() {
if (unmodifiableFunctionDescriptors == null) {
unmodifiableFunctionDescriptors = Collections.unmodifiableSet(getWritableFunctionDescriptors());
}
return unmodifiableFunctionDescriptors;
}
private Set<FunctionDescriptor> getWritableFunctionDescriptors() {
if (functionDescriptors == null) {
functionDescriptors = Sets.newLinkedHashSet();
}
return functionDescriptors;
}
@Override
public boolean isEmpty() {
return functionDescriptors == null || functionDescriptors.isEmpty();
}
public void addAllFunctions(@NotNull FunctionGroup functionGroup) {
if (functionGroup.isEmpty()) return;
getWritableFunctionDescriptors().addAll(functionGroup.getFunctionDescriptors());
}
}
@@ -0,0 +1,10 @@
package org.jetbrains.jet.lang.descriptors.annotations;
import java.util.List;
/**
* @author abreslav
*/
public interface Annotated {
List<AnnotationDescriptor> getAnnotations();
}
@@ -0,0 +1,19 @@
package org.jetbrains.jet.lang.descriptors.annotations;
import java.util.List;
/**
* @author abreslav
*/
public abstract class AnnotatedImpl implements Annotated {
private final List<AnnotationDescriptor> annotations;
public AnnotatedImpl(List<AnnotationDescriptor> annotations) {
this.annotations = annotations;
}
@Override
public List<AnnotationDescriptor> getAnnotations() {
return annotations;
}
}
@@ -0,0 +1,31 @@
package org.jetbrains.jet.lang.descriptors.annotations;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.constants.*;
/**
* @author abreslav
*/
public interface AnnotationArgumentVisitor<R, D> {
R visitLongValue(@NotNull LongValue value, D data);
R visitIntValue(IntValue value, D data);
R visitErrorValue(ErrorValue value, D data);
R visitShortValue(ShortValue value, D data);
R visitByteValue(ByteValue value, D data);
R visitDoubleValue(DoubleValue value, D data);
R visitFloatValue(FloatValue value, D data);
R visitBooleanValue(BooleanValue value, D data);
R visitCharValue(CharValue value, D data);
R visitStringValue(StringValue value, D data);
R visitNullValue(NullValue value, D data);
}
@@ -0,0 +1,33 @@
package org.jetbrains.jet.lang.descriptors.annotations;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.types.JetType;
import java.util.List;
/**
* @author abreslav
*/
public class AnnotationDescriptor {
private JetType annotationType;
private List<CompileTimeConstant<?>> valueArguments;
@NotNull
public JetType getType() {
return annotationType;
}
@NotNull
public List<CompileTimeConstant<?>> getValueArguments() {
return valueArguments;
}
public void setAnnotationType(@NotNull JetType annotationType) {
this.annotationType = annotationType;
}
public void setValueArguments(@NotNull List<CompileTimeConstant<?>> valueArguments) {
this.valueArguments = valueArguments;
}
}
@@ -0,0 +1,393 @@
package org.jetbrains.jet.lang.parsing;
import com.intellij.lang.PsiBuilder;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import org.jetbrains.jet.lexer.JetKeywordToken;
import org.jetbrains.jet.lexer.JetToken;
import org.jetbrains.jet.lexer.JetTokens;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
import static org.jetbrains.jet.lexer.JetTokens.*;
/**
* @author abreslav
*/
/*package*/ abstract class AbstractJetParsing {
private static final Map<String, JetKeywordToken> SOFT_KEYWORD_TEXTS = new HashMap<String, JetKeywordToken>();
static {
for (IElementType type : JetTokens.SOFT_KEYWORDS.getTypes()) {
JetKeywordToken keywordToken = (JetKeywordToken) type;
assert keywordToken.isSoft();
SOFT_KEYWORD_TEXTS.put(keywordToken.getValue(), keywordToken);
}
}
static {
for (IElementType token : JetTokens.KEYWORDS.getTypes()) {
assert token instanceof JetKeywordToken : "Must be JetKeywordToken: " + token;
assert !((JetKeywordToken) token).isSoft() : "Must not be soft: " + token;
}
}
protected final SemanticWhitespaceAwarePsiBuilder myBuilder;
public AbstractJetParsing(SemanticWhitespaceAwarePsiBuilder builder) {
this.myBuilder = builder;
}
protected IElementType getLastToken() {
int i = 1;
int currentOffset = myBuilder.getCurrentOffset();
while (i <= currentOffset && WHITE_SPACE_OR_COMMENT_BIT_SET.contains(myBuilder.rawLookup(-i))) {
i++;
}
return myBuilder.rawLookup(-i);
}
protected boolean expect(JetToken expectation, String message) {
return expect(expectation, message, null);
}
protected PsiBuilder.Marker mark() {
return myBuilder.mark();
}
protected void error(String message) {
myBuilder.error(message);
}
protected boolean expect(JetToken expectation, String message, TokenSet recoverySet) {
if (at(expectation)) {
advance(); // expectation
return true;
}
errorWithRecovery(message, recoverySet);
return false;
}
protected boolean expectNoAdvance(JetToken expectation, String message) {
if (at(expectation)) {
advance(); // expectation
return true;
}
error(message);
return false;
}
protected void errorWithRecovery(String message, TokenSet recoverySet) {
IElementType tt = tt();
if (recoverySet == null || recoverySet.contains(tt)
|| (recoverySet.contains(EOL_OR_SEMICOLON)
&& (eof() || tt == SEMICOLON || myBuilder.newlineBeforeCurrentToken()))) {
error(message);
}
else {
errorAndAdvance(message);
}
}
protected boolean errorAndAdvance(String message) {
PsiBuilder.Marker err = mark();
advance(); // erroneous token
err.error(message);
return false;
}
protected boolean eof() {
return myBuilder.eof();
}
protected void advance() {
// TODO: how to report errors on bad characters? (Other than highlighting)
myBuilder.advanceLexer();
}
protected IElementType tt() {
return myBuilder.getTokenType();
}
/**
* Side-effect-free version of at()
*/
protected boolean _at(IElementType expectation) {
IElementType token = tt();
return tokenMatches(token, expectation);
}
private boolean tokenMatches(IElementType token, IElementType expectation) {
if (token == expectation) return true;
if (expectation == EOL_OR_SEMICOLON) {
if (eof()) return true;
if (token == SEMICOLON) return true;
if (myBuilder.newlineBeforeCurrentToken()) return true;
}
return false;
}
protected boolean at(final IElementType expectation) {
if (_at(expectation)) return true;
IElementType token = tt();
if (token == IDENTIFIER && expectation instanceof JetKeywordToken) {
JetKeywordToken expectedKeyword = (JetKeywordToken) expectation;
if (expectedKeyword.isSoft() && expectedKeyword.getValue().equals(myBuilder.getTokenText())) {
myBuilder.remapCurrentToken(expectation);
return true;
}
}
if (expectation == IDENTIFIER && token instanceof JetKeywordToken) {
JetKeywordToken keywordToken = (JetKeywordToken) token;
if (keywordToken.isSoft()) {
myBuilder.remapCurrentToken(IDENTIFIER);
return true;
}
}
return false;
}
/**
* Side-effect-free version of atSet()
*/
protected boolean _atSet(IElementType... tokens) {
return _atSet(TokenSet.create(tokens));
}
/**
* Side-effect-free version of atSet()
*/
protected boolean _atSet(final TokenSet set) {
IElementType token = tt();
if (set.contains(token)) return true;
if (set.contains(EOL_OR_SEMICOLON)) {
if (eof()) return true;
if (token == SEMICOLON) return true;
if (myBuilder.newlineBeforeCurrentToken()) return true;
}
return false;
}
protected boolean atSet(IElementType... tokens) {
return atSet(TokenSet.create(tokens));
}
protected boolean atSet(final TokenSet set) {
if (_atSet(set)) return true;
IElementType token = tt();
if (token == IDENTIFIER) {
JetKeywordToken keywordToken = SOFT_KEYWORD_TEXTS.get(myBuilder.getTokenText());
if (keywordToken != null && set.contains(keywordToken)) {
myBuilder.remapCurrentToken(keywordToken);
return true;
}
}
else {
// We know at this point that <code>set</code> does not contain <code>token</code>
if (set.contains(IDENTIFIER) && token instanceof JetKeywordToken) {
if (((JetKeywordToken) token).isSoft()) {
myBuilder.remapCurrentToken(IDENTIFIER);
return true;
}
}
}
return false;
}
protected IElementType lookahead(int k) {
return myBuilder.lookAhead(k);
}
protected void consumeIf(JetToken token) {
if (at(token)) advance(); // token
}
// TODO: Migrate to predicates
protected void skipUntil(TokenSet tokenSet) {
boolean stopAtEolOrSemi = tokenSet.contains(EOL_OR_SEMICOLON);
while (!eof() && !tokenSet.contains(tt()) && !(stopAtEolOrSemi && at(EOL_OR_SEMICOLON))) {
advance();
}
}
protected void errorUntil(String message, TokenSet tokenSet) {
PsiBuilder.Marker error = mark();
skipUntil(tokenSet);
error.error(message);
}
protected void errorUntilOffset(String mesage, int offset) {
PsiBuilder.Marker error = mark();
while (!eof() && myBuilder.getCurrentOffset() < offset) {
advance();
}
error.error(mesage);
}
protected int matchTokenStreamPredicate(TokenStreamPattern pattern) {
PsiBuilder.Marker currentPosition = mark();
Stack<IElementType> opens = new Stack<IElementType>();
int openAngleBrackets = 0;
int openBraces = 0;
int openParentheses = 0;
int openBrackets = 0;
while (!eof()) {
if (pattern.processToken(
myBuilder.getCurrentOffset(),
pattern.isTopLevel(openAngleBrackets, openBrackets, openBraces, openParentheses))) {
break;
}
if (at(LPAR)) {
openParentheses++;
opens.push(LPAR);
}
else if (at(LT)) {
openAngleBrackets++;
opens.push(LT);
}
else if (at(LBRACE)) {
openBraces++;
opens.push(LBRACE);
}
else if (at(LBRACKET)) {
openBrackets++;
opens.push(LBRACKET);
}
else if (at(RPAR)) {
openParentheses--;
if (opens.isEmpty() || opens.pop() != LPAR) {
if (pattern.handleUnmatchedClosing(RPAR)) {
break;
}
}
}
else if (at(GT)) {
openAngleBrackets--;
}
else if (at(RBRACE)) {
openBraces--;
}
else if (at(RBRACKET)) {
openBrackets--;
}
advance(); // skip token
}
currentPosition.rollbackTo();
return pattern.result();
}
/*
* Looks for a the last top-level (not inside any {} [] () <>) '.' occurring before a
* top-level occurrence of a token from the <code>stopSet</code>
*
* Returns -1 if no occurrence is found
*
*/
protected int findLastBefore(TokenSet lookFor, TokenSet stopAt, boolean dontStopRightAfterOccurrence) {
return matchTokenStreamPredicate(new LastBefore(new AtSet(lookFor), new AtSet(stopAt), dontStopRightAfterOccurrence));
}
protected int findLastBefore(IElementType lookFor, TokenSet stopAt, boolean dontStopRightAfterOccurrence) {
return matchTokenStreamPredicate(new LastBefore(new At(lookFor), new AtSet(stopAt), dontStopRightAfterOccurrence));
}
protected boolean eol() {
return myBuilder.newlineBeforeCurrentToken() || eof();
}
protected abstract JetParsing create(SemanticWhitespaceAwarePsiBuilder builder);
protected JetParsing createTruncatedBuilder(int eofPosition) {
return create(new TruncatedSemanticWhitespaceAwarePsiBuilder(myBuilder, eofPosition));
}
protected class AtOffset extends AbstractTokenStreamPredicate {
private final int offset;
public AtOffset(int offset) {
this.offset = offset;
}
@Override
public boolean matching(boolean topLevel) {
return myBuilder.getCurrentOffset() == offset;
}
}
protected class At extends AbstractTokenStreamPredicate {
private final IElementType lookFor;
private final boolean topLevelOnly;
public At(IElementType lookFor, boolean topLevelOnly) {
this.lookFor = lookFor;
this.topLevelOnly = topLevelOnly;
}
public At(IElementType lookFor) {
this(lookFor, true);
}
@Override
public boolean matching(boolean topLevel) {
return (topLevel || !topLevelOnly) && at(lookFor);
}
}
protected class AtSet extends AbstractTokenStreamPredicate {
private final TokenSet lookFor;
private final TokenSet topLevelOnly;
public AtSet(TokenSet lookFor, TokenSet topLevelOnly) {
this.lookFor = lookFor;
this.topLevelOnly = topLevelOnly;
}
public AtSet(TokenSet lookFor) {
this(lookFor, lookFor);
}
public AtSet(IElementType... lookFor) {
this(TokenSet.create(lookFor), TokenSet.create(lookFor));
}
@Override
public boolean matching(boolean topLevel) {
return (topLevel || !atSet(topLevelOnly)) && atSet(lookFor);
}
}
protected class AtFirstTokenOfTokens extends AbstractTokenStreamPredicate {
private final IElementType[] tokens;
public AtFirstTokenOfTokens(IElementType... tokens) {
assert tokens.length > 0;
this.tokens = tokens;
}
@Override
public boolean matching(boolean topLevel) {
int length = tokens.length;
if (!at(tokens[0])) return false;
for (int i = 1; i < length; i++) {
IElementType lookAhead = myBuilder.lookAhead(i);
if (lookAhead == null || !tokenMatches(lookAhead, tokens[i])) {
return false;
}
}
return true;
}
}
}
@@ -0,0 +1,31 @@
package org.jetbrains.jet.lang.parsing;
import com.intellij.psi.tree.IElementType;
/**
* @author abreslav
*/
public abstract class AbstractTokenStreamPattern implements TokenStreamPattern {
protected int lastOccurrence = -1;
protected void fail() {
lastOccurrence = -1;
}
@Override
public int result() {
return lastOccurrence;
}
@Override
public boolean isTopLevel(int openAngleBrackets, int openBrackets, int openBraces, int openParentheses) {
return openBraces == 0 && openBrackets == 0 && openParentheses == 0 && openAngleBrackets == 0;
}
@Override
public boolean handleUnmatchedClosing(IElementType token) {
return false;
}
}
@@ -0,0 +1,18 @@
package org.jetbrains.jet.lang.parsing;
/**
* @author abreslav
*/
public abstract class AbstractTokenStreamPredicate implements TokenStreamPredicate {
@Override
public TokenStreamPredicate or(final TokenStreamPredicate other) {
return new AbstractTokenStreamPredicate() {
@Override
public boolean matching(boolean topLevel) {
if (AbstractTokenStreamPredicate.this.matching(topLevel)) return true;
return other.matching(topLevel);
}
};
}
}
@@ -0,0 +1,8 @@
package org.jetbrains.jet.lang.parsing;
/**
* @author abreslav
*/
public interface Consumer<T> {
void consume(T item);
}
@@ -0,0 +1,26 @@
package org.jetbrains.jet.lang.parsing;
/**
* @author abreslav
*/
public class FirstBefore extends AbstractTokenStreamPattern {
private final TokenStreamPredicate lookFor;
private final TokenStreamPredicate stopAt;
public FirstBefore(TokenStreamPredicate lookFor, TokenStreamPredicate stopAt) {
this.lookFor = lookFor;
this.stopAt = stopAt;
}
@Override
public boolean processToken(int offset, boolean topLevel) {
if (lookFor.matching(topLevel)) {
lastOccurrence = offset;
return true;
}
if (stopAt.matching(topLevel)) {
return true;
}
return false;
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,18 @@
/*
* @author max
*/
package org.jetbrains.jet.lang.parsing;
import com.intellij.lang.ASTNode;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.PsiParser;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
public class JetParser implements PsiParser {
@NotNull
public ASTNode parse(IElementType iElementType, PsiBuilder psiBuilder) {
JetParsing.createForTopLevel(new SemanticWhitespaceAwarePsiBuilderImpl(psiBuilder)).parseFile();
return psiBuilder.getTreeBuilt();
}
}
@@ -0,0 +1,65 @@
/*
* @author max
*/
package org.jetbrains.jet.lang.parsing;
import com.intellij.extapi.psi.ASTWrapperPsiElement;
import com.intellij.lang.ASTNode;
import com.intellij.lang.ParserDefinition;
import com.intellij.lang.PsiParser;
import com.intellij.lexer.Lexer;
import com.intellij.openapi.project.Project;
import com.intellij.psi.FileViewProvider;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.tree.IFileElementType;
import com.intellij.psi.tree.TokenSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetNodeType;
import org.jetbrains.jet.JetNodeTypes;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lexer.JetLexer;
import org.jetbrains.jet.lexer.JetTokens;
public class JetParserDefinition implements ParserDefinition {
@NotNull
public Lexer createLexer(Project project) {
return new JetLexer();
}
public PsiParser createParser(Project project) {
return new JetParser();
}
public IFileElementType getFileNodeType() {
return JetNodeTypes.JET_FILE;
}
@NotNull
public TokenSet getWhitespaceTokens() {
return JetTokens.WHITESPACES;
}
@NotNull
public TokenSet getCommentTokens() {
return JetTokens.COMMENTS;
}
@NotNull
public TokenSet getStringLiteralElements() {
return JetTokens.STRINGS;
}
@NotNull
public PsiElement createElement(ASTNode astNode) {
return ((JetNodeType) astNode.getElementType()).createPsi(astNode);
}
public PsiFile createFile(FileViewProvider fileViewProvider) {
return new JetFile(fileViewProvider);
}
public SpaceRequirements spaceExistanceTypeBetweenTokens(ASTNode astNode, ASTNode astNode1) {
return SpaceRequirements.MAY;
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,37 @@
package org.jetbrains.jet.lang.parsing;
/**
* @author abreslav
*/
public class LastBefore extends AbstractTokenStreamPattern {
private final boolean dontStopRightAfterOccurrence;
private final TokenStreamPredicate lookFor;
private final TokenStreamPredicate stopAt;
private boolean previousLookForResult;
public LastBefore(TokenStreamPredicate lookFor, TokenStreamPredicate stopAt, boolean dontStopRightAfterOccurrence) {
this.lookFor = lookFor;
this.stopAt = stopAt;
this.dontStopRightAfterOccurrence = dontStopRightAfterOccurrence;
}
public LastBefore(TokenStreamPredicate lookFor, TokenStreamPredicate stopAt) {
this(lookFor, stopAt, false);
}
@Override
public boolean processToken(int offset, boolean topLevel) {
boolean lookForResult = lookFor.matching(topLevel);
if (lookForResult) {
lastOccurrence = offset;
}
if (stopAt.matching(topLevel)) {
if (topLevel
&& (!dontStopRightAfterOccurrence
|| !previousLookForResult)) return true;
}
previousLookForResult = lookForResult;
return false;
}
}
@@ -0,0 +1,68 @@
package org.jetbrains.jet.lang.parsing;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.WhitespacesAndCommentsBinder;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.Nullable;
/**
* @author abreslav
*/
public class MarkerAdapter implements PsiBuilder.Marker {
private final PsiBuilder.Marker delegate;
public MarkerAdapter(PsiBuilder.Marker delegate) {
this.delegate = delegate;
}
@Override
public PsiBuilder.Marker precede() {
return delegate.precede();
}
@Override
public void drop() {
delegate.drop();
}
@Override
public void rollbackTo() {
delegate.rollbackTo();
}
@Override
public void done(IElementType type) {
delegate.done(type);
}
@Override
public void collapse(IElementType type) {
delegate.collapse(type);
}
@Override
public void doneBefore(IElementType type, PsiBuilder.Marker before) {
delegate.doneBefore(type, before);
}
@Override
public void doneBefore(IElementType type, PsiBuilder.Marker before, String errorMessage) {
delegate.doneBefore(type, before, errorMessage);
}
@Override
public void error(String message) {
delegate.error(message);
}
@Override
public void errorBefore(String message, PsiBuilder.Marker before) {
delegate.errorBefore(message, before);
}
@Override
public void setCustomEdgeTokenBinders(@Nullable WhitespacesAndCommentsBinder left, @Nullable WhitespacesAndCommentsBinder right) {
delegate.setCustomEdgeTokenBinders(left, right);
}
}
@@ -0,0 +1,15 @@
package org.jetbrains.jet.lang.parsing;
import com.intellij.lang.PsiBuilder;
/**
* @author abreslav
*/
public interface SemanticWhitespaceAwarePsiBuilder extends PsiBuilder {
// TODO: comments go to wrong place when an empty element is created, see IElementType.isLeftBound()
boolean newlineBeforeCurrentToken();
void disableNewlines();
void enableNewlines();
void restoreNewlinesState();
}

Some files were not shown because too many files have changed in this diff Show More