diff options
Diffstat (limited to 'examples/scala-js/ir/src')
15 files changed, 0 insertions, 3870 deletions
diff --git a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/ClassKind.scala b/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/ClassKind.scala deleted file mode 100644 index 5092d2c..0000000 --- a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/ClassKind.scala +++ /dev/null @@ -1,53 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ __ ____ Scala.js IR ** -** / __/ __// _ | / / / _ | __ / // __/ (c) 2014, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ ** -** /____/\___/_/ |_/____/_/ | |__/ /____/ ** -** |/____/ ** -\* */ - - -package scala.scalajs.ir - -import scala.annotation.switch - -sealed abstract class ClassKind { - import ClassKind._ - - def isClass = this match { - case Class | ModuleClass => true - case _ => false - } - - def isType = this match { - case TraitImpl => false - case _ => true - } -} - -object ClassKind { - case object Class extends ClassKind - case object ModuleClass extends ClassKind - case object Interface extends ClassKind - case object RawJSType extends ClassKind - case object HijackedClass extends ClassKind - case object TraitImpl extends ClassKind - - private[ir] def toByte(kind: ClassKind): Byte = kind match { - case ClassKind.Class => 1 - case ClassKind.ModuleClass => 2 - case ClassKind.Interface => 3 - case ClassKind.RawJSType => 4 - case ClassKind.HijackedClass => 5 - case ClassKind.TraitImpl => 6 - } - - private[ir] def fromByte(b: Byte): ClassKind = (b: @switch) match { - case 1 => ClassKind.Class - case 2 => ClassKind.ModuleClass - case 3 => ClassKind.Interface - case 4 => ClassKind.RawJSType - case 5 => ClassKind.HijackedClass - case 6 => ClassKind.TraitImpl - } -} diff --git a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Definitions.scala b/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Definitions.scala deleted file mode 100644 index 0762602..0000000 --- a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Definitions.scala +++ /dev/null @@ -1,144 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ __ ____ Scala.js IR ** -** / __/ __// _ | / / / _ | __ / // __/ (c) 2014, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ ** -** /____/\___/_/ |_/____/_/ | |__/ /____/ ** -** |/____/ ** -\* */ - - -package scala.scalajs.ir - -object Definitions { - val ObjectClass = "O" - val ClassClass = "jl_Class" - - val StringClass = "T" - - val PrimitiveClasses = Set("V", "Z", "C", "B", "S", "I", "J", "F", "D") - - def isPrimitiveClass(encodedName: String): Boolean = - PrimitiveClasses.contains(encodedName) - - val BoxedUnitClass = "sr_BoxedUnit" - val BoxedBooleanClass = "jl_Boolean" - val BoxedCharacterClass = "jl_Character" - val BoxedByteClass = "jl_Byte" - val BoxedShortClass = "jl_Short" - val BoxedIntegerClass = "jl_Integer" - val BoxedLongClass = "jl_Long" - val BoxedFloatClass = "jl_Float" - val BoxedDoubleClass = "jl_Double" - - val CharSequenceClass = "jl_CharSequence" - val SerializableClass = "Ljava_io_Serializable" - val ComparableClass = "jl_Comparable" - val NumberClass = "jl_Number" - - val HijackedBoxedClasses = Set( - BoxedUnitClass, BoxedBooleanClass, BoxedByteClass, BoxedShortClass, - BoxedIntegerClass, BoxedLongClass, BoxedFloatClass, BoxedDoubleClass) - val HijackedClasses = - HijackedBoxedClasses + StringClass - - val AncestorsOfStringClass = Set( - CharSequenceClass, ComparableClass, SerializableClass) - val AncestorsOfHijackedNumberClasses = Set( - NumberClass, ComparableClass, SerializableClass) - val AncestorsOfBoxedBooleanClass = Set( - ComparableClass, SerializableClass) - - val AncestorsOfHijackedClasses = - AncestorsOfStringClass ++ AncestorsOfHijackedNumberClasses ++ - AncestorsOfBoxedBooleanClass - - val RuntimeNullClass = "sr_Null$" - val RuntimeNothingClass = "sr_Nothing$" - - val ThrowableClass = "jl_Throwable" - - /** Encodes a class name. */ - def encodeClassName(fullName: String): String = { - val base = fullName.replace("_", "$und").replace(".", "_") - val encoded = compressedClasses.getOrElse(base, { - compressedPrefixes collectFirst { - case (prefix, compressed) if base.startsWith(prefix) => - compressed + base.substring(prefix.length) - } getOrElse { - "L"+base - } - }) - if (Trees.isKeyword(encoded) || encoded.charAt(0).isDigit || - encoded.charAt(0) == '$') { - "$" + encoded - } else encoded - } - - // !!! Duplicate logic: this code must be in sync with runtime.StackTrace - - /** Decodes a class name encoded with [[encodeClassName]]. */ - def decodeClassName(encodedName: String): String = { - val encoded = - if (encodedName.charAt(0) == '$') encodedName.substring(1) - else encodedName - val base = decompressedClasses.getOrElse(encoded, { - decompressedPrefixes collectFirst { - case (prefix, decompressed) if encoded.startsWith(prefix) => - decompressed + encoded.substring(prefix.length) - } getOrElse { - assert(!encoded.isEmpty && encoded.charAt(0) == 'L', - s"Cannot decode invalid encoded name '$encodedName'") - encoded.substring(1) - } - }) - base.replace("_", ".").replace("$und", "_") - } - - private val compressedClasses: Map[String, String] = Map( - "java_lang_Object" -> "O", - "java_lang_String" -> "T", - "scala_Unit" -> "V", - "scala_Boolean" -> "Z", - "scala_Char" -> "C", - "scala_Byte" -> "B", - "scala_Short" -> "S", - "scala_Int" -> "I", - "scala_Long" -> "J", - "scala_Float" -> "F", - "scala_Double" -> "D" - ) ++ ( - for (index <- 2 to 22) - yield s"scala_Tuple$index" -> ("T"+index) - ) ++ ( - for (index <- 0 to 22) - yield s"scala_Function$index" -> ("F"+index) - ) - - private val decompressedClasses: Map[String, String] = - compressedClasses map { case (a, b) => (b, a) } - - private val compressedPrefixes = Seq( - "scala_scalajs_runtime_" -> "sjsr_", - "scala_scalajs_" -> "sjs_", - "scala_collection_immutable_" -> "sci_", - "scala_collection_mutable_" -> "scm_", - "scala_collection_generic_" -> "scg_", - "scala_collection_" -> "sc_", - "scala_runtime_" -> "sr_", - "scala_" -> "s_", - "java_lang_" -> "jl_", - "java_util_" -> "ju_" - ) - - private val decompressedPrefixes: Seq[(String, String)] = - compressedPrefixes map { case (a, b) => (b, a) } - - /* Common predicates on encoded names */ - - def isConstructorName(name: String): Boolean = - name.startsWith("init___") - - def isReflProxyName(name: String): Boolean = - name.endsWith("__") && !isConstructorName(name) - -} diff --git a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Hashers.scala b/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Hashers.scala deleted file mode 100644 index 168d7c1..0000000 --- a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Hashers.scala +++ /dev/null @@ -1,459 +0,0 @@ -package scala.scalajs.ir - -import java.security.{MessageDigest, DigestOutputStream} -import java.io.{OutputStream, DataOutputStream} -import java.util.Arrays - -import Trees._ -import Types._ -import Tags._ - -object Hashers { - - def hashMethodDef(methodDef: MethodDef): MethodDef = { - if (methodDef.hash.isDefined) methodDef - else { - val hasher = new TreeHasher() - val MethodDef(name, args, resultType, body) = methodDef - - hasher.mixPos(methodDef.pos) - hasher.mixPropertyName(name) - hasher.mixTrees(args) - hasher.mixType(resultType) - hasher.mixTree(body) - - val hash = hasher.finalizeHash() - - MethodDef(name, args, resultType, body)(Some(hash))(methodDef.pos) - } - } - - /** Hash definitions from a ClassDef where applicable */ - def hashDefs(defs: List[Tree]): List[Tree] = defs map { - case methodDef: MethodDef => hashMethodDef(methodDef) - case otherDef => otherDef - } - - /** Hash the definitions in a ClassDef (where applicable) */ - def hashClassDef(classDef: ClassDef): ClassDef = - classDef.copy(defs = hashDefs(classDef.defs))(classDef.pos) - - def hashesEqual(x: TreeHash, y: TreeHash, considerPos: Boolean): Boolean = { - Arrays.equals(x.treeHash, y.treeHash) && - (!considerPos || Arrays.equals(x.posHash, y.posHash)) - } - - private final class TreeHasher { - private def newDigest = MessageDigest.getInstance("SHA-1") - private def newDigestStream(digest: MessageDigest) = { - val out = new OutputStream { - def write(b: Int): Unit = () - } - val digOut = new DigestOutputStream(out, digest) - new DataOutputStream(digOut) - } - - private[this] val treeDigest = newDigest - private[this] val treeStream = newDigestStream(treeDigest) - - private[this] val posDigest = newDigest - private[this] val posStream = newDigestStream(posDigest) - - def finalizeHash(): TreeHash = - new TreeHash(treeDigest.digest(), posDigest.digest()) - - def mixTree(tree: Tree): Unit = { - mixPos(tree.pos) - tree match { - case EmptyTree => - mixTag(TagEmptyTree) - - case VarDef(ident, vtpe, mutable, rhs) => - mixTag(TagVarDef) - mixIdent(ident) - mixType(vtpe) - mixBoolean(mutable) - mixTree(rhs) - - case ParamDef(ident, ptpe, mutable) => - mixTag(TagParamDef) - mixIdent(ident) - mixType(ptpe) - mixBoolean(mutable) - - case Skip() => - mixTag(TagSkip) - - case Block(stats) => - mixTag(TagBlock) - mixTrees(stats) - - case Labeled(label, tpe, body) => - mixTag(TagLabeled) - mixIdent(label) - mixType(tpe) - mixTree(body) - - case Assign(lhs, rhs) => - mixTag(TagAssign) - mixTree(lhs) - mixTree(rhs) - - case Return(expr, label) => - mixTag(TagReturn) - mixTree(expr) - mixOptIdent(label) - - case If(cond, thenp, elsep) => - mixTag(TagIf) - mixTree(cond) - mixTree(thenp) - mixTree(elsep) - mixType(tree.tpe) - - case While(cond, body, label) => - mixTag(TagWhile) - mixTree(cond) - mixTree(body) - mixOptIdent(label) - - case DoWhile(body, cond, label) => - mixTag(TagDoWhile) - mixTree(body) - mixTree(cond) - mixOptIdent(label) - - case Try(block, errVar, handler, finalizer) => - mixTag(TagTry) - mixTree(block) - mixIdent(errVar) - mixTree(handler) - mixTree(finalizer) - mixType(tree.tpe) - - case Throw(expr) => - mixTag(TagThrow) - mixTree(expr) - - case Continue(label) => - mixTag(TagContinue) - mixOptIdent(label) - - case Match(selector, cases, default) => - mixTag(TagMatch) - mixTree(selector) - cases foreach { case (patterns, body) => - mixTrees(patterns) - mixTree(body) - } - mixTree(default) - mixType(tree.tpe) - - case Debugger() => - mixTag(TagDebugger) - - case New(cls, ctor, args) => - mixTag(TagNew) - mixType(cls) - mixIdent(ctor) - mixTrees(args) - - case LoadModule(cls) => - mixTag(TagLoadModule) - mixType(cls) - - case StoreModule(cls, value) => - mixTag(TagStoreModule) - mixType(cls) - mixTree(value) - - case Select(qualifier, item, mutable) => - mixTag(TagSelect) - mixTree(qualifier) - mixIdent(item) - mixBoolean(mutable) - mixType(tree.tpe) - - case Apply(receiver, method, args) => - mixTag(TagApply) - mixTree(receiver) - mixIdent(method) - mixTrees(args) - mixType(tree.tpe) - - case StaticApply(receiver, cls, method, args) => - mixTag(TagStaticApply) - mixTree(receiver) - mixType(cls) - mixIdent(method) - mixTrees(args) - mixType(tree.tpe) - - case TraitImplApply(impl, method, args) => - mixTag(TagTraitImplApply) - mixType(impl) - mixIdent(method) - mixTrees(args) - mixType(tree.tpe) - - case UnaryOp(op, lhs) => - mixTag(TagUnaryOp) - mixInt(op) - mixTree(lhs) - - case BinaryOp(op, lhs, rhs) => - mixTag(TagBinaryOp) - mixInt(op) - mixTree(lhs) - mixTree(rhs) - - case NewArray(tpe, lengths) => - mixTag(TagNewArray) - mixType(tpe) - mixTrees(lengths) - - case ArrayValue(tpe, elems) => - mixTag(TagArrayValue) - mixType(tpe) - mixTrees(elems) - - case ArrayLength(array) => - mixTag(TagArrayLength) - mixTree(array) - - case ArraySelect(array, index) => - mixTag(TagArraySelect) - mixTree(array) - mixTree(index) - mixType(tree.tpe) - - case RecordValue(tpe, elems) => - mixTag(TagRecordValue) - mixType(tpe) - mixTrees(elems) - - case IsInstanceOf(expr, cls) => - mixTag(TagIsInstanceOf) - mixTree(expr) - mixType(cls) - - case AsInstanceOf(expr, cls) => - mixTag(TagAsInstanceOf) - mixTree(expr) - mixType(cls) - - case Unbox(expr, charCode) => - mixTag(TagUnbox) - mixTree(expr) - mixInt(charCode) - - case GetClass(expr) => - mixTag(TagGetClass) - mixTree(expr) - - case CallHelper(helper, args) => - mixTag(TagCallHelper) - mixString(helper) - mixTrees(args) - mixType(tree.tpe) - - case JSNew(ctor, args) => - mixTag(TagJSNew) - mixTree(ctor) - mixTrees(args) - - case JSDotSelect(qualifier, item) => - mixTag(TagJSDotSelect) - mixTree(qualifier) - mixIdent(item) - - case JSBracketSelect(qualifier, item) => - mixTag(TagJSBracketSelect) - mixTree(qualifier) - mixTree(item) - - case JSFunctionApply(fun, args) => - mixTag(TagJSFunctionApply) - mixTree(fun) - mixTrees(args) - - case JSDotMethodApply(receiver, method, args) => - mixTag(TagJSDotMethodApply) - mixTree(receiver) - mixIdent(method) - mixTrees(args) - - case JSBracketMethodApply(receiver, method, args) => - mixTag(TagJSBracketMethodApply) - mixTree(receiver) - mixTree(method) - mixTrees(args) - - case JSDelete(prop) => - mixTag(TagJSDelete) - mixTree(prop) - - case JSUnaryOp(op, lhs) => - mixTag(TagJSUnaryOp) - mixString(op) - mixTree(lhs) - - case JSBinaryOp(op, lhs, rhs) => - mixTag(TagJSBinaryOp) - mixString(op) - mixTree(lhs) - mixTree(rhs) - - case JSArrayConstr(items) => - mixTag(TagJSArrayConstr) - mixTrees(items) - - case JSObjectConstr(fields) => - mixTag(TagJSObjectConstr) - fields foreach { case (pn, value) => - mixPropertyName(pn) - mixTree(value) - } - - case JSEnvInfo() => - mixTag(TagJSEnvInfo) - - case Undefined() => - mixTag(TagUndefined) - - case UndefinedParam() => - mixTag(TagUndefinedParam) - mixType(tree.tpe) - - case Null() => - mixTag(TagNull) - - case BooleanLiteral(value) => - mixTag(TagBooleanLiteral) - mixBoolean(value) - - case IntLiteral(value) => - mixTag(TagIntLiteral) - mixInt(value) - - case LongLiteral(value) => - mixTag(TagLongLiteral) - mixLong(value) - - case FloatLiteral(value) => - mixTag(TagFloatLiteral) - mixFloat(value) - - case DoubleLiteral(value) => - mixTag(TagDoubleLiteral) - mixDouble(value) - - case StringLiteral(value) => - mixTag(TagStringLiteral) - mixString(value) - - case ClassOf(cls) => - mixTag(TagClassOf) - mixType(cls) - - case VarRef(ident, mutable) => - mixTag(TagVarRef) - mixIdent(ident) - mixBoolean(mutable) - mixType(tree.tpe) - - case This() => - mixTag(TagThis) - mixType(tree.tpe) - - case Closure(captureParams, params, body, captureValues) => - mixTag(TagClosure) - mixTrees(captureParams) - mixTrees(params) - mixTree(body) - mixTrees(captureValues) - - case _ => - sys.error(s"Unable to hash tree of class ${tree.getClass}") - - } - } - - def mixTrees(trees: List[Tree]): Unit = - trees.foreach(mixTree) - - def mixType(tpe: Type): Unit = tpe match { - case AnyType => mixTag(TagAnyType) - case NothingType => mixTag(TagNothingType) - case UndefType => mixTag(TagUndefType) - case BooleanType => mixTag(TagBooleanType) - case IntType => mixTag(TagIntType) - case LongType => mixTag(TagLongType) - case FloatType => mixTag(TagFloatType) - case DoubleType => mixTag(TagDoubleType) - case StringType => mixTag(TagStringType) - case NullType => mixTag(TagNullType) - case NoType => mixTag(TagNoType) - - case tpe: ClassType => - mixTag(TagClassType) - mixString(tpe.className) - - case tpe: ArrayType => - mixTag(TagArrayType) - mixString(tpe.baseClassName) - mixInt(tpe.dimensions) - - case RecordType(fields) => - mixTag(TagRecordType) - for (RecordType.Field(name, originalName, tpe, mutable) <- fields) { - mixString(name) - originalName.foreach(mixString) - mixType(tpe) - mixBoolean(mutable) - } - } - - def mixIdent(ident: Ident): Unit = { - mixPos(ident.pos) - mixString(ident.name) - ident.originalName.foreach(mixString) - } - - def mixOptIdent(optIdent: Option[Ident]): Unit = optIdent.foreach(mixIdent) - - def mixPropertyName(name: PropertyName): Unit = name match { - case name: Ident => mixIdent(name) - case name: StringLiteral => mixTree(name) - } - - def mixPos(pos: Position): Unit = { - posStream.writeUTF(pos.source.toString) - posStream.writeInt(pos.line) - posStream.writeInt(pos.column) - } - - @inline - private final def mixTag(tag: Int): Unit = mixInt(tag) - - @inline - private final def mixString(str: String): Unit = treeStream.writeUTF(str) - - @inline - private final def mixInt(i: Int): Unit = treeStream.writeInt(i) - - @inline - private final def mixLong(l: Long): Unit = treeStream.writeLong(l) - - @inline - private final def mixBoolean(b: Boolean): Unit = treeStream.writeBoolean(b) - - @inline - private final def mixFloat(f: Float): Unit = treeStream.writeFloat(f) - - @inline - private final def mixDouble(d: Double): Unit = treeStream.writeDouble(d) - - } - -} diff --git a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/InfoSerializers.scala b/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/InfoSerializers.scala deleted file mode 100644 index dfb520f..0000000 --- a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/InfoSerializers.scala +++ /dev/null @@ -1,180 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ __ ____ Scala.js IR ** -** / __/ __// _ | / / / _ | __ / // __/ (c) 2014, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ ** -** /____/\___/_/ |_/____/_/ | |__/ /____/ ** -** |/____/ ** -\* */ - - -package scala.scalajs.ir - -import java.io._ - -import Infos._ - -object InfoSerializers { - - /** Scala.js IR File Magic Number - * - * CA FE : first part of magic number of Java class files - * 4A 53 : "JS" in ASCII - * - */ - final val IRMagicNumber = 0xCAFE4A53 - - def serialize(stream: OutputStream, classInfo: ClassInfo): Unit = { - new Serializer().serialize(stream, classInfo) - } - - def deserializeRoughInfo(stream: InputStream): RoughClassInfo = { - deserializeVersionRoughInfo(stream)._2 - } - - def deserializeFullInfo(stream: InputStream): ClassInfo = { - deserializeVersionFullInfo(stream)._2 - } - - def deserializeVersionRoughInfo(stream: InputStream): (String, RoughClassInfo) = { - new Deserializer(stream).deserializeRough() - } - - def deserializeVersionFullInfo(stream: InputStream): (String, ClassInfo) = { - new Deserializer(stream).deserializeFull() - } - - private final class Serializer { - def serialize(stream: OutputStream, classInfo: ClassInfo): Unit = { - val s = new DataOutputStream(stream) - - def writeSeq[A](seq: Seq[A])(writeElem: A => Unit): Unit = { - s.writeInt(seq.size) - seq.foreach(writeElem) - } - - def writeStrings(seq: Seq[String]): Unit = - writeSeq(seq)(s.writeUTF(_)) - - // Write the Scala.js IR magic number - s.writeInt(IRMagicNumber) - - // Write the Scala.js Version - s.writeUTF(ScalaJSVersions.binaryEmitted) - - import classInfo._ - s.writeUTF(name) - s.writeUTF(encodedName) - s.writeBoolean(isExported) - s.writeInt(ancestorCount) - s.writeByte(ClassKind.toByte(kind)) - s.writeUTF(superClass) - writeStrings(ancestors) - s.writeInt(optimizerHints.bits) - - def writeMethodInfo(methodInfo: MethodInfo): Unit = { - import methodInfo._ - s.writeUTF(encodedName) - s.writeBoolean(isAbstract) - s.writeBoolean(isExported) - writeSeq(calledMethods.toSeq) { - case (caller, callees) => s.writeUTF(caller); writeStrings(callees) - } - writeSeq(calledMethodsStatic.toSeq) { - case (caller, callees) => s.writeUTF(caller); writeStrings(callees) - } - writeStrings(instantiatedClasses) - writeStrings(accessedModules) - writeStrings(accessedClassData) - s.writeInt(optimizerHints.bits) - } - - writeSeq(methods)(writeMethodInfo(_)) - - s.flush() - } - } - - private final class Deserializer(stream: InputStream) { - private[this] val input = new DataInputStream(stream) - - def readList[A](readElem: => A): List[A] = - List.fill(input.readInt())(readElem) - - def readStrings(): List[String] = - readList(input.readUTF()) - - def deserializeRough(): (String, RoughClassInfo) = { - val version = readHeader() - - import input._ - val name = readUTF() - val encodedName = readUTF() - val isExported = readBoolean() - val ancestorCount = readInt() - val info = RoughClassInfo(name, encodedName, isExported, ancestorCount) - - (version, info) - } - - def deserializeFull(): (String, ClassInfo) = { - val version = readHeader() - - import input._ - - val name = readUTF() - val encodedName = readUTF() - val isExported = readBoolean() - val ancestorCount = readInt() - val kind = ClassKind.fromByte(readByte()) - val superClass = readUTF() - val ancestors = readList(readUTF()) - - val optimizerHints = - if (version == "0.5.0" || version == "0.5.2") OptimizerHints.empty - else new OptimizerHints(readInt()) - - def readMethod(): MethodInfo = { - val encodedName = readUTF() - val isAbstract = readBoolean() - val isExported = readBoolean() - val calledMethods = readList(readUTF() -> readStrings()).toMap - val calledMethodsStatic = readList(readUTF() -> readStrings()).toMap - val instantiatedClasses = readStrings() - val accessedModules = readStrings() - val accessedClassData = readStrings() - val optimizerHints = new OptimizerHints(readInt()) - MethodInfo(encodedName, isAbstract, isExported, - calledMethods, calledMethodsStatic, - instantiatedClasses, accessedModules, accessedClassData, - optimizerHints) - } - - val methods = readList(readMethod()) - - val info = ClassInfo(name, encodedName, isExported, ancestorCount, kind, - superClass, ancestors, optimizerHints, methods) - - (version, info) - } - - /** Reads the Scala.js IR header and verifies the version compatibility. - * Returns the emitted binary version. - */ - def readHeader(): String = { - // Check magic number - if (input.readInt() != IRMagicNumber) - throw new IOException("Not a Scala.js IR file") - - // Check that we support this version of the IR - val version = input.readUTF() - val supported = ScalaJSVersions.binarySupported - if (!supported.contains(version)) { - throw new IOException( - s"This version ($version) of Scala.js IR is not supported. " + - s"Supported versions are: ${supported.mkString(", ")}") - } - - version - } - } -} diff --git a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Infos.scala b/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Infos.scala deleted file mode 100644 index 66feec2..0000000 --- a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Infos.scala +++ /dev/null @@ -1,118 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ __ ____ Scala.js IR ** -** / __/ __// _ | / / / _ | __ / // __/ (c) 2014, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ ** -** /____/\___/_/ |_/____/_/ | |__/ /____/ ** -** |/____/ ** -\* */ - - -package scala.scalajs.ir - -object Infos { - - sealed class RoughClassInfo protected ( - val name: String, - val encodedName: String, - val isExported: Boolean, - val ancestorCount: Int - ) - - object RoughClassInfo { - def apply(name: String, encodedName: String, isExported: Boolean, - ancestorCount: Int): RoughClassInfo = { - new RoughClassInfo(name, encodedName, isExported, ancestorCount) - } - } - - final class ClassInfo protected ( - name: String, - encodedName: String, - isExported: Boolean, - ancestorCount: Int, - val kind: ClassKind, - val superClass: String, - val ancestors: List[String], // includes this class - val optimizerHints: OptimizerHints, - val methods: List[MethodInfo] - ) extends RoughClassInfo(name, encodedName, isExported, ancestorCount) - - object ClassInfo { - def apply( - name: String, - encodedName: String, - isExported: Boolean = false, - ancestorCount: Int = 0, - kind: ClassKind = ClassKind.Class, - superClass: String = "", - ancestors: List[String] = Nil, - optimizerHints: OptimizerHints = OptimizerHints.empty, - methods: List[MethodInfo] = Nil): ClassInfo = { - new ClassInfo(name, encodedName, isExported, ancestorCount, - kind, superClass, ancestors, optimizerHints, methods) - } - } - - final class MethodInfo private ( - val encodedName: String, - val isAbstract: Boolean, - val isExported: Boolean, - val calledMethods: Map[String, List[String]], - val calledMethodsStatic: Map[String, List[String]], - val instantiatedClasses: List[String], - val accessedModules: List[String], - val accessedClassData: List[String], - val optimizerHints: OptimizerHints - ) - - object MethodInfo { - def apply( - encodedName: String, - isAbstract: Boolean = false, - isExported: Boolean = false, - calledMethods: Map[String, List[String]] = Map.empty, - calledMethodsStatic: Map[String, List[String]] = Map.empty, - instantiatedClasses: List[String] = Nil, - accessedModules: List[String] = Nil, - accessedClassData: List[String] = Nil, - optimizerHints: OptimizerHints = OptimizerHints.empty): MethodInfo = { - new MethodInfo(encodedName, isAbstract, isExported, calledMethods, - calledMethodsStatic, instantiatedClasses, accessedModules, - accessedClassData, optimizerHints) - } - } - - final class OptimizerHints(val bits: Int) extends AnyVal { - import OptimizerHints._ - - private[scalajs] def isAccessor: Boolean = (bits & AccessorMask) != 0 - private[scalajs] def hasInlineAnnot: Boolean = (bits & InlineAnnotMask) != 0 - - private[scalajs] def copy( - isAccessor: Boolean = this.isAccessor, - hasInlineAnnot: Boolean = this.hasInlineAnnot - ): OptimizerHints = { - var bits: Int = 0 - if (isAccessor) - bits |= AccessorMask - if (hasInlineAnnot) - bits |= InlineAnnotMask - new OptimizerHints(bits) - } - - override def toString(): String = - s"OptimizerHints($bits)" - } - - object OptimizerHints { - private final val AccessorShift = 0 - private final val AccessorMask = 1 << AccessorShift - - private final val InlineAnnotShift = 1 - private final val InlineAnnotMask = 1 << InlineAnnotShift - - final val empty: OptimizerHints = - new OptimizerHints(0) - } - -} diff --git a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Position.scala b/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Position.scala deleted file mode 100644 index 3b6d0a2..0000000 --- a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Position.scala +++ /dev/null @@ -1,42 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ __ ____ Scala.js IR ** -** / __/ __// _ | / / / _ | __ / // __/ (c) 2014, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ ** -** /____/\___/_/ |_/____/_/ | |__/ /____/ ** -** |/____/ ** -\* */ - - -package scala.scalajs.ir - -final case class Position( - /** Source file. */ - source: Position.SourceFile, - /** Zero-based line number. */ - line: Int, - /** Zero-based column number. */ - column: Int -) { - def show: String = s"$line:$column" - - def isEmpty: Boolean = { - source.getScheme == null && source.getRawAuthority == null && - source.getRawPath == "" && source.getRawQuery == null && - source.getRawFragment == null - } - - def isDefined: Boolean = !isEmpty - - def orElse(that: => Position): Position = if (isDefined) this else that -} - -object Position { - type SourceFile = java.net.URI - - object SourceFile { - def apply(f: java.io.File): SourceFile = f.toURI - def apply(f: String): SourceFile = new java.net.URI(f) - } - - val NoPosition = Position(SourceFile(""), 0, 0) -} diff --git a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Printers.scala b/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Printers.scala deleted file mode 100644 index 6208d5f..0000000 --- a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Printers.scala +++ /dev/null @@ -1,709 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ __ ____ Scala.js IR ** -** / __/ __// _ | / / / _ | __ / // __/ (c) 2014, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ ** -** /____/\___/_/ |_/____/_/ | |__/ /____/ ** -** |/____/ ** -\* */ - - -package scala.scalajs.ir - -import scala.annotation.{switch, tailrec} - -import java.io.Writer - -import Position._ -import Trees._ -import Types._ -import Infos._ -import Utils.escapeJS - -object Printers { - - /** Basically copied from scala.reflect.internal.Printers */ - trait IndentationManager { - protected val out: Writer - - protected var indentMargin = 0 - protected val indentStep = 2 - protected var indentString = " " // 40 - - protected def indent(): Unit = indentMargin += indentStep - protected def undent(): Unit = indentMargin -= indentStep - - protected def println(): Unit = { - out.write('\n') - while (indentMargin > indentString.length()) - indentString += indentString - if (indentMargin > 0) - out.write(indentString, 0, indentMargin) - } - - @tailrec - protected final def printSeq[A](ls: List[A])(printelem: A => Unit)( - printsep: A => Unit): Unit = { - ls match { - case Nil => - case x :: Nil => - printelem(x) - case x :: rest => - printelem(x) - printsep(x) - printSeq(rest)(printelem)(printsep) - } - } - - protected def printColumn(ts: List[Any], start: String, sep: String, - end: String): Unit = { - print(start); indent(); println() - printSeq(ts) { x => - print(x) - } { _ => - print(sep) - println() - } - undent(); println(); print(end) - } - - protected def printRow(ts: List[Any], start: String, sep: String, - end: String): Unit = { - print(start) - printSeq(ts) { x => - print(x) - } { _ => - print(sep) - } - print(end) - } - - protected def printRow(ts: List[Any], sep: String): Unit = - printRow(ts, "", sep, "") - - protected def print(args: Any*): Unit = - args.foreach(printOne) - - protected def printOne(arg: Any): Unit - } - - class IRTreePrinter(protected val out: Writer) extends IndentationManager { - def printTopLevelTree(tree: Tree) { - tree match { - case Skip() => - // do not print anything - case Block(stats) => - for (stat <- stats) - printTopLevelTree(stat) - case _ => - printTree(tree) - println() - } - } - - protected def printBlock(tree: Tree): Unit = { - val trees = tree match { - case Block(trees) => trees - case _ => List(tree) - } - printColumn(trees, "{", ";", "}") - } - - protected def printSig(args: List[ParamDef], resultType: Type): Unit = { - printRow(args, "(", ", ", ")") - if (resultType != NoType) - print(": ", resultType, " = ") - else - print(" ") - } - - protected def printArgs(args: List[Tree]): Unit = { - printRow(args, "(", ", ", ")") - } - - def printTree(tree: Tree): Unit = { - tree match { - case EmptyTree => - print("<empty>") - - // Definitions - - case VarDef(ident, vtpe, mutable, rhs) => - if (mutable) - print("var ") - else - print("val ") - print(ident, ": ", vtpe) - if (rhs != EmptyTree) - print(" = ", rhs) - - case ParamDef(ident, ptpe, mutable) => - if (mutable) - print("var ") - print(ident, ": ", ptpe) - - // Control flow constructs - - case Skip() => - print("/*<skip>*/") - - case tree: Block => - printBlock(tree) - - case Labeled(label, tpe, body) => - print(label) - if (tpe != NoType) - print("[", tpe, "]") - print(": ") - printBlock(body) - - case Assign(lhs, rhs) => - print(lhs, " = ", rhs) - - case Return(expr, label) => - if (label.isEmpty) print("return ", expr) - else print("return(", label.get, ") ", expr) - - case If(cond, BooleanLiteral(true), elsep) => - print(cond, " || ", elsep) - case If(cond, thenp, BooleanLiteral(false)) => - print(cond, " && ", thenp) - - case If(cond, thenp, elsep) => - print("if (", cond, ") ") - printBlock(thenp) - elsep match { - case Skip() => () - case If(_, _, _) => - print(" else ") - printTree(elsep) - case _ => - print(" else ") - printBlock(elsep) - } - - case While(cond, body, label) => - if (label.isDefined) - print(label.get, ": ") - print("while (", cond, ") ") - printBlock(body) - - case DoWhile(body, cond, label) => - if (label.isDefined) - print(label.get, ": ") - print("do ") - printBlock(body) - print(" while (", cond, ")") - - case Try(block, errVar, handler, finalizer) => - print("try ") - printBlock(block) - if (handler != EmptyTree) { - print(" catch (", errVar, ") ") - printBlock(handler) - } - if (finalizer != EmptyTree) { - print(" finally ") - printBlock(finalizer) - } - - case Throw(expr) => - print("throw ", expr) - - case Continue(label) => - if (label.isEmpty) print("continue") - else print("continue ", label.get) - - case Match(selector, cases, default) => - print("match (", selector, ") ") - print("{"); indent - for ((values, body) <- cases) { - println() - printRow(values, "case ", " | ", ":"); indent; println() - printTree(body) - print(";") - undent - } - if (default != EmptyTree) { - println() - print("default:"); indent; println() - printTree(default) - print(";") - undent - } - undent; println(); print("}") - - case Debugger() => - print("debugger") - - // Scala expressions - - case New(cls, ctor, args) => - print("new ", cls, "().", ctor) - printArgs(args) - - case LoadModule(cls) => - print("mod:", cls) - - case StoreModule(cls, value) => - print("mod:", cls, "<-", value) - - case Select(qualifier, item, _) => - print(qualifier, ".", item) - - case Apply(receiver, method, args) => - print(receiver, ".", method) - printArgs(args) - - case StaticApply(receiver, cls, method, args) => - print(receiver, ".", cls, "::", method) - printArgs(args) - - case TraitImplApply(impl, method, args) => - print(impl, "::", method) - printArgs(args) - - case UnaryOp(op, lhs) => - import UnaryOp._ - print("(", (op: @switch) match { - case `typeof` => "typeof" - case Boolean_! => "!" - case IntToLong | DoubleToLong => "(long)" - case DoubleToInt | LongToInt => "(int)" - case DoubleToFloat => "(float)" - case LongToDouble => "(double)" - }, lhs, ")") - - case BinaryOp(BinaryOp.Int_-, IntLiteral(0), rhs) => - print("(-", rhs, ")") - case BinaryOp(BinaryOp.Int_^, IntLiteral(-1), rhs) => - print("(~", rhs, ")") - case BinaryOp(BinaryOp.Long_-, LongLiteral(0L), rhs) => - print("(-", rhs, ")") - case BinaryOp(BinaryOp.Long_^, LongLiteral(-1L), rhs) => - print("(~", rhs, ")") - case BinaryOp(BinaryOp.Float_-, FloatLiteral(0.0f), rhs) => - print("(-", rhs, ")") - case BinaryOp(BinaryOp.Double_-, - IntLiteral(0) | FloatLiteral(0.0f) | DoubleLiteral(0.0), rhs) => - print("(-", rhs, ")") - - case BinaryOp(op, lhs, rhs) => - import BinaryOp._ - print("(", lhs, " ", (op: @switch) match { - case === => "===" - case !== => "!==" - - case String_+ => "+[string]" - - case `in` => "in" - case `instanceof` => "instanceof" - - case Int_+ => "+[int]" - case Int_- => "-[int]" - case Int_* => "*[int]" - case Int_/ => "/[int]" - case Int_% => "%[int]" - - case Int_| => "|" - case Int_& => "&" - case Int_^ => "^" - case Int_<< => "<<" - case Int_>>> => ">>>" - case Int_>> => ">>" - - case Float_+ => "+[float]" - case Float_- => "-[float]" - case Float_* => "*[float]" - case Float_/ => "/[float]" - case Float_% => "%[float]" - - case Double_+ => "+" - case Double_- => "-" - case Double_* => "*" - case Double_/ => "/" - case Double_% => "%" - - case Num_== => "==" - case Num_!= => "!=" - case Num_< => "<" - case Num_<= => "<=" - case Num_> => ">" - case Num_>= => ">=" - - case Long_+ => "+[long]" - case Long_- => "-[long]" - case Long_* => "*[long]" - case Long_/ => "/[long]" - case Long_% => "%[long]" - - case Long_| => "|[long]" - case Long_& => "&[long]" - case Long_^ => "^[long]" - case Long_<< => "<<[long]" - case Long_>>> => ">>>[long]" - case Long_>> => ">>[long]" - - case Long_== => "==[long]" - case Long_!= => "!=[long]" - case Long_< => "<[long]" - case Long_<= => "<=[long]" - case Long_> => ">[long]" - case Long_>= => ">=[long]" - - case Boolean_== => "==[bool]" - case Boolean_!= => "!=[bool]" - case Boolean_| => "|[bool]" - case Boolean_& => "&[bool]" - }, " ", rhs, ")") - - case NewArray(tpe, lengths) => - print("new ", tpe.baseClassName) - for (length <- lengths) - print("[", length, "]") - for (dim <- lengths.size until tpe.dimensions) - print("[]") - - case ArrayValue(tpe, elems) => - print(tpe) - printArgs(elems) - - case ArrayLength(array) => - print(array, ".length") - - case ArraySelect(array, index) => - print(array, "[", index, "]") - - case RecordValue(tpe, elems) => - print("(") - var first = true - for ((field, value) <- tpe.fields zip elems) { - if (first) first = false - else print(", ") - print(field.name, " = ", value) - } - print(")") - - case IsInstanceOf(expr, cls) => - print(expr, ".isInstanceOf[", cls, "]") - - case AsInstanceOf(expr, cls) => - print(expr, ".asInstanceOf[", cls, "]") - - case Unbox(expr, charCode) => - print(expr, ".asInstanceOf[", charCode, "]") - - case GetClass(expr) => - print(expr, ".getClass()") - - case CallHelper(helper, args) => - print(helper) - printArgs(args) - - // JavaScript expressions - - case JSNew(ctor, args) => - def containsOnlySelectsFromAtom(tree: Tree): Boolean = tree match { - case JSDotSelect(qual, _) => containsOnlySelectsFromAtom(qual) - case JSBracketSelect(qual, _) => containsOnlySelectsFromAtom(qual) - case VarRef(_, _) => true - case This() => true - case _ => false // in particular, Apply - } - if (containsOnlySelectsFromAtom(ctor)) - print("new ", ctor) - else - print("new (", ctor, ")") - printArgs(args) - - case JSDotSelect(qualifier, item) => - print(qualifier, ".", item) - - case JSBracketSelect(qualifier, item) => - print(qualifier, "[", item, "]") - - case JSFunctionApply(fun, args) => - fun match { - case _:JSDotSelect | _:JSBracketSelect | _:Select => - print("protect(", fun, ")") - case _ => - print(fun) - } - printArgs(args) - - case JSDotMethodApply(receiver, method, args) => - print(receiver, ".", method) - printArgs(args) - - case JSBracketMethodApply(receiver, method, args) => - print(receiver, "[", method, "]") - printArgs(args) - - case JSDelete(prop) => - print("delete ", prop) - - case JSUnaryOp("typeof", lhs) => - print("typeof(", lhs, ")") - - case JSUnaryOp(op, lhs) => - print("(", op, lhs, ")") - - case JSBinaryOp(op, lhs, rhs) => - print("(", lhs, " ", op, " ", rhs, ")") - - case JSArrayConstr(items) => - printRow(items, "[", ", ", "]") - - case JSObjectConstr(Nil) => - print("{}") - - case JSObjectConstr(fields) => - print("{"); indent; println() - printSeq(fields) { - case (name, value) => print(name, ": ", value) - } { _ => - print(",") - println() - } - undent; println(); print("}") - - case JSEnvInfo() => - print("<envinfo>") - - // Literals - - case Undefined() => - print("(void 0)") - - case UndefinedParam() => - print("<undefined param>") - - case Null() => - print("null") - - case BooleanLiteral(value) => - print(if (value) "true" else "false") - - case IntLiteral(value) => - if (value >= 0) - print(value) - else - print("(", value, ")") - - case FloatLiteral(value) => - if (value == 0.0f && 1.0f / value < 0.0f) - print("(-0)") - else if (value >= 0.0f) - print(value) - else - print("(", value, ")") - - case DoubleLiteral(value) => - if (value == 0.0 && 1.0 / value < 0.0) - print("(-0)") - else if (value >= 0.0) - print(value) - else - print("(", value, ")") - - case StringLiteral(value) => - print("\"", escapeJS(value), "\"") - - case ClassOf(cls) => - print("classOf[", cls, "]") - - // Atomic expressions - - case VarRef(ident, _) => - print(ident) - - case This() => - print("this") - - case Closure(captureParams, params, body, captureValues) => - print("(lambda") - printRow(captureValues, "<", ", ", ">") - printRow(captureParams ++ params, "(", ", ", ") = ") - printBlock(body) - print(")") - - // Classes - - case ClassDef(name, kind, parent, ancestors, defs) => - kind match { - case ClassKind.Class => print("class ") - case ClassKind.ModuleClass => print("module class ") - case ClassKind.Interface => print("interface ") - case ClassKind.RawJSType => print("jstype ") - case ClassKind.HijackedClass => print("hijacked class ") - case ClassKind.TraitImpl => print("trait impl ") - } - print(name) - parent.foreach(print(" extends ", _)) - if (ancestors.nonEmpty) - printRow(ancestors, " ancestors ", ", ", "") - print(" ") - printColumn(defs, "{", "", "}") - println() - - case MethodDef(name, args, resultType, body) => - print(name) - printSig(args, resultType) - printBlock(body) - - case PropertyDef(name, _, _, _) => - // TODO - print(s"<property: $name>") - - case ConstructorExportDef(fullName, args, body) => - print("export \"", escapeJS(fullName), "\"") - printSig(args, NoType) // NoType as trick not to display a type - printBlock(body) - - case ModuleExportDef(fullName) => - print("export \"", escapeJS(fullName), "\"") - - case _ => - print(s"<error, elem of class ${tree.getClass()}>") - } - } - - def printType(tpe: Type): Unit = tpe match { - case AnyType => print("any") - case NothingType => print("nothing") - case UndefType => print("void") - case BooleanType => print("boolean") - case IntType => print("int") - case LongType => print("long") - case FloatType => print("float") - case DoubleType => print("number") - case StringType => print("string") - case NullType => print("null") - case ClassType(className) => print(className) - case NoType => print("<notype>") - - case ArrayType(base, dims) => - print(base) - for (i <- 1 to dims) - print("[]") - - case RecordType(fields) => - print("(") - var first = false - for (RecordType.Field(name, _, tpe, mutable) <- fields) { - if (first) first = false - else print(", ") - if (mutable) - print("var ") - print(name, ": ", tpe) - } - print(")") - } - - protected def printIdent(ident: Ident): Unit = - printString(escapeJS(ident.name)) - - protected def printOne(arg: Any): Unit = arg match { - case tree: Tree => - printTree(tree) - case tpe: Type => - printType(tpe) - case ident: Ident => - printIdent(ident) - case arg => - printString(if (arg == null) "null" else arg.toString) - } - - protected def printString(s: String): Unit = { - out.write(s) - } - - // Make it public - override def println(): Unit = super.println() - - def complete(): Unit = () - } - - class InfoPrinter(protected val out: Writer) extends IndentationManager { - def printClassInfo(classInfo: ClassInfo): Unit = { - import classInfo._ - println("name: ", escapeJS(name)) - println("encodedName: ", escapeJS(encodedName)) - println("isExported: ", isExported) - println("ancestorCount: ", ancestorCount) - println("kind: ", kind) - println("superClass: ", superClass) - - if (ancestors.nonEmpty) { - println("ancestors: ", - ancestors.map(escapeJS).mkString("[", ", ", "]")) - } - - if (optimizerHints != OptimizerHints.empty) - println("optimizerHints: ", optimizerHints) - - print("methods:") - indent(); println() - methods.foreach(printMethodInfo) - undent(); println() - } - - def printMethodInfo(methodInfo: MethodInfo): Unit = { - import methodInfo._ - print(escapeJS(encodedName), ":") - indent(); println() - - if (isAbstract) - println("isAbstract: ", isAbstract) - if (isExported) - println("isExported: ", isExported) - if (calledMethods.nonEmpty) { - print("calledMethods:") - indent(); println() - printSeq(calledMethods.toList) { case (caller, callees) => - print(escapeJS(caller), ": ") - print(callees.map(escapeJS).mkString("[", ", ", "]")) - } { _ => println() } - undent(); println() - } - if (calledMethodsStatic.nonEmpty) { - print("calledMethodsStatic:") - indent(); println() - printSeq(calledMethodsStatic.toList) { case (caller, callees) => - print(escapeJS(caller), ": ") - print(callees.map(escapeJS).mkString("[", ", ", "]")) - } { _ => println() } - undent(); println() - } - if (instantiatedClasses.nonEmpty) { - println("instantiatedClasses: ", - instantiatedClasses.map(escapeJS).mkString("[", ", ", "]")) - } - if (accessedModules.nonEmpty) { - println("accessedModules: ", - accessedModules.map(escapeJS).mkString("[", ", ", "]")) - } - if (accessedClassData.nonEmpty) { - println("accessedClassData: ", - accessedClassData.map(escapeJS).mkString("[", ", ", "]")) - } - if (optimizerHints != OptimizerHints.empty) - println("optimizerHints: ", optimizerHints) - - undent(); println() - } - - private def println(arg1: Any, args: Any*): Unit = { - print((arg1 +: args): _*) - println() - } - - protected def printOne(arg: Any): Unit = arg match { - case classInfo: ClassInfo => printClassInfo(classInfo) - case methodInfo: MethodInfo => printMethodInfo(methodInfo) - case arg => out.write(arg.toString()) - } - - def complete(): Unit = () - } - -} diff --git a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/ScalaJSVersions.scala b/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/ScalaJSVersions.scala deleted file mode 100644 index 2690939..0000000 --- a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/ScalaJSVersions.scala +++ /dev/null @@ -1,25 +0,0 @@ -package scala.scalajs.ir - -object ScalaJSVersions { - - /** the Scala.js version of this build */ - final val current = "0.6.0-SNAPSHOT" - - /** true iff the Scala.js version of this build is a snapshot version. */ - final val currentIsSnapshot = current endsWith "-SNAPSHOT" - - /** Version of binary IR this Scala.js version emits - * - * This should be either of: - * - a prior release version (i.e. "0.5.0", *not* "0.5.0-SNAPSHOT") - * - `current` - */ - final val binaryEmitted = current - - /** Versions whose binary files we can support (used by deserializer) */ - val binarySupported: Set[String] = Set(binaryEmitted) - - // Just to be extra safe - assert(binarySupported contains binaryEmitted) - -} diff --git a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Serializers.scala b/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Serializers.scala deleted file mode 100644 index 04ec5c2..0000000 --- a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Serializers.scala +++ /dev/null @@ -1,790 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ __ ____ Scala.js IR ** -** / __/ __// _ | / / / _ | __ / // __/ (c) 2014, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ ** -** /____/\___/_/ |_/____/_/ | |__/ /____/ ** -** |/____/ ** -\* */ - - -package scala.scalajs.ir - -import scala.annotation.switch - -import java.io._ -import java.net.URI - -import scala.collection.mutable - -import Position._ -import Trees._ -import Types._ -import Tags._ - -import Utils.JumpBackByteArrayOutputStream - -object Serializers { - def serialize(stream: OutputStream, tree: Tree): Unit = { - new Serializer().serialize(stream, tree) - } - - def deserialize(stream: InputStream, version: String): Tree = { - new Deserializer(stream, version).deserialize() - } - - // true for easier debugging (not for "production", it adds 8 bytes per node) - private final val UseDebugMagic = false - private final val DebugMagic = 0x3fa8ef84 - private final val PosDebugMagic = 0x65f0ec32 - - private object PositionFormat { - /* Positions are serialized incrementally as diffs wrt the last position. - * - * Formats are (the first byte is decomposed in bits): - * - * 1st byte | next bytes | description - * ----------------------------------------- - * ccccccc0 | | Column diff (7-bit signed) - * llllll01 | CC | Line diff (6-bit signed), column (8-bit unsigned) - * ____0011 | LL LL CC | Line diff (16-bit signed), column (8-bit unsigned) - * ____0111 | 12 bytes | File index, line, column (all 32-bit signed) - * 11111111 | | NoPosition (is not compared/stored in last position) - * - * Underscores are irrelevant and must be set to 0. - */ - - final val Format1Mask = 0x01 - final val Format1MaskValue = 0x00 - final val Format1Shift = 1 - - final val Format2Mask = 0x03 - final val Format2MaskValue = 0x01 - final val Format2Shift = 2 - - final val Format3Mask = 0x0f - final val Format3MaskValue = 0x03 - - final val FormatFullMask = 0x0f - final val FormatFullMaskValue = 0x7 - - final val FormatNoPositionValue = -1 - } - - private final class Serializer { - private[this] val bufferUnderlying = new JumpBackByteArrayOutputStream - private[this] val buffer = new DataOutputStream(bufferUnderlying) - - private[this] val files = mutable.ListBuffer.empty[URI] - private[this] val fileIndexMap = mutable.Map.empty[URI, Int] - private def fileToIndex(file: URI): Int = - fileIndexMap.getOrElseUpdate(file, (files += file).size - 1) - - private[this] val strings = mutable.ListBuffer.empty[String] - private[this] val stringIndexMap = mutable.Map.empty[String, Int] - private def stringToIndex(str: String): Int = - stringIndexMap.getOrElseUpdate(str, (strings += str).size - 1) - - private[this] var lastPosition: Position = Position.NoPosition - - def serialize(stream: OutputStream, tree: Tree): Unit = { - // Write tree to buffer and record files and strings - writeTree(tree) - - val s = new DataOutputStream(stream) - - // Emit the files - s.writeInt(files.size) - files.foreach(f => s.writeUTF(f.toString)) - - // Emit the strings - s.writeInt(strings.size) - strings.foreach(s.writeUTF) - - // Paste the buffer - bufferUnderlying.writeTo(s) - - s.flush() - } - - def writeTree(tree: Tree): Unit = { - import buffer._ - writePosition(tree.pos) - tree match { - case EmptyTree => - writeByte(TagEmptyTree) - - case VarDef(ident, vtpe, mutable, rhs) => - writeByte(TagVarDef) - writeIdent(ident); writeType(vtpe); writeBoolean(mutable); writeTree(rhs) - - case ParamDef(ident, ptpe, mutable) => - writeByte(TagParamDef) - writeIdent(ident); writeType(ptpe); writeBoolean(mutable) - - case Skip() => - writeByte(TagSkip) - - case Block(stats) => - writeByte(TagBlock) - writeTrees(stats) - - case Labeled(label, tpe, body) => - writeByte(TagLabeled) - writeIdent(label); writeType(tpe); writeTree(body) - - case Assign(lhs, rhs) => - writeByte(TagAssign) - writeTree(lhs); writeTree(rhs) - - case Return(expr, label) => - writeByte(TagReturn) - writeTree(expr); writeOptIdent(label) - - case If(cond, thenp, elsep) => - writeByte(TagIf) - writeTree(cond); writeTree(thenp); writeTree(elsep) - writeType(tree.tpe) - - case While(cond, body, label) => - writeByte(TagWhile) - writeTree(cond); writeTree(body); writeOptIdent(label) - - case DoWhile(body, cond, label) => - writeByte(TagDoWhile) - writeTree(body); writeTree(cond); writeOptIdent(label) - - case Try(block, errVar, handler, finalizer) => - writeByte(TagTry) - writeTree(block); writeIdent(errVar); writeTree(handler); writeTree(finalizer) - writeType(tree.tpe) - - case Throw(expr) => - writeByte(TagThrow) - writeTree(expr) - - case Continue(label) => - writeByte(TagContinue) - writeOptIdent(label) - - case Match(selector, cases, default) => - writeByte(TagMatch) - writeTree(selector) - writeInt(cases.size) - cases foreach { caze => - writeTrees(caze._1); writeTree(caze._2) - } - writeTree(default) - writeType(tree.tpe) - - case Debugger() => - writeByte(TagDebugger) - - case New(cls, ctor, args) => - writeByte(TagNew) - writeClassType(cls); writeIdent(ctor); writeTrees(args) - - case LoadModule(cls) => - writeByte(TagLoadModule) - writeClassType(cls) - - case StoreModule(cls, value) => - writeByte(TagStoreModule) - writeClassType(cls); writeTree(value) - - case Select(qualifier, item, mutable) => - writeByte(TagSelect) - writeTree(qualifier); writeIdent(item); writeBoolean(mutable) - writeType(tree.tpe) - - case Apply(receiver, method, args) => - writeByte(TagApply) - writeTree(receiver); writeIdent(method); writeTrees(args) - writeType(tree.tpe) - - case StaticApply(receiver, cls, method, args) => - writeByte(TagStaticApply) - writeTree(receiver); writeClassType(cls); writeIdent(method); writeTrees(args) - writeType(tree.tpe) - - case TraitImplApply(impl, method, args) => - writeByte(TagTraitImplApply) - writeClassType(impl); writeIdent(method); writeTrees(args) - writeType(tree.tpe) - - case UnaryOp(op, lhs) => - writeByte(TagUnaryOp) - writeByte(op); writeTree(lhs) - - case BinaryOp(op, lhs, rhs) => - writeByte(TagBinaryOp) - writeByte(op); writeTree(lhs); writeTree(rhs) - - case NewArray(tpe, lengths) => - writeByte(TagNewArray) - writeArrayType(tpe); writeTrees(lengths) - - case ArrayValue(tpe, elems) => - writeByte(TagArrayValue) - writeArrayType(tpe); writeTrees(elems) - - case ArrayLength(array) => - writeByte(TagArrayLength) - writeTree(array) - - case ArraySelect(array, index) => - writeByte(TagArraySelect) - writeTree(array); writeTree(index) - writeType(tree.tpe) - - case RecordValue(tpe, elems) => - writeByte(TagRecordValue) - writeType(tpe); writeTrees(elems) - - case IsInstanceOf(expr, cls) => - writeByte(TagIsInstanceOf) - writeTree(expr); writeReferenceType(cls) - - case AsInstanceOf(expr, cls) => - writeByte(TagAsInstanceOf) - writeTree(expr); writeReferenceType(cls) - - case Unbox(expr, charCode) => - writeByte(TagUnbox) - writeTree(expr); writeByte(charCode.toByte) - - case GetClass(expr) => - writeByte(TagGetClass) - writeTree(expr) - - case CallHelper(helper, args) => - writeByte(TagCallHelper) - writeString(helper); writeTrees(args) - writeType(tree.tpe) - - case JSNew(ctor, args) => - writeByte(TagJSNew) - writeTree(ctor); writeTrees(args) - - case JSDotSelect(qualifier, item) => - writeByte(TagJSDotSelect) - writeTree(qualifier); writeIdent(item) - - case JSBracketSelect(qualifier, item) => - writeByte(TagJSBracketSelect) - writeTree(qualifier); writeTree(item) - - case JSFunctionApply(fun, args) => - writeByte(TagJSFunctionApply) - writeTree(fun); writeTrees(args) - - case JSDotMethodApply(receiver, method, args) => - writeByte(TagJSDotMethodApply) - writeTree(receiver); writeIdent(method); writeTrees(args) - - case JSBracketMethodApply(receiver, method, args) => - writeByte(TagJSBracketMethodApply) - writeTree(receiver); writeTree(method); writeTrees(args) - - case JSDelete(prop) => - writeByte(TagJSDelete) - writeTree(prop) - - case JSUnaryOp(op, lhs) => - writeByte(TagJSUnaryOp) - writeString(op); writeTree(lhs) - - case JSBinaryOp(op, lhs, rhs) => - writeByte(TagJSBinaryOp) - writeString(op); writeTree(lhs); writeTree(rhs) - - case JSArrayConstr(items) => - writeByte(TagJSArrayConstr) - writeTrees(items) - - case JSObjectConstr(fields) => - writeByte(TagJSObjectConstr) - writeInt(fields.size) - fields foreach { field => - writePropertyName(field._1); writeTree(field._2) - } - - case JSEnvInfo() => - writeByte(TagJSEnvInfo) - - // Literals - - case Undefined() => - writeByte(TagUndefined) - - case UndefinedParam() => - writeByte(TagUndefinedParam) - writeType(tree.tpe) - - case Null() => - writeByte(TagNull) - - case BooleanLiteral(value) => - writeByte(TagBooleanLiteral) - writeBoolean(value) - - case IntLiteral(value) => - writeByte(TagIntLiteral) - writeInt(value) - - case LongLiteral(value) => - writeByte(TagLongLiteral) - writeLong(value) - - case FloatLiteral(value) => - writeByte(TagFloatLiteral) - writeFloat(value) - - case DoubleLiteral(value) => - writeByte(TagDoubleLiteral) - writeDouble(value) - - case StringLiteral(value) => - writeByte(TagStringLiteral) - writeString(value) - - case ClassOf(cls) => - writeByte(TagClassOf) - writeReferenceType(cls) - - case VarRef(ident, mutable) => - writeByte(TagVarRef) - writeIdent(ident); writeBoolean(mutable) - writeType(tree.tpe) - - case This() => - writeByte(TagThis) - writeType(tree.tpe) - - case Closure(captureParams, params, body, captureValues) => - writeByte(TagClosure) - writeTrees(captureParams) - writeTrees(params) - writeTree(body) - writeTrees(captureValues) - - case ClassDef(name, kind, parent, ancestors, defs) => - writeByte(TagClassDef) - writeIdent(name) - writeByte(ClassKind.toByte(kind)) - writeOptIdent(parent) - writeIdents(ancestors) - writeTrees(defs) - - case methodDef: MethodDef => - val MethodDef(name, args, resultType, body) = methodDef - - writeByte(TagMethodDef) - writeOptHash(methodDef.hash) - - // Prepare for back-jump and write dummy length - bufferUnderlying.markJump() - writeInt(-1) - - // Write out method def - writePropertyName(name); writeTrees(args); writeType(resultType); writeTree(body) - - // Jump back and write true length - val length = bufferUnderlying.jumpBack() - writeInt(length) - bufferUnderlying.continue() - - case PropertyDef(name, getter, arg, setter) => - writeByte(TagPropertyDef) - writePropertyName(name); writeTree(getter); writeTree(arg); writeTree(setter) - - case ConstructorExportDef(fullName, args, body) => - writeByte(TagConstructorExportDef) - writeString(fullName); writeTrees(args); writeTree(body) - - case ModuleExportDef(fullName) => - writeByte(TagModuleExportDef) - writeString(fullName) - } - if (UseDebugMagic) - writeInt(DebugMagic) - } - - def writeTrees(trees: List[Tree]): Unit = { - buffer.writeInt(trees.size) - trees.foreach(writeTree) - } - - def writeIdent(ident: Ident): Unit = { - writePosition(ident.pos) - writeString(ident.name); writeString(ident.originalName.getOrElse("")) - } - - def writeIdents(idents: List[Ident]): Unit = { - buffer.writeInt(idents.size) - idents.foreach(writeIdent) - } - - def writeOptIdent(optIdent: Option[Ident]): Unit = { - buffer.writeBoolean(optIdent.isDefined) - optIdent.foreach(writeIdent) - } - - def writeType(tpe: Type): Unit = { - tpe match { - case AnyType => buffer.write(TagAnyType) - case NothingType => buffer.write(TagNothingType) - case UndefType => buffer.write(TagUndefType) - case BooleanType => buffer.write(TagBooleanType) - case IntType => buffer.write(TagIntType) - case LongType => buffer.write(TagLongType) - case FloatType => buffer.write(TagFloatType) - case DoubleType => buffer.write(TagDoubleType) - case StringType => buffer.write(TagStringType) - case NullType => buffer.write(TagNullType) - case NoType => buffer.write(TagNoType) - - case tpe: ClassType => - buffer.write(TagClassType) - writeClassType(tpe) - - case tpe: ArrayType => - buffer.write(TagArrayType) - writeArrayType(tpe) - - case RecordType(fields) => - buffer.write(TagRecordType) - buffer.writeInt(fields.size) - for (RecordType.Field(name, originalName, tpe, mutable) <- fields) { - writeString(name) - writeString(originalName.getOrElse("")) - writeType(tpe) - buffer.writeBoolean(mutable) - } - } - } - - def writeClassType(tpe: ClassType): Unit = - writeString(tpe.className) - - def writeArrayType(tpe: ArrayType): Unit = { - writeString(tpe.baseClassName) - buffer.writeInt(tpe.dimensions) - } - - def writeReferenceType(tpe: ReferenceType): Unit = - writeType(tpe) - - def writePropertyName(name: PropertyName): Unit = { - name match { - case name: Ident => buffer.writeBoolean(true); writeIdent(name) - case name: StringLiteral => buffer.writeBoolean(false); writeTree(name) - } - } - - def writePosition(pos: Position): Unit = { - import buffer._ - import PositionFormat._ - - def writeFull(): Unit = { - writeByte(FormatFullMaskValue) - writeInt(fileToIndex(pos.source)) - writeInt(pos.line) - writeInt(pos.column) - } - - if (pos == Position.NoPosition) { - writeByte(FormatNoPositionValue) - } else if (lastPosition == Position.NoPosition || - pos.source != lastPosition.source) { - writeFull() - lastPosition = pos - } else { - val line = pos.line - val column = pos.column - val lineDiff = line - lastPosition.line - val columnDiff = column - lastPosition.column - val columnIsByte = column >= 0 && column < 256 - - if (lineDiff == 0 && columnDiff >= -64 && columnDiff < 64) { - writeByte((columnDiff << Format1Shift) | Format1MaskValue) - } else if (lineDiff >= -32 && lineDiff < 32 && columnIsByte) { - writeByte((lineDiff << Format2Shift) | Format2MaskValue) - writeByte(column) - } else if (lineDiff >= Short.MinValue && lineDiff <= Short.MaxValue && columnIsByte) { - writeByte(Format3MaskValue) - writeShort(lineDiff) - writeByte(column) - } else { - writeFull() - } - - lastPosition = pos - } - - if (UseDebugMagic) - writeInt(PosDebugMagic) - } - - def writeOptHash(optHash: Option[TreeHash]): Unit = { - buffer.writeBoolean(optHash.isDefined) - for (hash <- optHash) { - buffer.write(hash.treeHash) - buffer.write(hash.posHash) - } - } - - def writeString(s: String): Unit = - buffer.writeInt(stringToIndex(s)) - } - - private final class Deserializer(stream: InputStream, sourceVersion: String) { - private[this] val input = new DataInputStream(stream) - - private[this] val files = - Array.fill(input.readInt())(new URI(input.readUTF())) - - private[this] val strings = - Array.fill(input.readInt())(input.readUTF()) - - private[this] var lastPosition: Position = Position.NoPosition - - def deserialize(): Tree = { - readTree() - } - - def readTree(): Tree = { - import input._ - implicit val pos = readPosition() - val tag = readByte() - val result = (tag: @switch) match { - case TagEmptyTree => EmptyTree - - case TagVarDef => VarDef(readIdent(), readType(), readBoolean(), readTree()) - case TagParamDef => ParamDef(readIdent(), readType(), readBoolean()) - - case TagSkip => Skip() - case TagBlock => Block(readTrees()) - case TagLabeled => Labeled(readIdent(), readType(), readTree()) - case TagAssign => Assign(readTree(), readTree()) - case TagReturn => Return(readTree(), readOptIdent()) - case TagIf => If(readTree(), readTree(), readTree())(readType()) - case TagWhile => While(readTree(), readTree(), readOptIdent()) - case TagDoWhile => DoWhile(readTree(), readTree(), readOptIdent()) - case TagTry => Try(readTree(), readIdent(), readTree(), readTree())(readType()) - case TagThrow => Throw(readTree()) - case TagContinue => Continue(readOptIdent()) - case TagMatch => - Match(readTree(), List.fill(readInt()) { - (readTrees().map(_.asInstanceOf[Literal]), readTree()) - }, readTree())(readType()) - case TagDebugger => Debugger() - - case TagNew => New(readClassType(), readIdent(), readTrees()) - case TagLoadModule => LoadModule(readClassType()) - case TagStoreModule => StoreModule(readClassType(), readTree()) - case TagSelect => Select(readTree(), readIdent(), readBoolean())(readType()) - case TagApply => Apply(readTree(), readIdent(), readTrees())(readType()) - case TagStaticApply => StaticApply(readTree(), readClassType(), readIdent(), readTrees())(readType()) - case TagTraitImplApply => TraitImplApply(readClassType(), readIdent(), readTrees())(readType()) - case TagUnaryOp => UnaryOp(readByte(), readTree()) - case TagBinaryOp => BinaryOp(readByte(), readTree(), readTree()) - case TagNewArray => NewArray(readArrayType(), readTrees()) - case TagArrayValue => ArrayValue(readArrayType(), readTrees()) - case TagArrayLength => ArrayLength(readTree()) - case TagArraySelect => ArraySelect(readTree(), readTree())(readType()) - case TagRecordValue => RecordValue(readType().asInstanceOf[RecordType], readTrees()) - case TagIsInstanceOf => IsInstanceOf(readTree(), readReferenceType()) - case TagAsInstanceOf => AsInstanceOf(readTree(), readReferenceType()) - case TagUnbox => Unbox(readTree(), readByte().toChar) - case TagGetClass => GetClass(readTree()) - case TagCallHelper => CallHelper(readString(), readTrees())(readType()) - - case TagJSNew => JSNew(readTree(), readTrees()) - case TagJSDotSelect => JSDotSelect(readTree(), readIdent()) - case TagJSBracketSelect => JSBracketSelect(readTree(), readTree()) - case TagJSFunctionApply => JSFunctionApply(readTree(), readTrees()) - case TagJSDotMethodApply => JSDotMethodApply(readTree(), readIdent(), readTrees()) - case TagJSBracketMethodApply => JSBracketMethodApply(readTree(), readTree(), readTrees()) - case TagJSDelete => JSDelete(readTree()) - case TagJSUnaryOp => JSUnaryOp(readString(), readTree()) - case TagJSBinaryOp => JSBinaryOp(readString(), readTree(), readTree()) - case TagJSArrayConstr => JSArrayConstr(readTrees()) - case TagJSObjectConstr => - JSObjectConstr(List.fill(readInt())((readPropertyName(), readTree()))) - case TagJSEnvInfo => JSEnvInfo() - - case TagUndefined => Undefined() - case TagUndefinedParam => UndefinedParam()(readType()) - case TagNull => Null() - case TagBooleanLiteral => BooleanLiteral(readBoolean()) - case TagIntLiteral => IntLiteral(readInt()) - case TagLongLiteral => LongLiteral(readLong()) - case TagFloatLiteral => FloatLiteral(readFloat()) - case TagDoubleLiteral => DoubleLiteral(readDouble()) - case TagStringLiteral => StringLiteral(readString()) - case TagClassOf => ClassOf(readReferenceType()) - - case TagVarRef => VarRef(readIdent(), readBoolean())(readType()) - case TagThis => This()(readType()) - case TagClosure => - Closure(readParamDefs(), readParamDefs(), readTree(), readTrees()) - - case TagClassDef => - val name = readIdent() - val kind = ClassKind.fromByte(readByte()) - val parent = readOptIdent() - val ancestors = readIdents() - val defs = readTrees() - ClassDef(name, kind, parent, ancestors, defs) - - case TagMethodDef => - val optHash = readOptHash() - // read and discard the length - val len = readInt() - assert(len >= 0) - MethodDef(readPropertyName(), readParamDefs(), readType(), readTree())(optHash) - case TagPropertyDef => - PropertyDef(readPropertyName(), readTree(), - readTree().asInstanceOf[ParamDef], readTree()) - case TagConstructorExportDef => - ConstructorExportDef(readString(), readParamDefs(), readTree()) - case TagModuleExportDef => - ModuleExportDef(readString()) - } - if (UseDebugMagic) { - val magic = readInt() - assert(magic == DebugMagic, - s"Bad magic after reading a ${result.getClass}!") - } - result - } - - def readTrees(): List[Tree] = - List.fill(input.readInt())(readTree()) - - def readParamDefs(): List[ParamDef] = - readTrees().map(_.asInstanceOf[ParamDef]) - - def readIdent(): Ident = { - implicit val pos = readPosition() - val name = readString() - val originalName = readString() - Ident(name, if (originalName.isEmpty) None else Some(originalName)) - } - - def readIdents(): List[Ident] = - List.fill(input.readInt())(readIdent()) - - def readOptIdent(): Option[Ident] = { - if (input.readBoolean()) Some(readIdent()) - else None - } - - def readType(): Type = { - val tag = input.readByte() - (tag: @switch) match { - case TagAnyType => AnyType - case TagNothingType => NothingType - case TagUndefType => UndefType - case TagBooleanType => BooleanType - case TagIntType => IntType - case TagLongType => LongType - case TagFloatType => FloatType - case TagDoubleType => DoubleType - case TagStringType => StringType - case TagNullType => NullType - case TagNoType => NoType - - case TagClassType => readClassType() - case TagArrayType => readArrayType() - - case TagRecordType => - RecordType(List.fill(input.readInt()) { - val name = readString() - val originalName = readString() - val tpe = readType() - val mutable = input.readBoolean() - RecordType.Field(name, - if (originalName.isEmpty) None else Some(originalName), - tpe, mutable) - }) - } - } - - def readClassType(): ClassType = - ClassType(readString()) - - def readArrayType(): ArrayType = - ArrayType(readString(), input.readInt()) - - def readReferenceType(): ReferenceType = - readType().asInstanceOf[ReferenceType] - - def readPropertyName(): PropertyName = { - if (input.readBoolean()) readIdent() - else readTree().asInstanceOf[StringLiteral] - } - - def readPosition(): Position = { - import input._ - import PositionFormat._ - - val first = readByte() - - val result = if (first == FormatNoPositionValue) { - Position.NoPosition - } else { - val result = if ((first & FormatFullMask) == FormatFullMaskValue) { - val file = files(readInt()) - val line = readInt() - val column = readInt() - Position(file, line, column) - } else { - assert(lastPosition != NoPosition, - "Position format error: first position must be full") - if ((first & Format1Mask) == Format1MaskValue) { - val columnDiff = first >> Format1Shift - Position(lastPosition.source, lastPosition.line, - lastPosition.column + columnDiff) - } else if ((first & Format2Mask) == Format2MaskValue) { - val lineDiff = first >> Format2Shift - val column = readByte() & 0xff // unsigned - Position(lastPosition.source, - lastPosition.line + lineDiff, column) - } else { - assert((first & Format3Mask) == Format3MaskValue, - s"Position format error: first byte $first does not match any format") - val lineDiff = readShort() - val column = readByte() & 0xff // unsigned - Position(lastPosition.source, - lastPosition.line + lineDiff, column) - } - } - lastPosition = result - result - } - - if (UseDebugMagic) { - val magic = readInt() - assert(magic == PosDebugMagic, - s"Bad magic after reading position with first byte $first") - } - - result - } - - def readOptHash(): Option[TreeHash] = { - if (input.readBoolean()) { - val treeHash = new Array[Byte](20) - val posHash = new Array[Byte](20) - input.readFully(treeHash) - input.readFully(posHash) - Some(new TreeHash(treeHash, posHash)) - } else None - } - - def readString(): String = { - strings(input.readInt()) - } - } -} diff --git a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Tags.scala b/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Tags.scala deleted file mode 100644 index a03926c..0000000 --- a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Tags.scala +++ /dev/null @@ -1,107 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ __ ____ Scala.js IR ** -** / __/ __// _ | / / / _ | __ / // __/ (c) 2014, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ ** -** /____/\___/_/ |_/____/_/ | |__/ /____/ ** -** |/____/ ** -\* */ - - -package scala.scalajs.ir - -/** Serialization and hashing tags for trees and types */ -private[ir] object Tags { - - // Tags for Trees - - final val TagEmptyTree = 1 - - final val TagVarDef = TagEmptyTree + 1 - final val TagParamDef = TagVarDef + 1 - - final val TagSkip = TagParamDef + 1 - final val TagBlock = TagSkip + 1 - final val TagLabeled = TagBlock + 1 - final val TagAssign = TagLabeled + 1 - final val TagReturn = TagAssign + 1 - final val TagIf = TagReturn + 1 - final val TagWhile = TagIf + 1 - final val TagDoWhile = TagWhile + 1 - final val TagTry = TagDoWhile + 1 - final val TagThrow = TagTry + 1 - final val TagContinue = TagThrow + 1 - final val TagMatch = TagContinue + 1 - final val TagDebugger = TagMatch + 1 - - final val TagNew = TagDebugger + 1 - final val TagLoadModule = TagNew + 1 - final val TagStoreModule = TagLoadModule + 1 - final val TagSelect = TagStoreModule + 1 - final val TagApply = TagSelect + 1 - final val TagStaticApply = TagApply + 1 - final val TagTraitImplApply = TagStaticApply + 1 - final val TagUnaryOp = TagTraitImplApply + 1 - final val TagBinaryOp = TagUnaryOp + 1 - final val TagNewArray = TagBinaryOp + 1 - final val TagArrayValue = TagNewArray + 1 - final val TagArrayLength = TagArrayValue + 1 - final val TagArraySelect = TagArrayLength + 1 - final val TagRecordValue = TagArraySelect + 1 - final val TagIsInstanceOf = TagRecordValue + 1 - final val TagAsInstanceOf = TagIsInstanceOf + 1 - final val TagUnbox = TagAsInstanceOf + 1 - final val TagGetClass = TagUnbox + 1 - final val TagCallHelper = TagGetClass + 1 - - final val TagJSNew = TagCallHelper + 1 - final val TagJSDotSelect = TagJSNew + 1 - final val TagJSBracketSelect = TagJSDotSelect + 1 - final val TagJSFunctionApply = TagJSBracketSelect + 1 - final val TagJSDotMethodApply = TagJSFunctionApply + 1 - final val TagJSBracketMethodApply = TagJSDotMethodApply + 1 - final val TagJSDelete = TagJSBracketMethodApply + 1 - final val TagJSUnaryOp = TagJSDelete + 1 - final val TagJSBinaryOp = TagJSUnaryOp + 1 - final val TagJSArrayConstr = TagJSBinaryOp + 1 - final val TagJSObjectConstr = TagJSArrayConstr + 1 - final val TagJSEnvInfo = TagJSObjectConstr + 1 - - final val TagUndefined = TagJSEnvInfo + 1 - final val TagUndefinedParam = TagUndefined + 1 - final val TagNull = TagUndefinedParam + 1 - final val TagBooleanLiteral = TagNull + 1 - final val TagIntLiteral = TagBooleanLiteral + 1 - final val TagLongLiteral = TagIntLiteral + 1 - final val TagFloatLiteral = TagLongLiteral + 1 - final val TagDoubleLiteral = TagFloatLiteral + 1 - final val TagStringLiteral = TagDoubleLiteral + 1 - final val TagClassOf = TagStringLiteral + 1 - - final val TagVarRef = TagClassOf + 1 - final val TagThis = TagVarRef + 1 - final val TagClosure = TagThis + 1 - - final val TagClassDef = TagClosure + 1 - final val TagMethodDef = TagClassDef + 1 - final val TagPropertyDef = TagMethodDef + 1 - final val TagConstructorExportDef = TagPropertyDef + 1 - final val TagModuleExportDef = TagConstructorExportDef + 1 - - // Tags for Types - - final val TagAnyType = 1 - final val TagNothingType = TagAnyType + 1 - final val TagUndefType = TagNothingType + 1 - final val TagBooleanType = TagUndefType + 1 - final val TagIntType = TagBooleanType + 1 - final val TagLongType = TagIntType + 1 - final val TagFloatType = TagLongType + 1 - final val TagDoubleType = TagFloatType + 1 - final val TagStringType = TagDoubleType + 1 - final val TagNullType = TagStringType + 1 - final val TagClassType = TagNullType + 1 - final val TagArrayType = TagClassType + 1 - final val TagRecordType = TagArrayType + 1 - final val TagNoType = TagRecordType + 1 - -} diff --git a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Transformers.scala b/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Transformers.scala deleted file mode 100644 index 5e4f40c..0000000 --- a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Transformers.scala +++ /dev/null @@ -1,218 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ __ ____ Scala.js IR ** -** / __/ __// _ | / / / _ | __ / // __/ (c) 2014, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ ** -** /____/\___/_/ |_/____/_/ | |__/ /____/ ** -** |/____/ ** -\* */ - - -package scala.scalajs.ir - -import Trees._ - -object Transformers { - - abstract class Transformer { - final def transformStat(tree: Tree): Tree = - transform(tree, isStat = true) - - final def transformExpr(tree: Tree): Tree = - transform(tree, isStat = false) - - def transform(tree: Tree, isStat: Boolean): Tree = { - implicit val pos = tree.pos - - tree match { - // Definitions - - case VarDef(ident, vtpe, mutable, rhs) => - VarDef(ident, vtpe, mutable, transformExpr(rhs)) - - // Control flow constructs - - case Block(stats :+ expr) => - Block(stats.map(transformStat) :+ transform(expr, isStat)) - - case Labeled(label, tpe, body) => - Labeled(label, tpe, transform(body, isStat)) - - case Assign(lhs, rhs) => - Assign(transformExpr(lhs), transformExpr(rhs)) - - case Return(expr, label) => - Return(transformExpr(expr), label) - - case If(cond, thenp, elsep) => - If(transformExpr(cond), transform(thenp, isStat), - transform(elsep, isStat))(tree.tpe) - - case While(cond, body, label) => - While(transformExpr(cond), transformStat(body), label) - - case DoWhile(body, cond, label) => - DoWhile(transformStat(body), transformExpr(cond), label) - - case Try(block, errVar, handler, finalizer) => - Try(transform(block, isStat), errVar, transform(handler, isStat), - transformStat(finalizer))(tree.tpe) - - case Throw(expr) => - Throw(transformExpr(expr)) - - case Match(selector, cases, default) => - Match(transformExpr(selector), - cases map (c => (c._1, transform(c._2, isStat))), - transform(default, isStat))(tree.tpe) - - // Scala expressions - - case New(cls, ctor, args) => - New(cls, ctor, args map transformExpr) - - case StoreModule(cls, value) => - StoreModule(cls, transformExpr(value)) - - case Select(qualifier, item, mutable) => - Select(transformExpr(qualifier), item, mutable)(tree.tpe) - - case Apply(receiver, method, args) => - Apply(transformExpr(receiver), method, - args map transformExpr)(tree.tpe) - - case StaticApply(receiver, cls, method, args) => - StaticApply(transformExpr(receiver), cls, method, - args map transformExpr)(tree.tpe) - - case TraitImplApply(impl, method, args) => - TraitImplApply(impl, method, args map transformExpr)(tree.tpe) - - case UnaryOp(op, lhs) => - UnaryOp(op, transformExpr(lhs)) - - case BinaryOp(op, lhs, rhs) => - BinaryOp(op, transformExpr(lhs), transformExpr(rhs)) - - case NewArray(tpe, lengths) => - NewArray(tpe, lengths map transformExpr) - - case ArrayValue(tpe, elems) => - ArrayValue(tpe, elems map transformExpr) - - case ArrayLength(array) => - ArrayLength(transformExpr(array)) - - case ArraySelect(array, index) => - ArraySelect(transformExpr(array), transformExpr(index))(tree.tpe) - - case RecordValue(tpe, elems) => - RecordValue(tpe, elems map transformExpr) - - case IsInstanceOf(expr, cls) => - IsInstanceOf(transformExpr(expr), cls) - - case AsInstanceOf(expr, cls) => - AsInstanceOf(transformExpr(expr), cls) - - case Unbox(expr, charCode) => - Unbox(transformExpr(expr), charCode) - - case GetClass(expr) => - GetClass(transformExpr(expr)) - - case CallHelper(helper, args) => - CallHelper(helper, args map transformExpr)(tree.tpe) - - // JavaScript expressions - - case JSNew(ctor, args) => - JSNew(transformExpr(ctor), args map transformExpr) - - case JSDotSelect(qualifier, item) => - JSDotSelect(transformExpr(qualifier), item) - - case JSBracketSelect(qualifier, item) => - JSBracketSelect(transformExpr(qualifier), transformExpr(item)) - - case JSFunctionApply(fun, args) => - JSFunctionApply(transformExpr(fun), args map transformExpr) - - case JSDotMethodApply(receiver, method, args) => - JSDotMethodApply(transformExpr(receiver), method, - args map transformExpr) - - case JSBracketMethodApply(receiver, method, args) => - JSBracketMethodApply(transformExpr(receiver), transformExpr(method), - args map transformExpr) - - case JSDelete(prop) => - JSDelete(transformExpr(prop)) - - case JSUnaryOp(op, lhs) => - JSUnaryOp(op, transformExpr(lhs)) - - case JSBinaryOp(op, lhs, rhs) => - JSBinaryOp(op, transformExpr(lhs), transformExpr(rhs)) - - case JSArrayConstr(items) => - JSArrayConstr(items map transformExpr) - - case JSObjectConstr(fields) => - JSObjectConstr(fields map { - case (name, value) => (name, transformExpr(value)) - }) - - // Atomic expressions - - case Closure(captureParams, params, body, captureValues) => - Closure(captureParams, params, transformExpr(body), - captureValues.map(transformExpr)) - - // Trees that need not be transformed - - case _:Skip | _:Continue | _:LoadModule | _:JSEnvInfo | - _:Literal | _:VarRef | _:This | EmptyTree => - tree - - case _ => - sys.error(s"Invalid tree in transform() of class ${tree.getClass}") - } - } - } - - abstract class ClassTransformer extends Transformer { - def transformClassDef(tree: ClassDef): ClassDef = { - val ClassDef(name, kind, parent, ancestors, defs) = tree - ClassDef(name, kind, parent, ancestors, defs.map(transformDef))(tree.pos) - } - - def transformDef(tree: Tree): Tree = { - implicit val pos = tree.pos - - tree match { - case VarDef(name, vtpe, mutable, rhs) => - VarDef(name, vtpe, mutable, transformExpr(rhs)) - - case MethodDef(name, args, resultType, body) => - MethodDef(name, args, resultType, transformStat(body))(None) - - case PropertyDef(name, getterBody, setterArg, setterBody) => - PropertyDef( - name, - transformStat(getterBody), - setterArg, - transformStat(setterBody)) - - case ConstructorExportDef(fullName, args, body) => - ConstructorExportDef(fullName, args, transformStat(body)) - - case ModuleExportDef(_) => - tree - - case _ => - sys.error(s"Invalid tree in transformDef() of class ${tree.getClass}") - } - } - } - -} diff --git a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Traversers.scala b/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Traversers.scala deleted file mode 100644 index 1b77e5e..0000000 --- a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Traversers.scala +++ /dev/null @@ -1,197 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ __ ____ Scala.js IR ** -** / __/ __// _ | / / / _ | __ / // __/ (c) 2014, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ ** -** /____/\___/_/ |_/____/_/ | |__/ /____/ ** -** |/____/ ** -\* */ - - -package scala.scalajs.ir - -import Trees._ - -object Traversers { - - class Traverser { - def traverse(tree: Tree): Unit = tree match { - // Definitions - - case VarDef(ident, vtpe, mutable, rhs) => - traverse(rhs) - - // Control flow constructs - - case Block(stats) => - stats foreach traverse - - case Labeled(label, tpe, body) => - traverse(body) - - case Assign(lhs, rhs) => - traverse(lhs) - traverse(rhs) - - case Return(expr, label) => - traverse(expr) - - case If(cond, thenp, elsep) => - traverse(cond) - traverse(thenp) - traverse(elsep) - - case While(cond, body, label) => - traverse(cond) - traverse(body) - - case DoWhile(body, cond, label) => - traverse(body) - traverse(cond) - - case Try(block, errVar, handler, finalizer) => - traverse(block) - traverse(handler) - traverse(finalizer) - - case Throw(expr) => - traverse(expr) - - case Match(selector, cases, default) => - traverse(selector) - cases foreach (c => (c._1 map traverse, traverse(c._2))) - traverse(default) - - // Scala expressions - - case New(cls, ctor, args) => - args foreach traverse - - case StoreModule(cls, value) => - traverse(value) - - case Select(qualifier, item, mutable) => - traverse(qualifier) - - case Apply(receiver, method, args) => - traverse(receiver) - args foreach traverse - - case StaticApply(receiver, cls, method, args) => - traverse(receiver) - args foreach traverse - - case TraitImplApply(impl, method, args) => - args foreach traverse - - case UnaryOp(op, lhs) => - traverse(lhs) - - case BinaryOp(op, lhs, rhs) => - traverse(lhs) - traverse(rhs) - - case NewArray(tpe, lengths) => - lengths foreach traverse - - case ArrayValue(tpe, elems) => - elems foreach traverse - - case ArrayLength(array) => - traverse(array) - - case ArraySelect(array, index) => - traverse(array) - traverse(index) - - case RecordValue(tpe, elems) => - elems foreach traverse - - case IsInstanceOf(expr, cls) => - traverse(expr) - - case AsInstanceOf(expr, cls) => - traverse(expr) - - case Unbox(expr, charCode) => - traverse(expr) - - case GetClass(expr) => - traverse(expr) - - case CallHelper(helper, args) => - args foreach traverse - - // JavaScript expressions - - case JSNew(ctor, args) => - traverse(ctor) - args foreach traverse - - case JSDotSelect(qualifier, item) => - traverse(qualifier) - - case JSBracketSelect(qualifier, item) => - traverse(qualifier) - traverse(item) - - case JSFunctionApply(fun, args) => - traverse(fun) - args foreach traverse - - case JSDotMethodApply(receiver, method, args) => - traverse(receiver) - args foreach traverse - - case JSBracketMethodApply(receiver, method, args) => - traverse(receiver) - traverse(method) - args foreach traverse - - case JSDelete(prop) => - traverse(prop) - - case JSUnaryOp(op, lhs) => - traverse(lhs) - - case JSBinaryOp(op, lhs, rhs) => - traverse(lhs) - traverse(rhs) - - case JSArrayConstr(items) => - items foreach traverse - - case JSObjectConstr(fields) => - fields foreach { f => traverse(f._2) } - - // Atomic expressions - - case Closure(captureParams, params, body, captureValues) => - traverse(body) - captureValues.foreach(traverse) - - // Classes - - case ClassDef(name, kind, parent, ancestors, defs) => - defs foreach traverse - - case MethodDef(name, args, resultType, body) => - traverse(body) - - case PropertyDef(name, getterBody, setterArg, setterBody) => - traverse(getterBody) - traverse(setterBody) - - case ConstructorExportDef(fullName, args, body) => - traverse(body) - - // Trees that need not be traversed - - case _:Skip | _:Continue | _:LoadModule | _:JSEnvInfo | - _:Literal | _:VarRef | _:This | _:ModuleExportDef | EmptyTree => - - case _ => - sys.error(s"Invalid tree in traverse() of class ${tree.getClass}") - } - } - -} diff --git a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Trees.scala b/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Trees.scala deleted file mode 100644 index 4f58ece..0000000 --- a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Trees.scala +++ /dev/null @@ -1,536 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ __ ____ Scala.js IR ** -** / __/ __// _ | / / / _ | __ / // __/ (c) 2014, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ ** -** /____/\___/_/ |_/____/_/ | |__/ /____/ ** -** |/____/ ** -\* */ - - -package scala.scalajs.ir - -import scala.annotation.switch - -import Position.NoPosition -import Types._ - -object Trees { - /** AST node of the IR. */ - abstract sealed class Tree { - val pos: Position - val tpe: Type - - def show: String = { - val writer = new java.io.StringWriter - val printer = new Printers.IRTreePrinter(writer) - printer.printTree(this) - writer.toString() - } - } - - case object EmptyTree extends Tree { - val pos = NoPosition - val tpe = NoType - } - - // Identifiers and properties - - sealed trait PropertyName { - def name: String - def pos: Position - } - - case class Ident(name: String, originalName: Option[String])( - implicit val pos: Position) extends PropertyName { - requireValidIdent(name) - } - - object Ident { - def apply(name: String)(implicit pos: Position): Ident = - new Ident(name, Some(name)) - } - - final def isValidIdentifier(name: String): Boolean = { - val c = name.head - (c == '$' || c == '_' || c.isUnicodeIdentifierStart) && - name.tail.forall(c => (c == '$') || c.isUnicodeIdentifierPart) && - !isKeyword(name) - } - - @inline final def requireValidIdent(name: String) { - require(isValidIdentifier(name), s"${name} is not a valid identifier") - } - - final val isKeyword: Set[String] = Set( - // Value keywords - "true", "false", "null", "undefined", - - // Current JavaScript keywords - "break", "case", "catch", "continue", "debugger", "default", "delete", - "do", "else", "finally", "for", "function", "if", "in", "instanceof", - "new", "return", "switch", "this", "throw", "try", "typeof", "var", - "void", "while", "with", - - // Future reserved keywords - "class", "const", "enum", "export", "extends", "import", "super", - - // Future reserved keywords in Strict mode - "implements", "interface", "let", "package", "private", "protected", - "public", "static", "yield", - - // Other reserved keywords found on the Web but not in the spec - "abstract", "boolean", "byte", "char", "double", "final", "float", - "goto", "int", "long", "native", "short", "synchronized", "throws", - "transient", "volatile" - ) - - // Definitions - - case class VarDef(name: Ident, vtpe: Type, mutable: Boolean, rhs: Tree)(implicit val pos: Position) extends Tree { - val tpe = NoType // cannot be in expression position - - def ref(implicit pos: Position): VarRef = - VarRef(name, mutable = mutable)(vtpe) - } - - case class ParamDef(name: Ident, ptpe: Type, mutable: Boolean)(implicit val pos: Position) extends Tree { - val tpe = NoType - - def ref(implicit pos: Position): VarRef = - VarRef(name, mutable = mutable)(ptpe) - } - - // Control flow constructs - - case class Skip()(implicit val pos: Position) extends Tree { - val tpe = NoType // cannot be in expression position - } - - class Block private (val stats: List[Tree])(implicit val pos: Position) extends Tree { - val tpe = stats.last.tpe - - override def toString(): String = - stats.mkString("Block(", ",", ")") - } - - object Block { - def apply(stats: List[Tree])(implicit pos: Position): Tree = { - val flattenedStats = stats flatMap { - case Skip() => Nil - case Block(subStats) => subStats - case other => other :: Nil - } - flattenedStats match { - case Nil => Skip() - case only :: Nil => only - case _ => new Block(flattenedStats) - } - } - - def apply(stats: Tree*)(implicit pos: Position): Tree = - apply(stats.toList) - - def unapply(block: Block): Some[List[Tree]] = Some(block.stats) - } - - case class Labeled(label: Ident, tpe: Type, body: Tree)(implicit val pos: Position) extends Tree - - case class Assign(lhs: Tree, rhs: Tree)(implicit val pos: Position) extends Tree { - require(lhs match { - case _:VarRef | _:Select | _:ArraySelect | - _:JSDotSelect | _:JSBracketSelect => true - case _ => false - }, s"Invalid lhs for Assign: $lhs") - - val tpe = NoType // cannot be in expression position - } - - case class Return(expr: Tree, label: Option[Ident] = None)(implicit val pos: Position) extends Tree { - val tpe = NothingType - } - - case class If(cond: Tree, thenp: Tree, elsep: Tree)(val tpe: Type)(implicit val pos: Position) extends Tree - - case class While(cond: Tree, body: Tree, label: Option[Ident] = None)(implicit val pos: Position) extends Tree { - // cannot be in expression position, unless it is infinite - val tpe = cond match { - case BooleanLiteral(true) => NothingType - case _ => NoType - } - } - - case class DoWhile(body: Tree, cond: Tree, label: Option[Ident] = None)(implicit val pos: Position) extends Tree { - val tpe = NoType // cannot be in expression position - } - - case class Try(block: Tree, errVar: Ident, handler: Tree, finalizer: Tree)(val tpe: Type)(implicit val pos: Position) extends Tree - - case class Throw(expr: Tree)(implicit val pos: Position) extends Tree { - val tpe = NothingType - } - - case class Continue(label: Option[Ident] = None)(implicit val pos: Position) extends Tree { - val tpe = NothingType - } - - /** A break-free switch (without fallthrough behavior). - * Unlike a JavaScript switch, it can be used in expression position. - * It supports alternatives explicitly (hence the List[Tree] in cases), - * whereas in a switch one would use the fallthrough behavior to - * implement alternatives. - * (This is not a pattern matching construct like in Scala.) - */ - case class Match(selector: Tree, cases: List[(List[Literal], Tree)], default: Tree)(val tpe: Type)(implicit val pos: Position) extends Tree - - case class Debugger()(implicit val pos: Position) extends Tree { - val tpe = NoType // cannot be in expression position - } - - // Scala expressions - - case class New(cls: ClassType, ctor: Ident, args: List[Tree])(implicit val pos: Position) extends Tree { - val tpe = cls - } - - case class LoadModule(cls: ClassType)(implicit val pos: Position) extends Tree { - val tpe = cls - } - - case class StoreModule(cls: ClassType, value: Tree)(implicit val pos: Position) extends Tree { - val tpe = NoType // cannot be in expression position - } - - case class Select(qualifier: Tree, item: Ident, mutable: Boolean)(val tpe: Type)(implicit val pos: Position) extends Tree - - case class Apply(receiver: Tree, method: Ident, args: List[Tree])(val tpe: Type)(implicit val pos: Position) extends Tree - - case class StaticApply(receiver: Tree, cls: ClassType, method: Ident, args: List[Tree])(val tpe: Type)(implicit val pos: Position) extends Tree - - case class TraitImplApply(impl: ClassType, method: Ident, args: List[Tree])(val tpe: Type)(implicit val pos: Position) extends Tree - - /** Unary operation (always preserves pureness). */ - case class UnaryOp(op: UnaryOp.Code, lhs: Tree)(implicit val pos: Position) extends Tree { - import UnaryOp._ - val tpe = (op: @switch) match { - case `typeof` => StringType - case LongToInt | DoubleToInt => IntType - case IntToLong | DoubleToLong => LongType - case DoubleToFloat => FloatType - case LongToDouble => DoubleType - case Boolean_! => BooleanType - } - } - - object UnaryOp { - /** Codes are raw Ints to be able to write switch matches on them. */ - type Code = Int - - final val typeof = 1 - - final val Boolean_! = 2 - - final val IntToLong = 3 - final val LongToInt = 4 - final val LongToDouble = 5 - final val DoubleToInt = 6 - final val DoubleToFloat = 7 - final val DoubleToLong = 8 - } - - /** Binary operation (always preserves pureness). */ - case class BinaryOp(op: BinaryOp.Code, lhs: Tree, rhs: Tree)(implicit val pos: Position) extends Tree { - import BinaryOp._ - val tpe = (op: @switch) match { - case === | !== | - `in` | `instanceof` | - Num_== | Num_!= | Num_< | Num_<= | Num_> | Num_>= | - Long_== | Long_!= | Long_< | Long_<= | Long_> | Long_>= | - Boolean_== | Boolean_!= | Boolean_| | Boolean_& => - BooleanType - case String_+ => - StringType - case Int_+ | Int_- | Int_* | Int_/ | Int_% | - Int_| | Int_& | Int_^ | Int_<< | Int_>>> | Int_>> => - IntType - case Float_+ | Float_- | Float_* | Float_/ | Float_% => - FloatType - case Double_+ | Double_- | Double_* | Double_/ | Double_% => - DoubleType - case Long_+ | Long_- | Long_* | Long_/ | Long_% | - Long_| | Long_& | Long_^ | Long_<< | Long_>>> | Long_>> => - LongType - } - } - - object BinaryOp { - /** Codes are raw Ints to be able to write switch matches on them. */ - type Code = Int - - final val === = 1 - final val !== = 2 - - final val String_+ = 3 - - final val in = 4 - final val instanceof = 5 - - final val Int_+ = 6 - final val Int_- = 7 - final val Int_* = 8 - final val Int_/ = 9 - final val Int_% = 10 - - final val Int_| = 11 - final val Int_& = 12 - final val Int_^ = 13 - final val Int_<< = 14 - final val Int_>>> = 15 - final val Int_>> = 16 - - final val Float_+ = 17 - final val Float_- = 18 - final val Float_* = 19 - final val Float_/ = 20 - final val Float_% = 21 - - final val Double_+ = 22 - final val Double_- = 23 - final val Double_* = 24 - final val Double_/ = 25 - final val Double_% = 26 - - final val Num_== = 27 - final val Num_!= = 28 - final val Num_< = 29 - final val Num_<= = 30 - final val Num_> = 31 - final val Num_>= = 32 - - final val Long_+ = 33 - final val Long_- = 34 - final val Long_* = 35 - final val Long_/ = 36 - final val Long_% = 37 - - final val Long_| = 38 - final val Long_& = 39 - final val Long_^ = 40 - final val Long_<< = 41 - final val Long_>>> = 42 - final val Long_>> = 43 - - final val Long_== = 44 - final val Long_!= = 45 - final val Long_< = 46 - final val Long_<= = 47 - final val Long_> = 48 - final val Long_>= = 49 - - final val Boolean_== = 50 - final val Boolean_!= = 51 - final val Boolean_| = 52 - final val Boolean_& = 53 - } - - case class NewArray(tpe: ArrayType, lengths: List[Tree])(implicit val pos: Position) extends Tree { - require(lengths.nonEmpty && lengths.size <= tpe.dimensions) - } - - case class ArrayValue(tpe: ArrayType, elems: List[Tree])(implicit val pos: Position) extends Tree - - case class ArrayLength(array: Tree)(implicit val pos: Position) extends Tree { - val tpe = IntType - } - - case class ArraySelect(array: Tree, index: Tree)(val tpe: Type)(implicit val pos: Position) extends Tree - - case class RecordValue(tpe: RecordType, elems: List[Tree])(implicit val pos: Position) extends Tree - - case class IsInstanceOf(expr: Tree, cls: ReferenceType)(implicit val pos: Position) extends Tree { - val tpe = BooleanType - } - - case class AsInstanceOf(expr: Tree, cls: ReferenceType)(implicit val pos: Position) extends Tree { - val tpe = cls match { - case ClassType(Definitions.RuntimeNullClass) => NullType - case ClassType(Definitions.RuntimeNothingClass) => NothingType - case _ => cls - } - } - - case class Unbox(expr: Tree, charCode: Char)(implicit val pos: Position) extends Tree { - val tpe = (charCode: @switch) match { - case 'Z' => BooleanType - case 'B' | 'S' | 'I' => IntType - case 'J' => LongType - case 'F' => FloatType - case 'D' => DoubleType - } - } - - case class GetClass(expr: Tree)(implicit val pos: Position) extends Tree { - val tpe = ClassType(Definitions.ClassClass) - } - - case class CallHelper(helper: String, args: List[Tree])(val tpe: Type)(implicit val pos: Position) extends Tree - - object CallHelper { - def apply(helper: String, args: Tree*)(tpe: Type)( - implicit pos: Position): CallHelper = { - CallHelper(helper, args.toList)(tpe) - } - } - - // JavaScript expressions - - case class JSNew(ctor: Tree, args: List[Tree])(implicit val pos: Position) extends Tree { - val tpe = AnyType - } - - case class JSDotSelect(qualifier: Tree, item: Ident)(implicit val pos: Position) extends Tree { - val tpe = AnyType - } - - case class JSBracketSelect(qualifier: Tree, item: Tree)(implicit val pos: Position) extends Tree { - val tpe = AnyType - } - - case class JSFunctionApply(fun: Tree, args: List[Tree])(implicit val pos: Position) extends Tree { - val tpe = AnyType - } - - case class JSDotMethodApply(receiver: Tree, method: Ident, args: List[Tree])(implicit val pos: Position) extends Tree { - val tpe = AnyType - } - - case class JSBracketMethodApply(receiver: Tree, method: Tree, args: List[Tree])(implicit val pos: Position) extends Tree { - val tpe = AnyType - } - - case class JSDelete(prop: Tree)(implicit val pos: Position) extends Tree { - require(prop match { - case _:JSDotSelect | _:JSBracketSelect => true - case _ => false - }, s"Invalid prop for JSDelete: $prop") - - val tpe = NoType // cannot be in expression position - } - - /** Unary operation (always preserves pureness). - * - * Operations which do not preserve pureness are not allowed in this tree. - * These are notably ++ and -- - */ - case class JSUnaryOp(op: String, lhs: Tree)(implicit val pos: Position) extends Tree { - val tpe = AnyType - } - - /** Binary operation (always preserves pureness). - * - * Operations which do not preserve pureness are not allowed in this tree. - * These are notably +=, -=, *=, /= and %= - */ - case class JSBinaryOp(op: String, lhs: Tree, rhs: Tree)(implicit val pos: Position) extends Tree { - val tpe = AnyType - } - - case class JSArrayConstr(items: List[Tree])(implicit val pos: Position) extends Tree { - val tpe = AnyType - } - - case class JSObjectConstr(fields: List[(PropertyName, Tree)])(implicit val pos: Position) extends Tree { - val tpe = AnyType - } - - case class JSEnvInfo()(implicit val pos: Position) extends Tree { - val tpe = AnyType - } - - // Literals - - /** Marker for literals. Literals are always pure. */ - sealed trait Literal extends Tree - - case class Undefined()(implicit val pos: Position) extends Literal { - val tpe = UndefType - } - - case class UndefinedParam()(val tpe: Type)(implicit val pos: Position) extends Literal - - case class Null()(implicit val pos: Position) extends Literal { - val tpe = NullType - } - - case class BooleanLiteral(value: Boolean)(implicit val pos: Position) extends Literal { - val tpe = BooleanType - } - - case class IntLiteral(value: Int)(implicit val pos: Position) extends Literal { - val tpe = IntType - } - - case class LongLiteral(value: Long)(implicit val pos: Position) extends Literal { - val tpe = LongType - } - - case class FloatLiteral(value: Float)(implicit val pos: Position) extends Literal { - val tpe = FloatType - } - - case class DoubleLiteral(value: Double)(implicit val pos: Position) extends Literal { - val tpe = DoubleType - } - - case class StringLiteral(value: String)( - implicit val pos: Position) extends Literal with PropertyName { - val tpe = StringType - override def name = value - } - - case class ClassOf(cls: ReferenceType)(implicit val pos: Position) extends Literal { - val tpe = ClassType(Definitions.ClassClass) - } - - // Atomic expressions - - case class VarRef(ident: Ident, mutable: Boolean)(val tpe: Type)(implicit val pos: Position) extends Tree - - case class This()(val tpe: Type)(implicit val pos: Position) extends Tree - - /** Closure with explicit captures. - * The n captures map to the n first formal arguments. - */ - case class Closure(captureParams: List[ParamDef], params: List[ParamDef], - body: Tree, captureValues: List[Tree])(implicit val pos: Position) extends Tree { - val tpe = AnyType - } - - // Classes - - case class ClassDef(name: Ident, kind: ClassKind, parent: Option[Ident], ancestors: List[Ident], defs: List[Tree])(implicit val pos: Position) extends Tree { - val tpe = NoType - } - - case class MethodDef(name: PropertyName, args: List[ParamDef], resultType: Type, body: Tree)( - val hash: Option[TreeHash])(implicit val pos: Position) extends Tree { - val tpe = NoType - } - - case class PropertyDef(name: PropertyName, getterBody: Tree, setterArg: ParamDef, setterBody: Tree)(implicit val pos: Position) extends Tree { - val tpe = NoType - } - - case class ConstructorExportDef(name: String, args: List[ParamDef], body: Tree)(implicit val pos: Position) extends Tree { - val tpe = NoType - } - - case class ModuleExportDef(fullName: String)(implicit val pos: Position) extends Tree { - val tpe = NoType - } - - /** A hash of a tree (usually a MethodDef). Contains two SHA-1 hashes */ - final class TreeHash(val treeHash: Array[Byte], val posHash: Array[Byte]) { - assert(treeHash.length == 20) - assert(posHash.length == 20) - } -} diff --git a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Types.scala b/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Types.scala deleted file mode 100644 index 4af493a..0000000 --- a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Types.scala +++ /dev/null @@ -1,182 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ __ ____ Scala.js IR ** -** / __/ __// _ | / / / _ | __ / // __/ (c) 2014, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ ** -** /____/\___/_/ |_/____/_/ | |__/ /____/ ** -** |/____/ ** -\* */ - - -package scala.scalajs.ir - -import scala.annotation.tailrec - -object Types { - - /** Type of an expression in the IR. */ - abstract sealed class Type { - def show(): String = { - val writer = new java.io.StringWriter - val printer = new Printers.IRTreePrinter(writer) - printer.printType(this) - writer.toString() - } - } - - /** Any type (the top type of this type system). - * A variable of this type can contain any value, including `undefined` - * and `null` and any raw JS value. This type supports a very limited set - * of Scala operations, the ones common to all values. Basically only - * reference equality tests and instance tests. It also supports all - * JavaScript operations, since all Scala objects are also genuine - * JavaScript objects. - * The type java.lang.Object in the back-end maps to [[AnyType]] because it - * can hold raw JS values (not only instances of Scala.js classes). - */ - case object AnyType extends Type - - /** Nothing type (the bottom type of this type system). - * Expressions from which one can never come back are typed as [[Nothing]]. - * For example, `throw` and `return`. - */ - case object NothingType extends Type - - /** The type of `undefined`. */ - case object UndefType extends Type - - /** Boolean type. - * It does not accept `null` nor `undefined`. - */ - case object BooleanType extends Type - - /** 32-bit signed integer type. - * It does not accept `null` nor `undefined`. - */ - case object IntType extends Type - - /** 64-bit signed integer type. - * It does not accept `null` nor `undefined`. - */ - case object LongType extends Type - - /** Float type (32-bit). - * It does not accept `null` nor `undefined`. - */ - case object FloatType extends Type - - /** Double type (64-bit). - * It does not accept `null` nor `undefined`. - */ - case object DoubleType extends Type - - /** String type. - * It does not accept `null` nor `undefined`. - */ - case object StringType extends Type - - /** The type of `null`. - * It does not accept `undefined`. - * The null type is a subtype of all class types and array types. - */ - case object NullType extends Type - - /** Reference types (allowed for classOf[], is/asInstanceOf[]). */ - sealed abstract class ReferenceType extends Type - - /** Class (or interface) type. */ - final case class ClassType(className: String) extends ReferenceType - - /** Array type. */ - final case class ArrayType(baseClassName: String, dimensions: Int) extends ReferenceType - - object ArrayType { - def apply(innerType: ReferenceType): ArrayType = innerType match { - case ClassType(className) => ArrayType(className, 1) - case ArrayType(className, dim) => ArrayType(className, dim + 1) - } - } - - /** Record type. - * Used by the optimizer to inline classes as records with multiple fields. - * They are desugared as several local variables by JSDesugaring. - * Record types cannot cross method boundaries, so they cannot appear as - * the type of fields or parameters, nor as result types of methods. - * The compiler itself never generates record types. - */ - final case class RecordType(fields: List[RecordType.Field]) extends Type { - def findField(name: String): RecordType.Field = - fields.find(_.name == name).get - } - - object RecordType { - final case class Field(name: String, originalName: Option[String], - tpe: Type, mutable: Boolean) - } - - /** No type. */ - case object NoType extends Type - - /** Tests whether a type `lhs` is a subtype of `rhs` (or equal). - * [[NoType]] is never a subtype or supertype of anything (including - * itself). All other types are subtypes of themselves. - * @param isSubclass A function testing whether a class/interface is a - * subclass of another class/interface. - */ - def isSubtype(lhs: Type, rhs: Type)( - isSubclass: (String, String) => Boolean): Boolean = { - import Definitions._ - - (lhs != NoType && rhs != NoType) && { - (lhs == rhs) || - ((lhs, rhs) match { - case (_, AnyType) => true - case (NothingType, _) => true - - case (ClassType(lhsClass), ClassType(rhsClass)) => - isSubclass(lhsClass, rhsClass) - - case (NullType, ClassType(_)) => true - case (NullType, ArrayType(_, _)) => true - - case (UndefType, ClassType(cls)) => - isSubclass(BoxedUnitClass, cls) - case (BooleanType, ClassType(cls)) => - isSubclass(BoxedBooleanClass, cls) - case (IntType, ClassType(cls)) => - isSubclass(BoxedIntegerClass, cls) || - cls == BoxedByteClass || - cls == BoxedShortClass || - cls == BoxedDoubleClass - case (LongType, ClassType(cls)) => - isSubclass(BoxedLongClass, cls) - case (FloatType, ClassType(cls)) => - isSubclass(BoxedFloatClass, cls) || - cls == BoxedDoubleClass - case (DoubleType, ClassType(cls)) => - isSubclass(BoxedDoubleClass, cls) - case (StringType, ClassType(cls)) => - isSubclass(StringClass, cls) - - case (IntType, DoubleType) => true - case (FloatType, DoubleType) => true - - case (ArrayType(lhsBase, lhsDims), ArrayType(rhsBase, rhsDims)) => - if (lhsDims < rhsDims) { - false // because Array[A] </: Array[Array[A]] - } else if (lhsDims > rhsDims) { - rhsBase == ObjectClass // because Array[Array[A]] <: Array[Object] - } else { // lhsDims == rhsDims - // lhsBase must be <: rhsBase - if (isPrimitiveClass(lhsBase) || isPrimitiveClass(rhsBase)) { - lhsBase == rhsBase - } else { - isSubclass(lhsBase, rhsBase) - } - } - - case _ => - false - }) - } - } -} diff --git a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Utils.scala b/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Utils.scala deleted file mode 100644 index d4769dc..0000000 --- a/examples/scala-js/ir/src/main/scala/scala/scalajs/ir/Utils.scala +++ /dev/null @@ -1,110 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ __ ____ Scala.js IR ** -** / __/ __// _ | / / / _ | __ / // __/ (c) 2014, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ ** -** /____/\___/_/ |_/____/_/ | |__/ /____/ ** -** |/____/ ** -\* */ - - -package scala.scalajs.ir - -import java.net.URI - -object Utils { - - /** Relativize target URI w.r.t. base URI */ - def relativize(base0: URI, trgt0: URI): URI = { - val base = base0.normalize - val trgt = trgt0.normalize - - if (base.isOpaque || !base.isAbsolute || base.getRawPath == null || - trgt.isOpaque || !trgt.isAbsolute || trgt.getRawPath == null || - base.getScheme != trgt.getScheme || - base.getRawAuthority != trgt.getRawAuthority) - trgt - else { - val trgtCmps = trgt.getRawPath.split('/') - val baseCmps = base.getRawPath.split('/') - - val prefixLen = (trgtCmps zip baseCmps).takeWhile(t => t._1 == t._2).size - - val newPathCmps = - List.fill(baseCmps.size - prefixLen)("..") ++ trgtCmps.drop(prefixLen) - - val newPath = newPathCmps.mkString("/") - - // Relative URI does not have scheme or authority - new URI(null, null, newPath, trgt.getRawQuery, trgt.getRawFragment) - } - } - - /** Adds an empty authority to URIs with the "file" scheme without authority. - * Some browsers don't fetch URIs without authority correctly. - */ - def fixFileURI(uri: URI): URI = - if (uri.getScheme() != "file" || uri.getAuthority() != null) uri - else new URI("file", "", uri.getPath(), uri.getQuery(), uri.getFragment()) - - def escapeJS(str: String): String = { - /* Note that Java and JavaScript happen to use the same encoding for - * Unicode, namely UTF-16, which means that 1 char from Java always equals - * 1 char in JavaScript. */ - val builder = new StringBuilder - str foreach { - case '\\' => builder.append("\\\\") - case '"' => builder.append("\\\"") - case '\u0007' => builder.append("\\a") - case '\u0008' => builder.append("\\b") - case '\u0009' => builder.append("\\t") - case '\u000A' => builder.append("\\n") - case '\u000B' => builder.append("\\v") - case '\u000C' => builder.append("\\f") - case '\u000D' => builder.append("\\r") - case c => - if (c >= 32 && c <= 126) builder.append(c.toChar) // ASCII printable characters - else builder.append(f"\\u$c%04x") - } - builder.result() - } - - /** A ByteArrayOutput stream that allows to jump back to a given - * position and complete some bytes. Methods must be called in the - * following order only: - * - [[markJump]] - * - [[jumpBack]] - * - [[continue]] - */ - private[ir] class JumpBackByteArrayOutputStream - extends java.io.ByteArrayOutputStream { - protected var jumpBackPos: Int = -1 - protected var headPos: Int = -1 - - /** Marks the current location for a jumpback */ - def markJump(): Unit = { - assert(jumpBackPos == -1) - assert(headPos == -1) - jumpBackPos = count - } - - /** Jumps back to the mark. Returns the number of bytes jumped */ - def jumpBack(): Int = { - assert(jumpBackPos >= 0) - assert(headPos == -1) - val jumped = count - jumpBackPos - headPos = count - count = jumpBackPos - jumpBackPos = -1 - jumped - } - - /** Continues to write at the head. */ - def continue(): Unit = { - assert(jumpBackPos == -1) - assert(headPos >= 0) - count = headPos - headPos = -1 - } - } - -} |