/* * 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 2006-2010. */ package x10.types; import java.util.ArrayList; import java.util.Collections; import java.util.List; import polyglot.types.ConstructorDef; import polyglot.types.Context; import polyglot.types.DerefTransform; import polyglot.types.FieldInstance; import polyglot.types.Flags; import polyglot.types.LocalDef; import polyglot.types.LocalInstance; import polyglot.types.MemberInstance; import polyglot.types.ObjectType; import polyglot.types.Package; import polyglot.types.ProcedureInstance; import polyglot.types.Ref; import polyglot.types.Resolver; import polyglot.types.SemanticException; import polyglot.types.Name; import polyglot.types.ContainerType; import polyglot.types.Type; import polyglot.types.TypeObject; import polyglot.types.TypeSystem; import polyglot.types.Types; import polyglot.types.UnknownType; import polyglot.types.UpcastTransform; import polyglot.types.TypeSystem_c.TypeEquals; import polyglot.util.CollectionUtil; import x10.util.CollectionFactory; import polyglot.util.InternalCompilerError; import polyglot.util.Position; import polyglot.util.Transformation; import polyglot.util.TransformingList; import polyglot.util.TypedList; import x10.types.constraints.ConstraintManager; import x10.constraint.XVar; import x10.types.constraints.CConstraint; import x10.types.constraints.TypeConstraint; /** * Represents a type definition * * @author njnystrom */ public class MacroType_c extends ParametrizedType_c implements MacroType { private static final long serialVersionUID = 2467878434635627679L; Ref<TypeDef> def; List<Type> typeParams; List<XVar> formals; List<Type> formalTypes; CConstraint guard; Ref<? extends Type> definedType; public MacroType_c(TypeSystem ts, Position pos, Ref<TypeDef> def) { super(ts, pos, pos); this.def = def; } public TypeDef def() { return Types.get(def); } public Ref<? extends Type> offerType() { return null; } public boolean isGloballyAccessible() { if (container != null && !container.isGloballyAccessible()) return false; return flags().isPublic(); } @Override public MacroType container(ContainerType container) { return (MacroType) super.container(container); } @Override public MacroType flags(Flags flags) { return (MacroType) super.flags(flags); } public Type setFlags(Flags xf) { MacroType_c c = (MacroType_c) this.copy(); if (c.flags == null) c.flags = Flags.NONE; c.flags = (xf.isStruct()) ? c.flags.Struct() : c.flags; return c; } public Type clearFlags(Flags f) { MacroType_c c = (MacroType_c) this.copy(); if (c.flags == null) c.flags = Flags.NONE; c.flags = c.flags.clear(f); return c; } @Override public boolean equalsImpl(TypeObject t) { if (t instanceof MacroType) { return super.equalsImpl(t); } return false; } public String translate(Resolver c) { return definedType().translate(c); } public Name name() { if (this.name == null) { return def().name(); } return name; } public MacroType name(Name name) { return (MacroType) super.name(name); } public List<Type> typeParameters() { if (typeParams == null) { return new TransformingList<ParameterType, Type>(def().typeParameters(), new UpcastTransform<Type, ParameterType>()); } return typeParams; } public MacroType typeParameters(List<Type> typeParams) { MacroType_c t = (MacroType_c) copy(); t.typeParams = TypedList.copyAndCheck(typeParams, Type.class, true); return (MacroType) t; } public MacroType newTypeParameters(List<Type> typeParams) { return typeParameters(typeParams); } public List<LocalInstance> formalNames; public List<LocalInstance> formalNames() { if (this.formalNames == null) { return new TransformingList<LocalDef, LocalInstance>(def().formalNames(), new Transformation<LocalDef,LocalInstance>() { public LocalInstance transform(LocalDef o) { return o.asInstance(); } }); } return formalNames; } public MacroType formalNames(List<LocalInstance> formalNames) { MacroType_c n = (MacroType_c) copy(); n.formalNames = formalNames; return n; } public boolean hasFormals(List<Type> formalTypes, Context context) { return CollectionUtil.allElementwise(this.formalTypes(), formalTypes, new TypeEquals(context)); } public List<XVar> formals() { if (formals == null) { List<Integer> indices = new ArrayList<Integer>(); for (int i = 0; i < def().formalNames().size(); i++) { indices.add(i); } return new TransformingList<Integer, XVar>(indices, new FormalToVarTransform(def().formalNames(), def().formalTypes())); } return formals; } public MacroType formals(List<XVar> formals) { MacroType_c t = (MacroType_c) copy(); t.formals = TypedList.copyAndCheck(formals, XVar.class, true); return (MacroType) t; } public List<Type> formalTypes() { if (formalTypes == null) { return new TransformingList<Ref<? extends Type>, Type>(def().formalTypes(), new DerefTransform<Type>()); } return formalTypes; } public MacroType formalTypes(List<Type> formalTypes) { MacroType_c t = (MacroType_c) copy(); t.formalTypes = TypedList.copyAndCheck(formalTypes, Type.class, true); return (MacroType) t; } public MacroType newFormalTypes(List<Type> formalTypes) { return formalTypes(formalTypes); } // todo: this guard&typeGuard is duplicated code similar to ProcedureInstance_c public CConstraint guard() { if (guard == null) return Types.get(def().guard()); return guard; } public MacroType guard(CConstraint guard) { MacroType_c t = (MacroType_c) copy(); t.guard = guard; return (MacroType) t; } public boolean checkConstraintsAtRuntime() { return false; } public MacroType_c checkConstraintsAtRuntime(boolean check) { throw new RuntimeException("The guard for a MacroType cannot be dynamically checked (at runtime)"); } /** Constraint on type parameters. */ protected TypeConstraint typeGuard; public TypeConstraint typeGuard() { if (typeGuard == null) return Types.get(def().typeGuard()); return typeGuard; } public MacroType typeGuard(TypeConstraint s) { MacroType_c n = (MacroType_c) copy(); n.typeGuard = s; return n; } public Type definedType() { if (definedType == null) return Types.get(def().definedType()); Ref<? extends Type> dt = definedType; definedType = Types.ref(typeSystem().unknownType(position())); // guard against recursion Type t = Types.processFlags(flags(), Types.get(dt)); definedType = dt; return t; } public MacroType definedType(Type t) { return definedTypeRef(Types.ref(t)); } public Ref<? extends Type> definedTypeRef() { if (definedType == null) return def().definedType(); return definedType; } public MacroType definedTypeRef(Ref<? extends Type> definedType) { MacroType_c t = (MacroType_c) copy(); t.definedType = definedType; return t; } public static class FormalToVarTransform implements Transformation<Integer, XVar> { List<LocalDef> formalNames; List<Ref<? extends Type>> formalTypes; public FormalToVarTransform(List<LocalDef> formalNames, List<Ref<? extends Type>> formalTypes) { this.formalNames = formalNames; this.formalTypes = formalTypes; } public XVar transform(Integer i) { final Ref<? extends Type> r = formalTypes.get(i); X10LocalDef li = (X10LocalDef) formalNames.get(i); XVar v = ConstraintManager.getConstraintSystem().makeLocal(li); return v; } } public static class ParamToVarTransform implements Transformation<Ref<? extends Type>, XVar> { public XVar transform(Ref<? extends Type> r) { Type t = r.get(); if (t instanceof ParameterType) { ParameterType pt = (ParameterType) t; // TODO: Replace with XTerms.makeUQV(pt.name().toString()); return ConstraintManager.getConstraintSystem().makeUQV(pt.name().toString()); // return XTerms.makeLocal(new XNameWrapper<String>(pt.name().toString())); } throw new InternalCompilerError("Cannot translate non-parameter type into var.", t.position()); } } public String designator() { return "type"; } public String typeToString() { StringBuilder sb = new StringBuilder(); sb.append(signature()); if (definedType != null && definedType.known()) { sb.append(" = "); sb.append(definedType); } return sb.toString(); } public String signature() { StringBuffer sb = new StringBuffer(); TypeDef d = def.getCached(); Ref<? extends ContainerType> cont = d.container(); if (cont != null) { Type t = cont.getCached(); if (t != null) { sb.append(t); sb.append("."); } } else { Ref<? extends Package> pkg = d.package_(); if (pkg != null) { Package p = pkg.getCached(); if (p != null) { sb.append(p); sb.append("."); } } } sb.append(d.name()); if (typeParams != null && typeParams.size() > 0) { sb.append("["); for (int i = 0; i < typeParams.size(); i++) { if (i != 0) sb.append(", "); sb.append(typeParams.get(i)); } sb.append("]"); } if (formals != null && formalTypes != null && formals.size() > 0) { sb.append("("); for (int i = 0; i < formals.size(); i++) { if (i != 0) sb.append(", "); if (! formals.get(i).toString().equals("")) { sb.append(formals.get(i)); sb.append(": "); } sb.append(formalTypes.get(i)); } sb.append(")"); } if (guard != null) sb.append(guard); return sb.toString(); } @Override public List<FieldInstance> fields() { Type base = definedType(); if (base instanceof ContainerType) { return ((ContainerType) base).fields(); } return Collections.emptyList(); } @Override public List<Type> interfaces() { Type base = definedType(); if (base instanceof ObjectType) { return ((ObjectType) base).interfaces(); } return Collections.emptyList(); } @Override public List<MethodInstance> methods() { Type base = definedType(); if (base instanceof ContainerType) { return ((ContainerType) base).methods(); } return Collections.emptyList(); } @Override public Type superClass() { Type base = definedType(); if (base instanceof ObjectType) { return ((ObjectType) base).superClass(); } return null; } public List<Type> throwTypes() { return Collections.<Type>emptyList(); } public boolean callValid(Type thisType, List<Type> actualTypes, Context context) { // this should have been instantiated correctly; if so, the call is valid return true; } public boolean moreSpecific(Type ct, ProcedureInstance<TypeDef> p, Context context) { return Types.moreSpecificImpl(ct, this, p, context); } public Type returnType() { return definedType(); } public Ref<? extends Type> returnTypeRef() { return definedTypeRef(); } public MacroType returnType(Type t) { return definedType(t); } public MacroType returnTypeRef(Ref<? extends Type> t) { return definedTypeRef(t); } public MacroType throwTypes(List<Type> throwTypes) { return this; } public boolean throwsSubset(ProcedureInstance<TypeDef> pi) { return true; } public boolean equalsNoFlag(Type t2) { return false; } }