📄 interp.java
字号:
throw new HeclException("Variable " + varname + " does not exist"); } return res;//#else if(res == GLOBALREFTHING) { // ref to a global var Hashtable globalhash = getVarhash(0); res = (Thing)globalhash.get(varname); if(res == GLOBALREFTHING) { // should not happen, but just in case... System.err.println("Unexpected GLOBALREFTHING in globalhash"); res = null; }//#ifdef emptyglobals else if (res == null) { // Return a fake empty value for a non-set global variable for // the sake of modifying commands. // !!!! THIS IS STRANGE !!! System.err.println("FAKE EMPTY VALUE for global var"); res = new Thing(""); globalhash.put(varname,res); }//#endif } if (res == null) { throw new HeclException("Variable " + varname + " does not exist"); } //System.err.println("<<getvar, res="+res); return res;//#endif } /** * <code>setVar</code> sets a variable in the innermost variable stack * frame to a value. * * @param varname a <code>Thing</code> value * @param value a <code>Thing</code> value */ public void setVar(Thing varname, Thing value) throws HeclException { setVar(varname.toString(), value); } /** * <code>setVar</code> sets a variable in the innermost variable stack * frame to a value. * * @param varname a <code>String</code> value * @param value a <code>Thing</code> value */ public void setVar(String varname, Thing value) { setVar(varname, value, -1); } /** * <code>setVar</code> sets a variable to a value in the variable stack * frame specified by <code>level</code>. * * @param varname a <code>String</code> value * @param value a <code>Thing</code> value * @param level an <code>int</code> value */ public synchronized void setVar(String varname, Thing value, int level) { Hashtable lookup = getVarhash(level); // Bump the cache number so that SubstThing.get refetches the // variable. cacheversion++; //if(value == GLOBALREFTHING) System.err.println("flag '"+varname+"' as global on level="+level); //System.err.println("set local("+level+") var="+varname + ", val="+value.toString());//#ifdef old if (lookup.containsKey(varname)) { Thing oldval = (Thing) lookup.get(varname); /* In order to make the 'global' command work, we check * and see if the previous 'inhabitant' of the hashtable * had its global flag set. If that's the case, then we * set the variable both at the local level, and at the * global level. */ if (oldval.global && level != 0) { value.global = true; Hashtable globalhash = getVarhash(0); globalhash.put(varname, value); } } lookup.put(varname, value);//#else if (value.isLiteral()) { try { Thing copy = value.deepcopy(); value = copy; } catch (HeclException he) { /* This isn't going to happen - we're dealing with a * literal from the parser. */ System.err.println("Interp.java: This can never happen!"); } } // first take care of GLOBALREFTHING used to flag ref to global var if(value == GLOBALREFTHING) { // do not clutter global table with GLOBALREFTHING Hashtable globalhash = getVarhash(0); if(lookup != globalhash) { //System.err.println(" not on global level"); lookup.put(varname, value);//#ifdef emptyglobals if(null == globalhash.get(varname)) { // Insert a new empty thing at top level for the sake of // modifying commands. //System.err.println(" inserting empty global value"); globalhash.put(varname, new Thing("")); }//#endif } else { //System.err.println(" ignored, already in global scope"); } return; } if(lookup.containsKey(varname)) { Thing oldval = (Thing)lookup.get(varname); if(oldval == GLOBALREFTHING) { // level must be at != 0 //System.err.println(" forwarded to global value"); lookup = getVarhash(0); } } lookup.put(varname, value);//#endif } /** * <code>unSetVar</code> unsets a variable in the current stack * frame. * * @param varname a <code>Thing</code> value */ public void unSetVar(Thing varname) throws HeclException { unSetVar(varname.toString(),-1); } public synchronized void unSetVar(String varname) throws HeclException { unSetVar(varname,-1); } public synchronized void unSetVar(String varname,int level) throws HeclException { Hashtable lookup = getVarhash(level); // Bump the cache number so that SubstThing.get refetches the // variable. Thing value = (Thing)lookup.get(varname); if (value != null) { cacheversion++; lookup.remove(varname); if (value.global) { Hashtable globalhash = getVarhash(0); value = (Thing)globalhash.get(varname); if (value != null) { globalhash.remove(varname); } } } else { throw new HeclException("Variable " + varname + " does not exist"); } } /** * <code>existsVar</code> returns <code>true</code> if the given * variable exists in the current variable stack frame, <code>false</code> * if it does not. * * @param varname a <code>Thing</code> value * @return a <code>boolean</code> value */ public boolean existsVar(Thing varname) throws HeclException { return existsVar(varname.toString()); } /** * <code>existsVar</code> returns <code>true</code> if the given * variable exists in the current variable stack frame, <code>false</code> * if it does not. * * @param varname a <code>String</code> value * @return a <code>boolean</code> value */ public boolean existsVar(String varname) { return existsVar(varname, -1); } /** * <code>existsVar</code> returns <code>true</code> if the given * variable exists in the variable stack frame given by <code>level</code>, * <code>false</code> if it does not. * * @param varname a <code>String</code> value * @param level an <code>int</code> value * @return a <code>boolean</code> value */ public synchronized boolean existsVar(String varname, int level) { Hashtable lookup = getVarhash(level); return lookup.containsKey(varname); } /** * <code>addError</code> adds a Thing as an error message. * * @param err a <code>Thing</code> value */ public void addError(Thing err) { error.push(err); } /** * <code>clearError</code> clears the error stack. * */ public void clearError() { error = new Stack(); } /** * <code>checkArgCount</code> checks to see whether the command * actually has the required number of arguments. The first element of the * parameter array <code>argv</code> is not counted as argument! * * @param argv A <code>Thing[]</code> parameter array. * @param minargs The minimal number of arguments or -1 if no check is required. * @param maxargs The maximal number of arguments or -1 if no check is required. * @exception HeclException if an error occurs */ public static void checkArgCount(Thing[] argv,int minargs,int maxargs) throws HeclException { int n = argv.length-1; // Ignore command name if(minargs >= 0 && n < minargs) { throw new HeclException("Too few arguments, at least " + minargs + " arguments required."); } if(maxargs >= 0 && n > maxargs) { throw new HeclException("Bad argument count, max. " + maxargs +" arguments allowed."); } } /** * <code>nextTask</code> extracts first element from given vector. * This function operates in a synchronized manner on the argument * <code>v</code>. * * @param v A <code>Vector</code> of tasks. * @param until A value to compare the result of * <code>getGeneration</code> of the <code>HeclTask</code>. If * <code>until</code> is less than 0 or <code>getGeneration</code> * is less than <code>until</code> for the first element of * <code>v</code>, the first task in the vector is returned, null * otherwise. */ protected synchronized HeclTask nextTask(Vector v,long until) { HeclTask t = null; if(v.size() > 0) { t = (HeclTask)v.elementAt(0); //System.err.println("now="+ts+", fire="+t.getGeneration()); if(until < 0 || t.getGeneration() <= until) { v.removeElementAt(0); } else { t = null; } } return t; } /** * Service at most one idle task of the idle task queue. * * @return a <code>boolean</code> indicatign that an idle task has been * serviced (=true) or not (=false). */ protected boolean serviceIdleTask() { // The code below is trickier than it may look, for the following // reasons: // // 1. New handlers can get added to the list while the current // one is being processed. If new ones get added, we don't // want to process them during this pass through the list (want // to check for other work to do first). This is implemented // using the generation number in the handler: new handlers // will have a different generation than any of the ones currently // on the list. // 2. The handler can call doOneEvent, so we have to remove // the handler from the list before calling it. Otherwise an // infinite loop could result. // 3. cancelIdleCall can be called to remove an element from // the list while a handler is executing, so the list could // change structure during the call. long oldgeneration; synchronized(this) { if(idle.size()== 0) { idlegeneration = 0; return false; } oldgeneration = idlegeneration; ++idlegeneration; } HeclTask t = nextTask(idle,oldgeneration); if(t != null) t.execute(this); if(idle.size() > 0) maxblocktime = 0; return true; } /** * Service at most one idle task of the idle task queue. * * @param v A <code>Vector</code> of tasks to add the task to. * @param task The <code>HeclTask</code> to add. * @param pos The </code>int</code> position of <code>v</code> where to * add <code>task</code> being in the range from 0 to * <code>v.size()</code>. -1 indicates to add <code>task</code> to the * end of <code>v</code>. * * @return A <code>String</code> being the name of the inserted task. */ private HeclTask addTask(Vector v,HeclTask task,int pos) { synchronized (v) { if(pos < 0) v.addElement(task); else v.insertElementAt(task,pos);// notify(); return task; } } /** * Cancel a task of the specified name in the specified vector. * The functions performs nothing when no task of the specified name is * an element of the vector. * * @param v A vector of <code>HeclTask</code>s. * @param name A <code>String</code> specifying the name of the * task to be removed from <code>v</code>. */ private synchronized void cancelTask(Vector v,String name) { int n = v.size(); for(int i = 0; i<n; ++i) { HeclTask t = (HeclTask)v.elementAt(i); if(name.equals(t.getName())) { v.removeElementAt(i); return; } } } /** * Execute a <code>task</code>. * * @return Always the boolean value <code>true</code> to indicate * that a task has been serviced. */ private boolean executeTask(HeclTask task) { try { task.execute(this); } catch(Exception e) { // Nothing to do. It is expected that each task handles // its exceptions locally but we use this block is to ensure // that the queue continues to operate. } return true; } protected static class WaitToken { public volatile boolean waiting = true; } static String readLine(InputStreamReader is) { StringBuffer b = new StringBuffer(); int ch = -1; try { while ((ch = is.read()) != -1) { if(ch == '\r') continue; if(ch == '\n') break; b.append((char)ch); } } catch(IOException iox) { } if(b.length() > 0 || ch != -1) return b.toString(); return null; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -