/* * 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.ast.Expr; import polyglot.frontend.Job; import polyglot.frontend.Source; import polyglot.types.ClassDef; import polyglot.types.ClassType; import polyglot.types.ClassType_c; import polyglot.types.ConstructorInstance; import polyglot.types.DerefTransform; import polyglot.types.FieldInstance; import polyglot.types.Flags; import polyglot.types.LazyRef; import polyglot.types.LocalInstance; import polyglot.types.Matcher; import polyglot.types.MethodAsTypeTransform; import polyglot.types.MethodDef; import polyglot.types.Package; import polyglot.types.Ref; import polyglot.types.Resolver; import polyglot.types.Name; import polyglot.types.ContainerType; import polyglot.types.SemanticException; import polyglot.types.Type; import polyglot.types.TypeObject; import polyglot.types.Types; import polyglot.types.TypeSystem; import polyglot.types.ClassDef.Kind; import polyglot.util.CodeWriter; import polyglot.util.InternalCompilerError; import polyglot.util.Position; import x10.constraint.XFailure; import x10.constraint.XVar; import x10.types.constraints.CConstraint; import x10.types.matcher.Subst; /** * A representation of the type of a function interface. * Treated as a ClassType representing an interface, with the signature for the * function type retrieved from the sole method (the apply method) defined on the * class type. */ public class FunctionType_c extends X10ParsedClassType_c implements FunctionType { private static final long serialVersionUID = 2768150875334536668L; public FunctionType_c(final TypeSystem ts, Position pos, Position errorPosition, final X10ClassDef def) { super(ts, pos, errorPosition, Types.ref(def)); } @Override public X10ParsedClassType typeArguments(List<Type> typeArgs) { return super.typeArguments(typeArgs); } public MethodInstance applyMethod() { try { return (MethodInstance) methods().get(0); } catch (Exception z) { return null; } } public Type returnType() { return applyMethod().returnType(); } public CConstraint guard() { return applyMethod().guard(); } public List<Type> typeParameters() { return applyMethod().typeParameters(); } public List<LocalInstance> formalNames() { return applyMethod().formalNames(); } public List<Type> argumentTypes() { return applyMethod().formalTypes(); } protected static String guardToString(CConstraint guard) { if (guard == null || guard.constraints().size() == 0) return ""; return guard.toString(); } @Override public String typeToString() { MethodInstance mi = applyMethod(); if (mi==null) // this could happen if the method is installed before the type is properly formed, e.g. in -report types=2 execution. return "???"; StringBuilder sb = new StringBuilder(); List<LocalInstance> formals = mi.formalNames(); for (int i=0; i < formals.size(); ++i) { LocalInstance f = formals.get(i); if (sb.length() > 0) sb.append(","); sb.append(f.type()); } return "(" + sb.toString() + ")" + guardToString(guard()) + "=>" + mi.returnType(); } @Override public int hashCode() { return def.get().hashCode(); } @Override public boolean equalsImpl(TypeObject o) { if (o == this) return true; if (o == null) return false; if (o instanceof FunctionType_c) { FunctionType_c t = (FunctionType_c) o; if (!flags().equals(t.flags())) return false; List<Type> Tl = this.argumentTypes(); Type T = this.returnType(); CConstraint h = this.guard(); List<Type> Sl = t.argumentTypes(); Type S = t.returnType(); CConstraint g = t.guard(); if (Tl.size() != Sl.size()) { return false; } XVar[] ys = Types.toVarArray(Types.toLocalDefList(this.formalNames())); XVar[] xs = Types.toVarArray(Types.toLocalDefList(t.formalNames())); try { T = Subst.subst(T, ys, xs, new Type[]{}, new ParameterType[]{}); S = Subst.subst(S, ys, xs, new Type[]{}, new ParameterType[]{}); } catch (SemanticException e) { throw new InternalCompilerError("Unexpected exception comparing function types", e); } if (!ts.typeEquals(T, S, ts.emptyContext())) { return false; } for (int i = 0; i < Sl.size(); i++) { Type Si = Sl.get(i); Type Ti = Tl.get(i); try { Ti = Subst.subst(Ti, ys, xs, new Type[]{}, new ParameterType[]{}); Si = Subst.subst(Si, ys, xs, new Type[]{}, new ParameterType[]{}); } catch (SemanticException e) { throw new InternalCompilerError("Unexpected exception comparing function types", e); } if (!ts.typeEquals(Ti, Si, ts.emptyContext())) return false; } if (g != null) { try { g = g.substitute(ys, xs); } catch (XFailure e) { throw new InternalCompilerError("Unexpected exception comparing function types", this.position(), e); } } if (!ts.env(ts.emptyContext()).entails(h, g) || !ts.env(ts.emptyContext()).entails(g, h)) { return false; } return true; } return false; } public void print(CodeWriter w) { w.write(toString()); } }