/* * 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.visit; import java.util.ArrayList; import java.util.List; import java.util.Map; import polyglot.ast.Call; import polyglot.ast.Field; import polyglot.ast.Formal; import polyglot.ast.LocalDecl; import polyglot.ast.Special; import polyglot.ast.TypeNode; import polyglot.types.LocalDef; import polyglot.types.Ref; import polyglot.types.SemanticException; import polyglot.types.Type; import polyglot.types.Types; import polyglot.util.InternalCompilerError; import polyglot.util.Pair; import polyglot.util.SubtypeSet; import x10.ast.DepParameterExpr; import x10.ast.TypeParamNode; import x10.ast.X10ClassDecl; import x10.ast.X10ConstructorCall; import x10.ast.X10ConstructorDecl; import x10.ast.X10FieldDecl; import x10.ast.X10Formal; import x10.ast.X10MethodDecl; import x10.constraint.XLocal; import x10.types.ClosureInstance; import x10.types.MethodInstance; import x10.types.TypeParamSubst; import x10.types.X10ConstructorDef; import x10.types.X10ConstructorInstance; import x10.types.X10FieldInstance; import x10.types.X10LocalDef; import x10.types.X10LocalInstance; import x10.types.X10MethodDef; import x10.types.constraints.ConstraintManager; import x10.types.matcher.Subst; public class Reinstantiator extends TypeParamSubstTransformer { public Reinstantiator(TypeParamSubst subst) { super(subst); } // TODO: move this up to TypeTransformer private Pair<XLocal[], XLocal[]> getLocalSubstitution() { Map<X10LocalDef, X10LocalDef> map = vars; XLocal[] X = new XLocal[map.keySet().size()]; XLocal[] Y = new XLocal[X.length]; int i = 0; for (X10LocalDef ld : map.keySet()) { X[i] = ConstraintManager.getConstraintSystem().makeLocal(ld); Y[i] = ConstraintManager.getConstraintSystem().makeLocal(map.get(ld)); i++; } return new Pair<XLocal[], XLocal[]>(X, Y); } @Override protected X10ConstructorInstance transformConstructorInstance(X10ConstructorInstance ci) { Pair<XLocal[], XLocal[]> p = getLocalSubstitution(); XLocal[] X = p.fst(); XLocal[] Y = p.snd(); try { ci = Subst.subst(ci, Y, X); } catch (SemanticException e) { throw new InternalCompilerError("Unexpected exception while reinstantiating "+ci, e); } return super.transformConstructorInstance(ci); } @Override protected ClosureInstance transformClosureInstance(ClosureInstance ci) { Pair<XLocal[], XLocal[]> p = getLocalSubstitution(); XLocal[] X = p.fst(); XLocal[] Y = p.snd(); try { ci = Subst.subst(ci, Y, X); } catch (SemanticException e) { throw new InternalCompilerError("Unexpected exception while reinstantiating "+ci, e); } return super.transformClosureInstance(ci); } @Override protected X10FieldInstance transformFieldInstance(X10FieldInstance fi) { Pair<XLocal[], XLocal[]> p = getLocalSubstitution(); XLocal[] X = p.fst(); XLocal[] Y = p.snd(); try { fi = Subst.subst(fi, Y, X); } catch (SemanticException e) { throw new InternalCompilerError("Unexpected exception while reinstantiating "+fi, e); } return super.transformFieldInstance(fi); } @Override protected X10LocalInstance transformLocalInstance(X10LocalInstance li) { // X10LocalDef ld = li.x10Def(); // X10LocalDef newld = vars.get(ld); // if (newld == null) { // newld = copyLocalDef(ld); // force reinstantiation // mapLocal(newld, newld); // } // mapLocal(ld, newld); Pair<XLocal[], XLocal[]> p = getLocalSubstitution(); XLocal[] X = p.fst(); XLocal[] Y = p.snd(); try { li = Subst.subst(li, Y, X); } catch (SemanticException e) { throw new InternalCompilerError("Unexpected exception while reinstantiating "+li, e); } return super.transformLocalInstance(li); } @Override protected MethodInstance transformMethodInstance(MethodInstance mi) { Pair<XLocal[], XLocal[]> p = getLocalSubstitution(); XLocal[] X = p.fst(); XLocal[] Y = p.snd(); try { mi = Subst.subst(mi, Y, X); } catch (SemanticException e) { throw new InternalCompilerError("Unexpected exception while reinstantiating "+mi, e); } return super.transformMethodInstance(mi); } @Override protected Type transformType(Type type) { Pair<XLocal[], XLocal[]> p = getLocalSubstitution(); XLocal[] X = p.fst(); XLocal[] Y = p.snd(); try { type = Subst.subst(type, Y, X); } catch (SemanticException e) { throw new InternalCompilerError("Unexpected exception while reinstantiating "+type, e); } return super.transformType(type); } @Override protected <T> Ref<T> transformRef(Ref<T> ref) { return remapRef(ref); } @Override protected TypeParamNode transform(TypeParamNode pn, TypeParamNode old) { return pn; } @Override protected Field transform(Field f, Field old) { f = f.targetImplicit(false); return super.transform(f, old); } @Override protected Call transform(Call c, Call old) { c = c.targetImplicit(false); return super.transform(c, old); } @Override protected X10ConstructorCall transform(X10ConstructorCall c, X10ConstructorCall old) { return super.transform(c, old); } @Override protected Special transform(Special s, Special old) { return super.transform(s, old); } @Override protected X10ClassDecl transform(X10ClassDecl d, X10ClassDecl old) { boolean sigChanged = d.superClass() != old.superClass(); List<TypeNode> interfaces = d.interfaces(); List<TypeNode> oldInterfaces = old.interfaces(); for (int i = 0; i < interfaces.size(); i++) { sigChanged |= interfaces.get(i) != oldInterfaces.get(i); } if (sigChanged) { throw new InternalCompilerError("Inlining of code with instantiated local classes not supported"); } return d; } @Override protected X10FieldDecl transform(X10FieldDecl d, X10FieldDecl old) { assert (false) : "Not yet implemented, can't instantiate " + d; return d; } @Override protected LocalDecl transform(LocalDecl d, LocalDecl old) { X10LocalDef ld = (X10LocalDef) d.localDef(); X10LocalDef newld = vars.get(ld); if (newld == null) { newld = copyLocalDef(ld); // force reinstantiation newld.setType(d.type().typeRef()); mapLocal(newld, newld); } mapLocal(ld, newld); return super.transform(d, old); } @Override protected X10Formal transform(X10Formal f, X10Formal old) { X10LocalDef ld = (X10LocalDef) f.localDef(); X10LocalDef newld = vars.get(ld); if (newld == null) { newld = copyLocalDef(ld); // force reinstantiation newld.setType(f.type().typeRef()); mapLocal(newld, newld); } mapLocal(ld, newld); return super.transform(f, old); } @Override protected X10ConstructorDecl transform(X10ConstructorDecl d, X10ConstructorDecl old) { boolean sigChanged = d.returnType() != old.returnType(); List<Formal> params = d.formals(); List<Formal> oldParams = old.formals(); for (int i = 0; i < params.size(); i++) { sigChanged |= params.get(i) != oldParams.get(i); } sigChanged |= d.guard() != old.guard(); List<Ref<? extends Type>> excTypes = new ArrayList<Ref<? extends Type>>(); SubtypeSet excs = d.exceptions() == null ? new SubtypeSet(visitor().typeSystem()) : d.exceptions(); SubtypeSet oldExcs = old.exceptions(); if (null != excs) { for (Type et : excs) { sigChanged |= !oldExcs.contains(et); excTypes.add(Types.ref(et)); } } sigChanged |= d.offerType() != old.offerType(); if (sigChanged) { List<Ref<? extends Type>> argTypes = new ArrayList<Ref<? extends Type>>(); List<LocalDef> formalNames = new ArrayList<LocalDef>(); for (int i = 0; i < params.size(); i++) { Formal p = params.get(i); argTypes.add(p.type().typeRef()); formalNames.add(p.localDef()); } return d.constructorDef(createConstructorDef(d, argTypes, excTypes, formalNames)); } return d; } @Override protected X10MethodDecl transform(X10MethodDecl d, X10MethodDecl old) { boolean sigChanged = d.returnType() != old.returnType(); List<Formal> params = d.formals(); List<Formal> oldParams = old.formals(); for (int i = 0; i < params.size(); i++) { sigChanged |= params.get(i) != oldParams.get(i); } sigChanged |= d.guard() != old.guard(); List<Ref<? extends Type>> excTypes = new ArrayList<Ref<? extends Type>>(); SubtypeSet excs = d.exceptions() == null ? new SubtypeSet(visitor().typeSystem()) : d.exceptions(); SubtypeSet oldExcs = old.exceptions(); if (null != excs) { for (Type et : excs) { sigChanged |= !oldExcs.contains(et); excTypes.add(Types.ref(et)); } } sigChanged |= d.offerType() != old.offerType(); if (sigChanged) { List<Ref<? extends Type>> argTypes = new ArrayList<Ref<? extends Type>>(); List<LocalDef> formalNames = new ArrayList<LocalDef>(); for (int i = 0; i < params.size(); i++) { Formal p = params.get(i); argTypes.add(p.type().typeRef()); formalNames.add(p.localDef()); } return d.methodDef(createMethodDef(d, argTypes, excTypes, formalNames)); } return d; } /** * @param d * @param argTypes * @param formalNames * @return */ private X10MethodDef createMethodDef(X10MethodDecl d, List<Ref<? extends Type>> argTypes, List<Ref<? extends Type>> throwTypes, List<LocalDef> formalNames) { X10MethodDef md = d.methodDef(); DepParameterExpr g = d.guard(); TypeNode ot = d.offerType(); return visitor().typeSystem().methodDef( md.position(), md.errorPosition(), md.container(), md.flags(), d.returnType().typeRef(), md.name(), md.typeParameters(), argTypes, throwTypes, md.thisDef(), formalNames, g == null ? null : g.valueConstraint(), g == null ? null : g.typeConstraint(), ot == null ? null : ot.typeRef(), null /* the body will never be used */ ); } /** * @param d * @param argTypes * @param formalNames * @return */ private X10ConstructorDef createConstructorDef(X10ConstructorDecl d, List<Ref<? extends Type>> argTypes, List<Ref<? extends Type>> throwTypes, List<LocalDef> formalNames) { X10ConstructorDef cd = d.constructorDef(); DepParameterExpr g = d.guard(); TypeNode ot = d.offerType(); Ref<? extends Type> returnTypeRef; if (null != d.returnType()) { returnTypeRef = d.returnType().typeRef(); } else { returnTypeRef = cd.returnType(); } return visitor().typeSystem().constructorDef( cd.position(), cd.errorPosition(), cd.container(), cd.flags(), returnTypeRef, argTypes, throwTypes, cd.thisDef(), formalNames, g == null ? null : g.valueConstraint(), g == null ? null : g.typeConstraint(), ot == null ? null : ot.typeRef() ); } }