📄 interp.java
字号:
} public Thing evalAsyncAndWait(Thing in) throws HeclException { HeclTask t = evalAsync(in); t.setErrorPrint(false); boolean done = false; while(!t.isDone()) { try { synchronized(t) { t.wait(); } } catch(Exception e) { // ignore e.printStackTrace(); } } try { Exception e = t.getError(); if(e != null) throw e; return t.getResult(); } catch (HeclException he) { throw he; } catch(Exception e) { throw new HeclException(e.getMessage()); } } /** * This version of <code>eval</code> takes a 'level' argument that * tells Hecl what level to run the code at. Level 0 means * global, negative numbers indicate relative levels down from the * current stackframe, and positive numbers mean absolute stack * frames counting up from 0. * * @param in a <code>Thing</code> value * @param level an <code>int</code> value * @return a <code>Thing</code> value * @exception HeclException if an error occurs */ public Thing eval(Thing in, int level) throws HeclException { Thing result = null; Vector savedstack = new Vector(); int stacklen = stack.size(); int i = 0; int end = 0; HeclException save_exception = null; if (level >= 0) { end = level; } else { end = (stacklen - 1 + level); } /* Save the old stack frames... */ for (i = stacklen - 1; i > end; i--) { savedstack.addElement(stackDecr()); } try { result = eval(in); } catch (HeclException he) { /* If this is an upeval situation, we need to catch the * exception and then throw it *after* the old stack frame * has been restored. */ save_exception = he; } /* ... and then restore them after evaluating the code. */ for (i = savedstack.size() - 1; i >= 0; i--) { stackPush((Hashtable)savedstack.elementAt(i)); } if (save_exception != null) { throw save_exception; } return result; } public boolean hasIdleTasks() { return this.idle.size() == 0; } public synchronized HeclTask getEvent(String name) { int n = timers.size(); Vector v = new Vector(); HeclTask t = null; for(int i=0; i<n; ++i) { t = (HeclTask)timers.elementAt(i); if(name.equals(t.getName())) return t; } n = idle.size(); for(int i=0; i<n; ++i) { t = (HeclTask)idle.elementAt(i); if(name.equals(t.getName())) return t; } return null; } public synchronized Vector getAllEvents() { int n = timers.size(); Vector v = new Vector(); for(int i=0; i<n; ++i) v.addElement(timers.elementAt(i)); n = idle.size(); for(int i=0; i<n; ++i) v.addElement(timers.elementAt(i)); return v; } public HeclTask addTimer(Thing timerThing, int millisecs) { synchronized (timers) { int n = timers.size(); long ts = System.currentTimeMillis()+millisecs; HeclTask t = new HeclTask(timerThing, ts, TIMERPREFIX); int i; for(i=0; i<n; ++i) { HeclTask other = (HeclTask)timers.elementAt(i); if(other.getGeneration() > ts) break; } //System.err.println("Adding timer, time="+ts); return addTask(timers,t,i); } } public void cancelTimer(String name) { cancelTask(timers,name); } public void cancelIdle(String name) { cancelTask(idle,name); } public void cancelAsync(String name) { cancelTask(asyncs,name); } public synchronized void cancelIdle(HeclTask idletask) { idle.removeElement(idletask); } public boolean doOneEvent(int flags) { if((flags & ALL_EVENTS) == 0) flags = ALL_EVENTS; // The core of this procedure is an infinite loop, even though // we only service one event. The reason for this is that we // may be processing events that don't do anything inside of Hecl. int count = 0; while(true) { // First check for async events... HeclTask t = nextTask(asyncs,-1); if(t != null) { return executeTask(t); } long now = System.currentTimeMillis(); if((flags & TIMER_EVENTS) != 0) { t = nextTask(timers,now); if(t != null) { return executeTask(t); } } // Determine maxblocktime if ((flags & DONT_WAIT) != 0) { maxblocktime = 0; } else { maxblocktime = 1000; synchronized(this) { if(timers.size() > 0) { t = (HeclTask)timers.elementAt(0); maxblocktime = t.getGeneration() - now; } } } // this may reduce maxblocktime! if((flags & IDLE_EVENTS) != 0) { serviceIdleTask(); } if(count > 0 || maxblocktime <= 0) break; yield(); // give other thread a chance synchronized(this) { try { this.wait(maxblocktime); } catch (InterruptedException e) { // it doesn't matter } } //System.err.println("interp wait done, next loop iteration"); ++count; } //System.err.println("<--doOneEvent:false"); return false; } public void waitForToken(String tokenname) throws HeclException { boolean exists = false; WaitToken token = null; synchronized(this) { exists = waittokens.containsKey(tokenname); if(exists) throw new HeclException("Wait token '"+tokenname+"' already exists."); token = new WaitToken(); waittokens.put(tokenname,token); } // Endless loop, some event in the future should kick us off this loop boolean b = true; while(b) { // Carefully read/modify status information synchronized(this) { b = token.waiting; } if(b) { // Service one event doOneEvent(Interp.ALL_EVENTS); } } } public void notifyToken(String tokenname) throws HeclException { synchronized(this) { WaitToken token = (WaitToken)waittokens.get(tokenname); if(token == null) throw new HeclException("No wait token '"+tokenname+"'."); token.waiting = false; waittokens.remove(tokenname); } } /** * The <code>terminate</code> method terminates the Hecl * interpreter thread in a graceful manner. The thread will * eventually finish its run-method. * */ public void terminate() { running = false; synchronized(this) { notify(); } } public void run() {// System.err.println("interp running..."); long now = System.currentTimeMillis(); while(running) { doOneEvent(ALL_EVENTS); }// System.err.println("interp stopped!"); } /** * The <code>initCommands</code> method initializes all the built in * commands. These are commands available in all versions of Hecl. J2SE * commands are initialized in Standard.java, and J2ME commands in * Micro.java. * * @exception HeclException if an error occurs */ private void initInterp() throws HeclException { /* Do not use the 'Facade' style commands as an example if you * just have to add a simple command or two. The pattern * works best when you need to add several commands with * related functionality. */ // System.err.println("-->initinterp"); // System.err.println("loading interp cmds..."); /* Commands that manipulate interp data structures - * variables, procs, commands, and so forth. */ InterpCmds.load(this); // System.err.println("loading math cmds..."); /* Math and logic commands. */ MathCmds.load(this); // System.err.println("loading list cmds..."); /* List related commands. */ ListCmds.load(this); // System.err.println("loading control cmds..."); /* Control commands. */ ControlCmds.load(this); // System.err.println("loading string cmds..."); /* String commands. */ StringCmds.load(this); // System.err.println("loading hash cmds..."); /* Hash table commands. */ HashCmds.load(this); commands.put("puts", new PutsCmd()); commands.put("sort", new SortCmd()); // System.err.println("<--initinterp"); } /** * The <code>cmdRename</code> method renames a command, or throws * an error if the original command didn't exist. * * @param oldname a <code>String</code> value * @param newname a <code>String</code> value * @exception HeclException if an error occurs */ public synchronized void cmdRename(String oldname, String newname) throws HeclException { Command tmp = (Command)commands.get(oldname); if (tmp == null) { throw new HeclException("Command " + oldname + " does not exist"); } commands.put(newname, tmp); commands.remove(oldname); } /** * The <code>stackIncr</code> method creates a new stack frame. Used in * the Proc class. * */ public synchronized void stackIncr() { stackPush(new Hashtable()); } /** * <code>stackDecr</code> pops the stack frame, returning it so that * commands like upeval can save it. If it's not saved, it's gone. * */ public synchronized Hashtable stackDecr() { return (Hashtable) stack.pop(); } /** * <code>stackDecr</code> pushes a new variable hashtable * (probably saved via upeval) onto the stack frame. * */ public synchronized void stackPush(Hashtable vars) { cacheversion++; stack.push(vars); } /** * <code>getVarhash</code> fetches the variable Hashtable at the * given level, where -1 means to just get the hashtable on top of * the stack. * * @param level an <code>int</code> value * @return a <code>Hashtable</code> value */ private Hashtable getVarhash(int level) { return level < 0 ? (Hashtable)stack.peek() : (Hashtable)stack.elementAt(level); } /** * <code>getVar</code> returns the value of a variable given its name. * * @param varname a <code>Thing</code> value * * @return a <code>Thing</code> value * @exception HeclException if an error occurs */ public Thing getVar(Thing varname) throws HeclException { return getVar(varname.toString(), -1); } /** * <code>getVar</code> returns the value of a variable given its name. * * @param varname a <code>String</code> value * @return a <code>Thing</code> value * @exception HeclException if an error occurs */ public Thing getVar(String varname) throws HeclException { return getVar(varname, -1); } /** * <code>getVar</code> returns the value of a variable given its name and * level. * * @param varname a <code>String</code> value * @param level an <code>int</code> value * @return a <code>Thing</code> value * @exception HeclException if an error occurs */ public synchronized Thing getVar(String varname, int level) throws HeclException { Hashtable lookup = getVarhash(level); //System.out.println("getvar: " + varname + " " + level + " " + lookup); Thing res = (Thing) lookup.get(varname);//#ifdef old if (res == null) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -