/* ____ ____ ____ ____ ______ *\ ** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** ** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** ** /_____/\____/\___/\____/____/ ** \* */ // $OldId: AddAccessors.java,v 1.2 2002/11/21 14:14:31 schinz Exp $ // $Id$ package scalac.transformer; import scalac.*; import scalac.ast.*; import scalac.typechecker.*; import scalac.symtab.*; import scalac.util.*; import java.util.*; /** * Add private accessor functions for all class constructor arguments * which are accessed from within the class' methods, or nested * classes. * * @author Michel Schinz * @version 1.0 */ public class AddAccessors extends Transformer { public AddAccessors(Global global) { super(global); } protected Name valName(Symbol sym) { return Name.fromString(sym.name.toString() + "$"); } protected final HashMap/**/ accessorMap = new HashMap(); protected boolean inClassContext; protected Symbol accessor(Symbol sym) { Symbol accessor = (Symbol)accessorMap.get(sym); if (accessor == null) { accessor = new TermSymbol(sym.pos, sym.name, sym.classOwner(), /* !!! Modifiers.STABLE | */ Modifiers.ACCESSOR | Modifiers.PRIVATE); accessor.setType(Type.MethodType(Symbol.EMPTY_ARRAY, sym.type())); accessorMap.put(sym, accessor); } return accessor; } public Tree transform(Tree tree) { switch (tree) { case ClassDef(_, // : _, Tree.AbsTypeDef[] tparams, Tree.ValDef[][] vparams, Tree tpe, Tree.Template impl): { Symbol clsSym = tree.symbol(); assert vparams.length == 1; Tree.ValDef[] params = vparams[0]; // Recursively transform body Tree[] body = impl.body; LinkedList/**/ newBody = new LinkedList(); for (int i = 0; i < body.length; ++i) { Tree mem = body[i]; Symbol sym = mem.symbol(); inClassContext = mem.definesSymbol() && (sym.isClass() || sym.isMethod()); newBody.add(transform(mem)); } // Add value definitions and accessors for all constructor // arguments which were found in the body of the class. Scope newMembers = new Scope(clsSym.members()); for (int i = 0; i < params.length; ++i) { Symbol paramSym = params[i].symbol(); if (accessorMap.containsKey(paramSym)) { int pos = paramSym.pos; Symbol accessorSym = (Symbol)accessorMap.get(paramSym); Symbol valSym = new TermSymbol(pos, valName(paramSym), clsSym, Modifiers.PRIVATE); valSym.setType(paramSym.type()); newBody.addFirst(gen.DefDef(accessorSym, gen.Ident(pos, valSym))); newMembers.enter(accessorSym); newBody.addFirst(gen.ValDef(valSym, gen.Ident(pos, paramSym))); newMembers.enter(valSym); } } // Update class type with new values/accessors. clsSym.updateInfo(Type.compoundType(clsSym.parents(), newMembers, clsSym)); inClassContext = false; Tree[] newParents = transform(impl.parents); Tree[] newBodyA = (Tree[])newBody.toArray(new Tree[newBody.size()]); return copy.ClassDef(tree, clsSym, transform(tparams), transform(vparams), transform(tpe), copy.Template(impl, newParents, newBodyA)); } case Select(Tree qualifier, _): { Symbol sym = tree.symbol(); assert sym.kind != Kinds.NONE : tree; if (sym.owner().isPrimaryConstructor()) return gen.Apply(gen.Select(tree.pos, transform(qualifier), accessor(sym))); else return copy.Select(tree, sym, transform(qualifier)); } case Ident(_): { Symbol sym = tree.symbol(); if (inClassContext && sym.name.isTermName() && sym.owner().isPrimaryConstructor()) return gen.Apply(gen.Ident(tree.pos, accessor(sym))); else return copy.Ident(tree, sym); } default: return super.transform(tree); } } }