/*
 *
 *  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 macromedia.abc;
import static macromedia.asc.parser.Tokens.EMPTY_TOKEN;
import static macromedia.asc.semantics.Slot.*;

import macromedia.asc.embedding.avmplus.*;
import macromedia.asc.util.*;
import macromedia.asc.parser.*;
import macromedia.asc.semantics.*;
import macromedia.asc.semantics.QName;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;

@SuppressWarnings("nls") // TODO: Remove
public final class AbcParser
{
    private Context ctx;
    private AbcData abcData;
    private static final boolean debug = false;

    public AbcParser(Context cx, String name) throws IOException
    {
        this.ctx = cx;
        this.abcData = new AbcData("");
        this.abcData.readAbc(new BytecodeBuffer(name));
    }

    public AbcParser(Context cx, byte[] bytes)
    {
        this.ctx = cx;
        this.abcData = new AbcData("");
        this.abcData.readAbc(new BytecodeBuffer(bytes));
    }

    private final Map<String, Integer> fun_names = new HashMap<String, Integer>();

    private final ObjectList<ObjectList<ClassDefinitionNode>> clsdefs_sets = new ObjectList<ObjectList<ClassDefinitionNode>>();
    private final ObjectList<String> region_name_stack = new ObjectList<String>();

    // TODO: better dependency analysis - this is used to populate FA's ce_unresolved_sets which
    // TODO: mxml uses to find dependencies - could be done earlier for abcs
    private ObjectList<Set<ReferenceValue>> ce_unresolved_sets = new ObjectList<Set<ReferenceValue>>();

    public ProgramNode parseAbc()
    {
        return parseAbc(false, false);
    }

    // first parameter causes BinaryProgramNode's toplevelDefinitions instance variable to be populated
    // second parameter turns on/off building full ast's - if you suspect an mxmlc problem caused by a lack of
    // ast from ABCs, turn this on to see if it fixes it.
    // if this is false, only BinaryProgramNode, and toplevel definition nodes are created (mostly BinaryClassDefNode).
    // hopefully we can get rid of those someday too.
    // both these parameters are set to true by Flash Authoring and left false by by mxmlc
    public ProgramNode parseAbc(boolean collectTopLevel, boolean buildASTForClasses)
    {
        try
        {
            // Create a program node that will represent the data in the abc file.
            // It won't actually be a parse tree, but it will contain the correct builder
            // objects which are usually built up by the FlowAnalyzer
            
            BinaryProgramNode program = ctx.getNodeFactory().binaryProgram(ctx, ctx.getNodeFactory().statementList(null, (StatementListNode)null));
            GlobalBuilder b = new GlobalBuilder();
            b.is_in_package = true; // cn: necessary for proper slot creation for top level functions
            program.frame = new ObjectValue(ctx, b, ctx.noType());
			ctx.pushScope(program.frame);
            clsdefs_sets.add(new ObjectList<ClassDefinitionNode>());
            ce_unresolved_sets.push_back(program.ce_unresolved);
            region_name_stack.push_back("");
            
            for( int i = 0; i < this.abcData.getScriptInfoSize(); ++i )
            {
                parseScript(i, program, collectTopLevel, buildASTForClasses);
            }

            program.clsdefs = clsdefs_sets.last();
    		clsdefs_sets.removeLast();
            ce_unresolved_sets.removeLast();
            region_name_stack.pop_back();
            ctx.popScope(); // global
            
			// For proper const and type enforcement of top level functions and vars, we need to 
			//  process those def nodes during CE.  These definitions need to be evaluated in the
			//  scope of the BinaryProgramNode's frame.
            // Conversely, class definition nodes are maintained in the clsdefs list rather than ever
            // being added to the binary program node's statement list. This is so that they get processed outside the 
            // BinaryProgramNode's frame...
            
            // {pmd} following builds <ProgramNode <StatementList <BinaryProgramNode ...>>>
            // {pmd} I wondered why? --probably to match some undefined visitor pattern behavior...
            
            ProgramNode prog = ctx.getNodeFactory().program(ctx, ctx.getNodeFactory().statementList(null, program));

            // Uncomment next line to get some debugging info to print to stdout.
            // {pmd} ??? for this to be useful it really should iterate the clsdefs list...(and print the objectvalue hierarchy too.)
            // dumpProgram(program);

            return prog;
        }
        catch(Exception t)
        {
        	if(debug) t.printStackTrace();
            // Clean up any scope we may have pushed and didn't pop when the exception was thrown
            ObjectValue scope = ctx.scope();
            ObjectValue global = ctx.globalScope();
            while( scope != global )
            {
                ctx.popScope();
                scope = ctx.scope();
            }
            return null;
        }
    }

    static private class DefAndSlot
    {
        public DefinitionNode def;
        public Slot slot;
    }

    /**
     * Returns a TypeValue for the qname specified by typeID.  If that type does not exist yet
     * a new placeholder TypeValue is created and returned.  The placeholder will be filled in later when
     * we actually see that type.  This allows us to avoid any forward reference problems when parsing an ABC
     * @param typeID the index of the QName we want the TypeValue for
     * @return the TypeValue representing the type specifed by typeID.
     */
    private TypeValue getTypeFromQName(int typeID)
    {
        if( typeID == 0 )
            return ctx.noType();

        QName typename = getFullName(getBinaryMNFromCPool(typeID));

        if( ctx.isBuiltin(typename.toString()) )
            return ctx.builtin( typename.toString() );

        TypeValue type = TypeValue.getTypeValue(ctx, typename);
        if( !type.resolved )
            ce_unresolved_sets.last().add(new ReferenceValue(ctx, null, typename.name, typename.ns));

        return TypeValue.getTypeValue(ctx, typename);

    }

    private DefAndSlot slotTrait(String name, ObjectValue ns, int slotID, int typeID, int valueID, int value_kind, boolean is_const, boolean build_ast)
    {
        ObjectValue obj = ctx.scope();
        DefAndSlot ret = new DefAndSlot();
        Namespaces nss = new Namespaces();
        nss.push_back(ns);
                
        TypeValue type = getTypeFromQName(typeID);
        
        int var_id = obj.builder.Variable(ctx, obj);
        int slot_id = obj.builder.ExplicitVar(ctx,obj,name,nss,type,-1,-1,var_id);

        Slot slot = obj.getSlot(ctx,slot_id);
		slot.setConst(is_const);
		slot.setImported(true);

        ret.slot = slot;

        IdentifierNode id=null;
        AttributeListNode attr=null;

        if( build_ast )
        {
            id = identifierNode(name, ns);
            attr = attributeList(false, false, false, ns, obj.builder);
        }
        if( value_kind == ActionBlockConstants.CONSTANT_Namespace )
        {
            ObjectValue nsValue = getNamespace(valueID);
            slot.setObjectValue(nsValue);
			slot.setConst(true);

            if( build_ast )
                ret.def = ctx.getNodeFactory().namespaceDefinition(attr, id, ctx.getNodeFactory().literalString(nsValue.name));

            return ret;
        }
        if( valueID != 0)
            slot.setObjectValue(getInitValue(valueID, value_kind));
        
        if( build_ast )
        {
	        MemberExpressionNode typeExpr = null;
	        if( typeID != 0 )
	        {
	            AbcData.BinaryMN t = getBinaryMNFromCPool(typeID);
	            typeExpr = memberExprFromMN(t);
	        }

	        Node init = getInitValueNode(valueID,value_kind);     // (0,0) means undefined
	        TypedIdentifierNode ty = ctx.getNodeFactory().typedIdentifier(id, typeExpr);
	        int tok = is_const ? Tokens.CONST_TOKEN : Tokens.VAR_TOKEN;
	        VariableBindingNode bind = ctx.getNodeFactory().variableBinding(attr, tok, ty, init);

	        bind.ref = id.ref;
	        if( typeExpr != null )
	        {
	            bind.typeref = typeExpr.ref;
	        }

	        ret.def = (DefinitionNode) ctx.getNodeFactory().variableDefinition(attr, tok, ctx.getNodeFactory().list(null, bind));
        }
        return ret;
    }

    private MemberExpressionNode memberExprFromMN(AbcData.BinaryMN mn)
    {
        MemberExpressionNode typeExpr = null;
        QName typeName = getFullName(mn);
        NodeFactory nf = ctx.getNodeFactory();
        
        if( typeName instanceof ParameterizedName )
        {
            ParameterizedName pn = (ParameterizedName)typeName;
            IdentifierNode baseIdNode = identifierNode(pn.name, pn.ns);
            MemberExpressionNode param_node = memberExprFromMN(getBinaryMNFromCPool(mn.params[0]));
            ListNode list = nf.list(null, param_node);
            Node apply = nf.applyTypeExpr(baseIdNode, list, -1);
            typeExpr = nf.memberExpression(null, (SelectorNode)apply);
            typeExpr.ref = baseIdNode.ref;
            typeExpr.ref.addTypeParam(param_node.ref);
        }
        else
        {
            IdentifierNode typeIdNode = identifierNode(typeName.name, typeName.ns);
            GetExpressionNode getNode = nf.getExpression(typeIdNode);
            typeExpr = nf.memberExpression(null, getNode);
            typeExpr.ref = typeIdNode.ref;
        }
        return typeExpr;
    }
    
    /**
     *  Creates an identifier node, and fills in the ref with the correct reference value
     * @param simpleName
     * @param ns
     * @return IdentifierNode
     */
    private IdentifierNode identifierNode(String simpleName, ObjectValue ns)
    {
        IdentifierNode id = ctx.getNodeFactory().identifier(simpleName);
        //IdentifierNode will clean this up
        id.ref = new ReferenceValue(ctx, null, id.name, ns);
        return id;
    }

    private DefAndSlot methodTrait(String methodName, ObjectValue ns, int dispID, int methInfo, int attrs, int kind, boolean build_ast)
    {
        ObjectValue obj = ctx.scope();
        DefAndSlot ret = new DefAndSlot();
        boolean isFinal = (attrs & ActionBlockConstants.TRAIT_FLAG_final) != 0;
        boolean isOverride = (attrs & ActionBlockConstants.TRAIT_FLAG_override) != 0;
        Namespaces names = new Namespaces(ns);
        int method_id = obj.builder.Method(ctx,obj,methodName,names,false);
        int method_slot;
        NodeFactory nf = ctx.getNodeFactory();

        // Create the right type of method based on what kind it is.  Either a setter, getter, or regular method
        switch(kind)
        {
        case ActionBlockConstants.TRAIT_Setter: //Set property
            method_slot = obj.builder.ExplicitSet(ctx,obj,methodName,names,ctx.noType(),isFinal,isOverride,-1,method_id,-1);
            break;
            
        case ActionBlockConstants.TRAIT_Getter: //get property
            method_slot = obj.builder.ExplicitGet(ctx,obj,methodName,names,ctx.noType(),isFinal,isOverride,-1,method_id,-1);
            break;
            
        default: // regular method
            method_slot = obj.builder.ExplicitCall(ctx,obj,methodName,names,ctx.noType(),isFinal,isOverride,-1,method_id,-1);
            break;
        }

        ObjectValue funcObj = getFunctionObject();
        Slot slot = obj.getSlot(ctx, method_slot);
        slot.setValue(funcObj);
		slot.setImported(true);

        // Calculate the internal name - this matter because with get/set properties you can end up with
        // multiple methods with the same name, but they must each have different internal names.
        StringBuilder internal_name = new StringBuilder(methodName.length() + 5);
        if( !fun_names.containsKey(methodName) )
        {
            fun_names.put(methodName,0);
        }
        internal_name.append(methodName).append('$');
        int num = fun_names.get(methodName);
        internal_name.append(num);
        num++;
        fun_names.put(methodName, num);

        int slot_id = obj.getImplicitIndex(ctx,method_slot,Tokens.EMPTY_TOKEN);
        Slot implied_slot = obj.getSlot(ctx, slot_id);
		implied_slot.setImported(true);

	    String n = internal_name.toString();
        implied_slot.setMethodName(n);//node->fexpr->internal_name;
        ret.slot = implied_slot;

        // Make sure the FunctionBuilder gets cleaned up
        int functionKind;
        switch( kind )
        {
            case ActionBlockConstants.TRAIT_Getter:
                functionKind = Tokens.GET_TOKEN;
                break;
            case ActionBlockConstants.TRAIT_Setter:
                functionKind = Tokens.SET_TOKEN;
                break;
            default:
                functionKind = Tokens.EMPTY_TOKEN;
                break;
        }

        // Come up with the function signature
        AbcData.Method m_info = this.abcData.getMethod(methInfo);

        int returnTypeID = m_info.getReturnType();
        int paramTypeIDs[] = m_info.getParamTypes();
        int paramCount = paramTypeIDs.length;
        ObjectList<Node> optional_nodes = null;
        int optional_count = 0;
        if( m_info.getHasOptional()  )
        {
            if( build_ast )
            {
                optional_nodes = parseOptionalParams(m_info);
            }
            optional_count = m_info.getOptionalParamTypes().length;
        }
        String[] param_names = m_info.getParamNames();

        // Set return type
        implied_slot.setType(getTypeFromQName(returnTypeID).getDefaultTypeInfo());

        ParameterListNode paramList = null;

        ObjectList<TypeInfo> param_types = new ObjectList<TypeInfo>(paramCount);
        ByteList decl_styles = new ByteList(1);

        for( int i = 0, cur_optional = 0; i < paramCount; ++i )
        {
            ParameterNode param = null;
            if( build_ast )
            {
                AbcData.BinaryMN typeMN = null;
                if( paramTypeIDs[i] != 0 )
                {
                    typeMN = getBinaryMNFromCPool(paramTypeIDs[i]);
                    // getFullName(typeMN); // for effect
                }

                String simple_param_name = i < param_names.length && param_names[i] != null ? param_names[i] : ("param" + (i+1)).intern();
                param = parameterNode(simple_param_name, typeMN);

                paramList = nf.parameterList(paramList, param);
            }

            param_types.push_back(getTypeFromQName(paramTypeIDs[i]).getDefaultTypeInfo());

            if( i >= paramCount - optional_count )
            {
                if( build_ast )
                    param.init = optional_nodes.get(cur_optional++);
                decl_styles.push_back((byte) Slot.PARAM_Optional);
            }
            else
            {
                decl_styles.push_back((byte) Slot.PARAM_Required);
            }
        }
 
        if( m_info.getNeedsRest() )
        {
            if( build_ast )
            {
                ParameterNode param = parameterNode("rest", ctx.arrayType().name);
                RestParameterNode restNode = ctx.getNodeFactory().restParameter(param , -1);
                restNode.ref = param.ref;
                restNode.typeref = param.typeref;
                paramList = nf.parameterList(paramList, restNode);

                // rsun 11.22.05 porting over a fix made to the 8ball_AS3 branch a long time
                // ago, but only to the C++ compiler. has_rest needs to be reset here since
                // MovieClipMaker is a special entry point that creates function nodes itself.
                // otherwise, has_rest is unnecessarily true for all functions processed after
                // this.
                ctx.getNodeFactory().has_rest = false;
            }

            param_types.push_back(ctx.arrayType().getDefaultTypeInfo());
            decl_styles.push_back((byte) Slot.PARAM_Rest);
        }

        if( param_types.size() > 0 )
        {
            implied_slot.setTypes(param_types);
            implied_slot.setDeclStyles(decl_styles);
        }
        else
        {
            param_types.push_back(ctx.voidType().getDefaultTypeInfo());
            implied_slot.setTypes(param_types);
            implied_slot.addDeclStyle(Slot.PARAM_Void);
        }

        if( build_ast )
        {
            MemberExpressionNode retTypeNode = null;
            if( returnTypeID != 0 )
            {
                AbcData.BinaryMN retMN = getBinaryMNFromCPool(returnTypeID);
                retTypeNode = memberExprFromMN(retMN);
            }
            FunctionSignatureNode fsn = nf.functionSignature(paramList,retTypeNode);
            if( retTypeNode != null )
            {
                fsn.typeref = retTypeNode.ref;
            }

            IdentifierNode id = identifierNode(methodName,ns);
            FunctionCommonNode fcn = nf.functionCommon(ctx, id, fsn, null);
            fcn.kind = functionKind;
            fcn.ref = id.ref;

            FunctionNameNode fn = nf.functionName(functionKind, id);
            AttributeListNode attr = attributeList(isFinal, isOverride, false, ns, obj.builder);
            FunctionDefinitionNode fdn = nf.binaryFunctionDefinition(ctx, attr, fn, fcn, -1);

            ret.def = fdn;
        }
        return ret;
    }

    private static ObjectValue dummyFunc = null;

    /**
     * Helper so we only allocate 1 ObjectValue to represent a method, instead
     * of 1 for each method.  This is safe because the OV is only used as the value
     * of a MethodSlot, and we only ever check for the existance of the value, never anything else
     * @return an ObjectValue that can be used for a function object
     */
    private ObjectValue getFunctionObject()
    {
        if( dummyFunc == null )
            dummyFunc = new ObjectValue(ctx,new FunctionBuilder(),ctx.functionType());

        return dummyFunc;
    }

    private Node getInitValueNode(int valueID,int kind)
    {
        Node t;
        NodeFactory nf = ctx.getNodeFactory();
        
        switch (kind)
        {
            case ActionBlockConstants.CONSTANT_Void:
                t = nf.unaryExpression(Tokens.VOID_TOKEN,nf.literalNumber("0",-1),-1);
                break;
                
            case ActionBlockConstants.CONSTANT_Integer:
            case ActionBlockConstants.CONSTANT_UInteger:
            case ActionBlockConstants.CONSTANT_Double:
                double val = getNumberFromCPool(valueID, kind);
                t = nf.literalNumber(String.valueOf(val));
                break;
                
            case ActionBlockConstants.CONSTANT_Decimal:
            	Decimal128 dval = getDecimalFromCPool(valueID);
            	String sval = dval.toString();
            	if (ctx.statics.es4_numerics)
            		sval += "m";
            	t = nf.literalNumber(sval);
            	break;
            
            case ActionBlockConstants.CONSTANT_True:
                t = nf.literalBoolean(true);
                break;
                
            case ActionBlockConstants.CONSTANT_False:
                t = nf.literalBoolean(false);
                break;
                
            case ActionBlockConstants.CONSTANT_Utf8:
                t = nf.literalString(getStringFromCPool(valueID));
                break;
                
            case ActionBlockConstants.CONSTANT_Null:
                t = nf.literalNull();
                break;
                
            case ActionBlockConstants.CONSTANT_Namespace:
                ObjectValue ns = getNamespace(valueID);
                t = nf.literalString(ns.name);
                break;
                
            default:
                t = nf.literalString("");
                break;
        }
        return t;
    }

    private ObjectValue getInitValue(int valueID,int kind)
    {
        ObjectValue ov;
        switch (kind)
        {
            case ActionBlockConstants.CONSTANT_Void:
                ov = ctx.voidType().prototype;
                break;

            case ActionBlockConstants.CONSTANT_Integer:
                double intval = getNumberFromCPool(valueID, kind);
                ov = new ObjectValue(String.valueOf(intval), ctx.intType());
                break;
            case ActionBlockConstants.CONSTANT_UInteger:
                double uintval = getNumberFromCPool(valueID, kind);
                ov = new ObjectValue(String.valueOf(uintval), ctx.uintType());
                break;
            case ActionBlockConstants.CONSTANT_Double:
                double val = getNumberFromCPool(valueID, kind);
                ov = new ObjectValue(String.valueOf(val), ctx.doubleType());
                break;

            case ActionBlockConstants.CONSTANT_Decimal:
            	Decimal128 dval = getDecimalFromCPool(valueID);
            	String sval = dval.toString();
            	if (ctx.statics.es4_numerics)
            		sval += "m";
            	ov = new ObjectValue(sval, ctx.decimalType());
            	break;

            case ActionBlockConstants.CONSTANT_True:
                ov = ctx.booleanTrue();
                break;

            case ActionBlockConstants.CONSTANT_False:
                ov = ctx.booleanFalse();
                break;

            case ActionBlockConstants.CONSTANT_Utf8:
                ov = new ObjectValue(getStringFromCPool(valueID), ctx.stringType());
                break;

            case ActionBlockConstants.CONSTANT_Null:
                ov = ctx.nullType().prototype;
                break;

            case ActionBlockConstants.CONSTANT_Namespace:
                ObjectValue ns = getNamespace(valueID);
                ov = ns;
                break;

            default:
                ov = null;
                break;
        }
        return ov;
    }

    private ObjectList<Node> parseOptionalParams(AbcData.Method method_info)
    {
        int[] optional_values = method_info.getOptionalParamTypes();
        int[] optional_kinds = method_info.getOptionalParamKinds();
        
        ObjectList<Node> optionals = new ObjectList<Node>(optional_values.length);
        for( int i = 0; i < optional_values.length; ++i)
        {
            int value_index = optional_values[i];
            int value_kind =  optional_kinds[i];
            Node current_node = getInitValueNode(value_index,value_kind);
            optionals.push_back(current_node);
        }
        return optionals;
    }


    private ParameterNode parameterNode(String simpleParamName, QName typeName)
    {
        IdentifierNode id = identifierNode(simpleParamName, ctx.publicNamespace());
        IdentifierNode ty = null;
        MemberExpressionNode paramType = null;
        
        if( typeName != null )
        {
            ty = identifierNode(typeName.name, typeName.ns);
            GetExpressionNode getNode = ctx.getNodeFactory().getExpression(ty);
            paramType = ctx.getNodeFactory().memberExpression(null, getNode);
        }
        ParameterNode param = ctx.getNodeFactory().parameter(Tokens.VAR_TOKEN, id, paramType);
        if( ty != null )
        {
            param.typeref = ty.ref;
        }
        param.ref = id.ref;

        return param;
    }

    private ParameterNode parameterNode(String simpleParamName, AbcData.BinaryMN typeMN)
    {
        IdentifierNode id = identifierNode(simpleParamName, ctx.publicNamespace());

        MemberExpressionNode paramType = null;
        if( typeMN != null )
        {
            paramType = memberExprFromMN(typeMN);
        }
        ParameterNode param = ctx.getNodeFactory().parameter(Tokens.VAR_TOKEN, id, paramType);
        if( paramType != null )
        {
            param.typeref = paramType.ref;
        }        
        param.ref = id.ref;

        return param;
    }

    private AttributeListNode attributeList(boolean isFinal, boolean isOverride, boolean isDynamic, ObjectValue ns, Builder builder)
    {
        AttributeListNode attr = ctx.getNodeFactory().attributeList(ctx.getNodeFactory().literalString(""), null);

        attr.hasFinal = isFinal;
        attr.hasOverride = isOverride;
        attr.hasDynamic = isDynamic;

        if( builder instanceof ClassBuilder ) //Statics are built by classbuilder, non statics by instancebuilder
        {
            attr.hasStatic = true;
        }
        if ( ns == null )
        	return attr;
        
        if( ns == ctx.publicNamespace() || (ns.getNamespaceKind() == Context.NS_PUBLIC && ns.isPackage()) )
        {
            // Only package public namespaces will have been qualified with the 'public' access specifier
            // user defined namespaces may also be public namespaces in the cpool, but they will not be package namespaces
            attr.hasPublic = true;
        }
        else if( ns.isInternal() )
            attr.hasInternal = true;
        else if( ns.isProtected() )
            attr.hasProtected = true;
        else if( ns.isPrivate() )
            attr.hasPrivate = true;
        else
        {
            if( builder.classname != null && ns == builder.classname.ns)
                attr.hasPublic = true;
            else
                attr.namespaces.add(ns);
        }
        return attr;
    }
    
    // Utility to get the full name based on a qname (ns + "/" + name)
    private QName getFullName(AbcData.BinaryMN mn)
    {
        if( mn.kind == ActionBlockConstants.CONSTANT_TypeName )
        {
            AbcData.BinaryMN base = getBinaryMNFromCPool(mn.baseMN);
            QName base_qn = getFullName(base);
            ObjectList<QName> params = new ObjectList<QName>(mn.params.length);
            
            for( int i = 0; i < mn.params.length; ++i) {
                params.add(getFullName(getBinaryMNFromCPool(mn.params[i])));
            }
            ParameterizedName pn = new ParameterizedName(params, base_qn.ns, base_qn.name);
            return pn;
        }
        else
        {
            assert (mn.nsIsSet != true):"expected a single namespace";

            String fullName = getStringFromCPool(mn.nameID);
            ObjectValue ns = getNamespace(mn.nsID);
            return ctx.computeQualifiedName("", fullName, ns, EMPTY_TOKEN);
        }
    }

    private DefAndSlot classTrait(String className, ObjectValue ns, int slotID, int classID, boolean build_ast)
    {
        if( classID >= this.abcData.getClassInfoSize() || classID < 0 )
            return null;

        DefAndSlot ret = new DefAndSlot();
        ObjectValue current_scope = ctx.scope();
        
        String region_name = region_name_stack.back();
        if( region_name.length() > 0 )
        {
            region_name += "/";
            ns = ctx.getNamespace(region_name + ns.name);
        }
 
        NodeFactory nf = ctx.getNodeFactory();

        // Instance info
        AbcData.InstanceInfo iinfo = this.abcData.getInstanceInfo(classID);

        AbcData.BinaryMN instanceMN = getBinaryMNFromCPool(iinfo.getInstanceNameID());
        QName fullName = getFullName(instanceMN);
        String fullNameString = fullName.toString();

        int superID = iinfo.getSuperID();
        boolean hasSuper = superID != 0;
        QName superName = null;
        String simpleSuperName ="";
        ObjectValue superNamespace = null;
        if( hasSuper )
        {
            AbcData.BinaryMN superMN = getBinaryMNFromCPool(superID);
            
            assert (superMN.nsIsSet != true):"expected a single namespace";
            
            superNamespace = getNamespace(superMN.nsID);
            superName = getFullName(superMN);
            simpleSuperName = getStringFromCPool(superMN.nameID);
        }

        int flags = iinfo.getFlags();

        int[] interfaces = iinfo.getInterfaces();
        ListNode interface_nodes = null;
		if(debug&&interfaces.length>0) System.out.println("parsing " + interfaces);
        for( int i = 0; i < interfaces.length; ++i )
        {
            int int_index = interfaces[i];
            AbcData.BinaryMN intMN = getBinaryMNFromCPool(int_index);
			String simpleIntName = getStringFromCPool(intMN.nameID);
			Namespaces intNamespaces;
			if(intMN.nsIsSet)
				intNamespaces = getNamespaces(intMN.nsID);
			else {
				intNamespaces = new Namespaces(1); 
				intNamespaces.add(getNamespace(intMN.nsID));
			}
		
            IdentifierNode ident = nf.identifier(simpleIntName);

            ident.ref = new ReferenceValue(ctx, null, simpleIntName, intNamespaces);
            GetExpressionNode getNode = nf.getExpression(ident);
            MemberExpressionNode interface_node = nf.memberExpression(null, getNode);
            interface_node.ref = ident.ref;
            interface_nodes = nf.list(interface_nodes, interface_node);
            interface_nodes.values.push_back(ident.ref);
        }

        boolean isFinal = (flags & ActionBlockConstants.CLASS_FLAG_final) != 0;
        boolean isDynamic = ( flags & ActionBlockConstants.CLASS_FLAG_sealed ) == 0;
        boolean isInterface = (flags & ActionBlockConstants.CLASS_FLAG_interface) != 0;
 
        ClassDefinitionNode cdn = null;
        IdentifierNode idNode = nf.identifier(className);
        idNode.ref = new ReferenceValue(ctx, null, idNode.name, ns);
        
        AttributeListNode attr = attributeList(isFinal, false, isDynamic, ns, current_scope.builder);
        StatementListNode stmtList = nf.statementList(null, (StatementListNode)null);
        
        if (isInterface)
        {
        	cdn = nf.binaryInterfaceDefinition(ctx, attr, idNode, null, stmtList);
        }
        else
        {
        	cdn = nf.binaryClassDefinition(ctx, attr, idNode, null, stmtList);
        }
        cdn.ref = idNode.ref;
        cdn.interfaces = interface_nodes;
        cdn.public_namespace = ctx.publicNamespace();
        cdn.protected_namespace = ctx.getNamespace(fullNameString, Context.NS_PROTECTED);
        cdn.static_protected_namespace = ctx.getNamespace(fullNameString, Context.NS_STATIC_PROTECTED);
        cdn.private_namespace = ctx.getNamespace(fullNameString, Context.NS_PRIVATE);
        cdn.default_namespace = ctx.getNamespace(fullName.ns.name, Context.NS_INTERNAL);

        boolean is_builtin = ctx.isBuiltin(fullNameString);
        TypeValue cframe;
        ObjectValue iframe;
        if( is_builtin )
        {
            cframe = ctx.builtin(fullNameString);
            iframe = cframe.prototype;
        }
        else
        {
        	ClassBuilder cb = new ClassBuilder(fullName,cdn.protected_namespace,cdn.static_protected_namespace);
            cframe = TypeValue.defineTypeValue(ctx,cb,fullName,RuntimeConstants.TYPE_object);
            
            InstanceBuilder ib = new InstanceBuilder(fullName);
            ib.canEarlyBind = false;
            iframe = new ObjectValue(ctx,ib,cframe);
            cframe.prototype = iframe;
           
            cdn.debug_name = fullNameString;
            // Make sure the ClassBuilder and InstanceBuilders get cleaned up
            cdn.owns_cframe = true;
        }
        cdn.cframe = cframe;
        cdn.iframe = iframe;

        if( isInterface )
        {
            ((ClassBuilder)cframe.builder).is_interface = true;
        }
        cframe.builder.is_dynamic = iframe.builder.is_dynamic = isDynamic;
        cframe.builder.is_final = iframe.builder.is_final = isFinal;

        clsdefs_sets.last().add(cdn);

        if( hasSuper )
        {
            TypeValue superType;
            cdn.baseclass = nf.literalString(superName.toString(), -1);
            if( ctx.isBuiltin(superName.toString()) )
            {
                // Set the super type, this important for int/uint which derive from Number
                superType = ctx.builtin(superName.toString());
                cframe.baseclass = superType;
                cdn.baseref = new ReferenceValue(ctx, null, superName.toString(), ctx.publicNamespace());
            }
            else
            {
                //cdn.baseclass = nf.literalString(superName.toString(), -1);
                cdn.baseref = new ReferenceValue(ctx, null, simpleSuperName, superNamespace);
                cdn.baseref.getSlot(ctx);

                cframe.baseclass = getTypeFromQName((int)superID) ;
            }
        }
        else if (cdn.cframe != ctx.objectType())
		{
				cdn.baseclass = nf.memberExpression(null, nf.getExpression(nf.identifier("Object")));
				cframe.baseclass = ctx.objectType();
		}
        else
        {
            cdn.baseclass = null;
            cframe.baseclass = null;
		}

        int var_id  = current_scope.builder.Variable(ctx,current_scope);
        int slot_id  = current_scope.builder.ExplicitVar(ctx,current_scope,className,ns,ctx.typeType(),-1,-1,var_id);
        Slot slot = current_scope.getSlot(ctx,slot_id);
        slot.setObjectValue(cframe);
		slot.setImported(true);
		slot.setConst(true);		// all class definitions are const.

        ret.slot = slot;

        current_scope.builder.ImplicitCall(ctx,current_scope,slot_id,cframe,CALL_Method,-1,-1);
		current_scope.builder.ImplicitConstruct(ctx,current_scope,slot_id,cframe,CALL_Method,-1,-1);

        if( isInterface )
        {
            ((ClassBuilder)cframe.builder).is_interface = true;
            slot.setImplNode(cdn);
        }

        clsdefs_sets.add(new ObjectList<ClassDefinitionNode>());

        region_name_stack.push_back(fullNameString);
        
        ctx.pushStaticClassScopes(cdn); // class
        {
        	ctx.pushScope(iframe); // instance
        	{
        		StatementListNode instance_stmts = nf.statementList(null, (StatementListNode)null);
        		parseTraits(iinfo.getITraits(), instance_stmts, build_ast, null, build_ast); // Traits for the instance
        		cdn.instanceinits = new ObjectList<Node>(instance_stmts.items.size());
        		if( instance_stmts.items.size() > 0)
        		{
        			cdn.instanceinits.addAll(instance_stmts.items);
        		}
        		// Add nodes for the constructor, which doesn't have a traits entry.
        		DefAndSlot d = methodTrait("$construct", ctx.publicNamespace(),0,iinfo.getInitIndex(),0,0, build_ast);
        		DefinitionNode iinit_node = d.def;
                if( build_ast )
        		    cdn.instanceinits.add(iinit_node);

                int implied_idx = current_scope.getImplicitIndex(ctx, slot_id, Tokens.NEW_TOKEN);
                Slot class_slot = current_scope.getSlot(ctx, implied_idx);
                if( class_slot != null)
                {
                    //class_slot.setType(d.slot.getType());
                    class_slot.setTypes(d.slot.getTypes());
                    class_slot.setDeclStyles(d.slot.getDeclStyles());
                }
        	}
        	ctx.popScope(); // instance

        	AbcData.ClassInfo cinfo = this.abcData.getClassInfo(classID);
        	parseTraits(cinfo.getCTraits(), cdn.statements, build_ast, null, build_ast); // Traits for the class (statics)
        }
        ctx.popStaticClassScopes(cdn); //class

        clsdefs_sets.removeLast();
        region_name_stack.pop_back();

        ret.def = cdn;
        return ret;
    }

    // parsetraits - if prog is non-null we will populate prog.toplevelDefinitions
    private void parseTraits(AbcData.Trait[] traits, StatementListNode statements, boolean build_ast, BinaryProgramNode prog, boolean buildASTForClasses)
    {
        for (AbcData.Trait t: traits)
        {   
			AbcData.BinaryMN mn = getBinaryMNFromCPool(t.getNameIndex());
			String name = getStringFromCPool(mn.nameID);
            ObjectValue ns;
            ns = getNamespaceFromMultiname(mn);

            DefAndSlot d = null;
            switch (t.getTag()) 
            {
            case ActionBlockConstants.TRAIT_Var:
            case ActionBlockConstants.TRAIT_Const:
			    d = slotTrait(name, ns, t.getSlotId(), t.getTypeName(), t.getValueIndex(), t.getValueKind(), t.isConstTrait(), build_ast);
                if( build_ast )
                    statements.items.add(d.def);

                if( prog != null )
                    prog.toplevelDefinitions.add(new QName(ns, name));

                break;
                
            case ActionBlockConstants.TRAIT_Method:
            case ActionBlockConstants.TRAIT_Getter:
            case ActionBlockConstants.TRAIT_Setter:
				d = methodTrait(name, ns, t.getDispId(), t.getMethodId(), t.getAttrs(), t.getTag(), build_ast);
				if( build_ast )
					statements.items.add(d.def);

                if( prog != null )
                    prog.toplevelDefinitions.add(new QName(ns, name));

                break;
                
            case ActionBlockConstants.TRAIT_Class:
				d = classTrait(name, ns, t.getSlotId(), t.getClassId(), buildASTForClasses);

                if( prog != null )
                    prog.toplevelDefinitions.add(new QName(ns, name));

                break;
                
            case ActionBlockConstants.TRAIT_Function: // currently unused
                break;
                
            default:
                break;
                //throw new DecoderException("Invalid trait kind: " + kind);
            }
            
            if( t.hasMetadata() && d!= null )
            {
                int[] metadata = t.getMetadata();
                for( int metaIndex: metadata )
                {   
                    MetaDataNode metaNode = parseMetadataInfo(metaIndex);
                    	
                	if ( d.def != null ){
                		metaNode.def = d.def;
                		d.def.addMetaDataNode(metaNode);
						if( build_ast )
                			statements.items.add(metaNode); //{pmd} now hasn't this just been hung off the def node? yup, but fails if not here too.
                	}
       
                	if( d.slot != null )
                	{
                		String md_id = metaNode.getId();
                		if( (MetaDataEvaluator.GO_TO_CTOR_DEFINITION_HELP != md_id) &&
                			(MetaDataEvaluator.GO_TO_DEFINITION_HELP != md_id)  ) // Should be ok since the cpool entries are interned
                		{
                			// Don't add the go_to_def metadata - its never needed by the compiler (its just a hint for tools)
                			// and it takes up a ton of memory if we add it.
                			//??? Used to only add 'deprecated' metadata...???ask Erik whats up here?
                			d.slot.addMetadata(metaNode);
                		}
                	}
                }
            }
        }
    }

    /**
     * Extract a namespace from a multiname.
     * @param mn - the multiname. It should only have one namespace if it's a set.
     * @return the multiname's namespace.
     */ 
    private ObjectValue getNamespaceFromMultiname(AbcData.BinaryMN mn)
    {
        ObjectValue ns;
        if( mn.nsIsSet )
        {
            Namespaces ns_set = getNamespaces(mn.nsID);
			if (ns_set.size() > 1) {       // they should all have the same URI modulo version maker
				ns = null;
				for (ObjectValue t : ns_set) {
					if (ns == null || t.name.length() < ns.name.length()) {
						ns = t; // the unmarked uri is always the shortest, so return it
					}
				}
			}
			else {
				ns = ns_set.at(0);
			}
        }
        else
        {
            ns = getNamespace(mn.nsID);
        }
        return ns;
    }

    private void parseScript(int scriptIndex, BinaryProgramNode program, boolean collectTopLevel, boolean buildASTForClasses)
    {
        if( scriptIndex < 0 || scriptIndex >= this.abcData.getScriptInfoSize() )
        {
            return;
        }
        
        AbcData.ScriptInfo s = this.abcData.getScriptInfo(scriptIndex);
		// at top level always want to set build_ast param to true
        parseTraits(s.getScriptTraits(), program.statements, true, collectTopLevel ? program : null, buildASTForClasses);
    }
    
    
    private MetaDataNode parseMetadataInfo( int index )
    { 
        //  TODO: Cache this data more aggressively.
        MetaDataNode metaNode = ctx.getNodeFactory().metaData(null, -1);
        metaNode.setMetadata(this.abcData.getMetadata(index, metaNode));
        return metaNode;
    }

        
    
    private String getStringFromCPool(int id)
    {
    	return this.abcData.getString(id);
    }

    private Decimal128 getDecimalFromCPool(int id) 
    {
    	return this.abcData.getDecimal(id);
    }
    
    private double getNumberFromCPool(int id, int kind)
    {
        double ret = 0.0;
        switch(kind)
        {
            case ActionBlockConstants.CONSTANT_Integer:
            	ret = this.abcData.getInt(id);
            	return ret;

            case ActionBlockConstants.CONSTANT_UInteger:
            	ret = this.abcData.getUint(id) & 0xFFFFFFFFL;
            	return ret;

            case ActionBlockConstants.CONSTANT_Double:
                ret = this.abcData.getDouble(id);
                return ret;
        }
        // {pmd} silent fail here...is this really a good idea?
        return ret;
    }


    private AbcData.BinaryMN getBinaryMNFromCPool(int index)
    {
        return this.abcData.getName(index);
    }

    Namespaces getNamespaces(int namespaceSetID)
    {
        int[] ns_ids = this.abcData.getNamespaceSet(namespaceSetID).getNamespaceIds();
        Namespaces val = new Namespaces(ns_ids.length);
        for(int i = 0; i < ns_ids.length; ++i)
        {
            val.add(getNamespace(ns_ids[i]));
        }
        return val;
    }

    ObjectValue getNamespace(int namespaceID)
    {
        ObjectValue ns = null;
        if( namespaceID == 0 )
        {
            ns = ctx.anyNamespace();
        }
        else
        {
            int kind = this.abcData.getNamespace(namespaceID).nsKind;
            String uri = this.abcData.getNamespace(namespaceID).getName();
            int ver = -1;
            byte ns_kind;
            
            switch(kind)
            {
            case ActionBlockConstants.CONSTANT_Namespace:
                //vers.add(getVersion(uri));
                ns_kind = Context.NS_PUBLIC;
                ns = ctx.getNamespace(uri);
                break;
            case ActionBlockConstants.CONSTANT_PackageNamespace:
                //vers.add(getVersion(uri));
                ns_kind = Context.NS_PUBLIC;
                ns = ctx.getNamespace(uri);
                ns.setPackage(true);
                break;
            case ActionBlockConstants.CONSTANT_ProtectedNamespace:
                ns_kind = Context.NS_PROTECTED;
                ns = ctx.getNamespace(uri, ns_kind);
                break;
            case ActionBlockConstants.CONSTANT_PackageInternalNs:
                ns_kind = Context.NS_INTERNAL;
                ns = ctx.getNamespace(uri, ns_kind);
                break;
            case ActionBlockConstants.CONSTANT_PrivateNamespace:
                ns_kind = Context.NS_PRIVATE;
                ns = ctx.getNamespace(uri, ns_kind);
                break;
            case ActionBlockConstants.CONSTANT_ExplicitNamespace:
                ns_kind = Context.NS_EXPLICIT;
                ns = ctx.getNamespace(uri, ns_kind);
                break;
            case ActionBlockConstants.CONSTANT_StaticProtectedNs:
                ns_kind = Context.NS_STATIC_PROTECTED;
                ns = ctx.getNamespace(uri, ns_kind);
                break;
            default:
                throw new IllegalStateException("Invalid kind:" + Integer.toString(kind));
            }
        }
        return ns;
    }


/*
    // These dump functions below are just some debugging aids.
    private void dumpProgram(BinaryProgramNode program)
    {

        if( program.statements != null)
        {
            dumpStatementList(program.statements);
        }
    }

    private void dumpClass(BinaryClassDefNode bincls)
    {
        if( bincls.attrs != null)
            System.out.print(attrsToString(bincls.attrs));
        System.out.print("class " + bincls.cframe.name);
        if( bincls.baseref != null)
        {
            System.out.print(" extends " + typeRefToString(bincls.baseref));
        }
        if( bincls.interfaces != null )
        {
            System.out.print(" implements " );
            for( int i = 0; i < bincls.interfaces.size(); ++ i)
            {
                Node n = bincls.interfaces.items.get(i);
                if( n instanceof MemberExpressionNode )
                {
                    System.out.print( typeRefToString(((MemberExpressionNode)n).ref));
                }
            }
        }
        System.out.println("");
        System.out.println("{");
        if( bincls.statements != null)
        {
            dumpStatementList(bincls.statements);
        }

        if( bincls.instanceinits != null)
        {
            dumpNodeList(bincls.instanceinits);
        }

        System.out.println("} //"+bincls.cframe.name);
    }

    private void dumpStatementList(StatementListNode stmts)
    {
        dumpNodeList(stmts.items);
    }
    private void dumpNodeList(ObjectList<Node> stmts)
    {
        for( Node n : stmts)
        {
            if( n instanceof FunctionDefinitionNode )
                dumpFunction((FunctionDefinitionNode)n);
            else if( n instanceof VariableDefinitionNode )
                dumpVar((VariableDefinitionNode)n);
            else if( n instanceof BinaryClassDefNode)
                dumpClass((BinaryClassDefNode)n);
            else if( n instanceof NamespaceDefinitionNode)
                dumpNamespace((NamespaceDefinitionNode)n);
        }
    }
    private void dumpFunction(FunctionDefinitionNode funcDef)
    {

        if( funcDef.attrs != null)
            System.out.print(attrsToString(funcDef.attrs));
        System.out.print("function ");
        if( funcDef.fexpr.kind == Tokens.GET_TOKEN)
            System.out.print("get ");
        else if (funcDef.fexpr.kind == Tokens.SET_TOKEN)
            System.out.print("set ");
        System.out.print( typeRefToString(funcDef.fexpr.identifier.ref) );
        System.out.print("(");
        if(funcDef.fexpr.signature.parameter != null)
        {
            ParameterListNode params = funcDef.fexpr.signature.parameter;
            for(int i = 0; i < params.size(); ++ i)
            {
                ParameterNode param = params.items.get(i);
                if(param != null && param.typeref != null)
                {
                    System.out.print(typeRefToString(param.typeref) );
                }
                System.out.print(", ");
            }
        }
        System.out.print(")");
        if( funcDef.fexpr.signature.result != null)
        {
            System.out.println( " : " + typeRefToString( ((MemberExpressionNode)funcDef.fexpr.signature.result).ref) );
        }
    }

    private void dumpVar(VariableDefinitionNode varDef)
    {
        if(varDef.attrs != null)
            System.out.print(attrsToString(varDef.attrs));
        Node first = varDef.list.items.at(0);
        System.out.print(" " + typeRefToString( ((VariableBindingNode)first).ref));
        System.out.println(" : " + typeRefToString( ((VariableBindingNode)first).typeref) );
//        /System.out.println("  Name: " + varDef.);
    }

    private void dumpNamespace(NamespaceDefinitionNode nsDef)
    {
        System.out.print( attrsToString(nsDef.attrs) );
        System.out.println( " namespace " + nsDef.name.name + " = \"" + ((LiteralStringNode)nsDef.value).value + "\"");

    }
    private String attrsToString(AttributeListNode attr)
    {
        String ret = "";
        if( attr.hasStatic )
            ret += "static ";
        if( attr.hasPublic)
            ret += "public ";
        else if( attr.hasPrivate)
            ret += "private ";
        if(attr.hasOverride)
            ret += " override ";
        if(attr.hasFinal)
            ret += " final ";
        if(attr.namespaces.size() > 0)
            ret += attr.namespaces.at(0).name + " ";

        return ret;
    }
    private String typeRefToString(ReferenceValue typeref)
    {
        String value = "";
        if( typeref.getImmutableNamespaces().size() == 1)
        {
            ObjectValue ns = typeref.getImmutableNamespaces().first();
            if( ns != null && !ns.name.equals("") )
            {
                value = ns.name + ":";
            }
            value += typeref.name;
        }
        else
        {
            value += "{";
            for( int i = 0; i < typeref.getImmutableNamespaces().size(); ++i )
            {
                ObjectValue ns = typeref.getImmutableNamespaces().get(i);
                value += ns.name + ", ";
            }
            value += "}:" + typeref.name;
        }
        return value;
    }
*/
    
    public static void main(String[] args) throws Throwable
     {
         File abcFile = new File(args[0]);
         byte[] bytes = getBytesFromFile(abcFile); 

         TypeValue.init();
         ObjectValue.init();
         Context ctx = new Context(new ContextStatics());
         AbcParser abcParser = new AbcParser(ctx, bytes);
         @SuppressWarnings("unused")
		ProgramNode programNode = abcParser.parseAbc();

         //System.out.println(programNode.toString());
     }

     private static byte[] getBytesFromFile(File file) throws IOException
     {
         FileInputStream is = new FileInputStream(file);
     
         // Get the size of the file
         long length = file.length();
     
         // Create the byte array to hold the data
         byte[] bytes = new byte[(int)length];
     
         // Read in the bytes
         int offset = 0;
         int numRead = 0;
         while (offset < bytes.length
                && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) 
         {
             offset += numRead;
         }
     
         // Ensure all the bytes have been read in
         if (offset < bytes.length)
         {
             throw new IOException("Could not completely read file "+file.getName());
         }
     
         // Close the input stream and return bytes
         is.close();
         return bytes;
     }
     
}

