⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 varcontext.java

📁 The ElectricTM VLSI Design System is an open-source Electronic Design Automation (EDA) system that c
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: VarContext.java * * Copyright (c) 2003 Sun Microsystems and Static Free Software * * Electric(tm) 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. * * Electric(tm) 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 Electric(tm); see the file COPYING.  If not, write to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, Mass 02111-1307, USA. */package com.sun.electric.database.variable;import com.sun.electric.database.hierarchy.Cell;import com.sun.electric.database.hierarchy.Nodable;import com.sun.electric.database.text.Name;import com.sun.electric.database.text.TextUtils;import com.sun.electric.database.topology.NodeInst;import com.sun.electric.database.topology.PortInst;import com.sun.electric.tool.generator.layout.LayoutLib;import java.io.Serializable;import java.util.HashMap;import java.util.Map;import java.util.Stack;import java.util.Iterator;import java.util.List;import java.util.ArrayList;import java.util.regex.Pattern;import java.util.regex.Matcher;/** * VarContext represents a hierarchical path of NodeInsts.  Its * primary use is to determine the value of variables which contain * Java code.  In particular, the syntax @foo expands to P("foo") * which looks for the variable called foo in the NodeInst of this * VarContext. * * <p>A VarContext can also be used to recover the names of instances * along a hierarchical path.  LE.getdrive() is an example of a * method that does this. * * <p> The VarContext object that represents the base top level is * VarContext.globalContext.  You can get a new VarContext with an extra * NodeInst context attached by calling push(NodeInst) on the parent * context.  You can get a VarContext with the most recent NodeInst * removed by calling pop().  Note that individual VarContexts are * immutable:  you get new ones by calling push and pop;  push and pop * do not edit their own VarContexts. * * <p>Retrieve a Variable by calling getVar(String name) on any * ElectricObject. * * <p>If the one knows that the Variable contains an object that * does not need to be evaluated, that object can be retrieved using * Variable.getObject(). * * <p>On the other hand, if the object may need to be evaluated because * it is type Java, TCL, or Lisp, then such evaluation may be hierarchy * dependent and one must call context.evalVar(variable). * * <p>Extra variables defined in the interpreter:<br> * * <p>Extra functions defined in the interpreter:<br> * * P(name) -- get the value of variable name on the most recent NodeInst. * Defaults to Integer(0).<br> * <p> * Methods PD(), PAR(), and PARD() are either gone or deprecated (RKao). Here * are what they used to do:<br> * * PD(name, default) -- get the value of variable name on the most recent * NodeInst.  Defaults to default.<br> * PAR(name) -- get the value of variable name on any NodeInst, starting * with the most recent.  Defaults to Integer(0).<br> * PARD(name, default) -- get the value of variable name on any NodeInst, * starting with the most recent.  Defaults to default. * <P> * This class is thread-safe. */public class VarContext implements Serializable{    private static class ValueCache {        private static class EvalPair {            private final CodeExpression ce;            private final Object info;            public EvalPair(CodeExpression e, Object i) {ce=e;  info=i;}            public int hashCode() {return ce.hashCode() * info.hashCode();}            public boolean equals(Object o) {                if (!(o instanceof EvalPair)) return false;                EvalPair ep = (EvalPair) o;                return ce==ep.ce && info==ep.info;            }        }        private final Map<EvalPair,Object> cache = new HashMap<EvalPair,Object>();        public synchronized boolean containsKey(CodeExpression ce, Object info) {            return cache.containsKey(new EvalPair(ce, info));        }        public synchronized Object get(CodeExpression ce, Object info) {            return cache.get(new EvalPair(ce, info));        }        public synchronized void put(CodeExpression ce, Object info, Object value) {            EvalPair key = new EvalPair(ce, info);            LayoutLib.error(cache.containsKey(key), "duplicate keys in ValueCache?");            cache.put(key, value);        }    }    private static final Object FAST_EVAL_FAILED = new Object();    private final VarContext prev;    private final Nodable ni;    private transient ValueCache cache;    // ------------------------ private methods -------------------------------    // For the global context.    private VarContext()    {        this.ni = null;        this.prev = this;        this.cache = null;    }    private VarContext(Nodable ni, VarContext prev, boolean caching)    {        this.ni = ni;        this.prev = prev;        this.cache = caching ? new ValueCache() : null;    }    private Object readResolve() {        return prev != this ? this : globalContext;    }    private void throwNotFound(String name) throws EvalException {        throw new EvalException(name.replaceFirst("ATTR_", "")+" not found");    }    private Object ifNotNumberTryToConvertToNumber(Object val) {        if (val == null) return val;        if (val instanceof Number) return val;        try {            Number d = TextUtils.parsePostFixNumber(val.toString());            val = d;        } catch (java.lang.NumberFormatException e) {            // just return original val object        }        return val;    }    /** If expression is a simple variable reference then return the name of     * the variable; otherwise return null */    private String getSimpleVarRef(String expr) {        final String pOpen = "P(\"";        final int pOpenLen = pOpen.length();        final String pClose = "\")";        final int pCloseLen = pClose.length();        if (expr.startsWith(pOpen) && expr.endsWith(pClose)) {            String varNm = expr.substring(pOpenLen, expr.length()-pCloseLen);            return isValidIdentifier(varNm) ? varNm : null;        }        if (expr.startsWith("@")) {            String varNm = expr.substring(1);            return isValidIdentifier(varNm) ? varNm : null;        }        return null;    }    private boolean isValidIdentifier(String identifier) {        final int len = identifier.length();        for (int i=0; i<len; i++) {            if (!TextUtils.isLetterOrDigit(identifier.charAt(i))) return false;        }        return true;    }    private Object fastJavaVarEval(CodeExpression ce, Object info) throws EvalException {        // Avoid re-computing the value if it is already in the cache.        // Use "contains" because the value might be null.        synchronized(this) {            if (cache!=null && cache.containsKey(ce, info)) {                return cache.get(ce, info);            }        }        // Avoid calling bean shell if value is just a reference to another        // variable.        String expr = ce.getExpr();        String varNm = getSimpleVarRef(expr);        if (varNm==null) return FAST_EVAL_FAILED;        return lookupVarEval("ATTR_"+varNm);    }//    private void printValueCheckValue(Object value, Object checkValue) {//        System.out.println("fast eval mismatch");//        System.out.println("  fast value: "+value.toString());//        System.out.println("  slow value: "+checkValue.toString());//    }//    private void checkFastValue(Object value, Variable var, Object info) throws EvalException {//        if (value==FAST_EVAL_FAILED) return;//        Object checkValue = EvalJavaBsh.evalJavaBsh.evalVarObject(var.getObject(), this, info);//        if (value==null) {//            LayoutLib.error(value!=checkValue, "fast eval null mismatch");//        } else {//            if (!value.equals(checkValue)) {//                System.out.println("fast eval mismatch");//                printValueCheckValue(value, checkValue);//                LayoutLib.error(true, "fast eval mismatch");//            }//        }//    }    // ----------------------------- public methods ---------------------------    /**     * The blank VarContext that is the parent of all VarContext chains.     */    public static final VarContext globalContext = new VarContext();    /**     * get a new VarContext that consists of the current VarContext with     * the given NodeInst pushed onto the stack     */    public VarContext push(Nodable ni)    {        return new VarContext(ni, this, false);    }    /**     * Push a new level onto the VarContext stack. If the value of any of     * ni's parameters is requested and if the computation of that value     * requires a call to the bean shell then the value is saved in this     * VarContext so that future requests don't result in additional calls     * to the bean shell.  Note that this is implementing Call-By-Value     * semantics whereas the non-caching VarContext implements Call-By-Name.     * <p>     * Be warned that there is no mechanism to automatically flush the caches     * when the design is modified. The design MUST NOT change over the     * life time of this VarContext. If the design might change then you should     * use the non-caching VarContext.     */    public VarContext pushCaching(Nodable ni) {        return new VarContext(ni, this, true);    }    /**     * get the VarContext that existed before you called push on it.     * may return globalContext if the stack is empty.     */    public VarContext pop()    {        return prev;    }    /**     * Return the Node Instance that provides the context for the     * variable evaluation for this level.     */    public Nodable getNodable()    {        return ni;    }    /**     * Return the PortInst that resides on the NodeInst that provides     * the context. This is currently only useful for Highlighting.     */    public PortInst getPortInst()    {        return null;    }    /**     * Does deep comparison of two VarContexts.  Matches     * hierarchy traversal.  Returns true if they both represent     * the same hierarchy traversal, false otherwise. (Recursive method).     * Does not compare PortInsts.     * @param o the VarContext to compare against.     * @return true if equal, false otherwise.     */    public boolean equals(Object o)    {        if (!(o instanceof VarContext)) return false;        VarContext c = (VarContext)o;        if (this == c) return true;             // both globalContext, or the same object        // the following line doesn't work (R KAO, IvanM)        //if (ni != c.getNodable()) return false; // compare nodeinsts        if (ni == null || c.getNodable() == null) return ni == c.getNodable();        Cell c1 = ni.getParent();        Cell c2 = c.getNodable().getParent();        String name1 = ni.getName();        String name2 = c.getNodable().getName();        if (! ((c1 == c2) && (name1.equals(name2)))) return false;        return prev.equals(c.pop());            // compare parents    }    /**     * Get an iterator over the Nodables that describe this context.     * This iterator starts from the top of the hierarchy, and goes down.     * @return an iterator over the context path     */    public Iterator<Nodable> getPathIterator() {        Stack<Nodable> stack = new Stack<Nodable>();        VarContext context = this;        while (context != VarContext.globalContext) {            Nodable no = context.getNodable();            stack.push(no);            context = context.pop();        }        List<Nodable> path = new ArrayList<Nodable>();        while (!stack.isEmpty())            path.add(stack.pop());        return path.iterator();    }    /**     * Remove N levels of parent context from this VarContext. Returns     * a new VarContext.  This will return VarContext.globalContext     * if the 'levels' is greater than or equal to the number of levels     * in this context.     * @param levels the number of levels of parent context to remove     * @return a new VarContext     */    public VarContext removeParentContext(int levels) {        Stack<Nodable> nodes = new Stack<Nodable>();        VarContext acontext = this;        while (acontext != VarContext.globalContext) {            nodes.push(acontext.getNodable());            acontext = acontext.pop();        }        for (int i=0; i<levels; i++)            nodes.pop();        acontext = VarContext.globalContext;        int size = nodes.size();        for (int i=0; i<size; i++) {            Nodable no = nodes.pop();            acontext = acontext.push(no);        }        return acontext;    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -