package carray.ast;

import polyglot.ast.Ext;
import polyglot.ast.JLang_c;
import polyglot.ast.Lang;
import polyglot.ast.Node;
import polyglot.ast.NodeOps;
import polyglot.util.InternalCompilerError;
import carray.visit.ArrayInitRemover;

public class CArrayLang_c extends JLang_c implements CArrayLang {
    public static final CArrayLang_c instance = new CArrayLang_c();

    public static CArrayLang lang(NodeOps n) {
        while (n != null) {
            Lang lang = n.lang();
            if (lang instanceof CArrayLang) return (CArrayLang) lang;
            if (n instanceof Ext)
                n = ((Ext) n).pred();
            else return null;
        }
        throw new InternalCompilerError("Impossible to reach");
    }

    protected CArrayLang_c() {
    }

    protected static CArrayExt carrayExt(Node n) {
        return CArrayExt.ext(n);
    }

    @Override
    protected NodeOps NodeOps(Node n) {
        return carrayExt(n);
    }

    /**
     * Return an object that implements CArray operations appropriate for this
     * language.
     * @param n
     * @return
     */
    protected CArrayOps CArrayOps(Node n) {
        return carrayExt(n);
    }

    @Override
    public final ArrayInitRemover removeArrayInitEnter(Node n,
            ArrayInitRemover v) {
        return CArrayOps(n).removeArrayInitEnter(v);
    }

    @Override
    public final Node removeArrayInit(Node n, ArrayInitRemover v) {
        // We always dispatch to the same method regardless of the language, but
        // the method _implementation_ we dispatch to will vary depending on the
        // language.  The receiver object, i.e., CArrayOps(n), will determine
        // the appropriate implementation.  Overriding method CArrayOps will
        // change the appropriate receiver object, so this method can be
        // declared final.
        return CArrayOps(n).removeArrayInit(v);
    }
}
