diff options
author | Iulian Dragos <jaguarul@gmail.com> | 2007-06-09 17:00:37 +0000 |
---|---|---|
committer | Iulian Dragos <jaguarul@gmail.com> | 2007-06-09 17:00:37 +0000 |
commit | d4cc633ec978a0a6e04e11c2d6d8425e2d3b3725 (patch) | |
tree | d4dfc570e0d8fa11f15ee2ae6c4bcc019a1ae975 /src/compiler | |
parent | 8414ebada9615aac0e8b436e7bdbeee5986ccaa3 (diff) | |
download | scala-d4cc633ec978a0a6e04e11c2d6d8425e2d3b3725.tar.gz scala-d4cc633ec978a0a6e04e11c2d6d8425e2d3b3725.tar.bz2 scala-d4cc633ec978a0a6e04e11c2d6d8425e2d3b3725.zip |
Added patch to allow definition of native metho...
Added patch to allow definition of native methods in Scala (contribution
from Stepan Koltsov)
Diffstat (limited to 'src/compiler')
7 files changed, 30 insertions, 8 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index fd396acd37..09935b69e6 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -109,8 +109,10 @@ abstract class GenICode extends SubComponent { var ctx1 = ctx.enterMethod(m, tree.asInstanceOf[DefDef]) addMethodParams(ctx1, vparamss) + val NativeAttr = atPhase(currentRun.typerPhase)(definitions.getClass("scala.native").tpe) + m.native = m.symbol.hasAttribute(NativeAttr) - if (!m.isDeferred) { + if (!m.isDeferred && !m.native) { ctx1 = genLoad(rhs, ctx1, m.returnType); // reverse the order of the local variables, to match the source-order diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index bc8f4b1dd9..0203d73f39 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -404,6 +404,10 @@ abstract class GenJVM extends SubComponent { if (jclass.isInterface()) flags = flags | JAccessFlags.ACC_ABSTRACT; + // native methods of objects are generated in mirror classes + if (method.native) + flags = flags | JAccessFlags.ACC_NATIVE + jmethod = jclass.addNewMethod(flags, javaName(m.symbol), resTpe, @@ -421,7 +425,7 @@ abstract class GenJVM extends SubComponent { m.symbol.attributes = ainfo :: m.symbol.attributes; } - if (!jmethod.isAbstract()) { + if (!jmethod.isAbstract() && !method.native) { jcode = jmethod.getCode().asInstanceOf[JExtendedCode] // add a fake local for debugging purpuses diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala index a4a3b0ce79..566568b16a 100644 --- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala +++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala @@ -99,6 +99,7 @@ trait Definitions { var PredefModule: Symbol = _ def Predef_classOf = getMember(PredefModule, nme.classOf) def Predef_identity = getMember(PredefModule, nme.identity) + def Predef_error = getMember(PredefModule, nme.error) var ConsoleModule: Symbol = _ var MatchErrorClass: Symbol = _ //var MatchErrorModule: Symbol = _ @@ -369,6 +370,7 @@ trait Definitions { var DeprecatedAttr: Symbol = _ var BeanPropertyAttr: Symbol = _ var AnnotationDefaultAttr: Symbol = _ + var NativeAttr: Symbol = _ def getModule(fullname: Name): Symbol = getModuleOrClass(fullname, true) @@ -937,6 +939,7 @@ trait Definitions { SerializableAttr = getClass("scala.serializable") BeanPropertyAttr = if (forCLDC || forMSIL) null else getClass("scala.reflect.BeanProperty") DeprecatedAttr = getClass("scala.deprecated") + NativeAttr = getClass("scala.native") SyntheticClasses = new HashSet[Symbol] SyntheticClasses ++= List( diff --git a/src/compiler/scala/tools/nsc/symtab/StdNames.scala b/src/compiler/scala/tools/nsc/symtab/StdNames.scala index 12fbe8cf80..60caa722a8 100644 --- a/src/compiler/scala/tools/nsc/symtab/StdNames.scala +++ b/src/compiler/scala/tools/nsc/symtab/StdNames.scala @@ -259,6 +259,7 @@ trait StdNames { val equals_ = newTermName("equals") val _equals = newTermName("_equals") val _equalsWithVarArgs = newTermName("_equalsWithVarArgs") + val error = newTermName("error") val ex = newTermName("ex") val fail = newTermName("fail") val false_ = newTermName("false") diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index c21a606ec4..f3f48d3c72 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -81,6 +81,11 @@ trait Symbols { } var attributes: List[AnnotationInfo] = List() + def hasAttribute(Tpe: Type): Boolean = + attributes.exists { + case AnnotationInfo(Tpe, _, _) => true + case _ => false + } var privateWithin: Symbol = _ diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 944d271d1d..9494b3bba6 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -741,7 +741,7 @@ trait Namers { self: Analyzer => * - `abstract' modifier only for classes * - `override' modifier never for classes * - `def' modifier never for parameters of case classes - * - declarations only in mixins or abstract classes + * - declarations only in mixins or abstract classes (when not @native) */ def validate(sym: Symbol): unit = { def checkNoConflict(flag1: int, flag2: int): unit = @@ -769,12 +769,14 @@ trait Namers { self: Analyzer => sym.isValueParameter && sym.owner.isClass && sym.owner.hasFlag(CASE)) context.error(sym.pos, "pass-by-name arguments not allowed for case class parameters"); if ((sym.flags & DEFERRED) != 0) { - if (!sym.isValueParameter && !sym.isTypeParameterOrSkolem && - !context.tree.isInstanceOf[ExistentialTypeTree] && - (!sym.owner.isClass || sym.owner.isModuleClass || sym.owner.isAnonymousClass)) { - context.error(sym.pos, - "only classes can have declared but undefined members" + varNotice(sym)) + if (sym.hasAttribute(definitions.NativeAttr.tpe)) sym.resetFlag(DEFERRED) + else if (!sym.isValueParameter && !sym.isTypeParameterOrSkolem && + !context.tree.isInstanceOf[ExistentialTypeTree] && + (!sym.owner.isClass || sym.owner.isModuleClass || sym.owner.isAnonymousClass)) { + context.error(sym.pos, + "only classes can have declared but undefined members" + varNotice(sym)) + sym.resetFlag(DEFERRED) } } checkNoConflict(DEFERRED, PRIVATE) diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index c81e28a398..f178590a42 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -692,6 +692,11 @@ abstract class RefChecks extends InfoTransform { validateVariance(sym, sym.info, CoVariance) validateVariance(sym, sym.typeOfThis, CoVariance) + case DefDef(mods, name, tparams, vparams, tpt, EmptyTree) if tree.symbol.hasAttribute(definitions.NativeAttr.tpe) => + tree.symbol.resetFlag(DEFERRED) + result = transform(copy.DefDef(tree, mods, name, tparams, vparams, tpt, + typed(Apply(gen.mkAttributedRef(definitions.Predef_error), List(Literal("native method stub")))))) + case DefDef(_, _, _, _, _, _) => validateVariance(sym, sym.tpe, CoVariance) //@M TODO: might be affected by change in tpe --> can't use tree.tpe though checkDeprecatedOvers() |