/* --COPYRIGHT--,EPL
 *  Copyright (c) 2008 Texas Instruments and others.
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  which accompanies this distribution, and is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 * 
 *  Contributors:
 *      Texas Instruments - initial implementation
 * 
 * --/COPYRIGHT--*/
package xdc.services.spec;

import java.util.*;

public class Decl
    extends Node
{
    // Static Serialization UID
    static final long serialVersionUID = 3468768778188819860L;

    Decl              over             = null;

    // Annexable
    public interface Annexable
    {
    }

    // AuxDef
    public interface AuxDef
    {
    }

    // IsType
    public interface IsType
    {
    }

    // LocalUnit
    public interface LocalUnit
    {
        Unit getUnit();
    }

    // OverridableDef
    public interface OverridableDef
    {
    }

    // Signature
    public interface Signature
    {
        enum ObjKind { NONE, SINGLE, ARRAY };
        
        Type getType();
        String getTypeCode();
        String getTypeSig();
    }

    // Sizeable
    public interface Sizeable
    {
        void sizeof( List<String> sL );
    }

    private static void checkSig( Signature sig )
    {
        Signature.ObjKind kind = Decl.objKind(sig);
        
        if (kind == Signature.ObjKind.NONE) {
            return;
        }
        
        if (sig instanceof Decl.Field) {
            Decl.Struct str = (Decl.Struct)((Decl.Field)sig).getParent();
            if (str.getName().equals("Module_State") || str.getName().equals("Instance_State")) {
                return;
            }
        }

        Decl decl = (Decl)sig;
        Session ses = decl.getSession();
        ses.msg.error(decl.getAtom(), "bad use of Object type");
    }
    
    // overrides
    public Decl overrides()
    {
        return this.over;
    }

    // finalCheck
    void finalCheck()
    {
        super.finalCheck();

        List<? extends Decl> dL = this.getChildren();
        if (dL == null) {
            return;
        }

        for (Decl d : dL) {
            d.finalCheck();
        }
    }

    // getChildren
    public List<? extends Decl> getChildren()
    {
        return null;
    }

    // getQualName
    public String getQualName()
    {
        return this.parent.getQualName() + '.' + this.name.text;
    }

    // getXmlTag
    public String getXmlTag()
    {
        return this.getClass().getSimpleName().toLowerCase();
    }
    
    /**
     * Generate the XDoc for a Decl. Unlike other Nodes, documentation
     * for a Decl accumulates any docs coming from parent interfaces. This
     * method collects the docs from the override chain, then appends the
     * docs specific for this Decl.
     */
    void parseXDoc() {
        XDoc od = overrides() == null ? null : overrides().makeXDoc();
        this.xdoc = new XDoc(getDocs(), od, summary, isNodoc);
    }

    // objKind
    public static final Decl.Signature.ObjKind objKind( Decl.Signature sig )
    {
        return objKind(sig.getType(), sig.getTypeCode());
    }
    
    public static final Decl.Signature.ObjKind objKind( Type type, String tcode )
    {
        if (tcode.equals("O")) {
            return Decl.Signature.ObjKind.SINGLE;
        }
        else if (tcode.equals("AO")) {
            Type.Array tarr = (Type.Array)type;
            return tarr.getDim() != null ? Decl.Signature.ObjKind.ARRAY : Decl.Signature.ObjKind.NONE;
        }
        else {
            return Decl.Signature.ObjKind.NONE;
        }
    }

    // parseDocs
    void parseDocs()
    {
    	
        super.parseDocs();

        List<? extends Decl> dL = this.getChildren();
        if (dL == null) {
            return;
        }

        for (Decl d : dL) {
            d.parseDocs();
        }
    }

    // pass1Check
    void pass1Check()
    {
        List<? extends Decl> dL = this.getChildren();
        if (dL == null) {
            return;
        }

        for (Decl d : dL) {
            d.bindParent(d instanceof Decl.EnumVal ? this.parent : this);
            Session ses = d.getSession();
            if (!ses.enterNode(d.getQualName(), d)) {
                ses.msg.error(d.name, "multiple declaration in enclosing scope");
                continue;
            }
        }
    }

    // resolve
    void resolve( Unit uspec )
    {
        // TODO: common stuff ???
    }

    // Decl.Arg
    static public class Arg
        extends Decl
        implements Decl.Signature
    {
        static final long serialVersionUID = -7298373774659045568L;

        Type              type;
        Expr              init;

        Arg( Atom name, EnumSet<Qual> quals, Type type )
        {
            this(name, quals, type, null);
        }

        Arg( Atom name, EnumSet<Qual> quals, Type type, Expr init )
        {
            this.name = name;
            this.quals = quals;
            this.type = type;
            this.init = init;
        }

        // getInit
        public final Expr getInit()
        {
            return this.init;
        }

        // getType
        public final Type getType()
        {
            return this.type;
        }

        // getTypeCode
        public final String getTypeCode()
        {
            return ((this.type == null) ? "" : this.type.tcode());
        }

        // getTypeSig
        public final String getTypeSig()
        {
            return ((this.type == null) ? "" : this.type.tsig());
        }

        // resolve
        void resolve( Unit uspec )
        {
            if (this.type != null) {
                this.type.resolve(uspec);
                if (this.init != null) {
                    this.init.resolve(uspec);
                }
            }
            
            Decl.checkSig(this);
        }
    }

    // Decl.Config
    static public class Config
        extends Decl
        implements Decl.Annexable, Decl.Signature
    {
        static final long      serialVersionUID = -3472392753188999914L;

        Type                   type;
        Expr                   init;

        static HashSet<String> reservedAttrs    = new HashSet(Arrays.asList(new String[] {
                Attr.A_Annex,
                Attr.A_CommandOption,
                Attr.A_Facet,
                Attr.A_System,
        }));

        Config( Atom name, EnumSet<Qual> quals, Type type, Expr init )
        {
            this.name = name;
            this.quals = quals;
            this.type = type;
            this.init = init;
        }
        
        // checkFacet
        private void checkFacet()
        {
            if (!this.isMeta()) {
                ses.msg.error(this.name, "@Facet configs must be metaonly");
            }
            
            Ref r = this.type.tspec().getRef();
            Node n = r.getNode();
            HashSet<String> facSet = ((Unit)this.getParent()).facSet;
            
            if (!(n instanceof Unit) || !n.hasAttr(Attr.A_Facet) || !r.getId().equals("Instance")) {
                ses.msg.error(this.name, "@Facet config types must be a @Facet Instance");
            }
            else if (facSet.contains(n.getQualName())) {
                ses.msg.error(this.name, "multiple @Facet configs of the same type");
            }
            else {
                facSet.add(n.getQualName());
            }
        }

        // finalCheck
        void finalCheck()
        {
            super.finalCheck();
            
            String tc = this.getTypeCode();

            if (this.hasAttr(Attr.A_Facet)) {
                this.checkFacet();
            }
        }
        
        // getInit
        public final Expr getInit()
        {
            return this.init;
        }

        // getType
        public final Type getType()
        {
            return this.type;
        }

        // getTypeCode
        public final String getTypeCode()
        {
            return ((this.type == null) ? "" : this.type.tcode());
        }

        // getTypeSig
        public final String getTypeSig()
        {
            return ((this.type == null) ? "" : this.type.tsig());
        }
        
        // overrides
        public final Decl.Config overrides()
        {
            return (Decl.Config) this.over;
        }

        // resolve
        void resolve( Unit uspec )
        {
            this.enterAttrs(Decl.Config.reservedAttrs);

            if (this.type != null) {
                this.type.resolve(uspec, true);
                if (this.init != null) {
                    this.init.resolve(uspec);
                }
            }
            
            Decl.checkSig(this);
        }
    }

    // Decl.Const
    static public class Const
        extends Decl
        implements Decl.AuxDef, Decl.OverridableDef, Decl.Signature
    {
        static final long serialVersionUID = -5129490619630763331L;

        Type              type;
        Expr              init;

        Const( Atom name, EnumSet<Qual> quals, Type type, Expr init )
        {
            this.name = name;
            this.quals = quals;
            this.type = type;
            this.init = init;
            
            if (this.init != null) {
                this.quals.add(Qual.FINAL);
            }
        }

        // getInit
        public final Expr getInit()
        {
            return this.init;
        }

        // getType
        public final Type getType()
        {
            return this.type;
        }

        // getTypeCode
        public final String getTypeCode()
        {
            return ((this.type == null) ? "" : this.type.tcode());
        }

        // getTypeSig
        public final String getTypeSig()
        {
            return ((this.type == null) ? "" : this.type.tsig());
        }

        // resolve
        void resolve( Unit uspec )
        {
            if (this.type != null) {
                this.type.resolve(uspec);
                if (this.init != null) {
                    this.init.resolve(uspec);
                }
                else {
                    ((Unit) this.parent).custHdr = true;
                }
            }
            
            Decl.checkSig(this);
        }
    }

    // Decl.Enum
    static public class Enum
        extends Decl
        implements Decl.AuxDef, Decl.IsType, Decl.Sizeable
    {
        static final long serialVersionUID = -7076604082337550848L;

        List<EnumVal>     vals;
        Type.Spec         rep;

        Enum( Atom name, EnumSet<Qual> quals, List<EnumVal> vals, Type.Spec rep )
        {
            this.name = name;
            this.quals = quals;
            this.vals = vals;
            this.rep = rep;
        }

        // getChildren
        public List<EnumVal> getChildren()
        {
            return this.vals;
        }

        // getRep
        public final Type.Spec getRep()
        {
            return this.rep;
        }
        
        // getVals
        public final List<EnumVal> getVals()
        {
            return this.vals;
        }

        // resolve
        void resolve( Unit uspec )
        {
            for (EnumVal e : this.vals) {
                if (e.init != null) {
                    e.init.resolve(uspec);
                }
            }
            if (this.rep != null) {
                this.rep.resolve(uspec);
            }
        }

        // sizeof
        public void sizeof( List<String> sL )
        {
            if (this.rep != null) {
                this.rep.sizeof(sL);
            }
            else {
                sL.add("N" + this.getQualName());
            }
        }
    }

    // Decl.EnumVal
    static public class EnumVal
        extends Decl
        implements Decl.AuxDef
    {
        static final long serialVersionUID = -3594208666128592956L;

        Expr              init;

        EnumVal( Atom name, EnumSet<Qual> quals, Expr init )
        {
            this.name = name;
            this.quals = quals;
            this.init = init;
        }

        // getInit
        public final Expr getInit()
        {
            return this.init;
        }
    }

    // Decl.Error
    static class Error
        extends Decl
    {
        static final long serialVersionUID = 3065995409031385368L;

        Error()
        {
        }
    }

    // Decl.Extern
    static public class Extern
        extends Decl
        implements Decl.AuxDef, Decl.Signature
    {
        static final long serialVersionUID = -5537398406232068500L;

        Type              type;
        Atom              init;

        Extern( Atom name, EnumSet<Qual> quals, Type type, Atom init )
        {
            this.name = name;
            this.quals = quals;
            this.type = type;
            this.init = init;
        }

        // finalCheck
        void finalCheck()
        {
            super.finalCheck();

            if (!this.parent.isMod()) {
                ses.msg.error(this.name, "extern declaration permitted only in modules");
            }
        }

        // getType
        public final Type getType()
        {
            return this.type;
        }

        // getTypeCode
        public final String getTypeCode()
        {
            return ((this.type == null) ? "" : this.type.tcode());
        }

        // getTypeSig
        public final String getTypeSig()
        {
            return ((this.type == null) ? "" : this.type.tsig());
        }

        // getValue
        public final String getValue()
        {
            return ((this.init == null) ? this.getQualName().replace('.', '_') : this.init.text);
        }

        // resolve
        void resolve( Unit uspec )
        {
            if (this.type != null) {
                this.type.resolve(uspec);
            }
            
            Decl.checkSig(this);
        }
    }

    // Decl.Field
    static public class Field
        extends Decl
        implements Decl.Signature
    {
        static final long serialVersionUID = 1865932903245823181L;

        Type              type;

        Field( Atom name, EnumSet<Qual> quals, Type type )
        {
            this.name = name;
            this.quals = quals;
            this.type = type;
        }

        // getType
        public final Type getType()
        {
            return this.type;
        }

        // getTypeCode
        public final String getTypeCode()
        {
            return ((this.type == null) ? "" : this.type.tcode());
        }

        // getTypeSig
        public final String getTypeSig()
        {
            return ((this.type == null) ? "" : this.type.tsig());
        }

        // resolve
        void resolve( Unit uspec )
        {
            if (this.type != null) {
                this.type.resolve(uspec);
            }
            
            Decl.checkSig(this);
        }
    }

    // Decl.Fxn
    static public class Fxn
        extends Decl
        implements Decl.Annexable, Decl.Signature
    {
        static final long      serialVersionUID = 4734759580216702060L;

        Type                   type;
        List<Arg>              args;
        boolean                isVarg;
        int                    minargc = 0;

        String				   structName = null;
        
        static HashSet<String> reservedAttrs    = new HashSet(Arrays.asList(new String[] {
                Attr.A_Annex,
                Attr.A_DirectCall,
                Attr.A_Macro,
                Attr.A_System,
        }));

        Fxn( Atom name, EnumSet<Qual> quals, Type type, List<Arg> args, boolean isVarg )
        {
            this.name = name;
            this.quals = quals;
            this.type = type;
            this.args = args;
            this.isVarg = isVarg;
        }

        // finalCheck
        void finalCheck()
        {
        	super.finalCheck();

            if (this.type == null) {
                return;
            }

            if (this.type instanceof Type.Creator && this.isStatic()) {
                ses.msg.error(this.name, "declaration must be per-instance");
            }

            Type t = this.type.root();

            if (t != null && (t instanceof Type.Fxn || t instanceof Type.Array)) {
                ses.msg.error(this.name, "function can't return functions or arrays");
            }

            if (!this.isStruct()) {
            	return;
            }
            
        	if (!this.isStatic()) {
        		ses.msg.error(this.name, "struct-qualified functions must be module-wide");
        	}

        	String fn = this.name.getText();
        	this.name.replaceText(fn.replace('.', '_'));
        	
        	int k = fn.lastIndexOf('.');
            if (k != -1) {
            	String sn = fn.substring(0, k);
            	String qn = this.parent.getQualName() + '.' + sn;
            	if (!(ses.lookup(qn) instanceof Decl.Struct)) {
            		ses.msg.error(this.name, "qualified name must reference a struct in scope");
            	}
            }
        }

        // getArgs
        public final List<Arg> getArgs()
        {
            return this.args;
        }

        // getChildren
        public List<Arg> getChildren()
        {
            return this.args;
        }
        
        // getMinArgc
        public final int getMinArgc()
        {
            return this.minargc;
        }
        
        // getStructName
        public final String getStructName()
        {
        	return this.structName;
        }
        
        // getType
        public final Type getType()
        {
            return this.type;
        }

        // getTypeCode
        public final String getTypeCode()
        {
            if (this.type == null) {
                return ("");
            }
            return this.type instanceof Type.Creator ? "C" : this.type.tcode();
        }

        // getTypeSig
        public final String getTypeSig()
        {
            if (this.type == null) {
                return "void";
            }

            String res = this.type instanceof Type.Creator ? "$Instance" : this.type.tsig();
            res += "(*)(";
            String sp = "";

            if (this.args.size() == 0 && !this.isVarg) {
                return res + "xdc_Void)";
            }

            for (Arg arg : this.args) {
                res += sp + arg.type.tsig();
                sp = ",";
            }

            res += this.isVarg ? ",...)" : ")";
            return res;
        }

        // isLoggable
        public final boolean isLoggable()
        {
            return
                !this.isMeta() &&
                !this.isSys() &&
                !this.isInternal() &&
                !this.hasAttr(Attr.A_Macro) &&
                !this.hasAttr(Attr.A_DirectCall);
        }
        
        // isStruct
        public final boolean isStruct()
        {
            return this.structName != null;
        }
        
        // isVarg
        public final boolean isVarg()
        {
            return this.isVarg;
        }
        
        // overrides
        public final Decl.Fxn overrides()
        {
            return (Decl.Fxn) this.over;
        }

        // resolve
        void resolve( Unit uspec )
        {
        	this.enterAttrs(Decl.Fxn.reservedAttrs);

            if (this.hasAttr(Attr.A_Macro)) {
                ((Unit) this.parent).custHdr = true;
            }

            if (this.type == null) {
                return;
            }


            String fn = this.name.getText();
            int k = fn.lastIndexOf('.');
            if (k != -1) {
            	this.structName = fn.substring(0, k);
            	Decl.Arg arg = new Decl.Arg(
            			new Atom("__this"),
    					EnumSet.noneOf(Qual.class),
    					new Type.Ptr(
    							new Type.Declarator(
    	    							new Type.Spec(new Ref(null, this.name.copy(this.structName)), null, false, null),
    	    							new Atom("__this")),
    	    					EnumSet.noneOf(Type.Modifier.class)),
    	    	    			null);
            	this.args.add(0, arg);
            }
            
            this.type.resolve(uspec);
            boolean defflg = false;
            for (Arg arg : this.args) {
                if (arg.init == null) {
                    if (!defflg) {
                        this.minargc++;
                    }
                    else {
                        ses.msg.error(arg.name, "default value required");
                    }
                }
                else {
                    defflg = true;
                }
                arg.resolve(uspec);
            }
            
            if (this.isStruct()) {
            	if (!(this.args.get(0).getType().tspec().getRef().getNode() instanceof Decl.Struct)) {
            		ses.msg.error(this.name, "qualified name does not reference a struct type");
            	}
            	this.minargc--;
            }
            
            Decl.checkSig(this);
        }
    }

    // Decl.Imp
    static public class Imp
        extends Decl
        implements Decl.AuxDef, Decl.LocalUnit
    {
        static final long serialVersionUID = -2L;

        Import imp;
        Sup sup;

        Imp( Atom name, Import imp )
        {
        	this(name, imp, null);
        }
        
        Imp( Atom name, Sup sup )
        {
        	this(name, null, sup);
        }
        
        private Imp( Atom name, Import imp, Sup sup )
        {
        	this.name = name;
            this.imp = imp;
            this.sup = sup;
            this.quals = EnumSet.noneOf(Qual.class);
        }

        public final void bindImport( Import imp )
        {
        	this.imp = imp;
        }

        public final Import getImport()
        {
        	return this.imp;
        }
        
        public final Unit getUnit()
        {
            return this.imp.unit;
        }
        
        // finalCheck
        void finalCheck()
        {
            super.finalCheck();

            if (this.imp == null) {
                ses.msg.error(this.name, "no corresponding import");
            }

        	boolean found = true;
            if (this.sup != null) {
            	found = false;
            	for (Unit iu : this.getUnit().getInherits()) {
            		if (iu == sup.getUnit()) {
            			found = true;
            			break;
            		}
            	}
            }
            
            if (!found) {
                ses.msg.error(this.name, "does not inherit from " + sup.getUnit().getQualName());
                throw new SessionRuntimeException("parser failed");
            }
        }
        
        // resolve
        void resolve( Unit u )
        {
        	if (this.sup != null) {
        		this.sup.resolve(u);
        	}
        }
    }

    // Decl.Proxy
    static public class Proxy
        extends Decl
        implements Decl.LocalUnit
    {
        static final long serialVersionUID = -5207411272617839552L;

        Sup               sup;

        Unit              unit;

        Proxy( Atom name, EnumSet<Qual> quals, Sup sup )
        {
            this.name = name;
            this.quals = quals;
            this.sup = sup;
        }

        // getInherits
        public final Unit getInherits()
        {
            return this.sup.unit;
        }

        // getUnit
        public final Unit getUnit()
        {
            Unit u = this.getParent().getSession().findUnit(
                    this.getParent().getQualName() + '_' + this.getName());

            return u == null ? this.sup.unit : u;
        }
    }

    // Decl.Struct
    static public class Struct
        extends Decl
        implements Decl.AuxDef, Decl.IsType, Decl.Sizeable
    {
        static final long      serialVersionUID = 8653474625146200716L;

        List<Field>            flds;
        List<String>           fldSizes;
        boolean                uflag;

        static HashSet<String> reservedAttrs    = new HashSet(Arrays.asList(new String[] {
                Attr.A_Opaque,
                Attr.A_XmlDtd,
        }));

        Struct( Atom name, EnumSet<Qual> quals, List<Field> flds, boolean uflag )
        {
            this.name = name;
            this.quals = quals;
            this.flds = flds;
            this.uflag = uflag;

            this.fldSizes = new ArrayList();
        }

        // finalCheck
        void finalCheck()
        {
            super.finalCheck();

            if (this.name.text.equals("Object")) {
                ses.msg.error(this.name, "reserved name");
            }
        }

        // getChildren
        public List<Field> getChildren()
        {
            return this.flds;
        }

        // getFields
        public final List<Field> getFields()
        {
            return this.flds;
        }

        // getSizes
        public final List<String> getSizes()
        {
            return this.fldSizes;
        }
        
        // getXmlTag
        public String getXmlTag()
        {
            return this.uflag ? "union" : "struct";
        }
        
        // isAnon
        public final boolean isAnon()
        {
            return this.name.text.startsWith("__struct__");
        }
        
        // isUnion
        public final boolean isUnion()
        {
            return this.uflag;
        }

        // resolve
        void resolve( Unit uspec )
        {
            this.enterAttrs(Decl.Struct.reservedAttrs);

            if (this.flds == null) {
                return;
            }
            
            boolean isState =
                this.getName().equals("Module_State") || this.getName().equals("Instance_State");
            
            for (Field fld : this.flds) {
                fld.resolve(uspec);
            }
            
            if (isState) {
                List<Field> fL = new ArrayList<Field>();
                for (ListIterator<Field> it = this.flds.listIterator(); it.hasNext(); ) {
                    Field fld = it.next();
                    if (Decl.objKind(fld) != Decl.Signature.ObjKind.NONE) {
                        fL.add(fld);
                        it.remove();
                    }
                }
                this.flds.addAll(fL);
            }

            for (Field fld : this.flds) {
                fld.type.sizeof(this.fldSizes);
            }
        }

        // sizeof
        public void sizeof( List<String> sL )
        {
            Unit unit = (Unit) this.parent;
            sL.add("S" + unit.getQualName() + ';' + this.name.text);
        }
    }

    // Decl.Typedef
    static public class Typedef
        extends Decl
        implements Decl.AuxDef, Decl.IsType, Decl.Signature, Decl.Sizeable
    {
        static final long      serialVersionUID = -3286912318315178858L;

        Type                   type;

        static HashSet<String> reservedAttrs    = new HashSet(Arrays
                                                        .asList(new String[] { Attr.A_Encoded,
                                                        }));

        Typedef( Atom name, EnumSet<Qual> quals, Type type )
        {
            this.name = name;
            this.quals = quals;
            this.type = type;
        }

        // getType
        public final Type getType()
        {
            return this.type;
        }

        // getTypeCode
        public final String getTypeCode()
        {
            return ((this.type == null) ? "" : this.type.tcode());
        }

        // getTypeSig
        public final String getTypeSig()
        {
            return ((this.type == null) ? "" : this.type.tsig());
        }

        // resolve
        void resolve( Unit uspec )
        {
            this.enterAttrs(Decl.Typedef.reservedAttrs);

            if (this.hasAttr(Attr.A_Encoded)) {
                ((Unit) this.parent).custHdr = true;
            }

            if (this.type == null) {
                return;
            }

            this.type.resolve(uspec, this.attrBool(Attr.A_Encoded));

            Type t = this.type;
            while (t instanceof Type.Declarator) {
                Node n = t.tspec().getRef().getNode();
                if (n == this) {
                    ses.msg.error(this.name, "circular typedef");
                    return;
                }
                if (!(n instanceof Typedef)) {
                    break;
                }
                t = ((Typedef) n).getType();
            }
            
            Decl.checkSig(this);
        }

        // sizeof
        public void sizeof( List<String> sL )
        {
            if (this.attrBool(Attr.A_Encoded)) {
                Unit unit = (Unit) this.parent;
                sL.add("E" + unit.getQualName() + ';' + this.name.text);
            }
            else {
                this.type.sizeof(sL);
            }
        }
    }
}
