/* * This file is part of the X10 project (http://x10-lang.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.opensource.org/licenses/eclipse-1.0.php * * (C) Copyright IBM Corporation 2010. */ package x10.util; import static x10cpp.visit.ASTQuery.assertNumberOfInitializers; import static x10cpp.visit.ASTQuery.getStringPropertyInit; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import polyglot.ast.Node; import polyglot.ast.ProcedureDecl; import polyglot.frontend.Job; import polyglot.types.NoClassException; import polyglot.types.ProcedureDef; import polyglot.types.QName; import polyglot.types.SemanticException; import polyglot.types.Type; import polyglot.types.TypeSystem; import polyglot.util.InternalCompilerError; import x10.ast.AnnotationNode; import x10.extension.X10Ext; import x10.types.X10ClassType; import x10.types.X10Def; import x10.types.X10ProcedureDef; import x10.visit.ExpressionFlattener; /** * @author Bowen Alpern * */ public abstract class AnnotationUtils { /** * @param memberDef * @param type * @return */ public static boolean hasAnnotation(X10Def def, Type type) { return !getAnnotations(def, type).isEmpty(); } /** * @param def * @return */ public static List<Type> getAnnotations(X10Def def) { return def.annotations(); } /** * @param def * @param type * @return */ public static List<Type> getAnnotations(X10Def def, Type type) { return def.annotationsMatching(type); } /** * @param node * @param type * @return */ public static boolean hasAnnotation(Node node, Type type) { return !getAnnotations(node, type).isEmpty(); } /** * @param node * @param type * @return * TODO [IP]: same as annotationsMatching() below. */ public static List<X10ClassType> getAnnotations(Node node, Type type) { assert node.ext() instanceof X10Ext; return ((X10Ext) node.ext()).annotationMatching(type); } /** * @param node * @return */ public static List<X10ClassType> getAnnotations(Node node) { assert node.ext() instanceof X10Ext; return ((X10Ext) node.ext()).annotationTypes(); } /** * @param ts * @param o * @param name * @return * @throws SemanticException */ public static X10ClassType annotationNamed(TypeSystem ts, Node o, QName name) throws SemanticException { // Nate's code. This one. if (o.ext() instanceof X10Ext) { X10Ext ext = (X10Ext) o.ext(); Type baseType = ts.systemResolver().findOne(name); List<X10ClassType> ats = ext.annotationMatching(baseType); if (ats.size() > 1) { throw new SemanticException("Expression has more than one "+ name + " annotation.", o.position()); } if (!ats.isEmpty()) { X10ClassType at = ats.get(0); return at; } } return null; } /** * @param o * @param name * @return */ public static List<AnnotationNode> annotationNodesNamed(Node o, QName name) { if (o != null && o.ext() instanceof X10Ext) { X10Ext ext = (X10Ext) o.ext(); List<AnnotationNode> l = new ArrayList<AnnotationNode>(); for (AnnotationNode an : ext.annotations()) { X10ClassType ct = an.annotationInterface(); if (name.equals(ct.fullName())) { l.add(an); } } return l; } return null; } /** * @param o * @param annotationType * @return */ public static List<X10ClassType> annotationsMatching(Node o, Type annotationType) { if (o != null && o.ext() instanceof X10Ext) { X10Ext ext = (X10Ext) o.ext(); return ext.annotationMatching(annotationType); } return null; } /** * @param o * @param annotationType * @return */ public static List<AnnotationNode> annotationNodesMatching(Node o, Type annotationType) { if (o != null && o.ext() instanceof X10Ext) { X10Ext ext = (X10Ext) o.ext(); List<AnnotationNode> l = new ArrayList<AnnotationNode>(); for (AnnotationNode an : ext.annotations()) { X10ClassType ct = an.annotationInterface(); if (ct.isSubtype(annotationType, annotationType.typeSystem().emptyContext())) { l.add(an); } } return l; } return null; } /** * @param ts * @param dec * @param name * @return */ public static boolean hasAnnotation(TypeSystem ts, Node dec, QName name) { try { if (AnnotationUtils.annotationNamed(ts, dec, name) != null) return true; } catch (NoClassException e) { if (!e.getClassName().equals(name.toString())) throw new InternalCompilerError( "Something went terribly wrong", e); } catch (SemanticException e) { throw new InternalCompilerError("Something is terribly wrong", e); } return false; } /** * @param o * @param fullName * @return */ public static List<X10ClassType> annotationsNamed(Node o, QName fullName) { if (o != null && o.ext() instanceof X10Ext) { X10Ext ext = (X10Ext) o.ext(); return ext.annotationNamed(fullName); } return null; } private static final List<String> javaNativeStrings = Arrays.asList("java"); private static final List<String> cudaNativeStrings = Arrays.asList("c++", "cuda"); private static final List<String> cppNativeStrings = Arrays.asList("c++"); // XTENLANG-2824: chose between cudaNativeStrings and cppNativeStrings based on whether or not // we are within a CUDAKernel public static List<X10ClassType> getNativeAnnotations (Node node, Job job) { List<X10ClassType> result = new ArrayList<X10ClassType>(); X10ClassType type = job.extensionInfo().typeSystem().NativeType(); List<X10ClassType> annotations = getAnnotations(node, type); for (X10ClassType annotation : annotations) { assertNumberOfInitializers(annotation, 2); String platform = getStringPropertyInit(annotation, 0); List<String> nativeStrings = (ExpressionFlattener.javaBackend(job) ? javaNativeStrings : cppNativeStrings); for (String ns : nativeStrings) { if (platform != null && platform.equals(ns)) { result.add(annotation); } } } return result; } public static boolean hasNativeAnnotations (Node node, Job job) { return !getNativeAnnotations(node, job).isEmpty(); } }