diff options
Diffstat (limited to 'src')
8 files changed, 54 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() diff --git a/src/library/scala/native.scala b/src/library/scala/native.scala new file mode 100644 index 0000000000..c49f0a0579 --- /dev/null +++ b/src/library/scala/native.scala @@ -0,0 +1,24 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: $ + + +package scala + +/** + * Marker for native methods. + * <p> + * <code>@native def f(x: Int, y: List[Long]): String = ..</code> + * </p> + * <p> + * Method body is not generated if method is marked with <code>@native</code>, + * but it is type checked when present. + * </p> + */ +class native extends Annotation {} |