"compiler" folder created
This commit is contained in:
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
+37
@@ -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);
|
||||
}
|
||||
}
|
||||
+58
@@ -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() + ")";
|
||||
}
|
||||
}
|
||||
+34
@@ -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);
|
||||
}
|
||||
}
|
||||
+20
@@ -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);
|
||||
}
|
||||
+283
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+12
@@ -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();
|
||||
}
|
||||
+21
@@ -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);
|
||||
}
|
||||
+43
@@ -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 + ";");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+24
@@ -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() + ")";
|
||||
}
|
||||
}
|
||||
+34
@@ -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();
|
||||
}
|
||||
}
|
||||
+35
@@ -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;
|
||||
}
|
||||
}
|
||||
+30
@@ -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>";
|
||||
}
|
||||
}
|
||||
+40
@@ -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;
|
||||
}
|
||||
}
|
||||
+25
@@ -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() + ")";
|
||||
}
|
||||
|
||||
}
|
||||
+24
@@ -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() + ")";
|
||||
}
|
||||
}
|
||||
+32
@@ -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() + ")";
|
||||
}
|
||||
}
|
||||
+39
@@ -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<T> for the class A<T>
|
||||
*/
|
||||
@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 "<init>" -- name is not stored for constructors
|
||||
*/
|
||||
@NotNull
|
||||
@Override
|
||||
String getName();
|
||||
|
||||
boolean isPrimary();
|
||||
}
|
||||
+81
@@ -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);
|
||||
}
|
||||
+51
@@ -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)) + "]";
|
||||
}
|
||||
}
|
||||
+62
@@ -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();
|
||||
}
|
||||
+173
@@ -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
|
||||
}
|
||||
}
|
||||
+54
@@ -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) + "]";
|
||||
}
|
||||
}
|
||||
+51
@@ -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);
|
||||
}
|
||||
}
|
||||
+11
@@ -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);
|
||||
}
|
||||
+63
@@ -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;
|
||||
}
|
||||
}
|
||||
+56
@@ -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);
|
||||
}
|
||||
}
|
||||
+66
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
+160
@@ -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;
|
||||
}
|
||||
}
|
||||
+26
@@ -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();
|
||||
}
|
||||
+104
@@ -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;
|
||||
}
|
||||
}
|
||||
+34
@@ -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();
|
||||
}
|
||||
+19
@@ -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;
|
||||
}
|
||||
}
|
||||
+31
@@ -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);
|
||||
}
|
||||
+33
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+18
@@ -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);
|
||||
}
|
||||
}
|
||||
+15
@@ -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
Reference in New Issue
Block a user