org.pshdl.model.utils.HDLResolver.java Source code

Java tutorial

Introduction

Here is the source code for org.pshdl.model.utils.HDLResolver.java

Source

/*******************************************************************************
 * PSHDL is a library and (trans-)compiler for PSHDL input. It generates
 *     output suitable for implementation or simulation of it.
 *
 *     Copyright (C) 2013 Karsten Becker (feedback (at) pshdl (dot) org)
 *
 *     This program is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public License
 *     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *     This License does not grant permission to use the trade names, trademarks,
 *     service marks, or product names of the Licensor, except as required for
 *     reasonable and customary use in describing the origin of the Work.
 *
 * Contributors:
 *     Karsten Becker - initial API and implementation
 ******************************************************************************/
package org.pshdl.model.utils;

import static org.pshdl.model.extensions.FullNameExtension.fullNameOf;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.pshdl.model.HDLClass;
import org.pshdl.model.HDLEnum;
import org.pshdl.model.HDLEnumDeclaration;
import org.pshdl.model.HDLFunction;
import org.pshdl.model.HDLInterface;
import org.pshdl.model.HDLRegisterConfig;
import org.pshdl.model.HDLStatement;
import org.pshdl.model.HDLType;
import org.pshdl.model.HDLUnit;
import org.pshdl.model.HDLVariable;
import org.pshdl.model.HDLVariableDeclaration;
import org.pshdl.model.IHDLObject;
import org.pshdl.model.extensions.ScopingExtension;

import com.google.common.base.Optional;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;

public class HDLResolver {

    private final boolean descent;

    private Map<HDLQualifiedName, HDLEnum> enumCache;

    private Map<HDLQualifiedName, HDLInterface> ifCache;

    private Multimap<HDLQualifiedName, HDLFunction> funcCache;

    private final IHDLObject resolveTo;

    private Map<HDLQualifiedName, HDLType> typeCache;

    private Map<HDLQualifiedName, HDLVariable> variableCache;

    private IHDLObject resolveContainer;

    private HDLQualifiedName resolveName;

    public HDLResolver(IHDLObject resolveTo, boolean descent) {
        super();
        this.resolveTo = resolveTo;
        this.resolveContainer = resolveTo.getContainer();
        this.resolveName = fullNameOf(resolveTo);
        this.descent = descent;
    }

    public HDLResolver(IHDLObject resolveTo, boolean descent, String libURI) {
        super();
        this.resolveTo = resolveTo;
        this.descent = descent;
    }

    protected List<HDLType> doGetTypeDeclarations() {
        final List<HDLType> types = new LinkedList<HDLType>();
        for (final HDLEnumDeclaration hEnumDecl : ScopingExtension.INST.doGetEnumDeclarations(resolveTo)) {
            types.add(hEnumDecl.getHEnum());
        }
        for (final HDLVariable varDecl : ScopingExtension.INST.doGetVariables(resolveTo)) {
            final IHDLObject container = varDecl.getContainer();
            if (container instanceof HDLVariableDeclaration) {
                final HDLVariableDeclaration hvd = (HDLVariableDeclaration) container;
                if (hvd.getPrimitive() != null) {
                    types.add(hvd.getPrimitive());
                }
            }
        }
        for (final HDLInterface ifDecl : ScopingExtension.INST.doGetInterfaceDeclarations(resolveTo)) {
            types.add(ifDecl);
        }
        return types;
    }

    public Optional<HDLEnum> resolveEnum(HDLQualifiedName hEnum) {
        if (enumCache == null) {
            synchronized (this) {
                final HDLEnumDeclaration[] enumDecl = resolveTo.getAllObjectsOf(HDLEnumDeclaration.class, false);
                enumCache = Maps.newLinkedHashMap();
                for (final HDLEnumDeclaration hdlEnumDeclaration : enumDecl) {
                    enumCache.put(fullNameOf(hdlEnumDeclaration.getHEnum()), hdlEnumDeclaration.getHEnum());
                }
            }
        }
        // XXX Check if the qualifier does either match the pkg name, or is not
        // existant
        final HDLEnum checkCache = checkCache(hEnum, enumCache);
        if (checkCache != null)
            return Optional.of(checkCache);
        if ((resolveContainer == null) || !descent)
            return Optional.absent();
        return ScopingExtension.INST.resolveEnum(resolveContainer, hEnum);
    }

    public Optional<Iterable<HDLFunction>> resolveFunction(HDLQualifiedName hEnum) {
        if (funcCache == null) {
            synchronized (this) {
                final HDLFunction[] funcDecl = resolveTo.getAllObjectsOf(HDLFunction.class, false);
                funcCache = LinkedHashMultimap.create();
                for (final HDLFunction hdlfuncDeclaration : funcDecl) {
                    funcCache.put(fullNameOf(hdlfuncDeclaration), hdlfuncDeclaration);
                }
            }
        }
        // XXX Check if the qualifier does either match the pkg name, or is not
        // existant
        final Iterable<HDLFunction> checkCache = checkCache(hEnum, funcCache);
        if ((checkCache != null) && checkCache.iterator().hasNext())
            return Optional.of(checkCache);
        if ((resolveContainer == null) || !descent)
            return Optional.absent();
        return ScopingExtension.INST.resolveFunctionName(resolveContainer, hEnum);
    }

    public Optional<HDLInterface> resolveInterface(HDLQualifiedName hIf) {
        if (ifCache == null) {
            synchronized (this) {
                final List<HDLInterface> ifDecl = ScopingExtension.INST.doGetInterfaceDeclarations(resolveTo);
                ifCache = Maps.newLinkedHashMap();
                for (final HDLInterface hdlIfDeclaration : ifDecl) {
                    final HDLQualifiedName fqn = fullNameOf(hdlIfDeclaration);
                    // Usually this should not happen, but when the interface
                    // can not be resolved, it might happen.
                    if (fqn != null) {
                        ifCache.put(fqn, hdlIfDeclaration);
                    }
                }
            }
        }
        // XXX Check if the qualifier does either match the pkg name, or is not
        // existant
        final HDLInterface checkCache = checkCache(hIf, ifCache);
        if (checkCache != null)
            return Optional.of(checkCache);
        if ((resolveContainer == null) || !descent)
            return Optional.absent();
        return ScopingExtension.INST.resolveInterface(resolveContainer, hIf);
    }

    public Optional<? extends HDLType> resolveType(HDLQualifiedName var) {
        if (typeCache == null) {
            synchronized (this) {
                final List<HDLType> typeDecl = doGetTypeDeclarations();
                typeCache = Maps.newLinkedHashMap();
                for (final HDLType hdlTypeDeclaration : typeDecl) {
                    if (hdlTypeDeclaration.getClassType() != HDLClass.HDLPrimitive) {
                        typeCache.put(fullNameOf(hdlTypeDeclaration), hdlTypeDeclaration);
                    }
                }
            }
        }
        final HDLType checkCache = checkCache(var, typeCache);
        if (checkCache != null)
            return Optional.of(checkCache);
        if ((resolveContainer == null) || !descent) {
            if (resolveTo instanceof HDLUnit) {
                final HDLUnit unit = (HDLUnit) resolveTo;
                final String uri = unit.getLibURI();
                if (uri != null) {
                    final HDLLibrary library = HDLLibrary.getLibrary(uri);
                    if (library != null) {
                        final List<String> imports = unit.getImports();
                        imports.add(fullNameOf(unit).skipLast(1).append("*").toString());
                        return library.resolve(imports, var);
                    }
                }
            }
            return Optional.absent();
        }
        return ScopingExtension.INST.resolveType(resolveContainer, var);
    }

    public Optional<HDLVariable> resolveVariable(HDLQualifiedName var) {
        if (variableCache == null) {
            synchronized (this) {
                final List<HDLVariable> varDecl = ScopingExtension.INST.doGetVariables(resolveTo);
                variableCache = Maps.newLinkedHashMap();
                for (final HDLVariable declVars : varDecl) {
                    variableCache.put(fullNameOf(declVars), declVars);
                }
            }
        }
        final HDLVariable checkCache = checkCache(var, variableCache);
        if (checkCache != null)
            return Optional.of(checkCache);
        if (var.length > 1) {
            // Using lastSgement if $for0.I or ThisObject.I
            if (var.getSegment(0).startsWith("$") || var.getTypePart().equals(resolveName.getTypePart())) {
                final String string = var.getLastSegment();
                for (final Entry<HDLQualifiedName, HDLVariable> entry : variableCache.entrySet())
                    if (entry.getKey().getLastSegment().equals(string))
                        return Optional.of(entry.getValue());
            }
        }
        if (HDLRegisterConfig.DEF_CLK.equals(var.getLastSegment()))
            return Optional.of(HDLRegisterConfig.defaultClk(true));
        if (HDLRegisterConfig.DEF_RST.equals(var.getLastSegment()))
            return Optional.of(HDLRegisterConfig.defaultRst(true));
        final IHDLObject container = resolveContainer;
        if ((container == null) || !descent)
            return Optional.absent();
        return ScopingExtension.INST.resolveVariable(container, var);
    }

    private <T> Iterable<T> checkCache(HDLQualifiedName var, Multimap<HDLQualifiedName, T> map) {
        if (map.get(var) != null)
            return map.get(var);
        if (var.length == 1) {
            final HDLQualifiedName fqn = resolveName.append(var);
            if (map.get(fqn) != null)
                return map.get(fqn);
        }
        return null;
    }

    private <T> T checkCache(HDLQualifiedName var, Map<HDLQualifiedName, T> map) {
        if (map.get(var) != null)
            return map.get(var);
        if (var.length == 1) {
            final HDLQualifiedName fqn = resolveName.append(var);
            if (map.get(fqn) != null)
                return map.get(fqn);
        }
        return null;
    }

    public static List<HDLEnumDeclaration> getallEnumDeclarations(List<HDLStatement> stmnts) {
        final List<HDLEnumDeclaration> res = new LinkedList<HDLEnumDeclaration>();
        for (final HDLStatement hdlStatement : stmnts) {
            res.addAll(ScopingExtension.INST.doGetEnumDeclarations(hdlStatement));
        }
        return res;
    }

    public static List<HDLInterface> getallInterfaceDeclarations(List<HDLStatement> stmnts) {
        final List<HDLInterface> res = new LinkedList<HDLInterface>();
        for (final HDLStatement hdlStatement : stmnts) {
            res.addAll(ScopingExtension.INST.doGetInterfaceDeclarations(hdlStatement));
        }
        return res;
    }

    public static List<HDLVariable> getallVariableDeclarations(List<HDLStatement> stmnts) {
        final List<HDLVariable> res = new LinkedList<HDLVariable>();
        for (final HDLStatement hdlStatement : stmnts) {
            res.addAll(ScopingExtension.INST.doGetVariables(hdlStatement));
        }
        return res;
    }

}