From: <ta...@us...> - 2009-12-25 23:53:26
|
Revision: 12416 http://x10.svn.sourceforge.net/x10/?rev=12416&view=rev Author: tardieu Date: 2009-12-25 23:53:19 +0000 (Fri, 25 Dec 2009) Log Message: ----------- added support for native constructors and factory methods in @NativeClass classes Modified Paths: -------------- trunk/x10.compiler/src/x10/visit/NativeClassVisitor.java trunk/x10.runtime/src-x10/x10/runtime/Lock.x10 trunk/x10.runtime/src-x10/x10/runtime/X10Deque.x10 Modified: trunk/x10.compiler/src/x10/visit/NativeClassVisitor.java =================================================================== --- trunk/x10.compiler/src/x10/visit/NativeClassVisitor.java 2009-12-25 04:31:10 UTC (rev 12415) +++ trunk/x10.compiler/src/x10/visit/NativeClassVisitor.java 2009-12-25 23:53:19 UTC (rev 12416) @@ -11,12 +11,17 @@ import java.util.Collections; import java.util.List; +import polyglot.ast.Assign; +import polyglot.ast.Call; import polyglot.ast.CanonicalTypeNode; import polyglot.ast.ClassBody; import polyglot.ast.ClassMember; +import polyglot.ast.ConstructorDecl; import polyglot.ast.Expr; import polyglot.ast.Formal; +import polyglot.ast.Id; import polyglot.ast.IntLit; +import polyglot.ast.New; import polyglot.ast.Node; import polyglot.ast.NodeFactory; import polyglot.ast.Receiver; @@ -27,8 +32,10 @@ import polyglot.types.ConstructorInstance; import polyglot.types.ClassDef; import polyglot.types.ClassType; +import polyglot.types.ConstructorDef; import polyglot.types.Flags; import polyglot.types.FieldDef; +import polyglot.types.LocalDef; import polyglot.types.MethodInstance; import polyglot.types.Name; import polyglot.types.QName; @@ -41,10 +48,13 @@ import polyglot.visit.ContextVisitor; import polyglot.visit.NodeVisitor; import x10.ast.AnnotationNode; +import x10.ast.X10ConstructorDecl; import x10.ast.X10ClassDecl; import x10.ast.X10MethodDecl; import x10.ast.X10NodeFactory; import x10.extension.X10Ext; +import x10.types.X10Def; +import x10.types.X10ConstructorDef; import x10.types.X10ClassDef; import x10.types.X10ClassType; import x10.types.X10Flags; @@ -59,64 +69,51 @@ final String theLanguage; final X10TypeSystem xts; final X10NodeFactory xnf; - final Position pos; - final Name fieldName; public NativeClassVisitor(Job job, TypeSystem ts, NodeFactory nf, String theLanguage) { super(job, ts, nf); xts = (X10TypeSystem) ts; xnf = (X10NodeFactory) nf; this.theLanguage = theLanguage; - pos = Position.COMPILER_GENERATED; - fieldName = Name.make("__NATIVE_FIELD__"); } - public boolean isNativeMethod(X10MethodDef def) { - try { - Type t = (Type) xts.systemResolver().find(QName.make("x10.compiler.NativeDef")); - List<Type> as = def.annotationsMatching(t); - for (Type at : as) { - String lang = getPropertyInit(at, 0); - if (theLanguage.equals(lang)) { - return true; - } + protected boolean isNativeDef(X10Def def) throws SemanticException { + Type t = (Type) xts.systemResolver().find(QName.make("x10.compiler.NativeDef")); + List<Type> as = def.annotationsMatching(t); + for (Type at : as) { + String lang = getPropertyInit(at, 0); + if (theLanguage.equals(lang)) { + return true; } } - catch (SemanticException e) {} return false; } - public String getNativeClassName(X10ClassDef def) { - try { - Type t = (Type) xts.systemResolver().find(QName.make("x10.compiler.NativeClass")); - List<Type> as = def.annotationsMatching(t); - for (Type at : as) { - String lang = getPropertyInit(at, 0); - if (theLanguage.equals(lang)) { - return getPropertyInit(at, 2); - } + protected String getNativeClassName(X10ClassDef def) throws SemanticException { + Type t = (Type) xts.systemResolver().find(QName.make("x10.compiler.NativeClass")); + List<Type> as = def.annotationsMatching(t); + for (Type at : as) { + String lang = getPropertyInit(at, 0); + if (theLanguage.equals(lang)) { + return getPropertyInit(at, 2); } } - catch (SemanticException e) {} return null; } - public String getNativeClassPackage(X10ClassDef def) { - try { - Type t = (Type) xts.systemResolver().find(QName.make("x10.compiler.NativeClass")); - List<Type> as = def.annotationsMatching(t); - for (Type at : as) { - String lang = getPropertyInit(at, 0); - if (theLanguage.equals(lang)) { - return getPropertyInit(at, 1); - } + protected String getNativeClassPackage(X10ClassDef def) throws SemanticException { + Type t = (Type) xts.systemResolver().find(QName.make("x10.compiler.NativeClass")); + List<Type> as = def.annotationsMatching(t); + for (Type at : as) { + String lang = getPropertyInit(at, 0); + if (theLanguage.equals(lang)) { + return getPropertyInit(at, 1); } } - catch (SemanticException e) {} return null; } - String getPropertyInit(Type at, int index) throws SemanticException { + protected String getPropertyInit(Type at, int index) throws SemanticException { at = X10TypeMixin.baseType(at); if (at instanceof X10ClassType) { X10ClassType act = (X10ClassType) at; @@ -124,8 +121,7 @@ Expr e = act.propertyInitializer(index); if (e.isConstant() && e.constantValue() instanceof String) { return (String) e.constantValue(); - } - else { + } else { throw new SemanticException("Property initializer for @" + at + " must be a string literal."); } } @@ -133,88 +129,179 @@ return null; } + protected static X10Flags clearNative(Flags flags) { + return X10Flags.toX10Flags(flags).clearX(Flags.NATIVE); + } + protected Node leaveCall(Node parent, Node old, Node n, NodeVisitor v) throws SemanticException { // look for @NativeClass class declarations - if (!(n instanceof X10ClassDecl)) + if (!(n instanceof X10ClassDecl)) return n; - - X10ClassDecl cd = (X10ClassDecl) n; - X10ClassDef cf = (X10ClassDef) cd.classDef(); - String cn = getNativeClassName(cf); - - if (cn == null) + X10ClassDecl cdecl = (X10ClassDecl) n; + X10ClassDef cdef = (X10ClassDef) cdecl.classDef(); + String cname = getNativeClassName(cdef); + + if (cname == null) return n; if (Report.should_report("nativeclass", 1)) - Report.report(1, "Processing @NativeClass " + cd); + Report.report(1, "Processing @NativeClass " + cdecl); - ClassBody cb = cd.body(); - List<ClassMember> cm = new ArrayList<ClassMember>(); + ClassBody cbody = cdecl.body(); + List<ClassMember> cmembers = new ArrayList<ClassMember>(); + Position p = Position.COMPILER_GENERATED; + // create fake def for native class - ClassDef def = xts.createClassDef(); - def.name(Name.make(cn)); - def.kind(ClassDef.TOP_LEVEL); - def.setFromEncodedClassFile(); - def.setFlags(X10Flags.NONE); - def.setPackage(Types.ref(ts.packageForName(QName.make(getNativeClassPackage(cf))))); - ClassType ft = def.asType(); + ClassDef fake = xts.createClassDef(); + fake.name(Name.make(cname)); + fake.kind(ClassDef.TOP_LEVEL); + fake.setFromEncodedClassFile(); + fake.setFlags(X10Flags.NONE); + fake.setPackage(Types.ref(ts.packageForName(QName.make(getNativeClassPackage(cdef))))); // add field with native type - Flags flags = X10Flags.GLOBAL.Private().Final(); - FieldDef ff = xts.fieldDef(pos, Types.ref(cf.asType()), flags, Types.ref(ft), fieldName); - ConstructorInstance ci = xts.constructorDef(pos, Types.ref(ft), flags, - Collections.<Ref<? extends Type>>emptyList(), - Collections.<Ref<? extends Type>>emptyList()).asInstance(); - CanonicalTypeNode tn = xnf.CanonicalTypeNode(pos, ft); - Expr init = xnf.New(pos, tn, Collections.<Expr>emptyList()).constructorInstance(ci).type(ft); - cm.add(xnf.FieldDecl(pos, xnf.FlagsNode(pos, flags), tn, xnf.Id(pos, fieldName), init).fieldDef(ff)); + Name fname = Name.make("__NATIVE_FIELD__"); + Id fid = xnf.Id(p, fname); + ClassType ftype = fake.asType(); + CanonicalTypeNode ftnode = xnf.CanonicalTypeNode(p, ftype); + Flags fflags = X10Flags.GLOBAL.Private().Final(); + FieldDef fdef = xts.fieldDef(p, Types.ref(cdef.asType()), fflags, Types.ref(ftype), fname); + cmembers.add(xnf.FieldDecl(p, xnf.FlagsNode(p, fflags), ftnode, fid).fieldDef(fdef)); - // look for @NativeDef methods and native methods - for (ClassMember m : cb.members()) { + // field selector + Receiver special = xnf.This(p).type(cdef.asType()); + Receiver field = xnf.Field(p, special, fid).fieldInstance(fdef.asInstance()).type(ftype); + + // add copy constructor + ConstructorInstance xinst; + { + Name id0 = Name.make("id0"); + LocalDef ldef = xts.localDef(p, X10Flags.FINAL, Types.ref(ftype), id0); + Expr init = xnf.Local(p, xnf.Id(p, id0)).localInstance(ldef.asInstance()).type(ftype); + Expr assign = xnf.FieldAssign(p, special, fid, Assign.ASSIGN, init).fieldInstance(fdef.asInstance()).type(ftype); + Formal f = xnf.Formal(p, xnf.FlagsNode(p, X10Flags.FINAL), ftnode, xnf.Id(p, id0)).localDef(ldef); + + // super constructor def (noarg) + ConstructorDef sdef = xts.findConstructor(cdecl.superClass().type(), + xts.ConstructorMatcher(cdecl.superClass().type(), Collections.<Type>emptyList(), context)).def(); + + ConstructorDecl xd = xnf.ConstructorDecl(p, + xnf.FlagsNode(p, X10Flags.PRIVATE), + cdecl.name(), + Collections.<Formal>singletonList(f), + Collections.<TypeNode>emptyList(), + xnf.Block(p, + xnf.SuperCall(p, Collections.<Expr>emptyList()).constructorInstance(sdef.asInstance()), + xnf.Eval(p, assign))); + + ConstructorDef xdef = xts.constructorDef(p, + Types.ref(cdef.asType()), + X10Flags.PRIVATE, + Collections.<Ref<? extends Type>>singletonList(Types.ref(ftype)), + Collections.<Ref<? extends Type>>emptyList()); + + cmembers.add(xd.constructorDef(xdef)); + + xinst = xdef.asInstance(); // to be used later + } + + Boolean hasNativeConstructor = false; + + // look for native methods and constructors + for (ClassMember m : cbody.members()) { if (m instanceof X10MethodDecl) { - X10MethodDecl md = (X10MethodDecl) m; - X10MethodDef mf = (X10MethodDef) md.methodDef(); - - if (!isNativeMethod(mf) && !mf.flags().isNative()) { - cm.add(m); + X10MethodDecl mdecl = (X10MethodDecl) m; + X10MethodDef mdef = (X10MethodDef) mdecl.methodDef(); + + if (!isNativeDef(mdef) && !mdef.flags().isNative()) { + cmembers.add(m); continue; } if (Report.should_report("nativeclass", 2)) - Report.report(1, "Processing @NativeDef " + md); + Report.report(1, "Processing @NativeDef " + mdecl); + // clear native flag + mdecl = (X10MethodDecl) mdecl.flags(xnf.FlagsNode(p, clearNative(mdecl.flags().flags()))); + mdef.setFlags(clearNative(mdef.flags())); + // turn formals into arguments of delegate call List<Expr> args = new ArrayList<Expr>(); - for (Formal f : md.formals()) - args.add(xnf.Local(pos, f.name()).localInstance(f.localDef().asInstance()).type(f.type().type())); + for (Formal f : mdecl.formals()) + args.add(xnf.Local(p, f.name()).localInstance(f.localDef().asInstance()).type(f.type().type())); + // reuse x10 method instance for delegate method but make it global to avoid place check + MethodInstance minst = mdef.asInstance(); + minst = (MethodInstance) minst.flags(((X10Flags) minst.flags()).Global()); + // call delegate - Receiver special = xnf.This(pos).type(cf.asType()); - Receiver field = xnf.Field(pos, special, xnf.Id(pos, fieldName)).fieldInstance(ff.asInstance()).type(ft); - // HACK: reuse x10 method instance for delegate method but make it global and non-native - MethodInstance mi = mf.asInstance(); - mi = (MethodInstance) mi.flags(((X10Flags) mi.flags()).Global().clearNative()); - Expr expr = xnf.Call(pos, field, md.name(), args).methodInstance(mi).type(md.returnType().type()); - - // void vs. non-void methods + Receiver target = mdef.flags().isStatic() ? ftnode : field; + Call call = xnf.Call(p, target, mdecl.name(), args); // no type yet + + // void vs factory vs non-void methods Stmt body; - if (md.returnType().type().isVoid()) { - body = xnf.Eval(pos, expr); - } else { - body = xnf.Return(pos, expr); + if (mdecl.returnType().type().isVoid()) { + body = xnf.Eval(p, call.methodInstance(minst).type(ts.Void())); + } else if (mdecl.returnType().type().isSubtype(cdef.asType(), context)) { + // delegate method return native object + minst = minst.returnType(ftype); + + // call copy constructor + New copy = xnf.New(p, + xnf.CanonicalTypeNode(p, Types.ref(cdef.asType())), + Collections.<Expr>singletonList(call.methodInstance(minst).type(ftype))); + body = xnf.Return(p, copy.constructorInstance(xinst).type(cdef.asType())); + } else{ + body = xnf.Return(p, call.methodInstance(minst).type(mdecl.returnType().type())); } + cmembers.add((X10MethodDecl) mdecl.body(xnf.Block(p, body))); + continue; + } + + if (m instanceof X10ConstructorDecl) { + X10ConstructorDecl xdecl = (X10ConstructorDecl) m; + X10ConstructorDef xdef = (X10ConstructorDef) xdecl.constructorDef(); + + if (!isNativeDef(xdef) && !xdef.flags().isNative()) { + // TODO: check that non-native constructors invoke native constructors + cmembers.add(m); + continue; + } + + hasNativeConstructor = true; // good! + + if (Report.should_report("nativeclass", 2)) + Report.report(1, "Processing @NativeDef " + xdecl); + // clear native flag - md = (X10MethodDecl) md.flags(xnf.FlagsNode(pos, md.flags().flags().clearNative())); - mf.setFlags(mf.flags().clearNative()); - cm.add((X10MethodDecl) md.body(xnf.Block(pos, body))); + xdecl = (X10ConstructorDecl) xdecl.flags(xnf.FlagsNode(p, clearNative(xdecl.flags().flags()))); + xdef.setFlags(clearNative(xdef.flags())); + + // turn formals into arguments of delegate call + List<Expr> args = new ArrayList<Expr>(); + for (Formal f : xdecl.formals()) + args.add(xnf.Local(p, f.name()).localInstance(f.localDef().asInstance()).type(f.type().type())); + + // call delegate constructor + Expr init = xnf.New(p, ftnode, args).constructorInstance(xdef.asInstance()).type(ftype); + + // invoke copy constructor + Stmt body = xnf.ThisCall(p, Collections.<Expr>singletonList(init)).constructorInstance(xinst); + + cmembers.add((X10ConstructorDecl) xdecl.body(xnf.Block(p, body))); continue; } - cm.add(m); + + cmembers.add(m); } - - return cd.body(cb.members(cm)); + + if (!hasNativeConstructor) { + throw new SemanticException("@NativeClass " + cdecl.name() + " must be declare a native constructor."); + } + + return cdecl.body(cbody.members(cmembers)); } } Modified: trunk/x10.runtime/src-x10/x10/runtime/Lock.x10 =================================================================== --- trunk/x10.runtime/src-x10/x10/runtime/Lock.x10 2009-12-25 04:31:10 UTC (rev 12415) +++ trunk/x10.runtime/src-x10/x10/runtime/Lock.x10 2009-12-25 23:53:19 UTC (rev 12416) @@ -20,6 +20,8 @@ @NativeClass("java", "java.util.concurrent.locks", "ReentrantLock") @NativeClass("c++", "x10.runtime", "Lock__ReentrantLock") public class Lock { + public native def this(); + public native def lock():Void; public native def tryLock():Void; Modified: trunk/x10.runtime/src-x10/x10/runtime/X10Deque.x10 =================================================================== --- trunk/x10.runtime/src-x10/x10/runtime/X10Deque.x10 2009-12-25 04:31:10 UTC (rev 12415) +++ trunk/x10.runtime/src-x10/x10/runtime/X10Deque.x10 2009-12-25 23:53:19 UTC (rev 12416) @@ -17,6 +17,8 @@ @NativeClass("java", "x10.runtime.impl.java", "Deque") @NativeClass("c++", "x10.runtime", "Deque") public final class X10Deque { + public native def this(); + public native def size():Int; public native def poll():Object; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |