Merged the dotnet-scala branch

git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@9896 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
This commit is contained in:
mihaylov 2007-02-06 16:06:34 +00:00
parent 904b292757
commit d7a62c5089
32 changed files with 3742 additions and 164 deletions

View File

@ -39,6 +39,7 @@ PROPERTIES
<property name="lib.starr.jar" value="${lib.dir}/scala-library.jar"/>
<property name="comp.starr.jar" value="${lib.dir}/scala-compiler.jar"/>
<property name="fjbg.jar" value="${lib.dir}/fjbg.jar"/>
<property name="msil.jar" value="${lib.dir}/msil.jar"/>
<property name="ant.jar" value="${ant.home}/lib/ant.jar"/>
<property name="ant-contrib.jar" value="${lib.dir}/ant-contrib.jar"/>
<!-- Sets location of build folders -->
@ -77,6 +78,7 @@ INITIALISATION
<available file="${lib.starr.jar}"/>
<available file="${comp.starr.jar}"/>
<available file="${fjbg.jar}"/>
<available file="${msil.jar}"/>
<available file="${ant-contrib.jar}"/>
</and></not></condition>
</fail>
@ -206,6 +208,7 @@ SETUP
<pathelement location="${locker.dir}/lib/library"/>
<pathelement location="${locker.dir}/lib/compiler"/>
<pathelement location="${fjbg.jar}"/>
<pathelement location="${msil.jar}"/>
</path>
<taskdef
name="locker"
@ -218,6 +221,7 @@ SETUP
<pathelement location="${quick.dir}/lib/library"/>
<pathelement location="${quick.dir}/lib/compiler"/>
<pathelement location="${fjbg.jar}"/>
<pathelement location="${msil.jar}"/>
</path>
<taskdef
name="quick" classname="scala.tools.ant.Scalac"
@ -268,6 +272,15 @@ BUILD SUPPORT MACROS
resource="${fjbg.jar}" overwrite="yes" failonerror="no"/>
</else></if>
</then></if>
<if><not><available file="@{build.dir}/lib/msil.jar"/></not><then>
<if><isset property="os.win"/><then>
<copy file="${msil.jar}" tofile="@{build.dir}/lib/msil.jar"/>
</then><else>
<symlink
link="@{build.dir}/lib/msil.jar"
resource="${msil.jar}" overwrite="yes" failonerror="no"/>
</else></if>
</then></if>
</sequential>
</macrodef>
@ -317,6 +330,7 @@ BUILD LOCAL REFERENCE (LOCKER) LAYER
<pathelement location="${locker.dir}/lib/library"/>
<pathelement location="${locker.dir}/lib/compiler"/>
<pathelement location="${fjbg.jar}"/>
<pathelement location="${msil.jar}"/>
<pathelement location="${ant.jar}"/>
</classpath>
<include name="**/*.scala"/>
@ -462,6 +476,7 @@ BUILD QUICK-TEST LAYER
<pathelement location="${quick.dir}/lib/library"/>
<pathelement location="${quick.dir}/lib/compiler"/>
<pathelement location="${fjbg.jar}"/>
<pathelement location="${msil.jar}"/>
<pathelement location="${ant.jar}"/>
</classpath>
<include name="**/*.scala"/>
@ -607,6 +622,7 @@ TEST
<pathelement location="${strap.dir}/lib/library"/>
<pathelement location="${strap.dir}/lib/compiler"/>
<pathelement location="${fjbg.jar}"/>
<pathelement location="${msil.jar}"/>
<pathelement location="${ant.jar}"/>
</classpath>
<include name="**/*.scala"/>
@ -743,6 +759,7 @@ DOCUMENTATION
<pathelement location="${quick.dir}/lib/library"/>
<pathelement location="${quick.dir}/lib/compiler"/>
<pathelement location="${fjbg.jar}"/>
<pathelement location="${msil.jar}"/>
<pathelement location="${ant.jar}"/>
</classpath>
<include name="**/*.scala"/>
@ -851,6 +868,7 @@ GENERATES A DISTRIBUTION
<jar destfile="${dist.current.dir}/lib/${comp.jar.name}">
<fileset dir="${strap.dir}/lib/compiler"/>
<zipfileset src="${fjbg.jar}"/>
<zipfileset src="${msil.jar}"/>
<manifest>
<attribute name="Signature-Version" value="${version.number}"/>
<attribute name="Built-By" value="${user.name}"/>

View File

@ -28,6 +28,7 @@ import transform._
import backend.icode.{ICodes, GenICode, Checkers}
import backend.ScalaPrimitives
import backend.jvm.GenJVM
import backend.msil.GenMSIL
import backend.opt.{Inliners, ClosureElimination, DeadCodeElimination}
import backend.icode.analysis._
@ -170,11 +171,11 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
val classPath0 = new ClassPath(false && onlyPresentation)
val classPath = new classPath0.Build(
settings.classpath.value,
if (forMSIL) "" else settings.classpath.value,
settings.sourcepath.value,
settings.outdir.value,
settings.bootclasspath.value,
settings.extdirs.value)
if (forMSIL) "" else settings.bootclasspath.value,
if (forMSIL) "" else settings.extdirs.value)
if (settings.verbose.value) {
inform("[Classpath = " + classPath+"]")
@ -201,7 +202,8 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
val global: Global.this.type = Global.this
}
def rootLoader: LazyType = new loaders.PackageLoader(classPath.root /* getRoot() */)
def rootLoader: LazyType = if (forMSIL) new loaders.NamespaceLoader(classPath.root)
else new loaders.PackageLoader(classPath.root /* getRoot() */)
val migrateMsg = "migration problem when moving from Scala version 1.0 to version 2.0:\n"
@ -343,6 +345,10 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
val global: Global.this.type = Global.this
}
object genMSIL extends GenMSIL {
val global: Global.this.type = Global.this
}
object icodeChecker extends checkers.ICodeChecker()
object typer extends analyzer.Typer(
@ -371,7 +377,7 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
// inliner,
// closureElimination,
// deadCode,
genJVM,
if (forMSIL) genMSIL else genJVM,
sampleTransform)
protected def insertBefore(c: SubComponent, cs: List[SubComponent], before: SubComponent): List[SubComponent] = cs match {
@ -633,6 +639,7 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
}
def forCLDC: Boolean = settings.target.value == "cldc"
def forMSIL: Boolean = settings.target.value == "msil"
def onlyPresentation = settings.doc.value
// position stuff
final val positionConfiguration: PositionConfiguration = initConfig;

View File

@ -92,6 +92,8 @@ class Settings(error: String => unit) {
val documenttitle = StringSetting ("-documenttitle", "documenttitle", "Specify document title of generated HTML documentation", documenttitleDefault)
val target = ChoiceSetting ("-target", "Specify which backend to use", List("jvm-1.5", "jvm-1.4", "msil", "cldc"), "jvm-1.4")
val migrate = BooleanSetting("-migrate", "Assist in migrating from Scala version 1.0")
val assemname = StringSetting ("-o", "file", "Name of the output assembly (only relevant with -target:msil)", "")
val assemrefs = StringSetting ("-r", "path", "List of assemblies referenced by the program (only relevant with -target:msil)", ".")
val debug = new BooleanSetting("-debug", "Output debugging messages") { override def hiddenToIDE = true }
val deprecation = BooleanSetting ("-deprecation", "enable detailed deprecation warnings")
val unchecked = BooleanSetting ("-unchecked", "enable detailed unchecked warnings")

View File

@ -445,7 +445,7 @@ abstract class ScalaPrimitives {
/** Add a primitive operation to the map */
def addPrimitive(s: Symbol, code: Int): Unit = {
assert(!(primitives contains s), "Duplicate primitive " + s)
primitives += s -> code
primitives(s) = code
}
def addPrimitives(cls: Symbol, method: Name, code: Int): Unit = {

View File

@ -23,7 +23,9 @@ trait ExceptionHandlers requires ICodes {
class ExceptionHandler(val method: IMethod, val label: String, val cls: Symbol) {
private var _startBlock: BasicBlock = _;
var finalizer: Finalizer = _;
var resultKind: TypeKind = _;
def setStartBlock(b: BasicBlock) = _startBlock = b;
def startBlock = _startBlock;

View File

@ -480,14 +480,14 @@ abstract class GenICode extends SubComponent {
val kind = toTypeKind(tree.tpe)
var handlers = for (val CaseDef(pat, _, body) <- catches.reverse)
yield pat match {
case Typed(Ident(nme.WILDCARD), tpt) => Pair(tpt.tpe.symbol, {
case Typed(Ident(nme.WILDCARD), tpt) => Triple(tpt.tpe.symbol, kind, {
ctx: Context =>
ctx.bb.emit(DROP(REFERENCE(tpt.tpe.symbol)));
val ctx1 = genLoad(body, ctx, kind);
genLoad(finalizer, ctx1, UNIT);
})
case Ident(nme.WILDCARD) => Pair(definitions.ThrowableClass, {
case Ident(nme.WILDCARD) => Triple(definitions.ThrowableClass, kind, {
ctx: Context =>
ctx.bb.emit(DROP(REFERENCE(definitions.ThrowableClass)))
val ctx1 = genLoad(body, ctx, kind)
@ -498,7 +498,7 @@ abstract class GenICode extends SubComponent {
val exception = new Local(pat.symbol, toTypeKind(pat.symbol.tpe), false)
ctx.method.addLocal(exception);
Pair(pat.symbol.tpe.symbol, {
Triple(pat.symbol.tpe.symbol, kind, {
ctx: Context =>
ctx.bb.emit(STORE_LOCAL(exception), pat.pos);
val ctx1 = genLoad(body, ctx, kind);
@ -507,7 +507,7 @@ abstract class GenICode extends SubComponent {
}
if (finalizer != EmptyTree)
handlers = Pair(NoSymbol, {
handlers = Triple(NoSymbol, kind, {
ctx: Context =>
val exception = new Local(ctx.method.symbol.newVariable(finalizer.pos, unit.fresh.newName("exc"))
.setFlag(Flags.SYNTHETIC)
@ -686,10 +686,10 @@ abstract class GenICode extends SubComponent {
ctx1.bb.close
ctx1.newBlock
} else if (isPrimitive(fun.symbol)) { // primitive method call
} else if (isPrimitive(sym)) { // primitive method call
val Select(receiver, _) = fun
val code = scalaPrimitives.getPrimitive(fun.symbol, receiver.tpe)
val code = scalaPrimitives.getPrimitive(sym, receiver.tpe)
var ctx1 = ctx
if (scalaPrimitives.isArithmeticOp(code)) {
@ -733,6 +733,7 @@ abstract class GenICode extends SubComponent {
if (settings.debug.value)
log("synchronized block start");
ctx1 = ctx1.Try(
bodyCtx => {
val ctx1 = genLoad(args.head, bodyCtx, expectedType /* toTypeKind(tree.tpe.resultType) */)
@ -740,7 +741,8 @@ abstract class GenICode extends SubComponent {
ctx1.bb.emit(MONITOR_EXIT(), tree.pos)
ctx1
}, List(
Pair(NoSymbol, exhCtx => {
// tree.tpe / fun.tpe is object, which is no longer true after this transformation
Triple(NoSymbol, expectedType, exhCtx => {
exhCtx.bb.emit(LOAD_LOCAL(monitor))
exhCtx.bb.emit(MONITOR_EXIT(), tree.pos)
exhCtx.bb.emit(THROW())
@ -756,9 +758,8 @@ abstract class GenICode extends SubComponent {
genCoercion(tree, ctx1, code)
generatedType = scalaPrimitives.generatedKind(code)
} else
abort("Primitive operation not handled yet: " +
fun.symbol.fullNameString + "(" + fun.symbol.simpleName + ") "
+ " at: " + unit.position(tree.pos));
abort("Primitive operation not handled yet: " + sym.fullNameString + "(" +
fun.symbol.simpleName + ") " + " at: " + unit.position(tree.pos));
ctx1
} else { // normal method call
if (settings.debug.value)
@ -775,7 +776,7 @@ abstract class GenICode extends SubComponent {
if (invokeStyle.hasInstance) genLoadQualifier(fun, ctx)
else ctx
ctx1 = genLoadArguments(args, fun.symbol.info.paramTypes, ctx1)
ctx1 = genLoadArguments(args, sym.info.paramTypes, ctx1)
val hostClass = fun match {
case Select(qualifier, _)
@ -983,6 +984,11 @@ abstract class GenICode extends SubComponent {
def isStaticSymbol(s: Symbol): Boolean =
s.hasFlag(Flags.STATIC) || s.hasFlag(Flags.STATICMEMBER) || s.owner.isImplClass
// def isUnbox(s: Symbol): Boolean = (
// s.name.==(nme.unbox) && s.owner.isModuleClass
// && s.owner.linkedClassOfClass.isSubClass(definitions.AnyValClass)
// )
/**
* Generate code that loads args into label parameters.
*/
@ -1044,7 +1050,7 @@ abstract class GenICode extends SubComponent {
* @param ctx ...
* @param cast ...
*/
def genBoxedConversion(from: TypeKind, to: TypeKind, ctx: Context, cast: Boolean) = {
def genBoxedConversion(from: TypeKind, to: TypeKind, ctx: Context, cast: Boolean): Unit = {
assert(to.isValueType || to.isArrayType,
"Expecting conversion to value type: " + to)
@ -1054,7 +1060,12 @@ abstract class GenICode extends SubComponent {
case ARRAY(elem) =>
definitions.boxedArrayClass(elem.toType.symbol)
case _ =>
definitions.boxedClass(to.toType.symbol)
if (cast) {
ctx.bb.emit(UNBOX(to))
return
}
else
definitions.boxedClass(to.toType.symbol)
}
if (cast) {
@ -1709,9 +1720,10 @@ abstract class GenICode extends SubComponent {
* 'covered' by this exception handler (in addition to the
* previously active handlers).
*/
def newHandler(cls: Symbol): ExceptionHandler = {
def newHandler(cls: Symbol, resultKind: TypeKind): ExceptionHandler = {
handlerCount = handlerCount + 1
val exh = new ExceptionHandler(method, "" + handlerCount, cls)
exh.resultKind = resultKind
method.addHandler(exh)
handlers = exh :: handlers
if (settings.debug.value)
@ -1762,14 +1774,14 @@ abstract class GenICode extends SubComponent {
* } ))</code>
*/
def Try(body: Context => Context,
handlers: List[Pair[Symbol, (Context => Context)]],
handlers: List[Triple[Symbol, TypeKind, (Context => Context)]],
finalizer: Tree) = {
val outerCtx = this.dup
val afterCtx = outerCtx.newBlock
val exhs = handlers.map { handler =>
val exh = this.newHandler(handler._1)
val ctx1 = handler._2(outerCtx.enterHandler(exh))
val exh = this.newHandler(handler._1, handler._2)
val ctx1 = handler._3(outerCtx.enterHandler(exh))
ctx1.bb.emit(JUMP(afterCtx.bb))
ctx1.bb.close
exh

View File

@ -32,23 +32,7 @@ trait TypeKinds requires ICodes {
* represent the types that the VM know (or the ICode
* view of what VMs know).
*/
abstract class TypeKind {
/** Returns a string representation of this type kind. */
override def toString(): String = this match {
case UNIT => "UNIT"
case BOOL => "BOOL"
case BYTE => "BYTE"
case SHORT => "SHORT"
case CHAR => "CHAR"
case INT => "INT"
case LONG => "LONG"
case FLOAT => "FLOAT"
case DOUBLE => "DOUBLE"
case REFERENCE(cls) => "REFERENCE(" + cls.fullNameString + ")"
case ARRAY(elem) => "ARRAY[" + elem + "]"
case _ => abort("Unkown type kind.")
}
sealed abstract class TypeKind {
def toType: Type = this match {
case UNIT => definitions.UnitClass.tpe
@ -61,6 +45,7 @@ trait TypeKinds requires ICodes {
case FLOAT => definitions.FloatClass.tpe
case DOUBLE => definitions.DoubleClass.tpe
case REFERENCE(cls) => typeRef(cls.typeConstructor.prefix, cls, Nil)
//case VALUE(cls) => typeRef(cls.typeConstructor.prefix, cls, Nil);
case ARRAY(elem) => typeRef(definitions.ArrayClass.typeConstructor.prefix,
definitions.ArrayClass,
elem.toType :: Nil)
@ -216,7 +201,7 @@ trait TypeKinds requires ICodes {
// }
/** A class type. */
case class REFERENCE(cls: Symbol) extends TypeKind {
final case class REFERENCE(cls: Symbol) extends TypeKind {
assert(cls ne null,
"REFERENCE to null class symbol.")
assert(cls != definitions.ArrayClass,
@ -260,8 +245,20 @@ trait TypeKinds requires ICodes {
}
}
// final case class VALUE(cls: Symbol) extends TypeKind {
// override def equals(other: Any): Boolean = other match {
// case VALUE(cls2) => cls == cls2;
// case _ => false;
// }
case class ARRAY(val elem: TypeKind) extends TypeKind {
// def maxType(other: TypeKind): TypeKind =
// abort(toString() + " maxType " + other.toString());
// override def toString(): String =
// "VALUE(" + cls.fullNameString + ")";
// }
final case class ARRAY(val elem: TypeKind) extends TypeKind {
override def toString(): String =
"ARRAY[" + elem + "]"

File diff suppressed because it is too large Load Diff

View File

@ -41,6 +41,13 @@ trait Definitions requires SymbolTable {
var NullPointerExceptionClass: Symbol = _
var NonLocalReturnExceptionClass: Symbol = _
var ValueTypeClass: Symbol = _ // System.ValueType
var DelegateClass: Symbol = _ // System.MulticastDelegate
var Delegate_scalaCallers: List[Symbol] = List()
// Symbol -> (Symbol, Type): scalaCaller -> (scalaMethodSym, DelegateType)
// var Delegate_scalaCallerInfos: HashMap[Symbol, Pair[Symbol, Type]] = _
var Delegate_scalaCallerTargets: HashMap[Symbol, Symbol] = _
// the scala value classes
var UnitClass: Symbol = _
var BooleanClass: Symbol = _
@ -269,6 +276,32 @@ trait Definitions requires SymbolTable {
case _ =>
false
}
def isCorrespondingDelegate(delegateType: Type, functionType: Type): boolean = {
var isCD: Boolean = false;
if (DelegateClass != null && delegateType != null &&
isSubType(delegateType, DelegateClass.tpe))
{
val meth: Symbol = delegateType.member(nme.apply)
meth.tpe match {
case MethodType(delegateParams, delegateReturn) =>
val delegateParamsO = delegateParams.map(pt => {if (pt == definitions.AnyClass.tpe) definitions.ObjectClass.tpe else pt});
if(isFunctionType(functionType))
functionType match {
case TypeRef(_, _, args) =>
if(delegateParamsO == args.dropRight(1) &&
delegateReturn == args.last)
isCD = true;
case _ => ();
}
case _ => ()
}
}
isCD
}
/* val RemoteFunctionClass: Array[Symbol] = new Array(MaxFunctionArity + 1)
def remoteFunctionApply(n: Int) = getMember(RemoteFunctionClass(n), nme.apply)
def remoteFunctionType(formals: List[Type], restpe: Type) =
@ -428,7 +461,17 @@ trait Definitions requires SymbolTable {
private def newValueClass(name: Name, tag: char): Symbol = {
def boxedName: String =
"scala.runtime.Boxed" + name
if (!forMSIL) "scala.runtime.Boxed" + name
else "System." + (name match {
case nme.Boolean => "Boolean"
case nme.Byte => "Byte"
case nme.Char => "Char"
case nme.Short => "Int16"
case nme.Int => "Int32"
case nme.Long => "Int64"
case nme.Float => "Single"
case nme.Double => "Double"
})
val clazz =
newClass(ScalaPackageClass, name, List(AnyValClass.typeConstructor))
.setFlag(ABSTRACT /* SEALED */) // bq: SEALED is interesting for case class descendants, only
@ -606,9 +649,12 @@ trait Definitions requires SymbolTable {
def isNumericValueClass(sym: Symbol): boolean =
(sym ne BooleanClass) && (boxedClass contains sym)
def isValueType(sym: Symbol) =
isValueClass(sym) || unboxMethod.contains(sym)
/** Is symbol a value or array class? */
def isUnboxedClass(sym: Symbol): boolean =
isValueClass(sym) || sym == ArrayClass
isValueType(sym) || sym == ArrayClass
def signature(tp: Type): String = {
def erasure(tp: Type): Type = tp match {
@ -650,7 +696,7 @@ trait Definitions requires SymbolTable {
RootClass.info.decls.enter(EmptyPackage)
RootClass.info.decls.enter(RootPackage)
JavaLangPackage = getModule("java.lang")
JavaLangPackage = getModule(if (forMSIL) "System" else "java.lang")
ScalaPackage = getModule("scala")
assert(ScalaPackage ne null, "Scala package is null")
ScalaPackageClass = ScalaPackage.tpe.symbol
@ -662,7 +708,7 @@ trait Definitions requires SymbolTable {
AnyValClass = newClass(ScalaPackageClass, nme.AnyVal, anyparam)
.setFlag(FINAL | SEALED)
ObjectClass = getClass("java.lang.Object")
ObjectClass = getClass(if (forMSIL) "System.Object" else "java.lang.Object")
AnyRefClass =
newAlias(ScalaPackageClass, nme.AnyRef, ObjectClass.typeConstructor)
@ -675,13 +721,17 @@ trait Definitions requires SymbolTable {
AllClass = newClass(ScalaPackageClass, nme.Nothing, anyparam)
.setFlag(ABSTRACT | TRAIT | FINAL)
StringClass = getClass("java.lang.String")
StringClass = getClass(if (forMSIL) "System.String" else "java.lang.String")
ClassClass = getClass("java.lang.Class")
ThrowableClass = getClass("java.lang.Throwable")
NullPointerExceptionClass = getClass("java.lang.NullPointerException")
ClassClass = getClass(if (forMSIL) "System.Type" else "java.lang.Class")
ThrowableClass = getClass(if (forMSIL) "System.Exception" else "java.lang.Throwable")
NullPointerExceptionClass = getClass(if (forMSIL) "System.NullReferenceException"
else "java.lang.NullPointerException")
NonLocalReturnExceptionClass = getClass("scala.runtime.NonLocalReturnException")
ValueTypeClass = if (forMSIL) getClass("System.ValueType") else null
DelegateClass = if (forMSIL) getClass("System.MulticastDelegate") else null
UnitClass =
newClass(ScalaPackageClass, nme.Unit, List(AnyValClass.typeConstructor))
abbrvTag(UnitClass) = 'V'
@ -704,7 +754,7 @@ trait Definitions requires SymbolTable {
StaticAttributeClass = getClass("scala.StaticAttribute")
//ChannelClass = getClass("scala.distributed.Channel")
//RemoteRefClass = getClass("scala.distributed.RemoteRef")
if (!forCLDC) {
if (!forCLDC && ! forMSIL) {
CodeClass = getClass("scala.reflect.Code")
CodeModule = getModule("scala.reflect.Code")
}
@ -716,12 +766,14 @@ trait Definitions requires SymbolTable {
ListClass = getClass("scala.List")
ListModule = getModule("scala.List")
ArrayClass = getClass("scala.Array")
SerializableClass = if (forCLDC) null else getClass("java.io.Serializable")
SerializableClass = if (forMSIL || forCLDC) null else getClass("java.io.Serializable")
PredefModule = getModule("scala.Predef")
ConsoleModule = getModule("scala.Console")
MatchErrorClass = getClass("scala.MatchError")
MatchErrorModule = getModule("scala.MatchError")
IndexOutOfBoundsExceptionClass = getClass("java.lang.IndexOutOfBoundsException")
IndexOutOfBoundsExceptionClass =
getClass(if (forMSIL) "System.IndexOutOfRangeException"
else "java.lang.IndexOutOfBoundsException")
//RemoteExecutionModule = getModule("scala.distributed.RemoteExecution")
ScalaRunTimeModule = getModule("scala.runtime.ScalaRunTime")
RepeatedParamClass = newCovariantPolyClass(
@ -792,12 +844,85 @@ trait Definitions requires SymbolTable {
BoxedUnitModule = getModule("scala.runtime.BoxedUnit")
ObjectRefClass = getClass("scala.runtime.ObjectRef")
if (forMSIL) {
val intType = IntClass.typeConstructor;
val intParam = List(intType);
val longType = LongClass.typeConstructor;
val charType = CharClass.typeConstructor;
val unitType = UnitClass.typeConstructor;
val stringType = StringClass.typeConstructor;
val stringParam = List(stringType);
// additional methods of Object
newMethod(ObjectClass, "clone", List(), AnyRefClass.typeConstructor);
newMethod(ObjectClass, "wait", List(), unitType);
newMethod(ObjectClass, "wait", List(longType), unitType);
newMethod(ObjectClass, "wait", List(longType, intType), unitType);
newMethod(ObjectClass, "notify", List(), unitType);
newMethod(ObjectClass, "notifyAll", List(), unitType);
// additional methods of String
newMethod(StringClass, "length", List(), intType);
newMethod(StringClass, "compareTo", stringParam, intType);
newMethod(StringClass, "charAt", intParam, charType);
newMethod(StringClass, "concat", stringParam, stringType);
newMethod(StringClass, "indexOf", intParam, intType);
newMethod(StringClass, "indexOf", List(intType, intType), intType);
newMethod(StringClass, "indexOf", stringParam, intType);
newMethod(StringClass, "indexOf", List(stringType, intType), intType);
newMethod(StringClass, "lastIndexOf", intParam, intType);
newMethod(StringClass, "lastIndexOf", List(intType, intType), intType);
newMethod(StringClass, "lastIndexOf", stringParam, intType);
newMethod(StringClass, "lastIndexOf", List(stringType, intType), intType);
newMethod(StringClass, "toLowerCase", List(), stringType);
newMethod(StringClass, "toUpperCase", List(), stringType);
newMethod(StringClass, "startsWith", stringParam, booltype);
newMethod(StringClass, "endsWith", stringParam, booltype);
newMethod(StringClass, "substring", intParam, stringType);
newMethod(StringClass, "substring", List(intType, intType), stringType);
newMethod(StringClass, "trim", List(), stringType);
newMethod(StringClass, "intern", List(), stringType);
newMethod(StringClass, "replace", List(charType, charType), stringType);
newMethod(StringClass, "toCharArray", List(),
appliedType(ArrayClass.typeConstructor, List(charType)));
// Delegate_scalaCallerInfos = new HashMap()
Delegate_scalaCallerTargets = new HashMap()
}
AnnotationDefaultAttr = newClass(RootClass,
nme.AnnotationDefaultATTR,
List(AttributeClass.typeConstructor))
SerializableAttr = getClass("scala.serializable")
BeanPropertyAttr = if (forCLDC || forMSIL) null else getClass("scala.reflect.BeanProperty")
DeprecatedAttr = getClass("scala.deprecated")
BeanPropertyAttr = if (forCLDC) null else getClass("scala.reflect.BeanProperty")
}
var nbScalaCallers: Int = 0
def newScalaCaller(delegateType: Type): Symbol = {
assert(forMSIL, "scalaCallers can only be created if target is .NET")
// object: reference to object on which to call (scala-)metod
val paramTypes: List[Type] = List(ObjectClass.tpe)
val name: String = "$scalaCaller$$" + nbScalaCallers
// tparam => resultType, which is the resultType of PolyType, i.e. the result type after applying the
// type parameter =-> a MethodType in this case
// TODO: set type bounds manually (-> MulticastDelegate), see newTypeParam
val newCaller = newMethod(DelegateClass, name, paramTypes, delegateType) setFlag (FINAL | STATIC)
// val newCaller = newPolyMethod(DelegateClass, name,
// tparam => MethodType(paramTypes, tparam.typeConstructor)) setFlag (FINAL | STATIC)
Delegate_scalaCallers = Delegate_scalaCallers ::: List(newCaller)
nbScalaCallers = nbScalaCallers + 1
newCaller
}
// def addScalaCallerInfo(scalaCaller: Symbol, methSym: Symbol, delType: Type) = {
// assert(Delegate_scalaCallers contains scalaCaller)
// Delegate_scalaCallerInfos += scalaCaller -> Pair(methSym, delType)
// }
def addScalaCallerInfo(scalaCaller: Symbol, methSym: Symbol) = {
assert(Delegate_scalaCallers contains scalaCaller)
Delegate_scalaCallerTargets += scalaCaller -> methSym
}
}
}

View File

@ -257,7 +257,7 @@ trait StdNames requires SymbolTable {
val filter = newTermName("filter")
val finalize_ = newTermName("finalize")
val flatMap = newTermName("flatMap")
val forName = newTermName("forName")
val forName = newTermName(if (forMSIL) "GetType" else "forName")
val foreach = newTermName("foreach")
val get = newTermName("get")
val getClass_ = newTermName("getClass")

View File

@ -8,12 +8,12 @@ package scala.tools.nsc.symtab
import compat.Platform.currentTime
import java.io.{File, IOException}
import scala.collection.mutable.HashMap
import scala.collection.mutable.{HashMap, HashSet}
import scala.tools.nsc.io.AbstractFile
import scala.tools.nsc.util.{ClassPath, NameTransformer, Position}
import classfile.{ClassfileParser, SymblfileParser}
import Flags._
import ch.epfl.lamp.compiler.msil.{Type => MSILType, Attribute => MSILAttribute};
/** This class ...
*
@ -57,8 +57,8 @@ abstract class SymbolLoaders {
phase = currentphase
def source = kindString + " " + sourceString
informTime("loaded " + source, start)
if (root.rawInfo == this && root.linkedSym.rawInfo == this)
throw new TypeError(source + " does not define " + root)
//if (root.rawInfo == this && root.linkedSym.rawInfo == this)
// throw new TypeError(source + " does not define " + root)
ok = true
} catch {
case ex: IOException =>
@ -88,12 +88,50 @@ abstract class SymbolLoaders {
/** Load contents of a package
*/
class PackageLoader(directory: global.classPath0.Context) extends SymbolLoader {
// System.err.println("PACKAGE LOADER: " + directory)
protected def sourceString = directory.toString()
protected def kindString: String = "directory path"
protected def newPackageLoader(dir: global.classPath0.Context): PackageLoader =
new PackageLoader(dir)
protected def checkSource(name: String, source: AbstractFile): Boolean = true;
protected var root: Symbol = _
def enterPackage(name: String, completer: SymbolLoader): unit = {
val pkg = root.newPackage(NoPos, newTermName(name))
pkg.moduleClass.setInfo(completer)
pkg.setInfo(pkg.moduleClass.tpe)
root.info.decls.enter(pkg)
}
// @return - the symbol of the class
def enterClassAndModule(name: String, completer: SymbolLoader): Symbol = {
val owner = if (root.isRoot) definitions.EmptyPackageClass else root
val className = newTermName(name)
assert(owner.info.decls.lookup(name) == NoSymbol, owner.fullNameString + "." + name)
val clazz = owner.newClass(NoPos, name.toTypeName)
val module = owner.newModule(NoPos, name)
clazz.setInfo(completer)
module.setInfo(completer)
module.moduleClass.setInfo(moduleClassLoader)
owner.info.decls.enter(clazz)
owner.info.decls.enter(module)
// if (completer.sourceFile != null) {
// clazz.sourceFile = completer.sourceFile;
// module.moduleClass.sourceFile = completer.sourceFile
// }
assert(clazz.linkedModuleOfClass == module, module)
assert(module.linkedClassOfModule == clazz, clazz)
//System.out.println("Added class " + clazz.fullNameString);
clazz
}
protected def doComplete(root: Symbol): unit = {
assert(root.isPackageClass, root)
this.root = root
val scope = newScope
root.setInfo(new PackageClassInfoType(scope, root))
@ -102,40 +140,13 @@ abstract class SymbolLoaders {
name.length() > 0 && (settings.XbytecodeRead.value ||
(!name.endsWith("$class") && name.indexOf("$anon") == -1));
def enterPackage(str: String, completer: SymbolLoader): unit = {
val pkg = root.newPackage(NoPos, newTermName(str))
pkg.moduleClass.setInfo(completer)
pkg.setInfo(pkg.moduleClass.tpe)
root.info.decls.enter(pkg)
}
def enterClassAndModule(str: String, completer: SymbolLoader): unit = {
val owner = if (root.isRoot) definitions.EmptyPackageClass else root
val name = newTermName(str)
val clazz = owner.newClass(NoPos, name.toTypeName)
val module = owner.newModule(NoPos, name)
clazz.setInfo(completer)
module.setInfo(completer)
module.moduleClass.setInfo(moduleClassLoader)
owner.info.decls.enter(clazz)
owner.info.decls.enter(module)
/*
if (completer.sourceFile ne null) {
clazz.sourceFile = completer.sourceFile;
module.moduleClass.sourceFile = completer.sourceFile
}
*/
assert(clazz.linkedModuleOfClass == module, module)
assert(module.linkedClassOfModule == clazz, clazz)
}
val classes = new HashMap[String, global.classPath0.Context]
val packages = new HashMap[String, global.classPath0.Context]
for (val dir <- directory.entries) if (dir.location ne null) {
for (val file <- dir.location) {
if (file.isDirectory && directory.validPackage(file.name) && !packages.isDefinedAt(file.name))
packages(file.name) = directory.find(file.name, true);
else if (!file.isDirectory && file.name.endsWith(".class")) {
else if (!global.forMSIL && !file.isDirectory && file.name.endsWith(".class")) {
val name = file.name.substring(0, file.name.length() - (".class").length());
if (isValid(name) && !classes.isDefinedAt(name)) {
val clazz = directory.find(name, false)
@ -147,33 +158,35 @@ abstract class SymbolLoaders {
for (val dir <- directory.entries) if (dir.source ne null) {
for (val file <- dir.source.location) {
if (file.isDirectory && directory.validPackage(file.name) && !packages.isDefinedAt(file.name))
packages(file.name) = directory.find(file.name, true);
packages(file.name) = directory.find(file.name, true)
else if (dir.source.compile && !file.isDirectory && file.name.endsWith(".scala")) {
val name = file.name.substring(0, file.name.length() - (".scala").length());
val name = file.name.substring(0, file.name.length() - (".scala").length())
if (isValid(name) && !classes.isDefinedAt(name)) {
val source = directory.find(name, false)
if (source ne null) classes(name) = source
if ((source ne null) && (source.sourceFile ne null))
if (checkSource(name, source.sourceFile))
classes(name) = source
else if (settings.debug.value)
Console.println("Skipping source file " + source.sourceFile)
}
}
}
}
//if (!packages.isEmpty) System.err.println("COMPLETE: " + packages)
//if (! classes.isEmpty) System.err.println("COMPLETE: " + classes)
// do classes first
// do classes first
for (val {name, file} <- classes.elements) {
val loader = if (!file.isSourceFile) {
new ClassfileLoader(file.classFile, file.sourceFile, file.sourcePath);
new ClassfileLoader(file.classFile, file.sourceFile, file.sourcePath)
} else {
assert(file.sourceFile ne null)
new SourcefileLoader(file.sourceFile)
}
enterClassAndModule(name, loader)
}
for (val {name, file} <- packages.elements)
enterPackage(name, new PackageLoader(file))
enterPackage(name, newPackageLoader(file))
}
protected def kindString: String = "directory path"
}
/*
@ -182,7 +195,68 @@ abstract class SymbolLoaders {
}
*/
class NamespaceLoader(directory: global.classPath0.Context) extends PackageLoader(directory) {
override protected def kindString: String = "namespace " + namespace
override protected def sourceString = "";
override def newPackageLoader(dir: global.classPath0.Context): PackageLoader =
new NamespaceLoader(dir);
val types = new HashMap[String,MSILType]();
val namespaces = new HashSet[String]();
def namespace: String = if (root.isRoot) "" else root.fullNameString;
// TODO: Add check whether the source is newer than the assembly
override protected def checkSource(name: String, source: AbstractFile): Boolean = {
!types.contains(name)
}
override protected def doComplete(root: Symbol): Unit = {
clrTypes.collectMembers(root, types, namespaces);
super.doComplete(root);
for (val namespace <- namespaces.elements) {
val oldPkg = root.info.decls.lookup(newTermName(namespace));
if (oldPkg == NoSymbol)
enterPackage(namespace, new NamespaceLoader(new classPath0.Context(List())));
//else System.out.println("PackageLoader: package already in scope: " + oldPkg.fullNameString);
}
// import the CLR types contained in the package (namespace)
for (val Pair(name, typ) <- types.elements) {
assert(namespace == typ.Namespace, typ.FullName);
if (typ.IsDefined(clrTypes.SCALA_SYMTAB_ATTR, false)) {
val attrs = typ.GetCustomAttributes(clrTypes.SCALA_SYMTAB_ATTR, false);
assert (attrs.length == 1, attrs.length);
val a = attrs(0).asInstanceOf[MSILAttribute];
if (a.getConstructor() == clrTypes.SYMTAB_CONSTR)
enterClassAndModule(name, new MSILTypeLoader(typ));
}
else
enterClassAndModule(name, new MSILTypeLoader(typ));
}
}
} // NamespaceLoader
class MSILTypeLoader(typ: MSILType) extends SymbolLoader {
private object typeParser extends clr.TypeParser {
val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global;
}
protected def doComplete(root: Symbol): Unit = {
typeParser.parse(typ, root);
}
protected def kindString: String = typ.FullName;
protected def sourceString = typ.Assembly.FullName;
}
class ClassfileLoader(classFile: AbstractFile, override val sourceFile: AbstractFile, sourcePath0: AbstractFile) extends SymbolLoader {
//throw new Error("classfile = " + classFile + "; sourcefile = " + sourceFile + "; sourcepath = " + sourcePath0)
private object classfileParser extends ClassfileParser {
val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global
override def sourcePath = sourcePath0 /* could be null */
@ -215,4 +289,10 @@ abstract class SymbolLoaders {
protected def kindString: String = "";
protected def sourceString = "";
}
object clrTypes extends clr.CLRTypes {
val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global;
if (global.forMSIL) init();
}
}

View File

@ -23,7 +23,10 @@ abstract class SymbolTable extends Names
/** Are we compiling for the J2ME CLDC platform? */
def forCLDC: Boolean
/** A period is an ordinal number for a phase in a run.
/** Are we compiling for .NET*/
def forMSIL: Boolean
/** A period is an ordinal number for a phase in a run.
* Phases in later runs have higher periods than phases in earlier runs.
* Later phases have higher periods than earlier phases in the same run.
*/

View File

@ -0,0 +1,254 @@
/* NSC -- new scala compiler
* Copyright 2004-2006 LAMP/EPFL
*/
// $Id: CLRTypes.scala 9524 2006-12-14 17:54:07Z mihaylov $
package scala.tools.nsc.symtab.clr;
import scala.tools.nsc.util.Position;
import scala.collection.mutable.{ListBuffer, Map, HashMap, Set, HashSet};
import java.util.{Arrays, Comparator, StringTokenizer};
import java.io.File;
import ch.epfl.lamp.compiler.msil._;
/**
* Collects all types from all reference assemblies.
*/
abstract class CLRTypes {
val global: Global;
import global.Symbol;
import global.definitions;
//##########################################################################
var BYTE: Type = _;
var UBYTE: Type = _;
var SHORT: Type = _;
var USHORT: Type = _;
var CHAR: Type = _;
var INT: Type = _;
var UINT: Type = _;
var LONG: Type = _;
var ULONG: Type = _;
var FLOAT: Type = _;
var DOUBLE: Type = _;
var BOOLEAN: Type = _;
var VOID: Type = _;
var ENUM: Type = _;
var DELEGATE: Type = _;
var OBJECT: Type = _;
var STRING: Type = _;
var STRING_ARRAY: Type = _;
var VALUE_TYPE: Type = _;
var SCALA_SYMTAB_ATTR: Type = _;
var SYMTAB_CONSTR: ConstructorInfo = _;
var SYMTAB_DEFAULT_CONSTR: ConstructorInfo = _;
var DELEGATE_COMBINE: MethodInfo = _;
var DELEGATE_REMOVE: MethodInfo = _;
val types: Map[Symbol,Type] = new HashMap;
val constructors: Map[Symbol,ConstructorInfo] = new HashMap;
val methods: Map[Symbol,MethodInfo] = new HashMap;
val fields: Map[Symbol, FieldInfo] = new HashMap;
val sym2type: Map[Type,Symbol] = new HashMap;
private var alltypes: Array[Type] = _;
def init(): Unit = { // initialize
val assems = new StringTokenizer(global.settings.assemrefs.value, File.pathSeparator);
while (assems.hasMoreTokens()) {
assemrefs += new File(assems.nextToken());
}
val mscorlib = findAssembly("mscorlib.dll");
Type.initMSCORLIB(mscorlib);
findAssembly("scalaruntime.dll");
findAllAssemblies();
BYTE = getTypeSafe("System.SByte");
UBYTE = getTypeSafe("System.Byte");
CHAR = getTypeSafe("System.Char");
SHORT = getTypeSafe("System.Int16");
USHORT = getTypeSafe("System.UInt16");
INT = getTypeSafe("System.Int32");
UINT = getTypeSafe("System.UInt32");
LONG = getTypeSafe("System.Int64");
ULONG = getTypeSafe("System.UInt64");
FLOAT = getTypeSafe("System.Single");
DOUBLE = getTypeSafe("System.Double");
BOOLEAN = getTypeSafe("System.Boolean");
VOID = getTypeSafe("System.Void");
ENUM = getTypeSafe("System.Enum");
DELEGATE = getTypeSafe("System.MulticastDelegate");
OBJECT = getTypeSafe("System.Object");
STRING = getTypeSafe("System.String");
STRING_ARRAY = getTypeSafe("System.String[]");
VALUE_TYPE = getTypeSafe("System.ValueType");
SCALA_SYMTAB_ATTR = getTypeSafe("scala.runtime.SymtabAttribute");
val bytearray: Array[Type] = Array( Type.GetType("System.Byte[]") );
SYMTAB_CONSTR = SCALA_SYMTAB_ATTR.GetConstructor(bytearray);
SYMTAB_DEFAULT_CONSTR = SCALA_SYMTAB_ATTR.GetConstructor(Type.EmptyTypes);
//assert(SCALA_SYMTAB_ATTR != null);
val delegate: Type = getTypeSafe("System.Delegate");
val dargs: Array[Type] = Array(delegate, delegate);
DELEGATE_COMBINE = delegate.GetMethod("Combine", dargs);
DELEGATE_REMOVE = delegate.GetMethod("Remove", dargs);
//assert(DELEGATE_COMBINE != null);
//assert(DELEGATE_REMOVE != null);
var alltypes: Array[Type] = Type.EmptyTypes;
for (val assem <- assemblies) {
val atypes = assem.GetTypes().filter((typ: Type) => typ.DeclaringType == null);
alltypes = Array.concat(alltypes, atypes);
}
val typeNameComparator: Comparator =
new Comparator() {
def compare(o1: Any, o2: Any): Int = {
val t1 = o1.asInstanceOf[Type];
val t2 = o2.asInstanceOf[Type];
t1.FullName.compareTo(t2.FullName);
}
};
Arrays.sort(alltypes.asInstanceOf[Array[Object]], typeNameComparator);
this.alltypes = alltypes;
}
//##########################################################################
// type mapping and lookup
// private class MyHashMap[A, B <: AnyRef] extends HashMap[A, B] {
// override def default(key: A): B = null;
// }
def getType(name: String): Type = Type.GetType(name);
def getTypeSafe(name: String): Type = {
val t = Type.GetType(name);
assert(t != null, name);
t;
}
def mkArrayType(elemType: Type): Type = getType(elemType.FullName + "[]");
def isDelegateType(t: Type): Boolean = { t.BaseType() == DELEGATE }
//##########################################################################
// assembly loading methods
// a list of all loaded assemblies
private var assemblies: ListBuffer[Assembly] = new ListBuffer();
// a set of all directories and assembly files
private var assemrefs: Set[File] = new HashSet();
/** Load the assembly with the given name
*/
private def findAssembly(name: String): Assembly = {
// see if the assembly is referenced directly
for (val file <- assemrefs.elements; file.getName() == name) {
val assem = Assembly.LoadFrom(file.getPath());
if (assem != null) {
assemrefs -= file;
assemblies += assem;
return assem;
}
}
// look in directories specified with the '-r' option
for (val dir <- assemrefs.elements; dir.isDirectory()) {
val file = new File(dir, name);
if (file.exists()) {
val assem = Assembly.LoadFrom(file.getPath());
if (assem != null) {
assemblies += assem;
return assem;
}
}
}
// try in the current directory
val file = new File(".", name);
if (file.exists()) {
val assem = Assembly.LoadFrom(file.getPath());
if (assem != null) {
assemblies += assem;
return assem;
}
}
global.reporter.error(new Position(null, Position.NOPOS),
"cannot find assembly " + name + "; use the -r option to specify its location");
throw new Error();
}
/** Load the rest of the assemblies specified with the '-r' option
*/
private def findAllAssemblies(): Unit = {
for (val file <- assemrefs.elements) {
if (file.isFile()) {
//System.out.println("Loading assembly " + file)
val assem = Assembly.LoadFrom(file.getPath());
if (assem != null) {
assemblies += assem;
}
}
assemrefs -= file;
}
assert(assemrefs.isEmpty, assemrefs.toString());
}
//##########################################################################
// collect the members contained in a given namespace
/** Find the position of the first type whose name starts with
* the given prefix; return the length of the types array if no match
* is found so the result can be used to terminate loop conditions
*/
private def findFirst(prefix: String): Int = {
var m = 0;
var n = alltypes.length - 1;
while (m < n) {
val l = (m + n) / 2;
val res = alltypes(l).FullName.compareTo(prefix);
if (res < 0) m = l + 1;
else n = l;
}
if (alltypes(m).FullName.startsWith(prefix)) m else alltypes.length;
}
/** Collects the members contained in the given Scala package (namespace)
*/
def collectMembers(pakage: Symbol, typesMap: Map[String,Type], namespacesSet: Set[String]) = {
val namespace = if (pakage.isRoot) "" else pakage.fullNameString + ".";
val nl = namespace.length();
var i = findFirst(namespace);
while (i < alltypes.length && alltypes(i).FullName.startsWith(namespace)) {
val typ = alltypes(i);
if (typ.FullName != "java.lang.Object" && typ.FullName != "java.lang.String") {
val k = typ.FullName.indexOf(".", nl);
if (k < 0) {
typesMap.update(typ.Name, typ);
} else {
namespacesSet += (typ.Namespace.substring(nl, k));
}
}
i = i + 1;
}
}
//##########################################################################
} // CLRTypes

View File

@ -0,0 +1,506 @@
/* NSC -- new scala compiler
* Copyright 2004-2006 LAMP/EPFL
*/
// $Id: TypeParser.scala 8734 2006-09-21 14:56:02Z mihaylov $
package scala.tools.nsc.symtab.clr;
import scala.tools.nsc.util.Position;
import classfile.UnPickler;
import ch.epfl.lamp.compiler.msil.{Type => MSILType, Attribute => MSILAttribute, _};
import scala.collection.mutable.{HashMap, HashSet};
import java.io.IOException;
abstract class TypeParser {
val global: Global;
import global._;
import loaders.clrTypes;
//##########################################################################
private var clazz: Symbol = _;
private var instanceDefs: Scope = _; // was members
private var staticModule: Symbol = _; // was staticsClass
private var staticDefs: Scope = _; // was statics
protected def statics: Symbol = staticModule.moduleClass
protected var busy: boolean = false // lock to detect recursive reads
private object unpickler extends UnPickler {
val global: TypeParser.this.global.type = TypeParser.this.global
}
def parse(typ: MSILType, root: Symbol): Unit = {
def handleError(e: Exception) = {
if (settings.debug.value) e.printStackTrace(); //debug
throw new IOException("type '" + typ.FullName + "' is broken\n(" + e.getMessage() + ")")
}
assert(!busy)
busy = true
if (root.isModule) {
this.clazz = root.linkedClassOfModule
this.staticModule = root
} else {
this.clazz = root
this.staticModule = root.linkedModuleOfClass
}
try {
parseClass(typ)
} catch {
case e: FatalError => handleError(e)
case e: RuntimeException => handleError(e)
}
busy = false
}
private def parseClass(typ: MSILType): Unit = {
clrTypes.types(clazz) = typ;
clrTypes.sym2type(typ) = clazz;
if (typ.IsDefined(clrTypes.SCALA_SYMTAB_ATTR, false)) {
val attrs = typ.GetCustomAttributes(clrTypes.SCALA_SYMTAB_ATTR, false);
assert (attrs.length == 1, attrs.length);
val a = attrs(0).asInstanceOf[MSILAttribute];
assert (a.getConstructor() == clrTypes.SYMTAB_CONSTR);
val symtab = a.getConstructorArguments()(0).asInstanceOf[Array[Byte]]
unpickler.unpickle(symtab, 0, clazz, staticModule, typ.FullName);
val mClass = clrTypes.getType(typ.FullName + "$");
if (mClass != null) {
clrTypes.types(statics) = mClass;
val moduleInstance = mClass.GetField("MODULE$");
assert (moduleInstance != null, mClass);
clrTypes.fields(statics) = moduleInstance;
}
return;
}
val flags = translateAttributes(typ);
val ifaces: Array[MSILType] = typ.getInterfaces();
val superType = if (typ.BaseType() != null) getCLRType(typ.BaseType())
else if (typ.IsInterface()) definitions.ObjectClass.tpe
else definitions.AnyClass.tpe; // this is System.Object
val parents = superType :: ifaces.map(getCLRType).toList;
instanceDefs = newScope;
staticDefs = newScope;
val classInfo = ClassInfoType(parents, instanceDefs, clazz);
val staticInfo = ClassInfoType(List(), staticDefs, statics);
clazz.setFlag(flags);
clazz.setInfo(classInfo);
statics.setFlag(Flags.JAVA);
statics.setInfo(staticInfo);
staticModule.setFlag(Flags.JAVA);
staticModule.setInfo(statics.tpe);
// import nested types
for (val ntype <- typ.getNestedTypes(); (!(ntype.IsNestedPrivate
|| ntype.IsNestedAssembly
|| ntype.IsNestedFamANDAssem)
|| ntype.IsInterface) )
{
val loader = new loaders.MSILTypeLoader(ntype)
val nclazz = statics.newClass(NoPos, ntype.Name.toTypeName)
val nmodule = statics.newModule(NoPos, ntype.Name)
nclazz.setInfo(loader)
nmodule.setInfo(loader)
staticDefs.enter(nclazz)
staticDefs.enter(nmodule)
assert(nclazz.linkedModuleOfClass == nmodule, nmodule);
assert(nmodule.linkedClassOfModule == nclazz, nclazz);
}
val fields = typ.getFields();
for (val field <- fields; !(field.IsPrivate() || field.IsAssembly() || field.IsFamilyAndAssembly)) {
val flags = translateAttributes(field);
val name = newTermName(field.Name);
val fieldType =
if (field.IsLiteral && !field.FieldType.IsEnum)
ConstantType(getConstant(getCLRType(field.FieldType), field.getValue))
else getCLRType(field.FieldType);
val owner = if (field.IsStatic()) statics else clazz;
val sym = owner.newValue(NoPos, name).setFlag(flags).setInfo(fieldType);
// TODO: set private within!!! -> look at typechecker/Namers.scala
(if (field.IsStatic()) staticDefs else instanceDefs).enter(sym);
clrTypes.fields(sym) = field;
}
for (val constr <- typ.getConstructors(); !constr.IsStatic() && !constr.IsPrivate() &&
!constr.IsAssembly() && !constr.IsFamilyAndAssembly())
createMethod(constr);
// initially also contains getters an setters of properties.
val methodsSet = new HashSet[MethodInfo]();
methodsSet ++= typ.getMethods();
for (val prop <- typ.getProperties) {
val propType: Type = getCLSType(prop.PropertyType);
if (propType != null) {
val getter: MethodInfo = prop.GetGetMethod(true);
val setter: MethodInfo = prop.GetSetMethod(true);
var gparamsLength: Int = -1;
if (!(getter == null || getter.IsPrivate || getter.IsAssembly
|| getter.IsFamilyAndAssembly))
{
assert(prop.PropertyType == getter.ReturnType);
val gparams: Array[ParameterInfo] = getter.GetParameters();
gparamsLength = gparams.length;
val name: Name = if (gparamsLength == 0) prop.Name else nme.apply;
val flags = translateAttributes(getter);
val mtype: Type = if (gparamsLength == 0) PolyType(List(), propType)
else methodType(getter, getter.ReturnType);
val owner: Symbol = if (getter.IsStatic) statics else clazz;
val methodSym = owner.newMethod(NoPos, name).setFlag(flags).setInfo(mtype);
methodSym.setFlag(Flags.ACCESSOR);
(if (getter.IsStatic) staticDefs else instanceDefs).enter(methodSym)
clrTypes.methods(methodSym) = getter;
methodsSet -= getter;
}
if (!(setter == null || setter.IsPrivate || setter.IsAssembly
|| setter.IsFamilyAndAssembly))
{
val sparams: Array[ParameterInfo] = setter.GetParameters()
if(getter != null)
assert(getter.IsStatic == setter.IsStatic);
assert(setter.ReturnType == clrTypes.VOID);
if(getter != null)
assert(sparams.length == gparamsLength + 1, "" + getter + "; " + setter);
val name: Name = if (gparamsLength == 0) nme.getterToSetter(prop.Name)
else nme.update;
val flags = translateAttributes(setter);
val mtype: Type = methodType(setter, definitions.UnitClass.tpe);
val owner: Symbol = if (setter.IsStatic) statics else clazz;
val methodSym = owner.newMethod(NoPos, name).setFlag(flags).setInfo(mtype);
methodSym.setFlag(Flags.ACCESSOR);
(if (setter.IsStatic) staticDefs else instanceDefs).enter(methodSym);
clrTypes.methods(methodSym) = setter;
methodsSet -= setter;
}
}
}
/* for (val event <- typ.GetEvents) {
// adding += and -= methods to add delegates to an event.
// raising the event ist not possible from outside the class (this is so
// generally in .net world)
val adder: MethodInfo = event.GetAddMethod();
val remover: MethodInfo = event.GetRemoveMethod();
if (!(adder == null || adder.IsPrivate || adder.IsAssembly
|| adder.IsFamilyAndAssembly))
{
assert(adder.ReturnType == clrTypes.VOID);
assert(adder.GetParameters().map(.ParameterType).toList == List(event.EventHandlerType));
val name = encode("+=");
val flags = translateAttributes(adder);
val mtype: Type = methodType(adder, adder.ReturnType);
createMethod(name, flags, mtype, adder, adder.IsStatic)
methodsSet -= adder;
}
if (!(remover == null || remover.IsPrivate || remover.IsAssembly
|| remover.IsFamilyAndAssembly))
{
assert(remover.ReturnType == clrTypes.VOID);
assert(remover.GetParameters().map(.ParameterType).toList == List(event.EventHandlerType));
val name = encode("-=");
val flags = translateAttributes(remover);
val mtype: Type = methodType(remover, remover.ReturnType);
createMethod(name, flags, mtype, remover, remover.IsStatic)
methodsSet -= remover;
}
} */
for (val method <- methodsSet.elements)
if (!method.IsPrivate() && !method.IsAssembly() && !method.IsFamilyAndAssembly())
createMethod(method);
// Create methods and views for delegate support
if (clrTypes.isDelegateType(typ)) {
createDelegateView(typ);
createDelegateChainers(typ);
}
// create the box/unbox methods for value types
if (typ.IsValueType) {
val box = statics.newMethod(NoPos, nme.box).
setInfo(MethodType(List(clazz.tpe), definitions.ObjectClass.tpe));
definitions.isBox += box;
definitions.boxMethod(clazz) = box;
val unbox = statics.newMethod(NoPos, nme.unbox).
setInfo(MethodType(List(definitions.ObjectClass.tpe), clazz.tpe));
definitions.isUnbox += unbox;
definitions.unboxMethod(clazz) = unbox;
//Console.println(typ.FullName + " : " + parents);
}
// for enumerations introduce comparison and bitwise logical operations;
// the backend should recognize and replace them with comparison or
// bitwise logical operations on the primitive underlying type
if (typ.IsEnum) {
val ENUM_CMP_NAMES = List(nme.EQ, nme.NE, nme.LT, nme.LE, nme.GT, nme.GE);
val ENUM_BIT_LOG_NAMES = List(nme.OR, nme.AND, nme.XOR);
val flags = Flags.JAVA | Flags.FINAL;
for (val cmpName <- ENUM_CMP_NAMES) {
val enumCmpType: Type = JavaMethodType(List(clazz.tpe), definitions.BooleanClass.tpe);
val enumCmp: Symbol = clazz.newMethod(NoPos, cmpName);
enumCmp.setFlag(flags).setInfo(enumCmpType)
instanceDefs.enter(enumCmp);
}
for (val bitLogName <- ENUM_BIT_LOG_NAMES) {
val enumBitLogType = JavaMethodType(List(clazz.tpe), classInfo);
val enumBitLog = clazz.newMethod(NoPos, bitLogName);
enumBitLog.setFlag(flags).setInfo(enumBitLogType);
instanceDefs.enter(enumBitLog);
}
}
} // parseClass
private def createMethod(method: MethodBase): Unit = {
val rettype = if (method.IsConstructor()) clazz.tpe
else getCLSType(method.asInstanceOf[MethodInfo].ReturnType);
if (rettype == null) return;
val mtype = methodType(method, rettype);
if (mtype == null) return;
val flags = translateAttributes(method);
val owner = if (method.IsStatic()) statics else clazz;
val methodSym = owner.newMethod(NoPos, getName(method)).setFlag(flags).
setInfo(mtype);
(if (method.IsStatic()) staticDefs else instanceDefs).enter(methodSym);
if (method.IsConstructor())
clrTypes.constructors(methodSym) = method.asInstanceOf[ConstructorInfo]
else clrTypes.methods(methodSym) = method.asInstanceOf[MethodInfo];
}
private def createMethod(name: Name, flags: Long, args: Array[MSILType], retType: MSILType, method: MethodInfo, statik: Boolean): Symbol = {
val mtype: Type = methodType(args, getCLSType(retType));
assert(mtype != null);
createMethod(name, flags, mtype, method, statik)
}
private def createMethod(name: Name, flags: Long, mtype: Type, method: MethodInfo, statik: Boolean): Symbol = {
val methodSym: Symbol = (if (statik) statics else clazz).newMethod(NoPos, name);
methodSym.setFlag(flags).setInfo(mtype);
(if (statik) staticDefs else instanceDefs).enter(methodSym);
if (method != null)
clrTypes.methods(methodSym) = method;
methodSym
}
private def createDelegateView(typ: MSILType) = {
val invoke: MethodInfo = typ.GetMember("Invoke")(0).asInstanceOf[MethodInfo];
val invokeRetType: Type = getCLRType(invoke.ReturnType);
val invokeParamTypes: List[Type] =invoke.GetParameters().map(.ParameterType).map(getCLSType).toList;
val funType: Type = definitions.functionType(invokeParamTypes, invokeRetType);
val typClrType: Type = getCLRType(typ);
val flags = Flags.JAVA | Flags.STATIC | Flags.IMPLICIT; // todo: static? think not needed
// create the forward view: delegate => function
val delegateParamTypes: List[Type] = List(typClrType);
// not ImplicitMethodType, this is for methods with implicit parameters (not implicit methods)
val forwardViewMethodType = JavaMethodType(delegateParamTypes, funType);
val fmsym = createMethod(nme.view_, flags, forwardViewMethodType, null, true);
// create the backward view: function => delegate
val functionParamTypes: List[Type] = List(funType);
val backwardViewMethodType = JavaMethodType(functionParamTypes, typClrType);
val bmsym = createMethod(nme.view_, flags, backwardViewMethodType, null, true);
}
private def createDelegateChainers(typ: MSILType) = {
val flags: Long = Flags.JAVA | Flags.FINAL;
val args: Array[MSILType] = Array(typ);
var s = createMethod(encode("+="), flags, args, clrTypes.VOID, clrTypes.DELEGATE_COMBINE, false);
s = createMethod(encode("-="), flags, args, clrTypes.VOID, clrTypes.DELEGATE_REMOVE, false);
s = createMethod(nme.PLUS, flags, args, typ, clrTypes.DELEGATE_COMBINE, false);
s = createMethod(nme.MINUS, flags, args, typ, clrTypes.DELEGATE_REMOVE, false);
}
private def getName(method: MethodBase): Name = {
if (method.IsConstructor()) return nme.CONSTRUCTOR;
val name = method.Name;
if (method.IsStatic()) return newTermName(name);
val params = method.GetParameters();
name match {
case "GetHashCode" if (params.length == 0) => nme.hashCode_;
case "ToString" if (params.length == 0) => nme.toString_;
case "Finalize" if (params.length == 0) => nme.finalize_;
case "Equals" if (params.length == 1 && params(0).ParameterType == clrTypes.OBJECT) =>
nme.equals_;
case "Invoke" if (clrTypes.isDelegateType(method.DeclaringType)) => nme.apply;
case _ => newTermName(name);
}
}
//##########################################################################
private def methodType(method: MethodBase, rettype: MSILType): Type = {
val rtype = getCLSType(rettype);
if (rtype == null) null else methodType(method, rtype);
}
/** Return a method type for the given method. */
private def methodType(method: MethodBase, rettype: Type): Type =
methodType(method.GetParameters().map(.ParameterType), rettype);
/** Return a method type for the provided argument types and return type. */
private def methodType(argtypes: Array[MSILType], rettype: Type): Type = {
def paramType(typ: MSILType): Type =
if (typ eq clrTypes.OBJECT) definitions.AnyClass.tpe
else getCLSType(typ);
val ptypes = argtypes.map(paramType).toList;
if (ptypes.contains(null)) null
else JavaMethodType(ptypes, rettype);
}
//##########################################################################
private def getClassType(typ: MSILType): Type = {
assert(typ != null);
val res = definitions.getClass(typ.FullName.replace('+', '.')).tpe;
//if (res.isError())
// global.reporter.error("unknown class reference " + type.FullName);
res
}
private def getCLSType(typ: MSILType): Type = {
if (/*type == clrTypes.BYTE ||*/ typ == clrTypes.USHORT
|| typ == clrTypes.UINT || typ == clrTypes.ULONG
|| typ.IsNotPublic() || typ.IsNestedPrivate()
|| typ.IsNestedAssembly() || typ.IsNestedFamANDAssem()
|| typ.IsPointer()
|| (typ.IsArray() && getCLSType(typ.GetElementType()) == null))
null;
//Symbol s = clrTypes.getSymbol(type);
//scalac.symtab.Type t = s != null ? make.classType(s) : getCLRType(type);
else
getCLRType(typ)
}
private def getCLRType(typ: MSILType): Type =
if (typ == clrTypes.OBJECT)
definitions.ObjectClass.tpe;
else if (typ == clrTypes.VALUE_TYPE)
definitions.AnyValClass.tpe
else if (typ == clrTypes.STRING)
definitions.StringClass.tpe;
else if (typ == clrTypes.VOID)
definitions.UnitClass.tpe
else if (typ == clrTypes.BOOLEAN)
definitions.BooleanClass.tpe
else if (typ == clrTypes.CHAR)
definitions.CharClass.tpe
else if (typ == clrTypes.BYTE || typ == clrTypes.UBYTE)
definitions.ByteClass.tpe
else if (typ == clrTypes.SHORT || typ == clrTypes.USHORT)
definitions.ShortClass.tpe
else if (typ == clrTypes.INT || typ == clrTypes.UINT)
definitions.IntClass.tpe
else if (typ == clrTypes.LONG || typ == clrTypes.ULONG)
definitions.LongClass.tpe
else if (typ == clrTypes.FLOAT)
definitions.FloatClass.tpe
else if (typ == clrTypes.DOUBLE)
definitions.DoubleClass.tpe
else if (typ.IsArray())
appliedType(definitions.ArrayClass.tpe,
List(getCLRType(typ.GetElementType())));
else {
val res = clrTypes.sym2type.get (typ) match {
case Some(sym) => sym.tpe
case None => getClassType(typ);
}
assert (res != null, typ)
res
}
// the values are Java-Box-Classes (e.g. Integer, Boolean, Character)
// java.lang.Number to get the value (if a number, not for boolean, character)
// see ch.epfl.lamp.compiler.msil.util.PEStream.java
def getConstant(constType: Type, value: Object): Constant = {
val typeClass = constType.symbol
if (typeClass == definitions.BooleanClass)
Constant(value.asInstanceOf[java.lang.Boolean].booleanValue)
else if (typeClass == definitions.ByteClass)
Constant(value.asInstanceOf[java.lang.Number].byteValue)
else if (typeClass == definitions.ShortClass)
Constant(value.asInstanceOf[java.lang.Number].shortValue)
else if (typeClass == definitions.CharClass)
Constant(value.asInstanceOf[java.lang.Character].charValue)
else if (typeClass == definitions.IntClass)
Constant(value.asInstanceOf[java.lang.Number].intValue)
else if (typeClass == definitions.LongClass)
Constant(value.asInstanceOf[java.lang.Number].longValue)
else if (typeClass == definitions.FloatClass)
Constant(value.asInstanceOf[java.lang.Number].floatValue)
else if (typeClass == definitions.DoubleClass)
Constant(value.asInstanceOf[java.lang.Number].doubleValue)
else if (typeClass == definitions.StringClass)
Constant(value.asInstanceOf[java.lang.String])
else
abort("illegal value: " + value + ", class-symbol: " + typeClass)
}
private def translateAttributes(typ: MSILType): Long = {
var flags: Long = Flags.JAVA;
if (typ.IsNotPublic() || typ.IsNestedPrivate()
|| typ.IsNestedAssembly() || typ.IsNestedFamANDAssem())
flags = flags | Flags.PRIVATE;
else if (typ.IsNestedFamily() || typ.IsNestedFamORAssem())
flags = flags | Flags.PROTECTED;
if (typ.IsAbstract())
flags = flags | Flags.ABSTRACT;
if (typ.IsSealed())
flags = flags | Flags.FINAL;
if (typ.IsInterface())
flags = flags | Flags.INTERFACE | Flags.TRAIT | Flags.ABSTRACT;
flags
}
private def translateAttributes(field: FieldInfo): Long = {
var flags: Long = Flags.JAVA;
if (field.IsPrivate() || field.IsAssembly() || field.IsFamilyAndAssembly())
flags = flags | Flags.PRIVATE;
else if (field.IsFamily() || field.IsFamilyOrAssembly())
flags = flags | Flags.PROTECTED;
if (field.IsInitOnly())
flags = flags | Flags.FINAL;
else
flags = flags | Flags.MUTABLE;
if (field.IsStatic)
flags = flags | Flags.STATIC
flags
}
private def translateAttributes(method: MethodBase): Long = {
var flags: Long = Flags.JAVA;
if (method.IsPrivate() || method.IsAssembly() || method.IsFamilyAndAssembly())
flags = flags | Flags.PRIVATE;
else if (method.IsFamily() || method.IsFamilyOrAssembly())
flags = flags | Flags.PROTECTED;
if (method.IsAbstract())
flags = flags | Flags.DEFERRED;
if (method.IsStatic)
flags = flags | Flags.STATIC
flags
}
}

View File

@ -69,7 +69,7 @@ abstract class CleanUp extends Transform {
}
override def transformUnit(unit: CompilationUnit) =
if (settings.target.value != "jvm-1.5") {
if (settings.target.value != "jvm-1.5" && !forMSIL) {
unit.body = transform(unit.body)
}

View File

@ -85,7 +85,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
else apply(parents.head)
case ClassInfoType(parents, decls, clazz) =>
ClassInfoType(
if ((clazz == ObjectClass) || (isValueClass(clazz))) List()
if ((clazz == ObjectClass) || (isValueType(clazz))) List()
else if (clazz == ArrayClass) List(erasedTypeRef(ObjectClass))
else removeDoubleObject(parents map this),
decls, clazz)
@ -308,7 +308,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
}
else gen.mkAttributedCast(tree, pt)
} else gen.mkAttributedCast(tree, pt)
/** Is symbol a member of unboxed arrays (which will be expanded directly
* later)?
*
@ -330,10 +330,10 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
*/
private def adaptToType(tree: Tree, pt: Type): Tree = {
if (settings.debug.value && pt != WildcardType)
log("adapting " + tree + ":" + tree.tpe + " to " + pt)//debug
if (tree.tpe <:< pt)
log("adapting " + tree + ":" + tree.tpe + " : " + tree.tpe.parents + " to " + pt)//debug
if (tree.tpe <:< pt)
tree
else if (isUnboxedClass(tree.tpe.symbol) && !isUnboxedClass(pt.symbol))
else if (isUnboxedClass(tree.tpe.symbol) && !isUnboxedClass(pt.symbol))
adaptToType(box(tree), pt)
else if (tree.tpe.isInstanceOf[MethodType] && tree.tpe.paramTypes.isEmpty) {
assert(tree.symbol.isStable);
@ -403,6 +403,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
* </ul>
*/
private def adaptMember(tree: Tree): Tree = {
//Console.println("adaptMember: " + tree);
tree match {
case Apply(Select(New(tpt), name), args) if (tpt.tpe.symbol == BoxedArrayClass) =>
assert(name == nme.CONSTRUCTOR);
@ -417,7 +418,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
if (isNumericValueClass(qualClass) && isNumericValueClass(targClass))
// convert numeric type casts
atPos(tree.pos)(Apply(Select(qual1, "to" + targClass.name), List()))
else if (isValueClass(targClass) ||
else if (isValueType(targClass) ||
(targClass == ArrayClass && (qualClass isNonBottomSubClass BoxedArrayClass)))
unbox(qual1, targ.tpe)
else if (targClass == ArrayClass && qualClass == ObjectClass)
@ -435,10 +436,10 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
adaptMember(atPos(tree.pos)(Select(qual, getMember(ObjectClass, name))))
else {
var qual1 = typedQualifier(qual);
if ((isValueClass(qual1.tpe.symbol) && !isUnboxedValueMember(tree.symbol)) ||
if ((isValueType(qual1.tpe.symbol) && !isUnboxedValueMember(tree.symbol)) ||
(qual1.tpe.symbol == ArrayClass && !isUnboxedArrayMember(tree.symbol)))
qual1 = box(qual1);
else if (!isValueClass(qual1.tpe.symbol) && isUnboxedValueMember(tree.symbol))
else if (!isValueType(qual1.tpe.symbol) && isUnboxedValueMember(tree.symbol))
qual1 = unbox(qual1, tree.symbol.owner.tpe)
else if (tree.symbol.owner == ArrayClass && qual1.tpe.symbol == ObjectClass)
qual1 = cast(qual1, BoxedArrayClass.tpe)

View File

@ -243,7 +243,7 @@ trait SyntheticMethods requires Analyzer {
// jw-04-2003/jw-0425-designpatterns_p.html)
if (!hasImplementation(nme.readResolve)) ts += readResolveMethod
}
if (!forCLDC)
if (!forCLDC && !forMSIL)
for (val sym <- clazz.info.decls.toList)
if (!sym.getAttributes(BeanPropertyAttr).isEmpty)
if (sym.isGetter)

View File

@ -639,6 +639,14 @@ trait Typers requires Analyzer {
// (13); the condition prevents chains of views
if (settings.debug.value) log("inferring view from "+tree.tpe+" to "+pt)
val coercion = inferView(tree.pos, tree.tpe, pt, true)
// convert forward views of delegate types into closures wrapped around
// the delegate's apply method (the "Invoke" method, which was translated into apply)
if (forMSIL && coercion != null && isCorrespondingDelegate(tree.tpe, pt)) {
val meth: Symbol = tree.tpe.member(nme.apply)
if(settings.debug.value)
log("replacing forward delegate view with: " + meth + ":" + meth.tpe)
return typed(Select(tree, meth), mode, pt)
}
if (coercion != EmptyTree) {
if (settings.debug.value) log("inferred view from "+tree.tpe+" to "+pt+" = "+coercion+":"+coercion.tpe)
return typed(Apply(coercion, List(tree)) setPos tree.pos, mode, pt)
@ -1187,7 +1195,7 @@ trait Typers requires Analyzer {
* @return ...
*/
def typedFunction(fun: Function, mode: int, pt: Type): Tree = {
val codeExpected = !forCLDC && (pt.symbol isNonBottomSubClass CodeClass)
val codeExpected = !forCLDC && !forMSIL && (pt.symbol isNonBottomSubClass CodeClass)
def decompose(pt: Type): {Symbol, List[Type], Type} =
if (isFunctionType(pt)
@ -1361,6 +1369,28 @@ trait Typers requires Analyzer {
case MethodType(_, rtp) if ((mode & PATTERNmode) != 0) => rtp
case _ => tp
}
// Replace the Delegate-Chainer methods += and -= with corresponding
// + and - calls, which are translated in the code generator into
// Combine and Remove
if (forMSIL) {
fun match {
case Select(qual, name) =>
if (isSubType(qual.tpe, definitions.DelegateClass.tpe)
&& (name == encode("+=") || name == encode("-=")))
{
val n = if (name == encode("+=")) nme.PLUS else nme.MINUS
val f = Select(qual, n)
// the compiler thinks, the PLUS method takes only one argument,
// but he thinks it's an instance method -> still two ref's on the stack
// -> translated by backend
val rhs = copy.Apply(tree, f, args)
return typed(Assign(qual, rhs))
}
case _ => ()
}
}
if (fun.symbol == List_apply && args.isEmpty) {
atPos(tree.pos) { gen.mkNil setType restpe }
} else if ((mode & CONSTmode) != 0 && fun.symbol.owner == PredefModule.tpe.symbol && fun.symbol.name == nme.Array) {
@ -2007,7 +2037,23 @@ trait Typers requires Analyzer {
case PolyType(_, MethodType(formals, _)) =>
adapt(expr1, mode, functionType(formals map (t => WildcardType), WildcardType))
case MethodType(formals, _) =>
adapt(expr1, mode, functionType(formals map (t => WildcardType), WildcardType))
expr1 match {
case Select(qual, name) =>
if(forMSIL && pt != WildcardType && pt != ErrorType && isSubType(pt, definitions.DelegateClass.tpe)) {
val scalaCaller = newScalaCaller(pt);
addScalaCallerInfo(scalaCaller, expr1.symbol)
val n: Name = scalaCaller.name
val del = Ident(DelegateClass) setType DelegateClass.tpe
val f = Select(del, n)
//val f1 = TypeApply(f, List(Ident(pt.symbol) setType pt))
val args: List[Tree] = if(expr1.symbol.isStatic) List(Literal(Constant(null)))
else List(qual) // where the scala-method is located
val rhs = Apply(f, args);
return typed(rhs)
}
case _ => ()
}
adapt(expr1, mode, functionType(formals map (t => WildcardType), WildcardType))
case ErrorType =>
expr1
case _ =>

View File

@ -204,7 +204,7 @@ object Console {
*/
def readLine(text: String, args: Any*): String = {
format(text, args: _*)
in.readLine()
readLine
}
@ -212,7 +212,7 @@ object Console {
*
* @return the boolean value read from the terminal.
*/
def readBoolean: Boolean = in.readLine().toLowerCase() match {
def readBoolean: Boolean = readLine.toLowerCase() match {
case "true" => true
case "t" => true
case "yes" => true
@ -252,7 +252,7 @@ object Console {
* @return a list of all extracted values.
*/
def readf(format: String): List[Any] =
textComponents(new MessageFormat(format).parse(in.readLine()))
textComponents(new MessageFormat(format).parse(readLine))
/** Read in some structured input, specified by a format specifier.
* Opposed to <code>readf</code>, this function only returns the

View File

@ -45,7 +45,7 @@ abstract class Enumeration(initial: Int, names: String*) {
def this(names: String*) = this(0, names: _*)
def name = {
val cname = compat.Platform.getClassName(this)
val cname = this.getClass().getName()
if (cname.endsWith("$"))
cname.substring(0, cname.length() - 1)
else if (cname.endsWith("$class"))

View File

@ -26,15 +26,12 @@ object Platform {
def createArray(elemClass: Class, length: Int): AnyRef =
java.lang.reflect.Array.newInstance(elemClass, length)
def getClass(obj: AnyRef) = obj.getClass()
def getClassName(obj: AnyRef) = obj.getClass().getName()
def getName(cls: Class) = cls.getName()
def getElementClass(obj: AnyRef) = obj.getClass().getComponentType()
def getClassForName(name: String): Class = java.lang.Class.forName(name)
val EOL = System.getProperty("line.separator", "\n")
def currentTime: Long = System.currentTimeMillis()
def collectGarbage: Unit = System.gc()
}

View File

@ -13,7 +13,7 @@ package scala.runtime
import Predef.Class
import compat.Platform.{createArray, getElementClass}
import compat.Platform.createArray
[serializable]
final class BoxedObjectArray(val value: Array[AnyRef]) extends BoxedArray {
@ -36,7 +36,7 @@ final class BoxedObjectArray(val value: Array[AnyRef]) extends BoxedArray {
override def hashCode(): Int = value.hashCode()
private def create(length: Int): Array[AnyRef] = {
createArray(getElementClass(value), length).asInstanceOf[Array[AnyRef]]
createArray(value.getClass().getComponentType(), length).asInstanceOf[Array[AnyRef]]
}
override def subArray(start: Int, end: Int): Array[AnyRef] = {

View File

@ -16,7 +16,6 @@ import scala.util.regexp.Base
import scala.collection.mutable
import scala.collection.immutable
import compat.Platform
/** this turns a regexp over A into a NondetWorkAutom over A using the
* celebrated position automata construction (also called Berry-Sethi or
@ -64,7 +63,7 @@ abstract class BaseBerrySethi {
tmp
case Star(t) => compFirst(t)
case _ =>
throw new IllegalArgumentException("unexpected pattern " + Platform.getClass(r))
throw new IllegalArgumentException("unexpected pattern " + r.getClass())
}
/** computes last( r ) for the regexp r */
@ -89,7 +88,7 @@ abstract class BaseBerrySethi {
tmp
case Star(t) => compLast(t)
case _ =>
throw new IllegalArgumentException("unexpected pattern " + Platform.getClass(r))
throw new IllegalArgumentException("unexpected pattern " + r.getClass())
}
/** Starts from the right-to-left
@ -170,7 +169,7 @@ abstract class BaseBerrySethi {
first
case _ =>
throw new IllegalArgumentException("unexpected pattern: " + Platform.getClass(r))
throw new IllegalArgumentException("unexpected pattern: " + r.getClass())
}
}
@ -193,7 +192,7 @@ abstract class BaseBerrySethi {
case Star(t) =>
traverse(t)
case _ =>
throw new IllegalArgumentException("unexp pattern " + Platform.getClass(r))
throw new IllegalArgumentException("unexp pattern " + r.getClass())
}
}

View File

@ -3,6 +3,8 @@
//############################################################################
// $Id$
import scala.compat.StringBuilder;
object M0 {
class Rational(x: Int, y: Int) {
def numer = x;
@ -230,10 +232,10 @@ object M8 {
def intersect2(that: IntSet): IntSet = filter(x => that.contains(x));
def filter(f: Int => Boolean): IntSet = filter0(f, new Empty);
def printOn(out: java.io.PrintStream) = foreach(out.println);
def print() = foreach(Console.println);
override def toString(): String = {
val buffer: java.lang.StringBuffer = new java.lang.StringBuffer();
val buffer: StringBuilder = new StringBuilder();
buffer.append('[');
foreach(i => {
if (buffer.length() > 1) {buffer.append(','); ()}; // !!! ; ()
@ -312,7 +314,7 @@ object M8 {
Console.println;
Console.println("set4 contains the following elements:");
set4.printOn(java.lang.System.out);
set4.print();
Console.println;
Console.println("2 <- set2: " + (set2 contains 2));

View File

@ -359,9 +359,9 @@ trait Bug266BB extends Bug266BA {
val in = 3;
}
object Bug266BTest extends Application {
val a: Bug266BA1 = new Bug266BA1 with Bug266BB;
a.mkP.f(a.in);
object Bug266BTest {
val a: Bug266BA1 = new Bug266BA1 with Bug266BB;
def test(args: Array[String]): Unit = a.mkP.f(a.in);
}
// main
@ -369,7 +369,7 @@ object Bug266BTest extends Application {
object Bug266Test {
def test(args: Array[String]): Unit = {
Bug266ATest.test(args);
Bug266BTest;
Bug266BTest.test(args);
}
}
@ -412,9 +412,9 @@ trait Bug396C extends Bug396A {
override def run = { super.run; Console.println("C"); }
}
}
object Bug396Test extends Application with Bug396B with Bug396C {
object Bug396Test extends Bug396B with Bug396C {
class I2 extends super[Bug396B].I with super[Bug396C].I;
(new I2).run
def test(args: Array[String]): Unit = (new I2).run
}
//############################################################################
@ -478,7 +478,7 @@ object Test {
test(266, Bug266Test.test(args));
test(316, Bug316Test.test(args));
test(328, Bug328Test.test(args));
test(396, Bug396Test);
test(396, Bug396Test.test(args));
test(399, Bug399Test.test(args));
if (errors > 0) {

View File

@ -0,0 +1,66 @@
RichCharTest1:
True
True
True
False
RichIntTest:
10
11
12
13
0
0
RichStringTest1:
s1: abc
s2: abc\txyz\n
s3: abc
xyz
s4: abc
|xyz
s5: abc
#xyz
RichStringTest2:
s1: abc
s2: abc\txyz\n
s3: abc
xyz
s4: abc
|xyz
s5: abc
#xyz
RichStringTest3:
s1: abc
s2: abc\txyz\n
s3: abc
xyz
s4: abc
|xyz
s5: abc
#xyz
RichStringTest4:
s1: abc
s2: abc\txyz\n
s3: abc
xyz
s4: abc
xyz
s5: abc
#xyz
RichStringTest5:
s1: abc
xyz
s2: abc
xyz
s3: abc
xyz
s4: abc
|xyz
s5: abc
xyz

View File

@ -5,9 +5,6 @@ true
true
true
RichCharTest2:
true
RichIntTest:
10
11

View File

@ -8,7 +8,7 @@ trait RichTest {
val s5 = """abc
#xyz"""
def getObjectName: String = {
val cn = compat.Platform.getClassName(this)
val cn = this.getClass().getName()
cn.substring(0, cn.length-1)
}
def length[A](it: Iterator[A]) = it.toList length
@ -23,24 +23,24 @@ object RichCharTest1 extends RichTest {
Console.println('A'.asDigit == 10)
}
}
object RichCharTest2 extends RichTest {
case class C(s: String) {
private val it = s.elements
private var c: Char = _
def ch(): Char = c
def nextch(): Unit = { c = if (it.hasNext) it.next else ';' }
def err(msg: String) = Console.println(msg)
nextch()
}
def run {
Console.println("\n" + getObjectName + ":")
val c1 = C("x4A;")
val s1 = xml.Utility.parseCharRef(c1.ch, c1.nextch, c1.err)
val c2 = C("74;")
val s2 = xml.Utility.parseCharRef(c2.ch, c2.nextch, c2.err)
Console.println(s1 == s2)
}
}
// object RichCharTest2 extends RichTest {
// case class C(s: String) {
// private val it = s.elements
// private var c: Char = _
// def ch(): Char = c
// def nextch(): Unit = { c = if (it.hasNext) it.next else ';' }
// def err(msg: String) = Console.println(msg)
// nextch()
// }
// def run {
// Console.println("\n" + getObjectName + ":")
// val c1 = C("x4A;")
// val s1 = xml.Utility.parseCharRef(c1.ch, c1.nextch, c1.err)
// val c2 = C("74;")
// val s2 = xml.Utility.parseCharRef(c2.ch, c2.nextch, c2.err)
// Console.println(s1 == s2)
// }
// }
object RichIntTest extends RichTest {
private val n = 10
private val m = -2
@ -107,7 +107,7 @@ object RichStringTest5 extends RichTest {
object Test {
def main(args: Array[String]): Unit = {
RichCharTest1.run
RichCharTest2.run
//RichCharTest2.run
RichIntTest.run
RichStringTest1.run
RichStringTest2.run

View File

@ -43,12 +43,12 @@ object Test extends AnyRef with Application {
def try4 = {
if (instance == null) {
instance = try {
new String();
} catch {
"" //new String();
} catch {
case _ =>
val cs = "aaa";
if (cs.length() > 0) {
new String();
"" //new String();
} else {
throw new Error("fatal error");
null

View File

@ -687,9 +687,9 @@ fi;
SCALA="${BIN_DIR}scala";
if [ "$USEFSC" = "true" ]; then
SCALAC="${BIN_DIR}fsc -deprecation -encoding iso-8859-1";
SCALAC="${BIN_DIR}fsc -nowarn -deprecation -encoding iso-8859-1";
else
SCALAC="${BIN_DIR}scalac -deprecation -encoding iso-8859-1";
SCALAC="${BIN_DIR}scalac -nowarn -deprecation -encoding iso-8859-1";
fi;
SCALAP="scalap";
ANT="ant";