Package flex2.compiler.mxml.rep.init

Source Code of flex2.compiler.mxml.rep.init.ValueInitializer$DeclaredAndProceduralWithinRepeater

/*
*
*  Licensed to the Apache Software Foundation (ASF) under one or more
*  contributor license agreements.  See the NOTICE file distributed with
*  this work for additional information regarding copyright ownership.
*  The ASF licenses this file to You under the Apache License, Version 2.0
*  (the "License"); you may not use this file except in compliance with
*  the License.  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*
*/

package flex2.compiler.mxml.rep.init;

import static macromedia.asc.parser.Tokens.ASSIGN_TOKEN;
import static macromedia.asc.parser.Tokens.CONST_TOKEN;
import flash.util.StringUtils;
import flex2.compiler.as3.AbstractSyntaxTreeUtil;
import flex2.compiler.mxml.ImplementationGenerator;
import flex2.compiler.mxml.gen.CodeFragmentList;
import flex2.compiler.mxml.gen.DescriptorGenerator;
import flex2.compiler.mxml.gen.TextGen;
import flex2.compiler.mxml.lang.StandardDefs;
import flex2.compiler.mxml.reflect.Type;
import flex2.compiler.mxml.reflect.TypeTable;
import flex2.compiler.mxml.rep.*;
import flex2.compiler.util.IteratorList;
import flex2.compiler.util.NameFormatter;
import flex2.compiler.util.ThreadLocalToolkit;
import flex2.compiler.util.CompilerMessage;
import macromedia.asc.parser.*;
import macromedia.asc.util.Context;
import org.apache.commons.collections.iterators.SingletonIterator;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
* This class represents a general rvalue initializer.  Subclasses
* handle codegen variations for different lvalues.
*/
/*
* TODO this logic is complicated a bit by the fact that some legacy builders upstream are still using POJOs
* as their initializer rvalues. Once those have all been ported to use (at least) Primitives, all the
* "if (value instanceof Model)" scaffolding can be removed. At that point it would also make sense to move
* from a subclasses-of-Model approach (another remaining bit of legacy) to an explicit-discriminant approach.
*/
public abstract class ValueInitializer implements Initializer, Cloneable
{
  private static final String INT = "int";
  private static final String ARRAY = "Array";
  private static final String NULL = "null";
  private static final String THIS = "this";
    private static final String DOT = ".";

    // intern all identifier constants
    private static final String NEW_VALUE = "newValue".intern();
    private static final String OLD_VALUE = "oldValue".intern();
    private static final String PROPERTY = "property".intern();
    private static final String OBJECT = "Object".intern();
    private static final String SOURCE = "source".intern();
    private static final String ADD_LAYER = "addLayer".intern();
    private static final String BINDING_MANAGER = "BindingManager".intern();
    private static final String CD = "cd".intern();
    private static final String CHILD_DESCRIPTORS = "childDescriptors".intern();
    private static final String CLASS = "Class".intern();
    private static final String CREATE_XML_DOCUMENT = "createXMLDocument".intern();
    private static final String DEFERRED_INSTANCE_FROM_CLASS = "DeferredInstanceFromClass".intern();
    private static final String DEFERRED_INSTANCE_FROM_FUNCTION = "DeferredInstanceFromFunction".intern();
    private static final String DESIGN_LAYER = "designLayer".intern();
    private static final String DISPATCH_EVENT = "dispatchEvent".intern();
    private static final String DOCUMENT = "document".intern();
    private static final String EXECUTE_BINDINGS = "executeBindings".intern();
    private static final String EVENT = "Event".intern();
    private static final String FIRST_CHILD = "firstChild".intern();
    private static final String GET_DEFINITION_BY_NAME = "getDefinitionByName".intern();
    private static final String I = "i".intern();
    private static final String ID = "id".intern();
    private static final String INITIALIZE = "initialize".intern();
    private static final String INITIALIZED = "initialized".intern();
    private static final String LENGTH = "length".intern();
    private static final String MX_INTERNAL = "mx_internal".intern();
    private static final String REGISTER_EFFECTS = "registerEffects".intern();
    private static final String TEMP = "temp".intern();
    private static final String UNDEFINED = "undefined".intern();
    private static final String XML_UTIL = "XMLUtil".intern();
    private static final String _DOCUMENT_DESCRIPTOR = "_documentDescriptor".intern();
    private static final String __CLASS = "__class".intern();
    private static final String __E = "__e".intern();

    protected final StandardDefs standardDefs;
    protected Object value;
  protected final int line;
  protected boolean stateSpecific;

  ValueInitializer(Object value, int line, StandardDefs defs)
  {
        this.value = value;
        this.line = line;
        this.stateSpecific = false;
        this.standardDefs = defs;
        setValue(value);
  }

  public Object getValue()
  {
    return value;
  }
 
  public void setValue(Object value)
  {
    this.value = value;
   
    if (value instanceof Model)
        {
            // Assume the current ValueInitializer instance is state specific
            // if the rvalue is itself state specific.
            this.stateSpecific = ((Model)value).isStateSpecific();
        }
  }

  //  Initializer impl

  public int getLineRef()
  {
    return line;
  }

  public boolean isBinding()
  {
    return value instanceof BindingExpression || (value instanceof Primitive && ((Primitive)value).hasBindings());
  }
 
  public boolean isDesignLayer()
  {
    return value instanceof DesignLayer;
  }
 
  public boolean isStateSpecific()
  {
    return stateSpecific;
  }
 
  public void setStateSpecific(boolean value)
  {
    stateSpecific = value;
  }

  /**
   *
   */
  public boolean hasDefinition()
  {
    if (value instanceof Model)
    {
      Model model = (Model)value;
      return model.isDeclared() || !modelHasInlineRValue() || isInstanceGeneratorOverDefinition();
    }
    else
    {
      assert isBinding() || !standardDefs.isInstanceGenerator(getLValueType())
          : "instance generator lvalue has non-Model, non-BindingExpression rvalue (" + value.getClass() + ")";
      return false;
    }
  }

  /**
   * note the exception for simple classdef-based deferrals
   */
  protected boolean isInstanceGeneratorOverDefinition()
  {
    Type ltype = getLValueType();
    return standardDefs.isIFactory(ltype) || (standardDefs.isIDeferredInstance(ltype) && !rvalueIsClassRef());
  }

  /**
   * TODO replace with actual ClassRef subclass of Model or Primitive
   */
  protected boolean rvalueIsClassRef()
  {
    return value instanceof Primitive && ((Primitive)value).getType().equals(getTypeTable().classType);
  }

  /**
   *
   */
  public String getValueExpr()
  {
    Type lvalueType = getLValueType();

    if (standardDefs.isIDeferredInstance(lvalueType))
    {
      if (rvalueIsClassRef())
      {
        return "new " + NameFormatter.toDot(standardDefs.CLASS_DEFERREDINSTANCEFROMCLASS) + "(" + getInlineRValue() + ")";
      }
      else
      {
        return "new " + NameFormatter.toDot(standardDefs.CLASS_DEFERREDINSTANCEFROMFUNCTION) + "(" + getDefinitionName() +
            (standardDefs.isITransientDeferredInstance(lvalueType) ? "," + ((Model)value).getDefinitionName() + "_r" : "") + ")";
      }
    }
    else
    {
      return hasDefinition() ? getDefinitionName() + "()" : getInlineRValue();
    }
  }

  /**
   *
   */
  public Node generateValueExpr(NodeFactory nodeFactory, HashSet<String> configNamespaces,
                                  boolean generateDocComments)
  {
    Node result;
    Type lvalueType = getLValueType();

    if (standardDefs.isIDeferredInstance(lvalueType))
    {
      IdentifierNode typeIdentifier;
      ArgumentListNode args;

      if (rvalueIsClassRef())
      {
        typeIdentifier = AbstractSyntaxTreeUtil.generateQualifiedIdentifier(nodeFactory,
                                          standardDefs.getCorePackage(),
                                          DEFERRED_INSTANCE_FROM_CLASS,
                                                                                    false);
                Node inlineRValue = generateInlineRValue(nodeFactory, configNamespaces, generateDocComments);
        args = nodeFactory.argumentList(null, inlineRValue);
      }
      else
      {
        typeIdentifier = AbstractSyntaxTreeUtil.generateQualifiedIdentifier(nodeFactory,
                                          standardDefs.getCorePackage(),
                                          DEFERRED_INSTANCE_FROM_FUNCTION,
                                                                                    false);
        IdentifierNode identifier =
                    AbstractSyntaxTreeUtil.generateIdentifier(nodeFactory, getDefinitionName(), true);
        args = nodeFactory.argumentList(null, identifier);
       
        if (standardDefs.isITransientDeferredInstance(lvalueType))
        {
          identifier = AbstractSyntaxTreeUtil.generateIdentifier(nodeFactory, ((Model)value).getDefinitionName() + "_r", true);
          args = nodeFactory.argumentList(args, identifier);
        }
      }

      CallExpressionNode callExpression =
        (CallExpressionNode) nodeFactory.callExpression(typeIdentifier, args);
      callExpression.is_new = true;
      callExpression.setRValue(false);
      result = nodeFactory.memberExpression(null, callExpression);
    }
    else if (hasDefinition())
    {
      IdentifierNode identifier =
                AbstractSyntaxTreeUtil.generateIdentifier(nodeFactory, getDefinitionName(), true);
      CallExpressionNode callExpression =
        (CallExpressionNode) nodeFactory.callExpression(identifier, null);
      callExpression.setRValue(false);
      result = nodeFactory.memberExpression(null, callExpression);
    }
    else
    {
      return generateInlineRValue(nodeFactory, configNamespaces, generateDocComments);
    }

    return result;
  }
 
    /**
     *
     */
    protected boolean modelHasInlineRValue()
    {
        boolean result = false;
        assert value instanceof Model;
        Model model = (Model) value;

        if (model instanceof Vector)
        {
            Vector vector = (Vector) model;

            if (!vector.isFixed())
            {
                result = true;
            }
        }
        else if (model instanceof XML ||
                 model instanceof XMLList ||
                 model instanceof Primitive ||
                 model instanceof Array ||
                 model.getType().equals(getTypeTable().objectType))
        {
            result = true;
        }

        return result;
    }

  /**
   *
   */
  private String getInlineRValue()
  {
    if (value instanceof Model)
    {
      if (value instanceof Primitive)
      {
        Primitive primitive = (Primitive)value;
        return formatExpr(primitive.getType(), primitive.getValue());
      }
      else if (value instanceof Vector)
      {
        return asVectorLiteral((Vector) value);
      }
      else if (value instanceof Array)
      {
        return asArrayLiteral((Array)value);
      }
      else if (value instanceof XML)
      {
        XML xml = (XML)value;
        return asXmlLiteral(xml);
      }
      else if (value instanceof XMLList)
      {
        return asXMLList((XMLList)value);
      }
      else if (((Model)value).getType().equals(getTypeTable().objectType))
      {
        return asObjectLiteral((Model)value);
      }
      else
      {
        assert false : "can't generate inline expr for values of type " + value.getClass();
        return null;
      }
    }
    else
    {
      return formatExpr(getLValueType(), value);
    }
  }

  private Node generateInlineRValue(NodeFactory nodeFactory, HashSet<String> configNamespaces,
                                      boolean generateDocComments)
  {
    if (value instanceof Model)
    {
      if (value instanceof Primitive)
      {
        Primitive primitive = (Primitive)value;
        return formatExpr(nodeFactory, configNamespaces, generateDocComments,
                                  primitive.getType(), primitive.getValue());
      }
      else if (value instanceof Vector)
      {
        return asVectorLiteral(nodeFactory, configNamespaces, generateDocComments, (Vector) value);
      }
      else if (value instanceof Array)
      {
        return asArrayLiteral(nodeFactory, configNamespaces, generateDocComments, (Array) value);
      }
      else if (value instanceof XML)
      {
        XML xml = (XML)value;
        return asXmlLiteral(nodeFactory, xml);
      }
      else if (value instanceof XMLList)
      {
        return asXMLList(nodeFactory, (XMLList) value);
      }
      else if (((Model)value).getType().equals(getTypeTable().objectType))
      {
        return asObjectLiteral(nodeFactory, configNamespaces, generateDocComments, (Model)value);
      }
      else
      {
        assert false : "can't generate inline expr for values of type " + value.getClass();
        return null;
      }
    }
    else
    {
      return formatExpr(nodeFactory, configNamespaces, generateDocComments, getLValueType(), value);
    }
  }

  /**
   * Note: the definition function will create and return our rvalue. If the rvalue is declared (i.e. carries an id),
   * then it will also initialize the declared variable by side effect. Hence the "_init" vs "_create" suffixes.
   */
  protected String getDefinitionName()
  {
    assert hasDefinition() : "no definition in getDefinitionName()";
    assert value instanceof Model : "non-Model value has definition in getDefinitionName()";

    return ((Model)value).getDefinitionName() + (((Model)value).isDeclared() ? "_i" : "_c");
  }

  /**
   *
   */
    protected CodeFragmentList getDefinitionBody()
    {
        assert hasDefinition() : "no definition in getDefinitionBody()";
        assert value instanceof Model : "non-Model value has definition in getDefinitionBody()";

        final String varName = "temp";

        Model self = (Model)value;
        Type selfType = self.getType();
        String selfTypeName;

        if (value instanceof Vector)
        {
            Vector vector = (Vector) value;
            String elementTypeName = vector.getElementTypeName();
            selfTypeName = StandardDefs.CLASS_VECTOR + ".<" + elementTypeName + ">";
        }
        else
        {
            selfTypeName = NameFormatter.toDot(selfType.getName());
        }

        boolean isDeclared = self.isDeclared();
        String id = isDeclared ? self.getId() : varName;

        int line = getLineRef();

        CodeFragmentList list = new CodeFragmentList();

        //  function header
        list.add("private function ", getDefinitionName(), "() : ", selfTypeName, line);
        list.add("{", line);

        //  value creation
        StringBuilder stringBuilder = new StringBuilder("\tvar " + varName + " : " + selfTypeName + " = ");

        if (modelHasInlineRValue())
        {
            stringBuilder.append(getInlineRValue());
        }
        else if (value instanceof Vector)
        {
            Vector vector = (Vector) value;

            stringBuilder.append("new " + selfTypeName + "(" + vector.size());
           
            if (vector.isFixed())
            {
                stringBuilder.append(", true)");
            }
            else
            {
                stringBuilder.append(")");
            }
        }
        else
        {
            // TODO confirm the availability of a 0-arg ctor!! but do it upstream from here, like when Model is built
            stringBuilder.append("new " + selfTypeName + "()");
        }

        stringBuilder.append(";");
        list.add(stringBuilder.toString(), line);

        if (!modelHasInlineRValue())
        {
            if (value instanceof Vector)
            {
                Vector vector = (Vector) value;
                addAssignExprs(list, vector.getElementInitializerIterator(), varName);
            }
            else
            {
                // set properties
                addAssignExprs(list, self.getPropertyInitializerIterator(self.getType().hasDynamic()), varName);
            }
        }
       
        //  set styles
        addAssignExprs(list, self.getStyleInitializerIterator(), varName);

        //  set effects
        addAssignExprs(list, self.getEffectInitializerIterator(), varName);

        //  add event handlers
        addAssignExprs(list, self.getEventInitializerIterator(), varName);

        //  register effect names
        String effectEventNames = self.getEffectNames();
        if (effectEventNames.length() > 0)
        {
            list.add("\t", varName, ".registerEffects([ ", effectEventNames, " ]);", line);
        }

        //  post-init actions for values that are being assigned to properties (via id attribution)
        if (isDeclared && standardDefs.isIUIComponentWithIdProperty(selfType))
        {
            //  set id on IUIComponents that carry an id prop
            list.add("\t", varName, ".id = \"", id, "\";", line);
        }

        // Design layer related items
        if (self.layerParent != null)
        {
            if (self instanceof DesignLayer)
            {
                list.add("\t", self.layerParent.getId(), ".addLayer(", varName, ");", line);
            }
            else if (self.getType().isAssignableTo(standardDefs.INTERFACE_IVISUALELEMENT))
            {
                list.add("\t", varName, ".designLayer = ", self.layerParent.getId(), ";", line);
            }   
        }
       
        //  UIComponent-specific init steps
        if (standardDefs.isIUIComponent(selfType))
        {
            assert self instanceof MovieClip : "isIUIComponent(selfType) but !(self instanceof MovieClip)";
            MovieClip movieClip = (MovieClip) self;

            //  MXML implementations of IUIComponent initialize set their document property to themselves at
            //  construction time. Others need it set to the enclosing document (us).

            list.add("\tif (!", varName, ".document) ", varName, ".document = this;", line);

            //  add visual children
            if (!standardDefs.isRepeater(selfType))
            {
                if (standardDefs.isContainer(selfType))
                {
                    if (movieClip.hasChildren())
                    {
                        list.add("\t", varName, ".mx_internal::_documentDescriptor = ", line);
                        DescriptorGenerator.addDescriptorInitializerFragments(list, movieClip,
                                                                              Collections.<String>emptySet(),
                                                                              false, "\t\t");
                        list.add("\t;", line);
                        list.add("\t", varName, ".mx_internal::_documentDescriptor.document = this;", line);
                    }
                }
                else
                {
                    //  non-repeater - replicate DI child-creation sequence procedurally:
                    Iterator childIter = movieClip.getChildInitializerIterator();

                    while (childIter.hasNext())
                    {
                        VisualChildInitializer init = (VisualChildInitializer)childIter.next();

                        // Filter out state specific children.
                        if ( !((Model)init.getValue()).isStateSpecific())
                        {
                            list.add("\t", init.getAssignExpr(varName), ";", init.getLineRef());
                        }
                    }
                }
            }
            else
            {
                //  repeater-specific init sequence: don't add children directly, instead use existing DI setup
                //  initializing repeater's childDescriptors property, for now

                list.add("\tvar cd:Array = ", varName, ".childDescriptors = [", line);

                for (Iterator childIter = movieClip.children().iterator(); childIter.hasNext(); )
                {
                    VisualChildInitializer init = (VisualChildInitializer)childIter.next();
                    DescriptorGenerator.addDescriptorInitializerFragments(list, (MovieClip)init.getValue(), "\t\t");

                    if (childIter.hasNext())
                    {
                        list.add(",", 0);
                    }
                }

                list.add("\t];", line);
                list.add("\tfor (var i:int = 0; i < cd.length; i++) cd[i].document = this;", line);
            }
        }

        // TODO: Remove [IMXMLObject] metadata support once we have a
        // non-framework dependent swc to link in mx.core.IMXMLObject

        //  call IMXMLObject.initialized() on implementors
        if (self.getType().isAssignableTo(standardDefs.INTERFACE_IMXMLOBJECT)
                || self.getType().hasMetadata(StandardDefs.MD_IMXMLOBJECT, true))
        {
            String idParam = (isDeclared ? TextGen.quoteWord(id) : "null");
            list.add("\t", varName, ".initialized(this, ", idParam, ")", line);
        }

        // generate idAssigned dispatching logic for user declared instances.
        if (isDeclared)
        {
            if (self.getRepeaterLevel() == 0)
            {
                list.add("\t", id, " = ", varName, ";", line);
            }
            else
            {
                ThreadLocalToolkit.log(new DeclaredAndProceduralWithinRepeater(), self.getDocument().getSourcePath(), line);
            }

            //  evaluate all property bindings for this object - i.e. initialize properties of the object whose values
            //  are binding expressions. E.g. if we've just created <mx:Foo id="bar" x="100" y="{baz.z}"/>, then
            //  we need to evaluate (baz.z) and assign it to bar.y. This explicit evaluation pass is necessary because
            //  baz may already have been initialized, although the fact that we do it even when that's not the case is
            //  suboptimal.
            list.add("\t", NameFormatter.toDot(standardDefs.CLASS_BINDINGMANAGER),
                     ".executeBindings(this, ", TextGen.quoteWord(id), ", " + id + ");", line);
        }

        // If this is a stateful Halo Container, with itemCreationPolicy "immediate" we need to ensure
        // that the instance and all descendants are instantiated.
        if (standardDefs.isContainer(selfType) && self.isEarlyInit())
        {
            list.add("\t", varName,".initialize();", line);
        }
       
        //  return created value
        list.add("\treturn ", varName, ";", line);
        list.add("}", line);
       
        Type lvalueType = getLValueType();
        if (standardDefs.isITransientDeferredInstance(lvalueType) || self.getIsTransient())
          list = getDestructorBody(list, line);

        return list;
    }

    /*
     * Helper function to collect all declarations and sub-declarations for a
     * given model initializer (used by getDestructorBody).
     */
    private void collectDeclarations(Iterator<Initializer> initializers, Set<String> ids)
    {
      for (Iterator<Initializer> iter = initializers; iter.hasNext(); )
        {
        Initializer initializer = iter.next();
        if (initializer instanceof ValueInitializer)
        {
          ValueInitializer valueInitializer = (ValueInitializer)initializer;
          Object value = valueInitializer.getValue();
            if (value instanceof Model)
          {
              if (((Model)value).isDeclared())
                ids.add(((Model)value).getId());
              collectDeclarations(((Model)value).getSubInitializerIterator(), ids);
          }
        }
        }
    }
   
    /**
     * Generates the destructor/reset method as necessary as required by
     * ITransientDeferredInstance rvalues.
     */
    protected CodeFragmentList getDestructorBody(CodeFragmentList list, int line)
    {
      Model model = (Model) value;
     
      Set<String> ids = new LinkedHashSet<String>();
      if (model.isDeclared()) ids.add(model.getId());

      // Collect ids (declarations) that this destructor needs to reset.
      collectDeclarations(model.getSubInitializerIterator(), ids);
     
        // function header
        list.add("\nprivate function ", model.getDefinitionName() + "_r", "() : void", line);
        list.add("{", line);

        // generate declaration and sub-declaration cleanup.
        for (String id : ids)
        {
            list.add("\t", id, " = null;", 0);
        }

        list.add("}", line);
       
      return list;
    }
   
  /**
   * return an iterator over our definition if we have one, and all the definitions of our children
   */
  public Iterator getDefinitionsIterator()
  {
    IteratorList iterList = null;

    if (hasDefinition())
    {
      //  Note: isDescribed() guard omits our own definition if we're in a descriptor tree
      //   TODO remove this once DI is done directly
      if (!(value instanceof Model) || !((Model)value).isDescribed())
      {
        (iterList = new IteratorList()).add(new SingletonIterator(getDefinitionBody()));
      }
    }

    if (value instanceof Model)
    {
      (iterList != null ? iterList : (iterList = new IteratorList())).add(((Model)value).getSubDefinitionsIterator());
    }

    return iterList != null ? iterList.toIterator() : Collections.EMPTY_LIST.iterator();
  }

    public StatementListNode generateDefinitionBody(Context context, HashSet<String> configNamespaces,
                                                    boolean generateDocComments, StatementListNode statementList)
    {
        assert hasDefinition() : "no definition in getDefinitionBody()";
        assert value instanceof Model : "non-Model value has definition in getDefinitionBody()";

        NodeFactory nodeFactory = context.getNodeFactory();
        StatementListNode result = statementList;

        final String varName = TEMP;
       
        Model self = (Model) value;
        Type selfType = self.getType();
        String selfTypeName;

        if (value instanceof Vector)
        {
            Vector vector = (Vector) value;
            String elementTypeName = vector.getElementTypeName();
            selfTypeName = StandardDefs.CLASS_VECTOR + ".<" + elementTypeName + ">";
        }
        else
        {
            selfTypeName = NameFormatter.toDot(selfType.getName());
        }

        boolean isDeclared = self.isDeclared();
        String id = isDeclared ? self.getId() : varName;

        TypeExpressionNode returnType =
            AbstractSyntaxTreeUtil.generateTypeExpression(nodeFactory, selfTypeName, true);
        FunctionSignatureNode functionSignature = nodeFactory.functionSignature(null, returnType);       
        int position = AbstractSyntaxTreeUtil.lineNumberToPosition(nodeFactory, getLineRef());
        VariableDefinitionNode variableDefinition;

        //  value creation
        if (modelHasInlineRValue())
        {
            Node inlineRValue = generateInlineRValue(nodeFactory, configNamespaces, generateDocComments);
            variableDefinition = AbstractSyntaxTreeUtil.generateVariable(nodeFactory, varName,
                                                                         selfTypeName, true,
                                                                         inlineRValue, position);
        }
        else if (value instanceof Vector)
        {
            Vector vector = (Vector) value;
            LiteralNumberNode literalNumber = nodeFactory.literalNumber(vector.size());
            ArgumentListNode argumentList = nodeFactory.argumentList(null, literalNumber);

            if (vector.isFixed())
            {
                LiteralBooleanNode literalBoolean = nodeFactory.literalBoolean(vector.isFixed());
                argumentList = nodeFactory.argumentList(argumentList, literalBoolean);
            }
           
            variableDefinition = AbstractSyntaxTreeUtil.generateVariableNew(nodeFactory, varName,
                                                                            selfTypeName, argumentList,
                                                                            position);
        }
        else
        {
            //  TODO confirm the availability of a 0-arg ctor!! but do
            //  it upstream from here, like when Model is built
            variableDefinition = AbstractSyntaxTreeUtil.generateVariableNew(nodeFactory, varName,
                                                                            selfTypeName, position);
        }

        StatementListNode functionStatementList = nodeFactory.statementList(null, variableDefinition);

        if (!modelHasInlineRValue())
        {
            if (value instanceof Vector)
            {
                Vector vector = (Vector) value;
                addAssignExprs(nodeFactory, configNamespaces, generateDocComments, functionStatementList,
                               vector.getElementInitializerIterator(), varName);
            }
            else
            {
                // set properties
                addAssignExprs(nodeFactory, configNamespaces, generateDocComments, functionStatementList,
                               self.getPropertyInitializerIterator(self.getType().hasDynamic()),
                               varName);
            }
        }
       
        //  set styles
        addAssignExprs(nodeFactory, configNamespaces, generateDocComments, functionStatementList,
                       self.getStyleInitializerIterator(), varName);

        //  set effects
        addAssignExprs(nodeFactory, configNamespaces, generateDocComments, functionStatementList,
                       self.getEffectInitializerIterator(), varName);

        //  add event handlers
        addAssignExprs(nodeFactory, configNamespaces, generateDocComments, functionStatementList,
                       self.getEventInitializerIterator(), varName);

        //  register effect names
        Iterator<Initializer> iterator = self.getEffectInitializerIterator();

        if (iterator.hasNext())
        {
            //list.add("\t", varName, ".registerEffects([ ", effectEventNames, " ]);", line);
            MemberExpressionNode base = AbstractSyntaxTreeUtil.generateGetterSelector(nodeFactory, varName, false);

            IdentifierNode identifier = nodeFactory.identifier(REGISTER_EFFECTS, false);
            ArgumentListNode effectEventNamesArgumentList = null;

            while (iterator.hasNext())
            {
                EffectInitializer effectInitializer = (EffectInitializer) iterator.next();
                String effectName = effectInitializer.getName();
                LiteralStringNode literalString = nodeFactory.literalString(effectName);
                effectEventNamesArgumentList = nodeFactory.argumentList(effectEventNamesArgumentList,
                                                                        literalString);
            }

            LiteralArrayNode literalArray = nodeFactory.literalArray(effectEventNamesArgumentList);
            ArgumentListNode argumentList = nodeFactory.argumentList(null, literalArray);
            CallExpressionNode selector = (CallExpressionNode) nodeFactory.callExpression(identifier,
                                                                                          argumentList);
            selector.setRValue(false);
            MemberExpressionNode memberExpression = nodeFactory.memberExpression(base, selector);
            ListNode list = nodeFactory.list(null, memberExpression);
            ExpressionStatementNode expressionStatement = nodeFactory.expressionStatement(list);
            functionStatementList = nodeFactory.statementList(functionStatementList, expressionStatement);
        }

        //  post-init actions for values that are being assigned to properties (via id attribution)
        if (isDeclared && standardDefs.isIUIComponentWithIdProperty(selfType))
        {
            //  set id on IUIComponents that carry an id prop
            MemberExpressionNode base = AbstractSyntaxTreeUtil.generateGetterSelector(nodeFactory, varName, false);
            IdentifierNode identifier = nodeFactory.identifier(ID, false);
            LiteralStringNode literalString = nodeFactory.literalString(id);
            ArgumentListNode argumentList = nodeFactory.argumentList(null, literalString);
            SetExpressionNode selector = nodeFactory.setExpression(identifier, argumentList, false);
            MemberExpressionNode memberExpression = nodeFactory.memberExpression(base, selector);
            ListNode list = nodeFactory.list(null, memberExpression);
            ExpressionStatementNode expressionStatement = nodeFactory.expressionStatement(list);
            functionStatementList = nodeFactory.statementList(functionStatementList, expressionStatement);
        }

        // Design layer related items
        if (self.layerParent != null)
        {
            if (self instanceof DesignLayer)
            {
                //list.add("\t", self.layerParent.getId(), ".addLayer(", varName, ");", line);
             
                IdentifierNode method = nodeFactory.identifier(ADD_LAYER, false);
               
                IdentifierNode layerIdentifier = nodeFactory.identifier(self.layerParent.getId());
              GetExpressionNode getExpression = nodeFactory.getExpression(layerIdentifier);
              MemberExpressionNode layerMemberExpression = nodeFactory.memberExpression(null, getExpression);
             
              IdentifierNode varIdentifier = nodeFactory.identifier(varName);
              GetExpressionNode varGetExpression = nodeFactory.getExpression(varIdentifier);
              MemberExpressionNode varMemberExpression = nodeFactory.memberExpression(null, varGetExpression);
             
                ArgumentListNode argumentList = nodeFactory.argumentList(null, varMemberExpression);
               
                CallExpressionNode selector = (CallExpressionNode) nodeFactory.callExpression(method, argumentList);
                selector.setRValue(false);
               
                MemberExpressionNode memberExpression = nodeFactory.memberExpression(layerMemberExpression, selector);
                ListNode list = nodeFactory.list(null, memberExpression);
                ExpressionStatementNode expressionStatement = nodeFactory.expressionStatement(list);
                functionStatementList = nodeFactory.statementList(functionStatementList, expressionStatement);
               
            }
            else if (self.getType().isAssignableTo(standardDefs.INTERFACE_IVISUALELEMENT))
            {  
              // list.add("\t", varName, ".layer = ", self.layerParent.getId(), ";", line);
              IdentifierNode varIdentifier = nodeFactory.identifier(varName);
              GetExpressionNode varGetExpression = nodeFactory.getExpression(varIdentifier);
              MemberExpressionNode base = nodeFactory.memberExpression(null, varGetExpression);
             

              IdentifierNode identifier = nodeFactory.identifier(DESIGN_LAYER, false);
             
              IdentifierNode layerIdentifier = nodeFactory.identifier(self.layerParent.getId());
              GetExpressionNode getExpression = nodeFactory.getExpression(layerIdentifier);
             
              MemberExpressionNode rvalueMemberExpression = nodeFactory.memberExpression(null, getExpression);
                ArgumentListNode argumentList = nodeFactory.argumentList(null, rvalueMemberExpression);
               
              SetExpressionNode selector = nodeFactory.setExpression(identifier, argumentList, false);
             
                MemberExpressionNode memberExpression = nodeFactory.memberExpression(base, selector);
                ListNode list = nodeFactory.list(null, memberExpression);
                ExpressionStatementNode expressionStatement = nodeFactory.expressionStatement(list);
                functionStatementList = nodeFactory.statementList(functionStatementList, expressionStatement);
            }   
        }
       
        //  UIComponent-specific init steps
        if (standardDefs.isIUIComponent(selfType))
        {
            assert self instanceof MovieClip : "isIUIComponent(selfType) but !(self instanceof MovieClip)";
            MovieClip movieClip = (MovieClip) self;

            //  MXML implementations of IUIComponent initialize set their document property to themselves at
            //  construction time. Others need it set to the enclosing document (us).

            ListNode test;
            {
                MemberExpressionNode base =
                    AbstractSyntaxTreeUtil.generateGetterSelector(nodeFactory, varName, false);
                IdentifierNode identifier = nodeFactory.identifier(DOCUMENT, false);
                GetExpressionNode selector = nodeFactory.getExpression(identifier);
                MemberExpressionNode memberExpression = nodeFactory.memberExpression(base, selector);
                Node unaryExpression = nodeFactory.unaryExpression(Tokens.NOT_TOKEN, memberExpression);
                test = nodeFactory.list(null, unaryExpression);
            }

            StatementListNode then;
            {
                MemberExpressionNode base =
                    AbstractSyntaxTreeUtil.generateGetterSelector(nodeFactory, varName, false);
                IdentifierNode identifier = nodeFactory.identifier(DOCUMENT, false);
                ThisExpressionNode thisExpression = nodeFactory.thisExpression(-1);
                ArgumentListNode argumentList = nodeFactory.argumentList(null, thisExpression);
                SetExpressionNode selector = nodeFactory.setExpression(identifier, argumentList, false);
                MemberExpressionNode memberExpression = nodeFactory.memberExpression(base, selector);
                ListNode list = nodeFactory.list(null, memberExpression);
                ExpressionStatementNode expressionStatement = nodeFactory.expressionStatement(list);
                then = nodeFactory.statementList(null, expressionStatement);
            }

            Node ifStatement = nodeFactory.ifStatement(test, then, null);
            functionStatementList = nodeFactory.statementList(functionStatementList, ifStatement);

            //  add visual children
            if (!standardDefs.isRepeater(selfType))
            {
                if (standardDefs.isContainer(selfType))
                {
                    if (movieClip.hasChildren())
                    {
                        functionStatementList = generateDocumentDescriptorAssignment(nodeFactory, configNamespaces, generateDocComments,
                                                                                     movieClip, varName, functionStatementList);
                        functionStatementList = generateDocumentDescriptorDocumentAssignment(nodeFactory, varName,
                                                                                             functionStatementList);
                    }
                }
                else
                {
                    //  non-repeater - replicate DI child-creation sequence procedurally:      
                    Iterator childIter = movieClip.getChildInitializerIterator();
                    while (childIter.hasNext())
                    {
                        VisualChildInitializer init = (VisualChildInitializer)childIter.next();
                   
                        // Filter out state specific children.
                        if ( !((Model)init.getValue()).isStateSpecific())
                        {
                            MemberExpressionNode memberExpression =
                                AbstractSyntaxTreeUtil.generateGetterSelector(nodeFactory, varName, true);
                            functionStatementList =
                                init.generateAssignExpr(nodeFactory, configNamespaces, generateDocComments,
                                                        functionStatementList, memberExpression);
                        }
                    }
                }
            }
            else
            {
                //  repeater-specific init sequence: don't add children directly, instead use existing DI setup
                //  initializing repeater's childDescriptors property, for now
                VariableDefinitionNode childDescriptorVariableDefinition =
                    generateChildDescriptorVariable(nodeFactory, configNamespaces, generateDocComments,
                                                    varName, movieClip);
                functionStatementList = nodeFactory.statementList(functionStatementList,
                                                                  childDescriptorVariableDefinition);
                Node forStatement = generateRepeaterChildDescriptorLoop(nodeFactory);
                functionStatementList = nodeFactory.statementList(functionStatementList, forStatement);
            }
        }

        //  call IMXMLObject.initialized() on implementors
        if (self.getType().isAssignableTo(standardDefs.INTERFACE_IMXMLOBJECT)
                || self.getType().hasMetadata(StandardDefs.MD_IMXMLOBJECT, true))
        {
            MemberExpressionNode varNameMemberExpression =
                AbstractSyntaxTreeUtil.generateGetterSelector(nodeFactory, varName, false);
            IdentifierNode identifier = nodeFactory.identifier(INITIALIZED, false);
            ThisExpressionNode thisExpression = nodeFactory.thisExpression(-1);
            ArgumentListNode argumentList = nodeFactory.argumentList(null, thisExpression);

            if (isDeclared)
            {
                LiteralStringNode literalString = nodeFactory.literalString(id);
                argumentList = nodeFactory.argumentList(argumentList, literalString);
            }
            else
            {
                LiteralNullNode literalNull = nodeFactory.literalNull(-1);
                argumentList = nodeFactory.argumentList(argumentList, literalNull);
            }

            CallExpressionNode callExpression =
                (CallExpressionNode) nodeFactory.callExpression(identifier, argumentList);
            callExpression.setRValue(false);
            MemberExpressionNode memberExpression = nodeFactory.memberExpression(varNameMemberExpression,
                                                                                 callExpression);
            ListNode list = nodeFactory.list(null, memberExpression);
            ExpressionStatementNode expressionStatement = nodeFactory.expressionStatement(list);
            functionStatementList = nodeFactory.statementList(functionStatementList, expressionStatement);
        }

        // generate idAssigned dispatching logic for user declared instances.
        if (isDeclared)
        {
            if (self.getRepeaterLevel() == 0)
            {
                functionStatementList = generateValueCreation(nodeFactory, functionStatementList, id, varName);
            }
            else
            {
                ThreadLocalToolkit.log(new DeclaredAndProceduralWithinRepeater(),
                                       self.getDocument().getSourcePath(), getLineRef());
            }
       
            //  evaluate all property bindings for this object - i.e. initialize properties of the object whose values
            //  are binding expressions. E.g. if we've just created <mx:Foo id="bar" x="100" y="{baz.z}"/>, then
            //  we need to evaluate (baz.z) and assign it to bar.y. This explicit evaluation pass is necessary because
            //  baz may already have been initialized, although the fact that we do it even when that's not the case is
            //  suboptimal.
            MemberExpressionNode base =
                AbstractSyntaxTreeUtil.generateGetterSelector(nodeFactory, standardDefs.getBindingPackage(), BINDING_MANAGER, false);
            IdentifierNode identifier = nodeFactory.identifier(EXECUTE_BINDINGS, false);
            ThisExpressionNode thisExpression = nodeFactory.thisExpression(-1);
            ArgumentListNode argumentList = nodeFactory.argumentList(null, thisExpression);
            LiteralStringNode literalString = nodeFactory.literalString(id);
            argumentList = nodeFactory.argumentList(argumentList, literalString);
            MemberExpressionNode idMemberExpression =
                AbstractSyntaxTreeUtil.generateGetterSelector(nodeFactory, id, true);
            argumentList = nodeFactory.argumentList(argumentList, idMemberExpression);
            CallExpressionNode selector = (CallExpressionNode) nodeFactory.callExpression(identifier, argumentList);
            selector.setRValue(false);
            MemberExpressionNode memberExpression = nodeFactory.memberExpression(base, selector);
            ListNode list = nodeFactory.list(null, memberExpression);
            ExpressionStatementNode expressionStatement = nodeFactory.expressionStatement(list);
            functionStatementList = nodeFactory.statementList(functionStatementList, expressionStatement);
        }

        // If this is a stateful Halo Container, with itemCreationPolicy "immediate" we need to ensure
        // that the instance and all descendants are instantiated.
        if (standardDefs.isContainer(selfType) && self.isEarlyInit())
        {
            MemberExpressionNode varNameMemberExpression =
                AbstractSyntaxTreeUtil.generateGetterSelector(nodeFactory, varName, false);
            IdentifierNode identifier = nodeFactory.identifier(INITIALIZE, false);
           
            CallExpressionNode callExpression =
                (CallExpressionNode) nodeFactory.callExpression(identifier, null);
            callExpression.setRValue(false);
            MemberExpressionNode memberExpression = nodeFactory.memberExpression(varNameMemberExpression,
                                                                                 callExpression);
            ListNode list = nodeFactory.list(null, memberExpression);
            ExpressionStatementNode expressionStatement = nodeFactory.expressionStatement(list);
            functionStatementList = nodeFactory.statementList(functionStatementList, expressionStatement);
        }
       
        //  return created value
        MemberExpressionNode memberExpression =
            AbstractSyntaxTreeUtil.generateGetterSelector(nodeFactory, varName, false);
        ListNode list = nodeFactory.list(null, memberExpression);
        ReturnStatementNode returnStatement = nodeFactory.returnStatement(list);
        functionStatementList = nodeFactory.statementList(functionStatementList, returnStatement);

        IdentifierNode functionIdentifier = nodeFactory.identifier(getDefinitionName());
        FunctionCommonNode functionCommon = nodeFactory.functionCommon(context,
                                                                       functionIdentifier,
                                                                       functionSignature,
                                                                       functionStatementList);
        functionCommon.setUserDefinedBody(true);
        AttributeListNode attributeList = AbstractSyntaxTreeUtil.generatePrivateAttribute(nodeFactory);
        FunctionNameNode functionName = nodeFactory.functionName(Tokens.EMPTY_TOKEN, functionIdentifier);

        FunctionDefinitionNode functionDefinition = nodeFactory.functionDefinition(context, attributeList,
                                                                                   functionName, functionCommon);

        result = nodeFactory.statementList(result, functionDefinition);

        Type lvalueType = getLValueType();
        if (standardDefs.isITransientDeferredInstance(lvalueType) || self.getIsTransient())
          result = generateDestructorBody(context, result);
       
        return result;
    }

    /**
     * Generates the destructor/reset method as necessary as required by
     * ITransientDeferredInstance rvalues.
     */
    protected StatementListNode generateDestructorBody(Context context, StatementListNode statementList)
    {     
      Model model = (Model) value;
     
      Set<String> ids = new LinkedHashSet<String>();
      if (model.isDeclared()) ids.add(model.getId());

      // Collect ids (declarations) that this destructor needs to reset.
      collectDeclarations(model.getSubInitializerIterator(), ids);
     
      NodeFactory nodeFactory = context.getNodeFactory();
        StatementListNode result = statementList;
       
        StatementListNode functionStatementList = null;
       
        // Assignment expressions.
       
        for (String id : ids)
        {
            LiteralNullNode literalNull = nodeFactory.literalNull();
            IdentifierNode identifier = nodeFactory.identifier(id);
            Node expressionStatement = nodeFactory.assignmentExpression(identifier,ASSIGN_TOKEN,literalNull);
            functionStatementList = nodeFactory.statementList(functionStatementList, expressionStatement);
        }
       
        // function body
       
        FunctionSignatureNode functionSignature = nodeFactory.functionSignature(null, null);
        functionSignature.void_anno = true;
        IdentifierNode functionIdentifier = nodeFactory.identifier(model.getDefinitionName() + "_r");
        FunctionCommonNode functionCommon = nodeFactory.functionCommon(context,
                                                                       functionIdentifier,
                                                                       functionSignature,
                                                                       functionStatementList);
     
        functionCommon.setUserDefinedBody(true);
        AttributeListNode attributeList = AbstractSyntaxTreeUtil.generatePrivateAttribute(nodeFactory);
        FunctionNameNode functionName = nodeFactory.functionName(Tokens.EMPTY_TOKEN, functionIdentifier);

        FunctionDefinitionNode functionDefinition = nodeFactory.functionDefinition(context, attributeList,
                                                                                   functionName, functionCommon);

        result = nodeFactory.statementList(result, functionDefinition);
       
      return result;
    }
   
  public VariableDefinitionNode generateChildDescriptorVariable(NodeFactory nodeFactory, HashSet<String> configNamespaces,
                                                                  boolean generateDocComments, String varName,
                                  MovieClip movieClip)
  {
    //list.add("\tvar cd:Array = ", varName, ".childDescriptors = [", line);
    MemberExpressionNode base = AbstractSyntaxTreeUtil.generateGetterSelector(nodeFactory, varName, true);
    IdentifierNode childDescriptorsIdentifier = nodeFactory.identifier(CHILD_DESCRIPTORS, false);
    ArgumentListNode visualChildArgumentList = null;

    for (Iterator childIter = movieClip.children().iterator(); childIter.hasNext(); )
    {
      //DescriptorGenerator.addDescriptorInitializerFragments(list, (MovieClip)init.getValue(), "\t\t");
      VisualChildInitializer init = (VisualChildInitializer) childIter.next();
      Model model = (MovieClip) init.getValue();
      MemberExpressionNode memberExpression =
        ImplementationGenerator.addDescriptorInitializerFragments(nodeFactory, configNamespaces,
                                                                          generateDocComments, movieClip,
                                                                          null, true);
      visualChildArgumentList = nodeFactory.argumentList(visualChildArgumentList,
                                 memberExpression);
    }

    LiteralArrayNode literalArray = nodeFactory.literalArray(visualChildArgumentList);
    ArgumentListNode argumentList = nodeFactory.argumentList(null, literalArray);
    SetExpressionNode selector = nodeFactory.setExpression(childDescriptorsIdentifier,
                                 argumentList, false);
    selector.setRValue(false);
    MemberExpressionNode initializer = nodeFactory.memberExpression(base, selector);
    return AbstractSyntaxTreeUtil.generateVariable(nodeFactory, CD, ARRAY, false, initializer);
  }

  private VariableDefinitionNode generateClassVariable(NodeFactory nodeFactory)
  {
    IdentifierNode getDefinitionByNameIdentifier = nodeFactory.identifier(GET_DEFINITION_BY_NAME);
    LiteralStringNode literalString = nodeFactory.literalString(standardDefs.CLASS_PROPERTYCHANGEEVENT_DOT);
    ArgumentListNode argumentList = nodeFactory.argumentList(null, literalString);
    CallExpressionNode callExpression =
      (CallExpressionNode) nodeFactory.callExpression(getDefinitionByNameIdentifier,
                              argumentList);
    callExpression.setRValue(false);
    MemberExpressionNode getDefinitionMemberExpression =
      nodeFactory.memberExpression(null, callExpression);
    IdentifierNode classIdentifier = nodeFactory.identifier(CLASS);
    GetExpressionNode getExpression = nodeFactory.getExpression(classIdentifier);
    MemberExpressionNode classMemberExpression =
      nodeFactory.memberExpression(null, getExpression);
    BinaryExpressionNode binaryExpression =
      nodeFactory.binaryExpression(Tokens.AS_TOKEN,
                     getDefinitionMemberExpression,
                     classMemberExpression);
    return AbstractSyntaxTreeUtil.generateVariable(nodeFactory, __CLASS, CLASS,
                             false, binaryExpression);
  }

  public StatementListNode generateDefinitions(Context context, HashSet<String> configNamespaces,
                                                 boolean generateDocComments, StatementListNode statementList)
  {
    StatementListNode result = statementList;

    if (hasDefinition())
    {
      //  Note: isDescribed() guard omits our own definition if we're in a descriptor tree
      //   TODO remove this once DI is done directly
      if (!(value instanceof Model) || !((Model) value).isDescribed())
      {
        result = generateDefinitionBody(context, configNamespaces, generateDocComments, result);
      }
    }

    if (value instanceof Model)
    {
      Iterator<Initializer> iterator = ((Model) value).getSubInitializerIterator();

      while (iterator.hasNext())
      {
        result = iterator.next().generateDefinitions(context, configNamespaces, generateDocComments, result);
      }
    }

    return result;
  }

  private ExpressionStatementNode generateDispatchEvent(NodeFactory nodeFactory)
  {
    IdentifierNode dispatchEventIdentifier = nodeFactory.identifier(DISPATCH_EVENT, false);
    IdentifierNode eventIdentifier = nodeFactory.identifier(EVENT, false);
    MemberExpressionNode eMemberExpression =
      AbstractSyntaxTreeUtil.generateGetterSelector(nodeFactory, __E, false);
    ArgumentListNode eventArgumentList = nodeFactory.argumentList(null, eMemberExpression);
    CallExpressionNode eventCallExpression =
      (CallExpressionNode) nodeFactory.callExpression(eventIdentifier, eventArgumentList);
    eventCallExpression.setRValue(false);
    MemberExpressionNode eventMemberExpression = nodeFactory.memberExpression(null, eventCallExpression);
    ArgumentListNode dispatchEventArgumentList = nodeFactory.argumentList(null, eventMemberExpression);
    CallExpressionNode dispatchEventCallExpression =
      (CallExpressionNode) nodeFactory.callExpression(dispatchEventIdentifier, dispatchEventArgumentList);
    dispatchEventCallExpression.setRValue(false);
    MemberExpressionNode memberExpression = nodeFactory.memberExpression(null, dispatchEventCallExpression);
    ListNode list = nodeFactory.list(null, memberExpression);
    return nodeFactory.expressionStatement(list);
  }

    private StatementListNode generateDocumentDescriptorAssignment(NodeFactory nodeFactory,
                                                                   HashSet<String> configNamespaces,
                                                                   boolean generateDocComments,
                                                                   MovieClip movieClip,
                                                                   String varName,
                                                                   StatementListNode statementList)
    {
        QualifiedIdentifierNode qualifiedIdentifier =
            AbstractSyntaxTreeUtil.generateMxInternalQualifiedIdentifier(nodeFactory,
                                                                         _DOCUMENT_DESCRIPTOR,
                                                                         false);
        MemberExpressionNode descriptorsMemberExpression =
            ImplementationGenerator.addDescriptorInitializerFragments(nodeFactory, configNamespaces,
                                                                      generateDocComments, movieClip,
                                                                      Collections.<String>emptySet(), false);
        ArgumentListNode argumentList = nodeFactory.argumentList(null, descriptorsMemberExpression);
        SetExpressionNode setExpression = nodeFactory.setExpression(qualifiedIdentifier, argumentList, false);
        MemberExpressionNode base =
            AbstractSyntaxTreeUtil.generateGetterSelector(nodeFactory, varName, false);
        MemberExpressionNode memberExpression = nodeFactory.memberExpression(base, setExpression);
        ListNode list = nodeFactory.list(null, memberExpression);
        ExpressionStatementNode expressionStatement = nodeFactory.expressionStatement(list);
        return nodeFactory.statementList(statementList, expressionStatement);
    }

    private StatementListNode generateDocumentDescriptorDocumentAssignment(NodeFactory nodeFactory,
                                                                           String varName,
                                                                           StatementListNode statementList)
    {
        MemberExpressionNode varNameMemberExpression =
            AbstractSyntaxTreeUtil.generateGetterSelector(nodeFactory, varName, false);
        QualifiedIdentifierNode qualifiedIdentifier =
            AbstractSyntaxTreeUtil.generateMxInternalQualifiedIdentifier(nodeFactory, _DOCUMENT_DESCRIPTOR, false);
        GetExpressionNode documentDescriptorGetExpression = nodeFactory.getExpression(qualifiedIdentifier);
        MemberExpressionNode varNameDocumentDescriptorMemberExpression =
            nodeFactory.memberExpression(varNameMemberExpression, documentDescriptorGetExpression);
        IdentifierNode identifier = nodeFactory.identifier(DOCUMENT, false);
        ThisExpressionNode thisExpression = nodeFactory.thisExpression(-1);
        ArgumentListNode argumentList = nodeFactory.argumentList(null, thisExpression);
        SetExpressionNode setExpression = nodeFactory.setExpression(identifier, argumentList, false);
        MemberExpressionNode memberExpression = nodeFactory.memberExpression(varNameDocumentDescriptorMemberExpression,
                                                                             setExpression);
        ListNode list = nodeFactory.list(null, memberExpression);
        ExpressionStatementNode expressionStatement = nodeFactory.expressionStatement(list);
        return nodeFactory.statementList(statementList, expressionStatement);
    }

  private Node generateRepeaterChildDescriptorLoop(NodeFactory nodeFactory)
  {
    //list.add("\tfor (var i:int = 0; i < cd.length; i++) cd[i].document = this;", line);
    LiteralNumberNode initializer = nodeFactory.literalNumber(0);
    VariableDefinitionNode init =
      AbstractSyntaxTreeUtil.generateVariable(nodeFactory, I, INT, false, initializer);
    MemberExpressionNode iMemberExpression =
      AbstractSyntaxTreeUtil.generateGetterSelector(nodeFactory, I, false);
    MemberExpressionNode cdMemberExpression =
      AbstractSyntaxTreeUtil.generateGetterSelector(nodeFactory, CD, false);

    IdentifierNode lengthIdentifier = nodeFactory.identifier(LENGTH, false);
    GetExpressionNode lengthGetExpression = nodeFactory.getExpression(lengthIdentifier);
    MemberExpressionNode cdLengthMemberExpression = nodeFactory.memberExpression(cdMemberExpression,
                                           lengthGetExpression);
    BinaryExpressionNode binaryExpression = nodeFactory.binaryExpression(Tokens.LESSTHAN_TOKEN,
                                       iMemberExpression,
                                       cdLengthMemberExpression);
    ListNode test = nodeFactory.list(null, binaryExpression);

    IdentifierNode iIdentifier = nodeFactory.identifier(I, false);
    IncrementNode increment = nodeFactory.increment(Tokens.PLUSPLUS_TOKEN, iIdentifier, true);
    MemberExpressionNode incrMemberExpression = nodeFactory.memberExpression(null, increment);
    ListNode incr = nodeFactory.list(null, incrMemberExpression);

    cdMemberExpression = AbstractSyntaxTreeUtil.generateGetterSelector(nodeFactory, CD, false);

    iMemberExpression = AbstractSyntaxTreeUtil.generateGetterSelector(nodeFactory, I, false);
    ArgumentListNode getArgumentList = nodeFactory.argumentList(null, iMemberExpression);
    GetExpressionNode iGetExpression = nodeFactory.getExpression(getArgumentList);
    iGetExpression.setMode(Tokens.LEFTBRACKET_TOKEN);
    MemberExpressionNode base = nodeFactory.memberExpression(cdMemberExpression, iGetExpression);

    IdentifierNode documentIdentifier = nodeFactory.identifier(DOCUMENT, false);
    ThisExpressionNode thisExpression = nodeFactory.thisExpression(-1);
    ArgumentListNode setArgumentList = nodeFactory.argumentList(null, thisExpression);
    SetExpressionNode selector = nodeFactory.setExpression(documentIdentifier,
                                 setArgumentList, false);

    MemberExpressionNode memberExpression = nodeFactory.memberExpression(base, selector);
    ListNode list = nodeFactory.list(null, memberExpression);
    ExpressionStatementNode expressionStatement = nodeFactory.expressionStatement(list);
    StatementListNode body = nodeFactory.statementList(null, expressionStatement);

    return nodeFactory.forStatement(init, test, incr, body);
  }

  private StatementListNode generateValueCreation(NodeFactory nodeFactory, StatementListNode statementList,
                          String id, String varName)
  {
    ExpressionStatementNode expressionStatement =
      AbstractSyntaxTreeUtil.generateAssignment(nodeFactory, id, varName);
    return nodeFactory.statementList(statementList, expressionStatement);
  }

  /**
   *
   */
  private TypeTable getTypeTable()
  {
    return getLValueType().getTypeTable();
  }

  /**
   *
   */
  private static void addAssignExprs(CodeFragmentList list, Iterator initIter, String name)
  {
        while (initIter.hasNext())
        {
            Initializer init = (Initializer)initIter.next();
            if (!init.isStateSpecific())
                list.add("\t", init.getAssignExpr(name), ";", init.getLineRef());
        }
  }

  /**
   *
   */
  private static void addAssignExprs(NodeFactory nodeFactory, HashSet<String> configNamespaces,
                                       boolean generateDocComments, StatementListNode statementList,
                     Iterator<? extends Initializer> initIter,
                     String name)
  {
        while (initIter.hasNext())
        {
            Initializer init = initIter.next();
            if (!init.isStateSpecific())
            {
                MemberExpressionNode memberExpression =
                    AbstractSyntaxTreeUtil.generateGetterSelector(nodeFactory, name, true);
                statementList = init.generateAssignExpr(nodeFactory, configNamespaces, generateDocComments,
                                                        statementList, memberExpression);
            }
        }
  }

  /**
   * TODO once all POJO rvalues have been eliminated, this can go away completely
   */
  protected String formatExpr(Type targetType, Object value)
  {
    assert targetType != null;
    assert value != null;

    TypeTable typeTable = getTypeTable();

    if (value instanceof BindingExpression)
    {
      if (targetType.equals(typeTable.booleanType) ||
        targetType.equals(typeTable.numberType) ||
        targetType.equals(typeTable.intType) ||
        targetType.equals(typeTable.uintType))
      {
        return StandardDefs.UNDEFINED;
      }
      else
      {
        return StandardDefs.NULL;
      }
    }

    if (value instanceof AtEmbed)
    {
      return ((AtEmbed) value).getPropName();
    }

    if (value instanceof AtResource)
    {
      return ((AtResource)value).getValueExpression();
    }

    if (targetType.equals(typeTable.stringType))
    {
      return StringUtils.formatString(value.toString());
    }
    else if (targetType.equals(typeTable.booleanType) ||
        targetType.equals(typeTable.numberType) ||
        targetType.equals(typeTable.intType) ||
        targetType.equals(typeTable.uintType))
    {
      return value.toString();
    }
    else if (targetType.equals(typeTable.objectType) || targetType.equals(typeTable.noType))
    {
      if (value instanceof String)
      {
        return StringUtils.formatString((String) value);
      }
      else if (value instanceof Number || value instanceof Boolean)
      {
        return value.toString();
      }
      else
      {
        assert false : "formatExpr: unsupported rvalue type '" + value.getClass() + "' for lvalue type 'Object'";
      }
    }
    else if (targetType.equals(typeTable.classType))
    {
      return value.toString();
    }
    else if (targetType.equals(typeTable.functionType))
    {
      return value.toString();
    }
    else if (targetType.equals(typeTable.regExpType))
    {
      return value.toString();
    }
    else if (targetType.equals(typeTable.xmlType))
    {
      return asXmlLiteral((XML)value);
    }
    else if (targetType.equals(typeTable.xmlListType))
    {
      return asXMLList((XMLList)value);
    }
    else if (standardDefs.isInstanceGenerator(targetType))
    {
      assert false : "formatExpr: instance generator lvalue with non-Model lvalue";
    }
    else
    {
      assert false : "formatExpr: unsupported lvalue type: " + targetType.getName();
    }

    assert false;
    return null;
  }

  /**
   * TODO once all POJO rvalues have been eliminated, this can go away completely
   */
  protected Node formatExpr(NodeFactory nodeFactory, HashSet<String> configNamespaces,
                              boolean generateDocComments, Type targetType, Object value)
  {
    assert targetType != null;
    assert value != null;

    TypeTable typeTable = getTypeTable();

    if (value instanceof BindingExpression)
    {
      if (targetType.equals(typeTable.booleanType) ||
        targetType.equals(typeTable.numberType) ||
        targetType.equals(typeTable.intType) ||
        targetType.equals(typeTable.uintType))
      {
        return nodeFactory.identifier(UNDEFINED, false);
      }
      else
      {
        return nodeFactory.literalNull(-1);
      }
    }

    if (value instanceof AtEmbed)
    {
      return AbstractSyntaxTreeUtil.generateGetterSelector(nodeFactory,
                                 ((AtEmbed) value).getPropName(),
                                 true);
    }

    if (value instanceof AtResource)
    {
      return ((AtResource) value).getValueExpression(nodeFactory);
    }

    if (targetType.equals(typeTable.stringType))
    {
      return nodeFactory.literalString(StringUtils.unformatString(value.toString()));
    }

    if (targetType.equals(typeTable.booleanType))
    {
      return nodeFactory.literalBoolean(Boolean.parseBoolean(value.toString()));
    }
    else if (targetType.equals(typeTable.numberType) ||
         targetType.equals(typeTable.intType) ||
         targetType.equals(typeTable.uintType))
    {
      return nodeFactory.literalNumber(value.toString());
    }
    else if (targetType.equals(typeTable.objectType) || targetType.equals(typeTable.noType))
    {
      if (value instanceof String)
      {
        return nodeFactory.literalString(StringUtils.unformatString((String) value));
      }
      else if (value instanceof Number)
      {
        return nodeFactory.literalNumber(value.toString());
      }
      else if (value instanceof Boolean)
      {
        return nodeFactory.literalBoolean(Boolean.parseBoolean(value.toString()));
      }
      else
      {
        assert false : "formatExpr: unsupported rvalue type '" + value.getClass() + "' for lvalue type 'Object'";
      }
    }
    else if (targetType.equals(typeTable.classType))
    {
            if (value.equals(THIS))
            {
                return nodeFactory.thisExpression(-1);
            }
            else if (value.equals(NULL))
            {
                return nodeFactory.literalNull(-1);
            }
            else
            {
              int position = AbstractSyntaxTreeUtil.lineNumberToPosition(nodeFactory, getLineRef());
                return AbstractSyntaxTreeUtil.generateMemberExpression(nodeFactory, value.toString(), position);
            }
    }
    else if (targetType.equals(typeTable.functionType))
    {
            // The value can be a function reference, like "foo",
            // "C.foo", or "a.b.C.foo", or it can be a function
            // definition, like "function () {}".  The "var f =" is
            // necessary to put ASC's parser into the correct state to
            // handle a function definition.
            List<Node> list =
                AbstractSyntaxTreeUtil.parse(nodeFactory.getContext(), configNamespaces,
                                             "var f = " + value.toString(), getLineRef(),
                                             generateDocComments);
           
            VariableDefinitionNode variableDefinition = null;
           
            if(list.get(0) instanceof DocCommentNode)
            {
                variableDefinition = (VariableDefinitionNode) ((DocCommentNode) list.get(0)).def;
            }
            else
            {
                variableDefinition = (VariableDefinitionNode) list.get(0);
            }
           
            VariableBindingNode variableBinding = (VariableBindingNode) variableDefinition.list.items.get(0);
            return variableBinding.initializer;
    }
    else if (targetType.equals(typeTable.regExpType))
    {
      return nodeFactory.literalRegExp(value.toString(), -1);
    }
    else if (targetType.equals(typeTable.xmlType))
    {
      return asXmlLiteral(nodeFactory, (XML) value);
    }
    else if (targetType.equals(typeTable.xmlListType))
    {
      return asXMLList(nodeFactory, (XMLList) value);
    }
    else if (standardDefs.isInstanceGenerator(targetType))
    {
      assert false : "formatExpr: instance generator lvalue with non-Model lvalue";
    }
    else
    {
      assert false : "formatExpr: unsupported lvalue type: " + targetType.getName();
    }

    assert false;
    return null;
  }

  /**
   *
   */
  private static String asArrayLiteral(Array array)
  {
    List<String> elements = new ArrayList<String>();

    for (Iterator<ArrayElementInitializer> iter = array.getElementInitializerIterator(); iter.hasNext(); )
    {
      ArrayElementInitializer initializer = iter.next();
     
      if (!initializer.isStateSpecific())
      {
        elements.add(initializer.getValueExpr());
      }
    }

    return "[" + TextGen.toCommaList(elements.iterator()) + "]";
  }

  /**
   *
   */
  private static LiteralArrayNode asArrayLiteral(NodeFactory nodeFactory, HashSet<String> configNamespaces,
                                                   boolean generateDocComments, Array array)
  {
    ArgumentListNode argumentList = null;

    for (Iterator<ArrayElementInitializer> iter = array.getElementInitializerIterator(); iter.hasNext(); )
    {
      ArrayElementInitializer initializer = iter.next();
      if (!initializer.isStateSpecific())
      {
        Node valueExprNode = initializer.generateValueExpr(nodeFactory, configNamespaces, generateDocComments);
        argumentList = nodeFactory.argumentList(argumentList, valueExprNode);
      }
    }

    return nodeFactory.literalArray(argumentList);
  }

  /**
   *
   */
  private static String asObjectLiteral(Model model)
  {
    List<String> pairs = new ArrayList<String>();

    for (Iterator<Initializer> iter = model.getPropertyInitializerIterator(); iter.hasNext(); )
    {
      NamedInitializer init = (NamedInitializer)iter.next();
      pairs.add(init.getName() + ": " + init.getValueExpr());
    }

    return "{" + TextGen.toCommaList(pairs.iterator()) + "}";
  }

  /**
   *
   */
  private static LiteralObjectNode asObjectLiteral(NodeFactory nodeFactory, HashSet<String> configNamespaces,
                                                     boolean generateDocComments, Model model)
  {
    ArgumentListNode argumentList = null;

    for (Iterator<Initializer> iter = model.getPropertyInitializerIterator(); iter.hasNext(); )
    {
      NamedInitializer init = (NamedInitializer) iter.next();
      IdentifierNode identifier = nodeFactory.identifier(init.getName());
      LiteralFieldNode literalField =
        nodeFactory.literalField(identifier,
                                         init.generateValueExpr(nodeFactory, configNamespaces,
                                                                generateDocComments));
      argumentList = nodeFactory.argumentList(argumentList, literalField);
    }

    return nodeFactory.literalObject(argumentList);
  }

    /**
     *
     */
    private static String asVectorLiteral(Vector vector)
    {
        List<String> elements = new ArrayList<String>();

        for (Iterator<ArrayElementInitializer> iter = vector.getElementInitializerIterator(); iter.hasNext(); )
        {
            ArrayElementInitializer initializer = iter.next();
   
            if (!initializer.isStateSpecific())
            {
                elements.add(initializer.getValueExpr());
            }
        }

        return "new <" + vector.getElementTypeName() + ">[" + TextGen.toCommaList(elements.iterator()) + "]";
    }

    /**
     *
     */
    private static LiteralVectorNode asVectorLiteral(NodeFactory nodeFactory, HashSet<String> configNamespaces,
                                                     boolean generateDocComments, Vector vector)
    {
        ArgumentListNode argumentList = null;

        for (Iterator<ArrayElementInitializer> iter = vector.getElementInitializerIterator(); iter.hasNext(); )
        {
            ArrayElementInitializer initializer = iter.next();
            if (!initializer.isStateSpecific())
            {
                Node valueExprNode = initializer.generateValueExpr(nodeFactory, configNamespaces, generateDocComments);
                argumentList = nodeFactory.argumentList(argumentList, valueExprNode);
            }
        }

        ApplyTypeExprNode applyTypeExpr =
            AbstractSyntaxTreeUtil.generateApplyTypeExpr(nodeFactory, vector.getElementTypeName());

        return nodeFactory.literalVector(applyTypeExpr, argumentList, 0);
    }

  /**
   *
   */
  private static String fixupXMLString(String orig)
  {
    StringBuilder result = new StringBuilder();

    for (int i = 0; i < orig.length(); i++)
    {
      if (orig.charAt(i) == '\r')
      {
        continue;
      }
      else if (orig.charAt(i) == '\n')
      {
        result.append("\\n");
        continue;
      }
      if (orig.charAt(i) == '\"')
      {
        result.append('\\');
      }
      result.append(orig.charAt(i));
    }

    return result.toString();
  }

  /**
   *
   */
  private String asXmlLiteral(XML component)
  {
    String xml = component.getLiteralXML();
    if (component.getIsE4X())
    {
      return xml;
    }
    else
    {
      StringBuilder buf = new StringBuilder(NameFormatter.toDot(standardDefs.CLASS_XMLUTIL) + ".createXMLDocument(\"");
      buf.append(fixupXMLString(xml));
      buf.append("\").firstChild");
      return buf.toString();
    }
  }

  /**
   *
   */
  private Node asXmlLiteral(NodeFactory nodeFactory, XML component)
  {
    String xml = component.getLiteralXML();
    if (component.getIsE4X())
    {
      LiteralStringNode literalString = nodeFactory.literalString(component.getLiteralXML());
      ListNode list = nodeFactory.list(null, literalString);
      return nodeFactory.literalXML(list, false, -1);
    }
    else
    {
      //StringBuilder buf = new StringBuilder(NameFormatter.toDot(StandardDefs.CLASS_XMLUTIL) + ".createXMLDocument(\"");
      //buf.append(fixupXMLString(xml));
      //buf.append("\").firstChild");
      //return buf.toString();
      MemberExpressionNode base =
        AbstractSyntaxTreeUtil.generateGetterSelector(nodeFactory, standardDefs.getUtilsPackage(), XML_UTIL, false);
      IdentifierNode createXMLDocumentIdentifier = nodeFactory.identifier(CREATE_XML_DOCUMENT, false);
      LiteralStringNode literalString = nodeFactory.literalString(xml);
      ArgumentListNode argumentList = nodeFactory.argumentList(null, literalString);
      CallExpressionNode selector =
        (CallExpressionNode) nodeFactory.callExpression(createXMLDocumentIdentifier,
                                argumentList);
      selector.setRValue(false);
      MemberExpressionNode memberExpression = nodeFactory.memberExpression(base, selector);

      IdentifierNode firstChildIdentifier = nodeFactory.identifier(FIRST_CHILD, false);
      GetExpressionNode getExpression = nodeFactory.getExpression(firstChildIdentifier);
      return nodeFactory.memberExpression(memberExpression, getExpression);
    }
  }

  private static String asXMLList(XMLList component)
  {
    StringBuilder buf = new StringBuilder("<>");
    buf.append(component.getLiteralXML());
    buf.append("</>");
    return buf.toString();
  }

  private static LiteralXMLNode asXMLList(NodeFactory nodeFactory, XMLList component)
  {
    LiteralStringNode literalString = nodeFactory.literalString(component.getLiteralXML());
    ListNode list = nodeFactory.list(null, literalString);
    LiteralXMLNode literalXML = nodeFactory.literalXML(list, false, -1);
    literalXML.is_xmllist = true;
    return literalXML;
  }

  /**
   * NOTE this class should NOT contain Errors or Warnings. This exception is a late-stage patch to replace
   * an intolerably obscure error from generated AS (due to an outstanding bug) with a more specific error,
   * to improve usability while the bug still exists. To be removed when 173905 is fixed.
   */
  public static class DeclaredAndProceduralWithinRepeater extends CompilerMessage.CompilerError
  {
    private static final long serialVersionUID = 5966918771156671871L;
  }

  /**
   * get the comment from the model.
   * @return comment associated with the model.
   */
  public String getComment()
  {
      if(value instanceof Model)
      {
          return ((Model)value).comment;
      }
     
      return null;
  }
 
  public ValueInitializer clone() throws CloneNotSupportedException
  {
        return (ValueInitializer) super.clone();
    }

}
TOP

Related Classes of flex2.compiler.mxml.rep.init.ValueInitializer$DeclaredAndProceduralWithinRepeater

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.