diff options
Diffstat (limited to 'examples/scala-js/compiler/src/main/scala/scala/scalajs/compiler/JSEncoding.scala')
-rw-r--r-- | examples/scala-js/compiler/src/main/scala/scala/scalajs/compiler/JSEncoding.scala | 261 |
1 files changed, 0 insertions, 261 deletions
diff --git a/examples/scala-js/compiler/src/main/scala/scala/scalajs/compiler/JSEncoding.scala b/examples/scala-js/compiler/src/main/scala/scala/scalajs/compiler/JSEncoding.scala deleted file mode 100644 index bc7f8be..0000000 --- a/examples/scala-js/compiler/src/main/scala/scala/scalajs/compiler/JSEncoding.scala +++ /dev/null @@ -1,261 +0,0 @@ -/* Scala.js compiler - * Copyright 2013 LAMP/EPFL - * @author Sébastien Doeraene - */ - -package scala.scalajs.compiler - -import scala.collection.mutable - -import scala.tools.nsc._ - -import scala.scalajs.ir -import ir.{Trees => js, Types => jstpe} - -import util.ScopedVar -import ScopedVar.withScopedVars - -/** Encoding of symbol names for JavaScript - * - * Some issues that this encoding solves: - * * Overloading: encode the full signature in the JS name - * * Same scope for fields and methods of a class - * * Global access to classes and modules (by their full name) - * - * @author Sébastien Doeraene - */ -trait JSEncoding extends SubComponent { self: GenJSCode => - import global._ - import jsAddons._ - - /** Outer separator string (between parameter types) */ - final val OuterSep = "__" - - /** Inner separator character (replace dots in full names) */ - final val InnerSep = "_" - - /** Name given to the local Scala.js environment variable */ - final val ScalaJSEnvironmentName = "ScalaJS" - - /** Name given to all exported stuff of a class for DCE */ - final val dceExportName = "<exported>" - - // Fresh local name generator ---------------------------------------------- - - private val usedLocalNames = new ScopedVar[mutable.Set[String]] - private val localSymbolNames = new ScopedVar[mutable.Map[Symbol, String]] - private val isKeywordOrReserved = - js.isKeyword ++ Seq("arguments", "eval", ScalaJSEnvironmentName) - - def withNewLocalNameScope[A](body: => A): A = - withScopedVars( - usedLocalNames := mutable.Set.empty, - localSymbolNames := mutable.Map.empty - )(body) - - private def freshName(base: String = "x"): String = { - var suffix = 1 - var longName = base - while (usedLocalNames(longName) || isKeywordOrReserved(longName)) { - suffix += 1 - longName = base+"$"+suffix - } - usedLocalNames += longName - longName - } - - def freshLocalIdent()(implicit pos: ir.Position): js.Ident = - js.Ident(freshName(), None) - - def freshLocalIdent(base: String)(implicit pos: ir.Position): js.Ident = - js.Ident(freshName(base), Some(base)) - - private def localSymbolName(sym: Symbol): String = - localSymbolNames.getOrElseUpdate(sym, freshName(sym.name.toString)) - - // Encoding methods ---------------------------------------------------------- - - def encodeLabelSym(sym: Symbol)(implicit pos: Position): js.Ident = { - require(sym.isLabel, "encodeLabelSym called with non-label symbol: " + sym) - js.Ident(localSymbolName(sym), Some(sym.unexpandedName.decoded)) - } - - private lazy val allRefClasses: Set[Symbol] = { - import definitions._ - (Set(ObjectRefClass, VolatileObjectRefClass) ++ - refClass.values ++ volatileRefClass.values) - } - - def encodeFieldSym(sym: Symbol)(implicit pos: Position): js.Ident = { - require(sym.owner.isClass && sym.isTerm && !sym.isMethod && !sym.isModule, - "encodeFieldSym called with non-field symbol: " + sym) - - val name0 = encodeMemberNameInternal(sym) - val name = - if (name0.charAt(name0.length()-1) != ' ') name0 - else name0.substring(0, name0.length()-1) - - /* We have to special-case fields of Ref types (IntRef, ObjectRef, etc.) - * because they are emitted as private by our .scala source files, but - * they are considered public at use site since their symbols come from - * Java-emitted .class files. - */ - val idSuffix = - if (sym.isPrivate || allRefClasses.contains(sym.owner)) - sym.owner.ancestors.count(!_.isInterface).toString - else - "f" - - val encodedName = name + "$" + idSuffix - js.Ident(mangleJSName(encodedName), Some(sym.unexpandedName.decoded)) - } - - def encodeMethodSym(sym: Symbol, reflProxy: Boolean = false) - (implicit pos: Position): js.Ident = { - val (encodedName, paramsString) = encodeMethodNameInternal(sym, reflProxy) - js.Ident(encodedName + paramsString, - Some(sym.unexpandedName.decoded + paramsString)) - } - - def encodeMethodName(sym: Symbol, reflProxy: Boolean = false): String = { - val (encodedName, paramsString) = encodeMethodNameInternal(sym, reflProxy) - encodedName + paramsString - } - - /** Encodes a method symbol of java.lang.String for use in RuntimeString. - * - * This basically means adding an initial parameter of type - * java.lang.String, which is the `this` parameter. - */ - def encodeRTStringMethodSym(sym: Symbol)( - implicit pos: Position): (Symbol, js.Ident) = { - require(sym.isMethod, "encodeMethodSym called with non-method symbol: " + sym) - require(sym.owner == definitions.StringClass) - require(!sym.isClassConstructor && !sym.isPrivate) - - val (encodedName, paramsString) = - encodeMethodNameInternal(sym, inRTClass = true) - val methodIdent = js.Ident(encodedName + paramsString, - Some(sym.unexpandedName.decoded + paramsString)) - - (jsDefinitions.RuntimeStringModuleClass, methodIdent) - } - - private def encodeMethodNameInternal(sym: Symbol, - reflProxy: Boolean = false, - inRTClass: Boolean = false): (String, String) = { - require(sym.isMethod, "encodeMethodSym called with non-method symbol: " + sym) - - def name = encodeMemberNameInternal(sym) - - val encodedName = { - if (sym.isClassConstructor) - "init" + InnerSep - else if (foreignIsImplClass(sym.owner)) - encodeClassFullName(sym.owner) + OuterSep + name - else if (sym.isPrivate) - mangleJSName(name) + OuterSep + "p" + - sym.owner.ancestors.count(!_.isInterface).toString - else - mangleJSName(name) - } - - val paramsString = makeParamsString(sym, reflProxy, inRTClass) - - (encodedName, paramsString) - } - - def encodeStaticMemberSym(sym: Symbol)(implicit pos: Position): js.Ident = { - require(sym.isStaticMember, - "encodeStaticMemberSym called with non-static symbol: " + sym) - js.Ident( - mangleJSName(encodeMemberNameInternal(sym)) + - makeParamsString(List(internalName(sym.tpe))), - Some(sym.unexpandedName.decoded)) - } - - def encodeLocalSym(sym: Symbol)(implicit pos: Position): js.Ident = { - require(!sym.owner.isClass && sym.isTerm && !sym.isMethod && !sym.isModule, - "encodeLocalSym called with non-local symbol: " + sym) - js.Ident(mangleJSName(localSymbolName(sym)), Some(sym.unexpandedName.decoded)) - } - - def foreignIsImplClass(sym: Symbol): Boolean = - sym.isModuleClass && nme.isImplClassName(sym.name) - - def encodeClassType(sym: Symbol): jstpe.Type = { - if (sym == definitions.ObjectClass) jstpe.AnyType - else if (isRawJSType(sym.toTypeConstructor)) jstpe.AnyType - else { - assert(sym != definitions.ArrayClass, - "encodeClassType() cannot be called with ArrayClass") - jstpe.ClassType(encodeClassFullName(sym)) - } - } - - def encodeClassFullNameIdent(sym: Symbol)(implicit pos: Position): js.Ident = { - js.Ident(encodeClassFullName(sym), Some(sym.fullName)) - } - - def encodeModuleFullNameIdent(sym: Symbol)(implicit pos: Position): js.Ident = { - js.Ident(encodeModuleFullName(sym), Some(sym.fullName)) - } - - def encodeClassFullName(sym: Symbol): String = { - ir.Definitions.encodeClassName( - sym.fullName + (if (needsModuleClassSuffix(sym)) "$" else "")) - } - - def needsModuleClassSuffix(sym: Symbol): Boolean = - sym.isModuleClass && !foreignIsImplClass(sym) - - def encodeModuleFullName(sym: Symbol): String = - ir.Definitions.encodeClassName(sym.fullName + "$").dropRight(1) - - private def encodeMemberNameInternal(sym: Symbol): String = - sym.name.toString.replace("_", "$und") - - // Encoding of method signatures - - private def makeParamsString(sym: Symbol, reflProxy: Boolean, - inRTClass: Boolean): String = { - val tpe = sym.tpe - val paramTypeNames = tpe.params map (p => internalName(p.tpe)) - val paramAndResultTypeNames = { - if (sym.isClassConstructor) - paramTypeNames - else if (reflProxy) - paramTypeNames :+ "" - else { - val paramAndResultTypeNames0 = - paramTypeNames :+ internalName(tpe.resultType) - if (!inRTClass) paramAndResultTypeNames0 - else internalName(sym.owner.toTypeConstructor) +: paramAndResultTypeNames0 - } - } - makeParamsString(paramAndResultTypeNames) - } - - private def makeParamsString(paramAndResultTypeNames: List[String]) = - paramAndResultTypeNames.mkString(OuterSep, OuterSep, "") - - /** Computes the internal name for a type. */ - private def internalName(tpe: Type): String = internalName(toTypeKind(tpe)) - - private def internalName(kind: TypeKind): String = kind match { - case VOID => "V" - case kind: ValueTypeKind => kind.primitiveCharCode.toString() - case NOTHING => ir.Definitions.RuntimeNothingClass - case NULL => ir.Definitions.RuntimeNullClass - case REFERENCE(cls) => encodeClassFullName(cls) - case ARRAY(elem) => "A"+internalName(elem) - } - - /** mangles names that are illegal in JavaScript by prepending a $ - * also mangles names that would collide with these mangled names - */ - private def mangleJSName(name: String) = - if (js.isKeyword(name) || name(0).isDigit || name(0) == '$') - "$" + name - else name -} |